我正在尝试模拟document.clipboard。
这是我的代码:
handleCopyIdToClipboard = () => {
const el = document.querySelector(`.${CLASS_NAME}`);
navigator.clipboard.writeText(el.textContent);
// some extra code
showPopup();
};
这是我开玩笑的测试:
describe('handleCopyToClipboard', () => {
const mockQuerySelector = jest.fn();
const mockBoundingClientRect = jest.fn();
const mockClipboard = jest.fn();
const mockWriteText = jest.fn();
mockQuerySelector.mockReturnValue({textContent: 'someText', getBoundingClientRect: mockBoundingClientRect});
mockBoundingClientRect.mockReturnValue({top: 100, left: 100});
Object.defineProperty(document, 'querySelector', {value: mockQuerySelector});
Object.defineProperty(navigator, 'clipboard', {value: mockClipboard});
Object.defineProperty(navigator.clipboard, 'writeText', {value: mockWriteText});
beforeEach(() =>
[mockQuerySelector, mockClipboard, mockWriteText, mockBoundingClientRect].map(mock =>
mock.mockClear(),
),
);
it('should copy to clipboard', () => {
const wrapper = buildComponent(DetailsPage, props);
wrapper.instance().handleCopyIdToClipboard('id');
expect(mockQuerySelector).toHaveBeenCalled();
expect(mockClipboard).toHaveBeenCalled();
expect(mockWriteText).toHaveBeenCalled();
expect(mockBoundingClientRect).toHaveBeenCalled();
expect(wrapper.state().showPopup).toEqual(true);
expect(wrapper.state().top).toEqual(90);
expect(wrapper.state().left).toEqual(200);
});
});
此行失败expect(mockClipboard).toHaveBeenCalled();
,指示从不调用模拟剪贴板。但是,如果我删除此行,expect(mockWriteText).toHaveBeenCalled();
不会失败。有想法吗?
编辑:
我已将功能更新为以下内容:
handleCopyIdToClipboard = () => {
navigator.clipboard
.writeText(this.state.urn)
.then(() => {
this.setState({showPopup: true});
})
.catch(doNothing);
};
当前的笑话测试:
describe('handleCopyToClipboard', () => {
const mockClipboard = jest.fn();
const mockWriteText = jest.fn();
Object.defineProperty(navigator, 'clipboard', {value: mockClipboard});
Object.defineProperty(navigator.clipboard, 'writeText', {value: mockWriteText});
beforeEach(() => [mockClipboard, mockWriteText].map(mock => mock.mockClear()));
it('should copy to clipboard', () => {
const wrapper = buildComponent(ServiceAccountDetailsPage, props);
mockWriteText.mockReturnValueOnce(true);
return wrapper
.instance()
.handleCopyIdToClipboard()
.then(() => {
expect(mockWriteText).toHaveBeenCalled();
expect(wrapper.state().showPopup).toEqual(true);
});
});
});
遇到此错误:navigator.clipboard.writeText(...).then is not a function
。我想同时测试.then()
和.catch()
块
答案 0 :(得分:0)
Navigator.clipboard不是一个函数,您不应该将它作为一个函数来嘲笑。您应该模拟整个clipboard
对象。例如
main.ts
:
export function handleCopyIdToClipboard() {
const el = document.querySelector('.class-name');
const textContent = el ? el.textContent || '' : '';
return navigator.clipboard.writeText(textContent);
}
main.test.ts
:
import { handleCopyIdToClipboard } from './main';
describe('61348091', () => {
it('should pass', async () => {
const mElement = { textContent: 'hello' };
const mockQuerySelector = jest.fn().mockReturnValueOnce(mElement);
const mockWriteText = jest.fn().mockResolvedValueOnce('clipText');
Object.defineProperty(document, 'querySelector', { value: mockQuerySelector });
Object.defineProperty(navigator, 'clipboard', {
value: {
writeText: mockWriteText,
},
});
const actual = await handleCopyIdToClipboard();
expect(actual).toBe('clipText');
expect(mockQuerySelector).toBeCalledWith('.class-name');
expect(mockWriteText).toBeCalledWith('hello');
});
});
具有覆盖率报告的单元测试结果:
PASS stackoverflow/61348091/main.test.ts (16.222s)
61348091
✓ should pass (6ms)
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 100 | 50 | 100 | 100 |
main.ts | 100 | 50 | 100 | 100 | 3
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 18.23s