@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,289 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import { schmock } from "./index";
3
-
4
- describe("schmock callable API", () => {
5
- describe("callable instance", () => {
6
- it("returns callable mock instance from factory", () => {
7
- const mock = schmock();
8
- expect(mock).toBeDefined();
9
- expect(typeof mock).toBe("function");
10
- expect(mock.handle).toBeTypeOf("function");
11
- expect(mock.pipe).toBeTypeOf("function");
12
- });
13
-
14
- it("allows defining routes through function calls", () => {
15
- const mock = schmock();
16
- const result = mock("GET /users", () => [], {});
17
-
18
- expect(result).toBe(mock); // Should return same instance for chaining
19
- expect(result.pipe).toBeTypeOf("function");
20
- });
21
-
22
- it("supports chaining with pipe method", () => {
23
- const mock = schmock();
24
- const result = mock("GET /users", () => [], {}).pipe({
25
- name: "test-plugin",
26
- process: (ctx, response) => ({ context: ctx, response }),
27
- });
28
-
29
- expect(result).toBe(mock); // Should return same instance for chaining
30
- });
31
- });
32
-
33
- describe("request handling", () => {
34
- it("handles simple GET request", async () => {
35
- const mock = schmock();
36
- mock("GET /users", () => [{ id: 1, name: "John" }], {});
37
-
38
- const response = await mock.handle("GET", "/users");
39
-
40
- expect(response.status).toBe(200);
41
- expect(response.body).toEqual([{ id: 1, name: "John" }]);
42
- expect(response.headers).toEqual({ "content-type": "application/json" });
43
- });
44
-
45
- it("returns 404 for undefined routes", async () => {
46
- const mock = schmock();
47
- mock("GET /users", () => [], {});
48
-
49
- const response = await mock.handle("GET", "/posts");
50
-
51
- expect(response.status).toBe(404);
52
- });
53
-
54
- it("handles route with parameters", async () => {
55
- const mock = schmock();
56
- mock("GET /users/:id", ({ params }) => ({ userId: params.id }), {});
57
-
58
- const response = await mock.handle("GET", "/users/123");
59
-
60
- expect(response.status).toBe(200);
61
- expect(response.body).toEqual({ userId: "123" });
62
- });
63
-
64
- it("handles custom status codes via tuple", async () => {
65
- const mock = schmock();
66
- mock("POST /users", ({ body }) => [201, { id: 1, ...body }], {});
67
-
68
- const response = await mock.handle("POST", "/users", {
69
- body: { name: "Alice" },
70
- });
71
-
72
- expect(response.status).toBe(201);
73
- expect(response.body).toEqual({ id: 1, name: "Alice" });
74
- });
75
-
76
- it("handles custom headers via triple tuple", async () => {
77
- const mock = schmock();
78
- mock(
79
- "POST /users",
80
- ({ body }) => [201, { id: 1, ...body }, { Location: "/users/1" }],
81
- {},
82
- );
83
-
84
- const response = await mock.handle("POST", "/users", {
85
- body: { name: "Alice" },
86
- });
87
-
88
- expect(response.status).toBe(201);
89
- expect(response.headers).toEqual({
90
- Location: "/users/1",
91
- });
92
- });
93
- });
94
-
95
- describe("state management", () => {
96
- it("maintains state across requests with global config", async () => {
97
- const globalState = { count: 0 };
98
- const mock = schmock({ state: globalState });
99
- mock(
100
- "GET /increment",
101
- ({ state }) => {
102
- state.count++;
103
- return { value: state.count };
104
- },
105
- {},
106
- );
107
-
108
- const first = await mock.handle("GET", "/increment");
109
- const second = await mock.handle("GET", "/increment");
110
-
111
- expect(first.body).toEqual({ value: 1 });
112
- expect(second.body).toEqual({ value: 2 });
113
- });
114
-
115
- it("shares state between routes with global config", async () => {
116
- const globalState = { users: [] as unknown[] };
117
- const mock = schmock({ state: globalState });
118
-
119
- mock(
120
- "POST /users",
121
- ({ body, state }) => {
122
- const user = { id: Date.now(), ...body };
123
- state.users.push(user);
124
- return [201, user];
125
- },
126
- {},
127
- );
128
-
129
- mock("GET /users", ({ state }) => state.users, {});
130
-
131
- await mock.handle("POST", "/users", { body: { name: "John" } });
132
- const response = await mock.handle("GET", "/users");
133
-
134
- expect(response.body).toHaveLength(1);
135
- expect(response.body[0]).toHaveProperty("name", "John");
136
- });
137
- });
138
-
139
- describe("configuration", () => {
140
- it("applies namespace to all routes", async () => {
141
- const mock = schmock({ namespace: "/api/v1" });
142
- mock("GET /users", () => [], {});
143
-
144
- const response = await mock.handle("GET", "/api/v1/users");
145
-
146
- expect(response.status).toBe(200);
147
- expect(response.body).toEqual([]);
148
- });
149
-
150
- it("returns 404 without namespace prefix", async () => {
151
- const mock = schmock({ namespace: "/api/v1" });
152
- mock("GET /users", () => [], {});
153
-
154
- const response = await mock.handle("GET", "/users");
155
-
156
- expect(response.status).toBe(404);
157
- });
158
- });
159
-
160
- describe("request context", () => {
161
- it("provides query parameters", async () => {
162
- const mock = schmock();
163
- mock(
164
- "GET /search",
165
- ({ query }) => ({
166
- results: [],
167
- query: query.q,
168
- }),
169
- {},
170
- );
171
-
172
- const response = await mock.handle("GET", "/search", {
173
- query: { q: "test" },
174
- });
175
-
176
- expect(response.body).toEqual({
177
- results: [],
178
- query: "test",
179
- });
180
- });
181
-
182
- it("provides headers", async () => {
183
- const mock = schmock();
184
- mock(
185
- "GET /auth",
186
- ({ headers }) => ({
187
- authenticated: headers.authorization === "Bearer token123",
188
- }),
189
- {},
190
- );
191
-
192
- const response = await mock.handle("GET", "/auth", {
193
- headers: { authorization: "Bearer token123" },
194
- });
195
-
196
- expect(response.body).toEqual({ authenticated: true });
197
- });
198
-
199
- it("provides method and path in context", async () => {
200
- const mock = schmock();
201
- mock("GET /info", ({ method, path }) => ({ method, path }), {});
202
-
203
- const response = await mock.handle("GET", "/info");
204
-
205
- expect(response.body).toEqual({
206
- method: "GET",
207
- path: "/info",
208
- });
209
- });
210
- });
211
-
212
- describe("contentType auto-detection", () => {
213
- it("defaults to application/json for function generators", async () => {
214
- const mock = schmock();
215
- mock("GET /users", () => [{ id: 1 }], {});
216
-
217
- const response = await mock.handle("GET", "/users");
218
- expect(response.status).toBe(200);
219
- expect(response.body).toEqual([{ id: 1 }]);
220
- });
221
-
222
- it("defaults to text/plain for string generators", async () => {
223
- const mock = schmock();
224
- mock("GET /text", "Hello World", {});
225
-
226
- const response = await mock.handle("GET", "/text");
227
- expect(response.status).toBe(200);
228
- expect(response.body).toBe("Hello World");
229
- });
230
-
231
- it("defaults to application/json for object generators", async () => {
232
- const mock = schmock();
233
- mock("GET /users", [{ id: 1, name: "John" }], {});
234
-
235
- const response = await mock.handle("GET", "/users");
236
- expect(response.status).toBe(200);
237
- expect(response.body).toEqual([{ id: 1, name: "John" }]);
238
- });
239
-
240
- it("allows explicit contentType override", async () => {
241
- const mock = schmock();
242
- mock("GET /json", "Hello World", { contentType: "application/json" });
243
-
244
- const response = await mock.handle("GET", "/json");
245
- expect(response.status).toBe(200);
246
- expect(response.body).toBe("Hello World");
247
- });
248
-
249
- it("validates JSON data for application/json contentType", () => {
250
- const mock = schmock();
251
-
252
- // This should work - valid JSON data
253
- expect(() => {
254
- mock("GET /users", [{ id: 1 }], { contentType: "application/json" });
255
- }).not.toThrow();
256
-
257
- // This should fail - circular reference can't be JSON serialized
258
- const circular: any = {};
259
- circular.self = circular;
260
-
261
- expect(() => {
262
- mock("GET /users", circular, { contentType: "application/json" });
263
- }).toThrow(
264
- "Generator data is not valid JSON but contentType is application/json",
265
- );
266
- });
267
- });
268
-
269
- describe("plugin integration", () => {
270
- it("supports plugin pipeline with pipe method", async () => {
271
- const mock = schmock();
272
- mock("GET /users", [{ id: 1, name: "John" }], {}).pipe({
273
- name: "test-plugin",
274
- process: (ctx, pluginResponse) => ({
275
- context: ctx,
276
- response: { data: pluginResponse, processed: true },
277
- }),
278
- });
279
-
280
- const response = await mock.handle("GET", "/users");
281
-
282
- expect(response.status).toBe(200);
283
- expect(response.body).toEqual({
284
- data: [{ id: 1, name: "John" }],
285
- processed: true,
286
- });
287
- });
288
- });
289
- });