Skip to content

test(web): pin four unprotected server-function surfaces - #3177

Open
frenzzy wants to merge 2 commits into
solidjs:nextfrom
frenzzy:test/server-function-coverage
Open

test(web): pin four unprotected server-function surfaces#3177
frenzzy wants to merge 2 commits into
solidjs:nextfrom
frenzzy:test/server-function-coverage

Conversation

@frenzzy

@frenzzy frenzzy commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Four areas of the server-function surface had no coverage in the tree. This adds 33 tests across four files, in the existing idiom, touching no existing test and no runtime code.

What is pinned, and why each earned a place

File Tests Why it was needed
server-functions-rich-arguments.spec.tsx 6 File/Blob/typed-array/FormData/URLSearchParams round trip, plus the bound ?args= + trailing-body ordering — which had no test at all
server-functions-invocation-wrap.spec.tsx 7 wrapInvocation on both legs, deny-gate, sync transparency, invocation identity. The direct SSR leg could skip the configured policy with nothing noticing
server-functions-outcome-digest.spec.tsx 11 foldedHeaders, targetUrl and revalidateKeys had zero references anywhere in the test tree, plus foldSetCookies
server-functions-nojs-destination.spec.tsx 9 createNoJSHandler destination choice and flash behaviour

Every test is mutation-proven

A test that passes both before and after a regression is worthless, so each one here was checked by mutating the built runtime and confirming it goes red, then reverting. Representative:

  • formData.get(FILE_FORM_KEY)get("file") — both File tests red
  • new Uint8Array(body)body.buffer — typed-array view test red (ships 8 bytes instead of 3)
  • parsed.push(decoded)unshift — both ?args= ordering tests red
  • direct leg skips config.wrapInvocation — "a render cannot walk around the policy" red
  • sanitizeServerError → passthrough — a secret leaks into the body, red
  • cross-origin targetUrl guard removed — off-site redirect test red
  • new Headers(headers)headers — three tests red (input mutation)
  • validRedirectStatuses.has(...) guard removed — a 201 becomes a 303, red

Three candidate assertions were dropped for failing that bar: a Headers-constructor Set-Cookie folding claim (modern undici does not fold, so nothing could regress), an expect(response.body).toBeNull() (guaranteed by the 303 status rather than by anything here), and a URLSearchParams decode assertion whose "proof" turned out to be a no-op edit.

Suite

before   Test Files 48 passed (48)    Tests 524 passed | 2 skipped (526)
after    Test Files 52 passed (52)    Tests 557 passed | 2 skipped (559)

packages/web green across all three configs; tsc --project packages/web/tsconfig.test.json and prettier --check clean for the new files.

Notes

These came out of a coverage comparison against another framework's server-function suite. Solid is ahead almost everywhere — method handling, response shapes, redirects, error sanitization, caching semantics and the CSRF gate are all substantially better covered here — so this PR is only the short list of places where the tree genuinely had nothing.

Two gaps found in that comparison are not addressed here because they are feature questions rather than test gaps: there is no argument-validation API, and wrapInvocation is a single slot rather than a composable chain. Happy to open issues for either if useful.

Four areas had no coverage in the tree. Each of the 33 tests here was proven
to detect a regression by mutating the built runtime and watching it go red;
three candidate assertions were dropped for passing both before and after.

- rich arguments: File/Blob/typed-array/FormData/URLSearchParams round trip,
  and the bound `?args=` + trailing-body ordering. `?args=` ordering had no
  test at all, and a `push`->`unshift` mutation showed why.
- wrapInvocation: both legs, deny-gate, sync transparency, invocation
  identity. The direct SSR leg could previously skip the configured policy
  with nothing noticing.
- outcome digest: `foldedHeaders`, `targetUrl` and `revalidateKeys` had zero
  references anywhere in the test tree, plus `foldSetCookies`.
- createNoJSHandler: destination choice and flash behaviour.

Suite: 524 -> 557 passing, no existing test touched.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VqfkrUXVM5zzVa2aNNFXXa
@changeset-bot

changeset-bot Bot commented Sep 1, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 83ea886

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@codspeed-hq

codspeed-hq Bot commented Sep 1, 2026

Copy link
Copy Markdown

Merging this PR will degrade performance by 14.29%

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

⚡ 1 improved benchmark
❌ 1 regressed benchmark
✅ 134 untouched benchmarks
⏩ 132 skipped benchmarks1

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Benchmark BASE HEAD Efficiency
merge 70.9 µs 138.2 µs -48.71%
merge 322.7 µs 225.3 µs +43.24%

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing frenzzy:test/server-function-coverage (83ea886) with next (f051db6)

Open in CodSpeed

Footnotes

  1. 132 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

Review against the surrounding specs turned up four things a maintainer
would have caught, so they are fixed here rather than argued about.

- rename rich-arguments -> body-formats. `enableRichArguments` is a real
  opt-in codec (server-functions/src/rich-args.ts) that this file explicitly
  disclaims and that still has no coverage anywhere; the old name sent
  anyone grepping for it to the one file that does not test it. The source
  calls what this file pins `BodyFormat`.
- name the wire formats. The header was spelled three different ways across
  the four files and disagreed with request-bounds and shared.ts; bare
  integers ("5", "4", "7", "2", "3") are now FILE_FORMAT and friends, and
  ERROR_HEADER / GENERIC_SERVER_ERROR_MESSAGE / FLASH_COOKIE are imported
  rather than spelled.
- strengthen three assertions. `not.toContain(secret)` alone is the exact
  anti-pattern failure-sanitization documents as having let a broken fix go
  green, so it is now paired with the positive; a substring match on an
  encoded body became `decodeResponse`; and `toEqual` with an `undefined`
  key asserted nothing, so it is `toStrictEqual`.
- delete ~30 lines of inert setup, each verified by removal: a hand-rolled
  createEvent in the transport helper, five unused createEvent options, and
  a whole AsyncLocalStorage install in a file that never enters the handler.

Also: the no-JS fixture posted to /_server/data/<id> without a form content
type — a browser form posts to fn.url, the bare address (solidjs#3094) — and the
four docblocks now say plainly that they pin previously-uncovered surface,
since every existing spec in this directory cites an issue and their silence
read as an omission.

Suite unchanged at 52 files / 557 passed / 2 skipped.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VqfkrUXVM5zzVa2aNNFXXa
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant