test-proxy-recorder 0.1.11 → 0.2.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/README.md CHANGED
@@ -99,10 +99,10 @@ This marks recording files as binary, which causes long mock files to be collaps
99
99
  Create `e2e/global-teardown.ts`:
100
100
 
101
101
  ```typescript
102
- import { setProxyMode } from 'test-proxy-recorder';
102
+ import { playwrightProxy } from 'test-proxy-recorder';
103
103
 
104
104
  async function globalTeardown() {
105
- await setProxyMode('transparent').catch(err => { console.error(err) });
105
+ await playwrightProxy.teardown();
106
106
  }
107
107
 
108
108
  export default globalTeardown;
@@ -128,15 +128,17 @@ Create `e2e/example.spec.ts`:
128
128
  import { test, expect } from '@playwright/test';
129
129
  import { playwrightProxy } from 'test-proxy-recorder';
130
130
 
131
+ // Setup afterEach hook to reset proxy after each test
132
+ test.afterEach(async ({ page: _page }, testInfo) => {
133
+ await playwrightProxy.after(testInfo);
134
+ });
135
+
131
136
  test('example test with proxy', async ({ page }, testInfo) => {
132
137
  // Set proxy mode: 'record' to capture, 'replay' to use recordings
133
138
  await playwrightProxy.before(testInfo, 'replay');
134
139
 
135
140
  await page.goto('/');
136
141
  await expect(page.getByText('Welcome')).toBeVisible();
137
-
138
- // Always cleanup after test
139
- await playwrightProxy.after(testInfo);
140
142
  });
141
143
  ```
142
144
 
@@ -186,27 +188,38 @@ test-proxy-recorder http://localhost:8000 http://localhost:9000 --port 8100
186
188
 
187
189
  ### Basic Test Structure
188
190
 
189
- Every test using the proxy should follow this pattern:
191
+ Every test file using the proxy should follow this pattern:
190
192
 
191
193
  ```typescript
192
194
  import { test } from '@playwright/test';
193
195
  import { playwrightProxy } from 'test-proxy-recorder';
194
196
 
197
+ // Setup afterEach hook once per test file
198
+ test.afterEach(async ({ page: _page }, testInfo) => {
199
+ await playwrightProxy.after(testInfo);
200
+ });
201
+
195
202
  test('test name', async ({ page }, testInfo) => {
196
203
  // 1. Set mode BEFORE test actions
197
204
  await playwrightProxy.before(testInfo, 'replay');
198
205
 
199
206
  // 2. Test code
200
207
  await page.goto('/page');
201
-
202
- // 3. Reset mode AFTER test completes
203
- await playwrightProxy.after(testInfo);
208
+ // Test assertions...
204
209
  });
205
210
  ```
206
211
 
207
212
  ### Recording vs Replay
208
213
 
209
214
  ```typescript
215
+ import { test } from '@playwright/test';
216
+ import { playwrightProxy } from 'test-proxy-recorder';
217
+
218
+ // Setup afterEach hook to automatically cleanup after each test
219
+ test.afterEach(async ({ page: _page }, testInfo) => {
220
+ await playwrightProxy.after(testInfo);
221
+ });
222
+
210
223
  // Recording mode - captures API responses
211
224
  test('create user', async ({ page }, testInfo) => {
212
225
  await playwrightProxy.before(testInfo, 'record');
@@ -214,8 +227,6 @@ test('create user', async ({ page }, testInfo) => {
214
227
  await page.goto('/users/new');
215
228
  await page.fill('[name="username"]', 'testuser');
216
229
  await page.click('button[type="submit"]');
217
-
218
- await playwrightProxy.after(testInfo);
219
230
  });
220
231
 
221
232
  // Replay mode - uses recorded responses
@@ -225,8 +236,6 @@ test('create user', async ({ page }, testInfo) => {
225
236
  await page.goto('/users/new');
226
237
  await page.fill('[name="username"]', 'testuser');
227
238
  await page.click('button[type="submit"]');
228
-
229
- await playwrightProxy.after(testInfo);
230
239
  });
231
240
  ```
232
241
 
@@ -244,10 +253,10 @@ Recording files are auto-generated from test names:
244
253
  Create `e2e/global-teardown.ts`:
245
254
 
