@testomatio/reporter 2.1.1 → 2.1.3-beta.1-xml-import
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/lib/adapter/codecept.js +2 -2
- package/lib/adapter/mocha.js +14 -0
- package/lib/adapter/webdriver.js +6 -4
- package/lib/bin/startTest.js +38 -91
- package/lib/client.js +6 -3
- package/lib/data-storage.d.ts +4 -4
- package/lib/data-storage.js +6 -6
- package/lib/reporter-functions.d.ts +10 -3
- package/lib/reporter-functions.js +18 -28
- package/lib/reporter.d.ts +16 -14
- package/lib/reporter.js +3 -1
- package/lib/services/artifacts.d.ts +1 -1
- package/lib/services/index.d.ts +2 -2
- package/lib/services/index.js +2 -2
- package/lib/services/key-values.d.ts +1 -1
- package/lib/services/labels.d.ts +1 -1
- package/lib/services/labels.js +2 -2
- package/lib/services/links.d.ts +22 -0
- package/lib/services/links.js +71 -0
- package/lib/services/logger.d.ts +1 -1
- package/lib/xmlReader.d.ts +7 -0
- package/lib/xmlReader.js +180 -7
- package/package.json +1 -1
- package/src/adapter/codecept.js +2 -2
- package/src/adapter/mocha.js +15 -0
- package/src/adapter/webdriver.js +6 -4
- package/src/bin/startTest.js +43 -114
- package/src/client.js +5 -3
- package/src/data-storage.js +6 -6
- package/src/reporter-functions.js +18 -29
- package/src/reporter.js +2 -0
- package/src/services/index.js +2 -2
- package/src/services/labels.js +2 -2
- package/src/services/links.js +69 -0
- package/src/xmlReader.js +210 -7
package/lib/adapter/codecept.js
CHANGED
|
@@ -140,7 +140,7 @@ function CodeceptReporter(config) {
|
|
|
140
140
|
const manuallyAttachedArtifacts = index_js_1.services.artifacts.get(test.fullTitle());
|
|
141
141
|
const keyValues = index_js_1.services.keyValues.get(test.fullTitle());
|
|
142
142
|
const stepHierarchy = buildUnifiedStepHierarchy(test.steps, hookSteps);
|
|
143
|
-
const
|
|
143
|
+
const links = index_js_1.services.links.get(test.fullTitle());
|
|
144
144
|
index_js_1.services.setContext(null);
|
|
145
145
|
client.addTestRun(test.state, {
|
|
146
146
|
...stripExampleFromTitle(title),
|
|
@@ -153,7 +153,7 @@ function CodeceptReporter(config) {
|
|
|
153
153
|
files,
|
|
154
154
|
steps: stepHierarchy, // Array of step objects per API schema
|
|
155
155
|
logs,
|
|
156
|
-
|
|
156
|
+
links,
|
|
157
157
|
manuallyAttachedArtifacts,
|
|
158
158
|
meta: { ...keyValues, ...test.meta },
|
|
159
159
|
});
|
package/lib/adapter/mocha.js
CHANGED
|
@@ -43,6 +43,7 @@ function MochaReporter(runner, opts) {
|
|
|
43
43
|
const logs = getTestLogs(test);
|
|
44
44
|
const artifacts = index_js_1.services.artifacts.get(test.fullTitle());
|
|
45
45
|
const keyValues = index_js_1.services.keyValues.get(test.fullTitle());
|
|
46
|
+
const links = index_js_1.services.links.get(test.fullTitle());
|
|
46
47
|
client.addTestRun(constants_js_1.STATUS.PASSED, {
|
|
47
48
|
test_id: testId,
|
|
48
49
|
suite_title: getSuiteTitle(test),
|
|
@@ -53,12 +54,16 @@ function MochaReporter(runner, opts) {
|
|
|
53
54
|
logs,
|
|
54
55
|
manuallyAttachedArtifacts: artifacts,
|
|
55
56
|
meta: keyValues,
|
|
57
|
+
links,
|
|
56
58
|
});
|
|
57
59
|
});
|
|
58
60
|
runner.on(EVENT_TEST_PENDING, test => {
|
|
59
61
|
skipped += 1;
|
|
60
62
|
console.log('skip: %s', test.fullTitle());
|
|
61
63
|
const testId = (0, utils_js_1.getTestomatIdFromTestTitle)(test.title);
|
|
64
|
+
const artifacts = index_js_1.services.artifacts.get(test.fullTitle());
|
|
65
|
+
const keyValues = index_js_1.services.keyValues.get(test.fullTitle());
|
|
66
|
+
const links = index_js_1.services.links.get(test.fullTitle());
|
|
62
67
|
client.addTestRun(constants_js_1.STATUS.SKIPPED, {
|
|
63
68
|
title: getTestName(test),
|
|
64
69
|
suite_title: getSuiteTitle(test),
|
|
@@ -66,6 +71,9 @@ function MochaReporter(runner, opts) {
|
|
|
66
71
|
file: getFile(test),
|
|
67
72
|
test_id: testId,
|
|
68
73
|
time: test.duration,
|
|
74
|
+
manuallyAttachedArtifacts: artifacts,
|
|
75
|
+
meta: keyValues,
|
|
76
|
+
links,
|
|
69
77
|
});
|
|
70
78
|
});
|
|
71
79
|
runner.on(EVENT_TEST_FAIL, async (test, err) => {
|
|
@@ -73,6 +81,9 @@ function MochaReporter(runner, opts) {
|
|
|
73
81
|
console.log(picocolors_1.default.bold(picocolors_1.default.red('✖')), test.fullTitle(), picocolors_1.default.gray(err.message));
|
|
74
82
|
const testId = (0, utils_js_1.getTestomatIdFromTestTitle)(test.title);
|
|
75
83
|
const logs = getTestLogs(test);
|
|
84
|
+
const artifacts = index_js_1.services.artifacts.get(test.fullTitle());
|
|
85
|
+
const keyValues = index_js_1.services.keyValues.get(test.fullTitle());
|
|
86
|
+
const links = index_js_1.services.links.get(test.fullTitle());
|
|
76
87
|
client.addTestRun(constants_js_1.STATUS.FAILED, {
|
|
77
88
|
error: err,
|
|
78
89
|
suite_title: getSuiteTitle(test),
|
|
@@ -82,6 +93,9 @@ function MochaReporter(runner, opts) {
|
|
|
82
93
|
code: process.env.TESTOMATIO_UPDATE_CODE ? test.body.toString() : '',
|
|
83
94
|
time: test.duration,
|
|
84
95
|
logs,
|
|
96
|
+
manuallyAttachedArtifacts: artifacts,
|
|
97
|
+
meta: keyValues,
|
|
98
|
+
links,
|
|
85
99
|
});
|
|
86
100
|
});
|
|
87
101
|
runner.on(EVENT_RUN_END, () => {
|
package/lib/adapter/webdriver.js
CHANGED
|
@@ -78,11 +78,13 @@ class WebdriverReporter extends reporter_1.default {
|
|
|
78
78
|
test.suite = test.parent;
|
|
79
79
|
const logs = getTestLogs(test.fullTitle);
|
|
80
80
|
// TODO: FIX: artifacts for some reason leads to empty report on Testomat.io
|
|
81
|
-
//
|
|
82
|
-
//
|
|
81
|
+
// ^ not reproduced anymore (Jul 2025)
|
|
82
|
+
// but still be under investigation
|
|
83
|
+
const artifacts = index_js_1.services.artifacts.get(test.fullTitle);
|
|
84
|
+
const keyValues = index_js_1.services.keyValues.get(test.fullTitle);
|
|
83
85
|
test.logs = logs;
|
|
84
|
-
|
|
85
|
-
|
|
86
|
+
test.artifacts = artifacts;
|
|
87
|
+
test.meta = keyValues;
|
|
86
88
|
this._addTestPromises.push(this.addTest(test));
|
|
87
89
|
}
|
|
88
90
|
// wdio-cucumber does not trigger onTestEnd hook, thus, using this one
|
package/lib/bin/startTest.js
CHANGED
|
@@ -4,103 +4,50 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
5
|
};
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const picocolors_1 = __importDefault(require("picocolors"));
|
|
10
|
-
const client_js_1 = __importDefault(require("../client.js"));
|
|
11
|
-
const constants_js_1 = require("../constants.js");
|
|
7
|
+
const node_child_process_1 = require("node:child_process");
|
|
8
|
+
const node_path_1 = require("node:path");
|
|
12
9
|
const utils_js_1 = require("../utils/utils.js");
|
|
13
|
-
const
|
|
14
|
-
|
|
10
|
+
const picocolors_1 = __importDefault(require("picocolors"));
|
|
11
|
+
// Define __dirname - this will be replaced by build script with actual __dirname for CommonJS
|
|
12
|
+
const cliPath = (0, node_path_1.join)(__dirname, 'cli.js');
|
|
15
13
|
const version = (0, utils_js_1.getPackageVersion)();
|
|
16
14
|
console.log(picocolors_1.default.cyan(picocolors_1.default.bold(` 🤩 Testomat.io Reporter v${version}`)));
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
dotenv_1.default.config({ path: opts.envFile });
|
|
29
|
-
const apiKey = process.env['INPUT_TESTOMATIO-KEY'] || config_js_1.config.TESTOMATIO;
|
|
30
|
-
const title = process.env.TESTOMATIO_TITLE;
|
|
31
|
-
if (launch) {
|
|
32
|
-
console.log('Starting a new Run on Testomat.io...');
|
|
33
|
-
const client = new client_js_1.default({ apiKey });
|
|
34
|
-
client.createRun().then(() => {
|
|
35
|
-
console.log(process.env.runId);
|
|
36
|
-
process.exit(0);
|
|
37
|
-
});
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
if (finish) {
|
|
41
|
-
// TODO: add error in case of TESTOMATIO environment variable is not set
|
|
42
|
-
// because command is fine in console, but actually (on testomat.io) run is not finished
|
|
43
|
-
if (!process.env.TESTOMATIO_RUN) {
|
|
44
|
-
console.log('TESTOMATIO_RUN environment variable must be set.');
|
|
45
|
-
return process.exit(1);
|
|
15
|
+
// Parse command line arguments to map start-test-run options to @testomatio/reporter run format
|
|
16
|
+
const args = process.argv.slice(2);
|
|
17
|
+
const newArgs = ['run'];
|
|
18
|
+
let i = 0;
|
|
19
|
+
while (i < args.length) {
|
|
20
|
+
const arg = args[i];
|
|
21
|
+
if (arg === '-c' || arg === '--command') {
|
|
22
|
+
// Map -c/--command to positional argument for run command
|
|
23
|
+
i++;
|
|
24
|
+
if (i < args.length) {
|
|
25
|
+
newArgs.push(args[i]);
|
|
46
26
|
}
|
|
47
|
-
console.log('Finishing Run on Testomat.io...');
|
|
48
|
-
const client = new client_js_1.default({ apiKey });
|
|
49
|
-
// @ts-ignore
|
|
50
|
-
client.updateRunStatus(constants_js_1.STATUS.FINISHED).then(() => {
|
|
51
|
-
console.log(picocolors_1.default.yellow(`Run ${process.env.TESTOMATIO_RUN} was finished`));
|
|
52
|
-
process.exit(0);
|
|
53
|
-
});
|
|
54
|
-
return;
|
|
55
27
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
return;
|
|
28
|
+
else if (arg.startsWith('--command=')) {
|
|
29
|
+
// Handle --command=value format
|
|
30
|
+
const command = arg.split('=', 2)[1];
|
|
31
|
+
newArgs.push(command);
|
|
61
32
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
const pipeOptions = optsArray.join(':');
|
|
66
|
-
try {
|
|
67
|
-
const tests = await client.prepareRun({ pipe, pipeOptions });
|
|
68
|
-
if (!tests || tests.length === 0) {
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
const grep = ` --grep (${tests.join('|')})`;
|
|
72
|
-
command += grep;
|
|
73
|
-
}
|
|
74
|
-
catch (err) {
|
|
75
|
-
console.log(constants_js_1.APP_PREFIX, err);
|
|
76
|
-
}
|
|
33
|
+
else if (arg === '--launch') {
|
|
34
|
+
// Map --launch to start command
|
|
35
|
+
newArgs[0] = 'start';
|
|
77
36
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
const cmd = (0, cross_spawn_1.spawn)(testCmds[0], testCmds.slice(1), { stdio: 'inherit' });
|
|
82
|
-
cmd.on('close', code => {
|
|
83
|
-
console.log(constants_js_1.APP_PREFIX, '⚠️ ', `Runner exited with ${picocolors_1.default.bold(code)}, report is ignored`);
|
|
84
|
-
if (code > exitCode)
|
|
85
|
-
exitCode = code;
|
|
86
|
-
process.exitCode = exitCode;
|
|
87
|
-
});
|
|
88
|
-
return;
|
|
37
|
+
else if (arg === '--finish') {
|
|
38
|
+
// Map --finish to finish command
|
|
39
|
+
newArgs[0] = 'finish';
|
|
89
40
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
const status = code === 0 ? 'passed' : 'failed';
|
|
96
|
-
client.updateRunStatus(status, true);
|
|
97
|
-
if (code > exitCode)
|
|
98
|
-
exitCode = code;
|
|
99
|
-
process.exitCode = exitCode;
|
|
100
|
-
});
|
|
101
|
-
});
|
|
102
|
-
});
|
|
103
|
-
if (process.argv.length <= 2) {
|
|
104
|
-
program.outputHelp();
|
|
41
|
+
else {
|
|
42
|
+
// Pass through other arguments
|
|
43
|
+
newArgs.push(arg);
|
|
44
|
+
}
|
|
45
|
+
i++;
|
|
105
46
|
}
|
|
106
|
-
|
|
47
|
+
// Execute the main CLI with mapped arguments
|
|
48
|
+
const child = (0, node_child_process_1.spawn)(process.execPath, [cliPath, ...newArgs], {
|
|
49
|
+
stdio: 'inherit'
|
|
50
|
+
});
|
|
51
|
+
child.on('exit', (code) => {
|
|
52
|
+
process.exit(code);
|
|
53
|
+
});
|
package/lib/client.js
CHANGED
|
@@ -50,6 +50,7 @@ const path_1 = __importStar(require("path"));
|
|
|
50
50
|
const node_url_1 = require("node:url");
|
|
51
51
|
const uploader_js_1 = require("./uploader.js");
|
|
52
52
|
const utils_js_1 = require("./utils/utils.js");
|
|
53
|
+
const links_js_1 = require("./services/links.js");
|
|
53
54
|
const filesize_1 = require("filesize");
|
|
54
55
|
const debug = (0, debug_1.default)('@testomatio/reporter:client');
|
|
55
56
|
// removed __dirname usage, because:
|
|
@@ -181,7 +182,7 @@ class Client {
|
|
|
181
182
|
/**
|
|
182
183
|
* @type {TestData}
|
|
183
184
|
*/
|
|
184
|
-
const { rid, error = null, time = 0, example = null, files = [], filesBuffers = [], steps, code = null, title, file, suite_title, suite_id, test_id, timestamp, manuallyAttachedArtifacts,
|
|
185
|
+
const { rid, error = null, time = 0, example = null, files = [], filesBuffers = [], steps, code = null, title, file, suite_title, suite_id, test_id, timestamp, manuallyAttachedArtifacts, overwrite, } = testData;
|
|
185
186
|
let { message = '', meta = {} } = testData;
|
|
186
187
|
// stringify meta values and limit keys and values length to 255
|
|
187
188
|
meta = Object.entries(meta)
|
|
@@ -220,7 +221,9 @@ class Client {
|
|
|
220
221
|
acc[key] = value;
|
|
221
222
|
return acc;
|
|
222
223
|
}, {});
|
|
223
|
-
//
|
|
224
|
+
// Get links from storage using the test context
|
|
225
|
+
const testContext = suite_title ? `${suite_title} ${title}` : title;
|
|
226
|
+
const links = links_js_1.linkStorage.get(testContext) || [];
|
|
224
227
|
let errorFormatted = '';
|
|
225
228
|
if (error) {
|
|
226
229
|
errorFormatted += this.formatError(error) || '';
|
|
@@ -268,7 +271,7 @@ class Client {
|
|
|
268
271
|
timestamp,
|
|
269
272
|
artifacts,
|
|
270
273
|
meta,
|
|
271
|
-
|
|
274
|
+
links,
|
|
272
275
|
overwrite,
|
|
273
276
|
...(rootSuiteId && { root_suite_id: rootSuiteId }),
|
|
274
277
|
};
|
package/lib/data-storage.d.ts
CHANGED
|
@@ -12,22 +12,22 @@ declare class DataStorage {
|
|
|
12
12
|
/**
|
|
13
13
|
* Puts any data to storage (file or global variable).
|
|
14
14
|
* If file: stores data as text, if global variable – stores as array of data.
|
|
15
|
-
* @param {'log' | 'artifact' | 'keyvalue' | '
|
|
15
|
+
* @param {'log' | 'artifact' | 'keyvalue' | 'links'} dataType
|
|
16
16
|
* @param {*} data anything you want to store (string, object, array, etc)
|
|
17
17
|
* @param {*} context could be testId or any context (test name, suite name, including their IDs etc)
|
|
18
18
|
* suite name + test name is used by default
|
|
19
19
|
* @returns
|
|
20
20
|
*/
|
|
21
|
-
putData(dataType: "log" | "artifact" | "keyvalue" | "
|
|
21
|
+
putData(dataType: "log" | "artifact" | "keyvalue" | "links", data: any, context?: any): void;
|
|
22
22
|
/**
|
|
23
23
|
* Returns data, stored for specific test/context (or data which was stored without test id specified).
|
|
24
24
|
* This method will get data from global variable and/or from from file (previosly saved with put method).
|
|
25
25
|
*
|
|
26
|
-
* @param {'log' | 'artifact' | 'keyvalue' | '
|
|
26
|
+
* @param {'log' | 'artifact' | 'keyvalue' | 'links'} dataType
|
|
27
27
|
* @param {string} context
|
|
28
28
|
* @returns {any []} array of data (any type), null (if no data found for context) or string (if data type is log)
|
|
29
29
|
*/
|
|
30
|
-
getData(dataType: "log" | "artifact" | "keyvalue" | "
|
|
30
|
+
getData(dataType: "log" | "artifact" | "keyvalue" | "links", context: string): any[];
|
|
31
31
|
#private;
|
|
32
32
|
}
|
|
33
33
|
export function stringToMD5Hash(str: any): string;
|
package/lib/data-storage.js
CHANGED
|
@@ -75,7 +75,7 @@ class DataStorage {
|
|
|
75
75
|
/**
|
|
76
76
|
* Puts any data to storage (file or global variable).
|
|
77
77
|
* If file: stores data as text, if global variable – stores as array of data.
|
|
78
|
-
* @param {'log' | 'artifact' | 'keyvalue' | '
|
|
78
|
+
* @param {'log' | 'artifact' | 'keyvalue' | 'links'} dataType
|
|
79
79
|
* @param {*} data anything you want to store (string, object, array, etc)
|
|
80
80
|
* @param {*} context could be testId or any context (test name, suite name, including their IDs etc)
|
|
81
81
|
* suite name + test name is used by default
|
|
@@ -103,7 +103,7 @@ class DataStorage {
|
|
|
103
103
|
* Returns data, stored for specific test/context (or data which was stored without test id specified).
|
|
104
104
|
* This method will get data from global variable and/or from from file (previosly saved with put method).
|
|
105
105
|
*
|
|
106
|
-
* @param {'log' | 'artifact' | 'keyvalue' | '
|
|
106
|
+
* @param {'log' | 'artifact' | 'keyvalue' | 'links'} dataType
|
|
107
107
|
* @param {string} context
|
|
108
108
|
* @returns {any []} array of data (any type), null (if no data found for context) or string (if data type is log)
|
|
109
109
|
*/
|
|
@@ -134,7 +134,7 @@ class DataStorage {
|
|
|
134
134
|
return null;
|
|
135
135
|
}
|
|
136
136
|
/**
|
|
137
|
-
* @param {'log' | 'artifact' | 'keyvalue' | '
|
|
137
|
+
* @param {'log' | 'artifact' | 'keyvalue' | 'links'} dataType
|
|
138
138
|
* @param {string} context
|
|
139
139
|
* @returns aray of data (any type)
|
|
140
140
|
*/
|
|
@@ -154,7 +154,7 @@ class DataStorage {
|
|
|
154
154
|
}
|
|
155
155
|
}
|
|
156
156
|
/**
|
|
157
|
-
* @param {'log' | 'artifact' | 'keyvalue' | '
|
|
157
|
+
* @param {'log' | 'artifact' | 'keyvalue' | 'links'} dataType
|
|
158
158
|
* @param {*} context
|
|
159
159
|
* @returns array of data (any type)
|
|
160
160
|
*/
|
|
@@ -179,7 +179,7 @@ class DataStorage {
|
|
|
179
179
|
}
|
|
180
180
|
/**
|
|
181
181
|
* Puts data to global variable. Unlike the file storage, stores data in array (file storage just append as string).
|
|
182
|
-
* @param {'log' | 'artifact' | 'keyvalue' | '
|
|
182
|
+
* @param {'log' | 'artifact' | 'keyvalue' | 'links'} dataType
|
|
183
183
|
* @param {*} data
|
|
184
184
|
* @param {*} context
|
|
185
185
|
*/
|
|
@@ -195,7 +195,7 @@ class DataStorage {
|
|
|
195
195
|
}
|
|
196
196
|
/**
|
|
197
197
|
* Puts data to file. Unlike the global variable storage, stores data as string
|
|
198
|
-
* @param {'log' | 'artifact' | 'keyvalue' | '
|
|
198
|
+
* @param {'log' | 'artifact' | 'keyvalue' | 'links'} dataType
|
|
199
199
|
* @param {*} data
|
|
200
200
|
* @param {string} context
|
|
201
201
|
* @returns
|
|
@@ -4,6 +4,7 @@ declare namespace _default {
|
|
|
4
4
|
export { addStep as step };
|
|
5
5
|
export { setKeyValue as keyValue };
|
|
6
6
|
export { setLabel as label };
|
|
7
|
+
export { linkTest };
|
|
7
8
|
}
|
|
8
9
|
export default _default;
|
|
9
10
|
/**
|
|
@@ -39,9 +40,15 @@ declare function setKeyValue(keyValue: {
|
|
|
39
40
|
[key: string]: string;
|
|
40
41
|
} | string, value?: string | null): void;
|
|
41
42
|
/**
|
|
42
|
-
* Add
|
|
43
|
+
* Add label(s) to the test report
|
|
43
44
|
* @param {string} key - label key (e.g. 'severity', 'feature', or just 'smoke' for labels without values)
|
|
44
|
-
* @param {string|null} [value=null] - optional label value (e.g. 'high', 'login')
|
|
45
|
+
* @param {string|string[]|null} [value=null] - optional label value(s) (e.g. 'high', 'login') or array of values
|
|
45
46
|
* @returns {void}
|
|
46
47
|
*/
|
|
47
|
-
declare function setLabel(key: string, value?: string | null): void;
|
|
48
|
+
declare function setLabel(key: string, value?: string | string[] | null): void;
|
|
49
|
+
/**
|
|
50
|
+
* Add link(s) to the test report
|
|
51
|
+
* @param {...string} testIds - test IDs to link
|
|
52
|
+
* @returns {void}
|
|
53
|
+
*/
|
|
54
|
+
declare function linkTest(...testIds: string[]): void;
|
|
@@ -50,40 +50,29 @@ function setKeyValue(keyValue, value = null) {
|
|
|
50
50
|
index_js_1.services.keyValues.put(keyValue);
|
|
51
51
|
}
|
|
52
52
|
/**
|
|
53
|
-
* Add
|
|
53
|
+
* Add label(s) to the test report
|
|
54
54
|
* @param {string} key - label key (e.g. 'severity', 'feature', or just 'smoke' for labels without values)
|
|
55
|
-
* @param {string|null} [value=null] - optional label value (e.g. 'high', 'login')
|
|
55
|
+
* @param {string|string[]|null} [value=null] - optional label value(s) (e.g. 'high', 'login') or array of values
|
|
56
56
|
* @returns {void}
|
|
57
57
|
*/
|
|
58
58
|
function setLabel(key, value = null) {
|
|
59
|
-
if (
|
|
60
|
-
|
|
59
|
+
if (Array.isArray(value)) {
|
|
60
|
+
value.forEach(val => setLabel(key, val));
|
|
61
61
|
return;
|
|
62
62
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
console.warn('Label value is too long, trimmed to 255 characters:', value);
|
|
77
|
-
value = value.substring(0, 255);
|
|
78
|
-
}
|
|
79
|
-
labelString = `${key}:${value}`;
|
|
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
|
-
index_js_1.services.labels.put([labelString]);
|
|
63
|
+
const labelObject = value !== null && value !== undefined && value !== ''
|
|
64
|
+
? { label: `${key}:${value}` }
|
|
65
|
+
: { label: key };
|
|
66
|
+
index_js_1.services.links.put([labelObject]);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Add link(s) to the test report
|
|
70
|
+
* @param {...string} testIds - test IDs to link
|
|
71
|
+
* @returns {void}
|
|
72
|
+
*/
|
|
73
|
+
function linkTest(...testIds) {
|
|
74
|
+
const links = testIds.map(testId => ({ test: testId }));
|
|
75
|
+
index_js_1.services.links.put(links);
|
|
87
76
|
}
|
|
88
77
|
module.exports = {
|
|
89
78
|
artifact: saveArtifact,
|
|
@@ -91,4 +80,5 @@ module.exports = {
|
|
|
91
80
|
step: addStep,
|
|
92
81
|
keyValue: setKeyValue,
|
|
93
82
|
label: setLabel,
|
|
83
|
+
linkTest,
|
|
94
84
|
};
|
package/lib/reporter.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export const artifact: (data: string | {
|
|
|
5
5
|
}, context?: any) => void;
|
|
6
6
|
export const log: (...args: any[]) => void;
|
|
7
7
|
export const logger: {
|
|
8
|
-
"__#
|
|
8
|
+
"__#14@#originalUserLogger": {
|
|
9
9
|
assert(condition?: boolean, ...data: any[]): void;
|
|
10
10
|
assert(value: any, message?: string, ...optionalParams: any[]): void;
|
|
11
11
|
clear(): void;
|
|
@@ -50,13 +50,13 @@ export const logger: {
|
|
|
50
50
|
profile(label?: string): void;
|
|
51
51
|
profileEnd(label?: string): void;
|
|
52
52
|
};
|
|
53
|
-
"__#
|
|
53
|
+
"__#14@#userLoggerWithOverridenMethods": any;
|
|
54
54
|
logLevel: string;
|
|
55
55
|
step(strings: any, ...values: any[]): void;
|
|
56
56
|
getLogs(context: string): string[];
|
|
57
|
-
"__#
|
|
57
|
+
"__#14@#stringifyLogs"(...args: any[]): string;
|
|
58
58
|
_templateLiteralLog(strings: any, ...args: any[]): void;
|
|
59
|
-
"__#
|
|
59
|
+
"__#14@#logWrapper"(argsArray: any, level: any): void;
|
|
60
60
|
assert(...args: any[]): void;
|
|
61
61
|
debug(...args: any[]): void;
|
|
62
62
|
error(...args: any[]): void;
|
|
@@ -76,10 +76,11 @@ export const meta: (keyValue: {
|
|
|
76
76
|
[key: string]: string;
|
|
77
77
|
} | string, value?: string | null) => void;
|
|
78
78
|
export const step: (message: string) => void;
|
|
79
|
-
export const label: (key: string, value?: string | null) => void;
|
|
79
|
+
export const label: (key: string, value?: string | string[] | null) => void;
|
|
80
|
+
export const linkTest: (...testIds: string[]) => void;
|
|
80
81
|
declare namespace _default {
|
|
81
82
|
let testomatioLogger: {
|
|
82
|
-
"__#
|
|
83
|
+
"__#14@#originalUserLogger": {
|
|
83
84
|
assert(condition?: boolean, ...data: any[]): void;
|
|
84
85
|
assert(value: any, message?: string, ...optionalParams: any[]): void;
|
|
85
86
|
clear(): void;
|
|
@@ -124,13 +125,13 @@ declare namespace _default {
|
|
|
124
125
|
profile(label?: string): void;
|
|
125
126
|
profileEnd(label?: string): void;
|
|
126
127
|
};
|
|
127
|
-
"__#
|
|
128
|
+
"__#14@#userLoggerWithOverridenMethods": any;
|
|
128
129
|
logLevel: string;
|
|
129
130
|
step(strings: any, ...values: any[]): void;
|
|
130
131
|
getLogs(context: string): string[];
|
|
131
|
-
"__#
|
|
132
|
+
"__#14@#stringifyLogs"(...args: any[]): string;
|
|
132
133
|
_templateLiteralLog(strings: any, ...args: any[]): void;
|
|
133
|
-
"__#
|
|
134
|
+
"__#14@#logWrapper"(argsArray: any, level: any): void;
|
|
134
135
|
assert(...args: any[]): void;
|
|
135
136
|
debug(...args: any[]): void;
|
|
136
137
|
error(...args: any[]): void;
|
|
@@ -153,7 +154,7 @@ declare namespace _default {
|
|
|
153
154
|
}, context?: any) => void;
|
|
154
155
|
let log: (...args: any[]) => void;
|
|
155
156
|
let logger: {
|
|
156
|
-
"__#
|
|
157
|
+
"__#14@#originalUserLogger": {
|
|
157
158
|
assert(condition?: boolean, ...data: any[]): void;
|
|
158
159
|
assert(value: any, message?: string, ...optionalParams: any[]): void;
|
|
159
160
|
clear(): void;
|
|
@@ -198,13 +199,13 @@ declare namespace _default {
|
|
|
198
199
|
profile(label?: string): void;
|
|
199
200
|
profileEnd(label?: string): void;
|
|
200
201
|
};
|
|
201
|
-
"__#
|
|
202
|
+
"__#14@#userLoggerWithOverridenMethods": any;
|
|
202
203
|
logLevel: string;
|
|
203
204
|
step(strings: any, ...values: any[]): void;
|
|
204
205
|
getLogs(context: string): string[];
|
|
205
|
-
"__#
|
|
206
|
+
"__#14@#stringifyLogs"(...args: any[]): string;
|
|
206
207
|
_templateLiteralLog(strings: any, ...args: any[]): void;
|
|
207
|
-
"__#
|
|
208
|
+
"__#14@#logWrapper"(argsArray: any, level: any): void;
|
|
208
209
|
assert(...args: any[]): void;
|
|
209
210
|
debug(...args: any[]): void;
|
|
210
211
|
error(...args: any[]): void;
|
|
@@ -224,7 +225,8 @@ declare namespace _default {
|
|
|
224
225
|
[key: string]: string;
|
|
225
226
|
} | string, value?: string | null) => void;
|
|
226
227
|
let step: (message: string) => void;
|
|
227
|
-
let label: (key: string, value?: string | null) => void;
|
|
228
|
+
let label: (key: string, value?: string | string[] | null) => void;
|
|
229
|
+
let linkTest: (...testIds: string[]) => void;
|
|
228
230
|
}
|
|
229
231
|
export default _default;
|
|
230
232
|
export type ArtifactFunction = typeof import("./reporter-functions.js").default.artifact;
|
package/lib/reporter.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.label = exports.step = exports.meta = exports.logger = exports.log = exports.artifact = void 0;
|
|
6
|
+
exports.linkTest = exports.label = exports.step = exports.meta = exports.logger = exports.log = exports.artifact = void 0;
|
|
7
7
|
// import TestomatClient from './client.js';
|
|
8
8
|
// import * as TRConstants from './constants.js';
|
|
9
9
|
const index_js_1 = require("./services/index.js");
|
|
@@ -14,6 +14,7 @@ exports.logger = index_js_1.services.logger;
|
|
|
14
14
|
exports.meta = reporter_functions_js_1.default.keyValue;
|
|
15
15
|
exports.step = reporter_functions_js_1.default.step;
|
|
16
16
|
exports.label = reporter_functions_js_1.default.label;
|
|
17
|
+
exports.linkTest = reporter_functions_js_1.default.linkTest;
|
|
17
18
|
/**
|
|
18
19
|
* @typedef {typeof import('./reporter-functions.js').default.artifact} ArtifactFunction
|
|
19
20
|
* @typedef {typeof import('./reporter-functions.js').default.log} LogFunction
|
|
@@ -33,6 +34,7 @@ module.exports = {
|
|
|
33
34
|
meta: reporter_functions_js_1.default.keyValue,
|
|
34
35
|
step: reporter_functions_js_1.default.step,
|
|
35
36
|
label: reporter_functions_js_1.default.label,
|
|
37
|
+
linkTest: reporter_functions_js_1.default.linkTest,
|
|
36
38
|
// TestomatClient,
|
|
37
39
|
// TRConstants,
|
|
38
40
|
};
|
package/lib/services/index.d.ts
CHANGED
|
@@ -2,10 +2,10 @@ export namespace services {
|
|
|
2
2
|
export { logger };
|
|
3
3
|
export { artifactStorage as artifacts };
|
|
4
4
|
export { keyValueStorage as keyValues };
|
|
5
|
-
export {
|
|
5
|
+
export { linkStorage as links };
|
|
6
6
|
export function setContext(context: any): void;
|
|
7
7
|
}
|
|
8
8
|
import { logger } from './logger.js';
|
|
9
9
|
import { artifactStorage } from './artifacts.js';
|
|
10
10
|
import { keyValueStorage } from './key-values.js';
|
|
11
|
-
import {
|
|
11
|
+
import { linkStorage } from './links.js';
|
package/lib/services/index.js
CHANGED
|
@@ -4,13 +4,13 @@ exports.services = void 0;
|
|
|
4
4
|
const logger_js_1 = require("./logger.js");
|
|
5
5
|
const artifacts_js_1 = require("./artifacts.js");
|
|
6
6
|
const key_values_js_1 = require("./key-values.js");
|
|
7
|
-
const
|
|
7
|
+
const links_js_1 = require("./links.js");
|
|
8
8
|
const data_storage_js_1 = require("../data-storage.js");
|
|
9
9
|
exports.services = {
|
|
10
10
|
logger: logger_js_1.logger,
|
|
11
11
|
artifacts: artifacts_js_1.artifactStorage,
|
|
12
12
|
keyValues: key_values_js_1.keyValueStorage,
|
|
13
|
-
|
|
13
|
+
links: links_js_1.linkStorage,
|
|
14
14
|
setContext: context => {
|
|
15
15
|
data_storage_js_1.dataStorage.setContext(context);
|
|
16
16
|
},
|
package/lib/services/labels.d.ts
CHANGED
package/lib/services/labels.js
CHANGED
|
@@ -27,7 +27,7 @@ class LabelStorage {
|
|
|
27
27
|
put(labels, context = null) {
|
|
28
28
|
if (!labels || !Array.isArray(labels))
|
|
29
29
|
return;
|
|
30
|
-
data_storage_js_1.dataStorage.putData('
|
|
30
|
+
data_storage_js_1.dataStorage.putData('links', labels, context);
|
|
31
31
|
}
|
|
32
32
|
/**
|
|
33
33
|
* Returns labels array for the test
|
|
@@ -35,7 +35,7 @@ class LabelStorage {
|
|
|
35
35
|
* @returns {string[]} labels array, e.g. ['smoke', 'severity:high', 'feature:user_account']
|
|
36
36
|
*/
|
|
37
37
|
get(context = null) {
|
|
38
|
-
const labelsList = data_storage_js_1.dataStorage.getData('
|
|
38
|
+
const labelsList = data_storage_js_1.dataStorage.getData('links', context);
|
|
39
39
|
if (!labelsList || !labelsList?.length)
|
|
40
40
|
return [];
|
|
41
41
|
const allLabels = [];
|