Skip to content

[test] store/admin has zero tests — and now owns every destructive operator control #280

Description

@serge-ivo

The gap

store/admin has zero tests — and as of 66fcc23 (#38/#41) it holds the most destructive controls in the product: suspend a user, unpublish or delete an agent, cancel an instance, change roles, revoke keys.

This needs no new infrastructure. vitest.config.ts already globs store/*/src/**/*.test.ts in its UNIT_TESTS project, with a comment noting the console was once missing from that glob so anything added there "would have passed locally and never run in CI". The harness is there; admin simply has nothing to run.

store/console shows the established pattern: 9 test files, all .test.ts (never .tsx), all pure logic extracted into lib/*.tssurfaces, workInFlight, identity, triggerSchedule, teamwork. Zero render any component.

What to test

Follow that pattern — extract the decisions out of JSX into pure modules, then test the modules:

  • Runtime status derivation. Four states, not two: live (relay socket) / offline / unknown (the list's fan-out budget returns null past 50) / no-runner-ever-registered. The bug this prevents is rendering null as offline — the DB's instance_runtime_nodes.status is never cleared on an unclean disconnect and already lies in the other direction, so a second wrong answer here is how an operator kills a healthy machine.
  • force is never sent on the first attempt. The 409 must be surfaced with its live-subscriber count before forcing is offered at all.
  • Echo gates: delete requires the slug, key revoke requires an explicit provider, suspend requires the login. Assert that a mismatched or empty echo cannot produce a request.
  • Key revoke is per-provider. An omitted provider must never widen to "all keys".
  • Self-targeting is refused — self-suspend and self-demote both lock the only operator out.
  • Filter + pagination state — the page and the COUNT share one predicate server-side; assert the client can't send a filter to one and not the other.

Acceptance

  • The guards above are covered by pure unit tests that run in the existing suite with no new dependency.
  • Each test comment names the failure it prevents (repo convention).
  • Logic needed for a test is moved to src/lib/*.ts rather than tested through a component.

Related: #38, #41. Sibling gap for JSX-resident logic: see the component-testing issue.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions