chore(clock): introduce pauseAt (#31255)

This commit is contained in:
Pavel Feldman 2024-06-11 12:51:00 -07:00 committed by GitHub
parent 8fd0a56427
commit 2b257ea963
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 157 additions and 201 deletions

View File

@ -45,43 +45,6 @@ await page.Clock.FastForwardAsync("30:00");
Time may be the number of milliseconds to advance the clock by or a human-readable string. Valid string formats are "08" for eight seconds, "01:00" for one minute and "02:34:10" for two hours, 34 minutes and ten seconds.
## async method: Clock.fastForwardTo
* since: v1.45
Advance the clock by jumping forward in time. Only fires due timers at most once. This is equivalent to user closing the laptop lid for a while and
reopening it at the specified time.
**Usage**
```js
await page.clock.fastForwardTo(new Date('2020-02-02'));
await page.clock.fastForwardTo('2020-02-02');
```
```python async
await page.clock.fast_forward_to(datetime.datetime(2020, 2, 2))
await page.clock.fast_forward_to("2020-02-02")
```
```python sync
page.clock.fast_forward_to(datetime.datetime(2020, 2, 2))
page.clock.fast_forward_to("2020-02-02")
```
```java
page.clock().fastForwardTo(Instant.parse("2020-02-02"));
page.clock().fastForwardTo("2020-02-02");
```
```csharp
await page.Clock.FastForwardToAsync(DateTime.Parse("2020-02-02"));
await page.Clock.FastForwardToAsync("2020-02-02");
```
### param: Clock.fastForwardTo.time
* since: v1.45
- `time` <[int]|[string]|[Date]>
## async method: Clock.install
* since: v1.45
@ -145,10 +108,47 @@ await page.Clock.RunForAsync("30:00");
Time may be the number of milliseconds to advance the clock by or a human-readable string. Valid string formats are "08" for eight seconds, "01:00" for one minute and "02:34:10" for two hours, 34 minutes and ten seconds.
## async method: Clock.pause
## async method: Clock.pauseAt
* since: v1.45
Pause timers. Once this method is called, no timers are fired unless [`method: Clock.runFor`], [`method: Clock.fastForward`], [`method: Clock.fastForwardTo`] or [`method: Clock.resume`] is called.
Advance the clock by jumping forward in time and pause the time. Once this method is called, no timers
are fired unless [`method: Clock.runFor`], [`method: Clock.fastForward`], [`method: Clock.pauseAt`] or [`method: Clock.resume`] is called.
Only fires due timers at most once.
This is equivalent to user closing the laptop lid for a while and reopening it at the specified time and
pausing.
**Usage**
```js
await page.clock.pauseAt(new Date('2020-02-02'));
await page.clock.pauseAt('2020-02-02');
```
```python async
await page.clock.pause_at(datetime.datetime(2020, 2, 2))
await page.clock.pause_at("2020-02-02")
```
```python sync
page.clock.pause_at(datetime.datetime(2020, 2, 2))
page.clock.pause_at("2020-02-02")
```
```java
page.clock().pauseAt(Instant.parse("2020-02-02"));
page.clock().pauseAt("2020-02-02");
```
```csharp
await page.Clock.PauseAtAsync(DateTime.Parse("2020-02-02"));
await page.Clock.PauseAtAsync("2020-02-02");
```
### param: Clock.pauseAt.time
* since: v1.45
- `time` <[int]|[string]|[Date]>
## async method: Clock.resume
* since: v1.45
@ -202,7 +202,7 @@ Time to be set.
## async method: Clock.setSystemTime
* since: v1.45
Sets current system time but does not trigger any timers, unlike [`method: Clock.fastForwardTo`].
Sets current system time but does not trigger any timers.
**Usage**

View File

@ -67,10 +67,9 @@ In this case, you can install the clock and fast forward to the time of interest
await page.clock.install({ time: new Date('2024-02-02T08:00:00') });
await page.goto('http://localhost:3333');
// Take control over time flow.
await page.clock.pause();
// Pretend that the user closed the laptop lid and opened it again at 10am.
await page.clock.fastForwardTo(new Date('2024-02-02T10:00:00'));
// Pretend that the user closed the laptop lid and opened it again at 10am,
// Pause the time once reached that point.
await page.clock.pauseAt(new Date('2024-02-02T10:00:00'));
// Assert the page state.
await expect(page.getByTestId('current-time')).toHaveText('2/2/2024, 10:00:00 AM');
@ -86,10 +85,9 @@ await expect(page.getByTestId('current-time')).toHaveText('2/2/2024, 10:30:00 AM
await page.clock.install(time=datetime.datetime(2024, 2, 2, 8, 0, 0))
await page.goto("http://localhost:3333")
# Take control over time flow.
await page.clock.pause()
# Pretend that the user closed the laptop lid and opened it again at 10am.
await page.clock.fast_forward_to(datetime.datetime(2024, 2, 2, 10, 0, 0))
# Pause the time once reached that point.
await page.clock.pause_at(datetime.datetime(2024, 2, 2, 10, 0, 0))
# Assert the page state.
await expect(page.get_by_test_id("current-time")).to_have_text("2/2/2024, 10:00:00 AM")
@ -105,10 +103,9 @@ await expect(page.get_by_test_id("current-time")).to_have_text("2/2/2024, 10:30:
page.clock.install(time=datetime.datetime(2024, 2, 2, 8, 0, 0))
page.goto("http://localhost:3333")
# Take control over time flow.
page.clock.pause()
# Pretend that the user closed the laptop lid and opened it again at 10am.
page.clock.fast_forward_to(datetime.datetime(2024, 2, 2, 10, 0, 0))
# Pause the time once reached that point.
page.clock.pause_at(datetime.datetime(2024, 2, 2, 10, 0, 0))
# Assert the page state.
expect(page.get_by_test_id("current-time")).to_have_text("2/2/2024, 10:00:00 AM")
@ -125,10 +122,9 @@ page.clock().install(new Clock.InstallOptions().setTime(Instant.parse("2024-02-0
page.navigate("http://localhost:3333");
Locator locator = page.getByTestId("current-time");
// Take control over time flow.
page.clock().pause();
// Pretend that the user closed the laptop lid and opened it again at 10am.
page.clock().fastForwardTo(Instant.parse("2024-02-02T10:00:00"));
// Pause the time once reached that point.
page.clock().pauseAt(Instant.parse("2024-02-02T10:00:00"));
// Assert the page state.
assertThat(locator).hasText("2/2/2024, 10:00:00 AM");
@ -147,10 +143,9 @@ await Page.Clock.InstallAsync(new
});
await Page.GotoAsync("http://localhost:3333");
// Take control over time flow.
await Page.Clock.PauseAsync();
// Pretend that the user closed the laptop lid and opened it again at 10am.
await Page.Clock.FastForwardToAsync(new DateTime(2024, 2, 2, 10, 0, 0));
// Pause the time once reached that point.
await Page.Clock.PauseAtAsync(new DateTime(2024, 2, 2, 10, 0, 0));
// Assert the page state.
await Expect(Page.GetByTestId("current-time")).ToHaveText("2/2/2024, 10:00:00 AM");
@ -272,8 +267,7 @@ await page.goto('http://localhost:3333');
// Pause the time flow, stop the timers, you now have manual control
// over the page time.
await page.clock.pause();
await page.clock.fastForwardTo(new Date('2024-02-02T10:00:00'));
await page.clock.pauseAt(new Date('2024-02-02T10:00:00'));
await expect(page.getByTestId('current-time')).toHaveText('2/2/2024, 10:00:00 AM');
// Tick through time manually, firing all timers in the process.
@ -292,8 +286,7 @@ locator = page.get_by_test_id("current-time")
# Pause the time flow, stop the timers, you now have manual control
# over the page time.
await page.clock.pause()
await page.clock.fast_forward_to(datetime.datetime(2024, 2, 2, 10, 0, 0))
await page.clock.pause_at(datetime.datetime(2024, 2, 2, 10, 0, 0))
await expect(locator).to_have_text("2/2/2024, 10:00:00 AM")
# Tick through time manually, firing all timers in the process.
@ -312,8 +305,7 @@ locator = page.get_by_test_id("current-time")
# Pause the time flow, stop the timers, you now have manual control
# over the page time.
page.clock.pause()
page.clock.fast_forward_to(datetime.datetime(2024, 2, 2, 10, 0, 0))
page.clock.pause_at(datetime.datetime(2024, 2, 2, 10, 0, 0))
expect(locator).to_have_text("2/2/2024, 10:00:00 AM")
# Tick through time manually, firing all timers in the process.
@ -331,8 +323,7 @@ Locator locator = page.getByTestId("current-time");
// Pause the time flow, stop the timers, you now have manual control
// over the page time.
page.clock().pause();
page.clock().fastForwardTo(Instant.parse("2024-02-02T10:00:00"));
page.clock().pauseAt(Instant.parse("2024-02-02T10:00:00"));
assertThat(locator).hasText("2/2/2024, 10:00:00 AM");
// Tick through time manually, firing all timers in the process.
@ -352,8 +343,7 @@ var locator = page.GetByTestId("current-time");
// Pause the time flow, stop the timers, you now have manual control
// over the page time.
await Page.Clock.PauseAsync();
await Page.Clock.FastForwardToAsync(new DateTime(2024, 2, 2, 10, 0, 0));
await Page.Clock.PauseAtAsync(new DateTime(2024, 2, 2, 10, 0, 0));
await Expect(locator).ToHaveTextAsync("2/2/2024, 10:00:00 AM");
// Tick through time manually, firing all timers in the process.

View File

@ -88,7 +88,7 @@ export class Browser extends ChannelOwner<channels.BrowserChannel> implements ap
if (!forReuse && !!process.env.PW_FREEZE_TIME) {
await this._wrapApiCall(async () => {
await context.clock.install({ time: 0 });
await context.clock.pause();
await context.clock.pauseAt(1000);
}, true);
}
return context;

View File

@ -32,12 +32,8 @@ export class Clock implements api.Clock {
await this._browserContext._channel.clockFastForward(parseTicks(ticks));
}
async fastForwardTo(time: number | string | Date) {
await this._browserContext._channel.clockFastForwardTo(parseTime(time));
}
async pause() {
await this._browserContext._channel.clockPause({});
async pauseAt(time: number | string | Date) {
await this._browserContext._channel.clockPauseAt(parseTime(time));
}
async resume() {

View File

@ -968,18 +968,16 @@ scheme.BrowserContextClockFastForwardParams = tObject({
ticksString: tOptional(tString),
});
scheme.BrowserContextClockFastForwardResult = tOptional(tObject({}));
scheme.BrowserContextClockFastForwardToParams = tObject({
timeNumber: tOptional(tNumber),
timeString: tOptional(tString),
});
scheme.BrowserContextClockFastForwardToResult = tOptional(tObject({}));
scheme.BrowserContextClockInstallParams = tObject({
timeNumber: tOptional(tNumber),
timeString: tOptional(tString),
});
scheme.BrowserContextClockInstallResult = tOptional(tObject({}));
scheme.BrowserContextClockPauseParams = tOptional(tObject({}));
scheme.BrowserContextClockPauseResult = tOptional(tObject({}));
scheme.BrowserContextClockPauseAtParams = tObject({
timeNumber: tOptional(tNumber),
timeString: tOptional(tString),
});
scheme.BrowserContextClockPauseAtResult = tOptional(tObject({}));
scheme.BrowserContextClockResumeParams = tOptional(tObject({}));
scheme.BrowserContextClockResumeResult = tOptional(tObject({}));
scheme.BrowserContextClockRunForParams = tObject({

View File

@ -33,13 +33,6 @@ export class Clock {
await this._evaluateInFrames(`globalThis.__pwClock.controller.fastForward(${ticksMillis})`);
}
async fastForwardTo(ticks: number | string) {
await this._installIfNeeded();
const timeMillis = parseTime(ticks);
await this._browserContext.addInitScript(`globalThis.__pwClock.controller.log('fastForwardTo', ${Date.now()}, ${timeMillis})`);
await this._evaluateInFrames(`globalThis.__pwClock.controller.fastForwardTo(${timeMillis})`);
}
async install(time: number | string | undefined) {
await this._installIfNeeded();
const timeMillis = time !== undefined ? parseTime(time) : Date.now();
@ -47,10 +40,11 @@ export class Clock {
await this._evaluateInFrames(`globalThis.__pwClock.controller.install(${timeMillis})`);
}
async pause() {
async pauseAt(ticks: number | string) {
await this._installIfNeeded();
await this._browserContext.addInitScript(`globalThis.__pwClock.controller.log('pause', ${Date.now()})`);
await this._evaluateInFrames(`globalThis.__pwClock.controller.pause()`);
const timeMillis = parseTime(ticks);
await this._browserContext.addInitScript(`globalThis.__pwClock.controller.log('pauseAt', ${Date.now()}, ${timeMillis})`);
await this._evaluateInFrames(`globalThis.__pwClock.controller.pauseAt(${timeMillis})`);
}
async resume() {

View File

@ -316,16 +316,12 @@ export class BrowserContextDispatcher extends Dispatcher<BrowserContext, channel
await this._context.clock.fastForward(params.ticksString ?? params.ticksNumber ?? 0);
}
async clockFastForwardTo(params: channels.BrowserContextClockFastForwardToParams, metadata?: CallMetadata | undefined): Promise<channels.BrowserContextClockFastForwardToResult> {
await this._context.clock.fastForwardTo(params.timeString ?? params.timeNumber ?? 0);
}
async clockInstall(params: channels.BrowserContextClockInstallParams, metadata?: CallMetadata | undefined): Promise<channels.BrowserContextClockInstallResult> {
await this._context.clock.install(params.timeString ?? params.timeNumber ?? undefined);
}
async clockPause(params: channels.BrowserContextClockPauseParams, metadata?: CallMetadata | undefined): Promise<channels.BrowserContextClockPauseResult> {
await this._context.clock.pause();
async clockPauseAt(params: channels.BrowserContextClockPauseAtParams, metadata?: CallMetadata | undefined): Promise<channels.BrowserContextClockPauseAtResult> {
await this._context.clock.pauseAt(params.timeString ?? params.timeNumber ?? 0);
}
async clockResume(params: channels.BrowserContextClockResumeParams, metadata?: CallMetadata | undefined): Promise<channels.BrowserContextClockResumeResult> {

View File

@ -69,7 +69,7 @@ type Time = {
origin: number;
};
type LogEntryType = 'fastForward' | 'fastForwardTo' | 'install' | 'pause' | 'resume' | 'runFor' | 'setFixedTime' | 'setSystemTime';
type LogEntryType = 'fastForward' |'install' | 'pauseAt' | 'resume' | 'runFor' | 'setFixedTime' | 'setSystemTime';
export class ClockController {
readonly _now: Time;
@ -163,9 +163,10 @@ export class ClockController {
throw firstException;
}
pause() {
async pauseAt(time: number) {
this._replayLogOnce();
this._innerPause();
await this._innerFastForwardTo(time);
}
private _innerPause() {
@ -218,18 +219,18 @@ export class ClockController {
async fastForward(ticks: number) {
this._replayLogOnce();
const ms = ticks | 0;
for (const timer of this._timers.values()) {
if (this._now.ticks + ms > timer.callAt)
timer.callAt = this._now.ticks + ms;
}
await this.runFor(ms);
await this._innerFastForwardTo(this._now.ticks + ticks | 0);
}
async fastForwardTo(time: number) {
this._replayLogOnce();
const ticks = time - this._now.time;
await this.fastForward(ticks);
private async _innerFastForwardTo(toTicks: number) {
if (toTicks < this._now.ticks)
throw new Error('Cannot fast-forward to the past');
for (const timer of this._timers.values()) {
if (toTicks > timer.callAt)
timer.callAt = toTicks;
}
await this._runTo(toTicks);
}
addTimer(options: { func: TimerHandler, type: TimerType, delay?: number | string, args?: any[] }): number {
@ -381,11 +382,10 @@ export class ClockController {
this._innerSetTime(param!);
} else if (type === 'fastForward' || type === 'runFor') {
this._advanceNow(this._now.ticks + param!);
} else if (type === 'fastForwardTo') {
this._innerSetTime(param!);
} else if (type === 'pause') {
this._innerPause();
} else if (type === 'pauseAt') {
isPaused = true;
this._innerPause();
this._innerSetTime(param!);
} else if (type === 'resume') {
this._innerResume();
isPaused = false;

View File

@ -17263,21 +17263,6 @@ export interface Clock {
*/
fastForward(ticks: number|string): Promise<void>;
/**
* Advance the clock by jumping forward in time. Only fires due timers at most once. This is equivalent to user
* closing the laptop lid for a while and reopening it at the specified time.
*
* **Usage**
*
* ```js
* await page.clock.fastForwardTo(new Date('2020-02-02'));
* await page.clock.fastForwardTo('2020-02-02');
* ```
*
* @param time
*/
fastForwardTo(time: number|string|Date): Promise<void>;
/**
* Install fake implementations for the following time-related functions:
* - `Date`
@ -17305,13 +17290,25 @@ export interface Clock {
}): Promise<void>;
/**
* Pause timers. Once this method is called, no timers are fired unless
* [clock.runFor(ticks)](https://playwright.dev/docs/api/class-clock#clock-run-for),
* Advance the clock by jumping forward in time and pause the time. Once this method is called, no timers are fired
* unless [clock.runFor(ticks)](https://playwright.dev/docs/api/class-clock#clock-run-for),
* [clock.fastForward(ticks)](https://playwright.dev/docs/api/class-clock#clock-fast-forward),
* [clock.fastForwardTo(time)](https://playwright.dev/docs/api/class-clock#clock-fast-forward-to) or
* [clock.pauseAt(time)](https://playwright.dev/docs/api/class-clock#clock-pause-at) or
* [clock.resume()](https://playwright.dev/docs/api/class-clock#clock-resume) is called.
*
* Only fires due timers at most once. This is equivalent to user closing the laptop lid for a while and reopening it
* at the specified time and pausing.
*
* **Usage**
*
* ```js
* await page.clock.pauseAt(new Date('2020-02-02'));
* await page.clock.pauseAt('2020-02-02');
* ```
*
* @param time
*/
pause(): Promise<void>;
pauseAt(time: number|string|Date): Promise<void>;
/**
* Resumes timers. Once this method is called, time resumes flowing, timers are fired as usual.
@ -17349,8 +17346,7 @@ export interface Clock {
setFixedTime(time: number|string|Date): Promise<void>;
/**
* Sets current system time but does not trigger any timers, unlike
* [clock.fastForwardTo(time)](https://playwright.dev/docs/api/class-clock#clock-fast-forward-to).
* Sets current system time but does not trigger any timers.
*
* **Usage**
*

View File

@ -1461,9 +1461,8 @@ export interface BrowserContextChannel extends BrowserContextEventTarget, EventT
createTempFile(params: BrowserContextCreateTempFileParams, metadata?: CallMetadata): Promise<BrowserContextCreateTempFileResult>;
updateSubscription(params: BrowserContextUpdateSubscriptionParams, metadata?: CallMetadata): Promise<BrowserContextUpdateSubscriptionResult>;
clockFastForward(params: BrowserContextClockFastForwardParams, metadata?: CallMetadata): Promise<BrowserContextClockFastForwardResult>;
clockFastForwardTo(params: BrowserContextClockFastForwardToParams, metadata?: CallMetadata): Promise<BrowserContextClockFastForwardToResult>;
clockInstall(params: BrowserContextClockInstallParams, metadata?: CallMetadata): Promise<BrowserContextClockInstallResult>;
clockPause(params?: BrowserContextClockPauseParams, metadata?: CallMetadata): Promise<BrowserContextClockPauseResult>;
clockPauseAt(params: BrowserContextClockPauseAtParams, metadata?: CallMetadata): Promise<BrowserContextClockPauseAtResult>;
clockResume(params?: BrowserContextClockResumeParams, metadata?: CallMetadata): Promise<BrowserContextClockResumeResult>;
clockRunFor(params: BrowserContextClockRunForParams, metadata?: CallMetadata): Promise<BrowserContextClockRunForResult>;
clockSetFixedTime(params: BrowserContextClockSetFixedTimeParams, metadata?: CallMetadata): Promise<BrowserContextClockSetFixedTimeResult>;
@ -1765,15 +1764,6 @@ export type BrowserContextClockFastForwardOptions = {
ticksString?: string,
};
export type BrowserContextClockFastForwardResult = void;
export type BrowserContextClockFastForwardToParams = {
timeNumber?: number,
timeString?: string,
};
export type BrowserContextClockFastForwardToOptions = {
timeNumber?: number,
timeString?: string,
};
export type BrowserContextClockFastForwardToResult = void;
export type BrowserContextClockInstallParams = {
timeNumber?: number,
timeString?: string,
@ -1783,9 +1773,15 @@ export type BrowserContextClockInstallOptions = {
timeString?: string,
};
export type BrowserContextClockInstallResult = void;
export type BrowserContextClockPauseParams = {};
export type BrowserContextClockPauseOptions = {};
export type BrowserContextClockPauseResult = void;
export type BrowserContextClockPauseAtParams = {
timeNumber?: number,
timeString?: string,
};
export type BrowserContextClockPauseAtOptions = {
timeNumber?: number,
timeString?: string,
};
export type BrowserContextClockPauseAtResult = void;
export type BrowserContextClockResumeParams = {};
export type BrowserContextClockResumeOptions = {};
export type BrowserContextClockResumeResult = void;

View File

@ -1209,17 +1209,15 @@ BrowserContext:
ticksNumber: number?
ticksString: string?
clockFastForwardTo:
parameters:
timeNumber: number?
timeString: string?
clockInstall:
parameters:
timeNumber: number?
timeString: string?
clockPause:
clockPauseAt:
parameters:
timeNumber: number?
timeString: string?
clockResume:

View File

@ -1342,10 +1342,11 @@ it.describe('fastForward', () => {
clock.setInterval(shortTimers[1], 100);
clock.requestAnimationFrame(shortTimers[2]);
await clock.fastForward(1500);
for (const stub of longTimers)
expect(stub.called).toBeFalsy();
for (const stub of shortTimers)
expect(stub.callCount).toBe(1);
expect(longTimers[0].called).toBeFalsy();
expect(longTimers[1].called).toBeFalsy();
expect(shortTimers[0].callCount).toBe(1);
expect(shortTimers[1].callCount).toBe(1);
expect(shortTimers[2].callCount).toBe(1);
});
});

View File

@ -36,8 +36,8 @@ const it = test.extend<{ calls: { params: any[] }[] }>({
it.describe('runFor', () => {
it.beforeEach(async ({ page }) => {
await page.clock.install();
await page.clock.pause();
await page.clock.install({ time: 0 });
await page.clock.pauseAt(1000);
});
it('triggers immediately without specified delay', async ({ page, calls }) => {
@ -171,9 +171,8 @@ it.describe('runFor', () => {
it.describe('fastForward', () => {
it.beforeEach(async ({ page }) => {
await page.clock.install();
await page.clock.pause();
await page.clock.setSystemTime(0);
await page.clock.install({ time: 0 });
await page.clock.pauseAt(1000);
});
it(`ignores timers which wouldn't be run`, async ({ page, calls }) => {
@ -194,7 +193,7 @@ it.describe('fastForward', () => {
});
await page.clock.fastForward(2000);
expect(calls).toEqual([{ params: [2000] }]);
expect(calls).toEqual([{ params: [1000 + 2000] }]);
});
it('supports string time arguments', async ({ page, calls }) => {
@ -204,15 +203,14 @@ it.describe('fastForward', () => {
}, 100000); // 100000 = 1:40
});
await page.clock.fastForward('01:50');
expect(calls).toEqual([{ params: [110000] }]);
expect(calls).toEqual([{ params: [1000 + 110000] }]);
});
});
it.describe('fastForwardTo', () => {
it.beforeEach(async ({ page }) => {
await page.clock.install();
await page.clock.pause();
await page.clock.setSystemTime(0);
await page.clock.install({ time: 0 });
await page.clock.pauseAt(1000);
});
it(`ignores timers which wouldn't be run`, async ({ page, calls }) => {
@ -221,7 +219,7 @@ it.describe('fastForwardTo', () => {
window.stub('should not be logged');
}, 1000);
});
await page.clock.fastForwardTo(500);
await page.clock.fastForward(500);
expect(calls).toEqual([]);
});
@ -232,16 +230,15 @@ it.describe('fastForwardTo', () => {
}, 1000);
});
await page.clock.fastForwardTo(2000);
expect(calls).toEqual([{ params: [2000] }]);
await page.clock.fastForward(2000);
expect(calls).toEqual([{ params: [1000 + 2000] }]);
});
});
it.describe('stubTimers', () => {
it.beforeEach(async ({ page }) => {
await page.clock.install();
await page.clock.pause();
await page.clock.setSystemTime(0);
await page.clock.install({ time: 0 });
await page.clock.pauseAt(1000);
});
it('sets initial timestamp', async ({ page, calls }) => {
await page.clock.setSystemTime(1400);
@ -295,20 +292,19 @@ it.describe('stubTimers', () => {
return { prev, next };
});
await page.clock.runFor(1000);
expect(await promise).toEqual({ prev: 0, next: 1000 });
expect(await promise).toEqual({ prev: 1000, next: 2000 });
});
it('fakes Date constructor', async ({ page }) => {
const now = await page.evaluate(() => new Date().getTime());
expect(now).toBe(0);
expect(now).toBe(1000);
});
});
it.describe('stubTimers', () => {
it('replaces global performance.timeOrigin', async ({ page }) => {
await page.clock.install({ time: 1000 });
await page.clock.pause();
await page.clock.setSystemTime(1000);
await page.clock.pauseAt(2000);
const promise = page.evaluate(async () => {
const prev = performance.now();
await new Promise(f => setTimeout(f, 1000));
@ -317,16 +313,15 @@ it.describe('stubTimers', () => {
});
await page.clock.runFor(1000);
expect(await page.evaluate(() => performance.timeOrigin)).toBe(1000);
expect(await promise).toEqual({ prev: 0, next: 1000 });
expect(await promise).toEqual({ prev: 2000, next: 3000 });
});
});
it.describe('popup', () => {
it('should tick after popup', async ({ page }) => {
await page.clock.install();
await page.clock.pause();
const now = new Date('2015-09-25');
await page.clock.setSystemTime(now);
await page.clock.pauseAt(now);
const [popup] = await Promise.all([
page.waitForEvent('popup'),
page.evaluate(() => window.open('about:blank')),
@ -340,9 +335,8 @@ it.describe('popup', () => {
it('should tick before popup', async ({ page }) => {
await page.clock.install();
await page.clock.pause();
const now = new Date('2015-09-25');
await page.clock.setSystemTime(now);
await page.clock.pauseAt(now);
await page.clock.runFor(1000);
const [popup] = await Promise.all([
@ -358,7 +352,6 @@ it.describe('popup', () => {
res.setHeader('Content-Type', 'text/html');
res.end(`<script>window.time = Date.now()</script>`);
});
await page.clock.setSystemTime(0);
await page.goto(server.EMPTY_PAGE);
// Wait for 2 second in real life to check that it is past in popup.
await page.waitForTimeout(2000);
@ -376,8 +369,7 @@ it.describe('popup', () => {
res.end(`<script>window.time = Date.now()</script>`);
});
await page.clock.install();
await page.clock.pause();
await page.clock.setSystemTime(0);
await page.clock.pauseAt(1000);
await page.goto(server.EMPTY_PAGE);
// Wait for 2 second in real life to check that it is past in popup.
await page.waitForTimeout(2000);
@ -386,7 +378,7 @@ it.describe('popup', () => {
page.evaluate(url => window.open(url), server.PREFIX + '/popup.html'),
]);
const popupTime = await popup.evaluate('time');
expect(popupTime).toBe(0);
expect(popupTime).toBe(1000);
});
});
@ -457,7 +449,7 @@ it.describe('while running', () => {
it('should fastForwardTo', async ({ page }) => {
await page.clock.install({ time: 0 });
await page.goto('data:text/html,');
await page.clock.fastForwardTo(10000);
await page.clock.fastForward(10000);
const now = await page.evaluate(() => Date.now());
expect(now).toBeGreaterThanOrEqual(10000);
expect(now).toBeLessThanOrEqual(11000);
@ -466,7 +458,7 @@ it.describe('while running', () => {
it('should pause', async ({ page }) => {
await page.clock.install({ time: 0 });
await page.goto('data:text/html,');
await page.clock.pause();
await page.clock.pauseAt(1000);
await page.waitForTimeout(1000);
await page.clock.resume();
const now = await page.evaluate(() => Date.now());
@ -474,20 +466,19 @@ it.describe('while running', () => {
expect(now).toBeLessThanOrEqual(1000);
});
it('should pause and fastForwardTo', async ({ page }) => {
it('should pause and fastForward', async ({ page }) => {
await page.clock.install({ time: 0 });
await page.goto('data:text/html,');
await page.clock.pause();
await page.clock.fastForwardTo(1000);
await page.clock.pauseAt(1000);
await page.clock.fastForward(1000);
const now = await page.evaluate(() => Date.now());
expect(now).toBe(1000);
expect(now).toBe(2000);
});
it('should set system time on pause', async ({ page }) => {
await page.clock.install();
await page.clock.install({ time: 0 });
await page.goto('data:text/html,');
await page.clock.pause();
await page.clock.setSystemTime(1000);
await page.clock.pauseAt(1000);
const now = await page.evaluate(() => Date.now());
expect(now).toBe(1000);
});
@ -495,9 +486,9 @@ it.describe('while running', () => {
it.describe('while on pause', () => {
it('fastForward should not run nested immediate', async ({ page, calls }) => {
await page.clock.install();
await page.clock.install({ time: 0 });
await page.goto('data:text/html,');
await page.clock.pause();
await page.clock.pauseAt(1000);
await page.evaluate(() => {
setTimeout(() => {
window.stub('outer');
@ -511,9 +502,9 @@ it.describe('while on pause', () => {
});
it('runFor should not run nested immediate', async ({ page, calls }) => {
await page.clock.install();
await page.clock.install({ time: 0 });
await page.goto('data:text/html,');
await page.clock.pause();
await page.clock.pauseAt(1000);
await page.evaluate(() => {
setTimeout(() => {
window.stub('outer');
@ -527,9 +518,9 @@ it.describe('while on pause', () => {
});
it('runFor should not run nested immediate from microtask', async ({ page, calls }) => {
await page.clock.install();
await page.clock.install({ time: 0 });
await page.goto('data:text/html,');
await page.clock.pause();
await page.clock.pauseAt(1000);
await page.evaluate(() => {
setTimeout(() => {
window.stub('outer');