From 713b3605751e70f0c0aad0d3c8a18712649d3a12 Mon Sep 17 00:00:00 2001 From: Nic Polumeyv <162764842+Nic-Polumeyv@users.noreply.github.com> Date: Thu, 20 Aug 2026 16:32:25 -0400 Subject: [PATCH 01/12] run the basics server tests against Server.respond instead of a browser --- .../kit/test/apps/basics/test/server.setup.js | 10 + .../kit/test/apps/basics/test/server.spec.js | 1555 +++++++++++++++++ .../kit/test/apps/basics/test/server.test.js | 1466 ---------------- packages/kit/test/records.js | 51 + packages/kit/test/utils.js | 49 +- packages/kit/vitest.kit.config.js | 10 + 6 files changed, 1629 insertions(+), 1512 deletions(-) create mode 100644 packages/kit/test/apps/basics/test/server.setup.js create mode 100644 packages/kit/test/apps/basics/test/server.spec.js create mode 100644 packages/kit/test/records.js diff --git a/packages/kit/test/apps/basics/test/server.setup.js b/packages/kit/test/apps/basics/test/server.setup.js new file mode 100644 index 000000000000..3e0f3ccbdea6 --- /dev/null +++ b/packages/kit/test/apps/basics/test/server.setup.js @@ -0,0 +1,10 @@ +import { execSync } from 'node:child_process'; +import path from 'node:path'; + +// builds the app once for server.spec.js, which calls the built server directly +export default function setup() { + execSync('node test/setup.js && pnpm svelte-kit sync && pnpm run build', { + cwd: path.resolve(import.meta.dirname, '..'), + stdio: 'inherit' + }); +} diff --git a/packages/kit/test/apps/basics/test/server.spec.js b/packages/kit/test/apps/basics/test/server.spec.js new file mode 100644 index 000000000000..922633f416af --- /dev/null +++ b/packages/kit/test/apps/basics/test/server.spec.js @@ -0,0 +1,1555 @@ +/** @import { Server } from '@sveltejs/kit' */ +import { createHash, randomBytes } from 'node:crypto'; +import fs from 'node:fs'; +import http from 'node:http'; +import path from 'node:path'; +import { pathToFileURL } from 'node:url'; +import { createReadableStream } from '@sveltejs/kit/node'; +import { loadEnv } from 'vite'; +import { afterEach, beforeAll, describe, expect, test } from 'vitest'; +import * as records from '../../../records.js'; + +// These tests call the built server directly, so they cover what the no-js Playwright +// project covered for server responses without a browser or a web server. server.setup.js +// builds the app first. + +const root = path.resolve(import.meta.dirname, '..'); +const out = path.join(root, '.svelte-kit/output/server'); +const origin = 'http://localhost:3000'; + +/** @type {Server} */ +let server; + +beforeAll(async () => { + // the app writes test/errors.jsonl and test/spans.jsonl relative to cwd + process.chdir(root); + + // the preview server gets these from Vite's .env loading + for (const [key, value] of Object.entries(loadEnv('production', root, ''))) { + process.env[key] ??= value; + } + + const { manifest } = await import(pathToFileURL(path.join(out, 'manifest.js')).href); + const { Server } = await import(pathToFileURL(path.join(out, 'index.js')).href); + + server = new Server(manifest); + await server.init({ + env: process.env, + read: (file) => + createReadableStream( + path.join(fs.existsSync(path.join(out, file)) ? out : `${root}/static`, file) + ) + }); +}); + +/** @type {WeakMap} */ +const urls = new WeakMap(); + +/** + * Request a path from the built server. Redirects are followed like Playwright's + * `request.get` follows them, unless `redirect: 'manual'` is passed. + * @param {string} pathname + * @param {RequestInit} [init] + */ +async function get(pathname, init = {}) { + let url = origin + pathname; + + for (let hops = 0; ; hops++) { + const request = new Request(url, init); + if (!request.headers.has('accept')) request.headers.set('accept', '*/*'); + + let response = await server.respond(request, { getClientAddress: () => '127.0.0.1' }); + + const location = response.headers.get('location'); + + if (init.redirect === 'manual' || !location || response.status < 300 || hops === 20) { + // an HTTP server drops the body of a HEAD response + if (request.method === 'HEAD') response = new Response(null, response); + urls.set(response, url); + return response; + } + + url = new URL(location, url).href; + if (response.status !== 307 && response.status !== 308) init = {}; + } +} + +/** The URL a followed redirect ended on, like Playwright's `response.url()` */ +const url_of = (/** @type {Response} */ response) => /** @type {string} */ (urls.get(response)); + +/** + * Request a page and parse it, for the assertions that used `page.textContent` + * @param {string} pathname + * @param {RequestInit} [init] + */ +async function load(pathname, init) { + const response = await get(pathname, init); + const document = new DOMParser().parseFromString(await response.text(), 'text/html'); + return { response, document }; +} + +const read_errors = (/** @type {string} */ pathname) => + records.read_errors(path.join(root, 'test/errors.jsonl'), pathname); + +const read_traces = (/** @type {string} */ test_id) => + records.read_traces(path.join(root, 'test/spans.jsonl'), test_id); + +/** @type {http.Server[]} */ +const servers = []; + +/** + * An external server for the tests that fetch across origins + * @param {(req: http.IncomingMessage, res: http.ServerResponse) => void} handler + */ +function start_server(handler) { + const server = http.createServer(handler); + servers.push(server); + + return new Promise((fulfil) => { + server.listen(0, 'localhost', () => { + const { port } = /** @type {import('net').AddressInfo} */ (server.address()); + fulfil({ port }); + }); + }); +} + +afterEach(async () => { + await Promise.all(servers.splice(0).map((server) => new Promise((r) => server.close(r)))); +}); + +describe('Caching', () => { + test('caches pages', async () => { + const response = await get('/caching'); + expect(response.headers.get('cache-control')).toBe('public, max-age=30'); + }); +}); + +describe('Content-Type', () => { + test('sets Content-Type on page', async () => { + const response = await get('/content-type-header'); + expect(response.headers.get('content-type')).toBe('text/html'); + }); +}); + +describe('Content-Length', () => { + test('sets Content-Length on page', async () => { + const response = await get('/content-length-header'); + + if (!response.headers.get('content-encoding')) { + expect(Number(response.headers.get('content-length'))).toBeGreaterThan(1000); + } + }); +}); + +describe('Cookies', () => { + test('does not forward cookies from external domains', async () => { + const { port } = await start_server(async (req, res) => { + if (req.url === '/') { + res.writeHead(200, { + 'set-cookie': 'external=true', + 'access-control-allow-origin': '*' + }); + + res.end('ok'); + } else { + res.writeHead(404); + res.end('not found'); + } + }); + + const response = await get(`/load/fetch-external-no-cookies?port=${port}`); + expect(response.headers.getSetCookie().join('\n')).not.toContain('external=true'); + }); +}); + +describe('CSRF', () => { + test('Blocks requests with incorrect origin', async () => { + const content_types = [ + 'application/x-www-form-urlencoded', + 'multipart/form-data', + 'text/plain', + 'text/plaiN' + ]; + const methods = ['POST', 'PUT', 'PATCH', 'DELETE']; + for (const method of methods) { + for (const content_type of content_types) { + const res = await get('/csrf', { method, headers: { 'content-type': content_type } }); + const message = `request method: ${method}, content-type: ${content_type}`; + expect(res.status, message).toBe(403); + expect(await res.text(), message).toBe( + `Cross-site ${method} form submissions are forbidden` + ); + } + } + }); + + test('Allows requests from same origin', async () => { + const res = await get('/csrf', { + method: 'POST', + headers: { 'content-type': 'application/x-www-form-urlencoded', origin } + }); + expect(res.status).toBe(200); + expect(await res.text()).toBe('ok'); + }); + + test('Allows requests from allowed origins', async () => { + // Test with trusted.example.com which is in trustedOrigins + const res1 = await get('/csrf', { + method: 'POST', + headers: { + 'content-type': 'application/x-www-form-urlencoded', + origin: 'https://trusted.example.com' + } + }); + expect(res1.status).toBe(200); + expect(await res1.text()).toBe('ok'); + + // Test with payment-gateway.test which is also in trustedOrigins + const res2 = await get('/csrf', { + method: 'POST', + headers: { + 'content-type': 'application/x-www-form-urlencoded', + origin: 'https://payment-gateway.test' + } + }); + expect(res2.status).toBe(200); + expect(await res2.text()).toBe('ok'); + }); + + test('Blocks requests from non-allowed origins', async () => { + // Test with origin not in trustedOrigins list + const res1 = await get('/csrf', { + method: 'POST', + headers: { + 'content-type': 'application/x-www-form-urlencoded', + origin: 'https://malicious-site.com' + } + }); + expect(res1.status).toBe(403); + expect(await res1.text()).toBe('Cross-site POST form submissions are forbidden'); + + // Test with similar but not exact origin + const res2 = await get('/csrf', { + method: 'POST', + headers: { + 'content-type': 'application/x-www-form-urlencoded', + origin: 'https://trusted.example.com.evil.com' + } + }); + expect(res2.status).toBe(403); + expect(await res2.text()).toBe('Cross-site POST form submissions are forbidden'); + + // Test subdomain attack (should be blocked) + const res3 = await get('/csrf', { + method: 'POST', + headers: { + 'content-type': 'application/x-www-form-urlencoded', + origin: 'https://evil.trusted.example.com' + } + }); + expect(res3.status).toBe(403); + expect(await res3.text()).toBe('Cross-site POST form submissions are forbidden'); + }); + + test('Allows GET requests regardless of origin', async () => { + const res = await get('/csrf', { + method: 'GET', + headers: { + 'content-type': 'application/x-www-form-urlencoded', + origin: 'https://any-origin.com' + } + }); + expect(res.status).toBe(200); + }); + + test('Allows non-form content types regardless of origin', async () => { + const res = await get('/csrf', { + method: 'POST', + headers: { + 'content-type': 'application/json', + origin: 'https://any-origin.com' + } + }); + expect(res.status).toBe(200); + }); + + test('Allows all protected HTTP methods from allowed origins', async () => { + const methods = ['POST', 'PUT', 'PATCH', 'DELETE']; + for (const method of methods) { + const res = await get('/csrf', { + method, + headers: { + 'content-type': 'application/x-www-form-urlencoded', + origin: 'https://trusted.example.com' + } + }); + expect(res.status, `Method ${method} should be allowed from trusted origin`).toBe(200); + expect(await res.text(), `Method ${method} should return ok`).toBe('ok'); + } + }); + + test('Handles undefined origin correctly', async () => { + // Some requests may have null origin (e.g., from certain mobile apps) + const res = await get('/csrf', { + method: 'POST', + headers: { + 'content-type': 'application/x-www-form-urlencoded' + } + }); + expect(res.status).toBe(403); + expect(await res.text()).toBe('Cross-site POST form submissions are forbidden'); + }); +}); + +describe('Endpoints', () => { + test('HEAD with matching headers but without body', async () => { + const url = '/endpoint-output/body'; + + const responses = { + head: await get(url, { method: 'HEAD' }), + get: await get(url) + }; + + const headers = { + head: Object.fromEntries(responses.head.headers), + get: Object.fromEntries(responses.get.headers) + }; + + expect(responses.head.status).toBe(200); + expect(responses.get.status).toBe(200); + expect(await responses.head.text()).toBe(''); + expect(await responses.get.text()).toBe('{}'); + + ['date', 'transfer-encoding'].forEach((name) => { + delete headers.head[name]; + delete headers.get[name]; + }); + + expect(headers.head).toEqual(headers.get); + }); + + test('invalid request method returns allow header', async () => { + const response = await get('/endpoint-output/body', { + method: 'POST', + headers: { origin: 'https://trusted.example.com' } + }); + + expect(response.status).toBe(405); + + const allow_header = response.headers.get('allow'); + expect(allow_header).toMatch(/\bGET\b/); + expect(allow_header).toMatch(/\bHEAD\b/); + }); + + test('405 allow header has no duplicate methods listed', async () => { + const response = await get('/endpoint-output/head-handler', { + method: 'POST', + headers: { origin: 'https://trusted.example.com' } + }); + + expect(response.status).toBe(405); + + const allow_header = /** @type {string} */ (response.headers.get('allow')); + const methods = allow_header.split(',').map((m) => m.trim()); + const unique_methods = [...new Set(methods)]; + + expect(methods).toEqual(unique_methods); + }); + + test('serves page for GET request when endpoint has no GET handler', async () => { + const response = await get('/endpoint-output/post-only-with-page', { + headers: { + accept: '*/*' + } + }); + + expect(response.status).toBe(200); + expect(response.headers.get('content-type')).toContain('text/html'); + expect(await response.text()).toContain('POST-only endpoint page'); + }); + + test('serves page for HEAD request when endpoint has no HEAD or GET handler', async () => { + const response = await get('/endpoint-output/post-only-with-page', { + method: 'HEAD', + headers: { + accept: '*/*' + } + }); + + expect(response.status).toBe(200); + expect(response.headers.get('content-type')).toContain('text/html'); + expect(response.headers.get('x-sveltekit-page')).toBe('true'); + expect(await response.text()).toBe(''); + }); + + test('POST to post-only endpoint with sibling page still hits endpoint', async () => { + const response = await get('/endpoint-output/post-only-with-page', { + method: 'POST', + headers: { origin: 'https://trusted.example.com' } + }); + + expect(response.status).toBe(200); + expect(await response.text()).toBe('ok'); + }); + + test('uses fallback handler instead of page when endpoint has no GET but has fallback', async () => { + const response = await get('/endpoint-output/fallback-with-page', { + headers: { + accept: '*/*' + } + }); + + expect(response.status).toBe(200); + expect(await response.text()).toBe('catch-all'); + }); + + test('content negotiation: API requests hit endpoint, browser requests hit page', async () => { + // application/json → endpoint + const api_response = await get('/routing/content-negotiation', { + headers: { + accept: 'application/json' + } + }); + + expect(api_response.status).toBe(200); + expect(await api_response.text()).toBe('GET'); + + // text/html → page + const html_response = await get('/routing/content-negotiation', { + headers: { + accept: 'text/html' + } + }); + + expect(html_response.status).toBe(200); + expect(html_response.headers.get('content-type')).toContain('text/html'); + expect(await html_response.text()).toContain('Hi'); + }); + + // TODO all the remaining tests in this section are really only testing + // setResponse, since we're not otherwise changing anything on the response. + // might be worth making these unit tests instead + test('multiple set-cookie on endpoints using GET', async () => { + const response = await get('/set-cookie'); + + const cookies = response.headers.getSetCookie(); + + expect(cookies).toEqual([ + 'answer=42; HttpOnly', + 'problem=comma, separated, values; HttpOnly', + 'name=SvelteKit; path=/; HttpOnly' + ]); + }); + + // TODO see above + test('body can be a binary ReadableStream', async () => { + const interruptedResponse = await get('/endpoint-output/stream-throw-error'); + await expect(interruptedResponse.text()).rejects.toThrow('simulate error'); + + const response = await get('/endpoint-output/stream'); + const body = Buffer.from(await response.arrayBuffer()); + const digest = createHash('sha256').update(body).digest('base64url'); + expect(response.headers.get('digest')).toEqual(`sha-256=${digest}`); + }); + + // TODO see above + test('request body can be read slow', async () => { + const data = randomBytes(1024 * 256); + const digest = createHash('sha256').update(data).digest('base64url'); + const response = await get('/endpoint-input/sha256', { + method: 'PUT', + headers: { 'content-type': 'application/octet-stream' }, + body: data + }); + expect(await response.text()).toEqual(digest); + }); + + test('OPTIONS handler', async () => { + const url = '/endpoint-output'; + + const response = await get(url, { + method: 'OPTIONS' + }); + + expect(response.status).toBe(200); + expect(await response.text()).toBe('ok'); + }); + + test('HEAD handler', async () => { + const url = '/endpoint-output/head-handler'; + + const page_response = await get(url, { + method: 'HEAD', + headers: { + accept: 'text/html' + } + }); + + expect(page_response.status).toBe(200); + expect(await page_response.text()).toBe(''); + expect(page_response.headers.get('x-sveltekit-page')).toBe('true'); + + const endpoint_response = await get(url, { + method: 'HEAD', + headers: { + accept: 'application/json' + } + }); + + expect(endpoint_response.status).toBe(200); + expect(await endpoint_response.text()).toBe(''); + expect(endpoint_response.headers.get('x-sveltekit-head-endpoint')).toBe('true'); + }); + + test('catch-all handler', async () => { + const url = '/endpoint-output/fallback'; + + let response = await get(url, { + method: 'GET' + }); + + expect(response.status).toBe(200); + expect(await response.text()).toBe('ok'); + + response = await get(url, { + method: 'MOVE' // also works with arcane methods + }); + + expect(response.status).toBe(200); + expect(await response.text()).toBe('catch-all'); + + response = await get(url, { + method: 'OPTIONS' + }); + + expect(response.status).toBe(200); + expect(await response.text()).toBe('catch-all'); + }); + + test('QUERY handler', async () => { + const url = '/endpoint-output/query'; + + let response = await get(url, { + method: 'QUERY', + body: 'name=world' + }); + + expect(response.status).toBe(200); + expect(await response.text()).toBe('query: name=world'); + + response = await get(url, { + method: 'MOVE' + }); + + expect(response.status).toBe(405); + expect(response.headers.get('allow')).toBe('GET, QUERY, HEAD'); + }); + + test('can get assets using absolute path', async () => { + const response = await get('/endpoint-output/fetch-asset/absolute'); + expect(response.status).toBe(200); + expect(response.headers.get('content-type')).toBe('text/plain'); + expect(await response.text()).toBe('Cos sie konczy, cos zaczyna'); + }); + + test('can get assets using relative path', async () => { + const response = await get('/endpoint-output/fetch-asset/relative'); + expect(response.status).toBe(200); + expect(response.headers.get('content-type')).toBe('text/plain'); + expect(await response.text()).toBe('Cos sie konczy, cos zaczyna'); + }); +}); + +describe('Errors', () => { + test('uses the handleError status for the fallback page served to error-page sub-requests', async () => { + const response = await get('/errors/handle-error-status-fallback', { + headers: { 'x-sveltekit-error': 'true' } + }); + expect(response.status).toBe(503); + }); + + test('invalid route response is handled', async () => { + const response = await get('/errors/invalid-route-response'); + + expect(response.status).toBe(500); + expect(await response.text()).toMatch( + 'Invalid response from route /errors/invalid-route-response: handler should return a Response object' + ); + }); + + test('unhandled http method', async () => { + const response = await get('/errors/invalid-route-response', { + method: 'PUT', + headers: { origin: 'https://trusted.example.com' } + }); + + expect(response.status).toBe(405); + expect(await response.text()).toMatch('PUT method not allowed'); + }); + + test('error evaluating module', async () => { + const response = await get('/errors/init-error-endpoint'); + + expect(response.status).toBe(500); + expect(await response.text()).toMatch('thisvariableisnotdefined is not defined'); + }); + + test('returns a lightweight 404 for subresource requests', async () => { + // distinct from the path used by the test below, which _does_ invoke the hook + const response = await get('/errors/does-not-exist-lightweight-subresource', { + headers: { 'sec-fetch-dest': 'image' } + }); + + expect(response.status).toBe(404); + expect(await response.text()).toBe('Not Found'); + expect(response.headers.get('vary')).toContain('Sec-Fetch-Dest'); + + // lightweight 404s bypass the handleError hook + expect(read_errors('/errors/does-not-exist-lightweight-subresource')).toBe(undefined); + }); + + test('renders the error page for document and fetch requests', async () => { + for (const destination of ['document', null, 'empty']) { + const response = await get( + '/errors/does-not-exist-subresource', + destination ? { headers: { 'sec-fetch-dest': destination } } : {} + ); + + expect(response.status).toBe(404); + expect(await response.text()).toContain('This is your custom error page saying:'); + } + }); + + test('stack traces are not fixed twice', async () => { + let { document } = await load('/errors/stack-trace'); + expect(document.querySelector('#message')?.textContent).toBe( + 'This is your custom error page saying: "Cannot read properties of undefined (reading \'toUpperCase\') (500 Internal Error)"' + ); + + // check the stack wasn't mutated + ({ document } = await load('/errors/stack-trace')); + expect(document.querySelector('#message')?.textContent).toBe( + 'This is your custom error page saying: "Cannot read properties of undefined (reading \'toUpperCase\') (500 Internal Error)"' + ); + }); + + test('error(...) in endpoint', async () => { + // HTML + { + const res = await get('/errors/endpoint-throw-error', { + headers: { + accept: 'text/html' + } + }); + + expect(read_errors('/errors/endpoint-throw-error')).toEqual({ + kind: 'app', + error: { status: 401, message: 'You shall not pass' } + }); + + expect(res.status).toBe(401); + expect(await res.text()).toContain( + 'This is the static error page with the following message: You shall not pass' + ); + } + + // JSON (default) + { + const res = await get('/errors/endpoint-throw-error'); + + expect(read_errors('/errors/endpoint-throw-error')).toEqual({ + kind: 'app', + error: { status: 401, message: 'You shall not pass' } + }); + + expect(res.status).toBe(401); + expect(await res.json()).toEqual({ + message: 'You shall not pass', + status: 401 + }); + } + }); + + test('redirect(...) in endpoint', async () => { + const { response, document } = await load('/errors/endpoint-throw-redirect'); + expect(response.status).toBe(200); // redirects are opaque to the browser + + const error = read_errors('/errors/endpoint-throw-redirect'); + expect(error).toBe(undefined); + + expect(document.querySelector('h1')?.textContent).toBe('the answer is 42'); + }); + + test('POST to missing page endpoint', async () => { + const res = await get('/errors/missing-actions', { + method: 'POST', + headers: { + accept: 'text/html', + origin: 'https://trusted.example.com' + } + }); + expect(res.status).toBe(405); + + const res_json = await get('/errors/missing-actions', { + method: 'POST', + headers: { + accept: 'application/json', + origin: 'https://trusted.example.com' + } + }); + expect(res_json.status).toBe(405); + expect(await res_json.json()).toEqual({ + type: 'error', + location: '/errors/missing-actions', + error: { + message: 'Method Not Allowed (405 Method Not Allowed)', + status: 405 + } + }); + }); + + test('error thrown in handle results in a rendered error page or JSON response', async () => { + // HTML + { + const res = await get('/errors/error-in-handle', { + headers: { + accept: 'text/html' + } + }); + + expect(res.status).toBe(500); + expect(await res.text()).toContain( + 'This is the static error page with the following message: Error in handle' + ); + } + + // JSON (default) + { + const res = await get('/errors/error-in-handle'); + + const error = await res.json(); + + expect(error.stack).toBe(undefined); + expect(res.status).toBe(500); + expect(error).toEqual({ + message: 'Error in handle (500 Internal Error)', + status: 500 + }); + } + }); + + test('expected error thrown in handle results in a rendered error page or JSON response', async () => { + // HTML + { + const res = await get('/errors/expected-error-in-handle', { + headers: { + accept: 'text/html' + } + }); + + expect(res.status).toBe(500); + expect(await res.text()).toContain( + 'This is the static error page with the following message: Expected error in handle' + ); + } + + // JSON (default) + { + const res = await get('/errors/expected-error-in-handle'); + + const error = await res.json(); + + expect(error.stack).toBe(undefined); + expect(res.status).toBe(500); + expect(error).toEqual({ + message: 'Expected error in handle', + status: 500 + }); + } + }); + + test('error thrown from load on the server respects page options when rendering the error page', async () => { + const res = await get('/errors/load-error-page-options/csr'); + expect(res.status).toBe(500); + const content = await res.text(); + expect(content).toContain('Crashing now'); + // the hydration script should not be present if the csr page option is respected + expect(content).not.toContain('kit.start(app'); + }); + + test('returns root layout data for a missing route error page data request', async () => { + const data_response = await get( + '/this-route-does-not-exist/__data.json?x-sveltekit-invalidated=1' + ); + expect(data_response.status).toBe(200); + expect(data_response.headers.get('content-type')).toContain('application/json'); + + const data = await data_response.json(); + expect(data.type).toBe('data'); + expect(data.nodes[0].type).toBe('data'); + expect(data.nodes[0].data).toContain('rootlayout'); + + const page_response = await get('/this-route-does-not-exist/__data.json'); + expect(page_response.status).toBe(404); + expect(page_response.headers.get('content-type')).toContain('text/html'); + + // a single-node request that invalidates nothing is not an error-page data request + const crafted_response = await get( + '/this-route-does-not-exist/__data.json?x-sveltekit-invalidated=0' + ); + expect(crafted_response.status).toBe(404); + }); +}); + +describe('Load', () => { + test('fetch reads universal load assets on the server', async () => { + const { document } = await load('/load/fetch-asset'); + expect(document.querySelector('p')?.textContent).toBe('1'); + }); + + test('does not forward accept-language to internal fetch when the request has none', async () => { + // unlike browsers and undici, the `request` fixture sends no accept-language header + const html = await (await get('/load/fetch-request-headers')).text(); + const headers = JSON.parse( + /** @type {RegExpMatchArray} */ (/
(.+?)<\/pre>/s.exec(html))[1]
+		);
+		expect(headers.accept).toBe('*/*');
+		expect(headers['accept-language']).toBeUndefined();
+	});
+
+	test('includes origin header on non-GET internal request', async () => {
+		const { document } = await load('/load/fetch-origin-internal');
+		expect(document.querySelector('h1')?.textContent).toBe(`origin: ${origin}`);
+	});
+
+	test('includes origin header on external request', async () => {
+		const { port } = await start_server((req, res) => {
+			if (req.url === '/') {
+				res.writeHead(200, {
+					'content-type': 'application/json',
+					'access-control-allow-origin': '*'
+				});
+
+				res.end(JSON.stringify({ origin: req.headers.origin }));
+			} else {
+				res.writeHead(404);
+				res.end('not found');
+			}
+		});
+
+		const { document } = await load(`/load/fetch-origin-external?port=${port}`);
+		expect(document.querySelector('h1')?.textContent).toBe(`origin: ${origin}`);
+	});
+
+	test('does not run when using invalid request methods', async () => {
+		const load_url = '/load';
+
+		let response = await get(load_url, {
+			method: 'OPTIONS'
+		});
+
+		expect(response.status).toBe(204);
+		expect(await response.text()).toBe('');
+		expect(response.headers.get('allow')).toBe('GET, HEAD, OPTIONS');
+
+		const actions_url = '/actions/enhance';
+		response = await get(actions_url, {
+			method: 'OPTIONS'
+		});
+
+		expect(response.status).toBe(204);
+		expect(await response.text()).toBe('');
+		expect(response.headers.get('allow')).toBe('GET, HEAD, OPTIONS, POST');
+	});
+
+	test('allows logging URL search params', async () => {
+		const { document } = await load('/load/server-log-search-param');
+
+		expect(document.querySelector('p')?.textContent).toBe('hello world');
+	});
+});
+
+describe('Routing', () => {
+	test('event.params are available in handle', async () => {
+		const response = await get('/routing/params-in-handle/banana');
+		expect(await response.json()).toStrictEqual({
+			key: '/routing/params-in-handle/[x]',
+			params: { x: 'banana' }
+		});
+	});
+
+	test('/favicon.ico is a valid route', async () => {
+		const response = await get('/favicon.ico');
+		expect(response.status).toBe(200);
+
+		const data = await response.json();
+		expect(data).toEqual({ surprise: 'lol' });
+	});
+
+	test('falls back to page actions if sibling endpoint has no POST handler', async () => {
+		const response = await get('/endpoint-output/actions-with-endpoint', {
+			method: 'POST',
+			body: new URLSearchParams(),
+			headers: {
+				accept: 'application/json',
+				origin
+			}
+		});
+
+		expect(response.status).toBe(200);
+		expect((await response.json()).type).toBe('success');
+	});
+});
+
+describe('Shadowed pages', () => {
+	test('Action can return undefined', async () => {
+		const response = await get('/shadowed/simple/post', {
+			method: 'POST',
+			body: new URLSearchParams(),
+			headers: {
+				accept: 'application/json',
+				origin
+			}
+		});
+
+		expect(response.status).toBe(200);
+		expect(await response.json()).toEqual({
+			type: 'success',
+			status: 204,
+			location: '/shadowed/simple/post'
+		});
+	});
+
+	test('action response includes the stripped landing location', async () => {
+		const response = await get('/actions/cross-page/destination?redirectTo=%2Fdashboard&/failure', {
+			method: 'POST',
+			body: new URLSearchParams({ username: 'paolo' }),
+			headers: {
+				accept: 'application/json',
+				origin
+			}
+		});
+
+		expect(response.status).toBe(400);
+		expect(await response.json()).toEqual({
+			type: 'failure',
+			status: 400,
+			location: '/actions/cross-page/destination?redirectTo=%2Fdashboard',
+			data: '[{"problem":1,"username":2},"invalid","paolo"]'
+		});
+	});
+
+	test('Action fail() returns matching HTTP status code', async () => {
+		const response = await get('/actions/form-errors', {
+			method: 'POST',
+			body: new URLSearchParams(),
+			headers: {
+				accept: 'application/json',
+				origin
+			}
+		});
+
+		expect(response.status).toBe(400);
+		const body = await response.json();
+		expect(body.type).toBe('failure');
+		expect(body.status).toBe(400);
+	});
+});
+
+describe('setHeaders', () => {
+	test('allows multiple set-cookie headers with different values', async () => {
+		const response = await get('/headers/set-cookie/sub');
+		const cookies = response.headers.getSetCookie().join('\n');
+
+		expect(cookies).toMatch('cookie1=value1');
+		expect(cookies).toMatch('cookie2=value2');
+	});
+});
+
+describe('cookies', () => {
+	test('cookie.stringifySetCookie created correct cookie header string', async () => {
+		const response = await get('/cookies/serialize');
+		const cookies = response.headers.getSetCookie().join('\n');
+
+		expect(cookies).toMatch('before=before');
+		expect(cookies).toMatch('after=after');
+		expect(cookies).toMatch('endpoint=endpoint');
+	});
+});
+
+describe('Miscellaneous', () => {
+	test('handles responses with immutable headers', async () => {
+		const response = await get('/immutable-headers');
+		expect(response.status).toBe(200);
+		expect(await response.text()).toBe('foo');
+	});
+
+	test('does not send x-sveltekit-version header on document responses', async () => {
+		const response = await get('/');
+		expect(response.headers.get('x-sveltekit-version')).toBeNull();
+	});
+
+	test('sends x-sveltekit-version header on data responses', async () => {
+		const response = await get('/__data.json');
+		expect(response.headers.get('x-sveltekit-version')).toBeTruthy();
+	});
+});
+
+describe('reroute', () => {
+	test('Apply reroute when directly accessing a page', async () => {
+		const { document } = await load('/reroute/basic/a');
+		expect(document.querySelector('h1')?.textContent).toContain(
+			'Successfully rewritten, URL should still show a: /reroute/basic/a'
+		);
+	});
+
+	test('Apply async reroute when directly accessing a page', async () => {
+		const { document } = await load('/reroute/async/a', {
+			headers: { cookie: 'reroute-cookie=yes' }
+		});
+		expect(document.querySelector('h1')?.textContent).toContain(
+			'Successfully rewritten, URL should still show a: /reroute/async/a'
+		);
+	});
+
+	test('Returns a 500 response if reroute throws an error on the server', async () => {
+		const response = await get('/reroute/error-handling/server-error');
+		expect(response.status).toBe(500);
+	});
+});
+
+describe('init', () => {
+	test('init server hook is called once before the load function', async () => {
+		let { document } = await load('/init-hooks');
+		expect(document.querySelector('p')?.textContent).toBe('1');
+		({ document } = await load('/init-hooks'));
+		expect(document.querySelector('p')?.textContent).toBe('1');
+	});
+});
+
+describe('getRequestEvent', () => {
+	test('getRequestEvent works in server endpoints', async () => {
+		const response = await get('/get-request-event/endpoint');
+		expect(await response.text()).toBe('hello from hooks.server.js');
+	});
+});
+
+describe('$app/forms', () => {
+	test('deserialize works on the server', async () => {
+		const response = await get('/serialization-form-non-enhanced/server-deserialize');
+		expect(await response.json()).toEqual({ data: 'It works!' });
+	});
+});
+
+describe('$app/env', () => {
+	test('treeshakes dev check', async () => {
+		const code = fs.readFileSync(
+			path.join(root, '.svelte-kit/output/server/entries/pages/treeshaking/dev/_page.svelte.js'),
+			'utf-8'
+		);
+		expect(code).not.toContain('not prod');
+	});
+
+	test('treeshakes browser check', async () => {
+		const code = fs.readFileSync(
+			path.join(
+				root,
+				'.svelte-kit/output/server/entries/pages/treeshaking/browser/_page.svelte.js'
+			),
+			'utf-8'
+		);
+		expect(code).not.toMatch('client');
+	});
+});
+
+describe('tracing', () => {
+	// Helper function to find the resolve.root span deep in the handle.child chain
+	/**
+	 * @param {import('../../../types.js').SpanTree} span
+	 * @returns {import('../../../types.js').SpanTree | null}
+	 */
+	function find_resolve_root_span(span) {
+		if (span.name === 'sveltekit.resolve') {
+			return span;
+		}
+		for (const child of span.children || []) {
+			const found = find_resolve_root_span(child);
+			if (found) return found;
+		}
+		return null;
+	}
+
+	function rand() {
+		// node 18 doesn't have crypto.randomUUID() and we run tests in node 18
+		return Math.random().toString(36).substring(2, 15);
+	}
+
+	test('correct spans are created for a regular navigation', async () => {
+		const test_id = rand();
+		await get(`/tracing/one/two/three/four/five?test_id=${test_id}`);
+		const traces = read_traces(test_id);
+		expect(traces.length).toBeGreaterThan(0);
+
+		const trace = traces[0];
+		const trace_id = trace.trace_id;
+
+		// Verify root span structure
+		expect(trace).toEqual({
+			name: 'sveltekit.handle.root',
+			status: { code: 0 },
+			start_time: [expect.any(Number), expect.any(Number)],
+			end_time: [expect.any(Number), expect.any(Number)],
+			attributes: {
+				'http.route': '/tracing/one/two/three/[...four]',
+				'http.method': 'GET',
+				'http.url': expect.stringContaining(`/tracing/one/two/three/four/five?test_id=${test_id}`),
+				'sveltekit.is_data_request': false,
+				'sveltekit.is_sub_request': false,
+				test_id
+			},
+			links: [],
+			trace_id,
+			span_id: expect.any(String),
+			children: expect.arrayContaining([
+				expect.objectContaining({
+					name: 'sveltekit.handle.sequenced.set_tracing_test_id',
+					attributes: {}
+				})
+			])
+		});
+
+		// Find and verify the resolve.root span
+		const resolve_root_span = find_resolve_root_span(trace);
+		expect(resolve_root_span).not.toBeNull();
+		expect(resolve_root_span).toEqual({
+			name: 'sveltekit.resolve',
+			status: { code: 0 },
+			start_time: [expect.any(Number), expect.any(Number)],
+			end_time: [expect.any(Number), expect.any(Number)],
+			attributes: {
+				'http.route': '/tracing/one/two/three/[...four]',
+				'http.response.status_code': 200,
+				'http.response.body.size': expect.stringMatching(/^\d+$/)
+			},
+			links: [],
+			trace_id,
+			span_id: expect.any(String),
+			parent_span_id: expect.any(String),
+			children: [
+				{
+					name: 'sveltekit.load',
+					status: { code: 0 },
+					start_time: [expect.any(Number), expect.any(Number)],
+					end_time: [expect.any(Number), expect.any(Number)],
+					attributes: {
+						'sveltekit.load.node_id': 'src/routes/+layout.server.js',
+						'sveltekit.load.node_type': '+layout.server',
+						'sveltekit.load.environment': 'server',
+						'http.route': '/tracing/one/two/three/[...four]'
+					},
+					links: [],
+					trace_id,
+					span_id: expect.any(String),
+					parent_span_id: expect.any(String),
+					children: []
+				},
+				{
+					name: 'sveltekit.load',
+					status: { code: 0 },
+					start_time: [expect.any(Number), expect.any(Number)],
+					end_time: [expect.any(Number), expect.any(Number)],
+					attributes: {
+						'sveltekit.load.node_id': 'src/routes/+layout.js',
+						'sveltekit.load.node_type': '+layout',
+						'sveltekit.load.environment': 'server',
+						'http.route': '/tracing/one/two/three/[...four]'
+					},
+					links: [],
+					trace_id,
+					span_id: expect.any(String),
+					parent_span_id: expect.any(String),
+					children: []
+				}
+			]
+		});
+	});
+
+	test('correct spans are created for HttpError', async () => {
+		const test_id = rand();
+		const response = await get(`/tracing/http-error?test_id=${test_id}`);
+		expect(response.status).toBe(500);
+
+		const traces = read_traces(test_id);
+		const trace_id = traces[0].trace_id;
+		const trace = traces[0];
+
+		// Verify root span structure
+		expect(trace).toEqual({
+			name: 'sveltekit.handle.root',
+			status: { code: 0 },
+			start_time: [expect.any(Number), expect.any(Number)],
+			end_time: [expect.any(Number), expect.any(Number)],
+			attributes: {
+				'http.route': '/tracing/http-error',
+				'http.method': 'GET',
+				'http.url': expect.stringContaining(`/tracing/http-error?test_id=${test_id}`),
+				'sveltekit.is_data_request': false,
+				'sveltekit.is_sub_request': false,
+				test_id
+			},
+			links: [],
+			trace_id,
+			span_id: expect.any(String),
+			children: expect.arrayContaining([
+				expect.objectContaining({
+					name: 'sveltekit.handle.sequenced.set_tracing_test_id',
+					attributes: {}
+				})
+			])
+		});
+
+		// Find and verify the resolve.root span
+		const resolve_root_span = find_resolve_root_span(trace);
+		expect(resolve_root_span).not.toBeNull();
+		expect(resolve_root_span).toEqual({
+			name: 'sveltekit.resolve',
+			status: { code: 0 },
+			start_time: [expect.any(Number), expect.any(Number)],
+			end_time: [expect.any(Number), expect.any(Number)],
+			attributes: {
+				'http.route': '/tracing/http-error',
+				'http.response.status_code': 500,
+				'http.response.body.size': expect.stringMatching(/^\d+$/)
+			},
+			links: [],
+			trace_id,
+			span_id: expect.any(String),
+			parent_span_id: expect.any(String),
+			children: expect.arrayContaining([
+				expect.objectContaining({
+					name: 'sveltekit.load',
+					status: { code: 2, message: 'Internal server error from tracing test' },
+					attributes: expect.objectContaining({
+						'sveltekit.load.node_id': 'src/routes/tracing/http-error/+page.server.js',
+						'sveltekit.load.result.type': 'known_error',
+						'sveltekit.load.result.status': 500,
+						'sveltekit.load.result.message': 'Internal server error from tracing test'
+					})
+				})
+			])
+		});
+	});
+
+	test('correct spans are created for Redirect', async () => {
+		const test_id = rand();
+		const response = await get(`/tracing/redirect?test_id=${test_id}`);
+		expect(response.status).toBe(200);
+
+		const traces = read_traces(test_id);
+		expect(traces).toHaveLength(2);
+		const redirect_trace_id = traces[0].trace_id;
+		const destination_trace_id = traces[1].trace_id;
+
+		const redirect_trace = traces[0];
+		const destination_trace = traces[1];
+
+		// Verify redirect trace root span structure
+		expect(redirect_trace).toEqual({
+			name: 'sveltekit.handle.root',
+			status: { code: 0 },
+			start_time: [expect.any(Number), expect.any(Number)],
+			end_time: [expect.any(Number), expect.any(Number)],
+			attributes: {
+				'http.route': '/tracing/redirect',
+				'http.method': 'GET',
+				'http.url': expect.stringContaining(`/tracing/redirect?test_id=${test_id}`),
+				'sveltekit.is_data_request': false,
+				'sveltekit.is_sub_request': false,
+				test_id
+			},
+			links: [],
+			trace_id: redirect_trace_id,
+			span_id: expect.any(String),
+			children: expect.arrayContaining([
+				expect.objectContaining({
+					name: 'sveltekit.handle.sequenced.set_tracing_test_id',
+					attributes: {}
+				})
+			])
+		});
+
+		// Find and verify the redirect resolve.root span
+		const redirect_resolve_root_span = find_resolve_root_span(redirect_trace);
+		expect(redirect_resolve_root_span).not.toBeNull();
+		expect(redirect_resolve_root_span).toEqual({
+			name: 'sveltekit.resolve',
+			status: { code: 0 },
+			start_time: [expect.any(Number), expect.any(Number)],
+			end_time: [expect.any(Number), expect.any(Number)],
+			attributes: {
+				'http.route': '/tracing/redirect',
+				'http.response.status_code': 307,
+				'http.response.body.size': expect.stringMatching(/^\d+$|^unknown$/)
+			},
+			links: [],
+			trace_id: redirect_trace_id,
+			span_id: expect.any(String),
+			parent_span_id: expect.any(String),
+			children: expect.arrayContaining([
+				expect.objectContaining({
+					name: 'sveltekit.load',
+					status: { code: 0 },
+					attributes: expect.objectContaining({
+						'sveltekit.load.node_id': 'src/routes/tracing/redirect/+page.server.js',
+						'sveltekit.load.result.type': 'redirect',
+						'sveltekit.load.result.status': 307,
+						'sveltekit.load.result.location': `/tracing/one/two/three/four/five?test_id=${test_id}`
+					})
+				})
+			])
+		});
+
+		// Verify destination trace root span structure
+		expect(destination_trace).toEqual({
+			name: 'sveltekit.handle.root',
+			status: { code: 0 },
+			start_time: [expect.any(Number), expect.any(Number)],
+			end_time: [expect.any(Number), expect.any(Number)],
+			attributes: {
+				'http.route': '/tracing/one/two/three/[...four]',
+				'http.method': 'GET',
+				'http.url': expect.stringContaining(`/tracing/one/two/three/four/five?test_id=${test_id}`),
+				'sveltekit.is_data_request': false,
+				'sveltekit.is_sub_request': false,
+				test_id
+			},
+			links: [],
+			trace_id: destination_trace_id,
+			span_id: expect.any(String),
+			children: expect.arrayContaining([
+				expect.objectContaining({
+					name: 'sveltekit.handle.sequenced.set_tracing_test_id',
+					attributes: {}
+				})
+			])
+		});
+
+		// Find and verify the destination resolve.root span
+		const destination_resolve_root_span = find_resolve_root_span(destination_trace);
+		expect(destination_resolve_root_span).not.toBeNull();
+		expect(destination_resolve_root_span).toEqual({
+			name: 'sveltekit.resolve',
+			status: { code: 0 },
+			start_time: [expect.any(Number), expect.any(Number)],
+			end_time: [expect.any(Number), expect.any(Number)],
+			attributes: {
+				'http.route': '/tracing/one/two/three/[...four]',
+				'http.response.status_code': 200,
+				'http.response.body.size': expect.stringMatching(/^\d+$/)
+			},
+			links: [],
+			trace_id: destination_trace_id,
+			span_id: expect.any(String),
+			parent_span_id: expect.any(String),
+			children: [
+				{
+					name: 'sveltekit.load',
+					status: { code: 0 },
+					start_time: [expect.any(Number), expect.any(Number)],
+					end_time: [expect.any(Number), expect.any(Number)],
+					attributes: {
+						'sveltekit.load.node_id': 'src/routes/+layout.server.js',
+						'sveltekit.load.node_type': '+layout.server',
+						'sveltekit.load.environment': 'server',
+						'http.route': '/tracing/one/two/three/[...four]'
+					},
+					links: [],
+					trace_id: destination_trace_id,
+					span_id: expect.any(String),
+					parent_span_id: expect.any(String),
+					children: []
+				},
+				{
+					name: 'sveltekit.load',
+					status: { code: 0 },
+					start_time: [expect.any(Number), expect.any(Number)],
+					end_time: [expect.any(Number), expect.any(Number)],
+					attributes: {
+						'sveltekit.load.node_id': 'src/routes/+layout.js',
+						'sveltekit.load.node_type': '+layout',
+						'sveltekit.load.environment': 'server',
+						'http.route': '/tracing/one/two/three/[...four]'
+					},
+					links: [],
+					trace_id: destination_trace_id,
+					span_id: expect.any(String),
+					parent_span_id: expect.any(String),
+					children: []
+				}
+			]
+		});
+	});
+
+	test('correct spans are created for regular Error', async () => {
+		const test_id = rand();
+		const response = await get(`/tracing/regular-error?test_id=${test_id}`);
+		expect(response.status).toBe(500);
+
+		const traces = read_traces(test_id);
+		const trace_id = traces[0].trace_id;
+		const trace = traces[0];
+
+		// Verify root span structure
+		expect(trace).toEqual({
+			name: 'sveltekit.handle.root',
+			status: { code: 0 },
+			start_time: [expect.any(Number), expect.any(Number)],
+			end_time: [expect.any(Number), expect.any(Number)],
+			attributes: {
+				'http.route': '/tracing/regular-error',
+				'http.method': 'GET',
+				'http.url': expect.stringContaining(`/tracing/regular-error?test_id=${test_id}`),
+				'sveltekit.is_data_request': false,
+				'sveltekit.is_sub_request': false,
+				test_id
+			},
+			links: [],
+			trace_id,
+			span_id: expect.any(String),
+			children: expect.arrayContaining([
+				expect.objectContaining({
+					name: 'sveltekit.handle.sequenced.set_tracing_test_id',
+					attributes: {}
+				})
+			])
+		});
+
+		// Find and verify the resolve.root span
+		const resolve_root_span = find_resolve_root_span(trace);
+		expect(resolve_root_span).not.toBeNull();
+		expect(resolve_root_span).toEqual({
+			name: 'sveltekit.resolve',
+			status: { code: 0 },
+			start_time: [expect.any(Number), expect.any(Number)],
+			end_time: [expect.any(Number), expect.any(Number)],
+			attributes: {
+				'http.route': '/tracing/regular-error',
+				'http.response.status_code': 500,
+				'http.response.body.size': expect.stringMatching(/^\d+$/)
+			},
+			links: [],
+			trace_id,
+			span_id: expect.any(String),
+			parent_span_id: expect.any(String),
+			children: expect.arrayContaining([
+				expect.objectContaining({
+					name: 'sveltekit.load',
+					status: { code: 2, message: 'Regular error from tracing test' },
+					attributes: expect.objectContaining({
+						'sveltekit.load.node_id': 'src/routes/tracing/regular-error/+page.server.js',
+						'sveltekit.load.result.type': 'unknown_error'
+					})
+				})
+			])
+		});
+	});
+
+	test('correct spans are created for non-error object', async () => {
+		const test_id = rand();
+		const response = await get(`/tracing/non-error-object?test_id=${test_id}`);
+		expect(response.status).toBe(500);
+
+		const traces = read_traces(test_id);
+		const trace_id = traces[0].trace_id;
+		const trace = traces[0];
+
+		// Verify root span structure
+		expect(trace).toEqual({
+			name: 'sveltekit.handle.root',
+			status: { code: 0 },
+			start_time: [expect.any(Number), expect.any(Number)],
+			end_time: [expect.any(Number), expect.any(Number)],
+			attributes: {
+				'http.route': '/tracing/non-error-object',
+				'http.method': 'GET',
+				'http.url': expect.stringContaining(`/tracing/non-error-object?test_id=${test_id}`),
+				'sveltekit.is_data_request': false,
+				'sveltekit.is_sub_request': false,
+				test_id
+			},
+			links: [],
+			trace_id,
+			span_id: expect.any(String),
+			children: expect.arrayContaining([
+				expect.objectContaining({
+					name: 'sveltekit.handle.sequenced.set_tracing_test_id',
+					attributes: {}
+				})
+			])
+		});
+
+		// Find and verify the resolve.root span
+		const resolve_root_span = find_resolve_root_span(trace);
+		expect(resolve_root_span).not.toBeNull();
+		expect(resolve_root_span).toEqual({
+			name: 'sveltekit.resolve',
+			status: { code: 0 },
+			start_time: [expect.any(Number), expect.any(Number)],
+			end_time: [expect.any(Number), expect.any(Number)],
+			attributes: {
+				'http.route': '/tracing/non-error-object',
+				'http.response.status_code': 500,
+				'http.response.body.size': expect.stringMatching(/^\d+$/)
+			},
+			links: [],
+			trace_id,
+			span_id: expect.any(String),
+			parent_span_id: expect.any(String),
+			children: expect.arrayContaining([
+				expect.objectContaining({
+					name: 'sveltekit.load',
+					status: { code: 2 },
+					attributes: expect.objectContaining({
+						'sveltekit.load.node_id': 'src/routes/tracing/non-error-object/+page.server.js',
+						'sveltekit.load.result.type': 'unknown_error'
+					})
+				})
+			])
+		});
+	});
+});
+
+describe('asset preload', () => {
+	test('does not inject Link headers', async () => {
+		const response = await get('/asset-preload');
+
+		const header = response.headers.get('link');
+		expect(header).toBeNull();
+	});
+
+	test('injects  tags', async () => {
+		const response = await get('/asset-preload');
+
+		const body = await response.text();
+
+		expect(body).toContain('rel="modulepreload"');
+		expect(body).toContain('as="font"');
+		expect(body).toMatch(/href="[^"]+\/shlop\.[^".]+\.woff2"/);
+		expect(body).toMatch(/href="[^"]+\/shlop\.var\.[^".]+\.woff2"/);
+		// the emitted file name is sanitized, but the filter matched on the original `shlop+bold.woff2`
+		expect(body).toMatch(/href="[^"]+\/shlop_bold\.[^".]+\.woff2"/);
+	});
+});
+
+describe('Streaming', () => {
+	test("Discarded promises from server load functions don't hang SSR request", async () => {
+		let error;
+		try {
+			await (await get('/streaming/discarded-promise')).text();
+		} catch (e) {
+			error = e;
+		}
+
+		expect(error).toBeUndefined();
+	});
+});
diff --git a/packages/kit/test/apps/basics/test/server.test.js b/packages/kit/test/apps/basics/test/server.test.js
index a2c707deb228..95416c6bbb71 100644
--- a/packages/kit/test/apps/basics/test/server.test.js
+++ b/packages/kit/test/apps/basics/test/server.test.js
@@ -1,10 +1,6 @@
 import process from 'node:process';
 import { expect } from '@playwright/test';
 import { test } from '../../../utils.js';
