@testomatio/reporter 1.6.0-beta-2-artifacts → 2.0.0-beta-esm
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 +288 -330
- package/lib/adapter/cucumber/current.js +195 -203
- package/lib/adapter/cucumber/legacy.js +130 -155
- package/lib/adapter/cucumber.js +5 -16
- package/lib/adapter/cypress-plugin/index.js +91 -105
- package/lib/adapter/jasmine/jasmine.js +63 -0
- package/lib/adapter/jasmine.js +54 -53
- package/lib/adapter/jest.js +97 -99
- package/lib/adapter/mocha/mocha.js +125 -0
- package/lib/adapter/mocha.js +111 -140
- package/lib/adapter/playwright.js +168 -200
- package/lib/adapter/vitest.js +144 -143
- package/lib/adapter/webdriver.js +113 -97
- package/lib/bin/reportXml.js +49 -49
- package/lib/bin/startTest.js +80 -97
- package/lib/client.js +344 -385
- package/lib/config.js +16 -21
- package/lib/constants.js +49 -43
- package/lib/data-storage.js +206 -188
- package/lib/fileUploader.js +245 -0
- package/lib/junit-adapter/adapter.js +17 -20
- package/lib/junit-adapter/csharp.js +18 -14
- package/lib/junit-adapter/index.js +27 -25
- package/lib/junit-adapter/java.js +41 -53
- package/lib/junit-adapter/javascript.js +30 -27
- package/lib/junit-adapter/python.js +38 -37
- package/lib/junit-adapter/ruby.js +11 -8
- package/lib/output.js +44 -52
- package/lib/package.json +1 -0
- package/lib/pipe/bitbucket.js +208 -227
- package/lib/pipe/csv.js +111 -124
- package/lib/pipe/github.js +184 -211
- package/lib/pipe/gitlab.js +164 -205
- package/lib/pipe/html.js +253 -312
- package/lib/pipe/index.js +83 -63
- package/lib/pipe/testomatio.js +391 -454
- package/lib/reporter-functions.js +16 -20
- package/lib/reporter.js +47 -17
- package/lib/services/artifacts.js +55 -51
- package/lib/services/index.js +14 -12
- package/lib/services/key-values.js +56 -53
- package/lib/services/logger.js +227 -245
- package/lib/utils/chalk.js +10 -0
- package/lib/utils/pipe_utils.js +91 -84
- package/lib/utils/utils.js +289 -273
- package/lib/xmlReader.js +480 -519
- package/package.json +57 -19
- package/src/adapter/codecept.js +369 -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/playwright.js +222 -0
- package/src/adapter/vitest.js +183 -0
- package/src/adapter/webdriver.js +111 -0
- package/src/bin/reportXml.js +67 -0
- package/src/bin/startTest.js +119 -0
- package/src/client.js +423 -0
- package/src/config.js +30 -0
- package/src/constants.js +49 -0
- package/src/data-storage.js +204 -0
- package/src/fileUploader.js +307 -0
- package/src/junit-adapter/adapter.js +23 -0
- package/src/junit-adapter/csharp.js +16 -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 +254 -0
- package/src/pipe/csv.js +140 -0
- package/src/pipe/github.js +234 -0
- package/src/pipe/gitlab.js +229 -0
- package/src/pipe/html.js +366 -0
- package/src/pipe/index.js +73 -0
- package/src/pipe/testomatio.js +498 -0
- package/src/reporter-functions.js +44 -0
- package/src/reporter.cjs +22 -0
- package/src/reporter.js +24 -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 +314 -0
- package/src/template/emptyData.svg +23 -0
- package/src/template/testomatio.hbs +1421 -0
- package/src/utils/chalk.js +13 -0
- package/src/utils/pipe_utils.js +127 -0
- package/src/utils/utils.js +341 -0
- package/src/xmlReader.js +551 -0
- package/lib/bin/cli.js +0 -216
- package/lib/bin/uploadArtifacts.js +0 -86
- package/lib/uploader.js +0 -312
package/lib/utils/utils.js
CHANGED
|
@@ -1,339 +1,355 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.testRunnerHelper = exports.foundedTestLog = exports.humanize = exports.parseSuite = exports.getTestomatIdFromTestTitle = exports.ansiRegExp = exports.isValidUrl = exports.specificTestInfo = exports.getCurrentDateTime = exports.fileSystem = exports.fetchFilesFromStackTrace = exports.fetchIdFromOutput = exports.fetchIdFromCode = exports.fetchSourceCodeFromStackTrace = exports.fetchSourceCode = exports.isSameTest = void 0;
|
|
7
|
+
exports.removeColorCodes = removeColorCodes;
|
|
8
|
+
const url_1 = require("url");
|
|
9
|
+
const path_1 = require("path");
|
|
10
|
+
const picocolors_1 = __importDefault(require("picocolors"));
|
|
11
|
+
const fs_1 = __importDefault(require("fs"));
|
|
12
|
+
const is_valid_path_1 = __importDefault(require("is-valid-path"));
|
|
13
|
+
const debug_1 = __importDefault(require("debug"));
|
|
14
|
+
const debug = (0, debug_1.default)('@testomatio/reporter:util');
|
|
8
15
|
/**
|
|
9
16
|
* @param {String} testTitle - Test title
|
|
10
17
|
*
|
|
11
18
|
* @returns {String|null} testId
|
|
12
19
|
*/
|
|
13
20
|
const getTestomatIdFromTestTitle = testTitle => {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
return null;
|
|
21
|
+
if (!testTitle)
|
|
22
|
+
return null;
|
|
23
|
+
const captures = testTitle.match(/@T[\w\d]{8}/);
|
|
24
|
+
if (captures) {
|
|
25
|
+
return captures[0];
|
|
26
|
+
}
|
|
27
|
+
return null;
|
|
23
28
|
};
|
|
24
|
-
|
|
29
|
+
exports.getTestomatIdFromTestTitle = getTestomatIdFromTestTitle;
|
|
25
30
|
/**
|
|
26
31
|
* @param {String} suiteTitle - suite title
|
|
27
32
|
*
|
|
28
33
|
* @returns {String|null} suiteId
|
|
29
34
|
*/
|
|
30
35
|
const parseSuite = suiteTitle => {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
return null;
|
|
36
|
+
const captures = suiteTitle.match(/@S[\w\d]{8}/);
|
|
37
|
+
if (captures) {
|
|
38
|
+
return captures[1];
|
|
39
|
+
}
|
|
40
|
+
return null;
|
|
37
41
|
};
|
|
38
|
-
|
|
42
|
+
exports.parseSuite = parseSuite;
|
|
39
43
|
const ansiRegExp = () => {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
return new RegExp(pattern, 'g');
|
|
44
|
+
const pattern = [
|
|
45
|
+
'[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)',
|
|
46
|
+
'(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))',
|
|
47
|
+
].join('|');
|
|
48
|
+
return new RegExp(pattern, 'g');
|
|
46
49
|
};
|
|
47
|
-
|
|
50
|
+
exports.ansiRegExp = ansiRegExp;
|
|
48
51
|
const isValidUrl = s => {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
52
|
+
try {
|
|
53
|
+
// eslint-disable-next-line no-new
|
|
54
|
+
new url_1.URL(s);
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
56
60
|
};
|
|
57
|
-
|
|
61
|
+
exports.isValidUrl = isValidUrl;
|
|
58
62
|
const fileMatchRegex = /file:(\/\/?[^:\s]+?\.(png|avi|webm|jpg|html|txt))/gi;
|
|
59
|
-
|
|
60
63
|
const fetchFilesFromStackTrace = (stack = '') => {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
});
|
|
64
|
+
const files = Array.from(stack.matchAll(fileMatchRegex))
|
|
65
|
+
.map(f => f[1].trim())
|
|
66
|
+
.map(f => (f.startsWith('//') ? f.substring(1) : f));
|
|
67
|
+
debug('Found files in stack trace: ', files);
|
|
68
|
+
return files.filter(f => {
|
|
69
|
+
const isFile = fs_1.default.existsSync(f);
|
|
70
|
+
if (!isFile)
|
|
71
|
+
debug('File %s could not be found and uploaded as artifact', f);
|
|
72
|
+
return isFile;
|
|
73
|
+
});
|
|
72
74
|
};
|
|
73
|
-
|
|
75
|
+
exports.fetchFilesFromStackTrace = fetchFilesFromStackTrace;
|
|
74
76
|
const fetchSourceCodeFromStackTrace = (stack = '') => {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
.map((l, i) => {
|
|
102
|
-
if (i === prepend) return `${line} > ${chalk.bold(l)}`;
|
|
103
|
-
return `${line - prepend + i} | ${l}`;
|
|
77
|
+
const stackLines = stack
|
|
78
|
+
.split('\n')
|
|
79
|
+
.filter(l => l.includes(':'))
|
|
80
|
+
// .map(l => l.match(/\[(.*?)\]/)?.[1] || l) // minitest format
|
|
81
|
+
// .map(l => l.split(':')[0])
|
|
82
|
+
.map(l => l.trim())
|
|
83
|
+
.map(l => l.split(' ').find(p => p.includes(':')) || '')
|
|
84
|
+
.filter(l => (0, is_valid_path_1.default)(l?.split(':')[0]))
|
|
85
|
+
// // filter out 3rd party libs
|
|
86
|
+
.filter(l => !l?.includes(`vendor${path_1.sep}`))
|
|
87
|
+
.filter(l => !l?.includes(`node_modules${path_1.sep}`))
|
|
88
|
+
.filter(l => fs_1.default.existsSync(l.split(':')[0]))
|
|
89
|
+
.filter(l => fs_1.default.lstatSync(l.split(':')[0]).isFile());
|
|
90
|
+
if (!stackLines.length)
|
|
91
|
+
return '';
|
|
92
|
+
const [file, line] = stackLines[0].split(':');
|
|
93
|
+
const prepend = 3;
|
|
94
|
+
const source = fetchSourceCode(fs_1.default.readFileSync(file).toString(), { line, prepend, limit: 7 });
|
|
95
|
+
if (!source)
|
|
96
|
+
return '';
|
|
97
|
+
return source
|
|
98
|
+
.split('\n')
|
|
99
|
+
.map((l, i) => {
|
|
100
|
+
if (i === prepend)
|
|
101
|
+
return `${line} > ${picocolors_1.default.bold(l)}`;
|
|
102
|
+
return `${+line - prepend + i} | ${l}`;
|
|
104
103
|
})
|
|
105
|
-
|
|
104
|
+
.join('\n');
|
|
106
105
|
};
|
|
107
|
-
|
|
106
|
+
exports.fetchSourceCodeFromStackTrace = fetchSourceCodeFromStackTrace;
|
|
108
107
|
const TEST_ID_REGEX = /@T([\w\d]{8})/;
|
|
109
|
-
|
|
110
108
|
const fetchIdFromCode = (code, opts = {}) => {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
109
|
+
const comments = code
|
|
110
|
+
.split('\n')
|
|
111
|
+
.map(l => l.trim())
|
|
112
|
+
.filter(l => {
|
|
113
|
+
switch (opts.lang) {
|
|
114
|
+
case 'ruby':
|
|
115
|
+
case 'python':
|
|
116
|
+
return l.startsWith('# ');
|
|
117
|
+
default:
|
|
118
|
+
return l.startsWith('// ');
|
|
119
|
+
}
|
|
122
120
|
});
|
|
123
|
-
|
|
124
|
-
return comments.find(c => c.match(TEST_ID_REGEX))?.match(TEST_ID_REGEX)?.[1];
|
|
121
|
+
return comments.find(c => c.match(TEST_ID_REGEX))?.match(TEST_ID_REGEX)?.[1];
|
|
125
122
|
};
|
|
126
|
-
|
|
123
|
+
exports.fetchIdFromCode = fetchIdFromCode;
|
|
127
124
|
const fetchIdFromOutput = output => {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
return lines.find(c => c.match(TEST_ID_REGEX))?.match(TEST_ID_REGEX)?.[1];
|
|
125
|
+
const lines = output
|
|
126
|
+
.split('\n')
|
|
127
|
+
.map(l => l.trim())
|
|
128
|
+
.filter(l => l.startsWith('tid://'));
|
|
129
|
+
return lines.find(c => c.match(TEST_ID_REGEX))?.match(TEST_ID_REGEX)?.[1];
|
|
134
130
|
};
|
|
135
|
-
|
|
131
|
+
exports.fetchIdFromOutput = fetchIdFromOutput;
|
|
136
132
|
const fetchSourceCode = (contents, opts = {}) => {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
133
|
+
if (!opts.title && !opts.line)
|
|
134
|
+
return '';
|
|
135
|
+
// code fragment is 20 lines
|
|
136
|
+
const limit = opts.limit || 50;
|
|
137
|
+
let lineIndex;
|
|
138
|
+
if (opts.line)
|
|
139
|
+
lineIndex = opts.line - 1;
|
|
140
|
+
const lines = contents.split('\n');
|
|
141
|
+
// remove special chars from title
|
|
142
|
+
if (!lineIndex && opts.title) {
|
|
143
|
+
const title = opts.title.replace(/[([@].*/g, '');
|
|
144
|
+
if (opts.lang === 'java') {
|
|
145
|
+
lineIndex = lines.findIndex(l => l.includes(`test${title}`));
|
|
146
|
+
if (lineIndex === -1)
|
|
147
|
+
lineIndex = lines.findIndex(l => l.includes(`@DisplayName("${title}`));
|
|
148
|
+
if (lineIndex === -1)
|
|
149
|
+
lineIndex = lines.findIndex(l => l.includes(`public void ${title}`));
|
|
150
|
+
if (lineIndex === -1)
|
|
151
|
+
lineIndex = lines.findIndex(l => l.includes(`${title}(`));
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
lineIndex = lines.findIndex(l => l.includes(title));
|
|
155
|
+
}
|
|
156
156
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
lineIndex
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
157
|
+
if (opts.prepend) {
|
|
158
|
+
lineIndex -= opts.prepend;
|
|
159
|
+
}
|
|
160
|
+
if (lineIndex) {
|
|
161
|
+
const result = [];
|
|
162
|
+
for (let i = lineIndex; i < lineIndex + limit; i++) {
|
|
163
|
+
if (lines[i] === undefined)
|
|
164
|
+
continue;
|
|
165
|
+
if (i > lineIndex + 2 && !opts.prepend) {
|
|
166
|
+
// annotation
|
|
167
|
+
if (opts.lang === 'php' && lines[i].trim().startsWith('#['))
|
|
168
|
+
break;
|
|
169
|
+
if (opts.lang === 'php' && lines[i].includes(' private function '))
|
|
170
|
+
break;
|
|
171
|
+
if (opts.lang === 'php' && lines[i].includes(' protected function '))
|
|
172
|
+
break;
|
|
173
|
+
if (opts.lang === 'php' && lines[i].includes(' public function '))
|
|
174
|
+
break;
|
|
175
|
+
if (opts.lang === 'python' && lines[i].trim().match(/^@\w+/))
|
|
176
|
+
break;
|
|
177
|
+
if (opts.lang === 'python' && lines[i].includes(' def '))
|
|
178
|
+
break;
|
|
179
|
+
if (opts.lang === 'ruby' && lines[i].includes(' def '))
|
|
180
|
+
break;
|
|
181
|
+
if (opts.lang === 'ruby' && lines[i].includes(' test '))
|
|
182
|
+
break;
|
|
183
|
+
if (opts.lang === 'ruby' && lines[i].includes(' it '))
|
|
184
|
+
break;
|
|
185
|
+
if (opts.lang === 'ruby' && lines[i].includes(' specify '))
|
|
186
|
+
break;
|
|
187
|
+
if (opts.lang === 'ruby' && lines[i].includes(' context '))
|
|
188
|
+
break;
|
|
189
|
+
if (opts.lang === 'ts' && lines[i].includes(' it('))
|
|
190
|
+
break;
|
|
191
|
+
if (opts.lang === 'ts' && lines[i].includes(' test('))
|
|
192
|
+
break;
|
|
193
|
+
if (opts.lang === 'js' && lines[i].includes(' it('))
|
|
194
|
+
break;
|
|
195
|
+
if (opts.lang === 'js' && lines[i].includes(' test('))
|
|
196
|
+
break;
|
|
197
|
+
if (opts.lang === 'java' && lines[i].trim().match(/^@\w+/))
|
|
198
|
+
break;
|
|
199
|
+
if (opts.lang === 'java' && lines[i].includes(' public void '))
|
|
200
|
+
break;
|
|
201
|
+
if (opts.lang === 'java' && lines[i].includes(' class '))
|
|
202
|
+
break;
|
|
203
|
+
}
|
|
204
|
+
result.push(lines[i]);
|
|
205
|
+
}
|
|
206
|
+
return result.join('\n');
|
|
190
207
|
}
|
|
191
|
-
return result.join('\n');
|
|
192
|
-
}
|
|
193
208
|
};
|
|
194
|
-
|
|
195
|
-
const isSameTest = (test, t) =>
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
209
|
+
exports.fetchSourceCode = fetchSourceCode;
|
|
210
|
+
const isSameTest = (test, t) => typeof t === 'object' &&
|
|
211
|
+
typeof test === 'object' &&
|
|
212
|
+
t.title === test.title &&
|
|
213
|
+
t.suite_title === test.suite_title &&
|
|
214
|
+
Object.values(t.example || {}) === Object.values(test.example || {}) &&
|
|
215
|
+
t.test_id === test.test_id;
|
|
216
|
+
exports.isSameTest = isSameTest;
|
|
203
217
|
const getCurrentDateTime = () => {
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
return `${today.getFullYear()}_${
|
|
207
|
-
today.getMonth() + 1
|
|
208
|
-
}_${today.getDate()}_${today.getHours()}_${today.getMinutes()}_${today.getSeconds()}`;
|
|
218
|
+
const today = new Date();
|
|
219
|
+
return `${today.getFullYear()}_${today.getMonth() + 1}_${today.getDate()}_${today.getHours()}_${today.getMinutes()}_${today.getSeconds()}`;
|
|
209
220
|
};
|
|
210
|
-
|
|
221
|
+
exports.getCurrentDateTime = getCurrentDateTime;
|
|
211
222
|
/**
|
|
212
223
|
* @param {Object} test - Test adapter object
|
|
213
224
|
*
|
|
214
225
|
* @returns {String|null} testInfo as one string
|
|
215
226
|
*/
|
|
216
227
|
const specificTestInfo = test => {
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
return null;
|
|
228
|
+
// TODO: afterEach has another context.... need to add specific handler, maybe...
|
|
229
|
+
if (test?.title && test?.file) {
|
|
230
|
+
return `${(0, path_1.basename)(test.file).split('.').join('#')}#${test.title.split(' ').join('#')}`;
|
|
231
|
+
}
|
|
232
|
+
return null;
|
|
223
233
|
};
|
|
224
|
-
|
|
234
|
+
exports.specificTestInfo = specificTestInfo;
|
|
225
235
|
const fileSystem = {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
236
|
+
createDir(dirPath) {
|
|
237
|
+
if (!fs_1.default.existsSync(dirPath)) {
|
|
238
|
+
fs_1.default.mkdirSync(dirPath, { recursive: true });
|
|
239
|
+
debug('Created dir: ', dirPath);
|
|
240
|
+
}
|
|
241
|
+
},
|
|
242
|
+
clearDir(dirPath) {
|
|
243
|
+
if (fs_1.default.existsSync(dirPath)) {
|
|
244
|
+
fs_1.default.rmSync(dirPath, { recursive: true });
|
|
245
|
+
debug(`Dir ${dirPath} was deleted`);
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
debug(`Trying to delete ${dirPath} but it doesn't exist`);
|
|
249
|
+
}
|
|
250
|
+
},
|
|
240
251
|
};
|
|
241
|
-
|
|
252
|
+
exports.fileSystem = fileSystem;
|
|
242
253
|
const foundedTestLog = (app, tests) => {
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
return n === 1 ? console.log(app, `✅ We found one test!`) : console.log(app, `✅ We found ${n} tests!`);
|
|
254
|
+
const n = tests.length;
|
|
255
|
+
return n === 1 ? console.log(app, `✅ We found one test!`) : console.log(app, `✅ We found ${n} tests!`);
|
|
246
256
|
};
|
|
247
|
-
|
|
257
|
+
exports.foundedTestLog = foundedTestLog;
|
|
248
258
|
const humanize = text => {
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
259
|
+
// if there are no spaces, decamelize
|
|
260
|
+
if (!text.trim().includes(' '))
|
|
261
|
+
text = decamelize(text);
|
|
262
|
+
return text
|
|
263
|
+
.replace(/_./g, match => ` ${match.charAt(1).toUpperCase()}`)
|
|
264
|
+
.trim()
|
|
265
|
+
.replace(/^(.)|\s(.)/g, $1 => $1.toUpperCase())
|
|
266
|
+
.trim()
|
|
267
|
+
.replace(/\sA\s/g, ' a ') // replace a|the
|
|
268
|
+
.replace(/\sThe\s/g, ' the ') // replace a|the
|
|
269
|
+
.replace(/^Test\s/, '')
|
|
270
|
+
.replace(/^Should\s/, '');
|
|
261
271
|
};
|
|
262
|
-
|
|
272
|
+
exports.humanize = humanize;
|
|
263
273
|
/**
|
|
264
274
|
* From https://github.com/sindresorhus/decamelize/blob/main/index.js
|
|
265
275
|
* @param {*} text
|
|
266
276
|
* @returns
|
|
267
277
|
*/
|
|
268
278
|
const decamelize = text => {
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
/(
|
|
283
|
-
$0 => $0.toLowerCase(),
|
|
284
|
-
);
|
|
285
|
-
|
|
286
|
-
// Remaining uppercase sequences will be separated from lowercase sequences.
|
|
287
|
-
// `data_For_USACounties` → `data_for_USA_counties`
|
|
288
|
-
return decamelized.replace(
|
|
289
|
-
/(\p{Uppercase_Letter}+)(\p{Uppercase_Letter}\p{Lowercase_Letter}+)/gu,
|
|
290
|
-
(_, $1, $2) => $1 + separator + $2.toLowerCase(),
|
|
291
|
-
);
|
|
279
|
+
const separator = '_';
|
|
280
|
+
const replacement = `$1${separator}$2`;
|
|
281
|
+
// Split lowercase sequences followed by uppercase character.
|
|
282
|
+
// `dataForUSACounties` → `data_For_USACounties`
|
|
283
|
+
// `myURLstring → `my_URLstring`
|
|
284
|
+
let decamelized = text.replace(/([\p{Lowercase_Letter}\d])(\p{Uppercase_Letter})/gu, replacement);
|
|
285
|
+
// Lowercase all single uppercase characters. As we
|
|
286
|
+
// want to preserve uppercase sequences, we cannot
|
|
287
|
+
// simply lowercase the separated string at the end.
|
|
288
|
+
// `data_For_USACounties` → `data_for_USACounties`
|
|
289
|
+
decamelized = decamelized.replace(/((?<![\p{Uppercase_Letter}\d])[\p{Uppercase_Letter}\d](?![\p{Uppercase_Letter}\d]))/gu, $0 => $0.toLowerCase());
|
|
290
|
+
// Remaining uppercase sequences will be separated from lowercase sequences.
|
|
291
|
+
// `data_For_USACounties` → `data_for_USA_counties`
|
|
292
|
+
return decamelized.replace(/(\p{Uppercase_Letter}+)(\p{Uppercase_Letter}\p{Lowercase_Letter}+)/gu, (_, $1, $2) => $1 + separator + $2.toLowerCase());
|
|
292
293
|
};
|
|
293
|
-
|
|
294
294
|
/**
|
|
295
295
|
* Used to remove color codes
|
|
296
296
|
* @param {*} input
|
|
297
297
|
* @returns
|
|
298
298
|
*/
|
|
299
299
|
function removeColorCodes(input) {
|
|
300
|
-
|
|
301
|
-
|
|
300
|
+
// eslint-disable-next-line no-control-regex
|
|
301
|
+
return input.replace(/\x1b\[[0-9;]*m/g, '');
|
|
302
302
|
}
|
|
303
|
-
|
|
304
303
|
const testRunnerHelper = {
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
304
|
+
// for Jest
|
|
305
|
+
getNameOfCurrentlyRunningTest: () => {
|
|
306
|
+
if (global.testomatioTestTitle)
|
|
307
|
+
return global.testomatioTestTitle;
|
|
308
|
+
if (!process.env.JEST_WORKER_ID)
|
|
309
|
+
return null;
|
|
310
|
+
try {
|
|
311
|
+
// TODO: expect?.getState()?.testPath + ' ' + expect?.getState()?.currentTestName
|
|
312
|
+
// @ts-expect-error "expect" could only be defined inside Jest environement (forbidden to import it outside)
|
|
313
|
+
// eslint-disable-next-line no-undef
|
|
314
|
+
return expect?.getState()?.currentTestName;
|
|
315
|
+
}
|
|
316
|
+
catch (e) {
|
|
317
|
+
return null;
|
|
318
|
+
}
|
|
319
|
+
},
|
|
319
320
|
};
|
|
321
|
+
exports.testRunnerHelper = testRunnerHelper;
|
|
320
322
|
|
|
321
|
-
module.exports =
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
323
|
+
module.exports.removeColorCodes = removeColorCodes;
|
|
324
|
+
|
|
325
|
+
module.exports.getTestomatIdFromTestTitle = getTestomatIdFromTestTitle;
|
|
326
|
+
|
|
327
|
+
module.exports.parseSuite = parseSuite;
|
|
328
|
+
|
|
329
|
+
module.exports.ansiRegExp = ansiRegExp;
|
|
330
|
+
|
|
331
|
+
module.exports.isValidUrl = isValidUrl;
|
|
332
|
+
|
|
333
|
+
module.exports.fetchFilesFromStackTrace = fetchFilesFromStackTrace;
|
|
334
|
+
|
|
335
|
+
module.exports.fetchSourceCodeFromStackTrace = fetchSourceCodeFromStackTrace;
|
|
336
|
+
|
|
337
|
+
module.exports.fetchIdFromCode = fetchIdFromCode;
|
|
338
|
+
|
|
339
|
+
module.exports.fetchIdFromOutput = fetchIdFromOutput;
|
|
340
|
+
|
|
341
|
+
module.exports.fetchSourceCode = fetchSourceCode;
|
|
342
|
+
|
|
343
|
+
module.exports.isSameTest = isSameTest;
|
|
344
|
+
|
|
345
|
+
module.exports.getCurrentDateTime = getCurrentDateTime;
|
|
346
|
+
|
|
347
|
+
module.exports.specificTestInfo = specificTestInfo;
|
|
348
|
+
|
|
349
|
+
module.exports.fileSystem = fileSystem;
|
|
350
|
+
|
|
351
|
+
module.exports.foundedTestLog = foundedTestLog;
|
|
352
|
+
|
|
353
|
+
module.exports.humanize = humanize;
|
|
354
|
+
|
|
355
|
+
module.exports.testRunnerHelper = testRunnerHelper;
|