@testomatio/reporter 2.8.2 â 2.8.4
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/bin/cli.js +33 -14
- package/lib/pipe/coverage.js +10 -10
- package/lib/utils/log.js +2 -1
- package/lib/utils/pipe_utils.d.ts +10 -0
- package/lib/utils/pipe_utils.js +23 -0
- package/package.json +1 -1
- package/src/bin/cli.js +31 -16
- package/src/pipe/coverage.js +10 -15
- package/src/utils/log.js +2 -1
- package/src/utils/pipe_utils.js +28 -7
package/lib/bin/cli.js
CHANGED
|
@@ -19,14 +19,14 @@ const filesize_1 = require("filesize");
|
|
|
19
19
|
const dotenv_1 = __importDefault(require("dotenv"));
|
|
20
20
|
const replay_js_1 = __importDefault(require("../replay.js"));
|
|
21
21
|
const log_js_1 = require("../utils/log.js");
|
|
22
|
+
const pipe_utils_js_1 = require("../utils/pipe_utils.js");
|
|
22
23
|
const debug = (0, debug_1.default)('@testomatio/reporter:cli');
|
|
23
24
|
const version = (0, utils_js_1.getPackageVersion)();
|
|
24
|
-
console.log(picocolors_1.default.cyan(picocolors_1.default.bold(` 𤊠Testomat.io Reporter v${version}`)));
|
|
25
25
|
const program = new commander_1.Command();
|
|
26
26
|
program
|
|
27
27
|
.version(version)
|
|
28
28
|
.option('--env-file <envfile>', 'Load environment variables from env file')
|
|
29
|
-
.hook('preAction', thisCommand => {
|
|
29
|
+
.hook('preAction', (thisCommand, actionCommand) => {
|
|
30
30
|
const opts = thisCommand.opts();
|
|
31
31
|
if (opts.envFile) {
|
|
32
32
|
dotenv_1.default.config({ path: opts.envFile });
|
|
@@ -34,6 +34,18 @@ program
|
|
|
34
34
|
else {
|
|
35
35
|
dotenv_1.default.config();
|
|
36
36
|
}
|
|
37
|
+
// --filter-list produces a machine-readable test list on stdout, so route
|
|
38
|
+
// remaining output to stderr, skip the banner, and silence info-level
|
|
39
|
+
// logs so the terminal isn't flooded with progress noise.
|
|
40
|
+
// Set TESTOMATIO_LOG_LEVEL=INFO to re-enable progress logs for debugging.
|
|
41
|
+
const subOpts = actionCommand.opts();
|
|
42
|
+
if (subOpts.filterList || subOpts.format) {
|
|
43
|
+
process.env.TESTOMATIO_LOG_STDERR = '1';
|
|
44
|
+
process.env.TESTOMATIO_LOG_LEVEL ||= 'WARN';
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
console.log(picocolors_1.default.cyan(picocolors_1.default.bold(` 𤊠Testomat.io Reporter v${version}`)));
|
|
48
|
+
}
|
|
37
49
|
});
|
|
38
50
|
program
|
|
39
51
|
.command('start')
|
|
@@ -77,6 +89,7 @@ program
|
|
|
77
89
|
.argument('[command]', 'Test runner command')
|
|
78
90
|
.option('--filter <filter>', 'Additional execution filter')
|
|
79
91
|
.option('--filter-list <filter>', 'Get a list of all tests by filter before running')
|
|
92
|
+
.option('--format <format>', 'Machine-readable output format for --filter-list (grep, json, newline, ids)')
|
|
80
93
|
.option('--kind <type>', 'Specify run type: automated, manual, or mixed')
|
|
81
94
|
.action(async (command, opts) => {
|
|
82
95
|
const apiKey = process.env['INPUT_TESTOMATIO-KEY'] || config_js_1.config.TESTOMATIO;
|
|
@@ -86,7 +99,7 @@ program
|
|
|
86
99
|
log_js_1.log.info('Filtering tests...');
|
|
87
100
|
// Example of use: npx @testomatio/reporter run "npx jest" --filter "testomatio:tag-name=frontend"
|
|
88
101
|
// Example of use: npx @testomatio/reporter run "npx jest" --filter "coverage:file=coverage.yml"
|
|
89
|
-
// Example of use: npx @testomatio/reporter run
|
|
102
|
+
// Example of use: npx @testomatio/reporter run --filter-list "coverage:file=coverage.yml" --format grep
|
|
90
103
|
const [pipe, ...optsArray] = opts?.filter ? opts?.filter.split(':') : opts?.filterList.split(':');
|
|
91
104
|
const pipeOptions = optsArray.join(':');
|
|
92
105
|
const prepareRunParams = { pipe, pipeOptions };
|
|
@@ -96,26 +109,32 @@ program
|
|
|
96
109
|
try {
|
|
97
110
|
const tests = await client.prepareRun(prepareRunParams);
|
|
98
111
|
if (!tests || tests.length === 0) {
|
|
99
|
-
log_js_1.log.
|
|
112
|
+
log_js_1.log.warn(picocolors_1.default.yellow('No tests found.'));
|
|
113
|
+
// Exit non-zero on --filter-list so scripts can detect "nothing to run"
|
|
114
|
+
// via $? and skip launching the runner.
|
|
115
|
+
if (opts.filterList)
|
|
116
|
+
process.exit(1);
|
|
100
117
|
return;
|
|
101
118
|
}
|
|
102
|
-
const pattern = `(${tests.join('|')})`;
|
|
103
|
-
const filteredCommand = (0, utils_js_1.applyFilter)(command, tests);
|
|
104
|
-
debug(`Execution pattern: "${pattern}"`);
|
|
105
119
|
if (opts.filterList) {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
120
|
+
const out = (0, pipe_utils_js_1.formatFilterListIds)(tests, opts.format || 'ids');
|
|
121
|
+
if (out)
|
|
122
|
+
console.log(out);
|
|
123
|
+
// Show the runnable-command hint only in interactive mode (no explicit --format).
|
|
124
|
+
// When --format is set the user is scripting and doesn't need stderr noise.
|
|
125
|
+
if (command && !opts.format) {
|
|
126
|
+
log_js_1.log.info(picocolors_1.default.green(`Full Running Command: ${(0, utils_js_1.applyFilter)(command, tests)}`));
|
|
127
|
+
}
|
|
111
128
|
return;
|
|
112
129
|
}
|
|
113
130
|
if (command && command.split) {
|
|
114
|
-
command =
|
|
131
|
+
command = (0, utils_js_1.applyFilter)(command, tests);
|
|
115
132
|
}
|
|
116
133
|
}
|
|
117
134
|
catch (err) {
|
|
118
|
-
log_js_1.log.
|
|
135
|
+
log_js_1.log.error(err.message || err);
|
|
136
|
+
if (opts.filterList)
|
|
137
|
+
process.exit(1);
|
|
119
138
|
return;
|
|
120
139
|
}
|
|
121
140
|
}
|
package/lib/pipe/coverage.js
CHANGED
|
@@ -54,7 +54,7 @@ class CoveragePipe {
|
|
|
54
54
|
this.branch = options?.diff || process.env.COVERAGE_BRANCH || this.#GIT.default_branch;
|
|
55
55
|
this.isBranchDefault = !options.diff && !process.env.COVERAGE_BRANCH;
|
|
56
56
|
if (this.isBranchDefault) {
|
|
57
|
-
|
|
57
|
+
log_js_1.log.info(`đĄ No "diff" branch provided. That's why we use default one = "${this.branch}".\n` +
|
|
58
58
|
'đ You can set it via --filter "coverage:file=coverage.yml,diff=your-branch"');
|
|
59
59
|
}
|
|
60
60
|
// Client config section
|
|
@@ -125,7 +125,7 @@ class CoveragePipe {
|
|
|
125
125
|
log_js_1.log.info(`Matched files: ${[...lines].join(', ')}`);
|
|
126
126
|
}
|
|
127
127
|
if (lines.size === 0) {
|
|
128
|
-
log_js_1.log.
|
|
128
|
+
log_js_1.log.warn('âšī¸ No matching entries in coverage file for provided Git changes.');
|
|
129
129
|
return [];
|
|
130
130
|
}
|
|
131
131
|
// Step 3: Handle tag labels tests from the server
|
|
@@ -136,13 +136,13 @@ class CoveragePipe {
|
|
|
136
136
|
const tests = await this.#getTestomatioTestsByParam(tagType, tag);
|
|
137
137
|
if (!tests)
|
|
138
138
|
return [];
|
|
139
|
-
|
|
139
|
+
log_js_1.log.info(`â
We found ${tests.length === 1 ? 'one entry' : `${tests.length} (test/suite) entries`}` +
|
|
140
140
|
' in Testomat.io service side.');
|
|
141
141
|
tests.forEach(testId => this.tests.add(testId));
|
|
142
142
|
}
|
|
143
143
|
}
|
|
144
144
|
if (this.tests.size === 0 && this.suiteIds.size === 0) {
|
|
145
|
-
log_js_1.log.
|
|
145
|
+
log_js_1.log.warn('âšī¸ No tests found for execution based on Git changes.');
|
|
146
146
|
return [];
|
|
147
147
|
}
|
|
148
148
|
this.results = [...this.tests, ...this.suiteIds];
|
|
@@ -201,7 +201,7 @@ class CoveragePipe {
|
|
|
201
201
|
...q,
|
|
202
202
|
});
|
|
203
203
|
if (!Array.isArray(resp.data?.tests) && resp.data?.tests?.length === 0) {
|
|
204
|
-
log_js_1.log.
|
|
204
|
+
log_js_1.log.warn(`đ No test by ${type}=${id} were found on the Testomat.io server side!`);
|
|
205
205
|
return undefined;
|
|
206
206
|
}
|
|
207
207
|
return resp.data.tests;
|
|
@@ -276,7 +276,7 @@ class CoveragePipe {
|
|
|
276
276
|
log_js_1.log.error(err.message);
|
|
277
277
|
return undefined;
|
|
278
278
|
}
|
|
279
|
-
log_js_1.log.
|
|
279
|
+
log_js_1.log.info(`We will use '${cmd}' Git command.`);
|
|
280
280
|
try {
|
|
281
281
|
// For clear unit testing process -> Like test_defaultGitChangedFile = todomvc-tests/edit-todos_test.js
|
|
282
282
|
if (this.isDefaultGitChanges) {
|
|
@@ -285,7 +285,7 @@ class CoveragePipe {
|
|
|
285
285
|
else {
|
|
286
286
|
this.changedFiles = this.#getChangedFilesFromGit(cmd);
|
|
287
287
|
if (this.changedFiles.length === 0) {
|
|
288
|
-
|
|
288
|
+
log_js_1.log.warn('âšī¸ No files changed in the latest Git commit. Skipping coverage processing.');
|
|
289
289
|
return undefined;
|
|
290
290
|
}
|
|
291
291
|
}
|
|
@@ -314,18 +314,18 @@ class CoveragePipe {
|
|
|
314
314
|
validateCoverageFile() {
|
|
315
315
|
// Validate the presence of the coverage filepath
|
|
316
316
|
if (!fs_1.default.existsSync(this.coverageFilePath)) {
|
|
317
|
-
log_js_1.log.
|
|
317
|
+
log_js_1.log.error('â Coverage file not found:', this.coverageFilePath);
|
|
318
318
|
return undefined;
|
|
319
319
|
}
|
|
320
320
|
// Ensure the given path is a file (not a directory or other type)
|
|
321
321
|
const stat = fs_1.default.statSync(this.coverageFilePath);
|
|
322
322
|
if (!stat.isFile()) {
|
|
323
|
-
log_js_1.log.
|
|
323
|
+
log_js_1.log.error('â Provided coverage path is not a file:', this.coverageFilePath);
|
|
324
324
|
return undefined;
|
|
325
325
|
}
|
|
326
326
|
// Validate the file extension to be ".yml" to ensure it's a YAML file
|
|
327
327
|
if (path_1.default.extname(this.coverageFilePath) !== ".yml") {
|
|
328
|
-
log_js_1.log.
|
|
328
|
+
log_js_1.log.error('â Coverage file must have a .yml extension:', this.coverageFilePath);
|
|
329
329
|
return undefined;
|
|
330
330
|
}
|
|
331
331
|
debug('Coverage file validation is OK!');
|
package/lib/utils/log.js
CHANGED
|
@@ -46,7 +46,8 @@ function shouldLog(messageLevel) {
|
|
|
46
46
|
*/
|
|
47
47
|
function info(...args) {
|
|
48
48
|
if (shouldLog(exports.LOG_LEVELS.INFO)) {
|
|
49
|
-
console.log
|
|
49
|
+
const fn = process.env.TESTOMATIO_LOG_STDERR === '1' ? console.error : console.log;
|
|
50
|
+
fn(constants_js_1.APP_PREFIX, ...args);
|
|
50
51
|
}
|
|
51
52
|
}
|
|
52
53
|
/**
|
|
@@ -54,3 +54,13 @@ export function fullName(t: object): string;
|
|
|
54
54
|
* => Returns: { foo: 'bar', baz: 'qux' }
|
|
55
55
|
*/
|
|
56
56
|
export function parsePipeOptions(optionsStr?: string): any;
|
|
57
|
+
/**
|
|
58
|
+
* Format a list of test IDs for `--filter-list` machine-readable output.
|
|
59
|
+
* Used when the CLI `--format` option is passed,
|
|
60
|
+
* e.g. `--filter-list "coverage:file=..." --format grep`.
|
|
61
|
+
*
|
|
62
|
+
* @param {string[]} ids
|
|
63
|
+
* @param {'grep'|'json'|'newline'|'ids'} format
|
|
64
|
+
* @returns {string} Empty string if no ids; otherwise the formatted output.
|
|
65
|
+
*/
|
|
66
|
+
export function formatFilterListIds(ids: string[], format: "grep" | "json" | "newline" | "ids"): string;
|
package/lib/utils/pipe_utils.js
CHANGED
|
@@ -7,6 +7,7 @@ exports.setS3Credentials = setS3Credentials;
|
|
|
7
7
|
exports.statusEmoji = statusEmoji;
|
|
8
8
|
exports.fullName = fullName;
|
|
9
9
|
exports.parsePipeOptions = parsePipeOptions;
|
|
10
|
+
exports.formatFilterListIds = formatFilterListIds;
|
|
10
11
|
const log_js_1 = require("./log.js");
|
|
11
12
|
/**
|
|
12
13
|
* Set S3 credentials from the provided artifacts object.
|
|
@@ -161,6 +162,26 @@ function parsePipeOptions(optionsStr) {
|
|
|
161
162
|
}
|
|
162
163
|
return options;
|
|
163
164
|
}
|
|
165
|
+
/**
|
|
166
|
+
* Format a list of test IDs for `--filter-list` machine-readable output.
|
|
167
|
+
* Used when the CLI `--format` option is passed,
|
|
168
|
+
* e.g. `--filter-list "coverage:file=..." --format grep`.
|
|
169
|
+
*
|
|
170
|
+
* @param {string[]} ids
|
|
171
|
+
* @param {'grep'|'json'|'newline'|'ids'} format
|
|
172
|
+
* @returns {string} Empty string if no ids; otherwise the formatted output.
|
|
173
|
+
*/
|
|
174
|
+
function formatFilterListIds(ids, format) {
|
|
175
|
+
if (!ids || ids.length === 0)
|
|
176
|
+
return '';
|
|
177
|
+
switch (format) {
|
|
178
|
+
case 'grep': return `(${ids.join('|')})`;
|
|
179
|
+
case 'json': return JSON.stringify(ids);
|
|
180
|
+
case 'newline': return ids.join('\n');
|
|
181
|
+
case 'ids':
|
|
182
|
+
default: return ids.join(',');
|
|
183
|
+
}
|
|
184
|
+
}
|
|
164
185
|
|
|
165
186
|
module.exports.updateFilterType = updateFilterType;
|
|
166
187
|
|
|
@@ -175,3 +196,5 @@ module.exports.statusEmoji = statusEmoji;
|
|
|
175
196
|
module.exports.fullName = fullName;
|
|
176
197
|
|
|
177
198
|
module.exports.parsePipeOptions = parsePipeOptions;
|
|
199
|
+
|
|
200
|
+
module.exports.formatFilterListIds = formatFilterListIds;
|
package/package.json
CHANGED
package/src/bin/cli.js
CHANGED
|
@@ -15,22 +15,34 @@ import { filesize as prettyBytes } from 'filesize';
|
|
|
15
15
|
import dotenv from 'dotenv';
|
|
16
16
|
import Replay from '../replay.js';
|
|
17
17
|
import { log } from '../utils/log.js';
|
|
18
|
+
import { formatFilterListIds } from '../utils/pipe_utils.js';
|
|
18
19
|
|
|
19
20
|
const debug = createDebugMessages('@testomatio/reporter:cli');
|
|
20
21
|
const version = getPackageVersion();
|
|
21
|
-
console.log(pc.cyan(pc.bold(` 𤊠Testomat.io Reporter v${version}`)));
|
|
22
22
|
const program = new Command();
|
|
23
23
|
|
|
24
24
|
program
|
|
25
25
|
.version(version)
|
|
26
26
|
.option('--env-file <envfile>', 'Load environment variables from env file')
|
|
27
|
-
.hook('preAction', thisCommand => {
|
|
27
|
+
.hook('preAction', (thisCommand, actionCommand) => {
|
|
28
28
|
const opts = thisCommand.opts();
|
|
29
29
|
if (opts.envFile) {
|
|
30
30
|
dotenv.config({ path: opts.envFile });
|
|
31
31
|
} else {
|
|
32
32
|
dotenv.config();
|
|
33
33
|
}
|
|
34
|
+
|
|
35
|
+
// --filter-list produces a machine-readable test list on stdout, so route
|
|
36
|
+
// remaining output to stderr, skip the banner, and silence info-level
|
|
37
|
+
// logs so the terminal isn't flooded with progress noise.
|
|
38
|
+
// Set TESTOMATIO_LOG_LEVEL=INFO to re-enable progress logs for debugging.
|
|
39
|
+
const subOpts = actionCommand.opts();
|
|
40
|
+
if (subOpts.filterList || subOpts.format) {
|
|
41
|
+
process.env.TESTOMATIO_LOG_STDERR = '1';
|
|
42
|
+
process.env.TESTOMATIO_LOG_LEVEL ||= 'WARN';
|
|
43
|
+
} else {
|
|
44
|
+
console.log(pc.cyan(pc.bold(` 𤊠Testomat.io Reporter v${version}`)));
|
|
45
|
+
}
|
|
34
46
|
});
|
|
35
47
|
|
|
36
48
|
program
|
|
@@ -83,6 +95,7 @@ program
|
|
|
83
95
|
.argument('[command]', 'Test runner command')
|
|
84
96
|
.option('--filter <filter>', 'Additional execution filter')
|
|
85
97
|
.option('--filter-list <filter>', 'Get a list of all tests by filter before running')
|
|
98
|
+
.option('--format <format>', 'Machine-readable output format for --filter-list (grep, json, newline, ids)')
|
|
86
99
|
.option('--kind <type>', 'Specify run type: automated, manual, or mixed')
|
|
87
100
|
.action(async (command, opts) => {
|
|
88
101
|
const apiKey = process.env['INPUT_TESTOMATIO-KEY'] || config.TESTOMATIO;
|
|
@@ -93,7 +106,7 @@ program
|
|
|
93
106
|
log.info('Filtering tests...');
|
|
94
107
|
// Example of use: npx @testomatio/reporter run "npx jest" --filter "testomatio:tag-name=frontend"
|
|
95
108
|
// Example of use: npx @testomatio/reporter run "npx jest" --filter "coverage:file=coverage.yml"
|
|
96
|
-
// Example of use: npx @testomatio/reporter run
|
|
109
|
+
// Example of use: npx @testomatio/reporter run --filter-list "coverage:file=coverage.yml" --format grep
|
|
97
110
|
const [pipe, ...optsArray] = opts?.filter ? opts?.filter.split(':') : opts?.filterList.split(':');
|
|
98
111
|
const pipeOptions = optsArray.join(':');
|
|
99
112
|
|
|
@@ -106,29 +119,31 @@ program
|
|
|
106
119
|
const tests = await client.prepareRun(prepareRunParams);
|
|
107
120
|
|
|
108
121
|
if (!tests || tests.length === 0) {
|
|
109
|
-
log.
|
|
122
|
+
log.warn( pc.yellow('No tests found.'));
|
|
123
|
+
// Exit non-zero on --filter-list so scripts can detect "nothing to run"
|
|
124
|
+
// via $? and skip launching the runner.
|
|
125
|
+
if (opts.filterList) process.exit(1);
|
|
110
126
|
return;
|
|
111
127
|
}
|
|
112
128
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
console.log(`Grep string:`);
|
|
122
|
-
console.log(`${tests.join(', ')}`);
|
|
129
|
+
if (opts.filterList) {
|
|
130
|
+
const out = formatFilterListIds(tests, opts.format || 'ids');
|
|
131
|
+
if (out) console.log(out);
|
|
132
|
+
// Show the runnable-command hint only in interactive mode (no explicit --format).
|
|
133
|
+
// When --format is set the user is scripting and doesn't need stderr noise.
|
|
134
|
+
if (command && !opts.format) {
|
|
135
|
+
log.info(pc.green(`Full Running Command: ${applyFilter(command, tests)}`));
|
|
136
|
+
}
|
|
123
137
|
return;
|
|
124
138
|
}
|
|
125
139
|
|
|
126
140
|
if (command && command.split) {
|
|
127
|
-
command =
|
|
141
|
+
command = applyFilter(command, tests);
|
|
128
142
|
}
|
|
129
143
|
}
|
|
130
144
|
catch (err) {
|
|
131
|
-
log.
|
|
145
|
+
log.error( err.message || err);
|
|
146
|
+
if (opts.filterList) process.exit(1);
|
|
132
147
|
return;
|
|
133
148
|
}
|
|
134
149
|
}
|
package/src/pipe/coverage.js
CHANGED
|
@@ -57,8 +57,7 @@ class CoveragePipe { // or Changes for the future???
|
|
|
57
57
|
this.isBranchDefault = !options.diff && !process.env.COVERAGE_BRANCH;
|
|
58
58
|
|
|
59
59
|
if (this.isBranchDefault) {
|
|
60
|
-
|
|
61
|
-
APP_PREFIX,
|
|
60
|
+
log.info(
|
|
62
61
|
`đĄ No "diff" branch provided. That's why we use default one = "${this.branch}".\n` +
|
|
63
62
|
'đ You can set it via --filter "coverage:file=coverage.yml,diff=your-branch"'
|
|
64
63
|
);
|
|
@@ -141,7 +140,7 @@ class CoveragePipe { // or Changes for the future???
|
|
|
141
140
|
}
|
|
142
141
|
|
|
143
142
|
if (lines.size === 0) {
|
|
144
|
-
log.
|
|
143
|
+
log.warn( 'âšī¸ No matching entries in coverage file for provided Git changes.');
|
|
145
144
|
return [];
|
|
146
145
|
}
|
|
147
146
|
|
|
@@ -154,8 +153,7 @@ class CoveragePipe { // or Changes for the future???
|
|
|
154
153
|
|
|
155
154
|
if (!tests) return [];
|
|
156
155
|
|
|
157
|
-
|
|
158
|
-
APP_PREFIX,
|
|
156
|
+
log.info(
|
|
159
157
|
`â
We found ${tests.length === 1 ? 'one entry' : `${tests.length} (test/suite) entries`}` +
|
|
160
158
|
' in Testomat.io service side.'
|
|
161
159
|
);
|
|
@@ -165,7 +163,7 @@ class CoveragePipe { // or Changes for the future???
|
|
|
165
163
|
}
|
|
166
164
|
|
|
167
165
|
if (this.tests.size === 0 && this.suiteIds.size === 0) {
|
|
168
|
-
log.
|
|
166
|
+
log.warn( 'âšī¸ No tests found for execution based on Git changes.');
|
|
169
167
|
return [];
|
|
170
168
|
}
|
|
171
169
|
|
|
@@ -236,7 +234,7 @@ class CoveragePipe { // or Changes for the future???
|
|
|
236
234
|
});
|
|
237
235
|
|
|
238
236
|
if (!Array.isArray(resp.data?.tests) && resp.data?.tests?.length === 0) {
|
|
239
|
-
log.
|
|
237
|
+
log.warn( `đ No test by ${type}=${id} were found on the Testomat.io server side!`);
|
|
240
238
|
|
|
241
239
|
return undefined;
|
|
242
240
|
}
|
|
@@ -324,7 +322,7 @@ class CoveragePipe { // or Changes for the future???
|
|
|
324
322
|
return undefined;
|
|
325
323
|
}
|
|
326
324
|
|
|
327
|
-
log.
|
|
325
|
+
log.info( `We will use '${cmd}' Git command.`);
|
|
328
326
|
|
|
329
327
|
try {
|
|
330
328
|
// For clear unit testing process -> Like test_defaultGitChangedFile = todomvc-tests/edit-todos_test.js
|
|
@@ -335,10 +333,7 @@ class CoveragePipe { // or Changes for the future???
|
|
|
335
333
|
this.changedFiles = this.#getChangedFilesFromGit(cmd);
|
|
336
334
|
|
|
337
335
|
if (this.changedFiles.length === 0) {
|
|
338
|
-
|
|
339
|
-
APP_PREFIX,
|
|
340
|
-
'âšī¸ No files changed in the latest Git commit. Skipping coverage processing.'
|
|
341
|
-
);
|
|
336
|
+
log.warn('âšī¸ No files changed in the latest Git commit. Skipping coverage processing.');
|
|
342
337
|
|
|
343
338
|
return undefined;
|
|
344
339
|
}
|
|
@@ -370,20 +365,20 @@ class CoveragePipe { // or Changes for the future???
|
|
|
370
365
|
validateCoverageFile() {
|
|
371
366
|
// Validate the presence of the coverage filepath
|
|
372
367
|
if (!fs.existsSync(this.coverageFilePath)) {
|
|
373
|
-
log.
|
|
368
|
+
log.error( 'â Coverage file not found:', this.coverageFilePath);
|
|
374
369
|
return undefined;
|
|
375
370
|
}
|
|
376
371
|
|
|
377
372
|
// Ensure the given path is a file (not a directory or other type)
|
|
378
373
|
const stat = fs.statSync(this.coverageFilePath);
|
|
379
374
|
if (!stat.isFile()) {
|
|
380
|
-
log.
|
|
375
|
+
log.error( 'â Provided coverage path is not a file:', this.coverageFilePath);
|
|
381
376
|
return undefined;
|
|
382
377
|
}
|
|
383
378
|
|
|
384
379
|
// Validate the file extension to be ".yml" to ensure it's a YAML file
|
|
385
380
|
if (path.extname(this.coverageFilePath) !== ".yml") {
|
|
386
|
-
log.
|
|
381
|
+
log.error( 'â Coverage file must have a .yml extension:', this.coverageFilePath);
|
|
387
382
|
return undefined;
|
|
388
383
|
}
|
|
389
384
|
|
package/src/utils/log.js
CHANGED
|
@@ -42,7 +42,8 @@ export function shouldLog(messageLevel) {
|
|
|
42
42
|
*/
|
|
43
43
|
export function info(...args) {
|
|
44
44
|
if (shouldLog(LOG_LEVELS.INFO)) {
|
|
45
|
-
console.log
|
|
45
|
+
const fn = process.env.TESTOMATIO_LOG_STDERR === '1' ? console.error : console.log;
|
|
46
|
+
fn(APP_PREFIX, ...args);
|
|
46
47
|
}
|
|
47
48
|
}
|
|
48
49
|
|
package/src/utils/pipe_utils.js
CHANGED
|
@@ -161,12 +161,33 @@ function parsePipeOptions(optionsStr) {
|
|
|
161
161
|
return options;
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
164
|
+
/**
|
|
165
|
+
* Format a list of test IDs for `--filter-list` machine-readable output.
|
|
166
|
+
* Used when the CLI `--format` option is passed,
|
|
167
|
+
* e.g. `--filter-list "coverage:file=..." --format grep`.
|
|
168
|
+
*
|
|
169
|
+
* @param {string[]} ids
|
|
170
|
+
* @param {'grep'|'json'|'newline'|'ids'} format
|
|
171
|
+
* @returns {string} Empty string if no ids; otherwise the formatted output.
|
|
172
|
+
*/
|
|
173
|
+
function formatFilterListIds(ids, format) {
|
|
174
|
+
if (!ids || ids.length === 0) return '';
|
|
175
|
+
switch (format) {
|
|
176
|
+
case 'grep': return `(${ids.join('|')})`;
|
|
177
|
+
case 'json': return JSON.stringify(ids);
|
|
178
|
+
case 'newline': return ids.join('\n');
|
|
179
|
+
case 'ids':
|
|
180
|
+
default: return ids.join(',');
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export {
|
|
185
|
+
updateFilterType,
|
|
186
|
+
parseFilterParams,
|
|
187
|
+
generateFilterRequestParams,
|
|
188
|
+
setS3Credentials,
|
|
189
|
+
statusEmoji,
|
|
170
190
|
fullName,
|
|
171
|
-
parsePipeOptions
|
|
191
|
+
parsePipeOptions,
|
|
192
|
+
formatFilterListIds,
|
|
172
193
|
};
|