diff --git a/tools/render/render-core.spec.ts b/tools/render/render-core.spec.ts index 094b9ab8..39402093 100644 --- a/tools/render/render-core.spec.ts +++ b/tools/render/render-core.spec.ts @@ -140,6 +140,28 @@ describe("the release's files", () => { } }); + it('a request answered after its render has ended is said, never thrown', async () => { + // Playwright runs a route's handler itself: a rejection from it is unhandled and ends + // the service, as a render that timed out while its file was being read once did. + const root = await mkdtemp(path.join(tmpdir(), 'render-core-files-')); + try { + await mkdir(path.join(root, '98', 'diagram'), { recursive: true }); + await writeFile(path.join(root, '98', 'diagram', 'R-HSA-1.json'), '{"x":1}'); + const { page, seen } = routed(); + await render(stand(page), { base: 'http://site', pathway: 'R-HSA-1', files: root }).catch( + () => undefined + ); + const [only] = seen(); + const handled = { + request: () => ({ url: () => 'https://download.reactome.org/98/diagram/R-HSA-1.json' }), + fulfill: () => Promise.reject(new Error('route.fulfill: Route is already handled!')), + } as unknown as Route; + await expect(only?.handler(handled)).resolves.toBeUndefined(); + } finally { + await rm(root, { recursive: true, force: true }); + } + }); + it('are left to the download site when no folder is given', async () => { const { page, seen } = routed(); await render(stand(page), { base: 'http://site', pathway: 'R-HSA-1' }).catch(() => undefined); diff --git a/tools/render/render-core.ts b/tools/render/render-core.ts index 64f1da38..1e8836be 100644 --- a/tools/render/render-core.ts +++ b/tools/render/render-core.ts @@ -186,9 +186,17 @@ export async function render( }; page.on('pageerror', onPageError); page.on('console', onConsole); + // A route handler's failure is no promise anyone awaits: Playwright runs the handler + // itself, so a rejection here is unhandled and ends the whole service. A request still + // being answered when the render has ended (timed out, its page closed) is "already + // handled" when its file arrives; that is said among the render's problems, never thrown. const fromFiles = async (route: Route, root: string) => { - const { status, contentType, body } = await localAnswer(root, new URL(route.request().url())); - return route.fulfill({ status, contentType, body }); + try { + const { status, contentType, body } = await localAnswer(root, new URL(route.request().url())); + await route.fulfill({ status, contentType, body }); + } catch (e) { + problems.push(`files: ${String(e).slice(0, 200)}`); + } }; const handler = files ? (route: Route) => fromFiles(route, files) : undefined; if (handler) await page.route(isDownload, handler);