2026-09-20 15:15:04 -04:00
|
|
|
import { test } from 'node:test';
|
|
|
|
|
import assert from 'node:assert/strict';
|
|
|
|
|
import { hapticsSupported, tick } from './haptics';
|
|
|
|
|
|
2026-09-20 15:32:32 -04:00
|
|
|
// Node 22 exposes a read-only `globalThis.navigator`; swap it via defineProperty.
|
|
|
|
|
const original = Object.getOwnPropertyDescriptor(globalThis, 'navigator');
|
|
|
|
|
const setGlobal = (name: 'navigator' | 'window', value: unknown) =>
|
|
|
|
|
Object.defineProperty(globalThis, name, { value, configurable: true, writable: true });
|
|
|
|
|
const restore = () => {
|
|
|
|
|
if (original) Object.defineProperty(globalThis, 'navigator', original);
|
|
|
|
|
else delete (globalThis as { navigator?: unknown }).navigator;
|
|
|
|
|
delete (globalThis as { window?: unknown }).window;
|
|
|
|
|
};
|
2026-09-20 15:15:04 -04:00
|
|
|
|
|
|
|
|
test('tick is a no-op without the API, with the setting off, or under reduced motion', () => {
|
2026-09-20 15:32:32 -04:00
|
|
|
setGlobal('navigator', {});
|
2026-09-20 15:15:04 -04:00
|
|
|
assert.equal(hapticsSupported(), false);
|
|
|
|
|
assert.equal(tick('ptt-on'), false);
|
|
|
|
|
|
|
|
|
|
const calls: number[] = [];
|
2026-09-20 15:32:32 -04:00
|
|
|
setGlobal('navigator', { vibrate: (ms: number) => calls.push(ms) === 1 });
|
|
|
|
|
setGlobal('window', { matchMedia: () => ({ matches: true }) });
|
2026-09-20 15:15:04 -04:00
|
|
|
assert.equal(tick('ptt-on'), false);
|
|
|
|
|
assert.deepEqual(calls, []);
|
|
|
|
|
|
2026-09-20 15:32:32 -04:00
|
|
|
setGlobal('window', { matchMedia: () => ({ matches: false }) });
|
2026-09-20 15:15:04 -04:00
|
|
|
assert.equal(tick('ptt-on', false), false);
|
|
|
|
|
assert.deepEqual(calls, []);
|
2026-09-20 15:32:32 -04:00
|
|
|
restore();
|
2026-09-20 15:15:04 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test('tick vibrates per kind when allowed', () => {
|
|
|
|
|
const calls: number[] = [];
|
2026-09-20 15:32:32 -04:00
|
|
|
setGlobal('navigator', { vibrate: (ms: number) => calls.push(ms) > 0 });
|
|
|
|
|
setGlobal('window', { matchMedia: () => ({ matches: false }) });
|
2026-09-20 15:15:04 -04:00
|
|
|
assert.equal(tick('ptt-on'), true);
|
|
|
|
|
assert.equal(tick('ptt-off'), true);
|
|
|
|
|
assert.equal(tick('reaction'), true);
|
|
|
|
|
assert.deepEqual(calls, [10, 10, 8]);
|
2026-09-20 15:32:32 -04:00
|
|
|
restore();
|
2026-09-20 15:15:04 -04:00
|
|
|
});
|