test-proxy-recorder 0.2.0 → 0.3.1

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.
@@ -0,0 +1,43 @@
1
+ 'use strict';
2
+
3
+ // src/constants.ts
4
+ var RECORDING_ID_HEADER = "x-test-rcrd-id";
5
+
6
+ // src/nextjs/middleware.ts
7
+ function isRecorderEnabled() {
8
+ const isProduction = process.env.NODE_ENV === "production";
9
+ const isExplicitlyEnabled = process.env.TEST_PROXY_RECORDER_ENABLED === "true" || Number.parseInt(process.env.TEST_PROXY_RECORDER_ENABLED || "") === 1;
10
+ return !isProduction || isExplicitlyEnabled;
11
+ }
12
+ function setNextProxyHeaders(request, response) {
13
+ if (!isRecorderEnabled()) {
14
+ return;
15
+ }
16
+ const recordingId = request.headers.get(RECORDING_ID_HEADER);
17
+ if (recordingId) {
18
+ response.headers.set(RECORDING_ID_HEADER, recordingId);
19
+ }
20
+ }
21
+ function getRecordingId(requestHeaders) {
22
+ if (requestHeaders instanceof Headers) {
23
+ return requestHeaders.get(RECORDING_ID_HEADER);
24
+ }
25
+ return requestHeaders.headers.get(RECORDING_ID_HEADER);
26
+ }
27
+ function createHeadersWithRecordingId(requestHeaders, additionalHeaders = {}) {
28
+ if (!isRecorderEnabled()) {
29
+ return additionalHeaders;
30
+ }
31
+ const recordingId = getRecordingId(requestHeaders);
32
+ return {
33
+ ...additionalHeaders,
34
+ ...recordingId && { [RECORDING_ID_HEADER]: recordingId }
35
+ };
36
+ }
37
+
38
+ exports.RECORDING_ID_HEADER = RECORDING_ID_HEADER;
39
+ exports.createHeadersWithRecordingId = createHeadersWithRecordingId;
40
+ exports.getRecordingId = getRecordingId;
41
+ exports.setNextProxyHeaders = setNextProxyHeaders;
42
+ //# sourceMappingURL=index.cjs.map
43
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1,89 @@
1
+ declare const RECORDING_ID_HEADER = "x-test-rcrd-id";
2
+
3
+ /**
4
+ * Minimal type for Next.js Request - compatible with next/server's NextRequest
5
+ * We define this locally to avoid requiring Next.js as a dependency
6
+ */
7
+ interface NextJSRequest {
8
+ headers: Headers;
9
+ }
10
+ /**
11
+ * Minimal type for Next.js Response - compatible with next/server's NextResponse
12
+ * We define this locally to avoid requiring Next.js as a dependency
13
+ */
14
+ interface NextJSResponse {
15
+ headers: Headers;
16
+ }
17
+ /**
18
+ * Next.js middleware helper for forwarding test proxy recording headers
19
+ * Automatically forwards the recording ID header from incoming requests to the proxy
20
+ * Only runs in non-production environments or when TEST_PROXY_RECORDER_ENABLED is set
21
+ *
22
+ * @example
23
+ * // middleware.ts
24
+ * import { NextResponse } from 'next/server';
25
+ * import type { NextRequest } from 'next/server';
26
+ * import { setNextProxyHeaders } from 'test-proxy-recorder/nextjs';
27
+ *
28
+ * export function middleware(request: NextRequest) {
29
+ * const response = NextResponse.next();
30
+ * // Only forwards headers in test/dev environments
31
+ * setNextProxyHeaders(request, response);
32
+ * return response;
33
+ * }
34
+ *
35
+ * @param request - Next.js request object (NextRequest from next/server)
36
+ * @param response - Next.js response object (NextResponse from next/server)
37
+ */
38
+ declare function setNextProxyHeaders(request: NextJSRequest, response: NextJSResponse): void;
39
+ /**
40
+ * Get the recording ID from the request if present
41
+ * Useful for manually adding the header to fetch requests in Next.js
42
+ *
43
+ * @example
44
+ * // In your API route or server component
45
+ * import { getRecordingId } from 'test-proxy-recorder/nextjs';
46
+ * import { headers } from 'next/headers';
47
+ *
48
+ * export async function GET() {
49
+ * const recordingId = getRecordingId(headers());
50
+ *
51
+ * const response = await fetch('http://localhost:8100/api/data', {
52
+ * headers: {
53
+ * ...(recordingId && { 'x-test-rcrd-id': recordingId })
54
+ * }
55
+ * });
56
+ *
57
+ * return Response.json(await response.json());
58
+ * }
59
+ *
60
+ * @param requestHeaders - Next.js headers object or NextRequest from next/server
61
+ * @returns The recording ID if present, null otherwise
62
+ */
63
+ declare function getRecordingId(requestHeaders: NextJSRequest | Headers): string | null;
64
+ /**
65
+ * Create headers object with recording ID for fetch requests
66
+ * Use this helper when making fetch requests in Next.js to forward the recording ID
67
+ *
68
+ * @example
69
+ * // In your API route or server component
70
+ * import { createHeadersWithRecordingId } from 'test-proxy-recorder/nextjs';
71
+ * import { headers } from 'next/headers';
72
+ *
73
+ * export async function GET() {
74
+ * const response = await fetch('http://localhost:8100/api/data', {
75
+ * headers: createHeadersWithRecordingId(headers(), {
76
+ * 'Content-Type': 'application/json',
77
+ * })
78
+ * });
79
+ *
80
+ * return Response.json(await response.json());
81
+ * }
82
+ *
83
+ * @param requestHeaders - Next.js headers object or NextRequest from next/server
84
+ * @param additionalHeaders - Optional additional headers to include
85
+ * @returns Headers object with recording ID if present
86
+ */
87
+ declare function createHeadersWithRecordingId(requestHeaders: NextJSRequest | Headers, additionalHeaders?: Record<string, string>): Record<string, string>;
88
+
89
+ export { type NextJSRequest, type NextJSResponse, RECORDING_ID_HEADER, createHeadersWithRecordingId, getRecordingId, setNextProxyHeaders };
@@ -0,0 +1,89 @@
1
+ declare const RECORDING_ID_HEADER = "x-test-rcrd-id";
2
+
3
+ /**
4
+ * Minimal type for Next.js Request - compatible with next/server's NextRequest
5
+ * We define this locally to avoid requiring Next.js as a dependency
6
+ */
7
+ interface NextJSRequest {
8
+ headers: Headers;
9
+ }
10
+ /**
11
+ * Minimal type for Next.js Response - compatible with next/server's NextResponse
12
+ * We define this locally to avoid requiring Next.js as a dependency
13
+ */
14
+ interface NextJSResponse {
15
+ headers: Headers;
16
+ }
17
+ /**
18
+ * Next.js middleware helper for forwarding test proxy recording headers
19
+ * Automatically forwards the recording ID header from incoming requests to the proxy
20
+ * Only runs in non-production environments or when TEST_PROXY_RECORDER_ENABLED is set
21
+ *
22
+ * @example
23
+ * // middleware.ts
24
+ * import { NextResponse } from 'next/server';
25
+ * import type { NextRequest } from 'next/server';
26
+ * import { setNextProxyHeaders } from 'test-proxy-recorder/nextjs';
27
+ *
28
+ * export function middleware(request: NextRequest) {
29
+ * const response = NextResponse.next();
30
+ * // Only forwards headers in test/dev environments
31
+ * setNextProxyHeaders(request, response);
32
+ * return response;
33
+ * }
34
+ *
35
+ * @param request - Next.js request object (NextRequest from next/server)
36
+ * @param response - Next.js response object (NextResponse from next/server)
37
+ */
38
+ declare function setNextProxyHeaders(request: NextJSRequest, response: NextJSResponse): void;
39
+ /**
40
+ * Get the recording ID from the request if present
41
+ * Useful for manually adding the header to fetch requests in Next.js
42
+ *
43
+ * @example
44
+ * // In your API route or server component
45
+ * import { getRecordingId } from 'test-proxy-recorder/nextjs';
46
+ * import { headers } from 'next/headers';
47
+ *
48
+ * export async function GET() {
49
+ * const recordingId = getRecordingId(headers());
50
+ *
51
+ * const response = await fetch('http://localhost:8100/api/data', {
52
+ * headers: {
53
+ * ...(recordingId && { 'x-test-rcrd-id': recordingId })
54
+ * }
55
+ * });
56
+ *
57
+ * return Response.json(await response.json());
58
+ * }
59
+ *
60
+ * @param requestHeaders - Next.js headers object or NextRequest from next/server
61
+ * @returns The recording ID if present, null otherwise
62
+ */
63
+ declare function getRecordingId(requestHeaders: NextJSRequest | Headers): string | null;
64
+ /**
65
+ * Create headers object with recording ID for fetch requests
66
+ * Use this helper when making fetch requests in Next.js to forward the recording ID
67
+ *
68
+ * @example
69
+ * // In your API route or server component
70
+ * import { createHeadersWithRecordingId } from 'test-proxy-recorder/nextjs';
71
+ * import { headers } from 'next/headers';
72
+ *
73
+ * export async function GET() {
74
+ * const response = await fetch('http://localhost:8100/api/data', {
75
+ * headers: createHeadersWithRecordingId(headers(), {
76
+ * 'Content-Type': 'application/json',
77
+ * })
78
+ * });
79
+ *
80
+ * return Response.json(await response.json());
81
+ * }
82
+ *
83
+ * @param requestHeaders - Next.js headers object or NextRequest from next/server
84
+ * @param additionalHeaders - Optional additional headers to include
85
+ * @returns Headers object with recording ID if present
86
+ */
87
+ declare function createHeadersWithRecordingId(requestHeaders: NextJSRequest | Headers, additionalHeaders?: Record<string, string>): Record<string, string>;
88
+
89
+ export { type NextJSRequest, type NextJSResponse, RECORDING_ID_HEADER, createHeadersWithRecordingId, getRecordingId, setNextProxyHeaders };
@@ -0,0 +1,38 @@
1
+ // src/constants.ts
2
+ var RECORDING_ID_HEADER = "x-test-rcrd-id";
3
+
4
+ // src/nextjs/middleware.ts
5
+ function isRecorderEnabled() {
6
+ const isProduction = process.env.NODE_ENV === "production";
7
+ const isExplicitlyEnabled = process.env.TEST_PROXY_RECORDER_ENABLED === "true" || Number.parseInt(process.env.TEST_PROXY_RECORDER_ENABLED || "") === 1;
8
+ return !isProduction || isExplicitlyEnabled;
9
+ }
10
+ function setNextProxyHeaders(request, response) {
11
+ if (!isRecorderEnabled()) {
12
+ return;
13
+ }
14
+ const recordingId = request.headers.get(RECORDING_ID_HEADER);
15
+ if (recordingId) {
16
+ response.headers.set(RECORDING_ID_HEADER, recordingId);
17
+ }
18
+ }
19
+ function getRecordingId(requestHeaders) {
20
+ if (requestHeaders instanceof Headers) {
21
+ return requestHeaders.get(RECORDING_ID_HEADER);
22
+ }
23
+ return requestHeaders.headers.get(RECORDING_ID_HEADER);
24
+ }
25
+ function createHeadersWithRecordingId(requestHeaders, additionalHeaders = {}) {
26
+ if (!isRecorderEnabled()) {
27
+ return additionalHeaders;
28
+ }
29
+ const recordingId = getRecordingId(requestHeaders);
30
+ return {
31
+ ...additionalHeaders,
32
+ ...recordingId && { [RECORDING_ID_HEADER]: recordingId }
33
+ };
34
+ }
35
+
36
+ export { RECORDING_ID_HEADER, createHeadersWithRecordingId, getRecordingId, setNextProxyHeaders };
37
+ //# sourceMappingURL=index.mjs.map
38
+ //# sourceMappingURL=index.mjs.map
@@ -1,5 +1,8 @@
1
1
  'use strict';
