@testomatio/reporter 2.19.0 → 2.21.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.
- package/lib/adapter/codecept.js +26 -2
- package/lib/adapter/cucumber/current.js +1 -0
- package/lib/adapter/cypress-plugin/index.js +1 -0
- package/lib/adapter/e2e.d.ts +49 -0
- package/lib/adapter/e2e.js +254 -0
- package/lib/adapter/jasmine.js +1 -0
- package/lib/adapter/jest.js +1 -0
- package/lib/adapter/mocha.d.ts +4 -1
- package/lib/adapter/mocha.js +123 -122
- package/lib/adapter/nightwatch.js +1 -0
- package/lib/adapter/playwright.js +33 -1
- package/lib/adapter/vitest.js +5 -1
- package/lib/adapter/webdriver.js +45 -2
- package/lib/allureReader.d.ts +4 -1
- package/lib/allureReader.js +2 -1
- package/lib/bin/cli.js +212 -19
- package/lib/client.d.ts +1 -0
- package/lib/client.js +12 -3
- package/lib/data-storage.js +4 -3
- package/lib/fetch/report.d.ts +31 -0
- package/lib/fetch/report.js +81 -0
- package/lib/fetch/testruns.d.ts +133 -0
- package/lib/fetch/testruns.js +286 -0
- package/lib/pipe/markdown.d.ts +1 -0
- package/lib/pipe/markdown.js +7 -0
- package/lib/pipe/testomatio.js +17 -1
- package/lib/replay.js +1 -0
- package/lib/reporter-functions.js +39 -0
- package/lib/uploader.d.ts +17 -0
- package/lib/uploader.js +75 -1
- package/lib/utils/detectRunner.d.ts +23 -0
- package/lib/utils/detectRunner.js +149 -0
- package/lib/utils/pipe_utils.d.ts +16 -3
- package/lib/utils/pipe_utils.js +45 -4
- package/lib/xmlReader.js +2 -0
- package/package.json +8 -3
- package/src/adapter/codecept.js +24 -2
- package/src/adapter/cucumber/current.js +2 -0
- package/src/adapter/cypress-plugin/index.js +2 -0
- package/src/adapter/e2e.js +248 -0
- package/src/adapter/jasmine.js +2 -0
- package/src/adapter/jest.js +2 -0
- package/src/adapter/mocha.js +146 -145
- package/src/adapter/nightwatch.js +2 -0
- package/src/adapter/playwright.js +33 -1
- package/src/adapter/vitest.js +6 -1
- package/src/adapter/webdriver.js +46 -2
- package/src/allureReader.js +2 -1
- package/src/bin/cli.js +246 -18
- package/src/client.js +11 -3
- package/src/data-storage.js +4 -3
- package/src/fetch/report.js +86 -0
- package/src/fetch/testruns.js +283 -0
- package/src/pipe/markdown.js +7 -0
- package/src/pipe/testomatio.js +27 -1
- package/src/replay.js +1 -0
- package/src/reporter-functions.js +41 -0
- package/src/uploader.js +81 -1
- package/src/utils/detectRunner.js +151 -0
- package/src/utils/pipe_utils.js +45 -4
- package/src/xmlReader.js +3 -0
- package/types/types.d.ts +1 -0
package/lib/adapter/codecept.js
CHANGED
|
@@ -16,13 +16,14 @@ 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
|
|
22
23
|
global.codeceptjs = codeceptjs_1.default;
|
|
23
24
|
}
|
|
24
25
|
// @ts-ignore
|
|
25
|
-
const { event, recorder, codecept, output } = global.codeceptjs;
|
|
26
|
+
const { event, recorder, codecept, output, container } = global.codeceptjs;
|
|
26
27
|
const [, MAJOR_VERSION, MINOR_VERSION] = codecept
|
|
27
28
|
.version()
|
|
28
29
|
.match(/(\d+)\.(\d+)/)
|
|
@@ -51,6 +52,7 @@ function CodeceptReporter(config) {
|
|
|
51
52
|
const reportTestPromises = [];
|
|
52
53
|
let isRunFinalized = false;
|
|
53
54
|
const testTimeMap = {};
|
|
55
|
+
const failedUrls = new Map();
|
|
54
56
|
const clientConfig = buildCodeceptClientConfig(config);
|
|
55
57
|
const client = new client_js_1.default(clientConfig);
|
|
56
58
|
// Store original output methods for fallback
|
|
@@ -211,6 +213,24 @@ function CodeceptReporter(config) {
|
|
|
211
213
|
await finalizeRun('all.after');
|
|
212
214
|
}, true);
|
|
213
215
|
});
|
|
216
|
+
event.dispatcher.on(event.test.failed, (test, _err, hookName) => {
|
|
217
|
+
// no browser in suite hooks
|
|
218
|
+
if (hookName === 'BeforeSuite' || hookName === 'AfterSuite')
|
|
219
|
+
return;
|
|
220
|
+
const helper = Object.values(container.helpers()).find(h => typeof h.grabCurrentUrl === 'function');
|
|
221
|
+
if (!helper)
|
|
222
|
+
return;
|
|
223
|
+
recorder.add('url of failed test', async () => {
|
|
224
|
+
try {
|
|
225
|
+
const url = await helper.grabCurrentUrl();
|
|
226
|
+
if (url)
|
|
227
|
+
failedUrls.set(test.uid, url);
|
|
228
|
+
}
|
|
229
|
+
catch (err) {
|
|
230
|
+
debug('Failed to grab url of failed test', err?.message || err);
|
|
231
|
+
}
|
|
232
|
+
}, true);
|
|
233
|
+
});
|
|
214
234
|
event.dispatcher.on(event.test.skipped, test => {
|
|
215
235
|
const { uid, tags, title } = test.simplify();
|
|
216
236
|
if (uid && reportedTestUids.has(uid))
|
|
@@ -239,6 +259,10 @@ function CodeceptReporter(config) {
|
|
|
239
259
|
const keyValues = index_js_1.services.keyValues.get(test.fullTitle());
|
|
240
260
|
const links = index_js_1.services.links.get(test.fullTitle());
|
|
241
261
|
const screenshotOnFailPath = artifacts.screenshot || null;
|
|
262
|
+
const meta = { ...keyValues, ...test.meta };
|
|
263
|
+
if (test.state === constants_js_1.STATUS.FAILED && failedUrls.has(uid))
|
|
264
|
+
meta.failedUrl = failedUrls.get(uid);
|
|
265
|
+
failedUrls.delete(uid);
|
|
242
266
|
// Build step hierarchy with screenshot from screenshotOnFail
|
|
243
267
|
const stepHierarchy = buildUnifiedStepHierarchy(test.steps, hookSteps, screenshotOnFailPath);
|
|
244
268
|
index_js_1.services.setContext(null);
|
|
@@ -255,7 +279,7 @@ function CodeceptReporter(config) {
|
|
|
255
279
|
logs,
|
|
256
280
|
links,
|
|
257
281
|
manuallyAttachedArtifacts,
|
|
258
|
-
meta
|
|
282
|
+
meta,
|
|
259
283
|
});
|
|
260
284
|
reportTestPromises.push(reportTestPromise);
|
|
261
285
|
processArtifactsForUpload(artifacts, uid, title, videos, traces);
|
|
@@ -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,254 @@
|
|
|
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 status = testStatus(result.status);
|
|
102
|
+
if (status === constants_js_1.STATUS.FAILED && final?.failure?.url)
|
|
103
|
+
meta.failedUrl = final.failure.url;
|
|
104
|
+
const filesById = new Map();
|
|
105
|
+
for (const artifact of final?.artifacts || []) {
|
|
106
|
+
if (artifact.path) {
|
|
107
|
+
filesById.set(artifact.id, {
|
|
108
|
+
path: path_1.default.join(artifactsRoot, artifact.path),
|
|
109
|
+
type: artifact.mediaType,
|
|
110
|
+
title: artifact.kind,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
else if (artifact.url) {
|
|
114
|
+
// hosted engines keep videos remotely
|
|
115
|
+
meta[artifact.kind] = artifact.url;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
const files = [...filesById.values()];
|
|
119
|
+
const steps = (final?.steps || []).map(step => toStep(step, filesById));
|
|
120
|
+
const data = {
|
|
121
|
+
rid: result.id,
|
|
122
|
+
title,
|
|
123
|
+
suite_title: suiteTitle,
|
|
124
|
+
file: result.file,
|
|
125
|
+
test_id: (0, utils_js_1.getTestomatIdFromTestTitle)(title),
|
|
126
|
+
tags: result.tags || [],
|
|
127
|
+
time: final?.durationMs || 0,
|
|
128
|
+
timestamp: timestampOf(final),
|
|
129
|
+
error: toError(final?.error, final?.secondaryErrors),
|
|
130
|
+
steps: steps.length ? steps : undefined,
|
|
131
|
+
logs: logsOf(result, final),
|
|
132
|
+
files: files.length ? files : undefined,
|
|
133
|
+
meta,
|
|
134
|
+
};
|
|
135
|
+
return { status, data };
|
|
136
|
+
}
|
|
137
|
+
/** Attempts of a result; a serial member keeps its part of the group's attempts. */
|
|
138
|
+
function attemptsOf(result, groups) {
|
|
139
|
+
if (!result.serialGroupId)
|
|
140
|
+
return result.attempts || [];
|
|
141
|
+
const groupAttempts = groups.get(result.serialGroupId)?.attempts || [];
|
|
142
|
+
return groupAttempts.map(attempt => {
|
|
143
|
+
const member = attempt.members?.find(candidate => candidate.testId === result.testId);
|
|
144
|
+
return {
|
|
145
|
+
status: member?.status || attempt.status,
|
|
146
|
+
error: member?.error || attempt.error,
|
|
147
|
+
failure: member?.failure || attempt.failure,
|
|
148
|
+
steps: member?.steps || [],
|
|
149
|
+
appLog: member?.appLog || [],
|
|
150
|
+
skip: member?.skip,
|
|
151
|
+
durationMs: member?.durationMs,
|
|
152
|
+
startedAt: member?.startedAt || attempt.startedAt,
|
|
153
|
+
artifacts: attempt.artifacts || [],
|
|
154
|
+
secondaryErrors: [...(member?.secondaryErrors || []), ...(attempt.secondaryErrors || [])],
|
|
155
|
+
environment: attempt.environment,
|
|
156
|
+
};
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
function timestampOf(attempt) {
|
|
160
|
+
if (!attempt?.startedAt)
|
|
161
|
+
return undefined;
|
|
162
|
+
return Date.parse(attempt.startedAt);
|
|
163
|
+
}
|
|
164
|
+
function testStatus(status) {
|
|
165
|
+
if (status === 'passed' || status === 'flaky')
|
|
166
|
+
return constants_js_1.STATUS.PASSED;
|
|
167
|
+
if (status === 'skipped')
|
|
168
|
+
return constants_js_1.STATUS.SKIPPED;
|
|
169
|
+
// failed, timed-out, interrupted: the test reached no passing verdict
|
|
170
|
+
return constants_js_1.STATUS.FAILED;
|
|
171
|
+
}
|
|
172
|
+
function runStatus(status) {
|
|
173
|
+
if (status === 'passed')
|
|
174
|
+
return constants_js_1.STATUS.PASSED;
|
|
175
|
+
return constants_js_1.STATUS.FAILED;
|
|
176
|
+
}
|
|
177
|
+
function toError(error, secondaryErrors = []) {
|
|
178
|
+
if (!error)
|
|
179
|
+
return undefined;
|
|
180
|
+
/** @type {Error & { expected?: string, actual?: string }} */
|
|
181
|
+
const err = new Error(error.message);
|
|
182
|
+
err.name = error.code;
|
|
183
|
+
err.stack = `${error.code}: ${error.message}\n${error.stack || sourceFrame(error.source)}`;
|
|
184
|
+
if (error.details?.expected && error.details?.observed) {
|
|
185
|
+
err.expected = error.details.expected;
|
|
186
|
+
err.actual = error.details.observed;
|
|
187
|
+
}
|
|
188
|
+
for (const secondary of secondaryErrors) {
|
|
189
|
+
err.stack += `\n\nAlso failed (${secondary.phase || secondary.category}) ${secondary.code}: ${secondary.message}`;
|
|
190
|
+
}
|
|
191
|
+
return err;
|
|
192
|
+
}
|
|
193
|
+
function sourceFrame(source) {
|
|
194
|
+
if (!source)
|
|
195
|
+
return '';
|
|
196
|
+
return ` at ${source.file}:${source.line}:${source.column}`;
|
|
197
|
+
}
|
|
198
|
+
function toStep(step, filesById) {
|
|
199
|
+
let category = 'user';
|
|
200
|
+
if (step.phase === 'beforeEach' || step.phase === 'afterEach')
|
|
201
|
+
category = 'hook';
|
|
202
|
+
let title = step.api;
|
|
203
|
+
if (step.label)
|
|
204
|
+
title = `${step.api} ${step.label}`;
|
|
205
|
+
const formatted = (0, step_formatter_js_1.formatStep)({
|
|
206
|
+
category,
|
|
207
|
+
title,
|
|
208
|
+
duration: step.durationMs,
|
|
209
|
+
log: stepLog(step),
|
|
210
|
+
});
|
|
211
|
+
let status = 'failed';
|
|
212
|
+
if (step.status === 'passed')
|
|
213
|
+
status = 'passed';
|
|
214
|
+
(0, step_formatter_js_1.addStatusToStep)(formatted, status, step.error);
|
|
215
|
+
if (step.error) {
|
|
216
|
+
formatted.error = { message: (0, utils_js_1.truncate)(`${step.error.code}: ${step.error.message}`, 250) };
|
|
217
|
+
}
|
|
218
|
+
if (constants_js_1.SCREENSHOTS_ON_STEPS) {
|
|
219
|
+
const screenshot = (step.artifacts || []).map(id => filesById.get(id)).find(file => file?.type === 'image/png');
|
|
220
|
+
if (screenshot)
|
|
221
|
+
(0, step_formatter_js_1.addArtifactsToStep)(formatted, { screenshot: screenshot.path });
|
|
222
|
+
}
|
|
223
|
+
return formatted;
|
|
224
|
+
}
|
|
225
|
+
/** Agent reasoning and non-binary step statuses, which a passed/failed step would lose. */
|
|
226
|
+
function stepLog(step) {
|
|
227
|
+
const lines = [];
|
|
228
|
+
if (step.status !== 'passed' && step.status !== 'failed')
|
|
229
|
+
lines.push(`status: ${step.status}`);
|
|
230
|
+
if (step.explanation)
|
|
231
|
+
lines.push(step.explanation);
|
|
232
|
+
for (const event of step.events || []) {
|
|
233
|
+
if (event.reasoning)
|
|
234
|
+
lines.push(event.reasoning);
|
|
235
|
+
}
|
|
236
|
+
return lines.join('\n');
|
|
237
|
+
}
|
|
238
|
+
function logsOf(result, final) {
|
|
239
|
+
const lines = [];
|
|
240
|
+
const skip = final?.skip || result.skip;
|
|
241
|
+
if (skip)
|
|
242
|
+
lines.push(`Skipped (${skip.cause}): ${skip.reason}`);
|
|
243
|
+
if (final?.appLog?.length) {
|
|
244
|
+
lines.push('App log:');
|
|
245
|
+
for (const line of final.appLog)
|
|
246
|
+
lines.push(`[${line.source}] ${line.level}: ${line.text}`);
|
|
247
|
+
}
|
|
248
|
+
return lines.join('\n');
|
|
249
|
+
}
|
|
250
|
+
module.exports = testomatio;
|
|
251
|
+
|
|
252
|
+
module.exports.testomatio = testomatio;
|
|
253
|
+
|
|
254
|
+
module.exports.toTestData = toTestData;
|
package/lib/adapter/jasmine.js
CHANGED
|
@@ -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 = {};
|
package/lib/adapter/jest.js
CHANGED
|
@@ -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;
|
package/lib/adapter/mocha.d.ts
CHANGED