mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
feat(test runner): support connectOptions (#11919)
This allows to specify `connectOptions` in the config that switch built-in `browser` to be remotely connected.
This commit is contained in:
parent
5881a46ecf
commit
19368e93af
@ -110,6 +110,13 @@ Learn more about [various timeouts](./test-timeouts.md).
|
|||||||
|
|
||||||
## property: TestOptions.colorScheme = %%-context-option-colorscheme-%%
|
## property: TestOptions.colorScheme = %%-context-option-colorscheme-%%
|
||||||
|
|
||||||
|
## property: TestOptions.connectOptions
|
||||||
|
- type: <[void]|[Object]>
|
||||||
|
- `wsEndpoint` <[string]> A browser websocket endpoint to connect to.
|
||||||
|
- `headers` <[void]|[Object]<[string], [string]>> Additional HTTP headers to be sent with web socket connect request. Optional.
|
||||||
|
|
||||||
|
When connect options are specified, default [`property: Fixtures.browser`], [`property: Fixtures.context`] and [`property: Fixtures.page`] use the remote browser instead of launching a browser locally, and any launch options like [`property: TestOptions.headless`] or [`property: TestOptions.channel`] are ignored.
|
||||||
|
|
||||||
## property: TestOptions.contextOptions
|
## property: TestOptions.contextOptions
|
||||||
- type: <[Object]>
|
- type: <[Object]>
|
||||||
|
|
||||||
|
|||||||
@ -63,6 +63,7 @@ export class BrowserTypeDispatcher extends Dispatcher<BrowserType, channels.Brow
|
|||||||
maxPayload: 256 * 1024 * 1024, // 256Mb,
|
maxPayload: 256 * 1024 * 1024, // 256Mb,
|
||||||
handshakeTimeout: params.timeout,
|
handshakeTimeout: params.timeout,
|
||||||
headers: paramsHeaders,
|
headers: paramsHeaders,
|
||||||
|
followRedirects: true,
|
||||||
});
|
});
|
||||||
const pipe = new JsonPipeDispatcher(this._scope);
|
const pipe = new JsonPipeDispatcher(this._scope);
|
||||||
const openPromise = new ManualPromise<{ pipe: JsonPipeDispatcher }>();
|
const openPromise = new ManualPromise<{ pipe: JsonPipeDispatcher }>();
|
||||||
|
|||||||
@ -70,6 +70,7 @@ export const test = _baseTest.extend<TestFixtures, WorkerFixtures>({
|
|||||||
headless: [ undefined, { scope: 'worker', option: true } ],
|
headless: [ undefined, { scope: 'worker', option: true } ],
|
||||||
channel: [ undefined, { scope: 'worker', option: true } ],
|
channel: [ undefined, { scope: 'worker', option: true } ],
|
||||||
launchOptions: [ {}, { scope: 'worker', option: true } ],
|
launchOptions: [ {}, { scope: 'worker', option: true } ],
|
||||||
|
connectOptions: [ undefined, { scope: 'worker', option: true } ],
|
||||||
screenshot: [ 'off', { scope: 'worker', option: true } ],
|
screenshot: [ 'off', { scope: 'worker', option: true } ],
|
||||||
video: [ 'off', { scope: 'worker', option: true } ],
|
video: [ 'off', { scope: 'worker', option: true } ],
|
||||||
trace: [ 'off', { scope: 'worker', option: true } ],
|
trace: [ 'off', { scope: 'worker', option: true } ],
|
||||||
@ -100,9 +101,16 @@ export const test = _baseTest.extend<TestFixtures, WorkerFixtures>({
|
|||||||
await use(options);
|
await use(options);
|
||||||
}, { scope: 'worker' }],
|
}, { scope: 'worker' }],
|
||||||
|
|
||||||
browser: [async ({ playwright, browserName }, use) => {
|
browser: [async ({ playwright, browserName, connectOptions }, use) => {
|
||||||
if (!['chromium', 'firefox', 'webkit'].includes(browserName))
|
if (!['chromium', 'firefox', 'webkit'].includes(browserName))
|
||||||
throw new Error(`Unexpected browserName "${browserName}", must be one of "chromium", "firefox" or "webkit"`);
|
throw new Error(`Unexpected browserName "${browserName}", must be one of "chromium", "firefox" or "webkit"`);
|
||||||
|
if (connectOptions) {
|
||||||
|
const browser = await playwright[browserName].connect(connectOptions);
|
||||||
|
await use(browser);
|
||||||
|
await browser.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const browser = await playwright[browserName].launch();
|
const browser = await playwright[browserName].launch();
|
||||||
await use(browser);
|
await use(browser);
|
||||||
await browser.close();
|
await browser.close();
|
||||||
|
|||||||
21
packages/playwright-test/types/test.d.ts
vendored
21
packages/playwright-test/types/test.d.ts
vendored
@ -2658,6 +2658,17 @@ type ColorScheme = Exclude<BrowserContextOptions['colorScheme'], undefined>;
|
|||||||
type ExtraHTTPHeaders = Exclude<BrowserContextOptions['extraHTTPHeaders'], undefined>;
|
type ExtraHTTPHeaders = Exclude<BrowserContextOptions['extraHTTPHeaders'], undefined>;
|
||||||
type Proxy = Exclude<BrowserContextOptions['proxy'], undefined>;
|
type Proxy = Exclude<BrowserContextOptions['proxy'], undefined>;
|
||||||
type StorageState = Exclude<BrowserContextOptions['storageState'], undefined>;
|
type StorageState = Exclude<BrowserContextOptions['storageState'], undefined>;
|
||||||
|
type ConnectOptions = {
|
||||||
|
/**
|
||||||
|
* A browser websocket endpoint to connect to.
|
||||||
|
*/
|
||||||
|
wsEndpoint: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Additional HTTP headers to be sent with web socket connect request.
|
||||||
|
*/
|
||||||
|
headers?: { [key: string]: string; };
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Playwright Test provides many options to configure test environment, [Browser], [BrowserContext] and more.
|
* Playwright Test provides many options to configure test environment, [Browser], [BrowserContext] and more.
|
||||||
@ -2735,6 +2746,16 @@ export interface PlaywrightWorkerOptions {
|
|||||||
* [testOptions.channel](https://playwright.dev/docs/api/class-testoptions#test-options-channel) take priority over this.
|
* [testOptions.channel](https://playwright.dev/docs/api/class-testoptions#test-options-channel) take priority over this.
|
||||||
*/
|
*/
|
||||||
launchOptions: LaunchOptions;
|
launchOptions: LaunchOptions;
|
||||||
|
/**
|
||||||
|
* When connect options are specified, default
|
||||||
|
* [fixtures.browser](https://playwright.dev/docs/api/class-fixtures#fixtures-browser),
|
||||||
|
* [fixtures.context](https://playwright.dev/docs/api/class-fixtures#fixtures-context) and
|
||||||
|
* [fixtures.page](https://playwright.dev/docs/api/class-fixtures#fixtures-page) use the remote browser instead of
|
||||||
|
* launching a browser locally, and any launch options like
|
||||||
|
* [testOptions.headless](https://playwright.dev/docs/api/class-testoptions#test-options-headless) or
|
||||||
|
* [testOptions.channel](https://playwright.dev/docs/api/class-testoptions#test-options-channel) are ignored.
|
||||||
|
*/
|
||||||
|
connectOptions: ConnectOptions | undefined;
|
||||||
/**
|
/**
|
||||||
* Whether to automatically capture a screenshot after each test. Defaults to `'off'`.
|
* Whether to automatically capture a screenshot after each test. Defaults to `'off'`.
|
||||||
* - `'off'`: Do not capture screenshots.
|
* - `'off'`: Do not capture screenshots.
|
||||||
|
|||||||
@ -546,3 +546,58 @@ test('should work with video.path() throwing', async ({ runInlineTest }, testInf
|
|||||||
const video = fs.readdirSync(dir).find(file => file.endsWith('webm'));
|
const video = fs.readdirSync(dir).find(file => file.endsWith('webm'));
|
||||||
expect(video).toBeTruthy();
|
expect(video).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should work with connectOptions', async ({ runInlineTest }) => {
|
||||||
|
const result = await runInlineTest({
|
||||||
|
'playwright.config.js': `
|
||||||
|
module.exports = {
|
||||||
|
globalSetup: './global-setup',
|
||||||
|
use: {
|
||||||
|
connectOptions: {
|
||||||
|
wsEndpoint: process.env.CONNECT_WS_ENDPOINT,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
`,
|
||||||
|
'global-setup.ts': `
|
||||||
|
module.exports = async () => {
|
||||||
|
const server = await pwt.chromium.launchServer();
|
||||||
|
process.env.CONNECT_WS_ENDPOINT = server.wsEndpoint();
|
||||||
|
return () => server.close();
|
||||||
|
};
|
||||||
|
`,
|
||||||
|
'a.test.ts': `
|
||||||
|
const { test } = pwt;
|
||||||
|
test('pass', async ({ page }) => {
|
||||||
|
await page.setContent('<div>PASS</div>');
|
||||||
|
await expect(page.locator('div')).toHaveText('PASS');
|
||||||
|
});
|
||||||
|
`,
|
||||||
|
});
|
||||||
|
expect(result.exitCode).toBe(0);
|
||||||
|
expect(result.passed).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should throw with bad connectOptions', async ({ runInlineTest }) => {
|
||||||
|
const result = await runInlineTest({
|
||||||
|
'playwright.config.js': `
|
||||||
|
module.exports = {
|
||||||
|
use: {
|
||||||
|
connectOptions: {
|
||||||
|
wsEndpoint: 'http://does-not-exist-bad-domain.oh-no-should-not-work',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
`,
|
||||||
|
'a.test.ts': `
|
||||||
|
const { test } = pwt;
|
||||||
|
test('pass', async ({ page }) => {
|
||||||
|
await page.setContent('<div>PASS</div>');
|
||||||
|
await expect(page.locator('div')).toHaveText('PASS');
|
||||||
|
});
|
||||||
|
`,
|
||||||
|
});
|
||||||
|
expect(result.exitCode).toBe(1);
|
||||||
|
expect(result.passed).toBe(0);
|
||||||
|
expect(result.output).toContain('browserType.connect:');
|
||||||
|
});
|
||||||
|
|||||||
12
utils/generate_types/overrides-test.d.ts
vendored
12
utils/generate_types/overrides-test.d.ts
vendored
@ -297,6 +297,17 @@ type ColorScheme = Exclude<BrowserContextOptions['colorScheme'], undefined>;
|
|||||||
type ExtraHTTPHeaders = Exclude<BrowserContextOptions['extraHTTPHeaders'], undefined>;
|
type ExtraHTTPHeaders = Exclude<BrowserContextOptions['extraHTTPHeaders'], undefined>;
|
||||||
type Proxy = Exclude<BrowserContextOptions['proxy'], undefined>;
|
type Proxy = Exclude<BrowserContextOptions['proxy'], undefined>;
|
||||||
type StorageState = Exclude<BrowserContextOptions['storageState'], undefined>;
|
type StorageState = Exclude<BrowserContextOptions['storageState'], undefined>;
|
||||||
|
type ConnectOptions = {
|
||||||
|
/**
|
||||||
|
* A browser websocket endpoint to connect to.
|
||||||
|
*/
|
||||||
|
wsEndpoint: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Additional HTTP headers to be sent with web socket connect request.
|
||||||
|
*/
|
||||||
|
headers?: { [key: string]: string; };
|
||||||
|
};
|
||||||
|
|
||||||
export interface PlaywrightWorkerOptions {
|
export interface PlaywrightWorkerOptions {
|
||||||
browserName: BrowserName;
|
browserName: BrowserName;
|
||||||
@ -304,6 +315,7 @@ export interface PlaywrightWorkerOptions {
|
|||||||
headless: boolean | undefined;
|
headless: boolean | undefined;
|
||||||
channel: BrowserChannel | undefined;
|
channel: BrowserChannel | undefined;
|
||||||
launchOptions: LaunchOptions;
|
launchOptions: LaunchOptions;
|
||||||
|
connectOptions: ConnectOptions | undefined;
|
||||||
screenshot: 'off' | 'on' | 'only-on-failure';
|
screenshot: 'off' | 'on' | 'only-on-failure';
|
||||||
trace: TraceMode | /** deprecated */ 'retry-with-trace' | { mode: TraceMode, snapshots?: boolean, screenshots?: boolean, sources?: boolean };
|
trace: TraceMode | /** deprecated */ 'retry-with-trace' | { mode: TraceMode, snapshots?: boolean, screenshots?: boolean, sources?: boolean };
|
||||||
video: VideoMode | /** deprecated */ 'retry-with-video' | { mode: VideoMode, size?: ViewportSize };
|
video: VideoMode | /** deprecated */ 'retry-with-video' | { mode: VideoMode, size?: ViewportSize };
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user