@schmock/core 2.3.0 → 2.4.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.
Files changed (93) 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/builder.d.ts +31 -10
  7. package/dist/builder.d.ts.map +1 -1
  8. package/dist/builder.js +760 -190
  9. package/dist/constants.d.ts +38 -0
  10. package/dist/constants.d.ts.map +1 -1
  11. package/dist/constants.js +123 -2
  12. package/dist/errors.d.ts +14 -3
  13. package/dist/errors.d.ts.map +1 -1
  14. package/dist/errors.js +41 -6
  15. package/dist/helpers.d.ts +9 -0
  16. package/dist/helpers.d.ts.map +1 -1
  17. package/dist/helpers.js +18 -2
  18. package/dist/http-helpers.d.ts +39 -4
  19. package/dist/http-helpers.d.ts.map +1 -1
  20. package/dist/http-helpers.js +147 -49
  21. package/dist/index.d.ts +292 -34
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +8 -3
  24. package/dist/interceptor.d.ts +11 -1
  25. package/dist/interceptor.d.ts.map +1 -1
  26. package/dist/interceptor.js +316 -169
  27. package/dist/parser.d.ts.map +1 -1
  28. package/dist/parser.js +12 -3
  29. package/dist/plugin-pipeline.d.ts +3 -3
  30. package/dist/plugin-pipeline.d.ts.map +1 -1
  31. package/dist/plugin-pipeline.js +29 -14
  32. package/dist/response-normalizer.d.ts +16 -0
  33. package/dist/response-normalizer.d.ts.map +1 -0
  34. package/dist/response-normalizer.js +316 -0
  35. package/dist/response-parser.d.ts.map +1 -1
  36. package/dist/response-parser.js +39 -2
  37. package/dist/route-matcher.d.ts +3 -0
  38. package/dist/route-matcher.d.ts.map +1 -1
  39. package/dist/route-matcher.js +12 -6
  40. package/dist/types.d.ts +7 -2
  41. package/dist/types.d.ts.map +1 -1
  42. package/package.json +18 -6
  43. package/src/audit-core-builder.test.ts +0 -218
  44. package/src/audit-response-guard.test.ts +0 -38
  45. package/src/binary.test.ts +0 -126
  46. package/src/binary.ts +0 -11
  47. package/src/builder.test.ts +0 -289
  48. package/src/builder.ts +0 -748
  49. package/src/constants.test.ts +0 -99
  50. package/src/constants.ts +0 -73
  51. package/src/debug.test.ts +0 -241
  52. package/src/delay.test.ts +0 -319
  53. package/src/dist-shape.test.ts +0 -35
  54. package/src/errors.test.ts +0 -223
  55. package/src/errors.ts +0 -130
  56. package/src/factory.test.ts +0 -133
  57. package/src/helpers.test.ts +0 -147
  58. package/src/helpers.ts +0 -58
  59. package/src/http-helpers.test.ts +0 -39
  60. package/src/http-helpers.ts +0 -149
  61. package/src/index.ts +0 -152
  62. package/src/interceptor.test.ts +0 -488
  63. package/src/interceptor.ts +0 -407
  64. package/src/namespace.test.ts +0 -274
  65. package/src/parser.property.test.ts +0 -630
  66. package/src/parser.test.ts +0 -148
  67. package/src/parser.ts +0 -64
  68. package/src/plugin-pipeline.ts +0 -208
  69. package/src/plugin-system.test.ts +0 -697
  70. package/src/response-parser.ts +0 -114
  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 -234
  75. package/src/smart-defaults.test.ts +0 -361
  76. package/src/steps/async-support.steps.ts +0 -421
  77. package/src/steps/audit-core-builder.steps.ts +0 -188
  78. package/src/steps/audit-onerror-tuple.steps.ts +0 -83
  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 -555
  82. package/src/steps/fetch-interceptor.steps.ts +0 -457
  83. package/src/steps/fluent-api.steps.ts +0 -255
  84. package/src/steps/http-methods.steps.ts +0 -342
  85. package/src/steps/lifecycle-events.steps.ts +0 -149
  86. package/src/steps/performance-reliability.steps.ts +0 -90
  87. package/src/steps/plugin-integration.steps.ts +0 -334
  88. package/src/steps/request-history.steps.ts +0 -458
  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 -227
  92. package/src/steps/state-concurrency.steps.ts +0 -167
  93. package/src/types.ts +0 -36
