如何使用Input对Angular指令进行单元测试



我有以下指令,该指令使用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实际上已经被调用,但不确定如何确认复制的值与输入字符串的值匹配?

我运行了您的测试,发现从未设置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);
});
});

最新更新