这里是单元测试的解决方案:
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
✓ 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
----------|----------|----------|----------|----------|-------------------|
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