Skip to content

Commit

Permalink
test(ivy): mark jit_summaries_integration_spec as obsolete in Ivy (#2…
Browse files Browse the repository at this point in the history
…8027)

These tests validate the ability of the View Engine TestBed to consume
summary metadata, a mechanism which allows the TestBed to use
AOT-compiled components & directives in tests. It achieves this through
two operations which are independently obsolete in Ivy:

1. It injects CompileMetadataResolver, a View Engine specific compiler
   internal class which extracts global analysis metadata from classes,
   and uses it to construct summary metadata. This happens in a
   beforeEach() block which calls createSummaries().

2. It uses TestBed.initTestEnvironment to pass summary metadata to the
   TestBed itself. Any such metadata is ignored in Ivy.

Operation #1 makes it impossible to run these tests under Ivy, as the
CompileMetadataResolver is not available with an Ivy compiler.

Ivy itself does not rely on summary data, and the R3TestBed can depend
directly on AOT compiled components without it. Thus, the spirit of thes
tests is obsolete in an Ivy world.

FW-838 #resolve

PR Close #28027
  • Loading branch information
alxhub authored and AndrewKushnir committed Jan 9, 2019
1 parent d0c3e25 commit 11325ba
Showing 1 changed file with 144 additions and 149 deletions.
293 changes: 144 additions & 149 deletions packages/core/test/linker/jit_summaries_integration_spec.ts
Expand Up @@ -12,133 +12,136 @@ import {MockResourceLoader} from '@angular/compiler/testing/src/resource_loader_
import {Component, Directive, Injectable, NgModule, OnDestroy, Pipe} from '@angular/core';
import {TestBed, async, getTestBed} from '@angular/core/testing';
import {expect} from '@angular/platform-browser/testing/src/matchers';
import {fixmeIvy} from '@angular/private/testing';
import {obsoleteInIvy} from '@angular/private/testing';

