@testomatio/reporter 1.0.0-beta.4 → 1.0.1-6.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/Changelog.md +100 -2
- package/README.md +92 -540
- package/lib/{ArtifactStorage.js → _ArtifactStorageOld.js} +16 -5
- package/lib/adapter/codecept.js +83 -53
- package/lib/adapter/cucumber/current.js +95 -59
- package/lib/adapter/cucumber/legacy.js +25 -11
- package/lib/adapter/cypress-plugin/index.js +1 -1
- package/lib/adapter/jasmine.js +1 -1
- package/lib/adapter/jest.js +30 -2
- package/lib/adapter/mocha.js +24 -24
- package/lib/adapter/playwright.js +18 -11
- package/lib/adapter/webdriver.js +1 -1
- package/lib/artifactStorage.js +25 -0
- package/lib/bin/reportXml.js +1 -0
- package/lib/bin/startTest.js +25 -4
- package/lib/client.js +117 -41
- package/lib/constants.js +5 -0
- package/lib/dataStorage.js +232 -0
- package/lib/junit-adapter/java.js +27 -9
- package/lib/logger.js +319 -0
- package/lib/pipe/csv.js +4 -1
- package/lib/pipe/github.js +26 -39
- package/lib/pipe/gitlab.js +5 -16
- package/lib/pipe/testomatio.js +138 -33
- package/lib/reporter.js +11 -2
- package/lib/utils/pipe_utils.js +135 -0
- package/lib/utils/utils.js +310 -0
- package/lib/xmlReader.js +132 -44
- package/package.json +9 -6
- package/lib/util.js +0 -184
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@testomatio/reporter",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.16.1",
|
|
4
4
|
"description": "Testomatio Reporter Client",
|
|
5
5
|
"main": "./lib/reporter.js",
|
|
6
6
|
"typings": "typings/index.d.ts",
|
|
@@ -20,13 +20,14 @@
|
|
|
20
20
|
"debug": "^4.3.4",
|
|
21
21
|
"dotenv": "^16.0.1",
|
|
22
22
|
"fast-xml-parser": "^4.0.8",
|
|
23
|
-
"glob": "^
|
|
23
|
+
"glob": "^10.3",
|
|
24
24
|
"has-flag": "^5.0.1",
|
|
25
25
|
"humanize-duration": "^3.27.3",
|
|
26
26
|
"is-valid-path": "^0.1.1",
|
|
27
27
|
"json-cycle": "^1.3.0",
|
|
28
28
|
"lodash.memoize": "^4.1.2",
|
|
29
29
|
"lodash.merge": "^4.6.2",
|
|
30
|
+
"minimatch": "^9.0.3",
|
|
30
31
|
"uuid": "^9.0.0"
|
|
31
32
|
},
|
|
32
33
|
"files": [
|
|
@@ -41,21 +42,22 @@
|
|
|
41
42
|
"lint:fix": "eslint lib --fix",
|
|
42
43
|
"test": "mocha tests/**",
|
|
43
44
|
"init": "cd ./tests/adapter/examples/cucumber && npm i",
|
|
44
|
-
"test:unit": "mocha tests",
|
|
45
45
|
"test:adapter": "mocha './tests/adapter/index.test.js'",
|
|
46
46
|
"test:pipes": "mocha './tests/pipes/*_test.js'",
|
|
47
47
|
"test:adapter:jest:example": "jest './tests/adapter/examples/jest/index.test.js' --config='./tests/adapter/examples/jest/jest.config.js'",
|
|
48
48
|
"test:adapter:mocha:example": "mocha './tests/adapter/examples/mocha/index.test.js' --config='./tests/adapter/examples/mocha/mocha.config.js'",
|
|
49
49
|
"test:adapter:jasmine:example": "./tests/adapter/examples/jasmine/passReporterOpts.sh && jasmine './tests/adapter/examples/jasmine/index.test.js' --reporter=./../../../lib/adapter/jasmine.js",
|
|
50
50
|
"test:adapter:codecept:example": "codeceptjs run --config='./tests/adapter/examples/codecept/codecept.conf.js'",
|
|
51
|
-
"test:adapter:cucumber:example": "cd ./tests/adapter/examples/cucumber && npx cucumber-js"
|
|
51
|
+
"test:adapter:cucumber:example": "cd ./tests/adapter/examples/cucumber && npx cucumber-js",
|
|
52
|
+
"test:storage": "npx mocha ./tests-storage/**"
|
|
52
53
|
},
|
|
53
54
|
"devDependencies": {
|
|
54
|
-
"@cucumber/cucumber": "^
|
|
55
|
+
"@cucumber/cucumber": "^9.3.0",
|
|
55
56
|
"@redocly/cli": "^1.0.0-beta.125",
|
|
56
57
|
"@wdio/reporter": "^7.16.13",
|
|
57
58
|
"chai": "^4.3.6",
|
|
58
|
-
"codeceptjs": "
|
|
59
|
+
"codeceptjs": "latest",
|
|
60
|
+
"cucumber": "^6.0.7",
|
|
59
61
|
"eslint": "^8.7.0",
|
|
60
62
|
"eslint-config-airbnb-base": "^15.0.0",
|
|
61
63
|
"eslint-config-prettier": "^8.3.0",
|
|
@@ -64,6 +66,7 @@
|
|
|
64
66
|
"jest": "^27.4.7",
|
|
65
67
|
"mocha": "^9.2.0",
|
|
66
68
|
"mock-http-server": "^1.4.5",
|
|
69
|
+
"pino": "^8.15.0",
|
|
67
70
|
"prettier": "2.5.1",
|
|
68
71
|
"puppeteer": "^13.1.2"
|
|
69
72
|
},
|
package/lib/util.js
DELETED
|
@@ -1,184 +0,0 @@
|
|
|
1
|
-
const { URL } = require('url');
|
|
2
|
-
const { sep, basename } = require('path');
|
|
3
|
-
const chalk = require('chalk');
|
|
4
|
-
const fs = require('fs');
|
|
5
|
-
const isValid = require('is-valid-path');
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* @param {String} testTitle - Test title
|
|
9
|
-
*
|
|
10
|
-
* @returns {String|null} testId
|
|
11
|
-
*/
|
|
12
|
-
const parseTest = testTitle => {
|
|
13
|
-
const captures = testTitle.match(/@T([\w\d]+)/);
|
|
14
|
-
if (captures) {
|
|
15
|
-
return captures[1];
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
return null;
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* @param {String} suiteTitle - suite title
|
|
23
|
-
*
|
|
24
|
-
* @returns {String|null} suiteId
|
|
25
|
-
*/
|
|
26
|
-
const parseSuite = suiteTitle => {
|
|
27
|
-
const captures = suiteTitle.match(/@S([\w\d]+)/);
|
|
28
|
-
if (captures) {
|
|
29
|
-
return captures[1];
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
return null;
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
const ansiRegExp = () => {
|
|
37
|
-
const pattern = [
|
|
38
|
-
'[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)',
|
|
39
|
-
'(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))',
|
|
40
|
-
].join('|');
|
|
41
|
-
|
|
42
|
-
return new RegExp(pattern, 'g');
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
const isValidUrl = s => {
|
|
46
|
-
try {
|
|
47
|
-
// eslint-disable-next-line no-new
|
|
48
|
-
new URL(s);
|
|
49
|
-
return true;
|
|
50
|
-
} catch (err) {
|
|
51
|
-
return false;
|
|
52
|
-
}
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
const fetchFilesFromStackTrace = (stack = '') => {
|
|
56
|
-
const files = stack.matchAll(/file:?\/(\/.*?\.(png|avi|webm|jpg|html|txt))/g);
|
|
57
|
-
return Array.from(files).map(f => f[1]).filter(f => fs.existsSync(f));
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const fetchSourceCodeFromStackTrace = (stack = '') => {
|
|
61
|
-
const stackLines = stack.split('\n')
|
|
62
|
-
.filter(l => l.includes(':'))
|
|
63
|
-
// .map(l => l.match(/\[(.*?)\]/)?.[1] || l) // minitest format
|
|
64
|
-
// .map(l => l.split(':')[0])
|
|
65
|
-
.map(l => l.trim())
|
|
66
|
-
.map(l => l.split(' ').find(p => p.includes(':')) || '')
|
|
67
|
-
.filter(l => isValid(l?.split(':')[0]))
|
|
68
|
-
|
|
69
|
-
// // filter out 3rd party libs
|
|
70
|
-
.filter(l => !l?.includes(`vendor${ sep}`))
|
|
71
|
-
.filter(l => !l?.includes(`node_modules${ sep}`))
|
|
72
|
-
.filter(l => fs.existsSync(l.split(':')[0]))
|
|
73
|
-
.filter(l => fs.lstatSync(l.split(':')[0]).isFile())
|
|
74
|
-
|
|
75
|
-
if (!stackLines.length) return '';
|
|
76
|
-
|
|
77
|
-
const [file, line] = stackLines[0].split(':');
|
|
78
|
-
|
|
79
|
-
const prepend = 3;
|
|
80
|
-
const source = fetchSourceCode(fs.readFileSync(file).toString(), { line, prepend, limit: 7 })
|
|
81
|
-
|
|
82
|
-
if (!source) return '';
|
|
83
|
-
|
|
84
|
-
return source.split('\n')
|
|
85
|
-
.map((l, i) => {
|
|
86
|
-
if (i === prepend) return `${line} > ${chalk.bold(l)}`;
|
|
87
|
-
return `${line - prepend + i} | ${l}`
|
|
88
|
-
}).join('\n')
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const fetchSourceCode = (contents, opts = {}) => {
|
|
92
|
-
if (!opts.title && !opts.line) return '';
|
|
93
|
-
|
|
94
|
-
// code fragment is 20 lines
|
|
95
|
-
const limit = opts.limit || 50;
|
|
96
|
-
let lineIndex;
|
|
97
|
-
if (opts.line) lineIndex = opts.line - 1;
|
|
98
|
-
const lines = contents.split('\n')
|
|
99
|
-
|
|
100
|
-
// remove special chars from title
|
|
101
|
-
if (!lineIndex && opts.title) {
|
|
102
|
-
const title = opts.title.replace(/[([@].*/g, '')
|
|
103
|
-
lineIndex = lines.findIndex(l => l.includes(title))
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
if (opts.prepend) {
|
|
107
|
-
lineIndex -= opts.prepend;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
if (lineIndex) {
|
|
111
|
-
const result = [];
|
|
112
|
-
for (let i = lineIndex; i < (lineIndex + limit); i++) {
|
|
113
|
-
if (lines[i] === undefined) continue;
|
|
114
|
-
|
|
115
|
-
if (i > lineIndex + 2 && !opts.prepend) {
|
|
116
|
-
// annotation
|
|
117
|
-
if (opts.lang === 'php' && lines[i].trim().startsWith('#[')) break;
|
|
118
|
-
if (opts.lang === 'php' && lines[i].includes(' private function ')) break;
|
|
119
|
-
if (opts.lang === 'php' && lines[i].includes(' protected function ')) break;
|
|
120
|
-
if (opts.lang === 'php' && lines[i].includes(' public function ')) break;
|
|
121
|
-
if (opts.lang === 'python' && lines[i].trim().match(/^@\w+/)) break;
|
|
122
|
-
if (opts.lang === 'python' && lines[i].includes(' def ')) break;
|
|
123
|
-
if (opts.lang === 'ruby' && lines[i].includes(' def ')) break;
|
|
124
|
-
if (opts.lang === 'ruby' && lines[i].includes(' test ')) break;
|
|
125
|
-
if (opts.lang === 'ruby' && lines[i].includes(' it ')) break;
|
|
126
|
-
if (opts.lang === 'ruby' && lines[i].includes(' specify ')) break;
|
|
127
|
-
if (opts.lang === 'ruby' && lines[i].includes(' context ')) break;
|
|
128
|
-
if (opts.lang === 'ts' && lines[i].includes(' it(')) break;
|
|
129
|
-
if (opts.lang === 'ts' && lines[i].includes(' test(')) break;
|
|
130
|
-
if (opts.lang === 'js' && lines[i].includes(' it(')) break;
|
|
131
|
-
if (opts.lang === 'js' && lines[i].includes(' test(')) break;
|
|
132
|
-
if (opts.lang === 'java' && lines[i].trim().match(/^@\w+/)) break;
|
|
133
|
-
if (opts.lang === 'java' && lines[i].includes(' public void ')) break;
|
|
134
|
-
if (opts.lang === 'java' && lines[i].includes(' class ')) break;
|
|
135
|
-
}
|
|
136
|
-
result.push(lines[i])
|
|
137
|
-
}
|
|
138
|
-
return result.join('\n');
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
const isSameTest = (test, t) => (typeof t === 'object')
|
|
143
|
-
&& (typeof test === 'object')
|
|
144
|
-
&& t.title === test.title
|
|
145
|
-
&& t.suite_title === test.suite_title
|
|
146
|
-
&& Object.values(t.example || {}) === Object.values(test.example || {})
|
|
147
|
-
&& t.test_id === test.test_id;
|
|
148
|
-
|
|
149
|
-
const getCurrentDateTime = () => {
|
|
150
|
-
const today = new Date();
|
|
151
|
-
|
|
152
|
-
return `${today.getFullYear() }_${ today.getMonth() + 1 }_${ today.getDate() }_${
|
|
153
|
-
today.getHours() }_${ today.getMinutes() }_${ today.getSeconds()}`;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* @param {Object} test - Test adapter object
|
|
158
|
-
*
|
|
159
|
-
* @returns {String|null} testInfo as one string
|
|
160
|
-
*/
|
|
161
|
-
const specificTestInfo = test => {
|
|
162
|
-
// TODO: afterEach has another context.... need to add specific handler, maybe...
|
|
163
|
-
if (test?.title && test?.file) {
|
|
164
|
-
|
|
165
|
-
return `${basename(test.file).split(".").join("#")
|
|
166
|
-
}#${
|
|
167
|
-
test.title.split(" ").join("#")}`;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
return null;
|
|
171
|
-
};
|
|
172
|
-
|
|
173
|
-
module.exports = {
|
|
174
|
-
isSameTest,
|
|
175
|
-
fetchSourceCode,
|
|
176
|
-
fetchSourceCodeFromStackTrace,
|
|
177
|
-
fetchFilesFromStackTrace,
|
|
178
|
-
getCurrentDateTime,
|
|
179
|
-
specificTestInfo,
|
|
180
|
-
isValidUrl,
|
|
181
|
-
ansiRegExp,
|
|
182
|
-
parseTest,
|
|
183
|
-
parseSuite
|
|
184
|
-
}
|