Skip to content

Instantly share code, notes, and snippets.

@Integralist
Last active October 17, 2017 09:44
Show Gist options
  • Save Integralist/7927745 to your computer and use it in GitHub Desktop.
Save Integralist/7927745 to your computer and use it in GitHub Desktop.
JavaScript: mocking the Window and Document objects

In tabloid/webapp/php/sharedmodules/tabloid-shared/views/layout/base.spv we run...

require(['module/base', 'domReady'], function (base, domReady) {
    domReady(function () {
        base.init();
        <?php $this->newsPageJavaScript(); ?>
    });
});

...this loads our base module which sets up stats and other baseline requirement stuff (such as setting classes on HTML elements).

This module loads module/bootstrap which sets up jQuery and our pubsub library. This module is typically imported EVERYWHERE, like so...

define(['module/bootstrap'], function (news) {
    var $      = news.$,
        pubsub = news.pubsub;
        
    // code
});

I'm thinking within module/bootstrap we could load up the WindowMock module like so...

define(['jquery', 'config', 'module/windowMock' 'vendor/events/pubsub'], function(jquery, config, windowMock) {
    // note: pubsub module doesn't return anything and so we put it last in the dependency list
    var news = {
        pubsub: jquery,
        $: jquery,
        config: config,
        window: (isTestEnvironment) ? windowMock : window,
        document: (isTestEnvironment) ? windowMock.document : window.document
    };

    return news;
});

...note: we'd need to move the windowMock helper file into the 'module' directory.

The windowMock file looks like this...

define([
    'module/bootstrap',
], function (news) {
        var windowMock = {
            resizeSet: false, // set within the fake News object below

            createFakeWindow: function(width, height) {
                return {
                    document: {
                        documentElement: {
                            clientWidth: width,
                            clientHeight: height
                        }
                    },

                    resizeTo: function(width, height) {
                        this.document.documentElement = {
                            clientWidth: width,
                            clientHeight: height
                        };
                    }
                };
            },

            fireResizeEvent: function() {
                this.handler(); // set within the fake News object below
            },

            news: {
                $: function(element) {
                    return {
                        on: function(event, handler) {
                            if (event === 'resize') {
                                windowMock.resizeSet = true;
                                windowMock.handler = handler;
                            }
                        }
                    };
                },

                pubsub: news.pubsub
            }
        };

        return windowMock;
    }
);

You can also use it like so...

function createFakeWindow (width, height) {
    var fakeWindow = WindowMock.createFakeWindow(width, height);

    someObject.init(fakeWindow, WindowMock.news); // this can be removed or changed appropriately

    return fakeWindow;
}

function resizeWindow (width, height, fakeWindow) {
    document.body.style.width = width + 'px'; // remember to reset this in the test tear down
    fakeWindow.resizeTo(width, height);
    WindowMock.fireResizeEvent();
}

See we use isTestEnvironment to check what to return. I'm guessing we'll set isTestEnvironment = true within our jasmine test runner set-up (before we load modules/bootstrap).

So within our code we can just do...

define([
    'module/bootstrap',
    'module/navigation/nav',
    'module/navigation/narrow'
], function(
    news,
    nav,
    narrow
) {
    var $ = news.$,
        pubsub = news.pubsub,
        window = news.window,
        document = news.document;

    // we can now use `window` and `document` and they'll either be our mock or the real thing
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment