@wdio/browserstack-service 7.35.0 → 7.36.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/build/bstackLogger.d.ts +14 -0
- package/build/bstackLogger.d.ts.map +1 -0
- package/build/bstackLogger.js +52 -0
- package/build/cleanup.d.ts +6 -2
- package/build/cleanup.d.ts.map +1 -1
- package/build/cleanup.js +104 -12
- package/build/config.d.ts +23 -0
- package/build/config.d.ts.map +1 -0
- package/build/config.js +32 -0
- package/build/constants.d.ts +17 -0
- package/build/constants.d.ts.map +1 -1
- package/build/constants.js +34 -1
- package/build/crash-reporter.js +1 -1
- package/build/data-store.d.ts +3 -0
- package/build/data-store.d.ts.map +1 -0
- package/build/data-store.js +49 -0
- package/build/exitHandler.d.ts +4 -0
- package/build/exitHandler.d.ts.map +1 -0
- package/build/exitHandler.js +37 -0
- package/build/insights-handler.d.ts +5 -11
- package/build/insights-handler.d.ts.map +1 -1
- package/build/insights-handler.js +45 -106
- package/build/instrumentation/funnelInstrumentation.d.ts +6 -0
- package/build/instrumentation/funnelInstrumentation.d.ts.map +1 -0
- package/build/instrumentation/funnelInstrumentation.js +127 -0
- package/build/launcher.d.ts +1 -2
- package/build/launcher.d.ts.map +1 -1
- package/build/launcher.js +21 -20
- package/build/reporter.d.ts +3 -3
- package/build/reporter.d.ts.map +1 -1
- package/build/reporter.js +10 -23
- package/build/request-handler.d.ts +5 -13
- package/build/request-handler.d.ts.map +1 -1
- package/build/request-handler.js +27 -48
- package/build/service.d.ts +1 -0
- package/build/service.d.ts.map +1 -1
- package/build/service.js +14 -6
- package/build/testOps/featureStats.d.ts +45 -0
- package/build/testOps/featureStats.d.ts.map +1 -0
- package/build/testOps/featureStats.js +120 -0
- package/build/testOps/featureUsage.d.ts +22 -0
- package/build/testOps/featureUsage.d.ts.map +1 -0
- package/build/testOps/featureUsage.js +46 -0
- package/build/testOps/listener.d.ts +33 -0
- package/build/testOps/listener.d.ts.map +1 -0
- package/build/testOps/listener.js +228 -0
- package/build/testOps/requestUtils.d.ts +4 -0
- package/build/testOps/requestUtils.d.ts.map +1 -0
- package/build/testOps/requestUtils.js +47 -0
- package/build/testOps/testOpsConfig.d.ts +11 -0
- package/build/testOps/testOpsConfig.d.ts.map +1 -0
- package/build/testOps/testOpsConfig.js +17 -0
- package/build/testOps/usageStats.d.ts +404 -0
- package/build/testOps/usageStats.d.ts.map +1 -0
- package/build/testOps/usageStats.js +110 -0
- package/build/types.d.ts +33 -7
- package/build/types.d.ts.map +1 -1
- package/build/util.d.ts +2 -6
- package/build/util.d.ts.map +1 -1
- package/build/util.js +60 -66
- package/package.json +3 -3
|
@@ -8,7 +8,7 @@ const logger_1 = __importDefault(require("@wdio/logger"));
|
|
|
8
8
|
const uuid_1 = require("uuid");
|
|
9
9
|
const reporter_1 = __importDefault(require("./reporter"));
|
|
10
10
|
const util_1 = require("./util");
|
|
11
|
-
const
|
|
11
|
+
const listener_1 = __importDefault(require("./testOps/listener"));
|
|
12
12
|
const constants_1 = require("./constants");
|
|
13
13
|
const log = (0, logger_1.default)('@wdio/browserstack-service');
|
|
14
14
|
class _InsightsHandler {
|
|
@@ -18,7 +18,6 @@ class _InsightsHandler {
|
|
|
18
18
|
this._tests = {};
|
|
19
19
|
this._hooks = {};
|
|
20
20
|
this._commands = {};
|
|
21
|
-
this._requestQueueHandler = request_handler_1.default.getInstance();
|
|
22
21
|
this._currentTest = {};
|
|
23
22
|
this._currentHook = {};
|
|
24
23
|
this._cucumberData = {
|
|
@@ -26,6 +25,7 @@ class _InsightsHandler {
|
|
|
26
25
|
scenariosStarted: false,
|
|
27
26
|
steps: []
|
|
28
27
|
};
|
|
28
|
+
this.listener = listener_1.default.getInstance();
|
|
29
29
|
this.appendTestItemLog = async (stdLog) => {
|
|
30
30
|
try {
|
|
31
31
|
if (this._currentHook.uuid && !this._currentHook.finished && (this._framework === 'mocha' || this._framework === 'cucumber')) {
|
|
@@ -35,17 +35,13 @@ class _InsightsHandler {
|
|
|
35
35
|
stdLog.test_run_uuid = this._currentTest.uuid;
|
|
36
36
|
}
|
|
37
37
|
if (stdLog.hook_run_uuid || stdLog.test_run_uuid) {
|
|
38
|
-
|
|
39
|
-
event_type: 'LogCreated',
|
|
40
|
-
logs: [stdLog]
|
|
41
|
-
});
|
|
38
|
+
this.listener.logCreated([stdLog]);
|
|
42
39
|
}
|
|
43
40
|
}
|
|
44
41
|
catch (error) {
|
|
45
42
|
log.debug(`Exception in uploading log data to Observability with error : ${error}`);
|
|
46
43
|
}
|
|
47
44
|
};
|
|
48
|
-
this._requestQueueHandler.start();
|
|
49
45
|
this._platformMeta = {
|
|
50
46
|
browserName: browserCaps === null || browserCaps === void 0 ? void 0 : browserCaps.browserName,
|
|
51
47
|
browserVersion: browserCaps === null || browserCaps === void 0 ? void 0 : browserCaps.browserVersion,
|
|
@@ -90,7 +86,7 @@ class _InsightsHandler {
|
|
|
90
86
|
};
|
|
91
87
|
this.setCurrentHook({ uuid: hookUUID });
|
|
92
88
|
this.attachHookData(context, hookUUID);
|
|
93
|
-
|
|
89
|
+
this.listener.hookStarted(this.getRunData(test, 'HookRunStarted'));
|
|
94
90
|
}
|
|
95
91
|
async afterHook(test, result) {
|
|
96
92
|
if (!(0, util_1.frameworkSupportsHook)('after', this._framework)) {
|
|
@@ -111,7 +107,7 @@ class _InsightsHandler {
|
|
|
111
107
|
};
|
|
112
108
|
}
|
|
113
109
|
this.setCurrentHook({ uuid: this._tests[fullTitle].uuid, finished: true });
|
|
114
|
-
|
|
110
|
+
this.listener.hookFinished(this.getRunData(test, 'HookRunFinished', result));
|
|
115
111
|
const hookType = (0, util_1.getHookType)(test.title);
|
|
116
112
|
/*
|
|
117
113
|
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)
|
|
@@ -128,7 +124,7 @@ class _InsightsHandler {
|
|
|
128
124
|
startedAt: (new Date()).toISOString(),
|
|
129
125
|
finishedAt: (new Date()).toISOString()
|
|
130
126
|
};
|
|
131
|
-
|
|
127
|
+
this.listener.testFinished(this.getRunData(skippedTest, 'TestRunSkipped'));
|
|
132
128
|
}
|
|
133
129
|
};
|
|
134
130
|
/*
|
|
@@ -157,7 +153,7 @@ class _InsightsHandler {
|
|
|
157
153
|
uuid: uuid,
|
|
158
154
|
startedAt: (new Date()).toISOString()
|
|
159
155
|
};
|
|
160
|
-
|
|
156
|
+
this.listener.testStarted(this.getRunData(test, 'TestRunStarted'));
|
|
161
157
|
}
|
|
162
158
|
async afterTest(test, result) {
|
|
163
159
|
if (this._framework !== 'mocha')
|
|
@@ -167,7 +163,7 @@ class _InsightsHandler {
|
|
|
167
163
|
...(this._tests[fullTitle] || {}),
|
|
168
164
|
finishedAt: (new Date()).toISOString()
|
|
169
165
|
};
|
|
170
|
-
|
|
166
|
+
this.listener.testFinished(this.getRunData(test, 'TestRunFinished', result));
|
|
171
167
|
}
|
|
172
168
|
/**
|
|
173
169
|
* Cucumber Only
|
|
@@ -206,11 +202,11 @@ class _InsightsHandler {
|
|
|
206
202
|
};
|
|
207
203
|
}
|
|
208
204
|
this._tests[uniqueId] = testMetaData;
|
|
209
|
-
|
|
205
|
+
this.listener.testStarted(this.getTestRunDataForCucumber(world, 'TestRunStarted'));
|
|
210
206
|
}
|
|
211
207
|
async afterScenario(world) {
|
|
212
208
|
this._cucumberData.scenario = undefined;
|
|
213
|
-
|
|
209
|
+
this.listener.testFinished(this.getTestRunDataForCucumber(world, 'TestRunFinished'));
|
|
214
210
|
}
|
|
215
211
|
async beforeStep(step, scenario) {
|
|
216
212
|
var _a;
|
|
@@ -286,7 +282,7 @@ class _InsightsHandler {
|
|
|
286
282
|
};
|
|
287
283
|
}),
|
|
288
284
|
};
|
|
289
|
-
|
|
285
|
+
this.listener.testFinished(this.getTestRunDataForCucumber(null, 'TestRunSkipped', testMetaData));
|
|
290
286
|
}
|
|
291
287
|
async processCucumberHook(test, params, result) {
|
|
292
288
|
const hookType = this.getCucumberHookType(test);
|
|
@@ -307,12 +303,12 @@ class _InsightsHandler {
|
|
|
307
303
|
hookType: hookType
|
|
308
304
|
};
|
|
309
305
|
this._tests[hookId] = hookMetaData;
|
|
310
|
-
|
|
306
|
+
this.listener.hookStarted(this.getHookRunDataForCucumber(hookMetaData, 'HookRunStarted'));
|
|
311
307
|
}
|
|
312
308
|
else {
|
|
313
309
|
this._tests[hookId].finishedAt = (new Date()).toISOString();
|
|
314
310
|
this.setCurrentHook({ uuid: this._tests[hookId].uuid, finished: true });
|
|
315
|
-
|
|
311
|
+
this.listener.hookFinished(this.getHookRunDataForCucumber(this._tests[hookId], 'HookRunFinished', result));
|
|
316
312
|
if (hookType === 'BEFORE_ALL' && result && !result.passed) {
|
|
317
313
|
const { feature, uri } = this._cucumberData;
|
|
318
314
|
if (!feature) {
|
|
@@ -333,21 +329,6 @@ class _InsightsHandler {
|
|
|
333
329
|
}
|
|
334
330
|
}
|
|
335
331
|
}
|
|
336
|
-
//@ts-ignore
|
|
337
|
-
async uploadPending(waitTimeout = constants_1.DEFAULT_WAIT_TIMEOUT_FOR_PENDING_UPLOADS, waitInterval = constants_1.DEFAULT_WAIT_INTERVAL_FOR_PENDING_UPLOADS) {
|
|
338
|
-
if (this._requestQueueHandler.pendingUploads <= 0 || waitTimeout <= 0) {
|
|
339
|
-
return;
|
|
340
|
-
}
|
|
341
|
-
await (0, util_1.sleep)(waitInterval);
|
|
342
|
-
return this.uploadPending(waitTimeout - waitInterval);
|
|
343
|
-
}
|
|
344
|
-
async teardown() {
|
|
345
|
-
this._requestQueueHandler.tearDownInvoked = true;
|
|
346
|
-
await this._requestQueueHandler.shutdown();
|
|
347
|
-
}
|
|
348
|
-
/**
|
|
349
|
-
* misc methods
|
|
350
|
-
*/
|
|
351
332
|
async browserCommand(commandType, args, test) {
|
|
352
333
|
if (commandType === 'client:beforeCommand') {
|
|
353
334
|
this._commands[`${args.sessionId}_${args.method}_${args.endpoint}`] = args;
|
|
@@ -362,16 +343,13 @@ class _InsightsHandler {
|
|
|
362
343
|
return;
|
|
363
344
|
}
|
|
364
345
|
// log screenshot
|
|
365
|
-
if (Boolean(process.env.
|
|
366
|
-
await
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
kind: 'TEST_SCREENSHOT'
|
|
373
|
-
}]
|
|
374
|
-
}], constants_1.DATA_SCREENSHOT_ENDPOINT);
|
|
346
|
+
if (Boolean(process.env[constants_1.TESTOPS_SCREENSHOT_ENV]) && (0, util_1.isScreenshotCommand)(args) && args.result.value) {
|
|
347
|
+
await this.listener.onScreenshot([{
|
|
348
|
+
test_run_uuid: testMeta.uuid,
|
|
349
|
+
timestamp: new Date().toISOString(),
|
|
350
|
+
message: args.result.value,
|
|
351
|
+
kind: 'TEST_SCREENSHOT'
|
|
352
|
+
}]);
|
|
375
353
|
}
|
|
376
354
|
const dataKey = `${args.sessionId}_${args.method}_${args.endpoint}`;
|
|
377
355
|
const requestData = this._commands[dataKey];
|
|
@@ -379,32 +357,17 @@ class _InsightsHandler {
|
|
|
379
357
|
return;
|
|
380
358
|
}
|
|
381
359
|
// log http request
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
}
|
|
394
|
-
}]
|
|
395
|
-
});
|
|
396
|
-
if (req.proceed && req.data) {
|
|
397
|
-
await (0, util_1.uploadEventData)(req.data, req.url);
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
/*
|
|
401
|
-
* private methods
|
|
402
|
-
*/
|
|
403
|
-
async sendData(data) {
|
|
404
|
-
const req = this._requestQueueHandler.add(data);
|
|
405
|
-
if (req.proceed && req.data) {
|
|
406
|
-
await (0, util_1.uploadEventData)(req.data, req.url);
|
|
407
|
-
}
|
|
360
|
+
this.listener.logCreated([{
|
|
361
|
+
test_run_uuid: testMeta.uuid,
|
|
362
|
+
timestamp: new Date().toISOString(),
|
|
363
|
+
kind: 'HTTP',
|
|
364
|
+
http_response: {
|
|
365
|
+
path: requestData.endpoint,
|
|
366
|
+
method: requestData.method,
|
|
367
|
+
body: requestData.body,
|
|
368
|
+
response: args.result
|
|
369
|
+
}
|
|
370
|
+
}]);
|
|
408
371
|
}
|
|
409
372
|
attachHookData(context, hookId) {
|
|
410
373
|
if (context.currentTest && context.currentTest.parent) {
|
|
@@ -542,7 +505,7 @@ class _InsightsHandler {
|
|
|
542
505
|
}
|
|
543
506
|
return;
|
|
544
507
|
}
|
|
545
|
-
|
|
508
|
+
getRunData(test, eventType, results) {
|
|
546
509
|
var _a;
|
|
547
510
|
const fullTitle = (0, util_1.getUniqueIdentifier)(test, this._framework);
|
|
548
511
|
const testMetaData = this._tests[fullTitle];
|
|
@@ -595,24 +558,14 @@ class _InsightsHandler {
|
|
|
595
558
|
testData.result = 'skipped';
|
|
596
559
|
eventType = 'TestRunFinished';
|
|
597
560
|
}
|
|
598
|
-
const uploadData = {
|
|
599
|
-
event_type: eventType,
|
|
600
|
-
};
|
|
601
561
|
/* istanbul ignore if */
|
|
602
562
|
if (eventType.match(/HookRun/)) {
|
|
603
563
|
testData.hook_type = ((_a = testData.name) === null || _a === void 0 ? void 0 : _a.toLowerCase()) ? (0, util_1.getHookType)(testData.name.toLowerCase()) : 'undefined';
|
|
604
564
|
testData.test_run_id = this.getTestRunId(test.ctx);
|
|
605
|
-
uploadData.hook_run = testData;
|
|
606
|
-
}
|
|
607
|
-
else {
|
|
608
|
-
uploadData.test_run = testData;
|
|
609
|
-
}
|
|
610
|
-
const req = this._requestQueueHandler.add(uploadData);
|
|
611
|
-
if (req.proceed && req.data) {
|
|
612
|
-
await (0, util_1.uploadEventData)(req.data, req.url);
|
|
613
565
|
}
|
|
566
|
+
return testData;
|
|
614
567
|
}
|
|
615
|
-
|
|
568
|
+
getTestRunDataForCucumber(worldObj, eventType, testMetaData = null) {
|
|
616
569
|
const world = worldObj;
|
|
617
570
|
const dataHub = testMetaData ? testMetaData : (this._tests[(0, util_1.getUniqueIdentifierForCucumber)(world)] || {});
|
|
618
571
|
const { feature, scenario, steps, uuid, startedAt, finishedAt } = dataHub;
|
|
@@ -686,18 +639,10 @@ class _InsightsHandler {
|
|
|
686
639
|
}
|
|
687
640
|
if (eventType === 'TestRunSkipped') {
|
|
688
641
|
testData.result = 'skipped';
|
|
689
|
-
eventType = 'TestRunFinished';
|
|
690
|
-
}
|
|
691
|
-
const uploadData = {
|
|
692
|
-
event_type: eventType,
|
|
693
|
-
test_run: testData
|
|
694
|
-
};
|
|
695
|
-
const req = this._requestQueueHandler.add(uploadData);
|
|
696
|
-
if (req.proceed && req.data) {
|
|
697
|
-
await (0, util_1.uploadEventData)(req.data, req.url);
|
|
698
642
|
}
|
|
643
|
+
return testData;
|
|
699
644
|
}
|
|
700
|
-
|
|
645
|
+
getHookRunDataForCucumber(hookData, eventType, result) {
|
|
701
646
|
const { uri, feature } = this._cucumberData;
|
|
702
647
|
const testData = {
|
|
703
648
|
uuid: hookData.uuid,
|
|
@@ -734,24 +679,18 @@ class _InsightsHandler {
|
|
|
734
679
|
testData.integrations[provider] = this.getIntegrationsObject();
|
|
735
680
|
}
|
|
736
681
|
}
|
|
737
|
-
|
|
738
|
-
event_type: eventType,
|
|
739
|
-
hook_run: testData
|
|
740
|
-
};
|
|
741
|
-
const req = this._requestQueueHandler.add(uploadData);
|
|
742
|
-
if (req.proceed && req.data) {
|
|
743
|
-
await (0, util_1.uploadEventData)(req.data, req.url);
|
|
744
|
-
}
|
|
682
|
+
return testData;
|
|
745
683
|
}
|
|
746
684
|
getIntegrationsObject() {
|
|
747
|
-
var _a, _b
|
|
685
|
+
var _a, _b;
|
|
686
|
+
const browserCaps = this._browser.capabilities;
|
|
748
687
|
return {
|
|
749
|
-
capabilities:
|
|
750
|
-
session_id: (
|
|
751
|
-
browser:
|
|
752
|
-
browser_version:
|
|
753
|
-
platform:
|
|
754
|
-
product: (
|
|
688
|
+
capabilities: browserCaps,
|
|
689
|
+
session_id: (_a = this._browser) === null || _a === void 0 ? void 0 : _a.sessionId,
|
|
690
|
+
browser: browserCaps === null || browserCaps === void 0 ? void 0 : browserCaps.browserName,
|
|
691
|
+
browser_version: browserCaps === null || browserCaps === void 0 ? void 0 : browserCaps.browserVersion,
|
|
692
|
+
platform: browserCaps === null || browserCaps === void 0 ? void 0 : browserCaps.platformName,
|
|
693
|
+
product: (_b = this._platformMeta) === null || _b === void 0 ? void 0 : _b.product
|
|
755
694
|
};
|
|
756
695
|
}
|
|
757
696
|
getIdentifier(test) {
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type BrowserStackConfig from '../config';
|
|
2
|
+
export declare function sendStart(config: BrowserStackConfig): Promise<void>;
|
|
3
|
+
export declare function sendFinish(config: BrowserStackConfig): Promise<void>;
|
|
4
|
+
export declare function saveFunnelData(eventType: string, config: BrowserStackConfig): string;
|
|
5
|
+
export declare function fireFunnelRequest(data: any): Promise<void>;
|
|
6
|
+
//# sourceMappingURL=funnelInstrumentation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"funnelInstrumentation.d.ts","sourceRoot":"","sources":["../../src/instrumentation/funnelInstrumentation.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,kBAAkB,MAAM,WAAW,CAAA;AAsB/C,wBAAsB,SAAS,CAAC,MAAM,EAAE,kBAAkB,iBAEzD;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,kBAAkB,iBAE1D;AAED,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,GAAG,MAAM,CAOpF;AAGD,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAOhE"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.fireFunnelRequest = exports.saveFunnelData = exports.sendFinish = exports.sendStart = void 0;
|
|
7
|
+
const node_os_1 = __importDefault(require("node:os"));
|
|
8
|
+
const node_util_1 = __importDefault(require("node:util"));
|
|
9
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
10
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
11
|
+
const got_1 = __importDefault(require("got"));
|
|
12
|
+
const usageStats_1 = __importDefault(require("../testOps/usageStats"));
|
|
13
|
+
const bstackLogger_1 = require("../bstackLogger");
|
|
14
|
+
const constants_1 = require("../constants");
|
|
15
|
+
const data_store_1 = require("../data-store");
|
|
16
|
+
async function fireFunnelTestEvent(eventType, config) {
|
|
17
|
+
if (!config.userName || !config.accessKey) {
|
|
18
|
+
bstackLogger_1.BStackLogger.debug('username/accesskey not passed');
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
try {
|
|
22
|
+
const data = buildEventData(eventType, config);
|
|
23
|
+
await fireFunnelRequest(data);
|
|
24
|
+
bstackLogger_1.BStackLogger.debug('Funnel event success');
|
|
25
|
+
if (eventType === 'SDKTestSuccessful') {
|
|
26
|
+
config.sentFunnelData();
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
bstackLogger_1.BStackLogger.debug('Exception in sending funnel data: ' + error);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
async function sendStart(config) {
|
|
34
|
+
await fireFunnelTestEvent('SDKTestAttempted', config);
|
|
35
|
+
}
|
|
36
|
+
exports.sendStart = sendStart;
|
|
37
|
+
async function sendFinish(config) {
|
|
38
|
+
await fireFunnelTestEvent('SDKTestSuccessful', config);
|
|
39
|
+
}
|
|
40
|
+
exports.sendFinish = sendFinish;
|
|
41
|
+
function saveFunnelData(eventType, config) {
|
|
42
|
+
const data = buildEventData(eventType, config);
|
|
43
|
+
bstackLogger_1.BStackLogger.ensureLogsFolder();
|
|
44
|
+
const filePath = node_path_1.default.join(bstackLogger_1.BStackLogger.logFolderPath, 'funnelData.json');
|
|
45
|
+
node_fs_1.default.writeFileSync(filePath, JSON.stringify(data));
|
|
46
|
+
return filePath;
|
|
47
|
+
}
|
|
48
|
+
exports.saveFunnelData = saveFunnelData;
|
|
49
|
+
// Called from two different process
|
|
50
|
+
async function fireFunnelRequest(data) {
|
|
51
|
+
bstackLogger_1.BStackLogger.debug('Sending SDK event with data ' + node_util_1.default.inspect(data, { depth: 6 }));
|
|
52
|
+
await got_1.default.post(constants_1.FUNNEL_INSTRUMENTATION_URL, {
|
|
53
|
+
headers: {
|
|
54
|
+
'content-type': 'application/json'
|
|
55
|
+
}, username: data.userName, password: data.accessKey, json: data
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
exports.fireFunnelRequest = fireFunnelRequest;
|
|
59
|
+
function getProductList(config) {
|
|
60
|
+
const products = [];
|
|
61
|
+
if (config.testObservability.enabled) {
|
|
62
|
+
products.push('observability');
|
|
63
|
+
}
|
|
64
|
+
if (config.accessibility) {
|
|
65
|
+
products.push('accessibility');
|
|
66
|
+
}
|
|
67
|
+
if (config.percy) {
|
|
68
|
+
products.push('percy');
|
|
69
|
+
}
|
|
70
|
+
if (config.automate) {
|
|
71
|
+
products.push('automate');
|
|
72
|
+
}
|
|
73
|
+
if (config.appAutomate) {
|
|
74
|
+
products.push('app-automate');
|
|
75
|
+
}
|
|
76
|
+
return products;
|
|
77
|
+
}
|
|
78
|
+
function getProductMap(config) {
|
|
79
|
+
return {
|
|
80
|
+
'observability': config.testObservability.enabled,
|
|
81
|
+
'accessibility': config.accessibility,
|
|
82
|
+
'percy': config.percy,
|
|
83
|
+
'automate': config.automate,
|
|
84
|
+
'app_automate': config.appAutomate
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
function buildEventData(eventType, config) {
|
|
88
|
+
const eventProperties = {
|
|
89
|
+
// Framework Details
|
|
90
|
+
language_framework: getLanguageFramework(config.framework),
|
|
91
|
+
referrer: getReferrer(config.framework),
|
|
92
|
+
language: 'WebdriverIO',
|
|
93
|
+
languageVersion: process.version,
|
|
94
|
+
// Build Details
|
|
95
|
+
buildName: config.buildName || 'undefined',
|
|
96
|
+
buildIdentifier: String(config.buildIdentifier),
|
|
97
|
+
// Host details
|
|
98
|
+
os: node_os_1.default.type() || 'unknown',
|
|
99
|
+
hostname: node_os_1.default.hostname() || 'unknown',
|
|
100
|
+
// Product Details
|
|
101
|
+
productMap: getProductMap(config),
|
|
102
|
+
product: getProductList(config),
|
|
103
|
+
};
|
|
104
|
+
if (eventType === 'SDKTestSuccessful') {
|
|
105
|
+
const workerData = (0, data_store_1.getDataFromWorkers)();
|
|
106
|
+
eventProperties.productUsage = getProductUsage(workerData);
|
|
107
|
+
}
|
|
108
|
+
return {
|
|
109
|
+
userName: config.userName,
|
|
110
|
+
accessKey: config.accessKey,
|
|
111
|
+
event_type: eventType,
|
|
112
|
+
detectedFramework: 'WebdriverIO-' + config.framework,
|
|
113
|
+
event_properties: eventProperties
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
function getProductUsage(workersData) {
|
|
117
|
+
return {
|
|
118
|
+
testObservability: usageStats_1.default.getInstance().getFormattedData(workersData)
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
function getLanguageFramework(framework) {
|
|
122
|
+
return 'WebdriverIO_' + framework;
|
|
123
|
+
}
|
|
124
|
+
function getReferrer(framework) {
|
|
125
|
+
const fullName = framework ? 'WebdriverIO-' + framework : 'WebdriverIO';
|
|
126
|
+
return `${fullName}/${constants_1.BSTACK_SERVICE_VERSION}`;
|
|
127
|
+
}
|
package/build/launcher.d.ts
CHANGED
|
@@ -16,10 +16,9 @@ export default class BrowserstackLauncherService implements Services.ServiceInst
|
|
|
16
16
|
private _accessibilityAutomation?;
|
|
17
17
|
private _percy?;
|
|
18
18
|
private _percyBestPlatformCaps?;
|
|
19
|
-
|
|
19
|
+
private readonly browserStackConfig;
|
|
20
20
|
constructor(_options: BrowserstackConfig & Options.Testrunner, capabilities: Capabilities.RemoteCapability, _config: Options.Testrunner);
|
|
21
21
|
onWorkerStart(cid: any, caps: any): Promise<void>;
|
|
22
|
-
setupExitHandlers(): void;
|
|
23
22
|
onPrepare(config?: Options.Testrunner, capabilities?: Capabilities.RemoteCapabilities): Promise<unknown>;
|
|
24
23
|
onComplete(): Promise<unknown>;
|
|
25
24
|
setupPercy(options: BrowserstackConfig & Options.Testrunner, config: Options.Testrunner, bsConfig: UserConfig): Promise<void>;
|
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;AAE/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;AAE/D,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAMlE,OAAO,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AA8BhG,KAAK,iBAAiB,GAAG,yBAAyB,CAAC,KAAK,GAAG;IACvD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI,CAAC;CAC/C,CAAA;AAED,MAAM,CAAC,OAAO,OAAO,2BAA4B,YAAW,QAAQ,CAAC,eAAe;IAY5E,OAAO,CAAC,QAAQ;IAEhB,OAAO,CAAC,OAAO;IAbnB,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;IACjC,OAAO,CAAC,wBAAwB,CAAC,CAAS;IAC1C,OAAO,CAAC,MAAM,CAAC,CAAO;IACtB,OAAO,CAAC,sBAAsB,CAAC,CAAkC;IACjE,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAoB;gBAG3C,QAAQ,EAAE,kBAAkB,GAAG,OAAO,CAAC,UAAU,EACzD,YAAY,EAAE,YAAY,CAAC,gBAAgB,EACnC,OAAO,EAAE,OAAO,CAAC,UAAU;IAsGjC,aAAa,CAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG;IAalC,SAAS,CAAE,MAAM,CAAC,EAAE,OAAO,CAAC,UAAU,EAAE,YAAY,CAAC,EAAE,YAAY,CAAC,kBAAkB;IA2JtF,UAAU;IAqEV,UAAU,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,UAAU,EAAE,QAAQ,EAAE,UAAU;IAuB7G,SAAS;IAYT,UAAU,CAAC,GAAG,EAAC,GAAG,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAqBrD;;;OAGG;IACG,YAAY,CAAE,SAAS,EAAE,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAyBhE,qBAAqB,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC,kBAAkB,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;KAAE;IAiFvH,WAAW,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC,kBAAkB,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAC,MAAM;IAoF3F,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
|
@@ -36,7 +36,6 @@ const os_1 = __importDefault(require("os"));
|
|
|
36
36
|
const webdriverio_1 = require("webdriverio");
|
|
37
37
|
const BrowserstackLocalLauncher = __importStar(require("browserstack-local"));
|
|
38
38
|
const logger_1 = __importDefault(require("@wdio/logger"));
|
|
39
|
-
const node_child_process_1 = require("node:child_process");
|
|
40
39
|
// @ts-ignore
|
|
41
40
|
const package_json_1 = require("../package.json");
|
|
42
41
|
const crash_reporter_1 = __importDefault(require("./crash-reporter"));
|
|
@@ -45,15 +44,19 @@ const constants_1 = require("./constants");
|
|
|
45
44
|
const util_2 = require("./util");
|
|
46
45
|
const performance_tester_1 = __importDefault(require("./performance-tester"));
|
|
47
46
|
const PercyLogger_1 = require("./Percy/PercyLogger");
|
|
47
|
+
const exitHandler_1 = require("./exitHandler");
|
|
48
|
+
const config_1 = __importDefault(require("./config"));
|
|
49
|
+
const funnelInstrumentation_1 = require("./instrumentation/funnelInstrumentation");
|
|
48
50
|
const log = (0, logger_1.default)('@wdio/browserstack-service');
|
|
49
51
|
class BrowserstackLauncherService {
|
|
50
52
|
constructor(_options, capabilities, _config) {
|
|
51
53
|
this._options = _options;
|
|
52
54
|
this._config = _config;
|
|
53
55
|
PercyLogger_1.PercyLogger.clearLogFile();
|
|
56
|
+
(0, exitHandler_1.setupExitHandlers)();
|
|
54
57
|
// added to maintain backward compatibility with webdriverIO v5
|
|
55
|
-
this.setupExitHandlers();
|
|
56
58
|
this._config || (this._config = _options);
|
|
59
|
+
this.browserStackConfig = config_1.default.getInstance(_options, _config);
|
|
57
60
|
if (Array.isArray(capabilities)) {
|
|
58
61
|
capabilities.forEach((capability) => {
|
|
59
62
|
var _a, _b;
|
|
@@ -127,7 +130,9 @@ class BrowserstackLauncherService {
|
|
|
127
130
|
}
|
|
128
131
|
});
|
|
129
132
|
}
|
|
130
|
-
|
|
133
|
+
this.browserStackConfig.buildIdentifier = this._buildIdentifier;
|
|
134
|
+
this.browserStackConfig.buildName = this._buildName;
|
|
135
|
+
if (process.env[constants_1.PERF_MEASUREMENT_ENV]) {
|
|
131
136
|
performance_tester_1.default.startMonitoring('performance-report-launcher.csv');
|
|
132
137
|
}
|
|
133
138
|
this._accessibilityAutomation || (this._accessibilityAutomation = (0, util_2.isTrue)(this._options.accessibility));
|
|
@@ -136,8 +141,8 @@ class BrowserstackLauncherService {
|
|
|
136
141
|
this._options.testObservability = this._options.testObservability == false ? false : true;
|
|
137
142
|
if (this._options.testObservability &&
|
|
138
143
|
// update files to run if it's a rerun
|
|
139
|
-
process.env.
|
|
140
|
-
this._config.specs = process.env.
|
|
144
|
+
process.env[constants_1.RERUN_ENV] && process.env[constants_1.RERUN_TESTS_ENV]) {
|
|
145
|
+
this._config.specs = process.env[constants_1.RERUN_TESTS_ENV].split(',');
|
|
141
146
|
}
|
|
142
147
|
try {
|
|
143
148
|
crash_reporter_1.default.setConfigDetails(this._config, capabilities, this._options);
|
|
@@ -159,16 +164,9 @@ class BrowserstackLauncherService {
|
|
|
159
164
|
PercyLogger_1.PercyLogger.error(`Error while setting best platform for Percy snapshot at worker start ${err}`);
|
|
160
165
|
}
|
|
161
166
|
}
|
|
162
|
-
setupExitHandlers() {
|
|
163
|
-
process.on('exit', (code) => {
|
|
164
|
-
if (!!process.env.BS_TESTOPS_JWT && !this._testOpsBuildStopped) {
|
|
165
|
-
const childProcess = (0, node_child_process_1.spawn)('node', [`${path_1.default.join(__dirname, 'cleanup.js')}`], { detached: true, stdio: 'inherit', env: { ...process.env } });
|
|
166
|
-
childProcess.unref();
|
|
167
|
-
process.exit(code);
|
|
168
|
-
}
|
|
169
|
-
});
|
|
170
|
-
}
|
|
171
167
|
async onPrepare(config, capabilities) {
|
|
168
|
+
// // Send Funnel start request
|
|
169
|
+
await (0, funnelInstrumentation_1.sendStart)(this.browserStackConfig);
|
|
172
170
|
/**
|
|
173
171
|
* Upload app to BrowserStack if valid file path to app is given.
|
|
174
172
|
* Update app value of capability directly if app_url, custom_id, shareable_id is given
|
|
@@ -316,12 +314,12 @@ class BrowserstackLauncherService {
|
|
|
316
314
|
if (this._options.testObservability) {
|
|
317
315
|
log.debug('Sending stop launch event');
|
|
318
316
|
await (0, util_2.stopBuildUpstream)();
|
|
319
|
-
if (process.env.
|
|
320
|
-
console.log(`\nVisit https://observability.browserstack.com/builds/${process.env.
|
|
321
|
-
this.
|
|
317
|
+
if (process.env[constants_1.TESTOPS_BUILD_ID_ENV]) {
|
|
318
|
+
console.log(`\nVisit https://observability.browserstack.com/builds/${process.env[constants_1.TESTOPS_BUILD_ID_ENV]} to view build report, insights, and many more debugging information all at one place!\n`);
|
|
319
|
+
this.browserStackConfig.testObservability.buildStopped = true;
|
|
322
320
|
}
|
|
323
321
|
}
|
|
324
|
-
if (process.env.
|
|
322
|
+
if (process.env[constants_1.PERF_MEASUREMENT_ENV]) {
|
|
325
323
|
await performance_tester_1.default.stopAndGenerate('performance-launcher.html');
|
|
326
324
|
performance_tester_1.default.calculateTimes(['launchTestSession', 'stopBuildUpstream']);
|
|
327
325
|
if (!process.env.START_TIME) {
|
|
@@ -334,6 +332,7 @@ class BrowserstackLauncherService {
|
|
|
334
332
|
await this.stopPercy();
|
|
335
333
|
}
|
|
336
334
|
PercyLogger_1.PercyLogger.clearLogger();
|
|
335
|
+
await (0, funnelInstrumentation_1.sendFinish)(this.browserStackConfig);
|
|
337
336
|
if (!this.browserstackLocal || !this.browserstackLocal.isRunning()) {
|
|
338
337
|
return;
|
|
339
338
|
}
|
|
@@ -402,8 +401,10 @@ class BrowserstackLauncherService {
|
|
|
402
401
|
async _uploadApp(app) {
|
|
403
402
|
log.info(`uploading app ${app.app} ${app.customId ? `and custom_id: ${app.customId}` : ''} to browserstack`);
|
|
404
403
|
const form = new form_data_1.default();
|
|
405
|
-
if (app.app)
|
|
406
|
-
|
|
404
|
+
if (app.app) {
|
|
405
|
+
const fileName = path_1.default.basename(app.app);
|
|
406
|
+
form.append('file', fs_1.default.createReadStream(app.app), fileName);
|
|
407
|
+
}
|
|
407
408
|
if (app.customId)
|
|
408
409
|
form.append('custom_id', app.customId);
|
|
409
410
|
const res = await got_1.default.post('https://api-cloud.browserstack.com/app-automate/upload', {
|
package/build/reporter.d.ts
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import WDIOReporter, { SuiteStats, TestStats, RunnerStats, HookStats } from '@wdio/reporter';
|
|
2
|
-
import type { CurrentRunInfo, StdLog, TestMeta } from './types';
|
|
2
|
+
import type { CurrentRunInfo, StdLog, TestData, TestMeta } from './types';
|
|
3
3
|
declare class _TestReporter extends WDIOReporter {
|
|
4
4
|
private _capabilities;
|
|
5
5
|
private _config?;
|
|
6
6
|
private _observability;
|
|
7
7
|
private _sessionId?;
|
|
8
8
|
private _suiteName?;
|
|
9
|
-
private _requestQueueHandler;
|
|
10
9
|
private _suites;
|
|
11
10
|
private static _tests;
|
|
12
11
|
private _gitConfigPath?;
|
|
13
12
|
private _gitConfigured;
|
|
14
13
|
private _currentHook;
|
|
15
14
|
private _currentTest;
|
|
15
|
+
private listener;
|
|
16
16
|
onRunnerStart(runnerStats: RunnerStats): Promise<void>;
|
|
17
17
|
registerListeners(): void;
|
|
18
18
|
appendTestItemLog(stdLog: StdLog): Promise<void>;
|
|
@@ -27,7 +27,7 @@ declare class _TestReporter extends WDIOReporter {
|
|
|
27
27
|
onHookStart(hookStats: HookStats): Promise<void>;
|
|
28
28
|
onHookEnd(hookStats: HookStats): Promise<void>;
|
|
29
29
|
getHookIdentifier(hookStats: HookStats): string;
|
|
30
|
-
|
|
30
|
+
getRunData(testStats: TestStats | HookStats, eventType: string): Promise<TestData>;
|
|
31
31
|
onTestSkip(testStats: TestStats): Promise<void>;
|
|
32
32
|
}
|
|
33
33
|
declare const TestReporter: typeof _TestReporter;
|
package/build/reporter.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reporter.d.ts","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"AAEA,OAAO,YAAY,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAO5F,OAAO,KAAK,EAAsB,cAAc,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"reporter.d.ts","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"AAEA,OAAO,YAAY,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAO5F,OAAO,KAAK,EAAsB,cAAc,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAY7F,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,OAAO,CAAmB;IAClC,OAAO,CAAC,MAAM,CAAC,MAAM,CAA+B;IACpD,OAAO,CAAC,cAAc,CAAC,CAAQ;IAC/B,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,QAAQ,CAAyB;IAEnC,aAAa,CAAE,WAAW,EAAE,WAAW;IAS7C,iBAAiB;IAQJ,iBAAiB,CAAC,MAAM,EAAE,MAAM;IAW7C,cAAc,CAAC,WAAW,EAAE,cAAc;IAapC,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;IAQ9B,WAAW,CAAC,SAAS,EAAE,SAAS;IAahC,WAAW,CAAC,SAAS,EAAE,SAAS;IAehC,SAAS,CAAC,SAAS,EAAE,SAAS;IAqBpC,iBAAiB,CAAC,SAAS,EAAE,SAAS;IAIhC,UAAU,CAAC,SAAS,EAAE,SAAS,GAAC,SAAS,EAAE,SAAS,EAAE,MAAM;IAwE5D,UAAU,CAAE,SAAS,EAAE,SAAS;CAQzC;AAED,QAAA,MAAM,YAAY,EAAE,OAAO,aAAoD,CAAA;AAC/E,KAAK,YAAY,GAAG,aAAa,CAAA;AACjC,eAAe,YAAY,CAAA"}
|