| 
									
										
										
										
											2024-05-30 09:38:27 -07:00
										 |  |  | /** | 
					
						
							|  |  |  |  * Copyright (c) Microsoft Corporation. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
					
						
							|  |  |  |  * you may not use this file except in compliance with the License. | 
					
						
							|  |  |  |  * You may obtain a copy of the License at | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *     http://www.apache.org/licenses/LICENSE-2.0
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Unless required by applicable law or agreed to in writing, software | 
					
						
							|  |  |  |  * distributed under the License is distributed on an "AS IS" BASIS, | 
					
						
							|  |  |  |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
					
						
							|  |  |  |  * See the License for the specific language governing permissions and | 
					
						
							|  |  |  |  * limitations under the License. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-18 14:45:45 +02:00
										 |  |  | import { browserTest as test, expect } from '../config/browserTest'; | 
					
						
							| 
									
										
										
										
											2024-05-30 09:38:27 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-17 09:17:38 -07:00
										 |  |  | test.skip(!!process.env.PW_CLOCK); | 
					
						
							| 
									
										
										
										
											2024-05-31 14:44:26 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-30 09:38:27 -07:00
										 |  |  | declare global { | 
					
						
							|  |  |  |   interface Window { | 
					
						
							|  |  |  |     stub: (param?: any) => void | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const it = test.extend<{ calls: { params: any[] }[] }>({ | 
					
						
							|  |  |  |   calls: async ({ page }, use) => { | 
					
						
							|  |  |  |     const calls = []; | 
					
						
							|  |  |  |     await page.exposeFunction('stub', async (...params: any[]) => { | 
					
						
							|  |  |  |       calls.push({ params }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     await use(calls); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-04 06:51:35 -07:00
										 |  |  | it.describe('runFor', () => { | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  |   it.beforeEach(async ({ page }) => { | 
					
						
							| 
									
										
										
										
											2024-06-11 12:51:00 -07:00
										 |  |  |     await page.clock.install({ time: 0 }); | 
					
						
							|  |  |  |     await page.clock.pauseAt(1000); | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-30 09:38:27 -07:00
										 |  |  |   it('triggers immediately without specified delay', async ({ page, calls }) => { | 
					
						
							|  |  |  |     await page.evaluate(async () => { | 
					
						
							|  |  |  |       setTimeout(window.stub); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-04 06:51:35 -07:00
										 |  |  |     await page.clock.runFor(0); | 
					
						
							| 
									
										
										
										
											2024-05-31 08:09:24 -07:00
										 |  |  |     expect(calls).toHaveLength(1); | 
					
						
							| 
									
										
										
										
											2024-05-30 09:38:27 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('does not trigger without sufficient delay', async ({ page, calls }) => { | 
					
						
							|  |  |  |     await page.evaluate(async () => { | 
					
						
							|  |  |  |       setTimeout(window.stub, 100); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2024-06-04 06:51:35 -07:00
										 |  |  |     await page.clock.runFor(10); | 
					
						
							| 
									
										
										
										
											2024-05-30 09:38:27 -07:00
										 |  |  |     expect(calls).toEqual([]); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('triggers after sufficient delay', async ({ page, calls }) => { | 
					
						
							|  |  |  |     await page.evaluate(async () => { | 
					
						
							|  |  |  |       setTimeout(window.stub, 100); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2024-06-04 06:51:35 -07:00
										 |  |  |     await page.clock.runFor(100); | 
					
						
							| 
									
										
										
										
											2024-05-31 08:09:24 -07:00
										 |  |  |     expect(calls).toHaveLength(1); | 
					
						
							| 
									
										
										
										
											2024-05-30 09:38:27 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('triggers simultaneous timers', async ({ page, calls }) => { | 
					
						
							|  |  |  |     await page.evaluate(async () => { | 
					
						
							|  |  |  |       setTimeout(window.stub, 100); | 
					
						
							|  |  |  |       setTimeout(window.stub, 100); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2024-06-04 06:51:35 -07:00
										 |  |  |     await page.clock.runFor(100); | 
					
						
							| 
									
										
										
										
											2024-05-31 08:09:24 -07:00
										 |  |  |     expect(calls).toHaveLength(2); | 
					
						
							| 
									
										
										
										
											2024-05-30 09:38:27 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('triggers multiple simultaneous timers', async ({ page, calls }) => { | 
					
						
							|  |  |  |     await page.evaluate(async () => { | 
					
						
							|  |  |  |       setTimeout(window.stub, 100); | 
					
						
							|  |  |  |       setTimeout(window.stub, 100); | 
					
						
							|  |  |  |       setTimeout(window.stub, 99); | 
					
						
							|  |  |  |       setTimeout(window.stub, 100); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2024-06-04 06:51:35 -07:00
										 |  |  |     await page.clock.runFor(100); | 
					
						
							| 
									
										
										
										
											2024-05-30 09:38:27 -07:00
										 |  |  |     expect(calls.length).toBe(4); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('waits after setTimeout was called', async ({ page, calls }) => { | 
					
						
							|  |  |  |     await page.evaluate(async () => { | 
					
						
							|  |  |  |       setTimeout(window.stub, 150); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2024-06-04 06:51:35 -07:00
										 |  |  |     await page.clock.runFor(50); | 
					
						
							| 
									
										
										
										
											2024-05-30 09:38:27 -07:00
										 |  |  |     expect(calls).toEqual([]); | 
					
						
							| 
									
										
										
										
											2024-06-04 06:51:35 -07:00
										 |  |  |     await page.clock.runFor(100); | 
					
						
							| 
									
										
										
										
											2024-05-31 08:09:24 -07:00
										 |  |  |     expect(calls).toHaveLength(1); | 
					
						
							| 
									
										
										
										
											2024-05-30 09:38:27 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('triggers event when some throw', async ({ page, calls }) => { | 
					
						
							|  |  |  |     await page.evaluate(async () => { | 
					
						
							|  |  |  |       setTimeout(() => { throw new Error(); }, 100); | 
					
						
							|  |  |  |       setTimeout(window.stub, 120); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2024-06-04 06:51:35 -07:00
										 |  |  |     await expect(page.clock.runFor(120)).rejects.toThrow(); | 
					
						
							| 
									
										
										
										
											2024-05-31 08:09:24 -07:00
										 |  |  |     expect(calls).toHaveLength(1); | 
					
						
							| 
									
										
										
										
											2024-05-30 09:38:27 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('creates updated Date while ticking', async ({ page, calls }) => { | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  |     await page.clock.setSystemTime(0); | 
					
						
							| 
									
										
										
										
											2024-05-30 09:38:27 -07:00
										 |  |  |     await page.evaluate(async () => { | 
					
						
							|  |  |  |       setInterval(() => { | 
					
						
							|  |  |  |         window.stub(new Date().getTime()); | 
					
						
							|  |  |  |       }, 10); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2024-06-04 06:51:35 -07:00
										 |  |  |     await page.clock.runFor(100); | 
					
						
							| 
									
										
										
										
											2024-05-30 09:38:27 -07:00
										 |  |  |     expect(calls).toEqual([ | 
					
						
							|  |  |  |       { params: [10] }, | 
					
						
							|  |  |  |       { params: [20] }, | 
					
						
							|  |  |  |       { params: [30] }, | 
					
						
							|  |  |  |       { params: [40] }, | 
					
						
							|  |  |  |       { params: [50] }, | 
					
						
							|  |  |  |       { params: [60] }, | 
					
						
							|  |  |  |       { params: [70] }, | 
					
						
							|  |  |  |       { params: [80] }, | 
					
						
							|  |  |  |       { params: [90] }, | 
					
						
							|  |  |  |       { params: [100] }, | 
					
						
							|  |  |  |     ]); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('passes 8 seconds', async ({ page, calls }) => { | 
					
						
							|  |  |  |     await page.evaluate(async () => { | 
					
						
							|  |  |  |       setInterval(window.stub, 4000); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-04 06:51:35 -07:00
										 |  |  |     await page.clock.runFor('08'); | 
					
						
							| 
									
										
										
										
											2024-05-30 09:38:27 -07:00
										 |  |  |     expect(calls.length).toBe(2); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('passes 1 minute', async ({ page, calls }) => { | 
					
						
							|  |  |  |     await page.evaluate(async () => { | 
					
						
							|  |  |  |       setInterval(window.stub, 6000); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-04 06:51:35 -07:00
										 |  |  |     await page.clock.runFor('01:00'); | 
					
						
							| 
									
										
										
										
											2024-05-30 09:38:27 -07:00
										 |  |  |     expect(calls.length).toBe(10); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('passes 2 hours, 34 minutes and 10 seconds', async ({ page, calls }) => { | 
					
						
							|  |  |  |     await page.evaluate(async () => { | 
					
						
							|  |  |  |       setInterval(window.stub, 10000); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-04 06:51:35 -07:00
										 |  |  |     await page.clock.runFor('02:34:10'); | 
					
						
							| 
									
										
										
										
											2024-05-30 09:38:27 -07:00
										 |  |  |     expect(calls.length).toBe(925); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('throws for invalid format', async ({ page, calls }) => { | 
					
						
							|  |  |  |     await page.evaluate(async () => { | 
					
						
							|  |  |  |       setInterval(window.stub, 10000); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2024-06-04 06:51:35 -07:00
										 |  |  |     await expect(page.clock.runFor('12:02:34:10')).rejects.toThrow(); | 
					
						
							| 
									
										
										
										
											2024-05-30 09:38:27 -07:00
										 |  |  |     expect(calls).toEqual([]); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('returns the current now value', async ({ page }) => { | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  |     await page.clock.setSystemTime(0); | 
					
						
							| 
									
										
										
										
											2024-05-30 09:38:27 -07:00
										 |  |  |     const value = 200; | 
					
						
							| 
									
										
										
										
											2024-06-04 06:51:35 -07:00
										 |  |  |     await page.clock.runFor(value); | 
					
						
							| 
									
										
										
										
											2024-05-30 09:38:27 -07:00
										 |  |  |     expect(await page.evaluate(() => Date.now())).toBe(value); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  | it.describe('fastForward', () => { | 
					
						
							|  |  |  |   it.beforeEach(async ({ page }) => { | 
					
						
							| 
									
										
										
										
											2024-06-11 12:51:00 -07:00
										 |  |  |     await page.clock.install({ time: 0 }); | 
					
						
							|  |  |  |     await page.clock.pauseAt(1000); | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-30 09:38:27 -07:00
										 |  |  |   it(`ignores timers which wouldn't be run`, async ({ page, calls }) => { | 
					
						
							|  |  |  |     await page.evaluate(async () => { | 
					
						
							|  |  |  |       setTimeout(() => { | 
					
						
							|  |  |  |         window.stub('should not be logged'); | 
					
						
							|  |  |  |       }, 1000); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  |     await page.clock.fastForward(500); | 
					
						
							| 
									
										
										
										
											2024-05-30 09:38:27 -07:00
										 |  |  |     expect(calls).toEqual([]); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('pushes back execution time for skipped timers', async ({ page, calls }) => { | 
					
						
							|  |  |  |     await page.evaluate(async () => { | 
					
						
							|  |  |  |       setTimeout(() => { | 
					
						
							|  |  |  |         window.stub(Date.now()); | 
					
						
							|  |  |  |       }, 1000); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  |     await page.clock.fastForward(2000); | 
					
						
							| 
									
										
										
										
											2024-06-11 12:51:00 -07:00
										 |  |  |     expect(calls).toEqual([{ params: [1000 + 2000] }]); | 
					
						
							| 
									
										
										
										
											2024-05-30 09:38:27 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('supports string time arguments', async ({ page, calls }) => { | 
					
						
							|  |  |  |     await page.evaluate(async () => { | 
					
						
							|  |  |  |       setTimeout(() => { | 
					
						
							|  |  |  |         window.stub(Date.now()); | 
					
						
							|  |  |  |       }, 100000);  // 100000 = 1:40
 | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  |     await page.clock.fastForward('01:50'); | 
					
						
							| 
									
										
										
										
											2024-06-11 12:51:00 -07:00
										 |  |  |     expect(calls).toEqual([{ params: [1000 + 110000] }]); | 
					
						
							| 
									
										
										
										
											2024-05-30 09:38:27 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | it.describe('stubTimers', () => { | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  |   it.beforeEach(async ({ page }) => { | 
					
						
							| 
									
										
										
										
											2024-06-11 12:51:00 -07:00
										 |  |  |     await page.clock.install({ time: 0 }); | 
					
						
							|  |  |  |     await page.clock.pauseAt(1000); | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  |   }); | 
					
						
							| 
									
										
										
										
											2024-05-30 09:38:27 -07:00
										 |  |  |   it('sets initial timestamp', async ({ page, calls }) => { | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  |     await page.clock.setSystemTime(1400); | 
					
						
							| 
									
										
										
										
											2024-05-30 09:38:27 -07:00
										 |  |  |     expect(await page.evaluate(() => Date.now())).toBe(1400); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-18 18:23:55 +02:00
										 |  |  |   it('should throw for invalid date', async ({ page }) => { | 
					
						
							|  |  |  |     await expect(page.clock.setSystemTime(new Date('invalid'))).rejects.toThrow('Invalid date: Invalid Date'); | 
					
						
							|  |  |  |     await expect(page.clock.setSystemTime('invalid')).rejects.toThrow('clock.setSystemTime: Invalid date: invalid'); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-30 09:38:27 -07:00
										 |  |  |   it('replaces global setTimeout', async ({ page, calls }) => { | 
					
						
							|  |  |  |     await page.evaluate(async () => { | 
					
						
							|  |  |  |       setTimeout(window.stub, 1000); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2024-06-04 06:51:35 -07:00
										 |  |  |     await page.clock.runFor(1000); | 
					
						
							| 
									
										
										
										
											2024-05-30 09:38:27 -07:00
										 |  |  |     expect(calls.length).toBe(1); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('global fake setTimeout should return id', async ({ page, calls }) => { | 
					
						
							|  |  |  |     const to = await page.evaluate(() => setTimeout(window.stub, 1000)); | 
					
						
							|  |  |  |     expect(typeof to).toBe('number'); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('replaces global clearTimeout', async ({ page, calls }) => { | 
					
						
							|  |  |  |     await page.evaluate(async () => { | 
					
						
							|  |  |  |       const to = setTimeout(window.stub, 1000); | 
					
						
							|  |  |  |       clearTimeout(to); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2024-06-04 06:51:35 -07:00
										 |  |  |     await page.clock.runFor(1000); | 
					
						
							| 
									
										
										
										
											2024-05-30 09:38:27 -07:00
										 |  |  |     expect(calls).toEqual([]); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('replaces global setInterval', async ({ page, calls }) => { | 
					
						
							|  |  |  |     await page.evaluate(async () => { | 
					
						
							|  |  |  |       setInterval(window.stub, 500); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2024-06-04 06:51:35 -07:00
										 |  |  |     await page.clock.runFor(1000); | 
					
						
							| 
									
										
										
										
											2024-05-30 09:38:27 -07:00
										 |  |  |     expect(calls.length).toBe(2); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('replaces global clearInterval', async ({ page, calls }) => { | 
					
						
							|  |  |  |     await page.evaluate(async () => { | 
					
						
							|  |  |  |       const to = setInterval(window.stub, 500); | 
					
						
							|  |  |  |       clearInterval(to); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2024-06-04 06:51:35 -07:00
										 |  |  |     await page.clock.runFor(1000); | 
					
						
							| 
									
										
										
										
											2024-05-30 09:38:27 -07:00
										 |  |  |     expect(calls).toEqual([]); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('replaces global performance.now', async ({ page }) => { | 
					
						
							|  |  |  |     const promise = page.evaluate(async () => { | 
					
						
							|  |  |  |       const prev = performance.now(); | 
					
						
							|  |  |  |       await new Promise(f => setTimeout(f, 1000)); | 
					
						
							|  |  |  |       const next = performance.now(); | 
					
						
							|  |  |  |       return { prev, next }; | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2024-06-04 06:51:35 -07:00
										 |  |  |     await page.clock.runFor(1000); | 
					
						
							| 
									
										
										
										
											2024-06-11 12:51:00 -07:00
										 |  |  |     expect(await promise).toEqual({ prev: 1000, next: 2000 }); | 
					
						
							| 
									
										
										
										
											2024-05-30 09:38:27 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  |   it('fakes Date constructor', async ({ page }) => { | 
					
						
							|  |  |  |     const now = await page.evaluate(() => new Date().getTime()); | 
					
						
							| 
									
										
										
										
											2024-06-11 12:51:00 -07:00
										 |  |  |     expect(now).toBe(1000); | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | it.describe('stubTimers', () => { | 
					
						
							| 
									
										
										
										
											2024-06-05 09:25:12 -07:00
										 |  |  |   it('replaces global performance.timeOrigin', async ({ page }) => { | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  |     await page.clock.install({ time: 1000 }); | 
					
						
							| 
									
										
										
										
											2024-06-11 12:51:00 -07:00
										 |  |  |     await page.clock.pauseAt(2000); | 
					
						
							| 
									
										
										
										
											2024-06-05 09:25:12 -07:00
										 |  |  |     const promise = page.evaluate(async () => { | 
					
						
							|  |  |  |       const prev = performance.now(); | 
					
						
							|  |  |  |       await new Promise(f => setTimeout(f, 1000)); | 
					
						
							|  |  |  |       const next = performance.now(); | 
					
						
							|  |  |  |       return { prev, next }; | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     await page.clock.runFor(1000); | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  |     expect(await page.evaluate(() => performance.timeOrigin)).toBe(1000); | 
					
						
							| 
									
										
										
										
											2024-06-13 10:21:00 -07:00
										 |  |  |     expect(await promise).toEqual({ prev: 1000, next: 2000 }); | 
					
						
							| 
									
										
										
										
											2024-06-05 09:25:12 -07:00
										 |  |  |   }); | 
					
						
							| 
									
										
										
										
											2024-05-30 09:38:27 -07:00
										 |  |  | }); | 
					
						
							| 
									
										
										
										
											2024-05-31 08:09:24 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | it.describe('popup', () => { | 
					
						
							|  |  |  |   it('should tick after popup', async ({ page }) => { | 
					
						
							| 
									
										
										
										
											2024-06-13 10:21:00 -07:00
										 |  |  |     await page.clock.install({ time: 0 }); | 
					
						
							| 
									
										
										
										
											2024-05-31 08:09:24 -07:00
										 |  |  |     const now = new Date('2015-09-25'); | 
					
						
							| 
									
										
										
										
											2024-06-11 12:51:00 -07:00
										 |  |  |     await page.clock.pauseAt(now); | 
					
						
							| 
									
										
										
										
											2024-05-31 08:09:24 -07:00
										 |  |  |     const [popup] = await Promise.all([ | 
					
						
							|  |  |  |       page.waitForEvent('popup'), | 
					
						
							|  |  |  |       page.evaluate(() => window.open('about:blank')), | 
					
						
							|  |  |  |     ]); | 
					
						
							|  |  |  |     const popupTime = await popup.evaluate(() => Date.now()); | 
					
						
							|  |  |  |     expect(popupTime).toBe(now.getTime()); | 
					
						
							| 
									
										
										
										
											2024-06-04 06:51:35 -07:00
										 |  |  |     await page.clock.runFor(1000); | 
					
						
							| 
									
										
										
										
											2024-05-31 08:09:24 -07:00
										 |  |  |     const popupTimeAfter = await popup.evaluate(() => Date.now()); | 
					
						
							|  |  |  |     expect(popupTimeAfter).toBe(now.getTime() + 1000); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  |   it('should tick before popup', async ({ page }) => { | 
					
						
							| 
									
										
										
										
											2024-06-13 10:21:00 -07:00
										 |  |  |     await page.clock.install({ time: 0 }); | 
					
						
							| 
									
										
										
										
											2024-05-31 08:09:24 -07:00
										 |  |  |     const now = new Date('2015-09-25'); | 
					
						
							| 
									
										
										
										
											2024-06-11 12:51:00 -07:00
										 |  |  |     await page.clock.pauseAt(now); | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  |     await page.clock.runFor(1000); | 
					
						
							| 
									
										
										
										
											2024-05-31 08:09:24 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     const [popup] = await Promise.all([ | 
					
						
							|  |  |  |       page.waitForEvent('popup'), | 
					
						
							|  |  |  |       page.evaluate(() => window.open('about:blank')), | 
					
						
							|  |  |  |     ]); | 
					
						
							|  |  |  |     const popupTime = await popup.evaluate(() => Date.now()); | 
					
						
							|  |  |  |     expect(popupTime).toBe(now.getTime() + 1000); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  |   it('should run time before popup', async ({ page, server }) => { | 
					
						
							|  |  |  |     server.setRoute('/popup.html', async (req, res) => { | 
					
						
							|  |  |  |       res.setHeader('Content-Type', 'text/html'); | 
					
						
							|  |  |  |       res.end(`<script>window.time = Date.now()</script>`); | 
					
						
							| 
									
										
										
										
											2024-05-31 08:09:24 -07:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  |     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); | 
					
						
							|  |  |  |     const [popup] = await Promise.all([ | 
					
						
							|  |  |  |       page.waitForEvent('popup'), | 
					
						
							|  |  |  |       page.evaluate(url => window.open(url), server.PREFIX + '/popup.html'), | 
					
						
							|  |  |  |     ]); | 
					
						
							|  |  |  |     const popupTime = await popup.evaluate('time'); | 
					
						
							|  |  |  |     expect(popupTime).toBeGreaterThanOrEqual(2000); | 
					
						
							| 
									
										
										
										
											2024-05-31 08:09:24 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  |   it('should not run time before popup on pause', async ({ page, server }) => { | 
					
						
							|  |  |  |     server.setRoute('/popup.html', async (req, res) => { | 
					
						
							|  |  |  |       res.setHeader('Content-Type', 'text/html'); | 
					
						
							|  |  |  |       res.end(`<script>window.time = Date.now()</script>`); | 
					
						
							| 
									
										
										
										
											2024-05-31 08:09:24 -07:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2024-06-13 10:21:00 -07:00
										 |  |  |     await page.clock.install({ time: 0 }); | 
					
						
							| 
									
										
										
										
											2024-06-11 12:51:00 -07:00
										 |  |  |     await page.clock.pauseAt(1000); | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  |     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); | 
					
						
							|  |  |  |     const [popup] = await Promise.all([ | 
					
						
							|  |  |  |       page.waitForEvent('popup'), | 
					
						
							|  |  |  |       page.evaluate(url => window.open(url), server.PREFIX + '/popup.html'), | 
					
						
							|  |  |  |     ]); | 
					
						
							| 
									
										
										
										
											2024-10-07 02:58:03 -07:00
										 |  |  |     await popup.waitForLoadState(); | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  |     const popupTime = await popup.evaluate('time'); | 
					
						
							| 
									
										
										
										
											2024-06-11 12:51:00 -07:00
										 |  |  |     expect(popupTime).toBe(1000); | 
					
						
							| 
									
										
										
										
											2024-06-04 06:51:35 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  | it.describe('setFixedTime', () => { | 
					
						
							| 
									
										
										
										
											2024-06-04 06:51:35 -07:00
										 |  |  |   it('does not fake methods', async ({ page }) => { | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  |     await page.clock.setFixedTime(0); | 
					
						
							| 
									
										
										
										
											2024-06-04 06:51:35 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // Should not stall.
 | 
					
						
							|  |  |  |     await page.evaluate(() => { | 
					
						
							|  |  |  |       return new Promise(f => setTimeout(f, 1)); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  |   it('allows setting time multiple times', async ({ page }) => { | 
					
						
							|  |  |  |     await page.clock.setFixedTime(100); | 
					
						
							| 
									
										
										
										
											2024-06-04 06:51:35 -07:00
										 |  |  |     expect(await page.evaluate(() => Date.now())).toBe(100); | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  |     await page.clock.setFixedTime(200); | 
					
						
							| 
									
										
										
										
											2024-06-04 06:51:35 -07:00
										 |  |  |     expect(await page.evaluate(() => Date.now())).toBe(200); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  |   it('fixed time is not affected by clock manipulation', async ({ page }) => { | 
					
						
							|  |  |  |     await page.clock.setFixedTime(100); | 
					
						
							|  |  |  |     expect(await page.evaluate(() => Date.now())).toBe(100); | 
					
						
							|  |  |  |     await page.clock.fastForward(20); | 
					
						
							| 
									
										
										
										
											2024-06-04 06:51:35 -07:00
										 |  |  |     expect(await page.evaluate(() => Date.now())).toBe(100); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('allows installing fake timers after settings time', async ({ page, calls }) => { | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  |     await page.clock.setFixedTime(100); | 
					
						
							| 
									
										
										
										
											2024-06-04 06:51:35 -07:00
										 |  |  |     expect(await page.evaluate(() => Date.now())).toBe(100); | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  |     await page.clock.setFixedTime(200); | 
					
						
							| 
									
										
										
										
											2024-06-04 06:51:35 -07:00
										 |  |  |     await page.evaluate(async () => { | 
					
						
							|  |  |  |       setTimeout(() => window.stub(Date.now())); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     await page.clock.runFor(0); | 
					
						
							|  |  |  |     expect(calls).toEqual([{ params: [200] }]); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  | }); | 
					
						
							| 
									
										
										
										
											2024-06-04 06:51:35 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  | it.describe('while running', () => { | 
					
						
							|  |  |  |   it('should progress time', async ({ page }) => { | 
					
						
							|  |  |  |     await page.clock.install({ time: 0 }); | 
					
						
							|  |  |  |     await page.goto('data:text/html,'); | 
					
						
							|  |  |  |     await page.waitForTimeout(1000); | 
					
						
							|  |  |  |     const now = await page.evaluate(() => Date.now()); | 
					
						
							|  |  |  |     expect(now).toBeGreaterThanOrEqual(1000); | 
					
						
							|  |  |  |     expect(now).toBeLessThanOrEqual(2000); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should runFor', async ({ page }) => { | 
					
						
							|  |  |  |     await page.clock.install({ time: 0 }); | 
					
						
							|  |  |  |     await page.goto('data:text/html,'); | 
					
						
							|  |  |  |     await page.clock.runFor(10000); | 
					
						
							|  |  |  |     const now = await page.evaluate(() => Date.now()); | 
					
						
							|  |  |  |     expect(now).toBeGreaterThanOrEqual(10000); | 
					
						
							|  |  |  |     expect(now).toBeLessThanOrEqual(11000); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should fastForward', async ({ page }) => { | 
					
						
							|  |  |  |     await page.clock.install({ time: 0 }); | 
					
						
							|  |  |  |     await page.goto('data:text/html,'); | 
					
						
							|  |  |  |     await page.clock.fastForward(10000); | 
					
						
							|  |  |  |     const now = await page.evaluate(() => Date.now()); | 
					
						
							|  |  |  |     expect(now).toBeGreaterThanOrEqual(10000); | 
					
						
							|  |  |  |     expect(now).toBeLessThanOrEqual(11000); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should fastForwardTo', async ({ page }) => { | 
					
						
							|  |  |  |     await page.clock.install({ time: 0 }); | 
					
						
							|  |  |  |     await page.goto('data:text/html,'); | 
					
						
							| 
									
										
										
										
											2024-06-11 12:51:00 -07:00
										 |  |  |     await page.clock.fastForward(10000); | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  |     const now = await page.evaluate(() => Date.now()); | 
					
						
							|  |  |  |     expect(now).toBeGreaterThanOrEqual(10000); | 
					
						
							|  |  |  |     expect(now).toBeLessThanOrEqual(11000); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should pause', async ({ page }) => { | 
					
						
							|  |  |  |     await page.clock.install({ time: 0 }); | 
					
						
							|  |  |  |     await page.goto('data:text/html,'); | 
					
						
							| 
									
										
										
										
											2024-06-11 12:51:00 -07:00
										 |  |  |     await page.clock.pauseAt(1000); | 
					
						
							| 
									
										
										
										
											2025-04-07 21:38:10 +01:00
										 |  |  |     // Internally wait to make sure the clock is paused and not running.
 | 
					
						
							|  |  |  |     await page.waitForTimeout(1111); | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  |     const now = await page.evaluate(() => Date.now()); | 
					
						
							|  |  |  |     expect(now).toBeGreaterThanOrEqual(0); | 
					
						
							|  |  |  |     expect(now).toBeLessThanOrEqual(1000); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-11 12:51:00 -07:00
										 |  |  |   it('should pause and fastForward', async ({ page }) => { | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  |     await page.clock.install({ time: 0 }); | 
					
						
							|  |  |  |     await page.goto('data:text/html,'); | 
					
						
							| 
									
										
										
										
											2024-06-11 12:51:00 -07:00
										 |  |  |     await page.clock.pauseAt(1000); | 
					
						
							|  |  |  |     await page.clock.fastForward(1000); | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  |     const now = await page.evaluate(() => Date.now()); | 
					
						
							| 
									
										
										
										
											2024-06-11 12:51:00 -07:00
										 |  |  |     expect(now).toBe(2000); | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should set system time on pause', async ({ page }) => { | 
					
						
							| 
									
										
										
										
											2024-06-11 12:51:00 -07:00
										 |  |  |     await page.clock.install({ time: 0 }); | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  |     await page.goto('data:text/html,'); | 
					
						
							| 
									
										
										
										
											2024-06-11 12:51:00 -07:00
										 |  |  |     await page.clock.pauseAt(1000); | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  |     const now = await page.evaluate(() => Date.now()); | 
					
						
							|  |  |  |     expect(now).toBe(1000); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | it.describe('while on pause', () => { | 
					
						
							|  |  |  |   it('fastForward should not run nested immediate', async ({ page, calls }) => { | 
					
						
							| 
									
										
										
										
											2024-06-11 12:51:00 -07:00
										 |  |  |     await page.clock.install({ time: 0 }); | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  |     await page.goto('data:text/html,'); | 
					
						
							| 
									
										
										
										
											2024-06-11 12:51:00 -07:00
										 |  |  |     await page.clock.pauseAt(1000); | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  |     await page.evaluate(() => { | 
					
						
							|  |  |  |       setTimeout(() => { | 
					
						
							|  |  |  |         window.stub('outer'); | 
					
						
							|  |  |  |         setTimeout(() => window.stub('inner'), 0); | 
					
						
							|  |  |  |       }, 1000); | 
					
						
							| 
									
										
										
										
											2024-06-04 06:51:35 -07:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  |     await page.clock.fastForward(1000); | 
					
						
							|  |  |  |     expect(calls).toEqual([{ params: ['outer'] }]); | 
					
						
							|  |  |  |     await page.clock.fastForward(1); | 
					
						
							|  |  |  |     expect(calls).toEqual([{ params: ['outer'] }, { params: ['inner'] }]); | 
					
						
							| 
									
										
										
										
											2024-06-04 06:51:35 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  |   it('runFor should not run nested immediate', async ({ page, calls }) => { | 
					
						
							| 
									
										
										
										
											2024-06-11 12:51:00 -07:00
										 |  |  |     await page.clock.install({ time: 0 }); | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  |     await page.goto('data:text/html,'); | 
					
						
							| 
									
										
										
										
											2024-06-11 12:51:00 -07:00
										 |  |  |     await page.clock.pauseAt(1000); | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  |     await page.evaluate(() => { | 
					
						
							|  |  |  |       setTimeout(() => { | 
					
						
							|  |  |  |         window.stub('outer'); | 
					
						
							|  |  |  |         setTimeout(() => window.stub('inner'), 0); | 
					
						
							|  |  |  |       }, 1000); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     await page.clock.runFor(1000); | 
					
						
							|  |  |  |     expect(calls).toEqual([{ params: ['outer'] }]); | 
					
						
							|  |  |  |     await page.clock.runFor(1); | 
					
						
							|  |  |  |     expect(calls).toEqual([{ params: ['outer'] }, { params: ['inner'] }]); | 
					
						
							| 
									
										
										
										
											2024-06-04 06:51:35 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  |   it('runFor should not run nested immediate from microtask', async ({ page, calls }) => { | 
					
						
							| 
									
										
										
										
											2024-06-11 12:51:00 -07:00
										 |  |  |     await page.clock.install({ time: 0 }); | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  |     await page.goto('data:text/html,'); | 
					
						
							| 
									
										
										
										
											2024-06-11 12:51:00 -07:00
										 |  |  |     await page.clock.pauseAt(1000); | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  |     await page.evaluate(() => { | 
					
						
							|  |  |  |       setTimeout(() => { | 
					
						
							|  |  |  |         window.stub('outer'); | 
					
						
							|  |  |  |         void Promise.resolve().then(() => setTimeout(() => window.stub('inner'), 0)); | 
					
						
							|  |  |  |       }, 1000); | 
					
						
							| 
									
										
										
										
											2024-06-04 06:51:35 -07:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2024-06-11 09:42:15 -07:00
										 |  |  |     await page.clock.runFor(1000); | 
					
						
							|  |  |  |     expect(calls).toEqual([{ params: ['outer'] }]); | 
					
						
							|  |  |  |     await page.clock.runFor(1); | 
					
						
							|  |  |  |     expect(calls).toEqual([{ params: ['outer'] }, { params: ['inner'] }]); | 
					
						
							| 
									
										
										
										
											2024-05-31 08:09:24 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | }); | 
					
						
							| 
									
										
										
										
											2024-07-12 11:44:25 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | it.describe('Date.now', () => { | 
					
						
							|  |  |  |   it('check Date.now is an integer', async ({ page }) => { | 
					
						
							|  |  |  |     await page.clock.install(); | 
					
						
							|  |  |  |     await page.goto('data:text/html,'); | 
					
						
							|  |  |  |     await page.waitForTimeout(1000); | 
					
						
							|  |  |  |     const dateValue = await page.evaluate('Date.now()'); | 
					
						
							|  |  |  |     expect(Number.isInteger(dateValue)).toBeTruthy(); | 
					
						
							|  |  |  |     await page.waitForTimeout(1000); | 
					
						
							|  |  |  |     const dateValue2 = await page.evaluate('Date.now()'); | 
					
						
							|  |  |  |     expect(Number.isInteger(dateValue2)).toBeTruthy(); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('check Date.now is an integer (2)', async ({ page }) => { | 
					
						
							|  |  |  |     await page.clock.install({ time: 0 }); | 
					
						
							|  |  |  |     await page.goto('data:text/html,'); | 
					
						
							|  |  |  |     await page.clock.pauseAt(1000); | 
					
						
							|  |  |  |     await page.clock.runFor(0.5); | 
					
						
							|  |  |  |     const dateValue = await page.evaluate('Date.now()'); | 
					
						
							|  |  |  |     expect(dateValue).toBe(1001); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | }); | 
					
						
							| 
									
										
										
										
											2025-04-07 21:40:58 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | it('correctly increments Date.now()/performance.now() during blocking execution', { | 
					
						
							|  |  |  |   annotation: { | 
					
						
							|  |  |  |     type: 'issue', | 
					
						
							|  |  |  |     description: 'https://github.com/microsoft/playwright/issues/35362', | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }, async ({ page, server }) => { | 
					
						
							|  |  |  |   await page.clock.setSystemTime(new Date('2026-01-01')); | 
					
						
							|  |  |  |   server.setRoute('/repro.html', (req, res) => { | 
					
						
							|  |  |  |     res.writeHead(200, { 'Content-Type': 'text/html' }); | 
					
						
							|  |  |  |     res.end(`
 | 
					
						
							|  |  |  |       <html> | 
					
						
							|  |  |  |         <body> | 
					
						
							|  |  |  |           <script> | 
					
						
							|  |  |  |           { | 
					
						
							|  |  |  |             const start = performance.now(); | 
					
						
							|  |  |  |             while (performance.now() - start < 100) { } | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           { | 
					
						
							|  |  |  |             const start = Date.now(); | 
					
						
							|  |  |  |             while (Date.now() - start < 100) { } | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           console.log('done'); | 
					
						
							|  |  |  |           </script> | 
					
						
							|  |  |  |         </body> | 
					
						
							|  |  |  |       </html> | 
					
						
							|  |  |  |     `);
 | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   const waitForDone = page.waitForEvent('console', msg => msg.text() === 'done'); | 
					
						
							|  |  |  |   await page.goto(server.PREFIX + '/repro.html'); | 
					
						
							|  |  |  |   await waitForDone; | 
					
						
							|  |  |  | }); |