@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,274 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import { schmock } from "./index";
3
-
4
- describe("namespace functionality", () => {
5
- describe("basic namespace behavior", () => {
6
- it("applies namespace to all routes", async () => {
7
- const mock = schmock({ namespace: "/api" });
8
- mock("GET /users", "users");
9
- mock("POST /users", "create-user");
10
-
11
- const getResponse = await mock.handle("GET", "/api/users");
12
- const postResponse = await mock.handle("POST", "/api/users");
13
-
14
- expect(getResponse.body).toBe("users");
15
- expect(postResponse.body).toBe("create-user");
16
- });
17
-
18
- it("returns 404 for requests without namespace prefix", async () => {
19
- const mock = schmock({ namespace: "/api" });
20
- mock("GET /users", "users");
21
-
22
- const response = await mock.handle("GET", "/users");
23
-
24
- expect(response.status).toBe(404);
25
- expect(response.body.error).toContain("Route not found: GET /users");
26
- });
27
-
28
- it("handles nested namespaces", async () => {
29
- const mock = schmock({ namespace: "/api/v1" });
30
- mock("GET /users", "v1-users");
31
-
32
- const response = await mock.handle("GET", "/api/v1/users");
33
-
34
- expect(response.body).toBe("v1-users");
35
- });
36
-
37
- it("works with root namespace", async () => {
38
- const mock = schmock({ namespace: "/" });
39
- mock("GET /users", "users");
40
-
41
- const response = await mock.handle("GET", "/users");
42
-
43
- expect(response.body).toBe("users");
44
- });
45
- });
46
-
47
- describe("namespace with parameters", () => {
48
- it("works with parameterized routes under namespace", async () => {
49
- const mock = schmock({ namespace: "/api" });
50
- mock("GET /users/:id", ({ params }) => ({ userId: params.id }));
51
-
52
- const response = await mock.handle("GET", "/api/users/123");
53
-
54
- expect(response.body).toEqual({ userId: "123" });
55
- });
56
-
57
- it("extracts parameters correctly after namespace removal", async () => {
58
- const mock = schmock({ namespace: "/api/v1" });
59
- mock("GET /users/:userId/posts/:postId", ({ params, path }) => ({
60
- params,
61
- processedPath: path,
62
- }));
63
-
64
- const response = await mock.handle("GET", "/api/v1/users/456/posts/789");
65
-
66
- expect(response.body).toEqual({
67
- params: { userId: "456", postId: "789" },
68
- processedPath: "/users/456/posts/789",
69
- });
70
- });
71
-
72
- it("passes correct path to context after namespace stripping", async () => {
73
- const mock = schmock({ namespace: "/api" });
74
- mock("GET /test/:param", ({ path, params }) => ({
75
- contextPath: path,
76
- params,
77
- }));
78
-
79
- const response = await mock.handle("GET", "/api/test/value");
80
-
81
- expect(response.body).toEqual({
82
- contextPath: "/test/value",
83
- params: { param: "value" },
84
- });
85
- });
86
- });
87
-
88
- describe("namespace edge cases", () => {
89
- it("handles namespace with trailing slash", async () => {
90
- const mock = schmock({ namespace: "/api/" });
91
- mock("GET /users", "users");
92
-
93
- // Should work with or without the trailing slash in the request
94
- const response1 = await mock.handle("GET", "/api/users");
95
- const response2 = await mock.handle("GET", "/api//users");
96
-
97
- expect(response1.body).toBe("users");
98
- // New logic gracefully handles double slashes by stripping the full namespace
99
- expect(response2.status).toBe(200);
100
- expect(response2.body).toBe("users");
101
- });
102
-
103
- it("handles empty namespace", async () => {
104
- const mock = schmock({ namespace: "" });
105
- mock("GET /users", "users");
106
-
107
- const response = await mock.handle("GET", "/users");
108
-
109
- expect(response.body).toBe("users");
110
- });
111
-
112
- it("handles namespace without leading slash", async () => {
113
- const mock = schmock({ namespace: "api" });
114
- mock("GET /users", "users");
115
-
116
- const response = await mock.handle("GET", "api/users");
117
-
118
- expect(response.body).toBe("users");
119
- });
120
-
121
- it("rejects requests that partially match namespace", async () => {
122
- const mock = schmock({ namespace: "/api" });
123
- mock("GET /users", "users");
124
-
125
- const response1 = await mock.handle("GET", "/ap/users");
126
- const response2 = await mock.handle("GET", "/apiextra/users");
127
-
128
- expect(response1.status).toBe(404);
129
- expect(response2.status).toBe(404);
130
- });
131
-
132
- it("handles very long namespaces", async () => {
133
- const longNamespace =
134
- "/api/v1/internal/microservice/health/monitoring/endpoints";
135
- const mock = schmock({ namespace: longNamespace });
136
- mock("GET /status", "healthy");
137
-
138
- const response = await mock.handle("GET", `${longNamespace}/status`);
139
-
140
- expect(response.body).toBe("healthy");
141
- });
142
- });
143
-
144
- describe("namespace without routes", () => {
145
- it("returns 404 when no routes defined", async () => {
146
- const mock = schmock({ namespace: "/api" });
147
-
148
- const response = await mock.handle("GET", "/api/anything");
149
-
150
- expect(response.status).toBe(404);
151
- });
152
-
153
- it("returns 404 for namespace root when no root route", async () => {
154
- const mock = schmock({ namespace: "/api" });
155
- mock("GET /users", "users");
156
-
157
- const response = await mock.handle("GET", "/api");
158
-
159
- expect(response.status).toBe(404);
160
- });
161
-
162
- it("supports root route under namespace", async () => {
163
- const mock = schmock({ namespace: "/api" });
164
- mock("GET /", "api-root");
165
-
166
- const response = await mock.handle("GET", "/api/");
167
-
168
- expect(response.body).toBe("api-root");
169
- });
170
- });
171
-
172
- describe("namespace with global state", () => {
173
- it("maintains global state across namespaced routes", async () => {
174
- const mock = schmock({
175
- namespace: "/api",
176
- state: { counter: 0 },
177
- });
178
-
179
- mock("POST /increment", ({ state }) => {
180
- state.counter++;
181
- return { counter: state.counter };
182
- });
183
-
184
- mock("GET /count", ({ state }) => ({ counter: state.counter }));
185
-
186
- await mock.handle("POST", "/api/increment");
187
- await mock.handle("POST", "/api/increment");
188
- const response = await mock.handle("GET", "/api/count");
189
-
190
- expect(response.body).toEqual({ counter: 2 });
191
- });
192
- });
193
-
194
- describe("namespace with plugins", () => {
195
- it("works correctly with plugin pipeline", async () => {
196
- const mock = schmock({ namespace: "/api" });
197
-
198
- const plugin = {
199
- name: "namespace-plugin",
200
- process: (ctx: any, res: any) => {
201
- return {
202
- context: ctx,
203
- response: {
204
- ...res,
205
- namespacedPath: ctx.path,
206
- },
207
- };
208
- },
209
- };
210
-
211
- mock("GET /users", { users: [] }).pipe(plugin);
212
-
213
- const response = await mock.handle("GET", "/api/users");
214
-
215
- expect(response.body).toEqual({
216
- users: [],
217
- namespacedPath: "/users", // Should be the path after namespace removal
218
- });
219
- });
220
- });
221
-
222
- describe("special characters in namespace", () => {
223
- it("handles namespace with special characters", async () => {
224
- const mock = schmock({ namespace: "/api-v1.2" });
225
- mock("GET /users", "users");
226
-
227
- const response = await mock.handle("GET", "/api-v1.2/users");
228
-
229
- expect(response.body).toBe("users");
230
- });
231
-
232
- it("handles namespace with underscores", async () => {
233
- const mock = schmock({ namespace: "/my_api" });
234
- mock("GET /test", "test");
235
-
236
- const response = await mock.handle("GET", "/my_api/test");
237
-
238
- expect(response.body).toBe("test");
239
- });
240
-
241
- it("handles namespace with numbers", async () => {
242
- const mock = schmock({ namespace: "/api2" });
243
- mock("GET /version", "v2");
244
-
245
- const response = await mock.handle("GET", "/api2/version");
246
-
247
- expect(response.body).toBe("v2");
248
- });
249
- });
250
-
251
- describe("namespace error messages", () => {
252
- it("provides clear error message for namespace mismatch", async () => {
253
- const mock = schmock({ namespace: "/api/v1" });
254
- mock("GET /users", "users");
255
-
256
- const response = await mock.handle("GET", "/api/v2/users");
257
-
258
- expect(response.status).toBe(404);
259
- expect(response.body.error).toContain(
260
- "Route not found: GET /api/v2/users",
261
- );
262
- expect(response.body.code).toBe("ROUTE_NOT_FOUND");
263
- });
264
-
265
- it("includes original requested path in error", async () => {
266
- const mock = schmock({ namespace: "/api" });
267
- mock("GET /users", "users");
268
-
269
- const response = await mock.handle("GET", "/wrong/path");
270
-
271
- expect(response.body.error).toContain("/wrong/path");
272
- });
273
- });
274
- });