Skip to content

Commit d86d6a9

Browse files
authored
Introduce Page.EmulateIdleStateAsync (#1883)
1 parent 498d651 commit d86d6a9

File tree

8 files changed

+185
-3
lines changed

8 files changed

+185
-3
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<!DOCTYPE html>
2+
<div id="state"></div>
3+
<script>
4+
const elState = document.querySelector('#state');
5+
function setState(msg) {
6+
elState.textContent = msg;
7+
}
8+
async function main() {
9+
const controller = new AbortController();
10+
const signal = controller.signal;
11+
const idleDetector = new IdleDetector({
12+
threshold: 60000,
13+
signal,
14+
});
15+
idleDetector.addEventListener('change', () => {
16+
const userState = idleDetector.userState;
17+
const screenState = idleDetector.screenState;
18+
setState(`Idle state: ${userState}, ${screenState}.`);
19+
});
20+
idleDetector.start();
21+
}
22+
main();
23+
</script>
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
using System.Threading.Tasks;
4+
using PuppeteerSharp.Tests.Attributes;
5+
using PuppeteerSharp.Xunit;
6+
using Xunit;
7+
using Xunit.Abstractions;
8+
9+
namespace PuppeteerSharp.Tests.IdleOverrideTests
10+
{
11+
[Collection(TestConstants.TestFixtureCollectionName)]
12+
public class IdleOverrideTests : PuppeteerPageBaseTest
13+
{
14+
public IdleOverrideTests(ITestOutputHelper output) : base(output)
15+
{
16+
}
17+
18+
private async Task<string> GetIdleStateAsync()
19+
{
20+
var stateElement = await Page.QuerySelectorAsync("#state");
21+
return await Page.EvaluateFunctionAsync<string>(
22+
@"(element) => {
23+
return element.innerText;
24+
}",
25+
stateElement);
26+
}
27+
28+
private async Task VerifyStateAsync(string expectedState)
29+
{
30+
var actualState = await GetIdleStateAsync();
31+
Assert.Equal(expectedState, actualState);
32+
}
33+
34+
[PuppeteerTest("idle_override.spec.ts", "Emulate idle state", "changing idle state emulation causes change of the IdleDetector state")]
35+
[SkipBrowserFact(skipFirefox: true)]
36+
public async Task ChangingIdleStateEmulationCausesChangeOfTheIdleDetectorState()
37+
{
38+
await Context.OverridePermissionsAsync(
39+
TestConstants.ServerUrl + "/idle-detector.html",
40+
new[]
41+
{
42+
OverridePermission.IdleDetection,
43+
});
44+
45+
await Page.GoToAsync(TestConstants.ServerUrl+ "/idle-detector.html");
46+
47+
// Store initial state, as soon as it is not guaranteed to be `active, unlocked`.
48+
var initialState = await GetIdleStateAsync();
49+
50+
// Emulate Idle states and verify IdleDetector updates state accordingly.
51+
await Page.EmulateIdleStateAsync(new EmulateIdleOverrides {
52+
IsUserActive = false,
53+
IsScreenUnlocked = false,
54+
});
55+
56+
await VerifyStateAsync("Idle state: idle, locked.");
57+
58+
await Page.EmulateIdleStateAsync(new EmulateIdleOverrides {
59+
IsUserActive = true,
60+
IsScreenUnlocked = false,
61+
});
62+
await VerifyStateAsync("Idle state: active, locked.");
63+
64+
await Page.EmulateIdleStateAsync(new EmulateIdleOverrides {
65+
IsUserActive = true,
66+
IsScreenUnlocked = true,
67+
});
68+
await VerifyStateAsync("Idle state: active, unlocked.");
69+
70+
await Page.EmulateIdleStateAsync(new EmulateIdleOverrides {
71+
IsUserActive = false,
72+
IsScreenUnlocked = true,
73+
});
74+
await VerifyStateAsync("Idle state: idle, unlocked.");
75+
76+
// Remove Idle emulation and verify IdleDetector is in initial state.
77+
await Page.EmulateIdleStateAsync();
78+
await VerifyStateAsync(initialState);
79+
80+
// Emulate idle state again after removing emulation.
81+
await Page.EmulateIdleStateAsync(new EmulateIdleOverrides {
82+
IsUserActive = false,
83+
IsScreenUnlocked = false,
84+
});
85+
await VerifyStateAsync("Idle state: idle, locked.");
86+
87+
// Remove emulation second time.
88+
await Page.EmulateIdleStateAsync();
89+
await VerifyStateAsync(initialState);
90+
}
91+
}
92+
}

