@elench/testkit 0.1.77 → 0.1.78

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.
@@ -4,9 +4,10 @@ import {
4
4
  database,
5
5
  defineConfig,
6
6
  defineFile,
7
- defineHttpProfile,
7
+ profiles,
8
8
  toolchain,
9
9
  } from "./index.mjs";
10
+ import { clearRuntimeContext, registerRuntimeContext } from "./runtime.mjs";
10
11
 
11
12
  describe("config api", () => {
12
13
  it("defines repo config plainly", () => {
@@ -15,9 +16,286 @@ describe("config api", () => {
15
16
  });
16
17
  });
17
18
 
18
- it("defines HTTP profiles plainly", () => {
19
- const profile = defineHttpProfile({ headers: () => ({ Authorization: "Bearer token" }) });
20
- expect(typeof profile.headers).toBe("function");
19
+ it("builds raw HTTP profiles with deterministic forwarded headers", () => {
20
+ const profile = profiles.raw({
21
+ headers: {
22
+ contentTypeJson: true,
23
+ forwardedFor: "deterministic",
24
+ values: { "X-Testkit-Mode": "raw" },
25
+ },
26
+ });
27
+
28
+ const headers = profile.headers?.(null, { env: { BASE: "http://api.test" } });
29
+ const rawHeaders = profile.rawHeaders?.(null, { env: { BASE: "http://api.test" } });
30
+
31
+ expect(headers).toMatchObject({
32
+ "Content-Type": "application/json",
33
+ "X-Testkit-Mode": "raw",
34
+ });
35
+ expect(headers["X-Forwarded-For"]).toMatch(/^10\.\d+\.\d+\.\d+$/);
36
+ expect(rawHeaders).toEqual(headers);
37
+ });
38
+
39
+ it("builds session profiles that perform bootstrap/login and derive auth/session headers", () => {
40
+ const requests = [];
41
+ registerRuntimeContext({
42
+ env: {
43
+ BASE: "http://api.test",
44
+ routeParams: { "x-route": "route-a" },
45
+ },
46
+ http: {
47
+ post(url, body, params) {
48
+ requests.push({ url, body, params });
49
+ if (url.endsWith("/signup")) {
50
+ return {
51
+ status: 201,
52
+ body: JSON.stringify({ data: { organizations: [{ id: "org-signup" }] } }),
53
+ headers: {
54
+ "set-cookie": ["fixture_session=signup-token; Path=/", "fixture_refresh=signup-refresh; Path=/"],
55
+ },
56
+ };
57
+ }
58
+ return {
59
+ status: 200,
60
+ body: JSON.stringify({ data: { organizations: [{ id: "org-123" }] } }),
61
+ headers: {
62
+ "set-cookie": ["fixture_session=jwt-123; Path=/", "fixture_refresh=refresh-123; Path=/"],
63
+ },
64
+ };
65
+ },
66
+ },
67
+ });
68
+
69
+ const profile = profiles.session({
70
+ actor: {
71
+ bootstrap: {
72
+ path: "/signup",
73
+ expect: [201, 409],
74
+ body: ({ actor }) => ({ email: `${actor}@example.com` }),
75
+ },
76
+ login: {
77
+ path: "/login",
78
+ expect: 200,
79
+ body: ({ actor }) => ({ email: `${actor}@example.com` }),
80
+ },
81
+ session: {
82
+ cookies: {
83
+ jwt: "fixture_session",
84
+ refreshToken: "fixture_refresh",
85
+ },
86
+ fields: {
87
+ organizationId: "data.organizations[0].id",
88
+ },
89
+ auth: {
90
+ source: { key: "jwt" },
91
+ },
92
+ },
93
+ },
94
+ headers: {
95
+ contentTypeJson: true,
96
+ forwardedFor: "deterministic",
97
+ fromSession: [{ header: "X-Organization-Id", field: "organizationId" }],
98
+ values: ({ actor }) => ({ "X-Testkit-Actor": actor || "primary" }),
99
+ },
100
+ });
101
+
102
+ const session = profile.auth.setup({
103
+ env: { BASE: "http://api.test", routeParams: { "x-route": "route-a" } },
104
+ });
105
+ const authHeaders = profile.auth.headers(session, { env: { BASE: "http://api.test" } });
106
+ const requestHeaders = profile.headers(session, { env: { BASE: "http://api.test" } });
107
+
108
+ expect(requests).toHaveLength(2);
109
+ expect(requests[0].params.headers["x-route"]).toBe("route-a");
110
+ expect(session).toEqual({
111
+ jwt: "jwt-123",
112
+ refreshToken: "refresh-123",
113
+ organizationId: "org-123",
114
+ });
115
+ expect(authHeaders).toEqual({
116
+ Authorization: "Bearer jwt-123",
117
+ });
118
+ expect(requestHeaders).toMatchObject({
119
+ "Content-Type": "application/json",
120
+ "X-Organization-Id": "org-123",
121
+ "X-Testkit-Actor": "primary",
122
+ });
123
+ expect(requestHeaders["X-Forwarded-For"]).toMatch(/^10\.\d+\.\d+\.\d+$/);
124
+ clearRuntimeContext();
125
+ });
126
+
127
+ it("builds local-json profile presets that derive session, multi-actor, and raw variants", () => {
128
+ const requests = [];
129
+ registerRuntimeContext({
130
+ env: {
131
+ BASE: "http://api.test",
132
+ },
133
+ http: {
134
+ post(url, body) {
135
+ const payload = JSON.parse(body);
136
+ requests.push({ url, payload });
137
+ const actor = payload.email.startsWith("primary")
138
+ ? "primary"
139
+ : payload.email.startsWith("user-a")
140
+ ? "userA"
141
+ : "userB";
142
+ return {
143
+ status: url.endsWith("/signup") ? 201 : 200,
144
+ body: JSON.stringify({
145
+ data: {
146
+ organizations: [{ id: `org-${actor}` }],
147
+ },
148
+ }),
149
+ headers: {
150
+ "set-cookie": [
151
+ `fixture_session=jwt-${actor}; Path=/`,
152
+ `fixture_refresh=refresh-${actor}; Path=/`,
153
+ ],
154
+ },
155
+ };
156
+ },
157
+ },
158
+ });
159
+
160
+ const auth = profiles.localJson({
161
+ password: "TestkitPass2026",
162
+ identities: {
163
+ primary: {
164
+ email: "primary@example.com",
165
+ name: "Primary User",
166
+ organizationName: "Primary Org",
167
+ },
168
+ userA: {
169
+ email: "user-a@example.com",
170
+ name: "User A",
171
+ organizationName: "Org A",
172
+ },
173
+ userB: {
174
+ email: "user-b@example.com",
175
+ name: "User B",
176
+ organizationName: "Org B",
177
+ },
178
+ },
179
+ session: {
180
+ authCookie: "fixture_session",
181
+ refreshCookie: "fixture_refresh",
182
+ organizationIdPath: "data.organizations[0].id",
183
+ },
184
+ headers: {
185
+ contentTypeJson: true,
186
+ forwardedFor: "deterministic",
187
+ organization: "X-Organization-Id",
188
+ },
189
+ });
190
+
191
+ const defaultProfile = auth.session();
192
+ const defaultSetup = defaultProfile.auth.setup({ env: { BASE: "http://api.test" } });
193
+ expect(defaultSetup).toEqual({
194
+ jwt: "jwt-primary",
195
+ refreshToken: "refresh-primary",
196
+ organizationId: "org-primary",
197
+ });
198
+ expect(defaultProfile.auth.headers(defaultSetup)).toEqual({
199
+ Authorization: "Bearer jwt-primary",
200
+ });
201
+ expect(defaultProfile.headers(defaultSetup, { env: { BASE: "http://api.test" } })).toMatchObject({
202
+ "Content-Type": "application/json",
203
+ "X-Organization-Id": "org-primary",
204
+ });
205
+
206
+ const dualProfile = auth.multiActor({
207
+ primaryActor: "userA",
208
+ actors: ["userA", "userB"],
209
+ });
210
+ const dualSetup = dualProfile.auth.setup({ env: { BASE: "http://api.test" } });
211
+ expect(dualSetup.userA.organizationId).toBe("org-userA");
212
+ expect(dualSetup.userB.organizationId).toBe("org-userB");
213
+ expect(dualProfile.auth.headers(dualSetup)).toEqual({
214
+ Authorization: "Bearer jwt-userA",
215
+ });
216
+
217
+ const rawProfile = auth.raw();
218
+ expect(rawProfile.rawHeaders(null, { env: { BASE: "http://api.test" } })).toMatchObject({
219
+ "Content-Type": "application/json",
220
+ });
221
+
222
+ expect(requests.map((entry) => entry.url)).toEqual([
223
+ "http://api.test/api/v1/auth/signup",
224
+ "http://api.test/api/v1/auth/login",
225
+ "http://api.test/api/v1/auth/signup",
226
+ "http://api.test/api/v1/auth/login",
227
+ "http://api.test/api/v1/auth/signup",
228
+ "http://api.test/api/v1/auth/login",
229
+ ]);
230
+ clearRuntimeContext();
231
+ });
232
+
233
+ it("builds multi-actor profiles and derives headers from the primary actor by default", () => {
234
+ const responses = {
235
+ alpha: {
236
+ status: 200,
237
+ body: JSON.stringify({ data: { organizations: [{ id: "org-alpha" }] } }),
238
+ headers: { "set-cookie": "fixture_session=token-alpha; Path=/" },
239
+ },
240
+ beta: {
241
+ status: 200,
242
+ body: JSON.stringify({ data: { organizations: [{ id: "org-beta" }] } }),
243
+ headers: { "set-cookie": "fixture_session=token-beta; Path=/" },
244
+ },
245
+ };
246
+ registerRuntimeContext({
247
+ env: {
248
+ BASE: "http://api.test",
249
+ },
250
+ http: {
251
+ post(_url, body) {
252
+ const payload = JSON.parse(body);
253
+ return payload.email.startsWith("alpha") ? responses.alpha : responses.beta;
254
+ },
255
+ },
256
+ });
257
+
258
+ const profile = profiles.multiActor({
259
+ primaryActor: "userA",
260
+ actors: {
261
+ userA: {
262
+ login: {
263
+ path: "/login",
264
+ body: () => ({ email: "alpha@example.com" }),
265
+ },
266
+ session: {
267
+ cookies: { jwt: "fixture_session" },
268
+ fields: { organizationId: "data.organizations[0].id" },
269
+ auth: { source: { key: "jwt" } },
270
+ },
271
+ },
272
+ userB: {
273
+ login: {
274
+ path: "/login",
275
+ body: () => ({ email: "beta@example.com" }),
276
+ },
277
+ session: {
278
+ cookies: { jwt: "fixture_session" },
279
+ fields: { organizationId: "data.organizations[0].id" },
280
+ auth: { source: { key: "jwt" } },
281
+ },
282
+ },
283
+ },
284
+ headers: {
285
+ fromSession: [{ header: "X-Organization-Id", field: "organizationId" }],
286
+ },
287
+ });
288
+
289
+ const setupData = profile.auth.setup({ env: { BASE: "http://api.test" } });
290
+ expect(setupData.userA.organizationId).toBe("org-alpha");
291
+ expect(setupData.userB.organizationId).toBe("org-beta");
292
+ expect(profile.auth.headers(setupData)).toEqual({
293
+ Authorization: "Bearer token-alpha",
294
+ });
295
+ expect(profile.headers(setupData, { env: { BASE: "http://api.test" } })).toMatchObject({
296
+ "X-Organization-Id": "org-alpha",
297
+ });
298
+ clearRuntimeContext();
21
299
  });
22
300
 
23
301
  it("defines file-local metadata plainly", () => {