【问题标题】:How to unit test an Angular directive with an Input?如何使用输入对 Angular 指令进行单元测试?
【发布时间】: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 实际上已被调用,但不确定如何确认复制的值与输入字符串的值匹配?

【问题讨论】:

    标签: angular unit-testing jasmine angular-directive


    【解决方案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);
        });
    });
    

    【讨论】:

      猜你喜欢
      • 2017-08-08
      • 2016-07-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-23
      • 1970-01-01
      相关资源
      最近更新 更多