@schmock/core 2.2.3 → 2.3.1

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.
Files changed (94) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +35 -0
  3. package/dist/abort.d.ts +3 -0
  4. package/dist/abort.d.ts.map +1 -0
  5. package/dist/abort.js +30 -0
  6. package/dist/binary.d.ts +8 -0
  7. package/dist/binary.d.ts.map +1 -0
  8. package/dist/binary.js +9 -0
  9. package/dist/builder.d.ts +31 -10
  10. package/dist/builder.d.ts.map +1 -1
  11. package/dist/builder.js +804 -203
  12. package/dist/constants.d.ts +38 -0
  13. package/dist/constants.d.ts.map +1 -1
  14. package/dist/constants.js +123 -2
  15. package/dist/errors.d.ts +14 -3
  16. package/dist/errors.d.ts.map +1 -1
  17. package/dist/errors.js +41 -6
  18. package/dist/helpers.d.ts +9 -0
  19. package/dist/helpers.d.ts.map +1 -1
  20. package/dist/helpers.js +18 -2
  21. package/dist/http-helpers.d.ts +52 -5
  22. package/dist/http-helpers.d.ts.map +1 -1
  23. package/dist/http-helpers.js +153 -37
  24. package/dist/index.d.ts +381 -60
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +9 -3
  27. package/dist/interceptor.d.ts +11 -1
  28. package/dist/interceptor.d.ts.map +1 -1
  29. package/dist/interceptor.js +354 -156
  30. package/dist/parser.d.ts.map +1 -1
  31. package/dist/parser.js +12 -3
  32. package/dist/plugin-pipeline.d.ts +11 -4
  33. package/dist/plugin-pipeline.d.ts.map +1 -1
  34. package/dist/plugin-pipeline.js +117 -39
  35. package/dist/response-normalizer.d.ts +16 -0
  36. package/dist/response-normalizer.d.ts.map +1 -0
  37. package/dist/response-normalizer.js +316 -0
  38. package/dist/response-parser.d.ts.map +1 -1
  39. package/dist/response-parser.js +85 -18
  40. package/dist/route-matcher.d.ts +3 -0
  41. package/dist/route-matcher.d.ts.map +1 -1
  42. package/dist/route-matcher.js +12 -6
  43. package/dist/types.d.ts +7 -2
  44. package/dist/types.d.ts.map +1 -1
  45. package/package.json +18 -8
  46. package/src/audit-core-builder.test.ts +0 -218
  47. package/src/audit-response-guard.test.ts +0 -38
  48. package/src/builder.test.ts +0 -289
  49. package/src/builder.ts +0 -701
  50. package/src/constants.test.ts +0 -99
  51. package/src/constants.ts +0 -73
  52. package/src/debug.test.ts +0 -241
  53. package/src/delay.test.ts +0 -319
  54. package/src/dist-shape.test.ts +0 -35
  55. package/src/errors.test.ts +0 -223
  56. package/src/errors.ts +0 -130
  57. package/src/factory.test.ts +0 -133
  58. package/src/helpers.test.ts +0 -147
  59. package/src/helpers.ts +0 -58
  60. package/src/http-helpers.ts +0 -113
  61. package/src/index.ts +0 -151
  62. package/src/interceptor.test.ts +0 -291
  63. package/src/interceptor.ts +0 -320
  64. package/src/namespace.test.ts +0 -274
  65. package/src/parser.property.test.ts +0 -594
  66. package/src/parser.test.ts +0 -148
  67. package/src/parser.ts +0 -64
  68. package/src/plugin-pipeline.ts +0 -103
  69. package/src/plugin-system.test.ts +0 -602
  70. package/src/response-parser.ts +0 -75
  71. package/src/response-parsing.test.ts +0 -333
  72. package/src/route-matcher.ts +0 -69
  73. package/src/route-matching.test.ts +0 -394
  74. package/src/server.test.ts +0 -165
  75. package/src/smart-defaults.test.ts +0 -361
  76. package/src/steps/async-support.steps.ts +0 -400
  77. package/src/steps/audit-core-builder.steps.ts +0 -188
  78. package/src/steps/audit-onerror-tuple.steps.ts +0 -99
  79. package/src/steps/basic-usage.steps.ts +0 -245
  80. package/src/steps/developer-experience.steps.ts +0 -204
  81. package/src/steps/error-handling.steps.ts +0 -345
  82. package/src/steps/fluent-api.steps.ts +0 -255
  83. package/src/steps/http-methods.steps.ts +0 -331
  84. package/src/steps/interceptor.steps.ts +0 -260
  85. package/src/steps/lifecycle-events.steps.ts +0 -142
  86. package/src/steps/performance-reliability.steps.ts +0 -423
  87. package/src/steps/plugin-integration.steps.ts +0 -280
  88. package/src/steps/request-history.steps.ts +0 -276
  89. package/src/steps/response-delay.steps.ts +0 -88
  90. package/src/steps/route-key-format.steps.ts +0 -99
  91. package/src/steps/standalone-server.steps.ts +0 -233
  92. package/src/steps/state-concurrency.steps.ts +0 -739
  93. package/src/steps/stateful-workflows.steps.ts +0 -353
  94. package/src/types.ts +0 -36
