@testomatio/reporter 2.3.9 → 2.5.0
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 -1
- package/lib/bin/cli.js +26 -7
- package/lib/client.js +18 -10
- package/lib/data-storage.d.ts +1 -1
- package/lib/helpers.d.ts +1 -0
- package/lib/helpers.js +4 -0
- package/lib/pipe/coverage.d.ts +82 -0
- package/lib/pipe/coverage.js +373 -0
- package/lib/pipe/index.js +2 -0
- package/lib/pipe/testomatio.d.ts +1 -1
- package/lib/pipe/testomatio.js +25 -4
- package/lib/reporter-functions.d.ts +7 -1
- package/lib/reporter-functions.js +21 -11
- package/lib/reporter.d.ts +21 -14
- package/lib/services/artifacts.d.ts +1 -1
- package/lib/services/key-values.d.ts +1 -1
- package/lib/services/links.d.ts +1 -1
- package/lib/services/logger.d.ts +3 -3
- package/lib/services/logger.js +36 -33
- package/lib/utils/pipe_utils.d.ts +15 -0
- package/lib/utils/pipe_utils.js +44 -2
- package/lib/utils/utils.d.ts +6 -0
- package/lib/utils/utils.js +71 -1
- package/package.json +5 -4
- package/src/bin/cli.js +35 -9
- package/src/client.js +22 -14
- package/src/helpers.js +1 -0
- package/src/pipe/coverage.js +440 -0
- package/src/pipe/index.js +2 -0
- package/src/pipe/testomatio.js +34 -5
- package/src/reporter-functions.js +20 -11
- package/src/services/logger.js +34 -29
- package/src/utils/pipe_utils.js +52 -3
- package/src/utils/utils.js +75 -0
- package/types/types.d.ts +2 -1
|
@@ -28,9 +28,15 @@ declare function logMessage(...args: any[]): void;
|
|
|
28
28
|
/**
|
|
29
29
|
* Similar to "log" function but marks message in report as a step
|
|
30
30
|
* @param {string} message - step message
|
|
31
|
+
* @param {{[key: string]: any}} [logs] optional key-value object with additional info, e.g. logs
|
|
31
32
|
* @returns {void}
|
|
33
|
+
*
|
|
34
|
+
* Example:
|
|
35
|
+
* step('Get response', { logs: {status: 'success'} });
|
|
32
36
|
*/
|
|
33
|
-
declare function addStep(message: string
|
|
37
|
+
declare function addStep(message: string, logs?: {
|
|
38
|
+
[key: string]: any;
|
|
39
|
+
}): void;
|
|
34
40
|
/**
|
|
35
41
|
* Add key-value pair(s) to the test report
|
|
36
42
|
* @param {{[key: string]: string} | string} keyValue - object { key: value } (multiple props allowed) or key (string)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const helpers_js_1 = require("./helpers.js");
|
|
3
4
|
const index_js_1 = require("./services/index.js");
|
|
4
5
|
/**
|
|
5
6
|
* Stores path to file as artifact and uploads it to the S3 storage
|
|
@@ -8,9 +9,7 @@ const index_js_1 = require("./services/index.js");
|
|
|
8
9
|
* @returns {void}
|
|
9
10
|
*/
|
|
10
11
|
function saveArtifact(data, context = null) {
|
|
11
|
-
|
|
12
|
-
throw new Error(`This function is not available in Playwright framework.
|
|
13
|
-
/Playwright supports artifacts out of the box`);
|
|
12
|
+
showPlaywrightWarning('artifact', 'Playwright supports artifacts out of the box.');
|
|
14
13
|
if (!data)
|
|
15
14
|
return;
|
|
16
15
|
index_js_1.services.artifacts.put(data, context);
|
|
@@ -21,19 +20,25 @@ function saveArtifact(data, context = null) {
|
|
|
21
20
|
* @returns {void}
|
|
22
21
|
*/
|
|
23
22
|
function logMessage(...args) {
|
|
24
|
-
if (process.env.IS_PLAYWRIGHT)
|
|
25
|
-
throw new Error('This function is not available in Playwright framework');
|
|
26
23
|
index_js_1.services.logger._templateLiteralLog(...args);
|
|
27
24
|
}
|
|
28
25
|
/**
|
|
29
26
|
* Similar to "log" function but marks message in report as a step
|
|
30
27
|
* @param {string} message - step message
|
|
28
|
+
* @param {{[key: string]: any}} [logs] optional key-value object with additional info, e.g. logs
|
|
31
29
|
* @returns {void}
|
|
30
|
+
*
|
|
31
|
+
* Example:
|
|
32
|
+
* step('Get response', { logs: {status: 'success'} });
|
|
32
33
|
*/
|
|
33
|
-
function addStep(message) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
function addStep(message, logs) {
|
|
35
|
+
// this is done because Playwright reporter intercepts console logs and then we gather them and show on Testomat
|
|
36
|
+
// if not console.log, the step message will be lost from reporter
|
|
37
|
+
if (helpers_js_1.isPlaywright)
|
|
38
|
+
index_js_1.services.logger._templateLiteralLog(message, logs);
|
|
39
|
+
// all other frameworks
|
|
40
|
+
else
|
|
41
|
+
index_js_1.services.logger.step(message, logs);
|
|
37
42
|
}
|
|
38
43
|
/**
|
|
39
44
|
* Add key-value pair(s) to the test report
|
|
@@ -42,8 +47,7 @@ function addStep(message) {
|
|
|
42
47
|
* @returns {void}
|
|
43
48
|
*/
|
|
44
49
|
function setKeyValue(keyValue, value = null) {
|
|
45
|
-
|
|
46
|
-
throw new Error('This function is not available in Playwright framework. Use test tag instead.');
|
|
50
|
+
showPlaywrightWarning('meta', 'Use test annotations instead.');
|
|
47
51
|
if (typeof keyValue === 'string') {
|
|
48
52
|
keyValue = { [keyValue]: value };
|
|
49
53
|
}
|
|
@@ -56,6 +60,7 @@ function setKeyValue(keyValue, value = null) {
|
|
|
56
60
|
* @returns {void}
|
|
57
61
|
*/
|
|
58
62
|
function setLabel(key, value = null) {
|
|
63
|
+
showPlaywrightWarning('label', 'Use test tag instead.');
|
|
59
64
|
if (Array.isArray(value)) {
|
|
60
65
|
return value.forEach(label => setLabel(key, label));
|
|
61
66
|
}
|
|
@@ -80,6 +85,11 @@ function linkJira(...jiraIds) {
|
|
|
80
85
|
const links = jiraIds.map(jiraId => ({ jira: jiraId }));
|
|
81
86
|
index_js_1.services.links.put(links);
|
|
82
87
|
}
|
|
88
|
+
function showPlaywrightWarning(functionName, recommendation) {
|
|
89
|
+
if (helpers_js_1.isPlaywright) {
|
|
90
|
+
console.warn(`[TESTOMATIO] '${functionName}' function is not supported for Playwright. ${recommendation}`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
83
93
|
module.exports = {
|
|
84
94
|
artifact: saveArtifact,
|
|
85
95
|
log: logMessage,
|
package/lib/reporter.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ export const artifact: (data: string | {
|
|
|
12
12
|
}, context?: any) => void;
|
|
13
13
|
export const log: (...args: any[]) => void;
|
|
14
14
|
export const logger: {
|
|
15
|
-
"__#
|
|
15
|
+
"__#14@#originalUserLogger": {
|
|
16
16
|
assert(condition?: boolean, ...data: any[]): void;
|
|
17
17
|
assert(value: any, message?: string, ...optionalParams: any[]): void;
|
|
18
18
|
clear(): void;
|
|
@@ -57,13 +57,14 @@ export const logger: {
|
|
|
57
57
|
profile(label?: string): void;
|
|
58
58
|
profileEnd(label?: string): void;
|
|
59
59
|
};
|
|
60
|
-
"__#
|
|
60
|
+
"__#14@#userLoggerWithOverridenMethods": any;
|
|
61
61
|
logLevel: string;
|
|
62
62
|
step(strings: any, ...values: any[]): void;
|
|
63
63
|
getLogs(context: string): string[];
|
|
64
|
-
"__#
|
|
64
|
+
"__#14@#stringifyLogs"(...args: any[]): string;
|
|
65
|
+
"__#14@#formatMessage"(strings: any, ...args: any[]): string;
|
|
65
66
|
_templateLiteralLog(strings: any, ...args: any[]): void;
|
|
66
|
-
"__#
|
|
67
|
+
"__#14@#logWrapper"(argsArray: any, level: any): void;
|
|
67
68
|
assert(...args: any[]): void;
|
|
68
69
|
debug(...args: any[]): void;
|
|
69
70
|
error(...args: any[]): void;
|
|
@@ -82,13 +83,15 @@ export const logger: {
|
|
|
82
83
|
export const meta: (keyValue: {
|
|
83
84
|
[key: string]: string;
|
|
84
85
|
} | string, value?: string | null) => void;
|
|
85
|
-
export const step: (message: string
|
|
86
|
+
export const step: (message: string, logs?: {
|
|
87
|
+
[key: string]: any;
|
|
88
|
+
}) => void;
|
|
86
89
|
export const label: (key: string, value?: string | null) => void;
|
|
87
90
|
export const linkTest: (...testIds: string[]) => void;
|
|
88
91
|
export const linkJira: (...jiraIds: string[]) => void;
|
|
89
92
|
declare namespace _default {
|
|
90
93
|
export let testomatioLogger: {
|
|
91
|
-
"__#
|
|
94
|
+
"__#14@#originalUserLogger": {
|
|
92
95
|
assert(condition?: boolean, ...data: any[]): void;
|
|
93
96
|
assert(value: any, message?: string, ...optionalParams: any[]): void;
|
|
94
97
|
clear(): void;
|
|
@@ -133,13 +136,14 @@ declare namespace _default {
|
|
|
133
136
|
profile(label?: string): void;
|
|
134
137
|
profileEnd(label?: string): void;
|
|
135
138
|
};
|
|
136
|
-
"__#
|
|
139
|
+
"__#14@#userLoggerWithOverridenMethods": any;
|
|
137
140
|
logLevel: string;
|
|
138
141
|
step(strings: any, ...values: any[]): void;
|
|
139
142
|
getLogs(context: string): string[];
|
|
140
|
-
"__#
|
|
143
|
+
"__#14@#stringifyLogs"(...args: any[]): string;
|
|
144
|
+
"__#14@#formatMessage"(strings: any, ...args: any[]): string;
|
|
141
145
|
_templateLiteralLog(strings: any, ...args: any[]): void;
|
|
142
|
-
"__#
|
|
146
|
+
"__#14@#logWrapper"(argsArray: any, level: any): void;
|
|
143
147
|
assert(...args: any[]): void;
|
|
144
148
|
debug(...args: any[]): void;
|
|
145
149
|
error(...args: any[]): void;
|
|
@@ -162,7 +166,7 @@ declare namespace _default {
|
|
|
162
166
|
}, context?: any) => void;
|
|
163
167
|
export let log: (...args: any[]) => void;
|
|
164
168
|
export let logger: {
|
|
165
|
-
"__#
|
|
169
|
+
"__#14@#originalUserLogger": {
|
|
166
170
|
assert(condition?: boolean, ...data: any[]): void;
|
|
167
171
|
assert(value: any, message?: string, ...optionalParams: any[]): void;
|
|
168
172
|
clear(): void;
|
|
@@ -207,13 +211,14 @@ declare namespace _default {
|
|
|
207
211
|
profile(label?: string): void;
|
|
208
212
|
profileEnd(label?: string): void;
|
|
209
213
|
};
|
|
210
|
-
"__#
|
|
214
|
+
"__#14@#userLoggerWithOverridenMethods": any;
|
|
211
215
|
logLevel: string;
|
|
212
216
|
step(strings: any, ...values: any[]): void;
|
|
213
217
|
getLogs(context: string): string[];
|
|
214
|
-
"__#
|
|
218
|
+
"__#14@#stringifyLogs"(...args: any[]): string;
|
|
219
|
+
"__#14@#formatMessage"(strings: any, ...args: any[]): string;
|
|
215
220
|
_templateLiteralLog(strings: any, ...args: any[]): void;
|
|
216
|
-
"__#
|
|
221
|
+
"__#14@#logWrapper"(argsArray: any, level: any): void;
|
|
217
222
|
assert(...args: any[]): void;
|
|
218
223
|
debug(...args: any[]): void;
|
|
219
224
|
error(...args: any[]): void;
|
|
@@ -232,7 +237,9 @@ declare namespace _default {
|
|
|
232
237
|
export let meta: (keyValue: {
|
|
233
238
|
[key: string]: string;
|
|
234
239
|
} | string, value?: string | null) => void;
|
|
235
|
-
export let step: (message: string
|
|
240
|
+
export let step: (message: string, logs?: {
|
|
241
|
+
[key: string]: any;
|
|
242
|
+
}) => void;
|
|
236
243
|
export let label: (key: string, value?: string | null) => void;
|
|
237
244
|
export let linkTest: (...testIds: string[]) => void;
|
|
238
245
|
export let linkJira: (...jiraIds: string[]) => void;
|
package/lib/services/links.d.ts
CHANGED
package/lib/services/logger.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export const logger: Logger;
|
|
|
5
5
|
* Supports different syntaxes to satisfy any user preferences.
|
|
6
6
|
*/
|
|
7
7
|
declare class Logger {
|
|
8
|
-
static "__#
|
|
8
|
+
static "__#14@#instance": any;
|
|
9
9
|
/**
|
|
10
10
|
*
|
|
11
11
|
* @returns {Logger}
|
|
@@ -26,8 +26,8 @@ declare class Logger {
|
|
|
26
26
|
*/
|
|
27
27
|
getLogs(context: string): string[];
|
|
28
28
|
/**
|
|
29
|
-
*
|
|
30
|
-
* 1.
|
|
29
|
+
* Tagged template literal. Allows to use different syntaxes:
|
|
30
|
+
* 1. Tagged template: log`text ${someVar}`
|
|
31
31
|
* 2. Standard: log(`text ${someVar}`)
|
|
32
32
|
* 3. Standard with multiple arguments: log('text', someVar)
|
|
33
33
|
*/
|
package/lib/services/logger.js
CHANGED
|
@@ -54,14 +54,10 @@ class Logger {
|
|
|
54
54
|
* @param {...any} values
|
|
55
55
|
*/
|
|
56
56
|
step(strings, ...values) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
logs += values[i];
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
logs = picocolors_1.default.blue(`> ${logs}`);
|
|
57
|
+
// Filter trailing undefined from optional params (e.g., step('message') called without second arg)
|
|
58
|
+
const filteredValues = values.filter(v => v !== undefined);
|
|
59
|
+
const message = this.#formatMessage(strings, ...filteredValues);
|
|
60
|
+
const logs = picocolors_1.default.blue(`> ${message}`);
|
|
65
61
|
data_storage_js_1.dataStorage.putData('log', logs);
|
|
66
62
|
}
|
|
67
63
|
/**
|
|
@@ -82,7 +78,13 @@ class Logger {
|
|
|
82
78
|
// ignore empty strings
|
|
83
79
|
if (arg === '')
|
|
84
80
|
continue;
|
|
85
|
-
if (
|
|
81
|
+
if (arg === undefined) {
|
|
82
|
+
logs.push('undefined');
|
|
83
|
+
}
|
|
84
|
+
else if (arg === null) {
|
|
85
|
+
logs.push('null');
|
|
86
|
+
}
|
|
87
|
+
else if (typeof arg === 'string') {
|
|
86
88
|
logs.push(arg);
|
|
87
89
|
}
|
|
88
90
|
else if (Array.isArray(arg)) {
|
|
@@ -101,36 +103,37 @@ class Logger {
|
|
|
101
103
|
return logs.join(' ');
|
|
102
104
|
}
|
|
103
105
|
/**
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
106
|
+
* Formats a message from either tagged template literal or standard function call.
|
|
107
|
+
* @param {*} strings - Template strings array or first argument
|
|
108
|
+
* @param {...any} args - Template values or additional arguments
|
|
109
|
+
* @returns {string} Formatted message
|
|
108
110
|
*/
|
|
109
|
-
|
|
110
|
-
if (Array.isArray(strings))
|
|
111
|
-
strings = strings.filter(item => item !== '').map(item => item.trim());
|
|
111
|
+
#formatMessage(strings, ...args) {
|
|
112
112
|
if (Array.isArray(args))
|
|
113
113
|
args = args.filter(item => item !== '');
|
|
114
|
-
|
|
115
|
-
// this block means tagged template is used (syntax like $`text ${someVar}`)
|
|
114
|
+
// Tagged template syntax: func`text ${someVar}`
|
|
116
115
|
if (Array.isArray(strings) && strings.length === args.length + 1) {
|
|
117
|
-
|
|
116
|
+
return strings.reduce((result, current, index) => result +
|
|
118
117
|
current +
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
: ''),
|
|
126
|
-
// initial accumulator value
|
|
127
|
-
'');
|
|
128
|
-
}
|
|
129
|
-
else {
|
|
130
|
-
// this block means arguments syntax is used (syntax like $('text', someVar))
|
|
131
|
-
// in this case strings represents just a first argument
|
|
132
|
-
logs = this.#stringifyLogs(strings, ...args);
|
|
118
|
+
(index < args.length
|
|
119
|
+
? args[index] === undefined
|
|
120
|
+
? 'undefined'
|
|
121
|
+
: typeof args[index] === 'string'
|
|
122
|
+
? args[index]
|
|
123
|
+
: this.#stringifyLogs(args[index])
|
|
124
|
+
: ''), '');
|
|
133
125
|
}
|
|
126
|
+
// Standard function call: func('text', someVar)
|
|
127
|
+
return this.#stringifyLogs(strings, ...args);
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Tagged template literal. Allows to use different syntaxes:
|
|
131
|
+
* 1. Tagged template: log`text ${someVar}`
|
|
132
|
+
* 2. Standard: log(`text ${someVar}`)
|
|
133
|
+
* 3. Standard with multiple arguments: log('text', someVar)
|
|
134
|
+
*/
|
|
135
|
+
_templateLiteralLog(strings, ...args) {
|
|
136
|
+
const logs = this.#formatMessage(strings, ...args);
|
|
134
137
|
this.#originalUserLogger.log(logs);
|
|
135
138
|
data_storage_js_1.dataStorage.putData('log', logs);
|
|
136
139
|
}
|
|
@@ -39,3 +39,18 @@ export function statusEmoji(status: string): string;
|
|
|
39
39
|
* @returns {string} - A formatted full name string for the test object.
|
|
40
40
|
*/
|
|
41
41
|
export function fullName(t: object): string;
|
|
42
|
+
/**
|
|
43
|
+
* Parses a comma-separated list of key-value pairs into an options object.
|
|
44
|
+
*
|
|
45
|
+
* The input string should be formatted as `"key1=value1,key2=value2,..."`.
|
|
46
|
+
* Whitespace around keys and values is trimmed. If the input is empty or undefined,
|
|
47
|
+
* an empty object is returned.
|
|
48
|
+
*
|
|
49
|
+
* @param {string} [optionsStr] - A comma-separated string of key=value pairs.
|
|
50
|
+
* @returns {Object} An object mapping option keys to their string values.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* parsePipeOptions('foo=bar,baz=qux');
|
|
54
|
+
* => Returns: { foo: 'bar', baz: 'qux' }
|
|
55
|
+
*/
|
|
56
|
+
export function parsePipeOptions(optionsStr?: string): any;
|
package/lib/utils/pipe_utils.js
CHANGED
|
@@ -6,6 +6,7 @@ exports.generateFilterRequestParams = generateFilterRequestParams;
|
|
|
6
6
|
exports.setS3Credentials = setS3Credentials;
|
|
7
7
|
exports.statusEmoji = statusEmoji;
|
|
8
8
|
exports.fullName = fullName;
|
|
9
|
+
exports.parsePipeOptions = parsePipeOptions;
|
|
9
10
|
const constants_js_1 = require("../constants.js");
|
|
10
11
|
/**
|
|
11
12
|
* Set S3 credentials from the provided artifacts object.
|
|
@@ -27,6 +28,8 @@ function setS3Credentials(artifacts) {
|
|
|
27
28
|
process.env.S3_SESSION_TOKEN = artifacts.SESSION_TOKEN;
|
|
28
29
|
if (artifacts.presign)
|
|
29
30
|
process.env.TESTOMATIO_PRIVATE_ARTIFACTS = '1';
|
|
31
|
+
if (artifacts.stack_artifacts)
|
|
32
|
+
process.env.TESTOMATIO_STACK_ARTIFACTS = '1';
|
|
30
33
|
// endpoint is not received from the server; and shuld be empty if IAM used (credentails obtained from the testomat)
|
|
31
34
|
process.env.S3_ENDPOINT = artifacts.ENDPOINT || '';
|
|
32
35
|
}
|
|
@@ -36,6 +39,11 @@ function setS3Credentials(artifacts) {
|
|
|
36
39
|
* @returns {Object|null} - An object containing the generated request parameters, or null if the type is invalid.
|
|
37
40
|
*/
|
|
38
41
|
function generateFilterRequestParams(params) {
|
|
42
|
+
// Defensive check: ensure params is an object
|
|
43
|
+
if (!params || typeof params !== 'object') {
|
|
44
|
+
console.error(constants_js_1.APP_PREFIX, `Invalid parameters provided. Expected an object, got: ${typeof params}`);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
39
47
|
const { type, id, apiKey } = params;
|
|
40
48
|
if (!type) {
|
|
41
49
|
return;
|
|
@@ -60,8 +68,11 @@ function generateFilterRequestParams(params) {
|
|
|
60
68
|
* The object has properties "type" and "id".
|
|
61
69
|
*/
|
|
62
70
|
function parseFilterParams(opts) {
|
|
63
|
-
const [type,
|
|
71
|
+
const [type, ...idParts] = opts.split('=');
|
|
72
|
+
const id = idParts.join('=');
|
|
64
73
|
const validType = updateFilterType(type);
|
|
74
|
+
if (!validType)
|
|
75
|
+
return undefined;
|
|
65
76
|
return {
|
|
66
77
|
type: validType,
|
|
67
78
|
id,
|
|
@@ -74,6 +85,8 @@ function parseFilterParams(opts) {
|
|
|
74
85
|
* Returns undefined if the type is not valid.
|
|
75
86
|
*/
|
|
76
87
|
function updateFilterType(type) {
|
|
88
|
+
if (!type || typeof type !== 'string')
|
|
89
|
+
return;
|
|
77
90
|
let typeLowerCase = type.toLowerCase();
|
|
78
91
|
const filterTypes = ['tag-name', 'plan', 'label', 'jira-ticket'];
|
|
79
92
|
if (typeLowerCase === 'plan-id') {
|
|
@@ -87,7 +100,7 @@ function updateFilterType(type) {
|
|
|
87
100
|
// "ims-issue", //TODO: WIP
|
|
88
101
|
];
|
|
89
102
|
if (!filterTypes.includes(typeLowerCase)) {
|
|
90
|
-
console.log(constants_js_1.APP_PREFIX, `❗❗❗ Invalid "
|
|
103
|
+
console.log(constants_js_1.APP_PREFIX, `❗❗❗ Invalid filter: "${type}" start settings! Available option list: ${filterTypes}`);
|
|
91
104
|
return;
|
|
92
105
|
}
|
|
93
106
|
const index = filterTypes.indexOf(typeLowerCase);
|
|
@@ -121,6 +134,33 @@ function fullName(t) {
|
|
|
121
134
|
line += ` \`[${Object.values(t.example)}]\``;
|
|
122
135
|
return line;
|
|
123
136
|
}
|
|
137
|
+
/**
|
|
138
|
+
* Parses a comma-separated list of key-value pairs into an options object.
|
|
139
|
+
*
|
|
140
|
+
* The input string should be formatted as `"key1=value1,key2=value2,..."`.
|
|
141
|
+
* Whitespace around keys and values is trimmed. If the input is empty or undefined,
|
|
142
|
+
* an empty object is returned.
|
|
143
|
+
*
|
|
144
|
+
* @param {string} [optionsStr] - A comma-separated string of key=value pairs.
|
|
145
|
+
* @returns {Object} An object mapping option keys to their string values.
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* parsePipeOptions('foo=bar,baz=qux');
|
|
149
|
+
* => Returns: { foo: 'bar', baz: 'qux' }
|
|
150
|
+
*/
|
|
151
|
+
function parsePipeOptions(optionsStr) {
|
|
152
|
+
const options = {};
|
|
153
|
+
if (!optionsStr)
|
|
154
|
+
return options;
|
|
155
|
+
const pairs = optionsStr.split(',');
|
|
156
|
+
for (const pair of pairs) {
|
|
157
|
+
const [key, value] = pair.split('=');
|
|
158
|
+
if (key && value) {
|
|
159
|
+
options[key.trim()] = value.trim();
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return options;
|
|
163
|
+
}
|
|
124
164
|
|
|
125
165
|
module.exports.updateFilterType = updateFilterType;
|
|
126
166
|
|
|
@@ -133,3 +173,5 @@ module.exports.setS3Credentials = setS3Credentials;
|
|
|
133
173
|
module.exports.statusEmoji = statusEmoji;
|
|
134
174
|
|
|
135
175
|
module.exports.fullName = fullName;
|
|
176
|
+
|
|
177
|
+
module.exports.parsePipeOptions = parsePipeOptions;
|
package/lib/utils/utils.d.ts
CHANGED
|
@@ -17,6 +17,11 @@ export namespace fileSystem {
|
|
|
17
17
|
export function foundedTestLog(app: any, tests: any): void;
|
|
18
18
|
export function formatStep(step: any, shift?: number): any;
|
|
19
19
|
export function getCurrentDateTime(): string;
|
|
20
|
+
/**
|
|
21
|
+
* Gets current git commit SHA
|
|
22
|
+
* @returns {String|null} git commit SHA or null if not available
|
|
23
|
+
*/
|
|
24
|
+
export function getGitCommitSha(): string | null;
|
|
20
25
|
/**
|
|
21
26
|
* @param {String} testTitle - Test title
|
|
22
27
|
*
|
|
@@ -59,3 +64,4 @@ export function transformEnvVarToBoolean(value: any): boolean;
|
|
|
59
64
|
* @returns {String|null} validated suite ID or null if invalid
|
|
60
65
|
*/
|
|
61
66
|
export function validateSuiteId(suiteId: string): string | null;
|
|
67
|
+
export function applyFilter(command: any, tests: any): any;
|
package/lib/utils/utils.js
CHANGED
|
@@ -36,7 +36,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
36
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.validateSuiteId = exports.testRunnerHelper = exports.specificTestInfo = exports.parseSuite = exports.isValidUrl = exports.humanize = exports.getTestomatIdFromTestTitle = exports.getCurrentDateTime = exports.foundedTestLog = exports.fileSystem = exports.fetchFilesFromStackTrace = exports.fetchIdFromOutput = exports.fetchIdFromCode = exports.fetchSourceCodeFromStackTrace = exports.fetchSourceCode = exports.isSameTest = exports.ansiRegExp = exports.SUITE_ID_REGEX = exports.TEST_ID_REGEX = void 0;
|
|
39
|
+
exports.validateSuiteId = exports.testRunnerHelper = exports.specificTestInfo = exports.parseSuite = exports.isValidUrl = exports.humanize = exports.getTestomatIdFromTestTitle = exports.getGitCommitSha = exports.getCurrentDateTime = exports.foundedTestLog = exports.fileSystem = exports.fetchFilesFromStackTrace = exports.fetchIdFromOutput = exports.fetchIdFromCode = exports.fetchSourceCodeFromStackTrace = exports.fetchSourceCode = exports.isSameTest = exports.ansiRegExp = exports.SUITE_ID_REGEX = exports.TEST_ID_REGEX = void 0;
|
|
40
40
|
exports.getPackageVersion = getPackageVersion;
|
|
41
41
|
exports.truncate = truncate;
|
|
42
42
|
exports.cleanLatestRunId = cleanLatestRunId;
|
|
@@ -45,6 +45,7 @@ exports.readLatestRunId = readLatestRunId;
|
|
|
45
45
|
exports.removeColorCodes = removeColorCodes;
|
|
46
46
|
exports.storeRunId = storeRunId;
|
|
47
47
|
exports.transformEnvVarToBoolean = transformEnvVarToBoolean;
|
|
48
|
+
exports.applyFilter = applyFilter;
|
|
48
49
|
const url_1 = require("url");
|
|
49
50
|
const path_1 = __importStar(require("path"));
|
|
50
51
|
const picocolors_1 = __importDefault(require("picocolors"));
|
|
@@ -53,6 +54,7 @@ const is_valid_path_1 = __importDefault(require("is-valid-path"));
|
|
|
53
54
|
const debug_1 = __importDefault(require("debug"));
|
|
54
55
|
const os_1 = __importDefault(require("os"));
|
|
55
56
|
const url_2 = require("url");
|
|
57
|
+
const child_process_1 = require("child_process");
|
|
56
58
|
const debug = (0, debug_1.default)('@testomatio/reporter:util');
|
|
57
59
|
// Use __dirname directly since we're compiling to CommonJS
|
|
58
60
|
// prettier-ignore
|
|
@@ -98,6 +100,22 @@ const validateSuiteId = suiteId => {
|
|
|
98
100
|
return match ? match[0] : null;
|
|
99
101
|
};
|
|
100
102
|
exports.validateSuiteId = validateSuiteId;
|
|
103
|
+
/**
|
|
104
|
+
* Gets current git commit SHA
|
|
105
|
+
* @returns {String|null} git commit SHA or null if not available
|
|
106
|
+
*/
|
|
107
|
+
const getGitCommitSha = () => {
|
|
108
|
+
try {
|
|
109
|
+
const sha = (0, child_process_1.execSync)('git rev-parse --short HEAD', {
|
|
110
|
+
stdio: ['ignore', 'pipe', 'ignore']
|
|
111
|
+
}).toString().trim();
|
|
112
|
+
return sha || null;
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
exports.getGitCommitSha = getGitCommitSha;
|
|
101
119
|
const ansiRegExp = () => {
|
|
102
120
|
const pattern = [
|
|
103
121
|
'[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)',
|
|
@@ -641,6 +659,54 @@ function truncate(s, size = 255) {
|
|
|
641
659
|
}
|
|
642
660
|
return `${str.substring(0, size)}...`;
|
|
643
661
|
}
|
|
662
|
+
function applyFilter(command, tests) {
|
|
663
|
+
if (!tests || !tests.length)
|
|
664
|
+
return command;
|
|
665
|
+
const lower = (command || '').toLowerCase();
|
|
666
|
+
const regexPattern = `(${tests.join('|')})`;
|
|
667
|
+
if (lower.includes('jest')) {
|
|
668
|
+
return `${command} --testNamePattern ${regexPattern}`;
|
|
669
|
+
}
|
|
670
|
+
if (lower.includes('cypress')) {
|
|
671
|
+
const grepValue = tests.join(',');
|
|
672
|
+
const baseEnv = {
|
|
673
|
+
grep: grepValue,
|
|
674
|
+
grepFilterSpecs: true,
|
|
675
|
+
grepOmitFiltered: true,
|
|
676
|
+
};
|
|
677
|
+
if (command.includes('--env')) {
|
|
678
|
+
return command.replace(/--env\s+(['"]?)([^\s'"]+)\1/, (match, quote, envVal) => {
|
|
679
|
+
const existingEnv = {};
|
|
680
|
+
if (envVal.startsWith('{') && envVal.endsWith('}')) {
|
|
681
|
+
try {
|
|
682
|
+
Object.assign(existingEnv, JSON.parse(envVal));
|
|
683
|
+
}
|
|
684
|
+
catch (e) {
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
if (!Object.keys(existingEnv).length) {
|
|
688
|
+
envVal.split(',').forEach((pair) => {
|
|
689
|
+
const [k, v] = pair.split('=');
|
|
690
|
+
if (!k)
|
|
691
|
+
return;
|
|
692
|
+
if (v === 'true')
|
|
693
|
+
existingEnv[k] = true;
|
|
694
|
+
else if (v === 'false')
|
|
695
|
+
existingEnv[k] = false;
|
|
696
|
+
else
|
|
697
|
+
existingEnv[k] = v;
|
|
698
|
+
});
|
|
699
|
+
}
|
|
700
|
+
const merged = { ...existingEnv, ...baseEnv };
|
|
701
|
+
const json = JSON.stringify(merged);
|
|
702
|
+
return `--env ${json}`;
|
|
703
|
+
});
|
|
704
|
+
}
|
|
705
|
+
const json = JSON.stringify(baseEnv);
|
|
706
|
+
return `${command} --env ${json}`;
|
|
707
|
+
}
|
|
708
|
+
return `${command} --grep ${regexPattern}`;
|
|
709
|
+
}
|
|
644
710
|
|
|
645
711
|
module.exports.getPackageVersion = getPackageVersion;
|
|
646
712
|
|
|
@@ -658,12 +724,16 @@ module.exports.storeRunId = storeRunId;
|
|
|
658
724
|
|
|
659
725
|
module.exports.transformEnvVarToBoolean = transformEnvVarToBoolean;
|
|
660
726
|
|
|
727
|
+
module.exports.applyFilter = applyFilter;
|
|
728
|
+
|
|
661
729
|
module.exports.getTestomatIdFromTestTitle = getTestomatIdFromTestTitle;
|
|
662
730
|
|
|
663
731
|
module.exports.parseSuite = parseSuite;
|
|
664
732
|
|
|
665
733
|
module.exports.validateSuiteId = validateSuiteId;
|
|
666
734
|
|
|
735
|
+
module.exports.getGitCommitSha = getGitCommitSha;
|
|
736
|
+
|
|
667
737
|
module.exports.ansiRegExp = ansiRegExp;
|
|
668
738
|
|
|
669
739
|
module.exports.isValidUrl = isValidUrl;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@testomatio/reporter",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.0",
|
|
4
4
|
"description": "Testomatio Reporter Client",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=18"
|
|
@@ -18,21 +18,22 @@
|
|
|
18
18
|
"@cucumber/cucumber": "^10.9.0",
|
|
19
19
|
"@octokit/rest": "^21.1.1",
|
|
20
20
|
"aws-sdk": "^2.1072.0",
|
|
21
|
-
"gaxios": ">=6.0 || >=7.0.0-rc.4 || <8",
|
|
22
21
|
"callsite-record": "^4.1.4",
|
|
23
22
|
"commander": "^12",
|
|
24
23
|
"cross-spawn": "^7.0.3",
|
|
25
24
|
"csv-writer": "^1.6.0",
|
|
26
|
-
"debug": "
|
|
25
|
+
"debug": "4.3.4",
|
|
27
26
|
"dotenv": "^16.0.1",
|
|
28
27
|
"fast-xml-parser": "^4.4.1",
|
|
29
28
|
"file-url": "3.0.0",
|
|
30
29
|
"filesize": "^10.1.6",
|
|
30
|
+
"gaxios": ">=6.0 || >=7.0.0-rc.4 || <8",
|
|
31
31
|
"glob": "^10.3",
|
|
32
32
|
"handlebars": "^4.7.8",
|
|
33
33
|
"has-flag": "^5.0.1",
|
|
34
34
|
"humanize-duration": "^3.27.3",
|
|
35
35
|
"is-valid-path": "^0.1.1",
|
|
36
|
+
"js-yaml": "^4.1.1",
|
|
36
37
|
"json-cycle": "^1.3.0",
|
|
37
38
|
"lodash.memoize": "^4.1.2",
|
|
38
39
|
"lodash.merge": "^4.6.2",
|
|
@@ -40,7 +41,7 @@
|
|
|
40
41
|
"picocolors": "^1.0.1",
|
|
41
42
|
"pretty-ms": "^7.0.1",
|
|
42
43
|
"promise-retry": "^2.0.1",
|
|
43
|
-
"strip-ansi": "
|
|
44
|
+
"strip-ansi": "7.1.0",
|
|
44
45
|
"uuid": "^9.0.0"
|
|
45
46
|
},
|
|
46
47
|
"files": [
|