feat(cdp): replace wsEndpoint with protocol neutral endpointURL (#6141)
This commit is contained in:
		
							parent
							
								
									53d50f9b72
								
							
						
					
					
						commit
						63d0d466e3
					
				|  | @ -116,7 +116,7 @@ Connecting over the Chrome DevTools Protocol is only supported for Chromium-base | |||
| ### param: BrowserType.connectOverCDP.params | ||||
| * langs: js | ||||
| - `params` <[Object]> | ||||
|   - `wsEndpoint` <[string]> A CDP websocket endpoint to connect to. | ||||
|   - `endpointURL` <[string]> A CDP websocket endpoint or http url to connect to. For example `http://localhost:9222/` or `ws://127.0.0.1:9222/devtools/browser/387adf4c-243f-4051-a181-46798f4a46f4`. | ||||
|   - `slowMo` <[float]> Slows down Playwright operations by the specified amount of milliseconds. Useful so that you | ||||
|     can see what is going on. Defaults to 0. | ||||
|   - `logger` <[Logger]> Logger sink for Playwright logging. Optional. | ||||
|  |  | |||
|  | @ -58,11 +58,11 @@ page.navigate("https://www.w3.org/"); | |||
| playwright.close(); | ||||
| ``` | ||||
| 
 | ||||
| ### param: BrowserType.connectOverCDP.wsEndpoint | ||||
| ### param: BrowserType.connectOverCDP.endpointURL | ||||
| * langs: java | ||||
| - `wsEndpoint` <[string]> | ||||
| - `endpointURL` <[string]> | ||||
| 
 | ||||
| A CDP websocket endpoint to connect to. | ||||
| A CDP websocket endpoint or http url to connect to. For example `http://localhost:9222/` or `ws://127.0.0.1:9222/devtools/browser/387adf4c-243f-4051-a181-46798f4a46f4`. | ||||
| 
 | ||||
| ### param: BrowserContext.waitForPage.callback = %%-java-wait-for-event-callback-%% | ||||
| 
 | ||||
|  |  | |||
|  | @ -187,14 +187,16 @@ export class BrowserType extends ChannelOwner<channels.BrowserTypeChannel, chann | |||
|     }, logger); | ||||
|   } | ||||
| 
 | ||||
