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