how to mock on global object in backstop.js/puppetter

339 views Asked by At

So backstop.js provides ability to run custom script against underlying engine. I use puppeteer as an engine so I try to mock Date.now with 'onReadyScript':

page.evaluate('window.Date.now = () => 0; Date.now = () => 0;');
...
page.addScriptTag({
  // btw `console.log` here is not executed, do I use it in wrong way?
  content: 'Date.now = () => 0;' 
});
...
page.evaluate(() => {
  window.Date.now = () => 0;
  Date.now = () => 0;
});

Last one, I think, is modifying Date in context of Node, not inside the puppeteer, but anyway tried that as well.

Nothing worked, script under the test still output real Date.now. Also I checked Override the browser date with puppeteer but it did not help me.

Yes, I know I'm able to skip particular selectors, but it does not always make sense(think about clock with arrows).

1

There are 1 answers

0
skyboyer On BEST ANSWER

After trying onBeforeScript with evaluateOnNewDocument() it works for me. Complete script:

module.exports = async function (page, scenario) {
    if (!page.dateIsMocked) {
        page.dateIsMocked = true
        await page.evaluateOnNewDocument(() => {
            const referenceTime = '2010-05-05 10:10:10.000';
            const oldDate = Date;
            Date = function(...args) {
                if (args.length) {
                    return new oldDate(...args);
                } else {
                    return new oldDate(referenceTime);
                }
            }
            Date.now = function() {
                return new oldDate(referenceTime).valueOf();
            }
            Date.prototype = oldDate.prototype;
        })
    }
};

Reason: onReadyScript is executed when page under testing has already been loaded and executed. So code is bound to original Date by closure, not the mocked version.