@testomatio/reporter 2.1.0-beta-nightwatch → 2.1.0-beta.2-codeceptjs
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/lib/adapter/codecept.js +288 -202
- package/lib/adapter/cypress-plugin/index.js +0 -2
- package/lib/adapter/mocha.js +0 -1
- package/lib/adapter/nightwatch.js +5 -5
- package/lib/adapter/playwright.js +11 -3
- package/lib/adapter/webdriver.d.ts +1 -1
- package/lib/adapter/webdriver.js +18 -8
- package/lib/bin/cli.js +73 -8
- package/lib/bin/reportXml.js +4 -2
- package/lib/bin/startTest.js +3 -2
- package/lib/bin/uploadArtifacts.js +5 -4
- package/lib/client.js +31 -10
- package/lib/data-storage.d.ts +5 -5
- package/lib/data-storage.js +23 -13
- package/lib/junit-adapter/csharp.d.ts +1 -0
- package/lib/junit-adapter/csharp.js +11 -1
- package/lib/pipe/bitbucket.d.ts +2 -0
- package/lib/pipe/bitbucket.js +38 -26
- package/lib/pipe/debug.js +27 -6
- package/lib/pipe/github.d.ts +2 -2
- package/lib/pipe/github.js +35 -3
- package/lib/pipe/gitlab.d.ts +2 -0
- package/lib/pipe/gitlab.js +27 -9
- package/lib/pipe/html.js +0 -3
- package/lib/pipe/index.js +17 -7
- package/lib/pipe/testomatio.d.ts +3 -2
- package/lib/pipe/testomatio.js +85 -75
- package/lib/replay.d.ts +31 -0
- package/lib/replay.js +259 -0
- package/lib/reporter-functions.d.ts +7 -0
- package/lib/reporter-functions.js +36 -0
- package/lib/reporter.d.ts +15 -12
- package/lib/reporter.js +4 -1
- package/lib/services/artifacts.d.ts +1 -1
- package/lib/services/index.d.ts +2 -0
- package/lib/services/index.js +2 -0
- package/lib/services/key-values.d.ts +1 -1
- package/lib/services/labels.d.ts +22 -0
- package/lib/services/labels.js +62 -0
- package/lib/services/logger.d.ts +1 -1
- package/lib/services/logger.js +1 -2
- package/lib/template/testomatio.hbs +443 -68
- package/lib/uploader.js +10 -6
- package/lib/utils/constants.d.ts +12 -0
- package/lib/utils/constants.js +15 -0
- package/lib/utils/utils.d.ts +10 -1
- package/lib/utils/utils.js +70 -22
- package/lib/xmlReader.js +57 -19
- package/package.json +16 -11
- package/src/adapter/codecept.js +320 -214
- package/src/adapter/cypress-plugin/index.js +0 -2
- package/src/adapter/mocha.js +0 -1
- package/src/adapter/nightwatch.js +1 -1
- package/src/adapter/playwright.js +10 -7
- package/src/adapter/webdriver.js +13 -5
- package/src/bin/cli.js +78 -7
- package/src/bin/reportXml.js +4 -1
- package/src/bin/startTest.js +2 -1
- package/src/bin/uploadArtifacts.js +2 -1
- package/src/client.js +28 -5
- package/src/data-storage.js +6 -6
- package/src/junit-adapter/csharp.js +13 -1
- package/src/pipe/bitbucket.js +22 -24
- package/src/pipe/debug.js +26 -5
- package/src/pipe/github.js +1 -2
- package/src/pipe/gitlab.js +27 -9
- package/src/pipe/html.js +1 -4
- package/src/pipe/testomatio.js +112 -107
- package/src/replay.js +268 -0
- package/src/reporter-functions.js +41 -0
- package/src/reporter.js +3 -0
- package/src/services/index.js +2 -0
- package/src/services/labels.js +59 -0
- package/src/services/logger.js +1 -2
- package/src/template/testomatio.hbs +443 -68
- package/src/uploader.js +11 -6
- package/src/utils/constants.js +12 -0
- package/src/utils/utils.js +67 -15
- package/src/xmlReader.js +73 -18
package/src/replay.js
ADDED
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import os from 'os';
|
|
4
|
+
import TestomatClient from './client.js';
|
|
5
|
+
import { STATUS } from './constants.js';
|
|
6
|
+
import { config } from './config.js';
|
|
7
|
+
|
|
8
|
+
export class Replay {
|
|
9
|
+
constructor(options = {}) {
|
|
10
|
+
this.apiKey = options.apiKey || config.TESTOMATIO || undefined;
|
|
11
|
+
this.dryRun = options.dryRun || false;
|
|
12
|
+
this.onProgress = options.onProgress || (() => {});
|
|
13
|
+
this.onLog = options.onLog || console.log;
|
|
14
|
+
this.onError = options.onError || console.error;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Get the default debug file path
|
|
19
|
+
* @returns {string} Path to the latest debug file
|
|
20
|
+
*/
|
|
21
|
+
getDefaultDebugFile() {
|
|
22
|
+
return path.join(os.tmpdir(), 'testomatio.debug.latest.json');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Parse a debug file and extract test data
|
|
27
|
+
* @param {string} debugFile - Path to the debug file
|
|
28
|
+
* @returns {Object} Parsed debug data
|
|
29
|
+
*/
|
|
30
|
+
parseDebugFile(debugFile) {
|
|
31
|
+
if (!fs.existsSync(debugFile)) {
|
|
32
|
+
throw new Error(`Debug file not found: ${debugFile}`);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const fileContent = fs.readFileSync(debugFile, 'utf-8');
|
|
36
|
+
const lines = fileContent
|
|
37
|
+
.trim()
|
|
38
|
+
.split('\n')
|
|
39
|
+
.filter(line => line.trim() !== '');
|
|
40
|
+
|
|
41
|
+
if (lines.length === 0) {
|
|
42
|
+
throw new Error('Debug file is empty');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
let runParams = {};
|
|
46
|
+
let finishParams = {};
|
|
47
|
+
let parseErrors = 0;
|
|
48
|
+
const testsMap = new Map(); // Use Map to deduplicate by rid
|
|
49
|
+
const testsWithoutRid = []; // For tests without rid (backward compatibility)
|
|
50
|
+
const envVars = {};
|
|
51
|
+
let runId = null;
|
|
52
|
+
|
|
53
|
+
// Parse debug file line by line
|
|
54
|
+
for (const [lineIndex, line] of lines.entries()) {
|
|
55
|
+
try {
|
|
56
|
+
const logEntry = JSON.parse(line);
|
|
57
|
+
|
|
58
|
+
if (logEntry.data === 'variables' && logEntry.testomatioEnvVars) {
|
|
59
|
+
Object.assign(envVars, logEntry.testomatioEnvVars);
|
|
60
|
+
} else if (logEntry.action === 'createRun') {
|
|
61
|
+
runParams = logEntry.params || {};
|
|
62
|
+
} else if (logEntry.action === 'addTestsBatch' && logEntry.tests) {
|
|
63
|
+
// Extract runId if available
|
|
64
|
+
if (logEntry.runId && !runId) {
|
|
65
|
+
runId = logEntry.runId;
|
|
66
|
+
}
|
|
67
|
+
// Process each test in the batch
|
|
68
|
+
for (const test of logEntry.tests) {
|
|
69
|
+
if (test.rid) {
|
|
70
|
+
// Handle tests with rid (deduplicate)
|
|
71
|
+
const existingTest = testsMap.get(test.rid);
|
|
72
|
+
if (existingTest) {
|
|
73
|
+
// Merge test data - prioritize non-null/non-empty values
|
|
74
|
+
const mergedTest = { ...existingTest };
|
|
75
|
+
Object.keys(test).forEach(key => {
|
|
76
|
+
if (test[key] !== null && test[key] !== undefined) {
|
|
77
|
+
if (key === 'files' && Array.isArray(test[key]) && test[key].length > 0) {
|
|
78
|
+
// Merge files arrays
|
|
79
|
+
mergedTest.files = [...(existingTest.files || []), ...test[key]];
|
|
80
|
+
} else if (key === 'artifacts' && Array.isArray(test[key]) && test[key].length > 0) {
|
|
81
|
+
// Merge artifacts arrays
|
|
82
|
+
mergedTest.artifacts = [...(existingTest.artifacts || []), ...test[key]];
|
|
83
|
+
} else if (
|
|
84
|
+
existingTest[key] === null ||
|
|
85
|
+
existingTest[key] === undefined ||
|
|
86
|
+
(Array.isArray(existingTest[key]) && existingTest[key].length === 0)
|
|
87
|
+
) {
|
|
88
|
+
// Use new value if existing is null/undefined/empty array
|
|
89
|
+
mergedTest[key] = test[key];
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
testsMap.set(test.rid, mergedTest);
|
|
94
|
+
} else {
|
|
95
|
+
testsMap.set(test.rid, { ...test });
|
|
96
|
+
}
|
|
97
|
+
} else {
|
|
98
|
+
// Handle tests without rid (no deduplication)
|
|
99
|
+
testsWithoutRid.push({ ...test });
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
} else if (logEntry.action === 'addTest' && logEntry.testId) {
|
|
103
|
+
// Extract runId if available
|
|
104
|
+
if (logEntry.runId && !runId) {
|
|
105
|
+
runId = logEntry.runId;
|
|
106
|
+
}
|
|
107
|
+
const test = logEntry.testId;
|
|
108
|
+
if (test.rid) {
|
|
109
|
+
// Handle tests with rid (deduplicate)
|
|
110
|
+
const existingTest = testsMap.get(test.rid);
|
|
111
|
+
if (existingTest) {
|
|
112
|
+
// Merge with existing test
|
|
113
|
+
const mergedTest = { ...existingTest, ...test };
|
|
114
|
+
testsMap.set(test.rid, mergedTest);
|
|
115
|
+
} else {
|
|
116
|
+
testsMap.set(test.rid, { ...test });
|
|
117
|
+
}
|
|
118
|
+
} else {
|
|
119
|
+
// Handle tests without rid (no deduplication)
|
|
120
|
+
testsWithoutRid.push({ ...test });
|
|
121
|
+
}
|
|
122
|
+
} else if (logEntry.actions === 'finishRun') {
|
|
123
|
+
finishParams = logEntry.params || {};
|
|
124
|
+
}
|
|
125
|
+
} catch (err) {
|
|
126
|
+
parseErrors++;
|
|
127
|
+
if (parseErrors <= 3) {
|
|
128
|
+
// Only show first 3 parse errors
|
|
129
|
+
this.onError(`Failed to parse line ${lineIndex + 1}: ${line.substring(0, 100)}...`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (parseErrors > 3) {
|
|
135
|
+
this.onError(`${parseErrors - 3} more parse errors occurred`);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Combine tests with rid and tests without rid
|
|
139
|
+
const allTests = [...Array.from(testsMap.values()), ...testsWithoutRid];
|
|
140
|
+
|
|
141
|
+
return {
|
|
142
|
+
runParams,
|
|
143
|
+
finishParams,
|
|
144
|
+
tests: allTests,
|
|
145
|
+
envVars,
|
|
146
|
+
parseErrors,
|
|
147
|
+
totalLines: lines.length,
|
|
148
|
+
runId,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Restore environment variables from debug data
|
|
154
|
+
* @param {Object} envVars - Environment variables to restore
|
|
155
|
+
*/
|
|
156
|
+
restoreEnvironmentVariables(envVars) {
|
|
157
|
+
// Only restore env vars that aren't already set (don't override current values)
|
|
158
|
+
Object.keys(envVars).forEach(key => {
|
|
159
|
+
if (process.env[key] === undefined || process.env[key] === '') {
|
|
160
|
+
process.env[key] = envVars[key];
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Replay test data to Testomat.io
|
|
167
|
+
* @param {string} debugFile - Path to debug file (optional, uses default if not provided)
|
|
168
|
+
* @returns {Promise<Object>} Replay results
|
|
169
|
+
*/
|
|
170
|
+
async replay(debugFile) {
|
|
171
|
+
if (!debugFile) {
|
|
172
|
+
debugFile = this.getDefaultDebugFile();
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (!this.apiKey) {
|
|
176
|
+
throw new Error('TESTOMATIO API key not found. Set TESTOMATIO environment variable.');
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
this.onLog(`Replaying data from debug file: ${debugFile}`);
|
|
180
|
+
|
|
181
|
+
// Parse the debug file
|
|
182
|
+
const debugData = this.parseDebugFile(debugFile);
|
|
183
|
+
const { runParams, finishParams, tests, envVars, runId } = debugData;
|
|
184
|
+
|
|
185
|
+
this.onLog(`Found ${tests.length} tests to replay`);
|
|
186
|
+
|
|
187
|
+
if (tests.length === 0) {
|
|
188
|
+
throw new Error('No test data found in debug file');
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Restore environment variables
|
|
192
|
+
this.restoreEnvironmentVariables(envVars);
|
|
193
|
+
|
|
194
|
+
if (this.dryRun) {
|
|
195
|
+
return {
|
|
196
|
+
success: true,
|
|
197
|
+
testsCount: tests.length,
|
|
198
|
+
runParams,
|
|
199
|
+
finishParams,
|
|
200
|
+
envVars,
|
|
201
|
+
runId,
|
|
202
|
+
dryRun: true,
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Create client and restore the run
|
|
207
|
+
const client = new TestomatClient({
|
|
208
|
+
apiKey: this.apiKey,
|
|
209
|
+
isBatchEnabled: true,
|
|
210
|
+
...runParams,
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
// Use the stored runId if available, otherwise create a new run
|
|
214
|
+
if (runId) {
|
|
215
|
+
this.onLog(`Using existing run ID: ${runId}`);
|
|
216
|
+
client.runId = runId;
|
|
217
|
+
} else {
|
|
218
|
+
this.onLog('Publishing to run...');
|
|
219
|
+
await client.createRun(runParams);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Send each test result
|
|
223
|
+
let successCount = 0;
|
|
224
|
+
let failureCount = 0;
|
|
225
|
+
|
|
226
|
+
for (const [index, test] of tests.entries()) {
|
|
227
|
+
try {
|
|
228
|
+
await client.addTestRun(test.status, { ...test, overwrite: true });
|
|
229
|
+
successCount++;
|
|
230
|
+
this.onProgress({
|
|
231
|
+
current: index + 1,
|
|
232
|
+
total: tests.length,
|
|
233
|
+
test,
|
|
234
|
+
success: true,
|
|
235
|
+
});
|
|
236
|
+
} catch (err) {
|
|
237
|
+
failureCount++;
|
|
238
|
+
this.onError(`Failed to send test ${index + 1}: ${err.message}`);
|
|
239
|
+
this.onProgress({
|
|
240
|
+
current: index + 1,
|
|
241
|
+
total: tests.length,
|
|
242
|
+
test,
|
|
243
|
+
success: false,
|
|
244
|
+
error: err.message,
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
await client.updateRunStatus(finishParams.status || STATUS.FINISHED, finishParams.parallel || false);
|
|
250
|
+
|
|
251
|
+
const result = {
|
|
252
|
+
success: true,
|
|
253
|
+
testsCount: tests.length,
|
|
254
|
+
successCount,
|
|
255
|
+
failureCount,
|
|
256
|
+
runParams,
|
|
257
|
+
finishParams,
|
|
258
|
+
envVars,
|
|
259
|
+
runId: runId || client.runId,
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
this.onLog(`Successfully replayed ${successCount}/${tests.length} tests from debug file`);
|
|
263
|
+
|
|
264
|
+
return result;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export default Replay;
|
|
@@ -47,9 +47,50 @@ function setKeyValue(keyValue, value = null) {
|
|
|
47
47
|
services.keyValues.put(keyValue);
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
+
/**
|
|
51
|
+
* Add a single label to the test report
|
|
52
|
+
* @param {string} key - label key (e.g. 'severity', 'feature', or just 'smoke' for labels without values)
|
|
53
|
+
* @param {string} [value] - optional label value (e.g. 'high', 'login')
|
|
54
|
+
*/
|
|
55
|
+
function setLabel(key, value = null) {
|
|
56
|
+
if (!key || typeof key !== 'string') {
|
|
57
|
+
console.warn('Label key must be a non-empty string');
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Limit key length to 255 characters
|
|
62
|
+
if (key.length > 255) {
|
|
63
|
+
console.warn('Label key is too long, trimmed to 255 characters:', key);
|
|
64
|
+
key = key.substring(0, 255);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
let labelString = key;
|
|
68
|
+
if (value !== null && value !== undefined && value !== '') {
|
|
69
|
+
if (typeof value !== 'string') {
|
|
70
|
+
console.warn('Label value must be a string, converting:', value);
|
|
71
|
+
value = String(value);
|
|
72
|
+
}
|
|
73
|
+
// Limit value length to 255 characters
|
|
74
|
+
if (value.length > 255) {
|
|
75
|
+
console.warn('Label value is too long, trimmed to 255 characters:', value);
|
|
76
|
+
value = value.substring(0, 255);
|
|
77
|
+
}
|
|
78
|
+
labelString = `${key}:${value}`;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Limit total label length to 255 characters
|
|
82
|
+
if (labelString.length > 255) {
|
|
83
|
+
console.warn('Label is too long, trimmed to 255 characters:', labelString);
|
|
84
|
+
labelString = labelString.substring(0, 255);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
services.labels.put([labelString]);
|
|
88
|
+
}
|
|
89
|
+
|
|
50
90
|
export default {
|
|
51
91
|
artifact: saveArtifact,
|
|
52
92
|
log: logMessage,
|
|
53
93
|
step: addStep,
|
|
54
94
|
keyValue: setKeyValue,
|
|
95
|
+
label: setLabel,
|
|
55
96
|
};
|
package/src/reporter.js
CHANGED
|
@@ -8,6 +8,7 @@ export const log = reporterFunctions.log;
|
|
|
8
8
|
export const logger = services.logger;
|
|
9
9
|
export const meta = reporterFunctions.keyValue;
|
|
10
10
|
export const step = reporterFunctions.step;
|
|
11
|
+
export const label = reporterFunctions.label;
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* @typedef {import('./reporter-functions.js')} artifact
|
|
@@ -15,6 +16,7 @@ export const step = reporterFunctions.step;
|
|
|
15
16
|
* @typedef {import('./services/index.js')} logger
|
|
16
17
|
* @typedef {import('./reporter-functions.js')} meta
|
|
17
18
|
* @typedef {import('./reporter-functions.js')} step
|
|
19
|
+
* @typedef {import('./reporter-functions.js')} label
|
|
18
20
|
*/
|
|
19
21
|
export default {
|
|
20
22
|
/**
|
|
@@ -27,6 +29,7 @@ export default {
|
|
|
27
29
|
logger: services.logger,
|
|
28
30
|
meta: reporterFunctions.keyValue,
|
|
29
31
|
step: reporterFunctions.step,
|
|
32
|
+
label: reporterFunctions.label,
|
|
30
33
|
|
|
31
34
|
// TestomatClient,
|
|
32
35
|
// TRConstants,
|
package/src/services/index.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { logger } from './logger.js';
|
|
2
2
|
import { artifactStorage } from './artifacts.js';
|
|
3
3
|
import { keyValueStorage } from './key-values.js';
|
|
4
|
+
import { labelStorage } from './labels.js';
|
|
4
5
|
import { dataStorage } from '../data-storage.js';
|
|
5
6
|
|
|
6
7
|
export const services = {
|
|
7
8
|
logger,
|
|
8
9
|
artifacts: artifactStorage,
|
|
9
10
|
keyValues: keyValueStorage,
|
|
11
|
+
labels: labelStorage,
|
|
10
12
|
setContext: context => {
|
|
11
13
|
dataStorage.setContext(context);
|
|
12
14
|
},
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import createDebugMessages from 'debug';
|
|
2
|
+
import { dataStorage } from '../data-storage.js';
|
|
3
|
+
|
|
4
|
+
const debug = createDebugMessages('@testomatio/reporter:services-labels');
|
|
5
|
+
class LabelStorage {
|
|
6
|
+
static #instance;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
*
|
|
10
|
+
* @returns {LabelStorage}
|
|
11
|
+
*/
|
|
12
|
+
static getInstance() {
|
|
13
|
+
if (!this.#instance) {
|
|
14
|
+
this.#instance = new LabelStorage();
|
|
15
|
+
}
|
|
16
|
+
return this.#instance;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Stores labels array and passes it to reporter
|
|
21
|
+
* @param {string[]} labels - array of label strings
|
|
22
|
+
* @param {*} context - full test title
|
|
23
|
+
*/
|
|
24
|
+
put(labels, context = null) {
|
|
25
|
+
if (!labels || !Array.isArray(labels)) return;
|
|
26
|
+
dataStorage.putData('labels', labels, context);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Returns labels array for the test
|
|
31
|
+
* @param {*} context testId or test context from test runner
|
|
32
|
+
* @returns {string[]} labels array, e.g. ['smoke', 'severity:high', 'feature:user_account']
|
|
33
|
+
*/
|
|
34
|
+
get(context = null) {
|
|
35
|
+
const labelsList = dataStorage.getData('labels', context);
|
|
36
|
+
if (!labelsList || !labelsList?.length) return [];
|
|
37
|
+
|
|
38
|
+
const allLabels = [];
|
|
39
|
+
for (const labels of labelsList) {
|
|
40
|
+
if (Array.isArray(labels)) {
|
|
41
|
+
allLabels.push(...labels);
|
|
42
|
+
} else if (typeof labels === 'string') {
|
|
43
|
+
try {
|
|
44
|
+
const parsedLabels = JSON.parse(labels);
|
|
45
|
+
if (Array.isArray(parsedLabels)) {
|
|
46
|
+
allLabels.push(...parsedLabels);
|
|
47
|
+
}
|
|
48
|
+
} catch (e) {
|
|
49
|
+
debug(`Error parsing labels for test ${context}`, labels);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Remove duplicates
|
|
55
|
+
return [...new Set(allLabels)];
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export const labelStorage = LabelStorage.getInstance();
|
package/src/services/logger.js
CHANGED
|
@@ -93,7 +93,6 @@ class Logger {
|
|
|
93
93
|
logs.push(arg.join(' '));
|
|
94
94
|
} else {
|
|
95
95
|
try {
|
|
96
|
-
// eslint-disable-next-line no-unused-expressions
|
|
97
96
|
this.prettyObjects ? logs.push(JSON.stringify(arg, null, 2)) : logs.push(JSON.stringify(arg));
|
|
98
97
|
} catch (e) {
|
|
99
98
|
debug('Error while stringify object', e);
|
|
@@ -123,7 +122,7 @@ class Logger {
|
|
|
123
122
|
current +
|
|
124
123
|
// strings are splitted by args when use tagged template, thus we add arg after each string
|
|
125
124
|
// it looks like: `string1 arg1 string2 arg2 string3`
|
|
126
|
-
(args[index] !== undefined
|
|
125
|
+
(args[index] !== undefined
|
|
127
126
|
? typeof args[index] === 'string'
|
|
128
127
|
? args[index] // add arg as it is
|
|
129
128
|
: this.#stringifyLogs(args[index]) // stringify arg
|