@testomatio/reporter 2.19.0-beta → 2.20.0

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 (54) hide show
  1. package/lib/adapter/codecept.js +1 -0
  2. package/lib/adapter/cucumber/current.js +1 -0
  3. package/lib/adapter/cypress-plugin/index.js +1 -0
  4. package/lib/adapter/e2e.d.ts +49 -0
  5. package/lib/adapter/e2e.js +250 -0
  6. package/lib/adapter/jasmine.js +1 -0
  7. package/lib/adapter/jest.js +1 -0
  8. package/lib/adapter/mocha.d.ts +4 -1
  9. package/lib/adapter/mocha.js +123 -122
  10. package/lib/adapter/nightwatch.js +1 -0
  11. package/lib/adapter/playwright.js +1 -0
  12. package/lib/adapter/vitest.js +1 -0
  13. package/lib/adapter/webdriver.js +1 -0
  14. package/lib/allureReader.d.ts +4 -1
  15. package/lib/allureReader.js +2 -1
  16. package/lib/bin/cli.js +32 -13
  17. package/lib/client.d.ts +1 -0
  18. package/lib/client.js +12 -3
  19. package/lib/data-storage.js +4 -3
  20. package/lib/pipe/bitbucket.js +5 -1
  21. package/lib/pipe/github.js +5 -1
  22. package/lib/pipe/gitlab.js +5 -1
  23. package/lib/pipe/testomatio.js +17 -1
  24. package/lib/replay.js +1 -0
  25. package/lib/uploader.d.ts +1 -0
  26. package/lib/uploader.js +21 -1
  27. package/lib/utils/pipe_utils.d.ts +32 -3
  28. package/lib/utils/pipe_utils.js +82 -4
  29. package/lib/xmlReader.js +2 -0
  30. package/package.json +7 -2
  31. package/src/adapter/codecept.js +2 -0
  32. package/src/adapter/cucumber/current.js +2 -0
  33. package/src/adapter/cypress-plugin/index.js +2 -0
  34. package/src/adapter/e2e.js +245 -0
  35. package/src/adapter/jasmine.js +2 -0
  36. package/src/adapter/jest.js +2 -0
  37. package/src/adapter/mocha.js +146 -145
  38. package/src/adapter/nightwatch.js +2 -0
  39. package/src/adapter/playwright.js +2 -0
  40. package/src/adapter/vitest.js +2 -0
  41. package/src/adapter/webdriver.js +2 -0
  42. package/src/allureReader.js +2 -1
  43. package/src/bin/cli.js +30 -11
  44. package/src/client.js +11 -3
  45. package/src/data-storage.js +4 -3
  46. package/src/pipe/bitbucket.js +7 -1
  47. package/src/pipe/github.js +7 -1
  48. package/src/pipe/gitlab.js +7 -1
  49. package/src/pipe/testomatio.js +27 -1
  50. package/src/replay.js +1 -0
  51. package/src/uploader.js +30 -1
  52. package/src/utils/pipe_utils.js +85 -4
  53. package/src/xmlReader.js +3 -0
  54. package/types/types.d.ts +1 -0
@@ -16,6 +16,7 @@ const step_formatter_js_1 = require("./utils/step-formatter.js");
16
16
  const codeceptjs_1 = __importDefault(require("codeceptjs"));
17
17
  const log_js_1 = require("../utils/log.js");
18
18
  const debug = (0, debug_1.default)('@testomatio/reporter:adapter:codeceptjs');
19
+ global.TESTOMATIO_ADAPTER = 'codeceptjs';
19
20
  // @ts-ignore
