chore: unify emulateMedia APIs (#53)

This commit is contained in:
Pavel Feldman 2019-11-22 11:24:56 -08:00 коммит произвёл GitHub
Родитель c26166203e
Коммит 508c1960dd
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
7 изменённых файлов: 86 добавлений и 113 удалений

Просмотреть файл

@ -99,9 +99,7 @@
* [page.dblclick(selector[, options])](#pagedblclickselector-options)
* [page.deleteCookie(...cookies)](#pagedeletecookiecookies)
* [page.emulate(options)](#pageemulateoptions)
* [page.emulateMedia(type)](#pageemulatemediatype)
* [page.emulateMediaFeatures(features)](#pageemulatemediafeaturesfeatures)
* [page.emulateMediaType(type)](#pageemulatemediatypetype)
* [page.emulateMedia(options)](#pageemulatemediaoptions)
* [page.emulateTimezone(timezoneId)](#pageemulatetimezonetimezoneid)
* [page.evaluate(pageFunction[, ...args])](#pageevaluatepagefunction-args)
* [page.evaluateHandle(pageFunction[, ...args])](#pageevaluatehandlepagefunction-args)
@ -1252,70 +1250,62 @@ const iPhone = playwright.devices['iPhone 6'];
List of all available devices is available in the source code: [DeviceDescriptors.js](https://github.com/Microsoft/playwright/blob/master/lib/DeviceDescriptors.js).
#### 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.
#### page.emulateMedia(options)
- `options` <[Object]>
- `type` <?[string]> Optional. Changes the CSS media type of the page. The only allowed values are `'screen'`, `'print'` and `null`. Passing `null` disables CSS media emulation.
- `features` <?[Array]<[Object]>> Optional. 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));
await page.evaluate(() => matchMedia('screen').matches));
// → true
await page.evaluate(() => matchMedia('print').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));
await page.emulateMedia({ type: 'print' });
await page.evaluate(() => matchMedia('screen').matches));
// → false
await page.evaluate(() => matchMedia('print').matches));
// → true
await page.emulateMediaFeatures([
{ name: 'prefers-color-scheme', value: 'dark' },
{ name: 'prefers-reduced-motion', value: 'reduce' },
]);
await page.evaluate(() => matchMedia('(prefers-color-scheme: dark)').matches));
await page.emulateMedia({});
await page.evaluate(() => matchMedia('screen').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));
await page.evaluate(() => matchMedia('print').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));
await page.emulateMedia({ features: [{ name: 'prefers-color-scheme', value: 'dark' }] });
await page.evaluate(() => matchMedia('(prefers-color-scheme: dark)').matches));
// → true
await page.evaluate(() => matchMedia('print').matches));
// → true
await page.emulateMediaType('print');
await page.evaluate(() => matchMedia('screen').matches));
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('print').matches));
// → true
await page.emulateMediaType(null);
await page.evaluate(() => matchMedia('screen').matches));
await page.emulateMedia({ features: [{ name: 'prefers-reduced-motion', value: 'reduce' }] });
await page.evaluate(() => matchMedia('(prefers-reduced-motion: reduce)').matches));
// → true
await page.evaluate(() => matchMedia('print').matches));
await page.evaluate(() => matchMedia('(prefers-color-scheme: no-preference)').matches));
// → false
await page.emulateMedia({ features: [
{ 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.emulateTimezone(timezoneId)
@ -2366,13 +2356,13 @@ Dispatches a `mouseup` event.
> **NOTE** Generating a pdf is currently only supported in Chrome headless.
`pdf.generate()` generates a pdf of the page with `print` css media. To generate a pdf with `screen` media, call [page.emulateMedia('screen')](#pageemulatemediamediatype) before calling `pdf.generate()`:
`pdf.generate()` generates a pdf of the page with `print` css media. To generate a pdf with `screen` media, call [page.emulateMedia({ type: 'screen' })](#pageemulatemedia) before calling `pdf.generate()`:
> **NOTE** By default, `pdf.generate()` generates a pdf with modified colors for printing. Use the [`-webkit-print-color-adjust`](https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-print-color-adjust) property to force rendering of exact colors.
```js
// Generates a PDF with 'screen' media type.
await page.emulateMedia('screen');
await page.emulateMedia({ type: 'screen' });
await page.pdf.generate({path: 'page.pdf'});
```

Просмотреть файл

@ -532,26 +532,15 @@ export class Page extends EventEmitter {
await this._client.send('Page.setBypassCSP', { enabled });
}
async emulateMedia(type: string | null) {
return this.emulateMediaType(type);
}
async emulateMediaType(type: string | null) {
assert(type === 'screen' || type === 'print' || type === null, 'Unsupported media type: ' + type);
await this._client.send('Emulation.setEmulatedMedia', {media: type || ''});
}
async emulateMediaFeatures(features: MediaFeature[] | null) {
if (features === null)
await this._client.send('Emulation.setEmulatedMedia', {features: null});
if (Array.isArray(features)) {
features.every(mediaFeature => {
async emulateMedia(options: { type?: string, features?: MediaFeature[] }) {
assert(options.type === 'screen' || options.type === 'print' || options.type === undefined, 'Unsupported media type: ' + options.type);
if (options.features) {
options.features.forEach(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});
}
await this._client.send('Emulation.setEmulatedMedia', { media: options.type, features: options.features });
}
async emulateTimezone(timezoneId: string | null) {

Просмотреть файл

@ -144,13 +144,10 @@ export class Page extends EventEmitter {
await this._networkManager.setExtraHTTPHeaders(headers);
}
async emulateMedia(type: string): Promise<void> {
await this.emulateMediaType(type);
}
async emulateMediaType(type: string | null) {
assert(type === 'screen' || type === 'print' || type === null, 'Unsupported media type: ' + type);
await this._session.send('Page.setEmulatedMedia', {media: type || ''});
async emulateMedia(options: { type?: string, features?: MediaFeature[] }) {
assert(!options.features, 'Media feature emulation is not supported');
assert(options.type === 'screen' || options.type === 'print' || options.type === undefined, 'Unsupported media type: ' + options.type);
await this._session.send('Page.setEmulatedMedia', { media: options.type || '' });
}
async exposeFunction(name: string, playwrightFunction: Function) {
@ -622,4 +619,9 @@ export type Viewport = {
isMobile?: boolean;
isLandscape?: boolean;
hasTouch?: boolean;
}
}
type MediaFeature = {
name: string,
value: string
}

Просмотреть файл

@ -323,13 +323,10 @@ export class Page extends EventEmitter {
]);
}
async emulateMedia(type: string | null) {
return this.emulateMediaType(type);
}
async emulateMediaType(type: string | null) {
assert(type === 'screen' || type === 'print' || type === null, 'Unsupported media type: ' + type);
await this._session.send('Page.setEmulatedMedia', {media: type || ''});
async emulateMedia(options: { type?: string, features?: MediaFeature[] }) {
assert(!options.features, 'Media feature emulation is not supported');
assert(options.type === 'screen' || options.type === 'print' || options.type === undefined, 'Unsupported media type: ' + options.type);
await this._session.send('Page.setEmulatedMedia', { media: options.type });
}
async setViewport(viewport: Viewport) {
@ -555,3 +552,8 @@ export class ConsoleMessage {
return this._location;
}
}
type MediaFeature = {
name: string,
value: string
}

Просмотреть файл

@ -15,10 +15,10 @@
*/
module.exports.addTests = function({testRunner, expect, playwright, FFOX, CHROME, WEBKIT}) {
const {describe, xdescribe, fdescribe} = testRunner;
let {describe, xdescribe, fdescribe} = testRunner;
const {it, fit, xit} = testRunner;
const {beforeAll, beforeEach, afterAll, afterEach} = testRunner;
describe = fdescribe;
const iPhone = playwright.devices['iPhone 6'];
const iPhoneLandscape = playwright.devices['iPhone 6 landscape'];
@ -97,53 +97,47 @@ module.exports.addTests = function({testRunner, expect, playwright, FFOX, CHROME
});
});
describe('Page.emulateMedia', function() {
it.skip(WEBKIT)('should be an alias for Page.emulateMediaType', async({page, server}) => {
expect(page.emulateMedia).toEqual(page.emulateMediaType);
});
});
describe.skip(WEBKIT)('Page.emulateMediaType', function() {
describe.skip(WEBKIT)('Page.emulateMedia type', function() {
it('should work', async({page, server}) => {
expect(await page.evaluate(() => matchMedia('screen').matches)).toBe(true);
expect(await page.evaluate(() => matchMedia('print').matches)).toBe(false);
await page.emulateMediaType('print');
await page.emulateMedia({ type: 'print' });
expect(await page.evaluate(() => matchMedia('screen').matches)).toBe(false);
expect(await page.evaluate(() => matchMedia('print').matches)).toBe(true);
await page.emulateMediaType(null);
await page.emulateMedia({});
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}) => {
it('should throw in case of bad type argument', async({page, server}) => {
let error = null;
await page.emulateMediaType('bad').catch(e => error = e);
await page.emulateMedia({ type: 'bad' }).catch(e => error = e);
expect(error.message).toBe('Unsupported media type: bad');
});
});
describe.skip(FFOX || WEBKIT)('Page.emulateMediaFeatures', function() {
describe.skip(FFOX || WEBKIT)('Page.emulateMedia features', function() {
it('should work', async({page, server}) => {
await page.emulateMediaFeatures([
await page.emulateMedia({ features: [
{ 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([
await page.emulateMedia({ features: [
{ 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([
await page.emulateMedia({ features: [
{ 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([
await page.emulateMedia({ features: [
{ 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);
@ -152,7 +146,7 @@ module.exports.addTests = function({testRunner, expect, playwright, FFOX, CHROME
});
it('should throw in case of bad argument', async({page, server}) => {
let error = null;
await page.emulateMediaFeatures([{ name: 'bad', value: '' }]).catch(e => error = e);
await page.emulateMedia({ features: [{ name: 'bad', value: '' }] }).catch(e => error = e);
expect(error.message).toBe('Unsupported media feature: bad');
});
});

Просмотреть файл

@ -72,10 +72,6 @@ beforeEach(async({server, httpsServer}) => {
httpsServer.reset();
});
const CHROMIUM_NO_COVERAGE = new Set([
'page.emulateMedia', // Legacy alias for `page.emulateMediaType`.
]);
if (process.env.BROWSER === 'firefox') {
describe('Firefox', () => {
require('./playwright.spec.js').addTests({
@ -100,7 +96,7 @@ if (process.env.BROWSER === 'firefox') {
testRunner,
});
if (process.env.COVERAGE)
utils.recordAPICoverage(testRunner, require('../lib/api').Chromium, require('../lib/chromium/events').Events, CHROMIUM_NO_COVERAGE);
utils.recordAPICoverage(testRunner, require('../lib/api').Chromium, require('../lib/chromium/events').Events);
});
}

Просмотреть файл

@ -55,7 +55,7 @@ function traceAPICoverage(apiCoverage, events, className, classType) {
}
const utils = module.exports = {
recordAPICoverage: function(testRunner, api, events, disabled) {
recordAPICoverage: function(testRunner, api, events) {
const coverage = new Map();
for (const [className, classType] of Object.entries(api))
traceAPICoverage(coverage, events, className, classType);
@ -63,7 +63,7 @@ const utils = module.exports = {
testRunner.it('should call all API methods', () => {
const missingMethods = [];
for (const method of coverage.keys()) {
if (!coverage.get(method) && !disabled.has(method))
if (!coverage.get(method))
missingMethods.push(method);
}
if (missingMethods.length)