I have a javascript utility file that makes API requests. It has two conditional's at the top that rely on window.VarA and window.VarB. Where VarA and VarB are variables given to the window by our software. If they are set the code inside the conditional is run. Since this file doesn't actually render a window I can't set these properties to anything and get code coverage inside the conditional.
I've attempted rendering a default window but that doesn't seem to work. I have Jest and Enzyme available to me.
The code from the object that I am testing looks like this
let param = "";
let url = "";
if(window.VarA !== underfined){
     param = window.VarA; <<--need coverage here
}
if(window.VarB !== underfined){
     url = window.VarB; <<--need coverage here
}
Is there some way to mock these window properties for my tests?
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.
There are two ways to mock functions: Either by creating a mock function to use in test code, or writing a manual mock to override a module dependency.
If you need to mock a global variable for all of your tests, you can use the setupFiles in your Jest config and point it to a file that mocks the necessary variables. This way, you will have the global variable mocked globally for all test suites.
You are right to mock getUsersPage() , but you setting up the mock/spy incorrectly. getUsersPages() is not defined/exported from within canViewPage() . Instead try targeting getUsersPage() directly to create a mock/spy. With the spy working, then you can assert canViewPage('premiumPage') accordingly.
The default test environment for Jest is a browser-like environment using jsdom which provides a window object.
If the test environment is jsdom then the window object is accessible as either window or global.
Setting variables on window then becomes as easy as doing the following:
window.VarA = 'foo';  // global.VarA works as well
window.VarB = 'bar';  // global.VarB works as well
The trickier part is getting those variables set before your code runs.
Consider the following config.js module:
let param = "";
let url = "";
if (window.VarA !== undefined) {
  param = window.VarA;
}
if (window.VarB !== undefined) {
  url = window.VarB;
}
export const config = {
  param,
  url
}
If you use require then the code doesn't run until the module is required, allowing for a test like this:
test('setting window variables', () => {
  window.VarA = 'foo';  // global.VarA works as well
  window.VarB = 'bar';  // global.VarB works as well
  const { config } = require('./config');  // now require the module
  expect(config.param).toBe('foo');  // SUCCESS
  expect(config.url).toBe('bar');  // SUCCESS
});
On the other hand, if you use import then the variables need to be defined on window before the test runs since imports are hoisted and happen before any test code runs:
import { config } from './config';  // this runs first
test('setting window variables', () => {
  window.VarA = 'foo';  // <= this doesn't affect config
  window.VarB = 'bar';  // <= this doesn't affect config
  expect(config.param).toBe('foo');  // FAIL
  expect(config.url).toBe('bar');  // FAIL
});
So if you are using import then you would need to use something like setupFilesAfterEnv to set the window variables before your test begins running:
// Configure Jest using setupFilesAfterEnv
// to run a module that sets the window variables
// so they are already set before the test begins...
import { config } from './config';
test('setting window variables', () => {
  expect(config.param).toBe('foo');  // SUCCESS
  expect(config.url).toBe('bar');  // SUCCESS
});
                        Great answer by Brian Adams. Just as an alternative to setupFilesAfterEnv you could also dynamically import module in the body of a test:
test('setting window variables', async () => {
  window.VarA = 'foo';
  window.VarB = 'bar';
  const { config } = await import('./config');
  expect(config.param).toBe('foo');  // SUCCESS
  expect(config.url).toBe('bar');  // SUCCESS
});
Please note that window variable cannot be reassigned - further tests will still reference originally assigned value in the first place or produce side effects. For example:
test('setting window variables', async () => { ... });
test('setting a different window variable A', async () => {
  window.VarA = 'baz';
  const { config } = await import('./config');
  expect(config.param).toBe('baz');  // FAIL, it's still 'foo'
});
So to avoid mental confusion it's worth to move window assignments in beforeAll or beforeEach:
beforeAll(() => {
  window.VarA = 'foo';
  window.VarB = 'bar';
});
test('setting window variables', async () => {
  const { config } = await import('./config');
  expect(config.param).toBe('foo');
  expect(config.url).toBe('bar');   
});
                        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