feat(api): add page.emulateMedia{Type,Features} (#5012)

This commit is contained in:
Mathias Bynens 2019-10-23 13:55:00 +02:00 committed by GitHub
parent 06dbb72c73
commit a86363fda6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 162 additions and 20 deletions

View File

@ -108,7 +108,9 @@
* [page.coverage](#pagecoverage)
* [page.deleteCookie(...cookies)](#pagedeletecookiecookies)
* [page.emulate(options)](#pageemulateoptions)
* [page.emulateMedia(mediaType)](#pageemulatemediamediatype)
* [page.emulateMedia(type)](#pageemulatemediatype)
* [page.emulateMediaFeatures(features)](#pageemulatemediafeaturesfeatures)
* [page.emulateMediaType(type)](#pageemulatemediatypetype)
* [page.evaluate(pageFunction[, ...args])](#pageevaluatepagefunction-args)
* [page.evaluateHandle(pageFunction[, ...args])](#pageevaluatehandlepagefunction-args)
* [page.evaluateOnNewDocument(pageFunction[, ...args])](#pageevaluateonnewdocumentpagefunction-args)
@ -1276,10 +1278,78 @@ puppeteer.launch().then(async browser => {
List of all available devices is available in the source code: [DeviceDescriptors.js](https://github.com/GoogleChrome/puppeteer/blob/master/lib/DeviceDescriptors.js).
#### page.emulateMedia(mediaType)
- `mediaType` <?[string]> Changes the CSS media type of the page. The only allowed values are `'screen'`, `'print'` and `null`. Passing `null` disables media emulation.
#### page.emulateMedia(type)
- `type` <?[string]> Changes the CSS media type of the page. The only allowed values are `'screen'`, `'print'` and `null`. Passing `null` disables CSS media emulation.
- returns: <[Promise]>
**Note:** This method is deprecated, and only kept around as an alias for backwards compatibility. Use [`page.emulateMediaType(type)`](#pageemulatemediatypetype) instead.
#### page.emulateMediaFeatures(features)
- `features` <?[Array]<[Object]>> Given an array of media feature objects, emulates CSS media features on the page. Each media feature object must have the following properties:
- `name` <[string]> The CSS media feature name. Supported names are `'prefers-colors-scheme'` and `'prefers-reduced-motion'`.
- `value` <[string]> The value for the given CSS media feature.
- returns: <[Promise]>
```js
await page.emulateMediaFeatures([{ name: 'prefers-color-scheme', value: 'dark' }]);
await page.evaluate(() => matchMedia('(prefers-color-scheme: dark)').matches));
// → true
await page.evaluate(() => matchMedia('(prefers-color-scheme: light)').matches));
// → false
await page.evaluate(() => matchMedia('(prefers-color-scheme: no-preference)').matches));
// → false
await page.emulateMediaFeatures([{ name: 'prefers-reduced-motion', value: 'reduce' }]);
await page.evaluate(() => matchMedia('(prefers-reduced-motion: reduce)').matches));
// → true
await page.evaluate(() => matchMedia('(prefers-color-scheme: no-preference)').matches));
// → false
await page.emulateMediaFeatures([{ name: 'prefers-reduced-motion', value: 'reduce' }]);
await page.evaluate(() => matchMedia('(prefers-reduced-motion: reduce)').matches));
// → true
await page.evaluate(() => matchMedia('(prefers-color-scheme: no-preference)').matches));
// → false
await page.emulateMediaFeatures([
{ name: 'prefers-color-scheme', value: 'dark' },
{ name: 'prefers-reduced-motion', value: 'reduce' },
]);
await page.evaluate(() => matchMedia('(prefers-color-scheme: dark)').matches));
// → true
await page.evaluate(() => matchMedia('(prefers-color-scheme: light)').matches));
// → false
await page.evaluate(() => matchMedia('(prefers-color-scheme: no-preference)').matches));
// → false
await page.evaluate(() => matchMedia('(prefers-reduced-motion: reduce)').matches));
// → true
await page.evaluate(() => matchMedia('(prefers-color-scheme: no-preference)').matches));
// → false
```
#### page.emulateMediaType(type)
- `type` <?[string]> Changes the CSS media type of the page. The only allowed values are `'screen'`, `'print'` and `null`. Passing `null` disables CSS media emulation.
- returns: <[Promise]>
```js
await page.evaluate(() => matchMedia('screen').matches));
// → true
await page.evaluate(() => matchMedia('print').matches));
// → true
await page.emulateMediaType('print');
await page.evaluate(() => matchMedia('screen').matches));
// → false
await page.evaluate(() => matchMedia('print').matches));
// → true
await page.emulateMediaType(null);
await page.evaluate(() => matchMedia('screen').matches));
// → true
await page.evaluate(() => matchMedia('print').matches));
// → true
```
#### page.evaluate(pageFunction[, ...args])
- `pageFunction` <[function]|[string]> Function to be evaluated in the page context
- `...args` <...[Serializable]|[JSHandle]> Arguments to pass to `pageFunction`

View File

@ -150,11 +150,11 @@ class Page extends EventEmitter {
}
/**
* @param {?string} mediaType
* @param {?string} type
*/
async emulateMedia(mediaType) {
assert(mediaType === 'screen' || mediaType === 'print' || mediaType === null, 'Unsupported media type: ' + mediaType);
await this._session.send('Page.setEmulatedMedia', {media: mediaType || ''});
async emulateMediaType(type) {
assert(type === 'screen' || type === 'print' || type === null, 'Unsupported media type: ' + type);
await this._session.send('Page.setEmulatedMedia', {media: type || ''});
}
/**
@ -747,6 +747,9 @@ class Page extends EventEmitter {
}
}
// Expose alias for deprecated method.
Page.prototype.emulateMedia = Page.prototype.emulateMediaType;
class ConsoleMessage {
/**
* @param {string} type

View File

@ -801,11 +801,27 @@ class Page extends EventEmitter {
}
/**
* @param {?string} mediaType
* @param {?string} type
*/
async emulateMedia(mediaType) {
assert(mediaType === 'screen' || mediaType === 'print' || mediaType === null, 'Unsupported media type: ' + mediaType);
await this._client.send('Emulation.setEmulatedMedia', {media: mediaType || ''});
async emulateMediaType(type) {
assert(type === 'screen' || type === 'print' || type === null, 'Unsupported media type: ' + type);
await this._client.send('Emulation.setEmulatedMedia', {media: type || ''});
}
/**
* @param {?Array<MediaFeature>} features
*/
async emulateMediaFeatures(features) {
if (features === null)
await this._client.send('Emulation.setEmulatedMedia', {features: null});
if (Array.isArray(features)) {
features.every(mediaFeature => {
const name = mediaFeature.name;
assert(/^prefers-(?:color-scheme|reduced-motion)$/.test(name), 'Unsupported media feature: ' + name);
return true;
});
await this._client.send('Emulation.setEmulatedMedia', {features: features});
}
}
/**
@ -1116,6 +1132,9 @@ class Page extends EventEmitter {
}
}
// Expose alias for deprecated method.
Page.prototype.emulateMedia = Page.prototype.emulateMediaType;
/**
* @typedef {Object} PDFOptions
* @property {number=} scale
@ -1161,6 +1180,12 @@ class Page extends EventEmitter {
* @property {string=} encoding
*/
/**
* @typedef {Object} MediaFeature
* @property {string} name
* @property {string} value
*/
/** @type {!Set<string>} */
const supportedMetrics = new Set([
'Timestamp',

View File

@ -98,20 +98,63 @@ module.exports.addTests = function({testRunner, expect, puppeteer}) {
});
describe('Page.emulateMedia', function() {
it('should be an alias for Page.emulateMediaType', async({page, server}) => {
expect(page.emulateMedia).toEqual(page.emulateMediaType);
});
});
describe('Page.emulateMediaType', function() {
it('should work', async({page, server}) => {
expect(await page.evaluate(() => window.matchMedia('screen').matches)).toBe(true);
expect(await page.evaluate(() => window.matchMedia('print').matches)).toBe(false);
await page.emulateMedia('print');
expect(await page.evaluate(() => window.matchMedia('screen').matches)).toBe(false);
expect(await page.evaluate(() => window.matchMedia('print').matches)).toBe(true);
await page.emulateMedia(null);
expect(await page.evaluate(() => window.matchMedia('screen').matches)).toBe(true);
expect(await page.evaluate(() => window.matchMedia('print').matches)).toBe(false);
expect(await page.evaluate(() => matchMedia('screen').matches)).toBe(true);
expect(await page.evaluate(() => matchMedia('print').matches)).toBe(false);
await page.emulateMediaType('print');
expect(await page.evaluate(() => matchMedia('screen').matches)).toBe(false);
expect(await page.evaluate(() => matchMedia('print').matches)).toBe(true);
await page.emulateMediaType(null);
expect(await page.evaluate(() => matchMedia('screen').matches)).toBe(true);
expect(await page.evaluate(() => matchMedia('print').matches)).toBe(false);
});
it('should throw in case of bad argument', async({page, server}) => {
let error = null;
await page.emulateMedia('bad').catch(e => error = e);
await page.emulateMediaType('bad').catch(e => error = e);
expect(error.message).toBe('Unsupported media type: bad');
});
});
describe_fails_ffox('Page.emulateMediaFeatures', function() {
it('should work', async({page, server}) => {
await page.emulateMediaFeatures([
{ name: 'prefers-reduced-motion', value: 'reduce' },
]);
expect(await page.evaluate(() => matchMedia('(prefers-reduced-motion: reduce)').matches)).toBe(true);
expect(await page.evaluate(() => matchMedia('(prefers-reduced-motion: no-preference)').matches)).toBe(false);
await page.emulateMediaFeatures([
{ name: 'prefers-color-scheme', value: 'light' },
]);
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.emulateMediaFeatures([
{ name: 'prefers-color-scheme', value: '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.emulateMediaFeatures([
{ name: 'prefers-reduced-motion', value: 'reduce' },
{ name: 'prefers-color-scheme', value: 'light' },
]);
expect(await page.evaluate(() => matchMedia('(prefers-reduced-motion: reduce)').matches)).toBe(true);
expect(await page.evaluate(() => matchMedia('(prefers-reduced-motion: no-preference)').matches)).toBe(false);
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);
});
it('should throw in case of bad argument', async({page, server}) => {
let error = null;
await page.emulateMediaFeatures([{ name: 'bad', value: '' }]).catch(e => error = e);
expect(error.message).toBe('Unsupported media feature: bad');
});
});
};

View File

@ -73,6 +73,7 @@ beforeEach(async({server, httpsServer}) => {
});
const CHROMIUM_NO_COVERAGE = new Set([
'page.emulateMedia', // Legacy alias for `page.emulateMediaType`.
]);
if (process.env.BROWSER === 'firefox') {