查看Jest问题和SO answers后,我尝试了以下4个选项,但我遇到TypeScript错误或运行时错误。我真的很想让选项1(spyOn)工作。
// ------ option 1 -----
// Gives this runtime error: "Cannot spyOn on a primitive value; undefined given"
const writeText = jest.spyOn(navigator.clipboard, 'writeText');
// ------ option 2 -----
Object.defineProperty(navigator, 'clipboard', {
writeText: jest.fn(),
});
// ------ option 3 -----
// This is from SO answer but gives a TypeScript error
window.__defineGetter__('navigator', function() {
return {
clipboard: {
writeText: jest.fn(x => x)
}
}
})
// ------ option 4 -----
const mockClipboard = {
writeText: jest.fn()
};
global.navigator.clipboard = mockClipboard;
答案 0 :(得分:6)
Jest测试是在JSdom环境中运行的,并不是所有的属性都已定义,但是您应该在监视该函数之前先定义它。
这里是一个例子:
Object.assign(navigator, {
clipboard: {
writeText: () => {},
},
});
describe("Clipboard", () => {
describe("writeText", () => {
jest.spyOn(navigator.clipboard, "writeText");
beforeAll(() => {
yourImplementationThatWouldInvokeClipboardWriteText();
});
it("should call clipboard.writeText", () => {
expect(navigator.clipboard.writeText).toHaveBeenCalledWith("zxc");
});
});
});
编辑:您也可以使用Object.defineProperty
,但是它接受描述符对象作为第三个参数
Object.defineProperty(navigator, "clipboard", {
value: {
writeText: () => {},
},
});
答案 1 :(得分:3)
我遇到了类似的情况,使用以下方法模拟导航器对象中的剪贴板:
const originalClipboard = { ...global.navigator.clipboard };
const mockData = {
"name": "Test Name",
"otherKey": "otherValue"
}
beforeEach(() => {
const mockClipboard = {
writeText: jest.fn(),
};
global.navigator.clipboard = mockClipboard;
});
afterEach(() => {
jest.resetAllMocks();
global.navigator.clipboard = originalClipboard;
});
test("copies data to the clipboard", () => {
copyData(); //my method in the source code which uses the clipboard
expect(navigator.clipboard.writeText).toBeCalledTimes(1);
expect(navigator.clipboard.writeText).toHaveBeenCalledWith(
JSON.stringify(mockData)
);
});