@wdio/browserstack-service 8.32.4 → 8.33.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 +2 -1
- package/build/bstackLogger.d.ts.map +1 -1
- package/build/bstackLogger.js +6 -3
- package/build/cleanup.d.ts +5 -1
- package/build/cleanup.d.ts.map +1 -1
- package/build/cleanup.js +72 -7
- package/build/config.d.ts +23 -0
- package/build/config.d.ts.map +1 -0
- package/build/config.js +39 -0
- package/build/constants.d.ts +14 -0
- package/build/constants.d.ts.map +1 -1
- package/build/constants.js +22 -0
- package/build/crash-reporter.js +2 -2
- package/build/data-store.d.ts +4 -0
- package/build/data-store.d.ts.map +1 -0
- package/build/data-store.js +41 -0
- package/build/exitHandler.d.ts +4 -0
- package/build/exitHandler.d.ts.map +1 -0
- package/build/exitHandler.js +32 -0
- package/build/insights-handler.d.ts +5 -8
- package/build/insights-handler.d.ts.map +1 -1
- package/build/insights-handler.js +40 -93
- package/build/instrumentation/funnelInstrumentation.d.ts +6 -0
- package/build/instrumentation/funnelInstrumentation.d.ts.map +1 -0
- package/build/instrumentation/funnelInstrumentation.js +119 -0
- package/build/launcher.d.ts +1 -1
- package/build/launcher.d.ts.map +1 -1
- package/build/launcher.js +22 -13
- package/build/reporter.d.ts +3 -3
- package/build/reporter.d.ts.map +1 -1
- package/build/reporter.js +11 -27
- package/build/request-handler.d.ts +5 -13
- package/build/request-handler.d.ts.map +1 -1
- package/build/request-handler.js +30 -48
- package/build/service.d.ts +1 -0
- package/build/service.d.ts.map +1 -1
- package/build/service.js +13 -5
- package/build/testOps/featureStats.d.ts +45 -0
- package/build/testOps/featureStats.d.ts.map +1 -0
- package/build/testOps/featureStats.js +116 -0
- package/build/testOps/featureUsage.d.ts +22 -0
- package/build/testOps/featureUsage.d.ts.map +1 -0
- package/build/testOps/featureUsage.js +47 -0
- package/build/testOps/listener.d.ts +33 -0
- package/build/testOps/listener.d.ts.map +1 -0
- package/build/testOps/listener.js +222 -0
- package/build/testOps/requestUtils.d.ts +4 -0
- package/build/testOps/requestUtils.d.ts.map +1 -0
- package/build/testOps/requestUtils.js +39 -0
- package/build/testOps/testOpsConfig.d.ts +11 -0
- package/build/testOps/testOpsConfig.d.ts.map +1 -0
- package/build/testOps/testOpsConfig.js +19 -0
- package/build/testOps/usageStats.d.ts +404 -0
- package/build/testOps/usageStats.d.ts.map +1 -0
- package/build/testOps/usageStats.js +114 -0
- package/build/types.d.ts +33 -7
- package/build/types.d.ts.map +1 -1
- package/build/util.d.ts +3 -7
- package/build/util.d.ts.map +1 -1
- package/build/util.js +57 -77
- package/package.json +4 -4
package/build/reporter.js
CHANGED
|
@@ -2,16 +2,15 @@ import path from 'node:path';
|
|
|
2
2
|
import WDIOReporter from '@wdio/reporter';
|
|
3
3
|
import * as url from 'node:url';
|
|
4
4
|
import { v4 as uuidv4 } from 'uuid';
|
|
5
|
-
import { getCloudProvider,
|
|
6
|
-
import RequestQueueHandler from './request-handler.js';
|
|
5
|
+
import { getCloudProvider, o11yClassErrorHandler, getGitMetaData, removeAnsiColors, getHookType, getPlatformVersion } from './util.js';
|
|
7
6
|
import { BStackLogger } from './bstackLogger.js';
|
|
7
|
+
import Listener from './testOps/listener.js';
|
|
8
8
|
class _TestReporter extends WDIOReporter {
|
|
9
9
|
_capabilities = {};
|
|
10
10
|
_config;
|
|
11
11
|
_observability = true;
|
|
12
12
|
_sessionId;
|
|
13
13
|
_suiteName;
|
|
14
|
-
_requestQueueHandler = RequestQueueHandler.getInstance();
|
|
15
14
|
_suites = [];
|
|
16
15
|
static _tests = {};
|
|
17
16
|
_gitConfigPath;
|
|
@@ -19,6 +18,7 @@ class _TestReporter extends WDIOReporter {
|
|
|
19
18
|
_currentHook = {};
|
|
20
19
|
_currentTest = {};
|
|
21
20
|
_userCaps = {};
|
|
21
|
+
listener = Listener.getInstance();
|
|
22
22
|
async onRunnerStart(runnerStats) {
|
|
23
23
|
this._capabilities = runnerStats.capabilities;
|
|
24
24
|
this._userCaps = this.getUserCaps(runnerStats);
|
|
@@ -48,10 +48,7 @@ class _TestReporter extends WDIOReporter {
|
|
|
48
48
|
stdLog.test_run_uuid = this._currentTest.uuid;
|
|
49
49
|
}
|
|
50
50
|
if (stdLog.hook_run_uuid || stdLog.test_run_uuid) {
|
|
51
|
-
|
|
52
|
-
event_type: 'LogCreated',
|
|
53
|
-
logs: [stdLog]
|
|
54
|
-
});
|
|
51
|
+
this.listener.logCreated([stdLog]);
|
|
55
52
|
}
|
|
56
53
|
}
|
|
57
54
|
setCurrentHook(hookDetails) {
|
|
@@ -124,7 +121,7 @@ class _TestReporter extends WDIOReporter {
|
|
|
124
121
|
return;
|
|
125
122
|
}
|
|
126
123
|
testStats.end ||= new Date();
|
|
127
|
-
await this.
|
|
124
|
+
this.listener.testFinished(await this.getRunData(testStats, 'TestRunFinished'));
|
|
128
125
|
}
|
|
129
126
|
async onTestStart(testStats) {
|
|
130
127
|
if (!this.needToSendData('test', 'start')) {
|
|
@@ -138,7 +135,7 @@ class _TestReporter extends WDIOReporter {
|
|
|
138
135
|
_TestReporter._tests[testStats.fullTitle] = {
|
|
139
136
|
uuid: uuid,
|
|
140
137
|
};
|
|
141
|
-
await this.
|
|
138
|
+
this.listener.testStarted(await this.getRunData(testStats, 'TestRunStarted'));
|
|
142
139
|
}
|
|
143
140
|
async onHookStart(hookStats) {
|
|
144
141
|
if (!this.needToSendData('hook', 'start')) {
|
|
@@ -151,7 +148,7 @@ class _TestReporter extends WDIOReporter {
|
|
|
151
148
|
uuid: hookId,
|
|
152
149
|
startedAt: (new Date()).toISOString()
|
|
153
150
|
};
|
|
154
|
-
await this.
|
|
151
|
+
this.listener.hookStarted(await this.getRunData(hookStats, 'HookRunStarted'));
|
|
155
152
|
}
|
|
156
153
|
async onHookEnd(hookStats) {
|
|
157
154
|
if (!this.needToSendData('hook', 'end')) {
|
|
@@ -170,7 +167,7 @@ class _TestReporter extends WDIOReporter {
|
|
|
170
167
|
if (!hookStats.state && !hookStats.error) {
|
|
171
168
|
hookStats.state = 'passed';
|
|
172
169
|
}
|
|
173
|
-
await this.
|
|
170
|
+
this.listener.hookFinished(await this.getRunData(hookStats, 'HookRunFinished'));
|
|
174
171
|
}
|
|
175
172
|
getHookIdentifier(hookStats) {
|
|
176
173
|
return `${hookStats.title} for ${this._suites.at(-1)?.title}`;
|
|
@@ -182,9 +179,9 @@ class _TestReporter extends WDIOReporter {
|
|
|
182
179
|
}
|
|
183
180
|
testStats.start ||= new Date();
|
|
184
181
|
testStats.end ||= new Date();
|
|
185
|
-
await this.
|
|
182
|
+
this.listener.testFinished(await this.getRunData(testStats, 'TestRunSkipped'));
|
|
186
183
|
}
|
|
187
|
-
async
|
|
184
|
+
async getRunData(testStats, eventType) {
|
|
188
185
|
const framework = this._config?.framework;
|
|
189
186
|
const scopes = this._suites.map(s => s.title);
|
|
190
187
|
const identifier = testStats.type === 'test' ? testStats.fullTitle : this.getHookIdentifier(testStats);
|
|
@@ -240,23 +237,10 @@ class _TestReporter extends WDIOReporter {
|
|
|
240
237
|
}
|
|
241
238
|
}
|
|
242
239
|
}
|
|
243
|
-
if (eventType === 'TestRunSkipped') {
|
|
244
|
-
eventType = 'TestRunFinished';
|
|
245
|
-
}
|
|
246
|
-
const uploadData = {
|
|
247
|
-
event_type: eventType,
|
|
248
|
-
};
|
|
249
240
|
if (eventType.match(/HookRun/)) {
|
|
250
241
|
testData.hook_type = testData.name?.toLowerCase() ? getHookType(testData.name.toLowerCase()) : 'undefined';
|
|
251
|
-
uploadData.hook_run = testData;
|
|
252
|
-
}
|
|
253
|
-
else {
|
|
254
|
-
uploadData.test_run = testData;
|
|
255
|
-
}
|
|
256
|
-
const req = this._requestQueueHandler.add(uploadData);
|
|
257
|
-
if (req.proceed && req.data) {
|
|
258
|
-
await uploadEventData(req.data, req.url);
|
|
259
242
|
}
|
|
243
|
+
return testData;
|
|
260
244
|
}
|
|
261
245
|
}
|
|
262
246
|
// https://github.com/microsoft/TypeScript/issues/6543
|
|
@@ -1,25 +1,17 @@
|
|
|
1
1
|
import type { UploadType } from './types.js';
|
|
2
2
|
export default class RequestQueueHandler {
|
|
3
3
|
private queue;
|
|
4
|
-
private started;
|
|
5
4
|
private pollEventBatchInterval?;
|
|
6
|
-
|
|
5
|
+
private readonly callback?;
|
|
7
6
|
static tearDownInvoked: boolean;
|
|
8
7
|
static instance: RequestQueueHandler;
|
|
9
8
|
private constructor();
|
|
10
|
-
static getInstance(): RequestQueueHandler;
|
|
11
|
-
|
|
12
|
-
add(event: UploadType): {
|
|
13
|
-
proceed: boolean;
|
|
14
|
-
data?: undefined;
|
|
15
|
-
url?: undefined;
|
|
16
|
-
} | {
|
|
17
|
-
proceed: boolean;
|
|
18
|
-
data: UploadType[] | undefined;
|
|
19
|
-
url: string;
|
|
20
|
-
};
|
|
9
|
+
static getInstance(callback?: Function): RequestQueueHandler;
|
|
10
|
+
add(event: UploadType): void;
|
|
21
11
|
shutdown(): Promise<void>;
|
|
22
12
|
startEventBatchPolling(): void;
|
|
13
|
+
sendBatch(): Promise<void>;
|
|
14
|
+
callCallback: (data: UploadType[], kind: string) => Promise<void>;
|
|
23
15
|
resetEventBatchPolling(): void;
|
|
24
16
|
removeEventBatchPolling(tag: string): void;
|
|
25
17
|
shouldProceed(): boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request-handler.d.ts","sourceRoot":"","sources":["../src/request-handler.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"request-handler.d.ts","sourceRoot":"","sources":["../src/request-handler.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAG5C,MAAM,CAAC,OAAO,OAAO,mBAAmB;IACpC,OAAO,CAAC,KAAK,CAAmB;IAChC,OAAO,CAAC,sBAAsB,CAAC,CAAgC;IAC/D,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAU;IACpC,OAAc,eAAe,UAAQ;IAErC,MAAM,CAAC,QAAQ,EAAE,mBAAmB,CAAA;IAGpC,OAAO;WAKO,WAAW,CAAC,QAAQ,CAAC,EAAE,QAAQ,GAAG,mBAAmB;IAOnE,GAAG,CAAE,KAAK,EAAE,UAAU;IAehB,QAAQ;IAUd,sBAAsB;IAIhB,SAAS;IASf,YAAY,SAAgB,UAAU,EAAE,QAAQ,MAAM,mBAGrD;IAED,sBAAsB;IAKtB,uBAAuB,CAAE,GAAG,EAAE,MAAM;IAOpC,aAAa;CAOhB"}
|
package/build/request-handler.js
CHANGED
|
@@ -1,76 +1,59 @@
|
|
|
1
|
-
import { DATA_BATCH_SIZE, DATA_BATCH_INTERVAL,
|
|
2
|
-
import { batchAndPostEvents } from './util.js';
|
|
1
|
+
import { DATA_BATCH_SIZE, DATA_BATCH_INTERVAL, TESTOPS_BUILD_COMPLETED_ENV } from './constants.js';
|
|
3
2
|
import { BStackLogger } from './bstackLogger.js';
|
|
4
3
|
export default class RequestQueueHandler {
|
|
5
4
|
queue = [];
|
|
6
|
-
started = false;
|
|
7
5
|
pollEventBatchInterval;
|
|
8
|
-
|
|
6
|
+
callback;
|
|
9
7
|
static tearDownInvoked = false;
|
|
10
8
|
static instance;
|
|
11
9
|
// making it private to use singleton pattern
|
|
12
|
-
constructor() {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
RequestQueueHandler.instance = new RequestQueueHandler();
|
|
16
|
-
}
|
|
17
|
-
return RequestQueueHandler.instance;
|
|
10
|
+
constructor(callback) {
|
|
11
|
+
this.callback = callback;
|
|
12
|
+
this.startEventBatchPolling();
|
|
18
13
|
}
|
|
19
|
-
|
|
20
|
-
if (!
|
|
21
|
-
|
|
22
|
-
this.startEventBatchPolling();
|
|
14
|
+
static getInstance(callback) {
|
|
15
|
+
if (!RequestQueueHandler.instance && callback) {
|
|
16
|
+
RequestQueueHandler.instance = new RequestQueueHandler(callback);
|
|
23
17
|
}
|
|
18
|
+
return RequestQueueHandler.instance;
|
|
24
19
|
}
|
|
25
20
|
add(event) {
|
|
26
|
-
if (!process.env
|
|
27
|
-
|
|
28
|
-
proceed: false
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
if (!BATCH_EVENT_TYPES.includes(event.event_type)) {
|
|
32
|
-
return {
|
|
33
|
-
proceed: true
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
if (event.logs && event.logs[0] && event.logs[0].kind === 'TEST_SCREENSHOT') {
|
|
37
|
-
return {
|
|
38
|
-
proceed: true,
|
|
39
|
-
data: [event],
|
|
40
|
-
url: DATA_SCREENSHOT_ENDPOINT
|
|
41
|
-
};
|
|
21
|
+
if (!process.env[TESTOPS_BUILD_COMPLETED_ENV]) {
|
|
22
|
+
throw new Error('Observability build start not completed yet.');
|
|
42
23
|
}
|
|
43
24
|
this.queue.push(event);
|
|
44
25
|
BStackLogger.debug(`Added data to request queue. Queue length = ${this.queue.length}`);
|
|
45
|
-
let data;
|
|
46
26
|
const shouldProceed = this.shouldProceed();
|
|
47
27
|
if (shouldProceed) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
28
|
+
this.sendBatch().catch((e) => {
|
|
29
|
+
BStackLogger.debug('Exception in sending batch: ' + e);
|
|
30
|
+
});
|
|
51
31
|
}
|
|
52
|
-
return {
|
|
53
|
-
proceed: shouldProceed,
|
|
54
|
-
data: data,
|
|
55
|
-
url: DATA_BATCH_ENDPOINT
|
|
56
|
-
};
|
|
57
32
|
}
|
|
58
33
|
async shutdown() {
|
|
34
|
+
BStackLogger.debug('shutdown started');
|
|
59
35
|
this.removeEventBatchPolling('Shutting down');
|
|
60
36
|
while (this.queue.length > 0) {
|
|
61
37
|
const data = this.queue.splice(0, DATA_BATCH_SIZE);
|
|
62
|
-
await
|
|
38
|
+
await this.callCallback(data, 'SHUTDOWN_QUEUE');
|
|
63
39
|
}
|
|
40
|
+
BStackLogger.debug('shutdown ended');
|
|
64
41
|
}
|
|
65
42
|
startEventBatchPolling() {
|
|
66
|
-
this.pollEventBatchInterval = setInterval(
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}
|
|
43
|
+
this.pollEventBatchInterval = setInterval(this.sendBatch.bind(this), DATA_BATCH_INTERVAL);
|
|
44
|
+
}
|
|
45
|
+
async sendBatch() {
|
|
46
|
+
const data = this.queue.splice(0, DATA_BATCH_SIZE);
|
|
47
|
+
if (data.length === 0) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
BStackLogger.debug(`Sending data from request queue. Data length = ${data.length}, Queue length after removal = ${this.queue.length}`);
|
|
51
|
+
await this.callCallback(data, 'INTERVAL_QUEUE');
|
|
73
52
|
}
|
|
53
|
+
callCallback = async (data, kind) => {
|
|
54
|
+
BStackLogger.debug('calling callback with kind ' + kind);
|
|
55
|
+
this.callback && await this.callback(data);
|
|
56
|
+
};
|
|
74
57
|
resetEventBatchPolling() {
|
|
75
58
|
this.removeEventBatchPolling('Resetting');
|
|
76
59
|
this.startEventBatchPolling();
|
|
@@ -79,7 +62,6 @@ export default class RequestQueueHandler {
|
|
|
79
62
|
if (this.pollEventBatchInterval) {
|
|
80
63
|
BStackLogger.debug(`${tag} request queue`);
|
|
81
64
|
clearInterval(this.pollEventBatchInterval);
|
|
82
|
-
this.started = false;
|
|
83
65
|
}
|
|
84
66
|
}
|
|
85
67
|
shouldProceed() {
|
package/build/service.d.ts
CHANGED
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;AAW9E,OAAO,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAA8C,MAAM,YAAY,CAAA;AACnH,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,sBAAsB,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"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"}
|
package/build/service.js
CHANGED
|
@@ -3,11 +3,14 @@ import PerformanceTester from './performance-tester.js';
|
|
|
3
3
|
import { getBrowserDescription, getBrowserCapabilities, isBrowserstackCapability, getParentSuiteName, isBrowserstackSession, patchConsoleLogs } from './util.js';
|
|
4
4
|
import InsightsHandler from './insights-handler.js';
|
|
5
5
|
import TestReporter from './reporter.js';
|
|
6
|
-
import { DEFAULT_OPTIONS } from './constants.js';
|
|
6
|
+
import { DEFAULT_OPTIONS, PERF_MEASUREMENT_ENV } from './constants.js';
|
|
7
7
|
import CrashReporter from './crash-reporter.js';
|
|
8
8
|
import AccessibilityHandler from './accessibility-handler.js';
|
|
9
9
|
import { BStackLogger } from './bstackLogger.js';
|
|
10
10
|
import PercyHandler from './Percy/Percy-Handler.js';
|
|
11
|
+
import Listener from './testOps/listener.js';
|
|
12
|
+
import { saveWorkerData } from './data-store.js';
|
|
13
|
+
import UsageStats from './testOps/usageStats.js';
|
|
11
14
|
export default class BrowserstackService {
|
|
12
15
|
_caps;
|
|
13
16
|
_config;
|
|
@@ -41,7 +44,7 @@ export default class BrowserstackService {
|
|
|
41
44
|
this._turboScale = this._options.turboScale;
|
|
42
45
|
if (this._observability) {
|
|
43
46
|
this._config.reporters?.push(TestReporter);
|
|
44
|
-
if (process.env
|
|
47
|
+
if (process.env[PERF_MEASUREMENT_ENV]) {
|
|
45
48
|
PerformanceTester.startMonitoring('performance-report-service.csv');
|
|
46
49
|
}
|
|
47
50
|
}
|
|
@@ -207,10 +210,10 @@ export default class BrowserstackService {
|
|
|
207
210
|
...(hasReasons ? { reason: this._failReasons.join('\n') } : {})
|
|
208
211
|
});
|
|
209
212
|
}
|
|
210
|
-
await
|
|
211
|
-
await this._insightsHandler?.teardown();
|
|
213
|
+
await Listener.getInstance().onWorkerEnd();
|
|
212
214
|
await this._percyHandler?.teardown();
|
|
213
|
-
|
|
215
|
+
this.saveWorkerData();
|
|
216
|
+
if (process.env[PERF_MEASUREMENT_ENV]) {
|
|
214
217
|
await PerformanceTester.stopAndGenerate('performance-service.html');
|
|
215
218
|
PerformanceTester.calculateTimes([
|
|
216
219
|
'onRunnerStart', 'onSuiteStart', 'onSuiteEnd',
|
|
@@ -405,4 +408,9 @@ export default class BrowserstackService {
|
|
|
405
408
|
}
|
|
406
409
|
return (await this._browser.execute(script));
|
|
407
410
|
}
|
|
411
|
+
saveWorkerData() {
|
|
412
|
+
saveWorkerData({
|
|
413
|
+
usageStats: UsageStats.getInstance().getDataToSave()
|
|
414
|
+
});
|
|
415
|
+
}
|
|
408
416
|
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { FeatureStatsOverview } from '../types.js';
|
|
2
|
+
interface FeatureStatsMap {
|
|
3
|
+
[groupId: string]: FeatureStats;
|
|
4
|
+
}
|
|
5
|
+
interface JSONConversionSettings {
|
|
6
|
+
omitGroups?: boolean;
|
|
7
|
+
onlyGroups?: boolean;
|
|
8
|
+
nestedGroups?: boolean;
|
|
9
|
+
}
|
|
10
|
+
declare class FeatureStats {
|
|
11
|
+
private triggeredCount;
|
|
12
|
+
private sentCount;
|
|
13
|
+
private failedCount;
|
|
14
|
+
private groups;
|
|
15
|
+
mark(status: string, groupId: string): void;
|
|
16
|
+
triggered(groupId?: string): void;
|
|
17
|
+
sent(groupId?: string): void;
|
|
18
|
+
failed(groupId?: string): void;
|
|
19
|
+
success(groupId?: string): void;
|
|
20
|
+
createGroup(groupId: string): FeatureStats;
|
|
21
|
+
getTriggeredCount(): number;
|
|
22
|
+
getSentCount(): number;
|
|
23
|
+
getFailedCount(): number;
|
|
24
|
+
getUsageForGroup(groupId: string): FeatureStats;
|
|
25
|
+
getOverview(): FeatureStatsOverview;
|
|
26
|
+
getGroups(): FeatureStatsMap;
|
|
27
|
+
add(featureStats: FeatureStats): void;
|
|
28
|
+
toJSON(config?: JSONConversionSettings): {
|
|
29
|
+
triggeredCount: number;
|
|
30
|
+
sentCount: number;
|
|
31
|
+
failedCount: number;
|
|
32
|
+
} | {
|
|
33
|
+
groups: Record<string, FeatureStatsOverview>;
|
|
34
|
+
triggeredCount: number;
|
|
35
|
+
sentCount: number;
|
|
36
|
+
failedCount: number;
|
|
37
|
+
} | {
|
|
38
|
+
[x: string]: FeatureStatsOverview;
|
|
39
|
+
} | {
|
|
40
|
+
groups: Record<string, FeatureStatsOverview>;
|
|
41
|
+
};
|
|
42
|
+
static fromJSON(json: any): FeatureStats;
|
|
43
|
+
}
|
|
44
|
+
export default FeatureStats;
|
|
45
|
+
//# sourceMappingURL=featureStats.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"featureStats.d.ts","sourceRoot":"","sources":["../../src/testOps/featureStats.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAGvD,UAAU,eAAe;IACrB,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,CAAC;CACnC;AAED,UAAU,sBAAsB;IAC5B,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,YAAY,CAAC,EAAE,OAAO,CAAA;CACzB;AAED,cAAM,YAAY;IACd,OAAO,CAAC,cAAc,CAAY;IAClC,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,WAAW,CAAY;IAC/B,OAAO,CAAC,MAAM,CAAsB;IAE7B,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAkB3C,SAAS,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAOjC,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAO5B,MAAM,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAO9B,OAAO,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAI/B,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY;IAO1C,iBAAiB,IAAI,MAAM;IAI3B,YAAY,IAAI,MAAM;IAItB,cAAc,IAAI,MAAM;IAIxB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY;IAI/C,WAAW,IAAI,oBAAoB;IAInC,SAAS,IAAI,eAAe;IAI5B,GAAG,CAAC,YAAY,EAAE,YAAY,GAAG,IAAI;IAarC,MAAM,CAAC,MAAM,GAAE,sBAA2B;;;;;;;;;;;;;;WAqBnC,QAAQ,CAAC,IAAI,EAAE,GAAG,GAAG,YAAY;CAkBlD;AAED,eAAe,YAAY,CAAA"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { BStackLogger } from '../bstackLogger.js';
|
|
2
|
+
import { isObjectEmpty } from '../util.js';
|
|
3
|
+
class FeatureStats {
|
|
4
|
+
triggeredCount = 0;
|
|
5
|
+
sentCount = 0;
|
|
6
|
+
failedCount = 0;
|
|
7
|
+
groups = {};
|
|
8
|
+
mark(status, groupId) {
|
|
9
|
+
switch (status) {
|
|
10
|
+
case 'triggered':
|
|
11
|
+
this.triggered(groupId);
|
|
12
|
+
break;
|
|
13
|
+
case 'success':
|
|
14
|
+
case 'sent':
|
|
15
|
+
this.sent(groupId);
|
|
16
|
+
break;
|
|
17
|
+
case 'failed':
|
|
18
|
+
this.failed(groupId);
|
|
19
|
+
break;
|
|
20
|
+
default:
|
|
21
|
+
BStackLogger.debug('Request to mark usage for unknown status - ' + status);
|
|
22
|
+
break;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
triggered(groupId) {
|
|
26
|
+
this.triggeredCount += 1;
|
|
27
|
+
if (groupId) {
|
|
28
|
+
this.createGroup(groupId).triggered();
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
sent(groupId) {
|
|
32
|
+
this.sentCount += 1;
|
|
33
|
+
if (groupId) {
|
|
34
|
+
this.createGroup(groupId).sent();
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
failed(groupId) {
|
|
38
|
+
this.failedCount += 1;
|
|
39
|
+
if (groupId) {
|
|
40
|
+
this.createGroup(groupId).failed();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
success(groupId) {
|
|
44
|
+
this.sent(groupId);
|
|
45
|
+
}
|
|
46
|
+
createGroup(groupId) {
|
|
47
|
+
if (!this.groups[groupId]) {
|
|
48
|
+
this.groups[groupId] = new FeatureStats();
|
|
49
|
+
}
|
|
50
|
+
return this.groups[groupId];
|
|
51
|
+
}
|
|
52
|
+
getTriggeredCount() {
|
|
53
|
+
return this.triggeredCount;
|
|
54
|
+
}
|
|
55
|
+
getSentCount() {
|
|
56
|
+
return this.sentCount;
|
|
57
|
+
}
|
|
58
|
+
getFailedCount() {
|
|
59
|
+
return this.failedCount;
|
|
60
|
+
}
|
|
61
|
+
getUsageForGroup(groupId) {
|
|
62
|
+
return this.groups[groupId] || new FeatureStats();
|
|
63
|
+
}
|
|
64
|
+
getOverview() {
|
|
65
|
+
return { triggeredCount: this.triggeredCount, sentCount: this.sentCount, failedCount: this.failedCount };
|
|
66
|
+
}
|
|
67
|
+
getGroups() {
|
|
68
|
+
return this.groups;
|
|
69
|
+
}
|
|
70
|
+
add(featureStats) {
|
|
71
|
+
this.triggeredCount += featureStats.getTriggeredCount();
|
|
72
|
+
this.sentCount += featureStats.getSentCount();
|
|
73
|
+
this.failedCount += featureStats.getFailedCount();
|
|
74
|
+
Object.entries(featureStats.getGroups()).forEach(([groupId, group]) => {
|
|
75
|
+
this.createGroup(groupId).add(group);
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
// omitGroups: true/false -> Include groups or not
|
|
79
|
+
// onlyGroups: true/false -> data includes only groups
|
|
80
|
+
// nestedGroups: true/false -> groups will be nested in groups if true
|
|
81
|
+
toJSON(config = {}) {
|
|
82
|
+
const overviewData = !config.onlyGroups ? {
|
|
83
|
+
triggeredCount: this.triggeredCount,
|
|
84
|
+
sentCount: this.sentCount,
|
|
85
|
+
failedCount: this.failedCount
|
|
86
|
+
} : {};
|
|
87
|
+
const groupsData = {};
|
|
88
|
+
if (!config.omitGroups) {
|
|
89
|
+
Object.entries(this.groups).forEach(([groupId, group]) => {
|
|
90
|
+
groupsData[groupId] = group.toJSON(); // Currently Nested groups are only overviews
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
const group = config.nestedGroups ? { groups: groupsData } : groupsData;
|
|
94
|
+
return {
|
|
95
|
+
...overviewData,
|
|
96
|
+
...group
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
static fromJSON(json) {
|
|
100
|
+
const stats = new FeatureStats();
|
|
101
|
+
if (!json || isObjectEmpty(json)) {
|
|
102
|
+
return stats;
|
|
103
|
+
}
|
|
104
|
+
stats.triggeredCount = json.triggeredCount;
|
|
105
|
+
stats.sentCount = json.sentCount;
|
|
106
|
+
stats.failedCount = json.failedCount;
|
|
107
|
+
if (!json.groups) {
|
|
108
|
+
return stats;
|
|
109
|
+
}
|
|
110
|
+
Object.entries(json.groups).forEach(([groupId, group]) => {
|
|
111
|
+
stats.groups[groupId] = FeatureStats.fromJSON(group);
|
|
112
|
+
});
|
|
113
|
+
return stats;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
export default FeatureStats;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
declare class FeatureUsage {
|
|
2
|
+
private isTriggered?;
|
|
3
|
+
private status?;
|
|
4
|
+
private error?;
|
|
5
|
+
constructor(isTriggered?: boolean);
|
|
6
|
+
getTriggered(): boolean | undefined;
|
|
7
|
+
setTriggered(triggered: boolean): void;
|
|
8
|
+
setStatus(status: string): void;
|
|
9
|
+
setError(error: string): void;
|
|
10
|
+
triggered(): void;
|
|
11
|
+
failed(e: unknown): void;
|
|
12
|
+
success(): void;
|
|
13
|
+
getStatus(): string | undefined;
|
|
14
|
+
getError(): string | undefined;
|
|
15
|
+
toJSON(): {
|
|
16
|
+
isTriggered: boolean | undefined;
|
|
17
|
+
status: string | undefined;
|
|
18
|
+
error: string | undefined;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
export default FeatureUsage;
|
|
22
|
+
//# sourceMappingURL=featureUsage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"featureUsage.d.ts","sourceRoot":"","sources":["../../src/testOps/featureUsage.ts"],"names":[],"mappings":"AAEA,cAAM,YAAY;IACd,OAAO,CAAC,WAAW,CAAC,CAAS;IAC7B,OAAO,CAAC,MAAM,CAAC,CAAQ;IACvB,OAAO,CAAC,KAAK,CAAC,CAAQ;gBAEV,WAAW,CAAC,EAAE,OAAO;IAM1B,YAAY,IAAI,OAAO,GAAG,SAAS;IAInC,YAAY,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI;IAItC,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAI/B,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAI7B,SAAS,IAAI,IAAI;IAIjB,MAAM,CAAC,CAAC,EAAE,OAAO,GAAG,IAAI;IAKxB,OAAO,IAAI,IAAI;IAIf,SAAS,IAAI,MAAM,GAAG,SAAS;IAI/B,QAAQ,IAAI,MAAM,GAAG,SAAS;IAI9B,MAAM;;;;;CAOhB;AAED,eAAe,YAAY,CAAA"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { getErrorString } from '../util.js';
|
|
2
|
+
class FeatureUsage {
|
|
3
|
+
isTriggered;
|
|
4
|
+
status;
|
|
5
|
+
error;
|
|
6
|
+
constructor(isTriggered) {
|
|
7
|
+
if (isTriggered !== undefined) {
|
|
8
|
+
this.isTriggered = isTriggered;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
getTriggered() {
|
|
12
|
+
return this.isTriggered;
|
|
13
|
+
}
|
|
14
|
+
setTriggered(triggered) {
|
|
15
|
+
this.isTriggered = triggered;
|
|
16
|
+
}
|
|
17
|
+
setStatus(status) {
|
|
18
|
+
this.status = status;
|
|
19
|
+
}
|
|
20
|
+
setError(error) {
|
|
21
|
+
this.error = error;
|
|
22
|
+
}
|
|
23
|
+
triggered() {
|
|
24
|
+
this.isTriggered = true;
|
|
25
|
+
}
|
|
26
|
+
failed(e) {
|
|
27
|
+
this.status = 'failed';
|
|
28
|
+
this.error = getErrorString(e);
|
|
29
|
+
}
|
|
30
|
+
success() {
|
|
31
|
+
this.status = 'success';
|
|
32
|
+
}
|
|
33
|
+
getStatus() {
|
|
34
|
+
return this.status;
|
|
35
|
+
}
|
|
36
|
+
getError() {
|
|
37
|
+
return this.error;
|
|
38
|
+
}
|
|
39
|
+
toJSON() {
|
|
40
|
+
return {
|
|
41
|
+
isTriggered: this.isTriggered,
|
|
42
|
+
status: this.status,
|
|
43
|
+
error: this.error
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
export default FeatureUsage;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { CBTData, LogData, ScreenshotLog, TestData } from '../types.js';
|
|
2
|
+
declare class Listener {
|
|
3
|
+
private static instance;
|
|
4
|
+
private readonly usageStats;
|
|
5
|
+
private readonly testStartedStats;
|
|
6
|
+
private readonly testFinishedStats;
|
|
7
|
+
private readonly hookStartedStats;
|
|
8
|
+
private readonly hookFinishedStats;
|
|
9
|
+
private readonly cbtSessionStats;
|
|
10
|
+
private readonly logEvents;
|
|
11
|
+
private requestBatcher?;
|
|
12
|
+
private pendingUploads;
|
|
13
|
+
private constructor();
|
|
14
|
+
static getInstance(): Listener;
|
|
15
|
+
onWorkerEnd(): Promise<void>;
|
|
16
|
+
uploadPending(waitTimeout?: number, waitInterval?: number): Promise<unknown>;
|
|
17
|
+
teardown(): Promise<void>;
|
|
18
|
+
hookStarted(hookData: TestData): void;
|
|
19
|
+
hookFinished(hookData: TestData): void;
|
|
20
|
+
testStarted(testData: TestData): void;
|
|
21
|
+
testFinished(testData: TestData): void;
|
|
22
|
+
logCreated(logs: LogData[]): void;
|
|
23
|
+
onScreenshot(jsonArray: ScreenshotLog[]): Promise<void>;
|
|
24
|
+
cbtSessionCreated(data: CBTData): void;
|
|
25
|
+
private markLogs;
|
|
26
|
+
private getResult;
|
|
27
|
+
private sendBatchEvents;
|
|
28
|
+
private eventsFailed;
|
|
29
|
+
private eventsSuccess;
|
|
30
|
+
private getEventForHook;
|
|
31
|
+
}
|
|
32
|
+
export default Listener;
|
|
33
|
+
//# sourceMappingURL=listener.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"listener.d.ts","sourceRoot":"","sources":["../../src/testOps/listener.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAc,MAAM,aAAa,CAAA;AAWxF,cAAM,QAAQ;IACV,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAU;IACjC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAuC;IAClE,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAiD;IAClF,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAkD;IACpF,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAiD;IAClF,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAkD;IACpF,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAgD;IAChF,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAyC;IACnE,OAAO,CAAC,cAAc,CAAC,CAAqB;IAC5C,OAAO,CAAC,cAAc,CAAI;IAG1B,OAAO;WAGO,WAAW,IAAI,QAAQ;IAOxB,WAAW;IASlB,aAAa,CAAC,WAAW,SAA2C,EAAE,YAAY,SAA4C,GAAG,OAAO,CAAC,OAAO,CAAC;IASjJ,QAAQ;IAOP,WAAW,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAUrC,YAAY,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAUtC,WAAW,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAUrC,YAAY,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAUtC,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAY3B,YAAY,CAAC,SAAS,EAAE,aAAa,EAAE;IAgB7C,iBAAiB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;IAU7C,OAAO,CAAC,QAAQ;IAgBhB,OAAO,CAAC,SAAS;IAMjB,OAAO,CAAC,eAAe;IAoBvB,OAAO,CAAC,YAAY;IAmBpB,OAAO,CAAC,aAAa;IAmBrB,OAAO,CAAC,eAAe;CAK1B;AAED,eAAe,QAAQ,CAAA"}
|