test-proxy-recorder 0.1.4 → 0.1.5

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/README.md CHANGED
@@ -191,7 +191,7 @@ interface ControlRequest {
191
191
  ### Playwright Integration API
192
192
 
193
193
  ```typescript
194
- import { playwrightProxy } from 'test-proxy-recorder';
194
+ import { playwrightProxy, setProxyMode } from 'test-proxy-recorder';
195
195
 
196
196
  // Main helper object for use with Playwright tests
197
197
  const playwrightProxy = {
@@ -203,14 +203,84 @@ const playwrightProxy = {
203
203
  };
204
204
  ```
205
205
 
206
- ## Recording Format
206
+ ### Global Teardown and Hooks Setup (Recommended)
207
+
208
+ For robust test setups, it's recommended to configure global teardown and afterEach hooks to ensure the proxy is properly reset even when tests fail. This prevents the proxy from staying in record/replay mode, which could affect subsequent test runs.
209
+
210
+ #### 1. Create Global Teardown File
211
+
212
+ Create `e2e/global-teardown.ts` to reset the proxy mode after all tests complete:
213
+
214
+ ```typescript
215
+ import { setProxyMode } from 'test-proxy-recorder';
216
+
217
+ async function globalTeardown() {
218
+ await setProxyMode('transparent');
219
+ }
220
+
221
+ export default globalTeardown;
222
+ ```
223
+
224
+ #### 2. Create Global Hooks File
225
+
226
+ Create `e2e/global-hooks.ts` to ensure proxy cleanup happens after each test, even on failure:
207
227
 
208
- Recordings are stored as JSON files in the recordings directory:
228
+ ```typescript
229
+ import { test } from '@playwright/test';
230
+ import { playwrightProxy } from 'test-proxy-recorder';
209
231
 
232
+ /**
233
+ * Global afterEach hook to ensure proxy cleanup happens even when tests fail.
234
+ * This will run after every test across all test files.
235
+ */
236
+ test.afterEach(async ({}, testInfo) => {
237
+ try {
238
+ await playwrightProxy.after(testInfo);
239
+ } catch (error) {
240
+ console.error('Error during proxy cleanup:', error);
241
+ // Don't throw - we want cleanup to continue even if this fails
242
+ }
243
+ });
210
244
  ```
245
+
246
+ #### 3. Configure Playwright
247
+
248
+ Update your `playwright.config.ts` to include the global teardown:
249
+
250
+ ```typescript
251
+ import { defineConfig } from '@playwright/test';
252
+
253
+ export default defineConfig({
254
+ testDir: './e2e',
255
+ globalTeardown: './e2e/global-teardown.ts',
256
+ // ... rest of your config
257
+ });
258
+ ```
259
+
260
+ #### 4. Import Global Hooks in Your Base Page or Test Setup
261
+
262
+ Import the global hooks file in your base test file or base page to register the afterEach hook:
263
+
264
+ ```typescript
265
+ // In your e2e/basePage.ts or similar base test file
266
+ import { test as base } from '@playwright/test';
267
+
268
+ // Import global hooks to register afterEach for proxy cleanup
269
+ import './global-hooks';
270
+
271
+ export const test = base.extend({
272
+ // your fixtures
273
+ });
274
+ ```
275
+
276
+ ## Recording Format
277
+
278
+ Recordings are stored as JSON files with `.mock.json` extension in the recordings directory:
279
+
280
+ ```text
211
281
  recordings/
212
- ├── test-session-1.json
213
- ├── test-session-2.json
282
+ ├── test-session-1.mock.json
283
+ ├── test-session-2.mock.json
214
284
  └── ...
215
285
  ```
216
286
 
@@ -228,11 +298,7 @@ Each recording contains:
228
298
  test-proxy-recorder http://localhost:8000 --port 8100
229
299
  ```
230
300
 
231
- 2. **Configure your app** to use the proxy:
232
-
233
- ```bash
234
- export EXTERNAL_API_URL=http://localhost:8100 yarn dev
235
- ```
301
+ 2. **Configure your app** to use the proxy (point your app to the proxy port, e.g., 8100)
236
302
 
237
303
  3. **Record responses** (first run):
238
304
 
@@ -47,7 +47,7 @@ interface RecordingSession {
47
47
  websocketRecordings: WebSocketRecording[];
48
48
  }
49
49
 
50
- type PlaywrightTestInfo = Pick<TestInfo, 'title'>;
50
+ type PlaywrightTestInfo = Pick<TestInfo, 'title' | 'titlePath'>;
51
51
  /**
52
52
  * Set the proxy mode for a given session
53
53
  * @param mode - The proxy mode to set (recording, replay, transparent)
@@ -57,6 +57,10 @@ type PlaywrightTestInfo = Pick<TestInfo, 'title'>;
57
57
  declare function setProxyMode(mode: Mode, sessionId?: string, timeout?: number): Promise<void>;
58
58
  /**
59
59
  * Generate a session ID from test info
60
+ * Uses titlePath to create folder structure with test file name
61
+ * Supports both .spec.ts and .test.ts extensions
62
+ * Example: ['jobs/Create.spec.ts', 'create a job'] becomes 'jobs/Create__create-a-job'
63
+ * Example: ['users/Auth.test.ts', 'login test'] becomes 'users/Auth__login-test'
60
64
  * @param testInfo - Playwright test info object
61
65
  */
62
66
  declare function generateSessionId(testInfo: PlaywrightTestInfo): string;
@@ -47,7 +47,7 @@ interface RecordingSession {
47
47
  websocketRecordings: WebSocketRecording[];
48
48
  }
49
49
 
50
- type PlaywrightTestInfo = Pick<TestInfo, 'title'>;
50
+ type PlaywrightTestInfo = Pick<TestInfo, 'title' | 'titlePath'>;
51
51
  /**
52
52
  * Set the proxy mode for a given session
53
53
  * @param mode - The proxy mode to set (recording, replay, transparent)
@@ -57,6 +57,10 @@ type PlaywrightTestInfo = Pick<TestInfo, 'title'>;
57
57
  declare function setProxyMode(mode: Mode, sessionId?: string, timeout?: number): Promise<void>;
58
58
  /**
59
59
  * Generate a session ID from test info
60
+ * Uses titlePath to create folder structure with test file name
61
+ * Supports both .spec.ts and .test.ts extensions
62
+ * Example: ['jobs/Create.spec.ts', 'create a job'] becomes 'jobs/Create__create-a-job'
63
+ * Example: ['users/Auth.test.ts', 'login test'] becomes 'users/Auth__login-test'
60
64
  * @param testInfo - Playwright test info object
61
65
  */
62
66
  declare function generateSessionId(testInfo: PlaywrightTestInfo): string;
package/dist/index.cjs CHANGED
@@ -35,7 +35,7 @@ var Modes = {
35
35
  };
36
36
  var JSON_INDENT_SPACES = 2;
37
37
  function getRecordingPath(recordingsDir, id) {
38
- return path__default.default.join(recordingsDir, `${id}.json`);
38
+ return path__default.default.join(recordingsDir, `${id}.mock.json`);
39
39
  }
40
40
  async function loadRecordingSession(filePath) {
41
41
  const fileContent = await fs__default.default.readFile(filePath, "utf8");
@@ -43,6 +43,8 @@ async function loadRecordingSession(filePath) {
43
43
  }
44
44
  async function saveRecordingSession(recordingsDir, session) {
45
45
  const filePath = getRecordingPath(recordingsDir, session.id);
46
+ const dirPath = path__default.default.dirname(filePath);
47
+ await fs__default.default.mkdir(dirPath, { recursive: true });
46
48
  await fs__default.default.writeFile(
47
49
  filePath,
48
50
  JSON.stringify(session, null, JSON_INDENT_SPACES)
@@ -127,6 +129,7 @@ var ProxyServer = class {
127
129
  this.handleUpgrade(req, socket, head);
128
130
  });
129
131
  server.listen(port, () => {
132
+ process.env.TEST_PROXY_RECORDER_PORT = String(port);
130
133
  this.logServerStartup(port);
131
134
  });
132
135
  return server;
@@ -605,15 +608,25 @@ var ProxyServer = class {
605
608
  };
606
609
 
607
610
  // src/playwright/index.ts
608
- var INTERNAL_API_URL = process.env.INTERNAL_API_URL || "http://localhost:8100";
611
+ function getProxyPort() {
612
+ const envPort = process.env.TEST_PROXY_RECORDER_PORT;
613
+ if (envPort) {
614
+ const parsed = Number.parseInt(envPort, 10);
615
+ if (!Number.isNaN(parsed)) {
616
+ return parsed;
617
+ }
618
+ }
619
+ return 8100;
620
+ }
609
621
  async function setProxyMode(mode, sessionId, timeout) {
622
+ const proxyPort = getProxyPort();
610
623
  try {
611
624
  const body = {
612
625
  mode,
613
626
  id: sessionId,
614
627
  ...timeout && { timeout }
615
628
  };
616
- const response = await fetch(`${INTERNAL_API_URL}/__control`, {
629
+ const response = await fetch(`http://127.0.0.1:${proxyPort}/__control`, {
617
630
  method: "POST",
618
631
  headers: { "Content-Type": "application/json" },
619
632
  body: JSON.stringify(body)
@@ -630,8 +643,34 @@ async function setProxyMode(mode, sessionId, timeout) {
630
643
  throw error;
631
644
  }
632
645
  }
