test(ivy): tests for view insertion before another view (#33627)
PR Close #33627
This commit is contained in:
parent
a33162bb66
commit
c57759f191
|
@ -7,7 +7,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {CommonModule} from '@angular/common';
|
import {CommonModule} from '@angular/common';
|
||||||
import {ChangeDetectorRef, Component, EmbeddedViewRef, TemplateRef, ViewChild, ViewContainerRef} from '@angular/core';
|
import {ChangeDetectorRef, Component, ComponentFactoryResolver, Directive, EmbeddedViewRef, Injector, NgModule, TemplateRef, ViewChild, ViewContainerRef, ViewRef} from '@angular/core';
|
||||||
import {TestBed} from '@angular/core/testing';
|
import {TestBed} from '@angular/core/testing';
|
||||||
import {By} from '@angular/platform-browser';
|
import {By} from '@angular/platform-browser';
|
||||||
|
|
||||||
|
@ -249,4 +249,246 @@ describe('view insertion', () => {
|
||||||
expect(fixture.debugElement.queryAll(By.css('div.dynamic')).length).toBe(4);
|
expect(fixture.debugElement.queryAll(By.css('div.dynamic')).length).toBe(4);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('before another view', () => {
|
||||||
|
@Directive({selector: '[viewInserting]', exportAs: 'vi'})
|
||||||
|
class ViewInsertingDir {
|
||||||
|
constructor(private _vcRef: ViewContainerRef) {}
|
||||||
|
|
||||||
|
insert(beforeView: ViewRef, insertTpl: TemplateRef<{}>) {
|
||||||
|
this._vcRef.insert(beforeView, 0);
|
||||||
|
this._vcRef.createEmbeddedView(insertTpl, {}, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('before embedded view', () => {
|
||||||
|
@Component({
|
||||||
|
selector: 'test-cmpt',
|
||||||
|
template: `
|
||||||
|
<ng-template #insert>insert</ng-template>
|
||||||
|
<ng-template #before>|before</ng-template>
|
||||||
|
|
||||||
|
<div><ng-template #vi="vi" viewInserting></ng-template></div>
|
||||||
|
`
|
||||||
|
})
|
||||||
|
class TestCmpt {
|
||||||
|
@ViewChild('before', {static: true}) beforeTpl !: TemplateRef<{}>;
|
||||||
|
@ViewChild('insert', {static: true}) insertTpl !: TemplateRef<{}>;
|
||||||
|
@ViewChild('vi', {static: true}) viewInsertingDir !: ViewInsertingDir;
|
||||||
|
|
||||||
|
minutes = 10;
|
||||||
|
|
||||||
|
insert() {
|
||||||
|
const beforeView = this.beforeTpl.createEmbeddedView({});
|
||||||
|
// change-detect the "before view" to create all child views
|
||||||
|
beforeView.detectChanges();
|
||||||
|
this.viewInsertingDir.insert(beforeView, this.insertTpl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [TestCmpt, ViewInsertingDir],
|
||||||
|
imports: [CommonModule],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function createAndInsertViews(beforeTpl: string): any {
|
||||||
|
TestBed.overrideTemplate(TestCmpt, `
|
||||||
|
<ng-template #insert>insert</ng-template>
|
||||||
|
<ng-template #before>${beforeTpl}</ng-template>
|
||||||
|
|
||||||
|
<div><ng-template #vi="vi" viewInserting></ng-template></div>
|
||||||
|
`);
|
||||||
|
const fixture = TestBed.createComponent(TestCmpt);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
fixture.componentInstance.insert();
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
return fixture.nativeElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
it('should insert before a view with the text node as the first root node',
|
||||||
|
() => { expect(createAndInsertViews('|before').textContent).toBe('insert|before'); });
|
||||||
|
|
||||||
|
it('should insert before a view with the element as the first root node', () => {
|
||||||
|
expect(createAndInsertViews('<span>|before</span>').textContent).toBe('insert|before');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should insert before a view with the ng-container as the first root node', () => {
|
||||||
|
expect(createAndInsertViews(`
|
||||||
|
<ng-container>
|
||||||
|
<ng-container>|before</ng-container>
|
||||||
|
</ng-container>
|
||||||
|
`).textContent)
|
||||||
|
.toBe('insert|before');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should insert before a view with ICU container inside a ng-container as the first root node',
|
||||||
|
() => {
|
||||||
|
expect(
|
||||||
|
createAndInsertViews(
|
||||||
|
`<ng-container i18n>{minutes, plural, =0 {just now} =1 {one minute ago} other {|before}}</ng-container>`)
|
||||||
|
.textContent)
|
||||||
|
.toBe('insert|before');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should insert before a view with a container as the first root node', () => {
|
||||||
|
expect(createAndInsertViews(`<ng-template [ngIf]="true">|before</ng-template>`).textContent)
|
||||||
|
.toBe('insert|before');
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should insert before a view with an empty container as the first root node', () => {
|
||||||
|
expect(createAndInsertViews(`<ng-template [ngIf]="true"></ng-template>`).textContent)
|
||||||
|
.toBe('insert');
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should insert before a view with an empty projection as the first root node', () => {
|
||||||
|
expect(createAndInsertViews(`<ng-content></ng-content>|before`).textContent)
|
||||||
|
.toBe('insert|before');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should insert before a view with complex node structure', () => {
|
||||||
|
expect(createAndInsertViews(`
|
||||||
|
<ng-template [ngIf]="true">
|
||||||
|
<ng-container>
|
||||||
|
<ng-container>
|
||||||
|
<ng-template [ngIf]="true">|before</ng-template>
|
||||||
|
</ng-container>
|
||||||
|
</ng-container>
|
||||||
|
</ng-template>
|
||||||
|
`).textContent)
|
||||||
|
.toBe('insert|before');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('before embedded view with projection', () => {
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'with-content',
|
||||||
|
template: `
|
||||||
|
<ng-template #insert>insert</ng-template>
|
||||||
|
<ng-template #before><ng-content></ng-content></ng-template>
|
||||||
|
<div><ng-template #vi="vi" viewInserting></ng-template></div>
|
||||||
|
`
|
||||||
|
})
|
||||||
|
class WithContentCmpt {
|
||||||
|
@ViewChild('insert', {static: true}) insertTpl !: TemplateRef<{}>;
|
||||||
|
@ViewChild('before', {static: true}) beforeTpl !: TemplateRef<{}>;
|
||||||
|
@ViewChild('vi', {static: true}) viewInsertingDir !: ViewInsertingDir;
|
||||||
|
|
||||||
|
insert() {
|
||||||
|
const beforeView = this.beforeTpl.createEmbeddedView({});
|
||||||
|
// change-detect the "before view" to create all child views
|
||||||
|
beforeView.detectChanges();
|
||||||
|
this.viewInsertingDir.insert(beforeView, this.insertTpl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({selector: 'test-cmpt', template: ''})
|
||||||
|
class TestCmpt {
|
||||||
|
@ViewChild('wc', {static: true}) withContentCmpt !: WithContentCmpt;
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ViewInsertingDir, WithContentCmpt, TestCmpt],
|
||||||
|
imports: [CommonModule],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should insert before a view with projected text nodes', () => {
|
||||||
|
TestBed.overrideTemplate(TestCmpt, `<with-content #wc>|before</with-content>`);
|
||||||
|
const fixture = TestBed.createComponent(TestCmpt);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
fixture.componentInstance.withContentCmpt.insert();
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(fixture.nativeElement.textContent).toBe('insert|before');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should insert before a view with projected container', () => {
|
||||||
|
TestBed.overrideTemplate(
|
||||||
|
TestCmpt,
|
||||||
|
`<with-content #wc><ng-template [ngIf]="true">|before</ng-template></with-content>`);
|
||||||
|
|
||||||
|
const fixture = TestBed.createComponent(TestCmpt);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
fixture.componentInstance.withContentCmpt.insert();
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(fixture.nativeElement.textContent).toBe('insert|before');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('before component view', () => {
|
||||||
|
@Directive({selector: '[viewInserting]', exportAs: 'vi'})
|
||||||
|
class ViewInsertingDir {
|
||||||
|
constructor(private _vcRef: ViewContainerRef) {}
|
||||||
|
|
||||||
|
insert(beforeView: ViewRef, insertTpl: TemplateRef<{}>) {
|
||||||
|
this._vcRef.insert(beforeView, 0);
|
||||||
|
this._vcRef.createEmbeddedView(insertTpl, {}, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({selector: 'dynamic-cmpt', template: '|before'})
|
||||||
|
class DynamicComponent {
|
||||||
|
}
|
||||||
|
|
||||||
|
it('should insert in front a dynamic component view', () => {
|
||||||
|
@Component({
|
||||||
|
selector: 'test-cmpt',
|
||||||
|
template: `
|
||||||
|
<ng-template #insert>insert</ng-template>
|
||||||
|
<div><ng-template #vi="vi" viewInserting></ng-template></div>
|
||||||
|
`
|
||||||
|
})
|
||||||
|
class TestCmpt {
|
||||||
|
@ViewChild('insert', {static: true}) insertTpl !: TemplateRef<{}>;
|
||||||
|
@ViewChild('vi', {static: true}) viewInsertingDir !: ViewInsertingDir;
|
||||||
|
|
||||||
|
constructor(private _cfr: ComponentFactoryResolver, private _injector: Injector) {}
|
||||||
|
|
||||||
|
insert() {
|
||||||
|
// create a dynamic component view to act as an "insert before" view
|
||||||
|
const componentFactory = this._cfr.resolveComponentFactory(DynamicComponent);
|
||||||
|
const beforeView = componentFactory.create(this._injector).hostView;
|
||||||
|
// change-detect the "before view" to create all child views
|
||||||
|
beforeView.detectChanges();
|
||||||
|
this.viewInsertingDir.insert(beforeView, this.insertTpl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [TestCmpt, ViewInsertingDir, DynamicComponent],
|
||||||
|
imports: [CommonModule],
|
||||||
|
entryComponents: [DynamicComponent]
|
||||||
|
})
|
||||||
|
class TestModule {
|
||||||
|
}
|
||||||
|
|
||||||
|
TestBed.configureTestingModule({imports: [TestModule]});
|
||||||
|
|
||||||
|
const fixture = TestBed.createComponent(TestCmpt);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
fixture.componentInstance.insert();
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(fixture.nativeElement.textContent).toBe('insert|before');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue