@schmock/core 1.0.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.
- package/dist/builder.d.ts +62 -0
- package/dist/builder.d.ts.map +1 -0
- package/dist/builder.js +432 -0
- package/dist/errors.d.ts +56 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +92 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1 -0
- package/dist/parser.d.ts +19 -0
- package/dist/parser.d.ts.map +1 -0
- package/dist/parser.js +40 -0
- package/dist/types.d.ts +15 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/package.json +39 -0
- package/src/builder.d.ts.map +1 -0
- package/src/builder.test.ts +289 -0
- package/src/builder.ts +580 -0
- package/src/debug.test.ts +241 -0
- package/src/delay.test.ts +319 -0
- package/src/errors.d.ts.map +1 -0
- package/src/errors.test.ts +223 -0
- package/src/errors.ts +124 -0
- package/src/factory.test.ts +133 -0
- package/src/index.d.ts.map +1 -0
- package/src/index.ts +80 -0
- package/src/namespace.test.ts +273 -0
- package/src/parser.d.ts.map +1 -0
- package/src/parser.test.ts +131 -0
- package/src/parser.ts +61 -0
- package/src/plugin-system.test.ts +511 -0
- package/src/response-parsing.test.ts +255 -0
- package/src/route-matching.test.ts +351 -0
- package/src/smart-defaults.test.ts +361 -0
- package/src/steps/async-support.steps.ts +427 -0
- package/src/steps/basic-usage.steps.ts +316 -0
- package/src/steps/developer-experience.steps.ts +439 -0
- package/src/steps/error-handling.steps.ts +387 -0
- package/src/steps/fluent-api.steps.ts +252 -0
- package/src/steps/http-methods.steps.ts +397 -0
- package/src/steps/performance-reliability.steps.ts +459 -0
- package/src/steps/plugin-integration.steps.ts +279 -0
- package/src/steps/route-key-format.steps.ts +118 -0
- package/src/steps/state-concurrency.steps.ts +643 -0
- package/src/steps/stateful-workflows.steps.ts +351 -0
- package/src/types.d.ts.map +1 -0
- package/src/types.ts +17 -0
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
import { describeFeature, loadFeature } from "@amiceli/vitest-cucumber";
|
|
2
|
+
import { expect } from "vitest";
|
|
3
|
+
import { schmock } from "../index";
|
|
4
|
+
import type { CallableMockInstance } from "../types";
|
|
5
|
+
|
|
6
|
+
const feature = await loadFeature("../../features/basic-usage.feature");
|
|
7
|
+
|
|
8
|
+
describeFeature(feature, ({ Scenario }) => {
|
|
9
|
+
let mock: CallableMockInstance;
|
|
10
|
+
let response: any;
|
|
11
|
+
|
|
12
|
+
Scenario("Simplest possible mock - plain text", ({ Given, When, Then, And }) => {
|
|
13
|
+
Given("I create a mock with:", (_, docString: string) => {
|
|
14
|
+
mock = schmock();
|
|
15
|
+
mock('GET /', 'Hello World');
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
When("I request {string}", async (_, request: string) => {
|
|
19
|
+
const [method, path] = request.split(" ");
|
|
20
|
+
response = await mock.handle(method as any, path);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
Then("I should receive text {string}", (_, expectedText: string) => {
|
|
24
|
+
expect(response.body).toBe(expectedText);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
And("the content-type should be {string}", (_, contentType: string) => {
|
|
28
|
+
expect(response.headers?.["content-type"]).toBe(contentType);
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
Scenario("Return JSON without specifying contentType", ({ Given, When, Then, And }) => {
|
|
33
|
+
Given("I create a mock with:", (_, docString: string) => {
|
|
34
|
+
mock = schmock();
|
|
35
|
+
mock('GET /users', [{ id: 1, name: 'John' }]);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
When("I request {string}", async (_, request: string) => {
|
|
39
|
+
const [method, path] = request.split(" ");
|
|
40
|
+
response = await mock.handle(method as any, path);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
Then("I should receive:", (_, docString: string) => {
|
|
44
|
+
const expected = JSON.parse(docString);
|
|
45
|
+
expect(response.body).toEqual(expected);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
And("the content-type should be {string}", (_, contentType: string) => {
|
|
49
|
+
expect(response.headers?.["content-type"]).toBe(contentType);
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
Scenario("Return object without contentType", ({ Given, When, Then, And }) => {
|
|
54
|
+
Given("I create a mock with:", (_, docString: string) => {
|
|
55
|
+
mock = schmock();
|
|
56
|
+
mock('GET /user', { id: 1, name: 'John' });
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
When("I request {string}", async (_, request: string) => {
|
|
60
|
+
const [method, path] = request.split(" ");
|
|
61
|
+
response = await mock.handle(method as any, path);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
Then("I should receive:", (_, docString: string) => {
|
|
65
|
+
const expected = JSON.parse(docString);
|
|
66
|
+
expect(response.body).toEqual(expected);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
And("the content-type should be {string}", (_, contentType: string) => {
|
|
70
|
+
expect(response.headers?.["content-type"]).toBe(contentType);
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
Scenario("Empty mock instance", ({ Given, When, Then }) => {
|
|
75
|
+
Given("I create a mock with:", (_, docString: string) => {
|
|
76
|
+
mock = schmock();
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
When("I request {string}", async (_, request: string) => {
|
|
80
|
+
const [method, path] = request.split(" ");
|
|
81
|
+
response = await mock.handle(method as any, path);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
Then("the status should be {int}", (_, status: number) => {
|
|
85
|
+
expect(response.status).toBe(status);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
Scenario("Null response", ({ Given, When, Then, And }) => {
|
|
90
|
+
Given("I create a mock with:", (_, docString: string) => {
|
|
91
|
+
mock = schmock();
|
|
92
|
+
mock('GET /null', null);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
When("I request {string}", async (_, request: string) => {
|
|
96
|
+
const [method, path] = request.split(" ");
|
|
97
|
+
response = await mock.handle(method as any, path);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
Then("I should receive empty response", () => {
|
|
101
|
+
expect(response.body).toBeUndefined();
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
And("the status should be {int}", (_, status: number) => {
|
|
105
|
+
expect(response.status).toBe(status);
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
Scenario("Undefined response", ({ Given, When, Then, And }) => {
|
|
110
|
+
Given("I create a mock with:", (_, docString: string) => {
|
|
111
|
+
mock = schmock();
|
|
112
|
+
mock('GET /undefined', undefined);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
When("I request {string}", async (_, request: string) => {
|
|
116
|
+
const [method, path] = request.split(" ");
|
|
117
|
+
response = await mock.handle(method as any, path);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
Then("I should receive empty response", () => {
|
|
121
|
+
expect(response.body).toBeUndefined();
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
And("the status should be {int}", (_, status: number) => {
|
|
125
|
+
expect(response.status).toBe(status);
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
Scenario("Empty string response", ({ Given, When, Then, And }) => {
|
|
130
|
+
Given("I create a mock with:", (_, docString: string) => {
|
|
131
|
+
mock = schmock();
|
|
132
|
+
mock('GET /empty', '');
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
When("I request {string}", async (_, request: string) => {
|
|
136
|
+
const [method, path] = request.split(" ");
|
|
137
|
+
response = await mock.handle(method as any, path);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
Then("I should receive text {string}", (_, expectedText: string) => {
|
|
141
|
+
expect(response.body).toBe(expectedText);
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
And("the content-type should be {string}", (_, contentType: string) => {
|
|
145
|
+
expect(response.headers?.["content-type"]).toBe(contentType);
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
Scenario("Number response", ({ Given, When, Then, And }) => {
|
|
150
|
+
Given("I create a mock with:", (_, docString: string) => {
|
|
151
|
+
mock = schmock();
|
|
152
|
+
mock('GET /count', 42);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
When("I request {string}", async (_, request: string) => {
|
|
156
|
+
const [method, path] = request.split(" ");
|
|
157
|
+
response = await mock.handle(method as any, path);
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
Then("I should receive text {string}", (_, expectedText: string) => {
|
|
161
|
+
expect(response.body).toBe(expectedText);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
And("the content-type should be {string}", (_, contentType: string) => {
|
|
165
|
+
expect(response.headers?.["content-type"]).toBe(contentType);
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
Scenario("Boolean response", ({ Given, When, Then, And }) => {
|
|
170
|
+
Given("I create a mock with:", (_, docString: string) => {
|
|
171
|
+
mock = schmock();
|
|
172
|
+
mock('GET /active', true);
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
When("I request {string}", async (_, request: string) => {
|
|
176
|
+
const [method, path] = request.split(" ");
|
|
177
|
+
response = await mock.handle(method as any, path);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
Then("I should receive text {string}", (_, expectedText: string) => {
|
|
181
|
+
expect(response.body).toBe(expectedText);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
And("the content-type should be {string}", (_, contentType: string) => {
|
|
185
|
+
expect(response.headers?.["content-type"]).toBe(contentType);
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
Scenario("Function returning string", ({ Given, When, Then }) => {
|
|
190
|
+
Given("I create a mock with:", (_, docString: string) => {
|
|
191
|
+
mock = schmock();
|
|
192
|
+
mock('GET /dynamic', () => 'Dynamic response');
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
When("I request {string}", async (_, request: string) => {
|
|
196
|
+
const [method, path] = request.split(" ");
|
|
197
|
+
response = await mock.handle(method as any, path);
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
Then("I should receive text {string}", (_, expectedText: string) => {
|
|
201
|
+
expect(response.body).toBe(expectedText);
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
Scenario("Function returning object", ({ Given, When, Then, And }) => {
|
|
206
|
+
Given("I create a mock with:", (_, docString: string) => {
|
|
207
|
+
mock = schmock();
|
|
208
|
+
mock('GET /dynamic-json', () => ({ timestamp: Date.now() }));
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
When("I request {string}", async (_, request: string) => {
|
|
212
|
+
const [method, path] = request.split(" ");
|
|
213
|
+
response = await mock.handle(method as any, path);
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
Then("the response should be valid JSON", () => {
|
|
217
|
+
expect(() => JSON.parse(JSON.stringify(response.body))).not.toThrow();
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
And("the response should have property {string}", (_, property: string) => {
|
|
221
|
+
expect(response.body).toHaveProperty(property);
|
|
222
|
+
});
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
Scenario("Multiple routes", ({ Given, When, Then, And }) => {
|
|
226
|
+
let homeResponse: any;
|
|
227
|
+
let aboutResponse: any;
|
|
228
|
+
let contactResponse: any;
|
|
229
|
+
|
|
230
|
+
Given("I create a mock with:", (_, docString: string) => {
|
|
231
|
+
mock = schmock();
|
|
232
|
+
mock('GET /', 'Home');
|
|
233
|
+
mock('GET /about', 'About Us');
|
|
234
|
+
mock('GET /contact', { email: 'test@example.com' });
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
When("I make three requests to different routes", async () => {
|
|
238
|
+
homeResponse = await mock.handle('GET', '/');
|
|
239
|
+
aboutResponse = await mock.handle('GET', '/about');
|
|
240
|
+
contactResponse = await mock.handle('GET', '/contact');
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
Then("the home route should return {string}", (_, expectedText: string) => {
|
|
244
|
+
expect(homeResponse.body).toBe(expectedText);
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
And("the about route should return {string}", (_, expectedText: string) => {
|
|
248
|
+
expect(aboutResponse.body).toBe(expectedText);
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
And("the contact route should return:", (_, docString: string) => {
|
|
252
|
+
const expected = JSON.parse(docString);
|
|
253
|
+
expect(contactResponse.body).toEqual(expected);
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
Scenario("Override contentType detection", ({ Given, When, Then, And }) => {
|
|
258
|
+
Given("I create a mock with:", (_, docString: string) => {
|
|
259
|
+
mock = schmock();
|
|
260
|
+
mock('GET /data', { foo: 'bar' }, { contentType: 'text/plain' });
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
When("I request {string}", async (_, request: string) => {
|
|
264
|
+
const [method, path] = request.split(" ");
|
|
265
|
+
response = await mock.handle(method as any, path);
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
Then("I should receive text {string}", (_, expectedText: string) => {
|
|
269
|
+
expect(response.body).toBe(expectedText);
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
And("the content-type should be {string}", (_, contentType: string) => {
|
|
273
|
+
expect(response.headers?.["content-type"]).toBe(contentType);
|
|
274
|
+
});
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
Scenario("HTML response", ({ Given, When, Then, And }) => {
|
|
278
|
+
Given("I create a mock with:", (_, docString: string) => {
|
|
279
|
+
mock = schmock();
|
|
280
|
+
mock('GET /page', '<h1>Hello</h1>', { contentType: 'text/html' });
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
When("I request {string}", async (_, request: string) => {
|
|
284
|
+
const [method, path] = request.split(" ");
|
|
285
|
+
response = await mock.handle(method as any, path);
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
Then("I should receive text {string}", (_, expectedText: string) => {
|
|
289
|
+
expect(response.body).toBe(expectedText);
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
And("the content-type should be {string}", (_, contentType: string) => {
|
|
293
|
+
expect(response.headers?.["content-type"]).toBe(contentType);
|
|
294
|
+
});
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
Scenario("Binary/buffer response detection", ({ Given, When, Then, And }) => {
|
|
298
|
+
Given("I create a mock with:", (_, docString: string) => {
|
|
299
|
+
mock = schmock();
|
|
300
|
+
mock('GET /binary', Buffer.from('binary data'));
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
When("I request {string}", async (_, request: string) => {
|
|
304
|
+
const [method, path] = request.split(" ");
|
|
305
|
+
response = await mock.handle(method as any, path);
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
Then("I should receive buffer data", () => {
|
|
309
|
+
expect(Buffer.isBuffer(response.body)).toBe(true);
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
And("the content-type should be {string}", (_, contentType: string) => {
|
|
313
|
+
expect(response.headers?.["content-type"]).toBe(contentType);
|
|
314
|
+
});
|
|
315
|
+
});
|
|
316
|
+
});
|