@testomatio/reporter 2.7.3-beta.1-vitest → 2.7.3-beta.3.allure

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 CHANGED
@@ -69,6 +69,7 @@ yarn add @testomatio/reporter --dev
69
69
  | [TestCafe](./docs/frameworks.md#testcafe) | [Detox](./docs/frameworks.md#detox) | [Codeception](https://github.com/testomatio/php-reporter) |
70
70
  | [Newman (Postman)](./docs/frameworks.md#newman) | [JUnit](./docs/junit.md#junit) | [NUnit](./docs/junit.md#nunit) |
71
71
  | [PyTest](./docs/junit.md#pytest) | [PHPUnit](./docs/junit.md#phpunit) | [Protractor](./docs/frameworks.md#protractor) |
72
+ | [Allure](./docs/allure.md) | | |
72
73
 
73
74
  or **any [other via JUnit](./docs/junit.md)** report....
74
75
 
@@ -129,9 +130,10 @@ Bring this reporter on CI and never lose test results again!
129
130
  - [CSV](./docs/pipes/csv.md)
130
131
  - [HTML report](./docs/pipes/html.md)
131
132
  - [Bitbucket](./docs/pipes/bitbucket.md)
132
- - 🔗 [Linking Tests](./docs/linking-tests.md)
133
- - 📓 [JUnit](./docs/junit.md)
133
+ - 📓 [JUnit Reports](./docs/junit.md)
134
134
  - 🗄️ [Artifacts](./docs/artifacts.md)
135
+ - 🔬 [Allure Reports](./docs/allure.md)
136
+ - 🔗 [Linking Tests](./docs/linking-tests.md)
135
137
  - 🔂 [Workflows](./docs/workflows.md)
136
138
  - 🖊️ [Logger](./docs/logger.md)
137
139
  - 🪲 [Debug File Format](./docs/debug-file-format.md)
@@ -18,22 +18,15 @@ export type TestData = import("../../types/types.js").TestData;
18
18
  export class VitestReporter {
19
19
  constructor(config?: {});
20
20
  client: TestomatioClient;
21
- /** @type {(TestData & {status: string, _reportKey?: string | null})[]} tests */
21
+ /**
22
+ * @type {(TestData & {status: string})[]} tests
23
+ */
22
24
  tests: (TestData & {
23
25
  status: string;
24
- _reportKey?: string | null;
25
26
  })[];
26
27
  _finalized: boolean;
27
28
  _finalizing: boolean;
28
- _runStartedAtMs: number;
29
- _runStartedAtMicros: number;
30
- _reportedTestKeys: Set<any>;
31
- _liveQueue: Promise<void>;
32
29
  onInit(): void;
33
- /**
34
- * Vitest 3/4 callback fired when test run starts.
35
- */
36
- onTestRunStart(): void;
37
30
  /**
38
31
  * @param {VitestTestFile[] | undefined} files // array with results;
39
32
  * @param {unknown[] | undefined} errors // errors does not contain errors from tests; probably its testrunner errors
@@ -46,18 +39,6 @@ export class VitestReporter {
46
39
  * @param {unknown[] | undefined} errors
47
40
  */
48
41
  onTestRunEnd(testModules: Array<unknown> | undefined, errors: unknown[] | undefined): Promise<void>;
49
- /**
50
- * Vitest 4 callback fired when single test case is finished.
51
- *
52
- * @param {unknown} testCase
53
- */
54
- onTestCaseResult(testCase: unknown): Promise<void>;
55
- /**
56
- * Vitest 3 fallback callback with task updates.
57
- *
58
- * @param {unknown[] | undefined} packs
59
- */
60
- onTaskUpdate(packs: unknown[] | undefined): Promise<void>;
61
42
  #private;
62
43
  }
63
44
  import { Client as TestomatioClient } from '../client.js';
@@ -22,34 +22,19 @@ const debug = (0, debug_1.default)('@testomatio/reporter:adapter-jest');
22
22
  class VitestReporter {
23
23
  constructor(config = {}) {
24
24
  this.client = new client_js_1.Client({ apiKey: config?.apiKey });
25
- /** @type {(TestData & {status: string, _reportKey?: string | null})[]} tests */
25
+ /**
26
+ * @type {(TestData & {status: string})[]} tests
27
+ */
26
28
  this.tests = [];
27
29
  this._finalized = false;
28
30
  this._finalizing = false;
29
- this._runStartedAtMs = null;
30
- this._runStartedAtMicros = null;
31
- this._reportedTestKeys = new Set();
32
- this._liveQueue = Promise.resolve();
33
31
  }
34
32
  // on run start
35
33
  onInit() {
36
- const now = Date.now();
37
34
  this._finalized = false;
38
35
  this._finalizing = false;
39
- this._runStartedAtMs = now;
40
- this._runStartedAtMicros = now * 1000;
41
- this._reportedTestKeys = new Set();
42
- this._liveQueue = Promise.resolve();
43
36
  this.client.createRun();
44
37
  }
45
- /**
46
- * Vitest 3/4 callback fired when test run starts.
47
- */
48
- onTestRunStart() {
49
- const now = Date.now();
50
- this._runStartedAtMs = now;
51
- this._runStartedAtMicros = now * 1000;
52
- }
53
38
  /**
54
39
  * @param {VitestTestFile[] | undefined} files // array with results;
55
40
  * @param {unknown[] | undefined} errors // errors does not contain errors from tests; probably its testrunner errors
@@ -83,19 +68,12 @@ class VitestReporter {
83
68
  debug(this.tests.length, 'tests collected');
84
69
  // send tests to Testomat.io
85
70
  for (const test of this.tests) {
86
- if (test._reportKey && this._reportedTestKeys.has(test._reportKey))
87
- continue;
88
- if (test._reportKey)
89
- this._reportedTestKeys.add(test._reportKey);
90
71
  await this.client.addTestRun(test.status, test);
91
72
  }
92
- await this._liveQueue;
93
73
  console.log('finished');
94
74
  if (errors.length)
95
75
  console.error('Vitest adapter errors:', errors);
96
- const startedAtMs = this._runStartedAtMs || getEarliestTestStartMs(files) || Date.now();
97
- const duration = Math.max(0, (Date.now() - startedAtMs) / 1000);
98
- await this.client.updateRunStatus(getRunStatusFromResults(files), { duration });
76
+ await this.client.updateRunStatus(getRunStatusFromResults(files));
99
77
  this._finalized = true;
100
78
  }
101
79
  finally {
@@ -114,28 +92,6 @@ class VitestReporter {
114
92
  .filter(Boolean);
115
93
  await this.onFinished(files, errors);
116
94
  }
117
- /**
118
- * Vitest 4 callback fired when single test case is finished.
119
- *
120
- * @param {unknown} testCase
121
- */
122
- async onTestCaseResult(testCase) {
123
- await this.#reportLive(testCase);
124
- }
125
- /**
126
- * Vitest 3 fallback callback with task updates.
127
- *
128
- * @param {unknown[] | undefined} packs
129
- */
130
- async onTaskUpdate(packs) {
131
- if (!Array.isArray(packs) || !packs.length)
132
- return;
133
- for (const pack of packs) {
134
- const test = getTestFromTaskUpdatePack(pack);
135
- if (test)
136
- await this.#reportLive(test);
137
- }
138
- }
139
95
  /* non-used listeners
140
96
  onUserConsoleLog(log) {}
141
97
  onPathsCollected(paths) {} // paths array to files with tests
@@ -170,50 +126,25 @@ class VitestReporter {
170
126
  /**
171
127
  * Processes task and returns test data ready to be sent to Testomat.io
172
128
  *
173
- * @param {any} test
129
+ * @param {VitestTest} test
174
130
  *
175
- * @returns {TestData & {status: 'passed' | 'failed' | 'skipped', _reportKey?: string | null}}
131
+ * @returns {TestData & {status: 'passed' | 'failed' | 'skipped'}}
176
132
  */
177
133
  #getDataFromTest(test) {
178
- const normalized = normalizeVitestTest(test);
179
- const reportKey = getReportKey(test, normalized);
180
- const startMicros = typeof normalized.startTime === 'number'
181
- ? Math.floor(normalized.startTime * 1000)
182
- : this._runStartedAtMicros || undefined;
183
134
  return {
184
- _reportKey: reportKey,
185
- error: normalized.error,
186
- file: normalized.file,
187
- logs: normalized.logs,
188
- meta: normalized.meta,
135
+ error: test.result?.errors ? test.result.errors[0] : undefined,
136
+ file: test.file?.name || test.file?.filepath || '',
137
+ logs: test.logs ? transformLogsToString(test.logs) : '',
138
+ meta: test.meta,
189
139
  // @ts-ignore - STATUS values are string literals but type system sees them as string
190
- status: getTestStatus(normalized.state, normalized.mode),
191
- suite_title: normalized.suiteTitle,
192
- test_id: (0, utils_js_1.getTestomatIdFromTestTitle)(normalized.name),
193
- time: normalized.duration,
194
- timestamp: startMicros,
195
- title: normalized.name,
140
+ status: getTestStatus(test),
141
+ suite_title: test.suite?.name || test.file?.name || test.file?.filepath,
142
+ test_id: (0, utils_js_1.getTestomatIdFromTestTitle)(test.name),
143
+ time: test.result?.duration || 0,
144
+ title: test.name,
196
145
  // testomatio functions (artifacts, logs, steps, meta) are not supported
197
146
  };
198
147
  }
199
- /**
200
- * @param {unknown} testCase
201
- */
202
- async #reportLive(testCase) {
203
- if (this._finalized || this._finalizing)
204
- return;
205
- const normalized = normalizeVitestTest(testCase);
206
- if (!isLiveReportableState(normalized.state, normalized.mode))
207
- return;
208
- const data = this.#getDataFromTest(testCase);
209
- if (!data._reportKey || this._reportedTestKeys.has(data._reportKey))
210
- return;
211
- this._reportedTestKeys.add(data._reportKey);
212
- this._liveQueue = this._liveQueue
213
- .then(() => this.client.addTestRun(data.status, data))
214
- .catch(() => undefined);
215
- await this._liveQueue;
216
- }
217
148
  }
218
149
  exports.VitestReporter = VitestReporter;
219
150
  /**
@@ -228,15 +159,16 @@ function getRunStatusFromResults(files) {
228
159
  */
229
160
  let status = 'finished'; // default status (if no failed or passed tests)
230
161
  files.forEach(file => {
231
- getTasks(file).forEach(taskOrSuite => {
232
- if (isFailedState(taskOrSuite?.result?.state)) {
162
+ // search for failed tests
163
+ file.tasks.forEach(taskOrSuite => {
164
+ if (taskOrSuite.result?.state === 'fail') {
233
165
  status = 'failed'; // set status to failed if any test failed
234
166
  }
235
167
  });
236
168
  // if there are no failed tests > search for passed tests
237
169
  if (status !== 'failed') {
238
- getTasks(file).forEach(taskOrSuite => {
239
- if (isPassedState(taskOrSuite?.result?.state)) {
170
+ file.tasks.forEach(taskOrSuite => {
171
+ if (taskOrSuite.result?.state === 'pass') {
240
172
  status = 'passed'; // set status to passed if any test passed (and there are no failed tests)
241
173
  }
242
174
  });
@@ -247,18 +179,17 @@ function getRunStatusFromResults(files) {
247
179
  /**
248
180
  * Returns test status in Testomat.io format
249
181
  *
250
- * @param {string | undefined} state
251
- * @param {string | undefined} mode
182
+ * @param {VitestTest} test
252
183
  * @returns 'passed' | 'failed' | 'skipped'
253
184
  */
254
- function getTestStatus(state, mode) {
255
- if (isFailedState(state))
185
+ function getTestStatus(test) {
186
+ if (test.result?.state === 'fail')
256
187
  return constants_js_1.STATUS.FAILED;
257
- if (isPassedState(state))
188
+ if (test.result?.state === 'pass')
258
189
  return constants_js_1.STATUS.PASSED;
259
- if (isSkippedState(state) || (!state && mode === 'skip'))
190
+ if (test.result?.state === 'skip' || (!test.result && test.mode === 'skip'))
260
191
  return constants_js_1.STATUS.SKIPPED;
261
- console.error(picocolors_1.default.red('Unprocessed case for defining test status. Contact dev team. State:'), state);
192
+ console.error(picocolors_1.default.red('Unprocessed case for defining test status. Contact dev team. Test:'), test);
262
193
  return constants_js_1.STATUS.SKIPPED;
263
194
  }
264
195
  /**
@@ -290,165 +221,10 @@ function getTasks(node) {
290
221
  return node.tasks;
291
222
  if (Array.isArray(node.children))
292
223
  return node.children;
293
- if (node.children && typeof node.children[Symbol.iterator] === 'function')
294
- return Array.from(node.children);
295
224
  if (node.task)
296
225
  return [node.task];
297
226
  return [];
298
227
  }
299
- /**
300
- * @param {string | undefined} state
301
- * @returns {boolean}
302
- */
303
- function isFailedState(state) {
304
- return state === 'fail' || state === 'failed';
305
- }
306
- /**
307
- * @param {string | undefined} state
308
- * @returns {boolean}
309
- */
310
- function isPassedState(state) {
311
- return state === 'pass' || state === 'passed';
312
- }
313
- /**
314
- * @param {string | undefined} state
315
- * @returns {boolean}
316
- */
317
- function isSkippedState(state) {
318
- return state === 'skip' || state === 'skipped' || state === 'todo';
319
- }
320
- /**
321
- * Accept only completed test states for live upload to avoid reporting
322
- * intermediate task updates as skipped.
323
- *
324
- * @param {string | undefined} state
325
- * @param {string | undefined} mode
326
- * @returns {boolean}
327
- */
328
- function isLiveReportableState(state, mode) {
329
- if (isFailedState(state) || isPassedState(state) || isSkippedState(state))
330
- return true;
331
- if (!state && mode === 'skip')
332
- return true;
333
- return false;
334
- }
335
- /**
336
- * @param {VitestTestFile[] | undefined} files
337
- * @returns {number | null}
338
- */
339
- function getEarliestTestStartMs(files) {
340
- let earliest = null;
341
- const walk = node => {
342
- if (!node)
343
- return;
344
- const startTime = node?.result?.startTime;
345
- if (typeof startTime === 'number' && !Number.isNaN(startTime)) {
346
- if (earliest == null || startTime < earliest)
347
- earliest = startTime;
348
- }
349
- getTasks(node).forEach(walk);
350
- };
351
- (files || []).forEach(walk);
352
- return earliest;
353
- }
354
- /**
355
- * @param {any} test
356
- * @returns {{
357
- * name: string,
358
- * state: string | undefined,
359
- * mode: string | undefined,
360
- * duration: number,
361
- * startTime: number | undefined,
362
- * error: any,
363
- * file: string,
364
- * suiteTitle: string,
365
- * logs: string,
366
- * meta: any
367
- * }}
368
- */
369
- function normalizeVitestTest(test) {
370
- if (test && typeof test.result === 'function') {
371
- const result = test.result();
372
- const diagnostic = typeof test.diagnostic === 'function' ? test.diagnostic() : undefined;
373
- const state = result?.state;
374
- const duration = diagnostic?.duration || 0;
375
- const startTime = diagnostic?.startTime;
376
- const error = Array.isArray(result?.errors) ? result.errors[0] : undefined;
377
- const file = test.module?.relativeModuleId ||
378
- test.module?.moduleId ||
379
- test.task?.file?.name ||
380
- test.task?.file?.filepath ||
381
- '';
382
- const suiteTitle = (test.parent?.type === 'suite' ? test.parent?.name : null) ||
383
- test.task?.suite?.name ||
384
- test.task?.file?.name ||
385
- file;
386
- return {
387
- name: test.name || test.task?.name || '',
388
- state,
389
- mode: test.options?.mode || test.task?.mode,
390
- duration,
391
- startTime,
392
- error,
393
- file,
394
- suiteTitle,
395
- logs: '',
396
- meta: typeof test.meta === 'function' ? test.meta() : {},
397
- };
398
- }
399
- return {
400
- name: test?.name || '',
401
- state: test?.result?.state,
402
- mode: test?.mode,
403
- duration: test?.result?.duration || 0,
404
- startTime: test?.result?.startTime,
405
- error: test?.result?.errors ? test.result.errors[0] : undefined,
406
- file: test?.file?.name || test?.file?.filepath || '',
407
- suiteTitle: test?.suite?.name || test?.file?.name || test?.file?.filepath || '',
408
- logs: test?.logs ? transformLogsToString(test.logs) : '',
409
- meta: test?.meta,
410
- };
411
- }
412
- /**
413
- * @param {any} test
414
- * @param {{file: string, suiteTitle: string, name: string, startTime?: number}} normalized
415
- * @returns {string | null}
416
- */
417
- function getReportKey(test, normalized) {
418
- if (test?.id)
419
- return String(test.id);
420
- if (test?.task?.id)
421
- return String(test.task.id);
422
- if (!normalized?.name)
423
- return null;
424
- const loc = test?.location || test?.task?.location;
425
- const locationKey = loc ? `${loc.line || ''}:${loc.column || ''}` : '';
426
- const startKey = typeof normalized.startTime === 'number' && !Number.isNaN(normalized.startTime) ? String(normalized.startTime) : '';
427
- return `${normalized.file}::${normalized.suiteTitle}::${normalized.name}::${locationKey}::${startKey}`;
428
- }
429
- /**
430
- * Vitest can pass task updates as tuples. Try to extract a test-like object.
431
- *
432
- * @param {unknown} pack
433
- * @returns {any | null}
434
- */
435
- function getTestFromTaskUpdatePack(pack) {
436
- if (!pack)
437
- return null;
438
- if (Array.isArray(pack)) {
439
- if (pack[2]?.type === 'test')
440
- return pack[2];
441
- if (pack[1]?.type === 'test')
442
- return pack[1];
443
- if (pack[0]?.type === 'test')
444
- return pack[0];
445
- return null;
446
- }
447
- const objectPack = /** @type {any} */ (pack);
448
- if (typeof objectPack === 'object' && objectPack?.type === 'test')
449
- return objectPack;
450
- return null;
451
- }
452
228
  module.exports = VitestReporter;
453
229
 
454
230
  module.exports.VitestReporter = VitestReporter;
@@ -0,0 +1,65 @@
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
+ isBatchEnabled: boolean;
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
+ extractSuiteTitle(result: any): any;
48
+ stripNamespace(suiteName: any): any;
49
+ extractFile(result: any): string;
50
+ getFileExtension(result: any): any;
51
+ extractMeta(result: any): {};
52
+ extractLinks(result: any): {
53
+ label: string;
54
+ }[];
55
+ convertSteps(steps: any, depth?: number): any;
56
+ calculateRunTime(item: any): number;
57
+ convertParameters(parameters: any): {};
58
+ combineRetryAttempts(attempts: any): any;
59
+ calculateStats(): {};
60
+ fetchSourceCode(): void;
61
+ getLanguage(): any;
62
+ uploadArtifacts(): Promise<void>;
63
+ uploadData(): Promise<any[]>;
64
+ }
65
+ import { S3Uploader } from './uploader.js';