Reputation: 2313
I've got a global object on window
that has a function. In my code I'm writing this:
if (window.foo) {
window.foo.bar();
}
In the tests, when window.foo
has a value I assert that window.foo.bar
has been called. Easy enough.
Jest coverage is complaining that I'm not testing the negative value, i.e. when window.foo
is undefined. But I've been struggling to work out what to assert on.
What I'd like to do - is mock window.foo
and assert that it is only called once, when we check whether it has a value or is undefined (i.e. the call to window.foo.bar
is never made.
I'm trying to mock the global window object and return an object but I'm getting confused as to how to mock and spyOn a value when it isn't a function, and then check it has been accessed.
Any help appreciated!
Upvotes: 1
Views: 506
Reputation: 22862
You could use a getter so whenever a property in the object is being accessed inside the getter we could run multiple actions, in our case we just trigger our spy manually.
describe('window.foo', () => {
afterEach(() => {
delete global.foo // make sure you clean your global object after each test
})
it('should be called twice', () => {
const fooSpy = jest.fn();
const barSpy = jest.fn();
Object.defineProperty(global, 'foo', {
configurable: true, // very important or else you can't delete
get() {
fooSpy(); //we manually call our spy so we can assert later
// and we return an object with another spy for our bar function
return { bar: barSpy};
}
});
if (global.foo) {
global.foo.bar()
}
expect(fooSpy).toHaveBeenCalledTimes(2);
expect(barSpy).toHaveBeenCalledTimes(1);
});
it('should be called once', () => {
const fooSpy = jest.fn();
Object.defineProperty(global, 'foo', {
writconfigurableable: true,
get() {
fooSpy(); // we trigger the spy manually
// we return undefined
return undefined;
}
});
if (global.foo) {
global.foo.bar()
}
expect(fooSpy).toHaveBeenCalledTimes(1);
});
});
You can see it working in here
Upvotes: 2