@browsermation/test 0.0.67 → 0.0.70
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/dist/reporter/reporter.d.ts +5 -0
- package/dist/reporter/reporter.test.d.ts +1 -0
- package/dist/reporter.js +151 -5
- package/dist/test.d.ts +1 -1
- package/package.json +17 -9
|
@@ -3,18 +3,23 @@ export default class BrowsermationReporter implements Reporter {
|
|
|
3
3
|
browsermationURL: string;
|
|
4
4
|
apiToken: string;
|
|
5
5
|
suiteRunId: string | null;
|
|
6
|
+
batchMode: boolean;
|
|
7
|
+
batchEvents: Array<Record<string, any>>;
|
|
6
8
|
log(message: string): void;
|
|
7
9
|
logEvent(message: string): void;
|
|
8
10
|
constructor(options?: {
|
|
9
11
|
reportingURL?: string;
|
|
10
12
|
apiToken?: string;
|
|
13
|
+
batchMode?: boolean;
|
|
11
14
|
});
|
|
12
15
|
getCurrentBranch(): Promise<string>;
|
|
13
16
|
getCurrentRepo(): Promise<string>;
|
|
14
17
|
getLatestCommitId(): Promise<string>;
|
|
15
18
|
getLatestCommitMessage(): Promise<string>;
|
|
16
19
|
gitRemoteOriginUrl(): Promise<string>;
|
|
20
|
+
getReportingURL(): string;
|
|
17
21
|
sendData(data: Record<string, any>): Promise<any>;
|
|
22
|
+
sendBatchData(): Promise<any>;
|
|
18
23
|
getProjectSuite(parent: Suite): FullProject | undefined;
|
|
19
24
|
/**
|
|
20
25
|
* onBegin() is called once with a root suite that contains all other suites and tests. Learn more about suites hierarchy.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/reporter.js
CHANGED
|
@@ -36,6 +36,8 @@ var BrowsermationReporter = class {
|
|
|
36
36
|
browsermationURL = "";
|
|
37
37
|
apiToken = "";
|
|
38
38
|
suiteRunId = null;
|
|
39
|
+
batchMode = false;
|
|
40
|
+
batchEvents = [];
|
|
39
41
|
log(message) {
|
|
40
42
|
if (process.env.BM_REPORTER_DEBUG_LOGS) {
|
|
41
43
|
console.log(message);
|
|
@@ -47,9 +49,11 @@ var BrowsermationReporter = class {
|
|
|
47
49
|
}
|
|
48
50
|
}
|
|
49
51
|
constructor(options = {}) {
|
|
52
|
+
this.batchMode = options.batchMode || process.env.BM_BATCH_MODE === "true" || false;
|
|
50
53
|
this.browsermationURL = options.reportingURL || process.env.BM_REPORTING_URL || "https://browsermation.com/api/v1/playwright/reporting";
|
|
51
54
|
this.apiToken = options.apiToken || process.env.BM_API_TOKEN || "";
|
|
52
55
|
this.log(`Using Browsermation reporting URL: ${this.browsermationURL}`);
|
|
56
|
+
this.log(`Batch mode: ${this.batchMode ? "enabled" : "disabled"}`);
|
|
53
57
|
this.log(
|
|
54
58
|
"Using API Token: " + (this.apiToken ? this.apiToken.slice(0, 4) + "****" : "not set")
|
|
55
59
|
);
|
|
@@ -152,6 +156,17 @@ var BrowsermationReporter = class {
|
|
|
152
156
|
});
|
|
153
157
|
});
|
|
154
158
|
}
|
|
159
|
+
getReportingURL() {
|
|
160
|
+
const browserRunId = process.env.BM_BROWSER_RUN_ID;
|
|
161
|
+
if (browserRunId) {
|
|
162
|
+
const baseURL = this.browsermationURL.replace(
|
|
163
|
+
/\/api\/v1\/playwright\/reporting$/,
|
|
164
|
+
""
|
|
165
|
+
);
|
|
166
|
+
return `${baseURL}/api/v1/browser-runs/${browserRunId}/reporting`;
|
|
167
|
+
}
|
|
168
|
+
return this.browsermationURL;
|
|
169
|
+
}
|
|
155
170
|
async sendData(data) {
|
|
156
171
|
if (process.env.BM_REPORTER_ONLY_LOG_EVENTS) {
|
|
157
172
|
this.log(
|
|
@@ -159,34 +174,158 @@ var BrowsermationReporter = class {
|
|
|
159
174
|
);
|
|
160
175
|
return;
|
|
161
176
|
}
|
|
162
|
-
if (
|
|
163
|
-
|
|
177
|
+
if (this.batchMode) {
|
|
178
|
+
this.log(`Batch mode: Adding event to batch: ${data.type}`);
|
|
179
|
+
this.batchEvents.push(data);
|
|
180
|
+
return;
|
|
164
181
|
}
|
|
165
182
|
if (!this.apiToken) {
|
|
166
183
|
this.log("API token not set. Skipping sending data to Browsermation.");
|
|
167
184
|
return;
|
|
168
185
|
}
|
|
169
186
|
this.log(`Sending data to Browsermation: ${JSON.stringify(data)}`);
|
|
187
|
+
const url = this.getReportingURL();
|
|
170
188
|
try {
|
|
171
|
-
|
|
189
|
+
this.log(`Making POST request to: ${url}`);
|
|
190
|
+
const response = await fetch(url, {
|
|
172
191
|
method: "POST",
|
|
173
192
|
headers: {
|
|
174
193
|
Accept: "application/json",
|
|
175
194
|
"Content-Type": "application/json",
|
|
176
|
-
Authorization: `Bearer ${this.apiToken}
|
|
195
|
+
Authorization: `Bearer ${this.apiToken}`,
|
|
196
|
+
"X-Browsermation-Reporter": "v0.0.67",
|
|
197
|
+
"User-Agent": "Browsermation-Reporter/0.0.67"
|
|
177
198
|
},
|
|
178
|
-
body: JSON.stringify(data)
|
|
199
|
+
body: JSON.stringify(data),
|
|
200
|
+
redirect: "manual"
|
|
201
|
+
// Don't follow redirects that might change method
|
|
179
202
|
});
|
|
203
|
+
this.log(`Response status: ${response.status} ${response.statusText}`);
|
|
204
|
+
this.log(`Response type: ${response.type}`);
|
|
205
|
+
this.log(`Response URL: ${response.url}`);
|
|
206
|
+
if (response.status === 301 || response.status === 302) {
|
|
207
|
+
const redirectUrl = response.headers.get("location");
|
|
208
|
+
if (redirectUrl) {
|
|
209
|
+
this.log(`Following redirect to: ${redirectUrl}`);
|
|
210
|
+
const redirectResponse = await fetch(redirectUrl, {
|
|
211
|
+
method: "POST",
|
|
212
|
+
headers: {
|
|
213
|
+
Accept: "application/json",
|
|
214
|
+
"Content-Type": "application/json",
|
|
215
|
+
Authorization: `Bearer ${this.apiToken}`,
|
|
216
|
+
"X-Browsermation-Reporter": "v0.0.67",
|
|
217
|
+
"User-Agent": "Browsermation-Reporter/0.0.67"
|
|
218
|
+
},
|
|
219
|
+
body: JSON.stringify(data)
|
|
220
|
+
});
|
|
221
|
+
if (!redirectResponse.ok) {
|
|
222
|
+
const responseText = await redirectResponse.text();
|
|
223
|
+
this.log(
|
|
224
|
+
`Failed to send data to Browsermation after redirect. Status: ${redirectResponse.status} - ${redirectResponse.statusText}`
|
|
225
|
+
);
|
|
226
|
+
this.log(`Response body: ${responseText.substring(0, 500)}`);
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
return await redirectResponse.json();
|
|
230
|
+
}
|
|
231
|
+
}
|
|
180
232
|
if (!response.ok) {
|
|
233
|
+
const responseText = await response.text();
|
|
181
234
|
this.log(
|
|
182
235
|
`Failed to send data to Browsermation. Status: ${response.status} - ${response.statusText}`
|
|
183
236
|
);
|
|
237
|
+
this.log(`Response body: ${responseText.substring(0, 500)}`);
|
|
238
|
+
return;
|
|
184
239
|
}
|
|
185
240
|
return await response.json();
|
|
186
241
|
} catch (error) {
|
|
187
242
|
console.error("Error sending data to Browsermation:", error);
|
|
188
243
|
}
|
|
189
244
|
}
|
|
245
|
+
async sendBatchData() {
|
|
246
|
+
if (process.env.BM_REPORTER_ONLY_LOG_EVENTS) {
|
|
247
|
+
this.log(
|
|
248
|
+
"BM_REPORTER_ONLY_LOG_EVENTS is set to true. Skipping sending batch data to Browsermation."
|
|
249
|
+
);
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
if (!this.apiToken) {
|
|
253
|
+
this.log(
|
|
254
|
+
"API token not set. Skipping sending batch data to Browsermation."
|
|
255
|
+
);
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
if (this.batchEvents.length === 0) {
|
|
259
|
+
this.log("No batch events to send.");
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
const batchURL = this.getReportingURL().replace(
|
|
263
|
+
"/reporting",
|
|
264
|
+
"/batch-reporting"
|
|
265
|
+
);
|
|
266
|
+
const batchData = {
|
|
267
|
+
events: this.batchEvents,
|
|
268
|
+
suite_run_id: this.suiteRunId
|
|
269
|
+
};
|
|
270
|
+
this.log(
|
|
271
|
+
`Sending ${this.batchEvents.length} events in batch to Browsermation`
|
|
272
|
+
);
|
|
273
|
+
try {
|
|
274
|
+
this.log(`Making POST request to: ${batchURL}`);
|
|
275
|
+
const response = await fetch(batchURL, {
|
|
276
|
+
method: "POST",
|
|
277
|
+
headers: {
|
|
278
|
+
Accept: "application/json",
|
|
279
|
+
"Content-Type": "application/json",
|
|
280
|
+
Authorization: `Bearer ${this.apiToken}`,
|
|
281
|
+
"X-Browsermation-Reporter": "v0.0.67",
|
|
282
|
+
"User-Agent": "Browsermation-Reporter/0.0.67"
|
|
283
|
+
},
|
|
284
|
+
body: JSON.stringify(batchData),
|
|
285
|
+
redirect: "manual"
|
|
286
|
+
});
|
|
287
|
+
this.log(`Response status: ${response.status} ${response.statusText}`);
|
|
288
|
+
this.log(`Response type: ${response.type}`);
|
|
289
|
+
this.log(`Response URL: ${response.url}`);
|
|
290
|
+
if (response.status === 301 || response.status === 302) {
|
|
291
|
+
const redirectUrl = response.headers.get("location");
|
|
292
|
+
if (redirectUrl) {
|
|
293
|
+
this.log(`Following redirect to: ${redirectUrl}`);
|
|
294
|
+
const redirectResponse = await fetch(redirectUrl, {
|
|
295
|
+
method: "POST",
|
|
296
|
+
headers: {
|
|
297
|
+
Accept: "application/json",
|
|
298
|
+
"Content-Type": "application/json",
|
|
299
|
+
Authorization: `Bearer ${this.apiToken}`,
|
|
300
|
+
"X-Browsermation-Reporter": "v0.0.67",
|
|
301
|
+
"User-Agent": "Browsermation-Reporter/0.0.67"
|
|
302
|
+
},
|
|
303
|
+
body: JSON.stringify(batchData)
|
|
304
|
+
});
|
|
305
|
+
if (!redirectResponse.ok) {
|
|
306
|
+
const responseText = await redirectResponse.text();
|
|
307
|
+
this.log(
|
|
308
|
+
`Failed to send batch data to Browsermation after redirect. Status: ${redirectResponse.status} - ${redirectResponse.statusText}`
|
|
309
|
+
);
|
|
310
|
+
this.log(`Response body: ${responseText.substring(0, 500)}`);
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
return await redirectResponse.json();
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
if (!response.ok) {
|
|
317
|
+
const responseText = await response.text();
|
|
318
|
+
this.log(
|
|
319
|
+
`Failed to send batch data to Browsermation. Status: ${response.status} - ${response.statusText}`
|
|
320
|
+
);
|
|
321
|
+
this.log(`Response body: ${responseText.substring(0, 500)}`);
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
return await response.json();
|
|
325
|
+
} catch (error) {
|
|
326
|
+
console.error("Error sending batch data to Browsermation:", error);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
190
329
|
getProjectSuite(parent) {
|
|
191
330
|
let currentSuite = parent;
|
|
192
331
|
while (currentSuite.parent) {
|
|
@@ -238,12 +377,16 @@ var BrowsermationReporter = class {
|
|
|
238
377
|
this.logEvent(`${JSON.stringify(data)}
|
|
239
378
|
`);
|
|
240
379
|
await this.sendData(data);
|
|
380
|
+
if (this.batchMode) {
|
|
381
|
+
await this.sendBatchData();
|
|
382
|
+
}
|
|
241
383
|
}
|
|
242
384
|
async onTestBegin(test) {
|
|
243
385
|
const data = {
|
|
244
386
|
id: test.id,
|
|
245
387
|
type: "test-start",
|
|
246
388
|
title: test.title,
|
|
389
|
+
title_path: test.titlePath,
|
|
247
390
|
file: test.location.file.replace(process.cwd(), ""),
|
|
248
391
|
hostname: (0, import_node_os.hostname)(),
|
|
249
392
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -306,5 +449,8 @@ var BrowsermationReporter = class {
|
|
|
306
449
|
this.logEvent(`${JSON.stringify(data)}
|
|
307
450
|
`);
|
|
308
451
|
await this.sendData(data);
|
|
452
|
+
if (this.batchMode && this.batchEvents.length > 0) {
|
|
453
|
+
await this.sendBatchData();
|
|
454
|
+
}
|
|
309
455
|
}
|
|
310
456
|
};
|
package/dist/test.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const test: import("
|
|
1
|
+
export declare const test: import("playwright/test").TestType<import("playwright/test").PlaywrightTestArgs & import("playwright/test").PlaywrightTestOptions, import("playwright/test").PlaywrightWorkerArgs & import("playwright/test").PlaywrightWorkerOptions>;
|
package/package.json
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@browsermation/test",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.70",
|
|
4
4
|
"description": "The testing platform for Playwright by Browsermation.",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
7
7
|
"exports": {
|
|
8
8
|
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
9
10
|
"import": "./dist/index.js",
|
|
10
11
|
"require": "./dist/index.js",
|
|
11
|
-
"types": "./dist/index.d.ts",
|
|
12
12
|
"default": "./dist/index.js"
|
|
13
13
|
},
|
|
14
14
|
"./reporter": {
|
|
15
|
+
"types": "./dist/reporter.d.ts",
|
|
15
16
|
"import": "./dist/reporter.js",
|
|
16
17
|
"require": "./dist/reporter.js",
|
|
17
|
-
"types": "./dist/reporter.d.ts",
|
|
18
18
|
"default": "./dist/reporter.js"
|
|
19
19
|
},
|
|
20
20
|
"./package.json": "./package.json"
|
|
@@ -32,6 +32,10 @@
|
|
|
32
32
|
"build": "rm -rf dist && npm run build:index && npm run build:reporter && npm run build:types",
|
|
33
33
|
"start": "node dist/bin/cli.js",
|
|
34
34
|
"build:start": "npm run build && npm start",
|
|
35
|
+
"test": "vitest",
|
|
36
|
+
"test:ui": "vitest --ui",
|
|
37
|
+
"test:run": "vitest run",
|
|
38
|
+
"test:coverage": "vitest run --coverage",
|
|
35
39
|
"publishPackage": "npm run build && npm publish --access public",
|
|
36
40
|
"publishBetaPackage": "npm run build && npm publish --access public --tag beta"
|
|
37
41
|
},
|
|
@@ -44,14 +48,18 @@
|
|
|
44
48
|
"author": "Browsermation Team",
|
|
45
49
|
"license": "MIT",
|
|
46
50
|
"devDependencies": {
|
|
47
|
-
"@types/node": "^
|
|
48
|
-
"
|
|
49
|
-
"
|
|
51
|
+
"@types/node": "^25.0.3",
|
|
52
|
+
"@vitest/coverage-v8": "^4.0.16",
|
|
53
|
+
"@vitest/ui": "^4.0.16",
|
|
54
|
+
"esbuild": "^0.27.2",
|
|
55
|
+
"happy-dom": "^20.0.11",
|
|
56
|
+
"typescript": "^5.9.3",
|
|
57
|
+
"vitest": "^4.0.16"
|
|
50
58
|
},
|
|
51
59
|
"dependencies": {
|
|
52
|
-
"@playwright/test": "^1.
|
|
53
|
-
"chalk": "^5.
|
|
54
|
-
"ora": "^
|
|
60
|
+
"@playwright/test": "^1.57.0",
|
|
61
|
+
"chalk": "^5.6.2",
|
|
62
|
+
"ora": "^9.0.0",
|
|
55
63
|
"ts-node": "^10.9.2"
|
|
56
64
|
}
|
|
57
65
|
}
|