Skip to content

Commit 3dc14ed

Browse files
authored
fix(colorScheme): make light scheme default on all browsers (#1668)
1 parent cd39053 commit 3dc14ed

File tree

9 files changed

+76
-13
lines changed

9 files changed

+76
-13
lines changed

docs/api.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ Indicates that the browser is connected.
215215
- `httpCredentials` <[Object]> Credentials for [HTTP authentication](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication).
216216
- `username` <[string]>
217217
- `password` <[string]>
218+
- `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`'.
218219
- returns: <[Promise]<[BrowserContext]>>
219220

220221
Creates a new browser context. It won't share cookies/cache with other browser contexts.
@@ -255,6 +256,7 @@ Creates a new browser context. It won't share cookies/cache with other browser c
255256
- `httpCredentials` <[Object]> Credentials for [HTTP authentication](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication).
256257
- `username` <[string]>
257258
- `password` <[string]>
259+
- `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`'.
258260
- returns: <[Promise]<[Page]>>
259261

260262
Creates a new page in a new browser context. Closing this page will close the context as well.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"main": "index.js",
1010
"playwright": {
1111
"chromium_revision": "754895",
12-
"firefox_revision": "1071",
12+
"firefox_revision": "1072",
1313
"webkit_revision": "1188"
1414
},
1515
"scripts": {

src/browserContext.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ export type BrowserContextOptions = {
4040
deviceScaleFactor?: number,
4141
isMobile?: boolean,
4242
hasTouch?: boolean,
43+
colorScheme?: types.ColorScheme,
4344
acceptDownloads?: boolean
4445
};
4546

src/chromium/crPage.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -150,8 +150,8 @@ export class CRPage implements PageDelegate {
150150
await this._mainFrameSession._updateViewport();
151151
}
152152

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

157157
async updateRequestInterception(): Promise<void> {
@@ -422,6 +422,7 @@ class FrameSession {
422422
promises.push(this._updateRequestInterception());
423423
promises.push(this._updateOffline());
424424
promises.push(this._updateHttpCredentials());
425+
promises.push(this._updateEmulateMedia());
425426
for (const binding of this._crPage._browserContext._pageBindings.values())
426427
promises.push(this._initBinding(binding));
427428
for (const source of this._crPage._browserContext._evaluateOnNewDocumentSources)
@@ -687,9 +688,10 @@ class FrameSession {
687688
await Promise.all(promises);
688689
}
689690

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

695697
async _updateRequestInterception(): Promise<void> {

src/firefox/ffBrowser.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,8 @@ export class FFBrowserContext extends BrowserContextBase {
164164
await this.setGeolocation(this._options.geolocation);
165165
if (this._options.offline)
166166
await this.setOffline(this._options.offline);
167+
if (this._options.colorScheme)
168+
await this._setColorScheme(this._options.colorScheme);
167169
}
168170

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

264+
async _setColorScheme(colorScheme?: types.ColorScheme): Promise<void> {
265+
await this._browser._connection.send('Browser.setColorScheme', { browserContextId: this._browserContextId || undefined, colorScheme });
266+
}
267+
262268
async setHTTPCredentials(httpCredentials: types.Credentials | null): Promise<void> {
263269
this._options.httpCredentials = httpCredentials || undefined;
264270
await this._browser._connection.send('Browser.setHTTPCredentials', { browserContextId: this._browserContextId || undefined, credentials: httpCredentials });

src/firefox/ffPage.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -284,10 +284,11 @@ export class FFPage implements PageDelegate {
284284
});
285285
}
286286

287-
async setEmulateMedia(mediaType: types.MediaType | null, colorScheme: types.ColorScheme | null): Promise<void> {
287+
async updateEmulateMedia(): Promise<void> {
288+
const colorScheme = this._page._state.colorScheme || this._browserContext._options.colorScheme || 'light';
288289
await this._session.send('Page.setEmulatedMedia', {
289-
type: mediaType === null ? undefined : mediaType,
290-
colorScheme: colorScheme === null ? undefined : colorScheme
290+
type: this._page._state.mediaType === null ? undefined : this._page._state.mediaType,
291+
colorScheme
291292
});
292293
}
293294

src/page.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ export interface PageDelegate {
4848

4949
updateExtraHTTPHeaders(): Promise<void>;
5050
setViewportSize(viewportSize: types.Size): Promise<void>;
51-
setEmulateMedia(mediaType: types.MediaType | null, colorScheme: types.ColorScheme | null): Promise<void>;
51+
updateEmulateMedia(): Promise<void>;
5252
updateRequestInterception(): Promise<void>;
5353
setFileChooserIntercepted(enabled: boolean): Promise<void>;
5454

@@ -357,7 +357,7 @@ export class Page extends ExtendedEventEmitter {
357357
this._state.mediaType = options.media;
358358
if (options.colorScheme !== undefined)
359359
this._state.colorScheme = options.colorScheme;
360-
await this._delegate.setEmulateMedia(this._state.mediaType, this._state.colorScheme);
360+
await this._delegate.updateEmulateMedia();
361361
}
362362

363363
async setViewportSize(viewportSize: types.Size) {

src/webkit/wkPage.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ export class WKPage implements PageDelegate {
162162
height: this._page._state.viewportSize.height,
163163
}));
164164
}
165-
165+
promises.push(this.updateEmulateMedia());
166166
promises.push(session.send('Network.setExtraHTTPHeaders', { headers: this._calculateExtraHTTPHeaders() }));
167167
if (contextOptions.offline)
168168
promises.push(session.send('Network.setEmulateOfflineState', { offline: true }));
@@ -492,8 +492,9 @@ export class WKPage implements PageDelegate {
492492
return headers;
493493
}
494494

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

499500
async setViewportSize(viewportSize: types.Size): Promise<void> {

test/emulation.spec.js

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
* limitations under the License.
1616
*/
1717

18+
const utils = require('./utils');
19+
1820
/**
1921
* @type {PageTestSuite}
2022
*/
@@ -236,6 +238,21 @@ module.exports.describe = function({testRunner, expect, playwright, headless, FF
236238
expect(await page.evaluate(() => matchMedia('(prefers-color-scheme: no-preference)').matches)).toBe(true);
237239
}
238240
});
241+
it('should default to light', async({page, server}) => {
242+
expect(await page.evaluate(() => matchMedia('(prefers-color-scheme: light)').matches)).toBe(true);
243+
expect(await page.evaluate(() => matchMedia('(prefers-color-scheme: dark)').matches)).toBe(false);
244+
expect(await page.evaluate(() => matchMedia('(prefers-color-scheme: no-preference)').matches)).toBe(false);
245+
246+
await page.emulateMedia({ colorScheme: 'dark' });
247+
expect(await page.evaluate(() => matchMedia('(prefers-color-scheme: dark)').matches)).toBe(true);
248+
expect(await page.evaluate(() => matchMedia('(prefers-color-scheme: light)').matches)).toBe(false);
249+
expect(await page.evaluate(() => matchMedia('(prefers-color-scheme: no-preference)').matches)).toBe(false);
250+
251+
await page.emulateMedia({ colorScheme: null });
252+
expect(await page.evaluate(() => matchMedia('(prefers-color-scheme: dark)').matches)).toBe(false);
253+
expect(await page.evaluate(() => matchMedia('(prefers-color-scheme: light)').matches)).toBe(true);
254+
expect(await page.evaluate(() => matchMedia('(prefers-color-scheme: no-preference)').matches)).toBe(false);
255+
});
239256
it('should throw in case of bad argument', async({page, server}) => {
240257
let error = null;
241258
await page.emulateMedia({ colorScheme: 'bad' }).catch(e => error = e);
@@ -253,6 +270,39 @@ module.exports.describe = function({testRunner, expect, playwright, headless, FF
253270
await navigated;
254271
expect(await page.evaluate(() => matchMedia('(prefers-color-scheme: dark)').matches)).toBe(true);
255272
});
273+
it('should work in popup', async({browser, server}) => {
274+
{
275+
const context = await browser.newContext({ colorScheme: 'dark' });
276+
const page = await context.newPage();
277+
await page.goto(server.EMPTY_PAGE);
278+
const [popup] = await Promise.all([
279+
page.waitForEvent('popup'),
280+
page.evaluate(url => { window.open(url); }, server.EMPTY_PAGE),
281+
]);
282+
expect(await popup.evaluate(() => matchMedia('(prefers-color-scheme: light)').matches)).toBe(false);
283+
expect(await popup.evaluate(() => matchMedia('(prefers-color-scheme: dark)').matches)).toBe(true);
284+
await context.close();
285+
}
286+
{
287+
const page = await browser.newPage({ colorScheme: 'light' });
288+
await page.goto(server.EMPTY_PAGE);
289+
const [popup] = await Promise.all([
290+
page.waitForEvent('popup'),
291+
page.evaluate(url => { window.open(url); }, server.EMPTY_PAGE),
292+
]);
293+
expect(await popup.evaluate(() => matchMedia('(prefers-color-scheme: light)').matches)).toBe(true);
294+
expect(await popup.evaluate(() => matchMedia('(prefers-color-scheme: dark)').matches)).toBe(false);
295+
await page.close();
296+
}
297+
});
298+
it('should work in cross-process iframe', async({browser, server}) => {
299+
const page = await browser.newPage({ colorScheme: 'dark' });
300+
await page.goto(server.EMPTY_PAGE);
301+
await utils.attachFrame(page, 'frame1', server.CROSS_PROCESS_PREFIX + '/empty.html');
302+
const frame = page.frames()[1];
303+
expect(await frame.evaluate(() => matchMedia('(prefers-color-scheme: dark)').matches)).toBe(true);
304+
await page.close();
305+
});
256306
});
257307

258308
describe('BrowserContext({timezoneId})', function() {

0 commit comments

Comments
 (0)