Paint saved playlists before the launch sync and swap a background-downloaded update instantly
This commit is contained in:
@@ -16,7 +16,16 @@
|
||||
|
||||
const { test } = require('node:test');
|
||||
const assert = require('node:assert');
|
||||
const { applyUpdate, refreshShellInPlace, BUST_PARAM } = require('./sw-update');
|
||||
const { applyUpdate, refreshShellInPlace, askCacheStatus, BUST_PARAM } = require('./sw-update');
|
||||
|
||||
// Minimal MessageChannel stand-in: port2 is handed to the "worker", which
|
||||
// delivers a reply back through port1.onmessage.
|
||||
function FakeChannel() {
|
||||
const p1 = { onmessage: null };
|
||||
const p2 = { __deliver: (data) => { if (p1.onmessage) p1.onmessage({ data }); } };
|
||||
this.port1 = p1;
|
||||
this.port2 = p2;
|
||||
}
|
||||
|
||||
const ORIGIN = 'https://worship.example';
|
||||
|
||||
@@ -211,3 +220,79 @@ test('applyUpdate with no registration at all still reloads', async () => {
|
||||
await applyUpdate({ reg: null, container: fakeContainer(), reload: () => { reloads++; } });
|
||||
assert.strictEqual(reloads, 1);
|
||||
});
|
||||
|
||||
// ---- background download + instant swap ------------------------------------
|
||||
|
||||
test('applyUpdate skips the download when the waiting worker already precached the build', async () => {
|
||||
const order = [];
|
||||
const container = fakeContainer();
|
||||
await applyUpdate({
|
||||
reg: { waiting: { postMessage: (m) => order.push('msg:' + m.type) } },
|
||||
container,
|
||||
reload: () => order.push('reload'),
|
||||
refreshShell: async () => { order.push('refresh'); },
|
||||
askStatus: async () => ({ ready: true, version: 'new' }),
|
||||
onPhase: (p) => order.push('phase:' + p),
|
||||
setTimeout: () => {},
|
||||
});
|
||||
assert.deepStrictEqual(order, ['phase:ready', 'msg:SKIP_WAITING'],
|
||||
'the whole point: no re-download when the shell is already on disk');
|
||||
container.fireControllerChange();
|
||||
assert.ok(order.includes('reload'));
|
||||
});
|
||||
|
||||
test('applyUpdate still downloads when the waiting worker reports an incomplete cache', async () => {
|
||||
const order = [];
|
||||
await applyUpdate({
|
||||
reg: { waiting: { postMessage: (m) => order.push('msg:' + m.type) } },
|
||||
container: fakeContainer(),
|
||||
reload: () => order.push('reload'),
|
||||
refreshShell: async () => { order.push('refresh'); },
|
||||
askStatus: async () => ({ ready: false, missing: 3 }),
|
||||
onPhase: (p) => order.push('phase:' + p),
|
||||
setTimeout: () => {},
|
||||
});
|
||||
assert.deepStrictEqual(order, ['phase:downloading', 'refresh', 'msg:SKIP_WAITING']);
|
||||
});
|
||||
|
||||
test('a worker that never answers falls back to downloading, it does not hang', async () => {
|
||||
const order = [];
|
||||
await applyUpdate({
|
||||
reg: { waiting: { postMessage: () => {} } },
|
||||
container: fakeContainer(),
|
||||
reload: () => order.push('reload'),
|
||||
refreshShell: async () => { order.push('refresh'); },
|
||||
askStatus: async () => null, // no reply / timed out
|
||||
setTimeout: () => {},
|
||||
});
|
||||
assert.deepStrictEqual(order, ['refresh']);
|
||||
});
|
||||
|
||||
test('a failing status probe is not fatal — the download path still runs', async () => {
|
||||
const order = [];
|
||||
await applyUpdate({
|
||||
reg: { waiting: { postMessage: () => {} } },
|
||||
container: fakeContainer(),
|
||||
reload: () => order.push('reload'),
|
||||
refreshShell: async () => { order.push('refresh'); },
|
||||
askStatus: async () => { throw new Error('port closed'); },
|
||||
setTimeout: () => {},
|
||||
});
|
||||
assert.deepStrictEqual(order, ['refresh']);
|
||||
});
|
||||
|
||||
test('askCacheStatus resolves null when the worker never replies', async () => {
|
||||
let fire = null;
|
||||
const p = askCacheStatus(
|
||||
{ postMessage() {} },
|
||||
{ timeoutMs: 10, setTimeout: (fn) => { fire = fn; }, Channel: FakeChannel },
|
||||
);
|
||||
fire();
|
||||
assert.strictEqual(await p, null);
|
||||
});
|
||||
|
||||
test('askCacheStatus returns the worker reply', async () => {
|
||||
const worker = { postMessage(_msg, ports) { ports[0].__deliver({ ready: true, version: 'abc' }); } };
|
||||
const got = await askCacheStatus(worker, { setTimeout: () => {}, Channel: FakeChannel });
|
||||
assert.deepStrictEqual(got, { ready: true, version: 'abc' });
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user