@testomatio/reporter 2.3.2-beta.3-xml-import → 2.3.3
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/playwright.d.ts +6 -0
- package/lib/adapter/playwright.js +3 -0
- package/lib/bin/cli.js +0 -1
- package/lib/junit-adapter/csharp.d.ts +1 -0
- package/lib/junit-adapter/csharp.js +7 -36
- package/lib/pipe/testomatio.d.ts +1 -1
- package/lib/pipe/testomatio.js +2 -1
- package/lib/utils/utils.d.ts +3 -2
- package/lib/utils/utils.js +32 -35
- package/lib/xmlReader.d.ts +1 -8
- package/lib/xmlReader.js +13 -317
- package/package.json +2 -2
- package/src/adapter/playwright.js +1 -0
- package/src/bin/cli.js +0 -1
- package/src/junit-adapter/csharp.js +6 -40
- package/src/pipe/testomatio.js +5 -2
- package/src/utils/utils.js +23 -35
- package/src/xmlReader.js +13 -367
|
@@ -11,4 +11,10 @@ declare class PlaywrightReporter {
|
|
|
11
11
|
onEnd(result: any): Promise<void>;
|
|
12
12
|
#private;
|
|
13
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Extracts and normalizes tags from test title, test options, and suite level
|
|
16
|
+
* @param {*} test - testInfo object from Playwright
|
|
17
|
+
* @returns {string[]} - array of normalized tags
|
|
18
|
+
*/
|
|
19
|
+
export function extractTags(test: any): string[];
|
|
14
20
|
import TestomatioClient from '../client.js';
|
|
@@ -3,6 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.extractTags = extractTags;
|
|
6
7
|
const picocolors_1 = __importDefault(require("picocolors"));
|
|
7
8
|
const crypto_1 = __importDefault(require("crypto"));
|
|
8
9
|
const os_1 = __importDefault(require("os"));
|
|
@@ -253,3 +254,5 @@ function getTestContextName(test) {
|
|
|
253
254
|
return `${test._requireFile || ''}_${test.title}`;
|
|
254
255
|
}
|
|
255
256
|
module.exports = PlaywrightReporter;
|
|
257
|
+
|
|
258
|
+
module.exports.extractTags = extractTags;
|
package/lib/bin/cli.js
CHANGED
|
@@ -61,7 +61,6 @@ program
|
|
|
61
61
|
const client = new client_js_1.default({ apiKey });
|
|
62
62
|
// @ts-ignore
|
|
63
63
|
client.updateRunStatus(constants_js_1.STATUS.FINISHED).then(() => {
|
|
64
|
-
console.log(picocolors_1.default.yellow(`Run ${process.env.TESTOMATIO_RUN} was finished`));
|
|
65
64
|
process.exit(0);
|
|
66
65
|
});
|
|
67
66
|
});
|
|
@@ -7,53 +7,24 @@ const path_1 = __importDefault(require("path"));
|
|
|
7
7
|
const adapter_js_1 = __importDefault(require("./adapter.js"));
|
|
8
8
|
class CSharpAdapter extends adapter_js_1.default {
|
|
9
9
|
formatTest(t) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
if (
|
|
13
|
-
|
|
14
|
-
const exampleMatch = t.title.match(/\((.*?)\)/);
|
|
15
|
-
if (exampleMatch) {
|
|
16
|
-
// Keep as array for consistency with NUnit XML processing
|
|
17
|
-
t.example = exampleMatch[1].split(',').map(param => param.trim());
|
|
18
|
-
}
|
|
19
|
-
t.title = title.trim();
|
|
20
|
-
}
|
|
10
|
+
const title = t.title.replace(/\(.*?\)/, '').trim();
|
|
11
|
+
const example = t.title.match(/\((.*?)\)/);
|
|
12
|
+
if (example)
|
|
13
|
+
t.example = { ...example[1].split(',') };
|
|
21
14
|
const suite = t.suite_title.split('.');
|
|
22
15
|
t.suite_title = suite.pop();
|
|
23
16
|
t.file = namespaceToFileName(t.file);
|
|
17
|
+
t.title = title.trim();
|
|
24
18
|
return t;
|
|
25
19
|
}
|
|
26
20
|
getFilePath(t) {
|
|
27
|
-
|
|
28
|
-
return null;
|
|
29
|
-
// Normalize path separators for cross-platform compatibility
|
|
30
|
-
let filePath = t.file.replace(/\\/g, '/');
|
|
31
|
-
// If file already has .cs extension, use it directly
|
|
32
|
-
if (filePath.endsWith('.cs')) {
|
|
33
|
-
// Make relative path if it's absolute
|
|
34
|
-
if (path_1.default.isAbsolute(filePath)) {
|
|
35
|
-
// Try to find project-relative path
|
|
36
|
-
const cwd = process.cwd().replace(/\\/g, '/');
|
|
37
|
-
if (filePath.startsWith(cwd)) {
|
|
38
|
-
filePath = path_1.default.relative(cwd, filePath).replace(/\\/g, '/');
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
return filePath;
|
|
42
|
-
}
|
|
43
|
-
// Convert namespace path to file path
|
|
44
|
-
const fileName = namespaceToFileName(filePath);
|
|
21
|
+
const fileName = namespaceToFileName(t.file);
|
|
45
22
|
return fileName;
|
|
46
23
|
}
|
|
47
24
|
}
|
|
48
25
|
module.exports = CSharpAdapter;
|
|
49
26
|
function namespaceToFileName(fileName) {
|
|
50
|
-
if (!fileName)
|
|
51
|
-
return '';
|
|
52
|
-
// If already a .cs file path, clean it up
|
|
53
|
-
if (fileName.endsWith('.cs')) {
|
|
54
|
-
return fileName.replace(/\\/g, '/');
|
|
55
|
-
}
|
|
56
27
|
const fileParts = fileName.split('.');
|
|
57
28
|
fileParts[fileParts.length - 1] = fileParts[fileParts.length - 1]?.replace(/\$.*/, '');
|
|
58
|
-
return `${fileParts.join(
|
|
29
|
+
return `${fileParts.join(path_1.default.sep)}.cs`;
|
|
59
30
|
}
|
package/lib/pipe/testomatio.d.ts
CHANGED
package/lib/pipe/testomatio.js
CHANGED
|
@@ -78,7 +78,7 @@ class TestomatioPipe {
|
|
|
78
78
|
});
|
|
79
79
|
this.isEnabled = true;
|
|
80
80
|
// do not finish this run (for parallel testing)
|
|
81
|
-
this.proceed = process.env.TESTOMATIO_PROCEED;
|
|
81
|
+
this.proceed = (0, utils_js_1.transformEnvVarToBoolean)(process.env.TESTOMATIO_PROCEED);
|
|
82
82
|
this.jiraId = process.env.TESTOMATIO_JIRA_ID;
|
|
83
83
|
this.runId = params.runId || process.env.TESTOMATIO_RUN;
|
|
84
84
|
this.createNewTests = params.createNewTests ?? !!process.env.TESTOMATIO_CREATE;
|
|
@@ -396,6 +396,7 @@ class TestomatioPipe {
|
|
|
396
396
|
tests: params.tests,
|
|
397
397
|
}
|
|
398
398
|
});
|
|
399
|
+
console.log(constants_js_1.APP_PREFIX, '✅ Testrun finished');
|
|
399
400
|
if (this.runUrl) {
|
|
400
401
|
console.log(constants_js_1.APP_PREFIX, '📊 Report Saved. Report URL:', picocolors_1.default.magenta(this.runUrl));
|
|
401
402
|
}
|
package/lib/utils/utils.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export function getPackageVersion(): any;
|
|
|
2
2
|
export const TEST_ID_REGEX: RegExp;
|
|
3
3
|
export const SUITE_ID_REGEX: RegExp;
|
|
4
4
|
export function ansiRegExp(): RegExp;
|
|
5
|
-
export function cleanLatestRunId():
|
|
5
|
+
export function cleanLatestRunId(): any;
|
|
6
6
|
export function isSameTest(test: any, t: any): boolean;
|
|
7
7
|
export function fetchSourceCode(contents: any, opts?: {}): string;
|
|
8
8
|
export function fetchSourceCodeFromStackTrace(stack?: string): string;
|
|
@@ -47,10 +47,11 @@ export function removeColorCodes(input: any): any;
|
|
|
47
47
|
* @returns {String|null} testInfo as one string
|
|
48
48
|
*/
|
|
49
49
|
export function specificTestInfo(test: any): string | null;
|
|
50
|
-
export function storeRunId(runId: any):
|
|
50
|
+
export function storeRunId(runId: any): any;
|
|
51
51
|
export namespace testRunnerHelper {
|
|
52
52
|
function getNameOfCurrentlyRunningTest(): any;
|
|
53
53
|
}
|
|
54
|
+
export function transformEnvVarToBoolean(value: any): boolean;
|
|
54
55
|
/**
|
|
55
56
|
* Validates TESTOMATIO_SUITE environment variable format
|
|
56
57
|
* @param {String} suiteId - suite ID to validate
|
package/lib/utils/utils.js
CHANGED
|
@@ -43,6 +43,7 @@ exports.formatStep = formatStep;
|
|
|
43
43
|
exports.readLatestRunId = readLatestRunId;
|
|
44
44
|
exports.removeColorCodes = removeColorCodes;
|
|
45
45
|
exports.storeRunId = storeRunId;
|
|
46
|
+
exports.transformEnvVarToBoolean = transformEnvVarToBoolean;
|
|
46
47
|
const url_1 = require("url");
|
|
47
48
|
const path_1 = __importStar(require("path"));
|
|
48
49
|
const picocolors_1 = __importDefault(require("picocolors"));
|
|
@@ -172,8 +173,6 @@ exports.fetchSourceCodeFromStackTrace = fetchSourceCodeFromStackTrace;
|
|
|
172
173
|
exports.TEST_ID_REGEX = /@T([\w\d]{8})/;
|
|
173
174
|
exports.SUITE_ID_REGEX = /@S([\w\d]{8})/;
|
|
174
175
|
const fetchIdFromCode = (code, opts = {}) => {
|
|
175
|
-
if (!code)
|
|
176
|
-
return null;
|
|
177
176
|
const comments = code
|
|
178
177
|
.split('\n')
|
|
179
178
|
.map(l => l.trim())
|
|
@@ -216,29 +215,10 @@ const fetchSourceCode = (contents, opts = {}) => {
|
|
|
216
215
|
lineIndex = lines.findIndex(l => l.includes(`${title}(`));
|
|
217
216
|
}
|
|
218
217
|
else if (opts.lang === 'csharp') {
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
if (lineIndex === -1)
|
|
222
|
-
lineIndex = lines.findIndex(l => l.includes(`public async Task ${title}(`));
|
|
223
|
-
}
|
|
224
|
-
if (lineIndex === -1) {
|
|
218
|
+
if (lineIndex === -1)
|
|
219
|
+
lineIndex = lines.findIndex(l => l.includes(`public void ${title}`));
|
|
220
|
+
if (lineIndex === -1)
|
|
225
221
|
lineIndex = lines.findIndex(l => l.includes(`${title}(`));
|
|
226
|
-
}
|
|
227
|
-
// Look for TestCase or Test attributes above the method
|
|
228
|
-
if (lineIndex === -1) {
|
|
229
|
-
const testAttributeIndex = lines.findIndex((l, index) => {
|
|
230
|
-
if (l.includes('[TestCase') || l.includes('[Test')) {
|
|
231
|
-
// Check next few lines for the method
|
|
232
|
-
const nextLines = lines.slice(index, Math.min(lines.length, index + 5));
|
|
233
|
-
const hasMethod = nextLines.some(nextLine => nextLine.includes(`${title}(`));
|
|
234
|
-
return hasMethod;
|
|
235
|
-
}
|
|
236
|
-
return false;
|
|
237
|
-
});
|
|
238
|
-
if (testAttributeIndex !== -1) {
|
|
239
|
-
lineIndex = testAttributeIndex;
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
222
|
}
|
|
243
223
|
else {
|
|
244
224
|
lineIndex = lines.findIndex(l => l.includes(title));
|
|
@@ -247,7 +227,7 @@ const fetchSourceCode = (contents, opts = {}) => {
|
|
|
247
227
|
if (opts.prepend) {
|
|
248
228
|
lineIndex -= opts.prepend;
|
|
249
229
|
}
|
|
250
|
-
if (lineIndex
|
|
230
|
+
if (lineIndex) {
|
|
251
231
|
const result = [];
|
|
252
232
|
for (let i = lineIndex; i < lineIndex + limit; i++) {
|
|
253
233
|
if (lines[i] === undefined)
|
|
@@ -290,14 +270,6 @@ const fetchSourceCode = (contents, opts = {}) => {
|
|
|
290
270
|
break;
|
|
291
271
|
if (opts.lang === 'java' && lines[i].includes(' class '))
|
|
292
272
|
break;
|
|
293
|
-
if (opts.lang === 'csharp' && lines[i].trim().match(/^\[Test/))
|
|
294
|
-
break;
|
|
295
|
-
if (opts.lang === 'csharp' && lines[i].includes(' public void '))
|
|
296
|
-
break;
|
|
297
|
-
if (opts.lang === 'csharp' && lines[i].includes(' public async Task '))
|
|
298
|
-
break;
|
|
299
|
-
if (opts.lang === 'csharp' && lines[i].includes(' class ') && lines[i].includes('public'))
|
|
300
|
-
break;
|
|
301
273
|
}
|
|
302
274
|
result.push(lines[i]);
|
|
303
275
|
}
|
|
@@ -419,7 +391,14 @@ function storeRunId(runId) {
|
|
|
419
391
|
if (!runId || runId === 'undefined')
|
|
420
392
|
return;
|
|
421
393
|
const filePath = path_1.default.join(os_1.default.tmpdir(), `testomatio.latest.run`);
|
|
422
|
-
|
|
394
|
+
try {
|
|
395
|
+
fs_1.default.writeFileSync(filePath, runId);
|
|
396
|
+
}
|
|
397
|
+
catch (e) {
|
|
398
|
+
if (e.code === 'ENOENT')
|
|
399
|
+
return null;
|
|
400
|
+
debug('Could not store latest run ID file: ', e.message);
|
|
401
|
+
}
|
|
423
402
|
}
|
|
424
403
|
/**
|
|
425
404
|
*
|
|
@@ -438,7 +417,6 @@ function readLatestRunId() {
|
|
|
438
417
|
return fs_1.default.readFileSync(filePath)?.toString()?.trim() ?? null;
|
|
439
418
|
}
|
|
440
419
|
catch (e) {
|
|
441
|
-
console.warn('Could not read latest run ID from file: ', e);
|
|
442
420
|
return null;
|
|
443
421
|
}
|
|
444
422
|
}
|
|
@@ -452,6 +430,8 @@ function cleanLatestRunId() {
|
|
|
452
430
|
debug(`Cleaned latest run ID (${runId}) file`, filePath);
|
|
453
431
|
}
|
|
454
432
|
catch (e) {
|
|
433
|
+
if (e.code === 'ENOENT')
|
|
434
|
+
return null;
|
|
455
435
|
console.warn('Could not clean latest run ID file: ', e);
|
|
456
436
|
}
|
|
457
437
|
}
|
|
@@ -474,6 +454,21 @@ function getPackageVersion() {
|
|
|
474
454
|
const packageJson = JSON.parse(fs_1.default.readFileSync(packageJsonPath, 'utf8'));
|
|
475
455
|
return packageJson.version;
|
|
476
456
|
}
|
|
457
|
+
function transformEnvVarToBoolean(value) {
|
|
458
|
+
if (value === undefined || value === null || value === 'undefined')
|
|
459
|
+
return false;
|
|
460
|
+
if (typeof value === 'boolean')
|
|
461
|
+
return value;
|
|
462
|
+
if (typeof value !== 'string')
|
|
463
|
+
value = String(value);
|
|
464
|
+
value = value.trim();
|
|
465
|
+
if (['1', 'true', 'yes', 'on'].includes(value.toLowerCase()))
|
|
466
|
+
return true;
|
|
467
|
+
if (['0', 'false', 'no', 'off'].includes(value.toLowerCase()))
|
|
468
|
+
return false;
|
|
469
|
+
// if not recognized, return truthy if any value is set
|
|
470
|
+
return Boolean(value);
|
|
471
|
+
}
|
|
477
472
|
|
|
478
473
|
module.exports.getPackageVersion = getPackageVersion;
|
|
479
474
|
|
|
@@ -487,6 +482,8 @@ module.exports.removeColorCodes = removeColorCodes;
|
|
|
487
482
|
|
|
488
483
|
module.exports.storeRunId = storeRunId;
|
|
489
484
|
|
|
485
|
+
module.exports.transformEnvVarToBoolean = transformEnvVarToBoolean;
|
|
486
|
+
|
|
490
487
|
module.exports.getTestomatIdFromTestTitle = getTestomatIdFromTestTitle;
|
|
491
488
|
|
|
492
489
|
module.exports.parseSuite = parseSuite;
|
package/lib/xmlReader.d.ts
CHANGED
|
@@ -46,7 +46,7 @@ declare class XmlReader {
|
|
|
46
46
|
passed_count: number;
|
|
47
47
|
skipped_count: number;
|
|
48
48
|
status: string;
|
|
49
|
-
tests: any;
|
|
49
|
+
tests: any[];
|
|
50
50
|
tests_count: number;
|
|
51
51
|
};
|
|
52
52
|
processNUnit(jsonSuite: any): {
|
|
@@ -77,13 +77,6 @@ declare class XmlReader {
|
|
|
77
77
|
skipped_count: number;
|
|
78
78
|
tests: any[];
|
|
79
79
|
};
|
|
80
|
-
deduplicateTestsByFQN(tests: any): any[];
|
|
81
|
-
generateFQN(test: any): string;
|
|
82
|
-
generateNormalizedFQN(test: any): string;
|
|
83
|
-
extractAssemblyName(test: any): any;
|
|
84
|
-
extractNamespace(test: any): any;
|
|
85
|
-
extractClassName(test: any): any;
|
|
86
|
-
extractCsFileFromPath(test: any): any;
|
|
87
80
|
calculateStats(): {};
|
|
88
81
|
fetchSourceCode(): void;
|
|
89
82
|
formatTests(): void;
|