@nwire/test-kit 0.10.1 → 0.11.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/bdd.d.ts CHANGED
@@ -1,43 +1,125 @@
1
1
  /**
2
- * BDD via `@amiceli/vitest-cucumber` thin wrapper that hooks the
3
- * generated steps into our harness lifecycle.
2
+ * BDD support — thin re-exports of `@amiceli/vitest-cucumber` so test-kit
3
+ * users have a single dependency for harness + BDD primitives, plus a
4
+ * `bddHarness({ buildApp })` factory that handles the Background-runs-
5
+ * before-BeforeEachScenario lifecycle quirk so step files don't have to.
4
6
  *
5
- * Usage (in a *.test.ts file):
7
+ * import { describeFeature, loadFeature } from "@amiceli/vitest-cucumber";
8
+ * import { bddHarness } from "@nwire/test-kit";
6
9
  *
7
- * import { feature } from "@nwire/test-kit";
8
- * import { harness } from "@nwire/test-kit";
9
- * import submissionsApp from "./submissions.app";
10
+ * describeFeature(feature, ({ Scenario, Background, AfterEachScenario }) => {
11
+ * const ctx = bddHarness({ buildApp });
10
12
  *
11
- * feature("./avi-submits.feature", async (ctx) => {
12
- * ctx.background(async () => { ctx.harness = await harness({ app: submissionsApp }); });
13
- * ctx.afterScenario(async () => ctx.harness?.stop());
13
+ * AfterEachScenario(async () => { await ctx.reset(); });
14
14
  *
15
- * ctx.when("Avi submits {answer}", async (answer) => {
16
- * await ctx.harness.dispatch(submitAnswer, { studentId: "avi", answer });
15
+ * Background(({ Given, And }) => {
16
+ * Given("the platform is up", async () => { await ctx.boot(); });
17
+ * And("a seed exists", async () => {
18
+ * await ctx.boot();
19
+ * await ctx.scoped().dispatch(...);
20
+ * });
17
21
  * });
18
- * ctx.then("event {name} should fire", async (name) => {
19
- * await ctx.harness.idle();
20
- * expect(ctx.harness.telemetry.count("event.published", (e) => e.event.eventName === name)).toBeGreaterThan(0);
22
+ *
23
+ * Scenario("does the thing", ({ When, Then }) => {
24
+ * When("we dispatch", async () => { await ctx.scoped().dispatch(...); });
25
+ * Then("we see the result", async () => {
26
+ * expect(ctx.harness.telemetry.count(...)).toBeGreaterThan(0);
27
+ * });
21
28
  * });
22
29
  * });
23
30
  *
24
- * The wrapper is intentionally tiny — we pass through to the real Gherkin
25
- * runner. `@amiceli/vitest-cucumber` is a peerDependency.
31
+ * Lifecycle quirk: in @amiceli/vitest-cucumber@4, `BeforeEachScenario`
32
+ * fires in the scenario's `beforeAll`, but **Background** steps live in
33
+ * a separate describe that runs BEFORE the scenario's beforeAll. The
34
+ * lazy-init pattern (call `ctx.boot()` at the head of every step) keeps
35
+ * Background + Scenario steps wired to the SAME fresh harness within a
36
+ * scenario, and `AfterEachScenario(() => ctx.reset())` releases it
37
+ * between scenarios.
38
+ *
39
+ * Step-text reuse: vitest-cucumber binds registrations to feature steps
40
+ * by the registration text. If a feature uses the same step pattern
41
+ * twice in one scope (Background or Scenario), each occurrence still
42
+ * binds to the FIRST matching registration — the second occurrence
43
+ * reports as "missing". Give each occurrence unique wording in the
44
+ * .feature file.
45
+ *
46
+ * `@amiceli/vitest-cucumber` is a peer dependency — install it in the
47
+ * consuming project: `pnpm add -D @amiceli/vitest-cucumber`.
48
+ */
49
+ import type { App } from "@nwire/app";
50
+ import { type Harness } from "./harness.js";
51
+ import { type ScopedHarness, type UserLike } from "./harness-extensions.js";
52
+ /**
53
+ * Re-export of vitest-cucumber's primary API surface. The package is a
54
+ * peer dep — we resolve it lazily so test-kit consumers that don't run
55
+ * BDD tests aren't forced to install it.
56
+ */
57
+ export declare function loadBddRunner(): Promise<typeof import("@amiceli/vitest-cucumber")>;
58
+ /**
59
+ * Marker type — `BddContext` was a planning placeholder in 0.10. The
60
+ * real API is `describeFeature` / `loadFeature` from
61
+ * `@amiceli/vitest-cucumber`, used directly in step files. This export
62
+ * is kept for back-compat of the test-kit barrel; consumers should
63
+ * import `describeFeature` / `loadFeature` directly from
64
+ * `@amiceli/vitest-cucumber`.
26
65
  */
