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