20
21
  if (!global.codeceptjs) {
21
22
  // @ts-ignore
@@ -12,6 +12,7 @@ const client_js_1 = __importDefault(require("../../client.js"));
12
12
  const utils_js_1 = require("../../utils/utils.js");
13
13
  const config_js_1 = require("../../config.js");
14
14
  const index_js_1 = require("../../services/index.js");
15
+ global.TESTOMATIO_ADAPTER = 'cucumber';
15
16
  const { GherkinDocumentParser, PickleParser } = cucumber_1.formatterHelpers;
16
17
  const { getGherkinScenarioLocationMap, getGherkinStepMap } = GherkinDocumentParser;
17
18
  const { getPickleStepMap } = PickleParser;
@@ -7,6 +7,7 @@ const constants_js_1 = require("../../constants.js");
7
7
  const utils_js_1 = require("../../utils/utils.js");
8
8
  const client_js_1 = __importDefault(require("../../client.js"));
9
9
  const config_js_1 = require("../../config.js");
10
+ global.TESTOMATIO_ADAPTER = 'cypress';
10
11
  const testomatioReporter = on => {
11
12
  if (!config_js_1.config.TESTOMATIO) {
12
13
  console.log('TESTOMATIO key is empty, ignoring reports');
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Reporter for the e2e framework (https://github.com/tester-army/e2e).
3
+ * Add it to `reporters` in `e2e.config.ts`: `reporters: ['list', testomatio()]`.
4
+ *
5
+ * The config is loaded by every worker, so the client is created only inside
6
+ * handlers, which run in the runner process.
7
+ *
8
+ * @param {{ apiKey?: string }} [options]
9
+ */
10
+ export function testomatio(options?: {
11
+ apiKey?: string;
12
+ }): {
13
+ name: string;
14
+ onEvent(event: any): void;
15
+ onRunFinished(run: any, signal: any): Promise<{
16
+ label: string;
17
+ text: any;
18
+ }[]>;
19
+ };
20
+ /**
21
+ * Converts one report-1 result into Testomat.io test data.
22
+ * Only the final attempt is reported; earlier attempts are counted as retries.
23
+ */
24
+ export function toTestData(result: any, groups: any, artifactsRoot: any): {
25
+ status: string;
26
+ data: {
27
+ rid: any;
28
+ title: any;
29
+ suite_title: string;
30
+ file: any;
31
+ test_id: string;
32
+ tags: any;
33
+ time: any;
34
+ timestamp: number;
35
+ error: Error & {
36
+ expected?: string;
37
+ actual?: string;
38
+ };
39
+ steps: any;
40
+ logs: string;
41
+ files: any[];
42
+ meta: {
43
+ target: any;
44
+ platform: any;
45
+ browser: any;
46
+ };
47
+ };
48
+ };
49
+ export default testomatio;
@@ -0,0 +1,250 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.testomatio = testomatio;
7
+ exports.toTestData = toTestData;
8
+ const path_1 = __importDefault(require("path"));
9
+ const debug_1 = __importDefault(require("debug"));
10
+ const client_js_1 = __importDefault(require("../client.js"));
11
+ const constants_js_1 = require("../constants.js");
12
+ const utils_js_1 = require("../utils/utils.js");
13
+ const step_formatter_js_1 = require("./utils/step-formatter.js");
14
+ const log_js_1 = require("../utils/log.js");
15
+ const debug = (0, debug_1.default)('@testomatio/reporter:adapter-e2e');
16
+ /**
17
+ * Reporter for the e2e framework (https://github.com/tester-army/e2e).
18
+ * Add it to `reporters` in `e2e.config.ts`: `reporters: ['list', testomatio()]`.
19
+ *
20
+ * The config is loaded by every worker, so the client is created only inside
21
+ * handlers, which run in the runner process.
22
+ *
23
+ * @param {{ apiKey?: string }} [options]
24
+ */
25
+ function testomatio(options = {}) {
26
+ let client = null;
27
+ let runPromise = null;
28
+ function getClient() {
29
+ if (!client)
30
+ client = new client_js_1.default({ apiKey: options.apiKey });
31
+ return client;
32
+ }
33
+ function startRun() {
34
+ if (!runPromise) {
35
+ runPromise = getClient()
36
+ .createRun()
37
+ .catch(err => log_js_1.log.error('Failed to create Testomat.io run:', err?.message || err));
38
+ }
39
+ return runPromise;
40
+ }
41
+ return {
42
+ name: 'testomatio',
43
+ onEvent(event) {
44
+ try {
45
+ if (event?.type === 'run-started')
46
+ startRun();
47
+ }
48
+ catch (err) {
49
+ debug('onEvent failed', err);
50
+ }
51
+ },
52
+ async onRunFinished(run, signal) {
53
+ const reporter = getClient();
54
+ await startRun();
55
+ const { report, artifactsRoot } = run;
56
+ const groups = new Map((report.run.serialGroups || []).map(group => [group.id, group]));
57
+ const promises = [];
58
+ for (const result of report.run.results) {
59
+ if (signal?.aborted)
60
+ break;
61
+ // results left out by `--last-failed` belong to the previous run
62
+ if (result.selected === false)
63
+ continue;
64
+ const { status, data } = toTestData(result, groups, artifactsRoot);
65
+ promises.push(reporter.addTestRun(status, data));
66
+ }
67
+ await Promise.all(promises);
68
+ const duration = (Date.parse(report.run.finishedAt) - Date.parse(report.run.startedAt)) / 1000;
69
+ await reporter.updateRunStatus(runStatus(report.run.status), { duration });
70
+ const runUrl = reporter.pipeStore?.runUrl;
71
+ if (runUrl)
72
+ return [{ label: 'Testomat.io', text: runUrl }];
73
+ },
74
+ };
75
+ }
76
+ /**
77
+ * Converts one report-1 result into Testomat.io test data.
78
+ * Only the final attempt is reported; earlier attempts are counted as retries.
79
+ */
80
+ function toTestData(result, groups, artifactsRoot) {
81
+ const attempts = attemptsOf(result, groups);
82
+ const final = attempts.at(-1);
83
+ const titlePath = [...result.titlePath];
84
+ const title = titlePath.pop();
85
+ let suiteTitle = titlePath.join(' › ');
86
+ if (!suiteTitle)
87
+ suiteTitle = path_1.default.basename(result.file);
88
+ const meta = {
89
+ target: result.targetId,
90
+ platform: result.platform,
91
+ browser: final?.environment?.browser,
92
+ };
93
+ if (result.agent && result.agent !== 'default')
94
+ meta.agent = result.agent;
95
+ if (result.repeat)
96
+ meta.repeat = result.repeat;
97
+ if (attempts.length > 1)
98
+ meta.retryCount = attempts.length - 1;
99
+ if (result.status === 'flaky')
100
+ meta.isFlaky = true;
101
+ const filesById = new Map();
102
+ for (const artifact of final?.artifacts || []) {
103
+ if (artifact.path) {
104
+ filesById.set(artifact.id, {
105
+ path: path_1.default.join(artifactsRoot, artifact.path),
106
+ type: artifact.mediaType,
107
+ title: artifact.kind,
108
+ });
109
+ }
110
+ else if (artifact.url) {
111
+ // hosted engines keep videos remotely
112
+ meta[artifact.kind] = artifact.url;
113
+ }
114
+ }
115
+ const files = [...filesById.values()];
116
+ const steps = (final?.steps || []).map(step => toStep(step, filesById));
117
+ const data = {
118
+ rid: result.id,
119
+ title,
120
+ suite_title: suiteTitle,
121
+ file: result.file,
122
+ test_id: (0, utils_js_1.getTestomatIdFromTestTitle)(title),
123
+ tags: result.tags || [],
124
+ time: final?.durationMs || 0,
125
+ timestamp: timestampOf(final),
126
+ error: toError(final?.error, final?.secondaryErrors),
127
+ steps: steps.length ? steps : undefined,
128
+ logs: logsOf(result, final),
129
+ files: files.length ? files : undefined,
130
+ meta,
131
+ };
132
+ return { status: testStatus(result.status), data };
133
+ }
134
+ /** Attempts of a result; a serial member keeps its part of the group's attempts. */
135
+ function attemptsOf(result, groups) {
136
+ if (!result.serialGroupId)
137
+ return result.attempts || [];
138
+ const groupAttempts = groups.get(result.serialGroupId)?.attempts || [];
139
+ return groupAttempts.map(attempt => {
140
+ const member = attempt.members?.find(candidate => candidate.testId === result.testId);
141
+ return {
142
+ status: member?.status || attempt.status,
143
+ error: member?.error || attempt.error,
144
+ steps: member?.steps || [],
145
+ appLog: member?.appLog || [],
146
+ skip: member?.skip,
147
+ durationMs: member?.durationMs,
148
+ startedAt: member?.startedAt || attempt.startedAt,
149
+ artifacts: attempt.artifacts || [],
150
+ secondaryErrors: [...(member?.secondaryErrors || []), ...(attempt.secondaryErrors || [])],
151
+ environment: attempt.environment,
152
+ };
153
+ });
154
+ }
155
+ function timestampOf(attempt) {
156
+ if (!attempt?.startedAt)
157
+ return undefined;
158
+ return Date.parse(attempt.startedAt);
159
+ }
160
+ function testStatus(status) {
161
+ if (status === 'passed' || status === 'flaky')
162
+ return constants_js_1.STATUS.PASSED;
163
+ if (status === 'skipped')
164
+ return constants_js_1.STATUS.SKIPPED;
165
+ // failed, timed-out, interrupted: the test reached no passing verdict
166
+ return constants_js_1.STATUS.FAILED;
167
+ }
168
+ function runStatus(status) {
169
+ if (status === 'passed')
170
+ return constants_js_1.STATUS.PASSED;
171
+ return constants_js_1.STATUS.FAILED;
172
+ }
173
+ function toError(error, secondaryErrors = []) {
174
+ if (!error)
175
+ return undefined;
176
+ /** @type {Error & { expected?: string, actual?: string }} */
177
+ const err = new Error(error.message);
178
+ err.name = error.code;
179
+ err.stack = `${error.code}: ${error.message}\n${error.stack || sourceFrame(error.source)}`;
180
+ if (error.details?.expected && error.details?.observed) {
181
+ err.expected = error.details.expected;
182
+ err.actual = error.details.observed;
183
+ }
184
+ for (const secondary of secondaryErrors) {
185
+ err.stack += `\n\nAlso failed (${secondary.phase || secondary.category}) ${secondary.code}: ${secondary.message}`;
186
+ }
187
+ return err;
188
+ }
189
+ function sourceFrame(source) {
190
+ if (!source)
191
+ return '';
192
+ return ` at ${source.file}:${source.line}:${source.column}`;
193
+ }
194
+ function toStep(step, filesById) {
195
+ let category = 'user';
196
+ if (step.phase === 'beforeEach' || step.phase === 'afterEach')
197
+ category = 'hook';
198
+ let title = step.api;
199
+ if (step.label)
200
+ title = `${step.api} ${step.label}`;
201
+ const formatted = (0, step_formatter_js_1.formatStep)({
202
+ category,
203
+ title,
204
+ duration: step.durationMs,
205
+ log: stepLog(step),
206
+ });
207
+ let status = 'failed';
208
+ if (step.status === 'passed')
209
+ status = 'passed';
210
+ (0, step_formatter_js_1.addStatusToStep)(formatted, status, step.error);
211
+ if (step.error) {
212
+ formatted.error = { message: (0, utils_js_1.truncate)(`${step.error.code}: ${step.error.message}`, 250) };
213
+ }
214
+ if (constants_js_1.SCREENSHOTS_ON_STEPS) {
215
+ const screenshot = (step.artifacts || []).map(id => filesById.get(id)).find(file => file?.type === 'image/png');
216
+ if (screenshot)
217
+ (0, step_formatter_js_1.addArtifactsToStep)(formatted, { screenshot: screenshot.path });
218
+ }
219
+ return formatted;
220
+ }
221
+ /** Agent reasoning and non-binary step statuses, which a passed/failed step would lose. */
222
+ function stepLog(step) {
223
+ const lines = [];
224
+ if (step.status !== 'passed' && step.status !== 'failed')
225
+ lines.push(`status: ${step.status}`);
226
+ if (step.explanation)
227
+ lines.push(step.explanation);
228
+ for (const event of step.events || []) {
229
+ if (event.reasoning)
230
+ lines.push(event.reasoning);
231
+ }
232
+ return lines.join('\n');
233
+ }
234
+ function logsOf(result, final) {
235
+ const lines = [];
236
+ const skip = final?.skip || result.skip;
237
+ if (skip)
238
+ lines.push(`Skipped (${skip.cause}): ${skip.reason}`);
239
+ if (final?.appLog?.length) {
240
+ lines.push('App log:');
241
+ for (const line of final.appLog)
242
+ lines.push(`[${line.source}] ${line.level}: ${line.text}`);
243
+ }
244
+ return lines.join('\n');
245
+ }
246
+ module.exports = testomatio;
247
+
248
+ module.exports.testomatio = testomatio;
249
+
250
+ module.exports.toTestData = toTestData;
@@ -7,6 +7,7 @@ exports.JasmineReporter = void 0;
7
7
  const client_js_1 = __importDefault(require("../client.js"));
8
8
  const utils_js_1 = require("../utils/utils.js");
9
9
  const constants_js_1 = require("../constants.js");
10
+ global.TESTOMATIO_ADAPTER = 'jasmine';
10
11
  class JasmineReporter {
11
12
  constructor(options) {
12
13
  this.testTimeMap = {};
@@ -12,6 +12,7 @@ const index_js_1 = require("../services/index.js");
12
12
  const path_1 = __importDefault(require("path"));
13
13
  const debug_1 = __importDefault(require("debug"));
14
14
  const debug = (0, debug_1.default)('@testomatio/reporter:adapter-jest');
15
+ global.TESTOMATIO_ADAPTER = 'jest';
15
16
  class JestReporter {
16
17
  constructor(globalConfig, options) {
17
18
  this._globalConfig = globalConfig;
@@ -1,2 +1,5 @@
1
1
  export default MochaReporter;
2
- declare function MochaReporter(runner: any, opts: any): void;
2
+ declare class MochaReporter extends Mocha.reporters.Base {
3
+ constructor(runner: any, opts: any);
4
+ }
5
+ import Mocha from 'mocha';
@@ -10,133 +10,137 @@ const utils_js_1 = require("../utils/utils.js");
10
10
  const config_js_1 = require("../config.js");
11
11
  const index_js_1 = require("../services/index.js");
12
12
  const picocolors_1 = __importDefault(require("picocolors"));
13
+ global.TESTOMATIO_ADAPTER = 'mocha';
13
14
  const { EVENT_RUN_BEGIN, EVENT_RUN_END, EVENT_TEST_FAIL, EVENT_TEST_PASS, EVENT_TEST_PENDING, EVENT_SUITE_BEGIN, EVENT_SUITE_END, EVENT_TEST_BEGIN, EVENT_TEST_END, } = mocha_1.default.Runner.constants;
14
- function MochaReporter(runner, opts) {
15
- mocha_1.default.reporters.Base.call(this, runner);
16
- let passes = 0;
17
- let failures = 0;
18
- let skipped = 0;
19
- // let artifactStore;
20
- const apiKey = opts?.reporterOptions?.apiKey || config_js_1.config.TESTOMATIO;
21
- const client = new client_js_1.default({ apiKey });
22
- // Track hook failures
23
- const hookFailures = new Map();
24
- runner.on(EVENT_RUN_BEGIN, () => {
25
- client.createRun();
26
- // clear dir with artifacts/logs
27
- utils_js_1.fileSystem.clearDir(constants_js_1.TESTOMAT_TMP_STORAGE_DIR);
28
- });
29
- runner.on(EVENT_SUITE_BEGIN, async (suite) => {
30
- index_js_1.services.setContext(suite.fullTitle());
31
- });
32
- runner.on(EVENT_SUITE_END, async (suite) => {
33
- if (hookFailures.has(suite.fullTitle())) {
34
- const { error, suiteTitle } = hookFailures.get(suite.fullTitle());
35
- for (const test of suite.tests) {
36
- if (test.state === 'pending' || !test.state) {
37
- const testId = (0, utils_js_1.getTestomatIdFromTestTitle)(test.title);
38
- const artifacts = index_js_1.services.artifacts.get(test.fullTitle());
39
- const keyValues = index_js_1.services.keyValues.get(test.fullTitle());
40
- const links = index_js_1.services.links.get(test.fullTitle());
41
- client.addTestRun(constants_js_1.STATUS.FAILED, {
42
- error,
43
- suite_title: suiteTitle || suite.title,
44
- file: suite.file,
45
- test_id: testId,
46
- title: test.title,
47
- code: process.env.TESTOMATIO_UPDATE_CODE ? test.body.toString() : '',
48
- time: 0,
49
- manuallyAttachedArtifacts: artifacts,
50
- meta: keyValues,
51
- links,
52
- });
15
+ // ES class so it works with mocha 12, where Base is a class and utils.inherits is gone
16
+ class MochaReporter extends mocha_1.default.reporters.Base {
17
+ constructor(runner, opts) {
18
+ super(runner, opts);
19
+ let passes = 0;
20
+ let failures = 0;
21
+ let skipped = 0;
22
+ // let artifactStore;
23
+ const apiKey = opts?.reporterOptions?.apiKey || config_js_1.config.TESTOMATIO;
24
+ const client = new client_js_1.default({ apiKey });
25
+ // Track hook failures
26
+ const hookFailures = new Map();
27
+ runner.on(EVENT_RUN_BEGIN, () => {
28
+ client.createRun();
29
+ // clear dir with artifacts/logs
30
+ utils_js_1.fileSystem.clearDir(constants_js_1.TESTOMAT_TMP_STORAGE_DIR);
31
+ });
32
+ runner.on(EVENT_SUITE_BEGIN, async (suite) => {
33
+ index_js_1.services.setContext(suite.fullTitle());
34
+ });
35
+ runner.on(EVENT_SUITE_END, async (suite) => {
36
+ if (hookFailures.has(suite.fullTitle())) {
37
+ const { error, suiteTitle } = hookFailures.get(suite.fullTitle());
38
+ for (const test of suite.tests) {
39
+ if (test.state === 'pending' || !test.state) {
40
+ const testId = (0, utils_js_1.getTestomatIdFromTestTitle)(test.title);
41
+ const artifacts = index_js_1.services.artifacts.get(test.fullTitle());
42
+ const keyValues = index_js_1.services.keyValues.get(test.fullTitle());
43
+ const links = index_js_1.services.links.get(test.fullTitle());
44
+ client.addTestRun(constants_js_1.STATUS.FAILED, {
45
+ error,
46
+ suite_title: suiteTitle || suite.title,
47
+ file: suite.file,
48
+ test_id: testId,
49
+ title: test.title,
50
+ code: process.env.TESTOMATIO_UPDATE_CODE ? test.body.toString() : '',
51
+ time: 0,
52
+ manuallyAttachedArtifacts: artifacts,
53
+ meta: keyValues,
54
+ links,
55
+ });
56
+ }
53
57
  }
54
58
  }
55
- }
56
- index_js_1.services.setContext(null);
57
- });
58
- runner.on(EVENT_TEST_BEGIN, async (test) => {
59
- index_js_1.services.setContext(test.fullTitle());
60
- });
61
- runner.on(EVENT_TEST_END, async () => {
62
- index_js_1.services.setContext(null);
63
- });
64
- runner.on(EVENT_TEST_PASS, async (test) => {
65
- passes += 1;
66
- console.log(picocolors_1.default.bold(picocolors_1.default.green('✔')), test.fullTitle());
67
- const testId = (0, utils_js_1.getTestomatIdFromTestTitle)(test.title);
68
- const logs = getTestLogs(test);
69
- const artifacts = index_js_1.services.artifacts.get(test.fullTitle());
70
- const keyValues = index_js_1.services.keyValues.get(test.fullTitle());
71
- const links = index_js_1.services.links.get(test.fullTitle());
72
- client.addTestRun(constants_js_1.STATUS.PASSED, {
73
- test_id: testId,
74
- suite_title: getSuiteTitle(test),
75
- title: getTestName(test),
76
- code: process.env.TESTOMATIO_UPDATE_CODE ? test.body.toString() : '',
77
- file: getFile(test),
78
- time: test.duration,
79
- logs,
80
- manuallyAttachedArtifacts: artifacts,
81
- meta: keyValues,
82
- links,
59
+ index_js_1.services.setContext(null);
60
+ });
61
+ runner.on(EVENT_TEST_BEGIN, async (test) => {
62
+ index_js_1.services.setContext(test.fullTitle());
63
+ });
64
+ runner.on(EVENT_TEST_END, async () => {
65
+ index_js_1.services.setContext(null);
66
+ });
67
+ runner.on(EVENT_TEST_PASS, async (test) => {
68
+ passes += 1;
69
+ console.log(picocolors_1.default.bold(picocolors_1.default.green('✔')), test.fullTitle());
70
+ const testId = (0, utils_js_1.getTestomatIdFromTestTitle)(test.title);
71
+ const logs = getTestLogs(test);
72
+ const artifacts = index_js_1.services.artifacts.get(test.fullTitle());
73
+ const keyValues = index_js_1.services.keyValues.get(test.fullTitle());
74
+ const links = index_js_1.services.links.get(test.fullTitle());
75
+ client.addTestRun(constants_js_1.STATUS.PASSED, {
76
+ test_id: testId,
77
+ suite_title: getSuiteTitle(test),
78
+ title: getTestName(test),
79
+ code: process.env.TESTOMATIO_UPDATE_CODE ? test.body.toString() : '',
80
+ file: getFile(test),
81
+ time: test.duration,
82
+ logs,
83
+ manuallyAttachedArtifacts: artifacts,
84
+ meta: keyValues,
85
+ links,
86
+ });
83
87
  });
84
- });
85
- runner.on(EVENT_TEST_PENDING, test => {
86
- skipped += 1;
87
- console.log('skip: %s', test.fullTitle());
88
- const testId = (0, utils_js_1.getTestomatIdFromTestTitle)(test.title);
89
- const artifacts = index_js_1.services.artifacts.get(test.fullTitle());
90
- const keyValues = index_js_1.services.keyValues.get(test.fullTitle());
91
- const links = index_js_1.services.links.get(test.fullTitle());
92
- client.addTestRun(constants_js_1.STATUS.SKIPPED, {
93
- title: getTestName(test),
94
- suite_title: getSuiteTitle(test),
95
- code: process.env.TESTOMATIO_UPDATE_CODE ? test.body.toString() : '',
96
- file: getFile(test),
97
- test_id: testId,
98
- time: test.duration,
99
- manuallyAttachedArtifacts: artifacts,
100
- meta: keyValues,
101
- links,
88
+ runner.on(EVENT_TEST_PENDING, test => {
89
+ skipped += 1;
90
+ console.log('skip: %s', test.fullTitle());
91
+ const testId = (0, utils_js_1.getTestomatIdFromTestTitle)(test.title);
92
+ const artifacts = index_js_1.services.artifacts.get(test.fullTitle());
93
+ const keyValues = index_js_1.services.keyValues.get(test.fullTitle());
94
+ const links = index_js_1.services.links.get(test.fullTitle());
95
+ client.addTestRun(constants_js_1.STATUS.SKIPPED, {
96
+ title: getTestName(test),
97
+ suite_title: getSuiteTitle(test),
98
+ code: process.env.TESTOMATIO_UPDATE_CODE ? test.body.toString() : '',
99
+ file: getFile(test),
100
+ test_id: testId,
101
+ time: test.duration,
102
+ manuallyAttachedArtifacts: artifacts,
103
+ meta: keyValues,
104
+ links,
105
+ });
102
106
  });
103
- });
104
- runner.on(EVENT_TEST_FAIL, async (test, err) => {
105
- failures += 1;
106
- console.log(picocolors_1.default.bold(picocolors_1.default.red('✖')), test.fullTitle(), picocolors_1.default.gray(err.message));
107
- const isHookFailure = test.title.includes('before each') || test.title.includes('after each');
108
- if (isHookFailure && test.parent) {
109
- hookFailures.set(test.parent.fullTitle(), {
107
+ runner.on(EVENT_TEST_FAIL, async (test, err) => {
108
+ failures += 1;
109
+ console.log(picocolors_1.default.bold(picocolors_1.default.red('✖')), test.fullTitle(), picocolors_1.default.gray(err.message));
110
+ const isHookFailure = test.title.includes('before each') || test.title.includes('after each');
111
+ if (isHookFailure && test.parent) {
112
+ hookFailures.set(test.parent.fullTitle(), {
113
+ error: err,
114
+ suiteTitle: getSuiteTitle(test),
115
+ });
116
+ return;
117
+ }
118
+ const testId = (0, utils_js_1.getTestomatIdFromTestTitle)(test.title);
119
+ const logs = getTestLogs(test);
120
+ const artifacts = index_js_1.services.artifacts.get(test.fullTitle());
121
+ const keyValues = index_js_1.services.keyValues.get(test.fullTitle());
122
+ const links = index_js_1.services.links.get(test.fullTitle());
123
+ client.addTestRun(constants_js_1.STATUS.FAILED, {
110
124
  error: err,
111
- suiteTitle: getSuiteTitle(test),
125
+ suite_title: getSuiteTitle(test),
126
+ file: getFile(test),
127
+ test_id: testId,
128
+ title: getTestName(test),
129
+ code: process.env.TESTOMATIO_UPDATE_CODE ? test.body.toString() : '',
130
+ time: test.duration,
131
+ logs,
132
+ manuallyAttachedArtifacts: artifacts,
133
+ meta: keyValues,
134
+ links,
112
135
  });
113
- return;
114
- }
115
- const testId = (0, utils_js_1.getTestomatIdFromTestTitle)(test.title);
116
- const logs = getTestLogs(test);
117
- const artifacts = index_js_1.services.artifacts.get(test.fullTitle());
118
- const keyValues = index_js_1.services.keyValues.get(test.fullTitle());
119
- const links = index_js_1.services.links.get(test.fullTitle());
120
- client.addTestRun(constants_js_1.STATUS.FAILED, {
121
- error: err,
122
- suite_title: getSuiteTitle(test),
123
- file: getFile(test),
124
- test_id: testId,
125
- title: getTestName(test),
126
- code: process.env.TESTOMATIO_UPDATE_CODE ? test.body.toString() : '',
127
- time: test.duration,
128
- logs,
129
- manuallyAttachedArtifacts: artifacts,
130
- meta: keyValues,
131
- links,
132
136
  });
133
- });
134
- runner.on(EVENT_RUN_END, () => {
135
- const status = failures === 0 ? constants_js_1.STATUS.PASSED : constants_js_1.STATUS.FAILED;
136
- console.log(picocolors_1.default.bold(status), `${passes} passed, ${failures} failed, ${skipped} skipped`);
137
- // @ts-ignore
138
- client.updateRunStatus(status);
139
- });
137
+ runner.on(EVENT_RUN_END, () => {
138
+ const status = failures === 0 ? constants_js_1.STATUS.PASSED : constants_js_1.STATUS.FAILED;
139
+ console.log(picocolors_1.default.bold(status), `${passes} passed, ${failures} failed, ${skipped} skipped`);
140
+ // @ts-ignore
141
+ client.updateRunStatus(status);
142
+ });
143
+ }
140
144
  }
141
145
  function getTestLogs(test) {
142
146
  const suiteLogsArr = index_js_1.services.logger.getLogs(test.parent.fullTitle());
@@ -166,7 +170,4 @@ function getTestName(test) {
166
170
  return test.fullTitle();
167
171
  return test.title;
168
172
  }
169
- // To have this reporter "extend" a built-in reporter uncomment the following line:
170
- // @ts-ignore
171
- mocha_1.default.utils.inherits(MochaReporter, mocha_1.default.reporters.Spec);
172
173
  module.exports = MochaReporter;
@@ -7,6 +7,7 @@ const client_js_1 = __importDefault(require("../client.js"));
7
7
  const config_js_1 = require("../config.js");
8
8
  const constants_js_1 = require("../constants.js");
9
9
  const utils_js_1 = require("../utils/utils.js");
10
+ global.TESTOMATIO_ADAPTER = 'nightwatch';
10
11
  const apiKey = config_js_1.config.TESTOMATIO;
11
12
  const client = new client_js_1.default({ apiKey });
12
13
  module.exports = {
@@ -21,6 +21,7 @@ const playwright_js_1 = require("./utils/playwright.js");
21
21
  Object.defineProperty(exports, "fetchLinksFromLogs", { enumerable: true, get: function () { return playwright_js_1.fetchLinksFromLogs; } });
22
22
  const step_formatter_js_1 = require("./utils/step-formatter.js");
23
23
  const log_js_1 = require("../utils/log.js");
24
+ global.TESTOMATIO_ADAPTER = 'playwright';
24
25
  class PlaywrightReporter {
25
26
  constructor(config = {}) {
26
27
  this.client = new client_js_1.default({ apiKey: config?.apiKey });
@@ -10,6 +10,7 @@ const constants_js_1 = require("../constants.js");
10
10
  const utils_js_1 = require("../utils/utils.js");
11
11
  const debug_1 = __importDefault(require("debug"));
12
12
  const debug = (0, debug_1.default)('@testomatio/reporter:adapter-jest');
13
+ global.TESTOMATIO_ADAPTER = 'vitest';
13
14
  /**
14
15
  * @typedef {import('../../types/types.js').VitestTest} VitestTest
15
16
  * @typedef {import('../../types/types.js').VitestTestFile} VitestTestFile
@@ -42,6 +42,7 @@ const utils_js_1 = require("../utils/utils.js");
42
42
  const index_js_1 = require("../services/index.js");
43
43
  const constants_js_1 = require("../constants.js");
44
44
  const data_storage_js_1 = require("../data-storage.js");
45
+ global.TESTOMATIO_ADAPTER = 'webdriverio';
45
46
  class WebdriverReporter extends reporter_1.default {
46
47
  constructor(options) {
47
48
  super(options);