27
- import type { Harness } from "./harness.js";
28
66
  export interface BddContext {
29
- /** Filled in by the user's background step. */
30
- harness?: Harness;
31
- background(fn: () => Promise<void> | void): void;
32
- afterScenario(fn: () => Promise<void> | void): void;
33
- given(pattern: string, fn: (...args: unknown[]) => Promise<void> | void): void;
34
- when(pattern: string, fn: (...args: unknown[]) => Promise<void> | void): void;
35
- then(pattern: string, fn: (...args: unknown[]) => Promise<void> | void): void;
36
- and(pattern: string, fn: (...args: unknown[]) => Promise<void> | void): void;
67
+ readonly harness?: Harness;
68
+ }
69
+ /**
70
+ * Convenience pass-through equivalent to importing `loadFeature`
71
+ * directly from `@amiceli/vitest-cucumber` but routed through the
72
+ * peer-dep loader so the error message is friendlier if the package
73
+ * is missing.
74
+ */
75
+ export declare function feature(path: string): Promise<Awaited<ReturnType<typeof import("@amiceli/vitest-cucumber").loadFeature>>>;
76
+ export interface BddHarnessOptions {
77
+ readonly buildApp: () => App;
78
+ /** Default user pinned via `asUser` when no scenario overrides it. */
79
+ readonly defaultUser?: UserLike;
80
+ /** Tenant prefix used to namespace each scenario's state. Default "t". */
81
+ readonly tenantPrefix?: string;
82
+ }
83
+ export interface BddHarnessCtx {
84
+ /** Current harness, or `null` before the first `boot()` in a scenario. */
85
+ readonly harness: Harness | null;
86
+ /** The pinned user for `scoped()`. Step files may swap it per scenario. */
87
+ user: UserLike;
88
+ /** Tenant string assigned to the current scenario. */
89
+ readonly tenant: string;
90
+ /**
91
+ * Boot the harness if it isn't already. Call at the head of every
92
+ * Background and Scenario step so Background's first invocation wins
93
+ * regardless of vitest-cucumber's hook ordering.
94
+ */
95
+ boot(): Promise<Harness>;
96
+ /**
97
+ * Scoped dispatcher pinned to `user` + `tenant`. Call after `boot()`.
98
+ * Throws if invoked before any `boot()` ran in the current scenario.
99
+ */
100
+ scoped(overrides?: Partial<UserLike>): ScopedHarness;
101
+ /**
102
+ * Tear down the current harness. Call from `AfterEachScenario` so the
103
+ * next scenario starts fresh.
104
+ */
105
+ reset(): Promise<void>;
37
106
  }