2
2
 
3
+ // src/constants.ts
4
+ var RECORDING_ID_HEADER = "x-test-rcrd-id";
5
+
3
6
  // src/types.ts
4
7
  var Modes = {
5
8
  transparent: "transparent",
@@ -86,23 +89,29 @@ async function stopProxy(testInfo) {
86
89
  }
87
90
  var playwrightProxy = {
88
91
  /**
89
- * Setup before test - sets the proxy mode
92
+ * Setup before test - sets the proxy mode and configures page with custom header
93
+ * Automatically sets up page.on('close') handler for cleanup
94
+ * @param page - Playwright page object
90
95
  * @param testInfo - Playwright test info object
91
96
  * @param mode - The proxy mode to use for this test
92
97
  * @param timeout - Optional timeout in milliseconds
93
98
  */
94
- async before(testInfo, mode, timeout) {
99
+ async before(page, testInfo, mode, timeout) {
95
100
  const sessionId = generateSessionId(testInfo);
101
+ await page.setExtraHTTPHeaders({
102
+ [RECORDING_ID_HEADER]: sessionId
103
+ });
96
104
  await setProxyMode(mode, sessionId, timeout);
97
- },
98
- /**
99
- * Cleanup after test - resets replay session by re-entering replay mode
100
- * switchToReplayMode automatically clears sequence counters
101
- * @param testInfo - Playwright test info object
102
- */
103
- async after(testInfo) {
104
- const sessionId = generateSessionId(testInfo);
105
- await setProxyMode(Modes.replay, sessionId);
105
+ page.on("close", async () => {
106
+ try {
107
+ await setProxyMode(Modes.replay, sessionId);
108
+ console.log(
109
+ `[Cleanup] Switched to replay mode for session: ${sessionId}`
110
+ );
111
+ } catch (error) {
112
+ console.error("[Cleanup] Error during page close cleanup:", error);
113
+ }
114
+ });
106
115
  },
107
116
  /**
108
117
  * Global teardown - switches proxy to transparent mode
@@ -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-nmNRt1WE.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-CVuiglPk.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-nmNRt1WE.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-CVuiglPk.js';
3
3
  import 'node:http';
@@ -1,3 +1,6 @@
1
+ // src/constants.ts
2
+ var RECORDING_ID_HEADER = "x-test-rcrd-id";
3
+
1
4
  // src/types.ts
2
5
  var Modes = {
3
6
  transparent: "transparent",
@@ -84,23 +87,29 @@ async function stopProxy(testInfo) {
84
87
  }
85
88
  var playwrightProxy = {
86
89
  /**
87
- * Setup before test - sets the proxy mode
90
+ * Setup before test - sets the proxy mode and configures page with custom header
91
+ * Automatically sets up page.on('close') handler for cleanup
92
+ * @param page - Playwright page object
88
93
  * @param testInfo - Playwright test info object
89
94
  * @param mode - The proxy mode to use for this test
90
95
  * @param timeout - Optional timeout in milliseconds
91
96
  */
92
- async before(testInfo, mode, timeout) {
97
+ async before(page, testInfo, mode, timeout) {
93
98
  const sessionId = generateSessionId(testInfo);
99
+ await page.setExtraHTTPHeaders({
100
+ [RECORDING_ID_HEADER]: sessionId
101
+ });
94
102
  await setProxyMode(mode, sessionId, timeout);
95
- },
96
- /**
97
- * Cleanup after test - resets replay session by re-entering replay mode
98
- * switchToReplayMode automatically clears sequence counters
99
- * @param testInfo - Playwright test info object
100
- */
101
- async after(testInfo) {
102
- const sessionId = generateSessionId(testInfo);
103
- await setProxyMode(Modes.replay, sessionId);
103
+ page.on("close", async () => {
104
+ try {
105
+ await setProxyMode(Modes.replay, sessionId);
106
+ console.log(
107
+ `[Cleanup] Switched to replay mode for session: ${sessionId}`
108
+ );
109
+ } catch (error) {
110
+ console.error("[Cleanup] Error during page close cleanup:", error);
111
+ }
112
+ });
104
113
  },
105
114
  /**
106
115
  * Global teardown - switches proxy to transparent mode