From cc2f175617dae7a7cb95a61ae00033ba67a2fbbd Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Sat, 11 May 2019 08:50:12 -0400 Subject: [PATCH] test(ivy): move discovery_utils tests to acceptance (#30416) Rewrites the discovery util tests to use `TestBed`. PR Close #30416 --- .../discover_utils_spec.ts} | 359 +++++------------- 1 file changed, 95 insertions(+), 264 deletions(-) rename packages/core/test/{render3/discovery_utils_spec.ts => acceptance/discover_utils_spec.ts} (51%) diff --git a/packages/core/test/render3/discovery_utils_spec.ts b/packages/core/test/acceptance/discover_utils_spec.ts similarity index 51% rename from packages/core/test/render3/discovery_utils_spec.ts rename to packages/core/test/acceptance/discover_utils_spec.ts index ac6acb306d..d55eb3d91d 100644 --- a/packages/core/test/render3/discovery_utils_spec.ts +++ b/packages/core/test/acceptance/discover_utils_spec.ts @@ -5,16 +5,15 @@ * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ -import {StaticInjector} from '../../src/di/injector'; -import {createInjector} from '../../src/di/r3_injector'; -import {AttributeMarker, RenderFlags, getHostElement, ɵɵProvidersFeature, ɵɵdefineComponent, ɵɵdefineDirective, ɵɵelementContainerEnd, ɵɵelementContainerStart, ɵɵi18n, ɵɵi18nApply, ɵɵi18nExp, ɵɵselect} from '../../src/render3/index'; -import {markDirty, ɵɵbind, ɵɵelement, ɵɵelementEnd, ɵɵelementProperty, ɵɵelementStart, ɵɵlistener, ɵɵstyling, ɵɵstylingApply, ɵɵtemplate, ɵɵtext, ɵɵtextBinding} from '../../src/render3/instructions/all'; +import {CommonModule} from '@angular/common'; +import {Component, Directive, InjectionToken, ViewChild} from '@angular/core'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {onlyInIvy} from '@angular/private/testing'; + +import {getHostElement, markDirty} from '../../src/render3/index'; import {getComponent, getContext, getDirectives, getInjectionTokens, getInjector, getListeners, getLocalRefs, getRootComponents, getViewComponent, loadLContext} from '../../src/render3/util/discovery_utils'; -import {NgIf} from './common_with_def'; -import {ComponentFixture} from './render_util'; - -describe('discovery utils', () => { +onlyInIvy('Ivy-specific utilities').describe('discovery utils', () => { let fixture: ComponentFixture; let myApp: MyApp; let dirA: DirectiveA[]; @@ -29,115 +28,46 @@ describe('discovery utils', () => { log = []; dirA = []; childComponent = []; - fixture = new ComponentFixture( - MyApp, {injector: createInjector(null, null, [{provide: String, useValue: 'Module'}])}); - child = fixture.hostElement.querySelectorAll('child'); - span = fixture.hostElement.querySelectorAll('span'); - div = fixture.hostElement.querySelectorAll('div'); - p = fixture.hostElement.querySelectorAll('p'); + TestBed.configureTestingModule({ + imports: [CommonModule], + declarations: [MyApp, DirectiveA, Child], + providers: [{provide: String, useValue: 'Module'}] + }); + fixture = TestBed.createComponent(MyApp); + fixture.detectChanges(); + child = fixture.nativeElement.querySelectorAll('child'); + span = fixture.nativeElement.querySelectorAll('span'); + div = fixture.nativeElement.querySelectorAll('div'); + p = fixture.nativeElement.querySelectorAll('p'); }); - /** - * For all tests assume this set up - * - * ``` - * - * <#VIEW> - * {{text}} - *
- * - * <#VIEW> - *

- * - *
- * - * <#VIEW> - *

- * - *
- * - * <#VIEW> - *

- * - *
- * ICU expression - * - *
- * ``` - */ + @Component( + {selector: 'child', template: '

', providers: [{provide: String, useValue: 'Child'}]}) class Child { constructor() { childComponent.push(this); } - - static ngComponentDef = ɵɵdefineComponent({ - type: Child, - selectors: [['child']], - factory: () => new Child(), - consts: 1, - vars: 0, - template: (rf: RenderFlags, ctx: Child) => { - if (rf & RenderFlags.Create) { - ɵɵelement(0, 'p'); - } - }, - features: [ɵɵProvidersFeature([{provide: String, useValue: 'Child'}])] - }); } + @Directive({selector: '[dirA]', exportAs: 'dirA'}) class DirectiveA { constructor() { dirA.push(this); } - - static ngDirectiveDef = ɵɵdefineDirective({ - type: DirectiveA, - selectors: [['', 'dirA', '']], - exportAs: ['dirA'], - factory: () => new DirectiveA(), - }); } - const MSG_DIV = `{�0�, select, - other {ICU expression} - }`; - + @Component({ + selector: 'my-app', + template: ` + {{text}} +
+ + + +

+ ` + }) class MyApp { text: string = 'INIT'; constructor() { myApp = this; } - static ngComponentDef = ɵɵdefineComponent({ - type: MyApp, - selectors: [['my-app']], - factory: () => new MyApp(), - consts: 13, - vars: 1, - directives: [Child, DirectiveA, NgIf], - template: (rf: RenderFlags, ctx: MyApp) => { - if (rf & RenderFlags.Create) { - ɵɵelementStart(0, 'span'); - ɵɵlistener('click', $event => log.push($event)); - ɵɵtext(1); - ɵɵelementEnd(); - ɵɵelement(2, 'div', ['dirA', ''], ['div', '', 'foo', 'dirA']); - ɵɵelement(5, 'child'); - ɵɵelement(6, 'child', ['dirA', ''], ['child', '']); - ɵɵtemplate(8, function(rf: RenderFlags, ctx: never) { - if (rf & RenderFlags.Create) { - ɵɵelement(0, 'child'); - } - }, 1, 0, 'child', ['dirA', AttributeMarker.Template, 'ngIf']); - ɵɵelementStart(9, 'i18n'); - ɵɵi18n(10, MSG_DIV); - ɵɵelementEnd(); - ɵɵelementContainerStart(11); - { ɵɵtext(12, 'content'); } - ɵɵelementContainerEnd(); - } - if (rf & RenderFlags.Update) { - ɵɵtextBinding(1, ɵɵbind(ctx.text)); - ɵɵelementProperty(8, 'ngIf', ɵɵbind(true)); - ɵɵi18nExp(ɵɵbind(ctx.text)); - ɵɵi18nApply(10); - } - } - }); + log(event: any) { log.push(event); } } describe('getComponent', () => { @@ -151,7 +81,7 @@ describe('discovery utils', () => { expect(() => getComponent(dirA[1] as any)).toThrowError(/Expecting instance of DOM Node/); }); it('should return component from element', () => { - expect(getComponent(fixture.hostElement)).toEqual(myApp); + expect(getComponent(fixture.nativeElement)).toEqual(myApp); expect(getComponent(child[0])).toEqual(childComponent[0]); expect(getComponent(child[1])).toEqual(childComponent[1]); }); @@ -171,7 +101,7 @@ describe('discovery utils', () => { describe('getHostElement', () => { it('should return element on component', () => { - expect(getHostElement(myApp)).toEqual(fixture.hostElement); + expect(getHostElement(myApp)).toEqual(fixture.nativeElement); expect(getHostElement(childComponent[0])).toEqual(child[0]); expect(getHostElement(childComponent[1])).toEqual(child[1]); }); @@ -186,7 +116,7 @@ describe('discovery utils', () => { describe('getInjector', () => { it('should return node-injector from element', () => { - expect(getInjector(fixture.hostElement).get(String)).toEqual('Module'); + expect(getInjector(fixture.nativeElement).get(String)).toEqual('Module'); expect(getInjector(child[0]).get(String)).toEqual('Child'); expect(getInjector(p[0]).get(String)).toEqual('Child'); }); @@ -203,7 +133,7 @@ describe('discovery utils', () => { describe('getDirectives', () => { it('should return empty array if no directives', () => { - expect(getDirectives(fixture.hostElement)).toEqual([]); + expect(getDirectives(fixture.nativeElement)).toEqual([]); expect(getDirectives(span[0])).toEqual([]); expect(getDirectives(child[0])).toEqual([]); }); @@ -215,7 +145,7 @@ describe('discovery utils', () => { describe('getViewComponent', () => { it('should return null when called on root component', () => { - expect(getViewComponent(fixture.hostElement)).toEqual(null); + expect(getViewComponent(fixture.nativeElement)).toEqual(null); expect(getViewComponent(myApp)).toEqual(null); }); it('should return containing component of child component', () => { @@ -242,7 +172,7 @@ describe('discovery utils', () => { describe('getLocalRefs', () => { it('should retrieve empty map', () => { - expect(getLocalRefs(fixture.hostElement)).toEqual({}); + expect(getLocalRefs(fixture.nativeElement)).toEqual({}); expect(getLocalRefs(myApp)).toEqual({}); expect(getLocalRefs(span[0])).toEqual({}); expect(getLocalRefs(child[0])).toEqual({}); @@ -274,7 +204,7 @@ describe('discovery utils', () => { describe('getListeners', () => { it('should return no listeners', () => { - expect(getListeners(fixture.hostElement)).toEqual([]); + expect(getListeners(fixture.nativeElement)).toEqual([]); expect(getListeners(child[0])).toEqual([]); }); it('should return the listeners', () => { @@ -290,7 +220,7 @@ describe('discovery utils', () => { describe('getInjectionTokens', () => { it('should retrieve tokens', () => { - expect(getInjectionTokens(fixture.hostElement)).toEqual([MyApp]); + expect(getInjectionTokens(fixture.nativeElement)).toEqual([MyApp]); expect(getInjectionTokens(child[0])).toEqual([String, Child]); expect(getInjectionTokens(child[1])).toEqual([String, Child, DirectiveA]); }); @@ -301,7 +231,7 @@ describe('discovery utils', () => { expect(span[0].textContent).toEqual('INIT'); myApp.text = 'WORKS'; markDirty(myApp); - fixture.requestAnimationFrame.flush(); + fixture.detectChanges(); expect(span[0].textContent).toEqual('WORKS'); }); }); @@ -314,23 +244,15 @@ describe('discovery utils', () => { }); it('should work on templates', () => { - const templateComment = Array.from(fixture.hostElement.childNodes) + const templateComment = Array.from(fixture.nativeElement.childNodes) .find((node: ChildNode) => node.nodeType === Node.COMMENT_NODE) !; const lContext = loadLContext(templateComment); expect(lContext).toBeDefined(); expect(lContext.native as any).toBe(templateComment); }); - it('should work on ICU expressions', () => { - const icuComment = Array.from(fixture.hostElement.querySelector('i18n') !.childNodes) - .find((node: ChildNode) => node.nodeType === Node.COMMENT_NODE) !; - const lContext = loadLContext(icuComment); - expect(lContext).toBeDefined(); - expect(lContext.native as any).toBe(icuComment); - }); - it('should work on ng-container', () => { - const ngContainerComment = Array.from(fixture.hostElement.childNodes) + const ngContainerComment = Array.from(fixture.nativeElement.childNodes) .find( (node: ChildNode) => node.nodeType === Node.COMMENT_NODE && node.textContent === `ng-container`) !; @@ -341,50 +263,26 @@ describe('discovery utils', () => { }); }); -describe('discovery utils deprecated', () => { - +onlyInIvy('Ivy-specific utilities').describe('discovery utils deprecated', () => { describe('getRootComponents()', () => { it('should return a list of the root components of the application from an element', () => { - let innerComp: InnerComp; + @Component({selector: 'inner-comp', template: '
'}) class InnerComp { - static ngComponentDef = ɵɵdefineComponent({ - type: InnerComp, - selectors: [['inner-comp']], - factory: () => innerComp = new InnerComp(), - consts: 1, - vars: 0, - template: (rf: RenderFlags, ctx: InnerComp) => { - if (rf & RenderFlags.Create) { - ɵɵelement(0, 'div'); - } - } - }); } + @Component({selector: 'comp', template: ''}) class Comp { - static ngComponentDef = ɵɵdefineComponent({ - type: Comp, - selectors: [['comp']], - factory: () => new Comp(), - consts: 1, - vars: 0, - template: (rf: RenderFlags, ctx: Comp) => { - if (rf & RenderFlags.Create) { - ɵɵelement(0, 'inner-comp'); - } - }, - directives: [InnerComp] - }); } - const fixture = new ComponentFixture(Comp); - fixture.update(); + TestBed.configureTestingModule({declarations: [Comp, InnerComp]}); + const fixture = TestBed.createComponent(Comp); + fixture.detectChanges(); - const hostElm = fixture.hostElement; + const hostElm = fixture.nativeElement; const innerElm = hostElm.querySelector('inner-comp') !; const divElm = hostElm.querySelector('div') !; - const component = fixture.component; + const component = fixture.componentInstance; expect(getRootComponents(hostElm) !).toEqual([component]); expect(getRootComponents(innerElm) !).toEqual([component]); @@ -394,65 +292,46 @@ describe('discovery utils deprecated', () => { describe('getDirectives()', () => { it('should return a list of the directives that are on the given element', () => { - let myDir1Instance: MyDir1|null = null; - let myDir2Instance: MyDir2|null = null; - let myDir3Instance: MyDir2|null = null; - + @Directive({selector: '[my-dir-1]'}) class MyDir1 { - static ngDirectiveDef = ɵɵdefineDirective({ - type: MyDir1, - selectors: [['', 'my-dir-1', '']], - factory: () => myDir1Instance = new MyDir1() - }); } + @Directive({selector: '[my-dir-2]'}) class MyDir2 { - static ngDirectiveDef = ɵɵdefineDirective({ - type: MyDir2, - selectors: [['', 'my-dir-2', '']], - factory: () => myDir2Instance = new MyDir2() - }); } + @Directive({selector: '[my-dir-3]'}) class MyDir3 { - static ngDirectiveDef = ɵɵdefineDirective({ - type: MyDir3, - selectors: [['', 'my-dir-3', '']], - factory: () => myDir3Instance = new MyDir2() - }); } + @Component({ + selector: 'comp', + template: ` +
+
+ ` + }) class Comp { - static ngComponentDef = ɵɵdefineComponent({ - type: Comp, - selectors: [['comp']], - factory: () => new Comp(), - consts: 2, - vars: 0, - template: (rf: RenderFlags, ctx: Comp) => { - if (rf & RenderFlags.Create) { - ɵɵelement(0, 'div', ['my-dir-1', '', 'my-dir-2', '']); - ɵɵelement(1, 'div', ['my-dir-3']); - } - }, - directives: [MyDir1, MyDir2, MyDir3] - }); + @ViewChild(MyDir1) myDir1Instance !: MyDir1; + @ViewChild(MyDir2) myDir2Instance !: MyDir2; + @ViewChild(MyDir3) myDir3Instance !: MyDir3; } - const fixture = new ComponentFixture(Comp); - fixture.update(); + TestBed.configureTestingModule({declarations: [Comp, MyDir1, MyDir2, MyDir3]}); + const fixture = TestBed.createComponent(Comp); + fixture.detectChanges(); - const hostElm = fixture.hostElement; + const hostElm = fixture.nativeElement; const elements = hostElm.querySelectorAll('div'); const elm1 = elements[0]; const elm1Dirs = getDirectives(elm1); - expect(elm1Dirs).toContain(myDir1Instance !); - expect(elm1Dirs).toContain(myDir2Instance !); + expect(elm1Dirs).toContain(fixture.componentInstance.myDir1Instance !); + expect(elm1Dirs).toContain(fixture.componentInstance.myDir2Instance !); const elm2 = elements[1]; const elm2Dirs = getDirectives(elm2); - expect(elm2Dirs).toContain(myDir3Instance !); + expect(elm2Dirs).toContain(fixture.componentInstance.myDir3Instance !); }); }); @@ -460,81 +339,48 @@ describe('discovery utils deprecated', () => { it('should return an injector that can return directive instances', () => { + @Component({template: ''}) class Comp { - static ngComponentDef = ɵɵdefineComponent({ - type: Comp, - selectors: [['comp']], - factory: () => new Comp(), - consts: 0, - vars: 0, - template: (rf: RenderFlags, ctx: Comp) => {} - }); } - const fixture = new ComponentFixture(Comp); - fixture.update(); - - const nodeInjector = getInjector(fixture.hostElement); + TestBed.configureTestingModule({declarations: [Comp]}); + const fixture = TestBed.createComponent(Comp); + const nodeInjector = getInjector(fixture.nativeElement); expect(nodeInjector.get(Comp)).toEqual(jasmine.any(Comp)); }); it('should return an injector that falls-back to a module injector', () => { - + @Component({template: ''}) class Comp { - static ngComponentDef = ɵɵdefineComponent({ - type: Comp, - selectors: [['comp']], - factory: () => new Comp(), - consts: 0, - vars: 0, - template: (rf: RenderFlags, ctx: Comp) => {} - }); } class TestToken {} + const token = new InjectionToken('test token'); - const staticInjector = new StaticInjector([{provide: TestToken, useValue: new TestToken()}]); - const fixture = new ComponentFixture(Comp, {injector: staticInjector}); - fixture.update(); - - const nodeInjector = getInjector(fixture.hostElement); - expect(nodeInjector.get(TestToken)).toEqual(jasmine.any(TestToken)); + TestBed.configureTestingModule( + {declarations: [Comp], providers: [{provide: token, useValue: new TestToken()}]}); + const fixture = TestBed.createComponent(Comp); + const nodeInjector = getInjector(fixture.nativeElement); + expect(nodeInjector.get(token)).toEqual(jasmine.any(TestToken)); }); }); describe('getLocalRefs', () => { it('should return a map of local refs for an element', () => { + @Directive({selector: '[myDir]', exportAs: 'myDir'}) class MyDir { - static ngDirectiveDef = ɵɵdefineDirective({ - type: MyDir, - selectors: [['', 'myDir', '']], - exportAs: ['myDir'], - factory: () => new MyDir() - }); } + @Component({template: '
'}) class Comp { - static ngComponentDef = ɵɵdefineComponent({ - type: Comp, - selectors: [['comp']], - factory: () => new Comp(), - consts: 3, - vars: 0, - template: (rf: RenderFlags, ctx: Comp) => { - if (rf & RenderFlags.Create) { - //
- ɵɵelement(0, 'div', ['myDir'], ['elRef', '', 'dirRef', 'myDir']); - } - }, - directives: [MyDir] - }); } - const fixture = new ComponentFixture(Comp); - fixture.update(); + TestBed.configureTestingModule({declarations: [Comp, MyDir]}); + const fixture = TestBed.createComponent(Comp); + fixture.detectChanges(); - const divEl = fixture.hostElement.querySelector('div') !; + const divEl = fixture.nativeElement.querySelector('div') !; const localRefs = getLocalRefs(divEl); expect(localRefs.elRef.tagName.toLowerCase()).toBe('div'); @@ -542,31 +388,16 @@ describe('discovery utils deprecated', () => { }); it('should return a map of local refs for an element with styling context', () => { + @Component({template: '
'}) class Comp { - static ngComponentDef = ɵɵdefineComponent({ - type: Comp, - selectors: [['comp']], - factory: () => new Comp(), - consts: 2, - vars: 0, - template: (rf: RenderFlags, ctx: Comp) => { - if (rf & RenderFlags.Create) { - //
- ɵɵelementStart(0, 'div', null, ['elRef', '']); - ɵɵelementEnd(); - } - if (rf & RenderFlags.Update) { - ɵɵselect(0); - ɵɵstylingApply(); - } - } - }); + color = 'red'; } - const fixture = new ComponentFixture(Comp); - fixture.update(); + TestBed.configureTestingModule({declarations: [Comp]}); + const fixture = TestBed.createComponent(Comp); + fixture.detectChanges(); - const divEl = fixture.hostElement.querySelector('div') !; + const divEl = fixture.nativeElement.querySelector('div') !; const localRefs = getLocalRefs(divEl); expect(localRefs.elRef.tagName.toLowerCase()).toBe('div');