diff --git a/tests/hs-run-filtered.js b/tests/hs-run-filtered.js index 8a1406a0..bbcb7f06 100755 --- a/tests/hs-run-filtered.js +++ b/tests/hs-run-filtered.js @@ -569,9 +569,28 @@ const _fetchRoutes = { '/number': { status: 200, body: '1.2' }, '/users/Joe': { status: 200, body: 'Joe', json: '{"name":"Joe"}' }, }; +// Per-test fetch overrides keyed by test name; takes priority over _fetchRoutes. +const _fetchScripts = { + "as response does not throw on 404": + { "/test": { status: 404, body: "not found" } }, + "do not throw passes through 404 response": + { "/test": { status: 404, body: "the body" } }, + "don't throw passes through 404 response": + { "/test": { status: 404, body: "the body" } }, + "throws on non-2xx response by default": + { "/test": { status: 404, body: "not found" } }, + "Response can be converted to JSON via as JSON": + { "/test": { status: 200, body: '{"name":"Joe"}', json: '{"name":"Joe"}', + contentType: "application/json" } }, + "can catch an error that occurs when using fetch": + { "/test": { networkError: true } }, + "triggers an event just before fetching": + { "/test": { status: 200, body: "yay", contentType: "text/html" } }, +}; function _mockFetch(url) { - const route = _fetchRoutes[url] || _fetchRoutes['/test']; - return { ok: route.status < 400, status: route.status || 200, url: url || '/test', + const scriptRoutes = _fetchScripts[globalThis.__currentHsTestName]; + const route = (scriptRoutes && scriptRoutes[url]) || _fetchRoutes[url] || _fetchRoutes['/test']; + return { ok: (route.status||200) < 400, status: route.status || 200, url: url || '/test', _body: route.body || '', _json: route.json || route.body || '', _html: route.html || route.body || '' }; } globalThis._driveAsync=function driveAsync(r,d){d=d||0;if(d>500||!r||!r.suspended)return;if(_testDeadline && Date.now()>_testDeadline)throw new Error('TIMEOUT: wall clock exceeded');const req=r.request;const items=req&&(req.items||req);const op=items&&items[0];const opName=typeof op==='string'?op:(op&&op.name)||String(op); @@ -580,8 +599,10 @@ globalThis._driveAsync=function driveAsync(r,d){d=d||0;if(d>500||!r||!r.suspende else if(opName==='io-fetch'){ const url=typeof items[1]==='string'?items[1]:'/test'; const fmt=typeof items[2]==='string'?items[2]:'text'; - const route=_fetchRoutes[url]||_fetchRoutes['/test']; - if(fmt==='json'){try{doResume(JSON.parse(route.json||route.body||'{}'));}catch(e){doResume(null);}} + const scriptRoutes=_fetchScripts[globalThis.__currentHsTestName]; + const route=(scriptRoutes&&scriptRoutes[url])||_fetchRoutes[url]||_fetchRoutes['/test']; + if(route&&route.networkError){doResume({_network_error:true,message:'aborted'});} + else if(fmt==='json'){try{doResume(JSON.parse(route.json||route.body||'{}'));}catch(e){doResume(null);}} else if(fmt==='html'){const frag=new El('fragment');frag.nodeType=11;frag.innerHTML=route.html||route.body||'';frag.textContent=frag.innerHTML.replace(/<[^>]*>/g,'');doResume(frag);} else if(fmt==='response')doResume({ok:(route.status||200)<400,status:route.status||200,url}); else if(fmt.toLowerCase()==='number')doResume(parseFloat(route.number||route.body||'0'));