646
+ function parseSpecFilePath(specPath) {
647
+ const folderMatch = specPath.match(/^(.+?)\/([^/]+)\.(spec|test)\.ts$/);
648
+ if (folderMatch) {
649
+ return { folder: folderMatch[1], fileName: folderMatch[2] };
650
+ }
651
+ const fileMatch = specPath.match(/^([^/]+)\.(spec|test)\.ts$/);
652
+ if (fileMatch) {
653
+ return { folder: null, fileName: fileMatch[1] };
654
+ }
655
+ return { folder: null, fileName: null };
656
+ }
657
+ function buildSessionPath(folder, fileName, testName) {
658
+ if (folder && fileName) {
659
+ return `${folder}/${fileName}__${testName}`;
660
+ }
661
+ if (fileName) {
662
+ return `${fileName}__${testName}`;
663
+ }
664
+ return testName;
665
+ }
633
666
  function generateSessionId(testInfo) {
634
- return testInfo.title.toLowerCase().replaceAll(/\s+/g, "-");
667
+ const { titlePath } = testInfo;
668
+ if (!titlePath || titlePath.length === 0) {
669
+ return testInfo.title.toLowerCase().replaceAll(/\s+/g, "-");
670
+ }
671
+ const { folder, fileName } = parseSpecFilePath(titlePath[0]);
672
+ const testName = titlePath.at(-1).toLowerCase().replaceAll(/\s+/g, "-");
673
+ return buildSessionPath(folder, fileName, testName);
635
674
  }
