mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 10:24:02 +00:00
127 lines
3.2 KiB
JavaScript
127 lines
3.2 KiB
JavaScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { readFileSync } from 'node:fs';
|
|
import vm from 'node:vm';
|
|
|
|
const source = readFileSync(
|
|
new URL('../app/startupChrome.js', import.meta.url),
|
|
'utf8',
|
|
)
|
|
.replace(/^import .*;\n/gm, '')
|
|
.replace('export function', 'function');
|
|
|
|
function fixture() {
|
|
const timers = new Map();
|
|
const listeners = new Map();
|
|
const events = [];
|
|
let restored;
|
|
let nextTimer = 0;
|
|
const controller = new AbortController();
|
|
const context = {
|
|
console,
|
|
setTimeout(fn, delay) {
|
|
const id = ++nextTimer;
|
|
timers.set(id, { fn, delay });
|
|
return id;
|
|
},
|
|
clearTimeout(id) {
|
|
timers.delete(id);
|
|
},
|
|
initFirstRunExperience() {
|
|
events.push('welcome');
|
|
return { destroy: () => events.push('welcome:destroy') };
|
|
},
|
|
async initKeySetup() {
|
|
return { destroy: () => events.push('settings:destroy') };
|
|
},
|
|
};
|
|
vm.createContext(context);
|
|
vm.runInContext(source, context);
|
|
const stop = context.startApplicationChrome({
|
|
initializeSettings: context.initKeySetup,
|
|
loadingScreen: {
|
|
classList: { add: (value) => events.push(value) },
|
|
addEventListener: (type, listener) => listeners.set(type, listener),
|
|
removeEventListener: (type) => listeners.delete(type),
|
|
},
|
|
styleManager: {
|
|
initialRestorePromise: new Promise((resolve) => {
|
|
restored = resolve;
|
|
}),
|
|
},
|
|
dataManager: {},
|
|
signal: controller.signal,
|
|
});
|
|
return {
|
|
events,
|
|
listeners,
|
|
stop,
|
|
restored,
|
|
controller,
|
|
fire(delay) {
|
|
for (const [id, task] of timers) {
|
|
if (task.delay === delay) {
|
|
timers.delete(id);
|
|
task.fn();
|
|
}
|
|
}
|
|
},
|
|
timers,
|
|
};
|
|
}
|
|
async function flush() {
|
|
for (let i = 0; i < 12; i++) await Promise.resolve();
|
|
}
|
|
|
|
test('welcome waits for restoration, minimum delay, and the cover transition', async () => {
|
|
const f = fixture();
|
|
f.fire(1000);
|
|
await flush();
|
|
assert.deepEqual(f.events, []);
|
|
f.restored();
|
|
await flush();
|
|
assert.deepEqual(f.events, ['hidden']);
|
|
f.listeners.get('transitionend')();
|
|
f.fire(900);
|
|
assert.deepEqual(f.events, ['hidden', 'welcome']);
|
|
await f.stop();
|
|
assert.deepEqual(f.events.slice(-2), ['welcome:destroy', 'settings:destroy']);
|
|
assert.equal(f.timers.size, 0);
|
|
});
|
|
|
|
test('reduced motion uses the bounded fallback after the cover hides', async () => {
|
|
const f = fixture();
|
|
f.restored();
|
|
f.fire(1000);
|
|
await flush();
|
|
f.fire(900);
|
|
assert.deepEqual(f.events, ['hidden', 'welcome']);
|
|
await f.stop();
|
|
});
|
|
|
|
test('shutdown while restore is pending never reveals late welcome UI', async () => {
|
|
const f = fixture();
|
|
f.controller.abort();
|
|
await f.stop();
|
|
f.restored();
|
|
await flush();
|
|
f.fire(1000);
|
|
f.fire(900);
|
|
assert.deepEqual(f.events, ['settings:destroy']);
|
|
assert.equal(f.listeners.size, 0);
|
|
assert.equal(f.timers.size, 0);
|
|
});
|
|
|
|
test('shutdown during the cover transition cancels the listener and fallback', async () => {
|
|
const f = fixture();
|
|
f.restored();
|
|
f.fire(1000);
|
|
await flush();
|
|
const transition = f.listeners.get('transitionend');
|
|
f.controller.abort();
|
|
await f.stop();
|
|
transition();
|
|
f.fire(900);
|
|
assert.deepEqual(f.events, ['hidden', 'settings:destroy']);
|
|
});
|