mirror of
https://github.com/puppeteer/puppeteer
synced 2024-06-14 14:02:48 +00:00
feat(page): emulate idle state (#6410)
* https://bugs.chromium.org/p/chromium/issues/detail?id=1090802 * added `page.emulateIdleState(...)` allowing emulate or remove emulation of the idle state; * added test `emulate idle` -> `remove emulation` -> `emulate idle` -> `remove emulation`; * added launch argument `--enable-blink-features=IdleDetection` to turn IdleDetection on.
This commit is contained in:
parent
03e41da465
commit
17960e5d8d
@ -118,6 +118,7 @@
|
||||
* [page.coverage](#pagecoverage)
|
||||
* [page.deleteCookie(...cookies)](#pagedeletecookiecookies)
|
||||
* [page.emulate(options)](#pageemulateoptions)
|
||||
* [page.emulateIdleState(overrides)](#pageemulateidlestateoverrides)
|
||||
* [page.emulateMediaFeatures(features)](#pageemulatemediafeaturesfeatures)
|
||||
* [page.emulateMediaType(type)](#pageemulatemediatypetype)
|
||||
* [page.emulateTimezone(timezoneId)](#pageemulatetimezonetimezoneid)
|
||||
@ -1342,6 +1343,12 @@ const iPhone = puppeteer.devices['iPhone 6'];
|
||||
|
||||
List of all available devices is available in the source code: [src/common/DeviceDescriptors.ts](https://github.com/puppeteer/puppeteer/blob/main/src/common/DeviceDescriptors.ts).
|
||||
|
||||
#### page.emulateIdleState(overrides)
|
||||
- `overrides` <?[Object]> If not set, clears emulation
|
||||
- `isUserActive` <[boolean]> **required**
|
||||
- `isScreenUnlocked` <[boolean]> **required**
|
||||
- returns: <[Promise]>
|
||||
|
||||
#### 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'`.
|
||||
|
42
new-docs/puppeteer.page.emulateidlestate.md
Normal file
42
new-docs/puppeteer.page.emulateidlestate.md
Normal file
@ -0,0 +1,42 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [puppeteer](./puppeteer.md) > [Page](./puppeteer.page.md) > [emulateIdleState](./puppeteer.page.emulateidlestate.md)
|
||||
|
||||
## Page.emulateIdleState() method
|
||||
|
||||
Emulates the idle state. If no arguments set, clears idle state emulation.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
emulateIdleState(overrides?: {
|
||||
isUserActive: boolean;
|
||||
isScreenUnlocked: boolean;
|
||||
}): Promise<void>;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| overrides | { isUserActive: boolean; isScreenUnlocked: boolean; } | Mock idle state. If not set, clears idle overrides |
|
||||
|
||||
<b>Returns:</b>
|
||||
|
||||
Promise<void>
|
||||
|
||||
## Example
|
||||
|
||||
|
||||
```js
|
||||
// set idle emulation
|
||||
await page.emulateIdleState({isUserActive: true, isScreenUnlocked: false});
|
||||
|
||||
// do some checks here
|
||||
...
|
||||
|
||||
// clear idle emulation
|
||||
await page.emulateIdleState();
|
||||
|
||||
```
|
||||
|
@ -89,6 +89,7 @@ page.off('request', logRequest);
|
||||
| [cookies(urls)](./puppeteer.page.cookies.md) | | If no URLs are specified, this method returns cookies for the current page URL. If URLs are specified, only cookies for those URLs are returned. |
|
||||
| [deleteCookie(cookies)](./puppeteer.page.deletecookie.md) | | |
|
||||
| [emulate(options)](./puppeteer.page.emulate.md) | | |
|
||||
| [emulateIdleState(overrides)](./puppeteer.page.emulateidlestate.md) | | Emulates the idle state. If no arguments set, clears idle state emulation. |
|
||||
| [emulateMediaFeatures(features)](./puppeteer.page.emulatemediafeatures.md) | | |
|
||||
| [emulateMediaType(type)](./puppeteer.page.emulatemediatype.md) | | |
|
||||
| [emulateTimezone(timezoneId)](./puppeteer.page.emulatetimezone.md) | | |
|
||||
|
@ -1443,6 +1443,40 @@ export class Page extends EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Emulates the idle state.
|
||||
* If no arguments set, clears idle state emulation.
|
||||
*
|
||||
* @example
|
||||
* ```js
|
||||
* // set idle emulation
|
||||
* await page.emulateIdleState({isUserActive: true, isScreenUnlocked: false});
|
||||
*
|
||||
* // do some checks here
|
||||
* ...
|
||||
*
|
||||
* // clear idle emulation
|
||||
* await page.emulateIdleState();
|
||||
* ```
|
||||
*
|
||||
* @param overrides Mock idle state. If not set, clears idle overrides
|
||||
* @param isUserActive Mock isUserActive
|
||||
* @param isScreenUnlocked Mock isScreenUnlocked
|
||||
*/
|
||||
async emulateIdleState(overrides?: {
|
||||
isUserActive: boolean;
|
||||
isScreenUnlocked: boolean;
|
||||
}): Promise<void> {
|
||||
if (overrides) {
|
||||
await this._client.send('Emulation.setIdleOverride', {
|
||||
isUserActive: overrides.isUserActive,
|
||||
isScreenUnlocked: overrides.isScreenUnlocked,
|
||||
});
|
||||
} else {
|
||||
await this._client.send('Emulation.clearIdleOverride');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Simulates the given vision deficiency on the page.
|
||||
*
|
||||
|
@ -190,6 +190,9 @@ class ChromeLauncher implements ProductLauncher {
|
||||
'--enable-automation',
|
||||
'--password-store=basic',
|
||||
'--use-mock-keychain',
|
||||
// TODO(sadym): remove '--enable-blink-features=IdleDetection'
|
||||
// once IdleDetection is turned on by default.
|
||||
'--enable-blink-features=IdleDetection',
|
||||
];
|
||||
const {
|
||||
devtools = false,
|
||||
|
23
test/assets/idle-detector.html
Normal file
23
test/assets/idle-detector.html
Normal file
@ -0,0 +1,23 @@
|
||||
<!DOCTYPE html>
|
||||
<div id="state"></div>
|
||||
<script>
|
||||
const elState = document.querySelector('#state');
|
||||
function setState(msg) {
|
||||
elState.textContent = msg;
|
||||
}
|
||||
async function main() {
|
||||
const controller = new AbortController();
|
||||
const signal = controller.signal;
|
||||
const idleDetector = new IdleDetector({
|
||||
threshold: 60000,
|
||||
signal,
|
||||
});
|
||||
idleDetector.addEventListener('change', () => {
|
||||
const userState = idleDetector.userState;
|
||||
const screenState = idleDetector.screenState;
|
||||
setState(`Idle state: ${userState}, ${screenState}.`);
|
||||
});
|
||||
idleDetector.start();
|
||||
}
|
||||
main();
|
||||
</script>
|
94
test/idle_override.spec.ts
Normal file
94
test/idle_override.spec.ts
Normal file
@ -0,0 +1,94 @@
|
||||
/**
|
||||
* Copyright 2020 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import expect from 'expect';
|
||||
import {
|
||||
getTestState,
|
||||
setupTestBrowserHooks,
|
||||
setupTestPageAndContextHooks,
|
||||
describeFailsFirefox,
|
||||
} from './mocha-utils'; // eslint-disable-line import/extensions
|
||||
|
||||
describeFailsFirefox('Emulate idle state', () => {
|
||||
setupTestBrowserHooks();
|
||||
setupTestPageAndContextHooks();
|
||||
|
||||
async function getIdleState() {
|
||||
const { page } = getTestState();
|
||||
|
||||
const stateElement = await page.$('#state');
|
||||
return await page.evaluate((element: HTMLElement) => {
|
||||
return element.innerText;
|
||||
}, stateElement);
|
||||
}
|
||||
|
||||
async function verifyState(expectedState: string) {
|
||||
const actualState = await getIdleState();
|
||||
expect(actualState).toEqual(expectedState);
|
||||
}
|
||||
|
||||
it('changing idle state emulation causes change of the IdleDetector state', async () => {
|
||||
const { page, server, context } = getTestState();
|
||||
await context.overridePermissions(server.PREFIX + '/idle-detector.html', [
|
||||
'notifications',
|
||||
]);
|
||||
|
||||
await page.goto(server.PREFIX + '/idle-detector.html');
|
||||
|
||||
// Store initial state, as soon as it is not guaranteed to be `active, unlocked`.
|
||||
const initialState = await getIdleState();
|
||||
|
||||
// Emulate Idle states and verify IdleDetector updates state accordingly.
|
||||
await page.emulateIdleState({
|
||||
isUserActive: false,
|
||||
isScreenUnlocked: false,
|
||||
});
|
||||
await verifyState('Idle state: idle, locked.');
|
||||
|
||||
await page.emulateIdleState({
|
||||
isUserActive: true,
|
||||
isScreenUnlocked: false,
|
||||
});
|
||||
await verifyState('Idle state: active, locked.');
|
||||
|
||||
await page.emulateIdleState({
|
||||
isUserActive: true,
|
||||
isScreenUnlocked: true,
|
||||
});
|
||||
await verifyState('Idle state: active, unlocked.');
|
||||
|
||||
await page.emulateIdleState({
|
||||
isUserActive: false,
|
||||
isScreenUnlocked: true,
|
||||
});
|
||||
await verifyState('Idle state: idle, unlocked.');
|
||||
|
||||
// Remove Idle emulation and verify IdleDetector is in initial state.
|
||||
await page.emulateIdleState();
|
||||
await verifyState(initialState);
|
||||
|
||||
// Emulate idle state again after removing emulation.
|
||||
await page.emulateIdleState({
|
||||
isUserActive: false,
|
||||
isScreenUnlocked: false,
|
||||
});
|
||||
await verifyState('Idle state: idle, locked.');
|
||||
|
||||
// Remove emulation second time.
|
||||
await page.emulateIdleState();
|
||||
await verifyState(initialState);
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user