@fuzdev/fuz_app 0.65.0 → 0.66.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/actions/CLAUDE.md +65 -86
- package/dist/actions/action_codegen.d.ts +1 -1
- package/dist/actions/action_codegen.js +1 -1
- package/dist/actions/action_event_data.d.ts +1 -1
- package/dist/auth/CLAUDE.md +83 -104
- package/dist/auth/audit_log_schema.js +2 -2
- package/dist/auth/daemon_token_middleware.d.ts +15 -5
- package/dist/auth/daemon_token_middleware.d.ts.map +1 -1
- package/dist/auth/daemon_token_middleware.js +24 -15
- package/dist/auth/invite_queries.d.ts +17 -7
- package/dist/auth/invite_queries.d.ts.map +1 -1
- package/dist/auth/invite_queries.js +19 -8
- package/dist/auth/signup_routes.d.ts +47 -1
- package/dist/auth/signup_routes.d.ts.map +1 -1
- package/dist/auth/signup_routes.js +103 -52
- package/dist/env/resolve.d.ts +44 -7
- package/dist/env/resolve.d.ts.map +1 -1
- package/dist/env/resolve.js +94 -27
- package/dist/http/CLAUDE.md +47 -52
- package/dist/http/jsonrpc.d.ts +23 -7
- package/dist/http/jsonrpc.d.ts.map +1 -1
- package/dist/http/jsonrpc.js +19 -3
- package/dist/http/surface.d.ts +9 -2
- package/dist/http/surface.d.ts.map +1 -1
- package/dist/runtime/mock.d.ts +1 -1
- package/dist/runtime/mock.js +1 -1
- package/dist/testing/CLAUDE.md +659 -511
- package/dist/testing/admin_integration.d.ts +5 -5
- package/dist/testing/admin_integration.d.ts.map +1 -1
- package/dist/testing/admin_integration.js +95 -39
- package/dist/testing/app_server.d.ts +16 -1
- package/dist/testing/app_server.d.ts.map +1 -1
- package/dist/testing/app_server.js +18 -3
- package/dist/testing/audit_completeness.d.ts +7 -5
- package/dist/testing/audit_completeness.d.ts.map +1 -1
- package/dist/testing/audit_completeness.js +5 -9
- package/dist/testing/bootstrap_success.js +2 -2
- package/dist/testing/cross_backend/backend_config.d.ts +113 -0
- package/dist/testing/cross_backend/backend_config.d.ts.map +1 -0
- package/dist/testing/cross_backend/backend_config.js +1 -0
- package/dist/testing/cross_backend/bench/bench_report.d.ts +46 -0
- package/dist/testing/cross_backend/bench/bench_report.d.ts.map +1 -0
- package/dist/testing/cross_backend/bench/bench_report.js +83 -0
- package/dist/testing/cross_backend/bench/run_cross_impl_bench.d.ts +44 -0
- package/dist/testing/cross_backend/bench/run_cross_impl_bench.d.ts.map +1 -0
- package/dist/testing/cross_backend/bench/run_cross_impl_bench.js +38 -0
- package/dist/testing/cross_backend/bench/scenario.d.ts +57 -0
- package/dist/testing/cross_backend/bench/scenario.d.ts.map +1 -0
- package/dist/testing/cross_backend/bench/scenario.js +28 -0
- package/dist/testing/cross_backend/bootstrap_backend.d.ts +41 -0
- package/dist/testing/cross_backend/bootstrap_backend.d.ts.map +1 -0
- package/dist/testing/cross_backend/bootstrap_backend.js +34 -0
- package/dist/testing/cross_backend/build_test_backend_paths.d.ts +24 -0
- package/dist/testing/cross_backend/build_test_backend_paths.d.ts.map +1 -0
- package/dist/testing/cross_backend/build_test_backend_paths.js +33 -0
- package/dist/testing/cross_backend/capabilities.d.ts +3 -2
- package/dist/testing/cross_backend/capabilities.d.ts.map +1 -1
- package/dist/testing/cross_backend/default_backend_configs.d.ts +122 -0
- package/dist/testing/cross_backend/default_backend_configs.d.ts.map +1 -0
- package/dist/testing/cross_backend/default_backend_configs.js +111 -0
- package/dist/testing/cross_backend/default_secrets.d.ts +40 -0
- package/dist/testing/cross_backend/default_secrets.d.ts.map +1 -0
- package/dist/testing/cross_backend/default_secrets.js +39 -0
- package/dist/testing/cross_backend/default_spine_surface.d.ts +64 -0
- package/dist/testing/cross_backend/default_spine_surface.d.ts.map +1 -0
- package/dist/testing/cross_backend/default_spine_surface.js +121 -0
- package/dist/testing/cross_backend/setup.d.ts +270 -34
- package/dist/testing/cross_backend/setup.d.ts.map +1 -1
- package/dist/testing/cross_backend/setup.js +495 -15
- package/dist/testing/cross_backend/spawn_backend.d.ts +58 -0
- package/dist/testing/cross_backend/spawn_backend.d.ts.map +1 -0
- package/dist/testing/cross_backend/spawn_backend.js +229 -0
- package/dist/testing/cross_backend/spine_stub_backend_config.d.ts +66 -0
- package/dist/testing/cross_backend/spine_stub_backend_config.d.ts.map +1 -0
- package/dist/testing/cross_backend/spine_stub_backend_config.js +49 -0
- package/dist/testing/cross_backend/sse_round_trip.d.ts +37 -0
- package/dist/testing/cross_backend/sse_round_trip.d.ts.map +1 -0
- package/dist/testing/cross_backend/sse_round_trip.js +137 -0
- package/dist/testing/cross_backend/standard.d.ts +96 -0
- package/dist/testing/cross_backend/standard.d.ts.map +1 -0
- package/dist/testing/cross_backend/standard.js +49 -0
- package/dist/testing/cross_backend/testing_reset_actions.d.ts +171 -0
- package/dist/testing/cross_backend/testing_reset_actions.d.ts.map +1 -0
- package/dist/testing/cross_backend/testing_reset_actions.js +213 -0
- package/dist/testing/cross_backend/testing_server_bun.d.ts +5 -0
- package/dist/testing/cross_backend/testing_server_bun.d.ts.map +1 -0
- package/dist/testing/cross_backend/testing_server_bun.js +59 -0
- package/dist/testing/cross_backend/testing_server_core.d.ts +140 -0
- package/dist/testing/cross_backend/testing_server_core.d.ts.map +1 -0
- package/dist/testing/cross_backend/testing_server_core.js +68 -0
- package/dist/testing/cross_backend/testing_server_deno.d.ts +5 -0
- package/dist/testing/cross_backend/testing_server_deno.d.ts.map +1 -0
- package/dist/testing/cross_backend/testing_server_deno.js +37 -0
- package/dist/testing/cross_backend/testing_server_node.d.ts +5 -0
- package/dist/testing/cross_backend/testing_server_node.d.ts.map +1 -0
- package/dist/testing/cross_backend/testing_server_node.js +50 -0
- package/dist/testing/cross_backend/ts_spine_backend_config.d.ts +72 -0
- package/dist/testing/cross_backend/ts_spine_backend_config.d.ts.map +1 -0
- package/dist/testing/cross_backend/ts_spine_backend_config.js +112 -0
- package/dist/testing/cross_backend/ws_round_trip.d.ts +35 -0
- package/dist/testing/cross_backend/ws_round_trip.d.ts.map +1 -0
- package/dist/testing/cross_backend/ws_round_trip.js +113 -0
- package/dist/testing/data_exposure.d.ts +4 -6
- package/dist/testing/data_exposure.d.ts.map +1 -1
- package/dist/testing/data_exposure.js +1 -5
- package/dist/testing/db_entities.d.ts +18 -7
- package/dist/testing/db_entities.d.ts.map +1 -1
- package/dist/testing/db_entities.js +18 -7
- package/dist/testing/integration.d.ts +27 -6
- package/dist/testing/integration.d.ts.map +1 -1
- package/dist/testing/integration.js +93 -58
- package/dist/testing/round_trip.d.ts +4 -5
- package/dist/testing/round_trip.d.ts.map +1 -1
- package/dist/testing/round_trip.js +1 -5
- package/dist/testing/rpc_helpers.d.ts +10 -4
- package/dist/testing/rpc_helpers.d.ts.map +1 -1
- package/dist/testing/rpc_helpers.js +1 -1
- package/dist/testing/rpc_round_trip.d.ts +5 -5
- package/dist/testing/rpc_round_trip.d.ts.map +1 -1
- package/dist/testing/rpc_round_trip.js +1 -5
- package/dist/testing/sse_round_trip.d.ts.map +1 -1
- package/dist/testing/sse_round_trip.js +1 -68
- package/dist/testing/standard.d.ts +4 -5
- package/dist/testing/standard.d.ts.map +1 -1
- package/dist/testing/stubs.d.ts +10 -3
- package/dist/testing/stubs.d.ts.map +1 -1
- package/dist/testing/stubs.js +9 -2
- package/dist/testing/testing_rate_limiter.d.ts +59 -0
- package/dist/testing/testing_rate_limiter.d.ts.map +1 -0
- package/dist/testing/testing_rate_limiter.js +74 -0
- package/dist/testing/transports/bootstrap.d.ts +52 -0
- package/dist/testing/transports/bootstrap.d.ts.map +1 -0
- package/dist/testing/transports/bootstrap.js +70 -0
- package/dist/testing/transports/fetch_transport.d.ts +81 -0
- package/dist/testing/transports/fetch_transport.d.ts.map +1 -0
- package/dist/testing/transports/fetch_transport.js +74 -0
- package/dist/testing/transports/sse_frame_reader.d.ts +41 -0
- package/dist/testing/transports/sse_frame_reader.d.ts.map +1 -0
- package/dist/testing/transports/sse_frame_reader.js +84 -0
- package/dist/testing/transports/sse_transport.d.ts +54 -0
- package/dist/testing/transports/sse_transport.d.ts.map +1 -0
- package/dist/testing/transports/sse_transport.js +51 -0
- package/dist/testing/transports/ws_client.d.ts +108 -0
- package/dist/testing/transports/ws_client.d.ts.map +1 -0
- package/dist/testing/transports/ws_client.js +56 -0
- package/dist/testing/transports/ws_transport.d.ts +43 -0
- package/dist/testing/transports/ws_transport.d.ts.map +1 -0
- package/dist/testing/transports/ws_transport.js +169 -0
- package/dist/testing/ws_round_trip.d.ts +21 -103
- package/dist/testing/ws_round_trip.d.ts.map +1 -1
- package/dist/testing/ws_round_trip.js +42 -40
- package/dist/ui/CLAUDE.md +5 -3
- package/dist/ui/MenuLink.svelte +16 -16
- package/dist/ui/MenuLink.svelte.d.ts +13 -4
- package/dist/ui/MenuLink.svelte.d.ts.map +1 -1
- package/package.json +7 -1
- package/dist/testing/transports/surface_source.d.ts +0 -51
- package/dist/testing/transports/surface_source.d.ts.map +0 -1
- package/dist/testing/transports/surface_source.js +0 -19
|
@@ -1,32 +1,15 @@
|
|
|
1
1
|
import '../assert_dev_env.js';
|
|
2
|
-
|
|
3
|
-
* Per-test fixture protocol shared by in-process and cross-process
|
|
4
|
-
* transports.
|
|
5
|
-
*
|
|
6
|
-
* Each standard suite body takes a required
|
|
7
|
-
* `setup_test: () => Promise<TestFixture>` callback and invokes it once
|
|
8
|
-
* per test. The fixture carries everything a test needs to fire requests
|
|
9
|
-
* and assert on a single bootstrapped keeper account — transport,
|
|
10
|
-
* account / actor identity, three header builders, a multi-account mint
|
|
11
|
-
* factory, and (in-process only) the in-memory keyring + raw backend.
|
|
12
|
-
*
|
|
13
|
-
* `default_in_process_setup(options)` wraps `create_test_app` into the
|
|
14
|
-
* `SetupTest` contract. The cross-process sibling
|
|
15
|
-
* (`default_cross_process_setup`) lands alongside the spawn-a-backend
|
|
16
|
-
* transport plumbing — it implements the same contract by spawning a
|
|
17
|
-
* binary and bootstrapping over real HTTP.
|
|
18
|
-
*
|
|
19
|
-
* @module
|
|
20
|
-
*/
|
|
21
|
-
import type { Uuid } from '@fuzdev/fuz_util/id.js';
|
|
2
|
+
import { Uuid } from '@fuzdev/fuz_util/id.js';
|
|
22
3
|
import type { Keyring } from '../../auth/keyring.js';
|
|
23
4
|
import type { RouteSpec } from '../../http/route_spec.js';
|
|
24
5
|
import type { AppServerContext, BootstrapServerOptions } from '../../server/app_server.js';
|
|
25
6
|
import type { SessionOptions } from '../../auth/session_cookie.js';
|
|
26
7
|
import { type CreateTestAppOptions, type SuiteAppOptions, type TestAccount, type TestAppServer } from '../app_server.js';
|
|
27
|
-
import { type
|
|
8
|
+
import { type RpcEndpointsSuiteOption } from '../rpc_helpers.js';
|
|
28
9
|
import { type BackendCapabilities } from './capabilities.js';
|
|
29
|
-
import type {
|
|
10
|
+
import type { AppSurfaceSpec } from '../../http/surface.js';
|
|
11
|
+
import { type FetchTransport } from '../transports/fetch_transport.js';
|
|
12
|
+
import type { BackendHandle } from './spawn_backend.js';
|
|
30
13
|
/**
|
|
31
14
|
* Options for `TestFixture.create_account` — mints an additional
|
|
32
15
|
* bootstrapped account alongside the keeper. Matches the existing
|
|
@@ -46,13 +29,88 @@ export interface CreateTestAccountOptions {
|
|
|
46
29
|
* crossing module boundaries.
|
|
47
30
|
*/
|
|
48
31
|
export type TestAccountFixture = TestAccount;
|
|
32
|
+
/**
|
|
33
|
+
* Spec for a bootstrap-time secondary account seeded alongside the
|
|
34
|
+
* keeper by `_testing_reset` (cross-process) or `create_test_app`
|
|
35
|
+
* (in-process). Used for accounts whose required roles aren't
|
|
36
|
+
* admin-grantable via offer/accept — primarily `ROLE_KEEPER` (whose
|
|
37
|
+
* `RoleSpec.grant_paths` is bootstrap-only), where the only way to
|
|
38
|
+
* land the grant is at the bootstrap-equivalent setup step.
|
|
39
|
+
*
|
|
40
|
+
* For admin-grantable roles, prefer `fixture.create_account({roles})`
|
|
41
|
+
* — that goes through the production offer/accept handlers and
|
|
42
|
+
* observes audit + WS fan-out. `extra_accounts` is the cradle-only
|
|
43
|
+
* bypass; the runtime has no equivalent action.
|
|
44
|
+
*/
|
|
45
|
+
export interface ExtraAccountSpec {
|
|
46
|
+
readonly username: string;
|
|
47
|
+
readonly password_value?: string;
|
|
48
|
+
readonly roles: ReadonlyArray<string>;
|
|
49
|
+
}
|
|
50
|
+
/** Bootstrap-time-seeded secondary account exposed on the fixture. */
|
|
51
|
+
export interface ExtraAccountFixture {
|
|
52
|
+
readonly account: {
|
|
53
|
+
readonly id: Uuid;
|
|
54
|
+
readonly username: string;
|
|
55
|
+
};
|
|
56
|
+
readonly actor: {
|
|
57
|
+
readonly id: Uuid;
|
|
58
|
+
};
|
|
59
|
+
readonly api_token: string;
|
|
60
|
+
readonly session_cookie: string;
|
|
61
|
+
readonly create_session_headers: (extra?: Record<string, string>) => Record<string, string>;
|
|
62
|
+
readonly create_bearer_headers: (extra?: Record<string, string>) => Record<string, string>;
|
|
63
|
+
}
|
|
49
64
|
/**
|
|
50
65
|
* Fields shared by every `TestFixture` regardless of transport. The
|
|
51
66
|
* discriminated union below adds in-process-only fields conditionally.
|
|
67
|
+
*
|
|
68
|
+
* **Keeper ≠ admin.** `fixture.account` / `fixture.actor` refer to the
|
|
69
|
+
* **fresh keeper** seeded per test. The keeper account holds
|
|
70
|
+
* `ROLE_KEEPER` + `ROLE_ADMIN` by default — matching the production
|
|
71
|
+
* `bootstrap_account` flow. The `ROLE_KEEPER` role itself does *not*
|
|
72
|
+
* grant admin reach; the bootstrap account just happens to hold both as
|
|
73
|
+
* separate grants. Tests probing the keeper-vs-admin separation (e.g.
|
|
74
|
+
* "non-admin cannot list accounts") declare a secondary at setup-time
|
|
75
|
+
* via `extra_accounts: [{username, roles: [ROLE_KEEPER]}]` and read it
|
|
76
|
+
* from `fixture.extra_accounts[username]`.
|
|
52
77
|
*/
|
|
53
78
|
export interface TestFixtureBase {
|
|
54
|
-
/**
|
|
55
|
-
|
|
79
|
+
/**
|
|
80
|
+
* Transport for this test's HTTP requests. Typed as `FetchTransport`
|
|
81
|
+
* so cross-process tests can call `transport.cookies()` for WS upgrade
|
|
82
|
+
* cookie threading; in-process provides a no-op `cookies()` returning
|
|
83
|
+
* `[]` (in-process tests construct cookies via `create_session_headers`
|
|
84
|
+
* directly and don't thread WS through this channel).
|
|
85
|
+
*/
|
|
86
|
+
readonly transport: FetchTransport;
|
|
87
|
+
/**
|
|
88
|
+
* Build a brand-new `FetchTransport` with an empty cookie jar pinned to
|
|
89
|
+
* the same backend. Use for unauthed assertions (`no cookie on protected
|
|
90
|
+
* route returns 401`, bearer-only calls expected to fall through to the
|
|
91
|
+
* unauthenticated path) where the per-test session cookie carried by
|
|
92
|
+
* `transport`'s jar would otherwise leak into the request and convert a
|
|
93
|
+
* 401 into a 200.
|
|
94
|
+
*
|
|
95
|
+
* **New-per-call, not memoized** — each invocation returns a fresh
|
|
96
|
+
* instance. If a call mutates the jar (e.g. an unauthed login attempt
|
|
97
|
+
* returning `Set-Cookie`) it can't pollute sibling calls.
|
|
98
|
+
*
|
|
99
|
+
* Pass `origin: null` for bearer-only probes that must look like
|
|
100
|
+
* non-browser callers — the auth middleware silently discards bearer
|
|
101
|
+
* credentials when `Origin`/`Referer` is present, so a default
|
|
102
|
+
* `Origin: <base_url>` would convert "bearer + no Origin → 200" into
|
|
103
|
+
* "bearer + Origin → discarded → 401" cross-process. In-process the
|
|
104
|
+
* wrapper is stateless and the option is a no-op (no auto-Origin to
|
|
105
|
+
* suppress).
|
|
106
|
+
*
|
|
107
|
+
* In-process this is functionally identical to `transport` (the wrapper's
|
|
108
|
+
* `cookies(): []` is a no-op already); cross-process the returned
|
|
109
|
+
* transport starts with an empty jar at the same `base_url`.
|
|
110
|
+
*/
|
|
111
|
+
readonly fresh_transport: (options?: {
|
|
112
|
+
readonly origin?: string | null;
|
|
113
|
+
}) => FetchTransport;
|
|
56
114
|
/** The freshly-bootstrapped keeper account. */
|
|
57
115
|
readonly account: {
|
|
58
116
|
readonly id: Uuid;
|
|
@@ -75,6 +133,13 @@ export interface TestFixtureBase {
|
|
|
75
133
|
* channel.
|
|
76
134
|
*/
|
|
77
135
|
readonly create_account: (options?: CreateTestAccountOptions) => Promise<TestAccountFixture>;
|
|
136
|
+
/**
|
|
137
|
+
* Bootstrap-time-seeded secondaries, keyed by their declared
|
|
138
|
+
* `username`. Populated from the `extra_accounts` option passed to
|
|
139
|
+
* `default_in_process_setup` / `default_cross_process_setup`. Empty
|
|
140
|
+
* for suites that don't declare any.
|
|
141
|
+
*/
|
|
142
|
+
readonly extra_accounts: Readonly<Record<string, ExtraAccountFixture>>;
|
|
78
143
|
}
|
|
79
144
|
/**
|
|
80
145
|
* The per-test bundle returned by `SetupTest`. Every Tier 1 suite body
|
|
@@ -103,11 +168,16 @@ export type TestFixture = (TestFixtureBase & {
|
|
|
103
168
|
*/
|
|
104
169
|
readonly keyring: Keyring;
|
|
105
170
|
/**
|
|
106
|
-
* Raw backend access (`deps.db`, etc.) — in-process only. Used
|
|
107
|
-
*
|
|
108
|
-
* `
|
|
109
|
-
*
|
|
110
|
-
* `
|
|
171
|
+
* Raw backend access (`deps.db`, etc.) — in-process only. Used
|
|
172
|
+
* by the origin-verification cookie-composition sites in
|
|
173
|
+
* `describe_standard_integration_tests`. Tests that need a
|
|
174
|
+
* direct DB role_grant seed at the in-process layer reach for
|
|
175
|
+
* `create_test_role_grant_direct` from `db_entities.ts`; that
|
|
176
|
+
* helper bypasses the consent flow on purpose for query-level
|
|
177
|
+
* (`*.db.test.ts`) tests and has no cross-process analog.
|
|
178
|
+
* Cross-process tests grant additional roles via
|
|
179
|
+
* `fixture.create_account({roles})` (offer/accept) or
|
|
180
|
+
* `extra_accounts` (bootstrap-time bypass).
|
|
111
181
|
*/
|
|
112
182
|
readonly backend_internals: TestAppServer;
|
|
113
183
|
}) | (TestFixtureBase & {
|
|
@@ -120,6 +190,21 @@ export type TestFixture = (TestFixtureBase & {
|
|
|
120
190
|
* a fresh per-test bundle on each call.
|
|
121
191
|
*/
|
|
122
192
|
export type SetupTest = () => Promise<TestFixture>;
|
|
193
|
+
/**
|
|
194
|
+
* Options for `default_in_process_setup`. Extends `CreateTestAppOptions`
|
|
195
|
+
* with the same `extra_accounts` slot the cross-process variant accepts
|
|
196
|
+
* — both transports observe the same bootstrap-time secondary set so
|
|
197
|
+
* suite bodies can read `fixture.extra_accounts[username]` uniformly.
|
|
198
|
+
*/
|
|
199
|
+
export interface InProcessSetupOptions extends CreateTestAppOptions {
|
|
200
|
+
/**
|
|
201
|
+
* Additional accounts seeded at this transport's bootstrap-equivalent
|
|
202
|
+
* step. See `ExtraAccountSpec` for the cradle-only-bypass rationale.
|
|
203
|
+
* Most suites pass `undefined` / `[]`; the `ROLE_KEEPER` probe (in
|
|
204
|
+
* `describe_standard_admin_integration_tests`) is the primary user.
|
|
205
|
+
*/
|
|
206
|
+
readonly extra_accounts?: ReadonlyArray<ExtraAccountSpec>;
|
|
207
|
+
}
|
|
123
208
|
/**
|
|
124
209
|
* Build a `SetupTest` that creates a fresh `TestApp` per call via
|
|
125
210
|
* `create_test_app` and projects it into the `TestFixture` shape.
|
|
@@ -127,14 +212,157 @@ export type SetupTest = () => Promise<TestFixture>;
|
|
|
127
212
|
* Same factory inputs `create_test_app` already takes — this helper
|
|
128
213
|
* is a projection layer, not a new lifecycle. fuz_app's own `src/test/`
|
|
129
214
|
* and consumer suites pass `default_in_process_setup({...factory_inputs})`
|
|
130
|
-
* in place of the old per-suite factory-input bundle.
|
|
215
|
+
* in place of the old per-suite factory-input bundle. The `extra_accounts`
|
|
216
|
+
* slot (see `InProcessSetupOptions`) seeds bootstrap-time secondaries
|
|
217
|
+
* directly via `create_test_account_with_credentials` against the same
|
|
218
|
+
* DB the keeper just landed on — mirrors the cross-process
|
|
219
|
+
* `_testing_reset` cradle so suite bodies read
|
|
220
|
+
* `fixture.extra_accounts[username]` uniformly regardless of transport.
|
|
131
221
|
*
|
|
132
222
|
* The describe-level `auth_integration_truncate_tables` / pglite WASM
|
|
133
223
|
* cache lifecycle stays in `create_pglite_factory` / `create_describe_db`
|
|
134
224
|
* (`testing/db.js`) — `default_in_process_setup` doesn't manage db state
|
|
135
225
|
* beyond what `create_test_app` already does.
|
|
136
226
|
*/
|
|
137
|
-
export declare const default_in_process_setup: (options:
|
|
227
|
+
export declare const default_in_process_setup: (options: InProcessSetupOptions) => SetupTest;
|
|
228
|
+
/**
|
|
229
|
+
* Cross-process backend handle enriched with the bootstrapped keeper's
|
|
230
|
+
* captured credentials. Consumers compose this in vitest's
|
|
231
|
+
* `globalSetup`:
|
|
232
|
+
*
|
|
233
|
+
* ```ts
|
|
234
|
+
* const handle = await spawn_backend(config);
|
|
235
|
+
* const keeper_transport = create_fetch_transport({base_url: config.base_url});
|
|
236
|
+
* const keeper = await bootstrap({transport: keeper_transport, config});
|
|
237
|
+
* const bootstrapped: BootstrappedBackendHandle = {
|
|
238
|
+
* ...handle,
|
|
239
|
+
* keeper_transport,
|
|
240
|
+
* keeper_account: keeper.account,
|
|
241
|
+
* keeper_actor: keeper.actor,
|
|
242
|
+
* keeper_cookies: keeper.cookies,
|
|
243
|
+
* };
|
|
244
|
+
* ```
|
|
245
|
+
*
|
|
246
|
+
* `default_cross_process_setup(bootstrapped, options)` reads from this
|
|
247
|
+
* shape — the per-test fixture closes over the keeper credentials so
|
|
248
|
+
* cross-process tests can drive admin-RPC / audit-observer flows
|
|
249
|
+
* against the long-lived bootstrapped admin alongside the per-test
|
|
250
|
+
* signup+login account.
|
|
251
|
+
*/
|
|
252
|
+
export interface BootstrappedBackendHandle extends BackendHandle {
|
|
253
|
+
/** Transport carrying the keeper session cookie + cookie jar. */
|
|
254
|
+
readonly keeper_transport: FetchTransport;
|
|
255
|
+
/** Keeper account JSON captured from `POST /bootstrap`. */
|
|
256
|
+
readonly keeper_account: {
|
|
257
|
+
readonly id: Uuid;
|
|
258
|
+
readonly username: string;
|
|
259
|
+
};
|
|
260
|
+
/** Keeper actor JSON captured from `POST /bootstrap`. */
|
|
261
|
+
readonly keeper_actor: {
|
|
262
|
+
readonly id: Uuid;
|
|
263
|
+
};
|
|
264
|
+
/** Raw keeper `Set-Cookie` values — thread into `ws_transport` for keeper-authenticated WS upgrades. */
|
|
265
|
+
readonly keeper_cookies: ReadonlyArray<string>;
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* `BootstrappedBackendHandle` minus the live `child` / `teardown` references
|
|
269
|
+
* that only make sense in the `globalSetup` process. The cross-process
|
|
270
|
+
* `provide`/`inject` path strips them on serialization, and the per-test
|
|
271
|
+
* helpers (`mint_account`, `fire_testing_reset`, `default_cross_process_setup`)
|
|
272
|
+
* never read either field — so the test-worker view of the handle has this
|
|
273
|
+
* shape. Also the return type of `reconstruct_bootstrapped_handle`.
|
|
274
|
+
*/
|
|
275
|
+
export type ReconstructedBootstrappedBackendHandle = Omit<BootstrappedBackendHandle, 'child' | 'teardown'>;
|
|
276
|
+
/**
|
|
277
|
+
* Serializable subset of {@link BootstrappedBackendHandle} suitable for
|
|
278
|
+
* vitest's `project.provide()` — vitest 4 hard-rejects non-serializable
|
|
279
|
+
* values, so the live `child: ChildProcess` + `teardown: () => Promise<void>`
|
|
280
|
+
* + `keeper_transport: FetchTransport` (closure) must stay in the
|
|
281
|
+
* `globalSetup` process. The handful of fields tests actually read
|
|
282
|
+
* (`config`, `daemon_token`, `keeper_account`, `keeper_actor`,
|
|
283
|
+
* `keeper_cookies`) round-trip through structured clone fine.
|
|
284
|
+
*
|
|
285
|
+
* `globalSetup` calls {@link serialize_bootstrapped_handle} before
|
|
286
|
+
* `project.provide`; test files call {@link reconstruct_bootstrapped_handle}
|
|
287
|
+
* on the injected value to rebuild a usable handle (without `child` /
|
|
288
|
+
* `teardown` — lifecycle stays with `globalSetup`).
|
|
289
|
+
*/
|
|
290
|
+
export interface SerializableBootstrappedBackendHandle {
|
|
291
|
+
readonly config: BackendHandle['config'];
|
|
292
|
+
readonly daemon_token: BackendHandle['daemon_token'];
|
|
293
|
+
readonly keeper_account: BootstrappedBackendHandle['keeper_account'];
|
|
294
|
+
readonly keeper_actor: BootstrappedBackendHandle['keeper_actor'];
|
|
295
|
+
readonly keeper_cookies: ReadonlyArray<string>;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Strip the non-serializable members so the result can be passed to
|
|
299
|
+
* vitest's `project.provide`. Call in `globalSetup` before provide.
|
|
300
|
+
*/
|
|
301
|
+
export declare const serialize_bootstrapped_handle: (handle: BootstrappedBackendHandle) => SerializableBootstrappedBackendHandle;
|
|
302
|
+
/**
|
|
303
|
+
* Rebuild a usable handle from the serialized subset. Synthesizes a
|
|
304
|
+
* fresh {@link FetchTransport} primed with the keeper's `Set-Cookie`
|
|
305
|
+
* values so `_testing_reset` and other keeper-authenticated calls work.
|
|
306
|
+
* The returned shape omits `child` and `teardown` — lifecycle stays
|
|
307
|
+
* with `globalSetup`; tests that try to teardown themselves wouldn't
|
|
308
|
+
* have a serializable reference anyway.
|
|
309
|
+
*/
|
|
310
|
+
export declare const reconstruct_bootstrapped_handle: (serialized: SerializableBootstrappedBackendHandle) => ReconstructedBootstrappedBackendHandle;
|
|
311
|
+
/** Options for `default_cross_process_setup`. */
|
|
312
|
+
export interface CrossProcessSetupOptions {
|
|
313
|
+
/**
|
|
314
|
+
* Additional roles to grant the fresh keeper on every per-test reset,
|
|
315
|
+
* *in addition to* the `[ROLE_KEEPER, ROLE_ADMIN]` defaults the
|
|
316
|
+
* `_testing_reset` action seeds. Cross-process mirror of in-process
|
|
317
|
+
* `extra_keeper_roles` on `default_in_process_suite_options`.
|
|
318
|
+
*
|
|
319
|
+
* Costs nothing extra per test — the `_testing_reset` action seeds
|
|
320
|
+
* the keeper in a single transaction regardless of how many roles
|
|
321
|
+
* are in the list.
|
|
322
|
+
*
|
|
323
|
+
* `ROLE_ADMIN` is already in the default set, so admin-suite
|
|
324
|
+
* consumers usually pass an empty / omitted array. Consumer-defined
|
|
325
|
+
* roles (e.g. `teacher`) are passed here when the keeper-acting test
|
|
326
|
+
* needs them.
|
|
327
|
+
*
|
|
328
|
+
* **Keeper ≠ admin.** Tests that need a *non-admin* secondary
|
|
329
|
+
* account with `ROLE_KEEPER` declare it via `extra_accounts` —
|
|
330
|
+
* `ROLE_KEEPER`'s `RoleSpec.grant_paths` is bootstrap-only, so it
|
|
331
|
+
* can only be granted at the test-binary bootstrap-equivalent step.
|
|
332
|
+
*/
|
|
333
|
+
readonly extra_keeper_roles?: ReadonlyArray<string>;
|
|
334
|
+
/**
|
|
335
|
+
* Bootstrap-time secondary accounts seeded alongside the keeper on
|
|
336
|
+
* every per-test reset. See `ExtraAccountSpec` for why this is a
|
|
337
|
+
* cradle-only bypass. The reset action seeds them in the same
|
|
338
|
+
* transaction as the keeper.
|
|
339
|
+
*/
|
|
340
|
+
readonly extra_accounts?: ReadonlyArray<ExtraAccountSpec>;
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Build a `SetupTest` against a spawned + bootstrapped backend.
|
|
344
|
+
*
|
|
345
|
+
* Per-test body (unconditional reset — fresh keeper every test):
|
|
346
|
+
*
|
|
347
|
+
* 1. Fire `_testing_reset` via the keeper's daemon-token channel. The
|
|
348
|
+
* action wipes auth tables, seeds a fresh keeper (with
|
|
349
|
+
* `extra_keeper_roles` applied), seeds any `extra_accounts`, and
|
|
350
|
+
* returns the new credentials.
|
|
351
|
+
* 2. Build the `TestFixture` closing over the new keeper as the
|
|
352
|
+
* fixture's primary `account` / `actor` (matching in-process
|
|
353
|
+
* semantics). `fixture.extra_accounts[username]` exposes any
|
|
354
|
+
* bootstrap-time secondaries.
|
|
355
|
+
* 3. `fixture.create_account()` mints additional *post-bootstrap*
|
|
356
|
+
* accounts via the production signup + login flow (invite → signup
|
|
357
|
+
* → login → token). Roles go through offer/accept (production
|
|
358
|
+
* consent path).
|
|
359
|
+
*
|
|
360
|
+
* No `reset: boolean` opt-in — every test runs against a freshly
|
|
361
|
+
* bootstrapped keeper. This converges in-process and cross-process
|
|
362
|
+
* keeper lifetimes; mutation-cascade tests (password change,
|
|
363
|
+
* revoke-all) and hardcoded-username signup tests work uniformly.
|
|
364
|
+
*/
|
|
365
|
+
export declare const default_cross_process_setup: (handle: ReconstructedBootstrappedBackendHandle, options?: CrossProcessSetupOptions) => SetupTest;
|
|
138
366
|
/**
|
|
139
367
|
* Consumer-facing options for `default_in_process_suite_options` — the
|
|
140
368
|
* minimal factory inputs both `default_in_process_setup` and
|
|
@@ -166,12 +394,20 @@ export interface DefaultInProcessSuiteOptions {
|
|
|
166
394
|
*/
|
|
167
395
|
extra_keeper_roles?: Array<string>;
|
|
168
396
|
/**
|
|
169
|
-
*
|
|
397
|
+
* Bootstrap-time secondary accounts seeded alongside the keeper. See
|
|
398
|
+
* `ExtraAccountSpec` for the cradle-only-bypass rationale. Same shape
|
|
399
|
+
* as the cross-process `extra_accounts` option — suites read seeded
|
|
400
|
+
* accounts from `fixture.extra_accounts[username]` regardless of
|
|
401
|
+
* transport.
|
|
402
|
+
*/
|
|
403
|
+
extra_accounts?: ReadonlyArray<ExtraAccountSpec>;
|
|
404
|
+
/**
|
|
405
|
+
* Pre-built `AppSurfaceSpec` — overrides the default which calls
|
|
170
406
|
* `create_test_app_surface_spec` against the same factory inputs.
|
|
171
407
|
* Pass when surface assembly needs fields outside the shared subset
|
|
172
408
|
* (e.g. `env_schema`, `event_specs`, `ws_endpoints`, `transform_middleware`).
|
|
173
409
|
*/
|
|
174
|
-
surface_source?:
|
|
410
|
+
surface_source?: AppSurfaceSpec;
|
|
175
411
|
}
|
|
176
412
|
/**
|
|
177
413
|
* Build the full in-process suite bundle in a single helper invocation.
|
|
@@ -206,7 +442,7 @@ export interface DefaultInProcessSuiteOptions {
|
|
|
206
442
|
*/
|
|
207
443
|
export declare const default_in_process_suite_options: <const O extends DefaultInProcessSuiteOptions>(options: O) => {
|
|
208
444
|
setup_test: SetupTest;
|
|
209
|
-
surface_source:
|
|
445
|
+
surface_source: AppSurfaceSpec;
|
|
210
446
|
capabilities: BackendCapabilities;
|
|
211
447
|
session_options: O["session_options"];
|
|
212
448
|
create_route_specs: O["create_route_specs"];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/setup.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/setup.ts"],"names":[],"mappings":"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"}
|