Skip to content

Commit

Permalink
Replace lolex with jest's fake timers in jest-dom-mock (#2642)
Browse files Browse the repository at this point in the history
  • Loading branch information
BPScott authored May 1, 2023
1 parent 69ec35a commit db05ac6
Show file tree
Hide file tree
Showing 7 changed files with 36 additions and 41 deletions.
16 changes: 16 additions & 0 deletions .changeset/few-mugs-live.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
'@shopify/jest-dom-mocks': major
---

Replace `lolex` with using Jest's built-in clock mocking, available since Jest 26. Internally Jest uses `@sinon/fake-timers` which is the API-compatible successor to `lolex`.

As of Jest 26, the functionality of the Clock and Timer mocks are built into Jest. We recommend replacing usage of these mocks with calling jest directly:

- Replace `clock.mock()` and `timer.mock()` with `jest.useFakeTimers()`
- Replace `clock.restore()` and `timer.restore()` with `jest.useRealTimers()`
- Replace `clock.tick(time)` with `jest.advanceTimersByTime(time)`
- Replace `clock.setTime(time)` with `jest.setSystemTime(time)`
- Replace `timer.runAllTimers()` with `jest.runAllTimers()`
- Replace `timer.runTimersToTime()` with `jest.advanceTimersByTime()`

You may encounter problems if you try to use the Clock and Timer mocks in the same file. We suggest migrating away from both of them, and replacing them with Jest's own mocking behaviour.
14 changes: 7 additions & 7 deletions packages/jest-dom-mocks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,10 @@ The following standard mocks are available:

- `animationFrame`
- `requestIdleCallback`
- `clock`
- `clock` (Deprecated, use `jest.useFakeTimers()` instead)
- `location`
- `matchMedia`
- `timer`
- `timer` (Deprecated, use `jest.useFakeTimers()` instead)
- `promise`
- `intersectionObserver`
- `dimension`
Expand Down Expand Up @@ -156,15 +156,15 @@ Cancels the idle callback specified by the passed argument. This value should be

#### `Clock.mock(now: number | Date): void`

In addition to the usual `.mock()` functionality (with no arguments), the `Clock` object can be `mock`ed by passing in a `number` or `Date` object to use as the current system time.
In addition to the usual `.mock()` functionality (with no arguments), the `Clock` object can be `mock`ed by passing in a `number` or `Date` object to use as the current system time. Deprecated - use `jest.useFakeTimers({now})` instead.

#### `Clock.tick(time: number): void`

Ticks the mocked `Clock` ahead by `time` milliseconds.
Ticks the mocked `Clock` ahead by `time` milliseconds. Deprecated - use `jest.advanceTimersByTime()` instead.

#### `Clock.setTime(time: number): void`

Sets the system time to the given `time`.
Sets the system time to the given `time`. Deprecated - use `jest.setSystemTime()` instead.

#### `MatchMedia.mock(media?: MediaMatching): void`

Expand Down Expand Up @@ -197,11 +197,11 @@ You can also call `setMedia` with no arguments to restore the default implementa

#### `Timer.runAllTimers(): void`

Runs all system timers to completion.
Runs all system timers to completion. Deprecated - use `jest.runAllTimers()` instead.

#### `Timer.runTimersToTime(time: number): void`

Runs all system timers to the given `time`.
Runs all system timers to the given `time`. Deprecated - use `jest.advanceTimersByTime()` instead.

#### `Promise.runPending(): void`

Expand Down
2 changes: 0 additions & 2 deletions packages/jest-dom-mocks/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,7 @@
"dependencies": {
"@shopify/async": "^4.0.3",
"@types/fetch-mock": "^7.3.3",
"@types/lolex": "^2.1.3",
"fetch-mock": "^9.11.0",
"lolex": "^2.7.5",
"promise": "^8.0.3"
},
"sideEffects": false,
Expand Down
19 changes: 4 additions & 15 deletions packages/jest-dom-mocks/src/clock.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import lolex from 'lolex';

export default class Clock {
private isUsingMockClock = false;
private mockClock?: lolex.Clock;

mock(now: number | Date = Date.now()) {
if (this.isUsingMockClock) {
Expand All @@ -11,8 +8,8 @@ export default class Clock {
);
}

jest.useFakeTimers({now});
this.isUsingMockClock = true;
this.mockClock = lolex.install({now});
}

restore() {
Expand All @@ -22,12 +19,8 @@ export default class Clock {
);
}

jest.useRealTimers();
this.isUsingMockClock = false;

if (this.mockClock) {
this.mockClock.uninstall();
delete this.mockClock;
}
}

