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 {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 {By} from '@angular/platform-browser';
|
||||
|
||||
|
@ -249,4 +249,246 @@ describe('view insertion', () => {
|
|||
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