38
107
  /**
39
- * Boot a feature file with steps. Resolves the `@amiceli/vitest-cucumber`
40
- * runner lazily so test-kit consumers without BDD don't have to install the
41
- * peer dep.
108
+ * Construct a BDD lifecycle helper for a feature.
109
+ *
110
+ * const ctx = bddHarness({ buildApp });
111
+ *
112
+ * AfterEachScenario(() => ctx.reset());
113
+ *
114
+ * Background(({ Given }) => {
115
+ * Given("the platform is up", () => ctx.boot());
116
+ * });
117
+ *
118
+ * Scenario("does X", ({ When, Then }) => {
119
+ * When("dispatch happens", async () => {
120
+ * await ctx.boot();
121
+ * await ctx.scoped().dispatch(...);
122
+ * });
123
+ * });
42
124
  */
43
- export declare function feature(featurePath: string, define: (ctx: BddContext) => void | Promise<void>): Promise<void>;
125
+ export declare function bddHarness(options: BddHarnessOptions): BddHarnessCtx;
package/dist/bdd.js CHANGED
@@ -1,66 +1,134 @@
1
1
  /**
2
- * BDD via `@amiceli/vitest-cucumber` thin wrapper that hooks the
3
- * generated steps into our harness lifecycle.
2
+ * BDD support — thin re-exports of `@amiceli/vitest-cucumber` so test-kit
3
+ * users have a single dependency for harness + BDD primitives, plus a
4
+ * `bddHarness({ buildApp })` factory that handles the Background-runs-
5
+ * before-BeforeEachScenario lifecycle quirk so step files don't have to.
4
6
  *
5
- * Usage (in a *.test.ts file):
7
+ * import { describeFeature, loadFeature } from "@amiceli/vitest-cucumber";
8
+ * import { bddHarness } from "@nwire/test-kit";
6
9
  *
7
- * import { feature } from "@nwire/test-kit";
8
- * import { harness } from "@nwire/test-kit";
9
- * import submissionsApp from "./submissions.app";
10
+ * describeFeature(feature, ({ Scenario, Background, AfterEachScenario }) => {
11
+ * const ctx = bddHarness({ buildApp });
10
12
  *
11
- * feature("./avi-submits.feature", async (ctx) => {
12
- * ctx.background(async () => { ctx.harness = await harness({ app: submissionsApp }); });
13
- * ctx.afterScenario(async () => ctx.harness?.stop());
13
+ * AfterEachScenario(async () => { await ctx.reset(); });
14
14
  *
15
- * ctx.when("Avi submits {answer}", async (answer) => {
16
- * await ctx.harness.dispatch(submitAnswer, { studentId: "avi", answer });
15
+ * Background(({ Given, And }) => {
16
+ * Given("the platform is up", async () => { await ctx.boot(); });
17
+ * And("a seed exists", async () => {
18
+ * await ctx.boot();
19
+ * await ctx.scoped().dispatch(...);
20
+ * });
17
21
  * });
18
- * ctx.then("event {name} should fire", async (name) => {
19
- * await ctx.harness.idle();
20
- * expect(ctx.harness.telemetry.count("event.published", (e) => e.event.eventName === name)).toBeGreaterThan(0);
22
+ *
23
+ * Scenario("does the thing", ({ When, Then }) => {
24
+ * When("we dispatch", async () => { await ctx.scoped().dispatch(...); });
25
+ * Then("we see the result", async () => {
26
+ * expect(ctx.harness.telemetry.count(...)).toBeGreaterThan(0);
27
+ * });
21
28
  * });
22
29
  * });
23
30
  *
24
- * The wrapper is intentionally tiny — we pass through to the real Gherkin
25
- * runner. `@amiceli/vitest-cucumber` is a peerDependency.
31
+ * Lifecycle quirk: in @amiceli/vitest-cucumber@4, `BeforeEachScenario`
32
+ * fires in the scenario's `beforeAll`, but **Background** steps live in
33
+ * a separate describe that runs BEFORE the scenario's beforeAll. The
34
+ * lazy-init pattern (call `ctx.boot()` at the head of every step) keeps
35
+ * Background + Scenario steps wired to the SAME fresh harness within a
36
+ * scenario, and `AfterEachScenario(() => ctx.reset())` releases it
37
+ * between scenarios.
38
+ *
39
+ * Step-text reuse: vitest-cucumber binds registrations to feature steps
40
+ * by the registration text. If a feature uses the same step pattern
41
+ * twice in one scope (Background or Scenario), each occurrence still
42
+ * binds to the FIRST matching registration — the second occurrence
43
+ * reports as "missing". Give each occurrence unique wording in the
44
+ * .feature file.
45
+ *
46
+ * `@amiceli/vitest-cucumber` is a peer dependency — install it in the
47
+ * consuming project: `pnpm add -D @amiceli/vitest-cucumber`.
26
48
  */
