From 8042140742708951f118501dc75a51b029513b1f Mon Sep 17 00:00:00 2001 From: Marc Laval Date: Thu, 13 Dec 2018 18:16:03 +0100 Subject: [PATCH] test(ivy): enable more @angular/core tests (#27654) PR Close #27654 --- packages/core/src/render3/di.ts | 2 +- packages/core/src/render3/util.ts | 2 + .../linker/view_injector_integration_spec.ts | 181 ++++++++++++------ .../private/testing/src/ivy_test_selectors.ts | 18 ++ 4 files changed, 143 insertions(+), 60 deletions(-) diff --git a/packages/core/src/render3/di.ts b/packages/core/src/render3/di.ts index d94b9172c3..74ee5aa5ef 100644 --- a/packages/core/src/render3/di.ts +++ b/packages/core/src/render3/di.ts @@ -308,7 +308,7 @@ export function getOrCreateInjectable( try { const value = bloomHash(); if (value == null && !(flags & InjectFlags.Optional)) { - throw new Error(`No provider for ${stringify(token)}`); + throw new Error(`No provider for ${stringify(token)}!`); } else { return value; } diff --git a/packages/core/src/render3/util.ts b/packages/core/src/render3/util.ts index 32c520bfa1..03c6fb29d4 100644 --- a/packages/core/src/render3/util.ts +++ b/packages/core/src/render3/util.ts @@ -35,6 +35,8 @@ export function stringify(value: any): string { if (typeof value == 'function') return value.name || value; if (typeof value == 'string') return value; if (value == null) return ''; + if (typeof value == 'object' && typeof value.type == 'function') + return value.type.name || value.type; return '' + value; } diff --git a/packages/core/test/linker/view_injector_integration_spec.ts b/packages/core/test/linker/view_injector_integration_spec.ts index f58ea53887..7748b3642e 100644 --- a/packages/core/test/linker/view_injector_integration_spec.ts +++ b/packages/core/test/linker/view_injector_integration_spec.ts @@ -10,7 +10,7 @@ import {Attribute, ChangeDetectionStrategy, ChangeDetectorRef, Component, Compon import {ComponentFixture, TestBed, fakeAsync} from '@angular/core/testing'; import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter'; import {expect} from '@angular/platform-browser/testing/src/matchers'; -import {fixmeIvy} from '@angular/private/testing'; +import {fixmeIvy, obsoleteInIvy, onlyInIvy} from '@angular/private/testing'; @Directive({selector: '[simpleDirective]'}) class SimpleDirective { @@ -598,57 +598,109 @@ class TestComp { expect(el.children[0].injector.get(NeedsAppService).service).toEqual('appService'); }); - fixmeIvy('unknown').it('should not instantiate a directive with cyclic dependencies', () => { - TestBed.configureTestingModule({declarations: [CycleDirective]}); - expect(() => createComponent('
')) - .toThrowError( - /Template parse errors:\nCannot instantiate cyclic dependency! CycleDirective \("\[ERROR ->\]
<\/div>"\): .*TestComp.html@0:0/); - }); - - fixmeIvy('unknown').it( - 'should not instantiate a directive in a view that has a host dependency on providers' + - ' of the component', - () => { - TestBed.configureTestingModule({declarations: [SimpleComponent, NeedsServiceFromHost]}); - TestBed.overrideComponent( - SimpleComponent, - {set: {providers: [{provide: 'service', useValue: 'hostService'}]}}); - TestBed.overrideComponent( - SimpleComponent, {set: {template: '
'}}); - - expect(() => createComponent('
')) + obsoleteInIvy('This error is no longer generated by the compiler') + .it('should not instantiate a directive with cyclic dependencies', () => { + TestBed.configureTestingModule({declarations: [CycleDirective]}); + expect(() => createComponent('
')) .toThrowError( - /Template parse errors:\nNo provider for service \("\[ERROR ->\]
"\): .*SimpleComponent.html@0:0/); + /Template parse errors:\nCannot instantiate cyclic dependency! CycleDirective \("\[ERROR ->\]
<\/div>"\): .*TestComp.html@0:0/); }); - fixmeIvy('unknown').it( - 'should not instantiate a directive in a view that has a host dependency on providers' + - ' of a decorator directive', - () => { - TestBed.configureTestingModule( - {declarations: [SimpleComponent, SomeOtherDirective, NeedsServiceFromHost]}); - TestBed.overrideComponent( - SimpleComponent, - {set: {providers: [{provide: 'service', useValue: 'hostService'}]}}); - TestBed.overrideComponent( - SimpleComponent, {set: {template: '
'}}); - - expect(() => createComponent('
')) - .toThrowError( - /Template parse errors:\nNo provider for service \("\[ERROR ->\]
"\): .*SimpleComponent.html@0:0/); + onlyInIvy('This error is generated by the runtime of Ivy') + .it('should not instantiate a directive with cyclic dependencies', () => { + TestBed.configureTestingModule({declarations: [CycleDirective]}); + expect(() => createComponent('
')) + .toThrowError('Circular dep for CycleDirective'); }); - fixmeIvy('unknown').it( - 'should not instantiate a directive in a view that has a self dependency on a parent directive', - () => { - TestBed.configureTestingModule( - {declarations: [SimpleDirective, NeedsDirectiveFromSelf]}); - expect( - () => createComponent( - '
')) - .toThrowError( - /Template parse errors:\nNo provider for SimpleDirective \("
\[ERROR ->\]
<\/div><\/div>"\): .*TestComp.html@0:21/); - }); + obsoleteInIvy('This error is no longer generated by the compiler') + .it('should not instantiate a directive in a view that has a host dependency on providers' + + ' of the component', + () => { + TestBed.configureTestingModule( + {declarations: [SimpleComponent, NeedsServiceFromHost]}); + TestBed.overrideComponent( + SimpleComponent, + {set: {providers: [{provide: 'service', useValue: 'hostService'}]}}); + TestBed.overrideComponent( + SimpleComponent, {set: {template: '
'}}); + + expect(() => createComponent('
')) + .toThrowError( + /Template parse errors:\nNo provider for service \("\[ERROR ->\]
"\): .*SimpleComponent.html@0:0/); + }); + + onlyInIvy('This error is generated by the runtime of Ivy') + .it('should not instantiate a directive in a view that has a host dependency on providers' + + ' of the component', + () => { + TestBed.configureTestingModule( + {declarations: [SimpleComponent, NeedsServiceFromHost]}); + TestBed.overrideComponent( + SimpleComponent, + {set: {providers: [{provide: 'service', useValue: 'hostService'}]}}); + TestBed.overrideComponent( + SimpleComponent, {set: {template: '
'}}); + + expect(() => createComponent('
')) + .toThrowError('NodeInjector: NOT_FOUND [service]'); + }); + + obsoleteInIvy('This error is no longer generated by the compiler') + .it('should not instantiate a directive in a view that has a host dependency on providers' + + ' of a decorator directive', + () => { + TestBed.configureTestingModule( + {declarations: [SimpleComponent, SomeOtherDirective, NeedsServiceFromHost]}); + TestBed.overrideComponent( + SimpleComponent, + {set: {providers: [{provide: 'service', useValue: 'hostService'}]}}); + TestBed.overrideComponent( + SimpleComponent, {set: {template: '
'}}); + + expect(() => createComponent('
')) + .toThrowError( + /Template parse errors:\nNo provider for service \("\[ERROR ->\]
"\): .*SimpleComponent.html@0:0/); + }); + + onlyInIvy('This error is generated by the runtime of Ivy') + .it('should not instantiate a directive in a view that has a host dependency on providers' + + ' of a decorator directive', + () => { + TestBed.configureTestingModule( + {declarations: [SimpleComponent, SomeOtherDirective, NeedsServiceFromHost]}); + TestBed.overrideComponent( + SimpleComponent, + {set: {providers: [{provide: 'service', useValue: 'hostService'}]}}); + TestBed.overrideComponent( + SimpleComponent, {set: {template: '
'}}); + + expect(() => createComponent('
')) + .toThrowError('NodeInjector: NOT_FOUND [service]'); + }); + + obsoleteInIvy('This error is no longer generated by the compiler') + .it('should not instantiate a directive in a view that has a self dependency on a parent directive', + () => { + TestBed.configureTestingModule( + {declarations: [SimpleDirective, NeedsDirectiveFromSelf]}); + expect( + () => createComponent( + '
')) + .toThrowError( + /Template parse errors:\nNo provider for SimpleDirective \("
\[ERROR ->\]
<\/div><\/div>"\): .*TestComp.html@0:21/); + }); + + onlyInIvy('This error is generated by the runtime of Ivy') + .it('should not instantiate a directive in a view that has a self dependency on a parent directive', + () => { + TestBed.configureTestingModule( + {declarations: [SimpleDirective, NeedsDirectiveFromSelf]}); + expect( + () => createComponent( + '
')) + .toThrowError('NodeInjector: NOT_FOUND [SimpleDirective]'); + }); it('should instantiate directives that depend on other directives', fakeAsync(() => { TestBed.configureTestingModule({declarations: [SimpleDirective, NeedsDirective]}); @@ -691,17 +743,28 @@ class TestComp { expect(el.componentInstance.service).toEqual('appService'); }); - fixmeIvy('unknown').it( - 'should not instantiate directives that depend on other directives on the host element', - () => { - TestBed.configureTestingModule( - {declarations: [SimpleComponent, SimpleDirective, NeedsDirectiveFromHost]}); - TestBed.overrideComponent( - SimpleComponent, {set: {template: '
'}}); - expect(() => createComponent('
')) - .toThrowError( - /Template parse errors:\nNo provider for SimpleDirective \("\[ERROR ->\]
<\/div>"\): .*SimpleComponent.html@0:0/); - }); + obsoleteInIvy('This error is no longer generated by the compiler') + .it('should not instantiate directives that depend on other directives on the host element', + () => { + TestBed.configureTestingModule( + {declarations: [SimpleComponent, SimpleDirective, NeedsDirectiveFromHost]}); + TestBed.overrideComponent( + SimpleComponent, {set: {template: '
'}}); + expect(() => createComponent('
')) + .toThrowError( + /Template parse errors:\nNo provider for SimpleDirective \("\[ERROR ->\]
<\/div>"\): .*SimpleComponent.html@0:0/); + }); + + onlyInIvy('This error is generated by the runtime of Ivy') + .it('should not instantiate directives that depend on other directives on the host element', + () => { + TestBed.configureTestingModule( + {declarations: [SimpleComponent, SimpleDirective, NeedsDirectiveFromHost]}); + TestBed.overrideComponent( + SimpleComponent, {set: {template: '
'}}); + expect(() => createComponent('
')) + .toThrowError('NodeInjector: NOT_FOUND [SimpleDirective]'); + }); fixmeIvy('unknown').it( 'should allow to use the NgModule injector from a root ViewContainerRef.parentInjector', @@ -884,7 +947,7 @@ class TestComp { .toEqual(el.childNodes[0].injector.get(NeedsViewContainerRef).viewContainer.element); }); - fixmeIvy('unknown').it('should throw if there is no TemplateRef', () => { + it('should throw if there is no TemplateRef', () => { TestBed.configureTestingModule({declarations: [NeedsTemplateRef]}); expect(() => createComponent('
')) .toThrowError(/No provider for TemplateRef!/); diff --git a/packages/private/testing/src/ivy_test_selectors.ts b/packages/private/testing/src/ivy_test_selectors.ts index 03b2756ab5..9111b61b45 100644 --- a/packages/private/testing/src/ivy_test_selectors.ts +++ b/packages/private/testing/src/ivy_test_selectors.ts @@ -79,6 +79,24 @@ export function obsoleteInIvy(reason: string): JasmineMethods { return ivyEnabled ? IGNORE : PASSTHROUGH; } +/** + * A function to conditionally skip the execution of tests that are not relevant when + * not running against Ivy. + * + * ``` + * onlyInIvy('some reason').describe(...); + * ``` + * + * or + * + * ``` + * onlyInIvy('some reason').it(...); + * ``` + */ +export function onlyInIvy(reason: string): JasmineMethods { + return ivyEnabled ? PASSTHROUGH : IGNORE; +} + /** * A function to conditionally skip the execution of tests that have intentionally * been broken when running against Ivy.