I have tried the following 4 options after looking at Jest issues and SO answers, but I am either getting TypeScript errors or runtime errors. I would really like to get option 1 (spyOn) working.
// ------ 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;
clipboard. The Clipboard API adds to the Navigator interface the read-only clipboard property, which returns the Clipboard object used to read and write the clipboard's contents. The Clipboard API can be used to implement cut, copy, and paste features within a web application.
To mock the JavaScript window object using Jest, we can use the jest. spyOn method. let windowSpy; beforeEach(() => { windowSpy = jest. spyOn(window, "window", "get"); }); afterEach(() => { windowSpy.
I expanded on the earlier solutions and also gave the mock clipboard functionality for readText so the content of the clipboard can be tested. Show activity on this post. In my environment, testing-library svelte and jest jsdom, I did not manage to mock the global.navigator.
Mock Return Values Mock functions can also be used to inject test values into your code during a test: const myMock = jest.fn();
Changing to global can't help because navigator is browser feature. It should exists if Jest was configured to use JSDOM. Make sure that you did that. But I'm not sure how you previous attempt could work because there would be no window.navigator without JSDOM. Make sure your dependencies are up to date.
Now, in order to test this method without actually hitting the API (and thus creating slow and fragile tests), we can use the jest.mock (...) function to automatically mock the axios module. Once we mock the module we can provide a mockResolvedValue for .get that returns the data we want our test to assert against.
Jest tests are running in JSdom environment and not all of the properties are defined, but so you should define the function before spying on it.
Here is an example:
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");
});
});
});
Edit: you can also use Object.defineProperty
, but it accepts descriptors object as third parameter
Object.defineProperty(navigator, "clipboard", {
value: {
writeText: () => {},
},
});
I ran into a similar situation and used the following method to mock the clipboard in the navigator object:
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)
);
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With