'Override the browser date with puppeteer

I'm trying to setup puppeteer to run a few performance tests. I'd like to override the date to a specific value so that I can mock the data my app needs without needing to generate content dynamically based on the date.

How to override the date of the puppeteer browser?



Solution 1:[1]

We found a much simpler way to mock out the date in puppeteer. Here is our example:

page.evaluate(() => {
  Date.now = () => {
    return 1539806611024;
  };
});

Solution 2:[2]

I ended up having the same problem. This is how I managed to solve it:

// mock date of document
if (!page.dateIsMocked) {
    page.dateIsMocked = true
    await page.evaluateOnNewDocument(() => {
        var _Date = Date,
            _getTimezoneOffset = Date.prototype.getTimezoneOffset,
            now = null
        function MockDate(y, m, d, h, M, s, ms) {
            var date
            switch (arguments.length) {
                case 0:
                    if (now !== null) {
                        date = new _Date(now)
                    } else {
                        date = new _Date()
                    }
                    break
                case 1:
                    date = new _Date(y)
                    break
                default:
                    d = typeof d === 'undefined' ? 1 : d
                    h = h || 0
                    M = M || 0
                    s = s || 0
                    ms = ms || 0
                    date = new _Date(y, m, d, h, M, s, ms)
                    break
            }

            return date
        }
        MockDate.UTC = _Date.UTC
        MockDate.now = function() {
            return new MockDate().valueOf()
        }
        MockDate.parse = function(dateString) {
            return _Date.parse(dateString)
        }
        MockDate.toString = function() {
            return _Date.toString()
        }
        MockDate.prototype = _Date.prototype

        function set(date, timezoneOffset) {
            var dateObj = new Date(date)
            if (isNaN(dateObj.getTime())) {
                throw new TypeError(
                    'mockdate: The time set is an invalid date: ' + date
                )
            }
            if (typeof timezoneOffset === 'number') {
                MockDate.prototype.getTimezoneOffset = function() {
                    return timezoneOffset
                }
            }
            Date = MockDate
            now = dateObj.valueOf()
        }

        // mock date
        set(1577840400000)
    })
}

The actual logic for mocking the Date is borrowed from the MockDate library.

Solution 3:[3]

Based on the lighthouse documentation around puppeteer I got it working. https://github.com/GoogleChrome/lighthouse/blob/master/docs/puppeteer.md

Basicly did this to override Date.now:

browser.on('targetchanged', async target => {
  const targetPage = await target.page();
  const client = await targetPage.target().createCDPSession();
  await client.send('Runtime.evaluate', {
    expression: `Date.now = function() { return 0; }`
  });
});

Solution 4:[4]

Based on gergof answer https://stackoverflow.com/a/60166824/3641075, it seems it is possible to use MockDate library directly, following the same approach as in puppeteer doc here : https://pptr.dev/#?product=Puppeteer&version=v13.7.0&show=api-pageevaluateonnewdocumentpagefunction-args

if (page.mockDate) return;
page.mockDate = true;
const MockDate = fs.readFileSync('./node_modules/mockdate/lib/mockdate.js', 'utf8');
await page.evaluateOnNewDocument(`
  ${MockDate}
  MockDate.set(new Date(2021, 5, 22), 0);
`);

I'm trying to mock the date with @storybook/addon-storyshots-puppeteer, and this approach works for me with imageSnapshot API, by using the customizePage option. Here is a full config :

import initStoryshots from "@storybook/addon-storyshots";
import { imageSnapshot } from "@storybook/addon-storyshots-puppeteer";
import fs from "fs";

initStoryshots({
  test: imageSnapshot({
    storybookUrl: "http://localhost:6007",
    customizePage: async (page) => {
      const MockDate = fs.readFileSync('./node_modules/mockdate/lib/mockdate.js', 'utf8');
      await page.evaluateOnNewDocument(`
        ${MockDate}
        MockDate.set(new Date(2021, 5, 22), 0);
      `);
    },
  }),
});

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 athornburg
Solution 2 gergof
Solution 3 RĂ©mi Gebski
Solution 4