gpt4 book ai didi

javascript - 如何测试 Angular 中嵌入的内容?

转载 作者:行者123 更新时间:2023-11-28 20:38:08 25 4
gpt4 key购买 nike

在使用 <ng-content> 测试具有嵌入槽的 Angular 组件时, 我们没有explicit 表示检查嵌入的内容是否按预期放置在组件内。例如:

// base-button.component.ts
@Component({
selector: 'base-button',
template: `<button [type]="type">
<ng-content></ng-content>
</button>`,
})
export class BaseButtonComponent {
@Input() type = 'button';
}

基本上,在规范文件中创建组件实例时,我们会这样做:

// base-button.component.spec.ts
it('should reflect the `type` property into the "type" attribute of the button', () => {
const fixture = TestBed.createComponent(BaseButtonComponent);
fixture.detectChanges();

const { componentInstance, nativeElement } = fixture;
componentInstance.type = 'reset';

const button = nativeElement.querySelector('button');
expect(button.type === 'reset');
});

我们可以对组件的每个属性和方法都这样做,但是嵌入的内容?解决方法是创建用于测试目的的主机组件:

// base-button.component.spec.ts
...
@Component({
template: `<base-button>Foo bar</base-button>`
})
export class BaseButtonHostComponent {}
...

beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ BaseButtonComponent, BaseButtonHostComponent ]
})
.compileComponents();
}));

it('should transclude the content correctly', () => {
const hostFixture = TestBed.createComponent(BaseButtonHostComponent);
hostFixture.detectChanges();
const button = hostFixture.nativeElement.querySelector('button');
expect(button.textContent === 'Foo bar');
});
...

但是,如您所想,这很不方便,还因为必须这样做对于包含嵌入内容的每个组件,并且可能对于每个 <ng-content>元素在它的模板中。还有其他方法吗?

最佳答案

确实有一种相当晦涩的方法可以做到这一点。基本上,TestBed.createComponent 调用组件的工厂 create 方法,它也支持可投影的 DOM 节点插入到嵌入槽中。

// @angular/core/testing.js
createComponent(component) {
...
const componentFactory = this._compiler.getComponentFactory(component);
...
const componentRef = componentFactory.create(Injector.NULL, [], `#${rootElId}`, this._moduleRef);
...
}

我们必须做同样的事情,技巧如下:

// base-button.component.spec.ts
describe('BaseButtonComponent', () => {
let factory: ComponentFactory<BaseButtonComponent>;

beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ BaseButtonComponent ]
})
.overrideModule(BrowserDynamicTestingModule, {
set: {
entryComponents: [ BaseButtonComponent ]
}
})
.compileComponents();

const resolver = <ComponentFactoryResolver>TestBed.get(ComponentFactoryResolver, null);
factory = resolver.resolveComponentFactory(BaseButtonComponent);
}));

it('should transclude the provided nodes into the button', () => {
const tnode = document.createTextNode('Foo bar');
const componentRef = factory.create(Injector.NULL, [[ tnode ]]);
const button = componentRef.location.nativeElement.querySelector('button');
expect(button.textContent === 'Foo bar');
});
});

TestBed.get 允许我们检索 ComponentFactoryResolver 服务。为了找回组件的工厂,但是,组件的类必须列在模块的 entryComponents 中属性(property)。有问题的模块是 BrowserDynamicTestingModuleTestBed 公开了一个方便的改变其属性的方法。

一旦你有了工厂,技巧就完成了。唯一烦人的部分是生成所有手动可投影节点,因此您可以为此创建实用函数:

function createComponentWithContents(factory, ...contents) {
const template = document.createElement('template');
const projectableNodes = contents.map(html => {
template.innerHTML = html;
return [ ...template.content.childNodes ];
});
return factory.create(Injector.NULL, projectableNodes);
}

const componentRef = createComponentWithContents(factory, '<i class="fa fa-star"></i> Win!');

遗憾的是 TestBed.createComponent 不允许立即执行此操作。

关于javascript - 如何测试 Angular 中嵌入的内容?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45998052/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com