isMocked() {
Expand All @@ -36,16 +29,12 @@ export default class Clock {

tick(time: number) {
this.ensureClockIsMocked();
if (this.mockClock) {
this.mockClock.tick(time);
}
jest.advanceTimersByTime(time);
}

setTime(time: number | Date) {
this.ensureClockIsMocked();
if (this.mockClock) {
this.mockClock.setSystemTime(time);
}
jest.setSystemTime(time);
}

private ensureClockIsMocked() {
Expand Down
2 changes: 2 additions & 0 deletions packages/jest-dom-mocks/src/tests/clock.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ describe('Clock', () => {
clock.mock();

expect(clock.isMocked()).toBe(true);
clock.restore();
});

it('throws if it is already mocked', () => {
Expand All @@ -19,6 +20,7 @@ describe('Clock', () => {
}).toThrow(
'The clock is already mocked, but you tried to mock it again.',
);
clock.restore();
});
});

Expand Down
14 changes: 7 additions & 7 deletions packages/react-effect/src/tests/server.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,17 @@

import React from 'react';
import {renderToString, renderToStaticMarkup} from 'react-dom/server';
import {clock} from '@shopify/jest-dom-mocks';

import {Effect} from '../Effect';
import {extract} from '../server';

describe('extract()', () => {
beforeEach(() => {
clock.mock();
jest.useFakeTimers();
});

afterEach(() => {
clock.restore();
jest.useRealTimers();
});

it('calls effects', async () => {
Expand All @@ -25,6 +24,7 @@ describe('extract()', () => {
});

it('waits for effects to resolve', async () => {
jest.useRealTimers();
const {promise, resolve, resolved} = createResolvablePromise();
const spy = jest.fn(() => (resolved() ? promise : undefined));
const extractSpy = jest.fn();
Expand Down Expand Up @@ -147,14 +147,14 @@ describe('extract()', () => {
return resolved()
? undefined
: resolve().then(() => {
clock.tick(resolveDuration);
jest.advanceTimersByTime(resolveDuration);
});
}}
/>,
{
betweenEachPass: spy,
renderFunction: (element: React.ReactElement<any>) => {
clock.tick(renderDuration);
jest.advanceTimersByTime(renderDuration);
return renderToString(element);
},
},
Expand Down Expand Up @@ -203,14 +203,14 @@ describe('extract()', () => {
return resolved()
? undefined
: resolve().then(() => {
clock.tick(resolveDuration);
jest.advanceTimersByTime(resolveDuration);
});
}}
/>,
{
afterEachPass: spy,
renderFunction: (element: React.ReactElement<any>) => {
clock.tick(renderDuration);
jest.advanceTimersByTime(renderDuration);
return renderToString(element);
},
},
Expand Down
10 changes: 0 additions & 10 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3306,11 +3306,6 @@
"@types/koa-compose" "*"
"@types/node" "*"

"@types/lolex@^2.1.3":
version "2.1.3"
resolved "https://registry.yarnpkg.com/@types/lolex/-/lolex-2.1.3.tgz#793557c9b8ad319b4c8e4c6548b90893f4aa5f69"
integrity sha512-nEipOLYyZJ4RKHCg7tlR37ewFy91oggmip2MBzPdVQ8QhTFqjcRhE8R0t4tfpDnSlxGWHoEGJl0UCC4kYhqoiw==

"@types/mdast@^3.0.0":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.3.tgz#2d7d671b1cd1ea3deb306ea75036c2a0407d2deb"
Expand Down Expand Up @@ -10176,11 +10171,6 @@ log-symbols@^2.2.0:
dependencies:
chalk "^2.0.1"

lolex@^2.7.5:
version "2.7.5"
resolved "https://registry.yarnpkg.com/lolex/-/lolex-2.7.5.tgz#113001d56bfc7e02d56e36291cc5c413d1aa0733"
integrity sha512-l9x0+1offnKKIzYVjyXU2SiwhXDLekRzKyhnbyldPHvC7BvLPVpdNUNR2KeMAiCN2D/kLNttZgQD5WjSxuBx3Q==

loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
Expand Down

0 comments on commit db05ac6

Please sign in to comment.