Reputation: 1953
There is a website I use which shows different content on different dates. In the JavaScript, it uses new Date()
to determine the current date, which it uses to determine which content to show.
If I would like to view content from a different date, I can change my system time. However, this is tedious and interferes with other applications. I am trying to figure out if there is some code I can run in the browser's javascipt console that will mock out new Date()
to return the date of my choosing
I see there are some questions that discuss creating a spy on Date with jest, but I do not see a way to mock this in my browser console
Upvotes: 0
Views: 1866
Reputation: 11
Here's implementation for mocking the Date object in browser. Month is always zero based and default date is set to January 1st 2024 which can be changed. This is best to be used for test purposes only:
((originalDate) => {
// Function to mock the Date object
function MockDate(...args) {
if (args.length) {
return new originalDate(...args);
}
// Default date: January 1, 2024
return new originalDate(2024, 0, 1);
}
MockDate.prototype = originalDate.prototype;
MockDate.now = () => new MockDate().getTime();
MockDate.UTC = originalDate.UTC;
MockDate.parse = originalDate.parse;
// Override the global Date object
Date = MockDate;
})(Date);
Can be tested with:
console.log(new Date());
Upvotes: 1
Reputation: 4549
thank you @t-j-crowder 🙏 for the best solution I have found so far... I made some customisation to it so Date.now works as well.
Also one advise, put breakpoint at the very beginning of your script, run the code in console and resume execution for best date consistency 😌
my modification:
// Save the original `Date` function
const OriginalDate = Date;
const fakeDateArgs = [2022, 5, 3]; // beware month is 0 based
let fakeDate;
// Replace it with our own
Date = function Date(...args) {
// Called via `new`?
if (!new.target) {
// No, just pass the call on
return OriginalDate(...args);
}
// Determine what constructor to call
const ctor = new.target === Date ? OriginalDate : new.target;
// Called via `new`
if (args.length !== 0) {
// Date constructor arguments were provided, just pass through
return Reflect.construct(ctor, args);
}
// It's a `new Date()` call, mock the date we want; in this
fakeDate = Reflect.construct(ctor, fakeDateArgs);
return fakeDate;
};
// Make our replacement look like the original (which has `length = 7`)
// You can't assign to `length`, but you can redefine it
Object.defineProperty(Date, "length", {
value: OriginalDate.length,
configurable: true
});
Object.defineProperty(Date, "now", {
value: () => fakeDate.getTime(),
configurable: true
});
Upvotes: 2
Reputation: 396
You can use this to modify the content before it is loaded: https://developer.chrome.com/docs/extensions/reference/webRequest/
There is this extension which I haven't used that may be able to do it: https://chrome.google.com/webstore/detail/page-manipulator/mdhellggnoabbnnchkeniomkpghbekko?hl=en
Upvotes: 0
Reputation: 1075755
It's possible to replace the Date
function with your own function that provides the results you want, but doing it before the page uses it will be tricky unless you write a browser extension.
The fundamental bit is (see comments):
// Save the original `Date` function
const OriginalDate = Date;
// Replace it with our own
Date = function Date(...args) {
// Called via `new`?
if (!new.target) {
// No, just pass the call on
return OriginalDate(...args);
}
// Determine what constructor to call
const ctor = new.target === Date ? OriginalDate : new.target;
// Called via `new`
if (args.length !== 0) {
// Date constructor arguments were provided, just pass through
return Reflect.construct(ctor, args);
}
// It's a `new Date()` call, mock the date we want; in this
// example, Jan 1st 2000:
return Reflect.construct(ctor, [2000, 0, 1]);
};
// Make our replacement look like the original (which has `length = 7`)
// You can't assign to `length`, but you can redefine it
Object.defineProperty(Date, "length", {
value: OriginalDate.length,
configurable: true
});
// Save the original `Date` function
const OriginalDate = Date;
// Replace it with our own
Date = function Date(...args) {
// Called via `new`?
if (!new.target) {
// No, just pass the call on
return OriginalDate(...args);
}
// Determine what constructor to call
const ctor = new.target === Date ? OriginalDate : new.target;
// Called via `new`
if (args.length !== 0) {
// Date constructor arguments were provided, just pass through
return Reflect.construct(ctor, args);
}
// It's a `new Date()` call, mock the date we want; in this
// example, Jan 1st 2000:
};
// Make our replacement look like the original (which has `length = 7`)
// You can't assign to `length`, but you can redefine it
Object.defineProperty(Date, "length", {
value: OriginalDate.length,
configurable: true
});
console.log("new Date()", new Date());
console.log("new Date(2021, 7, 3)", new Date(2021, 7, 3));
Upvotes: 4