lib/PuppeteerSharp/BrowserFetcher.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public class BrowserFetcher : IDisposable
6464
/// <summary>
6565
/// Default Chromium revision.
6666
/// </summary>
67-
public const string DefaultChromiumRevision = "884014";
67+
public const string DefaultChromiumRevision = "901912";
6868

6969
/// <summary>
7070
/// Default Firefox revision.

lib/PuppeteerSharp/ChromiumLauncher.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ public class ChromiumLauncher : LauncherBase
3838
"--no-first-run",
3939
"--enable-automation",
4040
"--password-store=basic",
41-
"--use-mock-keychain"
41+
"--use-mock-keychain",
42+
"--enable-blink-features=IdleDetection",
4243
};
4344

4445
private const string UserDataDirArgument = "--user-data-dir";
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
namespace PuppeteerSharp
2+
{
3+
/// <summary>
4+
/// Options for <see cref="Page.EmulateIdleStateAsync(EmulateIdleOverrides)"/>
5+
/// </summary>
6+
public class EmulateIdleOverrides
7+
{
8+
/// <summary>
9+
/// Whether the user is active or not.
10+
/// </summary>
11+
public bool IsUserActive { get; set; }
12+
13+
/// <summary>
14+
/// Whether the screen is unlocked or not.
15+
/// </summary>
16+
public bool IsScreenUnlocked { get; set; }
17+
}
18+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
namespace PuppeteerSharp.Messaging
2+
{
3+
internal class EmulationSetIdleOverrideRequest
4+
{
5+
public bool IsUserActive { get; set; }
6+
7+
public bool IsScreenUnlocked { get; set; }
8+
}
9+
}

lib/PuppeteerSharp/OverridePermission.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,11 @@ public enum OverridePermission
7575
/// MIDI sysex.
7676
/// </summary>
7777
[EnumMember(Value = "midiSysex")]
78-
MidiSysex
78+
MidiSysex,
79+
/// <summary>
80+
/// Idle detection.
81+
/// </summary>
82+
[EnumMember(Value = "idleDetection")]
83+
IdleDetection
7984
}
8085
}

lib/PuppeteerSharp/Page.cs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1931,6 +1931,40 @@ public async Task EmulateTimezoneAsync(string timezoneId)
19311931
}
19321932
}
19331933

1934+
/// <summary>
1935+
/// Emulates the idle state.
1936+
/// If no arguments set, clears idle state emulation.
1937+
/// </summary>
1938+
/// <example>
1939+
/// <code>
1940+
/// // set idle emulation
1941+
/// await page.EmulateIdleStateAsync(new EmulateIdleOverrides() {IsUserActive = true, IsScreenUnlocked = false});
1942+
/// // do some checks here
1943+
/// ...
1944+
/// // clear idle emulation
1945+
/// await page.EmulateIdleStateAsync();
1946+
/// </code>
1947+
/// </example>
1948+
/// <param name="overrides">Overrides</param>
1949+
/// <returns>A task that resolves when the message has been sent to the browser.</returns>
1950+
public async Task EmulateIdleStateAsync(EmulateIdleOverrides overrides = null)
1951+
{
1952+
if (overrides != null)
1953+
{
1954+
await Client.SendAsync(
1955+
"Emulation.setIdleOverride",
1956+
new EmulationSetIdleOverrideRequest
1957+
{
1958+
IsUserActive = overrides.IsUserActive,
1959+
IsScreenUnlocked = overrides.IsScreenUnlocked,
1960+
}).ConfigureAwait(false);
1961+
}
1962+
else
1963+
{
1964+
await Client.SendAsync("Emulation.clearIdleOverride").ConfigureAwait(false);
1965+
}
1966+
}
1967+
19341968
/// <summary>
19351969
/// Enables CPU throttling to emulate slow CPUs.
19361970
/// </summary>

0 commit comments

Comments
 (0)