test(ivy): finish root cause analysis for @angular/core TestBed failing tests (#27510)
PR Close #27510
This commit is contained in:
parent
8fa7e93c30
commit
913563a41d
|
@ -9,7 +9,7 @@
|
|||
import {ApplicationRef, Component, DoCheck, NgModule, OnInit, TestabilityRegistry, ɵivyEnabled as ivyEnabled} from '@angular/core';
|
||||
import {getTestBed} from '@angular/core/testing';
|
||||
import {BrowserModule} from '@angular/platform-browser';
|
||||
import {fixmeIvy, withBody} from '@angular/private/testing';
|
||||
import {withBody} from '@angular/private/testing';
|
||||
|
||||
import {NgModuleFactory} from '../src/render3/ng_module_ref';
|
||||
|
||||
|
@ -35,26 +35,27 @@ ivyEnabled && describe('ApplicationRef bootstrap', () => {
|
|||
class MyAppModule {
|
||||
}
|
||||
|
||||
fixmeIvy('unknown').it(
|
||||
'should bootstrap hello world', withBody('<hello-world></hello-world>', async() => {
|
||||
const MyAppModuleFactory = new NgModuleFactory(MyAppModule);
|
||||
const moduleRef = await getTestBed().platform.bootstrapModuleFactory(
|
||||
MyAppModuleFactory, {ngZone: 'noop'});
|
||||
const appRef = moduleRef.injector.get(ApplicationRef);
|
||||
const helloWorldComponent = appRef.components[0].instance as HelloWorldComponent;
|
||||
expect(document.body.innerHTML)
|
||||
.toEqual('<hello-world><div>Hello World</div></hello-world>');
|
||||
expect(helloWorldComponent.log).toEqual(['OnInit', 'DoCheck']);
|
||||
it('should bootstrap hello world', withBody('<hello-world></hello-world>', async() => {
|
||||
const MyAppModuleFactory = new NgModuleFactory(MyAppModule);
|
||||
const moduleRef =
|
||||
await getTestBed().platform.bootstrapModuleFactory(MyAppModuleFactory, {ngZone: 'noop'});
|
||||
const appRef = moduleRef.injector.get(ApplicationRef);
|
||||
const helloWorldComponent = appRef.components[0].instance as HelloWorldComponent;
|
||||
expect(document.body.innerHTML)
|
||||
.toEqual(
|
||||
'<hello-world ng-version="0.0.0-PLACEHOLDER"><div>Hello World</div></hello-world>');
|
||||
expect(helloWorldComponent.log).toEqual(['OnInit', 'DoCheck']);
|
||||
|
||||
helloWorldComponent.name = 'Mundo';
|
||||
appRef.tick();
|
||||
expect(document.body.innerHTML)
|
||||
.toEqual('<hello-world><div>Hello Mundo</div></hello-world>');
|
||||
expect(helloWorldComponent.log).toEqual(['OnInit', 'DoCheck', 'DoCheck']);
|
||||
helloWorldComponent.name = 'Mundo';
|
||||
appRef.tick();
|
||||
expect(document.body.innerHTML)
|
||||
.toEqual(
|
||||
'<hello-world ng-version="0.0.0-PLACEHOLDER"><div>Hello Mundo</div></hello-world>');
|
||||
expect(helloWorldComponent.log).toEqual(['OnInit', 'DoCheck', 'DoCheck']);
|
||||
|
||||
// Cleanup TestabilityRegistry
|
||||
const registry: TestabilityRegistry = getTestBed().get(TestabilityRegistry);
|
||||
registry.unregisterAllApplications();
|
||||
}));
|
||||
// Cleanup TestabilityRegistry
|
||||
const registry: TestabilityRegistry = getTestBed().get(TestabilityRegistry);
|
||||
registry.unregisterAllApplications();
|
||||
}));
|
||||
|
||||
});
|
||||
|
|
|
@ -33,10 +33,11 @@ const ProxyZoneSpec: {assertPresent: () => void} = (Zone as any)['ProxyZoneSpec'
|
|||
})('foo', 'bar');
|
||||
});
|
||||
|
||||
fixmeIvy('unknown').it(
|
||||
'should work with inject()', fakeAsync(inject([Parser], (parser: any /** TODO #9100 */) => {
|
||||
expect(parser).toBeAnInstanceOf(Parser);
|
||||
})));
|
||||
fixmeIvy('FW-806: Ivy\'s TestBed implementation doesn\'t inject compiler-related tokens')
|
||||
.it('should work with inject()',
|
||||
fakeAsync(inject([Parser], (parser: any /** TODO #9100 */) => {
|
||||
expect(parser).toBeAnInstanceOf(Parser);
|
||||
})));
|
||||
|
||||
it('should throw on nested calls', () => {
|
||||
expect(() => {
|
||||
|
|
|
@ -69,20 +69,22 @@ function declareTests(config?: {useJit: boolean}) {
|
|||
expect(childComp.cfr.resolveComponentFactory(ChildComp) !.componentType).toBe(ChildComp);
|
||||
});
|
||||
|
||||
fixmeIvy('unknown').it(
|
||||
'should not be able to get components from a parent component (content hierarchy)', () => {
|
||||
TestBed.overrideComponent(
|
||||
MainComp, {set: {template: '<child><nested></nested></child>'}});
|
||||
TestBed.overrideComponent(ChildComp, {set: {template: '<ng-content></ng-content>'}});
|
||||
fixmeIvy(
|
||||
'FW-805: Ivy\'s implementation of ComponentFactoryResolver doesn\'t have checks present in the view engine')
|
||||
.it('should not be able to get components from a parent component (content hierarchy)',
|
||||
() => {
|
||||
TestBed.overrideComponent(
|
||||
MainComp, {set: {template: '<child><nested></nested></child>'}});
|
||||
TestBed.overrideComponent(ChildComp, {set: {template: '<ng-content></ng-content>'}});
|
||||
|
||||
const compFixture = TestBed.createComponent(MainComp);
|
||||
const nestedChildCompEl = compFixture.debugElement.children[0].children[0];
|
||||
const nestedChildComp: NestedChildComp = nestedChildCompEl.componentInstance;
|
||||
expect(nestedChildComp.cfr.resolveComponentFactory(ChildComp) !.componentType)
|
||||
.toBe(ChildComp);
|
||||
expect(() => nestedChildComp.cfr.resolveComponentFactory(NestedChildComp))
|
||||
.toThrow(noComponentFactoryError(NestedChildComp));
|
||||
});
|
||||
const compFixture = TestBed.createComponent(MainComp);
|
||||
const nestedChildCompEl = compFixture.debugElement.children[0].children[0];
|
||||
const nestedChildComp: NestedChildComp = nestedChildCompEl.componentInstance;
|
||||
expect(nestedChildComp.cfr.resolveComponentFactory(ChildComp) !.componentType)
|
||||
.toBe(ChildComp);
|
||||
expect(() => nestedChildComp.cfr.resolveComponentFactory(NestedChildComp))
|
||||
.toThrow(noComponentFactoryError(NestedChildComp));
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1331,21 +1331,24 @@ function declareTests(config?: {useJit: boolean}) {
|
|||
expect(comp.injectable).toBeAnInstanceOf(InjectableService);
|
||||
});
|
||||
|
||||
fixmeIvy('unknown').it('should support viewProviders', () => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [MyComp, DirectiveProvidingInjectableInView, DirectiveConsumingInjectable],
|
||||
schemas: [NO_ERRORS_SCHEMA],
|
||||
});
|
||||
const template = `
|
||||
fixmeIvy(
|
||||
'FW-804: Injection of view providers with the @Host annotation works differently in ivy')
|
||||
.it('should support viewProviders', () => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations:
|
||||
[MyComp, DirectiveProvidingInjectableInView, DirectiveConsumingInjectable],
|
||||
schemas: [NO_ERRORS_SCHEMA],
|
||||
});
|
||||
const template = `
|
||||
<directive-consuming-injectable #consuming>
|
||||
</directive-consuming-injectable>
|
||||
`;
|
||||
TestBed.overrideComponent(DirectiveProvidingInjectableInView, {set: {template}});
|
||||
const fixture = TestBed.createComponent(DirectiveProvidingInjectableInView);
|
||||
TestBed.overrideComponent(DirectiveProvidingInjectableInView, {set: {template}});
|
||||
const fixture = TestBed.createComponent(DirectiveProvidingInjectableInView);
|
||||
|
||||
const comp = fixture.debugElement.children[0].references !['consuming'];
|
||||
expect(comp.injectable).toBeAnInstanceOf(InjectableService);
|
||||
});
|
||||
const comp = fixture.debugElement.children[0].references !['consuming'];
|
||||
expect(comp.injectable).toBeAnInstanceOf(InjectableService);
|
||||
});
|
||||
|
||||
it('should support unbounded lookup', () => {
|
||||
TestBed.configureTestingModule({
|
||||
|
|
|
@ -745,12 +745,11 @@ function declareTests(config?: {useJit: boolean}) {
|
|||
expect(cars[0]).toBe(injector.get(SportsCar));
|
||||
});
|
||||
|
||||
fixmeIvy('FW-682: Compiler error handling')
|
||||
.it('should throw when the aliased provider does not exist', () => {
|
||||
const injector = createInjector([{provide: 'car', useExisting: SportsCar}]);
|
||||
const e = `NullInjectorError: No provider for ${stringify(SportsCar)}!`;
|
||||
expect(() => injector.get('car')).toThrowError(e);
|
||||
});
|
||||
it('should throw when the aliased provider does not exist', () => {
|
||||
const injector = createInjector([{provide: 'car', useExisting: SportsCar}]);
|
||||
const e = `NullInjectorError: No provider for ${stringify(SportsCar)}!`;
|
||||
expect(() => injector.get('car')).toThrowError(e);
|
||||
});
|
||||
|
||||
it('should handle forwardRef in useExisting', () => {
|
||||
const injector = createInjector([
|
||||
|
|
|
@ -75,46 +75,43 @@ function declareTests(config?: {useJit: boolean}) {
|
|||
expect(CountingPipe.calls).toBe(1);
|
||||
});
|
||||
|
||||
fixmeIvy('FW-756: Pipes and directives from imported modules are not taken into account')
|
||||
.it('should only update the bound property when using asyncPipe - #15205',
|
||||
fakeAsync(() => {
|
||||
@Component({template: '<div myDir [a]="p | async" [b]="2"></div>'})
|
||||
class MyComp {
|
||||
p = Promise.resolve(1);
|
||||
}
|
||||
it('should only update the bound property when using asyncPipe - #15205', fakeAsync(() => {
|
||||
@Component({template: '<div myDir [a]="p | async" [b]="2"></div>'})
|
||||
class MyComp {
|
||||
p = Promise.resolve(1);
|
||||
}
|
||||
|
||||
@Directive({selector: '[myDir]'})
|
||||
class MyDir {
|
||||
setterCalls: {[key: string]: any} = {};
|
||||
// TODO(issue/24571): remove '!'.
|
||||
changes !: SimpleChanges;
|
||||
@Directive({selector: '[myDir]'})
|
||||
class MyDir {
|
||||
setterCalls: {[key: string]: any} = {};
|
||||
// TODO(issue/24571): remove '!'.
|
||||
changes !: SimpleChanges;
|
||||
|
||||
@Input()
|
||||
set a(v: number) { this.setterCalls['a'] = v; }
|
||||
@Input()
|
||||
set b(v: number) { this.setterCalls['b'] = v; }
|
||||
@Input()
|
||||
set a(v: number) { this.setterCalls['a'] = v; }
|
||||
@Input()
|
||||
set b(v: number) { this.setterCalls['b'] = v; }
|
||||
|
||||
ngOnChanges(changes: SimpleChanges) { this.changes = changes; }
|
||||
}
|
||||
ngOnChanges(changes: SimpleChanges) { this.changes = changes; }
|
||||
}
|
||||
|
||||
TestBed.configureTestingModule({declarations: [MyDir, MyComp]});
|
||||
const fixture = TestBed.createComponent(MyComp);
|
||||
const dir =
|
||||
fixture.debugElement.query(By.directive(MyDir)).injector.get(MyDir) as MyDir;
|
||||
TestBed.configureTestingModule({declarations: [MyDir, MyComp]});
|
||||
const fixture = TestBed.createComponent(MyComp);
|
||||
const dir = fixture.debugElement.query(By.directive(MyDir)).injector.get(MyDir) as MyDir;
|
||||
|
||||
fixture.detectChanges();
|
||||
expect(dir.setterCalls).toEqual({'a': null, 'b': 2});
|
||||
expect(Object.keys(dir.changes)).toEqual(['a', 'b']);
|
||||
fixture.detectChanges();
|
||||
expect(dir.setterCalls).toEqual({'a': null, 'b': 2});
|
||||
expect(Object.keys(dir.changes)).toEqual(['a', 'b']);
|
||||
|
||||
dir.setterCalls = {};
|
||||
dir.changes = {};
|
||||
dir.setterCalls = {};
|
||||
dir.changes = {};
|
||||
|
||||
tick();
|
||||
fixture.detectChanges();
|
||||
tick();
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(dir.setterCalls).toEqual({'a': 1});
|
||||
expect(Object.keys(dir.changes)).toEqual(['a']);
|
||||
}));
|
||||
expect(dir.setterCalls).toEqual({'a': 1});
|
||||
expect(Object.keys(dir.changes)).toEqual(['a']);
|
||||
}));
|
||||
|
||||
it('should only evaluate methods once - #10639', () => {
|
||||
TestBed.configureTestingModule({declarations: [MyCountingComp]});
|
||||
|
|
|
@ -138,34 +138,36 @@ import {fixmeIvy} from '@angular/private/testing';
|
|||
expect(instance.dep instanceof Dep).toBeTruthy();
|
||||
});
|
||||
|
||||
fixmeIvy('unknown').it('should not inject deps from sibling root elements', () => {
|
||||
const rootElNodes = [
|
||||
elementDef(0, NodeFlags.None, null, null, 1, 'span'),
|
||||
directiveDef(1, NodeFlags.None, null, 0, Dep, []),
|
||||
elementDef(2, NodeFlags.None, null, null, 1, 'span'),
|
||||
directiveDef(3, NodeFlags.None, null, 0, SomeService, [Dep]),
|
||||
];
|
||||
fixmeIvy(
|
||||
'FW-807: NgModule injector doesn\'t report full search path if a token is not found')
|
||||
.it('should not inject deps from sibling root elements', () => {
|
||||
const rootElNodes = [
|
||||
elementDef(0, NodeFlags.None, null, null, 1, 'span'),
|
||||
directiveDef(1, NodeFlags.None, null, 0, Dep, []),
|
||||
elementDef(2, NodeFlags.None, null, null, 1, 'span'),
|
||||
directiveDef(3, NodeFlags.None, null, 0, SomeService, [Dep]),
|
||||
];
|
||||
|
||||
expect(() => createAndGetRootNodes(compViewDef(rootElNodes)))
|
||||
.toThrowError(
|
||||
'StaticInjectorError(DynamicTestModule)[SomeService -> Dep]: \n' +
|
||||
' StaticInjectorError(Platform: core)[SomeService -> Dep]: \n' +
|
||||
' NullInjectorError: No provider for Dep!');
|
||||
expect(() => createAndGetRootNodes(compViewDef(rootElNodes)))
|
||||
.toThrowError(
|
||||
'StaticInjectorError(DynamicTestModule)[SomeService -> Dep]: \n' +
|
||||
' StaticInjectorError(Platform: core)[SomeService -> Dep]: \n' +
|
||||
' NullInjectorError: No provider for Dep!');
|
||||
|
||||
const nonRootElNodes = [
|
||||
elementDef(0, NodeFlags.None, null, null, 4, 'span'),
|
||||
elementDef(1, NodeFlags.None, null, null, 1, 'span'),
|
||||
directiveDef(2, NodeFlags.None, null, 0, Dep, []),
|
||||
elementDef(3, NodeFlags.None, null, null, 1, 'span'),
|
||||
directiveDef(4, NodeFlags.None, null, 0, SomeService, [Dep]),
|
||||
];
|
||||
const nonRootElNodes = [
|
||||
elementDef(0, NodeFlags.None, null, null, 4, 'span'),
|
||||
elementDef(1, NodeFlags.None, null, null, 1, 'span'),
|
||||
directiveDef(2, NodeFlags.None, null, 0, Dep, []),
|
||||
elementDef(3, NodeFlags.None, null, null, 1, 'span'),
|
||||
directiveDef(4, NodeFlags.None, null, 0, SomeService, [Dep]),
|
||||
];
|
||||
|
||||
expect(() => createAndGetRootNodes(compViewDef(nonRootElNodes)))
|
||||
.toThrowError(
|
||||
'StaticInjectorError(DynamicTestModule)[SomeService -> Dep]: \n' +
|
||||
' StaticInjectorError(Platform: core)[SomeService -> Dep]: \n' +
|
||||
' NullInjectorError: No provider for Dep!');
|
||||
});
|
||||
expect(() => createAndGetRootNodes(compViewDef(nonRootElNodes)))
|
||||
.toThrowError(
|
||||
'StaticInjectorError(DynamicTestModule)[SomeService -> Dep]: \n' +
|
||||
' StaticInjectorError(Platform: core)[SomeService -> Dep]: \n' +
|
||||
' NullInjectorError: No provider for Dep!');
|
||||
});
|
||||
|
||||
it('should inject from a parent element in a parent view', () => {
|
||||
createAndGetRootNodes(compViewDef([
|
||||
|
@ -181,16 +183,17 @@ import {fixmeIvy} from '@angular/private/testing';
|
|||
expect(instance.dep instanceof Dep).toBeTruthy();
|
||||
});
|
||||
|
||||
fixmeIvy('unknown').it('should throw for missing dependencies', () => {
|
||||
expect(() => createAndGetRootNodes(compViewDef([
|
||||
elementDef(0, NodeFlags.None, null, null, 1, 'span'),
|
||||
directiveDef(1, NodeFlags.None, null, 0, SomeService, ['nonExistingDep'])
|
||||
])))
|
||||
.toThrowError(
|
||||
'StaticInjectorError(DynamicTestModule)[nonExistingDep]: \n' +
|
||||
' StaticInjectorError(Platform: core)[nonExistingDep]: \n' +
|
||||
' NullInjectorError: No provider for nonExistingDep!');
|
||||
});
|
||||
fixmeIvy('FW-807: NgModule injector don\'t report full search path if a token is not found')
|
||||
.it('should throw for missing dependencies', () => {
|
||||
expect(() => createAndGetRootNodes(compViewDef([
|
||||
elementDef(0, NodeFlags.None, null, null, 1, 'span'),
|
||||
directiveDef(1, NodeFlags.None, null, 0, SomeService, ['nonExistingDep'])
|
||||
])))
|
||||
.toThrowError(
|
||||
'StaticInjectorError(DynamicTestModule)[nonExistingDep]: \n' +
|
||||
' StaticInjectorError(Platform: core)[nonExistingDep]: \n' +
|
||||
' NullInjectorError: No provider for nonExistingDep!');
|
||||
});
|
||||
|
||||
it('should use null for optional missing dependencies', () => {
|
||||
createAndGetRootNodes(compViewDef([
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {ApplicationInitStatus, Component, Directive, Injector, NgModule, NgZone, Pipe, PlatformRef, Provider, RendererFactory2, SchemaMetadata, Type, ɵInjectableDef as InjectableDef, ɵNgModuleDef as NgModuleDef, ɵNgModuleTransitiveScopes as NgModuleTransitiveScopes, ɵRender3ComponentFactory as ComponentFactory, ɵRender3NgModuleRef as NgModuleRef, ɵcompileComponent as compileComponent, ɵcompileDirective as compileDirective, ɵcompileNgModuleDefs as compileNgModuleDefs, ɵcompilePipe as compilePipe, ɵgetInjectableDef as getInjectableDef, ɵpatchComponentDefWithScope as patchComponentDefWithScope, ɵstringify as stringify} from '@angular/core';
|
||||
import {ApplicationInitStatus, Component, Directive, Injector, NgModule, NgZone, Pipe, PlatformRef, Provider, SchemaMetadata, Type, ɵInjectableDef as InjectableDef, ɵNgModuleDef as NgModuleDef, ɵNgModuleTransitiveScopes as NgModuleTransitiveScopes, ɵRender3ComponentFactory as ComponentFactory, ɵRender3NgModuleRef as NgModuleRef, ɵcompileComponent as compileComponent, ɵcompileDirective as compileDirective, ɵcompileNgModuleDefs as compileNgModuleDefs, ɵcompilePipe as compilePipe, ɵgetInjectableDef as getInjectableDef, ɵpatchComponentDefWithScope as patchComponentDefWithScope, ɵstringify as stringify} from '@angular/core';
|
||||
|
||||
import {ComponentFixture} from './component_fixture';
|
||||
import {MetadataOverride} from './metadata_override';
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {ApplicationInitStatus, CompilerOptions, Component, Directive, Injector, NgModule, NgModuleFactory, NgModuleRef, NgZone, Optional, Pipe, PlatformRef, Provider, SchemaMetadata, SkipSelf, StaticProvider, Type, ɵAPP_ROOT as APP_ROOT, ɵDepFlags as DepFlags, ɵInjectableDef as InjectableDef, ɵNodeFlags as NodeFlags, ɵclearOverrides as clearOverrides, ɵgetComponentViewDefinitionFactory as getComponentViewDefinitionFactory, ɵgetInjectableDef as getInjectableDef, ɵivyEnabled as ivyEnabled, ɵoverrideComponentView as overrideComponentView, ɵoverrideProvider as overrideProvider, ɵstringify as stringify} from '@angular/core';
|
||||
import {ApplicationInitStatus, CompilerOptions, Component, Directive, Injector, NgModule, NgModuleFactory, NgModuleRef, NgZone, Optional, Pipe, PlatformRef, Provider, SchemaMetadata, SkipSelf, StaticProvider, Type, ɵAPP_ROOT as APP_ROOT, ɵDepFlags as DepFlags, ɵInjectableDef as InjectableDef, ɵNodeFlags as NodeFlags, ɵclearOverrides as clearOverrides, ɵgetInjectableDef as getInjectableDef, ɵivyEnabled as ivyEnabled, ɵoverrideComponentView as overrideComponentView, ɵoverrideProvider as overrideProvider, ɵstringify as stringify} from '@angular/core';
|
||||
|
||||
import {AsyncTestCompleter} from './async_test_completer';
|
||||
import {ComponentFixture} from './component_fixture';
|
||||
|
@ -15,6 +15,7 @@ import {TestBedRender3, _getTestBedRender3} from './r3_test_bed';
|
|||
import {ComponentFixtureAutoDetect, ComponentFixtureNoNgZone, TestBedStatic, TestComponentRenderer, TestModuleMetadata} from './test_bed_common';
|
||||
import {TestingCompiler, TestingCompilerFactory} from './test_compiler';
|
||||
|
||||
|
||||
const UNDEFINED = new Object();
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue