@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.
@@ -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/http-methods.feature");
7
7
 
@@ -12,13 +12,13 @@ describeFeature(feature, ({ Scenario }) => {
12
12
  let error: Error | null = null;
13
13
 
14
14
  Scenario("GET method with query parameters", ({ Given, When, Then }) => {
15
- Given("I create a mock with GET endpoint:", (_, docString: string) => {
15
+ Given("I create a mock with a GET search endpoint", () => {
16
16
  mock = schmock();
17
17
  mock('GET /search', ({ query }) => ({
18
18
  results: [],
19
19
  query: query.q,
20
20
  page: parseInt(query.page || '1'),
21
- limit: parseInt(query.limit || '10')
21
+ limit: parseInt(query.limit || '10'),
22
22
  }));
23
23
  });
24
24
 
@@ -41,12 +41,12 @@ describeFeature(feature, ({ Scenario }) => {
41
41
  });
42
42
 
43
43
  Scenario("POST method with JSON body", ({ Given, When, Then, And }) => {
44
- Given("I create a mock with POST endpoint:", (_, docString: string) => {
44
+ Given("I create a mock with a POST users endpoint", () => {
45
45
  mock = schmock();
46
46
  mock('POST /users', ({ body }) => [201, {
47
47
  id: 123,
48
- ...body,
49
- createdAt: '2023-01-01T00:00:00Z'
48
+ ...(body as Record<string, unknown>),
49
+ createdAt: '2023-01-01T00:00:00Z',
50
50
  }]);
51
51
  });
52
52
 
@@ -66,12 +66,12 @@ describeFeature(feature, ({ Scenario }) => {
66
66
  });
67
67
 
68
68
  Scenario("PUT method for resource updates", ({ Given, When, Then }) => {
69
- Given("I create a mock with PUT endpoint:", (_, docString: string) => {
69
+ Given("I create a mock with a PUT users endpoint", () => {
70
70
  mock = schmock();
71
71
  mock('PUT /users/:id', ({ params, body }) => ({
72
72
  id: parseInt(params.id),
73
- ...body,
74
- updatedAt: '2023-01-01T00:00:00Z'
73
+ ...(body as Record<string, unknown>),
74
+ updatedAt: '2023-01-01T00:00:00Z',
75
75
  }));
76
76
  });
77
77
 
@@ -87,7 +87,7 @@ describeFeature(feature, ({ Scenario }) => {
87
87
  });
88
88
 
89
89
  Scenario("DELETE method with confirmation", ({ Given, When, Then, And }) => {
90
- Given("I create a mock with DELETE endpoint:", (_, docString: string) => {
90
+ Given("I create a mock with a DELETE users endpoint", () => {
91
91
  mock = schmock();
92
92
  mock('DELETE /users/:id', ({ params }) => [204, null]);
93
93
  });
@@ -106,13 +106,13 @@ describeFeature(feature, ({ Scenario }) => {
106
106
  });
107
107
 
108
108
  Scenario("PATCH method for partial updates", ({ Given, When, Then }) => {
109
- Given("I create a mock with PATCH endpoint:", (_, docString: string) => {
109
+ Given("I create a mock with a PATCH users endpoint", () => {
110
110
  mock = schmock();
111
111
  mock('PATCH /users/:id', ({ params, body }) => ({
112
112
  id: parseInt(params.id),
113
113
  email: 'existing@example.com',
114
- ...body,
115
- updatedAt: '2023-01-01T00:00:00Z'
114
+ ...(body as Record<string, unknown>),
115
+ updatedAt: '2023-01-01T00:00:00Z',
116
116
  }));
117
117
  });
118
118
 
@@ -128,12 +128,12 @@ describeFeature(feature, ({ Scenario }) => {
128
128
  });
129
129
 
130
130
  Scenario("HEAD method returns headers only", ({ Given, When, Then, And }) => {
131
- Given("I create a mock with HEAD endpoint:", (_, docString: string) => {
131
+ Given("I create a mock with a HEAD users endpoint", () => {
132
132
  mock = schmock();
133
133
  mock('HEAD /users/:id', ({ params }) => [200, null, {
134
134
  'Content-Type': 'application/json',
135
135
  'Last-Modified': 'Wed, 01 Jan 2023 00:00:00 GMT',
136
- 'Content-Length': '156'
136
+ 'Content-Length': '156',
137
137
  }]);
138
138
  });
139
139
 
@@ -157,12 +157,12 @@ describeFeature(feature, ({ Scenario }) => {
157
157
  });
158
158
 
159
159
  Scenario("OPTIONS method for CORS preflight", ({ Given, When, Then, And }) => {
160
- Given("I create a mock with OPTIONS endpoint:", (_, docString: string) => {
160
+ Given("I create a mock with an OPTIONS users endpoint", () => {
161
161
  mock = schmock();
162
162
  mock('OPTIONS /api/users', () => [200, null, {
163
163
  'Access-Control-Allow-Origin': '*',
164
164
  'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, OPTIONS',
165
- 'Access-Control-Allow-Headers': 'Content-Type, Authorization'
165
+ 'Access-Control-Allow-Headers': 'Content-Type, Authorization',
166
166
  }]);
167
167
  });
168
168
 
@@ -184,7 +184,7 @@ describeFeature(feature, ({ Scenario }) => {
184
184
  });
185
185
 
186
186
  Scenario("Multiple methods on same path", ({ Given, When, Then, And }) => {
187
- Given("I create a mock with multiple methods on same path:", (_, docString: string) => {
187
+ Given("I create a mock with GET, POST, PUT, and DELETE on the same path", () => {
188
188
  mock = schmock();
189
189
  mock('GET /resource', { action: 'read' });
190
190
  mock('POST /resource', { action: 'create' });
@@ -222,7 +222,7 @@ describeFeature(feature, ({ Scenario }) => {
222
222
  });
223
223
 
224
224
  Scenario("Method-specific content types", ({ Given, When, Then, And }) => {
225
- Given("I create a mock with method-specific content types:", (_, docString: string) => {
225
+ Given("I create a mock with JSON, XML, text, and upload endpoints", () => {
226
226
  mock = schmock();
227
227
  mock('GET /data.json', { data: 'json' });
228
228
  mock('GET /data.xml', '<data>xml</data>', { contentType: 'application/xml' });
@@ -258,14 +258,14 @@ describeFeature(feature, ({ Scenario }) => {
258
258
  Scenario("Method case sensitivity", ({ Given, When, Then }) => {
259
259
  error = null;
260
260
 
261
- Given("I create a mock with lowercase method:", (_, docString: string) => {
261
+ Given("I create an empty mock for case sensitivity testing", () => {
262
262
  mock = schmock();
263
263
  });
264
264
 
265
265
  When("I attempt to create a mock with lowercase method", () => {
266
266
  error = null;
267
267
  try {
268
- mock('get /test', { method: 'get' });
268
+ mock('get /test' as Schmock.RouteKey, { method: 'get' });
269
269
  } catch (e) {
270
270
  error = e as Error;
271
271
  }
@@ -281,14 +281,14 @@ describeFeature(feature, ({ Scenario }) => {
281
281
  Scenario("Unsupported HTTP methods", ({ Given, When, Then }) => {
282
282
  error = null;
283
283
 
284
- Given("I create a mock with custom method:", (_, docString: string) => {
284
+ Given("I create an empty mock for unsupported method testing", () => {
285
285
  mock = schmock();
286
286
  });
287
287
 
288
288
  When("I attempt to create a mock with unsupported method", () => {
289
289
  error = null;
290
290
  try {
291
- mock('CUSTOM /endpoint', { custom: true });
291
+ mock('CUSTOM /endpoint' as Schmock.RouteKey, { custom: true });
292
292
  } catch (e) {
293
293
  error = e as Error;
294
294
  }
@@ -302,11 +302,11 @@ describeFeature(feature, ({ Scenario }) => {
302
302
  });
303
303
 
304
304
  Scenario("Method with special characters in path", ({ Given, When, Then }) => {
305
- Given("I create a mock with special characters:", (_, docString: string) => {
305
+ Given("I create a mock with nested parameterized path segments", () => {
306
306
  mock = schmock();
307
307
  mock('GET /api/v1/users/:id/posts/:post-id', ({ params }) => ({
308
308
  userId: params.id,
309
- postId: params['post-id']
309
+ postId: params['post-id'],
310
310
  }));
311
311
  });
312
312
 
@@ -321,7 +321,7 @@ describeFeature(feature, ({ Scenario }) => {
321
321
  });
322
322
 
323
323
  Scenario("Method with request headers validation", ({ Given, When, Then, And }) => {
324
- Given("I create a mock with header validation:", (_, docString: string) => {
324
+ Given("I create a mock with authorization header checking", () => {
325
325
  mock = schmock();
326
326
  mock('POST /secure', ({ headers, body }) => {
327
327
  if (headers.authorization !== 'Bearer valid-token') {
@@ -361,18 +361,18 @@ describeFeature(feature, ({ Scenario }) => {
361
361
  });
362
362
 
363
363
  Scenario("Method chaining with plugins", ({ Given, When, Then, And }) => {
364
- Given("I create a mock with method-specific plugins:", (_, docString: string) => {
364
+ Given("I create a mock with a logger plugin on GET and POST", () => {
365
365
  mock = schmock();
366
- const loggerPlugin = {
366
+ const loggerPlugin: Plugin = {
367
367
  name: 'method-logger',
368
- process: (ctx: any, response: any) => ({
368
+ process: (ctx, response) => ({
369
369
  context: ctx,
370
370
  response: {
371
371
  ...response,
372
372
  method: ctx.method,
373
- logged: true
374
- }
375
- })
373
+ logged: true,
374
+ },
375
+ }),
376
376
  };
377
377
  mock('GET /logged', { data: 'get' }).pipe(loggerPlugin);
378
378
  mock('POST /logged', { data: 'post' }).pipe(loggerPlugin);
@@ -394,4 +394,4 @@ describeFeature(feature, ({ Scenario }) => {
394
394
  expect(responses[1].body).toEqual(expected);
395
395
  });
396
396
  });
397
- });
397
+ });
@@ -1,39 +1,35 @@
1
1
  import { describeFeature, loadFeature } from "@amiceli/vitest-cucumber";
2
2
  import { expect } from "vitest";
3
3
  import { schmock } from "../index";
4
- import type { MockInstance } from "../types";
4
+ import type { CallableMockInstance } from "../types";
5
5
 
6
6
  const feature = await loadFeature("../../features/performance-reliability.feature");
7
7
 
8
8
  describeFeature(feature, ({ Scenario }) => {
9
- let mock: MockInstance<any>;
9
+ let mock: CallableMockInstance;
10
10
  let responses: any[] = [];
11
11
  let responsesTimes: number[] = [];
12
+ let expectedResponseCount = 0;
12
13
 
13
14
  Scenario("High-volume concurrent requests", ({ Given, When, Then, And }) => {
14
15
  responses = [];
15
16
  responsesTimes = [];
16
17
 
17
- Given("I create a mock for load testing:", (_, docString: string) => {
18
- // Create mock with new callable API for load testing
18
+ Given("I create a mock for high-volume load testing", () => {
19
19
  mock = schmock();
20
-
21
- mock('GET /api/health', () => ({
22
- status: 'healthy',
23
- timestamp: Date.now()
20
+ mock('GET /api/health', () => ({
21
+ status: 'healthy',
22
+ timestamp: Date.now()
24
23
  }));
25
-
26
24
  mock('GET /api/data/:id', ({ params }) => ({
27
25
  id: params.id,
28
- data: Array.from({ length: 50 }, (_, i) => ({
29
- index: i,
30
- value: Math.random()
26
+ data: Array.from({ length: 50 }, (_, i) => ({
27
+ index: i,
28
+ value: Math.random()
31
29
  })),
32
30
  generated_at: new Date().toISOString()
33
31
  }));
34
-
35
32
  mock('POST /api/process', ({ body }) => {
36
- // Simulate processing time
37
33
  const items = Array.isArray(body) ? body : [body];
38
34
  return {
39
35
  processed: items.length,
@@ -47,6 +43,7 @@ describeFeature(feature, ({ Scenario }) => {
47
43
  const [method, path] = request.split(" ");
48
44
  responses = [];
49
45
  responsesTimes = [];
46
+ expectedResponseCount = count;
50
47
 
51
48
  const promises = Array.from({ length: count }, async () => {
52
49
  const startTime = Date.now();
@@ -61,8 +58,7 @@ describeFeature(feature, ({ Scenario }) => {
61
58
  });
62
59
 
63
60
  Then("all concurrent requests should complete successfully", () => {
64
- const expectedCount = responses.length;
65
- expect(responses).toHaveLength(expectedCount);
61
+ expect(responses).toHaveLength(expectedResponseCount);
66
62
  for (const response of responses) {
67
63
  expect(response.status).toBe(200);
68
64
  }
@@ -80,7 +76,7 @@ describeFeature(feature, ({ Scenario }) => {
80
76
 
81
77
  When("I send {int} concurrent requests to different {string} endpoints", async (_, count: number, pathPattern: string) => {
82
78
  responses = [];
83
-
79
+
84
80
  const promises = Array.from({ length: count }, async (_, i) => {
85
81
  const path = pathPattern.replace(":id", `id${i}`);
86
82
  return await mock.handle("GET", path);
@@ -104,6 +100,7 @@ describeFeature(feature, ({ Scenario }) => {
104
100
  When("I send {int} concurrent {string} requests with different payloads", async (_, count: number, request: string) => {
105
101
  const [method, path] = request.split(" ");
106
102
  responses = [];
103
+ expectedResponseCount = count;
107
104
 
108
105
  const promises = Array.from({ length: count }, async (_, i) => {
109
106
  return await mock.handle(method as any, path, {
@@ -115,8 +112,7 @@ describeFeature(feature, ({ Scenario }) => {
115
112
  });
116
113
 
117
114
  And("all concurrent requests should complete successfully", () => {
118
- const expectedCount = responses.length;
119
- expect(responses).toHaveLength(expectedCount);
115
+ expect(responses).toHaveLength(expectedResponseCount);
120
116
  for (const response of responses) {
121
117
  expect(response.status).toBe(200);
122
118
  }
@@ -130,19 +126,15 @@ describeFeature(feature, ({ Scenario }) => {
130
126
  });
131
127
 
132
128
  Scenario("Memory usage under sustained load", ({ Given, When, Then, And }) => {
133
- Given("I create a mock with potential memory concerns:", (_, docString: string) => {
134
- // Create mock with routes that handle large data
129
+ Given("I create a mock with large payload handling", () => {
135
130
  mock = schmock();
136
-
137
131
  mock('POST /api/large-data', ({ body }) => {
138
- // Create large response data
139
132
  const largeArray = Array.from({ length: 1000 }, (_, i) => ({
140
133
  id: i,
141
- data: 'x'.repeat(100), // 100 chars per item
134
+ data: 'x'.repeat(100),
142
135
  timestamp: Date.now(),
143
136
  payload: body
144
137
  }));
145
-
146
138
  return {
147
139
  results: largeArray,
148
140
  items: largeArray,
@@ -151,7 +143,6 @@ describeFeature(feature, ({ Scenario }) => {
151
143
  memory_usage: process.memoryUsage ? process.memoryUsage() : null
152
144
  };
153
145
  });
154
-
155
146
  mock('GET /api/accumulate/:count', ({ params }) => {
156
147
  const count = parseInt(params.count);
157
148
  const items = Array.from({ length: count }, (_, i) => ({
@@ -159,7 +150,6 @@ describeFeature(feature, ({ Scenario }) => {
159
150
  value: Math.random(),
160
151
  timestamp: Date.now()
161
152
  }));
162
-
163
153
  return {
164
154
  items: items,
165
155
  accumulated: items,
@@ -173,7 +163,7 @@ describeFeature(feature, ({ Scenario }) => {
173
163
  When("I send {int} requests to {string} with {int}KB payloads", async (_, count: number, request: string, payloadSize: number) => {
174
164
  const [method, path] = request.split(" ");
175
165
  responses = [];
176
-
166
+
177
167
  const largePayload = { data: 'x'.repeat(payloadSize * 1024) };
178
168
 
179
169
  for (let i = 0; i < count; i++) {
@@ -198,7 +188,7 @@ describeFeature(feature, ({ Scenario }) => {
198
188
  When("I request {string} multiple times", async (_, request: string) => {
199
189
  const [method, path] = request.split(" ");
200
190
  responses = [];
201
-
191
+
202
192
  for (let i = 0; i < 5; i++) {
203
193
  const response = await mock.handle(method as any, path);
204
194
  responses.push(response);
@@ -221,47 +211,34 @@ describeFeature(feature, ({ Scenario }) => {
221
211
  Scenario("Error resilience and recovery", ({ Given, When, Then, And }) => {
222
212
  responses = [];
223
213
 
224
- Given("I create a mock with intermittent failures:", (_, docString: string) => {
225
- // Create mock with intermittent failure simulation
214
+ Given("I create a mock with intermittent failure simulation", () => {
226
215
  mock = schmock();
227
-
228
216
  let requestCount = 0;
229
-
230
217
  mock('POST /api/unreliable', ({ body }) => {
231
218
  requestCount++;
232
-
233
- // Simulate 20% failure rate
234
219
  if (requestCount % 5 === 0) {
235
220
  return [500, { error: 'Simulated server error', request_id: requestCount }];
236
221
  }
237
-
238
222
  return [200, { success: true, data: body, request_id: requestCount }];
239
223
  });
240
-
241
224
  mock('GET /api/flaky', () => {
242
225
  requestCount++;
243
-
244
- // Simulate 20% failure rate (1 in 5 requests fail)
245
226
  if (requestCount % 5 === 0) {
246
227
  return [500, { error: 'Flaky service error', request_id: requestCount }];
247
228
  }
248
-
249
229
  return [200, { success: true, request_id: requestCount }];
250
230
  });
251
-
252
231
  mock('POST /api/validate-strict', ({ body }) => {
253
232
  if (!body || typeof body !== 'object') {
254
233
  return [400, { error: 'Request body is required and must be an object', code: 'INVALID_BODY' }];
255
234
  }
256
-
257
- if (!body.name || typeof body.name !== 'string') {
235
+ const record = body as Record<string, unknown>;
236
+ if (!record.name || typeof record.name !== 'string') {
258
237
  return [422, { error: 'Name field is required and must be a string', code: 'INVALID_NAME' }];
259
238
  }
260
-
261
- if (!body.email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(body.email)) {
239
+ if (!record.email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(record.email as string)) {
262
240
  return [422, { error: 'Valid email address is required', code: 'INVALID_EMAIL' }];
263
241
  }
264
-
265
242
  return [200, { message: 'Validation successful', data: body }];
266
243
  });
267
244
  });
@@ -279,7 +256,7 @@ describeFeature(feature, ({ Scenario }) => {
279
256
  Then("some requests should succeed and some should fail", () => {
280
257
  const successCount = responses.filter(r => r.status === 200).length;
281
258
  const errorCount = responses.filter(r => r.status >= 400).length;
282
-
259
+
283
260
  expect(successCount).toBeGreaterThan(0);
284
261
  expect(errorCount).toBeGreaterThan(0);
285
262
  expect(successCount + errorCount).toBe(responses.length);
@@ -288,7 +265,7 @@ describeFeature(feature, ({ Scenario }) => {
288
265
  And("the success rate should be approximately {int}%", (_, expectedRate: number) => {
289
266
  const successCount = responses.filter(r => r.status === 200).length;
290
267
  const actualRate = (successCount / responses.length) * 100;
291
-
268
+
292
269
  // Allow for some variance due to randomness
293
270
  expect(actualRate).toBeGreaterThan(expectedRate - 10);
294
271
  expect(actualRate).toBeLessThan(expectedRate + 10);
@@ -297,18 +274,18 @@ describeFeature(feature, ({ Scenario }) => {
297
274
  And("error responses should have appropriate status codes", () => {
298
275
  const errorResponses = responses.filter(r => r.status >= 400);
299
276
  const validErrorCodes = [429, 500, 503];
300
-
277
+
301
278
  for (const response of errorResponses) {
302
279
  expect(validErrorCodes).toContain(response.status);
303
280
  }
304
281
  });
305
282
 
306
283
  When("I send requests to {string} with various invalid inputs", async (_, request: string) => {
307
- const [method, path] = request.split(" ");
284
+ const [method, path] = request.split(" ");
308
285
  responses = [];
309
286
 
310
287
  // Test various invalid scenarios
311
- const testCases = [
288
+ const testCases: Schmock.RequestOptions[] = [
312
289
  { headers: {}, body: null }, // No content-type, no body
313
290
  { headers: { 'content-type': 'application/json' }, body: null }, // No body
314
291
  { headers: { 'content-type': 'application/json' }, body: "invalid" }, // Invalid body type
@@ -332,7 +309,7 @@ describeFeature(feature, ({ Scenario }) => {
332
309
 
333
310
  And("the error codes should correctly identify the validation issue", () => {
334
311
  expect(responses[0].status).toBe(400); // No content-type
335
- expect(responses[1].status).toBe(400); // No body
312
+ expect(responses[1].status).toBe(400); // No body
336
313
  expect(responses[2].status).toBe(400); // Invalid body type
337
314
  expect(responses[3].status).toBe(422); // Missing required field
338
315
  });
@@ -341,47 +318,44 @@ describeFeature(feature, ({ Scenario }) => {
341
318
  Scenario("Route matching performance with complex patterns", ({ Given, When, Then, And }) => {
342
319
  responses = [];
343
320
 
344
- Given("I create a mock with many route patterns:", (_, docString: string) => {
345
- // Create mock with many different route patterns for performance testing
321
+ Given("I create a mock with many nested route patterns", () => {
346
322
  mock = schmock();
347
-
348
- // Routes that match the test expectations
349
323
  mock('GET /api/users', () => ({ type: 'users-list' }));
350
324
  mock('GET /api/users/:id', ({ params }) => ({ type: 'user', id: params.id }));
351
325
  mock('GET /api/users/:userId/posts', ({ params }) => ({ type: 'user-posts', userId: params.userId }));
352
- mock('GET /api/users/:userId/posts/:postId', ({ params }) => ({
353
- type: 'user-post',
354
- userId: params.userId,
355
- postId: params.postId
326
+ mock('GET /api/users/:userId/posts/:postId', ({ params }) => ({
327
+ type: 'user-post',
328
+ userId: params.userId,
329
+ postId: params.postId
356
330
  }));
357
- mock('GET /api/users/:userId/posts/:postId/comments', ({ params }) => ({
358
- type: 'post-comments',
359
- userId: params.userId,
360
- postId: params.postId
331
+ mock('GET /api/users/:userId/posts/:postId/comments', ({ params }) => ({
332
+ type: 'post-comments',
333
+ userId: params.userId,
334
+ postId: params.postId
361
335
  }));
362
336
  mock('GET /api/posts', () => ({ type: 'posts-list' }));
363
337
  mock('GET /api/posts/:postId', ({ params }) => ({ type: 'post', postId: params.postId }));
364
- mock('GET /api/posts/:postId/comments/:commentId', ({ params }) => ({
365
- type: 'comment',
366
- postId: params.postId,
367
- commentId: params.commentId
338
+ mock('GET /api/posts/:postId/comments/:commentId', ({ params }) => ({
339
+ type: 'comment',
340
+ postId: params.postId,
341
+ commentId: params.commentId
368
342
  }));
369
- mock('GET /static/:category/:file', ({ params }) => ({
370
- type: 'static',
371
- category: params.category,
372
- file: params.file
343
+ mock('GET /static/:category/:file', ({ params }) => ({
344
+ type: 'static',
345
+ category: params.category,
346
+ file: params.file
373
347
  }));
374
- mock('GET /api/v2/users/:userId', ({ params }) => ({
375
- type: 'versioned-user',
376
- userId: params.userId,
377
- version: 'v2'
348
+ mock('GET /api/v2/users/:userId', ({ params }) => ({
349
+ type: 'versioned-user',
350
+ userId: params.userId,
351
+ version: 'v2'
378
352
  }));
379
353
  });
380
354
 
381
355
  When("I send requests to all route patterns simultaneously", async () => {
382
356
  const testPaths = [
383
357
  "GET /api/users",
384
- "GET /api/users/123",
358
+ "GET /api/users/123",
385
359
  "GET /api/users/123/posts",
386
360
  "GET /api/users/123/posts/456",
387
361
  "GET /api/users/123/posts/456/comments",
@@ -423,11 +397,6 @@ describeFeature(feature, ({ Scenario }) => {
423
397
  expect(responses[9].body.version).toBe("v2");
424
398
  });
425
399
 
426
- And("the route matching should be efficient even with many patterns", () => {
427
- // All requests completed quickly if we got here
428
- expect(responses).toHaveLength(10);
429
- });
430
-
431
400
  When("I send requests to non-matching paths", async () => {
432
401
  const invalidPaths = [
433
402
  "GET /api/invalid",
@@ -449,11 +418,6 @@ describeFeature(feature, ({ Scenario }) => {
449
418
  expect(response.status).toBe(expectedStatus);
450
419
  }
451
420
  });
452
-
453
- And("the {int} responses should be fast", (_, statusCode: number) => {
454
- // If we got here quickly, the 404 responses were fast
455
- expect(responses.every(r => r.status === statusCode)).toBe(true);
456
- });
457
421
  });
458
422
 
459
- });
423
+ });