fix: restrict PWA cache and report actual offline capabilities
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import vm from 'node:vm';
|
||||
import fs from 'node:fs';
|
||||
const script=fs.readFileSync(new URL('../public/sw.js',import.meta.url),'utf8');
|
||||
function harness() {
|
||||
const handlers={},writes=[],deleted=[];
|
||||
let network=()=>Promise.resolve(new Response('app',{headers:{'content-type':'text/html'}}));
|
||||
const cached=new Map([['/',new Response('offline app')]]);
|
||||
const key=r=>typeof r==='string'?r:new URL(r.url).pathname;
|
||||
const caches={keys:async()=>['ihaleist-v2','ihaleist-v3','other-app'],
|
||||
delete:async name=>{deleted.push(name);return true;},
|
||||
match:async request=>cached.get(key(request))?.clone(),
|
||||
open:async()=>({put:async(request,response)=>{writes.push(key(request));cached.set(key(request),response);},addAll:async()=>{}})};
|
||||
vm.runInNewContext(script,{URL,Response,caches,fetch:request=>network(request),self:{location:{origin:'https://ihaleist.test'},
|
||||
addEventListener:(name,handler)=>{handlers[name]=handler;},clients:{claim:async()=>{}},skipWaiting:async()=>{}}});
|
||||
return {writes,deleted,handlers,setNetwork:fn=>{network=fn;},async fetch(path,{mode='cors',authorization=false,method='GET'}={}) {
|
||||
let response;const pending=[];
|
||||
handlers.fetch({request:{url:'https://ihaleist.test'+path,method,mode,headers:new Headers(authorization?{authorization:'Bearer test'}:{})},
|
||||
respondWith:p=>{response=p;},waitUntil:p=>pending.push(p)});
|
||||
const out=await response;await Promise.all(pending);return out;
|
||||
}};
|
||||
}
|
||||
test('worker ignores API, arbitrary GET and authorized resources; removes only own old caches',async()=>{
|
||||
const h=harness();
|
||||
for(const path of ['/api/me/documents','/mcp','/private-report'])assert.equal(await h.fetch(path),undefined);
|
||||
assert.equal(await h.fetch('/assets/app.js',{authorization:true}),undefined);
|
||||
assert.equal(await h.fetch('/',{method:'POST'}),undefined);
|
||||
assert.deepEqual(h.writes,[]);
|
||||
let activation;h.handlers.activate({waitUntil:p=>{activation=p;}});await activation;
|
||||
assert.deepEqual(h.deleted,['ihaleist-v2']);
|
||||
});
|
||||
test('failed navigation never overwrites offline shell, assets never receive HTML fallback',async()=>{
|
||||
const h=harness();
|
||||
h.setNetwork(async()=>new Response('server error',{status:500}));
|
||||
assert.equal((await h.fetch('/',{mode:'navigate'})).status,500);
|
||||
assert.deepEqual(h.writes,[]);
|
||||
h.setNetwork(async()=>{throw new Error('offline');});
|
||||
assert.equal(await (await h.fetch('/',{mode:'navigate'})).text(),'offline app');
|
||||
await assert.rejects(()=>h.fetch('/assets/app.js'),/offline/);
|
||||
h.setNetwork(async()=>new Response('<html>wrong asset</html>',{headers:{'content-type':'text/html'}}));
|
||||
await h.fetch('/assets/app.js');await h.fetch('/assets/app.css');assert.deepEqual(h.writes,[]);
|
||||
h.setNetwork(async()=>new Response('export default 1',{headers:{'content-type':'text/javascript'}}));
|
||||
await h.fetch('/assets/app.js');assert.deepEqual(h.writes,['/assets/app.js']);
|
||||
});
|
||||
Reference in New Issue
Block a user