-import { createHash, randomBytes } from 'node:crypto';
-import fs from 'node:fs';
-import { fileURLToPath } from 'node:url';
-import path from 'node:path';
 
 /** @typedef {import('@playwright/test').Response} Response */
 
@@ -12,232 +8,7 @@ test.skip(({ javaScriptEnabled }) => javaScriptEnabled);
 
 test.describe.configure({ mode: 'parallel' });
 
-test.describe('Caching', () => {
-	test('caches pages', async ({ request }) => {
-		const response = await request.get('/caching');
-		expect(response.headers()['cache-control']).toBe('public, max-age=30');
-	});
-});
-
-test.describe('Content-Type', () => {
-	test('sets Content-Type on page', async ({ request }) => {
-		const response = await request.get('/content-type-header');
-		expect(response.headers()['content-type']).toBe('text/html');
-	});
-});
-
-test.describe('Content-Length', () => {
-	test('sets Content-Length on page', async ({ request }) => {
-		const response = await request.get('/content-length-header');
-
-		// TODO this would ideally be a unit test of `Server`,
-		// as would most of the tests in this file
-		if (!response.headers()['content-encoding']) {
-			expect(+response.headers()['content-length']).toBeGreaterThan(1000);
-		}
-	});
-});
-
-test.describe('Cookies', () => {
-	test('does not forward cookies from external domains', async ({ request, start_server }) => {
-		const { port } = await start_server(async (req, res) => {
-			if (req.url === '/') {
-				res.writeHead(200, {
-					'set-cookie': 'external=true',
-					'access-control-allow-origin': '*'
-				});
-
-				res.end('ok');
-			} else {
-				res.writeHead(404);
-				res.end('not found');
-			}
-		});
-
-		const response = await request.get(`/load/fetch-external-no-cookies?port=${port}`);
-		expect(response.headers()['set-cookie']).not.toContain('external=true');
-	});
-});
-
-test.describe('CSRF', () => {
-	if (process.env.DEV) {
-		return;
-	}
-
-	test('Blocks requests with incorrect origin', async ({ baseURL }) => {
-		const content_types = [
-			'application/x-www-form-urlencoded',
-			'multipart/form-data',
-			'text/plain',
-			'text/plaiN'
-		];
-		const methods = ['POST', 'PUT', 'PATCH', 'DELETE'];
-		for (const method of methods) {
-			for (const content_type of content_types) {
-				const res = await fetch(`${baseURL}/csrf`, {
-					method,
-					headers: {
-						'content-type': content_type
-					}
-				});
-				const message = `request method: ${method}, content-type: ${content_type}`;
-				expect(res.status, message).toBe(403);
-				expect(await res.text(), message).toBe(
-					`Cross-site ${method} form submissions are forbidden`
-				);
-			}
-		}
-	});
-
-	test('Allows requests from same origin', async ({ baseURL }) => {
-		const url = new URL(baseURL);
-		const res = await fetch(`${baseURL}/csrf`, {
-			method: 'POST',
-			headers: {
-				'content-type': 'application/x-www-form-urlencoded',
-				origin: url.origin
-			}
-		});
-		expect(res.status).toBe(200);
-		expect(await res.text()).toBe('ok');
-	});
-
-	test('Allows requests from allowed origins', async ({ baseURL }) => {
-		// Test with trusted.example.com which is in trustedOrigins
-		const res1 = await fetch(`${baseURL}/csrf`, {
-			method: 'POST',
-			headers: {
-				'content-type': 'application/x-www-form-urlencoded',
-				origin: 'https://trusted.example.com'
-			}
-		});
-		expect(res1.status).toBe(200);
-		expect(await res1.text()).toBe('ok');
-
-		// Test with payment-gateway.test which is also in trustedOrigins
-		const res2 = await fetch(`${baseURL}/csrf`, {
-			method: 'POST',
-			headers: {
-				'content-type': 'application/x-www-form-urlencoded',
-				origin: 'https://payment-gateway.test'
-			}
-		});
-		expect(res2.status).toBe(200);
-		expect(await res2.text()).toBe('ok');
-	});
-
-	test('Blocks requests from non-allowed origins', async ({ baseURL }) => {
-		// Test with origin not in trustedOrigins list
-		const res1 = await fetch(`${baseURL}/csrf`, {
-			method: 'POST',
-			headers: {
-				'content-type': 'application/x-www-form-urlencoded',
-				origin: 'https://malicious-site.com'
-			}
-		});
-		expect(res1.status).toBe(403);
-		expect(await res1.text()).toBe('Cross-site POST form submissions are forbidden');
-
-		// Test with similar but not exact origin
-		const res2 = await fetch(`${baseURL}/csrf`, {
-			method: 'POST',
-			headers: {
-				'content-type': 'application/x-www-form-urlencoded',
-				origin: 'https://trusted.example.com.evil.com'
-			}
-		});
-		expect(res2.status).toBe(403);
-		expect(await res2.text()).toBe('Cross-site POST form submissions are forbidden');
-
-		// Test subdomain attack (should be blocked)
-		const res3 = await fetch(`${baseURL}/csrf`, {
-			method: 'POST',
-			headers: {
-				'content-type': 'application/x-www-form-urlencoded',
-				origin: 'https://evil.trusted.example.com'
-			}
-		});
-		expect(res3.status).toBe(403);
-		expect(await res3.text()).toBe('Cross-site POST form submissions are forbidden');
-	});
-
-	test('Allows GET requests regardless of origin', async ({ baseURL }) => {
-		const res = await fetch(`${baseURL}/csrf`, {
-			method: 'GET',
-			headers: {
-				'content-type': 'application/x-www-form-urlencoded',
-				origin: 'https://any-origin.com'
-			}
-		});
-		expect(res.status).toBe(200);
-	});
-
-	test('Allows non-form content types regardless of origin', async ({ baseURL }) => {
-		const res = await fetch(`${baseURL}/csrf`, {
-			method: 'POST',
-			headers: {
-				'content-type': 'application/json',
-				origin: 'https://any-origin.com'
-			}
-		});
-		expect(res.status).toBe(200);
-	});
-
-	test('Allows all protected HTTP methods from allowed origins', async ({ baseURL }) => {
-		const methods = ['POST', 'PUT', 'PATCH', 'DELETE'];
-		for (const method of methods) {
-			const res = await fetch(`${baseURL}/csrf`, {
-				method,
-				headers: {
-					'content-type': 'application/x-www-form-urlencoded',
-					origin: 'https://trusted.example.com'
-				}
-			});
-			expect(res.status, `Method ${method} should be allowed from trusted origin`).toBe(200);
-			expect(await res.text(), `Method ${method} should return ok`).toBe('ok');
-		}
-	});
-
-	test('Handles undefined origin correctly', async ({ baseURL }) => {
-		// Some requests may have null origin (e.g., from certain mobile apps)
-		const res = await fetch(`${baseURL}/csrf`, {
-			method: 'POST',
-			headers: {
-				'content-type': 'application/x-www-form-urlencoded'
-			}
-		});
-		expect(res.status).toBe(403);
-		expect(await res.text()).toBe('Cross-site POST form submissions are forbidden');
-	});
-});
-
 test.describe('Endpoints', () => {
-	test('HEAD with matching headers but without body', async ({ request }) => {
-		const url = '/endpoint-output/body';
-
-		const responses = {
-			head: await request.head(url),
-			get: await request.get(url)
-		};
-
-		const headers = {
-			head: responses.head.headers(),
-			get: responses.get.headers()
-		};
-
-		expect(responses.head.status()).toBe(200);
-		expect(responses.get.status()).toBe(200);
-		expect(await responses.head.text()).toBe('');
-		expect(await responses.get.text()).toBe('{}');
-
-		['date', 'transfer-encoding'].forEach((name) => {
-			delete headers.head[name];
-			delete headers.get[name];
-		});
-
-		expect(headers.head).toEqual(headers.get);
-	});
-
 	test('Prerendered +server.js called from a non-prerendered +server.js works', async ({
 		baseURL
 	}) => {
@@ -270,137 +41,9 @@ test.describe('Endpoints', () => {
 		}
 	});
 
-	test('invalid request method returns allow header', async ({ request }) => {
-		const response = await request.post('/endpoint-output/body', {
-			headers: { origin: 'https://trusted.example.com' }
-		});
-
-		expect(response.status()).toBe(405);
-
-		const allow_header = response.headers()['allow'];
-		expect(allow_header).toMatch(/\bGET\b/);
-		expect(allow_header).toMatch(/\bHEAD\b/);
-	});
-
-	test('405 allow header has no duplicate methods listed', async ({ request }) => {
-		const response = await request.post('/endpoint-output/head-handler', {
-			headers: { origin: 'https://trusted.example.com' }
-		});
-
-		expect(response.status()).toBe(405);
-
-		const allow_header = response.headers()['allow'];
-		const methods = allow_header.split(',').map((m) => m.trim());
-		const unique_methods = [...new Set(methods)];
-
-		expect(methods).toEqual(unique_methods);
-	});
-
-	test('serves page for GET request when endpoint has no GET handler', async ({ request }) => {
-		const response = await request.fetch('/endpoint-output/post-only-with-page', {
-			headers: {
-				accept: '*/*'
-			}
-		});
-
-		expect(response.status()).toBe(200);
-		expect(response.headers()['content-type']).toContain('text/html');
-		expect(await response.text()).toContain('POST-only endpoint page');
-	});
-
-	test('serves page for HEAD request when endpoint has no HEAD or GET handler', async ({
-		request
-	}) => {
-		const response = await request.fetch('/endpoint-output/post-only-with-page', {
-			method: 'HEAD',
-			headers: {
-				accept: '*/*'
-			}
-		});
-
-		expect(response.status()).toBe(200);
-		expect(response.headers()['content-type']).toContain('text/html');
-		expect(response.headers()['x-sveltekit-page']).toBe('true');
-		expect(await response.text()).toBe('');
-	});
-
-	test('POST to post-only endpoint with sibling page still hits endpoint', async ({ request }) => {
-		const response = await request.post('/endpoint-output/post-only-with-page', {
-			headers: { origin: 'https://trusted.example.com' }
-		});
-
-		expect(response.status()).toBe(200);
-		expect(await response.text()).toBe('ok');
-	});
-
-	test('uses fallback handler instead of page when endpoint has no GET but has fallback', async ({
-		request
-	}) => {
-		const response = await request.fetch('/endpoint-output/fallback-with-page', {
-			headers: {
-				accept: '*/*'
-			}
-		});
-
-		expect(response.status()).toBe(200);
-		expect(await response.text()).toBe('catch-all');
-	});
-
-	test('content negotiation: API requests hit endpoint, browser requests hit page', async ({
-		request
-	}) => {
-		// application/json → endpoint
-		const api_response = await request.fetch('/routing/content-negotiation', {
-			headers: {
-				accept: 'application/json'
-			}
-		});
-
-		expect(api_response.status()).toBe(200);
-		expect(await api_response.text()).toBe('GET');
-
-		// text/html → page
-		const html_response = await request.fetch('/routing/content-negotiation', {
-			headers: {
-				accept: 'text/html'
-			}
-		});
-
-		expect(html_response.status()).toBe(200);
-		expect(html_response.headers()['content-type']).toContain('text/html');
-		expect(await html_response.text()).toContain('Hi');
-	});
-
 	// TODO all the remaining tests in this section are really only testing
 	// setResponse, since we're not otherwise changing anything on the response.
 	// might be worth making these unit tests instead
-	test('multiple set-cookie on endpoints using GET', async ({ request }) => {
-		const response = await request.get('/set-cookie');
-
-		const cookies = response
-			.headersArray()
-			.filter((obj) => obj.name === 'set-cookie')
-			.map((obj) => obj.value);
-
-		expect(cookies).toEqual([
-			'answer=42; HttpOnly',
-			'problem=comma, separated, values; HttpOnly',
-			'name=SvelteKit; path=/; HttpOnly'
-		]);
-	});
-
-	// TODO see above
-	test('body can be a binary ReadableStream', async ({ request }) => {
-		const interruptedResponse = request.get('/endpoint-output/stream-throw-error');
-		await expect(interruptedResponse).rejects.toThrow('socket hang up');
-
-		const response = await request.get('/endpoint-output/stream');
-		const body = await response.body();
-		const digest = createHash('sha256').update(body).digest('base64url');
-		expect(response.headers()['digest']).toEqual(`sha-256=${digest}`);
-	});
-
-	// TODO see above
 	test('stream can be canceled with TypeError', async ({ request }) => {
 		const responseBefore = await request.get('/endpoint-output/stream-typeerror?what');
 		expect(await responseBefore.text()).toEqual('null');
@@ -412,14 +55,6 @@ test.describe('Endpoints', () => {
 		expect(await responseAfter.text()).toEqual('TypeError');
 	});
 
-	// TODO see above
-	test('request body can be read slow', async ({ request }) => {
-		const data = randomBytes(1024 * 256);
-		const digest = createHash('sha256').update(data).digest('base64url');
-		const response = await request.put('/endpoint-input/sha256', { data });
-		expect(await response.text()).toEqual(digest);
-	});
-
 	// TODO see above
 	test('invalid headers return a 500', async ({ request }) => {
 		const response = await request.get('/endpoint-output/head-write-error');
@@ -428,138 +63,9 @@ test.describe('Endpoints', () => {
 			'TypeError [ERR_INVALID_CHAR]: Invalid character in header content ["x-test"]'
 		);
 	});
-
-	test('OPTIONS handler', async ({ request }) => {
-		const url = '/endpoint-output';
-
-		const response = await request.fetch(url, {
-			method: 'OPTIONS'
-		});
-
-		expect(response.status()).toBe(200);
-		expect(await response.text()).toBe('ok');
-	});
-
-	test('HEAD handler', async ({ request }) => {
-		const url = '/endpoint-output/head-handler';
-
-		const page_response = await request.fetch(url, {
-			method: 'HEAD',
-			headers: {
-				accept: 'text/html'
-			}
-		});
-
-		expect(page_response.status()).toBe(200);
-		expect(await page_response.text()).toBe('');
-		expect(page_response.headers()['x-sveltekit-page']).toBe('true');
-
-		const endpoint_response = await request.fetch(url, {
-			method: 'HEAD',
-			headers: {
-				accept: 'application/json'
-			}
-		});
-
-		expect(endpoint_response.status()).toBe(200);
-		expect(await endpoint_response.text()).toBe('');
-		expect(endpoint_response.headers()['x-sveltekit-head-endpoint']).toBe('true');
-	});
-
-	test('catch-all handler', async ({ request }) => {
-		const url = '/endpoint-output/fallback';
-
-		let response = await request.fetch(url, {
-			method: 'GET'
-		});
-
-		expect(response.status()).toBe(200);
-		expect(await response.text()).toBe('ok');
-
-		response = await request.fetch(url, {
-			method: 'MOVE' // also works with arcane methods
-		});
-
-		expect(response.status()).toBe(200);
-		expect(await response.text()).toBe('catch-all');
-
-		response = await request.fetch(url, {
-			method: 'OPTIONS'
-		});
-
-		expect(response.status()).toBe(200);
-		expect(await response.text()).toBe('catch-all');
-	});
-
-	test('QUERY handler', async ({ request }) => {
-		const url = '/endpoint-output/query';
-
-		let response = await request.fetch(url, {
-			method: 'QUERY',
-			data: 'name=world'
-		});
-
-		expect(response.status()).toBe(200);
-		expect(await response.text()).toBe('query: name=world');
-
-		response = await request.fetch(url, {
-			method: 'MOVE'
-		});
-
-		expect(response.status()).toBe(405);
-		expect(response.headers()['allow']).toBe('GET, QUERY, HEAD');
-	});
-
-	test('can get assets using absolute path', async ({ request }) => {
-		const response = await request.get('/endpoint-output/fetch-asset/absolute');
-		expect(response.status()).toBe(200);
-		expect(response.headers()['content-type']).toBe('text/plain');
-		expect(await response.text()).toBe('Cos sie konczy, cos zaczyna');
-	});
-
-	test('can get assets using relative path', async ({ request }) => {
-		const response = await request.get('/endpoint-output/fetch-asset/relative');
-		expect(response.status()).toBe(200);
-		expect(response.headers()['content-type']).toBe('text/plain');
-		expect(await response.text()).toBe('Cos sie konczy, cos zaczyna');
-	});
 });
 
 test.describe('Errors', () => {
-	test('uses the handleError status for the fallback page served to error-page sub-requests', async ({
-		request
-	}) => {
-		const response = await request.get('/errors/handle-error-status-fallback', {
-			headers: { 'x-sveltekit-error': 'true' }
-		});
-		expect(response.status()).toBe(503);
-	});
-
-	test('invalid route response is handled', async ({ request }) => {
-		const response = await request.get('/errors/invalid-route-response');
-
-		expect(/** @type {import('@playwright/test').APIResponse} */ (response).status()).toBe(500);
-		expect(await response.text()).toMatch(
-			'Invalid response from route /errors/invalid-route-response: handler should return a Response object'
-		);
-	});
-
-	test('unhandled http method', async ({ request }) => {
-		const response = await request.put('/errors/invalid-route-response', {
-			headers: { origin: 'https://trusted.example.com' }
-		});
-
-		expect(response.status()).toBe(405);
-		expect(await response.text()).toMatch('PUT method not allowed');
-	});
-
-	test('error evaluating module', async ({ request }) => {
-		const response = await request.get('/errors/init-error-endpoint');
-
-		expect(response.status()).toBe(500);
-		expect(await response.text()).toMatch('thisvariableisnotdefined is not defined');
-	});
-
 	test('returns 400 when accessing a malformed URI', async ({ page }) => {
 		const response = await page.goto('/%c0%ae%c0%ae/etc/passwd');
 		if (process.env.DEV) {
@@ -570,218 +76,6 @@ test.describe('Errors', () => {
 			expect(/** @type {Response} */ (response).status()).toBe(400);
 		}
 	});
-
-	test('returns a lightweight 404 for subresource requests', async ({ request, read_errors }) => {
-		// distinct from the path used by the test below, which _does_ invoke the hook
-		const response = await request.get('/errors/does-not-exist-lightweight-subresource', {
-			headers: { 'sec-fetch-dest': 'image' }
-		});
-
-		expect(response.status()).toBe(404);
-		expect(await response.text()).toBe('Not Found');
-		expect(response.headers()['vary']).toContain('Sec-Fetch-Dest');
-
-		// lightweight 404s bypass the handleError hook
-		expect(read_errors('/errors/does-not-exist-lightweight-subresource')).toBe(undefined);
-	});
-
-	test('renders the error page for document and fetch requests', async ({ request }) => {
-		for (const destination of ['document', null, 'empty']) {
-			const response = await request.get(
-				'/errors/does-not-exist-subresource',
-				destination ? { headers: { 'sec-fetch-dest': destination } } : {}
-			);
-
-			expect(response.status()).toBe(404);
-			expect(await response.text()).toContain('This is your custom error page saying:');
-		}
-	});
-
-	test('stack traces are not fixed twice', async ({ page }) => {
-		await page.goto('/errors/stack-trace');
-		expect(await page.textContent('#message')).toBe(
-			'This is your custom error page saying: "Cannot read properties of undefined (reading \'toUpperCase\') (500 Internal Error)"'
-		);
-
-		// check the stack wasn't mutated
-		await page.goto('/errors/stack-trace');
-		expect(await page.textContent('#message')).toBe(
-			'This is your custom error page saying: "Cannot read properties of undefined (reading \'toUpperCase\') (500 Internal Error)"'
-		);
-	});
-
-	test('error(...) in endpoint', async ({ request, read_errors }) => {
-		// HTML
-		{
-			const res = await request.get('/errors/endpoint-throw-error', {
-				headers: {
-					accept: 'text/html'
-				}
-			});
-
-			expect(read_errors('/errors/endpoint-throw-error')).toEqual({
-				kind: 'app',
-				error: { status: 401, message: 'You shall not pass' }
-			});
-
-			expect(res.status()).toBe(401);
-			expect(await res.text()).toContain(
-				'This is the static error page with the following message: You shall not pass'
-			);
-		}
-
-		// JSON (default)
-		{
-			const res = await request.get('/errors/endpoint-throw-error');
-
-			expect(read_errors('/errors/endpoint-throw-error')).toEqual({
-				kind: 'app',
-				error: { status: 401, message: 'You shall not pass' }
-			});
-
-			expect(res.status()).toBe(401);
-			expect(await res.json()).toEqual({
-				message: 'You shall not pass',
-				status: 401
-			});
-		}
-	});
-
-	test('redirect(...) in endpoint', async ({ page, read_errors }) => {
-		const res = await page.goto('/errors/endpoint-throw-redirect');
-		expect(res?.status()).toBe(200); // redirects are opaque to the browser
-
-		const error = read_errors('/errors/endpoint-throw-redirect');
-		expect(error).toBe(undefined);
-
-		expect(await page.textContent('h1')).toBe('the answer is 42');
-	});
-
-	test('POST to missing page endpoint', async ({ request }) => {
-		const res = await request.post('/errors/missing-actions', {
-			headers: {
-				accept: 'text/html',
-				origin: 'https://trusted.example.com'
-			}
-		});
-		expect(res?.status()).toBe(405);
-
-		const res_json = await request.post('/errors/missing-actions', {
-			headers: {
-				accept: 'application/json',
-				origin: 'https://trusted.example.com'
-			}
-		});
-		expect(res_json?.status()).toBe(405);
-		expect(await res_json.json()).toEqual({
-			type: 'error',
-			location: '/errors/missing-actions',
-			error: {
-				message: 'Method Not Allowed (405 Method Not Allowed)',
-				status: 405
-			}
-		});
-	});
-
-	test('error thrown in handle results in a rendered error page or JSON response', async ({
-		request
-	}) => {
-		// HTML
-		{
-			const res = await request.get('/errors/error-in-handle', {
-				headers: {
-					accept: 'text/html'
-				}
-			});
-
-			expect(res.status()).toBe(500);
-			expect(await res.text()).toContain(
-				'This is the static error page with the following message: Error in handle'
-			);
-		}
-
-		// JSON (default)
-		{
-			const res = await request.get('/errors/error-in-handle');
-
-			const error = await res.json();
-
-			expect(error.stack).toBe(undefined);
-			expect(res.status()).toBe(500);
-			expect(error).toEqual({
-				message: 'Error in handle (500 Internal Error)',
-				status: 500
-			});
-		}
-	});
-
-	test('expected error thrown in handle results in a rendered error page or JSON response', async ({
-		request
-	}) => {
-		// HTML
-		{
-			const res = await request.get('/errors/expected-error-in-handle', {
-				headers: {
-					accept: 'text/html'
-				}
-			});
-
-			expect(res.status()).toBe(500);
-			expect(await res.text()).toContain(
-				'This is the static error page with the following message: Expected error in handle'
-			);
-		}
-
-		// JSON (default)
-		{
-			const res = await request.get('/errors/expected-error-in-handle');
-
-			const error = await res.json();
-
-			expect(error.stack).toBe(undefined);
-			expect(res.status()).toBe(500);
-			expect(error).toEqual({
-				message: 'Expected error in handle',
-				status: 500
-			});
-		}
-	});
-
-	test('error thrown from load on the server respects page options when rendering the error page', async ({
-		request
-	}) => {
-		const res = await request.get('/errors/load-error-page-options/csr');
-		expect(res.status()).toBe(500);
-		const content = await res.text();
-		expect(content).toContain('Crashing now');
-		// the hydration script should not be present if the csr page option is respected
-		expect(content).not.toContain('kit.start(app');
-	});
-
-	test('returns root layout data for a missing route error page data request', async ({
-		request
-	}) => {
-		const data_response = await request.get(
-			'/this-route-does-not-exist/__data.json?x-sveltekit-invalidated=1'
-		);
-		expect(data_response.status()).toBe(200);
-		expect(data_response.headers()['content-type']).toContain('application/json');
-
-		const data = await data_response.json();
-		expect(data.type).toBe('data');
-		expect(data.nodes[0].type).toBe('data');
-		expect(data.nodes[0].data).toContain('rootlayout');
-
-		const page_response = await request.get('/this-route-does-not-exist/__data.json');
-		expect(page_response.status()).toBe(404);
-		expect(page_response.headers()['content-type']).toContain('text/html');
-
-		// a single-node request that invalidates nothing is not an error-page data request
-		const crafted_response = await request.get(
-			'/this-route-does-not-exist/__data.json?x-sveltekit-invalidated=0'
-		);
-		expect(crafted_response.status()).toBe(404);
-	});
 });
 
 test.describe('Load', () => {
@@ -796,109 +90,9 @@ test.describe('Load', () => {
 		const response = await request.get('/load/static-file-with-hash');
 		expect(await response.text()).toContain('status: 404');
 	});
-
-	test('fetch reads universal load assets on the server', async ({ page }) => {
-		await page.goto('/load/fetch-asset');
-		await expect(page.locator('p')).toHaveText('1');
-	});
-
-	test('does not forward accept-language to internal fetch when the request has none', async ({
-		request
-	}) => {
-		// unlike browsers and undici, the `request` fixture sends no accept-language header
-		const html = await (await request.get('/load/fetch-request-headers')).text();
-		const headers = JSON.parse(
-			/** @type {RegExpMatchArray} */ (/
(.+?)<\/pre>/s.exec(html))[1]
-		);
-		expect(headers.accept).toBe('*/*');
-		expect(headers['accept-language']).toBeUndefined();
-	});
-
-	test('includes origin header on non-GET internal request', async ({ page, baseURL }) => {
-		await page.goto('/load/fetch-origin-internal');
-		expect(await page.textContent('h1')).toBe(`origin: ${new URL(baseURL).origin}`);
-	});
-
-	test('includes origin header on external request', async ({ page, baseURL, start_server }) => {
-		const { port } = await start_server((req, res) => {
-			if (req.url === '/') {
-				res.writeHead(200, {
-					'content-type': 'application/json',
-					'access-control-allow-origin': '*'
-				});
-
-				res.end(JSON.stringify({ origin: req.headers.origin }));
-			} else {
-				res.writeHead(404);
-				res.end('not found');
-			}
-		});
-
-		await page.goto(`/load/fetch-origin-external?port=${port}`);
-		expect(await page.textContent('h1')).toBe(`origin: ${new URL(baseURL).origin}`);
-	});
-
-	test('does not run when using invalid request methods', async ({ request }) => {
-		const load_url = '/load';
-
-		let response = await request.fetch(load_url, {
-			method: 'OPTIONS'
-		});
-
-		expect(response.status()).toBe(204);
-		expect(await response.text()).toBe('');
-		expect(response.headers()['allow']).toBe('GET, HEAD, OPTIONS');
-
-		const actions_url = '/actions/enhance';
-		response = await request.fetch(actions_url, {
-			method: 'OPTIONS'
-		});
-
-		expect(response.status()).toBe(204);
-		expect(await response.text()).toBe('');
-		expect(response.headers()['allow']).toBe('GET, HEAD, OPTIONS, POST');
-	});
-
-	test('allows logging URL search params', async ({ page }) => {
-		await page.goto('/load/server-log-search-param');
-
-		expect(await page.textContent('p')).toBe('hello world');
-	});
 });
 
 test.describe('Routing', () => {
-	test('event.params are available in handle', async ({ request }) => {
-		const response = await request.get('/routing/params-in-handle/banana');
-		expect(await response.json()).toStrictEqual({
-			key: '/routing/params-in-handle/[x]',
-			params: { x: 'banana' }
-		});
-	});
-
-	test('/favicon.ico is a valid route', async ({ request }) => {
-		const response = await request.get('/favicon.ico');
-		expect(response.status()).toBe(200);
-
-		const data = await response.json();
-		expect(data).toEqual({ surprise: 'lol' });
-	});
-
-	test('falls back to page actions if sibling endpoint has no POST handler', async ({
-		baseURL,
-		request
-	}) => {
-		const response = await request.post('/endpoint-output/actions-with-endpoint', {
-			form: {},
-			headers: {
-				accept: 'application/json',
-				origin: new URL(baseURL).origin
-			}
-		});
-
-		expect(response.status()).toBe(200);
-		expect((await response.json()).type).toBe('success');
-	});
-
 	test('Vite trailing slash redirect for prerendered pages retains URL query string', async ({
 		request
 	}) => {
@@ -915,61 +109,6 @@ test.describe('Routing', () => {
 	});
 });
 
-test.describe('Shadowed pages', () => {
-	test('Action can return undefined', async ({ baseURL, request }) => {
-		const response = await request.post('/shadowed/simple/post', {
-			form: {},
-			headers: {
-				accept: 'application/json',
-				origin: new URL(baseURL).origin
-			}
-		});
-
-		expect(response.status()).toBe(200);
-		expect(await response.json()).toEqual({
-			type: 'success',
-			status: 204,
-			location: '/shadowed/simple/post'
-		});
-	});
-
-	test('action response includes the stripped landing location', async ({ baseURL, request }) => {
-		const response = await request.post(
-			'/actions/cross-page/destination?redirectTo=%2Fdashboard&/failure',
-			{
-				form: { username: 'paolo' },
-				headers: {
-					accept: 'application/json',
-					origin: new URL(baseURL).origin
-				}
-			}
-		);
-
-		expect(response.status()).toBe(400);
-		expect(await response.json()).toEqual({
-			type: 'failure',
-			status: 400,
-			location: '/actions/cross-page/destination?redirectTo=%2Fdashboard',
-			data: '[{"problem":1,"username":2},"invalid","paolo"]'
-		});
-	});
-
-	test('Action fail() returns matching HTTP status code', async ({ baseURL, request }) => {
-		const response = await request.post('/actions/form-errors', {
-			form: {},
-			headers: {
-				accept: 'application/json',
-				origin: new URL(baseURL).origin
-			}
-		});
-
-		expect(response.status()).toBe(400);
-		const body = await response.json();
-		expect(body.type).toBe('failure');
-		expect(body.status).toBe(400);
-	});
-});
-
 test.describe('Static files', () => {
 	test('static files', async ({ request }) => {
 		let response = await request.get('/static.json');
@@ -1025,27 +164,6 @@ test.describe('Static files', () => {
 	});
 });
 
-test.describe('setHeaders', () => {
-	test('allows multiple set-cookie headers with different values', async ({ page }) => {
-		const response = await page.goto('/headers/set-cookie/sub');
-		const cookies = response ? (await response.allHeaders())['set-cookie'] : '';
-
-		expect(cookies).toMatch('cookie1=value1');
-		expect(cookies).toMatch('cookie2=value2');
-	});
-});
-
-test.describe('cookies', () => {
-	test('cookie.stringifySetCookie created correct cookie header string', async ({ page }) => {
-		const response = await page.goto('/cookies/serialize');
-		const cookies = response ? await response.headerValue('set-cookie') : '';
-
-		expect(cookies).toMatch('before=before');
-		expect(cookies).toMatch('after=after');
-		expect(cookies).toMatch('endpoint=endpoint');
-	});
-});
-
 test.describe('Miscellaneous', () => {
 	test('does not serve version.json with an immutable cache header', async ({ request }) => {
 		// this isn't actually a great test, because caching behaviour is down to adapters.
@@ -1055,46 +173,13 @@ test.describe('Miscellaneous', () => {
 		expect(headers['cache-control'] || '').not.toContain('immutable');
 	});
 
-	test('handles responses with immutable headers', async ({ request }) => {
-		const response = await request.get('/immutable-headers');
-		expect(response.status()).toBe(200);
-		expect(await response.text()).toBe('foo');
-	});
-
 	test('serves prerendered non-latin pages', async ({ request }) => {
 		const response = await request.get('/prerendering/中文');
 		expect(response.status()).toBe(200);
 	});
-
-	test('does not send x-sveltekit-version header on document responses', async ({ page }) => {
-		const response = await page.goto('/');
-		expect(response?.headers()['x-sveltekit-version']).toBeUndefined();
-	});
-
-	test('sends x-sveltekit-version header on data responses', async ({ request }) => {
-		const response = await request.get('/__data.json');
-		expect(response.headers()['x-sveltekit-version']).toBeTruthy();
-	});
 });
 
 test.describe('reroute', () => {
-	test('Apply reroute when directly accessing a page', async ({ page }) => {
-		await page.goto('/reroute/basic/a');
-		expect(await page.textContent('h1')).toContain(
-			'Successfully rewritten, URL should still show a: /reroute/basic/a'
-		);
-	});
-
-	test('Apply async reroute when directly accessing a page', async ({ page }) => {
-		page
-			.context()
-			.addCookies([{ name: 'reroute-cookie', value: 'yes', path: '/', domain: 'localhost' }]);
-		await page.goto('/reroute/async/a');
-		expect(await page.textContent('h1')).toContain(
-			'Successfully rewritten, URL should still show a: /reroute/async/a'
-		);
-	});
-
 	test('Apply async prerendered reroute when directly accessing a page', async ({ page }) => {
 		await page.goto('/reroute/async/c');
 		expect(await page.textContent('h1')).toContain(
@@ -1106,555 +191,4 @@ test.describe('reroute', () => {
 		await page.goto('/reroute/prerendered/to-destination');
 		expect(await page.textContent('h1')).toContain('reroute that points to prerendered page works');
 	});
-
-	test('Returns a 500 response if reroute throws an error on the server', async ({ page }) => {
-		const response = await page.goto('/reroute/error-handling/server-error');
-		expect(response?.status()).toBe(500);
-	});
-});
-
-test.describe('init', () => {
-	test('init server hook is called once before the load function', async ({ page }) => {
-		await page.goto('/init-hooks');
-		await expect(page.locator('p')).toHaveText('1');
-		await page.reload();
-		await expect(page.locator('p')).toHaveText('1');
-	});
-});
-
-test.describe('getRequestEvent', () => {
-	test('getRequestEvent works in server endpoints', async ({ request }) => {
-		const response = await request.get('/get-request-event/endpoint');
-		expect(await response.text()).toBe('hello from hooks.server.js');
-	});
-});
-
-test.describe('$app/forms', () => {
-	test('deserialize works on the server', async ({ request }) => {
-		const response = await request.get('/serialization-form-non-enhanced/server-deserialize');
-		expect(await response.json()).toEqual({ data: 'It works!' });
-	});
-});
-
-const root = path.resolve(fileURLToPath(import.meta.url), '..', '..');
-
-test.describe('$app/env', () => {
-	test('treeshakes dev check', async () => {
-		test.skip(!!process.env.DEV, 'skip when in dev mode');
-
-		const code = fs.readFileSync(
-			path.join(root, '.svelte-kit/output/server/entries/pages/treeshaking/dev/_page.svelte.js'),
-			'utf-8'
-		);
-		expect(code).not.toContain('not prod');
-	});
-
-	test('treeshakes browser check', async () => {
-		test.skip(!!process.env.DEV, 'skip when in dev mode');
-
-		const code = fs.readFileSync(
-			path.join(
-				root,
-				'.svelte-kit/output/server/entries/pages/treeshaking/browser/_page.svelte.js'
-			),
-			'utf-8'
-		);
-		expect(code).not.toMatch('client');
-	});
-});
-
-test.describe('tracing', () => {
-	// Helper function to find the resolve.root span deep in the handle.child chain
-	/**
-	 * @param {import('../../../types.js').SpanTree} span
-	 * @returns {import('../../../types.js').SpanTree | null}
-	 */
-	function find_resolve_root_span(span) {
-		if (span.name === 'sveltekit.resolve') {
-			return span;
-		}
-		for (const child of span.children || []) {
-			const found = find_resolve_root_span(child);
-			if (found) return found;
-		}
-		return null;
-	}
-
-	function rand() {
-		// node 18 doesn't have crypto.randomUUID() and we run tests in node 18
-		return Math.random().toString(36).substring(2, 15);
-	}
-
-	test('correct spans are created for a regular navigation', async ({ page, read_traces }) => {
-		const test_id = rand();
-		await page.goto(`/tracing/one/two/three/four/five?test_id=${test_id}`);
-		const traces = read_traces(test_id);
-		expect(traces.length).toBeGreaterThan(0);
-
-		const trace = traces[0];
-		const trace_id = trace.trace_id;
-
-		// Verify root span structure
-		expect(trace).toEqual({
-			name: 'sveltekit.handle.root',
-			status: { code: 0 },
-			start_time: [expect.any(Number), expect.any(Number)],
-			end_time: [expect.any(Number), expect.any(Number)],
-			attributes: {
-				'http.route': '/tracing/one/two/three/[...four]',
-				'http.method': 'GET',
-				'http.url': expect.stringContaining(`/tracing/one/two/three/four/five?test_id=${test_id}`),
-				'sveltekit.is_data_request': false,
-				'sveltekit.is_sub_request': false,
-				test_id
-			},
-			links: [],
-			trace_id,
-			span_id: expect.any(String),
-			children: expect.arrayContaining([
-				expect.objectContaining({
-					name: 'sveltekit.handle.sequenced.set_tracing_test_id',
-					attributes: {}
-				})
-			])
-		});
-
-		// Find and verify the resolve.root span
-		const resolve_root_span = find_resolve_root_span(trace);
-		expect(resolve_root_span).not.toBeNull();
-		expect(resolve_root_span).toEqual({
-			name: 'sveltekit.resolve',
-			status: { code: 0 },
-			start_time: [expect.any(Number), expect.any(Number)],
-			end_time: [expect.any(Number), expect.any(Number)],
-			attributes: {
-				'http.route': '/tracing/one/two/three/[...four]',
-				'http.response.status_code': 200,
-				'http.response.body.size': expect.stringMatching(/^\d+$/)
-			},
-			links: [],
-			trace_id,
-			span_id: expect.any(String),
-			parent_span_id: expect.any(String),
-			children: [
-				{
-					name: 'sveltekit.load',
-					status: { code: 0 },
-					start_time: [expect.any(Number), expect.any(Number)],
-					end_time: [expect.any(Number), expect.any(Number)],
-					attributes: {
-						'sveltekit.load.node_id': 'src/routes/+layout.server.js',
-						'sveltekit.load.node_type': '+layout.server',
-						'sveltekit.load.environment': 'server',
-						'http.route': '/tracing/one/two/three/[...four]'
-					},
-					links: [],
-					trace_id,
-					span_id: expect.any(String),
-					parent_span_id: expect.any(String),
-					children: []
-				},
-				{
-					name: 'sveltekit.load',
-					status: { code: 0 },
-					start_time: [expect.any(Number), expect.any(Number)],
-					end_time: [expect.any(Number), expect.any(Number)],
-					attributes: {
-						'sveltekit.load.node_id': 'src/routes/+layout.js',
-						'sveltekit.load.node_type': '+layout',
-						'sveltekit.load.environment': 'server',
-						'http.route': '/tracing/one/two/three/[...four]'
-					},
-					links: [],
-					trace_id,
-					span_id: expect.any(String),
-					parent_span_id: expect.any(String),
-					children: []
-				}
-			]
-		});
-	});
-
-	test('correct spans are created for HttpError', async ({ page, read_traces }) => {
-		const test_id = rand();
-		const response = await page.goto(`/tracing/http-error?test_id=${test_id}`);
-		expect(response?.status()).toBe(500);
-
-		const traces = read_traces(test_id);
-		const trace_id = traces[0].trace_id;
-		const trace = traces[0];
-
-		// Verify root span structure
-		expect(trace).toEqual({
-			name: 'sveltekit.handle.root',
-			status: { code: 0 },
-			start_time: [expect.any(Number), expect.any(Number)],
-			end_time: [expect.any(Number), expect.any(Number)],
-			attributes: {
-				'http.route': '/tracing/http-error',
-				'http.method': 'GET',
-				'http.url': expect.stringContaining(`/tracing/http-error?test_id=${test_id}`),
-				'sveltekit.is_data_request': false,
-				'sveltekit.is_sub_request': false,
-				test_id
-			},
-			links: [],
-			trace_id,
-			span_id: expect.any(String),
-			children: expect.arrayContaining([
-				expect.objectContaining({
-					name: 'sveltekit.handle.sequenced.set_tracing_test_id',
-					attributes: {}
-				})
-			])
-		});
-
-		// Find and verify the resolve.root span
-		const resolve_root_span = find_resolve_root_span(trace);
-		expect(resolve_root_span).not.toBeNull();
-		expect(resolve_root_span).toEqual({
-			name: 'sveltekit.resolve',
-			status: { code: 0 },
-			start_time: [expect.any(Number), expect.any(Number)],
-			end_time: [expect.any(Number), expect.any(Number)],
-			attributes: {
-				'http.route': '/tracing/http-error',
-				'http.response.status_code': 500,
-				'http.response.body.size': expect.stringMatching(/^\d+$/)
-			},
-			links: [],
-			trace_id,
-			span_id: expect.any(String),
-			parent_span_id: expect.any(String),
-			children: expect.arrayContaining([
-				expect.objectContaining({
-					name: 'sveltekit.load',
-					status: { code: 2, message: 'Internal server error from tracing test' },
-					attributes: expect.objectContaining({
-						'sveltekit.load.node_id': 'src/routes/tracing/http-error/+page.server.js',
-						'sveltekit.load.result.type': 'known_error',
-						'sveltekit.load.result.status': 500,
-						'sveltekit.load.result.message': 'Internal server error from tracing test'
-					})
-				})
-			])
-		});
-	});
-
-	test('correct spans are created for Redirect', async ({ page, read_traces }) => {
-		const test_id = rand();
-		const response = await page.goto(`/tracing/redirect?test_id=${test_id}`);
-		expect(response?.status()).toBe(200);
-
-		const traces = read_traces(test_id);
-		expect(traces).toHaveLength(2);
-		const redirect_trace_id = traces[0].trace_id;
-		const destination_trace_id = traces[1].trace_id;
-
-		const redirect_trace = traces[0];
-		const destination_trace = traces[1];
-
-		// Verify redirect trace root span structure
-		expect(redirect_trace).toEqual({
-			name: 'sveltekit.handle.root',
-			status: { code: 0 },
-			start_time: [expect.any(Number), expect.any(Number)],
-			end_time: [expect.any(Number), expect.any(Number)],
-			attributes: {
-				'http.route': '/tracing/redirect',
-				'http.method': 'GET',
-				'http.url': expect.stringContaining(`/tracing/redirect?test_id=${test_id}`),
-				'sveltekit.is_data_request': false,
-				'sveltekit.is_sub_request': false,
-				test_id
-			},
-			links: [],
-			trace_id: redirect_trace_id,
-			span_id: expect.any(String),
-			children: expect.arrayContaining([
-				expect.objectContaining({
-					name: 'sveltekit.handle.sequenced.set_tracing_test_id',
-					attributes: {}
-				})
-			])
-		});
-
-		// Find and verify the redirect resolve.root span
-		const redirect_resolve_root_span = find_resolve_root_span(redirect_trace);
-		expect(redirect_resolve_root_span).not.toBeNull();
-		expect(redirect_resolve_root_span).toEqual({
-			name: 'sveltekit.resolve',
-			status: { code: 0 },
-			start_time: [expect.any(Number), expect.any(Number)],
-			end_time: [expect.any(Number), expect.any(Number)],
-			attributes: {
-				'http.route': '/tracing/redirect',
-				'http.response.status_code': 307,
-				'http.response.body.size': expect.stringMatching(/^\d+$|^unknown$/)
-			},
-			links: [],
-			trace_id: redirect_trace_id,
-			span_id: expect.any(String),
-			parent_span_id: expect.any(String),
-			children: expect.arrayContaining([
-				expect.objectContaining({
-					name: 'sveltekit.load',
-					status: { code: 0 },
-					attributes: expect.objectContaining({
-						'sveltekit.load.node_id': 'src/routes/tracing/redirect/+page.server.js',
-						'sveltekit.load.result.type': 'redirect',
-						'sveltekit.load.result.status': 307,
-						'sveltekit.load.result.location': `/tracing/one/two/three/four/five?test_id=${test_id}`
-					})
-				})
-			])
-		});
-
-		// Verify destination trace root span structure
-		expect(destination_trace).toEqual({
-			name: 'sveltekit.handle.root',
-			status: { code: 0 },
-			start_time: [expect.any(Number), expect.any(Number)],
-			end_time: [expect.any(Number), expect.any(Number)],
-			attributes: {
-				'http.route': '/tracing/one/two/three/[...four]',
-				'http.method': 'GET',
-				'http.url': expect.stringContaining(`/tracing/one/two/three/four/five?test_id=${test_id}`),
-				'sveltekit.is_data_request': false,
-				'sveltekit.is_sub_request': false,
-				test_id
-			},
-			links: [],
-			trace_id: destination_trace_id,
-			span_id: expect.any(String),
-			children: expect.arrayContaining([
-				expect.objectContaining({
-					name: 'sveltekit.handle.sequenced.set_tracing_test_id',
-					attributes: {}
-				})
-			])
-		});
-
-		// Find and verify the destination resolve.root span
-		const destination_resolve_root_span = find_resolve_root_span(destination_trace);
-		expect(destination_resolve_root_span).not.toBeNull();
-		expect(destination_resolve_root_span).toEqual({
-			name: 'sveltekit.resolve',
-			status: { code: 0 },
-			start_time: [expect.any(Number), expect.any(Number)],
-			end_time: [expect.any(Number), expect.any(Number)],
-			attributes: {
-				'http.route': '/tracing/one/two/three/[...four]',
-				'http.response.status_code': 200,
-				'http.response.body.size': expect.stringMatching(/^\d+$/)
-			},
-			links: [],
-			trace_id: destination_trace_id,
-			span_id: expect.any(String),
-			parent_span_id: expect.any(String),
-			children: [
-				{
-					name: 'sveltekit.load',
-					status: { code: 0 },
-					start_time: [expect.any(Number), expect.any(Number)],
-					end_time: [expect.any(Number), expect.any(Number)],
-					attributes: {
-						'sveltekit.load.node_id': 'src/routes/+layout.server.js',
-						'sveltekit.load.node_type': '+layout.server',
-						'sveltekit.load.environment': 'server',
-						'http.route': '/tracing/one/two/three/[...four]'
-					},
-					links: [],
-					trace_id: destination_trace_id,
-					span_id: expect.any(String),
-					parent_span_id: expect.any(String),
-					children: []
-				},
-				{
-					name: 'sveltekit.load',
-					status: { code: 0 },
-					start_time: [expect.any(Number), expect.any(Number)],
-					end_time: [expect.any(Number), expect.any(Number)],
-					attributes: {
-						'sveltekit.load.node_id': 'src/routes/+layout.js',
-						'sveltekit.load.node_type': '+layout',
-						'sveltekit.load.environment': 'server',
-						'http.route': '/tracing/one/two/three/[...four]'
-					},
-					links: [],
-					trace_id: destination_trace_id,
-					span_id: expect.any(String),
-					parent_span_id: expect.any(String),
-					children: []
-				}
-			]
-		});
-	});
-
-	test('correct spans are created for regular Error', async ({ page, read_traces }) => {
-		const test_id = rand();
-		const response = await page.goto(`/tracing/regular-error?test_id=${test_id}`);
-		expect(response?.status()).toBe(500);
-
-		const traces = read_traces(test_id);
-		const trace_id = traces[0].trace_id;
-		const trace = traces[0];
-
-		// Verify root span structure
-		expect(trace).toEqual({
-			name: 'sveltekit.handle.root',
-			status: { code: 0 },
-			start_time: [expect.any(Number), expect.any(Number)],
-			end_time: [expect.any(Number), expect.any(Number)],
-			attributes: {
-				'http.route': '/tracing/regular-error',
-				'http.method': 'GET',
-				'http.url': expect.stringContaining(`/tracing/regular-error?test_id=${test_id}`),
-				'sveltekit.is_data_request': false,
-				'sveltekit.is_sub_request': false,
-				test_id
-			},
-			links: [],
-			trace_id,
-			span_id: expect.any(String),
-			children: expect.arrayContaining([
-				expect.objectContaining({
-					name: 'sveltekit.handle.sequenced.set_tracing_test_id',
-					attributes: {}
-				})
-			])
-		});
-
-		// Find and verify the resolve.root span
-		const resolve_root_span = find_resolve_root_span(trace);
-		expect(resolve_root_span).not.toBeNull();
-		expect(resolve_root_span).toEqual({
-			name: 'sveltekit.resolve',
-			status: { code: 0 },
-			start_time: [expect.any(Number), expect.any(Number)],
-			end_time: [expect.any(Number), expect.any(Number)],
-			attributes: {
-				'http.route': '/tracing/regular-error',
-				'http.response.status_code': 500,
-				'http.response.body.size': expect.stringMatching(/^\d+$/)
-			},
-			links: [],
-			trace_id,
-			span_id: expect.any(String),
-			parent_span_id: expect.any(String),
-			children: expect.arrayContaining([
-				expect.objectContaining({
-					name: 'sveltekit.load',
-					status: { code: 2, message: 'Regular error from tracing test' },
-					attributes: expect.objectContaining({
-						'sveltekit.load.node_id': 'src/routes/tracing/regular-error/+page.server.js',
-						'sveltekit.load.result.type': 'unknown_error'
-					})
-				})
-			])
-		});
-	});
-
-	test('correct spans are created for non-error object', async ({ page, read_traces }) => {
-		const test_id = rand();
-		const response = await page.goto(`/tracing/non-error-object?test_id=${test_id}`);
-		expect(response?.status()).toBe(500);
-
-		const traces = read_traces(test_id);
-		const trace_id = traces[0].trace_id;
-		const trace = traces[0];
-
-		// Verify root span structure
-		expect(trace).toEqual({
-			name: 'sveltekit.handle.root',
-			status: { code: 0 },
-			start_time: [expect.any(Number), expect.any(Number)],
-			end_time: [expect.any(Number), expect.any(Number)],
-			attributes: {
-				'http.route': '/tracing/non-error-object',
-				'http.method': 'GET',
-				'http.url': expect.stringContaining(`/tracing/non-error-object?test_id=${test_id}`),
-				'sveltekit.is_data_request': false,
-				'sveltekit.is_sub_request': false,
-				test_id
-			},
-			links: [],
-			trace_id,
-			span_id: expect.any(String),
-			children: expect.arrayContaining([
-				expect.objectContaining({
-					name: 'sveltekit.handle.sequenced.set_tracing_test_id',
-					attributes: {}
-				})
-			])
-		});
-
-		// Find and verify the resolve.root span
-		const resolve_root_span = find_resolve_root_span(trace);
-		expect(resolve_root_span).not.toBeNull();
-		expect(resolve_root_span).toEqual({
-			name: 'sveltekit.resolve',
-			status: { code: 0 },
-			start_time: [expect.any(Number), expect.any(Number)],
-			end_time: [expect.any(Number), expect.any(Number)],
-			attributes: {
-				'http.route': '/tracing/non-error-object',
-				'http.response.status_code': 500,
-				'http.response.body.size': expect.stringMatching(/^\d+$/)
-			},
-			links: [],
-			trace_id,
-			span_id: expect.any(String),
-			parent_span_id: expect.any(String),
-			children: expect.arrayContaining([
-				expect.objectContaining({
-					name: 'sveltekit.load',
-					status: { code: 2 },
-					attributes: expect.objectContaining({
-						'sveltekit.load.node_id': 'src/routes/tracing/non-error-object/+page.server.js',
-						'sveltekit.load.result.type': 'unknown_error'
-					})
-				})
-			])
-		});
-	});
-});
-
-test.describe('asset preload', () => {
-	test.skip(!!process.env.DEV);
-
-	test('does not inject Link headers', async ({ request }) => {
-		const response = await request.get('/asset-preload');
-
-		const header = response.headers()['link'];
-		expect(header).toBeUndefined();
-	});
-
-	test('injects  tags', async ({ request }) => {
-		const response = await request.get('/asset-preload');
-
-		const body = await response.text();
-
-		expect(body).toContain('rel="modulepreload"');
-		expect(body).toContain('as="font"');
-		expect(body).toMatch(/href="[^"]+\/shlop\.[^".]+\.woff2"/);
-		expect(body).toMatch(/href="[^"]+\/shlop\.var\.[^".]+\.woff2"/);
-		// the emitted file name is sanitized, but the filter matched on the original `shlop+bold.woff2`
-		expect(body).toMatch(/href="[^"]+\/shlop_bold\.[^".]+\.woff2"/);
-	});
-});
-
-test.describe('Streaming', () => {
-	test("Discarded promises from server load functions don't hang SSR request", async ({
-		request
-	}) => {
-		let error;
-		try {
-			await request.get('/streaming/discarded-promise');
-		} catch (e) {
-			error = e;
-		}
-
-		expect(error).toBeUndefined();
-	});
 });
diff --git a/packages/kit/test/records.js b/packages/kit/test/records.js
new file mode 100644
index 000000000000..bb6416cc9948
--- /dev/null
+++ b/packages/kit/test/records.js
@@ -0,0 +1,51 @@
+/** @import { SpanData, SpanTree } from './types.js' */
+import fs from 'node:fs';
+
+/**
+ * The most recent error a test app's `handleError` hook appended for `path`
+ * @param {string} file the app's errors.jsonl
+ * @param {string} path
+ */
+export function read_errors(file, path) {
+	if (!fs.existsSync(file)) return;
+
+	const records = fs.readFileSync(file, 'utf8').split('\n');
+	records.pop(); // ignore a trailing partial record if this races an append
+
+	const match = records.map((line) => JSON.parse(line)).findLast((error) => error.path === path);
+
+	if (match) {
+		const { path: _, ...error } = match;
+		return error;
+	}
+}
+
+/**
+ * The span trees a test app's instrumentation exported for `test_id`
+ * @param {string} file the app's spans.jsonl
+ * @param {string} test_id
+ */
+export function read_traces(file, test_id) {
+	const raw = fs.readFileSync(file, 'utf8').split('\n').filter(Boolean);
+	const traces = /** @type {SpanData[]} */ (raw.map((line) => JSON.parse(line)));
+
+	return traces
+		.filter((t) => t.parent_span_id === undefined && t.attributes.test_id === test_id)
+		.map((root_trace) => {
+			const child_traces = traces.filter((span) => span.trace_id === root_trace.trace_id);
+			return build_span_tree(root_trace, child_traces);
+		});
+}
+
+/**
+ * @param {SpanData} current_span
+ * @param {SpanData[]} child_spans
+ * @returns {SpanTree}
+ */
+function build_span_tree(current_span, child_spans) {
+	const children = child_spans.filter((span) => span.parent_span_id === current_span.span_id);
+	return {
+		...current_span,
+		children: children.map((child) => build_span_tree(child, child_spans))
+	};
+}
diff --git a/packages/kit/test/utils.js b/packages/kit/test/utils.js
index c1dcf6acd143..5241602291d8 100644
--- a/packages/kit/test/utils.js
+++ b/packages/kit/test/utils.js
@@ -1,4 +1,3 @@
-/** @import { SpanData, SpanTree } from './types.js' */
 // This helps `pnpm check` pass in the test apps without having to include
 // the ambient.d.ts file in each of their tsconfig.json files.
 /** @import {} from './ambient.js' */
@@ -10,6 +9,7 @@ import process from 'node:process';
 import { fileURLToPath } from 'node:url';
 import { defineConfig, test as base, devices } from '@playwright/test';
 import { number_from_env } from '../../../test-utils/index.js';
+import { read_errors, read_traces } from './records.js';
 
 /** @type {typeof import('./types.js')['test']} */
 export const test = base.extend({
@@ -146,42 +146,12 @@ export const test = base.extend({
 
 	// eslint-disable-next-line no-empty-pattern -- Playwright doesn't let us use `_` as a parameter name. It must be a destructured object
 	read_errors: async ({}, use) => {
-		/** @param {string} path */
-		function read_errors(path) {
-			if (!fs.existsSync('test/errors.jsonl')) return;
-
-			const records = fs.readFileSync('test/errors.jsonl', 'utf8').split('\n');
-			records.pop(); // ignore a trailing partial record if this races an append
-
-			const match = records
-				.map((line) => JSON.parse(line))
-				.findLast((error) => error.path === path);
-
-			if (match) {
-				const { path: _, ...error } = match;
-				return error;
-			}
-		}
-
-		await use(read_errors);
+		await use((/** @type {string} */ path) => read_errors('test/errors.jsonl', path));
 	},
 
 	// eslint-disable-next-line no-empty-pattern -- Playwright doesn't let us use `_` as a parameter name. It must be a destructured object
 	read_traces: async ({}, use) => {
-		/** @param {string} test_id */
-		function read_traces(test_id) {
-			const raw = fs.readFileSync('test/spans.jsonl', 'utf8').split('\n').filter(Boolean);
-			const traces = /** @type {SpanData[]} */ (raw.map((line) => JSON.parse(line)));
-
-			return traces
-				.filter((t) => t.parent_span_id === undefined && t.attributes.test_id === test_id)
-				.map((root_trace) => {
-					const child_traces = traces.filter((span) => span.trace_id === root_trace.trace_id);
-					return build_span_tree(root_trace, child_traces);
-				});
-		}
-
-		await use(read_traces);
+		await use((/** @type {string} */ test_id) => read_traces('test/spans.jsonl', test_id));
 	},
 
 	// eslint-disable-next-line no-empty-pattern -- Playwright doesn't let us use `_` as a parameter name. It must be a destructured object
@@ -383,16 +353,3 @@ export const config = defineConfig({
 	testDir: 'test',
 	testMatch: /(.+\.)?(test|spec)\.[jt]s/
 });
-
-/**
- * @param {SpanData} current_span
- * @param {SpanData[]} child_spans
- * @returns {SpanTree}
- */
-function build_span_tree(current_span, child_spans) {
-	const children = child_spans.filter((span) => span.parent_span_id === current_span.span_id);
-	return {
-		...current_span,
-		children: children.map((child) => build_span_tree(child, child_spans))
-	};
-}
diff --git a/packages/kit/vitest.kit.config.js b/packages/kit/vitest.kit.config.js
index 03bb473a6c64..1164f9a60e8a 100644
--- a/packages/kit/vitest.kit.config.js
+++ b/packages/kit/vitest.kit.config.js
@@ -55,6 +55,16 @@ export default /** @satisfies {import('vitest/config').ViteUserConfig} */ ({
 					exclude: [...exclude, 'src/**/*.svelte.spec.js']
 				}
 			},
+			{
+				test: {
+					name: 'kit-basics-server',
+					// for DOMParser; Request and Response stay Node's
+					environment: 'jsdom',
+					root: fileURLToPath(new URL('./test/apps/basics', import.meta.url)),
+					include: ['test/server.spec.js'],
+					globalSetup: fileURLToPath(new URL('./test/apps/basics/test/server.setup.js', import.meta.url))
+				}
+			},
 			{
 				extends: true,
 				resolve: {

From cd4a23105ff24110bd502c07620576c571fddce6 Mon Sep 17 00:00:00 2001
From: Nic Polumeyv <162764842+Nic-Polumeyv@users.noreply.github.com>
Date: Thu, 20 Aug 2026 16:38:06 -0400
Subject: [PATCH 02/12] keep the vitest suite out of Playwright's test dir

---
 .../test/apps/basics/{test => unit-test}/server.setup.js    | 0
 .../kit/test/apps/basics/{test => unit-test}/server.spec.js | 0
 packages/kit/test/apps/basics/vite.config.js                | 2 +-
 packages/kit/vitest.kit.config.js                           | 6 ++++--
 4 files changed, 5 insertions(+), 3 deletions(-)
 rename packages/kit/test/apps/basics/{test => unit-test}/server.setup.js (100%)
 rename packages/kit/test/apps/basics/{test => unit-test}/server.spec.js (100%)

diff --git a/packages/kit/test/apps/basics/test/server.setup.js b/packages/kit/test/apps/basics/unit-test/server.setup.js
similarity index 100%
rename from packages/kit/test/apps/basics/test/server.setup.js
rename to packages/kit/test/apps/basics/unit-test/server.setup.js
diff --git a/packages/kit/test/apps/basics/test/server.spec.js b/packages/kit/test/apps/basics/unit-test/server.spec.js
similarity index 100%
rename from packages/kit/test/apps/basics/test/server.spec.js
rename to packages/kit/test/apps/basics/unit-test/server.spec.js
diff --git a/packages/kit/test/apps/basics/vite.config.js b/packages/kit/test/apps/basics/vite.config.js
index 8cd60550cfbf..4e673931cc90 100644
--- a/packages/kit/test/apps/basics/vite.config.js
+++ b/packages/kit/test/apps/basics/vite.config.js
@@ -114,6 +114,6 @@ export default defineConfig({
 			],
 			headless: true
 		},
-		include: ['unit-test/**/*.spec.js']
+		include: ['unit-test/client.spec.js']
 	}
 });
diff --git a/packages/kit/vitest.kit.config.js b/packages/kit/vitest.kit.config.js
index 1164f9a60e8a..0c9d2ba18ea8 100644
--- a/packages/kit/vitest.kit.config.js
+++ b/packages/kit/vitest.kit.config.js
@@ -61,8 +61,10 @@ export default /** @satisfies {import('vitest/config').ViteUserConfig} */ ({
 					// for DOMParser; Request and Response stay Node's
 					environment: 'jsdom',
 					root: fileURLToPath(new URL('./test/apps/basics', import.meta.url)),
-					include: ['test/server.spec.js'],
-					globalSetup: fileURLToPath(new URL('./test/apps/basics/test/server.setup.js', import.meta.url))
+					include: ['unit-test/server.spec.js'],
+					globalSetup: fileURLToPath(
+						new URL('./test/apps/basics/unit-test/server.setup.js', import.meta.url)
+					)
 				}
 			},
 			{

From 307b62acd3049542c79a18988be81042dbd43ed6 Mon Sep 17 00:00:00 2001
From: Nic Polumeyv <162764842+Nic-Polumeyv@users.noreply.github.com>
Date: Thu, 20 Aug 2026 16:50:46 -0400
Subject: [PATCH 03/12] serve the built app over http in the tests, so
 responses keep their HTTP semantics

---
 .../kit/test/apps/basics/test/server.test.js  | 32 -------
 .../test/apps/basics/unit-test/server.spec.js | 96 +++++++++++--------
 2 files changed, 56 insertions(+), 72 deletions(-)

diff --git a/packages/kit/test/apps/basics/test/server.test.js b/packages/kit/test/apps/basics/test/server.test.js
index 95416c6bbb71..7973f6ad39a2 100644
--- a/packages/kit/test/apps/basics/test/server.test.js
+++ b/packages/kit/test/apps/basics/test/server.test.js
@@ -44,25 +44,7 @@ test.describe('Endpoints', () => {
 	// TODO all the remaining tests in this section are really only testing
 	// setResponse, since we're not otherwise changing anything on the response.
 	// might be worth making these unit tests instead
-	test('stream can be canceled with TypeError', async ({ request }) => {
-		const responseBefore = await request.get('/endpoint-output/stream-typeerror?what');
-		expect(await responseBefore.text()).toEqual('null');
-
-		const interruptedResponse = request.get('/endpoint-output/stream-typeerror');
-		await expect(interruptedResponse).rejects.toThrow('socket hang up');
-
-		const responseAfter = await request.get('/endpoint-output/stream-typeerror?what');
-		expect(await responseAfter.text()).toEqual('TypeError');
-	});
-
 	// TODO see above
-	test('invalid headers return a 500', async ({ request }) => {
-		const response = await request.get('/endpoint-output/head-write-error');
-		expect(response.status()).toBe(500);
-		expect(await response.text()).toMatch(
-			'TypeError [ERR_INVALID_CHAR]: Invalid character in header content ["x-test"]'
-		);
-	});
 });
 
 test.describe('Errors', () => {
@@ -78,20 +60,6 @@ test.describe('Errors', () => {
 	});
 });
 
-test.describe('Load', () => {
-	test('fetching a non-existent resource in root layout fails without hanging', async ({
-		request
-	}) => {
-		const response = await request.get('/errors/error-in-layout');
-		expect(await response.text()).toContain('Error: 404');
-	});
-
-	test('fetch does not load a file with a # character', async ({ request }) => {
-		const response = await request.get('/load/static-file-with-hash');
-		expect(await response.text()).toContain('status: 404');
-	});
-});
-
 test.describe('Routing', () => {
 	test('Vite trailing slash redirect for prerendered pages retains URL query string', async ({
 		request
diff --git a/packages/kit/test/apps/basics/unit-test/server.spec.js b/packages/kit/test/apps/basics/unit-test/server.spec.js
index 922633f416af..de3fc7e012f1 100644
--- a/packages/kit/test/apps/basics/unit-test/server.spec.js
+++ b/packages/kit/test/apps/basics/unit-test/server.spec.js
@@ -4,7 +4,7 @@ import fs from 'node:fs';
 import http from 'node:http';
 import path from 'node:path';
 import { pathToFileURL } from 'node:url';
-import { createReadableStream } from '@sveltejs/kit/node';
+import { createReadableStream, getRequest, setResponse } from '@sveltejs/kit/node';
 import { loadEnv } from 'vite';
 import { afterEach, beforeAll, describe, expect, test } from 'vitest';
 import * as records from '../../../records.js';
@@ -15,10 +15,9 @@ import * as records from '../../../records.js';
 
 const root = path.resolve(import.meta.dirname, '..');
 const out = path.join(root, '.svelte-kit/output/server');
-const origin = 'http://localhost:3000';
 
-/** @type {Server} */
-let server;
+/** @type {string} */
+let origin;
 
 beforeAll(async () => {
 	// the app writes test/errors.jsonl and test/spans.jsonl relative to cwd
@@ -32,7 +31,8 @@ beforeAll(async () => {
 	const { manifest } = await import(pathToFileURL(path.join(out, 'manifest.js')).href);
 	const { Server } = await import(pathToFileURL(path.join(out, 'index.js')).href);
 
-	server = new Server(manifest);
+	/** @type {Server} */
+	const server = new Server(manifest);
 	await server.init({
 		env: process.env,
 		read: (file) =>
@@ -40,42 +40,21 @@ beforeAll(async () => {
 				path.join(fs.existsSync(path.join(out, file)) ? out : `${root}/static`, file)
 			)
 	});
-});
 
-/** @type {WeakMap} */
-const urls = new WeakMap();
+	// the same wrapping adapter-node does, so responses get real HTTP semantics
+	const listener = http.createServer(async (req, res) => {
+		const request = getRequest({ request: req, response: res, base: origin });
+		setResponse(res, await server.respond(request, { getClientAddress: () => '127.0.0.1' }));
+	});
+	await new Promise((fulfil) => listener.listen(0, 'localhost', () => fulfil(undefined)));
+	origin = `http://localhost:${/** @type {import('net').AddressInfo} */ (listener.address()).port}`;
+});
 
 /**
- * Request a path from the built server. Redirects are followed like Playwright's
- * `request.get` follows them, unless `redirect: 'manual'` is passed.
  * @param {string} pathname
  * @param {RequestInit} [init]
  */
-async function get(pathname, init = {}) {
-	let url = origin + pathname;
-
-	for (let hops = 0; ; hops++) {
-		const request = new Request(url, init);
-		if (!request.headers.has('accept')) request.headers.set('accept', '*/*');
-
-		let response = await server.respond(request, { getClientAddress: () => '127.0.0.1' });
-
-		const location = response.headers.get('location');
-
-		if (init.redirect === 'manual' || !location || response.status < 300 || hops === 20) {
-			// an HTTP server drops the body of a HEAD response
-			if (request.method === 'HEAD') response = new Response(null, response);
-			urls.set(response, url);
-			return response;
-		}
-
-		url = new URL(location, url).href;
-		if (response.status !== 307 && response.status !== 308) init = {};
-	}
-}
-
-/** The URL a followed redirect ended on, like Playwright's `response.url()` */
-const url_of = (/** @type {Response} */ response) => /** @type {string} */ (urls.get(response));
+const get = (pathname, init) => fetch(origin + pathname, init);
 
 /**
  * Request a page and parse it, for the assertions that used `page.textContent`
@@ -302,6 +281,24 @@ describe('CSRF', () => {
 });
 
 describe('Endpoints', () => {
+	test('invalid headers return a 500', async () => {
+		const response = await get('/endpoint-output/head-write-error');
+		expect(response.status).toBe(500);
+		expect(await response.text()).toMatch(
+			'TypeError [ERR_INVALID_CHAR]: Invalid character in header content ["x-test"]'
+		);
+	});
+
+	test('stream can be canceled with TypeError', async () => {
+		const responseBefore = await get('/endpoint-output/stream-typeerror?what');
+		expect(await responseBefore.text()).toEqual('null');
+
+		await expect(get('/endpoint-output/stream-typeerror')).rejects.toThrow('fetch failed');
+
+		const responseAfter = await get('/endpoint-output/stream-typeerror?what');
+		expect(await responseAfter.text()).toEqual('TypeError');
+	});
+
 	test('HEAD with matching headers but without body', async () => {
 		const url = '/endpoint-output/body';
 
@@ -320,7 +317,7 @@ describe('Endpoints', () => {
 		expect(await responses.head.text()).toBe('');
 		expect(await responses.get.text()).toBe('{}');
 
-		['date', 'transfer-encoding'].forEach((name) => {
+		['connection', 'date', 'keep-alive', 'transfer-encoding'].forEach((name) => {
 			delete headers.head[name];
 			delete headers.get[name];
 		});
@@ -443,8 +440,7 @@ describe('Endpoints', () => {
 
 	// TODO see above
 	test('body can be a binary ReadableStream', async () => {
-		const interruptedResponse = await get('/endpoint-output/stream-throw-error');
-		await expect(interruptedResponse.text()).rejects.toThrow('simulate error');
+		await expect(get('/endpoint-output/stream-throw-error')).rejects.toThrow('fetch failed');
 
 		const response = await get('/endpoint-output/stream');
 		const body = Buffer.from(await response.arrayBuffer());
@@ -802,14 +798,34 @@ describe('Errors', () => {
 });
 
 describe('Load', () => {
+	test('fetch does not load a file with a # character', async () => {
+		const response = await get('/load/static-file-with-hash');
+		expect(await response.text()).toContain('status: 404');
+	});
+
+	test('fetching a non-existent resource in root layout fails without hanging', async () => {
+		const response = await get('/errors/error-in-layout');
+		expect(await response.text()).toContain('Error: 404');
+	});
+
 	test('fetch reads universal load assets on the server', async () => {
 		const { document } = await load('/load/fetch-asset');
 		expect(document.querySelector('p')?.textContent).toBe('1');
 	});
 
 	test('does not forward accept-language to internal fetch when the request has none', async () => {
-		// unlike browsers and undici, the `request` fixture sends no accept-language header
-		const html = await (await get('/load/fetch-request-headers')).text();
+		// unlike browsers and fetch, a bare http client sends no accept-language header
+		const html = await new Promise((fulfil) => {
+			http.get(
+				`${origin}/load/fetch-request-headers`,
+				{ headers: { accept: '*/*', 'user-agent': 'node' } },
+				(res) => {
+					let body = '';
+					res.on('data', (chunk) => (body += chunk));
+					res.on('end', () => fulfil(body));
+				}
+			);
+		});
 		const headers = JSON.parse(
 			/** @type {RegExpMatchArray} */ (/
(.+?)<\/pre>/s.exec(html))[1]
 		);

From b92cd837417ed0edb7dc4c4587116b71e7457a9b Mon Sep 17 00:00:00 2001
From: Nic Polumeyv <162764842+Nic-Polumeyv@users.noreply.github.com>
Date: Thu, 20 Aug 2026 16:57:37 -0400
Subject: [PATCH 04/12] await listening with events.once

---
 .../kit/test/apps/basics/unit-test/server.spec.js  | 14 +++++---------
 1 file changed, 5 insertions(+), 9 deletions(-)

diff --git a/packages/kit/test/apps/basics/unit-test/server.spec.js b/packages/kit/test/apps/basics/unit-test/server.spec.js
index de3fc7e012f1..c98b81dcffb8 100644
--- a/packages/kit/test/apps/basics/unit-test/server.spec.js
+++ b/packages/kit/test/apps/basics/unit-test/server.spec.js
@@ -1,5 +1,6 @@
 /** @import { Server } from '@sveltejs/kit' */
 import { createHash, randomBytes } from 'node:crypto';
+import { once } from 'node:events';
 import fs from 'node:fs';
 import http from 'node:http';
 import path from 'node:path';
@@ -46,7 +47,7 @@ beforeAll(async () => {
 		const request = getRequest({ request: req, response: res, base: origin });
 		setResponse(res, await server.respond(request, { getClientAddress: () => '127.0.0.1' }));
 	});
-	await new Promise((fulfil) => listener.listen(0, 'localhost', () => fulfil(undefined)));
+	await once(listener.listen(0, 'localhost'), 'listening');
 	origin = `http://localhost:${/** @type {import('net').AddressInfo} */ (listener.address()).port}`;
 });
 
@@ -80,16 +81,11 @@ const servers = [];
  * An external server for the tests that fetch across origins
  * @param {(req: http.IncomingMessage, res: http.ServerResponse) => void} handler
  */
-function start_server(handler) {
+async function start_server(handler) {
 	const server = http.createServer(handler);
 	servers.push(server);
-
-	return new Promise((fulfil) => {
-		server.listen(0, 'localhost', () => {
-			const { port } = /** @type {import('net').AddressInfo} */ (server.address());
-			fulfil({ port });
-		});
-	});
+	await once(server.listen(0, 'localhost'), 'listening');
+	return { port: /** @type {import('net').AddressInfo} */ (server.address()).port };
 }
 
 afterEach(async () => {

From 2c0208d60571bac7ae29dace6cbaa0456779077b Mon Sep 17 00:00:00 2001
From: Nic Polumeyv <162764842+Nic-Polumeyv@users.noreply.github.com>
Date: Thu, 20 Aug 2026 17:05:31 -0400
Subject: [PATCH 05/12] load the env in one pass

---
 packages/kit/test/apps/basics/unit-test/server.spec.js | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/packages/kit/test/apps/basics/unit-test/server.spec.js b/packages/kit/test/apps/basics/unit-test/server.spec.js
index c98b81dcffb8..0a302dbfce7a 100644
--- a/packages/kit/test/apps/basics/unit-test/server.spec.js
+++ b/packages/kit/test/apps/basics/unit-test/server.spec.js
@@ -25,9 +25,9 @@ beforeAll(async () => {
 	process.chdir(root);
 
 	// the preview server gets these from Vite's .env loading
-	for (const [key, value] of Object.entries(loadEnv('production', root, ''))) {
-		process.env[key] ??= value;
-	}
+	Object.entries(loadEnv('production', root, '')).forEach(
+		([key, value]) => (process.env[key] ??= value)
+	);
 
 	const { manifest } = await import(pathToFileURL(path.join(out, 'manifest.js')).href);
 	const { Server } = await import(pathToFileURL(path.join(out, 'index.js')).href);

From 823002dec13fa7e7eddde12d86b19d8323bed50c Mon Sep 17 00:00:00 2001
From: Rich Harris 
Date: Thu, 20 Aug 2026 18:26:01 -0400
Subject: [PATCH 06/12] WIP

---
 .../test/apps/basics/unit-test/server.spec.js | 38 +++++++++++++++----
 packages/kit/vitest.kit.config.js             |  8 ++--
 2 files changed, 35 insertions(+), 11 deletions(-)

diff --git a/packages/kit/test/apps/basics/unit-test/server.spec.js b/packages/kit/test/apps/basics/unit-test/server.spec.js
index 0a302dbfce7a..dd89da17b070 100644
--- a/packages/kit/test/apps/basics/unit-test/server.spec.js
+++ b/packages/kit/test/apps/basics/unit-test/server.spec.js
@@ -20,6 +20,9 @@ const out = path.join(root, '.svelte-kit/output/server');
 /** @type {string} */
 let origin;
 
+/** @type {Server} */
+let server;
+
 beforeAll(async () => {
 	// the app writes test/errors.jsonl and test/spans.jsonl relative to cwd
 	process.chdir(root);
@@ -32,8 +35,7 @@ beforeAll(async () => {
 	const { manifest } = await import(pathToFileURL(path.join(out, 'manifest.js')).href);
 	const { Server } = await import(pathToFileURL(path.join(out, 'index.js')).href);
 
-	/** @type {Server} */
-	const server = new Server(manifest);
+	server = new Server(manifest);
 	await server.init({
 		env: process.env,
 		read: (file) =>
@@ -55,7 +57,18 @@ beforeAll(async () => {
  * @param {string} pathname
  * @param {RequestInit} [init]
  */
-const get = (pathname, init) => fetch(origin + pathname, init);
+// const get = (pathname, init) => fetch(origin + pathname, init);
+
+const get = async (pathname, init) => {
+	const url = origin + pathname;
+
+	const request = new Request(url, init);
+	const response = await server.respond(request, {
+		getClientAddress: () => ''
+	});
+
+	return response;
+};
 
 /**
  * Request a page and parse it, for the assertions that used `page.textContent`
@@ -63,7 +76,15 @@ const get = (pathname, init) => fetch(origin + pathname, init);
  * @param {RequestInit} [init]
  */
 async function load(pathname, init) {
-	const response = await get(pathname, init);
+	let response = await get(pathname, init);
+
+	while (response.status >= 300 && response.status < 400) {
+		const location = /** @type {string} */ (response.headers.get('location'));
+		const redirected = new URL(location, origin + pathname);
+
+		response = await get(redirected.pathname + redirected.search, init);
+	}
+
 	const document = new DOMParser().parseFromString(await response.text(), 'text/html');
 	return { response, document };
 }
@@ -664,7 +685,7 @@ describe('Errors', () => {
 
 	test('redirect(...) in endpoint', async () => {
 		const { response, document } = await load('/errors/endpoint-throw-redirect');
-		expect(response.status).toBe(200); // redirects are opaque to the browser
+		expect(response.status).toBe(200);
 
 		const error = read_errors('/errors/endpoint-throw-redirect');
 		expect(error).toBe(undefined);
@@ -1254,8 +1275,11 @@ describe('tracing', () => {
 
 	test('correct spans are created for Redirect', async () => {
 		const test_id = rand();
-		const response = await get(`/tracing/redirect?test_id=${test_id}`);
-		expect(response.status).toBe(200);
+		const r1 = await get(`/tracing/redirect?test_id=${test_id}`);
+		expect(r1.status).toBe(307);
+
+		const r2 = await get(/** @type {string} */ (r1.headers.get('location')));
+		expect(r2.status).toBe(200);
 
 		const traces = read_traces(test_id);
 		expect(traces).toHaveLength(2);
diff --git a/packages/kit/vitest.kit.config.js b/packages/kit/vitest.kit.config.js
index 0c9d2ba18ea8..05f9d0299f23 100644
--- a/packages/kit/vitest.kit.config.js
+++ b/packages/kit/vitest.kit.config.js
@@ -61,10 +61,10 @@ export default /** @satisfies {import('vitest/config').ViteUserConfig} */ ({
 					// for DOMParser; Request and Response stay Node's
 					environment: 'jsdom',
 					root: fileURLToPath(new URL('./test/apps/basics', import.meta.url)),
-					include: ['unit-test/server.spec.js'],
-					globalSetup: fileURLToPath(
-						new URL('./test/apps/basics/unit-test/server.setup.js', import.meta.url)
-					)
+					include: ['unit-test/server.spec.js']
+					// globalSetup: fileURLToPath(
+					// 	new URL('./test/apps/basics/unit-test/server.setup.js', import.meta.url)
+					// )
 				}
 			},
 			{

From ee02cc966b59fe0d8a103313e36860ff3137cdb0 Mon Sep 17 00:00:00 2001
From: Rich Harris 
Date: Thu, 20 Aug 2026 19:20:40 -0400
Subject: [PATCH 07/12] WIP

---
 packages/kit/src/runtime/server/endpoint.js   |  6 ++++-
 packages/kit/src/runtime/server/respond.js    |  2 +-
 .../head-write-error/+server.js               | 10 --------
 .../test/apps/basics/unit-test/server.spec.js | 24 ++++++++++++++-----
 4 files changed, 24 insertions(+), 18 deletions(-)
 delete mode 100644 packages/kit/test/apps/basics/src/routes/endpoint-output/head-write-error/+server.js

diff --git a/packages/kit/src/runtime/server/endpoint.js b/packages/kit/src/runtime/server/endpoint.js
index 7f16c177f8d4..2a7c0ae5df0b 100644
--- a/packages/kit/src/runtime/server/endpoint.js
+++ b/packages/kit/src/runtime/server/endpoint.js
@@ -46,10 +46,14 @@ export async function render_endpoint(event, state, mod) {
 	}
 
 	try {
-		const response = await with_request_store({ event, state }, () =>
+		let response = await with_request_store({ event, state }, () =>
 			handler(/** @type {import('@sveltejs/kit').RequestEvent>} */ (event))
 		);
 
+		if (event.request.method === 'HEAD' && response.body !== null) {
+			response = new Response(null, response);
+		}
+
 		if (!(response instanceof Response)) {
 			throw new Error(
 				`Invalid response from route ${event.url.pathname}: handler should return a Response object`
diff --git a/packages/kit/src/runtime/server/respond.js b/packages/kit/src/runtime/server/respond.js
index 7913f64f9dd3..0165800c60ad 100644
--- a/packages/kit/src/runtime/server/respond.js
+++ b/packages/kit/src/runtime/server/respond.js
@@ -734,7 +734,7 @@ export async function internal_respond(request, options, manifest, state) {
 					if (!(vary?.includes('accept') || vary?.includes('*'))) {
 						// the returned response might have immutable headers,
 						// so we have to clone them before trying to mutate them
-						response = new Response(response.body, {
+						response = new Response(request.method === 'HEAD' ? undefined : response.body, {
 							status: response.status,
 							statusText: response.statusText,
 							headers: new Headers(response.headers)
diff --git a/packages/kit/test/apps/basics/src/routes/endpoint-output/head-write-error/+server.js b/packages/kit/test/apps/basics/src/routes/endpoint-output/head-write-error/+server.js
deleted file mode 100644
index 72664eee7dcc..000000000000
--- a/packages/kit/test/apps/basics/src/routes/endpoint-output/head-write-error/+server.js
+++ /dev/null
@@ -1,10 +0,0 @@
-import { json } from '@sveltejs/kit';
-
-/** @type {import('@sveltejs/kit').RequestHandler} */
-export function GET({ setHeaders }) {
-	setHeaders({
-		'x-test': '\u001f'
-	});
-
-	return json({});
-}
diff --git a/packages/kit/test/apps/basics/unit-test/server.spec.js b/packages/kit/test/apps/basics/unit-test/server.spec.js
index dd89da17b070..39ce7429f8a2 100644
--- a/packages/kit/test/apps/basics/unit-test/server.spec.js
+++ b/packages/kit/test/apps/basics/unit-test/server.spec.js
@@ -57,8 +57,6 @@ beforeAll(async () => {
  * @param {string} pathname
  * @param {RequestInit} [init]
  */
-// const get = (pathname, init) => fetch(origin + pathname, init);
-
 const get = async (pathname, init) => {
 	const url = origin + pathname;
 
@@ -457,7 +455,9 @@ describe('Endpoints', () => {
 
 	// TODO see above
 	test('body can be a binary ReadableStream', async () => {
-		await expect(get('/endpoint-output/stream-throw-error')).rejects.toThrow('fetch failed');
+		await expect(
+			get('/endpoint-output/stream-throw-error').then((r) => r.arrayBuffer())
+		).rejects.toThrow('simulate error');
 
 		const response = await get('/endpoint-output/stream');
 		const body = Buffer.from(await response.arrayBuffer());
@@ -668,7 +668,11 @@ describe('Errors', () => {
 
 		// JSON (default)
 		{
-			const res = await get('/errors/endpoint-throw-error');
+			const res = await get('/errors/endpoint-throw-error', {
+				headers: {
+					accept: '*/*'
+				}
+			});
 
 			expect(read_errors('/errors/endpoint-throw-error')).toEqual({
 				kind: 'app',
@@ -738,7 +742,11 @@ describe('Errors', () => {
 
 		// JSON (default)
 		{
-			const res = await get('/errors/error-in-handle');
+			const res = await get('/errors/error-in-handle', {
+				headers: {
+					accept: '*/*'
+				}
+			});
 
 			const error = await res.json();
 
@@ -768,7 +776,11 @@ describe('Errors', () => {
 
 		// JSON (default)
 		{
-			const res = await get('/errors/expected-error-in-handle');
+			const res = await get('/errors/expected-error-in-handle', {
+				headers: {
+					accept: '*/*'
+				}
+			});
 
 			const error = await res.json();
 

From eca52f5f228657446ec181bc801826c624606c86 Mon Sep 17 00:00:00 2001
From: Rich Harris 
Date: Thu, 20 Aug 2026 19:34:58 -0400
Subject: [PATCH 08/12] fix

---
 .../kit/test/apps/basics/unit-test/server.spec.js     | 11 ++---------
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/packages/kit/test/apps/basics/unit-test/server.spec.js b/packages/kit/test/apps/basics/unit-test/server.spec.js
index 39ce7429f8a2..9f666a47c493 100644
--- a/packages/kit/test/apps/basics/unit-test/server.spec.js
+++ b/packages/kit/test/apps/basics/unit-test/server.spec.js
@@ -296,19 +296,12 @@ describe('CSRF', () => {
 });
 
 describe('Endpoints', () => {
-	test('invalid headers return a 500', async () => {
-		const response = await get('/endpoint-output/head-write-error');
-		expect(response.status).toBe(500);
-		expect(await response.text()).toMatch(
-			'TypeError [ERR_INVALID_CHAR]: Invalid character in header content ["x-test"]'
-		);
-	});
-
 	test('stream can be canceled with TypeError', async () => {
 		const responseBefore = await get('/endpoint-output/stream-typeerror?what');
 		expect(await responseBefore.text()).toEqual('null');
 
-		await expect(get('/endpoint-output/stream-typeerror')).rejects.toThrow('fetch failed');
+		const response = await get('/endpoint-output/stream-typeerror');
+		await response.body?.cancel(new TypeError());
 
 		const responseAfter = await get('/endpoint-output/stream-typeerror?what');
 		expect(await responseAfter.text()).toEqual('TypeError');

From d56dc2c9c89d6ab20017704947e30eb770078833 Mon Sep 17 00:00:00 2001
From: Nic Polumeyv <162764842+Nic-Polumeyv@users.noreply.github.com>
Date: Sat, 22 Aug 2026 13:27:02 -0400
Subject: [PATCH 09/12] restore the globalSetup build, the unit CI job has no
 other builder

---
 packages/kit/vitest.kit.config.js | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/packages/kit/vitest.kit.config.js b/packages/kit/vitest.kit.config.js
index 05f9d0299f23..0c9d2ba18ea8 100644
--- a/packages/kit/vitest.kit.config.js
+++ b/packages/kit/vitest.kit.config.js
@@ -61,10 +61,10 @@ export default /** @satisfies {import('vitest/config').ViteUserConfig} */ ({
 					// for DOMParser; Request and Response stay Node's
 					environment: 'jsdom',
 					root: fileURLToPath(new URL('./test/apps/basics', import.meta.url)),
-					include: ['unit-test/server.spec.js']
-					// globalSetup: fileURLToPath(
-					// 	new URL('./test/apps/basics/unit-test/server.setup.js', import.meta.url)
-					// )
+					include: ['unit-test/server.spec.js'],
+					globalSetup: fileURLToPath(
+						new URL('./test/apps/basics/unit-test/server.setup.js', import.meta.url)
+					)
 				}
 			},
 			{

From 822808d7cbf06735cc8863f94fa6a30b62c84b1d Mon Sep 17 00:00:00 2001
From: Nic Polumeyv <162764842+Nic-Polumeyv@users.noreply.github.com>
Date: Sat, 22 Aug 2026 13:27:02 -0400
Subject: [PATCH 10/12] strip HEAD response bodies in one place

---
 packages/kit/src/runtime/server/endpoint.js | 6 +-----
 packages/kit/src/runtime/server/index.js    | 8 +++++++-
 packages/kit/src/runtime/server/respond.js  | 2 +-
 3 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/packages/kit/src/runtime/server/endpoint.js b/packages/kit/src/runtime/server/endpoint.js
index 2a7c0ae5df0b..7f16c177f8d4 100644
--- a/packages/kit/src/runtime/server/endpoint.js
+++ b/packages/kit/src/runtime/server/endpoint.js
@@ -46,14 +46,10 @@ export async function render_endpoint(event, state, mod) {
 	}
 
 	try {
-		let response = await with_request_store({ event, state }, () =>
+		const response = await with_request_store({ event, state }, () =>
 			handler(/** @type {import('@sveltejs/kit').RequestEvent>} */ (event))
 		);
 
-		if (event.request.method === 'HEAD' && response.body !== null) {
-			response = new Response(null, response);
-		}
-
 		if (!(response instanceof Response)) {
 			throw new Error(
 				`Invalid response from route ${event.url.pathname}: handler should return a Response object`
diff --git a/packages/kit/src/runtime/server/index.js b/packages/kit/src/runtime/server/index.js
index e466c89baedb..c795968ac328 100644
--- a/packages/kit/src/runtime/server/index.js
+++ b/packages/kit/src/runtime/server/index.js
@@ -183,7 +183,13 @@ export class Server {
 	async respond(request, options) {
 		const request_state = create_request_state(options);
 
-		const response = await respond(request, this.#options, this.#manifest, request_state);
+		let response = await respond(request, this.#options, this.#manifest, request_state);
+
+		// the HTTP layer discards HEAD response bodies, but nothing does when the server is called directly
+		if (request.method === 'HEAD' && response.body !== null) {
+			response.body.cancel().catch(noop);
+			response = new Response(null, response);
+		}
 
 		if (DEV) {
 			const error = decoded_responses.get(response);
diff --git a/packages/kit/src/runtime/server/respond.js b/packages/kit/src/runtime/server/respond.js
index 0165800c60ad..7913f64f9dd3 100644
--- a/packages/kit/src/runtime/server/respond.js
+++ b/packages/kit/src/runtime/server/respond.js
@@ -734,7 +734,7 @@ export async function internal_respond(request, options, manifest, state) {
 					if (!(vary?.includes('accept') || vary?.includes('*'))) {
 						// the returned response might have immutable headers,
 						// so we have to clone them before trying to mutate them
-						response = new Response(request.method === 'HEAD' ? undefined : response.body, {
+						response = new Response(response.body, {
 							status: response.status,
 							statusText: response.statusText,
 							headers: new Headers(response.headers)

From 44b08cb4c65d3831358bb29dceaaa810455b7e11 Mon Sep 17 00:00:00 2001
From: Nic Polumeyv <162764842+Nic-Polumeyv@users.noreply.github.com>
Date: Sat, 22 Aug 2026 13:38:49 -0400
Subject: [PATCH 11/12] default the accept header in get, like fetch does

---
 .../test/apps/basics/unit-test/server.spec.js | 45 +++++--------------
 1 file changed, 12 insertions(+), 33 deletions(-)

diff --git a/packages/kit/test/apps/basics/unit-test/server.spec.js b/packages/kit/test/apps/basics/unit-test/server.spec.js
index 9f666a47c493..c03c8a7e0016 100644
--- a/packages/kit/test/apps/basics/unit-test/server.spec.js
+++ b/packages/kit/test/apps/basics/unit-test/server.spec.js
@@ -58,9 +58,13 @@ beforeAll(async () => {
  * @param {RequestInit} [init]
  */
 const get = async (pathname, init) => {
-	const url = origin + pathname;
+	const request = new Request(origin + pathname, init);
+
+	// `fetch` implies this
+	if (!request.headers.has('accept')) {
+		request.headers.set('accept', '*/*');
+	}
 
-	const request = new Request(url, init);
 	const response = await server.respond(request, {
 		getClientAddress: () => ''
 	});
@@ -362,11 +366,7 @@ describe('Endpoints', () => {
 	});
 
 	test('serves page for GET request when endpoint has no GET handler', async () => {
-		const response = await get('/endpoint-output/post-only-with-page', {
-			headers: {
-				accept: '*/*'
-			}
-		});
+		const response = await get('/endpoint-output/post-only-with-page');
 
 		expect(response.status).toBe(200);
 		expect(response.headers.get('content-type')).toContain('text/html');
@@ -374,12 +374,7 @@ describe('Endpoints', () => {
 	});
 
 	test('serves page for HEAD request when endpoint has no HEAD or GET handler', async () => {
-		const response = await get('/endpoint-output/post-only-with-page', {
-			method: 'HEAD',
-			headers: {
-				accept: '*/*'
-			}
-		});
+		const response = await get('/endpoint-output/post-only-with-page', { method: 'HEAD' });
 
 		expect(response.status).toBe(200);
 		expect(response.headers.get('content-type')).toContain('text/html');
@@ -398,11 +393,7 @@ describe('Endpoints', () => {
 	});
 
 	test('uses fallback handler instead of page when endpoint has no GET but has fallback', async () => {
-		const response = await get('/endpoint-output/fallback-with-page', {
-			headers: {
-				accept: '*/*'
-			}
-		});
+		const response = await get('/endpoint-output/fallback-with-page');
 
 		expect(response.status).toBe(200);
 		expect(await response.text()).toBe('catch-all');
@@ -661,11 +652,7 @@ describe('Errors', () => {
 
 		// JSON (default)
 		{
-			const res = await get('/errors/endpoint-throw-error', {
-				headers: {
-					accept: '*/*'
-				}
-			});
+			const res = await get('/errors/endpoint-throw-error');
 
 			expect(read_errors('/errors/endpoint-throw-error')).toEqual({
 				kind: 'app',
@@ -735,11 +722,7 @@ describe('Errors', () => {
 
 		// JSON (default)
 		{
-			const res = await get('/errors/error-in-handle', {
-				headers: {
-					accept: '*/*'
-				}
-			});
+			const res = await get('/errors/error-in-handle');
 
 			const error = await res.json();
 
@@ -769,11 +752,7 @@ describe('Errors', () => {
 
 		// JSON (default)
 		{
-			const res = await get('/errors/expected-error-in-handle', {
-				headers: {
-					accept: '*/*'
-				}
-			});
+			const res = await get('/errors/expected-error-in-handle');
 
 			const error = await res.json();
 

From 4bea7740859d2cf9d0e77ae5e51bc4e88f4bc24d Mon Sep 17 00:00:00 2001
From: Nic Polumeyv <162764842+Nic-Polumeyv@users.noreply.github.com>
Date: Sat, 22 Aug 2026 13:56:10 -0400
Subject: [PATCH 12/12] remove a test of undici's data: URL handling, and two
 leftovers from the http harness

---
 .../fetch-asset/absolute/+server.js              | 14 --------------
 .../test/apps/basics/unit-test/server.spec.js    | 16 +---------------
 2 files changed, 1 insertion(+), 29 deletions(-)
 delete mode 100644 packages/kit/test/apps/basics/src/routes/endpoint-output/fetch-asset/absolute/+server.js

diff --git a/packages/kit/test/apps/basics/src/routes/endpoint-output/fetch-asset/absolute/+server.js b/packages/kit/test/apps/basics/src/routes/endpoint-output/fetch-asset/absolute/+server.js
deleted file mode 100644
index 9f1b32595f58..000000000000
--- a/packages/kit/test/apps/basics/src/routes/endpoint-output/fetch-asset/absolute/+server.js
+++ /dev/null
@@ -1,14 +0,0 @@
-import file_path from '../test.txt?url';
-
-/** @type {import('@sveltejs/kit').RequestHandler} */
-export async function GET({ url }) {
-	const absolute = new URL(file_path, url.origin);
-
-	const response = await fetch(absolute);
-
-	return new Response(response.body, {
-		headers: {
-			'Content-Type': response.headers.get('Content-Type') ?? ''
-		}
-	});
-}
diff --git a/packages/kit/test/apps/basics/unit-test/server.spec.js b/packages/kit/test/apps/basics/unit-test/server.spec.js
index c03c8a7e0016..b257bbb70746 100644
--- a/packages/kit/test/apps/basics/unit-test/server.spec.js
+++ b/packages/kit/test/apps/basics/unit-test/server.spec.js
@@ -133,9 +133,7 @@ describe('Content-Length', () => {
 	test('sets Content-Length on page', async () => {
 		const response = await get('/content-length-header');
 
-		if (!response.headers.get('content-encoding')) {
-			expect(Number(response.headers.get('content-length'))).toBeGreaterThan(1000);
-		}
+		expect(Number(response.headers.get('content-length'))).toBeGreaterThan(1000);
 	});
 });
 
@@ -329,11 +327,6 @@ describe('Endpoints', () => {
 		expect(await responses.head.text()).toBe('');
 		expect(await responses.get.text()).toBe('{}');
 
-		['connection', 'date', 'keep-alive', 'transfer-encoding'].forEach((name) => {
-			delete headers.head[name];
-			delete headers.get[name];
-		});
-
 		expect(headers.head).toEqual(headers.get);
 	});
 
@@ -542,13 +535,6 @@ describe('Endpoints', () => {
 		expect(response.headers.get('allow')).toBe('GET, QUERY, HEAD');
 	});
 
-	test('can get assets using absolute path', async () => {
-		const response = await get('/endpoint-output/fetch-asset/absolute');
-		expect(response.status).toBe(200);
-		expect(response.headers.get('content-type')).toBe('text/plain');
-		expect(await response.text()).toBe('Cos sie konczy, cos zaczyna');
-	});
-
 	test('can get assets using relative path', async () => {
 		const response = await get('/endpoint-output/fetch-asset/relative');
 		expect(response.status).toBe(200);