mirror of
https://github.com/microsoft/playwright.git
synced 2024-10-27 05:46:28 +03:00
feat(electron): accept BrowserContextOptions in electron.launch (#6621)
This commit is contained in:
parent
972f0ec2b5
commit
754ee13c93
@ -76,3 +76,20 @@ Specifies environment variables that will be visible to Electron. Defaults to `p
|
|||||||
- `timeout` <[float]>
|
- `timeout` <[float]>
|
||||||
|
|
||||||
Maximum time in milliseconds to wait for the application to start. Defaults to `30000` (30 seconds). Pass `0` to disable timeout.
|
Maximum time in milliseconds to wait for the application to start. Defaults to `30000` (30 seconds). Pass `0` to disable timeout.
|
||||||
|
|
||||||
|
### option: Electron.launch.acceptdownloads = %%-context-option-acceptdownloads-%%
|
||||||
|
### option: Electron.launch.bypassCSP = %%-context-option-bypasscsp-%%
|
||||||
|
### option: Electron.launch.colorScheme = %%-context-option-colorscheme-%%
|
||||||
|
### option: Electron.launch.extraHTTPHeaders = %%-context-option-extrahttpheaders-%%
|
||||||
|
### option: Electron.launch.geolocation = %%-context-option-geolocation-%%
|
||||||
|
### option: Electron.launch.httpcredentials = %%-context-option-httpcredentials-%%
|
||||||
|
### option: Electron.launch.ignoreHTTPSErrors = %%-context-option-ignorehttpserrors-%%
|
||||||
|
### option: Electron.launch.locale = %%-context-option-locale-%%
|
||||||
|
### option: Electron.launch.offline = %%-context-option-offline-%%
|
||||||
|
### option: Electron.launch.recordhar = %%-context-option-recordhar-%%
|
||||||
|
### option: Electron.launch.recordhar.path = %%-context-option-recordhar-path-%%
|
||||||
|
### option: Electron.launch.recordhar.recordHarOmitContent = %%-context-option-recordhar-omit-content-%%
|
||||||
|
### option: Electron.launch.recordvideo = %%-context-option-recordvideo-%%
|
||||||
|
### option: Electron.launch.recordvideo.dir = %%-context-option-recordvideo-dir-%%
|
||||||
|
### option: Electron.launch.recordvideo.size = %%-context-option-recordvideo-size-%%
|
||||||
|
### option: Electron.launch.timezoneId = %%-context-option-timezoneid-%%
|
||||||
|
@ -19,17 +19,19 @@ import * as structs from '../../types/structs';
|
|||||||
import * as api from '../../types/types';
|
import * as api from '../../types/types';
|
||||||
import * as channels from '../protocol/channels';
|
import * as channels from '../protocol/channels';
|
||||||
import { TimeoutSettings } from '../utils/timeoutSettings';
|
import { TimeoutSettings } from '../utils/timeoutSettings';
|
||||||
|
import { headersObjectToArray } from '../utils/utils';
|
||||||
import { BrowserContext } from './browserContext';
|
import { BrowserContext } from './browserContext';
|
||||||
import { ChannelOwner } from './channelOwner';
|
import { ChannelOwner } from './channelOwner';
|
||||||
import { envObjectToArray } from './clientHelper';
|
import { envObjectToArray } from './clientHelper';
|
||||||
import { Events } from './events';
|
import { Events } from './events';
|
||||||
import { JSHandle, parseResult, serializeArgument } from './jsHandle';
|
import { JSHandle, parseResult, serializeArgument } from './jsHandle';
|
||||||
import { Page } from './page';
|
import { Page } from './page';
|
||||||
import { Env, WaitForEventOptions } from './types';
|
import { Env, WaitForEventOptions, Headers } from './types';
|
||||||
import { Waiter } from './waiter';
|
import { Waiter } from './waiter';
|
||||||
|
|
||||||
type ElectronOptions = Omit<channels.ElectronLaunchOptions, 'env'> & {
|
type ElectronOptions = Omit<channels.ElectronLaunchOptions, 'env'|'extraHTTPHeaders'> & {
|
||||||
env?: Env,
|
env?: Env,
|
||||||
|
extraHTTPHeaders?: Headers,
|
||||||
};
|
};
|
||||||
|
|
||||||
type ElectronAppType = typeof import('electron');
|
type ElectronAppType = typeof import('electron');
|
||||||
@ -48,6 +50,7 @@ export class Electron extends ChannelOwner<channels.ElectronChannel, channels.El
|
|||||||
const params: channels.ElectronLaunchParams = {
|
const params: channels.ElectronLaunchParams = {
|
||||||
sdkLanguage: 'javascript',
|
sdkLanguage: 'javascript',
|
||||||
...options,
|
...options,
|
||||||
|
extraHTTPHeaders: options.extraHTTPHeaders && headersObjectToArray(options.extraHTTPHeaders),
|
||||||
env: envObjectToArray(options.env ? options.env : process.env),
|
env: envObjectToArray(options.env ? options.env : process.env),
|
||||||
};
|
};
|
||||||
return ElectronApplication.from((await channel.launch(params)).electronApplication);
|
return ElectronApplication.from((await channel.launch(params)).electronApplication);
|
||||||
|
@ -2555,6 +2555,34 @@ export type ElectronLaunchParams = {
|
|||||||
cwd?: string,
|
cwd?: string,
|
||||||
env?: NameValue[],
|
env?: NameValue[],
|
||||||
timeout?: number,
|
timeout?: number,
|
||||||
|
acceptDownloads?: boolean,
|
||||||
|
bypassCSP?: boolean,
|
||||||
|
colorScheme?: 'dark' | 'light' | 'no-preference',
|
||||||
|
extraHTTPHeaders?: NameValue[],
|
||||||
|
geolocation?: {
|
||||||
|
longitude: number,
|
||||||
|
latitude: number,
|
||||||
|
accuracy?: number,
|
||||||
|
},
|
||||||
|
httpCredentials?: {
|
||||||
|
username: string,
|
||||||
|
password: string,
|
||||||
|
},
|
||||||
|
ignoreHTTPSErrors?: boolean,
|
||||||
|
locale?: string,
|
||||||
|
offline?: boolean,
|
||||||
|
recordHar?: {
|
||||||
|
omitContent?: boolean,
|
||||||
|
path: string,
|
||||||
|
},
|
||||||
|
recordVideo?: {
|
||||||
|
dir: string,
|
||||||
|
size?: {
|
||||||
|
width: number,
|
||||||
|
height: number,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
timezoneId?: string,
|
||||||
};
|
};
|
||||||
export type ElectronLaunchOptions = {
|
export type ElectronLaunchOptions = {
|
||||||
executablePath?: string,
|
executablePath?: string,
|
||||||
@ -2562,6 +2590,34 @@ export type ElectronLaunchOptions = {
|
|||||||
cwd?: string,
|
cwd?: string,
|
||||||
env?: NameValue[],
|
env?: NameValue[],
|
||||||
timeout?: number,
|
timeout?: number,
|
||||||
|
acceptDownloads?: boolean,
|
||||||
|
bypassCSP?: boolean,
|
||||||
|
colorScheme?: 'dark' | 'light' | 'no-preference',
|
||||||
|
extraHTTPHeaders?: NameValue[],
|
||||||
|
geolocation?: {
|
||||||
|
longitude: number,
|
||||||
|
latitude: number,
|
||||||
|
accuracy?: number,
|
||||||
|
},
|
||||||
|
httpCredentials?: {
|
||||||
|
username: string,
|
||||||
|
password: string,
|
||||||
|
},
|
||||||
|
ignoreHTTPSErrors?: boolean,
|
||||||
|
locale?: string,
|
||||||
|
offline?: boolean,
|
||||||
|
recordHar?: {
|
||||||
|
omitContent?: boolean,
|
||||||
|
path: string,
|
||||||
|
},
|
||||||
|
recordVideo?: {
|
||||||
|
dir: string,
|
||||||
|
size?: {
|
||||||
|
width: number,
|
||||||
|
height: number,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
timezoneId?: string,
|
||||||
};
|
};
|
||||||
export type ElectronLaunchResult = {
|
export type ElectronLaunchResult = {
|
||||||
electronApplication: ElectronApplicationChannel,
|
electronApplication: ElectronApplicationChannel,
|
||||||
|
@ -2094,6 +2094,47 @@ Electron:
|
|||||||
type: array?
|
type: array?
|
||||||
items: NameValue
|
items: NameValue
|
||||||
timeout: number?
|
timeout: number?
|
||||||
|
acceptDownloads: boolean?
|
||||||
|
bypassCSP: boolean?
|
||||||
|
colorScheme:
|
||||||
|
type: enum?
|
||||||
|
literals:
|
||||||
|
- dark
|
||||||
|
- light
|
||||||
|
- no-preference
|
||||||
|
extraHTTPHeaders:
|
||||||
|
type: array?
|
||||||
|
items: NameValue
|
||||||
|
geolocation:
|
||||||
|
type: object?
|
||||||
|
properties:
|
||||||
|
longitude: number
|
||||||
|
latitude: number
|
||||||
|
accuracy: number?
|
||||||
|
httpCredentials:
|
||||||
|
type: object?
|
||||||
|
properties:
|
||||||
|
username: string
|
||||||
|
password: string
|
||||||
|
ignoreHTTPSErrors: boolean?
|
||||||
|
locale: string?
|
||||||
|
offline: boolean?
|
||||||
|
recordHar:
|
||||||
|
type: object?
|
||||||
|
properties:
|
||||||
|
omitContent: boolean?
|
||||||
|
path: string
|
||||||
|
recordVideo:
|
||||||
|
type: object?
|
||||||
|
properties:
|
||||||
|
dir: string
|
||||||
|
size:
|
||||||
|
type: object?
|
||||||
|
properties:
|
||||||
|
width: number
|
||||||
|
height: number
|
||||||
|
timezoneId: string?
|
||||||
|
|
||||||
returns:
|
returns:
|
||||||
electronApplication: ElectronApplication
|
electronApplication: ElectronApplication
|
||||||
|
|
||||||
|
@ -973,6 +973,34 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme {
|
|||||||
cwd: tOptional(tString),
|
cwd: tOptional(tString),
|
||||||
env: tOptional(tArray(tType('NameValue'))),
|
env: tOptional(tArray(tType('NameValue'))),
|
||||||
timeout: tOptional(tNumber),
|
timeout: tOptional(tNumber),
|
||||||
|
acceptDownloads: tOptional(tBoolean),
|
||||||
|
bypassCSP: tOptional(tBoolean),
|
||||||
|
colorScheme: tOptional(tEnum(['dark', 'light', 'no-preference'])),
|
||||||
|
extraHTTPHeaders: tOptional(tArray(tType('NameValue'))),
|
||||||
|
geolocation: tOptional(tObject({
|
||||||
|
longitude: tNumber,
|
||||||
|
latitude: tNumber,
|
||||||
|
accuracy: tOptional(tNumber),
|
||||||
|
})),
|
||||||
|
httpCredentials: tOptional(tObject({
|
||||||
|
username: tString,
|
||||||
|
password: tString,
|
||||||
|
})),
|
||||||
|
ignoreHTTPSErrors: tOptional(tBoolean),
|
||||||
|
locale: tOptional(tString),
|
||||||
|
offline: tOptional(tBoolean),
|
||||||
|
recordHar: tOptional(tObject({
|
||||||
|
omitContent: tOptional(tBoolean),
|
||||||
|
path: tString,
|
||||||
|
})),
|
||||||
|
recordVideo: tOptional(tObject({
|
||||||
|
dir: tString,
|
||||||
|
size: tOptional(tObject({
|
||||||
|
width: tNumber,
|
||||||
|
height: tNumber,
|
||||||
|
})),
|
||||||
|
})),
|
||||||
|
timezoneId: tOptional(tString),
|
||||||
});
|
});
|
||||||
scheme.ElectronApplicationBrowserWindowParams = tObject({
|
scheme.ElectronApplicationBrowserWindowParams = tObject({
|
||||||
page: tChannel('Page'),
|
page: tChannel('Page'),
|
||||||
|
@ -22,7 +22,6 @@ import * as js from '../javascript';
|
|||||||
import { Page } from '../page';
|
import { Page } from '../page';
|
||||||
import { TimeoutSettings } from '../../utils/timeoutSettings';
|
import { TimeoutSettings } from '../../utils/timeoutSettings';
|
||||||
import { WebSocketTransport } from '../transport';
|
import { WebSocketTransport } from '../transport';
|
||||||
import * as types from '../types';
|
|
||||||
import { launchProcess, envArrayToObject } from '../processLauncher';
|
import { launchProcess, envArrayToObject } from '../processLauncher';
|
||||||
import { BrowserContext } from '../browserContext';
|
import { BrowserContext } from '../browserContext';
|
||||||
import type {BrowserWindow} from 'electron';
|
import type {BrowserWindow} from 'electron';
|
||||||
@ -33,15 +32,7 @@ import * as childProcess from 'child_process';
|
|||||||
import * as readline from 'readline';
|
import * as readline from 'readline';
|
||||||
import { RecentLogsCollector } from '../../utils/debugLogger';
|
import { RecentLogsCollector } from '../../utils/debugLogger';
|
||||||
import { internalCallMetadata, SdkObject } from '../instrumentation';
|
import { internalCallMetadata, SdkObject } from '../instrumentation';
|
||||||
|
import * as channels from '../../protocol/channels';
|
||||||
export type ElectronLaunchOptionsBase = {
|
|
||||||
sdkLanguage: string,
|
|
||||||
executablePath?: string,
|
|
||||||
args?: string[],
|
|
||||||
cwd?: string,
|
|
||||||
env?: types.EnvArray,
|
|
||||||
timeout?: number,
|
|
||||||
};
|
|
||||||
|
|
||||||
export class ElectronApplication extends SdkObject {
|
export class ElectronApplication extends SdkObject {
|
||||||
static Events = {
|
static Events = {
|
||||||
@ -112,7 +103,7 @@ export class Electron extends SdkObject {
|
|||||||
this._playwrightOptions = playwrightOptions;
|
this._playwrightOptions = playwrightOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
async launch(options: ElectronLaunchOptionsBase): Promise<ElectronApplication> {
|
async launch(options: channels.ElectronLaunchParams): Promise<ElectronApplication> {
|
||||||
const {
|
const {
|
||||||
args = [],
|
args = [],
|
||||||
} = options;
|
} = options;
|
||||||
@ -164,7 +155,22 @@ export class Electron extends SdkObject {
|
|||||||
name: 'electron',
|
name: 'electron',
|
||||||
isChromium: true,
|
isChromium: true,
|
||||||
headful: true,
|
headful: true,
|
||||||
persistent: { sdkLanguage: options.sdkLanguage, noDefaultViewport: true },
|
persistent: {
|
||||||
|
sdkLanguage: options.sdkLanguage,
|
||||||
|
noDefaultViewport: true,
|
||||||
|
acceptDownloads: options.acceptDownloads,
|
||||||
|
bypassCSP: options.bypassCSP,
|
||||||
|
colorScheme: options.colorScheme,
|
||||||
|
extraHTTPHeaders: options.extraHTTPHeaders,
|
||||||
|
geolocation: options.geolocation,
|
||||||
|
httpCredentials: options.httpCredentials,
|
||||||
|
ignoreHTTPSErrors: options.ignoreHTTPSErrors,
|
||||||
|
locale: options.locale,
|
||||||
|
offline: options.offline,
|
||||||
|
recordHar: options.recordHar,
|
||||||
|
recordVideo: options.recordVideo,
|
||||||
|
timezoneId: options.timezoneId,
|
||||||
|
},
|
||||||
browserProcess,
|
browserProcess,
|
||||||
protocolLogger: helper.debugProtocolLogger(),
|
protocolLogger: helper.debugProtocolLogger(),
|
||||||
browserLogsCollector,
|
browserLogsCollector,
|
||||||
|
@ -107,3 +107,22 @@ test('should return browser window', async ({ playwright }) => {
|
|||||||
expect(await bwHandle.evaluate((bw: BrowserWindow) => bw.title)).toBe('Electron');
|
expect(await bwHandle.evaluate((bw: BrowserWindow) => bw.title)).toBe('Electron');
|
||||||
await electronApp.close();
|
await electronApp.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should bypass csp', async ({playwright, server}) => {
|
||||||
|
const app = await playwright._electron.launch({
|
||||||
|
args: [require('path').join(__dirname, 'electron-app.js')],
|
||||||
|
bypassCSP: true,
|
||||||
|
});
|
||||||
|
await app.evaluate(electron => {
|
||||||
|
const window = new electron.BrowserWindow({
|
||||||
|
width: 800,
|
||||||
|
height: 600,
|
||||||
|
});
|
||||||
|
window.loadURL('about:blank');
|
||||||
|
});
|
||||||
|
const page = await app.firstWindow();
|
||||||
|
await page.goto(server.PREFIX + '/csp.html');
|
||||||
|
await page.addScriptTag({content: 'window["__injected"] = 42;'});
|
||||||
|
expect(await page.evaluate('window["__injected"]')).toBe(42);
|
||||||
|
await app.close();
|
||||||
|
});
|
||||||
|
118
types/types.d.ts
vendored
118
types/types.d.ts
vendored
@ -9617,11 +9617,28 @@ export interface Electron {
|
|||||||
* @param options
|
* @param options
|
||||||
*/
|
*/
|
||||||
launch(options?: {
|
launch(options?: {
|
||||||
|
/**
|
||||||
|
* Whether to automatically download all the attachments. Defaults to `false` where all the downloads are canceled.
|
||||||
|
*/
|
||||||
|
acceptDownloads?: boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Additional arguments to pass to the application when launching. You typically pass the main script name here.
|
* Additional arguments to pass to the application when launching. You typically pass the main script name here.
|
||||||
*/
|
*/
|
||||||
args?: Array<string>;
|
args?: Array<string>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggles bypassing page's Content-Security-Policy.
|
||||||
|
*/
|
||||||
|
bypassCSP?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emulates `'prefers-colors-scheme'` media feature, supported values are `'light'`, `'dark'`, `'no-preference'`. See
|
||||||
|
* [page.emulateMedia([options])](https://playwright.dev/docs/api/class-page#pageemulatemediaoptions) for more details.
|
||||||
|
* Defaults to `'light'`.
|
||||||
|
*/
|
||||||
|
colorScheme?: "light"|"dark"|"no-preference";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Current working directory to launch application from.
|
* Current working directory to launch application from.
|
||||||
*/
|
*/
|
||||||
@ -9637,6 +9654,107 @@ export interface Electron {
|
|||||||
* package, located at `node_modules/.bin/electron`.
|
* package, located at `node_modules/.bin/electron`.
|
||||||
*/
|
*/
|
||||||
executablePath?: string;
|
executablePath?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An object containing additional HTTP headers to be sent with every request. All header values must be strings.
|
||||||
|
*/
|
||||||
|
extraHTTPHeaders?: { [key: string]: string; };
|
||||||
|
|
||||||
|
geolocation?: {
|
||||||
|
/**
|
||||||
|
* Latitude between -90 and 90.
|
||||||
|
*/
|
||||||
|
latitude: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Longitude between -180 and 180.
|
||||||
|
*/
|
||||||
|
longitude: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Non-negative accuracy value. Defaults to `0`.
|
||||||
|
*/
|
||||||
|
accuracy?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Credentials for [HTTP authentication](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication).
|
||||||
|
*/
|
||||||
|
httpCredentials?: {
|
||||||
|
username: string;
|
||||||
|
|
||||||
|
password: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to ignore HTTPS errors during navigation. Defaults to `false`.
|
||||||
|
*/
|
||||||
|
ignoreHTTPSErrors?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify user locale, for example `en-GB`, `de-DE`, etc. Locale will affect `navigator.language` value, `Accept-Language`
|
||||||
|
* request header value as well as number and date formatting rules.
|
||||||
|
*/
|
||||||
|
locale?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to emulate network being offline. Defaults to `false`.
|
||||||
|
*/
|
||||||
|
offline?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables [HAR](http://www.softwareishard.com/blog/har-12-spec) recording for all pages into `recordHar.path` file. If not
|
||||||
|
* specified, the HAR is not recorded. Make sure to await
|
||||||
|
* [browserContext.close()](https://playwright.dev/docs/api/class-browsercontext#browsercontextclose) for the HAR to be
|
||||||
|
* saved.
|
||||||
|
*/
|
||||||
|
recordHar?: {
|
||||||
|
/**
|
||||||
|
* Optional setting to control whether to omit request content from the HAR. Defaults to `false`.
|
||||||
|
*/
|
||||||
|
omitContent?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Path on the filesystem to write the HAR file to.
|
||||||
|
*/
|
||||||
|
path: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables video recording for all pages into `recordVideo.dir` directory. If not specified videos are not recorded. Make
|
||||||
|
* sure to await [browserContext.close()](https://playwright.dev/docs/api/class-browsercontext#browsercontextclose) for
|
||||||
|
* videos to be saved.
|
||||||
|
*/
|
||||||
|
recordVideo?: {
|
||||||
|
/**
|
||||||
|
* Path to the directory to put videos into.
|
||||||
|
*/
|
||||||
|
dir: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optional dimensions of the recorded videos. If not specified the size will be equal to `viewport` scaled down to fit
|
||||||
|
* into 800x800. If `viewport` is not configured explicitly the video size defaults to 800x450. Actual picture of each page
|
||||||
|
* will be scaled down if necessary to fit the specified size.
|
||||||
|
*/
|
||||||
|
size?: {
|
||||||
|
/**
|
||||||
|
* Video frame width.
|
||||||
|
*/
|
||||||
|
width: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Video frame height.
|
||||||
|
*/
|
||||||
|
height: number;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes the timezone of the context. See
|
||||||
|
* [ICU's metaZones.txt](https://cs.chromium.org/chromium/src/third_party/icu/source/data/misc/metaZones.txt?rcl=faee8bc70570192d82d2978a71e2a615788597d1)
|
||||||
|
* for a list of supported timezone IDs.
|
||||||
|
*/
|
||||||
|
timezoneId?: string;
|
||||||
}): Promise<ElectronApplication>;
|
}): Promise<ElectronApplication>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user