| 
									
										
										
										
											2021-06-06 17:09:53 -07: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. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-10 15:10:25 -07:00
										 |  |  | import path from 'path'; | 
					
						
							| 
									
										
										
										
											2023-07-25 15:46:39 -07:00
										 |  |  | import { test, expect, parseTestRunnerOutput } from './playwright-test-fixtures'; | 
					
						
							| 
									
										
										
										
											2021-06-06 17:09:53 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-07 08:02:01 -07:00
										 |  |  | test('should be able to call expect.extend in config', async ({ runInlineTest }) => { | 
					
						
							| 
									
										
										
										
											2021-06-06 17:09:53 -07:00
										 |  |  |   const result = await runInlineTest({ | 
					
						
							|  |  |  |     'helper.ts': `
 | 
					
						
							| 
									
										
										
										
											2023-02-14 19:20:56 -08:00
										 |  |  |       import { test as base, expect } from '@playwright/test'; | 
					
						
							|  |  |  |       expect.extend({ | 
					
						
							| 
									
										
										
										
											2021-06-06 17:09:53 -07:00
										 |  |  |         toBeWithinRange(received, floor, ceiling) { | 
					
						
							|  |  |  |           const pass = received >= floor && received <= ceiling; | 
					
						
							|  |  |  |           if (pass) { | 
					
						
							|  |  |  |             return { | 
					
						
							|  |  |  |               message: () => | 
					
						
							|  |  |  |                 'passed', | 
					
						
							|  |  |  |               pass: true, | 
					
						
							|  |  |  |             }; | 
					
						
							|  |  |  |           } else { | 
					
						
							|  |  |  |             return { | 
					
						
							|  |  |  |               message: () => 'failed', | 
					
						
							|  |  |  |               pass: false, | 
					
						
							|  |  |  |             }; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2023-02-14 19:20:56 -08:00
										 |  |  |       export const test = base; | 
					
						
							| 
									
										
										
										
											2021-06-06 17:09:53 -07:00
										 |  |  |     `,
 | 
					
						
							|  |  |  |     'expect-test.spec.ts': `
 | 
					
						
							|  |  |  |       import { test } from './helper'; | 
					
						
							|  |  |  |       test('numeric ranges', () => { | 
					
						
							|  |  |  |         test.expect(100).toBeWithinRange(90, 110); | 
					
						
							|  |  |  |         test.expect(101).not.toBeWithinRange(0, 100); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     `
 | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   expect(result.exitCode).toBe(0); | 
					
						
							|  |  |  |   expect(result.passed).toBe(1); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 14:55:16 -08:00
										 |  |  | test('should not expand huge arrays', async ({ runInlineTest }) => { | 
					
						
							|  |  |  |   const result = await runInlineTest({ | 
					
						
							|  |  |  |     'expect-test.spec.ts': `
 | 
					
						
							| 
									
										
										
										
											2023-02-14 19:20:56 -08:00
										 |  |  |       import { test, expect } from '@playwright/test'; | 
					
						
							| 
									
										
										
										
											2021-12-03 14:55:16 -08:00
										 |  |  |       test('numeric ranges', () => { | 
					
						
							|  |  |  |         const a1 = Array(100000).fill(1); | 
					
						
							|  |  |  |         const a2 = Array(100000).fill(1); | 
					
						
							|  |  |  |         a2[500] = 2; | 
					
						
							|  |  |  |         test.expect(a1).toEqual(a2); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     `
 | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   expect(result.exitCode).toBe(1); | 
					
						
							|  |  |  |   expect(result.passed).toBe(0); | 
					
						
							|  |  |  |   expect(result.output.length).toBeLessThan(100000); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-31 18:14:59 -07:00
										 |  |  | test('should include custom error message', async ({ runInlineTest }) => { | 
					
						
							|  |  |  |   const result = await runInlineTest({ | 
					
						
							|  |  |  |     'expect-test.spec.ts': `
 | 
					
						
							| 
									
										
										
										
											2023-02-14 19:20:56 -08:00
										 |  |  |       import { test, expect } from '@playwright/test'; | 
					
						
							| 
									
										
										
										
											2022-01-31 18:14:59 -07:00
										 |  |  |       test('custom expect message', () => { | 
					
						
							|  |  |  |         test.expect(1+1, 'one plus one is two!').toEqual(3); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     `
 | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   expect(result.exitCode).toBe(1); | 
					
						
							|  |  |  |   expect(result.passed).toBe(0); | 
					
						
							| 
									
										
										
										
											2023-02-07 15:11:44 -08:00
										 |  |  |   expect(result.output).toContain([ | 
					
						
							| 
									
										
										
										
											2022-01-31 18:14:59 -07:00
										 |  |  |     `    Error: one plus one is two!`, | 
					
						
							|  |  |  |     ``, | 
					
						
							|  |  |  |     `    Expected: 3`, | 
					
						
							|  |  |  |     `    Received: 2`, | 
					
						
							|  |  |  |   ].join('\n')); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | test('should include custom error message with web-first assertions', async ({ runInlineTest }) => { | 
					
						
							|  |  |  |   const result = await runInlineTest({ | 
					
						
							|  |  |  |     'expect-test.spec.ts': `
 | 
					
						
							| 
									
										
										
										
											2023-02-14 19:20:56 -08:00
										 |  |  |       import { test, expect } from '@playwright/test'; | 
					
						
							| 
									
										
										
										
											2022-01-31 18:14:59 -07:00
										 |  |  |       test('custom expect message', async ({page}) => { | 
					
						
							| 
									
										
										
										
											2022-03-18 17:31:26 -06:00
										 |  |  |         await expect(page.locator('x-foo'), { message: 'x-foo must be visible' }).toBeVisible({timeout: 1}); | 
					
						
							| 
									
										
										
										
											2022-01-31 18:14:59 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  |     `
 | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   expect(result.exitCode).toBe(1); | 
					
						
							|  |  |  |   expect(result.passed).toBe(0); | 
					
						
							|  |  |  |   expect(result.output).toContain([ | 
					
						
							|  |  |  |     `    Error: x-foo must be visible`, | 
					
						
							|  |  |  |     ``, | 
					
						
							|  |  |  |     `    Call log:`, | 
					
						
							|  |  |  |   ].join('\n')); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-01 16:55:52 -08:00
										 |  |  | test('should work with generic matchers', async ({ runTSC }) => { | 
					
						
							| 
									
										
										
										
											2021-06-06 17:09:53 -07:00
										 |  |  |   const result = await runTSC({ | 
					
						
							|  |  |  |     'a.spec.ts': `
 | 
					
						
							| 
									
										
										
										
											2023-02-14 19:20:56 -08:00
										 |  |  |       import { expect } from '@playwright/test'; | 
					
						
							| 
									
										
										
										
											2023-02-01 16:55:52 -08:00
										 |  |  |       expect(42).toBe(42); | 
					
						
							|  |  |  |       expect(0.1 + 0.2).toBeCloseTo(0.3, 5); | 
					
						
							|  |  |  |       expect(null).toBeDefined(); | 
					
						
							|  |  |  |       expect(null).toBeFalsy(); | 
					
						
							|  |  |  |       expect(42).toBeGreaterThan(1); | 
					
						
							|  |  |  |       expect(42).toBeGreaterThanOrEqual(42); | 
					
						
							|  |  |  |       expect({}).toBeInstanceOf(Object); | 
					
						
							|  |  |  |       expect(42).toBeLessThan(100); | 
					
						
							|  |  |  |       expect(42).toBeLessThanOrEqual(42); | 
					
						
							|  |  |  |       expect(null).toBeNull(); | 
					
						
							|  |  |  |       expect(42).toBeTruthy(); | 
					
						
							|  |  |  |       expect(undefined).toBeUndefined(); | 
					
						
							|  |  |  |       expect(NaN).toBeNaN(); | 
					
						
							|  |  |  |       expect('abc').toContain('a'); | 
					
						
							|  |  |  |       expect(['abc']).toContain('abc'); | 
					
						
							|  |  |  |       expect(['abc']).toContainEqual('abc'); | 
					
						
							|  |  |  |       expect({}).toEqual({}); | 
					
						
							|  |  |  |       expect([1, 2]).toHaveLength(2); | 
					
						
							|  |  |  |       expect('abc').toMatch(/a.?c/); | 
					
						
							| 
									
										
										
										
											2023-03-07 17:53:50 +01:00
										 |  |  |       expect('abc').toMatch('abc'); | 
					
						
							| 
									
										
										
										
											2023-02-01 16:55:52 -08:00
										 |  |  |       expect({ a: 1, b: 2 }).toMatchObject({ a: 1 }); | 
					
						
							|  |  |  |       expect({}).toStrictEqual({}); | 
					
						
							|  |  |  |       expect(() => { throw new Error('Something bad'); }).toThrow('something'); | 
					
						
							|  |  |  |       expect(() => { throw new Error('Something bad'); }).toThrowError('something'); | 
					
						
							| 
									
										
										
										
											2023-02-03 15:56:31 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |       expect(['Bob', 'Eve']).not.toEqual(expect.arrayContaining(['Alice', 'Bob'])); | 
					
						
							|  |  |  |       expect({}).toEqual(expect.anything()); | 
					
						
							|  |  |  |       expect({ sum: 0.1 + 0.2 }).toEqual({ sum: expect.closeTo(0.3, 5) }); | 
					
						
							|  |  |  |       class Cat {} | 
					
						
							|  |  |  |       expect(new Cat()).toEqual(expect.any(Cat)); | 
					
						
							|  |  |  |       expect({ x: 2, y: 3, foo: 'bar' }).toEqual(expect.objectContaining({ | 
					
						
							|  |  |  |         x: expect.any(Number), | 
					
						
							|  |  |  |         y: expect.any(Number), | 
					
						
							|  |  |  |       })); | 
					
						
							|  |  |  |       expect('abc').toEqual(expect.stringContaining('bc')); | 
					
						
							| 
									
										
										
										
											2023-03-20 12:52:52 -07:00
										 |  |  |       expect('hello world').toEqual(expect.not.stringContaining('text')); | 
					
						
							| 
									
										
										
										
											2023-02-03 15:56:31 -08:00
										 |  |  |       expect(['Alicia', 'Roberto', 'Evelina']).toEqual( | 
					
						
							|  |  |  |         expect.arrayContaining([ | 
					
						
							|  |  |  |           expect.stringMatching(/^Alic/), | 
					
						
							|  |  |  |           expect.stringMatching('Roberto'), | 
					
						
							|  |  |  |         ]), | 
					
						
							|  |  |  |       ); | 
					
						
							| 
									
										
										
										
											2021-06-06 17:09:53 -07:00
										 |  |  |     `
 | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   expect(result.exitCode).toBe(0); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-01 16:55:52 -08:00
										 |  |  | test('should compile generic matchers', async ({ runTSC }) => { | 
					
						
							|  |  |  |   const result = await runTSC({ | 
					
						
							|  |  |  |     'a.spec.ts': `
 | 
					
						
							| 
									
										
										
										
											2023-02-14 19:20:56 -08:00
										 |  |  |       import { expect } from '@playwright/test'; | 
					
						
							| 
									
										
										
										
											2023-02-01 16:55:52 -08:00
										 |  |  |       expect(42).toBe(42); | 
					
						
							|  |  |  |       expect(42).toBeCloseTo(42); | 
					
						
							|  |  |  |       expect(42).toBeCloseTo(42, 5); | 
					
						
							|  |  |  |       expect(42).toBeDefined(); | 
					
						
							|  |  |  |       expect(42).toBeFalsy(); | 
					
						
							|  |  |  |       expect(42).toBeGreaterThan(1); | 
					
						
							|  |  |  |       expect(42n).toBeGreaterThan(1n); | 
					
						
							|  |  |  |       expect(42).toBeGreaterThanOrEqual(1); | 
					
						
							|  |  |  |       expect(42n).toBeGreaterThanOrEqual(1n); | 
					
						
							|  |  |  |       expect({}).toBeInstanceOf(Object); | 
					
						
							|  |  |  |       expect(42).toBeLessThan(1); | 
					
						
							|  |  |  |       expect(42n).toBeLessThan(1n); | 
					
						
							|  |  |  |       expect(42).toBeLessThanOrEqual(1); | 
					
						
							|  |  |  |       expect(42n).toBeLessThanOrEqual(1n); | 
					
						
							|  |  |  |       expect(42).toBeNull(); | 
					
						
							|  |  |  |       expect(42).toBeTruthy(); | 
					
						
							|  |  |  |       expect(42).toBeUndefined(); | 
					
						
							|  |  |  |       expect(42).toBeNaN(); | 
					
						
							|  |  |  |       expect('abc').toContain('b'); | 
					
						
							|  |  |  |       expect([1, 2]).toContain(1); | 
					
						
							|  |  |  |       expect(new Set([1, 2])).toContain(1); | 
					
						
							|  |  |  |       expect([{}, { a: 1 }]).toContainEqual({}); | 
					
						
							|  |  |  |       expect({}).toEqual({}); | 
					
						
							|  |  |  |       expect([1, 2]).toHaveLength(2); | 
					
						
							|  |  |  |       expect('abc').toMatch(/a.?c/); | 
					
						
							|  |  |  |       expect({ a: 1, b: 2 }).toMatchObject({ a: 1 }); | 
					
						
							|  |  |  |       expect([]).toMatchObject([]); | 
					
						
							|  |  |  |       expect({}).toStrictEqual({}); | 
					
						
							|  |  |  |       expect(() => { throw new Error('Something bad'); }).toThrow('something'); | 
					
						
							|  |  |  |       expect(() => { throw new Error('Something bad'); }).toThrow(); | 
					
						
							|  |  |  |       expect(() => { throw new Error('Something bad'); }).toThrowError('something'); | 
					
						
							|  |  |  |       expect(() => { throw new Error('Something bad'); }).toThrowError(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-03 15:56:31 -08:00
										 |  |  |       expect(['Bob', 'Eve']).not.toEqual(expect.arrayContaining(['Alice', 'Bob'])); | 
					
						
							|  |  |  |       expect({}).toEqual(expect.anything()); | 
					
						
							|  |  |  |       expect({ sum: 0.1 + 0.2 }).toEqual({ sum: expect.closeTo(0.3, 5) }); | 
					
						
							|  |  |  |       class Cat {} | 
					
						
							|  |  |  |       expect(new Cat()).toEqual(expect.any(Cat)); | 
					
						
							|  |  |  |       expect({ x: 2, y: 3, foo: 'bar' }).toEqual(expect.objectContaining({ | 
					
						
							|  |  |  |         x: expect.any(Number), | 
					
						
							|  |  |  |         y: expect.any(Number), | 
					
						
							|  |  |  |       })); | 
					
						
							|  |  |  |       expect('abc').toEqual(expect.stringContaining('bc')); | 
					
						
							|  |  |  |       expect(['Alicia', 'Roberto', 'Evelina']).toEqual( | 
					
						
							|  |  |  |         expect.arrayContaining([ | 
					
						
							|  |  |  |           expect.stringMatching(/^Alic/), | 
					
						
							|  |  |  |           expect.stringMatching('Roberto'), | 
					
						
							|  |  |  |         ]), | 
					
						
							|  |  |  |       ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-01 16:55:52 -08:00
										 |  |  |       // @ts-expect-error
 | 
					
						
							|  |  |  |       expect(42).toBe(123, 456); | 
					
						
							|  |  |  |       // @ts-expect-error
 | 
					
						
							|  |  |  |       expect(42).toBeCloseTo(42, '5'); | 
					
						
							|  |  |  |       // @ts-expect-error
 | 
					
						
							|  |  |  |       expect(42).toBeFalsy(123); | 
					
						
							|  |  |  |       // @ts-expect-error
 | 
					
						
							|  |  |  |       expect({}).toBeInstanceOf({}); | 
					
						
							|  |  |  |     `,
 | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   expect(result.exitCode).toBe(0); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-31 18:14:59 -07:00
										 |  |  | test('should work with expect message', async ({ runTSC }) => { | 
					
						
							|  |  |  |   const result = await runTSC({ | 
					
						
							|  |  |  |     'a.spec.ts': `
 | 
					
						
							| 
									
										
										
										
											2023-02-14 19:20:56 -08:00
										 |  |  |       import { test, expect } from '@playwright/test'; | 
					
						
							| 
									
										
										
										
											2022-01-31 18:14:59 -07:00
										 |  |  |       test.expect(42, 'this is expect message').toBe(42); | 
					
						
							|  |  |  |     `
 | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   expect(result.exitCode).toBe(0); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-27 18:58:08 +02:00
										 |  |  | test('should work with default expect matchers and esModuleInterop=false', async ({ runTSC }) => { | 
					
						
							| 
									
										
										
										
											2021-06-14 12:58:10 -07:00
										 |  |  |   const result = await runTSC({ | 
					
						
							|  |  |  |     'a.spec.ts': `
 | 
					
						
							| 
									
										
										
										
											2023-02-14 19:20:56 -08:00
										 |  |  |       import { test, expect } from '@playwright/test'; | 
					
						
							| 
									
										
										
										
											2021-06-14 12:58:10 -07:00
										 |  |  |       test.expect(42).toBe(42); | 
					
						
							|  |  |  |     `,
 | 
					
						
							|  |  |  |     'tsconfig.json': JSON.stringify({ | 
					
						
							|  |  |  |       'compilerOptions': { | 
					
						
							|  |  |  |         'target': 'ESNext', | 
					
						
							|  |  |  |         'moduleResolution': 'node', | 
					
						
							|  |  |  |         'module': 'commonjs', | 
					
						
							|  |  |  |         'strict': true, | 
					
						
							|  |  |  |         'rootDir': '.', | 
					
						
							|  |  |  |         'esModuleInterop': false, | 
					
						
							|  |  |  |         'allowSyntheticDefaultImports': false, | 
					
						
							|  |  |  |         'lib': ['esnext', 'dom', 'DOM.Iterable'] | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       'exclude': [ | 
					
						
							|  |  |  |         'node_modules' | 
					
						
							|  |  |  |       ] | 
					
						
							|  |  |  |     }), | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   expect(result.exitCode).toBe(0); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-27 18:58:08 +02:00
										 |  |  | test('should work with custom PlaywrightTest namespace', async ({ runTSC }) => { | 
					
						
							| 
									
										
										
										
											2021-06-06 17:09:53 -07:00
										 |  |  |   const result = await runTSC({ | 
					
						
							|  |  |  |     'global.d.ts': `
 | 
					
						
							| 
									
										
										
										
											2021-06-07 08:02:01 -07:00
										 |  |  |       declare namespace PlaywrightTest { | 
					
						
							| 
									
										
										
										
											2021-06-06 17:09:53 -07:00
										 |  |  |         interface Matchers<R> { | 
					
						
							|  |  |  |           toBeEmpty(): R; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-04-05 16:11:11 -07:00
										 |  |  |         interface Matchers<R, T> { | 
					
						
							|  |  |  |           toBeNonEmpty(): R; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-06-06 17:09:53 -07:00
										 |  |  |       } | 
					
						
							|  |  |  |     `,
 | 
					
						
							|  |  |  |     'a.spec.ts': `
 | 
					
						
							| 
									
										
										
										
											2023-02-14 19:20:56 -08:00
										 |  |  |       import { test, expect } from '@playwright/test'; | 
					
						
							| 
									
										
										
										
											2021-06-06 17:09:53 -07:00
										 |  |  |       test.expect.extend({ | 
					
						
							|  |  |  |         toBeWithinRange() { }, | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       test.expect('').toBeEmpty(); | 
					
						
							|  |  |  |       test.expect('hello').not.toBeEmpty(); | 
					
						
							|  |  |  |       test.expect([]).toBeEmpty(); | 
					
						
							|  |  |  |       test.expect(['hello']).not.toBeEmpty(); | 
					
						
							|  |  |  |       test.expect({}).toBeEmpty(); | 
					
						
							|  |  |  |       test.expect({ hello: 'world' }).not.toBeEmpty(); | 
					
						
							| 
									
										
										
										
											2022-04-05 16:11:11 -07:00
										 |  |  |       test.expect('').toBeNonEmpty(); | 
					
						
							| 
									
										
										
										
											2021-06-06 17:09:53 -07:00
										 |  |  |     `
 | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   expect(result.exitCode).toBe(0); | 
					
						
							|  |  |  | }); | 
					
						
							| 
									
										
										
										
											2021-07-19 11:59:53 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 14:55:16 -08:00
										 |  |  | test('should propose only the relevant matchers when custom expect matcher classes were passed', async ({ runTSC }) => { | 
					
						
							|  |  |  |   const result = await runTSC({ | 
					
						
							|  |  |  |     'a.spec.ts': `
 | 
					
						
							| 
									
										
										
										
											2023-02-14 19:20:56 -08:00
										 |  |  |     import { test, expect } from '@playwright/test'; | 
					
						
							| 
									
										
										
										
											2021-12-03 14:55:16 -08:00
										 |  |  |     test('custom matchers', async ({ page }) => { | 
					
						
							| 
									
										
										
										
											2023-08-23 13:14:39 -07:00
										 |  |  |       // Page-specific assertions apply to Page.
 | 
					
						
							| 
									
										
										
										
											2021-12-03 14:55:16 -08:00
										 |  |  |       await test.expect(page).toHaveURL('https://example.com'); | 
					
						
							| 
									
										
										
										
											2022-04-11 10:42:19 -07:00
										 |  |  |       await test.expect(page).not.toHaveURL('https://example.com'); | 
					
						
							| 
									
										
										
										
											2023-08-23 13:14:39 -07:00
										 |  |  |       // Some generic assertions also apply to Page.
 | 
					
						
							|  |  |  |       test.expect(page).toBe(true); | 
					
						
							|  |  |  |       test.expect(page).toBeDefined(); | 
					
						
							|  |  |  |       test.expect(page).toBeFalsy(); | 
					
						
							|  |  |  |       test.expect(page).toBeNull(); | 
					
						
							|  |  |  |       test.expect(page).toBeTruthy(); | 
					
						
							|  |  |  |       test.expect(page).toBeUndefined(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // Locator-specific and most generic assertions do not apply to Page.
 | 
					
						
							| 
									
										
										
										
											2021-12-03 14:55:16 -08:00
										 |  |  |       // @ts-expect-error
 | 
					
						
							|  |  |  |       await test.expect(page).toBeEnabled(); | 
					
						
							| 
									
										
										
										
											2022-04-11 10:42:19 -07:00
										 |  |  |       // @ts-expect-error
 | 
					
						
							|  |  |  |       await test.expect(page).not.toBeEnabled(); | 
					
						
							| 
									
										
										
										
											2023-08-23 13:14:39 -07:00
										 |  |  |       // @ts-expect-error
 | 
					
						
							|  |  |  |       test.expect(page).toEqual(); | 
					
						
							| 
									
										
										
										
											2021-12-03 14:55:16 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-23 13:14:39 -07:00
										 |  |  |       // Locator-specific assertions apply to Locator.
 | 
					
						
							| 
									
										
										
										
											2021-12-03 14:55:16 -08:00
										 |  |  |       await test.expect(page.locator('foo')).toBeEnabled(); | 
					
						
							| 
									
										
										
										
											2022-09-06 11:40:34 -07:00
										 |  |  |       await test.expect(page.locator('foo')).toBeEnabled({ enabled: false }); | 
					
						
							|  |  |  |       await test.expect(page.locator('foo')).not.toBeEnabled({ enabled: true }); | 
					
						
							| 
									
										
										
										
											2023-08-23 13:14:39 -07:00
										 |  |  |       await test.expect(page.locator('foo')).toBeChecked(); | 
					
						
							|  |  |  |       await test.expect(page.locator('foo')).not.toBeChecked({ checked: true }); | 
					
						
							|  |  |  |       await test.expect(page.locator('foo')).not.toBeEditable(); | 
					
						
							|  |  |  |       await test.expect(page.locator('foo')).toBeEditable({ editable: false }); | 
					
						
							|  |  |  |       await test.expect(page.locator('foo')).toBeVisible(); | 
					
						
							|  |  |  |       await test.expect(page.locator('foo')).not.toBeVisible({ visible: false }); | 
					
						
							|  |  |  |       // Some generic assertions also apply to Locator.
 | 
					
						
							|  |  |  |       test.expect(page.locator('foo')).toBe(true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // Page-specific and most generic assertions do not apply to Locator.
 | 
					
						
							|  |  |  |       // @ts-expect-error
 | 
					
						
							|  |  |  |       await test.expect(page.locator('foo')).toHaveURL('https://example.com'); | 
					
						
							|  |  |  |       // @ts-expect-error
 | 
					
						
							|  |  |  |       await test.expect(page.locator('foo')).toHaveLength(1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // Wrong arguments for assertions do not compile.
 | 
					
						
							| 
									
										
										
										
											2022-09-06 11:40:34 -07:00
										 |  |  |       // @ts-expect-error
 | 
					
						
							|  |  |  |       await test.expect(page.locator('foo')).toBeEnabled({ unknown: false }); | 
					
						
							|  |  |  |       // @ts-expect-error
 | 
					
						
							|  |  |  |       await test.expect(page.locator('foo')).toBeEnabled({ enabled: 'foo' }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-23 13:14:39 -07:00
										 |  |  |       // Generic assertions work.
 | 
					
						
							|  |  |  |       test.expect([123]).toHaveLength(1); | 
					
						
							|  |  |  |       test.expect('123').toMatchSnapshot('name'); | 
					
						
							|  |  |  |       test.expect(await page.screenshot()).toMatchSnapshot('screenshot.png'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // All possible assertions apply to "any" type.
 | 
					
						
							|  |  |  |       const x: any = 123; | 
					
						
							|  |  |  |       test.expect(x).toHaveLength(1); | 
					
						
							|  |  |  |       await test.expect(x).toHaveURL('url'); | 
					
						
							|  |  |  |       await test.expect(x).toBeEnabled(); | 
					
						
							|  |  |  |       test.expect(x).toMatchSnapshot('snapshot name'); | 
					
						
							| 
									
										
										
										
											2021-12-03 14:55:16 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-23 13:14:39 -07:00
										 |  |  |       // APIResponse-specific assertions apply to APIResponse.
 | 
					
						
							| 
									
										
										
										
											2021-12-03 14:55:16 -08:00
										 |  |  |       const res = await page.request.get('http://i-do-definitely-not-exist.com'); | 
					
						
							|  |  |  |       await test.expect(res).toBeOK(); | 
					
						
							| 
									
										
										
										
											2023-08-23 13:14:39 -07:00
										 |  |  |       // Some generic assertions also apply to APIResponse.
 | 
					
						
							|  |  |  |       test.expect(res).toBe(true); | 
					
						
							|  |  |  |       // Page-specific and most generic assertions do not apply to APIResponse.
 | 
					
						
							| 
									
										
										
										
											2021-12-03 14:55:16 -08:00
										 |  |  |       // @ts-expect-error
 | 
					
						
							|  |  |  |       await test.expect(res).toHaveURL('https://example.com'); | 
					
						
							| 
									
										
										
										
											2023-08-23 13:14:39 -07:00
										 |  |  |       // @ts-expect-error
 | 
					
						
							|  |  |  |       test.expect(res).toEqual(123); | 
					
						
							| 
									
										
										
										
											2021-12-13 13:42:36 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-23 13:14:39 -07:00
										 |  |  |       // Explicitly casting to "any" supports all assertions.
 | 
					
						
							| 
									
										
										
										
											2021-12-13 13:42:36 -05:00
										 |  |  |       await test.expect(res as any).toHaveURL('https://example.com'); | 
					
						
							| 
									
										
										
										
											2023-08-23 13:14:39 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |       // Playwright-specific assertions do not apply to generic values.
 | 
					
						
							| 
									
										
										
										
											2021-12-13 13:42:36 -05:00
										 |  |  |       // @ts-expect-error
 | 
					
						
							|  |  |  |       await test.expect(123).toHaveURL('https://example.com'); | 
					
						
							| 
									
										
										
										
											2021-12-03 14:55:16 -08:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2021-07-19 11:59:53 -05:00
										 |  |  |     `
 | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2021-12-03 14:55:16 -08:00
										 |  |  |   expect(result.exitCode).toBe(0); | 
					
						
							|  |  |  | }); | 
					
						
							| 
									
										
										
										
											2022-04-01 13:38:22 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-05 16:11:11 -07:00
										 |  |  | test('should return void/Promise when appropriate', 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-05 16:11:11 -07:00
										 |  |  |       type AssertType<T, S> = S extends T ? AssertNotAny<S> : false; | 
					
						
							|  |  |  |       type AssertNotAny<S> = {notRealProperty: number} extends S ? false : true; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-14 19:20:56 -08:00
										 |  |  |       test('example', async ({ page }) => { | 
					
						
							| 
									
										
										
										
											2022-04-05 16:11:11 -07:00
										 |  |  |         { | 
					
						
							|  |  |  |           const value = expect(1).toBe(2); | 
					
						
							|  |  |  |           const assertion: AssertType<void, typeof value> = true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           const value = expect(1).not.toBe(2); | 
					
						
							|  |  |  |           const assertion: AssertType<void, typeof value> = true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           const value = expect(page).toHaveURL(''); | 
					
						
							|  |  |  |           const assertion: AssertType<Promise<void>, typeof value> = true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           const value = expect(Promise.resolve(1)).resolves.toBe(1); | 
					
						
							|  |  |  |           const assertion: AssertType<Promise<void>, typeof value> = true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           const value = expect.soft(1).toBe(2); | 
					
						
							|  |  |  |           const assertion: AssertType<void, typeof value> = true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           const value = expect.poll(() => true).toBe(2); | 
					
						
							|  |  |  |           const assertion: AssertType<Promise<void>, typeof value> = true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     `
 | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   expect(result.exitCode).toBe(0); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-01 13:38:22 -07:00
										 |  |  | test.describe('helpful expect errors', () => { | 
					
						
							|  |  |  |   test('top-level', 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-01 13:38:22 -07:00
										 |  |  |         test('explodes', () => { | 
					
						
							|  |  |  |           expect(1).nope(); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       `
 | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     expect(result.output).toContain(`expect: Property 'nope' not found.`); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   test('soft', 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-01 13:38:22 -07:00
										 |  |  |         test('explodes', () => { | 
					
						
							|  |  |  |           expect.soft(1).nope(); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       `
 | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     expect(result.output).toContain(`expect: Property 'nope' not found.`); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   test('poll', 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-01 13:38:22 -07:00
										 |  |  |         test('explodes', () => { | 
					
						
							|  |  |  |           expect.poll(() => {}).nope(); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       `
 | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     expect(result.output).toContain(`expect: Property 'nope' not found.`); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   test('not', 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-01 13:38:22 -07:00
										 |  |  |         test('explodes', () => { | 
					
						
							|  |  |  |           expect(1).not.nope(); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       `
 | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     expect(result.output).toContain(`expect: Property 'nope' not found.`); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   test('bare', 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-01 13:38:22 -07:00
										 |  |  |         test('explodes', () => { | 
					
						
							|  |  |  |           expect(''); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       `
 | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     expect(result.exitCode).toBe(0); | 
					
						
							|  |  |  |     expect(result.passed).toBe(1); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | }); | 
					
						
							| 
									
										
										
										
											2022-05-03 21:53:15 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | test('should reasonably work in global setup', async ({ runInlineTest }) => { | 
					
						
							|  |  |  |   const result = await runInlineTest({ | 
					
						
							|  |  |  |     'playwright.config.ts': `
 | 
					
						
							|  |  |  |       export default { globalSetup: './global-setup' }; | 
					
						
							|  |  |  |     `,
 | 
					
						
							|  |  |  |     'global-setup.ts': `
 | 
					
						
							| 
									
										
										
										
											2023-02-14 19:20:56 -08:00
										 |  |  |       import { test, expect } from '@playwright/test'; | 
					
						
							| 
									
										
										
										
											2022-05-03 21:53:15 +01:00
										 |  |  |       export default async () => { | 
					
						
							|  |  |  |         expect(1).toBe(1); | 
					
						
							|  |  |  |         await expect.poll(async () => { | 
					
						
							|  |  |  |           await new Promise(f => setTimeout(f, 50)); | 
					
						
							|  |  |  |           return 42; | 
					
						
							|  |  |  |         }).toBe(42); | 
					
						
							|  |  |  |         expect(1).toBe(2); | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  |     `,
 | 
					
						
							|  |  |  |     'a.spec.ts': `
 | 
					
						
							| 
									
										
										
										
											2023-02-14 19:20:56 -08:00
										 |  |  |       import { test, expect } from '@playwright/test'; | 
					
						
							| 
									
										
										
										
											2022-05-03 21:53:15 +01:00
										 |  |  |       test('skipped', () => {}); | 
					
						
							|  |  |  |     `,
 | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   expect(result.exitCode).toBe(1); | 
					
						
							| 
									
										
										
										
											2023-02-14 19:20:56 -08:00
										 |  |  |   expect(result.output).toContain('>  9 |         expect(1).toBe(2);'); | 
					
						
							| 
									
										
										
										
											2022-05-03 21:53:15 +01:00
										 |  |  | }); | 
					
						
							| 
									
										
										
										
											2022-08-10 15:10:25 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | test('should support toHaveURL with baseURL from webServer', async ({ runInlineTest }, testInfo) => { | 
					
						
							|  |  |  |   const port = testInfo.workerIndex + 10500; | 
					
						
							|  |  |  |   const result = await runInlineTest({ | 
					
						
							|  |  |  |     'a.test.ts': `
 | 
					
						
							| 
									
										
										
										
											2023-02-14 19:20:56 -08:00
										 |  |  |       import { test, expect } from '@playwright/test'; | 
					
						
							| 
									
										
										
										
											2022-08-10 15:10:25 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |       test('pass', async ({ page }) => { | 
					
						
							|  |  |  |         await page.goto('/foobar'); | 
					
						
							|  |  |  |         await expect(page).toHaveURL('/foobar'); | 
					
						
							|  |  |  |         await expect(page).toHaveURL('http://localhost:${port}/foobar'); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       test('fail', async ({ page }) => { | 
					
						
							|  |  |  |         await page.goto('/foobar'); | 
					
						
							|  |  |  |         await expect(page).toHaveURL('/kek', { timeout: 1000 }); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |       `,
 | 
					
						
							|  |  |  |     'playwright.config.ts': `
 | 
					
						
							|  |  |  |       module.exports = { | 
					
						
							|  |  |  |         webServer: { | 
					
						
							|  |  |  |           command: 'node ${JSON.stringify(path.join(__dirname, 'assets', 'simple-server.js'))} ${port}', | 
					
						
							|  |  |  |           port: ${port}, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  |   `,
 | 
					
						
							|  |  |  |   }, { workers: 1 }); | 
					
						
							| 
									
										
										
										
											2023-02-07 15:11:44 -08:00
										 |  |  |   const output = result.output; | 
					
						
							| 
									
										
										
										
											2022-08-10 15:10:25 -07:00
										 |  |  |   expect(output).toContain('expect(page).toHaveURL'); | 
					
						
							|  |  |  |   expect(output).toContain(`Expected string: \"http://localhost:${port}/kek\"`); | 
					
						
							|  |  |  |   expect(result.passed).toBe(1); | 
					
						
							|  |  |  |   expect(result.failed).toBe(1); | 
					
						
							|  |  |  |   expect(result.exitCode).toBe(1); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | test('should respect expect.timeout', async ({ runInlineTest }) => { | 
					
						
							|  |  |  |   const result = await runInlineTest({ | 
					
						
							|  |  |  |     'playwright.config.js': `module.exports = { expect: { timeout: 1000 } }`, | 
					
						
							|  |  |  |     'a.test.ts': `
 | 
					
						
							| 
									
										
										
										
											2023-02-14 19:20:56 -08:00
										 |  |  |       import { test, expect } from '@playwright/test'; | 
					
						
							| 
									
										
										
										
											2022-08-10 15:10:25 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |       test('timeout', async ({ page }) => { | 
					
						
							|  |  |  |         await page.goto('data:text/html,<div>A</div>'); | 
					
						
							| 
									
										
										
										
											2022-11-29 12:54:53 -08:00
										 |  |  |         const error = await expect(page).toHaveURL('data:text/html,<div>B</div>').catch(e => e); | 
					
						
							|  |  |  |         expect(error.message).toContain('expect.toHaveURL with timeout 1000ms'); | 
					
						
							|  |  |  |         expect(error.message).toContain('data:text/html,<div>'); | 
					
						
							| 
									
										
										
										
											2022-08-10 15:10:25 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  |       `,
 | 
					
						
							|  |  |  |   }, { workers: 1 }); | 
					
						
							| 
									
										
										
										
											2022-11-29 12:54:53 -08:00
										 |  |  |   expect(result.exitCode).toBe(0); | 
					
						
							|  |  |  |   expect(result.passed).toBe(1); | 
					
						
							| 
									
										
										
										
											2022-08-10 15:10:25 -07:00
										 |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | test('should log scale the time', async ({ runInlineTest }) => { | 
					
						
							|  |  |  |   const result = await runInlineTest({ | 
					
						
							|  |  |  |     'a.test.ts': `
 | 
					
						
							| 
									
										
										
										
											2023-02-14 19:20:56 -08:00
										 |  |  |       import { test, expect } from '@playwright/test'; | 
					
						
							| 
									
										
										
										
											2022-08-10 15:10:25 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |       test('pass', async ({ page }) => { | 
					
						
							|  |  |  |         await page.setContent('<div id=div>Wrong</div>'); | 
					
						
							|  |  |  |         await expect(page.locator('div')).toHaveText('Text', { timeout: 2000 }); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |       `,
 | 
					
						
							|  |  |  |   }, { workers: 1 }); | 
					
						
							| 
									
										
										
										
											2023-02-07 15:11:44 -08:00
										 |  |  |   const output = result.output; | 
					
						
							| 
									
										
										
										
											2022-08-10 15:10:25 -07:00
										 |  |  |   const tokens = output.split('unexpected value'); | 
					
						
							|  |  |  |   // Log scale: 0, 100, 250, 500, 1000, 1000, should be less than 8.
 | 
					
						
							|  |  |  |   expect(tokens.length).toBeGreaterThan(1); | 
					
						
							|  |  |  |   expect(tokens.length).toBeLessThan(8); | 
					
						
							|  |  |  |   expect(result.passed).toBe(0); | 
					
						
							|  |  |  |   expect(result.exitCode).toBe(1); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | test('should print expected/received before timeout', async ({ runInlineTest }) => { | 
					
						
							|  |  |  |   const result = await runInlineTest({ | 
					
						
							|  |  |  |     'a.test.ts': `
 | 
					
						
							| 
									
										
										
										
											2023-02-14 19:20:56 -08:00
										 |  |  |       import { test, expect } from '@playwright/test'; | 
					
						
							| 
									
										
										
										
											2022-08-10 15:10:25 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |       test('times out waiting for text', async ({ page }) => { | 
					
						
							|  |  |  |         await page.setContent('<div id=node>Text content</div>'); | 
					
						
							|  |  |  |         await expect(page.locator('#node')).toHaveText('Text 2'); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |       `,
 | 
					
						
							|  |  |  |   }, { workers: 1, timeout: 2000 }); | 
					
						
							|  |  |  |   expect(result.exitCode).toBe(1); | 
					
						
							|  |  |  |   expect(result.passed).toBe(0); | 
					
						
							|  |  |  |   expect(result.failed).toBe(1); | 
					
						
							|  |  |  |   expect(result.output).toContain('Test timeout of 2000ms exceeded.'); | 
					
						
							| 
									
										
										
										
											2023-02-07 15:11:44 -08:00
										 |  |  |   expect(result.output).toContain('Expected string: "Text 2"'); | 
					
						
							|  |  |  |   expect(result.output).toContain('Received string: "Text content"'); | 
					
						
							| 
									
										
										
										
											2022-08-10 15:10:25 -07:00
										 |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | test('should print pending operations for toHaveText', async ({ runInlineTest }) => { | 
					
						
							|  |  |  |   const result = await runInlineTest({ | 
					
						
							|  |  |  |     'a.test.ts': `
 | 
					
						
							| 
									
										
										
										
											2023-02-14 19:20:56 -08:00
										 |  |  |       import { test, expect } from '@playwright/test'; | 
					
						
							| 
									
										
										
										
											2022-08-10 15:10:25 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |       test('fail', async ({ page }) => { | 
					
						
							|  |  |  |         await page.setContent('<div id=node>Text content</div>'); | 
					
						
							|  |  |  |         await expect(page.locator('no-such-thing')).toHaveText('Text'); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |       `,
 | 
					
						
							|  |  |  |   }, { workers: 1, timeout: 2000 }); | 
					
						
							|  |  |  |   expect(result.failed).toBe(1); | 
					
						
							|  |  |  |   expect(result.exitCode).toBe(1); | 
					
						
							| 
									
										
										
										
											2023-02-07 15:11:44 -08:00
										 |  |  |   const output = result.output; | 
					
						
							| 
									
										
										
										
											2022-08-10 15:10:25 -07:00
										 |  |  |   expect(output).toContain('Pending operations:'); | 
					
						
							| 
									
										
										
										
											2022-11-16 17:00:42 -08:00
										 |  |  |   expect(output).toContain('expect(received).toHaveText(expected)'); | 
					
						
							| 
									
										
										
										
											2022-08-10 15:10:25 -07:00
										 |  |  |   expect(output).toContain('Expected string: "Text"'); | 
					
						
							|  |  |  |   expect(output).toContain('Received string: ""'); | 
					
						
							| 
									
										
										
										
											2022-11-04 15:19:16 -07:00
										 |  |  |   expect(output).toContain('waiting for locator(\'no-such-thing\')'); | 
					
						
							| 
									
										
										
										
											2022-08-10 15:10:25 -07:00
										 |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-25 15:46:39 -07:00
										 |  |  | test('should print expected/received on Ctrl+C', async ({ interactWithTestRunner }) => { | 
					
						
							| 
									
										
										
										
											2022-08-10 15:10:25 -07:00
										 |  |  |   test.skip(process.platform === 'win32', 'No sending SIGINT on Windows'); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-25 15:46:39 -07:00
										 |  |  |   const testProcess = await interactWithTestRunner({ | 
					
						
							| 
									
										
										
										
											2022-08-10 15:10:25 -07:00
										 |  |  |     'a.test.ts': `
 | 
					
						
							| 
									
										
										
										
											2023-02-14 19:20:56 -08:00
										 |  |  |       import { test, expect } from '@playwright/test'; | 
					
						
							| 
									
										
										
										
											2022-08-10 15:10:25 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |       test('times out waiting for text', async ({ page }) => { | 
					
						
							|  |  |  |         await page.setContent('<div id=node>Text content</div>'); | 
					
						
							|  |  |  |         const promise = expect(page.locator('#node')).toHaveText('Text 2'); | 
					
						
							| 
									
										
										
										
											2022-12-21 14:27:35 -08:00
										 |  |  |         await new Promise(f => setTimeout(f, 1000)); | 
					
						
							| 
									
										
										
										
											2022-08-10 15:10:25 -07:00
										 |  |  |         console.log('\\n%%SEND-SIGINT%%'); | 
					
						
							|  |  |  |         await promise; | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |       `,
 | 
					
						
							| 
									
										
										
										
											2023-07-25 15:46:39 -07:00
										 |  |  |   }, { workers: 1 }); | 
					
						
							|  |  |  |   await testProcess.waitForOutput('%%SEND-SIGINT%%'); | 
					
						
							|  |  |  |   process.kill(testProcess.process.pid!, 'SIGINT'); | 
					
						
							|  |  |  |   const { exitCode } = await testProcess.exited; | 
					
						
							|  |  |  |   expect(exitCode).toBe(130); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const result = parseTestRunnerOutput(testProcess.output); | 
					
						
							| 
									
										
										
										
											2022-08-10 15:10:25 -07:00
										 |  |  |   expect(result.passed).toBe(0); | 
					
						
							|  |  |  |   expect(result.interrupted).toBe(1); | 
					
						
							| 
									
										
										
										
											2023-02-07 15:11:44 -08:00
										 |  |  |   expect(result.output).toContain('Expected string: "Text 2"'); | 
					
						
							|  |  |  |   expect(result.output).toContain('Received string: "Text content"'); | 
					
						
							| 
									
										
										
										
											2022-08-10 15:10:25 -07:00
										 |  |  | }); | 
					
						
							| 
									
										
										
										
											2022-11-16 17:00:42 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-03 15:06:13 -07:00
										 |  |  | test('should not print timed out error message when test times out', async ({ runInlineTest }) => { | 
					
						
							| 
									
										
										
										
											2022-11-16 17:00:42 -08:00
										 |  |  |   const result = await runInlineTest({ | 
					
						
							|  |  |  |     'a.test.ts': `
 | 
					
						
							| 
									
										
										
										
											2023-02-14 19:20:56 -08:00
										 |  |  |       import { test, expect } from '@playwright/test'; | 
					
						
							| 
									
										
										
										
											2022-11-16 17:00:42 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |       test('fail', async ({ page }) => { | 
					
						
							|  |  |  |         await page.setContent('<div id=node>Text content</div>'); | 
					
						
							| 
									
										
										
										
											2023-04-03 15:06:13 -07:00
										 |  |  |         await expect(page.locator('no-such-thing')).toHaveText('hey', { timeout: 5000 }); | 
					
						
							| 
									
										
										
										
											2022-11-16 17:00:42 -08:00
										 |  |  |       }); | 
					
						
							|  |  |  |       `,
 | 
					
						
							| 
									
										
										
										
											2023-04-03 15:06:13 -07:00
										 |  |  |   }, { workers: 1, timeout: 3000 }); | 
					
						
							| 
									
										
										
										
											2022-11-16 17:00:42 -08:00
										 |  |  |   expect(result.failed).toBe(1); | 
					
						
							|  |  |  |   expect(result.exitCode).toBe(1); | 
					
						
							| 
									
										
										
										
											2023-02-07 15:11:44 -08:00
										 |  |  |   const output = result.output; | 
					
						
							| 
									
										
										
										
											2023-04-03 15:06:13 -07:00
										 |  |  |   expect(output).toContain('Test timeout of 3000ms exceeded'); | 
					
						
							|  |  |  |   expect(output).not.toContain('Timed out 5000ms waiting for expect'); | 
					
						
							|  |  |  |   expect(output).toContain('Error: expect(received).toHaveText(expected)'); | 
					
						
							| 
									
										
										
										
											2022-11-16 17:00:42 -08:00
										 |  |  | }); | 
					
						
							| 
									
										
										
										
											2023-01-30 17:24:12 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | test('should not leak long expect message strings', async ({ runInlineTest }) => { | 
					
						
							|  |  |  |   const result = await runInlineTest({ | 
					
						
							|  |  |  |     'a.test.ts': `
 | 
					
						
							| 
									
										
										
										
											2023-02-14 19:20:56 -08:00
										 |  |  |       import { test, expect } from '@playwright/test'; | 
					
						
							| 
									
										
										
										
											2023-01-30 17:24:12 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |       let logs: string = 'Ab'; | 
					
						
							|  |  |  |       const consoleLogWatcher = (msg: ConsoleMessage) => { | 
					
						
							|  |  |  |         if (logs.length < (1<<28)) | 
					
						
							|  |  |  |           logs += logs; | 
					
						
							|  |  |  |         expect(msg.text(), logs).toMatch(/^\\d+$/); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       test('main', async ({ page }) => { | 
					
						
							|  |  |  |         page.on('console', consoleLogWatcher); | 
					
						
							|  |  |  |         await page.evaluate(() => { | 
					
						
							|  |  |  |           for (let i = 0; i < 20; i++) | 
					
						
							|  |  |  |             console.log(i); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |       `,
 | 
					
						
							|  |  |  |   }, { workers: 1 }); | 
					
						
							|  |  |  |   // expect(result.output).toBe('');
 | 
					
						
							|  |  |  |   expect(result.failed).toBe(0); | 
					
						
							|  |  |  |   expect(result.exitCode).toBe(0); | 
					
						
							|  |  |  | }); |