@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
|
@@ -3,6 +3,8 @@ import { services } from './services/index.js';
|
|
|
3
3
|
/**
|
|
4
4
|
* Stores path to file as artifact and uploads it to the S3 storage
|
|
5
5
|
* @param {string | {path: string, type: string, name: string}} data - path to file or object with path, type and name
|
|
6
|
+
* @param {any} [context=null] - optional context parameter
|
|
7
|
+
* @returns {void}
|
|
6
8
|
*/
|
|
7
9
|
function saveArtifact(data, context = null) {
|
|
8
10
|
if (process.env.IS_PLAYWRIGHT)
|
|
@@ -14,7 +16,8 @@ function saveArtifact(data, context = null) {
|
|
|
14
16
|
|
|
15
17
|
/**
|
|
16
18
|
* Attach log message(s) to the test report
|
|
17
|
-
* @param
|
|
19
|
+
* @param {...any} args - log messages to attach
|
|
20
|
+
* @returns {void}
|
|
18
21
|
*/
|
|
19
22
|
function logMessage(...args) {
|
|
20
23
|
if (process.env.IS_PLAYWRIGHT) throw new Error('This function is not available in Playwright framework');
|
|
@@ -23,7 +26,8 @@ function logMessage(...args) {
|
|
|
23
26
|
|
|
24
27
|
/**
|
|
25
28
|
* Similar to "log" function but marks message in report as a step
|
|
26
|
-
* @param {string} message
|
|
29
|
+
* @param {string} message - step message
|
|
30
|
+
* @returns {void}
|
|
27
31
|
*/
|
|
28
32
|
function addStep(message) {
|
|
29
33
|
if (process.env.IS_PLAYWRIGHT)
|
|
@@ -34,8 +38,9 @@ function addStep(message) {
|
|
|
34
38
|
|
|
35
39
|
/**
|
|
36
40
|
* Add key-value pair(s) to the test report
|
|
37
|
-
* @param {{[key: string]: string} | string} keyValue object { key: value } (multiple props allowed) or key (string)
|
|
38
|
-
* @param {string
|
|
41
|
+
* @param {{[key: string]: string} | string} keyValue - object { key: value } (multiple props allowed) or key (string)
|
|
42
|
+
* @param {string|null} [value=null] - optional value when keyValue is a string
|
|
43
|
+
* @returns {void}
|
|
39
44
|
*/
|
|
40
45
|
function setKeyValue(keyValue, value = null) {
|
|
41
46
|
if (process.env.IS_PLAYWRIGHT)
|
|
@@ -48,48 +53,32 @@ function setKeyValue(keyValue, value = null) {
|
|
|
48
53
|
}
|
|
49
54
|
|
|
50
55
|
/**
|
|
51
|
-
* Add
|
|
56
|
+
* Add label(s) to the test report
|
|
52
57
|
* @param {string} key - label key (e.g. 'severity', 'feature', or just 'smoke' for labels without values)
|
|
53
|
-
* @param {string} [value] - optional label value (e.g. 'high', 'login')
|
|
58
|
+
* @param {string|string[]|null} [value=null] - optional label value(s) (e.g. 'high', 'login') or array of values
|
|
59
|
+
* @returns {void}
|
|
54
60
|
*/
|
|
55
61
|
function setLabel(key, value = null) {
|
|
56
62
|
if (Array.isArray(value)) {
|
|
57
|
-
value.forEach(
|
|
63
|
+
value.forEach(val => setLabel(key, val));
|
|
58
64
|
return;
|
|
59
65
|
}
|
|
60
66
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
// Limit key length to 255 characters
|
|
67
|
-
if (key.length > 255) {
|
|
68
|
-
console.warn('Label key is too long, trimmed to 255 characters:', key);
|
|
69
|
-
key = key.substring(0, 255);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
let labelString = key;
|
|
73
|
-
if (value !== null && value !== undefined && value !== '') {
|
|
74
|
-
if (typeof value !== 'string') {
|
|
75
|
-
console.warn('Label value must be a string, converting:', value);
|
|
76
|
-
value = String(value);
|
|
77
|
-
}
|
|
78
|
-
// Limit value length to 255 characters
|
|
79
|
-
if (value.length > 255) {
|
|
80
|
-
console.warn('Label value is too long, trimmed to 255 characters:', value);
|
|
81
|
-
value = value.substring(0, 255);
|
|
82
|
-
}
|
|
83
|
-
labelString = `${key}:${value}`;
|
|
84
|
-
}
|
|
67
|
+
const labelObject = value !== null && value !== undefined && value !== ''
|
|
68
|
+
? { label: `${key}:${value}` }
|
|
69
|
+
: { label: key };
|
|
70
|
+
services.links.put([labelObject]);
|
|
71
|
+
}
|
|
85
72
|
|
|
86
|
-
// Limit total label length to 255 characters
|
|
87
|
-
if (labelString.length > 255) {
|
|
88
|
-
console.warn('Label is too long, trimmed to 255 characters:', labelString);
|
|
89
|
-
labelString = labelString.substring(0, 255);
|
|
90
|
-
}
|
|
91
73
|
|
|
92
|
-
|
|
74
|
+
/**
|
|
75
|
+
* Add link(s) to the test report
|
|
76
|
+
* @param {...string} testIds - test IDs to link
|
|
77
|
+
* @returns {void}
|
|
78
|
+
*/
|
|
79
|
+
function linkTest(...testIds) {
|
|
80
|
+
const links = testIds.map(testId => ({ test: testId }));
|
|
81
|
+
services.links.put(links);
|
|
93
82
|
}
|
|
94
83
|
|
|
95
84
|
export default {
|
|
@@ -98,4 +87,5 @@ export default {
|
|
|
98
87
|
step: addStep,
|
|
99
88
|
keyValue: setKeyValue,
|
|
100
89
|
label: setLabel,
|
|
90
|
+
linkTest,
|
|
101
91
|
};
|
package/src/reporter.js
CHANGED
|
@@ -9,14 +9,15 @@ export const logger = services.logger;
|
|
|
9
9
|
export const meta = reporterFunctions.keyValue;
|
|
10
10
|
export const step = reporterFunctions.step;
|
|
11
11
|
export const label = reporterFunctions.label;
|
|
12
|
+
export const linkTest = reporterFunctions.linkTest;
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
|
-
* @typedef {import('./reporter-functions.js')}
|
|
15
|
-
* @typedef {import('./reporter-functions.js')}
|
|
16
|
-
* @typedef {import('./services/index.js')}
|
|
17
|
-
* @typedef {import('./reporter-functions.js')}
|
|
18
|
-
* @typedef {import('./reporter-functions.js')}
|
|
19
|
-
* @typedef {import('./reporter-functions.js')}
|
|
15
|
+
* @typedef {typeof import('./reporter-functions.js').default.artifact} ArtifactFunction
|
|
16
|
+
* @typedef {typeof import('./reporter-functions.js').default.log} LogFunction
|
|
17
|
+
* @typedef {typeof import('./services/index.js').services.logger} LoggerService
|
|
18
|
+
* @typedef {typeof import('./reporter-functions.js').default.keyValue} MetaFunction
|
|
19
|
+
* @typedef {typeof import('./reporter-functions.js').default.step} StepFunction
|
|
20
|
+
* @typedef {typeof import('./reporter-functions.js').default.label} LabelFunction
|
|
20
21
|
*/
|
|
21
22
|
export default {
|
|
22
23
|
/**
|
|
@@ -30,6 +31,7 @@ export default {
|
|
|
30
31
|
meta: reporterFunctions.keyValue,
|
|
31
32
|
step: reporterFunctions.step,
|
|
32
33
|
label: reporterFunctions.label,
|
|
34
|
+
linkTest: reporterFunctions.linkTest,
|
|
33
35
|
|
|
34
36
|
// TestomatClient,
|
|
35
37
|
// TRConstants,
|
package/src/services/index.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { logger } from './logger.js';
|
|
2
2
|
import { artifactStorage } from './artifacts.js';
|
|
3
3
|
import { keyValueStorage } from './key-values.js';
|
|
4
|
-
import {
|
|
4
|
+
import { linkStorage } from './links.js';
|
|
5
5
|
import { dataStorage } from '../data-storage.js';
|
|
6
6
|
|
|
7
7
|
export const services = {
|
|
8
8
|
logger,
|
|
9
9
|
artifacts: artifactStorage,
|
|
10
10
|
keyValues: keyValueStorage,
|
|
11
|
-
|
|
11
|
+
links: linkStorage,
|
|
12
12
|
setContext: context => {
|
|
13
13
|
dataStorage.setContext(context);
|
|
14
14
|
},
|
package/src/services/labels.js
CHANGED
|
@@ -23,7 +23,7 @@ class LabelStorage {
|
|
|
23
23
|
*/
|
|
24
24
|
put(labels, context = null) {
|
|
25
25
|
if (!labels || !Array.isArray(labels)) return;
|
|
26
|
-
dataStorage.putData('
|
|
26
|
+
dataStorage.putData('links', labels, context);
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
/**
|
|
@@ -32,7 +32,7 @@ class LabelStorage {
|
|
|
32
32
|
* @returns {string[]} labels array, e.g. ['smoke', 'severity:high', 'feature:user_account']
|
|
33
33
|
*/
|
|
34
34
|
get(context = null) {
|
|
35
|
-
const labelsList = dataStorage.getData('
|
|
35
|
+
const labelsList = dataStorage.getData('links', context);
|
|
36
36
|
if (!labelsList || !labelsList?.length) return [];
|
|
37
37
|
|
|
38
38
|
const allLabels = [];
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import createDebugMessages from 'debug';
|
|
2
|
+
import { dataStorage } from '../data-storage.js';
|
|
3
|
+
|
|
4
|
+
const debug = createDebugMessages('@testomatio/reporter:services-links');
|
|
5
|
+
|
|
6
|
+
class LinkStorage {
|
|
7
|
+
static #instance;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
*
|
|
11
|
+
* @returns {LinkStorage}
|
|
12
|
+
*/
|
|
13
|
+
static getInstance() {
|
|
14
|
+
if (!this.#instance) {
|
|
15
|
+
this.#instance = new LinkStorage();
|
|
16
|
+
}
|
|
17
|
+
return this.#instance;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Stores links array and passes it to reporter
|
|
22
|
+
* @param {object[]} links - array of link objects
|
|
23
|
+
* @param {*} context - full test title
|
|
24
|
+
*/
|
|
25
|
+
put(links, context = null) {
|
|
26
|
+
if (!links || !Array.isArray(links)) return;
|
|
27
|
+
dataStorage.putData('links', links, context);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Returns links array for the test
|
|
32
|
+
* @param {*} context testId or test context from test runner
|
|
33
|
+
* @returns {object[]} links array, e.g. [{test: 'TEST-123'}, {jira: 'JIRA-456'}]
|
|
34
|
+
*/
|
|
35
|
+
get(context = null) {
|
|
36
|
+
const linksList = dataStorage.getData('links', context);
|
|
37
|
+
if (!linksList || !linksList?.length) return [];
|
|
38
|
+
|
|
39
|
+
const allLinks = [];
|
|
40
|
+
for (const links of linksList) {
|
|
41
|
+
if (Array.isArray(links)) {
|
|
42
|
+
allLinks.push(...links);
|
|
43
|
+
} else if (typeof links === 'string') {
|
|
44
|
+
try {
|
|
45
|
+
const parsedLinks = JSON.parse(links);
|
|
46
|
+
if (Array.isArray(parsedLinks)) {
|
|
47
|
+
allLinks.push(...parsedLinks);
|
|
48
|
+
}
|
|
49
|
+
} catch (e) {
|
|
50
|
+
debug(`Error parsing links for test ${context}`, links);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Remove duplicates based on JSON string comparison
|
|
56
|
+
const uniqueLinks = [];
|
|
57
|
+
const seen = new Set();
|
|
58
|
+
for (const link of allLinks) {
|
|
59
|
+
const key = JSON.stringify(link);
|
|
60
|
+
if (!seen.has(key)) {
|
|
61
|
+
seen.add(key);
|
|
62
|
+
uniqueLinks.push(link);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return uniqueLinks;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export const linkStorage = LinkStorage.getInstance();
|
package/src/utils/utils.js
CHANGED
|
@@ -53,7 +53,7 @@ const parseSuite = suiteTitle => {
|
|
|
53
53
|
*/
|
|
54
54
|
const validateSuiteId = suiteId => {
|
|
55
55
|
if (!suiteId) return null;
|
|
56
|
-
|
|
56
|
+
|
|
57
57
|
const match = suiteId.match(SUITE_ID_REGEX);
|
|
58
58
|
return match ? match[0] : null;
|
|
59
59
|
};
|
|
@@ -273,7 +273,7 @@ const fileSystem = {
|
|
|
273
273
|
const foundedTestLog = (app, tests) => {
|
|
274
274
|
const n = tests.length;
|
|
275
275
|
|
|
276
|
-
return
|
|
276
|
+
return console.log(app, `✅ We found ${n === 1 ? 'one test' : `${n} tests`} in Testomat.io!`);
|
|
277
277
|
};
|
|
278
278
|
|
|
279
279
|
const humanize = text => {
|
|
@@ -354,12 +354,14 @@ function storeRunId(runId) {
|
|
|
354
354
|
}
|
|
355
355
|
|
|
356
356
|
/**
|
|
357
|
-
*
|
|
357
|
+
*
|
|
358
358
|
* @returns {String|null} latest run ID
|
|
359
359
|
*/
|
|
360
360
|
function readLatestRunId() {
|
|
361
361
|
try {
|
|
362
362
|
const filePath = path.join(os.tmpdir(), `testomatio.latest.run`);
|
|
363
|
+
if (!fs.existsSync(filePath)) return null;
|
|
364
|
+
|
|
363
365
|
const stats = fs.statSync(filePath);
|
|
364
366
|
const diff = +new Date() - +stats.mtime;
|
|
365
367
|
const diffHours = diff / 1000 / 60 / 60;
|
package/lib/utils/cli_utils.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export function checkForEnvPassedAsArguments(): void;
|