playwright-api-logger 2.0.0 → 2.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
@@ -21,7 +21,7 @@
21
21
  ## How It Works
22
22
 
23
23
  ```mermaid
24
- flowchart TD
24
+ flowchart LR
25
25
  subgraph T[Playwright Test]
26
26
  F[Fixture setup]
27
27
  C[API Call GET/POST/PUT/DELETE]
@@ -56,10 +56,10 @@ API_LOGS=false → Logging OFF (zero overhead, default)
56
56
  ## Features
57
57
 
58
58
  - **One-line integration** — just wrap `request` with `withApiLogging()`, zero changes to controllers/clients
59
- - **Full Logging** — method, URL, headers, request/response body, status, timing
59
+ - **Structured logs** — one JSON document per test with `preconditions`, `steps`, and `teardown` sections
60
+ - **Step descriptions** — describe what each API call does with `.describe()`
60
61
  - **Curl Export** — copy from log, paste into terminal or import into Postman
61
62
  - **Env Control** — `API_LOGS=true/false` (default: `false`, zero overhead when off)
62
- - **Context Tracking** — setup / test / teardown phases
63
63
  - **Token Masking** — Authorization headers are automatically masked
64
64
  - **Form Data** — JSON, URL-encoded, and multipart/form-data support
65
65
  - **Error Resilient** — logging never breaks your tests
@@ -79,15 +79,38 @@ import { withApiLogging } from 'playwright-api-logger';
79
79
 
80
80
  export const test = base.extend({
81
81
  apiClient: async ({ request }, use, testInfo) => {
82
- // Just wrap request — all API calls are logged automatically
83
- const apiClient = new ApiClient(withApiLogging(request, testInfo));
82
+ const loggedRequest = withApiLogging(request, testInfo);
83
+ const apiClient = new ApiClient(loggedRequest);
84
84
  await use(apiClient);
85
+ loggedRequest.__logger.finalize(
86
+ testInfo.status === 'passed' ? 'PASSED' : 'FAILED'
87
+ );
85
88
  },
86
89
  });
87
90
  ```
88
91
 
89
92
  No changes to your controllers, clients, or test files.
90
93
 
94
+ ### With preconditions and step descriptions
95
+
96
+ ```typescript
97
+ test('GET Without token (401)', async ({ apiClient, request }) => {
98
+ const loggedRequest = (request as any).__logger as ApiLogger;
99
+
100
+ // Mark following calls as preconditions
101
+ loggedRequest.startPreconditions();
102
+ loggedRequest.describe('Get employee ID for test');
103
+ const employees = await apiClient.getEmployees({ page: 1, size: 1 });
104
+ const employeeId = employees.items[0].id;
105
+
106
+ // Switch to test steps
107
+ loggedRequest.startTest();
108
+ loggedRequest.describe('Get children without auth token');
109
+ const response = await apiClient.getChildrenWithoutAuth(employeeId);
110
+ expect(response.status).toBe(401);
111
+ });
112
+ ```
113
+
91
114
  ### Enable via environment variable
92
115
 
93
116
  ```bash
@@ -100,61 +123,70 @@ API_LOGS=false
100
123
  API_LOGS=true npx playwright test
101
124
  ```
102
125
 
103
- ### Finalize with test result (optional)
104
-
105
- ```typescript
106
- apiClient: async ({ request }, use, testInfo) => {
107
- const loggedRequest = withApiLogging(request, testInfo);
108
- const apiClient = new ApiClient(loggedRequest);
109
- await use(apiClient);
110
-
111
- // Write PASSED/FAILED to log
112
- loggedRequest.__logger.finalize(
113
- testInfo.status === 'passed' ? 'PASSED' : 'FAILED'
114
- );
115
- },
116
- ```
117
-
118
- ### Setup / Teardown logging
119
-
120
- ```typescript
121
- // In beforeAll
122
- const loggedRequest = withApiLogging(request, { testName: 'auth-setup', context: 'setup' });
123
-
124
- // In afterAll
125
- const loggedRequest = withApiLogging(request, { testName: 'cleanup', context: 'teardown' });
126
- ```
127
-
128
126
  ## Log Output
129
127
 
130
- Logs are saved to `logs/` directory:
128
+ One structured JSON document per test:
131
129
 
132
130
  ```
133
131
  logs/
134
- TEST_my-test-name_2026-03-16T12-00-00.log
135
- SETUP_auth-setup_2026-03-16T12-00-00.log
136
- TEARDOWN_cleanup_2026-03-16T12-00-00.log
132
+ get-without-token-401_2026-03-16T18-33-03.log
133
+ create-employee_2026-03-16T18-35-10.log
137
134
  ```
138
135
 
139
- Each log entry is a JSON object:
136
+ ### Example log:
140
137
 
141
138
  ```json
142
139
  {
143
- "timestamp": "2026-03-16T12:00:00.000Z",
144
- "testName": "my-test-name",
145
- "context": "test",
146
- "request": {
147
- "method": "POST",
148
- "url": "https://api.example.com/users",
149
- "headers": { "Content-Type": "application/json" },
150
- "body": { "name": "John" }
140
+ "test": {
141
+ "name": "GET Without token (401)",
142
+ "file": "tests/api/employees/children.spec.ts",
143
+ "startedAt": "2026-03-16T18:33:03.654Z",
144
+ "finishedAt": "2026-03-16T18:33:04.300Z",
145
+ "duration": 646,
146
+ "result": "PASSED"
151
147
  },
152
- "response": {
153
- "status": 201,
154
- "body": { "id": 1, "name": "John" }
155
- },
156
- "duration": 150,
157
- "curl": "curl -X POST 'https://api.example.com/users' -H 'Content-Type: application/json' --data '{\"name\":\"John\"}'"
148
+ "preconditions": [
149
+ {
150
+ "step": 1,
151
+ "description": "Get employee ID for test",
152
+ "timestamp": "2026-03-16T18:33:04.174Z",
153
+ "request": {
154
+ "method": "GET",
155
+ "url": "https://api.example.com/employees?page=1&size=1"
156
+ },
157
+ "response": {
158
+ "status": 200,
159
+ "body": { "items": [{ "id": "abc-123" }], "total": 27 }
160
+ },
161
+ "duration": 501,
162
+ "curl": "curl -X GET 'https://api.example.com/employees?page=1&size=1' -H 'Accept: application/json'"
163
+ }
164
+ ],
165
+ "steps": [
166
+ {
167
+ "step": 1,
168
+ "description": "Get children without auth token",
169
+ "timestamp": "2026-03-16T18:33:04.242Z",
170
+ "request": {
171
+ "method": "GET",
172
+ "url": "https://api.example.com/employees/abc-123/children"
173
+ },
174
+ "response": {
175
+ "status": 401,
176
+ "body": { "detail": "Not authenticated" }
177
+ },
178
+ "duration": 67,
179
+ "curl": "curl -X GET 'https://api.example.com/employees/abc-123/children'"
180
+ }
181
+ ],
182
+ "teardown": [],
183
+ "summary": {
184
+ "totalRequests": 2,
185
+ "preconditions": 1,
186
+ "testSteps": 1,
187
+ "teardown": 0,
188
+ "totalDuration": 568
189
+ }
158
190
  }
159
191
  ```
