Angular 如何使用输入对角度指令进行单元测试?

Angular 如何使用输入对角度指令进行单元测试?,angular,unit-testing,jasmine,angular-directive,Angular,Unit Testing,Jasmine,Angular Directive,我有以下指令,它使用复制到剪贴板属性添加到元素中,并在单击时将属性的内容复制到用户剪贴板: @Directive({ selector: '[copy-to-clipboard]' }) export class CopyToClipboardDirective { @Input('copy-to-clipboard') public payload: string; @HostListener('click', ['$event']) onClick(event: Mouse

我有以下指令,它使用
复制到剪贴板
属性添加到元素中,并在单击时将属性的内容复制到用户剪贴板:

@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();
  });
});

从'@angular/core/testing'导入{ComponentFixture,TestBed};
从“.”导入{CopyToClipboardDirective}/复制到剪贴板。指令“;
从'@angular/core'导入{Component};
@组成部分({
模板:``
})
类MockCopyToClipboardComponent{}
fdescribe('指令:CopyToClipboard',()=>{
let夹具:组件夹具;
let组件:MockCopyToClipboardComponent;
let元素;
在每个之前(()=>{
TestBed.configureTestingModule({
声明:[CopyToClipboardDirective,MockCopyToClipboardComponent]
});
fixture=TestBed.createComponent(MockCopyToClipboardComponent);
元素=fixture.debugElement.nativeElement;
组件=fixture.componentInstance;
});
它('应该运行复制命令',()=>{
spyOn(文档“execCommand”);
元素。querySelector('input')。单击();
fixture.detectChanges();
expect(document.execCommand).tohaveBeenCall();
});
});

我得到一个错误,说预期的情况从未发生。我正在尝试设置测试以确认
document.execCommand
实际上已被调用,但不确定如何确认复制的值与输入字符串的值匹配?

我运行了测试,发现从未设置
CopyToClipboardDirective#payload
的值。您可以通过在每个函数之前的
末尾放置
fixture.detectChanges()
来实现这一点

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');
});
要检查复制到剪贴板的文本,可以尝试使用将其读回。由于
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);
    });
});