@testomatio/reporter 2.1.3-beta.1-multi-links → 2.2.1
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 +6 -5
- 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/pipe/testomatio.js +3 -3
- 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 +6 -5
- 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/pipe/testomatio.js +3 -3
- 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 -65552
package/lib/reporter.d.ts
CHANGED
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
export type artifact = typeof import("./reporter-functions.js");
|
|
2
1
|
export const artifact: (data: string | {
|
|
3
2
|
path: string;
|
|
4
3
|
type: string;
|
|
5
4
|
name: string;
|
|
6
5
|
}, context?: any) => void;
|
|
7
|
-
export type log = typeof import("./reporter-functions.js");
|
|
8
6
|
export const log: (...args: any[]) => void;
|
|
9
|
-
export type logger = typeof import("./services/index.js");
|
|
10
7
|
export const logger: {
|
|
11
|
-
"__#
|
|
8
|
+
"__#14@#originalUserLogger": {
|
|
12
9
|
assert(condition?: boolean, ...data: any[]): void;
|
|
13
10
|
assert(value: any, message?: string, ...optionalParams: any[]): void;
|
|
14
11
|
clear(): void;
|
|
@@ -53,13 +50,13 @@ export const logger: {
|
|
|
53
50
|
profile(label?: string): void;
|
|
54
51
|
profileEnd(label?: string): void;
|
|
55
52
|
};
|
|
56
|
-
"__#
|
|
53
|
+
"__#14@#userLoggerWithOverridenMethods": any;
|
|
57
54
|
logLevel: string;
|
|
58
55
|
step(strings: any, ...values: any[]): void;
|
|
59
56
|
getLogs(context: string): string[];
|
|
60
|
-
"__#
|
|
57
|
+
"__#14@#stringifyLogs"(...args: any[]): string;
|
|
61
58
|
_templateLiteralLog(strings: any, ...args: any[]): void;
|
|
62
|
-
"__#
|
|
59
|
+
"__#14@#logWrapper"(argsArray: any, level: any): void;
|
|
63
60
|
assert(...args: any[]): void;
|
|
64
61
|
debug(...args: any[]): void;
|
|
65
62
|
error(...args: any[]): void;
|
|
@@ -75,17 +72,15 @@ export const logger: {
|
|
|
75
72
|
}): void;
|
|
76
73
|
prettyObjects: boolean;
|
|
77
74
|
};
|
|
78
|
-
export type meta = typeof import("./reporter-functions.js");
|
|
79
75
|
export const meta: (keyValue: {
|
|
80
76
|
[key: string]: string;
|
|
81
77
|
} | string, value?: string | null) => void;
|
|
82
|
-
export type step = typeof import("./reporter-functions.js");
|
|
83
78
|
export const step: (message: string) => void;
|
|
84
|
-
export
|
|
85
|
-
export const
|
|
79
|
+
export const label: (key: string, value?: string | string[] | null) => void;
|
|
80
|
+
export const linkTest: (...testIds: string[]) => void;
|
|
86
81
|
declare namespace _default {
|
|
87
82
|
let testomatioLogger: {
|
|
88
|
-
"__#
|
|
83
|
+
"__#14@#originalUserLogger": {
|
|
89
84
|
assert(condition?: boolean, ...data: any[]): void;
|
|
90
85
|
assert(value: any, message?: string, ...optionalParams: any[]): void;
|
|
91
86
|
clear(): void;
|
|
@@ -130,13 +125,13 @@ declare namespace _default {
|
|
|
130
125
|
profile(label?: string): void;
|
|
131
126
|
profileEnd(label?: string): void;
|
|
132
127
|
};
|
|
133
|
-
"__#
|
|
128
|
+
"__#14@#userLoggerWithOverridenMethods": any;
|
|
134
129
|
logLevel: string;
|
|
135
130
|
step(strings: any, ...values: any[]): void;
|
|
136
131
|
getLogs(context: string): string[];
|
|
137
|
-
"__#
|
|
132
|
+
"__#14@#stringifyLogs"(...args: any[]): string;
|
|
138
133
|
_templateLiteralLog(strings: any, ...args: any[]): void;
|
|
139
|
-
"__#
|
|
134
|
+
"__#14@#logWrapper"(argsArray: any, level: any): void;
|
|
140
135
|
assert(...args: any[]): void;
|
|
141
136
|
debug(...args: any[]): void;
|
|
142
137
|
error(...args: any[]): void;
|
|
@@ -159,7 +154,7 @@ declare namespace _default {
|
|
|
159
154
|
}, context?: any) => void;
|
|
160
155
|
let log: (...args: any[]) => void;
|
|
161
156
|
let logger: {
|
|
162
|
-
"__#
|
|
157
|
+
"__#14@#originalUserLogger": {
|
|
163
158
|
assert(condition?: boolean, ...data: any[]): void;
|
|
164
159
|
assert(value: any, message?: string, ...optionalParams: any[]): void;
|
|
165
160
|
clear(): void;
|
|
@@ -204,13 +199,13 @@ declare namespace _default {
|
|
|
204
199
|
profile(label?: string): void;
|
|
205
200
|
profileEnd(label?: string): void;
|
|
206
201
|
};
|
|
207
|
-
"__#
|
|
202
|
+
"__#14@#userLoggerWithOverridenMethods": any;
|
|
208
203
|
logLevel: string;
|
|
209
204
|
step(strings: any, ...values: any[]): void;
|
|
210
205
|
getLogs(context: string): string[];
|
|
211
|
-
"__#
|
|
206
|
+
"__#14@#stringifyLogs"(...args: any[]): string;
|
|
212
207
|
_templateLiteralLog(strings: any, ...args: any[]): void;
|
|
213
|
-
"__#
|
|
208
|
+
"__#14@#logWrapper"(argsArray: any, level: any): void;
|
|
214
209
|
assert(...args: any[]): void;
|
|
215
210
|
debug(...args: any[]): void;
|
|
216
211
|
error(...args: any[]): void;
|
|
@@ -230,6 +225,13 @@ declare namespace _default {
|
|
|
230
225
|
[key: string]: string;
|
|
231
226
|
} | string, value?: string | null) => void;
|
|
232
227
|
let step: (message: string) => void;
|
|
233
|
-
let label: (key: string, value?: string) => void;
|
|
228
|
+
let label: (key: string, value?: string | string[] | null) => void;
|
|
229
|
+
let linkTest: (...testIds: string[]) => void;
|
|
234
230
|
}
|
|
235
231
|
export default _default;
|
|
232
|
+
export type ArtifactFunction = typeof import("./reporter-functions.js").default.artifact;
|
|
233
|
+
export type LogFunction = typeof import("./reporter-functions.js").default.log;
|
|
234
|
+
export type LoggerService = typeof import("./services/index.js").services.logger;
|
|
235
|
+
export type MetaFunction = typeof import("./reporter-functions.js").default.keyValue;
|
|
236
|
+
export type StepFunction = typeof import("./reporter-functions.js").default.step;
|
|
237
|
+
export type LabelFunction = typeof import("./reporter-functions.js").default.label;
|
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,13 +14,14 @@ 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
|
-
* @typedef {import('./reporter-functions.js')}
|
|
19
|
-
* @typedef {import('./reporter-functions.js')}
|
|
20
|
-
* @typedef {import('./services/index.js')}
|
|
21
|
-
* @typedef {import('./reporter-functions.js')}
|
|
22
|
-
* @typedef {import('./reporter-functions.js')}
|
|
23
|
-
* @typedef {import('./reporter-functions.js')}
|
|
19
|
+
* @typedef {typeof import('./reporter-functions.js').default.artifact} ArtifactFunction
|
|
20
|
+
* @typedef {typeof import('./reporter-functions.js').default.log} LogFunction
|
|
21
|
+
* @typedef {typeof import('./services/index.js').services.logger} LoggerService
|
|
22
|
+
* @typedef {typeof import('./reporter-functions.js').default.keyValue} MetaFunction
|
|
23
|
+
* @typedef {typeof import('./reporter-functions.js').default.step} StepFunction
|
|
24
|
+
* @typedef {typeof import('./reporter-functions.js').default.label} LabelFunction
|
|
24
25
|
*/
|
|
25
26
|
module.exports = {
|
|
26
27
|
/**
|
|
@@ -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 = [];
|
package/lib/services/logger.d.ts
CHANGED
package/lib/utils/utils.js
CHANGED
|
@@ -321,7 +321,7 @@ const fileSystem = {
|
|
|
321
321
|
exports.fileSystem = fileSystem;
|
|
322
322
|
const foundedTestLog = (app, tests) => {
|
|
323
323
|
const n = tests.length;
|
|
324
|
-
return
|
|
324
|
+
return console.log(app, `✅ We found ${n === 1 ? 'one test' : `${n} tests`} in Testomat.io!`);
|
|
325
325
|
};
|
|
326
326
|
exports.foundedTestLog = foundedTestLog;
|
|
327
327
|
const humanize = text => {
|
|
@@ -399,6 +399,8 @@ function storeRunId(runId) {
|
|
|
399
399
|
function readLatestRunId() {
|
|
400
400
|
try {
|
|
401
401
|
const filePath = path_1.default.join(os_1.default.tmpdir(), `testomatio.latest.run`);
|
|
402
|
+
if (!fs_1.default.existsSync(filePath))
|
|
403
|
+
return null;
|
|
402
404
|
const stats = fs_1.default.statSync(filePath);
|
|
403
405
|
const diff = +new Date() - +stats.mtime;
|
|
404
406
|
const diffHours = diff / 1000 / 60 / 60;
|
package/package.json
CHANGED
package/src/adapter/codecept.js
CHANGED
|
@@ -56,19 +56,20 @@ function CodeceptReporter(config) {
|
|
|
56
56
|
|
|
57
57
|
output.debug = function(msg) {
|
|
58
58
|
originalOutput.debug(msg);
|
|
59
|
-
dataStorage.putData('log', repeat(this
|
|
59
|
+
dataStorage.putData('log', repeat(this?.stepShift || 0) + pc.cyan(msg.toString()));
|
|
60
60
|
};
|
|
61
61
|
|
|
62
62
|
output.say = function(message, color = 'cyan') {
|
|
63
63
|
originalOutput.say(message, color);
|
|
64
|
-
const sayMsg = repeat(this
|
|
64
|
+
const sayMsg = repeat(this?.stepShift || 0) + ` ${pc.bold(pc[color](message))}`;
|
|
65
65
|
dataStorage.putData('log', sayMsg);
|
|
66
66
|
};
|
|
67
67
|
|
|
68
68
|
output.log = function(msg) {
|
|
69
69
|
originalOutput.log(msg);
|
|
70
|
-
dataStorage.putData('log', repeat(this
|
|
70
|
+
dataStorage.putData('log', repeat(this?.stepShift || 0) + pc.gray(msg));
|
|
71
71
|
};
|
|
72
|
+
output.stepShift = 0;
|
|
72
73
|
|
|
73
74
|
recorder.startUnlessRunning();
|
|
74
75
|
|
|
@@ -162,7 +163,7 @@ function CodeceptReporter(config) {
|
|
|
162
163
|
const manuallyAttachedArtifacts = services.artifacts.get(test.fullTitle());
|
|
163
164
|
const keyValues = services.keyValues.get(test.fullTitle());
|
|
164
165
|
const stepHierarchy = buildUnifiedStepHierarchy(test.steps, hookSteps);
|
|
165
|
-
const
|
|
166
|
+
const links = services.links.get(test.fullTitle());
|
|
166
167
|
|
|
167
168
|
services.setContext(null);
|
|
168
169
|
|
|
@@ -177,7 +178,7 @@ function CodeceptReporter(config) {
|
|
|
177
178
|
files,
|
|
178
179
|
steps: stepHierarchy, // Array of step objects per API schema
|
|
179
180
|
logs,
|
|
180
|
-
|
|
181
|
+
links,
|
|
181
182
|
manuallyAttachedArtifacts,
|
|
182
183
|
meta: { ...keyValues, ...test.meta },
|
|
183
184
|
});
|
package/src/adapter/mocha.js
CHANGED
|
@@ -61,6 +61,7 @@ function MochaReporter(runner, opts) {
|
|
|
61
61
|
const logs = getTestLogs(test);
|
|
62
62
|
const artifacts = services.artifacts.get(test.fullTitle());
|
|
63
63
|
const keyValues = services.keyValues.get(test.fullTitle());
|
|
64
|
+
const links = services.links.get(test.fullTitle());
|
|
64
65
|
|
|
65
66
|
client.addTestRun(STATUS.PASSED, {
|
|
66
67
|
test_id: testId,
|
|
@@ -72,6 +73,7 @@ function MochaReporter(runner, opts) {
|
|
|
72
73
|
logs,
|
|
73
74
|
manuallyAttachedArtifacts: artifacts,
|
|
74
75
|
meta: keyValues,
|
|
76
|
+
links,
|
|
75
77
|
});
|
|
76
78
|
});
|
|
77
79
|
|
|
@@ -79,6 +81,10 @@ function MochaReporter(runner, opts) {
|
|
|
79
81
|
skipped += 1;
|
|
80
82
|
console.log('skip: %s', test.fullTitle());
|
|
81
83
|
const testId = getTestomatIdFromTestTitle(test.title);
|
|
84
|
+
const artifacts = services.artifacts.get(test.fullTitle());
|
|
85
|
+
const keyValues = services.keyValues.get(test.fullTitle());
|
|
86
|
+
const links = services.links.get(test.fullTitle());
|
|
87
|
+
|
|
82
88
|
client.addTestRun(STATUS.SKIPPED, {
|
|
83
89
|
title: getTestName(test),
|
|
84
90
|
suite_title: getSuiteTitle(test),
|
|
@@ -86,6 +92,9 @@ function MochaReporter(runner, opts) {
|
|
|
86
92
|
file: getFile(test),
|
|
87
93
|
test_id: testId,
|
|
88
94
|
time: test.duration,
|
|
95
|
+
manuallyAttachedArtifacts: artifacts,
|
|
96
|
+
meta: keyValues,
|
|
97
|
+
links,
|
|
89
98
|
});
|
|
90
99
|
});
|
|
91
100
|
|
|
@@ -95,6 +104,9 @@ function MochaReporter(runner, opts) {
|
|
|
95
104
|
const testId = getTestomatIdFromTestTitle(test.title);
|
|
96
105
|
|
|
97
106
|
const logs = getTestLogs(test);
|
|
107
|
+
const artifacts = services.artifacts.get(test.fullTitle());
|
|
108
|
+
const keyValues = services.keyValues.get(test.fullTitle());
|
|
109
|
+
const links = services.links.get(test.fullTitle());
|
|
98
110
|
|
|
99
111
|
client.addTestRun(STATUS.FAILED, {
|
|
100
112
|
error: err,
|
|
@@ -105,6 +117,9 @@ function MochaReporter(runner, opts) {
|
|
|
105
117
|
code: process.env.TESTOMATIO_UPDATE_CODE ? test.body.toString() : '',
|
|
106
118
|
time: test.duration,
|
|
107
119
|
logs,
|
|
120
|
+
manuallyAttachedArtifacts: artifacts,
|
|
121
|
+
meta: keyValues,
|
|
122
|
+
links,
|
|
108
123
|
});
|
|
109
124
|
});
|
|
110
125
|
|
package/src/adapter/webdriver.js
CHANGED
|
@@ -53,11 +53,13 @@ class WebdriverReporter extends WDIOReporter {
|
|
|
53
53
|
test.suite = test.parent;
|
|
54
54
|
const logs = getTestLogs(test.fullTitle);
|
|
55
55
|
// TODO: FIX: artifacts for some reason leads to empty report on Testomat.io
|
|
56
|
-
//
|
|
57
|
-
//
|
|
56
|
+
// ^ not reproduced anymore (Jul 2025)
|
|
57
|
+
// but still be under investigation
|
|
58
|
+
const artifacts = services.artifacts.get(test.fullTitle);
|
|
59
|
+
const keyValues = services.keyValues.get(test.fullTitle);
|
|
58
60
|
test.logs = logs;
|
|
59
|
-
|
|
60
|
-
|
|
61
|
+
test.artifacts = artifacts;
|
|
62
|
+
test.meta = keyValues;
|
|
61
63
|
|
|
62
64
|
this._addTestPromises.push(this.addTest(test));
|
|
63
65
|
}
|
package/src/bin/startTest.js
CHANGED
|
@@ -1,124 +1,53 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { spawn } from '
|
|
3
|
-
import {
|
|
4
|
-
import pc from 'picocolors';
|
|
5
|
-
import TestomatClient from '../client.js';
|
|
6
|
-
import { APP_PREFIX, STATUS } from '../constants.js';
|
|
2
|
+
import { spawn } from 'node:child_process';
|
|
3
|
+
import { join, dirname } from 'node:path';
|
|
7
4
|
import { getPackageVersion } from '../utils/utils.js';
|
|
8
|
-
import
|
|
9
|
-
|
|
5
|
+
import pc from 'picocolors';
|
|
6
|
+
|
|
7
|
+
// Define __dirname - this will be replaced by build script with actual __dirname for CommonJS
|
|
8
|
+
const __dirname = typeof globalThis.__dirname !== 'undefined' ? globalThis.__dirname : '.';
|
|
9
|
+
const cliPath = join(__dirname, 'cli.js');
|
|
10
10
|
|
|
11
11
|
const version = getPackageVersion();
|
|
12
12
|
console.log(pc.cyan(pc.bold(` 🤩 Testomat.io Reporter v${version}`)));
|
|
13
|
-
const program = new Command();
|
|
14
|
-
|
|
15
|
-
program
|
|
16
|
-
.option('-c, --command <cmd>', 'Test runner command')
|
|
17
|
-
.option('--launch', 'Start a new run and return its ID')
|
|
18
|
-
.option('--finish', 'Finish Run by its ID')
|
|
19
|
-
.option('--env-file <envfile>', 'Load environment variables from env file')
|
|
20
|
-
.option('--filter <filter>', 'Additional execution filter')
|
|
21
|
-
.action(async opts => {
|
|
22
|
-
const { launch, finish, filter } = opts;
|
|
23
|
-
let { command } = opts;
|
|
24
|
-
|
|
25
|
-
if (opts.envFile) dotenv.config({ path: opts.envFile });
|
|
26
|
-
|
|
27
|
-
const apiKey = process.env['INPUT_TESTOMATIO-KEY'] || config.TESTOMATIO;
|
|
28
|
-
const title = process.env.TESTOMATIO_TITLE;
|
|
29
|
-
|
|
30
|
-
if (launch) {
|
|
31
|
-
console.log('Starting a new Run on Testomat.io...');
|
|
32
|
-
const client = new TestomatClient({ apiKey });
|
|
33
|
-
|
|
34
|
-
client.createRun().then(() => {
|
|
35
|
-
console.log(process.env.runId);
|
|
36
|
-
process.exit(0);
|
|
37
|
-
});
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
if (finish) {
|
|
42
|
-
// TODO: add error in case of TESTOMATIO environment variable is not set
|
|
43
|
-
// because command is fine in console, but actually (on testomat.io) run is not finished
|
|
44
|
-
if (!process.env.TESTOMATIO_RUN) {
|
|
45
|
-
console.log('TESTOMATIO_RUN environment variable must be set.');
|
|
46
|
-
return process.exit(1);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
console.log('Finishing Run on Testomat.io...');
|
|
50
|
-
|
|
51
|
-
const client = new TestomatClient({ apiKey });
|
|
52
13
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
14
|
+
// Parse command line arguments to map start-test-run options to @testomatio/reporter run format
|
|
15
|
+
const args = process.argv.slice(2);
|
|
16
|
+
const newArgs = ['run'];
|
|
17
|
+
|
|
18
|
+
let i = 0;
|
|
19
|
+
while (i < args.length) {
|
|
20
|
+
const arg = args[i];
|
|
21
|
+
|
|
22
|
+
if (arg === '-c' || arg === '--command') {
|
|
23
|
+
// Map -c/--command to positional argument for run command
|
|
24
|
+
i++;
|
|
25
|
+
if (i < args.length) {
|
|
26
|
+
newArgs.push(args[i]);
|
|
59
27
|
}
|
|
28
|
+
} else if (arg.startsWith('--command=')) {
|
|
29
|
+
// Handle --command=value format
|
|
30
|
+
const command = arg.split('=', 2)[1];
|
|
31
|
+
newArgs.push(command);
|
|
32
|
+
} else if (arg === '--launch') {
|
|
33
|
+
// Map --launch to start command
|
|
34
|
+
newArgs[0] = 'start';
|
|
35
|
+
} else if (arg === '--finish') {
|
|
36
|
+
// Map --finish to finish command
|
|
37
|
+
newArgs[0] = 'finish';
|
|
38
|
+
} else {
|
|
39
|
+
// Pass through other arguments
|
|
40
|
+
newArgs.push(arg);
|
|
41
|
+
}
|
|
42
|
+
i++;
|
|
43
|
+
}
|
|
60
44
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
if (!command.split) {
|
|
64
|
-
process.exitCode = 255;
|
|
65
|
-
console.log(APP_PREFIX, `No command provided. Use -c option to launch a test runner.`);
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
const client = new TestomatClient({ apiKey, title, parallel: true });
|
|
70
|
-
|
|
71
|
-
if (filter) {
|
|
72
|
-
const [pipe, ...optsArray] = filter.split(':');
|
|
73
|
-
const pipeOptions = optsArray.join(':');
|
|
74
|
-
|
|
75
|
-
try {
|
|
76
|
-
const tests = await client.prepareRun({ pipe, pipeOptions });
|
|
77
|
-
|
|
78
|
-
if (!tests || tests.length === 0) {
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
const grep = ` --grep (${tests.join('|')})`;
|
|
83
|
-
command += grep;
|
|
84
|
-
} catch (err) {
|
|
85
|
-
console.log(APP_PREFIX, err);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const testCmds = command.split(' ');
|
|
90
|
-
console.log(APP_PREFIX, `🚀 Running`, pc.green(command));
|
|
91
|
-
|
|
92
|
-
if (!apiKey) {
|
|
93
|
-
const cmd = spawn(testCmds[0], testCmds.slice(1), { stdio: 'inherit' });
|
|
94
|
-
|
|
95
|
-
cmd.on('close', code => {
|
|
96
|
-
console.log(APP_PREFIX, '⚠️ ', `Runner exited with ${pc.bold(code)}, report is ignored`);
|
|
97
|
-
|
|
98
|
-
if (code > exitCode) exitCode = code;
|
|
99
|
-
process.exitCode = exitCode;
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
return;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
client.createRun().then(() => {
|
|
106
|
-
const cmd = spawn(testCmds[0], testCmds.slice(1), { stdio: 'inherit' });
|
|
107
|
-
|
|
108
|
-
cmd.on('close', code => {
|
|
109
|
-
const emoji = code === 0 ? '🟢' : '🔴';
|
|
110
|
-
console.log(APP_PREFIX, emoji, `Runner exited with ${pc.bold(code)}`);
|
|
111
|
-
const status = code === 0 ? 'passed' : 'failed';
|
|
112
|
-
client.updateRunStatus(status, true);
|
|
113
|
-
|
|
114
|
-
if (code > exitCode) exitCode = code;
|
|
115
|
-
process.exitCode = exitCode;
|
|
116
|
-
});
|
|
117
|
-
});
|
|
118
|
-
});
|
|
45
|
+
// Execute the main CLI with mapped arguments
|
|
119
46
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
}
|
|
47
|
+
const child = spawn(process.execPath, [cliPath, ...newArgs], {
|
|
48
|
+
stdio: 'inherit'
|
|
49
|
+
});
|
|
123
50
|
|
|
124
|
-
|
|
51
|
+
child.on('exit', (code) => {
|
|
52
|
+
process.exit(code);
|
|
53
|
+
});
|
package/src/client.js
CHANGED
|
@@ -11,6 +11,7 @@ import path, { sep } from 'path';
|
|
|
11
11
|
import { fileURLToPath } from 'node:url';
|
|
12
12
|
import { S3Uploader } from './uploader.js';
|
|
13
13
|
import { formatStep, readLatestRunId, storeRunId, validateSuiteId } from './utils/utils.js';
|
|
14
|
+
import { linkStorage } from './services/links.js';
|
|
14
15
|
import { filesize as prettyBytes } from 'filesize';
|
|
15
16
|
|
|
16
17
|
const debug = createDebugMessages('@testomatio/reporter:client');
|
|
@@ -182,7 +183,6 @@ class Client {
|
|
|
182
183
|
test_id,
|
|
183
184
|
timestamp,
|
|
184
185
|
manuallyAttachedArtifacts,
|
|
185
|
-
labels,
|
|
186
186
|
overwrite,
|
|
187
187
|
} = testData;
|
|
188
188
|
let { message = '', meta = {} } = testData;
|
|
@@ -224,7 +224,9 @@ class Client {
|
|
|
224
224
|
return acc;
|
|
225
225
|
}, {});
|
|
226
226
|
|
|
227
|
-
//
|
|
227
|
+
// Get links from storage using the test context
|
|
228
|
+
const testContext = suite_title ? `${suite_title} ${title}` : title;
|
|
229
|
+
const links = linkStorage.get(testContext) || [];
|
|
228
230
|
|
|
229
231
|
let errorFormatted = '';
|
|
230
232
|
if (error) {
|
|
@@ -280,7 +282,7 @@ class Client {
|
|
|
280
282
|
timestamp,
|
|
281
283
|
artifacts,
|
|
282
284
|
meta,
|
|
283
|
-
|
|
285
|
+
links,
|
|
284
286
|
overwrite,
|
|
285
287
|
...(rootSuiteId && { root_suite_id: rootSuiteId }),
|
|
286
288
|
};
|
package/src/data-storage.js
CHANGED
|
@@ -41,7 +41,7 @@ class DataStorage {
|
|
|
41
41
|
/**
|
|
42
42
|
* Puts any data to storage (file or global variable).
|
|
43
43
|
* If file: stores data as text, if global variable – stores as array of data.
|
|
44
|
-
* @param {'log' | 'artifact' | 'keyvalue' | '
|
|
44
|
+
* @param {'log' | 'artifact' | 'keyvalue' | 'links'} dataType
|
|
45
45
|
* @param {*} data anything you want to store (string, object, array, etc)
|
|
46
46
|
* @param {*} context could be testId or any context (test name, suite name, including their IDs etc)
|
|
47
47
|
* suite name + test name is used by default
|
|
@@ -70,7 +70,7 @@ class DataStorage {
|
|
|
70
70
|
* Returns data, stored for specific test/context (or data which was stored without test id specified).
|
|
71
71
|
* This method will get data from global variable and/or from from file (previosly saved with put method).
|
|
72
72
|
*
|
|
73
|
-
* @param {'log' | 'artifact' | 'keyvalue' | '
|
|
73
|
+
* @param {'log' | 'artifact' | 'keyvalue' | 'links'} dataType
|
|
74
74
|
* @param {string} context
|
|
75
75
|
* @returns {any []} array of data (any type), null (if no data found for context) or string (if data type is log)
|
|
76
76
|
*/
|
|
@@ -108,7 +108,7 @@ class DataStorage {
|
|
|
108
108
|
}
|
|
109
109
|
|
|
110
110
|
/**
|
|
111
|
-
* @param {'log' | 'artifact' | 'keyvalue' | '
|
|
111
|
+
* @param {'log' | 'artifact' | 'keyvalue' | 'links'} dataType
|
|
112
112
|
* @param {string} context
|
|
113
113
|
* @returns aray of data (any type)
|
|
114
114
|
*/
|
|
@@ -127,7 +127,7 @@ class DataStorage {
|
|
|
127
127
|
}
|
|
128
128
|
|
|
129
129
|
/**
|
|
130
|
-
* @param {'log' | 'artifact' | 'keyvalue' | '
|
|
130
|
+
* @param {'log' | 'artifact' | 'keyvalue' | 'links'} dataType
|
|
131
131
|
* @param {*} context
|
|
132
132
|
* @returns array of data (any type)
|
|
133
133
|
*/
|
|
@@ -151,7 +151,7 @@ class DataStorage {
|
|
|
151
151
|
|
|
152
152
|
/**
|
|
153
153
|
* Puts data to global variable. Unlike the file storage, stores data in array (file storage just append as string).
|
|
154
|
-
* @param {'log' | 'artifact' | 'keyvalue' | '
|
|
154
|
+
* @param {'log' | 'artifact' | 'keyvalue' | 'links'} dataType
|
|
155
155
|
* @param {*} data
|
|
156
156
|
* @param {*} context
|
|
157
157
|
*/
|
|
@@ -166,7 +166,7 @@ class DataStorage {
|
|
|
166
166
|
|
|
167
167
|
/**
|
|
168
168
|
* Puts data to file. Unlike the global variable storage, stores data as string
|
|
169
|
-
* @param {'log' | 'artifact' | 'keyvalue' | '
|
|
169
|
+
* @param {'log' | 'artifact' | 'keyvalue' | 'links'} dataType
|
|
170
170
|
* @param {*} data
|
|
171
171
|
* @param {string} context
|
|
172
172
|
* @returns
|
package/src/pipe/testomatio.js
CHANGED
|
@@ -119,8 +119,7 @@ class TestomatioPipe {
|
|
|
119
119
|
const resp = await this.client.request({
|
|
120
120
|
method: 'GET',
|
|
121
121
|
url: '/api/test_grep',
|
|
122
|
-
|
|
123
|
-
responseType: q.responseType
|
|
122
|
+
...q,
|
|
124
123
|
});
|
|
125
124
|
|
|
126
125
|
if (Array.isArray(resp.data?.tests) && resp.data?.tests?.length > 0) {
|
|
@@ -188,7 +187,8 @@ class TestomatioPipe {
|
|
|
188
187
|
const resp = await this.client.request({
|
|
189
188
|
method: 'PUT',
|
|
190
189
|
url: `/api/reporter/${this.runId}`,
|
|
191
|
-
data: runParams
|
|
190
|
+
data: runParams,
|
|
191
|
+
responseType: 'json'
|
|
192
192
|
});
|
|
193
193
|
if (resp.data.artifacts) setS3Credentials(resp.data.artifacts);
|
|
194
194
|
return;
|