@c9up/helix-plugin-ream 0.1.3 → 0.1.5

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/index.d.ts CHANGED
@@ -6,10 +6,25 @@
6
6
  * client itself (`TestClient`, `createTestClient`) stays in `@c9up/ream/testing`
7
7
  * — it drives a Ream server and owes nothing to the runner.
8
8
  *
9
+ * The split follows AdonisJS: the plugin puts a CLIENT on the test context, and
10
+ * the SERVER is started by a suite hook, so a suite that does not declare the
11
+ * hook never starts one.
12
+ *
9
13
  * // tests/bootstrap.ts
10
14
  * import { configure } from '@c9up/helix'
11
15
  * import { apiClient } from '@c9up/helix-plugin-ream'
12
- * await configure({ plugins: [apiClient({ boot: () => bootApp() })] })
16
+ * import { createTestUtils } from '@c9up/ream/testing/utils'
17
+ *
18
+ * export const testUtils = createTestUtils((port) => bootApp(port))
19
+ *
20
+ * await configure({
21
+ * plugins: [apiClient({ testUtils })],
22
+ * configureSuite(suite) {
23
+ * if (['functional', 'e2e'].includes(suite.name)) {
24
+ * return suite.setup(() => testUtils.httpServer().start())
25
+ * }
26
+ * },
27
+ * })
13
28
  *
14
29
  * // a test
