Имитация свойств событий окна, документа и щелчка мыши в Angular Jest-тестировании - PullRequest
1 голос
/ 14 января 2020

У меня есть функция, прикрепленная к четному слушателю, которая проверяет, щелкнули ли вы по всплывающему окну или в нем, и закрывает его, если вы отключили его. Он использует различные свойства окна и объекта документа для проверки этих вещей, а также getBoundingClientRect() для определения позиции всплывающего окна.

Проблема, с которой я сталкиваюсь, заключается в том, что я не могу понять, как имитировать все это в тесте. Я видел, что в Jest вы используете глобальный объект в качестве объекта окна, когда насмехаетесь над вещами?

Вот моя функция, которая проверяет расположение и щелчок:

popoverEscape = e => {
  const popover = this.panelEl.nativeElement.getBoundingClientRect();
  const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft
  const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
  const left = popover.left + scrollLeft
  const right = popover.left + scrollLeft + popover.width
  const top = popover.top + scrollTop
  const bottom = popover.top + scrollTop + popover.height

  if(!this.isBetween(e.clientX, left, right) || !this.isBetween(e.clientY, top, bottom)){
  this.closePopover()


  }
};

isBetween(n, a, b) {
   return (n - a) * (n - b) <= 0
}

1 Ответ

0 голосов
/ 15 января 2020

Вот решение для юнит-теста:

index.ts:

export class SomeComponent {
  panelEl = {
    nativeElement: document.createElement('div'),
  };

  popoverEscape = (e) => {
    const popover = this.panelEl.nativeElement.getBoundingClientRect();
    const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
    const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
    const left = popover.left + scrollLeft;
    const right = popover.left + scrollLeft + popover.width;
    const top = popover.top + scrollTop;
    const bottom = popover.top + scrollTop + popover.height;

    if (!this.isBetween(e.clientX, left, right) || !this.isBetween(e.clientY, top, bottom)) {
      this.closePopover();
    }
  };

  isBetween(n, a, b) {
    return (n - a) * (n - b) <= 0;
  }

  closePopover() {}
}

index.test.ts:

import { SomeComponent } from './';

describe('59737707', () => {
  afterEach(() => {
    jest.clearAllMocks();
    jest.restoreAllMocks();
  });
  describe('#popoverEscape', () => {
    it('should close popover if first isBetween return falsy', () => {
      Object.defineProperty(window, 'pageXOffset', { value: 100 });
      document.documentElement.scrollTop = 200;
      const comp = new SomeComponent();
      const rect = { left: 10, width: 20, top: 10, height: 50 };
      jest.spyOn(comp.panelEl.nativeElement, 'getBoundingClientRect').mockReturnValueOnce(rect as DOMRect);
      jest.spyOn(comp, 'isBetween').mockReturnValueOnce(false);
      comp.closePopover = jest.fn();
      const mEvent = { clientX: 100, clientY: 200 };
      comp.popoverEscape(mEvent);
      expect(comp.panelEl.nativeElement.getBoundingClientRect).toBeCalledTimes(1);
      expect(comp.closePopover).toBeCalledTimes(1);
      expect(comp.isBetween).toBeCalledTimes(1);
    });

    it('should close popover if second isBetween return falsy', () => {
      Object.defineProperty(window, 'pageXOffset', { value: 100 });
      document.documentElement.scrollTop = 200;
      const comp = new SomeComponent();
      const rect = { left: 10, width: 20, top: 10, height: 50 };
      jest.spyOn(comp.panelEl.nativeElement, 'getBoundingClientRect').mockReturnValueOnce(rect as DOMRect);
      jest
        .spyOn(comp, 'isBetween')
        .mockReturnValueOnce(true)
        .mockReturnValueOnce(false);
      comp.closePopover = jest.fn();
      const mEvent = { clientX: 100, clientY: 200 };
      comp.popoverEscape(mEvent);
      expect(comp.panelEl.nativeElement.getBoundingClientRect).toBeCalledTimes(1);
      expect(comp.closePopover).toBeCalledTimes(1);
      expect(comp.isBetween).toBeCalledTimes(2);
    });
  });
});

Результаты юнит-теста с отчетом о покрытии:

 PASS  src/stackoverflow/59737707/index.test.ts (14.308s)
  59737707
    #popoverEscape
      ✓ should close popover if first isBetween return falsy (12ms)
      ✓ should close popover if second isBetween return falsy (3ms)

----------|----------|----------|----------|----------|-------------------|
File      |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files |    94.12 |       75 |       50 |    93.75 |                   |
 index.ts |    94.12 |       75 |       50 |    93.75 |                21 |
----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        16.602s

Вы можете сделать то же самое для непокрытой ветви и функции и улучшить покрытие теста до 100%.

Исходный код: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/59737707

...