@testomatio/reporter 2.9.1-beta.1-allure-chunking → 2.9.1-beta.3-allure-steps
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/allureReader.d.ts +41 -0
- package/lib/allureReader.js +82 -1
- package/package.json +1 -1
- package/src/allureReader.js +86 -1
package/lib/allureReader.d.ts
CHANGED
|
@@ -44,6 +44,19 @@ declare class AllureReader {
|
|
|
44
44
|
overwrite: boolean;
|
|
45
45
|
};
|
|
46
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";
|
|
47
60
|
extractSuiteTitle(result: any): any;
|
|
48
61
|
stripNamespace(suiteName: any): any;
|
|
49
62
|
extractFile(result: any): string;
|
|
@@ -52,6 +65,34 @@ declare class AllureReader {
|
|
|
52
65
|
extractLinks(result: any): {
|
|
53
66
|
label: string;
|
|
54
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;
|
|
55
96
|
convertSteps(steps: any, depth?: number): any;
|
|
56
97
|
calculateRunTime(item: any): number;
|
|
57
98
|
convertParameters(parameters: any): {};
|
package/lib/allureReader.js
CHANGED
|
@@ -169,6 +169,12 @@ class AllureReader {
|
|
|
169
169
|
create: true,
|
|
170
170
|
overwrite: true,
|
|
171
171
|
};
|
|
172
|
+
// Use the @TmsLink / Testomat.io link as the test id so reported tests MATCH
|
|
173
|
+
// existing cases instead of creating duplicates on every run.
|
|
174
|
+
const testId = this.extractTestId(result);
|
|
175
|
+
if (testId) {
|
|
176
|
+
test.test_id = testId;
|
|
177
|
+
}
|
|
172
178
|
// Add description if present
|
|
173
179
|
if (result.description) {
|
|
174
180
|
test.description = result.description;
|
|
@@ -203,6 +209,28 @@ class AllureReader {
|
|
|
203
209
|
};
|
|
204
210
|
return statusMap[status] || 'failed';
|
|
205
211
|
}
|
|
212
|
+
/**
|
|
213
|
+
* Map an Allure step status to the Testomat.io Step status enum
|
|
214
|
+
* (`passed | failed | none | custom`, see testomat-api-definition.yml).
|
|
215
|
+
*
|
|
216
|
+
* Allure marks a step `broken` when it threw an unexpected error — that is a
|
|
217
|
+
* failure for reporting purposes, matching how `mapStatus` treats tests.
|
|
218
|
+
* `skipped` and anything unknown/absent become `none` (the neutral value),
|
|
219
|
+
* since the step enum has no `skipped`.
|
|
220
|
+
*
|
|
221
|
+
* @param {string} status - Allure step status
|
|
222
|
+
* @returns {'passed'|'failed'|'none'} Testomat.io step status
|
|
223
|
+
*/
|
|
224
|
+
mapStepStatus(status) {
|
|
225
|
+
const statusMap = {
|
|
226
|
+
passed: 'passed',
|
|
227
|
+
failed: 'failed',
|
|
228
|
+
broken: 'failed',
|
|
229
|
+
skipped: 'none',
|
|
230
|
+
pending: 'none',
|
|
231
|
+
};
|
|
232
|
+
return statusMap[status] || 'none';
|
|
233
|
+
}
|
|
206
234
|
extractSuiteTitle(result) {
|
|
207
235
|
const labels = result.labels || [];
|
|
208
236
|
// Only use suite label for suite_title
|
|
@@ -296,6 +324,56 @@ class AllureReader {
|
|
|
296
324
|
}
|
|
297
325
|
return links.length > 0 ? links : undefined;
|
|
298
326
|
}
|
|
327
|
+
/**
|
|
328
|
+
* Extract a Testomat.io test id from Allure links so reported tests match
|
|
329
|
+
* existing cases instead of creating duplicates.
|
|
330
|
+
*
|
|
331
|
+
* Allure's `@TmsLink("T1a2b3c4d")` produces a link with `type: "tms"`. Some exporters
|
|
332
|
+
* omit the type but still point the link URL at a Testomat.io test page; both are
|
|
333
|
+
* accepted. The link `name` is used as the id (falling back to the last URL segment).
|
|
334
|
+
*
|
|
335
|
+
* @param {object} result - Parsed Allure result JSON
|
|
336
|
+
* @returns {string|null} Normalized test id, or null when no usable link exists
|
|
337
|
+
*/
|
|
338
|
+
extractTestId(result) {
|
|
339
|
+
const links = result.links || [];
|
|
340
|
+
if (!links.length)
|
|
341
|
+
return null;
|
|
342
|
+
const isTmsLink = l => typeof l?.type === 'string' && l.type.toLowerCase() === 'tms';
|
|
343
|
+
const isTestomatioLink = l => typeof l?.url === 'string' && /testomat\.io\/[^\s]*\/test\//i.test(l.url);
|
|
344
|
+
const link = links.find(isTmsLink) || links.find(isTestomatioLink);
|
|
345
|
+
if (!link)
|
|
346
|
+
return null;
|
|
347
|
+
// Prefer the explicit link name; fall back to the id segment of a Testomat.io URL.
|
|
348
|
+
let id = this.normalizeTestId(link.name);
|
|
349
|
+
if (!id && typeof link.url === 'string') {
|
|
350
|
+
const fromUrl = link.url.match(/\/test\/([\w\d]{8})(?=$|[/?#])/i);
|
|
351
|
+
if (fromUrl)
|
|
352
|
+
id = fromUrl[1];
|
|
353
|
+
}
|
|
354
|
+
return id;
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Normalize a value into a Testomat.io test id.
|
|
358
|
+
*
|
|
359
|
+
* Testomat.io test ids are exactly **8 word characters**. The value may arrive bare
|
|
360
|
+
* (`1a2b3c4d`), or carrying the `T` / `@T` markers Testomat uses in code and titles
|
|
361
|
+
* (`T1a2b3c4d`, `@T1a2b3c4d`). The markers are removed only when doing so still leaves
|
|
362
|
+
* a valid 8-char id, so a real id that happens to start with `T` is preserved.
|
|
363
|
+
*
|
|
364
|
+
* Anything that does not resolve to a valid 8-char id — a numeric Allure TestOps id
|
|
365
|
+
* like `12345`, a JIRA key, a 6-digit TMS number — is rejected (returns null) so we
|
|
366
|
+
* never send an unmatchable id that would create duplicates.
|
|
367
|
+
*
|
|
368
|
+
* @param {string|number|null|undefined} value
|
|
369
|
+
* @returns {string|null} The bare 8-char id, or null when the value is not a valid id
|
|
370
|
+
*/
|
|
371
|
+
normalizeTestId(value) {
|
|
372
|
+
if (value === null || value === undefined)
|
|
373
|
+
return null;
|
|
374
|
+
const match = value.toString().trim().match(/^@?T?([\w\d]{8})$/);
|
|
375
|
+
return match ? match[1] : null;
|
|
376
|
+
}
|
|
299
377
|
convertSteps(steps, depth = 0) {
|
|
300
378
|
if (depth >= 10)
|
|
301
379
|
return null;
|
|
@@ -304,6 +382,7 @@ class AllureReader {
|
|
|
304
382
|
const convertedStep = {
|
|
305
383
|
category: 'user',
|
|
306
384
|
title: step.name || step.title || 'Unknown step',
|
|
385
|
+
status: this.mapStepStatus(step.status),
|
|
307
386
|
duration: this.calculateRunTime(step),
|
|
308
387
|
steps: this.convertSteps(step.steps || [], depth + 1),
|
|
309
388
|
};
|
|
@@ -413,8 +492,10 @@ class AllureReader {
|
|
|
413
492
|
t.code = code;
|
|
414
493
|
debug('Fetched code for test %s', t.title);
|
|
415
494
|
}
|
|
495
|
+
// Don't override an id already taken from a @TmsLink — the link is the
|
|
496
|
+
// explicit, source-independent match key the client maintains.
|
|
416
497
|
const testId = (0, utils_js_1.fetchIdFromCode)(contents, { lang: this.getLanguage() });
|
|
417
|
-
if (testId) {
|
|
498
|
+
if (testId && !t.test_id) {
|
|
418
499
|
t.test_id = testId;
|
|
419
500
|
debug('Fetched test id %s for test %s', testId, t.title);
|
|
420
501
|
}
|
package/package.json
CHANGED
package/src/allureReader.js
CHANGED
|
@@ -193,6 +193,13 @@ class AllureReader {
|
|
|
193
193
|
overwrite: true,
|
|
194
194
|
};
|
|
195
195
|
|
|
196
|
+
// Use the @TmsLink / Testomat.io link as the test id so reported tests MATCH
|
|
197
|
+
// existing cases instead of creating duplicates on every run.
|
|
198
|
+
const testId = this.extractTestId(result);
|
|
199
|
+
if (testId) {
|
|
200
|
+
test.test_id = testId;
|
|
201
|
+
}
|
|
202
|
+
|
|
196
203
|
// Add description if present
|
|
197
204
|
if (result.description) {
|
|
198
205
|
test.description = result.description;
|
|
@@ -233,6 +240,29 @@ class AllureReader {
|
|
|
233
240
|
return statusMap[status] || 'failed';
|
|
234
241
|
}
|
|
235
242
|
|
|
243
|
+
/**
|
|
244
|
+
* Map an Allure step status to the Testomat.io Step status enum
|
|
245
|
+
* (`passed | failed | none | custom`, see testomat-api-definition.yml).
|
|
246
|
+
*
|
|
247
|
+
* Allure marks a step `broken` when it threw an unexpected error — that is a
|
|
248
|
+
* failure for reporting purposes, matching how `mapStatus` treats tests.
|
|
249
|
+
* `skipped` and anything unknown/absent become `none` (the neutral value),
|
|
250
|
+
* since the step enum has no `skipped`.
|
|
251
|
+
*
|
|
252
|
+
* @param {string} status - Allure step status
|
|
253
|
+
* @returns {'passed'|'failed'|'none'} Testomat.io step status
|
|
254
|
+
*/
|
|
255
|
+
mapStepStatus(status) {
|
|
256
|
+
const statusMap = {
|
|
257
|
+
passed: 'passed',
|
|
258
|
+
failed: 'failed',
|
|
259
|
+
broken: 'failed',
|
|
260
|
+
skipped: 'none',
|
|
261
|
+
pending: 'none',
|
|
262
|
+
};
|
|
263
|
+
return statusMap[status] || 'none';
|
|
264
|
+
}
|
|
265
|
+
|
|
236
266
|
extractSuiteTitle(result) {
|
|
237
267
|
const labels = result.labels || [];
|
|
238
268
|
|
|
@@ -346,6 +376,58 @@ class AllureReader {
|
|
|
346
376
|
return links.length > 0 ? links : undefined;
|
|
347
377
|
}
|
|
348
378
|
|
|
379
|
+
/**
|
|
380
|
+
* Extract a Testomat.io test id from Allure links so reported tests match
|
|
381
|
+
* existing cases instead of creating duplicates.
|
|
382
|
+
*
|
|
383
|
+
* Allure's `@TmsLink("T1a2b3c4d")` produces a link with `type: "tms"`. Some exporters
|
|
384
|
+
* omit the type but still point the link URL at a Testomat.io test page; both are
|
|
385
|
+
* accepted. The link `name` is used as the id (falling back to the last URL segment).
|
|
386
|
+
*
|
|
387
|
+
* @param {object} result - Parsed Allure result JSON
|
|
388
|
+
* @returns {string|null} Normalized test id, or null when no usable link exists
|
|
389
|
+
*/
|
|
390
|
+
extractTestId(result) {
|
|
391
|
+
const links = result.links || [];
|
|
392
|
+
if (!links.length) return null;
|
|
393
|
+
|
|
394
|
+
const isTmsLink = l => typeof l?.type === 'string' && l.type.toLowerCase() === 'tms';
|
|
395
|
+
const isTestomatioLink = l => typeof l?.url === 'string' && /testomat\.io\/[^\s]*\/test\//i.test(l.url);
|
|
396
|
+
|
|
397
|
+
const link = links.find(isTmsLink) || links.find(isTestomatioLink);
|
|
398
|
+
if (!link) return null;
|
|
399
|
+
|
|
400
|
+
// Prefer the explicit link name; fall back to the id segment of a Testomat.io URL.
|
|
401
|
+
let id = this.normalizeTestId(link.name);
|
|
402
|
+
if (!id && typeof link.url === 'string') {
|
|
403
|
+
const fromUrl = link.url.match(/\/test\/([\w\d]{8})(?=$|[/?#])/i);
|
|
404
|
+
if (fromUrl) id = fromUrl[1];
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
return id;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* Normalize a value into a Testomat.io test id.
|
|
412
|
+
*
|
|
413
|
+
* Testomat.io test ids are exactly **8 word characters**. The value may arrive bare
|
|
414
|
+
* (`1a2b3c4d`), or carrying the `T` / `@T` markers Testomat uses in code and titles
|
|
415
|
+
* (`T1a2b3c4d`, `@T1a2b3c4d`). The markers are removed only when doing so still leaves
|
|
416
|
+
* a valid 8-char id, so a real id that happens to start with `T` is preserved.
|
|
417
|
+
*
|
|
418
|
+
* Anything that does not resolve to a valid 8-char id — a numeric Allure TestOps id
|
|
419
|
+
* like `12345`, a JIRA key, a 6-digit TMS number — is rejected (returns null) so we
|
|
420
|
+
* never send an unmatchable id that would create duplicates.
|
|
421
|
+
*
|
|
422
|
+
* @param {string|number|null|undefined} value
|
|
423
|
+
* @returns {string|null} The bare 8-char id, or null when the value is not a valid id
|
|
424
|
+
*/
|
|
425
|
+
normalizeTestId(value) {
|
|
426
|
+
if (value === null || value === undefined) return null;
|
|
427
|
+
const match = value.toString().trim().match(/^@?T?([\w\d]{8})$/);
|
|
428
|
+
return match ? match[1] : null;
|
|
429
|
+
}
|
|
430
|
+
|
|
349
431
|
convertSteps(steps, depth = 0) {
|
|
350
432
|
if (depth >= 10) return null;
|
|
351
433
|
|
|
@@ -354,6 +436,7 @@ class AllureReader {
|
|
|
354
436
|
const convertedStep = {
|
|
355
437
|
category: 'user',
|
|
356
438
|
title: step.name || step.title || 'Unknown step',
|
|
439
|
+
status: this.mapStepStatus(step.status),
|
|
357
440
|
duration: this.calculateRunTime(step),
|
|
358
441
|
steps: this.convertSteps(step.steps || [], depth + 1),
|
|
359
442
|
};
|
|
@@ -482,8 +565,10 @@ class AllureReader {
|
|
|
482
565
|
debug('Fetched code for test %s', t.title);
|
|
483
566
|
}
|
|
484
567
|
|
|
568
|
+
// Don't override an id already taken from a @TmsLink — the link is the
|
|
569
|
+
// explicit, source-independent match key the client maintains.
|
|
485
570
|
const testId = fetchIdFromCode(contents, { lang: this.getLanguage() });
|
|
486
|
-
if (testId) {
|
|
571
|
+
if (testId && !t.test_id) {
|
|
487
572
|
t.test_id = testId;
|
|
488
573
|
debug('Fetched test id %s for test %s', testId, t.title);
|
|
489
574
|
}
|