@warp-drive/holodeck 0.0.0-alpha.93 → 0.0.0-alpha.94
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/package.json +6 -6
- package/server/index.js +98 -78
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@warp-drive/holodeck",
|
|
3
3
|
"description": "⚡️ Simple, Fast HTTP Mocking for Tests",
|
|
4
|
-
"version": "0.0.0-alpha.
|
|
4
|
+
"version": "0.0.0-alpha.94",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Chris Thoburn <runspired@users.noreply.github.com>",
|
|
7
7
|
"repository": {
|
|
@@ -44,8 +44,8 @@
|
|
|
44
44
|
"sync-hardlinks": "bun run sync-dependencies-meta-injected"
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {
|
|
47
|
-
"@ember-data/request": "5.4.0-alpha.
|
|
48
|
-
"@warp-drive/core-types": "0.0.0-alpha.
|
|
47
|
+
"@ember-data/request": "5.4.0-alpha.108",
|
|
48
|
+
"@warp-drive/core-types": "0.0.0-alpha.94"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@babel/core": "^7.24.5",
|
|
@@ -53,9 +53,9 @@
|
|
|
53
53
|
"@babel/preset-env": "^7.24.5",
|
|
54
54
|
"@babel/preset-typescript": "^7.24.1",
|
|
55
55
|
"@babel/runtime": "^7.24.5",
|
|
56
|
-
"@ember-data/request": "5.4.0-alpha.
|
|
57
|
-
"@warp-drive/core-types": "0.0.0-alpha.
|
|
58
|
-
"@warp-drive/internal-config": "5.4.0-alpha.
|
|
56
|
+
"@ember-data/request": "5.4.0-alpha.108",
|
|
57
|
+
"@warp-drive/core-types": "0.0.0-alpha.94",
|
|
58
|
+
"@warp-drive/internal-config": "5.4.0-alpha.108",
|
|
59
59
|
"pnpm-sync-dependencies-meta-injected": "0.0.14",
|
|
60
60
|
"typescript": "^5.4.5",
|
|
61
61
|
"vite": "^5.2.11"
|
package/server/index.js
CHANGED
|
@@ -147,96 +147,116 @@ function replayRequest(context, cacheKey) {
|
|
|
147
147
|
|
|
148
148
|
function createTestHandler(projectRoot) {
|
|
149
149
|
const TestHandler = async (context) => {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
150
|
+
try {
|
|
151
|
+
const { req } = context;
|
|
152
|
+
|
|
153
|
+
const testId = req.query('__xTestId');
|
|
154
|
+
const testRequestNumber = req.query('__xTestRequestNumber');
|
|
155
|
+
const niceUrl = getNiceUrl(req.url);
|
|
156
|
+
|
|
157
|
+
if (!testId) {
|
|
158
|
+
context.header('Content-Type', 'application/vnd.api+json');
|
|
159
|
+
context.status(400);
|
|
160
|
+
return context.body(
|
|
161
|
+
JSON.stringify({
|
|
162
|
+
errors: [
|
|
163
|
+
{
|
|
164
|
+
status: '400',
|
|
165
|
+
code: 'MISSING_X_TEST_ID_HEADER',
|
|
166
|
+
title: 'Request to the http mock server is missing the `X-Test-Id` header',
|
|
167
|
+
detail:
|
|
168
|
+
"The `X-Test-Id` header is used to identify the test that is making the request to the mock server. This is used to ensure that the mock server is only used for the test that is currently running. If using @ember-data/request add import { MockServerHandler } from '@warp-drive/holodeck'; to your request handlers.",
|
|
169
|
+
source: { header: 'X-Test-Id' },
|
|
170
|
+
},
|
|
171
|
+
],
|
|
172
|
+
})
|
|
173
|
+
);
|
|
174
|
+
}
|
|
155
175
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
176
|
+
if (!testRequestNumber) {
|
|
177
|
+
context.header('Content-Type', 'application/vnd.api+json');
|
|
178
|
+
context.status(400);
|
|
179
|
+
return context.body(
|
|
180
|
+
JSON.stringify({
|
|
181
|
+
errors: [
|
|
182
|
+
{
|
|
183
|
+
status: '400',
|
|
184
|
+
code: 'MISSING_X_TEST_REQUEST_NUMBER_HEADER',
|
|
185
|
+
title: 'Request to the http mock server is missing the `X-Test-Request-Number` header',
|
|
186
|
+
detail:
|
|
187
|
+
"The `X-Test-Request-Number` header is used to identify the request number for the current test. This is used to ensure that the mock server response is deterministic for the test that is currently running. If using @ember-data/request add import { MockServerHandler } from '@warp-drive/holodeck'; to your request handlers.",
|
|
188
|
+
source: { header: 'X-Test-Request-Number' },
|
|
189
|
+
},
|
|
190
|
+
],
|
|
191
|
+
})
|
|
192
|
+
);
|
|
193
|
+
}
|
|
174
194
|
|
|
175
|
-
|
|
195
|
+
if (req.method === 'POST' || niceUrl === '__record') {
|
|
196
|
+
const payload = await req.json();
|
|
197
|
+
const { url, headers, method, status, statusText, body, response } = payload;
|
|
198
|
+
const cacheKey = generateFilepath({
|
|
199
|
+
projectRoot,
|
|
200
|
+
testId,
|
|
201
|
+
url,
|
|
202
|
+
method,
|
|
203
|
+
body: body ? JSON.stringify(body) : null,
|
|
204
|
+
testRequestNumber,
|
|
205
|
+
});
|
|
206
|
+
// allow Content-Type to be overridden
|
|
207
|
+
headers['Content-Type'] = headers['Content-Type'] || 'application/vnd.api+json';
|
|
208
|
+
// We always compress and chunk the response
|
|
209
|
+
headers['Content-Encoding'] = 'br';
|
|
210
|
+
// we don't cache since tests will often reuse similar urls for different payload
|
|
211
|
+
headers['Cache-Control'] = 'no-store';
|
|
212
|
+
|
|
213
|
+
const cacheDir = generateFileDir({
|
|
214
|
+
projectRoot,
|
|
215
|
+
testId,
|
|
216
|
+
url,
|
|
217
|
+
method,
|
|
218
|
+
testRequestNumber,
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
fs.mkdirSync(cacheDir, { recursive: true });
|
|
222
|
+
fs.writeFileSync(
|
|
223
|
+
`${cacheKey}.meta.json`,
|
|
224
|
+
JSON.stringify({ url, status, statusText, headers, method, requestBody: body }, null, 2)
|
|
225
|
+
);
|
|
226
|
+
fs.writeFileSync(`${cacheKey}.body.br`, compress(JSON.stringify(response)));
|
|
227
|
+
context.status(204);
|
|
228
|
+
return context.body(null);
|
|
229
|
+
} else {
|
|
230
|
+
const body = await req.text();
|
|
231
|
+
const cacheKey = generateFilepath({
|
|
232
|
+
projectRoot,
|
|
233
|
+
testId,
|
|
234
|
+
url: niceUrl,
|
|
235
|
+
method: req.method,
|
|
236
|
+
body,
|
|
237
|
+
testRequestNumber,
|
|
238
|
+
});
|
|
239
|
+
return replayRequest(context, cacheKey);
|
|
240
|
+
}
|
|
241
|
+
} catch (e) {
|
|
242
|
+
if (e instanceof HTTPException) {
|
|
243
|
+
throw e;
|
|
244
|
+
}
|
|
176
245
|
context.header('Content-Type', 'application/vnd.api+json');
|
|
177
|
-
context.status(
|
|
246
|
+
context.status(500);
|
|
178
247
|
return context.body(
|
|
179
248
|
JSON.stringify({
|
|
180
249
|
errors: [
|
|
181
250
|
{
|
|
182
|
-
status: '
|
|
183
|
-
code: '
|
|
184
|
-
title: '
|
|
185
|
-
detail:
|
|
186
|
-
"The `X-Test-Request-Number` header is used to identify the request number for the current test. This is used to ensure that the mock server response is deterministic for the test that is currently running. If using @ember-data/request add import { MockServerHandler } from '@warp-drive/holodeck'; to your request handlers.",
|
|
187
|
-
source: { header: 'X-Test-Request-Number' },
|
|
251
|
+
status: '500',
|
|
252
|
+
code: 'MOCK_SERVER_ERROR',
|
|
253
|
+
title: 'Mock Server Error during Request',
|
|
254
|
+
detail: e.message,
|
|
188
255
|
},
|
|
189
256
|
],
|
|
190
257
|
})
|
|
191
258
|
);
|
|
192
259
|
}
|
|
193
|
-
|
|
194
|
-
if (req.method === 'POST' || niceUrl === '__record') {
|
|
195
|
-
const payload = await req.json();
|
|
196
|
-
const { url, headers, method, status, statusText, body, response } = payload;
|
|
197
|
-
const cacheKey = generateFilepath({
|
|
198
|
-
projectRoot,
|
|
199
|
-
testId,
|
|
200
|
-
url,
|
|
201
|
-
method,
|
|
202
|
-
body: body ? JSON.stringify(body) : null,
|
|
203
|
-
testRequestNumber,
|
|
204
|
-
});
|
|
205
|
-
// allow Content-Type to be overridden
|
|
206
|
-
headers['Content-Type'] = headers['Content-Type'] || 'application/vnd.api+json';
|
|
207
|
-
// We always compress and chunk the response
|
|
208
|
-
headers['Content-Encoding'] = 'br';
|
|
209
|
-
// we don't cache since tests will often reuse similar urls for different payload
|
|
210
|
-
headers['Cache-Control'] = 'no-store';
|
|
211
|
-
|
|
212
|
-
const cacheDir = generateFileDir({
|
|
213
|
-
projectRoot,
|
|
214
|
-
testId,
|
|
215
|
-
url,
|
|
216
|
-
method,
|
|
217
|
-
testRequestNumber,
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
fs.mkdirSync(cacheDir, { recursive: true });
|
|
221
|
-
fs.writeFileSync(
|
|
222
|
-
`${cacheKey}.meta.json`,
|
|
223
|
-
JSON.stringify({ url, status, statusText, headers, method, requestBody: body }, null, 2)
|
|
224
|
-
);
|
|
225
|
-
fs.writeFileSync(`${cacheKey}.body.br`, compress(JSON.stringify(response)));
|
|
226
|
-
context.status(204);
|
|
227
|
-
return context.body(null);
|
|
228
|
-
} else {
|
|
229
|
-
const body = await req.text();
|
|
230
|
-
const cacheKey = generateFilepath({
|
|
231
|
-
projectRoot,
|
|
232
|
-
testId,
|
|
233
|
-
url: niceUrl,
|
|
234
|
-
method: req.method,
|
|
235
|
-
body,
|
|
236
|
-
testRequestNumber,
|
|
237
|
-
});
|
|
238
|
-
return replayRequest(context, cacheKey);
|
|
239
|
-
}
|
|
240
260
|
};
|
|
241
261
|
|
|
242
262
|
return TestHandler;
|