Osy#betaRun it on Osyrin: osyrin.com

Reference / Testing

Holding a test's world open

osy test [path] --test <id> --hold [--no-open] [--json]

Runs one test and, pass or fail, keeps the world it built serving on your machine — its data and its app version — and opens it in your browser signed in as the test's principal, with no password. Ctrl-C discards it.

stabletestinglocalcli

Summary#

A test builds a world — a fixture's rows, everything the test then wrote — and then throws it away. osy test --hold keeps it. It runs exactly ONE test and, when the verdict is in, leaves that test's throwaway copy of your app serving on the local platform, at an address of its own, and opens your browser on it signed in as whoever the test was. Click through it, look at it, feel how it responds. Ctrl-C ends it and the copy is discarded.

It is the way to see an app full of data without putting that data anywhere real: seed code that lives under tests/ is never compiled into what osy compile deploys, and a held world is a test's own copy, gone when you stop.

Signature#

osy test [path] --test <id> --hold [--no-open] [--json]

Description#

Which test does it hold?#

Exactly one. --hold refuses a selection that matches more than one test — listing the ids of what it matched — and one that matches none, before anything is compiled. Name the test by its id (file::fixture::name, the form every osy test report hands back):

osy test --test 'tests/hold.test.osy::Floor::a_filled_desk_to_click_through' --hold

--filter and --file work too, as long as they narrow to one test.

Who is the browser signed in as?#

Whoever the test WAS, at its outermost level:

The session is minted locally, over the instance's own operator key, for that principal in that copy — there is no password and no second-step code to type. That door exists only on a local platform (osyrin dev) and only for a copy --hold is holding right now; a deployed server refuses it by name. What it skips is the login page, never authorization: everything you see is what that principal's own security { } rules let them see.

What does it print?#

The test's verdict first, exactly as a normal run prints it — then:

⏸ HELD — the test passed. Its branch is serving at http://helpdesk--held-3bf1df3f.localhost:8100/
  signed in as Ines — a session minted locally over this instance's operator key: no password, no second step
  open: http://helpdesk--held-3bf1df3f.localhost:8100/api/osy-test/held-sign-in#…
  simulated latency: none — requests are answered at local speed
  Ctrl-C stops it and discards the branch (so does the local platform idling out). Only this machine can reach it.

The first address is the held copy itself — open it in another browser and you are signed out. The open: link is the one your browser was sent to: it signs that tab in and lands on the app's front page. --no-open prints both and opens nothing.

The open: link is always printed on one line, whole, however narrow the terminal — copy the line as it is. An app whose own sign-in refuses a tab that is not signed in (Studio's "This tab is not signed in" is one) is telling you the link you opened carried no session: the bare address, or a link cut short.

signed in as names the principal as the test declared it (principal Ines => …) when it can, and otherwise the account's email or display name.

The held copy has a host of its own (<app>--held-<8 hex>.localhost), so it is a separate origin from your live app: signing into one never signs you into, or out of, the other.

Does a failing test hold?#

Yes — the world a red test left behind is usually the one most worth looking at. The verdict is printed as a failure, the hold line says FAILED — held anyway, and when you stop it the command exits non-zero, exactly as the run would have without --hold. A test that did not run at all (a [Skip], or a capability your machine lacks) builds no world, so there is nothing to hold and the command says so and exits non-zero.

How does it end?#

Three ways, and each discards the copy — its databases are dropped:

  • Ctrl-C (or closing the terminal, or kill): the CLI ends the hold, then waits until the address stops answering and says so — ✓ released — … no longer answers.
  • The local platform idling out. A held test does not keep the server alive: what you DO in the held copy counts as activity, the hold itself does not, so the platform's usual idle ceiling still applies. When it is reached the CLI prints ⏹ released — the local platform is stopping….
  • osy stop, which ends the local platform and everything it was holding.

How do I feel it at a distance?#

A local platform answers in a few milliseconds, which hides how many requests a page waits on in a row. OSY_SIMULATED_LATENCY_MS makes it wait that long before every request — the round trip a real network adds — so clicking through the held copy feels like using it from far away.

The platform reads the variable when it starts, not per command. Setting it in the shell of an osy test --hold against a platform that is already running does nothing — and the CLI says so, naming both values. Stop the platform first, so the command starts a fresh one that carries it:

osy stop
OSY_SIMULATED_LATENCY_MS=40 osy test --test 'tests/hold.test.osy::Floor::a_filled_desk_to_click_through' --hold

The hold line always says which delay the serving platform is actually applying (simulated latency: 40 ms in front of every request, or none).

Who can reach it?#

Only this machine. A local platform listens on loopback, and a held copy additionally refuses any request that does not come from loopback. Its address stops answering the moment the hold ends — it never falls through to your live app.

Scripting it#

With --json, standard output is the run's event stream — the test's verdict, then a held event carrying url, branchId, passed, principal and simulatedLatencyMs — and the human lines above (including the open: link) go to standard error. The stream stays open until the hold ends, so a script reads up to held, does its work against url, and sends the process SIGTERM (or SIGINT) to end it.

See also#

Running tests locally — osy test itself, and the other ways to choose what runs.

runas and [runas(Name)] test attribute and principal selectors — how a test becomes somebody, which is who the held browser is.

Running a local platform — the local platform a held copy is served from, and its idle ceiling.

Stopping the local platform — osy stop.

Related

Running tests locally

Runs your app's tests against a Platform on your own machine — no account, no network, no setup beyond a running local…

runas

Runs a block as a given principal, so security rules apply exactly as they would for that user. It is how you test that…

[runas(Name)] test attribute and principal selectors

A test runs deny-all as an anonymous principal, so to read or write real data it must act AS a seeded `[Principal]`…

Ui — drive the app's UI from a test

Drive the real UI from a test: navigate to a route, click what a person would click, and assert on what the screen…

Running a local platform

Runs a full platform on your own machine — its own database, no account, no cloud, reachable only from your computer…

Stopping the local platform

Stops the local platform serving your project — the one the build-and-test loop starts on demand. Its database stops…