From 0b5c0a76ab2bb5048d8d901b9fb1456e39cc2888 Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Fri, 13 Dec 2019 17:34:02 -0800 Subject: [PATCH] feat(webkit): support emulating color scheme (#247) --- src/webkit/FrameManager.ts | 52 ++++++++++++++++++++++++++++---------- test/emulation.spec.js | 13 ++++++---- 2 files changed, 46 insertions(+), 19 deletions(-) diff --git a/src/webkit/FrameManager.ts b/src/webkit/FrameManager.ts index a97e6c5fe0..9564b55997 100644 --- a/src/webkit/FrameManager.ts +++ b/src/webkit/FrameManager.ts @@ -97,13 +97,13 @@ export class FrameManager extends EventEmitter implements PageDelegate { promises.push(session.send('Dialog.enable')); } if (this._page._state.userAgent !== null) - promises.push(session.send('Page.overrideUserAgent', { value: this._page._state.userAgent })); - if (this._page._state.mediaType !== null) - promises.push(session.send('Page.setEmulatedMedia', { media: this._page._state.mediaType || '' })); + promises.push(this._setUserAgent(session, this._page._state.userAgent)); + if (this._page._state.mediaType !== null || this._page._state.mediaColorScheme !== null) + promises.push(this._setEmulateMedia(session, this._page._state.mediaType, this._page._state.mediaColorScheme)); if (this._page._state.javascriptEnabled !== null) - promises.push(session.send('Emulation.setJavaScriptEnabled', { enabled: this._page._state.javascriptEnabled })); + promises.push(this._setJavaScriptEnabled(session, this._page._state.javascriptEnabled)); if (this._page._state.bypassCSP !== null) - promises.push(session.send('Page.setBypassCSP', { enabled: this._page._state.bypassCSP })); + promises.push(this._setBypassCSP(session, this._page._state.bypassCSP)); await Promise.all(promises); } @@ -401,16 +401,46 @@ export class FrameManager extends EventEmitter implements PageDelegate { }); } + private async _setUserAgent(session: TargetSession, userAgent: string): Promise { + await session.send('Page.overrideUserAgent', { value: userAgent }); + } + + private async _setJavaScriptEnabled(session: TargetSession, enabled: boolean): Promise { + await session.send('Emulation.setJavaScriptEnabled', { enabled }); + } + + private async _setBypassCSP(session: TargetSession, enabled: boolean): Promise { + await session.send('Page.setBypassCSP', { enabled }); + } + + private async _setEmulateMedia(session: TargetSession, mediaType: input.MediaType | null, mediaColorScheme: input.MediaColorScheme | null): Promise { + const promises = []; + promises.push(session.send('Page.setEmulatedMedia', { media: mediaType || '' })); + if (mediaColorScheme !== null) { + let appearance: any = ''; + switch (mediaColorScheme) { + case 'light': appearance = 'Light'; break; + case 'dark': appearance = 'Dark'; break; + } + promises.push(session.send('Page.setForcedAppearance', { appearance })); + } + await Promise.all(promises); + } + async setUserAgent(userAgent: string): Promise { - await this._session.send('Page.overrideUserAgent', { value: userAgent }); + await this._setUserAgent(this._session, userAgent); } async setJavaScriptEnabled(enabled: boolean): Promise { - await this._session.send('Emulation.setJavaScriptEnabled', { enabled }); + await this._setJavaScriptEnabled(this._session, enabled); } async setBypassCSP(enabled: boolean): Promise { - await this._session.send('Page.setBypassCSP', { enabled }); + await this._setBypassCSP(this._session, enabled); + } + + async setEmulateMedia(mediaType: input.MediaType | null, mediaColorScheme: input.MediaColorScheme | null): Promise { + await this._setEmulateMedia(this._session, mediaType, mediaColorScheme); } async setViewport(viewport: types.Viewport): Promise { @@ -421,12 +451,6 @@ export class FrameManager extends EventEmitter implements PageDelegate { await this._session.send('Emulation.setDeviceMetricsOverride', { width, height, deviceScaleFactor: viewport.deviceScaleFactor || 1 }); } - async setEmulateMedia(mediaType: input.MediaType | null, mediaColorScheme: input.MediaColorScheme | null): Promise { - if (mediaColorScheme !== null) - throw new Error('Not implemented'); - await this._session.send('Page.setEmulatedMedia', { media: mediaType || '' }); - } - setCacheEnabled(enabled: boolean): Promise { return this._networkManager.setCacheEnabled(enabled); } diff --git a/test/emulation.spec.js b/test/emulation.spec.js index 18b5234aea..8164f94374 100644 --- a/test/emulation.spec.js +++ b/test/emulation.spec.js @@ -118,7 +118,7 @@ module.exports.addTests = function({testRunner, expect, playwright, FFOX, CHROME }); }); - describe.skip(WEBKIT)('Page.emulateMedia colorScheme', function() { + describe('Page.emulateMedia colorScheme', function() { it('should work', async({page, server}) => { await page.emulateMedia({ colorScheme: 'light' }); expect(await page.evaluate(() => matchMedia('(prefers-color-scheme: light)').matches)).toBe(true); @@ -128,10 +128,13 @@ module.exports.addTests = function({testRunner, expect, playwright, FFOX, CHROME 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: 'no-preference' }); - expect(await page.evaluate(() => matchMedia('(prefers-color-scheme: dark)').matches)).toBe(false); - expect(await page.evaluate(() => matchMedia('(prefers-color-scheme: light)').matches)).toBe(false); - expect(await page.evaluate(() => matchMedia('(prefers-color-scheme: no-preference)').matches)).toBe(true); + if (!WEBKIT) { + // WebKit will always provide the value. + await page.emulateMedia({ colorScheme: 'no-preference' }); + expect(await page.evaluate(() => matchMedia('(prefers-color-scheme: dark)').matches)).toBe(false); + expect(await page.evaluate(() => matchMedia('(prefers-color-scheme: light)').matches)).toBe(false); + expect(await page.evaluate(() => matchMedia('(prefers-color-scheme: no-preference)').matches)).toBe(true); + } }); it('should throw in case of bad argument', async({page, server}) => { let error = null;