Mocking Window with Sinon, Mocha, Enzyme, and React

DimlyAware picture DimlyAware · Jun 10, 2016 · Viewed 21.5k times · Source

I'm trying to mock out the window object for a component I'm using with just the four libraries listed above.

I know it can be done with JSDom but the client is against using it. Based on my research simply doing sinon.stub(window,'location') should work but when I run my tests I still get Window undefined in my component.

Currently the component is called within the render return {window.location.host}

any thoughts to what I am doing wrong to get sinon to stub out that one piece. Once I stub out that piece then I can focus on testing the other parts of that component that have nothing to do with window.

My Test Method:

import React from 'react';

import { shallow } from 'enzyme';
import chai from 'chai';
chai.should();
import sinon from 'sinon';

import BillingStatementRow from '../BillingStatementRow';

describe('Test <BillingStatementRow /> Component', function() {

    context('Function Testing', function() {

        it('Test - onFieldChange - Make sure it handles NaN', function() {

            var e = {target: {value: NaN}};

            var window = { location : { host : "..." } };

            var mockedOnChange = sinon.spy();

            const wrapper = shallow (
                <BillingStatementRow slds={''} key={'1'}
                    Id={'1'} inputValue={'0'} salesInvoice={'SIN0001'}
                    invoicedAmount={1000} duedate={'1461628800000'}
                    outstandingBalance={1000} receiptRemaining={1000}
                    amountAllocated={1000} onChange={mockedOnChange.bind(this,'BS0001')} />
            );

            wrapper.instance().onFieldChange('amountAllocated', e);
            wrapper.update();


        })


    });

});

Answer

robertklep picture robertklep · Jun 10, 2016

Sinon stubs/spies/mocks only work with functions. In this case, you're trying to mock a global (nested) variable, for which Sinon isn't the right tool.

Instead, just like in a browser, you can create a global object that mocks just the right amount of window to work with your component, which is easy because it only accesses window.location.host.

So before instantiating the component, declare the following:

global.window = { location : { host : 'example.com' } };