feat: emulate prefers-contrast (#34494)
This commit is contained in:
parent
96d4dc1eda
commit
5d82567346
|
|
@ -1309,6 +1309,18 @@ Emulates `'forced-colors'` media feature, supported values are `'active'` and `'
|
||||||
* langs: csharp, python
|
* langs: csharp, python
|
||||||
- `forcedColors` <[ForcedColors]<"active"|"none"|"null">>
|
- `forcedColors` <[ForcedColors]<"active"|"none"|"null">>
|
||||||
|
|
||||||
|
### option: Page.emulateMedia.contrast
|
||||||
|
* since: v1.51
|
||||||
|
* langs: js, java
|
||||||
|
- `contrast` <null|[Contrast]<"no-preference"|"more">>
|
||||||
|
|
||||||
|
Emulates `'prefers-contrast'` media feature, supported values are `'no-preference'`, `'more'`. Passing `null` disables contrast emulation.
|
||||||
|
|
||||||
|
### option: Page.emulateMedia.contrast
|
||||||
|
* since: v1.51
|
||||||
|
* langs: csharp, python
|
||||||
|
- `contrast` <[Contrast]<"no-preference"|"more"|"null">>
|
||||||
|
|
||||||
## async method: Page.evalOnSelector
|
## async method: Page.evalOnSelector
|
||||||
* since: v1.9
|
* since: v1.9
|
||||||
* discouraged: This method does not wait for the element to pass actionability
|
* discouraged: This method does not wait for the element to pass actionability
|
||||||
|
|
|
||||||
|
|
@ -673,6 +673,18 @@ Emulates `'forced-colors'` media feature, supported values are `'active'`, `'non
|
||||||
|
|
||||||
Emulates `'forced-colors'` media feature, supported values are `'active'`, `'none'`. See [`method: Page.emulateMedia`] for more details. Passing `'null'` resets emulation to system defaults. Defaults to `'none'`.
|
Emulates `'forced-colors'` media feature, supported values are `'active'`, `'none'`. See [`method: Page.emulateMedia`] for more details. Passing `'null'` resets emulation to system defaults. Defaults to `'none'`.
|
||||||
|
|
||||||
|
## context-option-contrast
|
||||||
|
* langs: js, java
|
||||||
|
- `contrast` <null|[ForcedColors]<"no-preference"|"more">>
|
||||||
|
|
||||||
|
Emulates `'prefers-contrast'` media feature, supported values are `'no-preference'`, `'more'`. See [`method: Page.emulateMedia`] for more details. Passing `null` resets emulation to system defaults. Defaults to `'no-preference'`.
|
||||||
|
|
||||||
|
## context-option-contrast-csharp-python
|
||||||
|
* langs: csharp, python
|
||||||
|
- `contrast` <[ForcedColors]<"no-preference"|"more"|"null">>
|
||||||
|
|
||||||
|
Emulates `'prefers-contrast'` media feature, supported values are `'no-preference'`, `'more'`. See [`method: Page.emulateMedia`] for more details. Passing `'null'` resets emulation to system defaults. Defaults to `'no-preference'`.
|
||||||
|
|
||||||
## context-option-logger
|
## context-option-logger
|
||||||
* langs: js
|
* langs: js
|
||||||
- `logger` <[Logger]>
|
- `logger` <[Logger]>
|
||||||
|
|
@ -973,6 +985,8 @@ between the same pixel in compared images, between zero (strict) and one (lax),
|
||||||
- %%-context-option-reducedMotion-csharp-python-%%
|
- %%-context-option-reducedMotion-csharp-python-%%
|
||||||
- %%-context-option-forcedColors-%%
|
- %%-context-option-forcedColors-%%
|
||||||
- %%-context-option-forcedColors-csharp-python-%%
|
- %%-context-option-forcedColors-csharp-python-%%
|
||||||
|
- %%-context-option-contrast-%%
|
||||||
|
- %%-context-option-contrast-csharp-python-%%
|
||||||
- %%-context-option-logger-%%
|
- %%-context-option-logger-%%
|
||||||
- %%-context-option-videospath-%%
|
- %%-context-option-videospath-%%
|
||||||
- %%-context-option-videosize-%%
|
- %%-context-option-videosize-%%
|
||||||
|
|
|
||||||
|
|
@ -537,6 +537,7 @@ export async function prepareBrowserContextParams(options: BrowserContextOptions
|
||||||
colorScheme: options.colorScheme === null ? 'no-override' : options.colorScheme,
|
colorScheme: options.colorScheme === null ? 'no-override' : options.colorScheme,
|
||||||
reducedMotion: options.reducedMotion === null ? 'no-override' : options.reducedMotion,
|
reducedMotion: options.reducedMotion === null ? 'no-override' : options.reducedMotion,
|
||||||
forcedColors: options.forcedColors === null ? 'no-override' : options.forcedColors,
|
forcedColors: options.forcedColors === null ? 'no-override' : options.forcedColors,
|
||||||
|
contrast: options.contrast === null ? 'no-override' : options.contrast,
|
||||||
acceptDownloads: toAcceptDownloadsProtocol(options.acceptDownloads),
|
acceptDownloads: toAcceptDownloadsProtocol(options.acceptDownloads),
|
||||||
clientCertificates: await toClientCertificatesProtocol(options.clientCertificates),
|
clientCertificates: await toClientCertificatesProtocol(options.clientCertificates),
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -483,12 +483,13 @@ export class Page extends ChannelOwner<channels.PageChannel> implements api.Page
|
||||||
await this._channel.requestGC();
|
await this._channel.requestGC();
|
||||||
}
|
}
|
||||||
|
|
||||||
async emulateMedia(options: { media?: 'screen' | 'print' | null, colorScheme?: 'dark' | 'light' | 'no-preference' | null, reducedMotion?: 'reduce' | 'no-preference' | null, forcedColors?: 'active' | 'none' | null } = {}) {
|
async emulateMedia(options: { media?: 'screen' | 'print' | null, colorScheme?: 'dark' | 'light' | 'no-preference' | null, reducedMotion?: 'reduce' | 'no-preference' | null, forcedColors?: 'active' | 'none' | null, contrast?: 'no-preference' | 'more' | null } = {}) {
|
||||||
await this._channel.emulateMedia({
|
await this._channel.emulateMedia({
|
||||||
media: options.media === null ? 'no-override' : options.media,
|
media: options.media === null ? 'no-override' : options.media,
|
||||||
colorScheme: options.colorScheme === null ? 'no-override' : options.colorScheme,
|
colorScheme: options.colorScheme === null ? 'no-override' : options.colorScheme,
|
||||||
reducedMotion: options.reducedMotion === null ? 'no-override' : options.reducedMotion,
|
reducedMotion: options.reducedMotion === null ? 'no-override' : options.reducedMotion,
|
||||||
forcedColors: options.forcedColors === null ? 'no-override' : options.forcedColors,
|
forcedColors: options.forcedColors === null ? 'no-override' : options.forcedColors,
|
||||||
|
contrast: options.contrast === null ? 'no-override' : options.contrast,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ export type ClientCertificate = {
|
||||||
passphrase?: string;
|
passphrase?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type BrowserContextOptions = Omit<channels.BrowserNewContextOptions, 'viewport' | 'noDefaultViewport' | 'extraHTTPHeaders' | 'clientCertificates' | 'storageState' | 'recordHar' | 'colorScheme' | 'reducedMotion' | 'forcedColors' | 'acceptDownloads'> & {
|
export type BrowserContextOptions = Omit<channels.BrowserNewContextOptions, 'viewport' | 'noDefaultViewport' | 'extraHTTPHeaders' | 'clientCertificates' | 'storageState' | 'recordHar' | 'colorScheme' | 'reducedMotion' | 'forcedColors' | 'acceptDownloads' | 'contrast'> & {
|
||||||
viewport?: Size | null;
|
viewport?: Size | null;
|
||||||
extraHTTPHeaders?: Headers;
|
extraHTTPHeaders?: Headers;
|
||||||
logger?: Logger;
|
logger?: Logger;
|
||||||
|
|
@ -80,6 +80,7 @@ export type BrowserContextOptions = Omit<channels.BrowserNewContextOptions, 'vie
|
||||||
colorScheme?: 'dark' | 'light' | 'no-preference' | null;
|
colorScheme?: 'dark' | 'light' | 'no-preference' | null;
|
||||||
reducedMotion?: 'reduce' | 'no-preference' | null;
|
reducedMotion?: 'reduce' | 'no-preference' | null;
|
||||||
forcedColors?: 'active' | 'none' | null;
|
forcedColors?: 'active' | 'none' | null;
|
||||||
|
contrast?: 'more' | 'no-preference' | null;
|
||||||
acceptDownloads?: boolean;
|
acceptDownloads?: boolean;
|
||||||
clientCertificates?: ClientCertificate[];
|
clientCertificates?: ClientCertificate[];
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -582,6 +582,7 @@ scheme.BrowserTypeLaunchPersistentContextParams = tObject({
|
||||||
reducedMotion: tOptional(tEnum(['reduce', 'no-preference', 'no-override'])),
|
reducedMotion: tOptional(tEnum(['reduce', 'no-preference', 'no-override'])),
|
||||||
forcedColors: tOptional(tEnum(['active', 'none', 'no-override'])),
|
forcedColors: tOptional(tEnum(['active', 'none', 'no-override'])),
|
||||||
acceptDownloads: tOptional(tEnum(['accept', 'deny', 'internal-browser-default'])),
|
acceptDownloads: tOptional(tEnum(['accept', 'deny', 'internal-browser-default'])),
|
||||||
|
contrast: tOptional(tEnum(['no-preference', 'more', 'no-override'])),
|
||||||
baseURL: tOptional(tString),
|
baseURL: tOptional(tString),
|
||||||
recordVideo: tOptional(tObject({
|
recordVideo: tOptional(tObject({
|
||||||
dir: tString,
|
dir: tString,
|
||||||
|
|
@ -668,6 +669,7 @@ scheme.BrowserNewContextParams = tObject({
|
||||||
reducedMotion: tOptional(tEnum(['reduce', 'no-preference', 'no-override'])),
|
reducedMotion: tOptional(tEnum(['reduce', 'no-preference', 'no-override'])),
|
||||||
forcedColors: tOptional(tEnum(['active', 'none', 'no-override'])),
|
forcedColors: tOptional(tEnum(['active', 'none', 'no-override'])),
|
||||||
acceptDownloads: tOptional(tEnum(['accept', 'deny', 'internal-browser-default'])),
|
acceptDownloads: tOptional(tEnum(['accept', 'deny', 'internal-browser-default'])),
|
||||||
|
contrast: tOptional(tEnum(['no-preference', 'more', 'no-override'])),
|
||||||
baseURL: tOptional(tString),
|
baseURL: tOptional(tString),
|
||||||
recordVideo: tOptional(tObject({
|
recordVideo: tOptional(tObject({
|
||||||
dir: tString,
|
dir: tString,
|
||||||
|
|
@ -737,6 +739,7 @@ scheme.BrowserNewContextForReuseParams = tObject({
|
||||||
reducedMotion: tOptional(tEnum(['reduce', 'no-preference', 'no-override'])),
|
reducedMotion: tOptional(tEnum(['reduce', 'no-preference', 'no-override'])),
|
||||||
forcedColors: tOptional(tEnum(['active', 'none', 'no-override'])),
|
forcedColors: tOptional(tEnum(['active', 'none', 'no-override'])),
|
||||||
acceptDownloads: tOptional(tEnum(['accept', 'deny', 'internal-browser-default'])),
|
acceptDownloads: tOptional(tEnum(['accept', 'deny', 'internal-browser-default'])),
|
||||||
|
contrast: tOptional(tEnum(['no-preference', 'more', 'no-override'])),
|
||||||
baseURL: tOptional(tString),
|
baseURL: tOptional(tString),
|
||||||
recordVideo: tOptional(tObject({
|
recordVideo: tOptional(tObject({
|
||||||
dir: tString,
|
dir: tString,
|
||||||
|
|
@ -1118,6 +1121,7 @@ scheme.PageEmulateMediaParams = tObject({
|
||||||
colorScheme: tOptional(tEnum(['dark', 'light', 'no-preference', 'no-override'])),
|
colorScheme: tOptional(tEnum(['dark', 'light', 'no-preference', 'no-override'])),
|
||||||
reducedMotion: tOptional(tEnum(['reduce', 'no-preference', 'no-override'])),
|
reducedMotion: tOptional(tEnum(['reduce', 'no-preference', 'no-override'])),
|
||||||
forcedColors: tOptional(tEnum(['active', 'none', 'no-override'])),
|
forcedColors: tOptional(tEnum(['active', 'none', 'no-override'])),
|
||||||
|
contrast: tOptional(tEnum(['no-preference', 'more', 'no-override'])),
|
||||||
});
|
});
|
||||||
scheme.PageEmulateMediaResult = tOptional(tObject({}));
|
scheme.PageEmulateMediaResult = tOptional(tObject({}));
|
||||||
scheme.PageExposeBindingParams = tObject({
|
scheme.PageExposeBindingParams = tObject({
|
||||||
|
|
@ -2640,6 +2644,7 @@ scheme.AndroidDeviceLaunchBrowserParams = tObject({
|
||||||
reducedMotion: tOptional(tEnum(['reduce', 'no-preference', 'no-override'])),
|
reducedMotion: tOptional(tEnum(['reduce', 'no-preference', 'no-override'])),
|
||||||
forcedColors: tOptional(tEnum(['active', 'none', 'no-override'])),
|
forcedColors: tOptional(tEnum(['active', 'none', 'no-override'])),
|
||||||
acceptDownloads: tOptional(tEnum(['accept', 'deny', 'internal-browser-default'])),
|
acceptDownloads: tOptional(tEnum(['accept', 'deny', 'internal-browser-default'])),
|
||||||
|
contrast: tOptional(tEnum(['no-preference', 'more', 'no-override'])),
|
||||||
baseURL: tOptional(tString),
|
baseURL: tOptional(tString),
|
||||||
recordVideo: tOptional(tObject({
|
recordVideo: tOptional(tObject({
|
||||||
dir: tString,
|
dir: tString,
|
||||||
|
|
|
||||||
|
|
@ -762,6 +762,7 @@ const paramsThatAllowContextReuse: (keyof channels.BrowserNewContextForReusePara
|
||||||
'colorScheme',
|
'colorScheme',
|
||||||
'forcedColors',
|
'forcedColors',
|
||||||
'reducedMotion',
|
'reducedMotion',
|
||||||
|
'contrast',
|
||||||
'screen',
|
'screen',
|
||||||
'userAgent',
|
'userAgent',
|
||||||
'viewport',
|
'viewport',
|
||||||
|
|
|
||||||
|
|
@ -1026,10 +1026,12 @@ class FrameSession {
|
||||||
const colorScheme = emulatedMedia.colorScheme === 'no-override' ? '' : emulatedMedia.colorScheme;
|
const colorScheme = emulatedMedia.colorScheme === 'no-override' ? '' : emulatedMedia.colorScheme;
|
||||||
const reducedMotion = emulatedMedia.reducedMotion === 'no-override' ? '' : emulatedMedia.reducedMotion;
|
const reducedMotion = emulatedMedia.reducedMotion === 'no-override' ? '' : emulatedMedia.reducedMotion;
|
||||||
const forcedColors = emulatedMedia.forcedColors === 'no-override' ? '' : emulatedMedia.forcedColors;
|
const forcedColors = emulatedMedia.forcedColors === 'no-override' ? '' : emulatedMedia.forcedColors;
|
||||||
|
const contrast = emulatedMedia.contrast === 'no-override' ? '' : emulatedMedia.contrast;
|
||||||
const features = [
|
const features = [
|
||||||
{ name: 'prefers-color-scheme', value: colorScheme },
|
{ name: 'prefers-color-scheme', value: colorScheme },
|
||||||
{ name: 'prefers-reduced-motion', value: reducedMotion },
|
{ name: 'prefers-reduced-motion', value: reducedMotion },
|
||||||
{ name: 'forced-colors', value: forcedColors },
|
{ name: 'forced-colors', value: forcedColors },
|
||||||
|
{ name: 'prefers-contrast', value: contrast },
|
||||||
];
|
];
|
||||||
await this._client.send('Emulation.setEmulatedMedia', { media, features });
|
await this._client.send('Emulation.setEmulatedMedia', { media, features });
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -162,6 +162,7 @@ export class PageDispatcher extends Dispatcher<Page, channels.PageChannel, Brows
|
||||||
colorScheme: params.colorScheme,
|
colorScheme: params.colorScheme,
|
||||||
reducedMotion: params.reducedMotion,
|
reducedMotion: params.reducedMotion,
|
||||||
forcedColors: params.forcedColors,
|
forcedColors: params.forcedColors,
|
||||||
|
contrast: params.contrast,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -240,6 +240,12 @@ export class FFBrowserContext extends BrowserContext {
|
||||||
forcedColors: this._options.forcedColors !== undefined ? this._options.forcedColors : 'none',
|
forcedColors: this._options.forcedColors !== undefined ? this._options.forcedColors : 'none',
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
if (this._options.contrast !== 'no-override') {
|
||||||
|
promises.push(this._browser.session.send('Browser.setContrast', {
|
||||||
|
browserContextId,
|
||||||
|
contrast: this._options.contrast !== undefined ? this._options.contrast : 'no-preference',
|
||||||
|
}));
|
||||||
|
}
|
||||||
if (this._options.recordVideo) {
|
if (this._options.recordVideo) {
|
||||||
promises.push(this._ensureVideosPath().then(() => {
|
promises.push(this._ensureVideosPath().then(() => {
|
||||||
return this._browser.session.send('Browser.setVideoRecordingOptions', {
|
return this._browser.session.send('Browser.setVideoRecordingOptions', {
|
||||||
|
|
|
||||||
|
|
@ -347,12 +347,14 @@ export class FFPage implements PageDelegate {
|
||||||
const colorScheme = emulatedMedia.colorScheme === 'no-override' ? undefined : emulatedMedia.colorScheme;
|
const colorScheme = emulatedMedia.colorScheme === 'no-override' ? undefined : emulatedMedia.colorScheme;
|
||||||
const reducedMotion = emulatedMedia.reducedMotion === 'no-override' ? undefined : emulatedMedia.reducedMotion;
|
const reducedMotion = emulatedMedia.reducedMotion === 'no-override' ? undefined : emulatedMedia.reducedMotion;
|
||||||
const forcedColors = emulatedMedia.forcedColors === 'no-override' ? undefined : emulatedMedia.forcedColors;
|
const forcedColors = emulatedMedia.forcedColors === 'no-override' ? undefined : emulatedMedia.forcedColors;
|
||||||
|
const contrast = emulatedMedia.contrast === 'no-override' ? undefined : emulatedMedia.contrast;
|
||||||
await this._session.send('Page.setEmulatedMedia', {
|
await this._session.send('Page.setEmulatedMedia', {
|
||||||
// Empty string means reset.
|
// Empty string means reset.
|
||||||
type: emulatedMedia.media === 'no-override' ? '' : emulatedMedia.media,
|
type: emulatedMedia.media === 'no-override' ? '' : emulatedMedia.media,
|
||||||
colorScheme,
|
colorScheme,
|
||||||
reducedMotion,
|
reducedMotion,
|
||||||
forcedColors,
|
forcedColors,
|
||||||
|
contrast,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -107,6 +107,7 @@ type EmulatedMedia = {
|
||||||
colorScheme: types.ColorScheme;
|
colorScheme: types.ColorScheme;
|
||||||
reducedMotion: types.ReducedMotion;
|
reducedMotion: types.ReducedMotion;
|
||||||
forcedColors: types.ForcedColors;
|
forcedColors: types.ForcedColors;
|
||||||
|
contrast: types.Contrast;
|
||||||
};
|
};
|
||||||
|
|
||||||
type ExpectScreenshotOptions = ImageComparatorOptions & ScreenshotOptions & {
|
type ExpectScreenshotOptions = ImageComparatorOptions & ScreenshotOptions & {
|
||||||
|
|
@ -530,6 +531,8 @@ export class Page extends SdkObject {
|
||||||
this._emulatedMedia.reducedMotion = options.reducedMotion;
|
this._emulatedMedia.reducedMotion = options.reducedMotion;
|
||||||
if (options.forcedColors !== undefined)
|
if (options.forcedColors !== undefined)
|
||||||
this._emulatedMedia.forcedColors = options.forcedColors;
|
this._emulatedMedia.forcedColors = options.forcedColors;
|
||||||
|
if (options.contrast !== undefined)
|
||||||
|
this._emulatedMedia.contrast = options.contrast;
|
||||||
|
|
||||||
await this._delegate.updateEmulateMedia();
|
await this._delegate.updateEmulateMedia();
|
||||||
}
|
}
|
||||||
|
|
@ -541,6 +544,7 @@ export class Page extends SdkObject {
|
||||||
colorScheme: this._emulatedMedia.colorScheme !== undefined ? this._emulatedMedia.colorScheme : contextOptions.colorScheme ?? 'light',
|
colorScheme: this._emulatedMedia.colorScheme !== undefined ? this._emulatedMedia.colorScheme : contextOptions.colorScheme ?? 'light',
|
||||||
reducedMotion: this._emulatedMedia.reducedMotion !== undefined ? this._emulatedMedia.reducedMotion : contextOptions.reducedMotion ?? 'no-preference',
|
reducedMotion: this._emulatedMedia.reducedMotion !== undefined ? this._emulatedMedia.reducedMotion : contextOptions.reducedMotion ?? 'no-preference',
|
||||||
forcedColors: this._emulatedMedia.forcedColors !== undefined ? this._emulatedMedia.forcedColors : contextOptions.forcedColors ?? 'none',
|
forcedColors: this._emulatedMedia.forcedColors !== undefined ? this._emulatedMedia.forcedColors : contextOptions.forcedColors ?? 'none',
|
||||||
|
contrast: this._emulatedMedia.contrast !== undefined ? this._emulatedMedia.contrast : contextOptions.contrast ?? 'no-preference',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,8 @@ export type ReducedMotion = 'no-preference' | 'reduce' | 'no-override';
|
||||||
|
|
||||||
export type ForcedColors = 'active' | 'none' | 'no-override';
|
export type ForcedColors = 'active' | 'none' | 'no-override';
|
||||||
|
|
||||||
|
export type Contrast = 'no-preference' | 'more' | 'no-override';
|
||||||
|
|
||||||
export type DeviceDescriptor = {
|
export type DeviceDescriptor = {
|
||||||
userAgent: string,
|
userAgent: string,
|
||||||
viewport: Size,
|
viewport: Size,
|
||||||
|
|
|
||||||
|
|
@ -191,8 +191,8 @@ export class WKPage implements PageDelegate {
|
||||||
if (contextOptions.userAgent)
|
if (contextOptions.userAgent)
|
||||||
promises.push(this.updateUserAgent());
|
promises.push(this.updateUserAgent());
|
||||||
const emulatedMedia = this._page.emulatedMedia();
|
const emulatedMedia = this._page.emulatedMedia();
|
||||||
if (emulatedMedia.media || emulatedMedia.colorScheme || emulatedMedia.reducedMotion || emulatedMedia.forcedColors)
|
if (emulatedMedia.media || emulatedMedia.colorScheme || emulatedMedia.reducedMotion || emulatedMedia.forcedColors || emulatedMedia.contrast)
|
||||||
promises.push(WKPage._setEmulateMedia(session, emulatedMedia.media, emulatedMedia.colorScheme, emulatedMedia.reducedMotion, emulatedMedia.forcedColors));
|
promises.push(WKPage._setEmulateMedia(session, emulatedMedia.media, emulatedMedia.colorScheme, emulatedMedia.reducedMotion, emulatedMedia.forcedColors, emulatedMedia.contrast));
|
||||||
const bootstrapScript = this._calculateBootstrapScript();
|
const bootstrapScript = this._calculateBootstrapScript();
|
||||||
if (bootstrapScript.length)
|
if (bootstrapScript.length)
|
||||||
promises.push(session.send('Page.setBootstrapScript', { source: bootstrapScript }));
|
promises.push(session.send('Page.setBootstrapScript', { source: bootstrapScript }));
|
||||||
|
|
@ -615,7 +615,7 @@ export class WKPage implements PageDelegate {
|
||||||
await this._page._onFileChooserOpened(handle);
|
await this._page._onFileChooserOpened(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async _setEmulateMedia(session: WKSession, mediaType: types.MediaType, colorScheme: types.ColorScheme, reducedMotion: types.ReducedMotion, forcedColors: types.ForcedColors): Promise<void> {
|
private static async _setEmulateMedia(session: WKSession, mediaType: types.MediaType, colorScheme: types.ColorScheme, reducedMotion: types.ReducedMotion, forcedColors: types.ForcedColors, contrast: types.Contrast): Promise<void> {
|
||||||
const promises = [];
|
const promises = [];
|
||||||
promises.push(session.send('Page.setEmulatedMedia', { media: mediaType === 'no-override' ? '' : mediaType }));
|
promises.push(session.send('Page.setEmulatedMedia', { media: mediaType === 'no-override' ? '' : mediaType }));
|
||||||
let appearance: any = undefined;
|
let appearance: any = undefined;
|
||||||
|
|
@ -639,6 +639,13 @@ export class WKPage implements PageDelegate {
|
||||||
case 'no-override': forcedColorsWk = undefined; break;
|
case 'no-override': forcedColorsWk = undefined; break;
|
||||||
}
|
}
|
||||||
promises.push(session.send('Page.setForcedColors', { forcedColors: forcedColorsWk }));
|
promises.push(session.send('Page.setForcedColors', { forcedColors: forcedColorsWk }));
|
||||||
|
let contrastWk: any = undefined;
|
||||||
|
switch (contrast) {
|
||||||
|
case 'more': contrastWk = 'More'; break;
|
||||||
|
case 'no-preference': contrastWk = 'NoPreference'; break;
|
||||||
|
case 'no-override': contrastWk = undefined; break;
|
||||||
|
}
|
||||||
|
promises.push(session.send('Page.overrideUserPreference', { name: 'PrefersContrast', value: contrastWk }));
|
||||||
await Promise.all(promises);
|
await Promise.all(promises);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -661,7 +668,8 @@ export class WKPage implements PageDelegate {
|
||||||
const colorScheme = emulatedMedia.colorScheme;
|
const colorScheme = emulatedMedia.colorScheme;
|
||||||
const reducedMotion = emulatedMedia.reducedMotion;
|
const reducedMotion = emulatedMedia.reducedMotion;
|
||||||
const forcedColors = emulatedMedia.forcedColors;
|
const forcedColors = emulatedMedia.forcedColors;
|
||||||
await this._forAllSessions(session => WKPage._setEmulateMedia(session, emulatedMedia.media, colorScheme, reducedMotion, forcedColors));
|
const contrast = emulatedMedia.contrast;
|
||||||
|
await this._forAllSessions(session => WKPage._setEmulateMedia(session, emulatedMedia.media, colorScheme, reducedMotion, forcedColors, contrast));
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateEmulatedViewportSize(): Promise<void> {
|
async updateEmulatedViewportSize(): Promise<void> {
|
||||||
|
|
|
||||||
34
packages/playwright-core/types/types.d.ts
vendored
34
packages/playwright-core/types/types.d.ts
vendored
|
|
@ -2565,6 +2565,12 @@ export interface Page {
|
||||||
*/
|
*/
|
||||||
colorScheme?: null|"light"|"dark"|"no-preference";
|
colorScheme?: null|"light"|"dark"|"no-preference";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emulates `'prefers-contrast'` media feature, supported values are `'no-preference'`, `'more'`. Passing `null`
|
||||||
|
* disables contrast emulation.
|
||||||
|
*/
|
||||||
|
contrast?: null|"no-preference"|"more";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Emulates `'forced-colors'` media feature, supported values are `'active'` and `'none'`. Passing `null` disables
|
* Emulates `'forced-colors'` media feature, supported values are `'active'` and `'none'`. Passing `null` disables
|
||||||
* forced colors emulation.
|
* forced colors emulation.
|
||||||
|
|
@ -9770,6 +9776,13 @@ export interface Browser {
|
||||||
*/
|
*/
|
||||||
colorScheme?: null|"light"|"dark"|"no-preference";
|
colorScheme?: null|"light"|"dark"|"no-preference";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emulates `'prefers-contrast'` media feature, supported values are `'no-preference'`, `'more'`. See
|
||||||
|
* [page.emulateMedia([options])](https://playwright.dev/docs/api/class-page#page-emulate-media) for more details.
|
||||||
|
* Passing `null` resets emulation to system defaults. Defaults to `'no-preference'`.
|
||||||
|
*/
|
||||||
|
contrast?: null|"no-preference"|"more";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify device scale factor (can be thought of as dpr). Defaults to `1`. Learn more about
|
* Specify device scale factor (can be thought of as dpr). Defaults to `1`. Learn more about
|
||||||
* [emulating devices with device scale factor](https://playwright.dev/docs/emulation#devices).
|
* [emulating devices with device scale factor](https://playwright.dev/docs/emulation#devices).
|
||||||
|
|
@ -14797,6 +14810,13 @@ export interface BrowserType<Unused = {}> {
|
||||||
*/
|
*/
|
||||||
colorScheme?: null|"light"|"dark"|"no-preference";
|
colorScheme?: null|"light"|"dark"|"no-preference";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emulates `'prefers-contrast'` media feature, supported values are `'no-preference'`, `'more'`. See
|
||||||
|
* [page.emulateMedia([options])](https://playwright.dev/docs/api/class-page#page-emulate-media) for more details.
|
||||||
|
* Passing `null` resets emulation to system defaults. Defaults to `'no-preference'`.
|
||||||
|
*/
|
||||||
|
contrast?: null|"no-preference"|"more";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify device scale factor (can be thought of as dpr). Defaults to `1`. Learn more about
|
* Specify device scale factor (can be thought of as dpr). Defaults to `1`. Learn more about
|
||||||
* [emulating devices with device scale factor](https://playwright.dev/docs/emulation#devices).
|
* [emulating devices with device scale factor](https://playwright.dev/docs/emulation#devices).
|
||||||
|
|
@ -16609,6 +16629,13 @@ export interface AndroidDevice {
|
||||||
*/
|
*/
|
||||||
colorScheme?: null|"light"|"dark"|"no-preference";
|
colorScheme?: null|"light"|"dark"|"no-preference";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emulates `'prefers-contrast'` media feature, supported values are `'no-preference'`, `'more'`. See
|
||||||
|
* [page.emulateMedia([options])](https://playwright.dev/docs/api/class-page#page-emulate-media) for more details.
|
||||||
|
* Passing `null` resets emulation to system defaults. Defaults to `'no-preference'`.
|
||||||
|
*/
|
||||||
|
contrast?: null|"no-preference"|"more";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify device scale factor (can be thought of as dpr). Defaults to `1`. Learn more about
|
* Specify device scale factor (can be thought of as dpr). Defaults to `1`. Learn more about
|
||||||
* [emulating devices with device scale factor](https://playwright.dev/docs/emulation#devices).
|
* [emulating devices with device scale factor](https://playwright.dev/docs/emulation#devices).
|
||||||
|
|
@ -21969,6 +21996,13 @@ export interface BrowserContextOptions {
|
||||||
*/
|
*/
|
||||||
colorScheme?: null|"light"|"dark"|"no-preference";
|
colorScheme?: null|"light"|"dark"|"no-preference";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emulates `'prefers-contrast'` media feature, supported values are `'no-preference'`, `'more'`. See
|
||||||
|
* [page.emulateMedia([options])](https://playwright.dev/docs/api/class-page#page-emulate-media) for more details.
|
||||||
|
* Passing `null` resets emulation to system defaults. Defaults to `'no-preference'`.
|
||||||
|
*/
|
||||||
|
contrast?: null|"no-preference"|"more";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify device scale factor (can be thought of as dpr). Defaults to `1`. Learn more about
|
* Specify device scale factor (can be thought of as dpr). Defaults to `1`. Learn more about
|
||||||
* [emulating devices with device scale factor](https://playwright.dev/docs/emulation#devices).
|
* [emulating devices with device scale factor](https://playwright.dev/docs/emulation#devices).
|
||||||
|
|
|
||||||
10
packages/protocol/src/channels.d.ts
vendored
10
packages/protocol/src/channels.d.ts
vendored
|
|
@ -1006,6 +1006,7 @@ export type BrowserTypeLaunchPersistentContextParams = {
|
||||||
reducedMotion?: 'reduce' | 'no-preference' | 'no-override',
|
reducedMotion?: 'reduce' | 'no-preference' | 'no-override',
|
||||||
forcedColors?: 'active' | 'none' | 'no-override',
|
forcedColors?: 'active' | 'none' | 'no-override',
|
||||||
acceptDownloads?: 'accept' | 'deny' | 'internal-browser-default',
|
acceptDownloads?: 'accept' | 'deny' | 'internal-browser-default',
|
||||||
|
contrast?: 'no-preference' | 'more' | 'no-override',
|
||||||
baseURL?: string,
|
baseURL?: string,
|
||||||
recordVideo?: {
|
recordVideo?: {
|
||||||
dir: string,
|
dir: string,
|
||||||
|
|
@ -1086,6 +1087,7 @@ export type BrowserTypeLaunchPersistentContextOptions = {
|
||||||
reducedMotion?: 'reduce' | 'no-preference' | 'no-override',
|
reducedMotion?: 'reduce' | 'no-preference' | 'no-override',
|
||||||
forcedColors?: 'active' | 'none' | 'no-override',
|
forcedColors?: 'active' | 'none' | 'no-override',
|
||||||
acceptDownloads?: 'accept' | 'deny' | 'internal-browser-default',
|
acceptDownloads?: 'accept' | 'deny' | 'internal-browser-default',
|
||||||
|
contrast?: 'no-preference' | 'more' | 'no-override',
|
||||||
baseURL?: string,
|
baseURL?: string,
|
||||||
recordVideo?: {
|
recordVideo?: {
|
||||||
dir: string,
|
dir: string,
|
||||||
|
|
@ -1201,6 +1203,7 @@ export type BrowserNewContextParams = {
|
||||||
reducedMotion?: 'reduce' | 'no-preference' | 'no-override',
|
reducedMotion?: 'reduce' | 'no-preference' | 'no-override',
|
||||||
forcedColors?: 'active' | 'none' | 'no-override',
|
forcedColors?: 'active' | 'none' | 'no-override',
|
||||||
acceptDownloads?: 'accept' | 'deny' | 'internal-browser-default',
|
acceptDownloads?: 'accept' | 'deny' | 'internal-browser-default',
|
||||||
|
contrast?: 'no-preference' | 'more' | 'no-override',
|
||||||
baseURL?: string,
|
baseURL?: string,
|
||||||
recordVideo?: {
|
recordVideo?: {
|
||||||
dir: string,
|
dir: string,
|
||||||
|
|
@ -1267,6 +1270,7 @@ export type BrowserNewContextOptions = {
|
||||||
reducedMotion?: 'reduce' | 'no-preference' | 'no-override',
|
reducedMotion?: 'reduce' | 'no-preference' | 'no-override',
|
||||||
forcedColors?: 'active' | 'none' | 'no-override',
|
forcedColors?: 'active' | 'none' | 'no-override',
|
||||||
acceptDownloads?: 'accept' | 'deny' | 'internal-browser-default',
|
acceptDownloads?: 'accept' | 'deny' | 'internal-browser-default',
|
||||||
|
contrast?: 'no-preference' | 'more' | 'no-override',
|
||||||
baseURL?: string,
|
baseURL?: string,
|
||||||
recordVideo?: {
|
recordVideo?: {
|
||||||
dir: string,
|
dir: string,
|
||||||
|
|
@ -1336,6 +1340,7 @@ export type BrowserNewContextForReuseParams = {
|
||||||
reducedMotion?: 'reduce' | 'no-preference' | 'no-override',
|
reducedMotion?: 'reduce' | 'no-preference' | 'no-override',
|
||||||
forcedColors?: 'active' | 'none' | 'no-override',
|
forcedColors?: 'active' | 'none' | 'no-override',
|
||||||
acceptDownloads?: 'accept' | 'deny' | 'internal-browser-default',
|
acceptDownloads?: 'accept' | 'deny' | 'internal-browser-default',
|
||||||
|
contrast?: 'no-preference' | 'more' | 'no-override',
|
||||||
baseURL?: string,
|
baseURL?: string,
|
||||||
recordVideo?: {
|
recordVideo?: {
|
||||||
dir: string,
|
dir: string,
|
||||||
|
|
@ -1402,6 +1407,7 @@ export type BrowserNewContextForReuseOptions = {
|
||||||
reducedMotion?: 'reduce' | 'no-preference' | 'no-override',
|
reducedMotion?: 'reduce' | 'no-preference' | 'no-override',
|
||||||
forcedColors?: 'active' | 'none' | 'no-override',
|
forcedColors?: 'active' | 'none' | 'no-override',
|
||||||
acceptDownloads?: 'accept' | 'deny' | 'internal-browser-default',
|
acceptDownloads?: 'accept' | 'deny' | 'internal-browser-default',
|
||||||
|
contrast?: 'no-preference' | 'more' | 'no-override',
|
||||||
baseURL?: string,
|
baseURL?: string,
|
||||||
recordVideo?: {
|
recordVideo?: {
|
||||||
dir: string,
|
dir: string,
|
||||||
|
|
@ -2063,12 +2069,14 @@ export type PageEmulateMediaParams = {
|
||||||
colorScheme?: 'dark' | 'light' | 'no-preference' | 'no-override',
|
colorScheme?: 'dark' | 'light' | 'no-preference' | 'no-override',
|
||||||
reducedMotion?: 'reduce' | 'no-preference' | 'no-override',
|
reducedMotion?: 'reduce' | 'no-preference' | 'no-override',
|
||||||
forcedColors?: 'active' | 'none' | 'no-override',
|
forcedColors?: 'active' | 'none' | 'no-override',
|
||||||
|
contrast?: 'no-preference' | 'more' | 'no-override',
|
||||||
};
|
};
|
||||||
export type PageEmulateMediaOptions = {
|
export type PageEmulateMediaOptions = {
|
||||||
media?: 'screen' | 'print' | 'no-override',
|
media?: 'screen' | 'print' | 'no-override',
|
||||||
colorScheme?: 'dark' | 'light' | 'no-preference' | 'no-override',
|
colorScheme?: 'dark' | 'light' | 'no-preference' | 'no-override',
|
||||||
reducedMotion?: 'reduce' | 'no-preference' | 'no-override',
|
reducedMotion?: 'reduce' | 'no-preference' | 'no-override',
|
||||||
forcedColors?: 'active' | 'none' | 'no-override',
|
forcedColors?: 'active' | 'none' | 'no-override',
|
||||||
|
contrast?: 'no-preference' | 'more' | 'no-override',
|
||||||
};
|
};
|
||||||
export type PageEmulateMediaResult = void;
|
export type PageEmulateMediaResult = void;
|
||||||
export type PageExposeBindingParams = {
|
export type PageExposeBindingParams = {
|
||||||
|
|
@ -4761,6 +4769,7 @@ export type AndroidDeviceLaunchBrowserParams = {
|
||||||
reducedMotion?: 'reduce' | 'no-preference' | 'no-override',
|
reducedMotion?: 'reduce' | 'no-preference' | 'no-override',
|
||||||
forcedColors?: 'active' | 'none' | 'no-override',
|
forcedColors?: 'active' | 'none' | 'no-override',
|
||||||
acceptDownloads?: 'accept' | 'deny' | 'internal-browser-default',
|
acceptDownloads?: 'accept' | 'deny' | 'internal-browser-default',
|
||||||
|
contrast?: 'no-preference' | 'more' | 'no-override',
|
||||||
baseURL?: string,
|
baseURL?: string,
|
||||||
recordVideo?: {
|
recordVideo?: {
|
||||||
dir: string,
|
dir: string,
|
||||||
|
|
@ -4825,6 +4834,7 @@ export type AndroidDeviceLaunchBrowserOptions = {
|
||||||
reducedMotion?: 'reduce' | 'no-preference' | 'no-override',
|
reducedMotion?: 'reduce' | 'no-preference' | 'no-override',
|
||||||
forcedColors?: 'active' | 'none' | 'no-override',
|
forcedColors?: 'active' | 'none' | 'no-override',
|
||||||
acceptDownloads?: 'accept' | 'deny' | 'internal-browser-default',
|
acceptDownloads?: 'accept' | 'deny' | 'internal-browser-default',
|
||||||
|
contrast?: 'no-preference' | 'more' | 'no-override',
|
||||||
baseURL?: string,
|
baseURL?: string,
|
||||||
recordVideo?: {
|
recordVideo?: {
|
||||||
dir: string,
|
dir: string,
|
||||||
|
|
|
||||||
|
|
@ -508,6 +508,12 @@ ContextOptions:
|
||||||
- accept
|
- accept
|
||||||
- deny
|
- deny
|
||||||
- internal-browser-default
|
- internal-browser-default
|
||||||
|
contrast:
|
||||||
|
type: enum?
|
||||||
|
literals:
|
||||||
|
- no-preference
|
||||||
|
- more
|
||||||
|
- no-override
|
||||||
baseURL: string?
|
baseURL: string?
|
||||||
recordVideo:
|
recordVideo:
|
||||||
type: object?
|
type: object?
|
||||||
|
|
@ -1420,6 +1426,12 @@ Page:
|
||||||
- active
|
- active
|
||||||
- none
|
- none
|
||||||
- no-override
|
- no-override
|
||||||
|
contrast:
|
||||||
|
type: enum?
|
||||||
|
literals:
|
||||||
|
- no-preference
|
||||||
|
- more
|
||||||
|
- no-override
|
||||||
flags:
|
flags:
|
||||||
snapshot: true
|
snapshot: true
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,12 @@ it('should support forcedColors option', async ({ launchPersistent, browserName
|
||||||
expect(await page.evaluate(() => matchMedia('(forced-colors: none)').matches)).toBe(false);
|
expect(await page.evaluate(() => matchMedia('(forced-colors: none)').matches)).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should support contrast option', async ({ launchPersistent }) => {
|
||||||
|
const { page } = await launchPersistent({ contrast: 'more' });
|
||||||
|
expect.soft(await page.evaluate(() => matchMedia('(prefers-contrast: more)').matches)).toBe(true);
|
||||||
|
expect.soft(await page.evaluate(() => matchMedia('(prefers-contrast: no-preference)').matches)).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
it('should support timezoneId option', async ({ launchPersistent, browserName }) => {
|
it('should support timezoneId option', async ({ launchPersistent, browserName }) => {
|
||||||
const { page } = await launchPersistent({ locale: 'en-US', timezoneId: 'America/Jamaica' });
|
const { page } = await launchPersistent({ locale: 'en-US', timezoneId: 'America/Jamaica' });
|
||||||
expect(await page.evaluate(() => new Date(1479579154987).toString())).toBe('Sat Nov 19 2016 13:12:34 GMT-0500 (Eastern Standard Time)');
|
expect(await page.evaluate(() => new Date(1479579154987).toString())).toBe('Sat Nov 19 2016 13:12:34 GMT-0500 (Eastern Standard Time)');
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,24 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { test as it, expect } from './pageTest';
|
import type { Page } from 'packages/playwright-test';
|
||||||
|
import { test as it, expect as baseExpect } from './pageTest';
|
||||||
|
|
||||||
|
const expect = baseExpect.extend({
|
||||||
|
async toMatchMedia(page: Page, mediaQuery: string) {
|
||||||
|
const pass = await page.evaluate(mediaQuery => matchMedia(mediaQuery).matches, mediaQuery).catch(() => false);
|
||||||
|
return {
|
||||||
|
message() {
|
||||||
|
if (pass)
|
||||||
|
return `Expected "${mediaQuery}" not to match, but it did`;
|
||||||
|
else
|
||||||
|
return `Expected "${mediaQuery}" to match, but it did not`;
|
||||||
|
},
|
||||||
|
pass,
|
||||||
|
name: 'toMatchMedia',
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
it('should emulate type @smoke', async ({ page }) => {
|
it('should emulate type @smoke', async ({ page }) => {
|
||||||
expect(await page.evaluate(() => matchMedia('screen').matches)).toBe(true);
|
expect(await page.evaluate(() => matchMedia('screen').matches)).toBe(true);
|
||||||
|
|
@ -158,3 +175,15 @@ it('should emulate forcedColors ', async ({ page, browserName }) => {
|
||||||
await page.emulateMedia({ forcedColors: null });
|
await page.emulateMedia({ forcedColors: null });
|
||||||
expect(await page.evaluate(() => matchMedia('(forced-colors: none)').matches)).toBe(true);
|
expect(await page.evaluate(() => matchMedia('(forced-colors: none)').matches)).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should emulate contrast ', async ({ page }) => {
|
||||||
|
await expect(page).toMatchMedia('(prefers-contrast: no-preference)');
|
||||||
|
await page.emulateMedia({ contrast: 'no-preference' });
|
||||||
|
await expect(page).toMatchMedia('(prefers-contrast: no-preference)');
|
||||||
|
await expect(page).not.toMatchMedia('(prefers-contrast: more)');
|
||||||
|
await page.emulateMedia({ contrast: 'more' });
|
||||||
|
await expect(page).not.toMatchMedia('(prefers-contrast: no-preference)');
|
||||||
|
await expect(page).toMatchMedia('(prefers-contrast: more)');
|
||||||
|
await page.emulateMedia({ contrast: null });
|
||||||
|
await expect(page).toMatchMedia('(prefers-contrast: no-preference)');
|
||||||
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue