| <!DOCTYPE html> |
| <link rel="help" href="https://github.com/samuelgoto/idle-detection"> |
| <title>Tests the Idle Detection API</title> |
| <script src="/resources/testharness.js"></script> |
| <script src="/resources/testharnessreport.js"></script> |
| <script src="/resources/test-only-api.js"></script> |
| <script src="/resources/testdriver.js"></script> |
| <script src="/resources/testdriver-vendor.js"></script> |
| <script src="resources/idle-detection-helper.js"></script> |
| <script> |
| 'use strict'; |
| |
| promise_setup(async t => { |
| await test_driver.set_permission({ name: 'idle-detection' }, 'granted', false); |
| if (isChromiumBased) { |
| await loadChromiumResources(); |
| } |
| }) |
| |
| promise_test(async t => { |
| // Basic test that expects start() to call internally |
| // addMonitor, which in turn return an ACTIVE state. |
| expect(addMonitor).andReturn(async (monitorPtr) => { |
| return { |
| error: IdleDetectorError.SUCCESS, |
| state: { |
| idleTime: null, |
| screenLocked: true |
| } |
| }; |
| }); |
| |
| const controller = new AbortController(); |
| const detector = new IdleDetector(); |
| const watcher = new EventWatcher(t, detector, ["change"]); |
| const initial_state = watcher.wait_for("change"); |
| |
| await detector.start({ signal: controller.signal }); |
| await initial_state; |
| |
| assert_equals(detector.userState, "active"); |
| assert_equals(detector.screenState, "locked"); |
| |
| controller.abort(); |
| }, 'start()'); |
| |
| promise_test(async t => { |
| // Verifies that an event is thrown when a change of state from IDLE to ACTIVE |
| // is detected. |
| expect(addMonitor).andReturn(async (monitorPtr) => { |
| const first = { |
| error: IdleDetectorError.SUCCESS, |
| state: { |
| idleTime: null, |
| screenLocked: false |
| } |
| }; |
| |
| t.step_timeout(() => { |
| monitorPtr.update( |
| { |
| idleTime: { milliseconds: 0 }, |
| screenLocked: false |
| }, |
| /*is_overridden_by_devtools=*/true |
| ); |
| }, 0); |
| |
| return first; |
| }); |
| |
| const controller = new AbortController(); |
| const detector = new IdleDetector(); |
| const watcher = new EventWatcher(t, detector, ["change"]); |
| const initial_state = watcher.wait_for("change"); |
| |
| await detector.start({ signal: controller.signal }); |
| await initial_state; |
| assert_equals(detector.userState, "active"); |
| assert_equals(detector.screenState, "unlocked"); |
| |
| // Wait for the first change in state. |
| await watcher.wait_for("change"); |
| |
| assert_equals(detector.userState, "idle"); |
| assert_equals(detector.screenState, "unlocked"); |
| |
| controller.abort(); |
| }, 'updates once'); |
| |
| promise_test(async t => { |
| // Simulates the user being active, going idle and then going back active |
| // again. |
| expect(addMonitor).andReturn(async (monitorPtr) => { |
| const first = { |
| error: IdleDetectorError.SUCCESS, |
| state: { |
| idleTime: null, |
| screenLocked: false |
| } |
| }; |
| |
| // Updates the client once with the user idle. |
| t.step_timeout(() => { |
| monitorPtr.update( |
| { |
| idleTime: { milliseconds: 0 }, |
| screenLocked: false |
| }, |
| /*is_overridden_by_devtools=*/true |
| ); |
| }, 0); |
| |
| // Updates the client a second time with the user active. |
| t.step_timeout(() => { |
| monitorPtr.update( |
| { |
| idleTime: null, |
| screenLocked: false |
| }, |
| /*is_overridden_by_devtools=*/true |
| ); |
| }, 1); |
| |
| return first; |
| }); |
| |
| const controller = new AbortController(); |
| const detector = new IdleDetector(); |
| const watcher = new EventWatcher(t, detector, ["change"]); |
| const initial_state = watcher.wait_for("change"); |
| |
| await detector.start({ signal: controller.signal }); |
| await initial_state; |
| |
| // Waits for the first event. |
| await watcher.wait_for("change"); |
| assert_equals(detector.userState, "idle"); |
| |
| // Waits for the second event. |
| await watcher.wait_for("change"); |
| assert_equals(detector.userState, "active"); |
| |
| controller.abort(); |
| }, 'updates twice'); |
| |
| promise_test(async t => { |
| // Simulates a locked screen. |
| expect(addMonitor).andReturn(async (monitorPtr) => { |
| return { |
| error: IdleDetectorError.SUCCESS, |
| state: { |
| idleTime: null, |
| screenLocked: true |
| } |
| }; |
| }); |
| |
| const controller = new AbortController(); |
| const detector = new IdleDetector(); |
| const watcher = new EventWatcher(t, detector, ["change"]); |
| const initial_state = watcher.wait_for("change"); |
| |
| await detector.start({ signal: controller.signal }); |
| await initial_state; |
| |
| assert_equals(detector.screenState, "locked"); |
| |
| controller.abort(); |
| }, 'locked screen'); |
| |
| promise_test(async t => { |
| expect(addMonitor).andReturn(async (monitorPtr) => { |
| return { |
| error: IdleDetectorError.SUCCESS, |
| state: { |
| idleTime: null, |
| screenLocked: true |
| } |
| }; |
| }); |
| |
| const controller = new AbortController(); |
| const detector = new IdleDetector(); |
| |
| let event = new Promise((resolve, reject) => { |
| detector.onchange = resolve; |
| }); |
| |
| await detector.start({ signal: controller.signal }); |
| |
| // Waits for the first event. |
| await event; |
| |
| assert_equals(detector.userState, "active"); |
| assert_equals(detector.screenState, "locked"); |
| |
| controller.abort(); |
| }, 'IdleDetector.onchange'); |
| |
| promise_test(async t => { |
| expect(addMonitor).andReturn(async (monitorPtr) => { |
| return { |
| error: IdleDetectorError.SUCCESS, |
| state: { |
| idleTime: null, |
| screenLocked: false |
| } |
| }; |
| }); |
| |
| const controller = new AbortController(); |
| const detector = new IdleDetector({ signal: controller.signal }); |
| |
| const watcher = new EventWatcher(t, detector, ["change"]); |
| const initial_state = watcher.wait_for("change"); |
| |
| // Only the first call to start() is allowed. |
| const start_promise = detector.start({ signal: controller.signal }); |
| await promise_rejects_dom(t, 'InvalidStateError', detector.start()); |
| await start_promise; |
| |
| await initial_state; |
| assert_equals(detector.userState, "active"); |
| assert_equals(detector.screenState, "unlocked"); |
| |
| // Calling abort() multiple times is safe. |
| controller.abort(); |
| controller.abort(); |
| controller.abort(); |
| controller.abort(); |
| }, 'Calling start() and abort() multiple times'); |
| |
| promise_test(async t => { |
| expect(addMonitor).andReturn(async (monitorPtr) => { |
| return { |
| error: IdleDetectorError.SUCCESS, |
| state: { |
| idleTime: null, |
| screenLocked: false |
| } |
| }; |
| }); |
| |
| const controller = new AbortController(); |
| const detector = new IdleDetector(); |
| |
| controller.abort(); |
| |
| await promise_rejects_dom( |
| t, 'AbortError', detector.start({ signal: controller.signal })); |
| }, 'Calling abort() before start() makes it fail'); |
| |
| promise_test(async t => { |
| expect(addMonitor).andReturn(async (monitorPtr) => { |
| return { |
| error: IdleDetectorError.SUCCESS, |
| state: { |
| idleTime: null, |
| screenLocked: false |
| } |
| }; |
| }); |
| |
| const controller = new AbortController(); |
| const detector = new IdleDetector(); |
| |
| const promise = promise_rejects_dom( |
| t, 'AbortError', detector.start({ signal: controller.signal })) |
| controller.abort(); |
| |
| await promise; |
| }, 'Calling abort() after start() makes it fail'); |
| |
| promise_test(async t => { |
| expect(addMonitor).andReturn(async (monitorPtr) => { |
| return { |
| error: IdleDetectorError.SUCCESS, |
| state: { |
| idleTime: null, |
| screenLocked: false |
| } |
| }; |
| }); |
| |
| const detector = new IdleDetector(); |
| const watcher = new EventWatcher(t, detector, ["change"]); |
| |
| let controller = new AbortController(); |
| const first_start = promise_rejects_dom( |
| t, 'AbortError', detector.start({ signal: controller.signal })) |
| controller.abort(); |
| |
| controller = new AbortController(); |
| const initial_state = watcher.wait_for("change"); |
| const second_start = detector.start({ signal: controller.signal }); |
| |
| await first_start; |
| await second_start; |
| await initial_state; |
| assert_equals(detector.userState, "active"); |
| assert_equals(detector.screenState, "unlocked"); |
| |
| controller.abort(); |
| }, 'A start() that has been aborted can be retried'); |
| |
| promise_test(async t => { |
| expect(addMonitor).andReturn(async (monitorPtr) => { |
| return { |
| error: IdleDetectorError.SUCCESS, |
| state: { |
| idleTime: null, |
| screenLocked: false |
| } |
| }; |
| }); |
| |
| let controller = new AbortController(); |
| const detector = new IdleDetector(); |
| const watcher = new EventWatcher(t, detector, ["change"]); |
| let initial_state = watcher.wait_for("change"); |
| |
| await detector.start({ signal: controller.signal }); |
| await initial_state; |
| assert_equals(detector.userState, "active"); |
| assert_equals(detector.screenState, "unlocked"); |
| |
| controller.abort(); |
| |
| expect(addMonitor).andReturn(async (monitorPtr) => { |
| return { |
| error: IdleDetectorError.SUCCESS, |
| state: { |
| idleTime: { milliseconds: 0 }, |
| screenLocked: true |
| } |
| }; |
| }); |
| |
| // Restarting the monitor. |
| controller = new AbortController(); |
| |
| initial_state = watcher.wait_for("change"); |
| await detector.start({ signal: controller.signal }); |
| await initial_state; |
| assert_equals(detector.userState, "idle"); |
| assert_equals(detector.screenState, "locked"); |
| |
| controller.abort(); |
| }, 'Calling start() after abort(): re-starting monitor.'); |
| |
| </script> |