Angular:如何测试阻止输入粘贴事件的指令?

分享于2022年12月29日 angular angular-directive inputevent karma-jasmine paste 问答
【问题标题】:Angular: How to test a directive that blocks paste events on inputs?Angular:如何测试阻止输入粘贴事件的指令?
【发布时间】:2022-12-21 13:46:03
【问题描述】:

我正在尝试测试一个不允许我将任何数据粘贴到输入元素中的指令。

该指令如下所示:

import { Directive, HostListener } from '@angular/core';

/**
 * Applied to an input, it blocks the paste functionality
 */
@Directive({
  selector: '[kycBlockPaste]'
})
export class BlockPasteDirective {

  /**
   * Hooks for paste event and suppress it
   *
   * @param e
   */
  @HostListener('paste', ['$event']) blockPaste(e: KeyboardEvent) {
    e.preventDefault();
  }
}

我想测试它的方式是,在添加粘贴 InputEvent 时输入的值应该改变,但事实并非如此。在应用指令和不应用指令的两种情况下,值都由空字符串表示。

关于如何测试它的任何想法?提前致谢 :)

测试看起来像这样:


@Component({
  template: ''
})
class TestBlockPasteDirectiveComponent {}

fdescribe('Block Paste directive', () => {
  let component: TestBlockPasteDirectiveComponent;
  let fixture: ComponentFixture;
  let inputEl: DebugElement;
  let nativeEl: HTMLInputElement;

  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [TestBlockPasteDirectiveComponent, BlockPasteDirective]
    });
    fixture = TestBed.createComponent(TestBlockPasteDirectiveComponent);
    component = fixture.componentInstance;
    inputEl = fixture.debugElement.query(By.css('input'));
    nativeEl = inputEl.nativeElement;
  });

  it('should hook for paste event and suppress it', () => {
    const inputEvent = new InputEvent('paste', {
      data: 'test input',
    });

    nativeEl.dispatchEvent(inputEvent);
    fixture.detectChanges();

    expect(nativeEl.value).toEqual('');
  });
});type here

  • 监视 HTMLInputElement::onchange 是否未被调用?

【解决方案1】:

您可以模拟剪贴板数据。我正在使用 Jest。

type DropEffect = "none" | "copy" | "link" | "move";
type EffectAllowed = "none" | "copy" | "copyLink" | "copyMove" | "link" | "linkMove" | "move" | "all" | "uninitialized";


const clipboardData = {
  dataTransfer: undefined,
  dropEffect: 'none' as DropEffect,
  effectAllowed: 'uninitialized' as EffectAllowed,
  files: {
    item: jest.fn(),
    length: 0
  },
  items: {
    length: 0,
    add: jest.fn(),
    clear: jest.fn(),
    remove: jest.fn()
  },
  types: [],
  clearData: jest.fn(),
  setData: jest.fn(),
  setDragImage: jest.fn(),
  getData: (format: string) => {
    return 'test'
  }
}

 it('will call paste event and block it', () => {
      const event = { preventDefault: jest.fn(), clipboardData: clipboardData };
      const eventSpy = jest.spyOn(event, 'preventDefault');

      const fakeInput = fixture.debugElement.query(By.css(".input"));
      fakeInput.triggerEventHandler('paste', event);
      expect(eventSpy).toHaveBeenCalled();
      expect(eventSpy).toHaveBeenCalledTimes(1);
    });

【讨论】: