Angular: How to test a directive that blocks paste events on inputs?

576 Views Asked by At

I'm trying to test a directive which doesn't let me paste any data into an input element.

The directive looks like this:

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

The way I thought of testing it is that the value of the input should change when adding a paste InputEvent but it doesn't. In both cases when applying the directive and not, the value is represented by an empty string.

Any ideas on how to test it? Thanks in advance :)

The test looks like this:


@Component({
  template: '<input type="text" kycBlockPaste>'
})
class TestBlockPasteDirectiveComponent {}

fdescribe('Block Paste directive', () => {
  let component: TestBlockPasteDirectiveComponent;
  let fixture: ComponentFixture<TestBlockPasteDirectiveComponent>;
  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
1

There are 1 best solutions below

0
dan On

You can mock clipboard data. I am using 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);
    });