Closed alucryd closed 1 year ago
What version are you on? Fake timers support was only published a few weeks ago: https://github.com/nicolo-ribaudo/jest-light-runner/releases/tag/v0.5.0
I am on 0.5.0, here are my dev deps:
"devDependencies": {
"@babel/core": "^7.22.5",
"@babel/eslint-parser": "^7.22.5",
"@babel/plugin-syntax-import-assertions": "^7.22.5",
"babel-jest": "^29.5.0",
"better-sqlite3": "^8.4.0",
"c8": "^8.0.0",
"clinic": "^12.1.0",
"esmock": "^2.3.1",
"healthier": "^6.3.0",
"jest": "^29.5.0",
"jest-junit": "^16.0.0",
"jest-light-runner": "^0.5.0",
"mockdate": "^3.0.5",
"nodemon": "^2.0.22",
"prettier": "^2.8.8",
"supertest": "^6.3.3"
},
setSystemTime
takes a Date
object, not a Dayjs
object. The correct usage is this.
jest.useFakeTimers().setSystemTime(dayjs().toDate());
You would have caught this error if you would have used TypeScript:
Me and 2xic (feature author) have used the features released in 0.5.0 in our own larger codebase for 6 months now. Below are some code snippets and functions that have served us well.
jest.setup.after.env.js
const dayjs = require('dayjs');
expect.addSnapshotSerializer({
test: (arg) => dayjs.isDayjs(arg),
print: (val) => {
const content = val.isSame(val.startOf('day')) ? val.format('YYYY-MM-DD') : val.toISOString();
return '"' + content + '"';
},
});
setMockTime.ts
import dayjs, { Dayjs } from 'dayjs';
/**
* Be sure to call jest.useRealTimers() in afterEach when using this, or the pipeline will time out after 1 hour.
*/
export function setMockTime(dateTime: string | Dayjs): Dayjs {
const dayjsObject = dayjs(dateTime, { utc: true }).tz('Europe/Oslo'); // your timezone
// standard validation of dayjs objects
try {
dayjsObject.toISOString();
} catch (e) {
throw new Error(`Invalid date string: "${dateTime}"`);
}
jest.useFakeTimers().setSystemTime(dayjsObject.toDate());
return dayjsObject;
}
setMockTime.test.ts
import dayjs from 'dayjs';
import { setMockTime } from './setMockTime';
describe('setMockTime', () => {
afterEach(() => {
jest.useRealTimers();
});
it('should set the time to a constant value', async () => {
setMockTime('2023-01-01 12:00');
expect(dayjs()).toMatchInlineSnapshot(`"2023-01-01T12:00:00.000Z"`);
});
it('should throw error if we try to set the time to an invalid time string', () => {
expect(() => setMockTime('2023-01--01 12:00:00')).toThrowErrorMatchingInlineSnapshot(
`"Invalid date string: "2023-01--01 12:00:00""`,
);
});
});
This can be closed if the fix works for @alucryd
Thank you! I'll reopen if the fix does not work.
should probably be a runtime error in Jest...
@nicolo-ribaudo Using a Date
object does indeed work, thanks! However I'm now running into another issue, the timer logic works fine for a single test file, however if I try to put the following block in multiple files, subsequent calls to jest.useFakeTimers()
will completely freeze the tests, only the first file will run, then the terminal hangs indefinitely.
now = dayjs();
beforeAll(async () => {
jest.useFakeTimers().setSystemTime(now.toDate());
});
afterAll(async () => {
jest.useRealTimers();
});
Yes, i have also seen the bug you are describing. My current workound is to be sure to call jest.useRealTimers()
in afterEach
when i am using fake timers. I hinted at this in the docstring of my setMockTime
function above. We usually don't mock the time in every test, but only when the test relies on the time to pass. Most of your tests should work without mocking the time.
@alucryd Could you create a new issue with a minimal reproducible example and instructions of how to execute this bug? It is better to fix this in a new issue than to reuse this closed issue.
Hi there, I'm trying to use the fake timers from jest, but I can't get them to work. I'm using jest-light-runner with esmock, and my dates are handled by dayjs.
Non-working snippet:
Resulting in:
Working snippet:
Am I doing something wrong? I also tried legacy timers in jest to no avail.