test(ivy): update root causes for @angular/core TestBed failures (#27602)

PR Close #27602
This commit is contained in:
Pawel Kozlowski 2018-12-11 16:53:59 +01:00 committed by Alex Rickabaugh
parent 452668b581
commit 6980631631
1 changed files with 156 additions and 149 deletions

View File

@ -537,28 +537,28 @@ const TEST_COMPILER_PROVIDERS: Provider[] = [
expect(renderLog.log).toEqual(['someProp=Megatron']); expect(renderLog.log).toEqual(['someProp=Megatron']);
})); }));
fixmeIvy('unknown').it( fixmeIvy('FW-820: Pipes returning WrappedValue corrupt unrelated bindings ')
'should record unwrapped values via ngOnChanges', fakeAsync(() => { .it('should record unwrapped values via ngOnChanges', fakeAsync(() => {
const ctx = createCompFixture( const ctx = createCompFixture(
'<div [testDirective]="\'aName\' | wrappedPipe" [a]="1" [b]="2 | wrappedPipe"></div>'); '<div [testDirective]="\'aName\' | wrappedPipe" [a]="1" [b]="2 | wrappedPipe"></div>');
const dir: TestDirective = queryDirs(ctx.debugElement, TestDirective)[0]; const dir: TestDirective = queryDirs(ctx.debugElement, TestDirective)[0];
ctx.detectChanges(false); ctx.detectChanges(false);
dir.changes = {}; dir.changes = {};
ctx.detectChanges(false); ctx.detectChanges(false);
// Note: the binding for `b` did not change and has no ValueWrapper, // Note: the binding for `b` did not change and has no ValueWrapper,
// and should therefore stay unchanged. // and should therefore stay unchanged.
expect(dir.changes).toEqual({ expect(dir.changes).toEqual({
'name': new SimpleChange('aName', 'aName', false), 'name': new SimpleChange('aName', 'aName', false),
'b': new SimpleChange(2, 2, false) 'b': new SimpleChange(2, 2, false)
}); });
ctx.detectChanges(false); ctx.detectChanges(false);
expect(dir.changes).toEqual({ expect(dir.changes).toEqual({
'name': new SimpleChange('aName', 'aName', false), 'name': new SimpleChange('aName', 'aName', false),
'b': new SimpleChange(2, 2, false) 'b': new SimpleChange(2, 2, false)
}); });
})); }));
it('should call pure pipes only if the arguments change', fakeAsync(() => { it('should call pure pipes only if the arguments change', fakeAsync(() => {
const ctx = _bindSimpleValue('name | countingPipe', Person); const ctx = _bindSimpleValue('name | countingPipe', Person);
@ -589,30 +589,30 @@ const TEST_COMPILER_PROVIDERS: Provider[] = [
})); }));
fixmeIvy('unknown').it( fixmeIvy('FW-821: Pure pipes are instantiated differently in view engine and ivy')
'should call pure pipes that are used multiple times only when the arguments change', .it('should call pure pipes that are used multiple times only when the arguments change',
fakeAsync(() => { fakeAsync(() => {
const ctx = createCompFixture( const ctx = createCompFixture(
`<div [someProp]="name | countingPipe"></div><div [someProp]="age | countingPipe"></div>` + `<div [someProp]="name | countingPipe"></div><div [someProp]="age | countingPipe"></div>` +
'<div *ngFor="let x of [1,2]" [someProp]="address.city | countingPipe"></div>', '<div *ngFor="let x of [1,2]" [someProp]="address.city | countingPipe"></div>',
Person); Person);
ctx.componentInstance.name = 'a'; ctx.componentInstance.name = 'a';
ctx.componentInstance.age = 10; ctx.componentInstance.age = 10;
ctx.componentInstance.address = new Address('mtv'); ctx.componentInstance.address = new Address('mtv');
ctx.detectChanges(false); ctx.detectChanges(false);
expect(renderLog.loggedValues).toEqual([ expect(renderLog.loggedValues).toEqual([
'mtv state:0', 'mtv state:1', 'a state:2', '10 state:3' 'mtv state:0', 'mtv state:1', 'a state:2', '10 state:3'
]); ]);
ctx.detectChanges(false); ctx.detectChanges(false);
expect(renderLog.loggedValues).toEqual([ expect(renderLog.loggedValues).toEqual([
'mtv state:0', 'mtv state:1', 'a state:2', '10 state:3' 'mtv state:0', 'mtv state:1', 'a state:2', '10 state:3'
]); ]);
ctx.componentInstance.age = 11; ctx.componentInstance.age = 11;
ctx.detectChanges(false); ctx.detectChanges(false);
expect(renderLog.loggedValues).toEqual([ expect(renderLog.loggedValues).toEqual([
'mtv state:0', 'mtv state:1', 'a state:2', '10 state:3', '11 state:4' 'mtv state:0', 'mtv state:1', 'a state:2', '10 state:3', '11 state:4'
]); ]);
})); }));
it('should call impure pipes on each change detection run', fakeAsync(() => { it('should call impure pipes on each change detection run', fakeAsync(() => {
const ctx = _bindSimpleValue('name | countingImpurePipe', Person); const ctx = _bindSimpleValue('name | countingImpurePipe', Person);
@ -1076,110 +1076,114 @@ const TEST_COMPILER_PROVIDERS: Provider[] = [
}); });
describe('ngOnDestroy', () => { describe('ngOnDestroy', () => {
fixmeIvy('unknown').it( fixmeIvy('FW-763: LView tree not properly constructed / destroyed')
'should be called on view destruction', fakeAsync(() => { .it('should be called on view destruction', fakeAsync(() => {
const ctx = createCompFixture('<div testDirective="dir"></div>'); const ctx = createCompFixture('<div testDirective="dir"></div>');
ctx.detectChanges(false); ctx.detectChanges(false);
ctx.destroy(); ctx.destroy();
expect(directiveLog.filter(['ngOnDestroy'])).toEqual(['dir.ngOnDestroy']); expect(directiveLog.filter(['ngOnDestroy'])).toEqual(['dir.ngOnDestroy']);
})); }));
fixmeIvy('unknown').it( fixmeIvy('FW-763: LView tree not properly constructed / destroyed')
'should be called after processing the content and view children', fakeAsync(() => { .it('should be called after processing the content and view children', fakeAsync(() => {
TestBed.overrideComponent(AnotherComponent, { TestBed.overrideComponent(AnotherComponent, {
set: new Component( set: new Component({
{selector: 'other-cmp', template: '<div testDirective="viewChild"></div>'}) selector: 'other-cmp',
}); template: '<div testDirective="viewChild"></div>'
})
});
const ctx = createCompFixture( const ctx = createCompFixture(
'<div testDirective="parent"><div *ngFor="let x of [0,1]" testDirective="contentChild{{x}}"></div>' + '<div testDirective="parent"><div *ngFor="let x of [0,1]" testDirective="contentChild{{x}}"></div>' +
'<other-cmp></other-cmp></div>', '<other-cmp></other-cmp></div>',
TestComponent); TestComponent);
ctx.detectChanges(false); ctx.detectChanges(false);
ctx.destroy(); ctx.destroy();
expect(directiveLog.filter(['ngOnDestroy'])).toEqual([ expect(directiveLog.filter(['ngOnDestroy'])).toEqual([
'contentChild0.ngOnDestroy', 'contentChild1.ngOnDestroy', 'viewChild.ngOnDestroy', 'contentChild0.ngOnDestroy', 'contentChild1.ngOnDestroy',
'parent.ngOnDestroy' 'viewChild.ngOnDestroy', 'parent.ngOnDestroy'
]); ]);
})); }));
fixmeIvy('unknown').it( fixmeIvy('FW-763: LView tree not properly constructed / destroyed')
'should be called in reverse order so the child is always notified before the parent', .it('should be called in reverse order so the child is always notified before the parent',
fakeAsync(() => { fakeAsync(() => {
const ctx = createCompFixture( const ctx = createCompFixture(
'<div testDirective="parent"><div testDirective="child"></div></div><div testDirective="sibling"></div>'); '<div testDirective="parent"><div testDirective="child"></div></div><div testDirective="sibling"></div>');
ctx.detectChanges(false); ctx.detectChanges(false);
ctx.destroy(); ctx.destroy();
expect(directiveLog.filter(['ngOnDestroy'])).toEqual([ expect(directiveLog.filter(['ngOnDestroy'])).toEqual([
'child.ngOnDestroy', 'parent.ngOnDestroy', 'sibling.ngOnDestroy' 'child.ngOnDestroy', 'parent.ngOnDestroy', 'sibling.ngOnDestroy'
]); ]);
})); }));
fixmeIvy('unknown').it( fixmeIvy('FW-763: LView tree not properly constructed / destroyed')
'should deliver synchronous events to parent', fakeAsync(() => { .it('should deliver synchronous events to parent', fakeAsync(() => {
const ctx = createCompFixture('<div (destroy)="a=$event" onDestroyDirective></div>'); const ctx =
createCompFixture('<div (destroy)="a=$event" onDestroyDirective></div>');
ctx.detectChanges(false); ctx.detectChanges(false);
ctx.destroy(); ctx.destroy();
expect(ctx.componentInstance.a).toEqual('destroyed'); expect(ctx.componentInstance.a).toEqual('destroyed');
})); }));
fixmeIvy('unknown').it('should call ngOnDestroy on pipes', fakeAsync(() => { fixmeIvy('FW-763: LView tree not properly constructed / destroyed')
const ctx = createCompFixture('{{true | pipeWithOnDestroy }}'); .it('should call ngOnDestroy on pipes', fakeAsync(() => {
const ctx = createCompFixture('{{true | pipeWithOnDestroy }}');
ctx.detectChanges(false); ctx.detectChanges(false);
ctx.destroy(); ctx.destroy();
expect(directiveLog.filter(['ngOnDestroy'])).toEqual([ expect(directiveLog.filter(['ngOnDestroy'])).toEqual([
'pipeWithOnDestroy.ngOnDestroy' 'pipeWithOnDestroy.ngOnDestroy'
]); ]);
})); }));
fixmeIvy('unknown').it('should call ngOnDestroy on an injectable class', fakeAsync(() => { fixmeIvy('FW-763: LView tree not properly constructed / destroyed')
TestBed.overrideDirective( .it('should call ngOnDestroy on an injectable class', fakeAsync(() => {
TestDirective, {set: {providers: [InjectableWithLifecycle]}}); TestBed.overrideDirective(
TestDirective, {set: {providers: [InjectableWithLifecycle]}});
const ctx = createCompFixture( const ctx = createCompFixture('<div testDirective="dir"></div>', TestComponent);
'<div testDirective="dir"></div>', TestComponent);
ctx.debugElement.children[0].injector.get(InjectableWithLifecycle); ctx.debugElement.children[0].injector.get(InjectableWithLifecycle);
ctx.detectChanges(false); ctx.detectChanges(false);
ctx.destroy(); ctx.destroy();
// We don't care about the exact order in this test. // We don't care about the exact order in this test.
expect(directiveLog.filter(['ngOnDestroy']).sort()).toEqual([ expect(directiveLog.filter(['ngOnDestroy']).sort()).toEqual([
'dir.ngOnDestroy', 'injectable.ngOnDestroy' 'dir.ngOnDestroy', 'injectable.ngOnDestroy'
]); ]);
})); }));
}); });
}); });
describe('enforce no new changes', () => { describe('enforce no new changes', () => {
fixmeIvy('unknown').it( fixmeIvy('FW-823: ComponentFixture.checkNoChanges doesn\'t throw under TestBed')
'should throw when a record gets changed after it has been checked', fakeAsync(() => { .it('should throw when a record gets changed after it has been checked', fakeAsync(() => {
@Directive({selector: '[changed]'}) @Directive({selector: '[changed]'})
class ChangingDirective { class ChangingDirective {
@Input() changed: any; @Input() changed: any;
} }
TestBed.configureTestingModule({declarations: [ChangingDirective]}); TestBed.configureTestingModule({declarations: [ChangingDirective]});
const ctx = createCompFixture('<div [someProp]="a" [changed]="b"></div>', TestData); const ctx = createCompFixture('<div [someProp]="a" [changed]="b"></div>', TestData);
ctx.componentInstance.b = 1; ctx.componentInstance.b = 1;
expect(() => ctx.checkNoChanges()) expect(() => ctx.checkNoChanges())
.toThrowError( .toThrowError(
/Previous value: 'changed: undefined'\. Current value: 'changed: 1'/g); /Previous value: 'changed: undefined'\. Current value: 'changed: 1'/g);
})); }));
fixmeIvy('unknown').it( fixmeIvy('unknown').it(
'should warn when the view has been created in a cd hook', fakeAsync(() => { 'should warn when the view has been created in a cd hook', fakeAsync(() => {
@ -1198,14 +1202,15 @@ const TEST_COMPILER_PROVIDERS: Provider[] = [
expect(() => ctx.checkNoChanges()).not.toThrow(); expect(() => ctx.checkNoChanges()).not.toThrow();
})); }));
fixmeIvy('unknown').it('should not break the next run', fakeAsync(() => { fixmeIvy('FW-823: ComponentFixture.checkNoChanges doesn\'t throw under TestBed')
const ctx = _bindSimpleValue('a', TestData); .it('should not break the next run', fakeAsync(() => {
ctx.componentInstance.a = 'value'; const ctx = _bindSimpleValue('a', TestData);
expect(() => ctx.checkNoChanges()).toThrow(); ctx.componentInstance.a = 'value';
expect(() => ctx.checkNoChanges()).toThrow();
ctx.detectChanges(); ctx.detectChanges();
expect(renderLog.loggedValues).toEqual(['value']); expect(renderLog.loggedValues).toEqual(['value']);
})); }));
}); });
describe('mode', () => { describe('mode', () => {
@ -1271,36 +1276,38 @@ const TEST_COMPILER_PROVIDERS: Provider[] = [
})); }));
fixmeIvy('unknown').it('Reattaches in the original cd mode', fakeAsync(() => { fixmeIvy(
const ctx = createCompFixture('<push-cmp></push-cmp>'); 'FW-764: fixture.detectChanges() is not respecting OnPush flag on components in the root template')
const cmp: PushComp = queryDirs(ctx.debugElement, PushComp)[0]; .it('Reattaches in the original cd mode', fakeAsync(() => {
cmp.changeDetectorRef.detach(); const ctx = createCompFixture('<push-cmp></push-cmp>');
cmp.changeDetectorRef.reattach(); const cmp: PushComp = queryDirs(ctx.debugElement, PushComp)[0];
cmp.changeDetectorRef.detach();
cmp.changeDetectorRef.reattach();
// renderCount should NOT be incremented with each CD as CD mode // renderCount should NOT be incremented with each CD as CD mode
// should be resetted to // should be resetted to
// on-push // on-push
ctx.detectChanges(); ctx.detectChanges();
expect(cmp.renderCount).toBeGreaterThan(0); expect(cmp.renderCount).toBeGreaterThan(0);
const count = cmp.renderCount; const count = cmp.renderCount;
ctx.detectChanges(); ctx.detectChanges();
expect(cmp.renderCount).toBe(count); expect(cmp.renderCount).toBe(count);
})); }));
}); });
describe('multi directive order', () => { describe('multi directive order', () => {
fixmeIvy('unknown').it( fixmeIvy('FW-822: Order of bindings to directive inputs different in ivy')
'should follow the DI order for the same element', fakeAsync(() => { .it('should follow the DI order for the same element', fakeAsync(() => {
const ctx = const ctx = createCompFixture(
createCompFixture('<div orderCheck2="2" orderCheck0="0" orderCheck1="1"></div>'); '<div orderCheck2="2" orderCheck0="0" orderCheck1="1"></div>');
ctx.detectChanges(false); ctx.detectChanges(false);
ctx.destroy(); ctx.destroy();
expect(directiveLog.filter(['set'])).toEqual(['0.set', '1.set', '2.set']); expect(directiveLog.filter(['set'])).toEqual(['0.set', '1.set', '2.set']);
})); }));
}); });
describe('nested view recursion', () => { describe('nested view recursion', () => {