@@ -1,99 +0,0 @@
1
- import { describeFeature, loadFeature } from "@amiceli/vitest-cucumber";
2
- import { expect } from "vitest";
3
- import type { ParsedRoute } from "../parser";
4
- import { parseRouteKey } from "../parser";
5
-
6
- const feature = await loadFeature("../../features/route-key-format.feature");
7
-
8
- describeFeature(feature, ({ Scenario, ScenarioOutline }) => {
9
- let result: ParsedRoute;
10
- let error: Error | null = null;
11
-
12
- ScenarioOutline(
13
- "Valid route key formats",
14
- ({ When, Then, And }, variables) => {
15
- When("I parse route key {string}", () => {
16
- error = null;
17
- try {
18
- result = parseRouteKey(variables.key);
19
- } catch (e) {
20
- error = e as Error;
21
- }
22
- });
23
-
24
- Then("the method should be {string}", () => {
25
- expect(error).toBeNull();
26
- expect(result.method).toBe(variables.method);
27
- });
28
-
29
- And("the path should be {string}", () => {
30
- expect(result.path).toBe(variables.path);
31
- });
32
- },
33
- );
34
-
35
- ScenarioOutline("Invalid route key formats", ({ When, Then }, variables) => {
36
- When("I parse route key {string}", () => {
37
- error = null;
38
- try {
39
- result = parseRouteKey(variables.key);
40
- } catch (e) {
41
- error = e as Error;
42
- }
43
- });
44
-
45
- Then("an error should be thrown with message matching {string}", () => {
46
- expect(error).not.toBeNull();
47
- expect(error!.message).toMatch(variables.error);
48
- });
49
- });
50
-
51
- Scenario("Extract parameters from path", ({ When, Then, And }) => {
52
- When("I parse route key {string}", (_, routeKey: string) => {
53
- result = parseRouteKey(routeKey);
54
- });
55
-
56
- Then("the method should be {string}", (_, expectedMethod: string) => {
57
- expect(result.method).toBe(expectedMethod);
58
- });
59
-
60
- And("the path should be {string}", (_, expectedPath: string) => {
61
- expect(result.path).toBe(expectedPath);
62
- });
63
-
64
- And("the parameters should be:", (_, docString: string) => {
65
- const expectedParams = JSON.parse(docString);
66
- expect(result.params).toEqual(expectedParams);
67
- });
68
- });
69
-
70
- Scenario("No parameters in simple path", ({ When, Then }) => {
71
- When("I parse route key {string}", (_, routeKey: string) => {
72
- result = parseRouteKey(routeKey);
73
- });
74
-
75
- Then("the parameters should be:", (_, docString: string) => {
76
- const expectedParams = JSON.parse(docString);
77
- expect(result.params).toEqual(expectedParams);
78
- });
79
- });
80
-
81
- Scenario("Complex nested paths", ({ When, Then, And }) => {
82
- When("I parse route key {string}", (_, routeKey: string) => {
83
- result = parseRouteKey(routeKey);
84
- });
85
-
86
- Then("the method should be {string}", (_, expectedMethod: string) => {
87
- expect(result.method).toBe(expectedMethod);
88
- });
89
-
90
- And("the path should be {string}", (_, expectedPath: string) => {
91
- expect(result.path).toBe(expectedPath);
92
- });
93
-
94
- And("the parameters should be:", (_, docString: string) => {
95
- const expectedParams = JSON.parse(docString);
96
- expect(result.params).toEqual(expectedParams);
97
- });
98
- });
99
- });
@@ -1,233 +0,0 @@
1
- import { describeFeature, loadFeature } from "@amiceli/vitest-cucumber";
2
- import { expect } from "vitest";
3
- import { schmock } from "../index";
4
-
5
- const feature = await loadFeature("../../features/standalone-server.feature");
6
-
7
- describeFeature(feature, ({ Scenario }) => {
8
- let mock: Schmock.CallableMockInstance;
9
- let serverInfo: Schmock.ServerInfo;
10
- let httpResponse: Response;
11
-
12
- function baseUrl(): string {
13
- return `http://${serverInfo.hostname}:${serverInfo.port}`;
14
- }
15
-
16
- Scenario("Start and stop a simple server", ({ Given, When, Then, And }) => {
17
- Given("I create a mock with a GET /hello route", () => {
18
- mock = schmock();
19
- mock("GET /hello", { message: "hello" });
20
- });
21
-
22
- When("I start the server on a random port", async () => {
23
- serverInfo = await mock.listen(0);
24
- });
25
-
26
- Then("the server should be running", () => {
27
- expect(serverInfo.port).toBeGreaterThan(0);
28
- });
29
-
30
- When("I fetch {string} from the server", async (_, route: string) => {
31
- const [, path] = route.split(" ");
32
- httpResponse = await fetch(`${baseUrl()}${path}`);
33
- });
34
-
35
- Then("the HTTP response status should be {int}", (_, status: number) => {
36
- expect(httpResponse.status).toBe(status);
37
- });
38
-
39
- And(
40
- "the HTTP response body should have {string} equal to {string}",
41
- async (_, key: string, value: string) => {
42
- const body = await httpResponse.json();
43
- expect(body[key]).toBe(value);
44
- },
45
- );
46
-
47
- When("I stop the server", () => {
48
- mock.close();
49
- });
50
-
51
- Then("the server should not be running", async () => {
52
- try {
53
- await fetch(`${baseUrl()}/hello`);
54
- expect.unreachable("Should not be able to connect");
55
- } catch {
56
- // Connection refused — server is down
57
- }
58
- });
59
- });
60
-
61
- Scenario("Handle POST with JSON body", ({ Given, When, Then, And }) => {
62
- Given("I create a mock echoing POST at {string}", (_, path: string) => {
63
- mock = schmock();
64
- mock(`POST ${path}`, ({ body }) => body);
65
- });
66
-
67
- When("I start the server on a random port", async () => {
68
- serverInfo = await mock.listen(0);
69
- });
70
-
71
- And(
72
- "I fetch {string} with JSON body:",
73
- async (_, route: string, docString: string) => {
74
- const [method, path] = route.split(" ");
75
- httpResponse = await fetch(`${baseUrl()}${path}`, {
76
- method,
77
- headers: { "content-type": "application/json" },
78
- body: docString,
79
- });
80
- },
81
- );
82
-
83
- Then(
84
- "the response status from POST should be {int}",
85
- (_, status: number) => {
86
- expect(httpResponse.status).toBe(status);
87
- },
88
- );
89
-
90
- And(
91
- "the response body from POST should have {string} equal to {string}",
92
- async (_, key: string, value: string) => {
93
- const body = await httpResponse.json();
94
- expect(body[key]).toBe(value);
95
- },
96
- );
97
-
98
- When("I stop the server", () => {
99
- mock.close();
100
- });
101
- });
102
-
103
- Scenario(
104
- "Return 404 for unregistered routes",
105
- ({ Given, When, And, Then }) => {
106
- Given("I create a mock with a GET /hello route", () => {
107
- mock = schmock();
108
- mock("GET /hello", { message: "hello" });
109
- });
110
-
111
- When("I start the server on a random port", async () => {
112
- serverInfo = await mock.listen(0);
113
- });
114
-
115
- And("I fetch {string} from the server", async (_, route: string) => {
116
- const [, path] = route.split(" ");
117
- httpResponse = await fetch(`${baseUrl()}${path}`);
118
- });
119
-
120
- Then("the HTTP response status should be {int}", (_, status: number) => {
121
- expect(httpResponse.status).toBe(status);
122
- });
123
-
124
- When("I stop the server", () => {
125
- mock.close();
126
- });
127
- },
128
- );
129
-
130
- Scenario("Query parameters are forwarded", ({ Given, When, And, Then }) => {
131
- let parsedBody: Record<string, string>;
132
-
133
- Given(
134
- "I create a mock reflecting query params at {string}",
135
- (_, route: string) => {
136
- const [method, path] = route.split(" ");
137
- mock = schmock();
138
- mock(`${method} ${path}` as Schmock.RouteKey, ({ query }) => query);
139
- },
140
- );
141
-
142
- When("I start the server on a random port", async () => {
143
- serverInfo = await mock.listen(0);
144
- });
145
-
146
- And("I fetch {string} from the server", async (_, route: string) => {
147
- const [, pathWithQuery] = route.split(" ");
148
- httpResponse = await fetch(`${baseUrl()}${pathWithQuery}`);
149
- parsedBody = await httpResponse.json();
150
- });
151
-
152
- Then("the HTTP response status should be {int}", (_, status: number) => {
153
- expect(httpResponse.status).toBe(status);
154
- });
155
-
156
- And(
157
- "the HTTP response body should have {string} equal to {string}",
158
- (_, key: string, value: string) => {
159
- expect(parsedBody[key]).toBe(value);
160
- },
161
- );
162
-
163
- And(
164
- "the query param {string} should equal {string}",
165
- (_, key: string, value: string) => {
166
- expect(parsedBody[key]).toBe(value);
167
- },
168
- );
169
-
170
- When("I stop the server", () => {
171
- mock.close();
172
- });
173
- });
174
-
175
- Scenario("Double listen throws an error", ({ Given, When, Then }) => {
176
- Given("I create a mock with a GET /hello route", () => {
177
- mock = schmock();
178
- mock("GET /hello", { message: "hello" });
179
- });
180
-
181
- When("I start the server on a random port", async () => {
182
- serverInfo = await mock.listen(0);
183
- });
184
-
185
- Then("starting the server again should throw", () => {
186
- expect(() => mock.listen(0)).toThrow("Server is already running");
187
- mock.close();
188
- });
189
- });
190
-
191
- Scenario("Close is idempotent", ({ Given, When, And, Then }) => {
192
- Given("I create a mock with a GET /hello route", () => {
193
- mock = schmock();
194
- mock("GET /hello", { message: "hello" });
195
- });
196
-
197
- When("I start the server on a random port", async () => {
198
- serverInfo = await mock.listen(0);
199
- });
200
-
201
- And("I stop the server", () => {
202
- mock.close();
203
- });
204
-
205
- Then("stopping the server again should not throw", () => {
206
- expect(() => mock.close()).not.toThrow();
207
- });
208
- });
209
-
210
- Scenario("Reset stops the server", ({ Given, When, And, Then }) => {
211
- Given("I create a mock with a GET /hello route", () => {
212
- mock = schmock();
213
- mock("GET /hello", { message: "hello" });
214
- });
215
-
216
- When("I start the server on a random port", async () => {
217
- serverInfo = await mock.listen(0);
218
- });
219
-
220
- And("I reset the mock", () => {
221
- mock.reset();
222
- });
223
-
224
- Then("the server should not be running", async () => {
225
- try {
226
- await fetch(`${baseUrl()}/hello`);
227
- expect.unreachable("Should not be able to connect");
228
- } catch {
229
- // Connection refused — server is down
230
- }
231
- });
232
- });
233
- });