@wdio/browserstack-service 8.10.4 → 8.10.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/insights-handler.d.ts.map +1 -1
- package/build/insights-handler.js +11 -6
- package/build/launcher.d.ts.map +1 -1
- package/build/launcher.js +13 -0
- package/build/performance-tester.d.ts +15 -0
- package/build/performance-tester.d.ts.map +1 -0
- package/build/performance-tester.js +96 -0
- package/build/reporter.d.ts +17 -2
- package/build/reporter.d.ts.map +1 -1
- package/build/reporter.js +177 -31
- package/build/service.d.ts.map +1 -1
- package/build/service.js +13 -0
- package/build/util.d.ts.map +1 -1
- package/build/util.js +7 -5
- package/package.json +4 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"insights-handler.d.ts","sourceRoot":"","sources":["../src/insights-handler.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAgB,UAAU,EAAE,MAAM,aAAa,CAAA;AAC3D,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAGzE,OAAO,KAAK,EAAE,MAAM,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"insights-handler.d.ts","sourceRoot":"","sources":["../src/insights-handler.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAgB,UAAU,EAAE,MAAM,aAAa,CAAA;AAC3D,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAGzE,OAAO,KAAK,EAAE,MAAM,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAA;AAsBzE,cAAM,gBAAgB;IASL,OAAO,CAAC,QAAQ;IAAiF,OAAO,CAAC,UAAU,CAAC;IARjI,OAAO,CAAC,MAAM,CAA+B;IAC7C,OAAO,CAAC,MAAM,CAA+B;IAC7C,OAAO,CAAC,aAAa,CAAc;IACnC,OAAO,CAAC,SAAS,CAA2D;IAC5E,OAAO,CAAC,cAAc,CAAC,CAAQ;IAC/B,OAAO,CAAC,UAAU,CAAC,CAAQ;IAC3B,OAAO,CAAC,oBAAoB,CAAoC;gBAE3C,QAAQ,EAAE,WAAW,CAAC,OAAO,GAAG,WAAW,CAAC,kBAAkB,EAAE,aAAa,CAAC,EAAE,OAAO,EAAU,UAAU,CAAC,oBAAQ;IAezI,YAAY,CAAC,QAAQ,EAAE,MAAM;IAIvB,MAAM;IAiBN,UAAU,CAAE,IAAI,EAAE,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG;IAgB/C,SAAS,CAAE,IAAI,EAAE,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,UAAU;IAoD/D,UAAU,CAAE,IAAI,EAAE,UAAU,CAAC,IAAI;IAYjC,SAAS,CAAE,IAAI,EAAE,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,UAAU;IAYrE;;QAEI;IAEE,cAAc,CAAE,KAAK,EAAE,sBAAsB;IA4B7C,aAAa,CAAE,KAAK,EAAE,sBAAsB;IAI5C,UAAU,CAAE,IAAI,EAAE,UAAU,CAAC,UAAU,EAAE,QAAQ,EAAE,MAAM;IAkBzD,SAAS,CAAE,IAAI,EAAE,UAAU,CAAC,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,YAAY;IA0BzF,aAAa,CACf,WAAW,SAA2C,EACtD,YAAY,SAA4C,GACzD,OAAO,CAAC,OAAO,CAAC;IASb,QAAQ;IAId;;OAEG;IACG,cAAc,CAAE,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,GAAG,gBAAgB,EAAE,IAAI,CAAC,EAAE,UAAU,CAAC,IAAI,GAAG,sBAAsB;IA4DtI,OAAO,CAAC,cAAc;IActB,OAAO,CAAC,YAAY;YAiBN,gBAAgB;YA6EhB,2BAA2B;IAmFzC,OAAO,CAAC,qBAAqB;IAW7B,OAAO,CAAC,aAAa;CAMxB;AAGD,QAAA,MAAM,eAAe,EAAE,OAAO,gBAA0D,CAAA;AACxF,KAAK,eAAe,GAAG,gBAAgB,CAAA;AAEvC,eAAe,eAAe,CAAA"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import { v4 as uuidv4 } from 'uuid';
|
|
3
|
+
import TestReporter from './reporter.js';
|
|
3
4
|
import { frameworkSupportsHook, getCloudProvider, getGitMetaData, getHookType, getScenarioExamples, getUniqueIdentifier, getUniqueIdentifierForCucumber, isBrowserstackSession, isScreenshotCommand, o11yClassErrorHandler, removeAnsiColors, sleep, uploadEventData } from './util.js';
|
|
4
5
|
import RequestQueueHandler from './request-handler.js';
|
|
5
6
|
import { DATA_SCREENSHOT_ENDPOINT, DEFAULT_WAIT_INTERVAL_FOR_PENDING_UPLOADS, DEFAULT_WAIT_TIMEOUT_FOR_PENDING_UPLOADS } from './constants.js';
|
|
@@ -73,9 +74,6 @@ class _InsightsHandler {
|
|
|
73
74
|
};
|
|
74
75
|
}
|
|
75
76
|
await this.sendTestRunEvent(test, 'HookRunFinished', result);
|
|
76
|
-
if (this._framework !== 'mocha') {
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
77
|
const hookType = getHookType(test.title);
|
|
80
78
|
/*
|
|
81
79
|
If any of the `beforeAll`, `beforeEach`, `afterEach` then the tests after the hook won't run in mocha (https://github.com/mochajs/mocha/issues/4392)
|
|
@@ -110,6 +108,9 @@ class _InsightsHandler {
|
|
|
110
108
|
}
|
|
111
109
|
}
|
|
112
110
|
async beforeTest(test) {
|
|
111
|
+
if (this._framework !== 'mocha') {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
113
114
|
const fullTitle = getUniqueIdentifier(test, this._framework);
|
|
114
115
|
this._tests[fullTitle] = {
|
|
115
116
|
uuid: uuidv4(),
|
|
@@ -118,6 +119,9 @@ class _InsightsHandler {
|
|
|
118
119
|
await this.sendTestRunEvent(test, 'TestRunStarted');
|
|
119
120
|
}
|
|
120
121
|
async afterTest(test, result) {
|
|
122
|
+
if (this._framework !== 'mocha') {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
121
125
|
const fullTitle = getUniqueIdentifier(test, this._framework);
|
|
122
126
|
this._tests[fullTitle] = {
|
|
123
127
|
...(this._tests[fullTitle] || {}),
|
|
@@ -215,7 +219,8 @@ class _InsightsHandler {
|
|
|
215
219
|
return;
|
|
216
220
|
}
|
|
217
221
|
const identifier = this.getIdentifier(test);
|
|
218
|
-
|
|
222
|
+
const testMeta = this._tests[identifier] || TestReporter.getTests()[identifier];
|
|
223
|
+
if (!testMeta) {
|
|
219
224
|
return;
|
|
220
225
|
}
|
|
221
226
|
// log screenshot
|
|
@@ -223,7 +228,7 @@ class _InsightsHandler {
|
|
|
223
228
|
await uploadEventData([{
|
|
224
229
|
event_type: 'LogCreated',
|
|
225
230
|
logs: [{
|
|
226
|
-
test_run_uuid:
|
|
231
|
+
test_run_uuid: testMeta.uuid,
|
|
227
232
|
timestamp: new Date().toISOString(),
|
|
228
233
|
message: args.result.value,
|
|
229
234
|
kind: 'TEST_SCREENSHOT'
|
|
@@ -238,7 +243,7 @@ class _InsightsHandler {
|
|
|
238
243
|
const req = this._requestQueueHandler.add({
|
|
239
244
|
event_type: 'LogCreated',
|
|
240
245
|
logs: [{
|
|
241
|
-
test_run_uuid:
|
|
246
|
+
test_run_uuid: testMeta.uuid,
|
|
242
247
|
timestamp: new Date().toISOString(),
|
|
243
248
|
kind: 'HTTP',
|
|
244
249
|
http_response: {
|
package/build/launcher.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"launcher.d.ts","sourceRoot":"","sources":["../src/launcher.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,yBAAyB,MAAM,oBAAoB,CAAA;AAG/D,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"launcher.d.ts","sourceRoot":"","sources":["../src/launcher.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,yBAAyB,MAAM,oBAAoB,CAAA;AAG/D,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAGlE,OAAO,KAAK,EAAE,kBAAkB,EAAE,GAAG,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAavF,KAAK,iBAAiB,GAAG,yBAAyB,CAAC,KAAK,GAAG;IACvD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,EAAE,GAAG,KAAK,IAAI,GAAG,IAAI,CAAC;CAC7C,CAAA;AAED,MAAM,CAAC,OAAO,OAAO,2BAA4B,YAAW,QAAQ,CAAC,eAAe;IAQ5E,OAAO,CAAC,QAAQ;IAEhB,OAAO,CAAC,OAAO;IATnB,iBAAiB,CAAC,EAAE,iBAAiB,CAAA;IACrC,OAAO,CAAC,UAAU,CAAC,CAAQ;IAC3B,OAAO,CAAC,YAAY,CAAC,CAAQ;IAC7B,OAAO,CAAC,SAAS,CAAC,CAAQ;IAC1B,OAAO,CAAC,gBAAgB,CAAC,CAAQ;gBAGrB,QAAQ,EAAE,kBAAkB,GAAG,OAAO,CAAC,UAAU,EACzD,YAAY,EAAE,YAAY,CAAC,gBAAgB,EACnC,OAAO,EAAE,OAAO,CAAC,UAAU;IAyEjC,SAAS,CAAE,MAAM,CAAC,EAAE,OAAO,CAAC,UAAU,EAAE,YAAY,CAAC,EAAE,YAAY,CAAC,kBAAkB;IA0GtF,UAAU;IAsDV,UAAU,CAAC,GAAG,EAAC,GAAG,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAsBrD;;;OAGG;IACG,YAAY,CAAE,SAAS,EAAE,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAyBhE,WAAW,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC,kBAAkB,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAC,MAAM;IAqF3F,sBAAsB,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC,kBAAkB;IAyCrE;;;OAGG;IACH,oBAAoB;IA6BpB,sBAAsB,CAAC,QAAQ,CAAC,EAAC,MAAM,EAAE,SAAS,CAAC,EAAC,MAAM,EAAE,eAAe,CAAC,EAAC,MAAM;CAQtF"}
|
package/build/launcher.js
CHANGED
|
@@ -8,6 +8,7 @@ import { SevereServiceError } from 'webdriverio';
|
|
|
8
8
|
import os from 'node:os';
|
|
9
9
|
import * as BrowserstackLocalLauncher from 'browserstack-local';
|
|
10
10
|
import logger from '@wdio/logger';
|
|
11
|
+
import PerformanceTester from './performance-tester.js';
|
|
11
12
|
import { BSTACK_SERVICE_VERSION, VALID_APP_EXTENSION } from './constants.js';
|
|
12
13
|
import { launchTestSession, shouldAddServiceVersion, stopBuildUpstream, getCiInfo, isBStackSession, } from './util.js';
|
|
13
14
|
import CrashReporter from './crash-reporter.js';
|
|
@@ -75,6 +76,9 @@ export default class BrowserstackLauncherService {
|
|
|
75
76
|
}
|
|
76
77
|
});
|
|
77
78
|
}
|
|
79
|
+
if (process.env.BROWSERSTACK_O11Y_PERF_MEASUREMENT) {
|
|
80
|
+
PerformanceTester.startMonitoring('performance-report-launcher.csv');
|
|
81
|
+
}
|
|
78
82
|
// by default observability will be true unless specified as false
|
|
79
83
|
this._options.testObservability = this._options.testObservability === false ? false : true;
|
|
80
84
|
if (this._options.testObservability
|
|
@@ -192,6 +196,15 @@ export default class BrowserstackLauncherService {
|
|
|
192
196
|
if (process.env.BS_TESTOPS_BUILD_HASHED_ID) {
|
|
193
197
|
console.log(`\nVisit https://observability.browserstack.com/builds/${process.env.BS_TESTOPS_BUILD_HASHED_ID} to view build report, insights, and many more debugging information all at one place!\n`);
|
|
194
198
|
}
|
|
199
|
+
if (process.env.BROWSERSTACK_O11Y_PERF_MEASUREMENT) {
|
|
200
|
+
await PerformanceTester.stopAndGenerate('performance-launcher.html');
|
|
201
|
+
PerformanceTester.calculateTimes(['launchTestSession', 'stopBuildUpstream']);
|
|
202
|
+
if (!process.env.START_TIME) {
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
const duration = (new Date()).getTime() - (new Date(process.env.START_TIME)).getTime();
|
|
206
|
+
log.info(`Total duration is ${duration / 1000} s`);
|
|
207
|
+
}
|
|
195
208
|
}
|
|
196
209
|
if (!this.browserstackLocal || !this.browserstackLocal.isRunning()) {
|
|
197
210
|
return;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { PerformanceObserver } from 'node:perf_hooks';
|
|
3
|
+
export default class PerformanceTester {
|
|
4
|
+
static _observer: PerformanceObserver;
|
|
5
|
+
static _csvWriter: any;
|
|
6
|
+
private static _events;
|
|
7
|
+
static started: boolean;
|
|
8
|
+
static startMonitoring(csvName?: string): void;
|
|
9
|
+
static getPerformance(): import("perf_hooks").Performance;
|
|
10
|
+
static calculateTimes(methods: string[]): number;
|
|
11
|
+
static stopAndGenerate(filename?: string): Promise<void>;
|
|
12
|
+
static generateReport(entries: PerformanceEntry[]): string;
|
|
13
|
+
static generateCSV(entries: PerformanceEntry[]): void;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=performance-tester.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"performance-tester.d.ts","sourceRoot":"","sources":["../src/performance-tester.ts"],"names":[],"mappings":";AAEA,OAAO,EAAe,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AAMlE,MAAM,CAAC,OAAO,OAAO,iBAAiB;IAClC,MAAM,CAAC,SAAS,EAAE,mBAAmB,CAAA;IACrC,MAAM,CAAC,UAAU,EAAE,GAAG,CAAA;IACtB,OAAO,CAAC,MAAM,CAAC,OAAO,CAAyB;IAC/C,MAAM,CAAC,OAAO,UAAQ;IAEtB,MAAM,CAAC,eAAe,CAAC,OAAO,GAAE,MAAiC;IAiBjE,MAAM,CAAC,cAAc;IAIrB,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,GAAI,MAAM;WAepC,eAAe,CAAC,QAAQ,GAAE,MAA+B;IAoBtE,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,gBAAgB,EAAE;IAWjD,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,gBAAgB,EAAE;CAuBjD"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { createObjectCsvWriter } from 'csv-writer';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import { performance, PerformanceObserver } from 'node:perf_hooks';
|
|
4
|
+
import logger from '@wdio/logger';
|
|
5
|
+
import { sleep } from './util.js';
|
|
6
|
+
const log = logger('@wdio/browserstack-service');
|
|
7
|
+
class PerformanceTester {
|
|
8
|
+
static _observer;
|
|
9
|
+
static _csvWriter;
|
|
10
|
+
static _events = [];
|
|
11
|
+
static started = false;
|
|
12
|
+
static startMonitoring(csvName = 'performance-report.csv') {
|
|
13
|
+
this._observer = new PerformanceObserver(list => {
|
|
14
|
+
list.getEntries().forEach(entry => {
|
|
15
|
+
this._events.push(entry);
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
this._observer.observe({ buffered: true, entryTypes: ['function'] });
|
|
19
|
+
this.started = true;
|
|
20
|
+
this._csvWriter = createObjectCsvWriter({
|
|
21
|
+
path: csvName,
|
|
22
|
+
header: [
|
|
23
|
+
{ id: 'name', title: 'Function Name' },
|
|
24
|
+
{ id: 'time', title: 'Execution Time (ms)' }
|
|
25
|
+
]
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
static getPerformance() {
|
|
29
|
+
return performance;
|
|
30
|
+
}
|
|
31
|
+
static calculateTimes(methods) {
|
|
32
|
+
const times = {};
|
|
33
|
+
this._events.map((entry) => {
|
|
34
|
+
if (!times[entry.name]) {
|
|
35
|
+
times[entry.name] = 0;
|
|
36
|
+
}
|
|
37
|
+
times[entry.name] += entry.duration;
|
|
38
|
+
});
|
|
39
|
+
const timeTaken = methods.reduce((a, c) => {
|
|
40
|
+
return times[c] + (a || 0);
|
|
41
|
+
}, 0);
|
|
42
|
+
log.info(`Time for ${methods} is `, timeTaken);
|
|
43
|
+
return timeTaken;
|
|
44
|
+
}
|
|
45
|
+
static async stopAndGenerate(filename = 'performance-own.html') {
|
|
46
|
+
if (!this.started) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
await sleep(2000); // Wait to 2s just to finish any running callbacks for timerify
|
|
50
|
+
this._observer.disconnect();
|
|
51
|
+
this.started = false;
|
|
52
|
+
this.generateCSV(this._events);
|
|
53
|
+
const content = this.generateReport(this._events);
|
|
54
|
+
const path = process.cwd() + '/' + filename;
|
|
55
|
+
fs.writeFile(path, content, err => {
|
|
56
|
+
if (err) {
|
|
57
|
+
log.error('Error in writing html', err);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
log.info('Performance report is at ', path);
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
static generateReport(entries) {
|
|
64
|
+
let html = '<!DOCTYPE html><html><head><title>Performance Report</title></head><body>';
|
|
65
|
+
html += '<h1>Performance Report</h1>';
|
|
66
|
+
html += '<table><thead><tr><th>Function Name</th><th>Duration (ms)</th></tr></thead><tbody>';
|
|
67
|
+
entries.forEach((entry) => {
|
|
68
|
+
html += `<tr><td>${entry.name}</td><td>${entry.duration}</td></tr>`;
|
|
69
|
+
});
|
|
70
|
+
html += '</tbody></table></body></html>';
|
|
71
|
+
return html;
|
|
72
|
+
}
|
|
73
|
+
static generateCSV(entries) {
|
|
74
|
+
const times = {};
|
|
75
|
+
entries.map((entry) => {
|
|
76
|
+
if (!times[entry.name]) {
|
|
77
|
+
times[entry.name] = 0;
|
|
78
|
+
}
|
|
79
|
+
times[entry.name] += entry.duration;
|
|
80
|
+
return {
|
|
81
|
+
name: entry.name,
|
|
82
|
+
time: entry.duration
|
|
83
|
+
};
|
|
84
|
+
});
|
|
85
|
+
const dat = Object.entries(times).map(([key, value]) => {
|
|
86
|
+
return {
|
|
87
|
+
name: key,
|
|
88
|
+
time: value
|
|
89
|
+
};
|
|
90
|
+
});
|
|
91
|
+
this._csvWriter.writeRecords(dat)
|
|
92
|
+
.then(() => log.info('Performance CSV report generated successfully'))
|
|
93
|
+
.catch((error) => console.error(error));
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
export default PerformanceTester;
|
package/build/reporter.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type { SuiteStats, TestStats, RunnerStats } from '@wdio/reporter';
|
|
1
|
+
import type { SuiteStats, TestStats, RunnerStats, HookStats } from '@wdio/reporter';
|
|
2
2
|
import WDIOReporter from '@wdio/reporter';
|
|
3
|
+
import type { TestMeta } from './types.js';
|
|
3
4
|
declare class _TestReporter extends WDIOReporter {
|
|
4
5
|
private _capabilities;
|
|
5
6
|
private _config?;
|
|
@@ -7,9 +8,23 @@ declare class _TestReporter extends WDIOReporter {
|
|
|
7
8
|
private _sessionId?;
|
|
8
9
|
private _suiteName?;
|
|
9
10
|
private _requestQueueHandler;
|
|
10
|
-
|
|
11
|
+
private _suites;
|
|
12
|
+
private static _tests;
|
|
13
|
+
private _gitConfigPath?;
|
|
14
|
+
private _gitConfigured;
|
|
15
|
+
onRunnerStart(runnerStats: RunnerStats): Promise<void>;
|
|
16
|
+
configureGit(): Promise<void>;
|
|
17
|
+
static getTests(): Record<string, TestMeta>;
|
|
11
18
|
onSuiteStart(suiteStats: SuiteStats): void;
|
|
19
|
+
onSuiteEnd(): void;
|
|
20
|
+
needToSendData(testType?: string, event?: string): boolean;
|
|
21
|
+
onTestEnd(testStats: TestStats): Promise<void>;
|
|
22
|
+
onTestStart(testStats: TestStats): Promise<void>;
|
|
23
|
+
onHookStart(hookStats: HookStats): Promise<void>;
|
|
24
|
+
onHookEnd(hookStats: HookStats): Promise<void>;
|
|
25
|
+
getHookIdentifier(hookStats: HookStats): string;
|
|
12
26
|
onTestSkip(testStats: TestStats): Promise<void>;
|
|
27
|
+
sendTestRunEvent(testStats: TestStats | HookStats, eventType: string): Promise<void>;
|
|
13
28
|
}
|
|
14
29
|
declare const TestReporter: typeof _TestReporter;
|
|
15
30
|
type TestReporter = _TestReporter;
|
package/build/reporter.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reporter.d.ts","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"reporter.d.ts","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AACnF,OAAO,YAAY,MAAM,gBAAgB,CAAA;AAMzC,OAAO,KAAK,EAAgC,QAAQ,EAAc,MAAM,YAAY,CAAA;AAapF,cAAM,aAAc,SAAQ,YAAY;IACpC,OAAO,CAAC,aAAa,CAAgC;IACrD,OAAO,CAAC,OAAO,CAAC,CAAyC;IACzD,OAAO,CAAC,cAAc,CAAO;IAC7B,OAAO,CAAC,UAAU,CAAC,CAAQ;IAC3B,OAAO,CAAC,UAAU,CAAC,CAAQ;IAC3B,OAAO,CAAC,oBAAoB,CAAoC;IAChE,OAAO,CAAC,OAAO,CAAmB;IAClC,OAAO,CAAC,MAAM,CAAC,MAAM,CAA+B;IACpD,OAAO,CAAC,cAAc,CAAC,CAAQ;IAC/B,OAAO,CAAC,cAAc,CAAiB;IAEjC,aAAa,CAAE,WAAW,EAAE,WAAW;IAUvC,YAAY;IAWlB,MAAM,CAAC,QAAQ;IAIf,YAAY,CAAE,UAAU,EAAE,UAAU;IAoBpC,UAAU;IAIV,cAAc,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM;IAe1C,SAAS,CAAC,SAAS,EAAE,SAAS;IAY9B,WAAW,CAAC,SAAS,EAAE,SAAS;IAchC,WAAW,CAAC,SAAS,EAAE,SAAS;IAchC,SAAS,CAAC,SAAS,EAAE,SAAS;IAepC,iBAAiB,CAAC,SAAS,EAAE,SAAS;IAIhC,UAAU,CAAE,SAAS,EAAE,SAAS;IAWhC,gBAAgB,CAAC,SAAS,EAAE,SAAS,GAAG,SAAS,EAAE,SAAS,EAAE,MAAM;CA+E7E;AAED,QAAA,MAAM,YAAY,EAAE,OAAO,aAAoD,CAAA;AAC/E,KAAK,YAAY,GAAG,aAAa,CAAA;AACjC,eAAe,YAAY,CAAA"}
|
package/build/reporter.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
+
import logger from '@wdio/logger';
|
|
2
3
|
import WDIOReporter from '@wdio/reporter';
|
|
4
|
+
import * as url from 'node:url';
|
|
3
5
|
import { v4 as uuidv4 } from 'uuid';
|
|
4
|
-
import { getCloudProvider, uploadEventData,
|
|
6
|
+
import { getCloudProvider, uploadEventData, o11yClassErrorHandler, getGitMetaData, removeAnsiColors, getHookType } from './util.js';
|
|
5
7
|
import RequestQueueHandler from './request-handler.js';
|
|
8
|
+
const log = logger('@wdio/browserstack-service');
|
|
6
9
|
class _TestReporter extends WDIOReporter {
|
|
7
10
|
_capabilities = {};
|
|
8
11
|
_config;
|
|
@@ -10,43 +13,165 @@ class _TestReporter extends WDIOReporter {
|
|
|
10
13
|
_sessionId;
|
|
11
14
|
_suiteName;
|
|
12
15
|
_requestQueueHandler = RequestQueueHandler.getInstance();
|
|
13
|
-
|
|
16
|
+
_suites = [];
|
|
17
|
+
static _tests = {};
|
|
18
|
+
_gitConfigPath;
|
|
19
|
+
_gitConfigured = false;
|
|
20
|
+
async onRunnerStart(runnerStats) {
|
|
14
21
|
this._capabilities = runnerStats.capabilities;
|
|
15
22
|
this._config = runnerStats.config;
|
|
16
23
|
this._sessionId = runnerStats.sessionId;
|
|
17
24
|
if (typeof this._config.testObservability !== 'undefined') {
|
|
18
25
|
this._observability = this._config.testObservability;
|
|
19
26
|
}
|
|
27
|
+
await this.configureGit();
|
|
28
|
+
}
|
|
29
|
+
async configureGit() {
|
|
30
|
+
if (this._gitConfigured) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const gitMeta = await getGitMetaData();
|
|
34
|
+
if (gitMeta) {
|
|
35
|
+
this._gitConfigPath = gitMeta.root;
|
|
36
|
+
}
|
|
37
|
+
this._gitConfigured = true;
|
|
38
|
+
}
|
|
39
|
+
static getTests() {
|
|
40
|
+
return _TestReporter._tests;
|
|
20
41
|
}
|
|
21
42
|
onSuiteStart(suiteStats) {
|
|
22
|
-
|
|
43
|
+
let filename = suiteStats.file;
|
|
44
|
+
if (this._config?.framework === 'jasmine') {
|
|
45
|
+
try {
|
|
46
|
+
if (suiteStats.file.startsWith('file://')) {
|
|
47
|
+
filename = url.fileURLToPath(suiteStats.file);
|
|
48
|
+
}
|
|
49
|
+
if (filename === 'unknown spec file') {
|
|
50
|
+
// Sometimes in cases where a file has two suites. Then the file name be unknown for second suite, so getting the filename from first suite
|
|
51
|
+
filename = this._suiteName || suiteStats.file;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
catch (e) {
|
|
55
|
+
log.debug('Error in decoding file name of suite');
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
this._suiteName = filename;
|
|
59
|
+
this._suites.push(suiteStats);
|
|
60
|
+
}
|
|
61
|
+
onSuiteEnd() {
|
|
62
|
+
this._suites.pop();
|
|
63
|
+
}
|
|
64
|
+
needToSendData(testType, event) {
|
|
65
|
+
if (!this._observability) {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
switch (this._config?.framework) {
|
|
69
|
+
case 'mocha':
|
|
70
|
+
return event === 'skip';
|
|
71
|
+
case 'cucumber':
|
|
72
|
+
return false;
|
|
73
|
+
case 'jasmine':
|
|
74
|
+
return event !== 'skip';
|
|
75
|
+
default:
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
async onTestEnd(testStats) {
|
|
80
|
+
if (!this.needToSendData('test', 'end')) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
if (testStats.fullTitle === '<unknown test>') {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
testStats.end ||= new Date();
|
|
87
|
+
await this.sendTestRunEvent(testStats, 'TestRunFinished');
|
|
88
|
+
}
|
|
89
|
+
async onTestStart(testStats) {
|
|
90
|
+
if (!this.needToSendData('test', 'start')) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
if (testStats.fullTitle === '<unknown test>') {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
_TestReporter._tests[testStats.fullTitle] = {
|
|
97
|
+
uuid: uuidv4(),
|
|
98
|
+
};
|
|
99
|
+
await this.sendTestRunEvent(testStats, 'TestRunStarted');
|
|
100
|
+
}
|
|
101
|
+
async onHookStart(hookStats) {
|
|
102
|
+
if (!this.needToSendData('hook', 'start')) {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
const identifier = this.getHookIdentifier(hookStats);
|
|
106
|
+
const hookId = uuidv4();
|
|
107
|
+
_TestReporter._tests[identifier] = {
|
|
108
|
+
uuid: hookId,
|
|
109
|
+
startedAt: (new Date()).toISOString()
|
|
110
|
+
};
|
|
111
|
+
await this.sendTestRunEvent(hookStats, 'HookRunStarted');
|
|
112
|
+
}
|
|
113
|
+
async onHookEnd(hookStats) {
|
|
114
|
+
if (!this.needToSendData('hook', 'end')) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
const identifier = this.getHookIdentifier(hookStats);
|
|
118
|
+
if (_TestReporter._tests[identifier]) {
|
|
119
|
+
_TestReporter._tests[identifier].finishedAt = (new Date()).toISOString();
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
_TestReporter._tests[identifier] = {
|
|
123
|
+
finishedAt: (new Date()).toISOString()
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
await this.sendTestRunEvent(hookStats, 'HookRunFinished');
|
|
127
|
+
}
|
|
128
|
+
getHookIdentifier(hookStats) {
|
|
129
|
+
return `${hookStats.title} for ${this._suites.at(-1)?.title}`;
|
|
23
130
|
}
|
|
24
131
|
async onTestSkip(testStats) {
|
|
25
132
|
// cucumber steps call this method. We don't want step skipped state so skip for cucumber
|
|
133
|
+
if (!this.needToSendData('test', 'skip')) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
testStats.start ||= new Date();
|
|
137
|
+
testStats.end ||= new Date();
|
|
138
|
+
await this.sendTestRunEvent(testStats, 'TestRunSkipped');
|
|
139
|
+
}
|
|
140
|
+
async sendTestRunEvent(testStats, eventType) {
|
|
26
141
|
const framework = this._config?.framework;
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
142
|
+
const scopes = this._suites.map(s => s.title);
|
|
143
|
+
const identifier = testStats.type === 'test' ? testStats.fullTitle : this.getHookIdentifier(testStats);
|
|
144
|
+
const testMetaData = _TestReporter._tests[identifier];
|
|
145
|
+
const scope = testStats.type === 'test' ? testStats.fullTitle : `${this._suites[0].title} - ${testStats.title}`;
|
|
146
|
+
await this.configureGit();
|
|
147
|
+
const testData = {
|
|
148
|
+
uuid: testMetaData ? testMetaData.uuid : uuidv4(),
|
|
149
|
+
type: testStats.type,
|
|
150
|
+
name: testStats.title,
|
|
151
|
+
body: {
|
|
152
|
+
lang: 'webdriverio',
|
|
153
|
+
code: null
|
|
154
|
+
},
|
|
155
|
+
scope: scope,
|
|
156
|
+
scopes: scopes,
|
|
157
|
+
identifier: identifier,
|
|
158
|
+
file_name: this._suiteName ? path.relative(process.cwd(), this._suiteName) : undefined,
|
|
159
|
+
location: this._suiteName ? path.relative(process.cwd(), this._suiteName) : undefined,
|
|
160
|
+
vc_filepath: (this._gitConfigPath && this._suiteName) ? path.relative(this._gitConfigPath, this._suiteName) : undefined,
|
|
161
|
+
started_at: testStats.start && testStats.start.toISOString(),
|
|
162
|
+
finished_at: testStats.end && testStats.end.toISOString(),
|
|
163
|
+
framework: framework,
|
|
164
|
+
duration_in_ms: testStats._duration,
|
|
165
|
+
result: testStats.state,
|
|
166
|
+
};
|
|
167
|
+
if (testStats.type === 'test') {
|
|
168
|
+
testData.retries = { limit: testStats.retries || 0, attempts: testStats.retries || 0 };
|
|
169
|
+
}
|
|
170
|
+
if (eventType.startsWith('TestRun')) {
|
|
171
|
+
/* istanbul ignore next */
|
|
48
172
|
const cloudProvider = getCloudProvider({ options: { hostname: this._config?.hostname } });
|
|
49
173
|
testData.integrations = {};
|
|
174
|
+
/* istanbul ignore next */
|
|
50
175
|
testData.integrations[cloudProvider] = {
|
|
51
176
|
capabilities: this._capabilities,
|
|
52
177
|
session_id: this._sessionId,
|
|
@@ -54,15 +179,36 @@ class _TestReporter extends WDIOReporter {
|
|
|
54
179
|
browser_version: this._capabilities?.browserVersion,
|
|
55
180
|
platform: this._capabilities?.platformName,
|
|
56
181
|
};
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
182
|
+
}
|
|
183
|
+
if (eventType === 'TestRunFinished' || eventType === 'HookRunFinished') {
|
|
184
|
+
const { error } = testStats;
|
|
185
|
+
const failed = testStats.state === 'failed';
|
|
186
|
+
if (failed) {
|
|
187
|
+
testData.result = (error && error.message && error.message.includes('sync skip; aborting execution')) ? 'ignore' : 'failed';
|
|
188
|
+
if (error && testData.result !== 'skipped') {
|
|
189
|
+
testData.failure = [{ backtrace: [removeAnsiColors(error.message)] }]; // add all errors here
|
|
190
|
+
testData.failure_reason = removeAnsiColors(error.message);
|
|
191
|
+
testData.failure_type = error.message === null ? null : error.message.toString().match(/AssertionError/) ? 'AssertionError' : 'UnhandledError'; //verify if this is working
|
|
192
|
+
}
|
|
64
193
|
}
|
|
65
194
|
}
|
|
195
|
+
if (eventType === 'TestRunSkipped') {
|
|
196
|
+
eventType = 'TestRunFinished';
|
|
197
|
+
}
|
|
198
|
+
const uploadData = {
|
|
199
|
+
event_type: eventType,
|
|
200
|
+
};
|
|
201
|
+
if (eventType.match(/HookRun/)) {
|
|
202
|
+
testData.hook_type = testData.name?.toLowerCase() ? getHookType(testData.name.toLowerCase()) : 'undefined';
|
|
203
|
+
uploadData.hook_run = testData;
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
uploadData.test_run = testData;
|
|
207
|
+
}
|
|
208
|
+
const req = this._requestQueueHandler.add(uploadData);
|
|
209
|
+
if (req.proceed && req.data) {
|
|
210
|
+
await uploadEventData(req.data, req.url);
|
|
211
|
+
}
|
|
66
212
|
}
|
|
67
213
|
}
|
|
68
214
|
// https://github.com/microsoft/TypeScript/issues/6543
|
package/build/service.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAU9E,OAAO,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAmB,MAAM,YAAY,CAAA;AACxF,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAA;AAQlF,MAAM,CAAC,OAAO,OAAO,mBAAoB,YAAW,QAAQ,CAAC,eAAe;IAiBpE,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,OAAO;IAjBnB,OAAO,CAAC,eAAe,CAAmD;IAC1E,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,iBAAiB,CAAe;IACxC,OAAO,CAAC,gBAAgB,CAA4D;IACpF,OAAO,CAAC,QAAQ,CAAC,CAAqB;IACtC,OAAO,CAAC,WAAW,CAAC,CAAQ;IAC5B,OAAO,CAAC,UAAU,CAAC,CAAQ;IAC3B,OAAO,CAAC,UAAU,CAAC,CAAQ;IAC3B,OAAO,CAAC,QAAQ,CAAyC;IACzD,OAAO,CAAC,SAAS,CAAiB;IAClC,OAAO,CAAC,cAAc,CAAA;IACtB,OAAO,CAAC,YAAY,CAAC,CAA0C;IAC/D,OAAO,CAAC,gBAAgB,CAAC,CAAiB;gBAGtC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,UAAU,EACxC,KAAK,EAAE,YAAY,CAAC,gBAAgB,EACpC,OAAO,EAAE,OAAO,CAAC,UAAU;IAqBvC,WAAW,CAAE,EAAE,EAAE,CAAC,IAAI,EAAE,YAAY,CAAC,YAAY,GAAG,YAAY,CAAC,mBAAmB,KAAK,IAAI;IAU7F,aAAa,CAAE,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,cAAc,CAAC;IAgBzD,MAAM,CAAC,IAAI,EAAE,YAAY,CAAC,gBAAgB,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,WAAW,CAAC,OAAO;IA8C/F;;;;;;OAMG;IACG,WAAW,CAAE,KAAK,EAAE,UAAU,CAAC,KAAK;IASpC,UAAU,CAAE,IAAI,EAAE,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG;IAO/C,SAAS,CAAE,IAAI,EAAE,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,UAAU;IAIjF,UAAU,CAAE,IAAI,EAAE,UAAU,CAAC,IAAI;IAoBjC,SAAS,CAAC,IAAI,EAAE,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,CAAC,UAAU;IAS/E,KAAK,CAAE,MAAM,EAAE,MAAM;IA+B3B;;OAEG;IAEG,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO;IAMjD;;;OAGG;IACG,cAAc,CAAE,KAAK,EAAE,sBAAsB;IAO7C,aAAa,CAAE,KAAK,EAAE,sBAAsB;IAsB5C,UAAU,CAAE,IAAI,EAAE,UAAU,CAAC,UAAU,EAAE,QAAQ,EAAE,MAAM;IAKzD,SAAS,CAAE,IAAI,EAAE,UAAU,CAAC,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,YAAY;IAIzF,QAAQ,CAAC,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM;IAgCzD,cAAc,IAAI,OAAO;IAMzB,UAAU,CAAE,WAAW,EAAE,GAAG;IAU5B,kBAAkB,CAAE,MAAM,EAAE,iBAAiB;IAqB7C,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG;IAarC,gBAAgB;YAuBR,eAAe;IA0B7B,OAAO,CAAC,cAAc;YAIR,eAAe;CAqBhC"}
|
package/build/service.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import logger from '@wdio/logger';
|
|
2
2
|
import got from 'got';
|
|
3
|
+
import PerformanceTester from './performance-tester.js';
|
|
3
4
|
import { getBrowserDescription, getBrowserCapabilities, isBrowserstackCapability, getParentSuiteName, isBrowserstackSession, } from './util.js';
|
|
4
5
|
import InsightsHandler from './insights-handler.js';
|
|
5
6
|
import TestReporter from './reporter.js';
|
|
@@ -31,6 +32,9 @@ export default class BrowserstackService {
|
|
|
31
32
|
this._observability = this._options.testObservability;
|
|
32
33
|
if (this._observability) {
|
|
33
34
|
this._config.reporters?.push(TestReporter);
|
|
35
|
+
if (process.env.BROWSERSTACK_O11Y_PERF_MEASUREMENT) {
|
|
36
|
+
PerformanceTester.startMonitoring('performance-report-service.csv');
|
|
37
|
+
}
|
|
34
38
|
}
|
|
35
39
|
// Cucumber specific
|
|
36
40
|
const strict = Boolean(this._config.cucumberOpts && this._config.cucumberOpts.strict);
|
|
@@ -154,6 +158,15 @@ export default class BrowserstackService {
|
|
|
154
158
|
}
|
|
155
159
|
await this._insightsHandler?.uploadPending();
|
|
156
160
|
await this._insightsHandler?.teardown();
|
|
161
|
+
if (process.env.BROWSERSTACK_O11Y_PERF_MEASUREMENT) {
|
|
162
|
+
await PerformanceTester.stopAndGenerate('performance-service.html');
|
|
163
|
+
PerformanceTester.calculateTimes([
|
|
164
|
+
'onRunnerStart', 'onSuiteStart', 'onSuiteEnd',
|
|
165
|
+
'onTestStart', 'onTestEnd', 'onTestSkip', 'before',
|
|
166
|
+
'beforeHook', 'afterHook', 'beforeTest', 'afterTest',
|
|
167
|
+
'uploadPending', 'teardown', 'browserCommand'
|
|
168
|
+
]);
|
|
169
|
+
}
|
|
157
170
|
}
|
|
158
171
|
/**
|
|
159
172
|
* For CucumberJS
|
package/build/util.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":";;AAEA,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,KAAK,MAAM,YAAY,CAAA;AAI9B,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AACpE,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"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"}
|
package/build/util.js
CHANGED
|
@@ -8,6 +8,7 @@ import logger from '@wdio/logger';
|
|
|
8
8
|
import got, { HTTPError } from 'got';
|
|
9
9
|
import gitRepoInfo from 'git-repo-info';
|
|
10
10
|
import gitconfig from 'gitconfiglocal';
|
|
11
|
+
import PerformanceTester from './performance-tester.js';
|
|
11
12
|
import { BROWSER_DESCRIPTION, DATA_ENDPOINT, DATA_EVENT_ENDPOINT, DATA_SCREENSHOT_ENDPOINT } from './constants.js';
|
|
12
13
|
import RequestQueueHandler from './request-handler.js';
|
|
13
14
|
import CrashReporter from './crash-reporter.js';
|
|
@@ -92,7 +93,11 @@ function processError(error, fn, args) {
|
|
|
92
93
|
export function o11yErrorHandler(fn) {
|
|
93
94
|
return function (...args) {
|
|
94
95
|
try {
|
|
95
|
-
|
|
96
|
+
let functionToHandle = fn;
|
|
97
|
+
if (process.env.BROWSERSTACK_O11Y_PERF_MEASUREMENT) {
|
|
98
|
+
functionToHandle = PerformanceTester.getPerformance().timerify(functionToHandle);
|
|
99
|
+
}
|
|
100
|
+
const result = functionToHandle(...args);
|
|
96
101
|
if (result instanceof Promise) {
|
|
97
102
|
return result.catch(error => processError(error, fn, args));
|
|
98
103
|
}
|
|
@@ -116,7 +121,7 @@ export function o11yClassErrorHandler(errorClass) {
|
|
|
116
121
|
writable: true,
|
|
117
122
|
value: function (...args) {
|
|
118
123
|
try {
|
|
119
|
-
const result = method.call(this, ...args);
|
|
124
|
+
const result = (process.env.BROWSERSTACK_O11Y_PERF_MEASUREMENT ? PerformanceTester.getPerformance().timerify(method) : method).call(this, ...args);
|
|
120
125
|
if (result instanceof Promise) {
|
|
121
126
|
return result.catch(error => processError(error, method, args));
|
|
122
127
|
}
|
|
@@ -591,9 +596,6 @@ export function frameworkSupportsHook(hook, framework) {
|
|
|
591
596
|
if (framework === 'mocha' && (hook === 'before' || hook === 'after' || hook === 'beforeEach' || hook === 'afterEach')) {
|
|
592
597
|
return true;
|
|
593
598
|
}
|
|
594
|
-
if (framework === 'jasmine' && (hook === 'beforeEach' || hook === 'afterEach')) {
|
|
595
|
-
return true;
|
|
596
|
-
}
|
|
597
599
|
return false;
|
|
598
600
|
}
|
|
599
601
|
export const sleep = (ms = 100) => new Promise((resolve) => setTimeout(resolve, ms));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wdio/browserstack-service",
|
|
3
|
-
"version": "8.10.
|
|
3
|
+
"version": "8.10.5",
|
|
4
4
|
"description": "WebdriverIO service for better Browserstack integration",
|
|
5
5
|
"author": "Adam Bjerstedt <abjerstedt@gmail.com>",
|
|
6
6
|
"homepage": "https://github.com/webdriverio/webdriverio/tree/main/packages/wdio-browserstack-service",
|
|
@@ -35,12 +35,13 @@
|
|
|
35
35
|
"@wdio/reporter": "8.10.4",
|
|
36
36
|
"@wdio/types": "8.10.4",
|
|
37
37
|
"browserstack-local": "^1.5.1",
|
|
38
|
+
"csv-writer": "^1.6.0",
|
|
38
39
|
"form-data": "^4.0.0",
|
|
39
40
|
"git-repo-info": "^2.1.1",
|
|
40
41
|
"gitconfiglocal": "^2.1.0",
|
|
41
42
|
"got": "^12.1.0",
|
|
42
43
|
"uuid": "^8.3.2",
|
|
43
|
-
"webdriverio": "8.10.
|
|
44
|
+
"webdriverio": "8.10.5"
|
|
44
45
|
},
|
|
45
46
|
"peerDependencies": {
|
|
46
47
|
"@wdio/cli": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"
|
|
@@ -51,5 +52,5 @@
|
|
|
51
52
|
"publishConfig": {
|
|
52
53
|
"access": "public"
|
|
53
54
|
},
|
|
54
|
-
"gitHead": "
|
|
55
|
+
"gitHead": "d031049a102c7ca3ce6d4d26c8561c6cc71d6ac9"
|
|
55
56
|
}
|