636
675
  async function startRecording(testInfo) {
637
676
  const sessionId = generateSessionId(testInfo);
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import http from 'node:http';
2
- export { C as ControlRequest, M as Mode, P as PlaywrightTestInfo, R as Recording, a as RecordingSession, W as WebSocketRecording, g as generateSessionId, p as playwrightProxy, s as setProxyMode, b as startRecording, c as startReplay, d as stopProxy } from './index-De4mgziH.cjs';
2
+ export { C as ControlRequest, M as Mode, P as PlaywrightTestInfo, R as Recording, a as RecordingSession, W as WebSocketRecording, g as generateSessionId, p as playwrightProxy, s as setProxyMode, b as startRecording, c as startReplay, d as stopProxy } from './index-CBjvm5rb.cjs';
3
3
  import '@playwright/test';
4
4
 
5
5
  declare class ProxyServer {
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import http from 'node:http';
2
- export { C as ControlRequest, M as Mode, P as PlaywrightTestInfo, R as Recording, a as RecordingSession, W as WebSocketRecording, g as generateSessionId, p as playwrightProxy, s as setProxyMode, b as startRecording, c as startReplay, d as stopProxy } from './index-De4mgziH.js';
2
+ export { C as ControlRequest, M as Mode, P as PlaywrightTestInfo, R as Recording, a as RecordingSession, W as WebSocketRecording, g as generateSessionId, p as playwrightProxy, s as setProxyMode, b as startRecording, c as startReplay, d as stopProxy } from './index-CBjvm5rb.js';
3
3
  import '@playwright/test';
4
4
 
5
5
  declare class ProxyServer {
package/dist/index.mjs CHANGED
@@ -24,7 +24,7 @@ var Modes = {
24
24
  };
25
25
  var JSON_INDENT_SPACES = 2;
26
26
  function getRecordingPath(recordingsDir, id) {
27
- return path.join(recordingsDir, `${id}.json`);
27
+ return path.join(recordingsDir, `${id}.mock.json`);
28
28
  }
29
29
  async function loadRecordingSession(filePath) {
30
30
  const fileContent = await fs.readFile(filePath, "utf8");
@@ -32,6 +32,8 @@ async function loadRecordingSession(filePath) {
32
32
  }
33
33
  async function saveRecordingSession(recordingsDir, session) {
34
34
  const filePath = getRecordingPath(recordingsDir, session.id);
35
+ const dirPath = path.dirname(filePath);
36
+ await fs.mkdir(dirPath, { recursive: true });
35
37
  await fs.writeFile(
36
38
  filePath,
37
39
  JSON.stringify(session, null, JSON_INDENT_SPACES)
@@ -116,6 +118,7 @@ var ProxyServer = class {
116
118
  this.handleUpgrade(req, socket, head);
117
119
  });
118
120
  server.listen(port, () => {
121
+ process.env.TEST_PROXY_RECORDER_PORT = String(port);
119
122
  this.logServerStartup(port);
120
123
  });
121
124
  return server;
@@ -594,15 +597,25 @@ var ProxyServer = class {
594
597
  };
595
598
 
596
599
  // src/playwright/index.ts
597
- var INTERNAL_API_URL = process.env.INTERNAL_API_URL || "http://localhost:8100";
600
+ function getProxyPort() {
601
+ const envPort = process.env.TEST_PROXY_RECORDER_PORT;
602
+ if (envPort) {
603
+ const parsed = Number.parseInt(envPort, 10);
604
+ if (!Number.isNaN(parsed)) {
605
+ return parsed;
606
+ }
607
+ }
608
+ return 8100;
609
+ }
598
610
  async function setProxyMode(mode, sessionId, timeout) {
611
+ const proxyPort = getProxyPort();
599
612
  try {
600
613
  const body = {
601
614
  mode,
602
615
  id: sessionId,
603
616
  ...timeout && { timeout }
604
617
  };
605
- const response = await fetch(`${INTERNAL_API_URL}/__control`, {
618
+ const response = await fetch(`http://127.0.0.1:${proxyPort}/__control`, {
606
619
  method: "POST",
607
620
  headers: { "Content-Type": "application/json" },
608
621
  body: JSON.stringify(body)
@@ -619,8 +632,34 @@ async function setProxyMode(mode, sessionId, timeout) {
619
632
  throw error;
620
633
  }
621
634
  }
635
+ function parseSpecFilePath(specPath) {
636
+ const folderMatch = specPath.match(/^(.+?)\/([^/]+)\.(spec|test)\.ts$/);
637
+ if (folderMatch) {
638
+ return { folder: folderMatch[1], fileName: folderMatch[2] };
639
+ }
640
+ const fileMatch = specPath.match(/^([^/]+)\.(spec|test)\.ts$/);
641
+ if (fileMatch) {
642
+ return { folder: null, fileName: fileMatch[1] };
643
+ }
644
+ return { folder: null, fileName: null };
645
+ }
646
+ function buildSessionPath(folder, fileName, testName) {
647
+ if (folder && fileName) {
648
+ return `${folder}/${fileName}__${testName}`;
649
+ }
650
+ if (fileName) {
651
+ return `${fileName}__${testName}`;
652
+ }
653
+ return testName;
654
+ }
622
655
  function generateSessionId(testInfo) {
623
- return testInfo.title.toLowerCase().replaceAll(/\s+/g, "-");
656
+ const { titlePath } = testInfo;
657
+ if (!titlePath || titlePath.length === 0) {
658
+ return testInfo.title.toLowerCase().replaceAll(/\s+/g, "-");
659
+ }
660
+ const { folder, fileName } = parseSpecFilePath(titlePath[0]);
661
+ const testName = titlePath.at(-1).toLowerCase().replaceAll(/\s+/g, "-");
662
+ return buildSessionPath(folder, fileName, testName);
624
663
  }
625
664
  async function startRecording(testInfo) {
626
665
  const sessionId = generateSessionId(testInfo);
@@ -8,15 +8,25 @@ var Modes = {
8
8
  };
9
9
 
10
10
  // src/playwright/index.ts
11
- var INTERNAL_API_URL = process.env.INTERNAL_API_URL || "http://localhost:8100";
11
+ function getProxyPort() {
12
+ const envPort = process.env.TEST_PROXY_RECORDER_PORT;
13
+ if (envPort) {
14
+ const parsed = Number.parseInt(envPort, 10);
15
+ if (!Number.isNaN(parsed)) {
16
+ return parsed;
17
+ }
18
+ }
19
+ return 8100;
20
+ }
12
21
  async function setProxyMode(mode, sessionId, timeout) {
22
+ const proxyPort = getProxyPort();
13
23
  try {
14
24
  const body = {
15
25
  mode,
16
26
  id: sessionId,
17
27
  ...timeout && { timeout }
18
28
  };
19
- const response = await fetch(`${INTERNAL_API_URL}/__control`, {
29
+ const response = await fetch(`http://127.0.0.1:${proxyPort}/__control`, {
20
30
  method: "POST",
21
31
  headers: { "Content-Type": "application/json" },
22
32
  body: JSON.stringify(body)
@@ -33,8 +43,34 @@ async function setProxyMode(mode, sessionId, timeout) {
33
43
  throw error;
34
44
  }
35
45
  }
46
+ function parseSpecFilePath(specPath) {
47
+ const folderMatch = specPath.match(/^(.+?)\/([^/]+)\.(spec|test)\.ts$/);
48
+ if (folderMatch) {
49
+ return { folder: folderMatch[1], fileName: folderMatch[2] };
50
+ }
51
+ const fileMatch = specPath.match(/^([^/]+)\.(spec|test)\.ts$/);
52
+ if (fileMatch) {
53
+ return { folder: null, fileName: fileMatch[1] };
54
+ }
55
+ return { folder: null, fileName: null };
56
+ }
57
+ function buildSessionPath(folder, fileName, testName) {
58
+ if (folder && fileName) {
59
+ return `${folder}/${fileName}__${testName}`;
60
+ }
61
+ if (fileName) {
62
+ return `${fileName}__${testName}`;
63
+ }
64
+ return testName;
65
+ }
36
66
  function generateSessionId(testInfo) {
37
- return testInfo.title.toLowerCase().replaceAll(/\s+/g, "-");
67
+ const { titlePath } = testInfo;
68
+ if (!titlePath || titlePath.length === 0) {
69
+ return testInfo.title.toLowerCase().replaceAll(/\s+/g, "-");
70
+ }
71
+ const { folder, fileName } = parseSpecFilePath(titlePath[0]);
72
+ const testName = titlePath.at(-1).toLowerCase().replaceAll(/\s+/g, "-");
73
+ return buildSessionPath(folder, fileName, testName);
38
74
  }
39
75
  async function startRecording(testInfo) {
40
76
  const sessionId = generateSessionId(testInfo);
@@ -1,3 +1,3 @@
1
1
  import '@playwright/test';
2
- export { P as PlaywrightTestInfo, g as generateSessionId, p as playwrightProxy, s as setProxyMode, b as startRecording, c as startReplay, d as stopProxy } from '../index-De4mgziH.cjs';
2
+ export { P as PlaywrightTestInfo, g as generateSessionId, p as playwrightProxy, s as setProxyMode, b as startRecording, c as startReplay, d as stopProxy } from '../index-CBjvm5rb.cjs';
3
3
  import 'node:http';
@@ -1,3 +1,3 @@
1
1
  import '@playwright/test';
2
- export { P as PlaywrightTestInfo, g as generateSessionId, p as playwrightProxy, s as setProxyMode, b as startRecording, c as startReplay, d as stopProxy } from '../index-De4mgziH.js';
2
+ export { P as PlaywrightTestInfo, g as generateSessionId, p as playwrightProxy, s as setProxyMode, b as startRecording, c as startReplay, d as stopProxy } from '../index-CBjvm5rb.js';
3
3
  import 'node:http';
@@ -6,15 +6,25 @@ var Modes = {
6
6
  };
7
7
 
8
8
  // src/playwright/index.ts
9
- var INTERNAL_API_URL = process.env.INTERNAL_API_URL || "http://localhost:8100";
9
+ function getProxyPort() {
10
+ const envPort = process.env.TEST_PROXY_RECORDER_PORT;
11
+ if (envPort) {
12
+ const parsed = Number.parseInt(envPort, 10);
13
+ if (!Number.isNaN(parsed)) {
14
+ return parsed;
15
+ }
16
+ }
17
+ return 8100;
18
+ }
10
19
  async function setProxyMode(mode, sessionId, timeout) {
20
+ const proxyPort = getProxyPort();
11
21
  try {
12
22
  const body = {
13
23
  mode,
14
24
  id: sessionId,
15
25
  ...timeout && { timeout }
16
26
  };
17
- const response = await fetch(`${INTERNAL_API_URL}/__control`, {
27
+ const response = await fetch(`http://127.0.0.1:${proxyPort}/__control`, {
18
28
  method: "POST",
19
29
  headers: { "Content-Type": "application/json" },
20
30
  body: JSON.stringify(body)
@@ -31,8 +41,34 @@ async function setProxyMode(mode, sessionId, timeout) {
31
41
  throw error;
32
42
  }
33
43
  }
44
+ function parseSpecFilePath(specPath) {
45
+ const folderMatch = specPath.match(/^(.+?)\/([^/]+)\.(spec|test)\.ts$/);
46
+ if (folderMatch) {
47
+ return { folder: folderMatch[1], fileName: folderMatch[2] };
48
+ }
49
+ const fileMatch = specPath.match(/^([^/]+)\.(spec|test)\.ts$/);
50
+ if (fileMatch) {
51
+ return { folder: null, fileName: fileMatch[1] };
52
+ }
53
+ return { folder: null, fileName: null };
54
+ }
55
+ function buildSessionPath(folder, fileName, testName) {
56
+ if (folder && fileName) {
57
+ return `${folder}/${fileName}__${testName}`;
58
+ }
59
+ if (fileName) {
60
+ return `${fileName}__${testName}`;
61
+ }
62
+ return testName;
63
+ }
34
64
  function generateSessionId(testInfo) {
35
- return testInfo.title.toLowerCase().replaceAll(/\s+/g, "-");
65
+ const { titlePath } = testInfo;
66
+ if (!titlePath || titlePath.length === 0) {
67
+ return testInfo.title.toLowerCase().replaceAll(/\s+/g, "-");
68
+ }
69
+ const { folder, fileName } = parseSpecFilePath(titlePath[0]);
70
+ const testName = titlePath.at(-1).toLowerCase().replaceAll(/\s+/g, "-");
71
+ return buildSessionPath(folder, fileName, testName);
36
72
  }
37
73
  async function startRecording(testInfo) {
38
74
  const sessionId = generateSessionId(testInfo);
package/dist/proxy.js CHANGED
@@ -1,4 +1,4 @@
1
- import path from 'path';
1
+ import path2 from 'path';
2
2
  import { Command } from 'commander';
3
3
  import fs from 'fs/promises';
4
4
  import http from 'http';
@@ -38,7 +38,7 @@ function parseCliArgs() {
38
38
  if (targets2.length === 0) {
39
39
  program.help();
40
40
  }
41
- const recordingsDir2 = path.resolve(process.cwd(), options.recordingsDir);
41
+ const recordingsDir2 = path2.resolve(process.cwd(), options.recordingsDir);
42
42
  return { targets: targets2, port: port2, recordingsDir: recordingsDir2 };
43
43
  }
44
44
 
@@ -58,7 +58,7 @@ var Modes = {
58
58
  };
59
59
  var JSON_INDENT_SPACES = 2;
60
60
  function getRecordingPath(recordingsDir2, id) {
61
- return path.join(recordingsDir2, `${id}.json`);
61
+ return path2.join(recordingsDir2, `${id}.mock.json`);
62
62
  }
63
63
  async function loadRecordingSession(filePath) {
64
64
  const fileContent = await fs.readFile(filePath, "utf8");
@@ -66,6 +66,8 @@ async function loadRecordingSession(filePath) {
66
66
  }
67
67
  async function saveRecordingSession(recordingsDir2, session) {
68
68
  const filePath = getRecordingPath(recordingsDir2, session.id);
69
+ const dirPath = path2.dirname(filePath);
70
+ await fs.mkdir(dirPath, { recursive: true });
69
71
  await fs.writeFile(
70
72
  filePath,
71
73
  JSON.stringify(session, null, JSON_INDENT_SPACES)
@@ -150,6 +152,7 @@ var ProxyServer = class {
150
152
  this.handleUpgrade(req, socket, head);
151
153
  });
152
154
  server.listen(port2, () => {
155
+ process.env.TEST_PROXY_RECORDER_PORT = String(port2);
153
156
  this.logServerStartup(port2);
154
157
  });
155
158
  return server;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "test-proxy-recorder",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "HTTP proxy server for recording and replaying network requests in testing. Works seamlessly with Playwright testing framework.",
5
5
  "type": "module",
6
6
  "main": "dist/index.mjs",