@schmock/core 1.0.4 → 1.1.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/builder.d.ts +13 -5
- package/dist/builder.d.ts.map +1 -1
- package/dist/builder.js +139 -59
- package/dist/index.d.ts +2 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -11
- package/dist/parser.d.ts.map +1 -1
- package/dist/parser.js +2 -17
- package/dist/types.d.ts +17 -214
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -0
- package/package.json +1 -1
- package/src/builder.test.ts +2 -2
- package/src/builder.ts +216 -107
- package/src/constants.ts +1 -1
- package/src/index.ts +32 -29
- package/src/namespace.test.ts +3 -2
- package/src/parser.property.test.ts +495 -0
- package/src/parser.ts +2 -20
- package/src/steps/async-support.steps.ts +101 -91
- package/src/steps/basic-usage.steps.ts +49 -36
- package/src/steps/developer-experience.steps.ts +95 -97
- package/src/steps/error-handling.steps.ts +71 -72
- package/src/steps/fluent-api.steps.ts +75 -72
- package/src/steps/http-methods.steps.ts +33 -33
- package/src/steps/performance-reliability.steps.ts +52 -88
- package/src/steps/plugin-integration.steps.ts +176 -176
- package/src/steps/request-history.steps.ts +333 -0
- package/src/steps/state-concurrency.steps.ts +418 -316
- package/src/steps/stateful-workflows.steps.ts +138 -136
- package/src/types.ts +20 -271
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { describeFeature, loadFeature } from "@amiceli/vitest-cucumber";
|
|
2
2
|
import { expect } from "vitest";
|
|
3
3
|
import { schmock } from "../index";
|
|
4
|
-
import type { CallableMockInstance } from "../types";
|
|
4
|
+
import type { CallableMockInstance, Plugin } from "../types";
|
|
5
5
|
|
|
6
6
|
const feature = await loadFeature("../../features/async-support.feature");
|
|
7
7
|
|
|
@@ -13,11 +13,12 @@ describeFeature(feature, ({ Scenario }) => {
|
|
|
13
13
|
let endTime: number;
|
|
14
14
|
|
|
15
15
|
Scenario("Async generator function returns Promise", ({ Given, When, Then, And }) => {
|
|
16
|
-
Given("I create a mock with async generator
|
|
16
|
+
Given("I create a mock with an async generator at {string}", (_, route: string) => {
|
|
17
|
+
const [method, path] = route.split(" ");
|
|
17
18
|
mock = schmock();
|
|
18
|
-
mock(
|
|
19
|
+
mock(`${method} ${path}` as any, async () => {
|
|
19
20
|
await new Promise(resolve => setTimeout(resolve, 10));
|
|
20
|
-
return { message:
|
|
21
|
+
return { message: "async response" };
|
|
21
22
|
});
|
|
22
23
|
});
|
|
23
24
|
|
|
@@ -37,13 +38,14 @@ describeFeature(feature, ({ Scenario }) => {
|
|
|
37
38
|
});
|
|
38
39
|
|
|
39
40
|
Scenario("Async generator with context access", ({ Given, When, Then, And }) => {
|
|
40
|
-
Given("I create a mock with async
|
|
41
|
+
Given("I create a mock with an async param-based generator at {string}", (_, route: string) => {
|
|
42
|
+
const [method, path] = route.split(" ");
|
|
41
43
|
mock = schmock();
|
|
42
|
-
mock(
|
|
44
|
+
mock(`${method} ${path}` as any, async ({ params }: any) => {
|
|
43
45
|
await new Promise(resolve => setTimeout(resolve, 5));
|
|
44
|
-
return {
|
|
45
|
-
userId: params.id,
|
|
46
|
-
fetchedAt: new Date().toISOString()
|
|
46
|
+
return {
|
|
47
|
+
userId: params.id,
|
|
48
|
+
fetchedAt: new Date().toISOString(),
|
|
47
49
|
};
|
|
48
50
|
});
|
|
49
51
|
});
|
|
@@ -63,22 +65,22 @@ describeFeature(feature, ({ Scenario }) => {
|
|
|
63
65
|
});
|
|
64
66
|
|
|
65
67
|
Scenario("Multiple async generators in different routes", ({ Given, When, Then, And }) => {
|
|
66
|
-
Given("I create a mock with
|
|
68
|
+
Given("I create a mock with async routes for posts and comments", () => {
|
|
67
69
|
mock = schmock();
|
|
68
|
-
mock(
|
|
70
|
+
mock("GET /async-posts", async () => {
|
|
69
71
|
await new Promise(resolve => setTimeout(resolve, 5));
|
|
70
|
-
return [{ id: 1, title:
|
|
72
|
+
return [{ id: 1, title: "First Post" }];
|
|
71
73
|
});
|
|
72
|
-
mock(
|
|
74
|
+
mock("GET /async-comments", async () => {
|
|
73
75
|
await new Promise(resolve => setTimeout(resolve, 8));
|
|
74
|
-
return [{ id: 1, comment:
|
|
76
|
+
return [{ id: 1, comment: "Great post!" }];
|
|
75
77
|
});
|
|
76
78
|
});
|
|
77
79
|
|
|
78
80
|
When("I make concurrent requests to {string} and {string}", async (_, path1: string, path2: string) => {
|
|
79
81
|
const [posts, comments] = await Promise.all([
|
|
80
|
-
mock.handle(
|
|
81
|
-
mock.handle(
|
|
82
|
+
mock.handle("GET", path1),
|
|
83
|
+
mock.handle("GET", path2),
|
|
82
84
|
]);
|
|
83
85
|
responses = [posts, comments];
|
|
84
86
|
});
|
|
@@ -98,23 +100,24 @@ describeFeature(feature, ({ Scenario }) => {
|
|
|
98
100
|
});
|
|
99
101
|
|
|
100
102
|
Scenario("Async plugin processing", ({ Given, When, Then, And }) => {
|
|
101
|
-
Given("I create a mock with async plugin
|
|
103
|
+
Given("I create a mock with an async processing plugin at {string}", (_, route: string) => {
|
|
104
|
+
const [method, path] = route.split(" ");
|
|
102
105
|
mock = schmock();
|
|
103
|
-
const asyncPlugin = {
|
|
104
|
-
name:
|
|
105
|
-
process: async (ctx
|
|
106
|
+
const asyncPlugin: Plugin = {
|
|
107
|
+
name: "async-processor",
|
|
108
|
+
process: async (ctx, response) => {
|
|
106
109
|
await new Promise(resolve => setTimeout(resolve, 5));
|
|
107
110
|
return {
|
|
108
111
|
context: ctx,
|
|
109
112
|
response: {
|
|
110
113
|
data: response,
|
|
111
114
|
processedAsync: true,
|
|
112
|
-
timestamp: new Date().toISOString()
|
|
113
|
-
}
|
|
115
|
+
timestamp: new Date().toISOString(),
|
|
116
|
+
},
|
|
114
117
|
};
|
|
115
|
-
}
|
|
118
|
+
},
|
|
116
119
|
};
|
|
117
|
-
mock(
|
|
120
|
+
mock(`${method} ${path}` as any, { original: "data" }).pipe(asyncPlugin);
|
|
118
121
|
});
|
|
119
122
|
|
|
120
123
|
When("I request {string}", async (_, request: string) => {
|
|
@@ -127,7 +130,7 @@ describeFeature(feature, ({ Scenario }) => {
|
|
|
127
130
|
});
|
|
128
131
|
|
|
129
132
|
And("the async response should have property {string} with value {word}", (_, property: string, value: string) => {
|
|
130
|
-
const expectedValue = value ===
|
|
133
|
+
const expectedValue = value === "true" ? true : value === "false" ? false : value;
|
|
131
134
|
expect(response.body).toHaveProperty(property, expectedValue);
|
|
132
135
|
});
|
|
133
136
|
|
|
@@ -137,26 +140,27 @@ describeFeature(feature, ({ Scenario }) => {
|
|
|
137
140
|
});
|
|
138
141
|
|
|
139
142
|
Scenario("Mixed sync and async plugin pipeline", ({ Given, When, Then, And }) => {
|
|
140
|
-
Given("I create a mock with
|
|
143
|
+
Given("I create a mock with sync and async plugins at {string}", (_, route: string) => {
|
|
144
|
+
const [method, path] = route.split(" ");
|
|
141
145
|
mock = schmock();
|
|
142
|
-
const syncPlugin = {
|
|
143
|
-
name:
|
|
144
|
-
process: (ctx
|
|
146
|
+
const syncPlugin: Plugin = {
|
|
147
|
+
name: "sync-step",
|
|
148
|
+
process: (ctx, response) => ({
|
|
145
149
|
context: ctx,
|
|
146
|
-
response: { ...response, syncStep: true }
|
|
147
|
-
})
|
|
150
|
+
response: { ...response, syncStep: true },
|
|
151
|
+
}),
|
|
148
152
|
};
|
|
149
|
-
const asyncPlugin = {
|
|
150
|
-
name:
|
|
151
|
-
process: async (ctx
|
|
153
|
+
const asyncPlugin: Plugin = {
|
|
154
|
+
name: "async-step",
|
|
155
|
+
process: async (ctx, response) => {
|
|
152
156
|
await new Promise(resolve => setTimeout(resolve, 5));
|
|
153
157
|
return {
|
|
154
158
|
context: ctx,
|
|
155
|
-
response: { ...response, asyncStep: true }
|
|
159
|
+
response: { ...response, asyncStep: true },
|
|
156
160
|
};
|
|
157
|
-
}
|
|
161
|
+
},
|
|
158
162
|
};
|
|
159
|
-
mock(
|
|
163
|
+
mock(`${method} ${path}` as any, { base: "data" })
|
|
160
164
|
.pipe(syncPlugin)
|
|
161
165
|
.pipe(asyncPlugin);
|
|
162
166
|
});
|
|
@@ -171,22 +175,23 @@ describeFeature(feature, ({ Scenario }) => {
|
|
|
171
175
|
});
|
|
172
176
|
|
|
173
177
|
And("the response should have property {string} with value {word}", (_, property: string, value: string) => {
|
|
174
|
-
const expectedValue = value ===
|
|
178
|
+
const expectedValue = value === "true" ? true : value === "false" ? false : value;
|
|
175
179
|
expect(response.body).toHaveProperty(property, expectedValue);
|
|
176
180
|
});
|
|
177
181
|
|
|
178
182
|
And("the response should have property {string} with boolean value {word}", (_, property: string, value: string) => {
|
|
179
|
-
const expectedValue = value ===
|
|
183
|
+
const expectedValue = value === "true" ? true : value === "false" ? false : value;
|
|
180
184
|
expect(response.body).toHaveProperty(property, expectedValue);
|
|
181
185
|
});
|
|
182
186
|
});
|
|
183
187
|
|
|
184
188
|
Scenario("Async generator with Promise rejection", ({ Given, When, Then, And }) => {
|
|
185
|
-
Given("I create a mock with
|
|
189
|
+
Given("I create a mock with an async generator that throws at {string}", (_, route: string) => {
|
|
190
|
+
const [method, path] = route.split(" ");
|
|
186
191
|
mock = schmock();
|
|
187
|
-
mock(
|
|
192
|
+
mock(`${method} ${path}` as any, async () => {
|
|
188
193
|
await new Promise(resolve => setTimeout(resolve, 5));
|
|
189
|
-
throw new Error(
|
|
194
|
+
throw new Error("Async operation failed");
|
|
190
195
|
});
|
|
191
196
|
});
|
|
192
197
|
|
|
@@ -205,24 +210,25 @@ describeFeature(feature, ({ Scenario }) => {
|
|
|
205
210
|
});
|
|
206
211
|
|
|
207
212
|
Scenario("Async plugin error recovery", ({ Given, When, Then, And }) => {
|
|
208
|
-
Given("I create a mock with async error
|
|
213
|
+
Given("I create a mock with an async error-recovery plugin at {string}", (_, route: string) => {
|
|
214
|
+
const [method, path] = route.split(" ");
|
|
209
215
|
mock = schmock();
|
|
210
|
-
const asyncErrorPlugin = {
|
|
211
|
-
name:
|
|
216
|
+
const asyncErrorPlugin: Plugin = {
|
|
217
|
+
name: "async-error-handler",
|
|
212
218
|
process: async () => {
|
|
213
219
|
await new Promise(resolve => setTimeout(resolve, 5));
|
|
214
|
-
throw new Error(
|
|
220
|
+
throw new Error("Async plugin failed");
|
|
215
221
|
},
|
|
216
|
-
onError: async (error
|
|
222
|
+
onError: async (error) => {
|
|
217
223
|
await new Promise(resolve => setTimeout(resolve, 3));
|
|
218
224
|
return {
|
|
219
225
|
status: 200,
|
|
220
226
|
body: { recovered: true, originalError: error.message },
|
|
221
|
-
headers: {}
|
|
227
|
+
headers: {},
|
|
222
228
|
};
|
|
223
|
-
}
|
|
229
|
+
},
|
|
224
230
|
};
|
|
225
|
-
mock(
|
|
231
|
+
mock(`${method} ${path}` as any, "original").pipe(asyncErrorPlugin);
|
|
226
232
|
});
|
|
227
233
|
|
|
228
234
|
When("I request {string}", async (_, request: string) => {
|
|
@@ -235,7 +241,7 @@ describeFeature(feature, ({ Scenario }) => {
|
|
|
235
241
|
});
|
|
236
242
|
|
|
237
243
|
And("the response should have property {string} with value {word}", (_, property: string, value: string) => {
|
|
238
|
-
const expectedValue = value ===
|
|
244
|
+
const expectedValue = value === "true" ? true : value === "false" ? false : value;
|
|
239
245
|
expect(response.body).toHaveProperty(property, expectedValue);
|
|
240
246
|
});
|
|
241
247
|
|
|
@@ -245,9 +251,10 @@ describeFeature(feature, ({ Scenario }) => {
|
|
|
245
251
|
});
|
|
246
252
|
|
|
247
253
|
Scenario("Async generator with delay configuration", ({ Given, When, Then, And }) => {
|
|
248
|
-
Given("I create a mock with async generator
|
|
254
|
+
Given("I create a mock with delay 20ms and async generator at {string}", (_, route: string) => {
|
|
255
|
+
const [method, path] = route.split(" ");
|
|
249
256
|
mock = schmock({ delay: 20 });
|
|
250
|
-
mock(
|
|
257
|
+
mock(`${method} ${path}` as any, async () => {
|
|
251
258
|
await new Promise(resolve => setTimeout(resolve, 10));
|
|
252
259
|
return { delayed: true, async: true };
|
|
253
260
|
});
|
|
@@ -272,14 +279,15 @@ describeFeature(feature, ({ Scenario }) => {
|
|
|
272
279
|
});
|
|
273
280
|
|
|
274
281
|
Scenario("Async generator with state management", ({ Given, When, Then, And }) => {
|
|
275
|
-
Given("I create a mock with async stateful
|
|
282
|
+
Given("I create a mock with async stateful counter at {string}", (_, route: string) => {
|
|
283
|
+
const [method, path] = route.split(" ");
|
|
276
284
|
mock = schmock({ state: { asyncCounter: 0 } });
|
|
277
|
-
mock(
|
|
285
|
+
mock(`${method} ${path}` as any, async ({ state }: any) => {
|
|
278
286
|
await new Promise(resolve => setTimeout(resolve, 5));
|
|
279
287
|
state.asyncCounter = (state.asyncCounter || 0) + 1;
|
|
280
|
-
return {
|
|
288
|
+
return {
|
|
281
289
|
count: state.asyncCounter,
|
|
282
|
-
processedAsync: true
|
|
290
|
+
processedAsync: true,
|
|
283
291
|
};
|
|
284
292
|
});
|
|
285
293
|
});
|
|
@@ -300,26 +308,27 @@ describeFeature(feature, ({ Scenario }) => {
|
|
|
300
308
|
});
|
|
301
309
|
|
|
302
310
|
And("both responses should have processedAsync {word}", (_, value: string) => {
|
|
303
|
-
const expectedValue = value ===
|
|
311
|
+
const expectedValue = value === "true" ? true : value === "false" ? false : value;
|
|
304
312
|
expect(responses[0].body.processedAsync).toBe(expectedValue);
|
|
305
313
|
expect(responses[1].body.processedAsync).toBe(expectedValue);
|
|
306
314
|
});
|
|
307
315
|
});
|
|
308
316
|
|
|
309
317
|
Scenario("Promise-based plugin response generation", ({ Given, When, Then }) => {
|
|
310
|
-
Given("I create a mock with Promise-generating plugin
|
|
318
|
+
Given("I create a mock with a Promise-generating plugin at {string}", (_, route: string) => {
|
|
319
|
+
const [method, path] = route.split(" ");
|
|
311
320
|
mock = schmock();
|
|
312
|
-
const promisePlugin = {
|
|
313
|
-
name:
|
|
314
|
-
process: async (ctx
|
|
321
|
+
const promisePlugin: Plugin = {
|
|
322
|
+
name: "promise-generator",
|
|
323
|
+
process: async (ctx, response) => {
|
|
315
324
|
if (!response) {
|
|
316
|
-
const data = await Promise.resolve({ generated:
|
|
325
|
+
const data = await Promise.resolve({ generated: "by promise" });
|
|
317
326
|
return { context: ctx, response: data };
|
|
318
327
|
}
|
|
319
328
|
return { context: ctx, response };
|
|
320
|
-
}
|
|
329
|
+
},
|
|
321
330
|
};
|
|
322
|
-
mock(
|
|
331
|
+
mock(`${method} ${path}` as any, null).pipe(promisePlugin);
|
|
323
332
|
});
|
|
324
333
|
|
|
325
334
|
When("I request {string}", async (_, request: string) => {
|
|
@@ -334,33 +343,33 @@ describeFeature(feature, ({ Scenario }) => {
|
|
|
334
343
|
});
|
|
335
344
|
|
|
336
345
|
Scenario("Concurrent async requests isolation", ({ Given, When, Then, And }) => {
|
|
337
|
-
Given("I create a mock with async
|
|
346
|
+
Given("I create a mock with async delay per id at {string}", (_, route: string) => {
|
|
347
|
+
const [method, path] = route.split(" ");
|
|
338
348
|
mock = schmock();
|
|
339
|
-
mock(
|
|
349
|
+
mock(`${method} ${path}` as any, async ({ params }: any) => {
|
|
340
350
|
const delay = parseInt(params.id) * 5;
|
|
341
351
|
await new Promise(resolve => setTimeout(resolve, delay));
|
|
342
|
-
return {
|
|
352
|
+
return {
|
|
343
353
|
id: params.id,
|
|
344
|
-
processedAt: Date.now()
|
|
354
|
+
processedAt: Date.now(),
|
|
345
355
|
};
|
|
346
356
|
});
|
|
347
357
|
});
|
|
348
358
|
|
|
349
359
|
When("I make concurrent requests to {string}, {string}, and {string}", async (_, path1: string, path2: string, path3: string) => {
|
|
350
360
|
const promises = [
|
|
351
|
-
mock.handle(
|
|
352
|
-
mock.handle(
|
|
353
|
-
mock.handle(
|
|
361
|
+
mock.handle("GET", path1),
|
|
362
|
+
mock.handle("GET", path2),
|
|
363
|
+
mock.handle("GET", path3),
|
|
354
364
|
];
|
|
355
365
|
responses = await Promise.all(promises);
|
|
356
366
|
});
|
|
357
367
|
|
|
358
368
|
Then("all responses should have different processedAt timestamps", () => {
|
|
359
369
|
const timestamps = responses.map(r => r.body.processedAt);
|
|
360
|
-
const uniqueTimestamps = new Set(timestamps);
|
|
361
370
|
// In fast test environments, timestamps might be the same, so just check they exist
|
|
362
371
|
expect(timestamps).toHaveLength(3);
|
|
363
|
-
timestamps.forEach(timestamp => expect(timestamp).toBeGreaterThan(0));
|
|
372
|
+
timestamps.forEach((timestamp: number) => expect(timestamp).toBeGreaterThan(0));
|
|
364
373
|
});
|
|
365
374
|
|
|
366
375
|
And("each response should have the correct id value", () => {
|
|
@@ -373,39 +382,40 @@ describeFeature(feature, ({ Scenario }) => {
|
|
|
373
382
|
// All responses should be successful regardless of timing
|
|
374
383
|
for (const response of responses) {
|
|
375
384
|
expect(response.status).toBe(200);
|
|
376
|
-
expect(response.body).toHaveProperty(
|
|
377
|
-
expect(response.body).toHaveProperty(
|
|
385
|
+
expect(response.body).toHaveProperty("id");
|
|
386
|
+
expect(response.body).toHaveProperty("processedAt");
|
|
378
387
|
}
|
|
379
388
|
});
|
|
380
389
|
});
|
|
381
390
|
|
|
382
391
|
Scenario("Async plugin pipeline with context state", ({ Given, When, Then, And }) => {
|
|
383
|
-
Given("I create a mock with async stateful plugins
|
|
392
|
+
Given("I create a mock with two async stateful plugins at {string}", (_, route: string) => {
|
|
393
|
+
const [method, path] = route.split(" ");
|
|
384
394
|
mock = schmock();
|
|
385
|
-
const plugin1 = {
|
|
386
|
-
name:
|
|
387
|
-
process: async (ctx
|
|
395
|
+
const plugin1: Plugin = {
|
|
396
|
+
name: "async-step-1",
|
|
397
|
+
process: async (ctx, response) => {
|
|
388
398
|
await new Promise(resolve => setTimeout(resolve, 5));
|
|
389
|
-
ctx.state.set(
|
|
399
|
+
ctx.state.set("step1", "completed");
|
|
390
400
|
return { context: ctx, response };
|
|
391
|
-
}
|
|
401
|
+
},
|
|
392
402
|
};
|
|
393
|
-
const plugin2 = {
|
|
394
|
-
name:
|
|
395
|
-
process: async (ctx
|
|
403
|
+
const plugin2: Plugin = {
|
|
404
|
+
name: "async-step-2",
|
|
405
|
+
process: async (ctx, response) => {
|
|
396
406
|
await new Promise(resolve => setTimeout(resolve, 3));
|
|
397
|
-
const step1Status = ctx.state.get(
|
|
407
|
+
const step1Status = ctx.state.get("step1");
|
|
398
408
|
return {
|
|
399
409
|
context: ctx,
|
|
400
410
|
response: {
|
|
401
411
|
...response,
|
|
402
412
|
step1: step1Status,
|
|
403
|
-
step2:
|
|
404
|
-
}
|
|
413
|
+
step2: "completed",
|
|
414
|
+
},
|
|
405
415
|
};
|
|
406
|
-
}
|
|
416
|
+
},
|
|
407
417
|
};
|
|
408
|
-
mock(
|
|
418
|
+
mock(`${method} ${path}` as any, { base: "data" })
|
|
409
419
|
.pipe(plugin1)
|
|
410
420
|
.pipe(plugin2);
|
|
411
421
|
});
|
|
@@ -424,4 +434,4 @@ describeFeature(feature, ({ Scenario }) => {
|
|
|
424
434
|
expect(response.body).toHaveProperty("step2", "completed");
|
|
425
435
|
});
|
|
426
436
|
});
|
|
427
|
-
});
|
|
437
|
+
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { describeFeature, loadFeature } from "@amiceli/vitest-cucumber";
|
|
2
2
|
import { expect } from "vitest";
|
|
3
|
-
import { schmock } from "../index";
|
|
4
3
|
import type { CallableMockInstance } from "../types";
|
|
4
|
+
import { schmock } from "../index";
|
|
5
5
|
|
|
6
6
|
const feature = await loadFeature("../../features/basic-usage.feature");
|
|
7
7
|
|
|
@@ -10,9 +10,10 @@ describeFeature(feature, ({ Scenario }) => {
|
|
|
10
10
|
let response: any;
|
|
11
11
|
|
|
12
12
|
Scenario("Simplest possible mock - plain text", ({ Given, When, Then, And }) => {
|
|
13
|
-
Given("I create a mock
|
|
13
|
+
Given("I create a plain text mock returning {string} at {string}", (_, text: string, route: string) => {
|
|
14
|
+
const [method, path] = route.split(" ");
|
|
14
15
|
mock = schmock();
|
|
15
|
-
mock(
|
|
16
|
+
mock(`${method} ${path}` as Schmock.RouteKey, text);
|
|
16
17
|
});
|
|
17
18
|
|
|
18
19
|
When("I request {string}", async (_, request: string) => {
|
|
@@ -30,9 +31,10 @@ describeFeature(feature, ({ Scenario }) => {
|
|
|
30
31
|
});
|
|
31
32
|
|
|
32
33
|
Scenario("Return JSON without specifying contentType", ({ Given, When, Then, And }) => {
|
|
33
|
-
Given("I create a mock
|
|
34
|
+
Given("I create a mock returning a JSON array at {string}", (_, route: string) => {
|
|
35
|
+
const [method, path] = route.split(" ");
|
|
34
36
|
mock = schmock();
|
|
35
|
-
mock(
|
|
37
|
+
mock(`${method} ${path}` as Schmock.RouteKey, [{ id: 1, name: "John" }]);
|
|
36
38
|
});
|
|
37
39
|
|
|
38
40
|
When("I request {string}", async (_, request: string) => {
|
|
@@ -51,9 +53,10 @@ describeFeature(feature, ({ Scenario }) => {
|
|
|
51
53
|
});
|
|
52
54
|
|
|
53
55
|
Scenario("Return object without contentType", ({ Given, When, Then, And }) => {
|
|
54
|
-
Given("I create a mock
|
|
56
|
+
Given("I create a mock returning a JSON object at {string}", (_, route: string) => {
|
|
57
|
+
const [method, path] = route.split(" ");
|
|
55
58
|
mock = schmock();
|
|
56
|
-
mock(
|
|
59
|
+
mock(`${method} ${path}` as Schmock.RouteKey, { id: 1, name: "John" });
|
|
57
60
|
});
|
|
58
61
|
|
|
59
62
|
When("I request {string}", async (_, request: string) => {
|
|
@@ -72,7 +75,7 @@ describeFeature(feature, ({ Scenario }) => {
|
|
|
72
75
|
});
|
|
73
76
|
|
|
74
77
|
Scenario("Empty mock instance", ({ Given, When, Then }) => {
|
|
75
|
-
Given("I create
|
|
78
|
+
Given("I create an empty mock with no routes", () => {
|
|
76
79
|
mock = schmock();
|
|
77
80
|
});
|
|
78
81
|
|
|
@@ -87,9 +90,10 @@ describeFeature(feature, ({ Scenario }) => {
|
|
|
87
90
|
});
|
|
88
91
|
|
|
89
92
|
Scenario("Null response", ({ Given, When, Then, And }) => {
|
|
90
|
-
Given("I create a mock
|
|
93
|
+
Given("I create a mock returning null at {string}", (_, route: string) => {
|
|
94
|
+
const [method, path] = route.split(" ");
|
|
91
95
|
mock = schmock();
|
|
92
|
-
mock(
|
|
96
|
+
mock(`${method} ${path}` as Schmock.RouteKey, null);
|
|
93
97
|
});
|
|
94
98
|
|
|
95
99
|
When("I request {string}", async (_, request: string) => {
|
|
@@ -107,9 +111,10 @@ describeFeature(feature, ({ Scenario }) => {
|
|
|
107
111
|
});
|
|
108
112
|
|
|
109
113
|
Scenario("Undefined response", ({ Given, When, Then, And }) => {
|
|
110
|
-
Given("I create a mock
|
|
114
|
+
Given("I create a mock returning undefined at {string}", (_, route: string) => {
|
|
115
|
+
const [method, path] = route.split(" ");
|
|
111
116
|
mock = schmock();
|
|
112
|
-
mock(
|
|
117
|
+
mock(`${method} ${path}` as Schmock.RouteKey, undefined);
|
|
113
118
|
});
|
|
114
119
|
|
|
115
120
|
When("I request {string}", async (_, request: string) => {
|
|
@@ -127,9 +132,10 @@ describeFeature(feature, ({ Scenario }) => {
|
|
|
127
132
|
});
|
|
128
133
|
|
|
129
134
|
Scenario("Empty string response", ({ Given, When, Then, And }) => {
|
|
130
|
-
Given("I create a mock
|
|
135
|
+
Given("I create a mock returning empty string at {string}", (_, route: string) => {
|
|
136
|
+
const [method, path] = route.split(" ");
|
|
131
137
|
mock = schmock();
|
|
132
|
-
mock(
|
|
138
|
+
mock(`${method} ${path}` as Schmock.RouteKey, "");
|
|
133
139
|
});
|
|
134
140
|
|
|
135
141
|
When("I request {string}", async (_, request: string) => {
|
|
@@ -147,9 +153,10 @@ describeFeature(feature, ({ Scenario }) => {
|
|
|
147
153
|
});
|
|
148
154
|
|
|
149
155
|
Scenario("Number response", ({ Given, When, Then, And }) => {
|
|
150
|
-
Given("I create a mock
|
|
156
|
+
Given("I create a mock returning number {int} at {string}", (_, num: number, route: string) => {
|
|
157
|
+
const [method, path] = route.split(" ");
|
|
151
158
|
mock = schmock();
|
|
152
|
-
mock(
|
|
159
|
+
mock(`${method} ${path}` as Schmock.RouteKey, num);
|
|
153
160
|
});
|
|
154
161
|
|
|
155
162
|
When("I request {string}", async (_, request: string) => {
|
|
@@ -167,9 +174,10 @@ describeFeature(feature, ({ Scenario }) => {
|
|
|
167
174
|
});
|
|
168
175
|
|
|
169
176
|
Scenario("Boolean response", ({ Given, When, Then, And }) => {
|
|
170
|
-
Given("I create a mock
|
|
177
|
+
Given("I create a mock returning boolean true at {string}", (_, route: string) => {
|
|
178
|
+
const [method, path] = route.split(" ");
|
|
171
179
|
mock = schmock();
|
|
172
|
-
mock(
|
|
180
|
+
mock(`${method} ${path}` as Schmock.RouteKey, true);
|
|
173
181
|
});
|
|
174
182
|
|
|
175
183
|
When("I request {string}", async (_, request: string) => {
|
|
@@ -187,9 +195,10 @@ describeFeature(feature, ({ Scenario }) => {
|
|
|
187
195
|
});
|
|
188
196
|
|
|
189
197
|
Scenario("Function returning string", ({ Given, When, Then }) => {
|
|
190
|
-
Given("I create a mock with
|
|
198
|
+
Given("I create a mock with a string generator at {string}", (_, route: string) => {
|
|
199
|
+
const [method, path] = route.split(" ");
|
|
191
200
|
mock = schmock();
|
|
192
|
-
mock(
|
|
201
|
+
mock(`${method} ${path}` as Schmock.RouteKey, () => "Dynamic response");
|
|
193
202
|
});
|
|
194
203
|
|
|
195
204
|
When("I request {string}", async (_, request: string) => {
|
|
@@ -203,9 +212,10 @@ describeFeature(feature, ({ Scenario }) => {
|
|
|
203
212
|
});
|
|
204
213
|
|
|
205
214
|
Scenario("Function returning object", ({ Given, When, Then, And }) => {
|
|
206
|
-
Given("I create a mock with
|
|
215
|
+
Given("I create a mock with an object generator at {string}", (_, route: string) => {
|
|
216
|
+
const [method, path] = route.split(" ");
|
|
207
217
|
mock = schmock();
|
|
208
|
-
mock(
|
|
218
|
+
mock(`${method} ${path}` as Schmock.RouteKey, () => ({ timestamp: Date.now() }));
|
|
209
219
|
});
|
|
210
220
|
|
|
211
221
|
When("I request {string}", async (_, request: string) => {
|
|
@@ -227,17 +237,17 @@ describeFeature(feature, ({ Scenario }) => {
|
|
|
227
237
|
let aboutResponse: any;
|
|
228
238
|
let contactResponse: any;
|
|
229
239
|
|
|
230
|
-
Given("I create a mock with
|
|
240
|
+
Given("I create a mock with three routes", () => {
|
|
231
241
|
mock = schmock();
|
|
232
|
-
mock(
|
|
233
|
-
mock(
|
|
234
|
-
mock(
|
|
242
|
+
mock("GET /", "Home");
|
|
243
|
+
mock("GET /about", "About Us");
|
|
244
|
+
mock("GET /contact", { email: "test@example.com" });
|
|
235
245
|
});
|
|
236
246
|
|
|
237
247
|
When("I make three requests to different routes", async () => {
|
|
238
|
-
homeResponse = await mock.handle(
|
|
239
|
-
aboutResponse = await mock.handle(
|
|
240
|
-
contactResponse = await mock.handle(
|
|
248
|
+
homeResponse = await mock.handle("GET", "/");
|
|
249
|
+
aboutResponse = await mock.handle("GET", "/about");
|
|
250
|
+
contactResponse = await mock.handle("GET", "/contact");
|
|
241
251
|
});
|
|
242
252
|
|
|
243
253
|
Then("the home route should return {string}", (_, expectedText: string) => {
|
|
@@ -255,9 +265,10 @@ describeFeature(feature, ({ Scenario }) => {
|
|
|
255
265
|
});
|
|
256
266
|
|
|
257
267
|
Scenario("Override contentType detection", ({ Given, When, Then, And }) => {
|
|
258
|
-
Given("I create a mock with
|
|
268
|
+
Given("I create a mock with explicit text/plain contentType at {string}", (_, route: string) => {
|
|
269
|
+
const [method, path] = route.split(" ");
|
|
259
270
|
mock = schmock();
|
|
260
|
-
mock(
|
|
271
|
+
mock(`${method} ${path}` as Schmock.RouteKey, { foo: "bar" }, { contentType: "text/plain" });
|
|
261
272
|
});
|
|
262
273
|
|
|
263
274
|
When("I request {string}", async (_, request: string) => {
|
|
@@ -275,9 +286,10 @@ describeFeature(feature, ({ Scenario }) => {
|
|
|
275
286
|
});
|
|
276
287
|
|
|
277
288
|
Scenario("HTML response", ({ Given, When, Then, And }) => {
|
|
278
|
-
Given("I create a mock
|
|
289
|
+
Given("I create a mock returning HTML at {string}", (_, route: string) => {
|
|
290
|
+
const [method, path] = route.split(" ");
|
|
279
291
|
mock = schmock();
|
|
280
|
-
mock(
|
|
292
|
+
mock(`${method} ${path}` as Schmock.RouteKey, "<h1>Hello</h1>", { contentType: "text/html" });
|
|
281
293
|
});
|
|
282
294
|
|
|
283
295
|
When("I request {string}", async (_, request: string) => {
|
|
@@ -295,9 +307,10 @@ describeFeature(feature, ({ Scenario }) => {
|
|
|
295
307
|
});
|
|
296
308
|
|
|
297
309
|
Scenario("Binary/buffer response detection", ({ Given, When, Then, And }) => {
|
|
298
|
-
Given("I create a mock
|
|
310
|
+
Given("I create a mock returning a Buffer at {string}", (_, route: string) => {
|
|
311
|
+
const [method, path] = route.split(" ");
|
|
299
312
|
mock = schmock();
|
|
300
|
-
mock(
|
|
313
|
+
mock(`${method} ${path}` as Schmock.RouteKey, Buffer.from("binary data") as unknown as Schmock.Generator);
|
|
301
314
|
});
|
|
302
315
|
|
|
303
316
|
When("I request {string}", async (_, request: string) => {
|
|
@@ -313,4 +326,4 @@ describeFeature(feature, ({ Scenario }) => {
|
|
|
313
326
|
expect(response.headers?.["content-type"]).toBe(contentType);
|
|
314
327
|
});
|
|
315
328
|
});
|
|
316
|
-
});
|
|
329
|
+
});
|