| 
									
										
										
										
											2021-04-01 16:35:26 -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. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-29 11:11:32 -07:00
										 |  |  | import * as fs from 'fs'; | 
					
						
							|  |  |  | import * as os from 'os'; | 
					
						
							| 
									
										
										
										
											2022-04-06 13:57:14 -08:00
										 |  |  | import type { PageTestFixtures, PageWorkerFixtures } from '../page/pageTestApi'; | 
					
						
							| 
									
										
										
										
											2021-10-28 07:31:30 -08:00
										 |  |  | import * as path from 'path'; | 
					
						
							|  |  |  | import type { BrowserContext, BrowserContextOptions, BrowserType, Page } from 'playwright-core'; | 
					
						
							| 
									
										
										
										
											2022-04-07 19:18:22 -08:00
										 |  |  | import { removeFolders } from '../../packages/playwright-core/lib/utils/fileUtils'; | 
					
						
							| 
									
										
										
										
											2021-10-27 07:28:53 -08:00
										 |  |  | import { baseTest } from './baseTest'; | 
					
						
							| 
									
										
										
										
											2022-12-07 14:36:32 -08:00
										 |  |  | import { type RemoteServerOptions, type PlaywrightServer, RunServer, RemoteServer } from './remoteServer'; | 
					
						
							| 
									
										
										
										
											2022-09-20 18:41:51 -07:00
										 |  |  | import type { Log } from '../../packages/trace/src/har'; | 
					
						
							| 
									
										
										
										
											2022-07-01 12:49:43 -07:00
										 |  |  | import { parseHar } from '../config/utils'; | 
					
						
							| 
									
										
										
										
											2021-04-29 11:11:32 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-28 07:31:30 -08:00
										 |  |  | export type BrowserTestWorkerFixtures = PageWorkerFixtures & { | 
					
						
							| 
									
										
										
										
											2021-05-16 19:58:26 -07:00
										 |  |  |   browserVersion: string; | 
					
						
							| 
									
										
										
										
											2022-03-01 02:32:40 -07:00
										 |  |  |   defaultSameSiteCookieValue: string; | 
					
						
							| 
									
										
										
										
											2022-08-03 16:55:19 -07:00
										 |  |  |   allowsThirdParty | 
					
						
							| 
									
										
										
										
											2021-10-28 07:31:30 -08:00
										 |  |  |   browserMajorVersion: number; | 
					
						
							|  |  |  |   browserType: BrowserType; | 
					
						
							|  |  |  |   isAndroid: boolean; | 
					
						
							|  |  |  |   isElectron: boolean; | 
					
						
							| 
									
										
										
										
											2021-04-29 11:11:32 -07:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2021-10-26 12:45:53 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-07 14:36:32 -08:00
										 |  |  | interface StartRemoteServer { | 
					
						
							|  |  |  |   (kind: 'run-server' | 'launchServer'): Promise<PlaywrightServer>; | 
					
						
							|  |  |  |   (kind: 'launchServer', options?: RemoteServerOptions): Promise<RemoteServer>; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-28 07:31:30 -08:00
										 |  |  | type BrowserTestTestFixtures = PageTestFixtures & { | 
					
						
							| 
									
										
										
										
											2021-05-16 19:58:26 -07:00
										 |  |  |   createUserDataDir: () => Promise<string>; | 
					
						
							|  |  |  |   launchPersistent: (options?: Parameters<BrowserType['launchPersistentContext']>[1]) => Promise<{ context: BrowserContext, page: Page }>; | 
					
						
							| 
									
										
										
										
											2022-12-07 14:36:32 -08:00
										 |  |  |   startRemoteServer: StartRemoteServer; | 
					
						
							| 
									
										
										
										
											2021-05-16 19:58:26 -07:00
										 |  |  |   contextFactory: (options?: BrowserContextOptions) => Promise<BrowserContext>; | 
					
						
							| 
									
										
										
										
											2022-07-01 12:49:43 -07:00
										 |  |  |   pageWithHar(options?: { outputPath?: string, content?: 'embed' | 'attach' | 'omit', omitContent?: boolean }): Promise<{ context: BrowserContext, page: Page, getLog: () => Promise<Log>, getZip: () => Promise<Map<string, Buffer>> }> | 
					
						
							| 
									
										
										
										
											2021-05-16 19:58:26 -07:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-28 07:31:30 -08:00
										 |  |  | const test = baseTest.extend<BrowserTestTestFixtures, BrowserTestWorkerFixtures>({ | 
					
						
							|  |  |  |   browserVersion: [async ({ browser }, run) => { | 
					
						
							|  |  |  |     await run(browser.version()); | 
					
						
							| 
									
										
										
										
											2022-08-18 20:12:33 +02:00
										 |  |  |   }, { scope: 'worker' }], | 
					
						
							| 
									
										
										
										
											2021-10-27 07:28:53 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-04 14:59:48 -07:00
										 |  |  |   browserType: [async ({ playwright, browserName, mode }, run) => { | 
					
						
							|  |  |  |     test.skip(mode.startsWith('service')); | 
					
						
							| 
									
										
										
										
											2022-01-28 10:51:55 -08:00
										 |  |  |     await run(playwright[browserName]); | 
					
						
							| 
									
										
										
										
											2022-08-18 20:12:33 +02:00
										 |  |  |   }, { scope: 'worker' }], | 
					
						
							| 
									
										
										
										
											2021-04-29 11:11:32 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-03 16:55:19 -07:00
										 |  |  |   allowsThirdParty: [async ({ browserName, browserMajorVersion, channel }, run) => { | 
					
						
							| 
									
										
										
										
											2022-08-10 02:00:59 -07:00
										 |  |  |     if (browserName === 'firefox' && !channel) | 
					
						
							|  |  |  |       await run(browserMajorVersion >= 103); | 
					
						
							|  |  |  |     else if (browserName === 'firefox' && channel === 'firefox-beta') | 
					
						
							| 
									
										
										
										
											2023-02-02 07:14:18 -08:00
										 |  |  |       await run(browserMajorVersion < 103 || browserMajorVersion >= 110); | 
					
						
							| 
									
										
										
										
											2022-08-10 02:00:59 -07:00
										 |  |  |     else | 
					
						
							| 
									
										
										
										
											2022-08-03 16:55:19 -07:00
										 |  |  |       await run(false); | 
					
						
							| 
									
										
										
										
											2022-08-18 20:12:33 +02:00
										 |  |  |   }, { scope: 'worker' }], | 
					
						
							| 
									
										
										
										
											2022-08-03 16:55:19 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   defaultSameSiteCookieValue: [async ({ browserName, browserMajorVersion, channel }, run) => { | 
					
						
							| 
									
										
										
										
											2022-07-05 15:47:35 -07:00
										 |  |  |     if (browserName === 'chromium') | 
					
						
							|  |  |  |       await run('Lax'); | 
					
						
							|  |  |  |     else if (browserName === 'webkit') | 
					
						
							|  |  |  |       await run('None'); | 
					
						
							| 
									
										
										
										
											2022-08-03 16:55:19 -07:00
										 |  |  |     else if (browserName === 'firefox' && channel === 'firefox-beta') | 
					
						
							| 
									
										
										
										
											2023-02-02 07:14:18 -08:00
										 |  |  |       await run(browserMajorVersion >= 103 && browserMajorVersion < 110 ? 'Lax' : 'None'); | 
					
						
							| 
									
										
										
										
											2022-08-03 16:55:19 -07:00
										 |  |  |     else if (browserName === 'firefox' && channel !== 'firefox-beta') | 
					
						
							|  |  |  |       await run(browserMajorVersion >= 103 ? 'None' : 'Lax'); | 
					
						
							| 
									
										
										
										
											2022-07-05 15:47:35 -07:00
										 |  |  |     else | 
					
						
							|  |  |  |       throw new Error('unknown browser - ' + browserName); | 
					
						
							| 
									
										
										
										
											2022-08-18 20:12:33 +02:00
										 |  |  |   }, { scope: 'worker' }], | 
					
						
							| 
									
										
										
										
											2022-03-01 01:17:33 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-28 07:31:30 -08:00
										 |  |  |   browserMajorVersion: [async ({ browserVersion }, run) => { | 
					
						
							|  |  |  |     await run(Number(browserVersion.split('.')[0])); | 
					
						
							| 
									
										
										
										
											2022-08-18 20:12:33 +02:00
										 |  |  |   }, { scope: 'worker' }], | 
					
						
							| 
									
										
										
										
											2021-04-29 11:11:32 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-18 20:12:33 +02:00
										 |  |  |   isAndroid: [false, { scope: 'worker' }], | 
					
						
							|  |  |  |   isElectron: [false, { scope: 'worker' }], | 
					
						
							| 
									
										
										
										
											2022-09-07 20:09:22 +02:00
										 |  |  |   isWebView2: [false, { scope: 'worker' }], | 
					
						
							| 
									
										
										
										
											2021-10-28 07:31:30 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   contextFactory: async ({ _contextFactory }: any, run) => { | 
					
						
							|  |  |  |     await run(_contextFactory); | 
					
						
							|  |  |  |   }, | 
					
						
							| 
									
										
										
										
											2021-10-07 23:01:08 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-25 16:47:04 -07:00
										 |  |  |   createUserDataDir: async ({ mode }, run) => { | 
					
						
							|  |  |  |     test.skip(mode.startsWith('service')); | 
					
						
							| 
									
										
										
										
											2021-05-16 19:58:26 -07:00
										 |  |  |     const dirs: string[] = []; | 
					
						
							| 
									
										
										
										
											2021-04-29 11:11:32 -07:00
										 |  |  |     // We do not put user data dir in testOutputPath,
 | 
					
						
							|  |  |  |     // because we do not want to upload them as test result artifacts.
 | 
					
						
							|  |  |  |     //
 | 
					
						
							|  |  |  |     // Additionally, it is impossible to upload user data dir after test run:
 | 
					
						
							|  |  |  |     // - Firefox removes lock file later, presumably from another watchdog process?
 | 
					
						
							|  |  |  |     // - WebKit has circular symlinks that makes CI go crazy.
 | 
					
						
							| 
									
										
										
										
											2021-05-16 19:58:26 -07:00
										 |  |  |     await run(async () => { | 
					
						
							| 
									
										
										
										
											2021-06-03 09:55:33 -07:00
										 |  |  |       const dir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'playwright-test-')); | 
					
						
							| 
									
										
										
										
											2021-05-16 19:58:26 -07:00
										 |  |  |       dirs.push(dir); | 
					
						
							|  |  |  |       return dir; | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     await removeFolders(dirs); | 
					
						
							|  |  |  |   }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-04 14:59:48 -07:00
										 |  |  |   launchPersistent: async ({ createUserDataDir, browserType }, run) => { | 
					
						
							| 
									
										
										
										
											2021-05-16 19:58:26 -07:00
										 |  |  |     let persistentContext: BrowserContext | undefined; | 
					
						
							|  |  |  |     await run(async options => { | 
					
						
							|  |  |  |       if (persistentContext) | 
					
						
							| 
									
										
										
										
											2021-10-28 07:31:30 -08:00
										 |  |  |         throw new Error('can only launch one persistent context'); | 
					
						
							| 
									
										
										
										
											2021-05-16 19:58:26 -07:00
										 |  |  |       const userDataDir = await createUserDataDir(); | 
					
						
							| 
									
										
										
										
											2021-10-27 18:00:06 -08:00
										 |  |  |       persistentContext = await browserType.launchPersistentContext(userDataDir, { ...options }); | 
					
						
							| 
									
										
										
										
											2021-05-16 19:58:26 -07:00
										 |  |  |       const page = persistentContext.pages()[0]; | 
					
						
							|  |  |  |       return { context: persistentContext, page }; | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     if (persistentContext) | 
					
						
							|  |  |  |       await persistentContext.close(); | 
					
						
							|  |  |  |   }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-04 14:59:48 -07:00
										 |  |  |   startRemoteServer: async ({ childProcess, browserType }, run) => { | 
					
						
							| 
									
										
										
										
											2022-12-07 14:36:32 -08:00
										 |  |  |     let server: PlaywrightServer | undefined; | 
					
						
							|  |  |  |     const fn = async (kind: 'launchServer' | 'run-server', options?: RemoteServerOptions) => { | 
					
						
							|  |  |  |       if (server) | 
					
						
							| 
									
										
										
										
											2021-05-16 19:58:26 -07:00
										 |  |  |         throw new Error('can only start one remote server'); | 
					
						
							| 
									
										
										
										
											2022-12-07 14:36:32 -08:00
										 |  |  |       if (kind === 'launchServer') { | 
					
						
							|  |  |  |         const remoteServer = new RemoteServer(); | 
					
						
							|  |  |  |         await remoteServer._start(childProcess, browserType, options); | 
					
						
							|  |  |  |         server = remoteServer; | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         const runServer = new RunServer(); | 
					
						
							| 
									
										
										
										
											2023-05-23 10:56:37 -07:00
										 |  |  |         await runServer.start(childProcess); | 
					
						
							| 
									
										
										
										
											2022-12-07 14:36:32 -08:00
										 |  |  |         server = runServer; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       return server; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     await run(fn as any); | 
					
						
							|  |  |  |     if (server) { | 
					
						
							|  |  |  |       await server.close(); | 
					
						
							| 
									
										
										
										
											2022-02-09 17:00:33 -08:00
										 |  |  |       // Give any connected browsers a chance to disconnect to avoid
 | 
					
						
							|  |  |  |       // poisoning next test with quasy-alive browsers.
 | 
					
						
							|  |  |  |       await new Promise(f => setTimeout(f, 1000)); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-05-16 19:58:26 -07:00
										 |  |  |   }, | 
					
						
							| 
									
										
										
										
											2022-07-01 12:49:43 -07:00
										 |  |  |   pageWithHar: async ({ contextFactory }, use, testInfo) => { | 
					
						
							|  |  |  |     const pageWithHar = async (options: { outputPath?: string, content?: 'embed' | 'attach' | 'omit', omitContent?: boolean } = {}) => { | 
					
						
							|  |  |  |       const harPath = testInfo.outputPath(options.outputPath || 'test.har'); | 
					
						
							|  |  |  |       const context = await contextFactory({ recordHar: { path: harPath, content: options.content, omitContent: options.omitContent }, ignoreHTTPSErrors: true }); | 
					
						
							|  |  |  |       const page = await context.newPage(); | 
					
						
							|  |  |  |       return { | 
					
						
							|  |  |  |         page, | 
					
						
							|  |  |  |         context, | 
					
						
							|  |  |  |         getLog: async () => { | 
					
						
							|  |  |  |           await context.close(); | 
					
						
							|  |  |  |           return JSON.parse(fs.readFileSync(harPath).toString())['log'] as Log; | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         getZip: async () => { | 
					
						
							|  |  |  |           await context.close(); | 
					
						
							|  |  |  |           return parseHar(harPath); | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     await use(pageWithHar); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2021-10-28 07:31:30 -08:00
										 |  |  | }); | 
					
						
							| 
									
										
										
										
											2021-05-16 19:58:26 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | export const playwrightTest = test; | 
					
						
							|  |  |  | export const browserTest = test; | 
					
						
							|  |  |  | export const contextTest = test; | 
					
						
							| 
									
										
										
										
											2021-04-29 11:11:32 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-11 10:52:17 -04:00
										 |  |  | export { expect } from '@playwright/test'; |