49
+ import { harness } from "./harness.js";
50
+ import { asUser } from "./harness-extensions.js";
27
51
  /**
28
- * Boot a feature file with steps. Resolves the `@amiceli/vitest-cucumber`
29
- * runner lazily so test-kit consumers without BDD don't have to install the
30
- * peer dep.
52
+ * Re-export of vitest-cucumber's primary API surface. The package is a
53
+ * peer dep — we resolve it lazily so test-kit consumers that don't run
54
+ * BDD tests aren't forced to install it.
31
55
  */
32
- export async function feature(featurePath, define) {
33
- let cucumber;
56
+ export async function loadBddRunner() {
34
57
  try {
35
- cucumber = await import("@amiceli/vitest-cucumber");
58
+ return await import("@amiceli/vitest-cucumber");
36
59
  }
37
60
  catch {
38
- throw new Error("@nwire/test-kit/bdd requires '@amiceli/vitest-cucumber' as a peer dependency. " +
61
+ throw new Error("@nwire/test-kit BDD helpers require '@amiceli/vitest-cucumber' as a peer dependency. " +
39
62
  "Install it: pnpm add -D @amiceli/vitest-cucumber");
40
63
  }
41
- // Adapter — the package's exact API surface differs slightly across
42
- // versions, so we resolve loosely and route step kinds through.
43
- const adapter = cucumber;
44
- if (!adapter.loadFeature || !adapter.describeFeature) {
45
- throw new Error("@amiceli/vitest-cucumber: unexpected API surface. " +
46
- "Pin to a version supported by @nwire/test-kit, or drop down to using the package directly.");
47
- }
48
- // For v1 of this wrapper we just hand the user a thin facade. Users can
49
- // also import @amiceli/vitest-cucumber directly for full control.
64
+ }
65
+ /**
66
+ * Convenience pass-through — equivalent to importing `loadFeature`
67
+ * directly from `@amiceli/vitest-cucumber` but routed through the
68
+ * peer-dep loader so the error message is friendlier if the package
69
+ * is missing.
70
+ */
71
+ export async function feature(path) {
72
+ const cucumber = await loadBddRunner();
73
+ return cucumber.loadFeature(path);
74
+ }
75
+ /**
76
+ * Construct a BDD lifecycle helper for a feature.
77
+ *
78
+ * const ctx = bddHarness({ buildApp });
79
+ *
80
+ * AfterEachScenario(() => ctx.reset());
81
+ *
82
+ * Background(({ Given }) => {
83
+ * Given("the platform is up", () => ctx.boot());
84
+ * });
85
+ *
86
+ * Scenario("does X", ({ When, Then }) => {
87
+ * When("dispatch happens", async () => {
88
+ * await ctx.boot();
89
+ * await ctx.scoped().dispatch(...);
90
+ * });
91
+ * });
92
+ */
93
+ export function bddHarness(options) {
94
+ let current = null;
95
+ let scenarioCounter = 0;
96
+ let tenant = `${options.tenantPrefix ?? "t"}-0`;
97
+ let user = options.defaultUser ?? { id: "bdd", tenant };
50
98
  const ctx = {
51
- harness: undefined,
52
- background: () => { },
53
- afterScenario: () => { },
54
- given: () => { },
55
- when: () => { },
56
- then: () => { },
57
- and: () => { },
99
+ get harness() {
100
+ return current;
101
+ },
102
+ get user() {
103
+ return user;
104
+ },
105
+ set user(next) {
106
+ user = next;
107
+ },
108
+ get tenant() {
109
+ return tenant;
110
+ },
111
+ async boot() {
112
+ if (current)
113
+ return current;
114
+ const app = options.buildApp();
115
+ current = await harness({ app });
116
+ tenant = `${options.tenantPrefix ?? "t"}-${++scenarioCounter}`;
117
+ user = options.defaultUser ? { ...options.defaultUser, tenant } : { id: "bdd", tenant };
118
+ return current;
119
+ },
120
+ scoped(overrides) {
121
+ if (!current) {
122
+ throw new Error("bddHarness.scoped: boot the harness first via ctx.boot() before scoped() runs.");
123
+ }
124
+ return asUser(current, { ...user, ...overrides, tenant });
125
+ },
126
+ async reset() {
127
+ if (current) {
128
+ await current.stop();
129
+ current = null;
130
+ }
131
+ },
58
132
  };
59
- await define(ctx);
60
- // The complete wiring is left as a follow-up: each step pattern needs to
61
- // register with the cucumber adapter's per-version API. Today this
62
- // function validates the user's intent and surfaces a helpful error if
63
- // the BDD dependency is missing — full step-pattern wiring lands in a
64
- // follow-up turn when we exercise a real .feature file against the
65
- // RealWorld migration.
133
+ return ctx;
66
134
  }
@@ -18,7 +18,7 @@
18
18
  * They live in a separate file so the in-memory `harness` core stays small
19
19
  * and the optional deps (`@nwire/auth`, `@nwire/rbac`, `koa`) stay opt-in.
20
20
  */
21
- import type { ActionDefinition } from "@nwire/forge";
21
+ import { type ActionDefinition } from "@nwire/forge";
22
22
  import type { ZodTypeAny } from "@nwire/messages";
23
23
  import type { z } from "zod";
24
24
  import type { Harness } from "./harness.js";
@@ -19,6 +19,7 @@
19
19
  * and the optional deps (`@nwire/auth`, `@nwire/rbac`, `koa`) stay opt-in.
20
20
  */
21
21
  import supertest from "supertest";
22
+ import { forgeDispatcher } from "@nwire/forge";
22
23
  /**
23
24
  * Return a thin proxy that pins `envelope.user` (and `envelope.userId`,
24
25
  * `envelope.tenant` derived from the user) on every dispatch/query.
@@ -32,11 +33,11 @@ export function asUser(harness, user) {
32
33
  // `user` too, which is on MessageEnvelope but not on the public dispatch
33
34
  // overload. Going through runtime.dispatch with a hand-seeded envelope
34
35
  // keeps the type contract honest without widening the public Harness API.
35
- const app = harness.app;
36
+ const dispatcher = forgeDispatcher(harness.app);
36
37
  return {
37
38
  async dispatch(action, input, envelope) {
38
39
  if (!user)
39
- return app.dispatch(action, input);
40
+ return dispatcher.dispatch(action, input);
40
41
  const { seedEnvelope } = await import("@nwire/envelope");
41
42
  const seeded = seedEnvelope({
42
43
  tenant: envelope?.tenant ?? user.tenant,
@@ -44,10 +45,10 @@ export function asUser(harness, user) {
44
45
  user,
45
46
  correlationId: envelope?.correlationId,
46
47
  });
47
- return app.dispatch(action, input, seeded);
48
+ return dispatcher.dispatch(action, input, seeded);
48
49
  },
49
50
  async query(queryDef, input, tenant) {
50
- return app.query(queryDef.name, input, tenant ?? user?.tenant ?? "");
51
+ return dispatcher.query(queryDef.name, input, tenant ?? user?.tenant ?? "");
51
52
  },
52
53
  };
53
54
  }
package/dist/harness.d.ts CHANGED
@@ -1,23 +1,25 @@
1
1
  /**
2
- * `harness(app)` — wrap an already-constructed `ForgeApp` with a light test
3
- * handle: dispatch helpers, idle-wait, and a buffered telemetry probe.
2
+ * `harness(app)` — wrap an already-constructed App with a light test handle:
3
+ * dispatch helpers, idle-wait, and a buffered telemetry probe.
4
4
  *
5
- * const app = createForgeApp({ name: "submissions", handlers, actors })
6
- * const h = await harness({ app })
7
- * await h.dispatch(submitAnswer, { })
8
- * await h.idle()
9
- * expect(h.telemetry.count("event.published")).toBeGreaterThan(0)
10
- * await h.stop()
5
+ * const app = createApp({ appName: "submissions",
6
+ * plugins: [createForgePlugin({ handlers, actors })] });
7
+ * const h = await harness({ app });
8
+ * await h.dispatch(submitAnswer, { … });
9
+ * await h.idle();
10
+ * expect(h.telemetry.count("event.published")).toBeGreaterThan(0);
11
+ * await h.stop();
11
12
  */
12
- import type { ActionDefinition, ForgeApp } from "@nwire/forge";
13
+ import type { App } from "@nwire/app";
14
+ import type { ActionDefinition } from "@nwire/forge";
13
15
  import type { z } from "zod";
14
16
  import type { ZodTypeAny } from "@nwire/messages";
15
17
  import { TelemetryProbe } from "./telemetry-probe.js";
16
18
  export interface HarnessOptions {
17
- readonly app: ForgeApp;
19
+ readonly app: App;
18
20
  }
19
21
  export interface Harness {
20
- readonly app: ForgeApp;
22
+ readonly app: App;
21
23
  readonly telemetry: TelemetryProbe;
22
24
  dispatch<TSchema extends ZodTypeAny>(action: ActionDefinition<TSchema>, input: z.input<TSchema>, envelope?: {
23
25
  tenant?: string;
package/dist/harness.js CHANGED
@@ -1,20 +1,23 @@
1
1
  /**
2
- * `harness(app)` — wrap an already-constructed `ForgeApp` with a light test
3
- * handle: dispatch helpers, idle-wait, and a buffered telemetry probe.
2
+ * `harness(app)` — wrap an already-constructed App with a light test handle:
3
+ * dispatch helpers, idle-wait, and a buffered telemetry probe.
4
4
  *
5
- * const app = createForgeApp({ name: "submissions", handlers, actors })
6
- * const h = await harness({ app })
7
- * await h.dispatch(submitAnswer, { })
8
- * await h.idle()
9
- * expect(h.telemetry.count("event.published")).toBeGreaterThan(0)
10
- * await h.stop()
5
+ * const app = createApp({ appName: "submissions",
6
+ * plugins: [createForgePlugin({ handlers, actors })] });
7
+ * const h = await harness({ app });
8
+ * await h.dispatch(submitAnswer, { … });
9
+ * await h.idle();
10
+ * expect(h.telemetry.count("event.published")).toBeGreaterThan(0);
11
+ * await h.stop();
11
12
  */
13
+ import { forgeDispatcher } from "@nwire/forge";
12
14
  import { TelemetryProbe } from "./telemetry-probe.js";
13
15
  export async function harness(options) {
14
16
  const app = options.app;
15
17
  const probe = new TelemetryProbe();
16
18
  const unsubscribe = app.runtime.onTelemetry((rec) => probe.record(rec));
17
19
  await app.start();
20
+ const dispatcher = forgeDispatcher(app);
18
21
  let pending = 0;
19
22
  let lastRecordAt = Date.now();
20
23
  app.runtime.onTelemetry(() => {
@@ -33,16 +36,16 @@ export async function harness(options) {
33
36
  userId: envelope.userId,
34
37
  correlationId: envelope.correlationId,
35
38
  });
36
- return await app.dispatch(action, input, seeded);
39
+ return await dispatcher.dispatch(action, input, seeded);
37
40
  }
38
- return await app.dispatch(action, input);
41
+ return await dispatcher.dispatch(action, input);
39
42
  }
40
43
  finally {
41
44
  pending--;
42
45
  }
43
46
  },
44
47
  async query(queryDef, input, tenant = "") {
45
- return app.query(queryDef.name, input, tenant);
48
+ return dispatcher.query(queryDef.name, input, tenant);
46
49
  },
47
50
  async idle(graceMs = 25, timeoutMs = 5000) {
48
51
  const deadline = Date.now() + timeoutMs;
@@ -20,6 +20,6 @@ export { asUser, simulateRequest, checkPolicy, onLog, type UserLike, type Scoped
20
20
  export { TelemetryProbe, type TelemetryFilter } from "./telemetry-probe.js";
21
21
  export { dockerCompose, PRESETS as DOCKER_COMPOSE_PRESETS, type ComposeStack, type ComposePreset, } from "./docker-compose.js";
22
22
  export { isReachable } from "./is-reachable.js";
23
- export { feature, type BddContext } from "./bdd.js";
23
+ export { feature, loadBddRunner, bddHarness, type BddContext, type BddHarnessOptions, type BddHarnessCtx, } from "./bdd.js";
24
24
  export { factory, sequence, type Factory, type SequenceCounter } from "./zod-fixture-factory.js";
25
25
  export { createTestApp, bootTestApp, type BootedTestApp } from "./supertest-app-helper.js";
package/dist/test-kit.js CHANGED
@@ -20,7 +20,7 @@ export { asUser, simulateRequest, checkPolicy, onLog, } from "./harness-extensio
20
20
  export { TelemetryProbe } from "./telemetry-probe.js";
21
21
  export { dockerCompose, PRESETS as DOCKER_COMPOSE_PRESETS, } from "./docker-compose.js";
22
22
  export { isReachable } from "./is-reachable.js";
23
- export { feature } from "./bdd.js";
23
+ export { feature, loadBddRunner, bddHarness, } from "./bdd.js";
24
24
  // Pre-existing helpers
25
25
  export { factory, sequence } from "./zod-fixture-factory.js";
26
26
  export { createTestApp, bootTestApp } from "./supertest-app-helper.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nwire/test-kit",
3
- "version": "0.10.1",
3
+ "version": "0.11.0",
4
4
  "description": "Shared test helpers and zod-driven fixture factories",
5
5
  "keywords": [
6
6
  "fixtures",
@@ -28,20 +28,20 @@
28
28
  "dependencies": {
29
29
  "supertest": "^7.2.2",
30
30
  "zod": "^4.0.0",
31
- "@nwire/logger": "0.10.1",
32
- "@nwire/messages": "0.10.1",
33
- "@nwire/forge": "0.10.1",
34
- "@nwire/envelope": "0.10.1"
31
+ "@nwire/envelope": "0.11.0",
32
+ "@nwire/forge": "0.11.0",
33
+ "@nwire/logger": "0.11.0",
34
+ "@nwire/messages": "0.11.0"
35
35
  },
36
36
  "devDependencies": {
37
37
  "@types/koa": "^2.15.0",
38
38
  "@types/node": "^22.19.9",
39
39
  "@types/supertest": "^6.0.3",
40
40
  "typescript": "^5.9.3",
41
- "@nwire/app": "0.10.1",
42
- "@nwire/koa": "0.10.1",
43
- "@nwire/wires": "0.10.1",
44
- "@nwire/endpoint": "0.10.1"
41
+ "@nwire/app": "0.11.0",
42
+ "@nwire/endpoint": "0.11.0",
43
+ "@nwire/wires": "0.11.0",
44
+ "@nwire/koa": "0.11.0"
45
45
  },
46
46
  "peerDependencies": {
47
47
  "@amiceli/vitest-cucumber": "^4.0.0",