test(ivy): move some local ref tests to use TestBed infrastructure. (#28534)
When we first started writing tests for Ivy, we did not yet have a compatible compiler. For this reason, we set up the Ivy runtime tests to run with generated code that we wrote by hand (instead of real code generated by the compiler). Now that we have a working Ivy compiler and TestBed infrastructure that is compatible with Ivy, we should start writing integration tests that leverage them (no more handwritten generated code!). This will prevent bugs where the compiler code and runtime code become out of sync (which is easy if they are tested separately). And eventually, we should migrate all the existing runtime tests in "core/test/render3" to TestBed and ngtsc. To kick off this effort, this commit migrates some existing tests from "core/test/render3/exports_spec.ts" and saves them in a new file with the same name in the "core/test/acceptance" folder. PR Close #28534
This commit is contained in:
parent
baf103c98f
commit
8f15cdbc7c
|
@ -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",
|
||||
],
|
||||
)
|
|
@ -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, '<input value="one" #myInput> {{ myInput.value }}');
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(fixture.nativeElement.innerHTML).toEqual('<input value="one"> one');
|
||||
});
|
||||
|
||||
it('should support basic export of component', () => {
|
||||
const fixture =
|
||||
initWithTemplate(AppComp, '<comp-to-ref #myComp></comp-to-ref> {{ myComp.name }}');
|
||||
fixture.detectChanges();
|
||||
expect(fixture.nativeElement.innerHTML).toEqual('<comp-to-ref></comp-to-ref> Nancy');
|
||||
});
|
||||
|
||||
it('should work with directives with exportAs set', () => {
|
||||
const fixture = initWithTemplate(AppComp, '<div dir #myDir="dir"></div> {{ myDir.name }}');
|
||||
fixture.detectChanges();
|
||||
expect(fixture.nativeElement.innerHTML).toEqual('<div dir=""></div> Drew');
|
||||
});
|
||||
|
||||
onlyInIvy('Different error message is thrown in View Engine')
|
||||
.it('should throw if export name is not found', () => {
|
||||
expect(() => {
|
||||
const fixture = initWithTemplate(AppComp, '<div #myDir="dir"></div>');
|
||||
fixture.detectChanges();
|
||||
}).toThrowError(/Export of name 'dir' not found!/);
|
||||
});
|
||||
|
||||
it('should support component instance fed into directive', () => {
|
||||
const fixture = initWithTemplate(
|
||||
AppComp, '<comp-to-ref #myComp></comp-to-ref> <div [dirWithInput]="myComp"></div>');
|
||||
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<any>, 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;
|
||||
}
|
|
@ -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', () => {
|
||||
|
||||
/** <input value="one" #myInput> {{ 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('<input value="one">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
|
||||
});
|
||||
}
|
||||
|
||||
/** <comp #myComp></comp> {{ 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('<comp></comp>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];
|
||||
|
||||
/** <comp #myComp></comp> <div [myDir]="myComp"></div> */
|
||||
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']
|
||||
});
|
||||
}
|
||||
|
||||
/** <div someDir #myDir="someDir"></div> {{ 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('<div somedir=""></div>Drew');
|
||||
});
|
||||
|
||||
it('should throw if export name is not found', () => {
|
||||
|
||||
/** <div #myDir="someDir"></div> */
|
||||
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', () => {
|
||||
|
|
Loading…
Reference in New Issue