{
describe('Jit Summaries', () => {
let instances: Map<any, Base>;
let summaries: () => any[];

class SomeDep {}

class Base {
static annotations: any[];
static parameters: any[][];

constructor(public dep: SomeDep) {
instances.set(Object.getPrototypeOf(this).constructor, this);
}
}

function expectInstanceCreated(type: any) {
const instance = instances.get(type) !;
expect(instance).toBeDefined();
expect(instance.dep instanceof SomeDep).toBe(true);
}

class SomeModule extends Base {}

class SomePrivateComponent extends Base {}

class SomePublicComponent extends Base {}

class SomeDirective extends Base {}

class SomePipe extends Base {
transform(value: any) { return value; }
}

class SomeService extends Base {}

// Move back into the it which needs it after https://github.com/angular/tsickle/issues/547 is
// fixed.
@Component({template: '<div someDir>{{1 | somePipe}}</div>'})
class TestComp3 {
constructor(service: SomeService) {}
}

@Component({template: ''})
class TestCompErrorOnDestroy implements OnDestroy {
ngOnDestroy() {}
}

function resetTestEnvironmentWithSummaries(summaries?: () => any[]) {
const {platform, ngModule} = getTestBed();
TestBed.resetTestEnvironment();
TestBed.initTestEnvironment(ngModule, platform, summaries);
}

function createSummaries() {
const resourceLoader = new MockResourceLoader();

setMetadata(resourceLoader);

TestBed.configureCompiler({providers: [{provide: ResourceLoader, useValue: resourceLoader}]});
TestBed.configureTestingModule({imports: [SomeModule], providers: [SomeDep]});

let summariesPromise = TestBed.compileComponents().then(() => {
const metadataResolver = TestBed.get(CompileMetadataResolver) as CompileMetadataResolver;
const summaries = [
metadataResolver.getNgModuleSummary(SomeModule),
// test nesting via closures, as we use this in the generated code too.
() =>
[metadataResolver.getDirectiveSummary(SomePublicComponent),
metadataResolver.getDirectiveSummary(SomePrivateComponent),
],
metadataResolver.getDirectiveSummary(SomeDirective),
metadataResolver.getPipeSummary(SomePipe),
metadataResolver.getInjectableSummary(SomeService)
];
clearMetadata();
TestBed.resetTestingModule();
return () => summaries;
});
obsoleteInIvy('Summaries are not used/supported/able to be produced in Ivy. See FW-838.')
.describe('Jit Summaries', () => {
let instances: Map<any, Base>;
let summaries: () => any[];

class SomeDep {}

class Base {
static annotations: any[];
static parameters: any[][];

constructor(public dep: SomeDep) {
instances.set(Object.getPrototypeOf(this).constructor, this);
}
}

function expectInstanceCreated(type: any) {
const instance = instances.get(type) !;
expect(instance).toBeDefined();
expect(instance.dep instanceof SomeDep).toBe(true);
}

class SomeModule extends Base {}

class SomePrivateComponent extends Base {}

class SomePublicComponent extends Base {}

class SomeDirective extends Base {}

class SomePipe extends Base {
transform(value: any) { return value; }
}

class SomeService extends Base {}

// Move back into the it which needs it after https://github.com/angular/tsickle/issues/547
// is
// fixed.
@Component({template: '<div someDir>{{1 | somePipe}}</div>'})
class TestComp3 {
constructor(service: SomeService) {}
}

@Component({template: ''})
class TestCompErrorOnDestroy implements OnDestroy {
ngOnDestroy() {}
}

function resetTestEnvironmentWithSummaries(summaries?: () => any[]) {
const {platform, ngModule} = getTestBed();
TestBed.resetTestEnvironment();
TestBed.initTestEnvironment(ngModule, platform, summaries);
}

function createSummaries() {
const resourceLoader = new MockResourceLoader();

setMetadata(resourceLoader);

TestBed.configureCompiler(
{providers: [{provide: ResourceLoader, useValue: resourceLoader}]});
TestBed.configureTestingModule({imports: [SomeModule], providers: [SomeDep]});

let summariesPromise = TestBed.compileComponents().then(() => {
const metadataResolver =
TestBed.get(CompileMetadataResolver) as CompileMetadataResolver;
const summaries = [
metadataResolver.getNgModuleSummary(SomeModule),
// test nesting via closures, as we use this in the generated code too.
() =>
[metadataResolver.getDirectiveSummary(SomePublicComponent),
metadataResolver.getDirectiveSummary(SomePrivateComponent),
],
metadataResolver.getDirectiveSummary(SomeDirective),
metadataResolver.getPipeSummary(SomePipe),
metadataResolver.getInjectableSummary(SomeService)
];
clearMetadata();
TestBed.resetTestingModule();
return () => summaries;
});

resourceLoader.flush();
return summariesPromise;
}
resourceLoader.flush();
return summariesPromise;
}

function setMetadata(resourceLoader: MockResourceLoader) {
Base.parameters = [[SomeDep]];
function setMetadata(resourceLoader: MockResourceLoader) {
Base.parameters = [[SomeDep]];

SomeModule.annotations = [new NgModule({
declarations: [SomePublicComponent, SomePrivateComponent, SomeDirective, SomePipe],
exports: [SomeDirective, SomePipe, SomePublicComponent],
providers: [SomeService]
})];
SomeModule.annotations = [new NgModule({
declarations: [SomePublicComponent, SomePrivateComponent, SomeDirective, SomePipe],
exports: [SomeDirective, SomePipe, SomePublicComponent],
providers: [SomeService]
})];

SomePublicComponent.annotations = [new Component({templateUrl: 'somePublicUrl.html'})];
resourceLoader.expect('somePublicUrl.html', `Hello public world!`);
SomePublicComponent.annotations = [new Component({templateUrl: 'somePublicUrl.html'})];
resourceLoader.expect('somePublicUrl.html', `Hello public world!`);

SomePrivateComponent.annotations = [new Component({templateUrl: 'somePrivateUrl.html'})];
resourceLoader.expect('somePrivateUrl.html', `Hello private world!`);
SomePrivateComponent.annotations = [new Component({templateUrl: 'somePrivateUrl.html'})];
resourceLoader.expect('somePrivateUrl.html', `Hello private world!`);

SomeDirective.annotations = [new Directive({selector: '[someDir]'})];
SomeDirective.annotations = [new Directive({selector: '[someDir]'})];

SomePipe.annotations = [new Pipe({name: 'somePipe'})];
SomePipe.annotations = [new Pipe({name: 'somePipe'})];

SomeService.annotations = [new Injectable()];
}
SomeService.annotations = [new Injectable()];
}

function clearMetadata() {
Base.parameters = [];
SomeModule.annotations = [];
SomePublicComponent.annotations = [];
SomePrivateComponent.annotations = [];
SomeDirective.annotations = [];
SomePipe.annotations = [];
SomeService.annotations = [];
}
function clearMetadata() {
Base.parameters = [];
SomeModule.annotations = [];
SomePublicComponent.annotations = [];
SomePrivateComponent.annotations = [];
SomeDirective.annotations = [];
SomePipe.annotations = [];
SomeService.annotations = [];
}

beforeEach(async(() => {
instances = new Map<any, any>();
createSummaries().then(s => summaries = s);
}));
beforeEach(async(() => {
instances = new Map<any, any>();
createSummaries().then(s => summaries = s);
}));

afterEach(() => { resetTestEnvironmentWithSummaries(); });
afterEach(() => { resetTestEnvironmentWithSummaries(); });

fixmeIvy('FW-838: ivy testbed doesn\'t support jit summaries')
.it('should use directive metadata from summaries', () => {
it('should use directive metadata from summaries', () => {
resetTestEnvironmentWithSummaries(summaries);

@Component({template: '<div someDir></div>'})
Expand All @@ -152,8 +155,8 @@ import {fixmeIvy} from '@angular/private/testing';
expectInstanceCreated(SomeDirective);
});

fixmeIvy('FW-838: ivy testbed doesn\'t support jit summaries')
.it('should use pipe metadata from summaries', () => {

it('should use pipe metadata from summaries', () => {
resetTestEnvironmentWithSummaries(summaries);

@Component({template: '{{1 | somePipe}}'})
Expand All @@ -165,8 +168,7 @@ import {fixmeIvy} from '@angular/private/testing';
expectInstanceCreated(SomePipe);
});

fixmeIvy('FW-838: ivy testbed doesn\'t support jit summaries')
.it('should use Service metadata from summaries', () => {
it('should use Service metadata from summaries', () => {
resetTestEnvironmentWithSummaries(summaries);

TestBed.configureTestingModule({
Expand All @@ -176,8 +178,7 @@ import {fixmeIvy} from '@angular/private/testing';
expectInstanceCreated(SomeService);
});

fixmeIvy('FW-838: ivy testbed doesn\'t support jit summaries')
.it('should use NgModule metadata from summaries', () => {
it('should use NgModule metadata from summaries', () => {
resetTestEnvironmentWithSummaries(summaries);

TestBed
Expand All @@ -191,17 +192,15 @@ import {fixmeIvy} from '@angular/private/testing';
expectInstanceCreated(SomeService);
});

fixmeIvy('FW-838: ivy testbed doesn\'t support jit summaries')
.it('should allow to create private components from imported NgModule summaries', () => {
it('should allow to create private components from imported NgModule summaries', () => {
resetTestEnvironmentWithSummaries(summaries);

TestBed.configureTestingModule({providers: [SomeDep], imports: [SomeModule]})
.createComponent(SomePrivateComponent);
expectInstanceCreated(SomePrivateComponent);
});

fixmeIvy('FW-838: ivy testbed doesn\'t support jit summaries')
.it('should throw when trying to mock a type with a summary', () => {
it('should throw when trying to mock a type with a summary', () => {
resetTestEnvironmentWithSummaries(summaries);

TestBed.resetTestingModule();
Expand All @@ -220,35 +219,33 @@ import {fixmeIvy} from '@angular/private/testing';
.toThrowError('SomeModule was AOT compiled, so its metadata cannot be changed.');
});

fixmeIvy('FW-838: ivy testbed doesn\'t support jit summaries')
.it('should return stack trace and component data on resetTestingModule when error is thrown',
() => {
resetTestEnvironmentWithSummaries();
it('should return stack trace and component data on resetTestingModule when error is thrown',
() => {
resetTestEnvironmentWithSummaries();

const fixture =
TestBed.configureTestingModule({declarations: [TestCompErrorOnDestroy]})
.createComponent<TestCompErrorOnDestroy>(TestCompErrorOnDestroy);
const fixture =
TestBed.configureTestingModule({declarations: [TestCompErrorOnDestroy]})
.createComponent<TestCompErrorOnDestroy>(TestCompErrorOnDestroy);

const expectedError = 'Error from ngOnDestroy';
const expectedError = 'Error from ngOnDestroy';

const component: TestCompErrorOnDestroy = fixture.componentInstance;
const component: TestCompErrorOnDestroy = fixture.componentInstance;

spyOn(console, 'error');
spyOn(component, 'ngOnDestroy').and.throwError(expectedError);
spyOn(console, 'error');
spyOn(component, 'ngOnDestroy').and.throwError(expectedError);

const expectedObject = {
stacktrace: new Error(expectedError),
component,
};
const expectedObject = {
stacktrace: new Error(expectedError),
component,
};

TestBed.resetTestingModule();
TestBed.resetTestingModule();

expect(console.error)
.toHaveBeenCalledWith('Error during cleanup of component', expectedObject);
});
expect(console.error)
.toHaveBeenCalledWith('Error during cleanup of component', expectedObject);
});

fixmeIvy('FW-838: ivy testbed doesn\'t support jit summaries')
.it('should allow to add summaries via configureTestingModule', () => {
it('should allow to add summaries via configureTestingModule', () => {
resetTestEnvironmentWithSummaries();

@Component({template: '<div someDir></div>'})
Expand All @@ -265,8 +262,7 @@ import {fixmeIvy} from '@angular/private/testing';
expectInstanceCreated(SomeDirective);
});

fixmeIvy('FW-838: ivy testbed doesn\'t support jit summaries')
.it('should allow to override a provider', () => {
it('should allow to override a provider', () => {
resetTestEnvironmentWithSummaries(summaries);

const overwrittenValue = {};
Expand All @@ -279,8 +275,7 @@ import {fixmeIvy} from '@angular/private/testing';
expect(fixture.componentInstance.dep).toBe(overwrittenValue);
});

fixmeIvy('FW-838: ivy testbed doesn\'t support jit summaries')
.it('should allow to override a template', () => {
it('should allow to override a template', () => {
resetTestEnvironmentWithSummaries(summaries);

TestBed.overrideTemplateUsingTestingModule(SomePublicComponent, 'overwritten');
Expand All @@ -292,5 +287,5 @@ import {fixmeIvy} from '@angular/private/testing';

expect(fixture.nativeElement).toHaveText('overwritten');
});
});
});
}

0 comments on commit 11325ba

Please sign in to comment.