Skip to content

Commit

Permalink
fix(colorScheme): make light scheme default on all browsers (#1668)
Browse files Browse the repository at this point in the history
  • Loading branch information
pavelfeldman committed Apr 7, 2020
1 parent cd39053 commit 3dc14ed
Show file tree
Hide file tree
Showing 9 changed files with 76 additions and 13 deletions.
2 changes: 2 additions & 0 deletions docs/api.md
Expand Up @@ -215,6 +215,7 @@ Indicates that the browser is connected.
- `httpCredentials` <[Object]> Credentials for [HTTP authentication](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication).
- `username` <[string]>
- `password` <[string]>
- `colorScheme` <"dark"|"light"|"no-preference"> Emulates `'prefers-colors-scheme'` media feature, supported values are `'light'`, `'dark'`, `'no-preference'`. See [page.emulateMedia(options)](#pageemulatemediaoptions) for more details. Defaults to '`light`'.
- returns: <[Promise]<[BrowserContext]>>

Creates a new browser context. It won't share cookies/cache with other browser contexts.
Expand Down Expand Up @@ -255,6 +256,7 @@ Creates a new browser context. It won't share cookies/cache with other browser c
- `httpCredentials` <[Object]> Credentials for [HTTP authentication](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication).
- `username` <[string]>
- `password` <[string]>
- `colorScheme` <"dark"|"light"|"no-preference"> Emulates `'prefers-colors-scheme'` media feature, supported values are `'light'`, `'dark'`, `'no-preference'`. See [page.emulateMedia(options)](#pageemulatemediaoptions) for more details. Defaults to '`light`'.
- returns: <[Promise]<[Page]>>

Creates a new page in a new browser context. Closing this page will close the context as well.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -9,7 +9,7 @@
"main": "index.js",
"playwright": {
"chromium_revision": "754895",
"firefox_revision": "1071",
"firefox_revision": "1072",
"webkit_revision": "1188"
},
"scripts": {
Expand Down
1 change: 1 addition & 0 deletions src/browserContext.ts
Expand Up @@ -40,6 +40,7 @@ export type BrowserContextOptions = {
deviceScaleFactor?: number,
isMobile?: boolean,
hasTouch?: boolean,
colorScheme?: types.ColorScheme,
acceptDownloads?: boolean
};

Expand Down
10 changes: 6 additions & 4 deletions src/chromium/crPage.ts
Expand Up @@ -150,8 +150,8 @@ export class CRPage implements PageDelegate {
await this._mainFrameSession._updateViewport();
}

async setEmulateMedia(mediaType: types.MediaType | null, colorScheme: types.ColorScheme | null): Promise<void> {
await this._forAllFrameSessions(frame => frame._setEmulateMedia(mediaType, colorScheme));
async updateEmulateMedia(): Promise<void> {
await this._forAllFrameSessions(frame => frame._updateEmulateMedia());
}

async updateRequestInterception(): Promise<void> {
Expand Down Expand Up @@ -422,6 +422,7 @@ class FrameSession {
promises.push(this._updateRequestInterception());
promises.push(this._updateOffline());
promises.push(this._updateHttpCredentials());
promises.push(this._updateEmulateMedia());
for (const binding of this._crPage._browserContext._pageBindings.values())
promises.push(this._initBinding(binding));
for (const source of this._crPage._browserContext._evaluateOnNewDocumentSources)
Expand Down Expand Up @@ -687,9 +688,10 @@ class FrameSession {
await Promise.all(promises);
}

async _setEmulateMedia(mediaType: types.MediaType | null, colorScheme: types.ColorScheme | null): Promise<void> {
async _updateEmulateMedia(): Promise<void> {
const colorScheme = this._page._state.colorScheme || this._crPage._browserContext._options.colorScheme || 'light';
const features = colorScheme ? [{ name: 'prefers-color-scheme', value: colorScheme }] : [];
await this._client.send('Emulation.setEmulatedMedia', { media: mediaType || '', features });
await this._client.send('Emulation.setEmulatedMedia', { media: this._page._state.mediaType || '', features });
}

async _updateRequestInterception(): Promise<void> {
Expand Down
6 changes: 6 additions & 0 deletions src/firefox/ffBrowser.ts
Expand Up @@ -164,6 +164,8 @@ export class FFBrowserContext extends BrowserContextBase {
await this.setGeolocation(this._options.geolocation);
if (this._options.offline)
await this.setOffline(this._options.offline);
if (this._options.colorScheme)
await this._setColorScheme(this._options.colorScheme);
}

_ffPages(): FFPage[] {
Expand Down Expand Up @@ -259,6 +261,10 @@ export class FFBrowserContext extends BrowserContextBase {
await this._browser._connection.send('Browser.setOnlineOverride', { browserContextId: this._browserContextId || undefined, override: offline ? 'offline' : 'online' });
}

async _setColorScheme(colorScheme?: types.ColorScheme): Promise<void> {
await this._browser._connection.send('Browser.setColorScheme', { browserContextId: this._browserContextId || undefined, colorScheme });
}

async setHTTPCredentials(httpCredentials: types.Credentials | null): Promise<void> {
this._options.httpCredentials = httpCredentials || undefined;
await this._browser._connection.send('Browser.setHTTPCredentials', { browserContextId: this._browserContextId || undefined, credentials: httpCredentials });
Expand Down
7 changes: 4 additions & 3 deletions src/firefox/ffPage.ts
Expand Up @@ -284,10 +284,11 @@ export class FFPage implements PageDelegate {
});
}

async setEmulateMedia(mediaType: types.MediaType | null, colorScheme: types.ColorScheme | null): Promise<void> {
async updateEmulateMedia(): Promise<void> {
const colorScheme = this._page._state.colorScheme || this._browserContext._options.colorScheme || 'light';
await this._session.send('Page.setEmulatedMedia', {
type: mediaType === null ? undefined : mediaType,
colorScheme: colorScheme === null ? undefined : colorScheme
type: this._page._state.mediaType === null ? undefined : this._page._state.mediaType,
colorScheme
});
}

Expand Down
4 changes: 2 additions & 2 deletions src/page.ts
Expand Up @@ -48,7 +48,7 @@ export interface PageDelegate {

updateExtraHTTPHeaders(): Promise<void>;
setViewportSize(viewportSize: types.Size): Promise<void>;
setEmulateMedia(mediaType: types.MediaType | null, colorScheme: types.ColorScheme | null): Promise<void>;
updateEmulateMedia(): Promise<void>;
updateRequestInterception(): Promise<void>;
setFileChooserIntercepted(enabled: boolean): Promise<void>;

Expand Down Expand Up @@ -357,7 +357,7 @@ export class Page extends ExtendedEventEmitter {
this._state.mediaType = options.media;
if (options.colorScheme !== undefined)
this._state.colorScheme = options.colorScheme;
await this._delegate.setEmulateMedia(this._state.mediaType, this._state.colorScheme);
await this._delegate.updateEmulateMedia();
}

async setViewportSize(viewportSize: types.Size) {
Expand Down
7 changes: 4 additions & 3 deletions src/webkit/wkPage.ts
Expand Up @@ -162,7 +162,7 @@ export class WKPage implements PageDelegate {
height: this._page._state.viewportSize.height,
}));
}

promises.push(this.updateEmulateMedia());
promises.push(session.send('Network.setExtraHTTPHeaders', { headers: this._calculateExtraHTTPHeaders() }));
if (contextOptions.offline)
promises.push(session.send('Network.setEmulateOfflineState', { offline: true }));
Expand Down Expand Up @@ -492,8 +492,9 @@ export class WKPage implements PageDelegate {
return headers;
}

async setEmulateMedia(mediaType: types.MediaType | null, colorScheme: types.ColorScheme | null): Promise<void> {
await this._forAllSessions(session => WKPage._setEmulateMedia(session, mediaType, colorScheme));
async updateEmulateMedia(): Promise<void> {
const colorScheme = this._page._state.colorScheme || this._browserContext._options.colorScheme || 'light';
await this._forAllSessions(session => WKPage._setEmulateMedia(session, this._page._state.mediaType, colorScheme));
}

async setViewportSize(viewportSize: types.Size): Promise<void> {
Expand Down
50 changes: 50 additions & 0 deletions test/emulation.spec.js
Expand Up @@ -15,6 +15,8 @@
* limitations under the License.
*/

const utils = require('./utils');

/**
* @type {PageTestSuite}
*/
Expand Down Expand Up @@ -236,6 +238,21 @@ module.exports.describe = function({testRunner, expect, playwright, headless, FF
expect(await page.evaluate(() => matchMedia('(prefers-color-scheme: no-preference)').matches)).toBe(true);
}
});
it('should default to light', async({page, server}) => {
expect(await page.evaluate(() => matchMedia('(prefers-color-scheme: light)').matches)).toBe(true);
expect(await page.evaluate(() => matchMedia('(prefers-color-scheme: dark)').matches)).toBe(false);
expect(await page.evaluate(() => matchMedia('(prefers-color-scheme: no-preference)').matches)).toBe(false);

await page.emulateMedia({ colorScheme: 'dark' });
expect(await page.evaluate(() => matchMedia('(prefers-color-scheme: dark)').matches)).toBe(true);
expect(await page.evaluate(() => matchMedia('(prefers-color-scheme: light)').matches)).toBe(false);
expect(await page.evaluate(() => matchMedia('(prefers-color-scheme: no-preference)').matches)).toBe(false);

await page.emulateMedia({ colorScheme: null });
expect(await page.evaluate(() => matchMedia('(prefers-color-scheme: dark)').matches)).toBe(false);
expect(await page.evaluate(() => matchMedia('(prefers-color-scheme: light)').matches)).toBe(true);
expect(await page.evaluate(() => matchMedia('(prefers-color-scheme: no-preference)').matches)).toBe(false);
});
it('should throw in case of bad argument', async({page, server}) => {
let error = null;
await page.emulateMedia({ colorScheme: 'bad' }).catch(e => error = e);
Expand All @@ -253,6 +270,39 @@ module.exports.describe = function({testRunner, expect, playwright, headless, FF
await navigated;
expect(await page.evaluate(() => matchMedia('(prefers-color-scheme: dark)').matches)).toBe(true);
});
it('should work in popup', async({browser, server}) => {
{
const context = await browser.newContext({ colorScheme: 'dark' });
const page = await context.newPage();
await page.goto(server.EMPTY_PAGE);
const [popup] = await Promise.all([
page.waitForEvent('popup'),
page.evaluate(url => { window.open(url); }, server.EMPTY_PAGE),
]);
expect(await popup.evaluate(() => matchMedia('(prefers-color-scheme: light)').matches)).toBe(false);
expect(await popup.evaluate(() => matchMedia('(prefers-color-scheme: dark)').matches)).toBe(true);
await context.close();
}
{
const page = await browser.newPage({ colorScheme: 'light' });
await page.goto(server.EMPTY_PAGE);
const [popup] = await Promise.all([
page.waitForEvent('popup'),
page.evaluate(url => { window.open(url); }, server.EMPTY_PAGE),
]);
expect(await popup.evaluate(() => matchMedia('(prefers-color-scheme: light)').matches)).toBe(true);
expect(await popup.evaluate(() => matchMedia('(prefers-color-scheme: dark)').matches)).toBe(false);
await page.close();
}
});
it('should work in cross-process iframe', async({browser, server}) => {
const page = await browser.newPage({ colorScheme: 'dark' });
await page.goto(server.EMPTY_PAGE);
await utils.attachFrame(page, 'frame1', server.CROSS_PROCESS_PREFIX + '/empty.html');
const frame = page.frames()[1];
expect(await frame.evaluate(() => matchMedia('(prefers-color-scheme: dark)').matches)).toBe(true);
await page.close();
});
});

describe('BrowserContext({timezoneId})', function() {
Expand Down

0 comments on commit 3dc14ed

Please sign in to comment.