mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
test: update acceptance core tests to work with es2015 (#44505)
Updates the acceptance core tests to work with ES2015 devmode output. There were two issues surfacing: * The NodeJS test execution failed because Domino does not handle destructuring syntax properly. This is because `Node.children` is not an iterable. * `forwardRef` does not work with ES2015 and TypeScript's decorator downlevel emit. This is a known limitation we work around in Angular applications by either compiling tests with the Angular compiler, or by running a custom decorator downlevel transform (like in the CLI). PR Close #44505
This commit is contained in:
committed by
Andrew Scott
parent
92806ff042
commit
807c6a4e10
@@ -1,12 +1,17 @@
|
|||||||
load("//tools:defaults.bzl", "jasmine_node_test", "karma_web_test_suite", "ts_library")
|
load("//tools:defaults.bzl", "jasmine_node_test", "karma_web_test_suite", "ng_module", "ts_library")
|
||||||
|
|
||||||
package(default_visibility = ["//visibility:private"])
|
package(default_visibility = ["//visibility:private"])
|
||||||
|
|
||||||
|
SPEC_FILES_WITH_FORWARD_REFS = [
|
||||||
|
"di_forward_ref_spec.ts",
|
||||||
|
]
|
||||||
|
|
||||||
ts_library(
|
ts_library(
|
||||||
name = "acceptance_lib",
|
name = "acceptance_lib",
|
||||||
testonly = True,
|
testonly = True,
|
||||||
srcs = glob(
|
srcs = glob(
|
||||||
["**/*.ts"],
|
["**/*.ts"],
|
||||||
|
exclude = SPEC_FILES_WITH_FORWARD_REFS,
|
||||||
),
|
),
|
||||||
# Visible to //:saucelabs_unit_tests
|
# Visible to //:saucelabs_unit_tests
|
||||||
visibility = ["//:__pkg__"],
|
visibility = ["//:__pkg__"],
|
||||||
@@ -35,11 +40,28 @@ ts_library(
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Note: The `forward_ref` example tests are built through this `ng_module` sub-target.
|
||||||
|
# This is done so that DI decorator/type metadata is processed manually by the compiler
|
||||||
|
# ahead of time. We cannot rely on the official TypeScript decorator downlevel emit (for JIT),
|
||||||
|
# as the output is not compatible with `forwardRef` and ES2015+. More details here:
|
||||||
|
# https://github.com/angular/angular/commit/323651bd38909b0f4226bcb6c8f5abafa91cf9d9.
|
||||||
|
# https://github.com/microsoft/TypeScript/issues/27519.
|
||||||
|
ng_module(
|
||||||
|
name = "forward_ref_test_lib",
|
||||||
|
testonly = True,
|
||||||
|
srcs = SPEC_FILES_WITH_FORWARD_REFS,
|
||||||
|
deps = [
|
||||||
|
"//packages/core",
|
||||||
|
"//packages/core/testing",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
jasmine_node_test(
|
jasmine_node_test(
|
||||||
name = "acceptance",
|
name = "acceptance",
|
||||||
bootstrap = ["//tools/testing:node_es2015"],
|
bootstrap = ["//tools/testing:node_es2015"],
|
||||||
deps = [
|
deps = [
|
||||||
":acceptance_lib",
|
":acceptance_lib",
|
||||||
|
":forward_ref_test_lib",
|
||||||
"//packages/zone.js/lib:zone_d_ts",
|
"//packages/zone.js/lib:zone_d_ts",
|
||||||
"@npm//base64-js",
|
"@npm//base64-js",
|
||||||
"@npm//source-map",
|
"@npm//source-map",
|
||||||
@@ -50,5 +72,6 @@ karma_web_test_suite(
|
|||||||
name = "acceptance_web",
|
name = "acceptance_web",
|
||||||
deps = [
|
deps = [
|
||||||
":acceptance_lib",
|
":acceptance_lib",
|
||||||
|
":forward_ref_test_lib",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -0,0 +1,67 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google LLC 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, forwardRef, Host, Inject, ViewChild} from '@angular/core';
|
||||||
|
import {TestBed} from '@angular/core/testing';
|
||||||
|
|
||||||
|
// **NOTE**: More details on why tests relying on `forwardRef` are put into this
|
||||||
|
// file can be found in the `BUILD.bazel` file declaring the forward ref test target.
|
||||||
|
|
||||||
|
describe('di with forwardRef', () => {
|
||||||
|
describe('directive injection', () => {
|
||||||
|
it('should throw if directives try to inject each other', () => {
|
||||||
|
@Directive({selector: '[dirB]'})
|
||||||
|
class DirectiveB {
|
||||||
|
constructor(@Inject(forwardRef(() => DirectiveA)) siblingDir: DirectiveA) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Directive({selector: '[dirA]'})
|
||||||
|
class DirectiveA {
|
||||||
|
constructor(siblingDir: DirectiveB) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({template: '<div dirA dirB></div>'})
|
||||||
|
class MyComp {
|
||||||
|
}
|
||||||
|
|
||||||
|
TestBed.configureTestingModule({declarations: [DirectiveA, DirectiveB, MyComp]});
|
||||||
|
expect(() => TestBed.createComponent(MyComp))
|
||||||
|
.toThrowError(
|
||||||
|
'NG0200: Circular dependency in DI detected for DirectiveA. Find more at https://angular.io/errors/NG0200');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('flags', () => {
|
||||||
|
describe('@Host', () => {
|
||||||
|
it('should find host component on the host itself', () => {
|
||||||
|
@Directive({selector: '[dirComp]'})
|
||||||
|
class DirectiveComp {
|
||||||
|
constructor(@Inject(forwardRef(() => MyComp)) @Host() public comp: MyComp) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({selector: 'my-comp', template: '<div dirComp></div>'})
|
||||||
|
class MyComp {
|
||||||
|
@ViewChild(DirectiveComp) dirComp!: DirectiveComp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({template: '<my-comp></my-comp>', jit: true})
|
||||||
|
class MyApp {
|
||||||
|
@ViewChild(MyComp) myComp!: MyComp;
|
||||||
|
}
|
||||||
|
|
||||||
|
TestBed.configureTestingModule({declarations: [DirectiveComp, MyComp, MyApp]});
|
||||||
|
const fixture = TestBed.createComponent(MyApp);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const myComp = fixture.componentInstance.myComp;
|
||||||
|
const dirComp = myComp.dirComp;
|
||||||
|
expect(dirComp.comp).toBe(myComp);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -684,27 +684,6 @@ describe('di', () => {
|
|||||||
expect(cmp.componentInstance.testB.a).toBeNull();
|
expect(cmp.componentInstance.testB.a).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if directives try to inject each other', () => {
|
|
||||||
@Directive({selector: '[dirB]'})
|
|
||||||
class DirectiveB {
|
|
||||||
constructor(@Inject(forwardRef(() => DirectiveA)) siblingDir: DirectiveA) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Directive({selector: '[dirA]'})
|
|
||||||
class DirectiveA {
|
|
||||||
constructor(siblingDir: DirectiveB) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component({template: '<div dirA dirB></div>'})
|
|
||||||
class MyComp {
|
|
||||||
}
|
|
||||||
|
|
||||||
TestBed.configureTestingModule({declarations: [DirectiveA, DirectiveB, MyComp]});
|
|
||||||
expect(() => TestBed.createComponent(MyComp))
|
|
||||||
.toThrowError(
|
|
||||||
'NG0200: Circular dependency in DI detected for DirectiveA. Find more at https://angular.io/errors/NG0200');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw if directive tries to inject itself', () => {
|
it('should throw if directive tries to inject itself', () => {
|
||||||
@Directive({selector: '[dirA]'})
|
@Directive({selector: '[dirA]'})
|
||||||
class DirectiveA {
|
class DirectiveA {
|
||||||
@@ -1781,31 +1760,6 @@ describe('di', () => {
|
|||||||
expect(dirString.s).toBe('Foo');
|
expect(dirString.s).toBe('Foo');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should find host component on the host itself', () => {
|
|
||||||
@Directive({selector: '[dirComp]'})
|
|
||||||
class DirectiveComp {
|
|
||||||
constructor(@Inject(forwardRef(() => MyComp)) @Host() public comp: MyComp) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component({selector: 'my-comp', template: '<div dirComp></div>'})
|
|
||||||
class MyComp {
|
|
||||||
@ViewChild(DirectiveComp) dirComp!: DirectiveComp;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component({template: '<my-comp></my-comp>'})
|
|
||||||
class MyApp {
|
|
||||||
@ViewChild(MyComp) myComp!: MyComp;
|
|
||||||
}
|
|
||||||
|
|
||||||
TestBed.configureTestingModule({declarations: [DirectiveComp, MyComp, MyApp]});
|
|
||||||
const fixture = TestBed.createComponent(MyApp);
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
const myComp = fixture.componentInstance.myComp;
|
|
||||||
const dirComp = myComp.dirComp;
|
|
||||||
expect(dirComp.comp).toBe(myComp);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not find providers on the host itself', () => {
|
it('should not find providers on the host itself', () => {
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-comp',
|
selector: 'my-comp',
|
||||||
@@ -1882,19 +1836,19 @@ describe('di', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should not find component above the host', () => {
|
it('should not find component above the host', () => {
|
||||||
|
@Component({template: '<my-comp></my-comp>'})
|
||||||
|
class MyApp {
|
||||||
|
}
|
||||||
|
|
||||||
@Directive({selector: '[dirComp]'})
|
@Directive({selector: '[dirComp]'})
|
||||||
class DirectiveComp {
|
class DirectiveComp {
|
||||||
constructor(@Inject(forwardRef(() => MyApp)) @Host() public comp: MyApp) {}
|
constructor(@Host() public comp: MyApp) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({selector: 'my-comp', template: '<div dirComp></div>'})
|
@Component({selector: 'my-comp', template: '<div dirComp></div>'})
|
||||||
class MyComp {
|
class MyComp {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({template: '<my-comp></my-comp>'})
|
|
||||||
class MyApp {
|
|
||||||
}
|
|
||||||
|
|
||||||
TestBed.configureTestingModule({declarations: [DirectiveComp, MyComp, MyApp]});
|
TestBed.configureTestingModule({declarations: [DirectiveComp, MyComp, MyApp]});
|
||||||
expect(() => TestBed.createComponent(MyApp))
|
expect(() => TestBed.createComponent(MyApp))
|
||||||
.toThrowError(
|
.toThrowError(
|
||||||
|
|||||||
@@ -510,7 +510,12 @@ describe('property bindings', () => {
|
|||||||
const fixture = TestBed.createComponent(App);
|
const fixture = TestBed.createComponent(App);
|
||||||
const myDir = fixture.debugElement.query(By.directive(MyDir)).injector.get(MyDir);
|
const myDir = fixture.debugElement.query(By.directive(MyDir)).injector.get(MyDir);
|
||||||
const myDirB = fixture.debugElement.query(By.directive(MyDirB)).injector.get(MyDirB);
|
const myDirB = fixture.debugElement.query(By.directive(MyDirB)).injector.get(MyDirB);
|
||||||
const [buttonEl, listboxEl] = fixture.nativeElement.children;
|
const fixtureElements = fixture.nativeElement.children;
|
||||||
|
|
||||||
|
// TODO: Use destructuring once Domino supports native ES2015, or when jsdom is used.
|
||||||
|
const buttonEl = fixtureElements[0];
|
||||||
|
const listboxEl = fixtureElements[1];
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
expect(buttonEl.getAttribute('role')).toBe('button');
|
expect(buttonEl.getAttribute('role')).toBe('button');
|
||||||
@@ -581,7 +586,11 @@ describe('property bindings', () => {
|
|||||||
|
|
||||||
expect(fixture.nativeElement.children.length).toBe(2);
|
expect(fixture.nativeElement.children.length).toBe(2);
|
||||||
|
|
||||||
const [comp1, comp2] = fixture.nativeElement.children;
|
const compElements = fixture.nativeElement.children;
|
||||||
|
|
||||||
|
// TODO: Use destructuring once Domino supports native ES2015, or when jsdom is used.
|
||||||
|
const comp1 = compElements[0];
|
||||||
|
const comp2 = compElements[1];
|
||||||
|
|
||||||
expect(comp1.tagName).toBe('COMP');
|
expect(comp1.tagName).toBe('COMP');
|
||||||
expect(comp2.tagName).toBe('COMP');
|
expect(comp2.tagName).toBe('COMP');
|
||||||
|
|||||||
@@ -60,8 +60,8 @@ describe('styling', () => {
|
|||||||
|
|
||||||
TestBed.configureTestingModule({declarations: [Cmp]});
|
TestBed.configureTestingModule({declarations: [Cmp]});
|
||||||
const fixture = TestBed.createComponent(Cmp);
|
const fixture = TestBed.createComponent(Cmp);
|
||||||
|
const staticDiv = fixture.nativeElement.querySelectorAll('div')[0];
|
||||||
|
|
||||||
const [staticDiv] = fixture.nativeElement.querySelectorAll('div');
|
|
||||||
expect(getSortedClassName(staticDiv)).toEqual('STATIC');
|
expect(getSortedClassName(staticDiv)).toEqual('STATIC');
|
||||||
expect(getSortedStyle(staticDiv)).toEqual('color: blue;');
|
expect(getSortedStyle(staticDiv)).toEqual('color: blue;');
|
||||||
});
|
});
|
||||||
@@ -335,7 +335,12 @@ describe('styling', () => {
|
|||||||
const fixture = TestBed.createComponent(Cmp);
|
const fixture = TestBed.createComponent(Cmp);
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
const [div1, div2] = fixture.nativeElement.querySelectorAll('div');
|
const divs = fixture.nativeElement.querySelectorAll('div');
|
||||||
|
|
||||||
|
// TODO: Use destructuring once Domino supports native ES2015, or when jsdom is used.
|
||||||
|
const div1 = divs[0];
|
||||||
|
const div2 = divs[1];
|
||||||
|
|
||||||
// Static value `class="s1"` is always written to the DOM.
|
// Static value `class="s1"` is always written to the DOM.
|
||||||
expect(div1.className).toEqual('s1');
|
expect(div1.className).toEqual('s1');
|
||||||
expect(div1.getAttribute('shadow-class')).toEqual('s1 d1');
|
expect(div1.getAttribute('shadow-class')).toEqual('s1 d1');
|
||||||
@@ -367,7 +372,12 @@ describe('styling', () => {
|
|||||||
const fixture = TestBed.createComponent(Cmp);
|
const fixture = TestBed.createComponent(Cmp);
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
const [divStatic, divBinding] = fixture.nativeElement.querySelectorAll('div');
|
const divs = fixture.nativeElement.querySelectorAll('div');
|
||||||
|
|
||||||
|
// TODO: Use destructuring once Domino supports native ES2015, or when jsdom is used.
|
||||||
|
const divStatic = divs[0];
|
||||||
|
const divBinding = divs[1];
|
||||||
|
|
||||||
expectClass(divStatic).toEqual({'DIRECTIVE': true, 's1': true});
|
expectClass(divStatic).toEqual({'DIRECTIVE': true, 's1': true});
|
||||||
expect(divStatic.getAttribute('shadow-class')).toEqual('s1');
|
expect(divStatic.getAttribute('shadow-class')).toEqual('s1');
|
||||||
|
|
||||||
@@ -398,7 +408,12 @@ describe('styling', () => {
|
|||||||
const fixture = TestBed.createComponent(Cmp);
|
const fixture = TestBed.createComponent(Cmp);
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
const [divStatic, divBinding] = fixture.nativeElement.querySelectorAll('div');
|
const divs = fixture.nativeElement.querySelectorAll('div');
|
||||||
|
|
||||||
|
// TODO: Use destructuring once Domino supports native ES2015, or when jsdom is used.
|
||||||
|
const divStatic = divs[0];
|
||||||
|
const divBinding = divs[1];
|
||||||
|
|
||||||
expectStyle(divStatic).toEqual({'color': 'red', 'width': '1px'});
|
expectStyle(divStatic).toEqual({'color': 'red', 'width': '1px'});
|
||||||
expect(divStatic.getAttribute('shadow-style')).toEqual('width: 1px;');
|
expect(divStatic.getAttribute('shadow-style')).toEqual('width: 1px;');
|
||||||
|
|
||||||
@@ -2451,11 +2466,10 @@ describe('styling', () => {
|
|||||||
|
|
||||||
const items = fixture.nativeElement.querySelectorAll('.item');
|
const items = fixture.nativeElement.querySelectorAll('.item');
|
||||||
expect(items.length).toEqual(4);
|
expect(items.length).toEqual(4);
|
||||||
const [a, b, c, d] = items;
|
expect(items[0].style.height).toEqual('0px');
|
||||||
expect(a.style.height).toEqual('0px');
|
expect(items[1].style.height).toEqual('100px');
|
||||||
expect(b.style.height).toEqual('100px');
|
expect(items[2].style.height).toEqual('200px');
|
||||||
expect(c.style.height).toEqual('200px');
|
expect(items[3].style.height).toEqual('300px');
|
||||||
expect(d.style.height).toEqual('300px');
|
|
||||||
|
|
||||||
const section = fixture.nativeElement.querySelector('section');
|
const section = fixture.nativeElement.querySelector('section');
|
||||||
const p = fixture.nativeElement.querySelector('p');
|
const p = fixture.nativeElement.querySelector('p');
|
||||||
@@ -3342,7 +3356,11 @@ describe('styling', () => {
|
|||||||
const fixture = TestBed.createComponent(MyComp);
|
const fixture = TestBed.createComponent(MyComp);
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
const [div1, div2] = fixture.nativeElement.querySelectorAll('div') as HTMLDivElement[];
|
const divs = fixture.nativeElement.querySelectorAll('div') as HTMLDivElement[];
|
||||||
|
|
||||||
|
// TODO: Use destructuring once Domino supports native ES2015, or when jsdom is used.
|
||||||
|
const div1 = divs[0];
|
||||||
|
const div2 = divs[1];
|
||||||
|
|
||||||
expect(div1.className).toBe('');
|
expect(div1.className).toBe('');
|
||||||
expect(div2.className).toBe('');
|
expect(div2.className).toBe('');
|
||||||
|
|||||||
Reference in New Issue
Block a user