如何使用输入对 Angular 指令进行单元测试?
Posted
技术标签:
【中文标题】如何使用输入对 Angular 指令进行单元测试?【英文标题】:How to unit test an Angular directive with an Input? 【发布时间】:2020-02-29 21:14:57 【问题描述】:我使用copy-to-clipboard
属性将以下指令添加到元素中,并在单击时将属性的内容复制到用户剪贴板:
@Directive(
selector: '[copy-to-clipboard]'
)
export class CopyToClipboardDirective
@Input('copy-to-clipboard') public payload: string;
@HostListener('click', ['$event'])
onClick(event: MouseEvent): void
event.preventDefault();
if (!this.payload)
return;
const listener = (e: ClipboardEvent) =>
const clipboard = e.clipboardData;
clipboard.setData('text', this.payload.toString());
e.preventDefault();
;
document.addEventListener('copy', listener, false);
document.execCommand('copy');
document.removeEventListener('copy', listener, false);
我的单元测试设置如下:
import ComponentFixture, TestBed from '@angular/core/testing';
import CopyToClipboardDirective from './copy-to-clipboard.directive';
import Component from '@angular/core';
@Component(
template: `<input [copy-to-clipboard]="'this is the passed string'" role="button" type="button">`
)
class MockCopyToClipboardComponent
fdescribe('Directive: CopyToClipboard', () =>
let fixture: ComponentFixture<MockCopyToClipboardComponent>;
let component: MockCopyToClipboardComponent;
let element;
beforeEach(() =>
TestBed.configureTestingModule(
declarations: [CopyToClipboardDirective, MockCopyToClipboardComponent]
);
fixture = TestBed.createComponent(MockCopyToClipboardComponent);
element = fixture.debugElement.nativeElement;
component = fixture.componentInstance;
);
it('should run the copy command', () =>
spyOn(document, 'execCommand');
element.querySelector('input').click();
fixture.detectChanges();
expect(document.execCommand).toHaveBeenCalled();
);
);
我收到一条错误消息,说预期的情况永远不会发生。我正在尝试设置测试以确认 document.execCommand
实际上已被调用,但不确定如何确认复制的值与输入字符串的值匹配?
【问题讨论】:
【参考方案1】:我运行了您的测试,发现 CopyToClipboardDirective#payload
的值从未设置过。您可以通过将fixture.detectChanges()
放在beforeEach
函数的末尾来完成这项工作。
beforeEach(() =>
TestBed.configureTestingModule(
declarations: [CopyToClipboardDirective, MockCopyToClipboardComponent]
);
fixture = TestBed.createComponent(MockCopyToClipboardComponent);
element = fixture.debugElement.nativeElement;
component = fixture.componentInstance;
fixture.detectChanges(); // >>>>>> ADD this line
);
it('should run the copy command', () =>
spyOn(document, 'execCommand');
element.querySelector('input').click();
// fixture.detectChanges(); // >>>>>> REMOVE this line
expect(document.execCommand).toHaveBeenCalledWith('copy');
);
要检查复制到剪贴板的文本,您可以尝试使用Clipboard#readText
将其读回。由于readText
返回Promise
,因此您需要处理其异步性质。以下示例使用done
函数来执行此操作。
it('should run the copy command', (done) =>
spyOn(document, 'execCommand');
element.querySelector('input').click();
expect(document.execCommand).toHaveBeenCalledWith('copy');
element.querySelector('input').focus();
navigator.clipboard.readText()
.then(t =>
expect(t).toBe('this is the passed string');
done();
)
.catch(err =>
fail(err);
);
);
【讨论】:
以上是关于如何使用输入对 Angular 指令进行单元测试?的主要内容,如果未能解决你的问题,请参考以下文章
在 Angular 中使用 Jasmine 使用 *ngIf 指令时,如何对元素是不是可见进行单元测试
是否可以像我们在 Angular 2 中测试属性指令一样对结构指令进行单元测试