@testomatio/reporter 2.9.1-beta.4-allure-step-status → 2.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -4
- package/lib/bin/cli.js +0 -28
- package/lib/junit-adapter/index.js +0 -4
- package/lib/utils/pipe_utils.d.ts +0 -17
- package/lib/utils/pipe_utils.js +0 -45
- package/lib/utils/utils.js +0 -9
- package/lib/xmlReader.d.ts +1 -0
- package/lib/xmlReader.js +38 -2
- package/package.json +1 -1
- package/src/bin/cli.js +0 -35
- package/src/junit-adapter/index.js +0 -4
- package/src/utils/pipe_utils.js +0 -49
- package/src/utils/utils.js +0 -5
- package/src/xmlReader.js +47 -2
- package/lib/allureReader.d.ts +0 -121
- package/lib/allureReader.js +0 -599
- package/lib/junit-adapter/kotlin.d.ts +0 -5
- package/lib/junit-adapter/kotlin.js +0 -46
- package/src/allureReader.js +0 -691
- package/src/junit-adapter/kotlin.js +0 -48
package/README.md
CHANGED
|
@@ -76,7 +76,6 @@ npx testomatio-reporter <command> [options]
|
|
|
76
76
|
| [TestCafe](./docs/frameworks.md#testcafe) | [Detox](./docs/frameworks.md#detox) | [Codeception](https://github.com/testomatio/php-reporter) |
|
|
77
77
|
| [Newman (Postman)](./docs/frameworks.md#newman) | [JUnit](./docs/junit.md#junit) | [NUnit](./docs/junit.md#nunit) |
|
|
78
78
|
| [PyTest](./docs/junit.md#pytest) | [PHPUnit](./docs/junit.md#phpunit) | [Protractor](./docs/frameworks.md#protractor) |
|
|
79
|
-
| [Allure](./docs/allure.md) | | |
|
|
80
79
|
|
|
81
80
|
or **any [other via JUnit](./docs/junit.md)** report....
|
|
82
81
|
|
|
@@ -138,10 +137,9 @@ Bring this reporter on CI and never lose test results again!
|
|
|
138
137
|
- [HTML report](./docs/pipes/html.md)
|
|
139
138
|
- [Markdown report](./docs/pipes/markdown.md)
|
|
140
139
|
- [Bitbucket](./docs/pipes/bitbucket.md)
|
|
141
|
-
- 📓 [JUnit Reports](./docs/junit.md)
|
|
142
|
-
- 🗄️ [Artifacts](./docs/artifacts.md)
|
|
143
|
-
- 🔬 [Allure Reports](./docs/allure.md)
|
|
144
140
|
- 🔗 [Linking Tests](./docs/linking-tests.md)
|
|
141
|
+
- 📓 [JUnit](./docs/junit.md)
|
|
142
|
+
- 🗄️ [Artifacts](./docs/artifacts.md)
|
|
145
143
|
- 🔂 [Workflows](./docs/workflows.md)
|
|
146
144
|
- 🖊️ [Logger](./docs/logger.md)
|
|
147
145
|
- 🪲 [Debug File Format](./docs/debug-file-format.md)
|
package/lib/bin/cli.js
CHANGED
|
@@ -10,7 +10,6 @@ const glob_1 = require("glob");
|
|
|
10
10
|
const debug_1 = __importDefault(require("debug"));
|
|
11
11
|
const client_js_1 = __importDefault(require("../client.js"));
|
|
12
12
|
const xmlReader_js_1 = __importDefault(require("../xmlReader.js"));
|
|
13
|
-
const allureReader_js_1 = __importDefault(require("../allureReader.js"));
|
|
14
13
|
const constants_js_1 = require("../constants.js");
|
|
15
14
|
const utils_js_1 = require("../utils/utils.js");
|
|
16
15
|
const config_js_1 = require("../config.js");
|
|
@@ -319,33 +318,6 @@ program
|
|
|
319
318
|
if (timeoutTimer)
|
|
320
319
|
clearTimeout(timeoutTimer);
|
|
321
320
|
});
|
|
322
|
-
program
|
|
323
|
-
.command('allure')
|
|
324
|
-
.description('Parse Allure result files and upload to Testomat.io')
|
|
325
|
-
.argument('<pattern>', 'Allure result directory pattern')
|
|
326
|
-
.option('-d, --dir <dir>', 'Project directory')
|
|
327
|
-
.option('--timelimit <time>', 'default time limit in seconds to kill a stuck process')
|
|
328
|
-
.option('--with-package', 'Keep full package path in file names (default: strip package prefix)')
|
|
329
|
-
.action(async (pattern, opts) => {
|
|
330
|
-
const runReader = new allureReader_js_1.default({ withPackage: opts.withPackage });
|
|
331
|
-
let timeoutTimer;
|
|
332
|
-
if (opts.timelimit) {
|
|
333
|
-
timeoutTimer = setTimeout(() => {
|
|
334
|
-
console.log(`⚠️ Reached timeout of ${opts.timelimit}s. Exiting... (Exit code is 0 to not fail the pipeline)`);
|
|
335
|
-
process.exit(0);
|
|
336
|
-
}, parseInt(opts.timelimit, 10) * 1000);
|
|
337
|
-
}
|
|
338
|
-
try {
|
|
339
|
-
await runReader.parse(pattern);
|
|
340
|
-
await runReader.createRun();
|
|
341
|
-
await runReader.uploadData();
|
|
342
|
-
}
|
|
343
|
-
catch (err) {
|
|
344
|
-
console.log(constants_js_1.APP_PREFIX, 'Error uploading Allure results:', err);
|
|
345
|
-
}
|
|
346
|
-
if (timeoutTimer)
|
|
347
|
-
clearTimeout(timeoutTimer);
|
|
348
|
-
});
|
|
349
321
|
program
|
|
350
322
|
.command('upload-artifacts')
|
|
351
323
|
.description('Upload artifacts to Testomat.io')
|
|
@@ -9,7 +9,6 @@ const java_js_1 = __importDefault(require("./java.js"));
|
|
|
9
9
|
const python_js_1 = __importDefault(require("./python.js"));
|
|
10
10
|
const ruby_js_1 = __importDefault(require("./ruby.js"));
|
|
11
11
|
const csharp_js_1 = __importDefault(require("./csharp.js"));
|
|
12
|
-
const kotlin_js_1 = __importDefault(require("./kotlin.js"));
|
|
13
12
|
function AdapterFactory(lang, opts) {
|
|
14
13
|
if (lang === 'java') {
|
|
15
14
|
return new java_js_1.default(opts);
|
|
@@ -26,9 +25,6 @@ function AdapterFactory(lang, opts) {
|
|
|
26
25
|
if (lang === 'c#' || lang === 'csharp') {
|
|
27
26
|
return new csharp_js_1.default(opts);
|
|
28
27
|
}
|
|
29
|
-
if (lang === 'kotlin') {
|
|
30
|
-
return new kotlin_js_1.default(opts);
|
|
31
|
-
}
|
|
32
28
|
return new adapter_js_1.default(opts);
|
|
33
29
|
}
|
|
34
30
|
module.exports = AdapterFactory;
|
|
@@ -64,20 +64,3 @@ export function parsePipeOptions(optionsStr?: string): any;
|
|
|
64
64
|
* @returns {string} Empty string if no ids; otherwise the formatted output.
|
|
65
65
|
*/
|
|
66
66
|
export function formatFilterListIds(ids: string[], format: "grep" | "json" | "newline" | "ids"): string;
|
|
67
|
-
/**
|
|
68
|
-
* Calculate the approximate size of data in bytes (JSON stringified, UTF-8 encoded length).
|
|
69
|
-
* @param {Object} data - Data to measure
|
|
70
|
-
* @returns {number} Size in bytes
|
|
71
|
-
*/
|
|
72
|
-
export function getObjectSize(data: any): number;
|
|
73
|
-
/**
|
|
74
|
-
* Split a tests array into chunks bounded by serialized size.
|
|
75
|
-
* Used by the XML and Allure readers so both upload tests with identical batching:
|
|
76
|
-
* each chunk becomes a single batch request (manual batch mode), which keeps requests
|
|
77
|
-
* under the size limit and guarantees every test is sent exactly once.
|
|
78
|
-
*
|
|
79
|
-
* @param {Array} tests - Array of tests to split
|
|
80
|
-
* @param {number} [maxSizeBytes=1048576] - Maximum serialized size per chunk (default 1MB)
|
|
81
|
-
* @returns {Array<Array>} Array of test chunks
|
|
82
|
-
*/
|
|
83
|
-
export function splitTestsIntoChunks(tests: any[], maxSizeBytes?: number): Array<any[]>;
|
package/lib/utils/pipe_utils.js
CHANGED
|
@@ -8,8 +8,6 @@ exports.statusEmoji = statusEmoji;
|
|
|
8
8
|
exports.fullName = fullName;
|
|
9
9
|
exports.parsePipeOptions = parsePipeOptions;
|
|
10
10
|
exports.formatFilterListIds = formatFilterListIds;
|
|
11
|
-
exports.getObjectSize = getObjectSize;
|
|
12
|
-
exports.splitTestsIntoChunks = splitTestsIntoChunks;
|
|
13
11
|
const log_js_1 = require("./log.js");
|
|
14
12
|
/**
|
|
15
13
|
* Set S3 credentials from the provided artifacts object.
|
|
@@ -164,45 +162,6 @@ function parsePipeOptions(optionsStr) {
|
|
|
164
162
|
}
|
|
165
163
|
return options;
|
|
166
164
|
}
|
|
167
|
-
/**
|
|
168
|
-
* Calculate the approximate size of data in bytes (JSON stringified, UTF-8 encoded length).
|
|
169
|
-
* @param {Object} data - Data to measure
|
|
170
|
-
* @returns {number} Size in bytes
|
|
171
|
-
*/
|
|
172
|
-
function getObjectSize(data) {
|
|
173
|
-
const body = JSON.stringify(data);
|
|
174
|
-
return new TextEncoder().encode(body).length;
|
|
175
|
-
}
|
|
176
|
-
/**
|
|
177
|
-
* Split a tests array into chunks bounded by serialized size.
|
|
178
|
-
* Used by the XML and Allure readers so both upload tests with identical batching:
|
|
179
|
-
* each chunk becomes a single batch request (manual batch mode), which keeps requests
|
|
180
|
-
* under the size limit and guarantees every test is sent exactly once.
|
|
181
|
-
*
|
|
182
|
-
* @param {Array} tests - Array of tests to split
|
|
183
|
-
* @param {number} [maxSizeBytes=1048576] - Maximum serialized size per chunk (default 1MB)
|
|
184
|
-
* @returns {Array<Array>} Array of test chunks
|
|
185
|
-
*/
|
|
186
|
-
function splitTestsIntoChunks(tests, maxSizeBytes = 1 * 1024 * 1024) {
|
|
187
|
-
const chunks = [];
|
|
188
|
-
let currentChunk = [];
|
|
189
|
-
let currentChunkSize = 0;
|
|
190
|
-
for (const test of tests) {
|
|
191
|
-
const testSize = getObjectSize(test);
|
|
192
|
-
const wouldExceedSize = currentChunkSize + testSize > maxSizeBytes;
|
|
193
|
-
if (wouldExceedSize && currentChunk.length > 0) {
|
|
194
|
-
chunks.push(currentChunk);
|
|
195
|
-
currentChunk = [];
|
|
196
|
-
currentChunkSize = 0;
|
|
197
|
-
}
|
|
198
|
-
currentChunk.push(test);
|
|
199
|
-
currentChunkSize += testSize;
|
|
200
|
-
}
|
|
201
|
-
if (currentChunk.length > 0) {
|
|
202
|
-
chunks.push(currentChunk);
|
|
203
|
-
}
|
|
204
|
-
return chunks;
|
|
205
|
-
}
|
|
206
165
|
/**
|
|
207
166
|
* Format a list of test IDs for `--filter-list` machine-readable output.
|
|
208
167
|
* Used when the CLI `--format` option is passed,
|
|
@@ -239,7 +198,3 @@ module.exports.fullName = fullName;
|
|
|
239
198
|
module.exports.parsePipeOptions = parsePipeOptions;
|
|
240
199
|
|
|
241
200
|
module.exports.formatFilterListIds = formatFilterListIds;
|
|
242
|
-
|
|
243
|
-
module.exports.getObjectSize = getObjectSize;
|
|
244
|
-
|
|
245
|
-
module.exports.splitTestsIntoChunks = splitTestsIntoChunks;
|
package/lib/utils/utils.js
CHANGED
|
@@ -324,15 +324,6 @@ const fetchSourceCode = (contents, opts = {}) => {
|
|
|
324
324
|
if (lineIndex === -1)
|
|
325
325
|
lineIndex = lines.findIndex(l => l.includes(`${title}(`));
|
|
326
326
|
}
|
|
327
|
-
else if (opts.lang === 'kotlin') {
|
|
328
|
-
lineIndex = lines.findIndex(l => l.includes(`fun test${title}`));
|
|
329
|
-
if (lineIndex === -1)
|
|
330
|
-
lineIndex = lines.findIndex(l => l.includes(`@DisplayName("${title}`));
|
|
331
|
-
if (lineIndex === -1)
|
|
332
|
-
lineIndex = lines.findIndex(l => l.includes(`fun ${title}`));
|
|
333
|
-
if (lineIndex === -1)
|
|
334
|
-
lineIndex = lines.findIndex(l => l.includes(`${title}(`));
|
|
335
|
-
}
|
|
336
327
|
else if (opts.lang === 'csharp') {
|
|
337
328
|
// Find the method declaration line
|
|
338
329
|
let methodLineIndex = lines.findIndex(l => l.includes(`public void ${title}(`));
|
package/lib/xmlReader.d.ts
CHANGED
package/lib/xmlReader.js
CHANGED
|
@@ -14,7 +14,6 @@ const url_1 = require("url");
|
|
|
14
14
|
const nunit_parser_js_1 = require("./junit-adapter/nunit-parser.js");
|
|
15
15
|
const utils_js_1 = require("./utils/utils.js");
|
|
16
16
|
const index_js_1 = require("./pipe/index.js");
|
|
17
|
-
const pipe_utils_js_1 = require("./utils/pipe_utils.js");
|
|
18
17
|
const index_js_2 = __importDefault(require("./junit-adapter/index.js"));
|
|
19
18
|
const config_js_1 = require("./config.js");
|
|
20
19
|
const uploader_js_1 = require("./uploader.js");
|
|
@@ -475,6 +474,43 @@ class XmlReader {
|
|
|
475
474
|
this.uploader.checkEnabled();
|
|
476
475
|
return run;
|
|
477
476
|
}
|
|
477
|
+
/**
|
|
478
|
+
* Calculate the approximate size of data in bytes (JSON stringified length)
|
|
479
|
+
* @param {Object} data - Data to measure
|
|
480
|
+
* @returns {number} Size in bytes
|
|
481
|
+
*/
|
|
482
|
+
#getObjectSize(data) {
|
|
483
|
+
const body = JSON.stringify(data);
|
|
484
|
+
return new TextEncoder().encode(body).length;
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* Split tests array into chunks based on data size
|
|
488
|
+
* @param {Array} tests - Array of tests to split
|
|
489
|
+
* @returns {Array<Array>} Array of test chunks
|
|
490
|
+
*/
|
|
491
|
+
#splitTestsIntoChunks(tests) {
|
|
492
|
+
const maxSizeBytes = 1 * 1024 * 1024;
|
|
493
|
+
const chunks = [];
|
|
494
|
+
let currentChunk = [];
|
|
495
|
+
let currentChunkSize = 0;
|
|
496
|
+
for (const test of tests) {
|
|
497
|
+
const testSize = this.#getObjectSize(test);
|
|
498
|
+
const wouldExceedSize = currentChunkSize + testSize > maxSizeBytes;
|
|
499
|
+
if (wouldExceedSize) {
|
|
500
|
+
if (currentChunk.length > 0) {
|
|
501
|
+
chunks.push(currentChunk);
|
|
502
|
+
}
|
|
503
|
+
currentChunk = [];
|
|
504
|
+
currentChunkSize = 0;
|
|
505
|
+
}
|
|
506
|
+
currentChunk.push(test);
|
|
507
|
+
currentChunkSize += testSize;
|
|
508
|
+
}
|
|
509
|
+
if (currentChunk.length > 0) {
|
|
510
|
+
chunks.push(currentChunk);
|
|
511
|
+
}
|
|
512
|
+
return chunks;
|
|
513
|
+
}
|
|
478
514
|
async uploadData() {
|
|
479
515
|
await this.uploadArtifacts();
|
|
480
516
|
this.calculateStats();
|
|
@@ -495,7 +531,7 @@ class XmlReader {
|
|
|
495
531
|
};
|
|
496
532
|
return Promise.all(this.pipes.map(p => p.finishRun(finishData)));
|
|
497
533
|
}
|
|
498
|
-
const testChunks =
|
|
534
|
+
const testChunks = this.#splitTestsIntoChunks(this.tests);
|
|
499
535
|
const totalChunks = testChunks.length;
|
|
500
536
|
const totalTests = this.tests.length;
|
|
501
537
|
debug(`Split ${totalTests} tests into ${totalChunks} chunks (max 1MB per chunk)`);
|
package/package.json
CHANGED
package/src/bin/cli.js
CHANGED
|
@@ -6,7 +6,6 @@ import { glob } from 'glob';
|
|
|
6
6
|
import createDebugMessages from 'debug';
|
|
7
7
|
import TestomatClient from '../client.js';
|
|
8
8
|
import XmlReader from '../xmlReader.js';
|
|
9
|
-
import AllureReader from '../allureReader.js';
|
|
10
9
|
import { APP_PREFIX, STATUS, DEBUG_FILE, BATCH_MODE } from '../constants.js';
|
|
11
10
|
import { cleanLatestRunId, getPackageVersion, applyFilter } from '../utils/utils.js';
|
|
12
11
|
import { config } from '../config.js';
|
|
@@ -352,40 +351,6 @@ program
|
|
|
352
351
|
if (timeoutTimer) clearTimeout(timeoutTimer);
|
|
353
352
|
});
|
|
354
353
|
|
|
355
|
-
program
|
|
356
|
-
.command('allure')
|
|
357
|
-
.description('Parse Allure result files and upload to Testomat.io')
|
|
358
|
-
.argument('<pattern>', 'Allure result directory pattern')
|
|
359
|
-
.option('-d, --dir <dir>', 'Project directory')
|
|
360
|
-
.option('--timelimit <time>', 'default time limit in seconds to kill a stuck process')
|
|
361
|
-
.option('--with-package', 'Keep full package path in file names (default: strip package prefix)')
|
|
362
|
-
.action(async (pattern, opts) => {
|
|
363
|
-
const runReader = new AllureReader({ withPackage: opts.withPackage });
|
|
364
|
-
|
|
365
|
-
let timeoutTimer;
|
|
366
|
-
if (opts.timelimit) {
|
|
367
|
-
timeoutTimer = setTimeout(
|
|
368
|
-
() => {
|
|
369
|
-
console.log(
|
|
370
|
-
`⚠️ Reached timeout of ${opts.timelimit}s. Exiting... (Exit code is 0 to not fail the pipeline)`,
|
|
371
|
-
);
|
|
372
|
-
process.exit(0);
|
|
373
|
-
},
|
|
374
|
-
parseInt(opts.timelimit, 10) * 1000,
|
|
375
|
-
);
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
try {
|
|
379
|
-
await runReader.parse(pattern);
|
|
380
|
-
await runReader.createRun();
|
|
381
|
-
await runReader.uploadData();
|
|
382
|
-
} catch (err) {
|
|
383
|
-
console.log(APP_PREFIX, 'Error uploading Allure results:', err);
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
if (timeoutTimer) clearTimeout(timeoutTimer);
|
|
387
|
-
});
|
|
388
|
-
|
|
389
354
|
program
|
|
390
355
|
.command('upload-artifacts')
|
|
391
356
|
.description('Upload artifacts to Testomat.io')
|
|
@@ -4,7 +4,6 @@ import JavaAdapter from './java.js';
|
|
|
4
4
|
import PythonAdapter from './python.js';
|
|
5
5
|
import RubyAdapter from './ruby.js';
|
|
6
6
|
import CSharpAdapter from './csharp.js';
|
|
7
|
-
import KotlinAdapter from './kotlin.js';
|
|
8
7
|
|
|
9
8
|
function AdapterFactory(lang, opts) {
|
|
10
9
|
if (lang === 'java') {
|
|
@@ -22,9 +21,6 @@ function AdapterFactory(lang, opts) {
|
|
|
22
21
|
if (lang === 'c#' || lang === 'csharp') {
|
|
23
22
|
return new CSharpAdapter(opts);
|
|
24
23
|
}
|
|
25
|
-
if (lang === 'kotlin') {
|
|
26
|
-
return new KotlinAdapter(opts);
|
|
27
|
-
}
|
|
28
24
|
|
|
29
25
|
return new Adapter(opts);
|
|
30
26
|
}
|
package/src/utils/pipe_utils.js
CHANGED
|
@@ -161,53 +161,6 @@ function parsePipeOptions(optionsStr) {
|
|
|
161
161
|
return options;
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
-
/**
|
|
165
|
-
* Calculate the approximate size of data in bytes (JSON stringified, UTF-8 encoded length).
|
|
166
|
-
* @param {Object} data - Data to measure
|
|
167
|
-
* @returns {number} Size in bytes
|
|
168
|
-
*/
|
|
169
|
-
function getObjectSize(data) {
|
|
170
|
-
const body = JSON.stringify(data);
|
|
171
|
-
return new TextEncoder().encode(body).length;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
/**
|
|
175
|
-
* Split a tests array into chunks bounded by serialized size.
|
|
176
|
-
* Used by the XML and Allure readers so both upload tests with identical batching:
|
|
177
|
-
* each chunk becomes a single batch request (manual batch mode), which keeps requests
|
|
178
|
-
* under the size limit and guarantees every test is sent exactly once.
|
|
179
|
-
*
|
|
180
|
-
* @param {Array} tests - Array of tests to split
|
|
181
|
-
* @param {number} [maxSizeBytes=1048576] - Maximum serialized size per chunk (default 1MB)
|
|
182
|
-
* @returns {Array<Array>} Array of test chunks
|
|
183
|
-
*/
|
|
184
|
-
function splitTestsIntoChunks(tests, maxSizeBytes = 1 * 1024 * 1024) {
|
|
185
|
-
const chunks = [];
|
|
186
|
-
let currentChunk = [];
|
|
187
|
-
let currentChunkSize = 0;
|
|
188
|
-
|
|
189
|
-
for (const test of tests) {
|
|
190
|
-
const testSize = getObjectSize(test);
|
|
191
|
-
|
|
192
|
-
const wouldExceedSize = currentChunkSize + testSize > maxSizeBytes;
|
|
193
|
-
|
|
194
|
-
if (wouldExceedSize && currentChunk.length > 0) {
|
|
195
|
-
chunks.push(currentChunk);
|
|
196
|
-
currentChunk = [];
|
|
197
|
-
currentChunkSize = 0;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
currentChunk.push(test);
|
|
201
|
-
currentChunkSize += testSize;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
if (currentChunk.length > 0) {
|
|
205
|
-
chunks.push(currentChunk);
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
return chunks;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
164
|
/**
|
|
212
165
|
* Format a list of test IDs for `--filter-list` machine-readable output.
|
|
213
166
|
* Used when the CLI `--format` option is passed,
|
|
@@ -237,6 +190,4 @@ export {
|
|
|
237
190
|
fullName,
|
|
238
191
|
parsePipeOptions,
|
|
239
192
|
formatFilterListIds,
|
|
240
|
-
getObjectSize,
|
|
241
|
-
splitTestsIntoChunks,
|
|
242
193
|
};
|
package/src/utils/utils.js
CHANGED
|
@@ -289,11 +289,6 @@ const fetchSourceCode = (contents, opts = {}) => {
|
|
|
289
289
|
if (lineIndex === -1) lineIndex = lines.findIndex(l => l.includes(`@DisplayName("${title}`));
|
|
290
290
|
if (lineIndex === -1) lineIndex = lines.findIndex(l => l.includes(`public void ${title}`));
|
|
291
291
|
if (lineIndex === -1) lineIndex = lines.findIndex(l => l.includes(`${title}(`));
|
|
292
|
-
} else if (opts.lang === 'kotlin') {
|
|
293
|
-
lineIndex = lines.findIndex(l => l.includes(`fun test${title}`));
|
|
294
|
-
if (lineIndex === -1) lineIndex = lines.findIndex(l => l.includes(`@DisplayName("${title}`));
|
|
295
|
-
if (lineIndex === -1) lineIndex = lines.findIndex(l => l.includes(`fun ${title}`));
|
|
296
|
-
if (lineIndex === -1) lineIndex = lines.findIndex(l => l.includes(`${title}(`));
|
|
297
292
|
} else if (opts.lang === 'csharp') {
|
|
298
293
|
// Find the method declaration line
|
|
299
294
|
let methodLineIndex = lines.findIndex(l => l.includes(`public void ${title}(`));
|
package/src/xmlReader.js
CHANGED
|
@@ -18,7 +18,6 @@ import {
|
|
|
18
18
|
transformEnvVarToBoolean,
|
|
19
19
|
} from './utils/utils.js';
|
|
20
20
|
import { pipesFactory } from './pipe/index.js';
|
|
21
|
-
import { splitTestsIntoChunks } from './utils/pipe_utils.js';
|
|
22
21
|
import adapterFactory from './junit-adapter/index.js';
|
|
23
22
|
import { config } from './config.js';
|
|
24
23
|
import { S3Uploader } from './uploader.js';
|
|
@@ -554,6 +553,52 @@ class XmlReader {
|
|
|
554
553
|
return run;
|
|
555
554
|
}
|
|
556
555
|
|
|
556
|
+
/**
|
|
557
|
+
* Calculate the approximate size of data in bytes (JSON stringified length)
|
|
558
|
+
* @param {Object} data - Data to measure
|
|
559
|
+
* @returns {number} Size in bytes
|
|
560
|
+
*/
|
|
561
|
+
#getObjectSize(data) {
|
|
562
|
+
const body = JSON.stringify(data);
|
|
563
|
+
return new TextEncoder().encode(body).length;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
/**
|
|
567
|
+
* Split tests array into chunks based on data size
|
|
568
|
+
* @param {Array} tests - Array of tests to split
|
|
569
|
+
* @returns {Array<Array>} Array of test chunks
|
|
570
|
+
*/
|
|
571
|
+
#splitTestsIntoChunks(tests) {
|
|
572
|
+
const maxSizeBytes = 1 * 1024 * 1024;
|
|
573
|
+
|
|
574
|
+
const chunks = [];
|
|
575
|
+
let currentChunk = [];
|
|
576
|
+
let currentChunkSize = 0;
|
|
577
|
+
|
|
578
|
+
for (const test of tests) {
|
|
579
|
+
const testSize = this.#getObjectSize(test);
|
|
580
|
+
|
|
581
|
+
const wouldExceedSize = currentChunkSize + testSize > maxSizeBytes;
|
|
582
|
+
|
|
583
|
+
if (wouldExceedSize) {
|
|
584
|
+
if (currentChunk.length > 0) {
|
|
585
|
+
chunks.push(currentChunk);
|
|
586
|
+
}
|
|
587
|
+
currentChunk = [];
|
|
588
|
+
currentChunkSize = 0;
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
currentChunk.push(test);
|
|
592
|
+
currentChunkSize += testSize;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
if (currentChunk.length > 0) {
|
|
596
|
+
chunks.push(currentChunk);
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
return chunks;
|
|
600
|
+
}
|
|
601
|
+
|
|
557
602
|
async uploadData() {
|
|
558
603
|
await this.uploadArtifacts();
|
|
559
604
|
this.calculateStats();
|
|
@@ -578,7 +623,7 @@ class XmlReader {
|
|
|
578
623
|
return Promise.all(this.pipes.map(p => p.finishRun(finishData)));
|
|
579
624
|
}
|
|
580
625
|
|
|
581
|
-
const testChunks = splitTestsIntoChunks(this.tests);
|
|
626
|
+
const testChunks = this.#splitTestsIntoChunks(this.tests);
|
|
582
627
|
|
|
583
628
|
const totalChunks = testChunks.length;
|
|
584
629
|
const totalTests = this.tests.length;
|
package/lib/allureReader.d.ts
DELETED
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
export default AllureReader;
|
|
2
|
-
declare class AllureReader {
|
|
3
|
-
constructor(opts?: {});
|
|
4
|
-
requestParams: {
|
|
5
|
-
apiKey: any;
|
|
6
|
-
url: any;
|
|
7
|
-
title: string;
|
|
8
|
-
env: string;
|
|
9
|
-
group_title: string;
|
|
10
|
-
batchMode: "manual";
|
|
11
|
-
};
|
|
12
|
-
runId: any;
|
|
13
|
-
opts: {};
|
|
14
|
-
withPackage: any;
|
|
15
|
-
store: {};
|
|
16
|
-
pipesPromise: Promise<any[]>;
|
|
17
|
-
_tests: any[];
|
|
18
|
-
stats: {};
|
|
19
|
-
suites: {};
|
|
20
|
-
uploader: S3Uploader;
|
|
21
|
-
version: any;
|
|
22
|
-
set tests(value: any[]);
|
|
23
|
-
get tests(): any[];
|
|
24
|
-
createRun(): Promise<any[]>;
|
|
25
|
-
pipes: any;
|
|
26
|
-
parse(resultsPattern: any): {};
|
|
27
|
-
parseContainerFiles(containerFiles: any): void;
|
|
28
|
-
processAllureResult(result: any, resultsDir: any): {
|
|
29
|
-
rid: any;
|
|
30
|
-
title: any;
|
|
31
|
-
status: any;
|
|
32
|
-
suite_title: any;
|
|
33
|
-
file: string;
|
|
34
|
-
run_time: number;
|
|
35
|
-
steps: any;
|
|
36
|
-
message: any;
|
|
37
|
-
stack: any;
|
|
38
|
-
meta: {};
|
|
39
|
-
links: {
|
|
40
|
-
label: string;
|
|
41
|
-
}[];
|
|
42
|
-
artifacts: any[];
|
|
43
|
-
create: boolean;
|
|
44
|
-
overwrite: boolean;
|
|
45
|
-
};
|
|
46
|
-
mapStatus(status: any): any;
|
|
47
|
-
/**
|
|
48
|
-
* Map an Allure step status to the Testomat.io Step status enum
|
|
49
|
-
* (`passed | failed | none | custom`, see testomat-api-definition.yml).
|
|
50
|
-
*
|
|
51
|
-
* Allure marks a step `broken` when it threw an unexpected error — that is a
|
|
52
|
-
* failure for reporting purposes, matching how `mapStatus` treats tests.
|
|
53
|
-
* `skipped` and anything unknown/absent become `none` (the neutral value),
|
|
54
|
-
* since the step enum has no `skipped`.
|
|
55
|
-
*
|
|
56
|
-
* @param {string} status - Allure step status
|
|
57
|
-
* @returns {'passed'|'failed'|'none'} Testomat.io step status
|
|
58
|
-
*/
|
|
59
|
-
mapStepStatus(status: string): "passed" | "failed" | "none";
|
|
60
|
-
extractSuiteTitle(result: any): any;
|
|
61
|
-
stripNamespace(suiteName: any): any;
|
|
62
|
-
extractFile(result: any): string;
|
|
63
|
-
getFileExtension(result: any): any;
|
|
64
|
-
extractMeta(result: any): {};
|
|
65
|
-
extractLinks(result: any): {
|
|
66
|
-
label: string;
|
|
67
|
-
}[];
|
|
68
|
-
/**
|
|
69
|
-
* Extract a Testomat.io test id from Allure links so reported tests match
|
|
70
|
-
* existing cases instead of creating duplicates.
|
|
71
|
-
*
|
|
72
|
-
* Allure's `@TmsLink("T1a2b3c4d")` produces a link with `type: "tms"`. Some exporters
|
|
73
|
-
* omit the type but still point the link URL at a Testomat.io test page; both are
|
|
74
|
-
* accepted. The link `name` is used as the id (falling back to the last URL segment).
|
|
75
|
-
*
|
|
76
|
-
* @param {object} result - Parsed Allure result JSON
|
|
77
|
-
* @returns {string|null} Normalized test id, or null when no usable link exists
|
|
78
|
-
*/
|
|
79
|
-
extractTestId(result: object): string | null;
|
|
80
|
-
/**
|
|
81
|
-
* Normalize a value into a Testomat.io test id.
|
|
82
|
-
*
|
|
83
|
-
* Testomat.io test ids are exactly **8 word characters**. The value may arrive bare
|
|
84
|
-
* (`1a2b3c4d`), or carrying the `T` / `@T` markers Testomat uses in code and titles
|
|
85
|
-
* (`T1a2b3c4d`, `@T1a2b3c4d`). The markers are removed only when doing so still leaves
|
|
86
|
-
* a valid 8-char id, so a real id that happens to start with `T` is preserved.
|
|
87
|
-
*
|
|
88
|
-
* Anything that does not resolve to a valid 8-char id — a numeric Allure TestOps id
|
|
89
|
-
* like `12345`, a JIRA key, a 6-digit TMS number — is rejected (returns null) so we
|
|
90
|
-
* never send an unmatchable id that would create duplicates.
|
|
91
|
-
*
|
|
92
|
-
* @param {string|number|null|undefined} value
|
|
93
|
-
* @returns {string|null} The bare 8-char id, or null when the value is not a valid id
|
|
94
|
-
*/
|
|
95
|
-
normalizeTestId(value: string | number | null | undefined): string | null;
|
|
96
|
-
convertSteps(steps: any, depth?: number): any;
|
|
97
|
-
/**
|
|
98
|
-
* Build the `error` payload for a failed step from its Allure `statusDetails`.
|
|
99
|
-
*
|
|
100
|
-
* Allure stores the failure message and stack trace (which includes the failing
|
|
101
|
-
* source line) in `statusDetails` on the step itself. We only surface it for
|
|
102
|
-
* failed/broken steps — passing or skipped steps carry no error. Returns null
|
|
103
|
-
* when there is no usable failure information so the field is omitted entirely.
|
|
104
|
-
*
|
|
105
|
-
* @param {object} step - Allure step
|
|
106
|
-
* @returns {{message: string, stack: string}|null}
|
|
107
|
-
*/
|
|
108
|
-
extractStepError(step: object): {
|
|
109
|
-
message: string;
|
|
110
|
-
stack: string;
|
|
111
|
-
} | null;
|
|
112
|
-
calculateRunTime(item: any): number;
|
|
113
|
-
convertParameters(parameters: any): {};
|
|
114
|
-
combineRetryAttempts(attempts: any): any;
|
|
115
|
-
calculateStats(): {};
|
|
116
|
-
fetchSourceCode(): void;
|
|
117
|
-
getLanguage(): any;
|
|
118
|
-
uploadArtifacts(): Promise<void>;
|
|
119
|
-
uploadData(): Promise<any[]>;
|
|
120
|
-
}
|
|
121
|
-
import { S3Uploader } from './uploader.js';
|