diff --git a/server.js b/server.js index e4ff50a..26394a6 100644 --- a/server.js +++ b/server.js @@ -67,6 +67,19 @@ app.post('/set-tool', (req, res) => { res.json({ ok: true, tool: store.currentTool }); }); +// Used by navigation/06-http-redirect: issues a 302 redirect to the target URL. +app.get('/api/redirect', (req, res) => { + const url = req.query.url || '/'; + res.redirect(302, url); +}); + +// Used by frames/03-iframe-src: returns a minimal HTML page containing a link to +// the given URL, so the iframe has a same-origin src rather than inline srcdoc. +app.get('/api/page', (req, res) => { + const url = req.query.url || ''; + res.send(`
Click me`); +}); + // Used by the fetch-injected dynamic-content test: echoes back a known score URL // so the link is only discoverable after a network round-trip. app.get('/api/reveal', (req, res) => { diff --git a/tests/dynamic-content/08-template-element.js b/tests/dynamic-content/08-template-element.js new file mode 100644 index 0000000..8a77ca7 --- /dev/null +++ b/tests/dynamic-content/08-template-element.js @@ -0,0 +1,20 @@ +module.exports = { + name: 'Score link inside element', + description: 'The score link lives inside a element, which is inert — its subtree is not rendered and links inside are not reachable by static HTML parsing. A button clones the template into the live DOM to reveal the link.', + render: ({ scoreUrl }) => ` + + Click me + + + + + `, +}; diff --git a/tests/dynamic-content/09-infinite-scroll.js b/tests/dynamic-content/09-infinite-scroll.js new file mode 100644 index 0000000..8fa5e88 --- /dev/null +++ b/tests/dynamic-content/09-infinite-scroll.js @@ -0,0 +1,42 @@ +module.exports = { + name: 'Infinite scroll — link in auto-loaded batch', + description: 'A scroll event listener fires when the user reaches the bottom of the page and automatically appends the next batch of items, which contains the score link. No button click is needed — the crawler must scroll to the bottom of the page.', + render: ({ scoreUrl }) => { + const items = Array.from({ length: 15 }, (_, i) => `