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

3
我有一个函数附加到事件监听器上,它会检查您是否已经点击了弹出窗口或在其中,并在您点击其外部时关闭它。它使用窗口和文档对象上的各种属性来检查这些内容,以及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个回答

1
这里是单元测试的解决方案:

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

哇!非常感谢你如此详细的回答!太完美了,谢谢! - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接