@warp-drive/holodeck 0.0.0-alpha.92 → 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.
Files changed (2) hide show
  1. package/package.json +6 -6
  2. 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.92",
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.106",
48
- "@warp-drive/core-types": "0.0.0-alpha.92"
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.106",
57
- "@warp-drive/core-types": "0.0.0-alpha.92",
58
- "@warp-drive/internal-config": "5.4.0-alpha.106",
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
- const { req } = context;
151
-
152
- const testId = req.query('__xTestId');
153
- const testRequestNumber = req.query('__xTestRequestNumber');
154
- const niceUrl = getNiceUrl(req.url);
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
- if (!testId) {
157
- context.header('Content-Type', 'application/vnd.api+json');
158
- context.status(400);
159
- return context.body(
160
- JSON.stringify({
161
- errors: [
162
- {
163
- status: '400',
164
- code: 'MISSING_X_TEST_ID_HEADER',
165
- title: 'Request to the http mock server is missing the `X-Test-Id` header',
166
- detail:
167
- "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.",
168
- source: { header: 'X-Test-Id' },
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
- if (!testRequestNumber) {
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(400);
246
+ context.status(500);
178
247
  return context.body(
179
248
  JSON.stringify({
180
249
  errors: [
181
250
  {
182
- status: '400',
183
- code: 'MISSING_X_TEST_REQUEST_NUMBER_HEADER',
184
- title: 'Request to the http mock server is missing the `X-Test-Request-Number` header',
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;