|   async connectOverCDP(params: ConnectOptions): Promise<Browser> { | ||||
|   async connectOverCDP(params: api.ConnectOverCDPOptions): Promise<Browser> | ||||
|   async connectOverCDP(params: api.ConnectOptions): Promise<Browser> | ||||
|   async connectOverCDP(params: api.ConnectOverCDPOptions | api.ConnectOptions): Promise<Browser> { | ||||
|     if (this.name() !== 'chromium') | ||||
|       throw new Error('Connecting over CDP is only supported in Chromium.'); | ||||
|     const logger = params.logger; | ||||
|     return this._wrapApiCall('browserType.connectOverCDP', async (channel: channels.BrowserTypeChannel) => { | ||||
|       const result = await channel.connectOverCDP({ | ||||
|         sdkLanguage: 'javascript', | ||||
|         wsEndpoint: params.wsEndpoint, | ||||
|         endpointURL: 'endpointURL' in params ? params.endpointURL : params.wsEndpoint, | ||||
|         slowMo: params.slowMo, | ||||
|         timeout: params.timeout | ||||
|       }); | ||||
|  |  | |||
|  | @ -40,7 +40,7 @@ export class BrowserTypeDispatcher extends Dispatcher<BrowserType, channels.Brow | |||
|   } | ||||
| 
 | ||||
|   async connectOverCDP(params: channels.BrowserTypeConnectOverCDPParams, metadata: CallMetadata): Promise<channels.BrowserTypeConnectOverCDPResult> { | ||||
|     const browser = await this._object.connectOverCDP(metadata, params.wsEndpoint, params, params.timeout); | ||||
|     const browser = await this._object.connectOverCDP(metadata, params.endpointURL, params, params.timeout); | ||||
|     return { | ||||
|       browser: new BrowserDispatcher(this._scope, browser), | ||||
|       defaultContext: browser._defaultContext ? new BrowserContextDispatcher(this._scope, browser._defaultContext) : undefined, | ||||
|  |  | |||
|  | @ -408,7 +408,7 @@ export type BrowserTypeLaunchPersistentContextResult = { | |||
| }; | ||||
| export type BrowserTypeConnectOverCDPParams = { | ||||
|   sdkLanguage: string, | ||||
|   wsEndpoint: string, | ||||
|   endpointURL: string, | ||||
|   slowMo?: number, | ||||
|   timeout?: number, | ||||
| }; | ||||
|  |  | |||
|  | @ -422,7 +422,7 @@ BrowserType: | |||
|     connectOverCDP: | ||||
|       parameters: | ||||
|         sdkLanguage: string | ||||
|         wsEndpoint: string | ||||
|         endpointURL: string | ||||
|         slowMo: number? | ||||
|         timeout: number? | ||||
|       returns: | ||||
|  |  | |||
|  | @ -249,7 +249,7 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme { | |||
|   }); | ||||
|   scheme.BrowserTypeConnectOverCDPParams = tObject({ | ||||
|     sdkLanguage: tString, | ||||
|     wsEndpoint: tString, | ||||
|     endpointURL: tString, | ||||
|     slowMo: tOptional(tNumber), | ||||
|     timeout: tOptional(tNumber), | ||||
|   }); | ||||
|  |  | |||
|  | @ -248,7 +248,7 @@ export abstract class BrowserType extends SdkObject { | |||
|     return { browserProcess, downloadsPath, transport }; | ||||
|   } | ||||
| 
 | ||||
|   async connectOverCDP(metadata: CallMetadata, wsEndpoint: string, options: { slowMo?: number, sdkLanguage: string }, timeout?: number): Promise<Browser> { | ||||
|   async connectOverCDP(metadata: CallMetadata, endpointURL: string, options: { slowMo?: number, sdkLanguage: string }, timeout?: number): Promise<Browser> { | ||||
|     throw new Error('CDP connections are only supported by Chromium'); | ||||
|   } | ||||
| 
 | ||||
|  |  | |||
|  | @ -32,6 +32,7 @@ import { TimeoutSettings } from '../../utils/timeoutSettings'; | |||
| import { helper } from '../helper'; | ||||
| import { CallMetadata } from '../instrumentation'; | ||||
| import { findChromiumChannel } from './findChromiumChannel'; | ||||
| import http from 'http'; | ||||
| 
 | ||||
| export class Chromium extends BrowserType { | ||||
|   private _devtools: CRDevTools | undefined; | ||||
|  | @ -49,12 +50,12 @@ export class Chromium extends BrowserType { | |||
|     return super.executablePath(options); | ||||
|   } | ||||
| 
 | ||||
|   async connectOverCDP(metadata: CallMetadata, wsEndpoint: string, options: { slowMo?: number, sdkLanguage: string }, timeout?: number) { | ||||
|   async connectOverCDP(metadata: CallMetadata, endpointURL: string, options: { slowMo?: number, sdkLanguage: string }, timeout?: number) { | ||||
|     const controller = new ProgressController(metadata, this); | ||||
|     controller.setLogName('browser'); | ||||
|     const browserLogsCollector = new RecentLogsCollector(); | ||||
|     return controller.run(async progress => { | ||||
|       const chromeTransport = await WebSocketTransport.connect(progress, wsEndpoint); | ||||
|       const chromeTransport = await WebSocketTransport.connect(progress, await urlToWSEndpoint(endpointURL)); | ||||
|       const browserProcess: BrowserProcess = { | ||||
|         close: async () => { | ||||
|           await chromeTransport.closeAndWait(); | ||||
|  | @ -192,3 +193,17 @@ const DEFAULT_ARGS = [ | |||
|   '--password-store=basic', | ||||
|   '--use-mock-keychain', | ||||
| ]; | ||||
| 
 | ||||
| async function urlToWSEndpoint(endpointURL: string) { | ||||
|   if (endpointURL.startsWith('ws')) | ||||
|     return endpointURL; | ||||
|   const httpURL = endpointURL.endsWith('/') ? `${endpointURL}json/version/` : `${endpointURL}/json/version/`; | ||||
|   const json = await new Promise<string>((resolve, reject) => { | ||||
|     http.get(httpURL, resp => { | ||||
|       let data = ''; | ||||
|       resp.on('data', chunk => data += chunk); | ||||
|       resp.on('end', () => resolve(data)); | ||||
|     }).on('error', reject); | ||||
|   }); | ||||
|   return JSON.parse(json).webSocketDebuggerUrl; | ||||
| } | ||||
|  |  | |||
|  | @ -33,6 +33,6 @@ test('browserType.name should work', async ({browserType, browserName}) => { | |||
| test('should throw when trying to connect with not-chromium', async ({ browserType, browserName }) => { | ||||
|   test.skip(browserName === 'chromium'); | ||||
| 
 | ||||
|   const error = await browserType.connectOverCDP({wsEndpoint: 'foo'}).catch(e => e); | ||||
|   const error = await browserType.connectOverCDP({endpointURL: 'ws://foo'}).catch(e => e); | ||||
|   expect(error.message).toBe('Connecting over CDP is only supported in Chromium.'); | ||||
| }); | ||||
|  |  | |||
|  | @ -112,15 +112,8 @@ playwrightTest.describe('chromium', () => { | |||
|       args: ['--remote-debugging-port=' + port] | ||||
|     }); | ||||
|     try { | ||||
|       const json = await new Promise<string>((resolve, reject) => { | ||||
|         http.get(`http://localhost:${port}/json/version/`, resp => { | ||||
|           let data = ''; | ||||
|           resp.on('data', chunk => data += chunk); | ||||
|           resp.on('end', () => resolve(data)); | ||||
|         }).on('error', reject); | ||||
|       }); | ||||
|       const cdpBrowser = await browserType.connectOverCDP({ | ||||
|         wsEndpoint: JSON.parse(json).webSocketDebuggerUrl, | ||||
|         endpointURL: `http://localhost:${port}/`, | ||||
|       }); | ||||
|       const contexts = cdpBrowser.contexts(); | ||||
|       expect(contexts.length).toBe(1); | ||||
|  | @ -137,18 +130,11 @@ playwrightTest.describe('chromium', () => { | |||
|       args: ['--remote-debugging-port=' + port] | ||||
|     }); | ||||
|     try { | ||||
|       const json = await new Promise<string>((resolve, reject) => { | ||||
|         http.get(`http://localhost:${port}/json/version/`, resp => { | ||||
|           let data = ''; | ||||
|           resp.on('data', chunk => data += chunk); | ||||
|           resp.on('end', () => resolve(data)); | ||||
|         }).on('error', reject); | ||||
|       }); | ||||
|       const cdpBrowser1 = await browserType.connectOverCDP({ | ||||
|         wsEndpoint: JSON.parse(json).webSocketDebuggerUrl, | ||||
|         endpointURL: `http://localhost:${port}/`, | ||||
|       }); | ||||
|       const cdpBrowser2 = await browserType.connectOverCDP({ | ||||
|         wsEndpoint: JSON.parse(json).webSocketDebuggerUrl, | ||||
|         endpointURL: `http://localhost:${port}/`, | ||||
|       }); | ||||
|       const contexts1 = cdpBrowser1.contexts(); | ||||
|       expect(contexts1.length).toBe(1); | ||||
|  | @ -179,15 +165,8 @@ playwrightTest.describe('chromium', () => { | |||
|       args: ['--remote-debugging-port=' + port] | ||||
|     }); | ||||
|     try { | ||||
|       const json = await new Promise<string>((resolve, reject) => { | ||||
|         http.get(`http://localhost:${port}/json/version/`, resp => { | ||||
|           let data = ''; | ||||
|           resp.on('data', chunk => data += chunk); | ||||
|           resp.on('end', () => resolve(data)); | ||||
|         }).on('error', reject); | ||||
|       }); | ||||
|       const cdpBrowser1 = await browserType.connectOverCDP({ | ||||
|         wsEndpoint: JSON.parse(json).webSocketDebuggerUrl, | ||||
|         endpointURL: `http://localhost:${port}`, | ||||
|       }); | ||||
|       const context = cdpBrowser1.contexts()[0]; | ||||
|       const page = await cdpBrowser1.contexts()[0].newPage(); | ||||
|  | @ -199,7 +178,7 @@ playwrightTest.describe('chromium', () => { | |||
|       await cdpBrowser1.close(); | ||||
| 
 | ||||
|       const cdpBrowser2 = await browserType.connectOverCDP({ | ||||
|         wsEndpoint: JSON.parse(json).webSocketDebuggerUrl, | ||||
|         endpointURL: `http://localhost:${port}`, | ||||
|       }); | ||||
|       const context2 = cdpBrowser2.contexts()[0]; | ||||
|       expect(context2.serviceWorkers().length).toBe(1); | ||||
|  | @ -208,4 +187,36 @@ playwrightTest.describe('chromium', () => { | |||
|       await browserServer.close(); | ||||
|     } | ||||
|   }); | ||||
|   playwrightTest('should connect over a ws endpoint', async ({browserType, browserOptions, server}, testInfo) => { | ||||
|     const port = 9339 + testInfo.workerIndex; | ||||
|     const browserServer = await browserType.launch({ | ||||
|       ...browserOptions, | ||||
|       args: ['--remote-debugging-port=' + port] | ||||
|     }); | ||||
|     try { | ||||
|       const json = await new Promise<string>((resolve, reject) => { | ||||
|         http.get(`http://localhost:${port}/json/version/`, resp => { | ||||
|           let data = ''; | ||||
|           resp.on('data', chunk => data += chunk); | ||||
|           resp.on('end', () => resolve(data)); | ||||
|         }).on('error', reject); | ||||
|       }); | ||||
|       const cdpBrowser = await browserType.connectOverCDP({ | ||||
|         endpointURL: JSON.parse(json).webSocketDebuggerUrl, | ||||
|       }); | ||||
|       const contexts = cdpBrowser.contexts(); | ||||
|       expect(contexts.length).toBe(1); | ||||
|       await cdpBrowser.close(); | ||||
| 
 | ||||
|       // also connect with the depercreated wsEndpoint option
 | ||||
|       const cdpBrowser2 = await browserType.connectOverCDP({ | ||||
|         wsEndpoint: JSON.parse(json).webSocketDebuggerUrl, | ||||
|       }); | ||||
|       const contexts2 = cdpBrowser.contexts(); | ||||
|       expect(contexts2.length).toBe(1); | ||||
|       await cdpBrowser2.close(); | ||||
|     } finally { | ||||
|       await browserServer.close(); | ||||
|     } | ||||
|   }); | ||||
| }); | ||||
|  |  | |||
|  | @ -6460,13 +6460,6 @@ export interface ElementHandle<T=Node> extends JSHandle<T> { | |||
|  *  | ||||
|  */ | ||||
| export interface BrowserType<Unused = {}> { | ||||
| 
 | ||||
|   /** | ||||
|    * This methods attaches Playwright to an existing browser instance. | ||||
|    * @param params  | ||||
|    */ | ||||
|   connect(params: ConnectOptions): Promise<Browser>; | ||||
| 
 | ||||
|   /** | ||||
|    * This methods attaches Playwright to an existing browser instance using the Chrome DevTools Protocol. | ||||
|    *  | ||||
|  | @ -6476,29 +6469,17 @@ export interface BrowserType<Unused = {}> { | |||
|    * > NOTE: Connecting over the Chrome DevTools Protocol is only supported for Chromium-based browsers. | ||||
|    * @param params  | ||||
|    */ | ||||
|   connectOverCDP(params: { | ||||
|   connectOverCDP(options: ConnectOverCDPOptions): Promise<Browser>; | ||||
|   /** | ||||
|      * A CDP websocket endpoint to connect to. | ||||
|    * Option `wsEndpoint` is deprecated. Instead use `endpointURL`. | ||||
|    * @deprecated | ||||
|    */ | ||||
|     wsEndpoint: string; | ||||
| 
 | ||||
|   connectOverCDP(options: ConnectOptions): Promise<Browser>; | ||||
|   /** | ||||
|      * Slows down Playwright operations by the specified amount of milliseconds. Useful so that you can see what is going on. | ||||
|      * Defaults to 0. | ||||
|    * This methods attaches Playwright to an existing browser instance. | ||||
|    * @param params  | ||||
|    */ | ||||
|     slowMo?: number; | ||||
| 
 | ||||
|     /** | ||||
|      * Logger sink for Playwright logging. Optional. | ||||
|      */ | ||||
|     logger?: Logger; | ||||
| 
 | ||||
|     /** | ||||
|      * Maximum time in milliseconds to wait for the connection to be established. Defaults to `30000` (30 seconds). Pass `0` to | ||||
|      * disable timeout. | ||||
|      */ | ||||
|     timeout?: number; | ||||
|   }): Promise<Browser>; | ||||
|   connect(params: ConnectOptions): Promise<Browser>; | ||||
| 
 | ||||
|   /** | ||||
|    * A path where Playwright expects to find a bundled browser executable. | ||||
|  | @ -10687,6 +10668,31 @@ export interface LaunchOptions { | |||
|   timeout?: number; | ||||
| } | ||||
| 
 | ||||
| export interface ConnectOverCDPOptions { | ||||
|   /** | ||||
|    * A CDP websocket endpoint or http url to connect to. For example `http://localhost:9222/` or | ||||
|    * `ws://127.0.0.1:9222/devtools/browser/387adf4c-243f-4051-a181-46798f4a46f4`. | ||||
|    */ | ||||
|   endpointURL: string; | ||||
| 
 | ||||
|   /** | ||||
|    * Slows down Playwright operations by the specified amount of milliseconds. Useful so that you can see what is going on. | ||||
|    * Defaults to 0. | ||||
|    */ | ||||
|   slowMo?: number; | ||||
| 
 | ||||
|   /** | ||||
|    * Logger sink for Playwright logging. Optional. | ||||
|    */ | ||||
|   logger?: Logger; | ||||
| 
 | ||||
|   /** | ||||
|    * Maximum time in milliseconds to wait for the connection to be established. Defaults to `30000` (30 seconds). Pass `0` to | ||||
|    * disable timeout. | ||||
|    */ | ||||
|   timeout?: number; | ||||
| } | ||||
| 
 | ||||
| export interface ConnectOptions { | ||||
|   /** | ||||
|    * A browser websocket endpoint to connect to. | ||||
|  |  | |||
|  | @ -1,6 +1,7 @@ | |||
| { | ||||
|   "BrowserTypeLaunchOptions": "LaunchOptions", | ||||
|   "BrowserTypeConnectParams": "ConnectOptions", | ||||
|   "BrowserTypeConnectOverCDPParams": "ConnectOverCDPOptions", | ||||
|   "BrowserContextCookies": "Cookie", | ||||
|   "BrowserNewContextOptions": "BrowserContextOptions", | ||||
|   "BrowserNewContextOptionsViewport": "ViewportSize", | ||||
|  |  | |||
|  | @ -141,7 +141,12 @@ export interface ElementHandle<T=Node> extends JSHandle<T> { | |||
| } | ||||
| 
 | ||||
| export interface BrowserType<Unused = {}> { | ||||
| 
 | ||||
|   connectOverCDP(options: ConnectOverCDPOptions): Promise<Browser>; | ||||
|   /** | ||||
|    * Option `wsEndpoint` is deprecated. Instead use `endpointURL`. | ||||
|    * @deprecated | ||||
|    */ | ||||
|   connectOverCDP(options: ConnectOptions): Promise<Browser>; | ||||
| } | ||||
| 
 | ||||
| export interface CDPSession { | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue