the whole setup · one sentence per flow · no test code

End-to-end tests for SolidJS.

Solid does not re-render: it mutates the exact node whose signal changed. That is why it is fast, and why a test holding a reference to that node can happily pass while the thing it is measuring never updated. Describe what should be on screen instead, in a sentence.

the whole setup
$ npx smolanalytics test \
    --url http://localhost:3000 \
    --test "adding two items to the cart shows a total of 2 in the header"

Run it against dev on your own machine before you wire anything into CI. No account is needed for the first run.

how do I write end-to-end tests for a SolidJS app?

End-to-end testing a SolidJS app without writing test code: put one sentence per flow in a markdown file, or pass a single --test flag, and run npx smolanalytics test against a running URL. An agent opens a real browser and decides what to click by reading the page's accessibility tree, so it never holds a reference to a DOM node — which matters more in Solid than elsewhere, because fine-grained reactivity mutates nodes in place and a node reference in a test can therefore keep passing while the signal behind it stopped updating. It checks the value it can see on screen instead. The verdict is passed, failed, stale or errored, and those are kept strictly apart: failed means your app did not do what the test describes, stale means a recording no longer fits the page and the agent is going back to find out whether that was a rename or a removal, and errored means our runner could not run, which is our fault and never a statement about your app. On a pull request, one comment says what broke, edited in place. A passing run is recorded and replays with no model call at all. Setup is a URL and a sentence; nothing is written to your repo. 14-day trial at Pro limits, no card, then $19/month.

Fine-grained reactivity changes what a test can trust. In a framework that re-renders, a stale element reference throws and the test goes red. In Solid the node survives every update, so a test written against it keeps resolving and keeps asserting on whatever text happens to be in there — including text that never changed because the signal it depended on was read outside a tracking scope. That is the classic Solid bug: a value destructured out of props at the top of a component, frozen at its first value, rendering forever. It looks correct. It is correct once. The agent has no node reference to go stale, because it re-reads the page each time and checks the number it can see.

The other one worth a sentence is the resource: <Suspense> falls back, the fetch rejects, and the fallback stays up. A spinner that never resolves is the hardest failure to alert on and the easiest one to describe — "confirm the list of orders appears" fails on it every time.

Instrumentation is the second half and it comes free of the same walk. Solid apps tend to have very few components and a lot of signals, so the events worth having are the handful of real user actions the agent just performed. It writes and maintains those tracking calls in the SDK you already use — PostHog, Mixpanel, Amplitude, Google Analytics, Plausible or Segment — rather than asking you to adopt ours.

How it works walks the whole loop from the sentence to the comment on the pull request, instrumentation covers the second half — the tracking calls the same walk writes and maintains — and the free tools run without an account. The docs have the flags, the suite format and the CI step.

Pro $19/mo, 100 tested pull requests included, unlimited projects, after a 14-day trial at Pro limits with no card. full pricing, including overage →

One sentence, on your SolidJS app, tonight.

Point it at a URL that is already running and describe what should work. The first run uses the agent; once it passes it is recorded, so every run after that replays with no model at all — measured on our own site, 8.0s the first time and 1.4s the second.

questions

Does it work with Solid Start's server functions and streaming?
Yes, because it never talks to your framework — it talks to a browser. Streamed HTML arrives, Suspense boundaries resolve or do not, and the agent looks at the page in whatever state it ends up in. The failure worth writing a sentence for is the one streaming makes possible: a boundary that never resolves because the server function rejected, leaving a fallback on screen indefinitely. "Confirm the order list appears" catches that; a check on the response status does not, because the response was fine.
How much does it cost to run this on every push?
Almost nothing after the first pass, because a test that has passed is recorded and replayed with no model call at all. Measured on our own site: 8.0 seconds for the agent run and 1.4 seconds for the replay. The agent only re-engages when the recording no longer fits, which is exactly when judgement is worth paying for. The meter is the tested pull request rather than the run: Pro is $19/month with 100 included and 10c each after.
What do I actually get back after a run on SolidJS?
One of four words, and the difference between them is the product. Passed. Failed, which means your app did not do what the test describes, so it is a bug report. Stale, which means a recording no longer fits the page — a rename and a removal look identical to a replay, so this is never worded or coloured as a failure and the agent goes and works out which it was. Errored, which means our runner could not run at all: no browser, no network, no key. That one is our fault and it says so, because telling you your checkout is broken when our own runner fell over is the fastest way to lose you.

keep reading