diff --git a/packages/core/test/linker/change_detection_integration_spec.ts b/packages/core/test/linker/change_detection_integration_spec.ts
index 82ae3fd7ea..ea57cad708 100644
--- a/packages/core/test/linker/change_detection_integration_spec.ts
+++ b/packages/core/test/linker/change_detection_integration_spec.ts
@@ -996,32 +996,33 @@ const TEST_COMPILER_PROVIDERS: Provider[] = [
expect(directiveLog.filter(['ngAfterViewInit'])).toEqual([]);
}));
- fixmeIvy('unknown').it(
- 'should not call ngAfterViewInit again if it throws', fakeAsync(() => {
- const ctx =
- createCompFixture('
');
+ fixmeIvy(
+ 'FW-830: Exception thrown in ngAfterViewInit triggers ngAfterViewInit re-execution')
+ .it('should not call ngAfterViewInit again if it throws', fakeAsync(() => {
+ const ctx = createCompFixture(
+ '');
- let errored = false;
- // First pass fails, but ngAfterViewInit should be called.
- try {
- ctx.detectChanges(false);
- } catch (e) {
- errored = true;
- }
- expect(errored).toBe(true);
+ let errored = false;
+ // First pass fails, but ngAfterViewInit should be called.
+ try {
+ ctx.detectChanges(false);
+ } catch (e) {
+ errored = true;
+ }
+ expect(errored).toBe(true);
- expect(directiveLog.filter(['ngAfterViewInit'])).toEqual(['dir.ngAfterViewInit']);
- directiveLog.clear();
+ expect(directiveLog.filter(['ngAfterViewInit'])).toEqual(['dir.ngAfterViewInit']);
+ directiveLog.clear();
- // Second change detection also fails, but this time ngAfterViewInit should not be
- // called.
- try {
- ctx.detectChanges(false);
- } catch (e) {
- throw new Error('Second detectChanges() should not have run detection.');
- }
- expect(directiveLog.filter(['ngAfterViewInit'])).toEqual([]);
- }));
+ // Second change detection also fails, but this time ngAfterViewInit should not be
+ // called.
+ try {
+ ctx.detectChanges(false);
+ } catch (e) {
+ throw new Error('Second detectChanges() should not have run detection.');
+ }
+ expect(directiveLog.filter(['ngAfterViewInit'])).toEqual([]);
+ }));
});
describe('ngAfterViewChecked', () => {
@@ -1185,14 +1186,14 @@ const TEST_COMPILER_PROVIDERS: Provider[] = [
/Previous value: 'changed: undefined'\. Current value: 'changed: 1'/g);
}));
- fixmeIvy('unknown').it(
- 'should warn when the view has been created in a cd hook', fakeAsync(() => {
- const ctx = createCompFixture('
{{ a }}
', TestData);
- ctx.componentInstance.a = 1;
- expect(() => ctx.detectChanges())
- .toThrowError(
- /It seems like the view has been created after its parent and its children have been dirty checked/);
- }));
+ fixmeIvy('FW-831: Views created in a cd hooks throw in view engine')
+ .it('should warn when the view has been created in a cd hook', fakeAsync(() => {
+ const ctx = createCompFixture('
{{ a }}
', TestData);
+ ctx.componentInstance.a = 1;
+ expect(() => ctx.detectChanges())
+ .toThrowError(
+ /It seems like the view has been created after its parent and its children have been dirty checked/);
+ }));
it('should not throw when two arrays are structurally the same', fakeAsync(() => {
const ctx = _bindSimpleValue('a', TestData);
@@ -1537,110 +1538,111 @@ const TEST_COMPILER_PROVIDERS: Provider[] = [
childThrows: LifetimeMethods;
}
- fixmeIvy('unknown').describe('calling init', () => {
- function initialize(options: Options) {
- @Component({selector: 'my-child', template: ''})
- class MyChild {
- private thrown = LifetimeMethods.None;
+ fixmeIvy('FW-832: View engine supports recursive detectChanges() calls')
+ .describe('calling init', () => {
+ function initialize(options: Options) {
+ @Component({selector: 'my-child', template: ''})
+ class MyChild {
+ private thrown = LifetimeMethods.None;
- // TODO(issue/24571): remove '!'.
- @Input() inp !: boolean;
- @Output() outp = new EventEmitter();
+ // TODO(issue/24571): remove '!'.
+ @Input() inp !: boolean;
+ @Output() outp = new EventEmitter();
- constructor() {}
+ constructor() {}
- ngDoCheck() { this.check(LifetimeMethods.ngDoCheck); }
- ngOnInit() { this.check(LifetimeMethods.ngOnInit); }
- ngOnChanges() { this.check(LifetimeMethods.ngOnChanges); }
- ngAfterViewInit() { this.check(LifetimeMethods.ngAfterViewInit); }
- ngAfterContentInit() { this.check(LifetimeMethods.ngAfterContentInit); }
+ ngDoCheck() { this.check(LifetimeMethods.ngDoCheck); }
+ ngOnInit() { this.check(LifetimeMethods.ngOnInit); }
+ ngOnChanges() { this.check(LifetimeMethods.ngOnChanges); }
+ ngAfterViewInit() { this.check(LifetimeMethods.ngAfterViewInit); }
+ ngAfterContentInit() { this.check(LifetimeMethods.ngAfterContentInit); }
- private check(method: LifetimeMethods) {
- log(`MyChild::${LifetimeMethods[method]}()`);
+ private check(method: LifetimeMethods) {
+ log(`MyChild::${LifetimeMethods[method]}()`);
- if ((options.childRecursion & method) !== 0) {
- if (logged.length < 20) {
- this.outp.emit(null);
- } else {
- fail(`Unexpected MyChild::${LifetimeMethods[method]} recursion`);
+ if ((options.childRecursion & method) !== 0) {
+ if (logged.length < 20) {
+ this.outp.emit(null);
+ } else {
+ fail(`Unexpected MyChild::${LifetimeMethods[method]} recursion`);
+ }
+ }
+ if ((options.childThrows & method) !== 0) {
+ if ((this.thrown & method) === 0) {
+ this.thrown |= method;
+ log(`()`);
+ throw new Error(`Throw from MyChild::${LifetimeMethods[method]}`);
+ }
+ }
}
}
- if ((options.childThrows & method) !== 0) {
- if ((this.thrown & method) === 0) {
- this.thrown |= method;
- log(`()`);
- throw new Error(`Throw from MyChild::${LifetimeMethods[method]}`);
+
+ @Component({
+ selector: 'my-component',
+ template: ``
+ })
+ class MyComponent {
+ constructor(private changeDetectionRef: ChangeDetectorRef) {}
+ ngDoCheck() { this.check(LifetimeMethods.ngDoCheck); }
+ ngOnInit() { this.check(LifetimeMethods.ngOnInit); }
+ ngAfterViewInit() { this.check(LifetimeMethods.ngAfterViewInit); }
+ ngAfterContentInit() { this.check(LifetimeMethods.ngAfterContentInit); }
+ onOutp() {
+ log('');
+ this.changeDetectionRef.detectChanges();
+ log('');
+ }
+
+ private check(method: LifetimeMethods) {
+ log(`MyComponent::${LifetimeMethods[method]}()`);
}
}
- }
- }
- @Component({
- selector: 'my-component',
- template: ``
- })
- class MyComponent {
- constructor(private changeDetectionRef: ChangeDetectorRef) {}
- ngDoCheck() { this.check(LifetimeMethods.ngDoCheck); }
- ngOnInit() { this.check(LifetimeMethods.ngOnInit); }
- ngAfterViewInit() { this.check(LifetimeMethods.ngAfterViewInit); }
- ngAfterContentInit() { this.check(LifetimeMethods.ngAfterContentInit); }
- onOutp() {
- log('');
- this.changeDetectionRef.detectChanges();
- log('');
+ TestBed.configureTestingModule({declarations: [MyChild, MyComponent]});
+
+ return createCompFixture(``);
}
- private check(method: LifetimeMethods) {
- log(`MyComponent::${LifetimeMethods[method]}()`);
- }
- }
-
- TestBed.configureTestingModule({declarations: [MyChild, MyComponent]});
-
- return createCompFixture(``);
- }
-
- function ensureOneInit(options: Options) {
- const ctx = initialize(options);
+ function ensureOneInit(options: Options) {
+ const ctx = initialize(options);
- const throws = options.childThrows != LifetimeMethods.None;
- if (throws) {
- log(``);
- expect(() => {
- // Expect child to throw.
+ const throws = options.childThrows != LifetimeMethods.None;
+ if (throws) {
+ log(``);
+ expect(() => {
+ // Expect child to throw.
+ ctx.detectChanges();
+ }).toThrow();
+ log(``);
+ log(``);
+ }
ctx.detectChanges();
- }).toThrow();
- log(``);
- log(``);
- }
- ctx.detectChanges();
- if (throws) log(``);
- expectOnceAndOnlyOnce('MyComponent::ngOnInit()');
- expectOnceAndOnlyOnce('MyChild::ngOnInit()');
- expectOnceAndOnlyOnce('MyComponent::ngAfterViewInit()');
- expectOnceAndOnlyOnce('MyComponent::ngAfterContentInit()');
- expectOnceAndOnlyOnce('MyChild::ngAfterViewInit()');
- expectOnceAndOnlyOnce('MyChild::ngAfterContentInit()');
- }
+ if (throws) log(``);
+ expectOnceAndOnlyOnce('MyComponent::ngOnInit()');
+ expectOnceAndOnlyOnce('MyChild::ngOnInit()');
+ expectOnceAndOnlyOnce('MyComponent::ngAfterViewInit()');
+ expectOnceAndOnlyOnce('MyComponent::ngAfterContentInit()');
+ expectOnceAndOnlyOnce('MyChild::ngAfterViewInit()');
+ expectOnceAndOnlyOnce('MyChild::ngAfterContentInit()');
+ }
- forEachMethod(LifetimeMethods.InitMethodsAndChanges, method => {
- it(`should ensure that init hooks are called once an only once with recursion in ${LifetimeMethods[method]} `,
- () => {
- // Ensure all the init methods are called once.
- ensureOneInit({childRecursion: method, childThrows: LifetimeMethods.None});
- });
- });
- forEachMethod(LifetimeMethods.All, method => {
- it(`should ensure that init hooks are called once an only once with a throw in ${LifetimeMethods[method]} `,
- () => {
- // Ensure all the init methods are called once.
- // the first cycle throws but the next cycle should complete the inits.
- ensureOneInit({childRecursion: LifetimeMethods.None, childThrows: method});
- });
- });
- });
+ forEachMethod(LifetimeMethods.InitMethodsAndChanges, method => {
+ it(`should ensure that init hooks are called once an only once with recursion in ${LifetimeMethods[method]} `,
+ () => {
+ // Ensure all the init methods are called once.
+ ensureOneInit({childRecursion: method, childThrows: LifetimeMethods.None});
+ });
+ });
+ forEachMethod(LifetimeMethods.All, method => {
+ it(`should ensure that init hooks are called once an only once with a throw in ${LifetimeMethods[method]} `,
+ () => {
+ // Ensure all the init methods are called once.
+ // the first cycle throws but the next cycle should complete the inits.
+ ensureOneInit({childRecursion: LifetimeMethods.None, childThrows: method});
+ });
+ });
+ });
});
});
})();
diff --git a/packages/core/test/linker/integration_spec.ts b/packages/core/test/linker/integration_spec.ts
index c0afbf6e7c..623af7d9c1 100644
--- a/packages/core/test/linker/integration_spec.ts
+++ b/packages/core/test/linker/integration_spec.ts
@@ -699,33 +699,32 @@ function declareTests(config?: {useJit: boolean}) {
expect(cmp.prop).toEqual('two');
});
- if (getDOM().supportsDOMEvents()) {
- fixmeIvy('unknown').it(
- 'should be checked when an async pipe requests a check', fakeAsync(() => {
- TestBed.configureTestingModule(
- {declarations: [MyComp, PushCmpWithAsyncPipe], imports: [CommonModule]});
- const template = '';
- TestBed.overrideComponent(MyComp, {set: {template}});
- const fixture = TestBed.createComponent(MyComp);
+ fixmeIvy(
+ 'FW-764: fixture.detectChanges() is not respecting OnPush flag on components in the root template')
+ .it('should be checked when an async pipe requests a check', fakeAsync(() => {
+ TestBed.configureTestingModule(
+ {declarations: [MyComp, PushCmpWithAsyncPipe], imports: [CommonModule]});
+ const template = '';
+ TestBed.overrideComponent(MyComp, {set: {template}});
+ const fixture = TestBed.createComponent(MyComp);
- tick();
+ tick();
- const cmp: PushCmpWithAsyncPipe =
- fixture.debugElement.children[0].references !['cmp'];
- fixture.detectChanges();
- expect(cmp.numberOfChecks).toEqual(1);
+ const cmp: PushCmpWithAsyncPipe =
+ fixture.debugElement.children[0].references !['cmp'];
+ fixture.detectChanges();
+ expect(cmp.numberOfChecks).toEqual(1);
- fixture.detectChanges();
- fixture.detectChanges();
- expect(cmp.numberOfChecks).toEqual(1);
+ fixture.detectChanges();
+ fixture.detectChanges();
+ expect(cmp.numberOfChecks).toEqual(1);
- cmp.resolve(2);
- tick();
+ cmp.resolve(2);
+ tick();
- fixture.detectChanges();
- expect(cmp.numberOfChecks).toEqual(2);
- }));
- }
+ fixture.detectChanges();
+ expect(cmp.numberOfChecks).toEqual(2);
+ }));
});
it('should create a component that injects an @Host', () => {
@@ -1871,79 +1870,83 @@ function declareTests(config?: {useJit: boolean}) {
if (getDOM().supportsDOMEvents()) {
describe('svg', () => {
- fixmeIvy('unknown').it('should support svg elements', () => {
- TestBed.configureTestingModule({declarations: [MyComp]});
- const template = '';
- TestBed.overrideComponent(MyComp, {set: {template}});
- const fixture = TestBed.createComponent(MyComp);
+ fixmeIvy('FW-672: SVG attribute xlink:href is output as :xlink:href (extra ":")')
+ .it('should support svg elements', () => {
+ TestBed.configureTestingModule({declarations: [MyComp]});
+ const template = '';
+ TestBed.overrideComponent(MyComp, {set: {template}});
+ const fixture = TestBed.createComponent(MyComp);
- const el = fixture.nativeElement;
- const svg = getDOM().childNodes(el)[0];
- const use = getDOM().childNodes(svg)[0];
- expect(getDOM().getProperty(svg, 'namespaceURI'))
- .toEqual('http://www.w3.org/2000/svg');
- expect(getDOM().getProperty(use, 'namespaceURI'))
- .toEqual('http://www.w3.org/2000/svg');
+ const el = fixture.nativeElement;
+ const svg = getDOM().childNodes(el)[0];
+ const use = getDOM().childNodes(svg)[0];
+ expect(getDOM().getProperty(svg, 'namespaceURI'))
+ .toEqual('http://www.w3.org/2000/svg');
+ expect(getDOM().getProperty(use, 'namespaceURI'))
+ .toEqual('http://www.w3.org/2000/svg');
- const firstAttribute = getDOM().getProperty(use, 'attributes')[0];
- expect(firstAttribute.name).toEqual('xlink:href');
- expect(firstAttribute.namespaceURI).toEqual('http://www.w3.org/1999/xlink');
- });
+ const firstAttribute = getDOM().getProperty(use, 'attributes')[0];
+ expect(firstAttribute.name).toEqual('xlink:href');
+ expect(firstAttribute.namespaceURI).toEqual('http://www.w3.org/1999/xlink');
+ });
- fixmeIvy('unknown').it('should support foreignObjects with document fragments', () => {
- TestBed.configureTestingModule({declarations: [MyComp]});
- const template =
- '';
- TestBed.overrideComponent(MyComp, {set: {template}});
- const fixture = TestBed.createComponent(MyComp);
+ fixmeIvy('FW-811: Align HTML namespaces between Ivy and Render2')
+ .it('should support foreignObjects with document fragments', () => {
+ TestBed.configureTestingModule({declarations: [MyComp]});
+ const template =
+ '';
+ TestBed.overrideComponent(MyComp, {set: {template}});
+ const fixture = TestBed.createComponent(MyComp);
- const el = fixture.nativeElement;
- const svg = getDOM().childNodes(el)[0];
- const foreignObject = getDOM().childNodes(svg)[0];
- const p = getDOM().childNodes(foreignObject)[0];
- expect(getDOM().getProperty(svg, 'namespaceURI'))
- .toEqual('http://www.w3.org/2000/svg');
- expect(getDOM().getProperty(foreignObject, 'namespaceURI'))
- .toEqual('http://www.w3.org/2000/svg');
- expect(getDOM().getProperty(p, 'namespaceURI'))
- .toEqual('http://www.w3.org/1999/xhtml');
- });
+ const el = fixture.nativeElement;
+ const svg = getDOM().childNodes(el)[0];
+ const foreignObject = getDOM().childNodes(svg)[0];
+ const p = getDOM().childNodes(foreignObject)[0];
+ expect(getDOM().getProperty(svg, 'namespaceURI'))
+ .toEqual('http://www.w3.org/2000/svg');
+ expect(getDOM().getProperty(foreignObject, 'namespaceURI'))
+ .toEqual('http://www.w3.org/2000/svg');
+ expect(getDOM().getProperty(p, 'namespaceURI'))
+ .toEqual('http://www.w3.org/1999/xhtml');
+ });
});
describe('attributes', () => {
- fixmeIvy('unknown').it('should support attributes with namespace', () => {
- TestBed.configureTestingModule({declarations: [MyComp, SomeCmp]});
- const template = '';
- TestBed.overrideComponent(SomeCmp, {set: {template}});
- const fixture = TestBed.createComponent(SomeCmp);
+ fixmeIvy('FW-672: SVG attribute xlink:href is output as :xlink:href (extra ":")')
+ .it('should support attributes with namespace', () => {
+ TestBed.configureTestingModule({declarations: [MyComp, SomeCmp]});
+ const template = '';
+ TestBed.overrideComponent(SomeCmp, {set: {template}});
+ const fixture = TestBed.createComponent(SomeCmp);
- const useEl = getDOM().firstChild(fixture.nativeElement);
- expect(getDOM().getAttributeNS(useEl, 'http://www.w3.org/1999/xlink', 'href'))
- .toEqual('#id');
- });
+ const useEl = getDOM().firstChild(fixture.nativeElement);
+ expect(getDOM().getAttributeNS(useEl, 'http://www.w3.org/1999/xlink', 'href'))
+ .toEqual('#id');
+ });
- fixmeIvy('unknown').it('should support binding to attributes with namespace', () => {
- TestBed.configureTestingModule({declarations: [MyComp, SomeCmp]});
- const template = '';
- TestBed.overrideComponent(SomeCmp, {set: {template}});
- const fixture = TestBed.createComponent(SomeCmp);
+ fixmeIvy('FW-672: SVG attribute xlink:href is output as :xlink:href (extra ":")')
+ .it('should support binding to attributes with namespace', () => {
+ TestBed.configureTestingModule({declarations: [MyComp, SomeCmp]});
+ const template = '';
+ TestBed.overrideComponent(SomeCmp, {set: {template}});
+ const fixture = TestBed.createComponent(SomeCmp);
- const cmp = fixture.componentInstance;
- const useEl = getDOM().firstChild(fixture.nativeElement);
+ const cmp = fixture.componentInstance;
+ const useEl = getDOM().firstChild(fixture.nativeElement);
- cmp.value = '#id';
- fixture.detectChanges();
+ cmp.value = '#id';
+ fixture.detectChanges();
- expect(getDOM().getAttributeNS(useEl, 'http://www.w3.org/1999/xlink', 'href'))
- .toEqual('#id');
+ expect(getDOM().getAttributeNS(useEl, 'http://www.w3.org/1999/xlink', 'href'))
+ .toEqual('#id');
- cmp.value = null;
- fixture.detectChanges();
+ cmp.value = null;
+ fixture.detectChanges();
- expect(getDOM().hasAttributeNS(useEl, 'http://www.w3.org/1999/xlink', 'href'))
- .toEqual(false);
- });
+ expect(getDOM().hasAttributeNS(useEl, 'http://www.w3.org/1999/xlink', 'href'))
+ .toEqual(false);
+ });
});
}
});
diff --git a/packages/core/test/linker/projection_integration_spec.ts b/packages/core/test/linker/projection_integration_spec.ts
index 8e6f0f0bdc..182e5baa46 100644
--- a/packages/core/test/linker/projection_integration_spec.ts
+++ b/packages/core/test/linker/projection_integration_spec.ts
@@ -81,21 +81,22 @@ describe('projection', () => {
expect(main.nativeElement).toHaveText('');
});
- fixmeIvy('unknown').it('should support multiple content tags', () => {
- TestBed.configureTestingModule({declarations: [MultipleContentTagsComponent]});
- TestBed.overrideComponent(MainComp, {
- set: {
- template: '' +
- '