246
255
  ```typescript
247
- import { setProxyMode } from 'test-proxy-recorder';
256
+ import { playwrightProxy } from 'test-proxy-recorder';
248
257
 
249
258
  async function globalTeardown() {
250
- await setProxyMode('transparent').catch(err => { console.error(err) });
259
+ await playwrightProxy.teardown();
251
260
  }
252
261
 
253
262
  export default globalTeardown;
@@ -412,8 +421,13 @@ const playwrightProxy = {
412
421
  timeout?: number
413
422
  ): Promise<void>;
414
423
 
415
- // Reset to transparent mode after test
424
+ // Reset replay session and return to transparent mode after test
425
+ // Resets sequence counters to ensure next replay starts fresh
416
426
  async after(testInfo: TestInfo): Promise<void>;
427
+
428
+ // Global teardown - switches proxy to transparent mode
429
+ // Use in Playwright's globalTeardown configuration
430
+ async teardown(): Promise<void>;
417
431
  };
418
432
 
419
433
  // Direct mode control
@@ -438,6 +452,8 @@ async function setProxyMode(
438
452
  }
439
453
  ```
440
454
 
455
+ **Note**: Switching to replay mode automatically resets session counters (clears served recordings tracker), allowing replay from the beginning.
456
+
441
457
  **Response**:
442
458
 
443
459
  ```typescript
@@ -89,13 +89,20 @@ declare const playwrightProxy: {
89
89
  * Setup before test - sets the proxy mode
90
90
  * @param testInfo - Playwright test info object
91
91
  * @param mode - The proxy mode to use for this test
92
+ * @param timeout - Optional timeout in milliseconds
92
93
  */
93
- before(testInfo: PlaywrightTestInfo, mode: Mode): Promise<void>;
94
+ before(testInfo: PlaywrightTestInfo, mode: Mode, timeout?: number): Promise<void>;
94
95
  /**
95
- * Cleanup after test - returns to transparent mode
96
+ * Cleanup after test - resets replay session by re-entering replay mode
97
+ * switchToReplayMode automatically clears sequence counters
96
98
  * @param testInfo - Playwright test info object
97
99
  */
98
100
  after(testInfo: PlaywrightTestInfo): Promise<void>;
101
+ /**
102
+ * Global teardown - switches proxy to transparent mode
103
+ * Use this in Playwright's globalTeardown to ensure clean state
104
+ */
105
+ teardown(): Promise<void>;
99
106
  };
100
107
 
101
108
  export { type ControlRequest as C, type Mode as M, type PlaywrightTestInfo as P, type Recording as R, type WebSocketRecording as W, type RecordingSession as a, startRecording as b, startReplay as c, stopProxy as d, generateSessionId as g, playwrightProxy as p, setProxyMode as s };
@@ -89,13 +89,20 @@ declare const playwrightProxy: {
89
89
  * Setup before test - sets the proxy mode
90
90
  * @param testInfo - Playwright test info object
91
91
  * @param mode - The proxy mode to use for this test
92
+ * @param timeout - Optional timeout in milliseconds
92
93
  */
93
- before(testInfo: PlaywrightTestInfo, mode: Mode): Promise<void>;
94
+ before(testInfo: PlaywrightTestInfo, mode: Mode, timeout?: number): Promise<void>;
94
95
  /**
95
- * Cleanup after test - returns to transparent mode
96
+ * Cleanup after test - resets replay session by re-entering replay mode
97
+ * switchToReplayMode automatically clears sequence counters
96
98
  * @param testInfo - Playwright test info object
97
99
  */
98
100
  after(testInfo: PlaywrightTestInfo): Promise<void>;
101
+ /**
102
+ * Global teardown - switches proxy to transparent mode
103
+ * Use this in Playwright's globalTeardown to ensure clean state
104
+ */
105
+ teardown(): Promise<void>;
99
106
  };
100
107
 
101
108
  export { type ControlRequest as C, type Mode as M, type PlaywrightTestInfo as P, type Recording as R, type WebSocketRecording as W, type RecordingSession as a, startRecording as b, startReplay as c, stopProxy as d, generateSessionId as g, playwrightProxy as p, setProxyMode as s };
package/dist/index.cjs CHANGED
@@ -529,7 +529,11 @@ var ProxyServer = class {
529
529
  }
530
530
  const servedForThisKey = sessionState.servedRecordingIdsByKey.get(key);
531
531
  const host = req.headers.host || "unknown";
532
- const recordsWithKey = session.recordings.filter((r) => r.key === key && r.response).toSorted((a, b) => a.recordingId - b.recordingId);
532
+ const recordsWithKey = session.recordings.filter((r) => r.key === key && r.response).toSorted((a, b) => {
533
+ const aSeq = a.sequence !== void 0 ? a.sequence : a.recordingId;
534
+ const bSeq = b.sequence !== void 0 ? b.sequence : b.recordingId;
535
+ return aSeq - bSeq;
536
+ });
533
537
  if (recordsWithKey.length === 0) {
534
538
  const errorMsg = `No recording found for ${key} at ${req.method} ${host}${req.url}`;
535
539
  console.error(`[REPLAY ERROR] ${errorMsg} (session: ${recordingId})`);
@@ -552,7 +556,7 @@ var ProxyServer = class {
552
556
  }
553
557
  const requestCount = servedForThisKey.size + 1;
554
558
  console.log(
555
- `[REPLAY REQUEST #${requestCount}] ${req.method} ${req.url} (session: ${recordingId}, total: ${recordsWithKey.length}, served: ${servedForThisKey.size})`
559
+ `[replay request #${requestCount}] ${req.method} ${req.url} (session: ${recordingId}, total: ${recordsWithKey.length}, served: ${servedForThisKey.size})`
556
560
  );