160
192
 
@@ -165,28 +197,22 @@ Each log entry is a JSON object:
165
197
  Main integration point. Wraps `APIRequestContext` with a Proxy that logs all HTTP calls.
166
198
 
167
199
  ```typescript
168
- // With TestInfo (recommended)
169
200
  const loggedRequest = withApiLogging(request, testInfo);
170
-
171
- // With options
172
- const loggedRequest = withApiLogging(request, {
173
- testName: 'my-test',
174
- context: 'setup',
175
- logDirectory: 'custom-logs/',
176
- maskAuthTokens: true,
177
- });
178
-
179
- // Access logger for finalization
180
- loggedRequest.__logger.finalize('PASSED');
201
+ loggedRequest.__logger // access the ApiLogger instance
181
202
  ```
182
203
 
183
- ### Factory Functions (advanced)
204
+ ### `ApiLogger` context & description
184
205
 
185
- | Function | Description |
186
- |----------|-------------|
187
- | `createApiLogger(testName, context?)` | Create standalone logger |
188
- | `createSetupLogger(testName)` | Logger with `'setup'` context |
189
- | `createTeardownLogger(testName)` | Logger with `'teardown'` context |
206
+ | Method | Description |
207
+ |--------|-------------|
208
+ | `describe(text)` | Set description for the **next** API call |
209
+ | `startPreconditions()` | Following calls `preconditions` section |
210
+ | `startTest()` | Following calls `steps` section |
211
+ | `startTeardown()` | Following calls → `teardown` section |
212
+ | `setContext(ctx)` | Set context directly (`'preconditions'` / `'test'` / `'teardown'`) |
213
+ | `finalize(result, info?)` | Write structured JSON document to file |
214
+ | `isEnabled()` | Check if logging is active |
215
+ | `getLogFilePath()` | Get current log file path |
190
216
 
191
217
  ### `CurlGenerator`
192
218
 
@@ -205,19 +231,24 @@ loggedRequest.__logger.finalize('PASSED');
205
231
  ```typescript
206
232
  {
207
233
  testName?: string; // Test name (default: 'unknown-test')
208
- context?: LogContext; // 'setup' | 'test' | 'teardown'
234
+ testFile?: string; // Test file path
235
+ context?: LogContext; // 'preconditions' | 'test' | 'teardown'
209
236
  logDirectory?: string; // Custom log dir (default: 'logs/')
210
237
  maskAuthTokens?: boolean; // Mask auth headers (default: true)
238
+ logger?: ApiLogger; // Share logger across phases
211
239
  }
212
240
  ```
213
241
 
214
- ## Migration from v1
215
-
216
- v1 required changes to controllers, clients, and fixtures. v2 needs only **one line**:
242
+ ## Migration from v1 → v2
217
243
 
218
244
  ```diff
219
- - const apiClient = new ApiClient(request);
220
- + const apiClient = new ApiClient(withApiLogging(request, testInfo));
245
+ - // v1: manual logger setup in controllers and clients
246
+ - const logger = createApiLogger(testInfo.title);
247
+ - apiClient.setApiLogger(logger);
248
+
249
+ + // v2: one line, structured logs with sections
250
+ + const loggedRequest = withApiLogging(request, testInfo);
251
+ + const apiClient = new ApiClient(loggedRequest);
221
252
  ```
222
253
 
223
254
  ## License
@@ -1,74 +1,83 @@
1
1
  /**
2
2
  * API Logger for capturing and logging HTTP requests/responses
3
+ * Produces a single structured test document with preconditions, steps, and teardown sections.
4
+ *
3
5
  * Features:
4
- * - Comprehensive request/response logging
6
+ * - Structured test document (one JSON per test)
7
+ * - Preconditions / Steps / Teardown sections
8
+ * - Step descriptions and numbering
5
9
  * - Curl command generation for manual testing
6
10
  * - Environment-based enable/disable via API_LOGS
7
- * - Automatic file logging with JSON format
8
- * - Test context tracking (setup/test/teardown)
11
+ * - Test context tracking and switching
9
12
  */
10
13
  import { LogContext, LoggerConfig } from './types';
11
14
  export declare class ApiLogger {
12
15
  private enabled;
13
16
  private testName;
14
- private context;
17
+ private testFile?;
18
+ private currentContext;
15
19
  private logDirectory;
16
20
  private logFilePath;
17
21
  private maskAuthTokens;
18
- private currentRequest;
19
- private requestStartTime;
22
+ private startedAt;
23
+ private preconditions;
24
+ private steps;
25
+ private teardownSteps;
26
+ private nextDescription?;
20
27
  constructor(config?: LoggerConfig);
21
- /**
22
- * Get default log directory path
23
- */
24
28
  private getDefaultLogDirectory;
25
- /**
26
- * Initialize log file and directory
27
- */
28
29
  private initializeLogFile;
29
30
  /**
30
- * Log an API call with request and response
31
+ * Set description for the next API call
32
+ * @example
33
+ * logger.describe('Get employee ID for testing');
34
+ * await apiClient.getEmployees(); // this call gets the description
31
35
  */
32
- logApiCall(method: string, url: string, requestHeaders: Record<string, string | string[]> | undefined, requestBody: any, status: number, responseHeaders: Record<string, string> | undefined, responseBody: any, duration: number): void;
36
+ describe(description: string): void;
33
37
  /**
34
- * Log just the request part (when response isn't available yet)
38
+ * Switch current context (preconditions test teardown)
39
+ * All subsequent API calls will be logged to the new context section
35
40
  */
36
- logRequest(method: string, url: string, headers?: Record<string, string | string[]>, body?: any): void;
41
+ setContext(context: LogContext): void;
37
42
  /**
38
- * Log just the response part (pairs with logRequest)
43
+ * Shortcut: switch to preconditions context
39
44
  */
40
- logResponse(status: number, headers?: Record<string, string>, body?: any): void;
45
+ startPreconditions(): void;
41
46
  /**
42
- * Write log entry to file
47
+ * Shortcut: switch to test steps context
43
48
  */
44
- private writeLogEntry;
49
+ startTest(): void;
45
50
  /**
46
- * Generate ISO timestamp for filenames
51
+ * Shortcut: switch to teardown context
47
52
  */
48
- private generateTimestamp;
53
+ startTeardown(): void;
49
54
  /**
50
- * Sanitize test name for use in filename
55
+ * Log an API call with request and response
51
56
  */
52
- private sanitizeTestName;
57
+ logApiCall(method: string, url: string, requestHeaders: Record<string, string | string[]> | undefined, requestBody: any, status: number, responseHeaders: Record<string, string> | undefined, responseBody: any, duration: number): void;
53
58
  /**
54
- * Get the current log file path
59
+ * Get the target array for current context
55
60
  */
56
- getLogFilePath(): string | null;
61
+ private getTargetArray;
57
62
  /**
58
- * Check if logger is enabled
63
+ * Finalize and write the structured test document to file
59
64
  */
60
- isEnabled(): boolean;
65
+ finalize(result: 'PASSED' | 'FAILED' | 'SKIPPED', additionalInfo?: Record<string, any>): void;
61
66
  /**
62
- * Finalize logging for test completion
67
+ * Write structured document to file
63
68
  */
64
- finalize(result: 'PASSED' | 'FAILED' | 'SKIPPED', additionalInfo?: Record<string, any>): void;
69
+ private writeDocument;
70
+ private generateTimestamp;
71
+ private sanitizeTestName;
72
+ getLogFilePath(): string | null;
73
+ isEnabled(): boolean;
65
74
  }
