@testomatio/reporter 2.0.1-beta.5-timestamp → 2.0.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/README.md +1 -0
- package/lib/adapter/codecept.d.ts +2 -0
- package/lib/adapter/codecept.js +293 -335
- package/lib/adapter/cucumber/current.d.ts +14 -0
- package/lib/adapter/cucumber/current.js +195 -203
- package/lib/adapter/cucumber/legacy.d.ts +0 -0
- package/lib/adapter/cucumber/legacy.js +130 -155
- package/lib/adapter/cucumber.d.ts +2 -0
- package/lib/adapter/cucumber.js +5 -16
- package/lib/adapter/cypress-plugin/index.d.ts +2 -0
- package/lib/adapter/cypress-plugin/index.js +91 -105
- package/lib/adapter/jasmine.d.ts +11 -0
- package/lib/adapter/jasmine.js +54 -53
- package/lib/adapter/jest.d.ts +13 -0
- package/lib/adapter/jest.js +97 -99
- package/lib/adapter/mocha.d.ts +2 -0
- package/lib/adapter/mocha.js +112 -141
- package/lib/adapter/nightwatch.d.ts +4 -0
- package/lib/adapter/nightwatch.js +80 -0
- package/lib/adapter/playwright.d.ts +14 -0
- package/lib/adapter/playwright.js +199 -231
- package/lib/adapter/vitest.d.ts +35 -0
- package/lib/adapter/vitest.js +150 -149
- package/lib/adapter/webdriver.d.ts +24 -0
- package/lib/adapter/webdriver.js +144 -121
- package/lib/bin/cli.d.ts +2 -0
- package/lib/bin/cli.js +229 -211
- package/lib/bin/reportXml.d.ts +2 -0
- package/lib/bin/reportXml.js +51 -52
- package/lib/bin/startTest.d.ts +2 -0
- package/lib/bin/startTest.js +83 -95
- package/lib/bin/uploadArtifacts.d.ts +2 -0
- package/lib/bin/uploadArtifacts.js +56 -61
- package/lib/client.d.ts +76 -0
- package/lib/client.js +429 -465
- package/lib/config.d.ts +1 -0
- package/lib/config.js +18 -23
- package/lib/constants.d.ts +25 -0
- package/lib/constants.js +50 -44
- package/lib/data-storage.d.ts +34 -0
- package/lib/data-storage.js +216 -188
- package/lib/junit-adapter/adapter.d.ts +9 -0
- package/lib/junit-adapter/adapter.js +17 -20
- package/lib/junit-adapter/csharp.d.ts +5 -0
- package/lib/junit-adapter/csharp.js +28 -14
- package/lib/junit-adapter/index.d.ts +3 -0
- package/lib/junit-adapter/index.js +27 -25
- package/lib/junit-adapter/java.d.ts +5 -0
- package/lib/junit-adapter/java.js +41 -53
- package/lib/junit-adapter/javascript.d.ts +4 -0
- package/lib/junit-adapter/javascript.js +30 -27
- package/lib/junit-adapter/python.d.ts +5 -0
- package/lib/junit-adapter/python.js +38 -37
- package/lib/junit-adapter/ruby.d.ts +4 -0
- package/lib/junit-adapter/ruby.js +11 -8
- package/lib/output.d.ts +11 -0
- package/lib/output.js +44 -52
- package/lib/package.json +3 -0
- package/lib/pipe/bitbucket.d.ts +25 -0
- package/lib/pipe/bitbucket.js +223 -230
- package/lib/pipe/csv.d.ts +47 -0
- package/lib/pipe/csv.js +113 -126
- package/lib/pipe/debug.d.ts +29 -0
- package/lib/pipe/debug.js +125 -99
- package/lib/pipe/github.d.ts +30 -0
- package/lib/pipe/github.js +218 -213
- package/lib/pipe/gitlab.d.ts +25 -0
- package/lib/pipe/gitlab.js +183 -206
- package/lib/pipe/html.d.ts +35 -0
- package/lib/pipe/html.js +258 -321
- package/lib/pipe/index.d.ts +1 -0
- package/lib/pipe/index.js +94 -66
- package/lib/pipe/testomatio.d.ts +71 -0
- package/lib/pipe/testomatio.js +429 -474
- package/lib/replay.d.ts +31 -0
- package/lib/replay.js +255 -0
- package/lib/reporter-functions.d.ts +34 -0
- package/lib/reporter-functions.js +28 -26
- package/lib/reporter.d.ts +232 -0
- package/lib/reporter.js +34 -29
- package/lib/services/artifacts.d.ts +33 -0
- package/lib/services/artifacts.js +55 -51
- package/lib/services/index.d.ts +9 -0
- package/lib/services/index.js +14 -12
- package/lib/services/key-values.d.ts +27 -0
- package/lib/services/key-values.js +56 -53
- package/lib/services/logger.d.ts +64 -0
- package/lib/services/logger.js +226 -245
- package/lib/template/testomatio.hbs +1026 -1366
- package/lib/uploader.d.ts +60 -0
- package/lib/uploader.js +295 -364
- package/lib/utils/pipe_utils.d.ts +41 -0
- package/lib/utils/pipe_utils.js +89 -85
- package/lib/utils/utils.d.ts +54 -0
- package/lib/utils/utils.js +398 -307
- package/lib/xmlReader.d.ts +92 -0
- package/lib/xmlReader.js +525 -532
- package/package.json +64 -21
- package/src/adapter/codecept.js +373 -0
- package/src/adapter/cucumber/current.js +228 -0
- package/src/adapter/cucumber/legacy.js +158 -0
- package/src/adapter/cucumber.js +4 -0
- package/src/adapter/cypress-plugin/index.js +110 -0
- package/src/adapter/jasmine.js +60 -0
- package/src/adapter/jest.js +107 -0
- package/src/adapter/mocha.cjs +2 -0
- package/src/adapter/mocha.js +156 -0
- package/src/adapter/nightwatch.js +88 -0
- package/src/adapter/playwright.js +254 -0
- package/src/adapter/vitest.js +183 -0
- package/src/adapter/webdriver.js +142 -0
- package/src/bin/cli.js +348 -0
- package/src/bin/reportXml.js +77 -0
- package/src/bin/startTest.js +124 -0
- package/src/bin/uploadArtifacts.js +91 -0
- package/src/client.js +515 -0
- package/src/config.js +30 -0
- package/src/constants.js +53 -0
- package/src/data-storage.js +204 -0
- package/src/junit-adapter/adapter.js +23 -0
- package/src/junit-adapter/csharp.js +28 -0
- package/src/junit-adapter/index.js +28 -0
- package/src/junit-adapter/java.js +58 -0
- package/src/junit-adapter/javascript.js +31 -0
- package/src/junit-adapter/python.js +42 -0
- package/src/junit-adapter/ruby.js +10 -0
- package/src/output.js +57 -0
- package/src/pipe/bitbucket.js +252 -0
- package/src/pipe/csv.js +140 -0
- package/src/pipe/debug.js +125 -0
- package/src/pipe/github.js +232 -0
- package/src/pipe/gitlab.js +247 -0
- package/src/pipe/html.js +373 -0
- package/src/pipe/index.js +71 -0
- package/src/pipe/testomatio.js +504 -0
- package/src/replay.js +262 -0
- package/src/reporter-functions.js +55 -0
- package/src/reporter.cjs_decprecated +21 -0
- package/src/reporter.js +33 -0
- package/src/services/artifacts.js +59 -0
- package/src/services/index.js +13 -0
- package/src/services/key-values.js +59 -0
- package/src/services/logger.js +315 -0
- package/src/template/emptyData.svg +23 -0
- package/src/template/testomatio.hbs +1081 -0
- package/src/uploader.js +376 -0
- package/src/utils/pipe_utils.js +119 -0
- package/src/utils/utils.js +416 -0
- package/src/xmlReader.js +614 -0
package/lib/bin/cli.js
CHANGED
|
@@ -1,275 +1,293 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
2
|
+
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
const commander_1 = require("commander");
|
|
8
|
+
const cross_spawn_1 = require("cross-spawn");
|
|
9
|
+
const glob_1 = require("glob");
|
|
10
|
+
const debug_1 = __importDefault(require("debug"));
|
|
11
|
+
const client_js_1 = __importDefault(require("../client.js"));
|
|
12
|
+
const xmlReader_js_1 = __importDefault(require("../xmlReader.js"));
|
|
13
|
+
const constants_js_1 = require("../constants.js");
|
|
14
|
+
const utils_js_1 = require("../utils/utils.js");
|
|
15
|
+
const config_js_1 = require("../config.js");
|
|
16
|
+
const utils_js_2 = require("../utils/utils.js");
|
|
17
|
+
const picocolors_1 = __importDefault(require("picocolors"));
|
|
18
|
+
const filesize_1 = require("filesize");
|
|
19
|
+
const dotenv_1 = __importDefault(require("dotenv"));
|
|
20
|
+
const replay_js_1 = __importDefault(require("../replay.js"));
|
|
21
|
+
const debug = (0, debug_1.default)('@testomatio/reporter:xml-cli');
|
|
22
|
+
const version = (0, utils_js_1.getPackageVersion)();
|
|
23
|
+
console.log(picocolors_1.default.cyan(picocolors_1.default.bold(` 🤩 Testomat.io Reporter v${version}`)));
|
|
24
|
+
const program = new commander_1.Command();
|
|
17
25
|
program
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
26
|
+
.version(version)
|
|
27
|
+
.option('--env-file <envfile>', 'Load environment variables from env file')
|
|
28
|
+
.hook('preAction', thisCommand => {
|
|
21
29
|
const opts = thisCommand.opts();
|
|
22
30
|
if (opts.envFile) {
|
|
23
|
-
|
|
24
|
-
} else {
|
|
25
|
-
require('dotenv').config();
|
|
31
|
+
dotenv_1.default.config({ path: opts.envFile });
|
|
26
32
|
}
|
|
27
|
-
|
|
28
|
-
|
|
33
|
+
else {
|
|
34
|
+
dotenv_1.default.config();
|
|
35
|
+
}
|
|
36
|
+
});
|
|
29
37
|
program
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
38
|
+
.command('start')
|
|
39
|
+
.description('Start a new run and return its ID')
|
|
40
|
+
.action(async () => {
|
|
33
41
|
console.log('Starting a new Run on Testomat.io...');
|
|
34
|
-
const apiKey = process.env['INPUT_TESTOMATIO-KEY'] || config.TESTOMATIO;
|
|
35
|
-
const client = new
|
|
36
|
-
|
|
42
|
+
const apiKey = process.env['INPUT_TESTOMATIO-KEY'] || config_js_1.config.TESTOMATIO;
|
|
43
|
+
const client = new client_js_1.default({ apiKey });
|
|
37
44
|
client.createRun().then(() => {
|
|
38
|
-
|
|
39
|
-
|
|
45
|
+
console.log(process.env.runId);
|
|
46
|
+
process.exit(0);
|
|
40
47
|
});
|
|
41
|
-
|
|
42
|
-
|
|
48
|
+
});
|
|
43
49
|
program
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
process.env.TESTOMATIO_RUN ||= readLatestRunId();
|
|
48
|
-
|
|
50
|
+
.command('finish')
|
|
51
|
+
.description('Finish Run by its ID')
|
|
52
|
+
.action(async () => {
|
|
53
|
+
process.env.TESTOMATIO_RUN ||= (0, utils_js_2.readLatestRunId)();
|
|
49
54
|
if (!process.env.TESTOMATIO_RUN) {
|
|
50
|
-
|
|
51
|
-
|
|
55
|
+
console.log('TESTOMATIO_RUN environment variable must be set or restored from a previous run.');
|
|
56
|
+
return process.exit(1);
|
|
52
57
|
}
|
|
53
|
-
|
|
54
58
|
console.log('Finishing Run on Testomat.io...');
|
|
55
|
-
const apiKey = process.env['INPUT_TESTOMATIO-KEY'] || config.TESTOMATIO;
|
|
56
|
-
const client = new
|
|
57
|
-
|
|
58
|
-
client.updateRunStatus(STATUS.FINISHED).then(() => {
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
const apiKey = process.env['INPUT_TESTOMATIO-KEY'] || config_js_1.config.TESTOMATIO;
|
|
60
|
+
const client = new client_js_1.default({ apiKey });
|
|
61
|
+
// @ts-ignore
|
|
62
|
+
client.updateRunStatus(constants_js_1.STATUS.FINISHED).then(() => {
|
|
63
|
+
console.log(picocolors_1.default.yellow(`Run ${process.env.TESTOMATIO_RUN} was finished`));
|
|
64
|
+
process.exit(0);
|
|
61
65
|
});
|
|
62
|
-
|
|
63
|
-
|
|
66
|
+
});
|
|
64
67
|
program
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
const apiKey = process.env['INPUT_TESTOMATIO-KEY'] || config.TESTOMATIO;
|
|
68
|
+
.command('run')
|
|
69
|
+
.description('Run tests with the specified command')
|
|
70
|
+
.argument('<command>', 'Test runner command')
|
|
71
|
+
.option('--filter <filter>', 'Additional execution filter')
|
|
72
|
+
.action(async (command, opts) => {
|
|
73
|
+
const apiKey = process.env['INPUT_TESTOMATIO-KEY'] || config_js_1.config.TESTOMATIO;
|
|
71
74
|
const title = process.env.TESTOMATIO_TITLE;
|
|
72
|
-
|
|
73
75
|
if (!command || !command.split) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
+
console.log(constants_js_1.APP_PREFIX, `No command provided. Use -c option to launch a test runner.`);
|
|
77
|
+
return process.exit(255);
|
|
76
78
|
}
|
|
77
|
-
|
|
78
|
-
const client = new TestomatClient({ apiKey, title, parallel: true });
|
|
79
|
-
|
|
79
|
+
const client = new client_js_1.default({ apiKey, title, parallel: true });
|
|
80
80
|
if (opts.filter) {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
81
|
+
const [pipe, ...optsArray] = opts.filter.split(':');
|
|
82
|
+
const pipeOptions = optsArray.join(':');
|
|
83
|
+
try {
|
|
84
|
+
const tests = await client.prepareRun({ pipe, pipeOptions });
|
|
85
|
+
if (tests && tests.length > 0) {
|
|
86
|
+
command += ` --grep (${tests.join('|')})`;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
catch (err) {
|
|
90
|
+
console.log(constants_js_1.APP_PREFIX, err);
|
|
88
91
|
}
|
|
89
|
-
} catch (err) {
|
|
90
|
-
console.log(APP_PREFIX, err);
|
|
91
|
-
}
|
|
92
92
|
}
|
|
93
|
-
|
|
94
|
-
console.log(APP_PREFIX, `🚀 Running`, chalk.green(command));
|
|
95
|
-
|
|
93
|
+
console.log(constants_js_1.APP_PREFIX, `🚀 Running`, picocolors_1.default.green(command));
|
|
96
94
|
const runTests = () => {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
});
|
|
95
|
+
const testCmds = command.split(' ');
|
|
96
|
+
const cmd = (0, cross_spawn_1.spawn)(testCmds[0], testCmds.slice(1), { stdio: 'inherit' });
|
|
97
|
+
cmd.on('close', code => {
|
|
98
|
+
const emoji = code === 0 ? '🟢' : '🔴';
|
|
99
|
+
console.log(constants_js_1.APP_PREFIX, emoji, `Runner exited with ${picocolors_1.default.bold(code)}`);
|
|
100
|
+
if (apiKey) {
|
|
101
|
+
const status = code === 0 ? 'passed' : 'failed';
|
|
102
|
+
client.updateRunStatus(status, true);
|
|
103
|
+
}
|
|
104
|
+
process.exit(code);
|
|
105
|
+
});
|
|
109
106
|
};
|
|
110
|
-
|
|
111
107
|
if (apiKey) {
|
|
112
|
-
|
|
113
|
-
}
|
|
114
|
-
|
|
108
|
+
client.createRun().then(runTests);
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
runTests();
|
|
115
112
|
}
|
|
116
|
-
|
|
117
|
-
|
|
113
|
+
});
|
|
114
|
+
// program
|
|
115
|
+
// .command('xml')
|
|
116
|
+
// .description('Parse XML reports and upload to Testomat.io')
|
|
117
|
+
// .argument('<pattern>', 'XML file pattern')
|
|
118
|
+
// .option('-d, --dir <dir>', 'Project directory')
|
|
119
|
+
// .option('--java-tests [java-path]', 'Load Java tests from path, by default: src/test/java')
|
|
120
|
+
// .option('--lang <lang>', 'Language used (python, ruby, java)')
|
|
121
|
+
// .option('--timelimit <time>', 'default time limit in seconds to kill a stuck process')
|
|
122
|
+
// .action(async (pattern, opts) => {
|
|
123
|
+
// if (!pattern.endsWith('.xml')) {
|
|
124
|
+
// pattern += '.xml';
|
|
125
|
+
// }
|
|
126
|
+
// let { javaTests, lang } = opts;
|
|
127
|
+
// if (javaTests === true) javaTests = 'src/test/java';
|
|
128
|
+
// lang = lang?.toLowerCase();
|
|
129
|
+
// const runReader = new XmlReader({ javaTests, lang });
|
|
130
|
+
// const files = glob.sync(pattern, { cwd: opts.dir || process.cwd() });
|
|
131
|
+
// if (!files.length) {
|
|
132
|
+
// console.log(APP_PREFIX, `Report can't be created. No XML files found 😥`);
|
|
133
|
+
// process.exit(1);
|
|
134
|
+
// }
|
|
118
135
|
program
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
136
|
+
.command('xml')
|
|
137
|
+
.description('Parse XML reports and upload to Testomat.io')
|
|
138
|
+
.argument('<pattern>', 'XML file pattern')
|
|
139
|
+
.option('-d, --dir <dir>', 'Project directory')
|
|
140
|
+
.option('--java-tests [java-path]', 'Load Java tests from path, by default: src/test/java')
|
|
141
|
+
.option('--lang <lang>', 'Language used (python, ruby, java)')
|
|
142
|
+
.option('--timelimit <time>', 'default time limit in seconds to kill a stuck process')
|
|
143
|
+
.action(async (pattern, opts) => {
|
|
127
144
|
if (!pattern.endsWith('.xml')) {
|
|
128
|
-
|
|
145
|
+
pattern += '.xml';
|
|
129
146
|
}
|
|
130
147
|
let { javaTests, lang } = opts;
|
|
131
|
-
if (javaTests === true)
|
|
148
|
+
if (javaTests === true)
|
|
149
|
+
javaTests = 'src/test/java';
|
|
132
150
|
lang = lang?.toLowerCase();
|
|
133
|
-
const runReader = new
|
|
134
|
-
const files = glob.sync(pattern, { cwd: opts.dir || process.cwd() });
|
|
151
|
+
const runReader = new xmlReader_js_1.default({ javaTests, lang });
|
|
152
|
+
const files = glob_1.glob.sync(pattern, { cwd: opts.dir || process.cwd() });
|
|
135
153
|
if (!files.length) {
|
|
136
|
-
|
|
137
|
-
|
|
154
|
+
console.log(constants_js_1.APP_PREFIX, `Report can't be created. No XML files found 😥`);
|
|
155
|
+
process.exit(1);
|
|
138
156
|
}
|
|
139
|
-
|
|
140
157
|
for (const file of files) {
|
|
141
|
-
|
|
142
|
-
|
|
158
|
+
console.log(constants_js_1.APP_PREFIX, `Parsed ${file}`);
|
|
159
|
+
runReader.parse(file);
|
|
143
160
|
}
|
|
144
|
-
|
|
145
161
|
let timeoutTimer;
|
|
146
162
|
if (opts.timelimit) {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
);
|
|
152
|
-
process.exit(0);
|
|
153
|
-
},
|
|
154
|
-
parseInt(opts.timelimit, 10) * 1000,
|
|
155
|
-
);
|
|
163
|
+
timeoutTimer = setTimeout(() => {
|
|
164
|
+
console.log(`⚠️ Reached timeout of ${opts.timelimit}s. Exiting... (Exit code is 0 to not fail the pipeline)`);
|
|
165
|
+
process.exit(0);
|
|
166
|
+
}, parseInt(opts.timelimit, 10) * 1000);
|
|
156
167
|
}
|
|
157
|
-
|
|
158
168
|
try {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
} catch (err) {
|
|
162
|
-
console.log(APP_PREFIX, 'Error updating status, skipping...', err);
|
|
169
|
+
await runReader.createRun();
|
|
170
|
+
await runReader.uploadData();
|
|
163
171
|
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
172
|
+
catch (err) {
|
|
173
|
+
console.log(constants_js_1.APP_PREFIX, 'Error updating status, skipping...', err);
|
|
174
|
+
}
|
|
175
|
+
if (timeoutTimer)
|
|
176
|
+
clearTimeout(timeoutTimer);
|
|
177
|
+
});
|
|
168
178
|
program
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
const apiKey = config.TESTOMATIO;
|
|
174
|
-
|
|
179
|
+
.command('upload-artifacts')
|
|
180
|
+
.description('Upload artifacts to Testomat.io')
|
|
181
|
+
.option('--force', 'Re-upload artifacts even if they were uploaded before')
|
|
182
|
+
.action(async (opts) => {
|
|
183
|
+
const apiKey = config_js_1.config.TESTOMATIO;
|
|
175
184
|
process.env.TESTOMATIO_DISABLE_ARTIFACTS = '';
|
|
176
|
-
const runId = process.env.TESTOMATIO_RUN || process.env.runId || readLatestRunId();
|
|
177
|
-
|
|
185
|
+
const runId = process.env.TESTOMATIO_RUN || process.env.runId || (0, utils_js_2.readLatestRunId)();
|
|
178
186
|
if (!runId) {
|
|
179
|
-
|
|
180
|
-
|
|
187
|
+
console.log('TESTOMATIO_RUN environment variable must be set or restored from a previous run.');
|
|
188
|
+
return process.exit(1);
|
|
181
189
|
}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
isBatchEnabled: false,
|
|
190
|
+
const client = new client_js_1.default({
|
|
191
|
+
apiKey,
|
|
192
|
+
runId,
|
|
193
|
+
isBatchEnabled: false,
|
|
187
194
|
});
|
|
188
|
-
|
|
189
195
|
let testruns = client.uploader.readUploadedFiles(runId);
|
|
190
196
|
const numTotalArtifacts = testruns.length;
|
|
191
|
-
|
|
192
197
|
debug('Found testruns:', testruns);
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
198
|
+
if (!opts.force)
|
|
199
|
+
testruns = testruns.filter(tr => !tr.uploaded);
|
|
196
200
|
if (!testruns.length) {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
201
|
+
console.log(constants_js_1.APP_PREFIX, '🗄️ Total artifacts:', numTotalArtifacts);
|
|
202
|
+
if (numTotalArtifacts) {
|
|
203
|
+
console.log(constants_js_1.APP_PREFIX, 'No new artifacts to upload');
|
|
204
|
+
console.log(constants_js_1.APP_PREFIX, 'To re-upload artifacts run this command with --force flag');
|
|
205
|
+
}
|
|
206
|
+
process.exit(0);
|
|
203
207
|
}
|
|
204
|
-
|
|
205
208
|
const testrunsByRid = testruns.reduce((acc, { rid, file }) => {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
209
|
+
if (!acc[rid]) {
|
|
210
|
+
acc[rid] = [];
|
|
211
|
+
}
|
|
212
|
+
if (!acc[rid].includes(file))
|
|
213
|
+
acc[rid].push(file);
|
|
214
|
+
return acc;
|
|
211
215
|
}, {});
|
|
212
|
-
|
|
213
216
|
await client.createRun();
|
|
214
217
|
client.uploader.checkEnabled();
|
|
215
218
|
client.uploader.disableLogStorage();
|
|
216
|
-
|
|
217
219
|
for (const rid in testrunsByRid) {
|
|
218
|
-
|
|
219
|
-
|
|
220
|
+
const files = testrunsByRid[rid];
|
|
221
|
+
await client.addTestRun(undefined, { rid, files });
|
|
220
222
|
}
|
|
221
|
-
|
|
222
|
-
console.log(APP_PREFIX, '🗄️', client.uploader.successfulUploads.length, 'artifacts 🟢uploaded');
|
|
223
|
-
|
|
223
|
+
console.log(constants_js_1.APP_PREFIX, '🗄️', client.uploader.successfulUploads.length, 'artifacts 🟢uploaded');
|
|
224
224
|
if (client.uploader.successfulUploads.length) {
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
`🟢 Uploaded artifact`,
|
|
235
|
-
`${upload.relativePath},`,
|
|
236
|
-
'size:',
|
|
237
|
-
`${upload.sizePretty},`,
|
|
238
|
-
'link:',
|
|
239
|
-
`${upload.link}`,
|
|
240
|
-
);
|
|
241
|
-
});
|
|
225
|
+
debug('\n', constants_js_1.APP_PREFIX, `🗄️ ${client.uploader.successfulUploads.length} artifacts uploaded to S3 bucket`);
|
|
226
|
+
const uploadedArtifacts = client.uploader.successfulUploads.map(file => ({
|
|
227
|
+
relativePath: file.path.replace(process.cwd(), ''),
|
|
228
|
+
link: file.link,
|
|
229
|
+
sizePretty: (0, filesize_1.filesize)(file.size, { round: 0 }).toString(),
|
|
230
|
+
}));
|
|
231
|
+
uploadedArtifacts.forEach(upload => {
|
|
232
|
+
debug(`🟢Uploaded artifact`, `${upload.relativePath},`, 'size:', `${upload.sizePretty},`, 'link:', `${upload.link}`);
|
|
233
|
+
});
|
|
242
234
|
}
|
|
243
|
-
|
|
244
235
|
const filesizeStrMaxLength = 7;
|
|
245
|
-
|
|
246
236
|
if (client.uploader.failedUploads.length) {
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
237
|
+
console.log('\n', constants_js_1.APP_PREFIX, '🗄️', client.uploader.failedUploads.length, `artifacts 🔴${picocolors_1.default.bold('failed')} to upload`);
|
|
238
|
+
const failedUploads = client.uploader.failedUploads.map(({ path, size }) => ({
|
|
239
|
+
relativePath: path.replace(process.cwd(), ''),
|
|
240
|
+
sizePretty: (0, filesize_1.filesize)(size, { round: 0 }).toString(),
|
|
241
|
+
}));
|
|
242
|
+
const pathPadding = Math.max(...failedUploads.map(upload => upload.relativePath.length)) + 1;
|
|
243
|
+
failedUploads.forEach(upload => {
|
|
244
|
+
console.log(` ${picocolors_1.default.gray('|')} 🔴 ${upload.relativePath.padEnd(pathPadding)} ${picocolors_1.default.gray(`| ${upload.sizePretty.padStart(filesizeStrMaxLength)} |`)}`);
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
program
|
|
249
|
+
.command('replay')
|
|
250
|
+
.description('Replay test data from debug file and re-send to Testomat.io')
|
|
251
|
+
.argument('[debug-file]', 'Path to debug file (defaults to /tmp/testomatio.debug.latest.json)')
|
|
252
|
+
.option('--dry-run', 'Preview the data without sending to Testomat.io')
|
|
253
|
+
.action(async (debugFile, opts) => {
|
|
254
|
+
try {
|
|
255
|
+
const replayService = new replay_js_1.default({
|
|
256
|
+
apiKey: config_js_1.config.TESTOMATIO,
|
|
257
|
+
dryRun: opts.dryRun,
|
|
258
|
+
onLog: (message) => console.log(constants_js_1.APP_PREFIX, message),
|
|
259
|
+
onError: (message) => console.error(constants_js_1.APP_PREFIX, '⚠️ ', message),
|
|
260
|
+
onProgress: ({ current, total }) => {
|
|
261
|
+
if (current % 10 === 0 || current === total) {
|
|
262
|
+
console.log(constants_js_1.APP_PREFIX, `📊 Progress: ${current}/${total} tests processed`);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
const result = await replayService.replay(debugFile);
|
|
267
|
+
if (result.dryRun) {
|
|
268
|
+
console.log(constants_js_1.APP_PREFIX, '🔍 Dry run completed:');
|
|
269
|
+
console.log(constants_js_1.APP_PREFIX, ` - Tests found: ${result.testsCount}`);
|
|
270
|
+
console.log(constants_js_1.APP_PREFIX, ` - Environment variables: ${Object.keys(result.envVars).length}`);
|
|
271
|
+
console.log(constants_js_1.APP_PREFIX, ` - Run parameters:`, result.runParams);
|
|
272
|
+
console.log(constants_js_1.APP_PREFIX, ' Use without --dry-run to actually send the data');
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
console.log(constants_js_1.APP_PREFIX, `✅ Successfully replayed ${result.successCount}/${result.testsCount} tests`);
|
|
276
|
+
if (result.failureCount > 0) {
|
|
277
|
+
console.log(constants_js_1.APP_PREFIX, `⚠️ ${result.failureCount} tests failed to upload`);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
process.exit(0);
|
|
281
|
+
}
|
|
282
|
+
catch (err) {
|
|
283
|
+
console.error(constants_js_1.APP_PREFIX, '❌ Error replaying debug data:', err.message);
|
|
284
|
+
if (err.message.includes('Debug file not found')) {
|
|
285
|
+
console.error(constants_js_1.APP_PREFIX, '💡 Hint: Run tests with TESTOMATIO_DEBUG=1 to generate debug files');
|
|
286
|
+
}
|
|
287
|
+
process.exit(1);
|
|
268
288
|
}
|
|
269
|
-
|
|
270
|
-
|
|
289
|
+
});
|
|
271
290
|
program.parse(process.argv);
|
|
272
|
-
|
|
273
291
|
if (!process.argv.slice(2).length) {
|
|
274
|
-
|
|
292
|
+
program.outputHelp();
|
|
275
293
|
}
|
package/lib/bin/reportXml.js
CHANGED
|
@@ -1,72 +1,71 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
2
|
+
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
const commander_1 = require("commander");
|
|
8
|
+
const picocolors_1 = __importDefault(require("picocolors"));
|
|
9
|
+
const glob_1 = require("glob");
|
|
10
|
+
const debug_1 = __importDefault(require("debug"));
|
|
11
|
+
const constants_js_1 = require("../constants.js");
|
|
12
|
+
const xmlReader_js_1 = __importDefault(require("../xmlReader.js"));
|
|
13
|
+
const utils_js_1 = require("../utils/utils.js");
|
|
14
|
+
const dotenv_1 = __importDefault(require("dotenv"));
|
|
15
|
+
const path_1 = __importDefault(require("path"));
|
|
16
|
+
const version = (0, utils_js_1.getPackageVersion)();
|
|
17
|
+
const debug = (0, debug_1.default)('@testomatio/reporter:xml-cli');
|
|
18
|
+
console.log(picocolors_1.default.cyan(picocolors_1.default.bold(` 🤩 Testomat.io XML Reporter v${version}`)));
|
|
19
|
+
const program = new commander_1.Command();
|
|
13
20
|
program
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
+
.arguments('<pattern>')
|
|
22
|
+
.option('-d, --dir <dir>', 'Project directory')
|
|
23
|
+
.option('--java-tests [java-path]', 'Load Java tests from path, by default: src/test/java')
|
|
24
|
+
.option('--lang <lang>', 'Language used (python, ruby, java)')
|
|
25
|
+
.option('--timelimit <time>', 'default time limit in seconds to kill a stuck process')
|
|
26
|
+
.option('--env-file <envfile>', 'Load environment variables from env file')
|
|
27
|
+
.action(async (pattern, opts) => {
|
|
21
28
|
if (!pattern.endsWith('.xml')) {
|
|
22
|
-
|
|
29
|
+
pattern += '.xml';
|
|
23
30
|
}
|
|
24
31
|
let { javaTests, lang } = opts;
|
|
25
32
|
if (opts.envFile) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
33
|
+
console.log(constants_js_1.APP_PREFIX, 'Loading env file:', opts.envFile);
|
|
34
|
+
debug('Loading env file: %s', opts.envFile);
|
|
35
|
+
dotenv_1.default.config({ path: opts.envFile });
|
|
29
36
|
}
|
|
30
|
-
if (javaTests === true) javaTests = 'src/test/java';
|
|
31
37
|
lang = lang?.toLowerCase();
|
|
32
|
-
|
|
33
|
-
|
|
38
|
+
if (javaTests === true || (lang === 'java' && !javaTests))
|
|
39
|
+
javaTests = 'src/test/java';
|
|
40
|
+
const runReader = new xmlReader_js_1.default({ javaTests, lang });
|
|
41
|
+
const files = glob_1.glob.sync(pattern, { cwd: opts.dir || process.cwd() });
|
|
34
42
|
if (!files.length) {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
43
|
+
console.log(constants_js_1.APP_PREFIX, `Report can't be created. No XML files found 😥`);
|
|
44
|
+
process.exitCode = 1;
|
|
45
|
+
return;
|
|
38
46
|
}
|
|
39
|
-
|
|
40
47
|
for (const file of files) {
|
|
41
|
-
|
|
42
|
-
|
|
48
|
+
console.log(constants_js_1.APP_PREFIX, `Parsed ${file}`);
|
|
49
|
+
runReader.parse(file);
|
|
43
50
|
}
|
|
44
|
-
|
|
45
51
|
let timeoutTimer;
|
|
46
52
|
if (opts.timelimit) {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
);
|
|
52
|
-
process.exit(0);
|
|
53
|
-
},
|
|
54
|
-
parseInt(opts.timelimit, 10) * 1000,
|
|
55
|
-
);
|
|
53
|
+
timeoutTimer = setTimeout(() => {
|
|
54
|
+
console.log(`⚠️ Reached timeout of ${opts.timelimit}s. Exiting... (Exit code is 0 to not fail the pipeline)`);
|
|
55
|
+
process.exit(0);
|
|
56
|
+
}, parseInt(opts.timelimit, 10) * 1000);
|
|
56
57
|
}
|
|
57
|
-
|
|
58
58
|
try {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
} catch (err) {
|
|
62
|
-
console.log(APP_PREFIX, 'Error updating status, skipping...', err);
|
|
59
|
+
await runReader.createRun();
|
|
60
|
+
await runReader.uploadData();
|
|
63
61
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
62
|
+
catch (err) {
|
|
63
|
+
console.log(constants_js_1.APP_PREFIX, 'Error updating status, skipping...', err);
|
|
64
|
+
}
|
|
65
|
+
if (timeoutTimer)
|
|
66
|
+
clearTimeout(timeoutTimer);
|
|
67
|
+
});
|
|
68
68
|
if (process.argv.length < 3) {
|
|
69
|
-
|
|
69
|
+
program.outputHelp();
|
|
70
70
|
}
|
|
71
|
-
|
|
72
71
|
program.parse(process.argv);
|