在Angular Jest测试中模拟窗口,文档和鼠标单击事件属性

时间:2020-01-14 16:11:37

标签: javascript angular unit-testing jestjs

我在一个偶数侦听器上附加了一个功能,该功能可以检查您是否单击了弹出窗口或弹出窗口,如果单击了弹出窗口,则将其关闭。它使用窗口和文档对象上的各种属性来检查这些内容,以及使用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 :(得分:0)

这是单元测试解决方案:

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