557
561
  let record;
558
562
  for (const rec of recordsWithKey) {
@@ -569,7 +573,7 @@ var ProxyServer = class {
569
573
  }
570
574
  servedForThisKey.add(record.recordingId);
571
575
  console.log(
572
- `[REPLAY SERVING] recordingId: ${record.recordingId}, session: ${recordingId}, body_len: ${record.response?.body?.length || 0}`
576
+ `[replay serving] recordingId: ${record.recordingId}, session: ${recordingId}, body_len: ${record.response?.body?.length || 0}`
573
577
  );
574
578
  if (!record.response) {
575
579
  throw new Error(
@@ -953,19 +957,27 @@ var playwrightProxy = {
953
957
  * Setup before test - sets the proxy mode
954
958
  * @param testInfo - Playwright test info object
955
959
  * @param mode - The proxy mode to use for this test
960
+ * @param timeout - Optional timeout in milliseconds
956
961
  */
957
- async before(testInfo, mode) {
962
+ async before(testInfo, mode, timeout) {
958
963
  const sessionId = generateSessionId(testInfo);
959
- console.log("Proxy setup:", { mode, sessionId });
960
- await setProxyMode(mode, sessionId);
964
+ await setProxyMode(mode, sessionId, timeout);
961
965
  },
962
966
  /**
963
- * Cleanup after test - returns to transparent mode
967
+ * Cleanup after test - resets replay session by re-entering replay mode
968
+ * switchToReplayMode automatically clears sequence counters
964
969
  * @param testInfo - Playwright test info object
965
970
  */
966
971
  async after(testInfo) {
967
972
  const sessionId = generateSessionId(testInfo);
968
- await setProxyMode(Modes.transparent, sessionId);
973
+ await setProxyMode(Modes.replay, sessionId);
974
+ },
975
+ /**
976
+ * Global teardown - switches proxy to transparent mode
977
+ * Use this in Playwright's globalTeardown to ensure clean state
978
+ */
979
+ async teardown() {
980
+ await setProxyMode(Modes.transparent);
969
981
  }
970
982
  };
971
983
 
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-Cx_Kflfl.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-nmNRt1WE.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-Cx_Kflfl.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-nmNRt1WE.js';
3
3
  import '@playwright/test';
4
4
 
5
5
  declare class ProxyServer {
package/dist/index.mjs CHANGED
@@ -517,7 +517,11 @@ var ProxyServer = class {
517
517
  }
518
518
  const servedForThisKey = sessionState.servedRecordingIdsByKey.get(key);
519
519
  const host = req.headers.host || "unknown";
520
- const recordsWithKey = session.recordings.filter((r) => r.key === key && r.response).toSorted((a, b) => a.recordingId - b.recordingId);
520
+ const recordsWithKey = session.recordings.filter((r) => r.key === key && r.response).toSorted((a, b) => {
521
+ const aSeq = a.sequence !== void 0 ? a.sequence : a.recordingId;
522
+ const bSeq = b.sequence !== void 0 ? b.sequence : b.recordingId;
523
+ return aSeq - bSeq;
524
+ });
521
525
  if (recordsWithKey.length === 0) {
522
526
  const errorMsg = `No recording found for ${key} at ${req.method} ${host}${req.url}`;
523
527
  console.error(`[REPLAY ERROR] ${errorMsg} (session: ${recordingId})`);
@@ -540,7 +544,7 @@ var ProxyServer = class {
540
544
  }
541
545
  const requestCount = servedForThisKey.size + 1;
542
546
  console.log(
543
- `[REPLAY REQUEST #${requestCount}] ${req.method} ${req.url} (session: ${recordingId}, total: ${recordsWithKey.length}, served: ${servedForThisKey.size})`
547
+ `[replay request #${requestCount}] ${req.method} ${req.url} (session: ${recordingId}, total: ${recordsWithKey.length}, served: ${servedForThisKey.size})`
544
548
  );
545
549
  let record;
546
550
  for (const rec of recordsWithKey) {
@@ -557,7 +561,7 @@ var ProxyServer = class {
557
561
  }
558
562
  servedForThisKey.add(record.recordingId);
559
563
  console.log(
560
- `[REPLAY SERVING] recordingId: ${record.recordingId}, session: ${recordingId}, body_len: ${record.response?.body?.length || 0}`
564
+ `[replay serving] recordingId: ${record.recordingId}, session: ${recordingId}, body_len: ${record.response?.body?.length || 0}`
561
565
  );
562
566
  if (!record.response) {
563
567
  throw new Error(
@@ -941,19 +945,27 @@ var playwrightProxy = {
941
945
  * Setup before test - sets the proxy mode
942
946
  * @param testInfo - Playwright test info object
943
947
  * @param mode - The proxy mode to use for this test
948
+ * @param timeout - Optional timeout in milliseconds
944
949
  */
945
- async before(testInfo, mode) {
950
+ async before(testInfo, mode, timeout) {
946
951
  const sessionId = generateSessionId(testInfo);
947
- console.log("Proxy setup:", { mode, sessionId });
948
- await setProxyMode(mode, sessionId);
952
+ await setProxyMode(mode, sessionId, timeout);
949
953
  },
950
954
  /**
951
- * Cleanup after test - returns to transparent mode
955
+ * Cleanup after test - resets replay session by re-entering replay mode
956
+ * switchToReplayMode automatically clears sequence counters
952
957
  * @param testInfo - Playwright test info object
953
958
  */
954
959
  async after(testInfo) {
955
960
  const sessionId = generateSessionId(testInfo);
956
- await setProxyMode(Modes.transparent, sessionId);
961
+ await setProxyMode(Modes.replay, sessionId);
962
+ },
963
+ /**
964
+ * Global teardown - switches proxy to transparent mode
965
+ * Use this in Playwright's globalTeardown to ensure clean state
966
+ */
967
+ async teardown() {
968
+ await setProxyMode(Modes.transparent);
957
969
  }
958
970
  };
959
971
 
@@ -89,19 +89,27 @@ var playwrightProxy = {
89
89
  * Setup before test - sets the proxy mode
90
90
  * @param testInfo - Playwright test info object
91
91
  * @param mode - The proxy mode to use for this test
92
+ * @param timeout - Optional timeout in milliseconds
92
93
  */
93
- async before(testInfo, mode) {
94
+ async before(testInfo, mode, timeout) {
94
95
  const sessionId = generateSessionId(testInfo);
95
- console.log("Proxy setup:", { mode, sessionId });
96
- await setProxyMode(mode, sessionId);
96
+ await setProxyMode(mode, sessionId, timeout);
97
97
  },
98
98
  /**
99
- * Cleanup after test - returns to transparent mode
99
+ * Cleanup after test - resets replay session by re-entering replay mode
100
+ * switchToReplayMode automatically clears sequence counters
100
101
  * @param testInfo - Playwright test info object
101
102
  */
102
103
  async after(testInfo) {
103
104
  const sessionId = generateSessionId(testInfo);
104
- await setProxyMode(Modes.transparent, sessionId);
105
+ await setProxyMode(Modes.replay, sessionId);
106
+ },
107
+ /**
108
+ * Global teardown - switches proxy to transparent mode
109
+ * Use this in Playwright's globalTeardown to ensure clean state
110
+ */
111
+ async teardown() {
112
+ await setProxyMode(Modes.transparent);
105
113
  }
106
114
  };
107
115
 
@@ -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-Cx_Kflfl.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-nmNRt1WE.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-Cx_Kflfl.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-nmNRt1WE.js';
3
3
  import 'node:http';
@@ -87,19 +87,27 @@ var playwrightProxy = {
87
87
  * Setup before test - sets the proxy mode
88
88
  * @param testInfo - Playwright test info object
89
89
  * @param mode - The proxy mode to use for this test
90
+ * @param timeout - Optional timeout in milliseconds
90
91
  */
91
- async before(testInfo, mode) {
92
+ async before(testInfo, mode, timeout) {
92
93
  const sessionId = generateSessionId(testInfo);
93
- console.log("Proxy setup:", { mode, sessionId });
94
- await setProxyMode(mode, sessionId);
94
+ await setProxyMode(mode, sessionId, timeout);
95
95
  },
96
96
  /**
97
- * Cleanup after test - returns to transparent mode
97
+ * Cleanup after test - resets replay session by re-entering replay mode
98
+ * switchToReplayMode automatically clears sequence counters
98
99
  * @param testInfo - Playwright test info object
99
100
  */
100
101
  async after(testInfo) {
101
102
  const sessionId = generateSessionId(testInfo);
102
- await setProxyMode(Modes.transparent, sessionId);
103
+ await setProxyMode(Modes.replay, sessionId);
104
+ },
105
+ /**
106
+ * Global teardown - switches proxy to transparent mode
107
+ * Use this in Playwright's globalTeardown to ensure clean state
108
+ */
109
+ async teardown() {
110
+ await setProxyMode(Modes.transparent);
103
111
  }
104
112
  };
105
113
 
package/dist/proxy.js CHANGED
@@ -551,7 +551,11 @@ var ProxyServer = class {
551
551
  }
552
552
  const servedForThisKey = sessionState.servedRecordingIdsByKey.get(key);
553
553
  const host = req.headers.host || "unknown";
554
- const recordsWithKey = session.recordings.filter((r) => r.key === key && r.response).toSorted((a, b) => a.recordingId - b.recordingId);
554
+ const recordsWithKey = session.recordings.filter((r) => r.key === key && r.response).toSorted((a, b) => {
555
+ const aSeq = a.sequence !== void 0 ? a.sequence : a.recordingId;
556
+ const bSeq = b.sequence !== void 0 ? b.sequence : b.recordingId;
557
+ return aSeq - bSeq;
558
+ });
555
559
  if (recordsWithKey.length === 0) {
556
560
  const errorMsg = `No recording found for ${key} at ${req.method} ${host}${req.url}`;
557
561
  console.error(`[REPLAY ERROR] ${errorMsg} (session: ${recordingId})`);
@@ -574,7 +578,7 @@ var ProxyServer = class {
574
578
  }
575
579
  const requestCount = servedForThisKey.size + 1;
576
580
  console.log(
577
- `[REPLAY REQUEST #${requestCount}] ${req.method} ${req.url} (session: ${recordingId}, total: ${recordsWithKey.length}, served: ${servedForThisKey.size})`
581
+ `[replay request #${requestCount}] ${req.method} ${req.url} (session: ${recordingId}, total: ${recordsWithKey.length}, served: ${servedForThisKey.size})`
578
582
  );
579
583
  let record;
580
584
  for (const rec of recordsWithKey) {
@@ -591,7 +595,7 @@ var ProxyServer = class {
591
595
  }
592
596
  servedForThisKey.add(record.recordingId);
593
597
  console.log(
594
- `[REPLAY SERVING] recordingId: ${record.recordingId}, session: ${recordingId}, body_len: ${record.response?.body?.length || 0}`
598
+ `[replay serving] recordingId: ${record.recordingId}, session: ${recordingId}, body_len: ${record.response?.body?.length || 0}`
595
599
  );
596
600
  if (!record.response) {
597
601
  throw new Error(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "test-proxy-recorder",
3
- "version": "0.1.11",
3
+ "version": "0.2.0",
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",