@testomatio/reporter 2.1.3-beta.3-multi-links → 2.2.2
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 +3 -3
- package/lib/adapter/mocha.js +14 -0
- package/lib/adapter/webdriver.js +8 -6
- package/lib/bin/cli.js +9 -6
- package/lib/bin/startTest.js +38 -91
- package/lib/client.d.ts +1 -2
- package/lib/client.js +8 -6
- package/lib/data-storage.d.ts +4 -4
- package/lib/data-storage.js +7 -8
- package/lib/pipe/testomatio.d.ts +0 -1
- package/lib/pipe/testomatio.js +4 -8
- package/lib/replay.js +1 -1
- package/lib/reporter-functions.d.ts +20 -7
- package/lib/reporter-functions.js +27 -35
- package/lib/reporter.d.ts +22 -20
- package/lib/reporter.js +9 -7
- 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/logger.d.ts +1 -1
- package/lib/utils/utils.js +3 -1
- package/package.json +1 -1
- package/src/adapter/codecept.js +3 -4
- package/src/adapter/mocha.js +15 -0
- package/src/adapter/webdriver.js +9 -6
- package/src/bin/cli.js +9 -6
- package/src/bin/startTest.js +43 -114
- package/src/client.js +7 -6
- package/src/data-storage.js +7 -9
- package/src/pipe/testomatio.js +4 -7
- package/src/replay.js +1 -1
- package/src/reporter-functions.js +27 -37
- package/src/reporter.js +8 -6
- package/src/services/index.js +2 -2
- package/src/services/labels.js +2 -2
- package/src/services/links.js +69 -0
- package/src/utils/utils.js +5 -3
- package/lib/utils/cli_utils.d.ts +0 -1
- package/lib/utils/cli_utils.js +0 -524304
package/lib/adapter/codecept.js
CHANGED
|
@@ -48,7 +48,6 @@ function CodeceptReporter(config) {
|
|
|
48
48
|
step: output.step,
|
|
49
49
|
say: output.say,
|
|
50
50
|
};
|
|
51
|
-
output.stepShift = 0;
|
|
52
51
|
output.debug = function (msg) {
|
|
53
52
|
originalOutput.debug(msg);
|
|
54
53
|
data_storage_js_1.dataStorage.putData('log', repeat(this?.stepShift || 0) + picocolors_1.default.cyan(msg.toString()));
|
|
@@ -62,6 +61,7 @@ function CodeceptReporter(config) {
|
|
|
62
61
|
originalOutput.log(msg);
|
|
63
62
|
data_storage_js_1.dataStorage.putData('log', repeat(this?.stepShift || 0) + picocolors_1.default.gray(msg));
|
|
64
63
|
};
|
|
64
|
+
output.stepShift = 0;
|
|
65
65
|
recorder.startUnlessRunning();
|
|
66
66
|
const hookSteps = new Map();
|
|
67
67
|
let currentHook = null;
|
|
@@ -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
|
@@ -41,6 +41,7 @@ const client_js_1 = __importDefault(require("../client.js"));
|
|
|
41
41
|
const utils_js_1 = require("../utils/utils.js");
|
|
42
42
|
const index_js_1 = require("../services/index.js");
|
|
43
43
|
const constants_js_1 = require("../constants.js");
|
|
44
|
+
const data_storage_js_1 = require("../data-storage.js");
|
|
44
45
|
class WebdriverReporter extends reporter_1.default {
|
|
45
46
|
constructor(options) {
|
|
46
47
|
super(options);
|
|
@@ -77,12 +78,12 @@ class WebdriverReporter extends reporter_1.default {
|
|
|
77
78
|
onTestEnd(test) {
|
|
78
79
|
test.suite = test.parent;
|
|
79
80
|
const logs = getTestLogs(test.fullTitle);
|
|
80
|
-
//
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
// still be under investigation
|
|
82
|
+
const artifacts = index_js_1.services.artifacts.get(test.fullTitle);
|
|
83
|
+
const keyValues = index_js_1.services.keyValues.get(test.fullTitle);
|
|
83
84
|
test.logs = logs;
|
|
84
|
-
|
|
85
|
-
|
|
85
|
+
test.artifacts = artifacts;
|
|
86
|
+
test.meta = keyValues;
|
|
86
87
|
this._addTestPromises.push(this.addTest(test));
|
|
87
88
|
}
|
|
88
89
|
// wdio-cucumber does not trigger onTestEnd hook, thus, using this one
|
|
@@ -100,8 +101,9 @@ class WebdriverReporter extends reporter_1.default {
|
|
|
100
101
|
const screenshotsBuffers = output
|
|
101
102
|
.filter(el => el.endpoint === screenshotEndpoint && el.result && el.result.value)
|
|
102
103
|
.map(el => Buffer.from(el.result.value, 'base64'));
|
|
104
|
+
const rid = (0, data_storage_js_1.stringToMD5Hash)(test.fullTitle);
|
|
103
105
|
await this.client.addTestRun(state, {
|
|
104
|
-
rid
|
|
106
|
+
rid,
|
|
105
107
|
manuallyAttachedArtifacts: test.artifacts,
|
|
106
108
|
error,
|
|
107
109
|
logs: test.logs,
|
package/lib/bin/cli.js
CHANGED
|
@@ -78,7 +78,7 @@ program
|
|
|
78
78
|
console.log(constants_js_1.APP_PREFIX, `No command provided. Use -c option to launch a test runner.`);
|
|
79
79
|
return process.exit(255);
|
|
80
80
|
}
|
|
81
|
-
const client = new client_js_1.default({ apiKey, title
|
|
81
|
+
const client = new client_js_1.default({ apiKey, title });
|
|
82
82
|
if (opts.filter) {
|
|
83
83
|
const [pipe, ...optsArray] = opts.filter.split(':');
|
|
84
84
|
const pipeOptions = optsArray.join(':');
|
|
@@ -95,13 +95,16 @@ program
|
|
|
95
95
|
console.log(constants_js_1.APP_PREFIX, `🚀 Running`, picocolors_1.default.green(command));
|
|
96
96
|
const runTests = async () => {
|
|
97
97
|
const testCmds = command.split(' ');
|
|
98
|
-
const cmd = (0, cross_spawn_1.spawn)(testCmds[0], testCmds.slice(1), {
|
|
98
|
+
const cmd = (0, cross_spawn_1.spawn)(testCmds[0], testCmds.slice(1), {
|
|
99
|
+
stdio: 'inherit',
|
|
100
|
+
env: { ...process.env, TESTOMATIO_PROCEED: 'true', runId: client.runId },
|
|
101
|
+
});
|
|
99
102
|
cmd.on('close', async (code) => {
|
|
100
103
|
const emoji = code === 0 ? '🟢' : '🔴';
|
|
101
104
|
console.log(constants_js_1.APP_PREFIX, emoji, `Runner exited with ${picocolors_1.default.bold(code)}`);
|
|
102
105
|
if (apiKey) {
|
|
103
106
|
const status = code === 0 ? 'passed' : 'failed';
|
|
104
|
-
await client.updateRunStatus(status
|
|
107
|
+
await client.updateRunStatus(status);
|
|
105
108
|
}
|
|
106
109
|
process.exit(code);
|
|
107
110
|
});
|
|
@@ -257,13 +260,13 @@ program
|
|
|
257
260
|
const replayService = new replay_js_1.default({
|
|
258
261
|
apiKey: config_js_1.config.TESTOMATIO,
|
|
259
262
|
dryRun: opts.dryRun,
|
|
260
|
-
onLog:
|
|
261
|
-
onError:
|
|
263
|
+
onLog: message => console.log(constants_js_1.APP_PREFIX, message),
|
|
264
|
+
onError: message => console.error(constants_js_1.APP_PREFIX, '⚠️ ', message),
|
|
262
265
|
onProgress: ({ current, total }) => {
|
|
263
266
|
if (current % 10 === 0 || current === total) {
|
|
264
267
|
console.log(constants_js_1.APP_PREFIX, `📊 Progress: ${current}/${total} tests processed`);
|
|
265
268
|
}
|
|
266
|
-
}
|
|
269
|
+
},
|
|
267
270
|
});
|
|
268
271
|
const result = await replayService.replay(debugFile);
|
|
269
272
|
if (result.dryRun) {
|
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.d.ts
CHANGED
|
@@ -58,10 +58,9 @@ export class Client {
|
|
|
58
58
|
* Updates the status of the current test run and finishes the run.
|
|
59
59
|
* @param {'passed' | 'failed' | 'skipped' | 'finished'} status - The status of the current test run.
|
|
60
60
|
* Must be one of "passed", "failed", or "finished"
|
|
61
|
-
* @param {boolean} [isParallel] - Whether the current test run was executed in parallel with other tests.
|
|
62
61
|
* @returns {Promise<any>} - A Promise that resolves when finishes the run.
|
|
63
62
|
*/
|
|
64
|
-
updateRunStatus(status: "passed" | "failed" | "skipped" | "finished"
|
|
63
|
+
updateRunStatus(status: "passed" | "failed" | "skipped" | "finished"): Promise<any>;
|
|
65
64
|
/**
|
|
66
65
|
* Returns the formatted stack including the stack trace, steps, and logs.
|
|
67
66
|
* @returns {string}
|
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
|
};
|
|
@@ -291,17 +294,16 @@ class Client {
|
|
|
291
294
|
* Updates the status of the current test run and finishes the run.
|
|
292
295
|
* @param {'passed' | 'failed' | 'skipped' | 'finished'} status - The status of the current test run.
|
|
293
296
|
* Must be one of "passed", "failed", or "finished"
|
|
294
|
-
* @param {boolean} [isParallel] - Whether the current test run was executed in parallel with other tests.
|
|
295
297
|
* @returns {Promise<any>} - A Promise that resolves when finishes the run.
|
|
296
298
|
*/
|
|
297
|
-
async updateRunStatus(status
|
|
299
|
+
async updateRunStatus(status) {
|
|
298
300
|
this.pipes ||= await (0, index_js_1.pipesFactory)(this.paramsForPipesFactory || {}, this.pipeStore);
|
|
299
301
|
this.runId ||= (0, utils_js_1.readLatestRunId)();
|
|
300
302
|
debug('Updating run status...');
|
|
301
303
|
// all pipes disabled, skipping
|
|
302
304
|
if (!this.pipes?.filter(p => p.isEnabled).length)
|
|
303
305
|
return Promise.resolve();
|
|
304
|
-
const runParams = { status
|
|
306
|
+
const runParams = { status };
|
|
305
307
|
this.queue = this.queue
|
|
306
308
|
.then(() => Promise.all(this.pipes.map(p => p.finishRun(runParams))))
|
|
307
309
|
.then(() => {
|
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
|
@@ -45,7 +45,6 @@ const os_1 = __importDefault(require("os"));
|
|
|
45
45
|
const constants_js_1 = require("./constants.js");
|
|
46
46
|
const utils_js_1 = require("./utils/utils.js");
|
|
47
47
|
const crypto_1 = __importDefault(require("crypto"));
|
|
48
|
-
const startTime = Date.now();
|
|
49
48
|
const debug = (0, debug_1.default)('@testomatio/reporter:storage');
|
|
50
49
|
class DataStorage {
|
|
51
50
|
static #instance;
|
|
@@ -76,7 +75,7 @@ class DataStorage {
|
|
|
76
75
|
/**
|
|
77
76
|
* Puts any data to storage (file or global variable).
|
|
78
77
|
* If file: stores data as text, if global variable – stores as array of data.
|
|
79
|
-
* @param {'log' | 'artifact' | 'keyvalue' | '
|
|
78
|
+
* @param {'log' | 'artifact' | 'keyvalue' | 'links'} dataType
|
|
80
79
|
* @param {*} data anything you want to store (string, object, array, etc)
|
|
81
80
|
* @param {*} context could be testId or any context (test name, suite name, including their IDs etc)
|
|
82
81
|
* suite name + test name is used by default
|
|
@@ -104,7 +103,7 @@ class DataStorage {
|
|
|
104
103
|
* Returns data, stored for specific test/context (or data which was stored without test id specified).
|
|
105
104
|
* This method will get data from global variable and/or from from file (previosly saved with put method).
|
|
106
105
|
*
|
|
107
|
-
* @param {'log' | 'artifact' | 'keyvalue' | '
|
|
106
|
+
* @param {'log' | 'artifact' | 'keyvalue' | 'links'} dataType
|
|
108
107
|
* @param {string} context
|
|
109
108
|
* @returns {any []} array of data (any type), null (if no data found for context) or string (if data type is log)
|
|
110
109
|
*/
|
|
@@ -135,7 +134,7 @@ class DataStorage {
|
|
|
135
134
|
return null;
|
|
136
135
|
}
|
|
137
136
|
/**
|
|
138
|
-
* @param {'log' | 'artifact' | 'keyvalue' | '
|
|
137
|
+
* @param {'log' | 'artifact' | 'keyvalue' | 'links'} dataType
|
|
139
138
|
* @param {string} context
|
|
140
139
|
* @returns aray of data (any type)
|
|
141
140
|
*/
|
|
@@ -155,7 +154,7 @@ class DataStorage {
|
|
|
155
154
|
}
|
|
156
155
|
}
|
|
157
156
|
/**
|
|
158
|
-
* @param {'log' | 'artifact' | 'keyvalue' | '
|
|
157
|
+
* @param {'log' | 'artifact' | 'keyvalue' | 'links'} dataType
|
|
159
158
|
* @param {*} context
|
|
160
159
|
* @returns array of data (any type)
|
|
161
160
|
*/
|
|
@@ -180,7 +179,7 @@ class DataStorage {
|
|
|
180
179
|
}
|
|
181
180
|
/**
|
|
182
181
|
* Puts data to global variable. Unlike the file storage, stores data in array (file storage just append as string).
|
|
183
|
-
* @param {'log' | 'artifact' | 'keyvalue' | '
|
|
182
|
+
* @param {'log' | 'artifact' | 'keyvalue' | 'links'} dataType
|
|
184
183
|
* @param {*} data
|
|
185
184
|
* @param {*} context
|
|
186
185
|
*/
|
|
@@ -196,7 +195,7 @@ class DataStorage {
|
|
|
196
195
|
}
|
|
197
196
|
/**
|
|
198
197
|
* Puts data to file. Unlike the global variable storage, stores data as string
|
|
199
|
-
* @param {'log' | 'artifact' | 'keyvalue' | '
|
|
198
|
+
* @param {'log' | 'artifact' | 'keyvalue' | 'links'} dataType
|
|
200
199
|
* @param {*} data
|
|
201
200
|
* @param {string} context
|
|
202
201
|
* @returns
|
|
@@ -223,7 +222,7 @@ function stringToMD5Hash(str) {
|
|
|
223
222
|
const md5 = crypto_1.default.createHash('md5');
|
|
224
223
|
md5.update(str);
|
|
225
224
|
const hash = md5.digest('hex');
|
|
226
|
-
return
|
|
225
|
+
return hash;
|
|
227
226
|
}
|
|
228
227
|
exports.dataStorage = DataStorage.getInstance();
|
|
229
228
|
// TODO: consider using fs promises instead of writeSync/appendFileSync to
|
package/lib/pipe/testomatio.d.ts
CHANGED
package/lib/pipe/testomatio.js
CHANGED
|
@@ -43,7 +43,6 @@ class TestomatioPipe {
|
|
|
43
43
|
debug('Testomatio Pipe: Enabled');
|
|
44
44
|
const proxyUrl = process.env.HTTP_PROXY || process.env.HTTPS_PROXY;
|
|
45
45
|
const proxy = proxyUrl ? new URL(proxyUrl) : null;
|
|
46
|
-
this.parallel = params.parallel;
|
|
47
46
|
this.store = store || {};
|
|
48
47
|
this.title = params.title || process.env.TESTOMATIO_TITLE;
|
|
49
48
|
this.sharedRun = !!process.env.TESTOMATIO_SHARED_RUN;
|
|
@@ -113,8 +112,7 @@ class TestomatioPipe {
|
|
|
113
112
|
const resp = await this.client.request({
|
|
114
113
|
method: 'GET',
|
|
115
114
|
url: '/api/test_grep',
|
|
116
|
-
|
|
117
|
-
responseType: q.responseType
|
|
115
|
+
...q,
|
|
118
116
|
});
|
|
119
117
|
if (Array.isArray(resp.data?.tests) && resp.data?.tests?.length > 0) {
|
|
120
118
|
(0, utils_js_1.foundedTestLog)(constants_js_1.APP_PREFIX, resp.data.tests);
|
|
@@ -155,7 +153,6 @@ class TestomatioPipe {
|
|
|
155
153
|
const accessEvent = process.env.TESTOMATIO_PUBLISH ? 'publish' : null;
|
|
156
154
|
const runParams = Object.fromEntries(Object.entries({
|
|
157
155
|
ci_build_url: buildUrl,
|
|
158
|
-
parallel: this.parallel,
|
|
159
156
|
api_key: this.apiKey.trim(),
|
|
160
157
|
group_title: this.groupTitle,
|
|
161
158
|
access_event: accessEvent,
|
|
@@ -173,7 +170,8 @@ class TestomatioPipe {
|
|
|
173
170
|
const resp = await this.client.request({
|
|
174
171
|
method: 'PUT',
|
|
175
172
|
url: `/api/reporter/${this.runId}`,
|
|
176
|
-
data: runParams
|
|
173
|
+
data: runParams,
|
|
174
|
+
responseType: 'json'
|
|
177
175
|
});
|
|
178
176
|
if (resp.data.artifacts)
|
|
179
177
|
(0, pipe_utils_js_1.setS3Credentials)(resp.data.artifacts);
|
|
@@ -377,7 +375,7 @@ class TestomatioPipe {
|
|
|
377
375
|
const errorMessage = picocolors_1.default.red(`⚠️ Due to request failures, ${this.notReportedTestsCount} test(s) were not reported to Testomat.io`);
|
|
378
376
|
console.warn(`${constants_js_1.APP_PREFIX} ${errorMessage}`);
|
|
379
377
|
}
|
|
380
|
-
const { status
|
|
378
|
+
const { status } = params;
|
|
381
379
|
let status_event;
|
|
382
380
|
if (status === constants_js_1.STATUS.FINISHED)
|
|
383
381
|
status_event = 'finish';
|
|
@@ -385,8 +383,6 @@ class TestomatioPipe {
|
|
|
385
383
|
status_event = 'pass';
|
|
386
384
|
if (status === constants_js_1.STATUS.FAILED)
|
|
387
385
|
status_event = 'fail';
|
|
388
|
-
if (parallel)
|
|
389
|
-
status_event += '_parallel';
|
|
390
386
|
try {
|
|
391
387
|
if (this.runId && !this.proceed) {
|
|
392
388
|
await this.client.request({
|
package/lib/replay.js
CHANGED
|
@@ -238,7 +238,7 @@ class Replay {
|
|
|
238
238
|
});
|
|
239
239
|
}
|
|
240
240
|
}
|
|
241
|
-
await client.updateRunStatus(finishParams.status || constants_js_1.STATUS.FINISHED
|
|
241
|
+
await client.updateRunStatus(finishParams.status || constants_js_1.STATUS.FINISHED);
|
|
242
242
|
const result = {
|
|
243
243
|
success: true,
|
|
244
244
|
testsCount: tests.length,
|
|
@@ -4,11 +4,14 @@ 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
|
/**
|
|
10
11
|
* Stores path to file as artifact and uploads it to the S3 storage
|
|
11
12
|
* @param {string | {path: string, type: string, name: string}} data - path to file or object with path, type and name
|
|
13
|
+
* @param {any} [context=null] - optional context parameter
|
|
14
|
+
* @returns {void}
|
|
12
15
|
*/
|
|
13
16
|
declare function saveArtifact(data: string | {
|
|
14
17
|
path: string;
|
|
@@ -17,25 +20,35 @@ declare function saveArtifact(data: string | {
|
|
|
17
20
|
}, context?: any): void;
|
|
18
21
|
/**
|
|
19
22
|
* Attach log message(s) to the test report
|
|
20
|
-
* @param
|
|
23
|
+
* @param {...any} args - log messages to attach
|
|
24
|
+
* @returns {void}
|
|
21
25
|
*/
|
|
22
26
|
declare function logMessage(...args: any[]): void;
|
|
23
27
|
/**
|
|
24
28
|
* Similar to "log" function but marks message in report as a step
|
|
25
|
-
* @param {string} message
|
|
29
|
+
* @param {string} message - step message
|
|
30
|
+
* @returns {void}
|
|
26
31
|
*/
|
|
27
32
|
declare function addStep(message: string): void;
|
|
28
33
|
/**
|
|
29
34
|
* Add key-value pair(s) to the test report
|
|
30
|
-
* @param {{[key: string]: string} | string} keyValue object { key: value } (multiple props allowed) or key (string)
|
|
31
|
-
* @param {string
|
|
35
|
+
* @param {{[key: string]: string} | string} keyValue - object { key: value } (multiple props allowed) or key (string)
|
|
36
|
+
* @param {string|null} [value=null] - optional value when keyValue is a string
|
|
37
|
+
* @returns {void}
|
|
32
38
|
*/
|
|
33
39
|
declare function setKeyValue(keyValue: {
|
|
34
40
|
[key: string]: string;
|
|
35
41
|
} | string, value?: string | null): void;
|
|
36
42
|
/**
|
|
37
|
-
* Add
|
|
43
|
+
* Add label(s) to the test report
|
|
38
44
|
* @param {string} key - label key (e.g. 'severity', 'feature', or just 'smoke' for labels without values)
|
|
39
|
-
* @param {string} [value] - 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
|
|
46
|
+
* @returns {void}
|
|
40
47
|
*/
|
|
41
|
-
declare function setLabel(key: string, value?: string): 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;
|