15
30
  * test('health', async ({ client }) => {
@@ -19,27 +34,55 @@
19
34
  import type { PluginApi } from "@c9up/helix";
20
35
  import type { AuthStrategy, RouteManifest } from "@c9up/ream/testing";
21
36
  import { TestClient } from "@c9up/ream/testing";
37
+ import type { BootServer, TestUtils } from "@c9up/ream/testing/utils";
22
38
  /** The slice of helix's `PluginApi` this plugin actually uses. */
23
39
  export type ClientHost = Pick<PluginApi, "context" | "cleanup">;
24
40
  export interface ApiClientConfig {
25
- /** Boot the app under test on the given port; return the port + a close fn. */
26
- boot: (port: number) => Promise<{
27
- port: number;
28
- close: () => Promise<void> | void;
29
- }>;
41
+ /**
42
+ * The utilities whose `httpServer()` a suite hook starts. The plugin reads
43
+ * the client of the server that hook started, so both point at one server.
44
+ */
45
+ testUtils?: TestUtils;
46
+ /**
47
+ * Boot the app directly, for a project that does not split its suites.
48
+ *
49
+ * A deviation from AdonisJS, where starting the server is always the suite
50
+ * hook's job. It exists because the server then starts on the client's FIRST
51
+ * REQUEST rather than at plugin time, so a file that issues none pays
52
+ * nothing — the same saving `testUtils` obtains by scoping, without having
53
+ * to split the suites first. Prefer `testUtils`; reach for this when the
54
+ * files are not separated.
55
+ */
56
+ boot?: BootServer;
30
57
  /** Warden auth strategy for `client.withAuth()`/`asUser()`. */
31
58
  auth?: AuthStrategy;
32
59
  /** Named-route manifest (`router.namedManifest()`) for `client.visit()`. */
33
60
  routes?: RouteManifest;
34
61
  }
35
62
  /**
36
- * Injects a booted {@link TestClient} on the test context as `ctx.client`.
63
+ * Injects a {@link TestClient} on the test context as `ctx.client`.
64
+ *
65
+ * With `testUtils`, the client is the one belonging to the server the suite
66
+ * hook started — so nothing is booted here, and a suite without the hook has no
67
+ * server at all. With `boot`, the client owns its server and starts it on the
68
+ * first request.
37
69
  *
38
- * The server is booted once at `configure()` time, shared across the run, and
39
- * closed via `api.cleanup` after the run finishes a proper lifecycle, with no
40
- * reliance on process exit.
70
+ * Either way `api.cleanup` closes what this plugin started, which is nothing in
71
+ * the `testUtils` case the hook's own teardown owns that server.
41
72
  */
42
73
  export declare function apiClient(config: ApiClientConfig): (api: ClientHost) => Promise<void>;
74
+ /**
75
+ * The client this run is using, reachable without a test context.
76
+ *
77
+ * `ctx.client` covers a test body. A helper module, a fixture, or a
78
+ * `runnerHooks` setup has no context to read it from and had to be handed one
79
+ * through a parameter every call site then had to thread. Same instance as
80
+ * `ctx.client` — the AdonisJS `services/test_utils` idiom.
81
+ *
82
+ * Throws when no client is in play, which is a wiring mistake rather than a
83
+ * state to handle.
84
+ */
85
+ export declare function testClient(): TestClient;
43
86
  declare module "@c9up/helix" {
44
87
  interface TestContext {
45
88
  client: TestClient;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAU,SAAS,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACtE,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEhD,kEAAkE;AAClE,MAAM,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,EAAE,SAAS,GAAG,SAAS,CAAC,CAAC;AAEhE,MAAM,WAAW,eAAe;IAC/B,+EAA+E;IAC/E,IAAI,EAAE,CACL,IAAI,EAAE,MAAM,KACR,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC;IAClE,+DAA+D;IAC/D,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,4EAA4E;IAC5E,MAAM,CAAC,EAAE,aAAa,CAAC;CACvB;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,eAAe,SACrB,UAAU,KAAG,OAAO,CAAC,IAAI,CAAC,CAarD;AAGD,OAAO,QAAQ,aAAa,CAAC;IAC5B,UAAU,WAAW;QACpB,MAAM,EAAE,UAAU,CAAC;KACnB;CACD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,KAAK,EAAU,SAAS,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACtE,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAEtE,kEAAkE;AAClE,MAAM,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,EAAE,SAAS,GAAG,SAAS,CAAC,CAAC;AAEhE,MAAM,WAAW,eAAe;IAC/B;;;OAGG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB;;;;;;;;;OASG;IACH,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,+DAA+D;IAC/D,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,4EAA4E;IAC5E,MAAM,CAAC,EAAE,aAAa,CAAC;CACvB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,eAAe,SACrB,UAAU,KAAG,OAAO,CAAC,IAAI,CAAC,CAkDrD;AAiBD;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,IAAI,UAAU,CAUvC;AAGD,OAAO,QAAQ,aAAa,CAAC;IAC5B,UAAU,WAAW;QACpB,MAAM,EAAE,UAAU,CAAC;KACnB;CACD"}
package/dist/index.js CHANGED
@@ -6,10 +6,25 @@
6
6
  * client itself (`TestClient`, `createTestClient`) stays in `@c9up/ream/testing`
7
7
  * — it drives a Ream server and owes nothing to the runner.
8
8
  *
9
+ * The split follows AdonisJS: the plugin puts a CLIENT on the test context, and
10
+ * the SERVER is started by a suite hook, so a suite that does not declare the
11
+ * hook never starts one.
12
+ *
9
13
  * // tests/bootstrap.ts
10
14
  * import { configure } from '@c9up/helix'
11
15
  * import { apiClient } from '@c9up/helix-plugin-ream'
12
- * await configure({ plugins: [apiClient({ boot: () => bootApp() })] })
16
+ * import { createTestUtils } from '@c9up/ream/testing/utils'
17
+ *
18
+ * export const testUtils = createTestUtils((port) => bootApp(port))
19
+ *
20
+ * await configure({
21
+ * plugins: [apiClient({ testUtils })],
22
+ * configureSuite(suite) {
23
+ * if (['functional', 'e2e'].includes(suite.name)) {
24
+ * return suite.setup(() => testUtils.httpServer().start())
25
+ * }
26
+ * },
27
+ * })
13
28
  *
14
29
  * // a test
15
30
  * test('health', async ({ client }) => {
@@ -18,25 +33,93 @@
18
33
  */
19
34
  import { TestClient } from "@c9up/ream/testing";
20
35
  /**
21
- * Injects a booted {@link TestClient} on the test context as `ctx.client`.
36
+ * Injects a {@link TestClient} on the test context as `ctx.client`.
22
37
  *
23
- * The server is booted once at `configure()` time, shared across the run, and
24
- * closed via `api.cleanup` after the run finishes a proper lifecycle, with no
25
- * reliance on process exit.
38
+ * With `testUtils`, the client is the one belonging to the server the suite
39
+ * hook started so nothing is booted here, and a suite without the hook has no
40
+ * server at all. With `boot`, the client owns its server and starts it on the
41
+ * first request.
42
+ *
43
+ * Either way `api.cleanup` closes what this plugin started, which is nothing in
44
+ * the `testUtils` case — the hook's own teardown owns that server.
26
45
  */
27
46
  export function apiClient(config) {
28
47
  const plugin = async (api) => {
29
- const client = new TestClient(config.boot, {
30
- auth: config.auth,
31
- routes: config.routes,
48
+ if (!config.testUtils && !config.boot) {
49
+ throw new Error("[E_NO_SERVER] apiClient() needs either `testUtils` (the AdonisJS shape: " +
50
+ "a suite hook starts the server) or `boot` (the client starts one on its " +
51
+ "first request). It was given neither, so `ctx.client` would have had " +
52
+ "nothing to talk to.");
53
+ }
54
+ // Resolved per access, not once: with `testUtils` the server does not
55
+ // exist yet when the plugin runs — the suite's setup hook starts it.
56
+ const owned = config.boot
57
+ ? new TestClient(config.boot, {
58
+ auth: config.auth,
59
+ routes: config.routes,
60
+ })
61
+ : undefined;
62
+ const read = () => {
63
+ const client = owned ?? config.testUtils?.client();
64
+ if (!client) {
65
+ throw new Error("[E_SERVER_NOT_STARTED] No server is running for this suite. Add the " +
66
+ "hook that starts it:\n" +
67
+ " configureSuite(suite) {\n" +
68
+ " if (suite.name === 'functional') {\n" +
69
+ " return suite.setup(() => testUtils.httpServer().start())\n" +
70
+ " }\n" +
71
+ " }");
72
+ }
73
+ return client;
74
+ };
75
+ // The resolver, not a client: with `testUtils` there is nothing to record
76
+ // yet, and `testClient()` must not depend on someone having read
77
+ // `ctx.client` first — a fixture or a runner hook has no context to read
78
+ // it from, which is the reason the accessor exists.
79
+ setResolver(read);
80
+ api.context.getter("client", read);
81
+ api.cleanup(async () => {
82
+ if (owned)
83
+ await owned.close();
84
+ clearResolver(read);
32
85
  });
33
- await client.boot();
34
- api.context.macro("client", client);
35
- api.cleanup(() => client.close());
36
86
  };
37
87
  // A wider parameter than `PluginApi` stays assignable to `Plugin`, so the
38
88
  // plugin declares exactly what it touches and a caller can drive it with
39
89
  // nothing more than that.
40
90
  return plugin;
41
91
  }
92
+ let resolve;
93
+ /** @internal Record how to reach the client in play. */
94
+ function setResolver(read) {
95
+ resolve = read;
96
+ }
97
+ /**
98
+ * @internal Forget it IF it is still the one recorded — a second `configure()`
99
+ * in the same process must not have the first one's teardown clear its client.
100
+ */
101
+ function clearResolver(read) {
102
+ if (resolve === read)
103
+ resolve = undefined;
104
+ }
105
+ /**
106
+ * The client this run is using, reachable without a test context.
107
+ *
108
+ * `ctx.client` covers a test body. A helper module, a fixture, or a
109
+ * `runnerHooks` setup has no context to read it from and had to be handed one
110
+ * through a parameter every call site then had to thread. Same instance as
111
+ * `ctx.client` — the AdonisJS `services/test_utils` idiom.
112
+ *
113
+ * Throws when no client is in play, which is a wiring mistake rather than a
114
+ * state to handle.
115
+ */
116
+ export function testClient() {
117
+ if (!resolve) {
118
+ throw new Error("[E_NO_TEST_CLIENT] No client is in play. Add `apiClient()` to the plugins " +
119
+ "in tests/bootstrap.ts, and — with the `testUtils` shape — make sure the " +
120
+ "suite's setup hook has started the server. This reads the client of the " +
121
+ "CURRENT process.");
122
+ }
123
+ return resolve();
124
+ }
42
125
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAgBhD;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CAAC,MAAuB;IAChD,MAAM,MAAM,GAAG,KAAK,EAAE,GAAe,EAAiB,EAAE;QACvD,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE;YAC1C,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,MAAM,EAAE,MAAM,CAAC,MAAM;SACrB,CAAC,CAAC;QACH,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACpC,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;IACnC,CAAC,CAAC;IACF,0EAA0E;IAC1E,yEAAyE;IACzE,0BAA0B;IAC1B,OAAO,MAAuB,CAAC;AAChC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAIH,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AA6BhD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,SAAS,CAAC,MAAuB;IAChD,MAAM,MAAM,GAAG,KAAK,EAAE,GAAe,EAAiB,EAAE;QACvD,IAAI,CAAC,MAAM,CAAC,SAAS,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;YACvC,MAAM,IAAI,KAAK,CACd,0EAA0E;gBACzE,0EAA0E;gBAC1E,uEAAuE;gBACvE,qBAAqB,CACtB,CAAC;QACH,CAAC;QAED,sEAAsE;QACtE,qEAAqE;QACrE,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI;YACxB,CAAC,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE;gBAC5B,IAAI,EAAE,MAAM,CAAC,IAAI;gBACjB,MAAM,EAAE,MAAM,CAAC,MAAM;aACrB,CAAC;YACH,CAAC,CAAC,SAAS,CAAC;QAEb,MAAM,IAAI,GAAG,GAAe,EAAE;YAC7B,MAAM,MAAM,GAAG,KAAK,IAAI,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC;YACnD,IAAI,CAAC,MAAM,EAAE,CAAC;gBACb,MAAM,IAAI,KAAK,CACd,sEAAsE;oBACrE,wBAAwB;oBACxB,6BAA6B;oBAC7B,0CAA0C;oBAC1C,kEAAkE;oBAClE,SAAS;oBACT,KAAK,CACN,CAAC;YACH,CAAC;YACD,OAAO,MAAM,CAAC;QACf,CAAC,CAAC;QAEF,0EAA0E;QAC1E,iEAAiE;QACjE,yEAAyE;QACzE,oDAAoD;QACpD,WAAW,CAAC,IAAI,CAAC,CAAC;QAClB,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACnC,GAAG,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE;YACtB,IAAI,KAAK;gBAAE,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC;YAC/B,aAAa,CAAC,IAAI,CAAC,CAAC;QACrB,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC;IACF,0EAA0E;IAC1E,yEAAyE;IACzE,0BAA0B;IAC1B,OAAO,MAAuB,CAAC;AAChC,CAAC;AAED,IAAI,OAAuC,CAAC;AAE5C,wDAAwD;AACxD,SAAS,WAAW,CAAC,IAAsB;IAC1C,OAAO,GAAG,IAAI,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,SAAS,aAAa,CAAC,IAAsB;IAC5C,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO,GAAG,SAAS,CAAC;AAC3C,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,UAAU;IACzB,IAAI,CAAC,OAAO,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CACd,4EAA4E;YAC3E,0EAA0E;YAC1E,0EAA0E;YAC1E,kBAAkB,CACnB,CAAC;IACH,CAAC;IACD,OAAO,OAAO,EAAE,CAAC;AAClB,CAAC"}
@@ -67,12 +67,10 @@ export declare class SuiteConfigureUnreachableError extends Error {
67
67
  /**
68
68
  * The flags the worker processes are spawned with.
69
69
  *
70
- * Split out because it is a decision, not plumbing: the helix alias loader
71
- * redirects a package specifier, so it goes in only when a project asks. It
72
- * rides ALONGSIDE whatever loader is already there — the test files still need
73
- * theirs to read TypeScript.
70
+ * A project's own flags win; otherwise the workers inherit this process's, so
71
+ * the loader that lets the test files be read as TypeScript carries over.
74
72
  */
75
- export declare function workerNodeArgs(tests: TestsConfig | undefined, options: RunTestsOptions): string[];
73
+ export declare function workerNodeArgs(options: RunTestsOptions): string[];
76
74
  /**
77
75
  * Run the rc file's test suites. Returns the process exit code; the caller
78
76
  * decides what to do with it, so this stays usable from a `bin/test.ts`, from a
@@ -1 +1 @@
1
- {"version":3,"file":"runTests.d.ts","sourceRoot":"","sources":["../src/runTests.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAIH,OAAO,KAAK,EAAmB,WAAW,EAAE,MAAM,YAAY,CAAC;AAG/D,wDAAwD;AACxD,MAAM,WAAW,eAAe;IAC/B,4EAA4E;IAC5E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,mCAAmC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sDAAsD;IACtD,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,iCAAiC;IACjC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,2DAA2D;AAC3D,qBAAa,iBAAkB,SAAQ,KAAK;gBAC/B,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE;CAQ5C;AAED;;;;;;GAMG;AACH,qBAAa,8BAA+B,SAAQ,KAAK;gBAC5C,KAAK,EAAE,MAAM,EAAE;CAU3B;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC7B,KAAK,EAAE,WAAW,GAAG,SAAS,EAC9B,OAAO,EAAE,eAAe,GACtB,MAAM,EAAE,CAEV;AAkBD;;;;;;;;;;GAUG;AACH,wBAAsB,QAAQ,CAC7B,KAAK,EAAE,WAAW,GAAG,SAAS,EAC9B,OAAO,GAAE,eAAoB,GAC3B,OAAO,CAAC,MAAM,CAAC,CAyGjB;AA2BD;;;GAGG;AACH,wBAAsB,kBAAkB,CACvC,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,eAAoB,GAC3B,OAAO,CAAC,MAAM,CAAC,CAmBjB"}
1
+ {"version":3,"file":"runTests.d.ts","sourceRoot":"","sources":["../src/runTests.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAIH,OAAO,KAAK,EAAmB,WAAW,EAAE,MAAM,YAAY,CAAC;AAG/D,wDAAwD;AACxD,MAAM,WAAW,eAAe;IAC/B,4EAA4E;IAC5E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,mCAAmC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sDAAsD;IACtD,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,iCAAiC;IACjC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,2DAA2D;AAC3D,qBAAa,iBAAkB,SAAQ,KAAK;gBAC/B,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE;CAQ5C;AAED;;;;;;GAMG;AACH,qBAAa,8BAA+B,SAAQ,KAAK;gBAC5C,KAAK,EAAE,MAAM,EAAE;CAU3B;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,EAAE,CAEjE;AAkBD;;;;;;;;;;GAUG;AACH,wBAAsB,QAAQ,CAC7B,KAAK,EAAE,WAAW,GAAG,SAAS,EAC9B,OAAO,GAAE,eAAoB,GAC3B,OAAO,CAAC,MAAM,CAAC,CAyGjB;AA2BD;;;GAGG;AACH,wBAAsB,kBAAkB,CACvC,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,eAAoB,GAC3B,OAAO,CAAC,MAAM,CAAC,CAmBjB"}
package/dist/runTests.js CHANGED
@@ -51,12 +51,10 @@ export class SuiteConfigureUnreachableError extends Error {
51
51
  /**
52
52
  * The flags the worker processes are spawned with.
53
53
  *
54
- * Split out because it is a decision, not plumbing: the helix alias loader
55
- * redirects a package specifier, so it goes in only when a project asks. It
56
- * rides ALONGSIDE whatever loader is already there — the test files still need
57
- * theirs to read TypeScript.
54
+ * A project's own flags win; otherwise the workers inherit this process's, so
55
+ * the loader that lets the test files be read as TypeScript carries over.
58
56
  */
59
- export function workerNodeArgs(tests, options) {
57
+ export function workerNodeArgs(options) {
60
58
  return [...(options.nodeArgs ?? process.execArgv)];
61
59
  }
62
60
  /** The suites to run, in declaration order, for the given selection. */
@@ -119,7 +117,7 @@ export async function runTests(tests, options = {}) {
119
117
  process.env.HELIX_SUITE_CONFIG_KEY = "tests.suites";
120
118
  const base = {
121
119
  root,
122
- nodeArgs: workerNodeArgs(tests, options),
120
+ nodeArgs: workerNodeArgs(options),
123
121
  threads: options.threads,
124
122
  timeoutMs: tests?.timeout,
125
123
  reporters: options.reporters,
@@ -1 +1 @@
1
- {"version":3,"file":"runTests.js","sourceRoot":"","sources":["../src/runTests.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"runTests.js","sourceRoot":"","sources":["../src/runTests.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@c9up/helix-plugin-ream",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Helix plugin for Ream — boots a Ream app under test and injects a TestClient on the test context",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -18,12 +18,12 @@
18
18
  },
19
19
  "peerDependencies": {
20
20
  "@c9up/helix": "^0.2.3",
21
- "@c9up/ream": "^0.2.0"
21
+ "@c9up/ream": "^0.2.7"
22
22
  },
23
23
  "devDependencies": {
24
24
  "@biomejs/biome": "^2.4.10",
25
25
  "@c9up/helix": "^0.2.3",
26
- "@c9up/ream": "^0.2.0",
26
+ "@c9up/ream": "^0.2.7",
27
27
  "@types/node": "^22.19.15",
28
28
  "tsx": "^4",
29
29
  "typescript": "^6.0.2",
package/src/index.ts CHANGED
@@ -6,10 +6,25 @@
6
6
  * client itself (`TestClient`, `createTestClient`) stays in `@c9up/ream/testing`
7
7
  * — it drives a Ream server and owes nothing to the runner.
8
8
  *
9
+ * The split follows AdonisJS: the plugin puts a CLIENT on the test context, and
10
+ * the SERVER is started by a suite hook, so a suite that does not declare the
11
+ * hook never starts one.
12
+ *
9
13
  * // tests/bootstrap.ts
10
14
  * import { configure } from '@c9up/helix'
11
15
  * import { apiClient } from '@c9up/helix-plugin-ream'
12
- * await configure({ plugins: [apiClient({ boot: () => bootApp() })] })
16
+ * import { createTestUtils } from '@c9up/ream/testing/utils'
17
+ *
18
+ * export const testUtils = createTestUtils((port) => bootApp(port))
19
+ *
20
+ * await configure({
21
+ * plugins: [apiClient({ testUtils })],
22
+ * configureSuite(suite) {
23
+ * if (['functional', 'e2e'].includes(suite.name)) {
24
+ * return suite.setup(() => testUtils.httpServer().start())
25
+ * }
26
+ * },
27
+ * })
13
28
  *
14
29
  * // a test
15
30
  * test('health', async ({ client }) => {
@@ -20,15 +35,28 @@
20
35
  import type { Plugin, PluginApi } from "@c9up/helix";
21
36
  import type { AuthStrategy, RouteManifest } from "@c9up/ream/testing";
22
37
  import { TestClient } from "@c9up/ream/testing";
38
+ import type { BootServer, TestUtils } from "@c9up/ream/testing/utils";
23
39
 
24
40
  /** The slice of helix's `PluginApi` this plugin actually uses. */
25
41
  export type ClientHost = Pick<PluginApi, "context" | "cleanup">;
26
42
 
27
43
  export interface ApiClientConfig {
28
- /** Boot the app under test on the given port; return the port + a close fn. */
29
- boot: (
30
- port: number,
31
- ) => Promise<{ port: number; close: () => Promise<void> | void }>;
44
+ /**
45
+ * The utilities whose `httpServer()` a suite hook starts. The plugin reads
46
+ * the client of the server that hook started, so both point at one server.
47
+ */
48
+ testUtils?: TestUtils;
49
+ /**
50
+ * Boot the app directly, for a project that does not split its suites.
51
+ *
52
+ * A deviation from AdonisJS, where starting the server is always the suite
53
+ * hook's job. It exists because the server then starts on the client's FIRST
54
+ * REQUEST rather than at plugin time, so a file that issues none pays
55
+ * nothing — the same saving `testUtils` obtains by scoping, without having
56
+ * to split the suites first. Prefer `testUtils`; reach for this when the
57
+ * files are not separated.
58
+ */
59
+ boot?: BootServer;
32
60
  /** Warden auth strategy for `client.withAuth()`/`asUser()`. */
33
61
  auth?: AuthStrategy;
34
62
  /** Named-route manifest (`router.namedManifest()`) for `client.visit()`. */
@@ -36,21 +64,62 @@ export interface ApiClientConfig {
36
64
  }
37
65
 
38
66
  /**
39
- * Injects a booted {@link TestClient} on the test context as `ctx.client`.
67
+ * Injects a {@link TestClient} on the test context as `ctx.client`.
68
+ *
69
+ * With `testUtils`, the client is the one belonging to the server the suite
70
+ * hook started — so nothing is booted here, and a suite without the hook has no
71
+ * server at all. With `boot`, the client owns its server and starts it on the
72
+ * first request.
40
73
  *
41
- * The server is booted once at `configure()` time, shared across the run, and
42
- * closed via `api.cleanup` after the run finishes a proper lifecycle, with no
43
- * reliance on process exit.
74
+ * Either way `api.cleanup` closes what this plugin started, which is nothing in
75
+ * the `testUtils` case the hook's own teardown owns that server.
44
76
  */
45
77
  export function apiClient(config: ApiClientConfig) {
46
78
  const plugin = async (api: ClientHost): Promise<void> => {
47
- const client = new TestClient(config.boot, {
48
- auth: config.auth,
49
- routes: config.routes,
79
+ if (!config.testUtils && !config.boot) {
80
+ throw new Error(
81
+ "[E_NO_SERVER] apiClient() needs either `testUtils` (the AdonisJS shape: " +
82
+ "a suite hook starts the server) or `boot` (the client starts one on its " +
83
+ "first request). It was given neither, so `ctx.client` would have had " +
84
+ "nothing to talk to.",
85
+ );
86
+ }
87
+
88
+ // Resolved per access, not once: with `testUtils` the server does not
89
+ // exist yet when the plugin runs — the suite's setup hook starts it.
90
+ const owned = config.boot
91
+ ? new TestClient(config.boot, {
92
+ auth: config.auth,
93
+ routes: config.routes,
94
+ })
95
+ : undefined;
96
+
97
+ const read = (): TestClient => {
98
+ const client = owned ?? config.testUtils?.client();
99
+ if (!client) {
100
+ throw new Error(
101
+ "[E_SERVER_NOT_STARTED] No server is running for this suite. Add the " +
102
+ "hook that starts it:\n" +
103
+ " configureSuite(suite) {\n" +
104
+ " if (suite.name === 'functional') {\n" +
105
+ " return suite.setup(() => testUtils.httpServer().start())\n" +
106
+ " }\n" +
107
+ " }",
108
+ );
109
+ }
110
+ return client;
111
+ };
112
+
113
+ // The resolver, not a client: with `testUtils` there is nothing to record
114
+ // yet, and `testClient()` must not depend on someone having read
115
+ // `ctx.client` first — a fixture or a runner hook has no context to read
116
+ // it from, which is the reason the accessor exists.
117
+ setResolver(read);
118
+ api.context.getter("client", read);
119
+ api.cleanup(async () => {
120
+ if (owned) await owned.close();
121
+ clearResolver(read);
50
122
  });
51
- await client.boot();
52
- api.context.macro("client", client);
53
- api.cleanup(() => client.close());
54
123
  };
55
124
  // A wider parameter than `PluginApi` stays assignable to `Plugin`, so the
56
125
  // plugin declares exactly what it touches and a caller can drive it with
@@ -58,6 +127,44 @@ export function apiClient(config: ApiClientConfig) {
58
127
  return plugin satisfies Plugin;
59
128
  }
60
129
 
130
+ let resolve: (() => TestClient) | undefined;
131
+
132
+ /** @internal Record how to reach the client in play. */
133
+ function setResolver(read: () => TestClient): void {
134
+ resolve = read;
135
+ }
136
+
137
+ /**
138
+ * @internal Forget it IF it is still the one recorded — a second `configure()`
139
+ * in the same process must not have the first one's teardown clear its client.
140
+ */
141
+ function clearResolver(read: () => TestClient): void {
142
+ if (resolve === read) resolve = undefined;
143
+ }
144
+
145
+ /**
146
+ * The client this run is using, reachable without a test context.
147
+ *
148
+ * `ctx.client` covers a test body. A helper module, a fixture, or a
149
+ * `runnerHooks` setup has no context to read it from and had to be handed one
150
+ * through a parameter every call site then had to thread. Same instance as
151
+ * `ctx.client` — the AdonisJS `services/test_utils` idiom.
152
+ *
153
+ * Throws when no client is in play, which is a wiring mistake rather than a
154
+ * state to handle.
155
+ */
156
+ export function testClient(): TestClient {
157
+ if (!resolve) {
158
+ throw new Error(
159
+ "[E_NO_TEST_CLIENT] No client is in play. Add `apiClient()` to the plugins " +
160
+ "in tests/bootstrap.ts, and — with the `testUtils` shape — make sure the " +
161
+ "suite's setup hook has started the server. This reads the client of the " +
162
+ "CURRENT process.",
163
+ );
164
+ }
165
+ return resolve();
166
+ }
167
+
61
168
  // Typing side of the plugin — importing it augments the helix test context.
62
169
  declare module "@c9up/helix" {
63
170
  interface TestContext {
package/src/runTests.ts CHANGED
@@ -91,15 +91,10 @@ export class SuiteConfigureUnreachableError extends Error {
91
91
  /**
92
92
  * The flags the worker processes are spawned with.
93
93
  *
94
- * Split out because it is a decision, not plumbing: the helix alias loader
95
- * redirects a package specifier, so it goes in only when a project asks. It
96
- * rides ALONGSIDE whatever loader is already there — the test files still need
97
- * theirs to read TypeScript.
94
+ * A project's own flags win; otherwise the workers inherit this process's, so
95
+ * the loader that lets the test files be read as TypeScript carries over.
98
96
  */
99
- export function workerNodeArgs(
100
- tests: TestsConfig | undefined,
101
- options: RunTestsOptions,
102
- ): string[] {
97
+ export function workerNodeArgs(options: RunTestsOptions): string[] {
103
98
  return [...(options.nodeArgs ?? process.execArgv)];
104
99
  }
105
100
 
@@ -178,7 +173,7 @@ export async function runTests(
178
173
 
179
174
  const base = {
180
175
  root,
181
- nodeArgs: workerNodeArgs(tests, options),
176
+ nodeArgs: workerNodeArgs(options),
182
177
  threads: options.threads,
183
178
  timeoutMs: tests?.timeout,
184
179
  reporters: options.reporters,