66
75
  /**
67
76
  * Factory function for creating test-context loggers
68
77
  */
69
78
  export declare function createApiLogger(testName: string, context?: LogContext): ApiLogger;
70
79
  /**
71
- * Factory for setup context
80
+ * Factory for setup/preconditions context
72
81
  */
73
82
  export declare function createSetupLogger(testName: string): ApiLogger;
74
83
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"ApiLogger.d.ts","sourceRoot":"","sources":["../src/ApiLogger.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,EACL,UAAU,EACV,YAAY,EAIb,MAAM,SAAS,CAAC;AAEjB,qBAAa,SAAS;IACpB,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,OAAO,CAAa;IAC5B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,cAAc,CAAU;IAChC,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,gBAAgB,CAAuB;gBAEnC,MAAM,GAAE,YAAiB;IAcrC;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAI9B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAoBzB;;OAEG;IACH,UAAU,CACR,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,GAAG,SAAS,EAC7D,WAAW,EAAE,GAAG,EAChB,MAAM,EAAE,MAAM,EACd,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,EACnD,YAAY,EAAE,GAAG,EACjB,QAAQ,EAAE,MAAM,GACf,IAAI;IAmDP;;OAEG;IACH,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,IAAI;IAStG;;OAEG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,IAAI;IAsB/E;;OAEG;IACH,OAAO,CAAC,aAAa;IAarB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IASzB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IASxB;;OAEG;IACH,cAAc,IAAI,MAAM,GAAG,IAAI;IAI/B;;OAEG;IACH,SAAS,IAAI,OAAO;IAIpB;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;CAuB9F;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,UAAmB,GAAG,SAAS,CAEzF;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAE7D;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAEhE"}
1
+ {"version":3,"file":"ApiLogger.d.ts","sourceRoot":"","sources":["../src/ApiLogger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,OAAO,EACL,UAAU,EACV,YAAY,EAKb,MAAM,SAAS,CAAC;AAEjB,qBAAa,SAAS;IACpB,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAAC,CAAS;IAC1B,OAAO,CAAC,cAAc,CAAa;IACnC,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,cAAc,CAAU;IAChC,OAAO,CAAC,SAAS,CAAS;IAG1B,OAAO,CAAC,aAAa,CAAsB;IAC3C,OAAO,CAAC,KAAK,CAAsB;IACnC,OAAO,CAAC,aAAa,CAAsB;IAG3C,OAAO,CAAC,eAAe,CAAC,CAAS;gBAErB,MAAM,GAAE,YAAiB;IAerC,OAAO,CAAC,sBAAsB;IAI9B,OAAO,CAAC,iBAAiB;IAgBzB;;;;;OAKG;IACH,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAInC;;;OAGG;IACH,UAAU,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI;IAIrC;;OAEG;IACH,kBAAkB,IAAI,IAAI;IAI1B;;OAEG;IACH,SAAS,IAAI,IAAI;IAIjB;;OAEG;IACH,aAAa,IAAI,IAAI;IAIrB;;OAEG;IACH,UAAU,CACR,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,GAAG,SAAS,EAC7D,WAAW,EAAE,GAAG,EAChB,MAAM,EAAE,MAAM,EACd,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,EACnD,YAAY,EAAE,GAAG,EACjB,QAAQ,EAAE,MAAM,GACf,IAAI;IAuDP;;OAEG;IACH,OAAO,CAAC,cAAc;IAYtB;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAyC7F;;OAEG;IACH,OAAO,CAAC,aAAa;IAWrB,OAAO,CAAC,iBAAiB;IAOzB,OAAO,CAAC,gBAAgB;IASxB,cAAc,IAAI,MAAM,GAAG,IAAI;IAI/B,SAAS,IAAI,OAAO;CAGrB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,UAAmB,GAAG,SAAS,CAEzF;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAE7D;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAEhE"}
package/dist/ApiLogger.js CHANGED
@@ -1,12 +1,15 @@
1
1
  "use strict";
2
2
  /**
3
3
  * API Logger for capturing and logging HTTP requests/responses
4
+ * Produces a single structured test document with preconditions, steps, and teardown sections.
5
+ *
4
6
  * Features:
5
- * - Comprehensive request/response logging
7
+ * - Structured test document (one JSON per test)
8
+ * - Preconditions / Steps / Teardown sections
9
+ * - Step descriptions and numbering
6
10
  * - Curl command generation for manual testing
7
11
  * - Environment-based enable/disable via API_LOGS
8
- * - Automatic file logging with JSON format
9
- * - Test context tracking (setup/test/teardown)
12
+ * - Test context tracking and switching
10
13
  */
11
14
  var __importDefault = (this && this.__importDefault) || function (mod) {
12
15
  return (mod && mod.__esModule) ? mod : { "default": mod };
@@ -22,27 +25,24 @@ const CurlGenerator_1 = require("./CurlGenerator");
22
25
  class ApiLogger {
23
26
  constructor(config = {}) {
24
27
  this.logFilePath = null;
25
- this.currentRequest = null;
26
- this.requestStartTime = null;
27
- // Check if logging is enabled via environment variable
28
+ // Structured storage
29
+ this.preconditions = [];
30
+ this.steps = [];
31
+ this.teardownSteps = [];
28
32
  this.enabled = process.env.API_LOGS === 'true';
29
33
  this.testName = config.testName || 'unknown-test';
30
- this.context = config.context || 'test';
34
+ this.testFile = config.testFile;
35
+ this.currentContext = config.context || 'test';
31
36
  this.logDirectory = config.logDirectory || this.getDefaultLogDirectory();
32
37
  this.maskAuthTokens = config.maskAuthTokens ?? true;
38
+ this.startedAt = new Date().toISOString();
33
39
  if (this.enabled) {
34
40
  this.initializeLogFile();
35
41
  }
36
42
  }
37
- /**
38
- * Get default log directory path
39
- */
40
43
  getDefaultLogDirectory() {
41
44
  return path_1.default.join(process.cwd(), 'logs');
42
45
  }
43
- /**
44
- * Initialize log file and directory
45
- */
46
46
  initializeLogFile() {
47
47
  try {
48
48
  if (!fs_1.default.existsSync(this.logDirectory)) {
@@ -50,17 +50,48 @@ class ApiLogger {
50
50
  }
51
51
  const timestamp = this.generateTimestamp();
52
52
  const sanitizedTestName = this.sanitizeTestName(this.testName);
53
- const filename = `${this.context.toUpperCase()}_${sanitizedTestName}_${timestamp}.log`;
53
+ const filename = `${sanitizedTestName}_${timestamp}.log`;
54
54
  this.logFilePath = path_1.default.join(this.logDirectory, filename);
55
- if (!fs_1.default.existsSync(this.logFilePath)) {
56
- fs_1.default.writeFileSync(this.logFilePath, '');
57
- }
58
55
  }
59
56
  catch (error) {
60
57
  console.warn('[ApiLogger] Failed to initialize log file:', error);
61
58
  this.logFilePath = null;
62
59
  }
63
60
  }
61
+ /**
62
+ * Set description for the next API call
63
+ * @example
64
+ * logger.describe('Get employee ID for testing');
65
+ * await apiClient.getEmployees(); // this call gets the description
66
+ */
67
+ describe(description) {
68
+ this.nextDescription = description;
69
+ }
70
+ /**
71
+ * Switch current context (preconditions → test → teardown)
72
+ * All subsequent API calls will be logged to the new context section
73
+ */
74
+ setContext(context) {
75
+ this.currentContext = context;
76
+ }
77
+ /**
78
+ * Shortcut: switch to preconditions context
79
+ */
80
+ startPreconditions() {
81
+ this.currentContext = 'preconditions';
82
+ }
83
+ /**
84
+ * Shortcut: switch to test steps context
85
+ */
86
+ startTest() {
87
+ this.currentContext = 'test';
88
+ }
89
+ /**
90
+ * Shortcut: switch to teardown context
91
+ */
92
+ startTeardown() {
93
+ this.currentContext = 'teardown';
94
+ }
64
95
  /**
65
96
  * Log an API call with request and response
66
97
  */
@@ -69,7 +100,6 @@ class ApiLogger {
69
100
  return;
70
101
  }
71
102
  try {
72
- // Extract content type from headers
73
103
  let contentType;
74
104
  if (requestHeaders) {
75
105
  for (const [key, value] of Object.entries(requestHeaders)) {
@@ -91,75 +121,101 @@ class ApiLogger {
91
121
  headers: responseHeaders,
92
122
  body: responseBody,
93
123
  };
94
- // Generate curl command
95
124
  const curl = CurlGenerator_1.CurlGenerator.generate(requestData, this.maskAuthTokens);
96
- // Create log entry
97
- const logEntry = {
125
+ // Get target array and step number
126
+ const targetArray = this.getTargetArray();
127
+ const stepNumber = targetArray.length + 1;
128
+ const stepEntry = {
129
+ step: stepNumber,
130
+ description: this.nextDescription,
98
131
  timestamp: new Date().toISOString(),
99
- testName: this.testName,
100
- context: this.context,
101
132
  request: requestData,
102
133
  response: responseData,
103
134
  duration,
104
135
  curl,
105
136
  };
106
- this.writeLogEntry(logEntry);
137
+ // Clear description after use
138
+ this.nextDescription = undefined;
139
+ targetArray.push(stepEntry);
107
140
  }
108
141
  catch (error) {
109
142
  console.warn('[ApiLogger] Error logging API call:', error);
110
143
  }
111
144
  }
112
145
  /**
113
- * Log just the request part (when response isn't available yet)
146
+ * Get the target array for current context
114
147
  */
115
- logRequest(method, url, headers, body) {
116
- if (!this.enabled) {
117
- return;
148
+ getTargetArray() {
149
+ switch (this.currentContext) {
150
+ case 'preconditions':
151
+ return this.preconditions;
152
+ case 'teardown':
153
+ return this.teardownSteps;
154
+ case 'test':
155
+ default:
156
+ return this.steps;
118
157
  }
119
- this.currentRequest = { method, url, headers, body };
120
- this.requestStartTime = Date.now();
121
158
  }
122
159
  /**
123
- * Log just the response part (pairs with logRequest)
160
+ * Finalize and write the structured test document to file
124
161
  */
125
- logResponse(status, headers, body) {
126
- if (!this.enabled || !this.currentRequest) {
162
+ finalize(result, additionalInfo) {
163
+ if (!this.enabled) {
127
164
  return;
128
165
  }
129
- const duration = this.requestStartTime ? Date.now() - this.requestStartTime : 0;
130
- this.logApiCall(this.currentRequest.method, this.currentRequest.url, this.currentRequest.headers, this.currentRequest.body, status, headers, body, duration);
131
- this.currentRequest = null;
132
- this.requestStartTime = null;
166
+ try {
167
+ const finishedAt = new Date().toISOString();
168
+ const startTime = new Date(this.startedAt).getTime();
169
+ const endTime = new Date(finishedAt).getTime();
170
+ // Calculate total API duration
171
+ const allSteps = [...this.preconditions, ...this.steps, ...this.teardownSteps];
172
+ const totalApiDuration = allSteps.reduce((sum, s) => sum + s.duration, 0);
173
+ const document = {
174
+ test: {
175
+ name: this.testName,
176
+ file: this.testFile || additionalInfo?.testFile,
177
+ startedAt: this.startedAt,
178
+ finishedAt,
179
+ duration: endTime - startTime,
180
+ result,
181
+ },
182
+ preconditions: this.preconditions,
183
+ steps: this.steps,
184
+ teardown: this.teardownSteps,
185
+ summary: {
186
+ totalRequests: allSteps.length,
187
+ preconditions: this.preconditions.length,
188
+ testSteps: this.steps.length,
189
+ teardown: this.teardownSteps.length,
190
+ totalDuration: totalApiDuration,
191
+ },
192
+ };
193
+ this.writeDocument(document);
194
+ }
195
+ catch (error) {
196
+ console.warn('[ApiLogger] Error finalizing log:', error);
197
+ }
133
198
  }
134
199
  /**
135
- * Write log entry to file
200
+ * Write structured document to file
136
201
  */
137
- writeLogEntry(entry) {
202
+ writeDocument(document) {
138
203
  try {
139
204
  if (!this.logFilePath) {
140
205
  return;
141
206
  }
142
- const logLine = JSON.stringify(entry, null, 2);
143
- fs_1.default.appendFileSync(this.logFilePath, logLine + '\n\n');
207
+ fs_1.default.writeFileSync(this.logFilePath, JSON.stringify(document, null, 2) + '\n');
144
208
  }
145
209
  catch (error) {
146
210
  console.warn('[ApiLogger] Failed to write log file:', error);
147
211
  }
148
212
  }
149
- /**
150
- * Generate ISO timestamp for filenames
151
- */
152
213
  generateTimestamp() {
153
- const now = new Date();
154
- return now
214
+ return new Date()
155
215
  .toISOString()
156
216
  .replace(/[:.]/g, '-')
157
- .replace('T', 'T')
158
217
  .split('.')[0];
159
218
  }
160
- /**
161
- * Sanitize test name for use in filename
162
- */
163
219
  sanitizeTestName(name) {
164
220
  return name
165
221
  .toLowerCase()
@@ -168,43 +224,12 @@ class ApiLogger {
168
224
  .replace(/^-|-$/g, '')
169
225
  .substring(0, 80);
170
226
  }
171
- /**
172
- * Get the current log file path
173
- */
174
227
  getLogFilePath() {
175
228
  return this.logFilePath;
176
229
  }
177
- /**
178
- * Check if logger is enabled
179
- */
180
230
  isEnabled() {
181
231
  return this.enabled;
182
232
  }
183
- /**
184
- * Finalize logging for test completion
185
- */
186
- finalize(result, additionalInfo) {
187
- if (!this.enabled) {
188
- return;
189
- }
190
- try {
191
- const finalizationEntry = {
192
- timestamp: new Date().toISOString(),
193
- step: 'TEST_FINALIZATION',
194
- testName: this.testName,
195
- context: this.context,
196
- result,
197
- logFilePath: this.logFilePath,
198
- additionalInfo,
199
- };
200
- if (this.logFilePath) {
201
- fs_1.default.appendFileSync(this.logFilePath, JSON.stringify(finalizationEntry, null, 2) + '\n\n');
202
- }
203
- }
204
- catch (error) {
205
- console.warn('[ApiLogger] Error finalizing log:', error);
206
- }
207
- }
208
233
  }
209
234
  exports.ApiLogger = ApiLogger;
210
235
  /**
@@ -214,10 +239,10 @@ function createApiLogger(testName, context = 'test') {
214
239
  return new ApiLogger({ testName, context });
215
240
  }
216
241
  /**
217
- * Factory for setup context
242
+ * Factory for setup/preconditions context
218
243
  */
219
244
  function createSetupLogger(testName) {
220
- return new ApiLogger({ testName, context: 'setup' });
245
+ return new ApiLogger({ testName, context: 'preconditions' });
221
246
  }
222
247
  /**
223
248
  * Factory for teardown context
@@ -1 +1 @@
1
- {"version":3,"file":"ApiLogger.js","sourceRoot":"","sources":["../src/ApiLogger.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ApiLogger.js","sourceRoot":"","sources":["../src/ApiLogger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Global registry for sharing ApiLogger instances across
3
+ * beforeAll / test / afterAll in a Playwright test.describe block.
4
+ *
5
+ * Solves the problem: Playwright creates separate fixture instances
6
+ * for beforeAll, each test(), and afterAll — without a shared store
7
+ * each gets its own logger and writes a separate file.
8
+ *
9
+ * With LoggerRegistry, all phases write to the SAME structured log.
10
+ */
11
+ import { ApiLogger } from './ApiLogger';
12
+ import { LoggerConfig } from './types';
13
+ /**
14
+ * Get or create a shared logger by key.
15
+ * First call creates the logger, subsequent calls return the same instance.
16
+ *
17
+ * @param key - Unique key for the logger (e.g. describe block name)
18
+ * @param config - Logger config (only used on first call when creating)
19
+ * @returns Shared ApiLogger instance
20
+ *
21
+ * @example
22
+ * test.describe('GET /api/v1/employees', () => {
23
+ * const LOG_KEY = 'get-employees';
24
+ *
25
+ * test.beforeAll(async ({ apiClient }) => {
26
+ * const logger = getSharedLogger(LOG_KEY, { testName: 'GET employees' });
27
+ * logger.startPreconditions();
28
+ * // ... apiClient calls logged to preconditions
29
+ * });
30
+ *
31
+ * test('should return 200', async ({ apiClient }) => {
32
+ * const logger = getSharedLogger(LOG_KEY);
33
+ * logger.startTest();
34
+ * // ... apiClient calls logged to steps
35
+ * });
36
+ *
37
+ * test.afterAll(() => {
38
+ * finalizeSharedLogger(LOG_KEY, 'PASSED');
39
+ * });
40
+ * });
41
+ */
42
+ export declare function getSharedLogger(key: string, config?: LoggerConfig): ApiLogger;
43
+ /**
44
+ * Finalize a shared logger: write the structured document and remove from registry.
45
+ *
46
+ * @param key - The logger key used in getSharedLogger()
47
+ * @param result - Test result: 'PASSED' | 'FAILED' | 'SKIPPED'
48
+ * @param additionalInfo - Optional extra info to include
49
+ */
50
+ export declare function finalizeSharedLogger(key: string, result: 'PASSED' | 'FAILED' | 'SKIPPED', additionalInfo?: Record<string, any>): void;
51
+ /**
52
+ * Check if a shared logger exists for the given key.
53
+ */
54
+ export declare function hasSharedLogger(key: string): boolean;
55
+ /**
56
+ * Remove a shared logger without finalizing (cleanup).
57
+ */
58
+ export declare function removeSharedLogger(key: string): void;
59
+ //# sourceMappingURL=LoggerRegistry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LoggerRegistry.d.ts","sourceRoot":"","sources":["../src/LoggerRegistry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAIvC;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,YAAY,GAAG,SAAS,CAK7E;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,EACvC,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GACnC,IAAI,CAMN;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAEpD"}
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ /**
3
+ * Global registry for sharing ApiLogger instances across
4
+ * beforeAll / test / afterAll in a Playwright test.describe block.
5
+ *
6
+ * Solves the problem: Playwright creates separate fixture instances
7
+ * for beforeAll, each test(), and afterAll — without a shared store
8
+ * each gets its own logger and writes a separate file.
9
+ *
10
+ * With LoggerRegistry, all phases write to the SAME structured log.
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.getSharedLogger = getSharedLogger;
14
+ exports.finalizeSharedLogger = finalizeSharedLogger;
15
+ exports.hasSharedLogger = hasSharedLogger;
16
+ exports.removeSharedLogger = removeSharedLogger;
17
+ const ApiLogger_1 = require("./ApiLogger");
18
+ const registry = new Map();
19
+ /**
20
+ * Get or create a shared logger by key.
21
+ * First call creates the logger, subsequent calls return the same instance.
22
+ *
23
+ * @param key - Unique key for the logger (e.g. describe block name)
24
+ * @param config - Logger config (only used on first call when creating)
25
+ * @returns Shared ApiLogger instance
26
+ *
27
+ * @example
28
+ * test.describe('GET /api/v1/employees', () => {
29
+ * const LOG_KEY = 'get-employees';
30
+ *
31
+ * test.beforeAll(async ({ apiClient }) => {
32
+ * const logger = getSharedLogger(LOG_KEY, { testName: 'GET employees' });
33
+ * logger.startPreconditions();
34
+ * // ... apiClient calls logged to preconditions
35
+ * });
36
+ *
37
+ * test('should return 200', async ({ apiClient }) => {
38
+ * const logger = getSharedLogger(LOG_KEY);
39
+ * logger.startTest();
40
+ * // ... apiClient calls logged to steps
41
+ * });
42
+ *
43
+ * test.afterAll(() => {
44
+ * finalizeSharedLogger(LOG_KEY, 'PASSED');
45
+ * });
46
+ * });
47
+ */
48
+ function getSharedLogger(key, config) {
49
+ if (!registry.has(key)) {
50
+ registry.set(key, new ApiLogger_1.ApiLogger(config));
51
+ }
52
+ return registry.get(key);
53
+ }
54
+ /**
55
+ * Finalize a shared logger: write the structured document and remove from registry.
56
+ *
57
+ * @param key - The logger key used in getSharedLogger()
58
+ * @param result - Test result: 'PASSED' | 'FAILED' | 'SKIPPED'
59
+ * @param additionalInfo - Optional extra info to include
60
+ */
61
+ function finalizeSharedLogger(key, result, additionalInfo) {
62
+ const logger = registry.get(key);
63
+ if (logger) {
64
+ logger.finalize(result, additionalInfo);
65
+ registry.delete(key);
66
+ }
67
+ }
68
+ /**
69
+ * Check if a shared logger exists for the given key.
70
+ */
71
+ function hasSharedLogger(key) {
72
+ return registry.has(key);
73
+ }
74
+ /**
75
+ * Remove a shared logger without finalizing (cleanup).
76
+ */
77
+ function removeSharedLogger(key) {
78
+ registry.delete(key);
79
+ }
80
+ //# sourceMappingURL=LoggerRegistry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LoggerRegistry.js","sourceRoot":"","sources":["../src/LoggerRegistry.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;;AAoCH,0CAKC;AASD,oDAUC;AAKD,0CAEC;AAKD,gDAEC;AAxED,2CAAwC;AAGxC,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAqB,CAAC;AAE9C;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,SAAgB,eAAe,CAAC,GAAW,EAAE,MAAqB;IAChE,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;QACvB,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,qBAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IAC3C,CAAC;IACD,OAAO,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC;AAC5B,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,oBAAoB,CAClC,GAAW,EACX,MAAuC,EACvC,cAAoC;IAEpC,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACjC,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;QACxC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACvB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAgB,eAAe,CAAC,GAAW;IACzC,OAAO,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAC3B,CAAC;AAED;;GAEG;AACH,SAAgB,kBAAkB,CAAC,GAAW;IAC5C,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AACvB,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  export { ApiLogger, createApiLogger, createSetupLogger, createTeardownLogger } from './ApiLogger';
2
2
  export { CurlGenerator } from './CurlGenerator';
3
3
  export { withApiLogging } from './withApiLogging';
4
+ export { getSharedLogger, finalizeSharedLogger, hasSharedLogger, removeSharedLogger } from './LoggerRegistry';
4
5
  export type { ApiLoggingOptions } from './withApiLogging';
5
- export type { LoggerConfig, RequestLogData, ResponseLogData, LogEntry, LogContext } from './types';
6
+ export type { LoggerConfig, RequestLogData, ResponseLogData, StepLogEntry, TestLogDocument, LogEntry, LogContext, } from './types';
6
7
  export type { RequestData } from './CurlGenerator';
7
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAClG,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,YAAY,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACnG,YAAY,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAClG,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC9G,YAAY,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,YAAY,EACV,YAAY,EACZ,cAAc,EACd,eAAe,EACf,YAAY,EACZ,eAAe,EACf,QAAQ,EACR,UAAU,GACX,MAAM,SAAS,CAAC;AACjB,YAAY,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC"}
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.withApiLogging = exports.CurlGenerator = exports.createTeardownLogger = exports.createSetupLogger = exports.createApiLogger = exports.ApiLogger = void 0;
3
+ exports.removeSharedLogger = exports.hasSharedLogger = exports.finalizeSharedLogger = exports.getSharedLogger = exports.withApiLogging = exports.CurlGenerator = exports.createTeardownLogger = exports.createSetupLogger = exports.createApiLogger = exports.ApiLogger = void 0;
4
4
  var ApiLogger_1 = require("./ApiLogger");
5
5
  Object.defineProperty(exports, "ApiLogger", { enumerable: true, get: function () { return ApiLogger_1.ApiLogger; } });
6
6
  Object.defineProperty(exports, "createApiLogger", { enumerable: true, get: function () { return ApiLogger_1.createApiLogger; } });
@@ -10,4 +10,9 @@ var CurlGenerator_1 = require("./CurlGenerator");
10
10
  Object.defineProperty(exports, "CurlGenerator", { enumerable: true, get: function () { return CurlGenerator_1.CurlGenerator; } });
11
11
  var withApiLogging_1 = require("./withApiLogging");
12
12
  Object.defineProperty(exports, "withApiLogging", { enumerable: true, get: function () { return withApiLogging_1.withApiLogging; } });
13
+ var LoggerRegistry_1 = require("./LoggerRegistry");
14
+ Object.defineProperty(exports, "getSharedLogger", { enumerable: true, get: function () { return LoggerRegistry_1.getSharedLogger; } });
15
+ Object.defineProperty(exports, "finalizeSharedLogger", { enumerable: true, get: function () { return LoggerRegistry_1.finalizeSharedLogger; } });
16
+ Object.defineProperty(exports, "hasSharedLogger", { enumerable: true, get: function () { return LoggerRegistry_1.hasSharedLogger; } });
17
+ Object.defineProperty(exports, "removeSharedLogger", { enumerable: true, get: function () { return LoggerRegistry_1.removeSharedLogger; } });
13
18
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,yCAAkG;AAAzF,sGAAA,SAAS,OAAA;AAAE,4GAAA,eAAe,OAAA;AAAE,8GAAA,iBAAiB,OAAA;AAAE,iHAAA,oBAAoB,OAAA;AAC5E,iDAAgD;AAAvC,8GAAA,aAAa,OAAA;AACtB,mDAAkD;AAAzC,gHAAA,cAAc,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,yCAAkG;AAAzF,sGAAA,SAAS,OAAA;AAAE,4GAAA,eAAe,OAAA;AAAE,8GAAA,iBAAiB,OAAA;AAAE,iHAAA,oBAAoB,OAAA;AAC5E,iDAAgD;AAAvC,8GAAA,aAAa,OAAA;AACtB,mDAAkD;AAAzC,gHAAA,cAAc,OAAA;AACvB,mDAA8G;AAArG,iHAAA,eAAe,OAAA;AAAE,sHAAA,oBAAoB,OAAA;AAAE,iHAAA,eAAe,OAAA;AAAE,oHAAA,kBAAkB,OAAA"}
package/dist/types.d.ts CHANGED
@@ -1,6 +1,7 @@
1
- export type LogContext = 'setup' | 'test' | 'teardown';
1
+ export type LogContext = 'preconditions' | 'test' | 'teardown';
2
2
  export interface LoggerConfig {
3
3
  testName?: string;
4
+ testFile?: string;
4
5
  context?: LogContext;
5
6
  logDirectory?: string;
6
7
  maskAuthTokens?: boolean;
@@ -17,6 +18,36 @@ export interface ResponseLogData {
17
18
  headers?: Record<string, string>;
18
19
  body?: any;
19
20
  }
21
+ export interface StepLogEntry {
22
+ step: number;
23
+ description?: string;
24
+ timestamp: string;
25
+ request: RequestLogData;
26
+ response: ResponseLogData;
27
+ duration: number;
28
+ curl: string;
29
+ }
30
+ export interface TestLogDocument {
31
+ test: {
32
+ name: string;
33
+ file?: string;
34
+ startedAt: string;
35
+ finishedAt?: string;
36
+ duration?: number;
37
+ result?: 'PASSED' | 'FAILED' | 'SKIPPED';
38
+ };
39
+ preconditions: StepLogEntry[];
40
+ steps: StepLogEntry[];
41
+ teardown: StepLogEntry[];
42
+ summary: {
43
+ totalRequests: number;
44
+ preconditions: number;
45
+ testSteps: number;
46
+ teardown: number;
47
+ totalDuration: number;
48
+ };
49
+ }
50
+ /** @deprecated Use StepLogEntry instead */
20
51
  export interface LogEntry {
21
52
  timestamp: string;
22
53
  testName: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,MAAM,GAAG,UAAU,CAAC;AAEvD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,UAAU,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;IAC5C,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,IAAI,CAAC,EAAE,GAAG,CAAC;CACZ;AAED,MAAM,WAAW,QAAQ;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,UAAU,CAAC;IACpB,OAAO,EAAE,cAAc,CAAC;IACxB,QAAQ,EAAE,eAAe,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG,eAAe,GAAG,MAAM,GAAG,UAAU,CAAC;AAE/D,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,UAAU,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;IAC5C,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,IAAI,CAAC,EAAE,GAAG,CAAC;CACZ;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,cAAc,CAAC;IACxB,QAAQ,EAAE,eAAe,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE;QACJ,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,MAAM,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;KAC1C,CAAC;IACF,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,OAAO,EAAE;QACP,aAAa,EAAE,MAAM,CAAC;QACtB,aAAa,EAAE,MAAM,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,aAAa,EAAE,MAAM,CAAC;KACvB,CAAC;CACH;AAED,2CAA2C;AAC3C,MAAM,WAAW,QAAQ;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,UAAU,CAAC;IACpB,OAAO,EAAE,cAAc,CAAC;IACxB,QAAQ,EAAE,eAAe,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd"}
@@ -8,12 +8,18 @@ import { LogContext } from './types';
8
8
  export interface ApiLoggingOptions {
9
9
  /** Test name for log filename (auto-detected from testInfo if provided) */
10
10
  testName?: string;
11
- /** Log context: 'setup' | 'test' | 'teardown' (default: 'test') */
11
+ /** Test file path (auto-detected from testInfo if provided) */
12
+ testFile?: string;
13
+ /** Log context: 'preconditions' | 'test' | 'teardown' (default: 'test') */
12
14
  context?: LogContext;
13
15
  /** Custom log directory (default: 'logs/') */
14
16
  logDirectory?: string;
15
17
  /** Mask Authorization headers (default: true) */
16
18
  maskAuthTokens?: boolean;
19
+ /** Existing logger instance to reuse */
20
+ logger?: ApiLogger;
21
+ /** Shared logger key — use same key in beforeAll/test/afterAll to write ONE log file */
22
+ sharedKey?: string;
17
23
  }
18
24
  /**
19
25
  * Wrap Playwright's APIRequestContext with automatic logging.
@@ -29,8 +35,12 @@ export interface ApiLoggingOptions {
29
35
  * const apiClient = new ApiClient(loggedRequest);
30
36
  *
31
37
  * @example
32
- * // With options:
33
- * const loggedRequest = withApiLogging(request, { testName: 'my-test', context: 'setup' });
38
+ * // Shared logger across beforeAll/test/afterAll:
39
+ * const loggedRequest = withApiLogging(request, {
40
+ * sharedKey: 'my-describe',
41
+ * testName: 'My Test',
42
+ * context: 'preconditions'
43
+ * });
34
44
  */
35
45
  export declare function withApiLogging(request: APIRequestContext, testInfoOrOptions?: TestInfo | ApiLoggingOptions): APIRequestContext & {
36
46
  __logger: ApiLogger;
@@ -1 +1 @@
1
- {"version":3,"file":"withApiLogging.d.ts","sourceRoot":"","sources":["../src/withApiLogging.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAe,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACjF,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,UAAU,EAAgB,MAAM,SAAS,CAAC;AAEnD,MAAM,WAAW,iBAAiB;IAChC,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mEAAmE;IACnE,OAAO,CAAC,EAAE,UAAU,CAAC;IACrB,8CAA8C;IAC9C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iDAAiD;IACjD,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,iBAAiB,EAC1B,iBAAiB,CAAC,EAAE,QAAQ,GAAG,iBAAiB,GAC/C,iBAAiB,GAAG;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,CA6F7C"}
1
+ {"version":3,"file":"withApiLogging.d.ts","sourceRoot":"","sources":["../src/withApiLogging.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAe,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACjF,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,UAAU,EAAgB,MAAM,SAAS,CAAC;AAGnD,MAAM,WAAW,iBAAiB;IAChC,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2EAA2E;IAC3E,OAAO,CAAC,EAAE,UAAU,CAAC;IACrB,8CAA8C;IAC9C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iDAAiD;IACjD,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,wCAAwC;IACxC,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,wFAAwF;IACxF,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,iBAAiB,EAC1B,iBAAiB,CAAC,EAAE,QAAQ,GAAG,iBAAiB,GAC/C,iBAAiB,GAAG;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,CAiH7C"}
@@ -6,6 +6,7 @@
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
7
  exports.withApiLogging = withApiLogging;
8
8
  const ApiLogger_1 = require("./ApiLogger");
9
+ const LoggerRegistry_1 = require("./LoggerRegistry");
9
10
  /**
10
11
  * Wrap Playwright's APIRequestContext with automatic logging.
11
12
  * All HTTP calls (get, post, put, patch, delete, head, fetch) are intercepted and logged.
@@ -20,30 +21,60 @@ const ApiLogger_1 = require("./ApiLogger");
20
21
  * const apiClient = new ApiClient(loggedRequest);
21
22
  *
22
23
  * @example
23
- * // With options:
24
- * const loggedRequest = withApiLogging(request, { testName: 'my-test', context: 'setup' });
24
+ * // Shared logger across beforeAll/test/afterAll:
25
+ * const loggedRequest = withApiLogging(request, {
26
+ * sharedKey: 'my-describe',
27
+ * testName: 'My Test',
28
+ * context: 'preconditions'
29
+ * });
25
30
  */
26
31
  function withApiLogging(request, testInfoOrOptions) {
27
- // Resolve options
28
32
  let options;
29
33
  if (testInfoOrOptions && 'title' in testInfoOrOptions) {
30
- // TestInfo object
34
+ const testInfo = testInfoOrOptions;
31
35
  options = {
32
- testName: testInfoOrOptions.title,
36
+ testName: testInfo.title,
37
+ testFile: testInfo.file,
33
38
  context: 'test',
34
39
  };
35
40
  }
36
41
  else {
37
42
  options = testInfoOrOptions || {};
38
43
  }
39
- const config = {
40
- testName: options.testName,
41
- context: options.context || 'test',
42
- logDirectory: options.logDirectory,
43
- maskAuthTokens: options.maskAuthTokens,
44
- };
45
- const logger = new ApiLogger_1.ApiLogger(config);
46
- // If logging is disabled, return original request with dummy logger
44
+ // Resolve logger: shared → existing → new
45
+ let logger;
46
+ if (options.sharedKey) {
47
+ // Shared logger by key — same instance across beforeAll/test/afterAll
48
+ const config = {
49
+ testName: options.testName,
50
+ testFile: options.testFile,
51
+ context: options.context || 'test',
52
+ logDirectory: options.logDirectory,
53
+ maskAuthTokens: options.maskAuthTokens,
54
+ };
55
+ logger = (0, LoggerRegistry_1.getSharedLogger)(options.sharedKey, config);
56
+ // Switch context for this phase
57
+ if (options.context) {
58
+ logger.setContext(options.context);
59
+ }
60
+ }
61
+ else if (options.logger) {
62
+ logger = options.logger;
63
+ if (options.context) {
64
+ logger.setContext(options.context);
65
+ }
66
+ }
67
+ else {
68
+ const config = {
69
+ testName: options.testName,
70
+ testFile: options.testFile,
71
+ context: options.context || 'test',
72
+ logDirectory: options.logDirectory,
73
+ maskAuthTokens: options.maskAuthTokens,
74
+ };
75
+ logger = new ApiLogger_1.ApiLogger(config);
76
+ }
77
+ // If logging is disabled, return original request with logger ref
47
78
  if (!logger.isEnabled()) {
48
79
  return Object.assign(request, { __logger: logger });
49
80
  }
@@ -51,22 +82,18 @@ function withApiLogging(request, testInfoOrOptions) {
51
82
  const proxy = new Proxy(request, {
52
83
  get(target, prop, receiver) {
53
84
  const propName = typeof prop === 'string' ? prop : '';
54
- // Expose logger reference
55
85
  if (propName === '__logger') {
56
86
  return logger;
57
87
  }
58
88
  if (HTTP_METHODS.includes(propName)) {
59
- return async (url, options) => {
60
- const method = propName === 'fetch' ? (options?.method || 'GET') : propName;
89
+ return async (url, reqOptions) => {
90
+ const method = propName === 'fetch' ? (reqOptions?.method || 'GET') : propName;
61
91
  const startTime = Date.now();
62
- // Extract request details from Playwright options
63
- const requestHeaders = options?.headers;
64
- const requestBody = extractBody(options);
65
- const contentType = extractContentType(options, requestHeaders);
92
+ const requestHeaders = reqOptions?.headers;
93
+ const requestBody = extractBody(reqOptions);
66
94
  try {
67
- const response = await target[propName](url, options);
95
+ const response = await target[propName](url, reqOptions);
68
96
  const duration = Date.now() - startTime;
69
- // Parse response body safely
70
97
  const responseBody = await safeParseResponseBody(response);
71
98
  const responseHeaders = extractResponseHeaders(response);
72
99
  logger.logApiCall(method.toUpperCase(), response.url(), requestHeaders, requestBody, response.status(), responseHeaders, responseBody, duration);
@@ -84,9 +111,6 @@ function withApiLogging(request, testInfoOrOptions) {
84
111
  });
85
112
  return Object.assign(proxy, { __logger: logger });
86
113
  }
87
- /**
88
- * Extract body from Playwright request options
89
- */
90
114
  function extractBody(options) {
91
115
  if (!options)
92
116
  return undefined;
@@ -98,26 +122,6 @@ function extractBody(options) {
98
122
  return options.multipart;
99
123
  return undefined;
100
124
  }
101
- /**
102
- * Detect content type from options
103
- */
104
- function extractContentType(options, headers) {
105
- if (options?.form)
106
- return 'application/x-www-form-urlencoded';
107
- if (options?.multipart)
108
- return 'multipart/form-data';
109
- if (headers) {
110
- for (const [key, value] of Object.entries(headers)) {
111
- if (key.toLowerCase() === 'content-type') {
112
- return Array.isArray(value) ? value[0] : String(value);
113
- }
114
- }
115
- }
116
- return undefined;
117
- }
118
- /**
119
- * Safely parse response body (try JSON, fallback to text)
120
- */
121
125
  async function safeParseResponseBody(response) {
122
126
  try {
123
127
  return await response.json();
@@ -131,9 +135,6 @@ async function safeParseResponseBody(response) {
131
135
  }
132
136
  }
133
137
  }
134
- /**
135
- * Extract headers from APIResponse
136
- */
137
138
  function extractResponseHeaders(response) {
138
139
  try {
139
140
  return response.headers();
@@ -1 +1 @@
1
- {"version":3,"file":"withApiLogging.js","sourceRoot":"","sources":["../src/withApiLogging.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"withApiLogging.js","sourceRoot":"","sources":["../src/withApiLogging.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "playwright-api-logger",
3
- "version": "2.0.0",
3
+ "version": "2.2.0",
4
4
  "description": "Comprehensive API request/response logger with curl export for Playwright tests",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",