@@ -1,361 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import { schmock } from "./index";
3
-
4
- describe("smart content-type defaults", () => {
5
- describe("primitive values", () => {
6
- it("converts numbers to strings with text/plain", async () => {
7
- const mock = schmock();
8
- mock("GET /number", 42);
9
-
10
- const response = await mock.handle("GET", "/number");
11
-
12
- expect(response.status).toBe(200);
13
- expect(response.body).toBe("42");
14
- expect(response.headers["content-type"]).toBe("text/plain");
15
- });
16
-
17
- it("converts booleans to strings with text/plain", async () => {
18
- const mock = schmock();
19
- mock("GET /bool", true);
20
-
21
- const response = await mock.handle("GET", "/bool");
22
-
23
- expect(response.status).toBe(200);
24
- expect(response.body).toBe("true");
25
- expect(response.headers["content-type"]).toBe("text/plain");
26
- });
27
-
28
- it("handles strings as text/plain", async () => {
29
- const mock = schmock();
30
- mock("GET /string", "Hello World");
31
-
32
- const response = await mock.handle("GET", "/string");
33
-
34
- expect(response.status).toBe(200);
35
- expect(response.body).toBe("Hello World");
36
- expect(response.headers["content-type"]).toBe("text/plain");
37
- });
38
-
39
- it("handles empty string as text/plain", async () => {
40
- const mock = schmock();
41
- mock("GET /empty", "");
42
-
43
- const response = await mock.handle("GET", "/empty");
44
-
45
- expect(response.status).toBe(200);
46
- expect(response.body).toBe("");
47
- expect(response.headers["content-type"]).toBe("text/plain");
48
- });
49
- });
50
-
51
- describe("objects and arrays", () => {
52
- it("handles objects as application/json", async () => {
53
- const mock = schmock();
54
- mock("GET /object", { id: 1, name: "John" });
55
-
56
- const response = await mock.handle("GET", "/object");
57
-
58
- expect(response.status).toBe(200);
59
- expect(response.body).toEqual({ id: 1, name: "John" });
60
- expect(response.headers["content-type"]).toBe("application/json");
61
- });
62
-
63
- it("handles arrays as application/json", async () => {
64
- const mock = schmock();
65
- mock("GET /array", ["one", "two", "three"]);
66
-
67
- const response = await mock.handle("GET", "/array");
68
-
69
- expect(response.status).toBe(200);
70
- expect(response.body).toEqual(["one", "two", "three"]);
71
- expect(response.headers["content-type"]).toBe("application/json");
72
- });
73
-
74
- it("handles empty arrays as application/json", async () => {
75
- const mock = schmock();
76
- mock("GET /empty-array", []);
77
-
78
- const response = await mock.handle("GET", "/empty-array");
79
-
80
- expect(response.status).toBe(200);
81
- expect(response.body).toEqual([]);
82
- expect(response.headers["content-type"]).toBe("application/json");
83
- });
84
-
85
- it("handles empty objects as application/json", async () => {
86
- const mock = schmock();
87
- mock("GET /empty-object", {});
88
-
89
- const response = await mock.handle("GET", "/empty-object");
90
-
91
- expect(response.status).toBe(200);
92
- expect(response.body).toEqual({});
93
- expect(response.headers["content-type"]).toBe("application/json");
94
- });
95
- });
96
-
97
- describe("null and undefined values", () => {
98
- it("handles null with 204 No Content", async () => {
99
- const mock = schmock();
100
- mock("GET /null", null);
101
-
102
- const response = await mock.handle("GET", "/null");
103
-
104
- expect(response.status).toBe(204);
105
- expect(response.body).toBeUndefined();
106
- expect(response.headers["content-type"]).toBe("application/json");
107
- });
108
-
109
- it("handles undefined with 204 No Content", async () => {
110
- const mock = schmock();
111
- mock("GET /undefined", undefined);
112
-
113
- const response = await mock.handle("GET", "/undefined");
114
-
115
- expect(response.status).toBe(204);
116
- expect(response.body).toBeUndefined();
117
- expect(response.headers["content-type"]).toBe("application/json");
118
- });
119
- });
120
-
121
- describe("Buffer responses", () => {
122
- it("handles Buffers as application/octet-stream", async () => {
123
- const mock = schmock();
124
- const buffer = Buffer.from("binary data");
125
- mock("GET /binary", buffer);
126
-
127
- const response = await mock.handle("GET", "/binary");
128
-
129
- expect(response.status).toBe(200);
130
- expect(response.body).toBe(buffer);
131
- expect(response.headers["content-type"]).toBe("application/octet-stream");
132
- });
133
- });
134
-
135
- describe("function generators", () => {
136
- it("function returning string gets application/json by default", async () => {
137
- const mock = schmock();
138
- mock("GET /func-string", () => "Hello");
139
-
140
- const response = await mock.handle("GET", "/func-string");
141
-
142
- expect(response.status).toBe(200);
143
- expect(response.body).toBe("Hello");
144
- expect(response.headers["content-type"]).toBe("application/json");
145
- });
146
-
147
- it("function returning number gets application/json by default", async () => {
148
- const mock = schmock();
149
- mock("GET /func-number", () => 42);
150
-
151
- const response = await mock.handle("GET", "/func-number");
152
-
153
- expect(response.status).toBe(200);
154
- expect(response.body).toBe(42);
155
- expect(response.headers["content-type"]).toBe("application/json");
156
- });
157
-
158
- it("function returning object gets application/json by default", async () => {
159
- const mock = schmock();
160
- mock("GET /func-object", () => ({ id: 1 }));
161
-
162
- const response = await mock.handle("GET", "/func-object");
163
-
164
- expect(response.status).toBe(200);
165
- expect(response.body).toEqual({ id: 1 });
166
- expect(response.headers["content-type"]).toBe("application/json");
167
- });
168
-
169
- it("function returning null gets 204 status", async () => {
170
- const mock = schmock();
171
- mock("GET /func-null", () => null);
172
-
173
- const response = await mock.handle("GET", "/func-null");
174
-
175
- expect(response.status).toBe(204);
176
- expect(response.body).toBeUndefined();
177
- expect(response.headers["content-type"]).toBe("application/json");
178
- });
179
- });
180
-
181
- describe("explicit contentType overrides", () => {
182
- it("overrides object to text/plain and stringifies", async () => {
183
- const mock = schmock();
184
- mock("GET /override", { foo: "bar" }, { contentType: "text/plain" });
185
-
186
- const response = await mock.handle("GET", "/override");
187
-
188
- expect(response.status).toBe(200);
189
- expect(response.body).toBe('{"foo":"bar"}');
190
- expect(response.headers["content-type"]).toBe("text/plain");
191
- });
192
-
193
- it("overrides number to text/plain and converts to string", async () => {
194
- const mock = schmock();
195
- mock("GET /override-number", 123, { contentType: "text/plain" });
196
-
197
- const response = await mock.handle("GET", "/override-number");
198
-
199
- expect(response.status).toBe(200);
200
- expect(response.body).toBe("123");
201
- expect(response.headers["content-type"]).toBe("text/plain");
202
- });
203
-
204
- it("overrides string to application/json", async () => {
205
- const mock = schmock();
206
- mock("GET /override-string", "hello", {
207
- contentType: "application/json",
208
- });
209
-
210
- const response = await mock.handle("GET", "/override-string");
211
-
212
- expect(response.status).toBe(200);
213
- expect(response.body).toBe("hello");
214
- expect(response.headers["content-type"]).toBe("application/json");
215
- });
216
-
217
- it("sets custom content-type", async () => {
218
- const mock = schmock();
219
- mock("GET /custom", "<h1>Hello</h1>", { contentType: "text/html" });
220
-
221
- const response = await mock.handle("GET", "/custom");
222
-
223
- expect(response.status).toBe(200);
224
- expect(response.body).toBe("<h1>Hello</h1>");
225
- expect(response.headers["content-type"]).toBe("text/html");
226
- });
227
- });
228
-
229
- describe("tuple responses preserve explicit control", () => {
230
- it("tuple responses don't get automatic content-type", async () => {
231
- const mock = schmock();
232
- mock("GET /tuple", () => [200, { id: 1 }]);
233
-
234
- const response = await mock.handle("GET", "/tuple");
235
-
236
- expect(response.status).toBe(200);
237
- expect(response.body).toEqual({ id: 1 });
238
- expect(response.headers).toEqual({});
239
- });
240
-
241
- it("tuple with explicit headers keeps them", async () => {
242
- const mock = schmock();
243
- mock("GET /tuple-headers", () => [
244
- 201,
245
- { created: true },
246
- { "X-Custom": "value" },
247
- ]);
248
-
249
- const response = await mock.handle("GET", "/tuple-headers");
250
-
251
- expect(response.status).toBe(201);
252
- expect(response.body).toEqual({ created: true });
253
- expect(response.headers).toEqual({ "X-Custom": "value" });
254
- });
255
-
256
- it("tuple with null body preserves explicit status", async () => {
257
- const mock = schmock();
258
- mock("GET /tuple-null", () => [200, null]);
259
-
260
- const response = await mock.handle("GET", "/tuple-null");
261
-
262
- expect(response.status).toBe(200); // Tuple format preserves explicit status
263
- expect(response.body).toBeUndefined();
264
- expect(response.headers).toEqual({});
265
- });
266
-
267
- it("tuple with 204 status and null body", async () => {
268
- const mock = schmock();
269
- mock("GET /tuple-204", () => [204, null]);
270
-
271
- const response = await mock.handle("GET", "/tuple-204");
272
-
273
- expect(response.status).toBe(204);
274
- expect(response.body).toBeUndefined();
275
- expect(response.headers).toEqual({});
276
- });
277
- });
278
-
279
- describe("edge cases", () => {
280
- it("handles zero as text/plain", async () => {
281
- const mock = schmock();
282
- mock("GET /zero", 0);
283
-
284
- const response = await mock.handle("GET", "/zero");
285
-
286
- expect(response.status).toBe(200);
287
- expect(response.body).toBe("0");
288
- expect(response.headers["content-type"]).toBe("text/plain");
289
- });
290
-
291
- it("handles false as text/plain", async () => {
292
- const mock = schmock();
293
- mock("GET /false", false);
294
-
295
- const response = await mock.handle("GET", "/false");
296
-
297
- expect(response.status).toBe(200);
298
- expect(response.body).toBe("false");
299
- expect(response.headers["content-type"]).toBe("text/plain");
300
- });
301
-
302
- it("handles nested objects as application/json", async () => {
303
- const mock = schmock();
304
- const nested = {
305
- user: { id: 1, profile: { name: "John", settings: { theme: "dark" } } },
306
- };
307
- mock("GET /nested", nested);
308
-
309
- const response = await mock.handle("GET", "/nested");
310
-
311
- expect(response.status).toBe(200);
312
- expect(response.body).toEqual(nested);
313
- expect(response.headers["content-type"]).toBe("application/json");
314
- });
315
-
316
- it("handles arrays with mixed types as application/json", async () => {
317
- const mock = schmock();
318
- mock("GET /mixed", ["first", 2, { id: 1 }, ["nested", "array"]]);
319
-
320
- const response = await mock.handle("GET", "/mixed");
321
-
322
- expect(response.status).toBe(200);
323
- expect(response.body).toEqual([
324
- "first",
325
- 2,
326
- { id: 1 },
327
- ["nested", "array"],
328
- ]);
329
- expect(response.headers["content-type"]).toBe("application/json");
330
- });
331
- });
332
-
333
- describe("consistency with existing auto-detection", () => {
334
- it("static string gets text/plain", async () => {
335
- const mock = schmock();
336
- mock("GET /static-string", "Hello World");
337
-
338
- const response = await mock.handle("GET", "/static-string");
339
-
340
- expect(response.headers["content-type"]).toBe("text/plain");
341
- });
342
-
343
- it("static object gets application/json", async () => {
344
- const mock = schmock();
345
- mock("GET /static-object", { id: 1 });
346
-
347
- const response = await mock.handle("GET", "/static-object");
348
-
349
- expect(response.headers["content-type"]).toBe("application/json");
350
- });
351
-
352
- it("function generator gets application/json by default", async () => {
353
- const mock = schmock();
354
- mock("GET /func", () => "anything");
355
-
356
- const response = await mock.handle("GET", "/func");
357
-
358
- expect(response.headers["content-type"]).toBe("application/json");
359
- });
360
- });
361
- });