diff --git a/packages/core/test/acceptance/BUILD.bazel b/packages/core/test/acceptance/BUILD.bazel new file mode 100644 index 0000000000..6ef8cb8dd6 --- /dev/null +++ b/packages/core/test/acceptance/BUILD.bazel @@ -0,0 +1,35 @@ +package(default_visibility = ["//visibility:private"]) + +load("//tools:defaults.bzl", "jasmine_node_test", "ts_library") + +ts_library( + name = "acceptance_lib", + testonly = True, + srcs = glob( + ["**/*.ts"], + ), + deps = [ + "//packages/common", + "//packages/compiler", + "//packages/compiler/testing", + "//packages/core", + "//packages/core/testing", + "//packages/platform-browser", + "//packages/platform-browser-dynamic", + "//packages/platform-browser/testing", + "//packages/private/testing", + "@ngdeps//zone.js", + ], +) + +jasmine_node_test( + name = "acceptance", + bootstrap = ["angular/tools/testing/init_node_spec.js"], + deps = [ + ":acceptance_lib", + "//tools/testing:node", + "@ngdeps//base64-js", + "@ngdeps//source-map", + "@ngdeps//zone.js", + ], +) diff --git a/packages/core/test/acceptance/exports_spec.ts b/packages/core/test/acceptance/exports_spec.ts new file mode 100644 index 0000000000..0945171357 --- /dev/null +++ b/packages/core/test/acceptance/exports_spec.ts @@ -0,0 +1,82 @@ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * 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 {Component, Directive, Input, Type} from '@angular/core'; +import {TestBed} from '@angular/core/testing'; +import {onlyInIvy} from '@angular/private/testing'; + +describe('exports', () => { + beforeEach(() => { + TestBed.configureTestingModule( + {declarations: [AppComp, ComponentToReference, DirToReference, DirWithCompInput]}); + }); + + it('should support export of DOM element', () => { + const fixture = initWithTemplate(AppComp, ' {{ myInput.value }}'); + fixture.detectChanges(); + + expect(fixture.nativeElement.innerHTML).toEqual(' one'); + }); + + it('should support basic export of component', () => { + const fixture = + initWithTemplate(AppComp, ' {{ myComp.name }}'); + fixture.detectChanges(); + expect(fixture.nativeElement.innerHTML).toEqual(' Nancy'); + }); + + it('should work with directives with exportAs set', () => { + const fixture = initWithTemplate(AppComp, '
{{ myDir.name }}'); + fixture.detectChanges(); + expect(fixture.nativeElement.innerHTML).toEqual('
Drew'); + }); + + onlyInIvy('Different error message is thrown in View Engine') + .it('should throw if export name is not found', () => { + expect(() => { + const fixture = initWithTemplate(AppComp, '
'); + fixture.detectChanges(); + }).toThrowError(/Export of name 'dir' not found!/); + }); + + it('should support component instance fed into directive', () => { + const fixture = initWithTemplate( + AppComp, '
'); + fixture.detectChanges(); + + const myComp = fixture.debugElement.children[0].injector.get(ComponentToReference); + const dirWithInput = fixture.debugElement.children[1].injector.get(DirWithCompInput); + + expect(dirWithInput.comp).toEqual(myComp); + }); + +}); + +function initWithTemplate(compType: Type, template: string) { + TestBed.overrideComponent(compType, {set: new Component({template})}); + return TestBed.createComponent(compType); +} + +@Component({selector: 'comp-to-ref', template: ''}) +class ComponentToReference { + name = 'Nancy'; +} + +@Component({selector: 'app-comp', template: ``}) +class AppComp { +} + +@Directive({selector: '[dir]', exportAs: 'dir'}) +class DirToReference { + name = 'Drew'; +} + +@Directive({selector: '[dirWithInput]'}) +class DirWithCompInput { + @Input('dirWithInput') comp: ComponentToReference|null = null; +} diff --git a/packages/core/test/render3/exports_spec.ts b/packages/core/test/render3/exports_spec.ts index da2928230c..c8cab82482 100644 --- a/packages/core/test/render3/exports_spec.ts +++ b/packages/core/test/render3/exports_spec.ts @@ -14,140 +14,7 @@ import {NgIf} from './common_with_def'; import {ComponentFixture, createComponent, renderToHtml} from './render_util'; describe('exports', () => { - it('should support export of DOM element', () => { - - /** {{ myInput.value }} */ - const App = createComponent('app', function(rf: RenderFlags, ctx: any) { - if (rf & RenderFlags.Create) { - element(0, 'input', ['value', 'one'], ['myInput', '']); - text(2); - } - if (rf & RenderFlags.Update) { - const tmp = reference(1) as any; - textBinding(2, bind(tmp.value)); - } - }, 3, 1); - - const fixture = new ComponentFixture(App); - expect(fixture.html).toEqual('one'); - }); - - it('should support basic export of component', () => { - class MyComponent { - name = 'Nancy'; - - static ngComponentDef = defineComponent({ - type: MyComponent, - selectors: [['comp']], - consts: 0, - vars: 0, - template: function() {}, - factory: () => new MyComponent - }); - } - - /** {{ myComp.name }} */ - const App = createComponent('app', function(rf: RenderFlags, ctx: any) { - if (rf & RenderFlags.Create) { - element(0, 'comp', null, ['myComp', '']); - text(2); - } - if (rf & RenderFlags.Update) { - const tmp = reference(1) as any; - textBinding(2, tmp.name); - } - }, 3, 1, [MyComponent]); - - const fixture = new ComponentFixture(App); - expect(fixture.html).toEqual('Nancy'); - }); - - it('should support component instance fed into directive', () => { - - let myComponent: MyComponent; - let myDir: MyDir; - class MyComponent { - constructor() { myComponent = this; } - static ngComponentDef = defineComponent({ - type: MyComponent, - selectors: [['comp']], - consts: 0, - vars: 0, - template: function() {}, - factory: () => new MyComponent - }); - } - - class MyDir { - // TODO(issue/24571): remove '!'. - myDir !: MyComponent; - constructor() { myDir = this; } - static ngDirectiveDef = defineDirective({ - type: MyDir, - selectors: [['', 'myDir', '']], - factory: () => new MyDir, - inputs: {myDir: 'myDir'} - }); - } - - const defs = [MyComponent, MyDir]; - - /**
*/ - const App = createComponent('app', function(rf: RenderFlags, ctx: any) { - if (rf & RenderFlags.Create) { - element(0, 'comp', null, ['myComp', '']); - element(2, 'div', ['myDir', '']); - } - if (rf & RenderFlags.Update) { - const tmp = reference(1) as any; - elementProperty(2, 'myDir', bind(tmp)); - } - }, 3, 1, defs); - - const fixture = new ComponentFixture(App); - expect(myDir !.myDir).toEqual(myComponent !); - }); - - it('should work with directives with exportAs set', () => { - class SomeDir { - name = 'Drew'; - static ngDirectiveDef = defineDirective({ - type: SomeDir, - selectors: [['', 'someDir', '']], - factory: () => new SomeDir, - exportAs: ['someDir'] - }); - } - - /**
{{ myDir.name }} */ - const App = createComponent('app', function(rf: RenderFlags, ctx: any) { - if (rf & RenderFlags.Create) { - element(0, 'div', ['someDir', ''], ['myDir', 'someDir']); - text(2); - } - if (rf & RenderFlags.Update) { - const tmp = reference(1) as any; - textBinding(2, bind(tmp.name)); - } - }, 3, 1, [SomeDir]); - - const fixture = new ComponentFixture(App); - expect(fixture.html).toEqual('
Drew'); - }); - - it('should throw if export name is not found', () => { - - /**
*/ - const App = createComponent('app', function(rf: RenderFlags, ctx: any) { - if (rf & RenderFlags.Create) { - element(0, 'div', null, ['myDir', 'someDir']); - } - }, 1); - - expect(() => { - const fixture = new ComponentFixture(App); - }).toThrowError(/Export of name 'someDir' not found!/); - }); + // For basic use cases, see core/test/acceptance/exports_spec.ts. describe('forward refs', () => { it('should work with basic text bindings', () => {