Files
gmtool/tests/core/wake-lock.test.js
slaguru666andClaude Opus 4.8 6d529c9799 feat: parking-lot note + wake-lock tray tools
Add the last two design-§5 tray tools:
- <parking-lot>: one-tap capture of a thread to return to, stamped with
  the session time, persisted per-scenario (parkingLot store key), 📝 chip.
- src/core/wake-lock.js: injectable Screen Wake Lock controller (keeps the
  tablet awake, re-acquires on foreground, graceful no-op where the API is
  absent). Toggled by a 💡 rail chip that lights when active.

Tests: parking-lot.test.js, wake-lock.test.js, gm-shell-parking.test.js,
gm-shell-wake.test.js. 179 tests pass; build clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-20 23:15:14 +01:00

76 lines
2.7 KiB
JavaScript

import { describe, it, expect } from 'vitest';
import { createWakeLock } from '../../src/core/wake-lock.js';
function mockNav() {
const requests = [];
return {
requests,
wakeLock: {
request: async () => {
let onRelease = null;
const s = {
released: false,
release: async () => { s.released = true; onRelease?.(); },
addEventListener: (ev, h) => { if (ev === 'release') onRelease = h; },
};
requests.push(s);
return s;
},
},
};
}
const mockDoc = () => ({ visibilityState: 'visible', addEventListener() {} });
describe('createWakeLock', () => {
it('reports supported when the API is present', () => {
expect(createWakeLock({ navigator: mockNav(), documentRef: mockDoc() }).supported).toBe(true);
expect(createWakeLock({ navigator: {}, documentRef: mockDoc() }).supported).toBe(false);
});
it('acquires a lock on enable and releases it on disable', async () => {
const nav = mockNav();
const wl = createWakeLock({ navigator: nav, documentRef: mockDoc() });
await wl.enable();
expect(wl.isActive()).toBe(true);
expect(nav.requests.length).toBe(1);
await wl.disable();
expect(wl.isActive()).toBe(false);
expect(nav.requests[0].released).toBe(true);
});
it('toggles between states and returns the new state', async () => {
const wl = createWakeLock({ navigator: mockNav(), documentRef: mockDoc() });
expect(await wl.toggle()).toBe(true);
expect(await wl.toggle()).toBe(false);
});
it('does not double-acquire while already held', async () => {
const nav = mockNav();
const wl = createWakeLock({ navigator: nav, documentRef: mockDoc() });
await wl.enable();
await wl.enable();
expect(nav.requests.length).toBe(1);
});
it('is a graceful no-op when unsupported', async () => {
const wl = createWakeLock({ navigator: {}, documentRef: mockDoc() });
await wl.enable();
expect(wl.isActive()).toBe(false);
expect(await wl.toggle()).toBe(false);
});
it('re-acquires when the tab becomes visible again after the lock dropped', async () => {
const nav = mockNav();
let handler = null;
const doc = { visibilityState: 'visible', addEventListener: (_e, h) => { handler = h; } };
const wl = createWakeLock({ navigator: nav, documentRef: doc });
await wl.enable();
expect(nav.requests.length).toBe(1);
await nav.requests[0].release(); // browser drops the lock on hide → sentinel cleared
handler(); // visibilitychange back to visible
await Promise.resolve(); // let the async acquire settle
expect(nav.requests.length).toBe(2);
expect(wl.isActive()).toBe(true);
});
});