| 
									
										
										
										
											2022-03-18 17:31:26 -06:00
										 |  |  | /** | 
					
						
							|  |  |  |  * Copyright Microsoft Corporation. All rights reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * 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. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-07 15:11:44 -08:00
										 |  |  | import { test, expect } from './playwright-test-fixtures'; | 
					
						
							| 
									
										
										
										
											2022-03-18 17:31:26 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | test('should poll predicate', async ({ runInlineTest }) => { | 
					
						
							|  |  |  |   const result = await runInlineTest({ | 
					
						
							|  |  |  |     'a.spec.ts': `
 | 
					
						
							| 
									
										
										
										
											2023-02-14 19:20:56 -08:00
										 |  |  |       import { test, expect } from '@playwright/test'; | 
					
						
							| 
									
										
										
										
											2022-03-18 17:31:26 -06:00
										 |  |  |       test('should poll sync predicate', async () => { | 
					
						
							|  |  |  |         let i = 0; | 
					
						
							|  |  |  |         await test.expect.poll(() => ++i).toBe(3); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |       test('should poll async predicate', async () => { | 
					
						
							|  |  |  |         let i = 0; | 
					
						
							|  |  |  |         await test.expect.poll(async () => { | 
					
						
							|  |  |  |           await new Promise(x => setTimeout(x, 50)); | 
					
						
							|  |  |  |           return ++i; | 
					
						
							|  |  |  |         }).toBe(3); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |       test('should poll predicate that returns a promise', async () => { | 
					
						
							|  |  |  |         let i = 0; | 
					
						
							|  |  |  |         await test.expect.poll(() => Promise.resolve(++i)).toBe(3); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     `
 | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   expect(result.exitCode).toBe(0); | 
					
						
							|  |  |  |   expect(result.passed).toBe(3); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | test('should compile', async ({ runTSC }) => { | 
					
						
							|  |  |  |   const result = await runTSC({ | 
					
						
							|  |  |  |     'a.spec.ts': `
 | 
					
						
							| 
									
										
										
										
											2023-02-14 19:20:56 -08:00
										 |  |  |       import { test, expect } from '@playwright/test'; | 
					
						
							| 
									
										
										
										
											2022-04-11 10:42:19 -07:00
										 |  |  |       test('should poll sync predicate', async ({ page }) => { | 
					
						
							| 
									
										
										
										
											2022-03-18 17:31:26 -06:00
										 |  |  |         let i = 0; | 
					
						
							|  |  |  |         test.expect.poll(() => ++i).toBe(3); | 
					
						
							|  |  |  |         test.expect.poll(() => ++i, 'message').toBe(3); | 
					
						
							|  |  |  |         test.expect.poll(() => ++i, { message: 'message' }).toBe(3); | 
					
						
							|  |  |  |         test.expect.poll(() => ++i, { timeout: 100 }).toBe(3); | 
					
						
							|  |  |  |         test.expect.poll(() => ++i, { message: 'message', timeout: 100 }).toBe(3); | 
					
						
							|  |  |  |         test.expect.poll(async () => { | 
					
						
							|  |  |  |           await new Promise(x => setTimeout(x, 50)); | 
					
						
							|  |  |  |           return ++i; | 
					
						
							|  |  |  |         }).toBe(3); | 
					
						
							|  |  |  |         test.expect.poll(() => Promise.resolve(++i)).toBe(3); | 
					
						
							| 
									
										
										
										
											2022-04-11 10:42:19 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // @ts-expect-error
 | 
					
						
							|  |  |  |         await test.expect.poll(() => page.locator('foo')).toBeEnabled(); | 
					
						
							|  |  |  |         // @ts-expect-error
 | 
					
						
							|  |  |  |         await test.expect.poll(() => page.locator('foo')).not.toBeEnabled(); | 
					
						
							| 
									
										
										
										
											2022-03-18 17:31:26 -06:00
										 |  |  |       }); | 
					
						
							|  |  |  |     `
 | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   expect(result.exitCode).toBe(0); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | test('should respect timeout', async ({ runInlineTest }) => { | 
					
						
							|  |  |  |   const result = await runInlineTest({ | 
					
						
							|  |  |  |     'a.spec.ts': `
 | 
					
						
							| 
									
										
										
										
											2023-02-14 19:20:56 -08:00
										 |  |  |       import { test, expect } from '@playwright/test'; | 
					
						
							| 
									
										
										
										
											2022-03-18 17:31:26 -06:00
										 |  |  |       test('should fail', async () => { | 
					
						
							|  |  |  |         await test.expect.poll(() => false, { timeout: 100 }).toBe(3); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     `
 | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   expect(result.exitCode).toBe(1); | 
					
						
							| 
									
										
										
										
											2023-02-07 15:11:44 -08:00
										 |  |  |   expect(result.output).toContain('Timeout 100ms exceeded while waiting on the predicate'); | 
					
						
							|  |  |  |   expect(result.output).toContain('Received: false'); | 
					
						
							|  |  |  |   expect(result.output).toContain(`
 | 
					
						
							| 
									
										
										
										
											2023-02-14 19:20:56 -08:00
										 |  |  |   4 |         await test.expect.poll(() => false, { timeout: 100 }). | 
					
						
							| 
									
										
										
										
											2022-03-18 17:31:26 -06:00
										 |  |  |   `.trim());
 | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | test('should fail when passed in non-function', async ({ runInlineTest }) => { | 
					
						
							|  |  |  |   const result = await runInlineTest({ | 
					
						
							|  |  |  |     'a.spec.ts': `
 | 
					
						
							| 
									
										
										
										
											2023-02-14 19:20:56 -08:00
										 |  |  |       import { test, expect } from '@playwright/test'; | 
					
						
							| 
									
										
										
										
											2022-03-18 17:31:26 -06:00
										 |  |  |       test('should fail', async () => { | 
					
						
							|  |  |  |         await test.expect.poll(false).toBe(3); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     `
 | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   expect(result.exitCode).toBe(1); | 
					
						
							| 
									
										
										
										
											2023-02-07 15:11:44 -08:00
										 |  |  |   expect(result.output).toContain('Error: `expect.poll()` accepts only function as a first argument'); | 
					
						
							| 
									
										
										
										
											2022-03-18 17:31:26 -06:00
										 |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | test('should fail when used with web-first assertion', async ({ runInlineTest }) => { | 
					
						
							|  |  |  |   const result = await runInlineTest({ | 
					
						
							|  |  |  |     'a.spec.ts': `
 | 
					
						
							| 
									
										
										
										
											2023-02-14 19:20:56 -08:00
										 |  |  |       import { test, expect } from '@playwright/test'; | 
					
						
							| 
									
										
										
										
											2022-03-18 17:31:26 -06:00
										 |  |  |       test('should fail', async ({ page }) => { | 
					
						
							|  |  |  |         await test.expect.poll(() => page.locator('body')).toHaveText('foo'); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     `
 | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   expect(result.exitCode).toBe(1); | 
					
						
							| 
									
										
										
										
											2023-02-07 15:11:44 -08:00
										 |  |  |   expect(result.output).toContain('Error: `expect.poll()` does not support "toHaveText" matcher'); | 
					
						
							| 
									
										
										
										
											2022-03-18 17:31:26 -06:00
										 |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | test('should time out when running infinite predicate', async ({ runInlineTest }) => { | 
					
						
							|  |  |  |   const result = await runInlineTest({ | 
					
						
							|  |  |  |     'a.spec.ts': `
 | 
					
						
							| 
									
										
										
										
											2023-02-14 19:20:56 -08:00
										 |  |  |       import { test, expect } from '@playwright/test'; | 
					
						
							| 
									
										
										
										
											2022-03-18 17:31:26 -06:00
										 |  |  |       test('should fail', async ({ page }) => { | 
					
						
							|  |  |  |         await test.expect.poll(() => new Promise(x => {}), { timeout: 100 }).toBe(42); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     `
 | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   expect(result.exitCode).toBe(1); | 
					
						
							| 
									
										
										
										
											2023-02-07 15:11:44 -08:00
										 |  |  |   expect(result.output).toContain('Timeout 100ms exceeded'); | 
					
						
							| 
									
										
										
										
											2022-03-18 17:31:26 -06:00
										 |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | test('should show error that is thrown from predicate', async ({ runInlineTest }) => { | 
					
						
							|  |  |  |   const result = await runInlineTest({ | 
					
						
							|  |  |  |     'a.spec.ts': `
 | 
					
						
							| 
									
										
										
										
											2023-02-14 19:20:56 -08:00
										 |  |  |       import { test, expect } from '@playwright/test'; | 
					
						
							| 
									
										
										
										
											2022-03-18 17:31:26 -06:00
										 |  |  |       test('should fail', async ({ page }) => { | 
					
						
							|  |  |  |         await test.expect.poll(() => { throw new Error('foo bar baz'); }, { timeout: 100 }).toBe(42); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     `
 | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   expect(result.exitCode).toBe(1); | 
					
						
							| 
									
										
										
										
											2023-02-07 15:11:44 -08:00
										 |  |  |   expect(result.output).toContain('foo bar baz'); | 
					
						
							| 
									
										
										
										
											2022-03-18 17:31:26 -06:00
										 |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-05 11:14:37 -08:00
										 |  |  | test('should not retry predicate that threw an error', async ({ runInlineTest }) => { | 
					
						
							|  |  |  |   const result = await runInlineTest({ | 
					
						
							|  |  |  |     'a.spec.ts': `
 | 
					
						
							| 
									
										
										
										
											2023-02-14 19:20:56 -08:00
										 |  |  |       import { test, expect } from '@playwright/test'; | 
					
						
							| 
									
										
										
										
											2023-01-05 11:14:37 -08:00
										 |  |  |       test('should fail', async ({ page }) => { | 
					
						
							|  |  |  |         let iteration = 0; | 
					
						
							|  |  |  |         await test.expect.poll(() => { | 
					
						
							|  |  |  |           if (iteration++ === 0) | 
					
						
							|  |  |  |             throw new Error('foo bar baz'); | 
					
						
							|  |  |  |           return 42; | 
					
						
							|  |  |  |         }).toBe(42); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     `
 | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   expect(result.exitCode).toBe(1); | 
					
						
							| 
									
										
										
										
											2023-02-07 15:11:44 -08:00
										 |  |  |   expect(result.output).toContain('foo bar baz'); | 
					
						
							| 
									
										
										
										
											2023-01-05 11:14:37 -08:00
										 |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-18 17:31:26 -06:00
										 |  |  | test('should support .not predicate', async ({ runInlineTest }) => { | 
					
						
							|  |  |  |   const result = await runInlineTest({ | 
					
						
							|  |  |  |     'a.spec.ts': `
 | 
					
						
							| 
									
										
										
										
											2023-02-14 19:20:56 -08:00
										 |  |  |       import { test, expect } from '@playwright/test'; | 
					
						
							| 
									
										
										
										
											2022-03-18 17:31:26 -06:00
										 |  |  |       test('should fail', async ({ page }) => { | 
					
						
							|  |  |  |         let i = 0; | 
					
						
							|  |  |  |         await test.expect.poll(() => ++i).not.toBeLessThan(3); | 
					
						
							|  |  |  |         expect(i).toBe(3); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     `
 | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   expect(result.exitCode).toBe(0); | 
					
						
							|  |  |  | }); | 
					
						
							| 
									
										
										
										
											2022-04-05 16:47:35 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | test('should support custom matchers', async ({ runInlineTest }) => { | 
					
						
							|  |  |  |   const result = await runInlineTest({ | 
					
						
							|  |  |  |     'a.spec.ts': `
 | 
					
						
							|  |  |  |       expect.extend({ | 
					
						
							|  |  |  |         toBeWithinRange(received, floor, ceiling) { | 
					
						
							|  |  |  |           const pass = received >= floor && received <= ceiling; | 
					
						
							|  |  |  |           if (pass) { | 
					
						
							|  |  |  |             return { | 
					
						
							|  |  |  |               message: () => | 
					
						
							|  |  |  |                 "expected " + received + " not to be within range " + floor + " - " + ceiling, | 
					
						
							|  |  |  |               pass: true, | 
					
						
							|  |  |  |             }; | 
					
						
							|  |  |  |           } else { | 
					
						
							|  |  |  |             return { | 
					
						
							|  |  |  |               message: () => | 
					
						
							|  |  |  |                 "expected " + received + " to be within range " + floor + " - " + ceiling, | 
					
						
							|  |  |  |               pass: false, | 
					
						
							|  |  |  |             }; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-14 19:20:56 -08:00
										 |  |  |       import { test, expect } from '@playwright/test'; | 
					
						
							| 
									
										
										
										
											2022-04-05 16:47:35 -08:00
										 |  |  |       test('should poll', async () => { | 
					
						
							|  |  |  |         let i = 0; | 
					
						
							|  |  |  |         await test.expect.poll(() => ++i).toBeWithinRange(3, Number.MAX_VALUE); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     `
 | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   expect(result.exitCode).toBe(0); | 
					
						
							|  |  |  |   expect(result.passed).toBe(1); | 
					
						
							|  |  |  | }); | 
					
						
							| 
									
										
										
										
											2022-04-26 20:32:38 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | test('should respect interval', async ({ runInlineTest }) => { | 
					
						
							|  |  |  |   const result = await runInlineTest({ | 
					
						
							|  |  |  |     'a.spec.ts': `
 | 
					
						
							| 
									
										
										
										
											2023-02-14 19:20:56 -08:00
										 |  |  |       import { test, expect } from '@playwright/test'; | 
					
						
							| 
									
										
										
										
											2022-04-26 20:32:38 -08:00
										 |  |  |       test('should fail', async () => { | 
					
						
							|  |  |  |         let probes = 0; | 
					
						
							| 
									
										
										
										
											2023-01-20 15:47:24 -08:00
										 |  |  |         const startTime = Date.now(); | 
					
						
							|  |  |  |         await test.expect.poll(() => ++probes, { timeout: 1000, intervals: [0, 10000] }).toBe(3).catch(() => {}); | 
					
						
							|  |  |  |         // Probe at 0 and epsilon.
 | 
					
						
							| 
									
										
										
										
											2022-04-26 20:32:38 -08:00
										 |  |  |         expect(probes).toBe(2); | 
					
						
							| 
									
										
										
										
											2023-01-20 15:47:24 -08:00
										 |  |  |         expect(Date.now() - startTime).toBeLessThan(5000); | 
					
						
							| 
									
										
										
										
											2022-04-26 20:32:38 -08:00
										 |  |  |       }); | 
					
						
							|  |  |  |     `
 | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   expect(result.exitCode).toBe(0); | 
					
						
							|  |  |  | }); |