@testomatio/reporter 2.0.1-beta.3 → 2.0.1-beta.5-timestamp
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 +335 -293
- package/lib/adapter/cucumber/current.js +203 -195
- package/lib/adapter/cucumber/legacy.js +155 -130
- package/lib/adapter/cucumber.js +16 -5
- package/lib/adapter/cypress-plugin/index.js +105 -91
- package/lib/adapter/jasmine.js +53 -54
- package/lib/adapter/jest.js +99 -97
- package/lib/adapter/mocha.js +141 -112
- package/lib/adapter/playwright.js +231 -199
- package/lib/adapter/vitest.js +149 -150
- package/lib/adapter/webdriver.js +121 -144
- package/lib/bin/cli.js +211 -229
- package/lib/bin/reportXml.js +52 -51
- package/lib/bin/startTest.js +95 -83
- package/lib/bin/uploadArtifacts.js +61 -56
- package/lib/client.js +465 -424
- package/lib/config.js +23 -18
- package/lib/constants.js +44 -50
- package/lib/data-storage.js +188 -216
- package/lib/junit-adapter/adapter.js +20 -17
- package/lib/junit-adapter/csharp.js +14 -28
- package/lib/junit-adapter/index.js +25 -27
- package/lib/junit-adapter/java.js +53 -41
- package/lib/junit-adapter/javascript.js +27 -30
- package/lib/junit-adapter/python.js +37 -38
- package/lib/junit-adapter/ruby.js +8 -11
- package/lib/output.js +52 -44
- package/lib/pipe/bitbucket.js +230 -223
- package/lib/pipe/csv.js +126 -113
- package/lib/pipe/debug.js +99 -118
- package/lib/pipe/github.js +213 -218
- package/lib/pipe/gitlab.js +206 -183
- package/lib/pipe/html.js +321 -258
- package/lib/pipe/index.js +66 -94
- package/lib/pipe/testomatio.js +474 -429
- package/lib/reporter-functions.js +26 -28
- package/lib/reporter.js +29 -34
- package/lib/services/artifacts.js +51 -55
- package/lib/services/index.js +12 -14
- package/lib/services/key-values.js +53 -56
- package/lib/services/logger.js +245 -226
- package/lib/template/testomatio.hbs +1366 -1026
- package/lib/uploader.js +364 -295
- package/lib/utils/pipe_utils.js +85 -89
- package/lib/utils/utils.js +307 -398
- package/lib/xmlReader.js +532 -525
- package/package.json +21 -64
- package/lib/adapter/codecept.d.ts +0 -2
- package/lib/adapter/cucumber/current.d.ts +0 -14
- package/lib/adapter/cucumber/legacy.d.ts +0 -0
- package/lib/adapter/cucumber.d.ts +0 -2
- package/lib/adapter/cypress-plugin/index.d.ts +0 -2
- package/lib/adapter/jasmine.d.ts +0 -11
- package/lib/adapter/jest.d.ts +0 -13
- package/lib/adapter/mocha.d.ts +0 -2
- package/lib/adapter/nightwatch.d.ts +0 -4
- package/lib/adapter/nightwatch.js +0 -80
- package/lib/adapter/playwright.d.ts +0 -14
- package/lib/adapter/vitest.d.ts +0 -35
- package/lib/adapter/webdriver.d.ts +0 -24
- package/lib/bin/cli.d.ts +0 -2
- package/lib/bin/reportXml.d.ts +0 -2
- package/lib/bin/startTest.d.ts +0 -2
- package/lib/bin/uploadArtifacts.d.ts +0 -2
- package/lib/client.d.ts +0 -76
- package/lib/config.d.ts +0 -1
- package/lib/constants.d.ts +0 -25
- package/lib/data-storage.d.ts +0 -34
- package/lib/junit-adapter/adapter.d.ts +0 -9
- package/lib/junit-adapter/csharp.d.ts +0 -5
- package/lib/junit-adapter/index.d.ts +0 -3
- package/lib/junit-adapter/java.d.ts +0 -5
- package/lib/junit-adapter/javascript.d.ts +0 -4
- package/lib/junit-adapter/python.d.ts +0 -5
- package/lib/junit-adapter/ruby.d.ts +0 -4
- package/lib/output.d.ts +0 -11
- package/lib/package.json +0 -3
- package/lib/pipe/bitbucket.d.ts +0 -25
- package/lib/pipe/csv.d.ts +0 -47
- package/lib/pipe/debug.d.ts +0 -29
- package/lib/pipe/github.d.ts +0 -30
- package/lib/pipe/gitlab.d.ts +0 -25
- package/lib/pipe/html.d.ts +0 -35
- package/lib/pipe/index.d.ts +0 -1
- package/lib/pipe/testomatio.d.ts +0 -71
- package/lib/replay.d.ts +0 -31
- package/lib/replay.js +0 -237
- package/lib/reporter-functions.d.ts +0 -34
- package/lib/reporter.d.ts +0 -232
- package/lib/services/artifacts.d.ts +0 -33
- package/lib/services/index.d.ts +0 -9
- package/lib/services/key-values.d.ts +0 -27
- package/lib/services/logger.d.ts +0 -64
- package/lib/uploader.d.ts +0 -60
- package/lib/utils/pipe_utils.d.ts +0 -41
- package/lib/utils/utils.d.ts +0 -54
- package/lib/xmlReader.d.ts +0 -92
- package/src/adapter/codecept.js +0 -373
- package/src/adapter/cucumber/current.js +0 -228
- package/src/adapter/cucumber/legacy.js +0 -158
- package/src/adapter/cucumber.js +0 -4
- package/src/adapter/cypress-plugin/index.js +0 -110
- package/src/adapter/jasmine.js +0 -60
- package/src/adapter/jest.js +0 -107
- package/src/adapter/mocha.cjs +0 -2
- package/src/adapter/mocha.js +0 -156
- package/src/adapter/nightwatch.js +0 -88
- package/src/adapter/playwright.js +0 -254
- package/src/adapter/vitest.js +0 -183
- package/src/adapter/webdriver.js +0 -142
- package/src/bin/cli.js +0 -348
- package/src/bin/reportXml.js +0 -77
- package/src/bin/startTest.js +0 -124
- package/src/bin/uploadArtifacts.js +0 -91
- package/src/client.js +0 -508
- package/src/config.js +0 -30
- package/src/constants.js +0 -53
- package/src/data-storage.js +0 -204
- package/src/junit-adapter/adapter.js +0 -23
- package/src/junit-adapter/csharp.js +0 -28
- package/src/junit-adapter/index.js +0 -28
- package/src/junit-adapter/java.js +0 -58
- package/src/junit-adapter/javascript.js +0 -31
- package/src/junit-adapter/python.js +0 -42
- package/src/junit-adapter/ruby.js +0 -10
- package/src/output.js +0 -57
- package/src/pipe/bitbucket.js +0 -252
- package/src/pipe/csv.js +0 -140
- package/src/pipe/debug.js +0 -119
- package/src/pipe/github.js +0 -232
- package/src/pipe/gitlab.js +0 -247
- package/src/pipe/html.js +0 -373
- package/src/pipe/index.js +0 -71
- package/src/pipe/testomatio.js +0 -504
- package/src/replay.js +0 -245
- package/src/reporter-functions.js +0 -55
- package/src/reporter.cjs_decprecated +0 -21
- package/src/reporter.js +0 -33
- package/src/services/artifacts.js +0 -59
- package/src/services/index.js +0 -13
- package/src/services/key-values.js +0 -59
- package/src/services/logger.js +0 -315
- package/src/template/emptyData.svg +0 -23
- package/src/template/testomatio.hbs +0 -1081
- package/src/uploader.js +0 -376
- package/src/utils/pipe_utils.js +0 -119
- package/src/utils/utils.js +0 -416
- package/src/xmlReader.js +0 -614
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
// import { Formatter } from 'cucumber';
|
|
2
|
-
|
|
3
|
-
// import pc from 'picocolors';
|
|
4
|
-
// import { getTestomatIdFromTestTitle, fileSystem } from '../../utils/utils.js';
|
|
5
|
-
// import { STATUS, TESTOMAT_TMP_STORAGE_DIR } from '../../constants.js';
|
|
6
|
-
// import TestomatClient from '../../client.js';
|
|
7
|
-
// import {config} from '../../config.js';
|
|
8
|
-
|
|
9
|
-
// const createTestomatFormatter = apiKey => {
|
|
10
|
-
// if (!apiKey || apiKey === '') {
|
|
11
|
-
// console.log(pc.red('TESTOMATIO key is empty, ignoring reports'));
|
|
12
|
-
// }
|
|
13
|
-
|
|
14
|
-
// const documents = {};
|
|
15
|
-
// const dataTableMap = {};
|
|
16
|
-
|
|
17
|
-
// const addDocument = gherkinDocument => {
|
|
18
|
-
// documents[gherkinDocument.uri] = gherkinDocument.document;
|
|
19
|
-
// };
|
|
20
|
-
|
|
21
|
-
// const getTitle = scenario => {
|
|
22
|
-
// let { name } = scenario;
|
|
23
|
-
// if (scenario.tags.length) {
|
|
24
|
-
// let tags = '';
|
|
25
|
-
// for (const tag of scenario.tags) {
|
|
26
|
-
// tags = `${tags} ${tag.name}`;
|
|
27
|
-
// }
|
|
28
|
-
// name = `${name}${tags}`;
|
|
29
|
-
// }
|
|
30
|
-
// return name;
|
|
31
|
-
// };
|
|
32
|
-
|
|
33
|
-
// const getFeature = uri => documents[uri].feature;
|
|
34
|
-
|
|
35
|
-
// const getScenario = location => {
|
|
36
|
-
// const { children } = getFeature(location.uri);
|
|
37
|
-
// for (const scenario of children) {
|
|
38
|
-
// if (scenario.type === 'Scenario' && scenario.location.line === location.line) {
|
|
39
|
-
// return scenario;
|
|
40
|
-
// }
|
|
41
|
-
// if (scenario.type === 'ScenarioOutline') {
|
|
42
|
-
// for (const example of scenario.examples) {
|
|
43
|
-
// for (const tableBody of example.tableBody) {
|
|
44
|
-
// if (tableBody.location.line === location.line) {
|
|
45
|
-
// return scenario;
|
|
46
|
-
// }
|
|
47
|
-
// }
|
|
48
|
-
// }
|
|
49
|
-
// }
|
|
50
|
-
// }
|
|
51
|
-
|
|
52
|
-
// return null;
|
|
53
|
-
// };
|
|
54
|
-
|
|
55
|
-
// const loadDataTable = (scenario, uri) => {
|
|
56
|
-
// if (scenario.type === 'ScenarioOutline') {
|
|
57
|
-
// for (const example of scenario.examples) {
|
|
58
|
-
// for (const tableBody of example.tableBody) {
|
|
59
|
-
// const dataMap = example.tableHeader.cells.reduce((acc, cell, index) => {
|
|
60
|
-
// acc[cell.value] = tableBody.cells[index].value;
|
|
61
|
-
// return acc;
|
|
62
|
-
// }, {});
|
|
63
|
-
|
|
64
|
-
// dataTableMap[`${uri}:${tableBody.location.line}`] = JSON.stringify(dataMap);
|
|
65
|
-
// }
|
|
66
|
-
// }
|
|
67
|
-
// }
|
|
68
|
-
// };
|
|
69
|
-
|
|
70
|
-
// const getDataTableMap = (scenario, sourceLocation) => {
|
|
71
|
-
// const key = `${sourceLocation.uri}:${sourceLocation.line}`;
|
|
72
|
-
// if (!dataTableMap[key]) {
|
|
73
|
-
// loadDataTable(scenario, sourceLocation.uri);
|
|
74
|
-
// }
|
|
75
|
-
|
|
76
|
-
// return dataTableMap[key] || '';
|
|
77
|
-
// };
|
|
78
|
-
|
|
79
|
-
// const getTestId = scenario => {
|
|
80
|
-
// if (scenario) {
|
|
81
|
-
// for (const tag of scenario.tags) {
|
|
82
|
-
// const testId = getTestomatIdFromTestTitle(tag.name);
|
|
83
|
-
// if (testId) return testId;
|
|
84
|
-
// }
|
|
85
|
-
// }
|
|
86
|
-
|
|
87
|
-
// return null;
|
|
88
|
-
// };
|
|
89
|
-
|
|
90
|
-
// return class TestomatFormatter extends Formatter {
|
|
91
|
-
// constructor(options) {
|
|
92
|
-
// super(options);
|
|
93
|
-
|
|
94
|
-
// if (!apiKey) return;
|
|
95
|
-
|
|
96
|
-
// this.client = new TestomatClient({ apiKey });
|
|
97
|
-
// this.status = STATUS.PASSED.toString();
|
|
98
|
-
|
|
99
|
-
// options.eventBroadcaster.on('gherkin-document', addDocument);
|
|
100
|
-
// options.eventBroadcaster.on('test-run-started', () => {
|
|
101
|
-
// fileSystem.clearDir(TESTOMAT_TMP_STORAGE_DIR);
|
|
102
|
-
// this?.client?.createRun();
|
|
103
|
-
// });
|
|
104
|
-
// options.eventBroadcaster.on('test-case-finished', this.onTestCaseFinished.bind(this));
|
|
105
|
-
// options.eventBroadcaster.on('test-case-started', this.onTestCaseStarted.bind(this));
|
|
106
|
-
// // @ts-ignore
|
|
107
|
-
// options.eventBroadcaster.on('test-run-finished', () => this?.client?.updateRunStatus(this.status));
|
|
108
|
-
|
|
109
|
-
// global.testomatioRunningEnvironment = 'cucumber:legacy';
|
|
110
|
-
// }
|
|
111
|
-
|
|
112
|
-
// onTestCaseStarted(event) {
|
|
113
|
-
// const scenario = getScenario(event.sourceLocation);
|
|
114
|
-
// const testId = getTestId(scenario);
|
|
115
|
-
|
|
116
|
-
// if (!global.testomatioDataStore) global.testomatioDataStore = {};
|
|
117
|
-
// global.testomatioDataStore.currentlyRunningTestId = testId;
|
|
118
|
-
// }
|
|
119
|
-
|
|
120
|
-
// onTestCaseFinished(event) {
|
|
121
|
-
// const scenario = getScenario(event.sourceLocation);
|
|
122
|
-
// const testId = getTestId(scenario);
|
|
123
|
-
// const status = event.result.status === 'undefined' ? STATUS.SKIPPED : event.result.status;
|
|
124
|
-
|
|
125
|
-
// let example = getDataTableMap(scenario, event.sourceLocation);
|
|
126
|
-
// if (example) example = JSON.parse(example);
|
|
127
|
-
|
|
128
|
-
// if (!scenario.name) return;
|
|
129
|
-
|
|
130
|
-
// const message = '';
|
|
131
|
-
// const cliMessage = `- ${scenario.name}: ${pc.bold(status.toUpperCase())}`;
|
|
132
|
-
|
|
133
|
-
// // if (event.result.status === 'undefined') {
|
|
134
|
-
// // cliMessage += pc.yellow(
|
|
135
|
-
// // ' (undefined steps. Run Cucumber without this formatter and implement missing steps)',
|
|
136
|
-
// // );
|
|
137
|
-
// // message = 'Undefined steps. Implement missing steps and rerun this scenario';
|
|
138
|
-
// // }
|
|
139
|
-
// console.log(cliMessage);
|
|
140
|
-
// if (status !== STATUS.PASSED && status !== STATUS.SKIPPED) {
|
|
141
|
-
// this.status = STATUS.FAILED;
|
|
142
|
-
// }
|
|
143
|
-
|
|
144
|
-
// this.client?.addTestRun(status, {
|
|
145
|
-
// error: event.result.exception instanceof Error ? event.result.exception : undefined,
|
|
146
|
-
// message,
|
|
147
|
-
// example,
|
|
148
|
-
// test_id: testId,
|
|
149
|
-
// title: getTitle(scenario),
|
|
150
|
-
// suite_title: getTitle(getFeature(event.sourceLocation.uri)),
|
|
151
|
-
// });
|
|
152
|
-
// }
|
|
153
|
-
// };
|
|
154
|
-
// };
|
|
155
|
-
|
|
156
|
-
// const CucumberLegacyReporter = createTestomatFormatter(config.TESTOMATIO);
|
|
157
|
-
// export { CucumberLegacyReporter };
|
|
158
|
-
// export default CucumberLegacyReporter;
|
package/src/adapter/cucumber.js
DELETED
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
import { STATUS } from '../../constants.js';
|
|
2
|
-
import { getTestomatIdFromTestTitle, parseSuite } from '../../utils/utils.js';
|
|
3
|
-
import TestomatClient from '../../client.js';
|
|
4
|
-
import { config } from '../../config.js';
|
|
5
|
-
|
|
6
|
-
const testomatioReporter = on => {
|
|
7
|
-
if (!config.TESTOMATIO) {
|
|
8
|
-
console.log('TESTOMATIO key is empty, ignoring reports');
|
|
9
|
-
return;
|
|
10
|
-
}
|
|
11
|
-
const client = new TestomatClient({ apiKey: config.TESTOMATIO });
|
|
12
|
-
|
|
13
|
-
on('before:run', async () => {
|
|
14
|
-
// TODO: looks like client.env does not exist
|
|
15
|
-
// if (!client.env) {
|
|
16
|
-
// client.env = `${run.browser.displayName},${run.system.osName}`;
|
|
17
|
-
// }
|
|
18
|
-
await client.createRun();
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
on('after:spec', async (_spec, results) => {
|
|
22
|
-
const addSpecTestsPromises = [];
|
|
23
|
-
|
|
24
|
-
const videos = [results.video];
|
|
25
|
-
|
|
26
|
-
for (const test of results.tests) {
|
|
27
|
-
const lastAttemptIndex = test.attempts.length - 1;
|
|
28
|
-
const latestAttempt = test.attempts[lastAttemptIndex];
|
|
29
|
-
|
|
30
|
-
// latestAttempt.duration && latestAttempt.error were available in adapters version up to 13 JFYI
|
|
31
|
-
const time = latestAttempt.duration || latestAttempt.wallClockDuration || test.duration;
|
|
32
|
-
let error = latestAttempt.error;
|
|
33
|
-
|
|
34
|
-
let title = test.title.pop();
|
|
35
|
-
const examples = title.match(/\(example (#\d+)\)/);
|
|
36
|
-
let example = null;
|
|
37
|
-
if (examples && examples[1]) example = { example: examples[1] };
|
|
38
|
-
title = title.replace(/\(example #\d+\)/, '').trim();
|
|
39
|
-
|
|
40
|
-
const suiteTitle = test.title.pop();
|
|
41
|
-
|
|
42
|
-
const testId = getTestomatIdFromTestTitle(title);
|
|
43
|
-
const suiteId = parseSuite(suiteTitle);
|
|
44
|
-
|
|
45
|
-
if (!error && test.displayError) {
|
|
46
|
-
error = { message: test.displayError };
|
|
47
|
-
error.inspect = function () {
|
|
48
|
-
return this.message;
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const formattedError = error
|
|
53
|
-
? {
|
|
54
|
-
message: error.message,
|
|
55
|
-
name: error.name,
|
|
56
|
-
inspect:
|
|
57
|
-
error.inspect ||
|
|
58
|
-
function () {
|
|
59
|
-
return this.message;
|
|
60
|
-
},
|
|
61
|
-
}
|
|
62
|
-
: undefined;
|
|
63
|
-
|
|
64
|
-
const screenshots = Array.isArray(results.screenshots)
|
|
65
|
-
? results.screenshots
|
|
66
|
-
.filter(screenshot => screenshot?.path && screenshot?.path.includes(title) && screenshot?.takenAt)
|
|
67
|
-
.map(screenshot => screenshot.path)
|
|
68
|
-
: [];
|
|
69
|
-
|
|
70
|
-
const files = [...videos, ...screenshots];
|
|
71
|
-
|
|
72
|
-
let state;
|
|
73
|
-
switch (test.state) {
|
|
74
|
-
case 'passed':
|
|
75
|
-
state = STATUS.PASSED;
|
|
76
|
-
break;
|
|
77
|
-
case 'failed':
|
|
78
|
-
state = STATUS.FAILED;
|
|
79
|
-
break;
|
|
80
|
-
case 'skipped':
|
|
81
|
-
case 'pending':
|
|
82
|
-
default:
|
|
83
|
-
state = STATUS.SKIPPED;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
addSpecTestsPromises.push(
|
|
87
|
-
client.addTestRun(state, {
|
|
88
|
-
title,
|
|
89
|
-
time,
|
|
90
|
-
example,
|
|
91
|
-
error: formattedError,
|
|
92
|
-
files,
|
|
93
|
-
suite_title: suiteTitle,
|
|
94
|
-
test_id: testId,
|
|
95
|
-
suite_id: suiteId,
|
|
96
|
-
}),
|
|
97
|
-
);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
await Promise.all(addSpecTestsPromises);
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
on('after:run', async results => {
|
|
104
|
-
const status = results.totalFailed ? STATUS.FAILED : STATUS.PASSED;
|
|
105
|
-
// @ts-ignore
|
|
106
|
-
await client.updateRunStatus(status);
|
|
107
|
-
});
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
export default testomatioReporter;
|
package/src/adapter/jasmine.js
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import TestomatClient from '../client.js';
|
|
2
|
-
import { getTestomatIdFromTestTitle, ansiRegExp } from '../utils/utils.js';
|
|
3
|
-
import { STATUS } from '../constants.js';
|
|
4
|
-
|
|
5
|
-
class JasmineReporter {
|
|
6
|
-
constructor(options) {
|
|
7
|
-
this.testTimeMap = {};
|
|
8
|
-
this.client = new TestomatClient({ apiKey: options?.apiKey });
|
|
9
|
-
this.client.createRun();
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
getDuration(test) {
|
|
13
|
-
if (this.testTimeMap[test.id]) {
|
|
14
|
-
return Date.now() - this.testTimeMap[test.id];
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
return 0;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
specStarted(result) {
|
|
21
|
-
this.testTimeMap[result.id] = Date.now();
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
specDone(result) {
|
|
25
|
-
if (!this.client) return;
|
|
26
|
-
|
|
27
|
-
const title = result.description;
|
|
28
|
-
const { status } = result;
|
|
29
|
-
let errorMessage = '';
|
|
30
|
-
|
|
31
|
-
for (let i = 0; i < result.failedExpectations.length; i += 1) {
|
|
32
|
-
errorMessage = `${errorMessage}Failure: ${result.failedExpectations[i].message}\n`;
|
|
33
|
-
errorMessage = `${errorMessage}\n ${result.failedExpectations[i].stack}`;
|
|
34
|
-
}
|
|
35
|
-
console.log(`${title} : ${STATUS.PASSED}`);
|
|
36
|
-
console.log(errorMessage);
|
|
37
|
-
const testId = getTestomatIdFromTestTitle(title);
|
|
38
|
-
errorMessage = errorMessage.replace(ansiRegExp(), '');
|
|
39
|
-
this.client.addTestRun(status, {
|
|
40
|
-
error: result.failedExpectations[0],
|
|
41
|
-
message: errorMessage,
|
|
42
|
-
test_id: testId,
|
|
43
|
-
title,
|
|
44
|
-
time: this.getDuration(result),
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
jasmineDone(suiteInfo, done) {
|
|
49
|
-
if (!this.client) return;
|
|
50
|
-
|
|
51
|
-
const { overallStatus } = suiteInfo;
|
|
52
|
-
const status = overallStatus === 'failed' ? STATUS.FAILED : STATUS.PASSED;
|
|
53
|
-
|
|
54
|
-
// @ts-ignore
|
|
55
|
-
this.client.updateRunStatus(status).then(() => done);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export { JasmineReporter };
|
|
60
|
-
export default JasmineReporter;
|
package/src/adapter/jest.js
DELETED
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
import pc from 'picocolors';
|
|
2
|
-
import TestomatClient from '../client.js';
|
|
3
|
-
import { TESTOMAT_TMP_STORAGE_DIR } from '../constants.js';
|
|
4
|
-
import { getTestomatIdFromTestTitle, ansiRegExp, fileSystem } from '../utils/utils.js';
|
|
5
|
-
import { services } from '../services/index.js';
|
|
6
|
-
import path from 'path';
|
|
7
|
-
import createDebugMessages from 'debug';
|
|
8
|
-
|
|
9
|
-
const debug = createDebugMessages('@testomatio/reporter:adapter-jest');
|
|
10
|
-
|
|
11
|
-
export class JestReporter {
|
|
12
|
-
constructor(globalConfig, options) {
|
|
13
|
-
this._globalConfig = globalConfig;
|
|
14
|
-
this._options = options;
|
|
15
|
-
|
|
16
|
-
this.client = new TestomatClient({ apiKey: options?.apiKey });
|
|
17
|
-
this.client.createRun();
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
onRunStart() {
|
|
21
|
-
// clear tmp dir
|
|
22
|
-
fileSystem.clearDir(TESTOMAT_TMP_STORAGE_DIR);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
// start of test file (including beforeAll)
|
|
26
|
-
onTestStart(testFile) {
|
|
27
|
-
debug('Start running test file:', testFile.path);
|
|
28
|
-
services.setContext(testFile.path);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// start of the test (including beforeEach)
|
|
32
|
-
onTestCaseStart(test, testCase) {
|
|
33
|
-
debug('Start running test:', testCase.fullName);
|
|
34
|
-
services.setContext(testCase.fullName);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// end of test file! (there is also onTestCaseResult listener)
|
|
38
|
-
onTestResult(test, testResult) {
|
|
39
|
-
if (!this.client) return;
|
|
40
|
-
|
|
41
|
-
const { testResults } = testResult;
|
|
42
|
-
for (const result of testResults) {
|
|
43
|
-
let error;
|
|
44
|
-
let steps;
|
|
45
|
-
const { status, title, duration, failureMessages } = result;
|
|
46
|
-
if (failureMessages[0]) {
|
|
47
|
-
let errorMessage = failureMessages[0].replace(ansiRegExp(), '');
|
|
48
|
-
errorMessage = errorMessage.split('\n')[0];
|
|
49
|
-
error = new Error(errorMessage);
|
|
50
|
-
steps = failureMessages[0];
|
|
51
|
-
}
|
|
52
|
-
const testId = getTestomatIdFromTestTitle(title);
|
|
53
|
-
|
|
54
|
-
// suite titles from most outer to most inner, separated by space
|
|
55
|
-
let fullSuiteTitle = testResult.ancestorTitles?.join(' ');
|
|
56
|
-
// if no suite titles, use file name
|
|
57
|
-
if (!fullSuiteTitle && testResult.testFilePath) fullSuiteTitle = path.basename(testResult.testFilePath);
|
|
58
|
-
|
|
59
|
-
const logs = getTestLogs(result);
|
|
60
|
-
const artifacts = services.artifacts.get(result.fullName);
|
|
61
|
-
const keyValues = services.keyValues.get(result.fullName);
|
|
62
|
-
|
|
63
|
-
const deducedStatus = status === 'pending' ? 'skipped' : status;
|
|
64
|
-
// In jest if test is not matched with test name pattern it is considered as skipped.
|
|
65
|
-
// So adding a check if it is skipped for real or because of test pattern
|
|
66
|
-
if (!this._globalConfig.testNamePattern || deducedStatus !== 'skipped') {
|
|
67
|
-
this.client.addTestRun(deducedStatus, {
|
|
68
|
-
test_id: testId,
|
|
69
|
-
suite_title: fullSuiteTitle,
|
|
70
|
-
error,
|
|
71
|
-
steps,
|
|
72
|
-
title,
|
|
73
|
-
time: duration,
|
|
74
|
-
logs,
|
|
75
|
-
manuallyAttachedArtifacts: artifacts,
|
|
76
|
-
meta: keyValues,
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
onRunComplete(contexts, results) {
|
|
83
|
-
if (!this.client) return;
|
|
84
|
-
|
|
85
|
-
const { numFailedTests } = results;
|
|
86
|
-
const status = numFailedTests === 0 ? 'passed' : 'failed';
|
|
87
|
-
this.client.updateRunStatus(status);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function getTestLogs(testResult) {
|
|
92
|
-
const suiteLogsArr = services.logger.getLogs(testResult.testFilePath);
|
|
93
|
-
const suiteLogs = suiteLogsArr ? suiteLogsArr.join('\n').trim() : '';
|
|
94
|
-
const testLogsArr = services.logger.getLogs(testResult.fullName);
|
|
95
|
-
const testLogs = testLogsArr ? testLogsArr.join('\n').trim() : '';
|
|
96
|
-
|
|
97
|
-
let logs = '';
|
|
98
|
-
if (suiteLogs) {
|
|
99
|
-
logs += `${pc.bold('\t--- Suite ---')}\n${suiteLogs}`;
|
|
100
|
-
}
|
|
101
|
-
if (testLogs) {
|
|
102
|
-
logs += `\n${pc.bold('\t--- Test ---')}\n${testLogs}`;
|
|
103
|
-
}
|
|
104
|
-
return logs;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
export default JestReporter;
|
package/src/adapter/mocha.cjs
DELETED
package/src/adapter/mocha.js
DELETED
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
import Mocha from 'mocha';
|
|
2
|
-
import TestomatClient from '../client.js';
|
|
3
|
-
import { STATUS, TESTOMAT_TMP_STORAGE_DIR } from '../constants.js';
|
|
4
|
-
import { getTestomatIdFromTestTitle, fileSystem } from '../utils/utils.js';
|
|
5
|
-
import { config } from '../config.js';
|
|
6
|
-
import { services } from '../services/index.js';
|
|
7
|
-
import pc from 'picocolors';
|
|
8
|
-
|
|
9
|
-
const {
|
|
10
|
-
EVENT_RUN_BEGIN,
|
|
11
|
-
EVENT_RUN_END,
|
|
12
|
-
EVENT_TEST_FAIL,
|
|
13
|
-
EVENT_TEST_PASS,
|
|
14
|
-
EVENT_TEST_PENDING,
|
|
15
|
-
EVENT_SUITE_BEGIN,
|
|
16
|
-
EVENT_SUITE_END,
|
|
17
|
-
EVENT_TEST_BEGIN,
|
|
18
|
-
EVENT_TEST_END,
|
|
19
|
-
} = Mocha.Runner.constants;
|
|
20
|
-
|
|
21
|
-
function MochaReporter(runner, opts) {
|
|
22
|
-
Mocha.reporters.Base.call(this, runner);
|
|
23
|
-
let passes = 0;
|
|
24
|
-
let failures = 0;
|
|
25
|
-
let skipped = 0;
|
|
26
|
-
// let artifactStore;
|
|
27
|
-
|
|
28
|
-
const apiKey = opts?.reporterOptions?.apiKey || config.TESTOMATIO;
|
|
29
|
-
|
|
30
|
-
const client = new TestomatClient({ apiKey });
|
|
31
|
-
|
|
32
|
-
runner.on(EVENT_RUN_BEGIN, () => {
|
|
33
|
-
client.createRun();
|
|
34
|
-
|
|
35
|
-
// clear dir with artifacts/logs
|
|
36
|
-
fileSystem.clearDir(TESTOMAT_TMP_STORAGE_DIR);
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
runner.on(EVENT_SUITE_BEGIN, async suite => {
|
|
40
|
-
services.setContext(suite.fullTitle());
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
runner.on(EVENT_SUITE_END, async () => {
|
|
44
|
-
services.setContext(null);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
runner.on(EVENT_TEST_BEGIN, async test => {
|
|
48
|
-
services.setContext(test.fullTitle());
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
runner.on(EVENT_TEST_END, async () => {
|
|
52
|
-
services.setContext(null);
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
runner.on(EVENT_TEST_PASS, async test => {
|
|
56
|
-
passes += 1;
|
|
57
|
-
|
|
58
|
-
console.log(pc.bold(pc.green('✔')), test.fullTitle());
|
|
59
|
-
const testId = getTestomatIdFromTestTitle(test.title);
|
|
60
|
-
|
|
61
|
-
const logs = getTestLogs(test);
|
|
62
|
-
const artifacts = services.artifacts.get(test.fullTitle());
|
|
63
|
-
const keyValues = services.keyValues.get(test.fullTitle());
|
|
64
|
-
|
|
65
|
-
client.addTestRun(STATUS.PASSED, {
|
|
66
|
-
test_id: testId,
|
|
67
|
-
suite_title: getSuiteTitle(test),
|
|
68
|
-
title: getTestName(test),
|
|
69
|
-
code: process.env.TESTOMATIO_UPDATE_CODE ? test.body.toString() : '',
|
|
70
|
-
file: getFile(test),
|
|
71
|
-
time: test.duration,
|
|
72
|
-
logs,
|
|
73
|
-
manuallyAttachedArtifacts: artifacts,
|
|
74
|
-
meta: keyValues,
|
|
75
|
-
});
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
runner.on(EVENT_TEST_PENDING, test => {
|
|
79
|
-
skipped += 1;
|
|
80
|
-
console.log('skip: %s', test.fullTitle());
|
|
81
|
-
const testId = getTestomatIdFromTestTitle(test.title);
|
|
82
|
-
client.addTestRun(STATUS.SKIPPED, {
|
|
83
|
-
title: getTestName(test),
|
|
84
|
-
suite_title: getSuiteTitle(test),
|
|
85
|
-
code: process.env.TESTOMATIO_UPDATE_CODE ? test.body.toString() : '',
|
|
86
|
-
file: getFile(test),
|
|
87
|
-
test_id: testId,
|
|
88
|
-
time: test.duration,
|
|
89
|
-
});
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
runner.on(EVENT_TEST_FAIL, async (test, err) => {
|
|
93
|
-
failures += 1;
|
|
94
|
-
console.log(pc.bold(pc.red('✖')), test.fullTitle(), pc.gray(err.message));
|
|
95
|
-
const testId = getTestomatIdFromTestTitle(test.title);
|
|
96
|
-
|
|
97
|
-
const logs = getTestLogs(test);
|
|
98
|
-
|
|
99
|
-
client.addTestRun(STATUS.FAILED, {
|
|
100
|
-
error: err,
|
|
101
|
-
suite_title: getSuiteTitle(test),
|
|
102
|
-
file: getFile(test),
|
|
103
|
-
test_id: testId,
|
|
104
|
-
title: getTestName(test),
|
|
105
|
-
code: process.env.TESTOMATIO_UPDATE_CODE ? test.body.toString() : '',
|
|
106
|
-
time: test.duration,
|
|
107
|
-
logs,
|
|
108
|
-
});
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
runner.on(EVENT_RUN_END, () => {
|
|
112
|
-
const status = failures === 0 ? STATUS.PASSED : STATUS.FAILED;
|
|
113
|
-
console.log(pc.bold(status), `${passes} passed, ${failures} failed, ${skipped} skipped`);
|
|
114
|
-
// @ts-ignore
|
|
115
|
-
client.updateRunStatus(status);
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
function getTestLogs(test) {
|
|
120
|
-
const suiteLogsArr = services.logger.getLogs(test.parent.fullTitle());
|
|
121
|
-
const suiteLogs = suiteLogsArr ? suiteLogsArr.join('\n').trim() : '';
|
|
122
|
-
const testLogsArr = services.logger.getLogs(test.fullTitle());
|
|
123
|
-
const testLogs = testLogsArr ? testLogsArr.join('\n').trim() : '';
|
|
124
|
-
|
|
125
|
-
let logs = '';
|
|
126
|
-
if (suiteLogs) {
|
|
127
|
-
logs += `${pc.bold('\t--- BeforeSuite ---')}\n${suiteLogs}`;
|
|
128
|
-
}
|
|
129
|
-
if (testLogs) {
|
|
130
|
-
logs += `\n${pc.bold('\t--- Test ---')}\n${testLogs}`;
|
|
131
|
-
}
|
|
132
|
-
return logs;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
function getSuiteTitle(test, pathArr = []) {
|
|
136
|
-
if (test.parent.parent) getSuiteTitle(test.parent, pathArr);
|
|
137
|
-
|
|
138
|
-
pathArr.push(test.parent.title);
|
|
139
|
-
|
|
140
|
-
return pathArr.filter(t => !!t)[0];
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
function getFile(test) {
|
|
144
|
-
return test.parent.file?.replace(process.cwd(), '');
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
function getTestName(test) {
|
|
148
|
-
if (process.env.TESTOMATIO_CREATE === 'fulltitle') return test.fullTitle();
|
|
149
|
-
return test.title;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// To have this reporter "extend" a built-in reporter uncomment the following line:
|
|
153
|
-
// @ts-ignore
|
|
154
|
-
Mocha.utils.inherits(MochaReporter, Mocha.reporters.Spec);
|
|
155
|
-
|
|
156
|
-
export default MochaReporter;
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import TestomatClient from '../client.js';
|
|
2
|
-
import { config } from '../config.js';
|
|
3
|
-
import { STATUS } from '../constants.js';
|
|
4
|
-
import { getTestomatIdFromTestTitle } from '../utils/utils.js';
|
|
5
|
-
|
|
6
|
-
const apiKey = config.TESTOMATIO;
|
|
7
|
-
const client = new TestomatClient({ apiKey });
|
|
8
|
-
|
|
9
|
-
export default {
|
|
10
|
-
write: async (results, options, done) => {
|
|
11
|
-
await client.createRun();
|
|
12
|
-
|
|
13
|
-
const testFiles = results.modules;
|
|
14
|
-
|
|
15
|
-
for (const fileName in testFiles) {
|
|
16
|
-
// in nightwatch: object containing tests from a single file
|
|
17
|
-
const testModule = testFiles[fileName];
|
|
18
|
-
|
|
19
|
-
// passed and failed tests (tests with assertions)
|
|
20
|
-
const completedTests = testModule.completed;
|
|
21
|
-
|
|
22
|
-
// skipped tests (skipped by user or tests without assertions)
|
|
23
|
-
const skippedTests = testModule.skipped;
|
|
24
|
-
|
|
25
|
-
const tags = testModule.tags || [];
|
|
26
|
-
|
|
27
|
-
// if test file contains multiple suites, the last suite name is used as a name 🤷♂️
|
|
28
|
-
// no other places which contain suite name (even inside test object)
|
|
29
|
-
const suiteTitle = testModule.name;
|
|
30
|
-
|
|
31
|
-
for (const testTitle in completedTests) {
|
|
32
|
-
const test = completedTests[testTitle];
|
|
33
|
-
let status;
|
|
34
|
-
switch (test.status) {
|
|
35
|
-
case 'pass':
|
|
36
|
-
status = STATUS.PASSED;
|
|
37
|
-
break;
|
|
38
|
-
case 'fail':
|
|
39
|
-
status = STATUS.FAILED;
|
|
40
|
-
break;
|
|
41
|
-
// probably not required (because skipped tests are in separate array), but just in case
|
|
42
|
-
case 'skip':
|
|
43
|
-
status = STATUS.SKIPPED;
|
|
44
|
-
console.info('Skipped test is in completed tests array:', test, 'Not expected behavior.');
|
|
45
|
-
break;
|
|
46
|
-
default:
|
|
47
|
-
console.error('Test status processing error:', test.status);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const testId = getTestomatIdFromTestTitle(testTitle);
|
|
51
|
-
|
|
52
|
-
client.addTestRun(status, {
|
|
53
|
-
error: { name: test.assertions?.[0]?.name, message: test.assertions?.[0]?.message, stack: test.stackTrace },
|
|
54
|
-
file: testModule.modulePath?.replace(process.cwd(), ''),
|
|
55
|
-
message: test.assertions?.[0]?.message,
|
|
56
|
-
rid: `${testModule.uuid || ''}_${testTitle || ''}`,
|
|
57
|
-
stack: test.stackTrace,
|
|
58
|
-
suite_title: suiteTitle,
|
|
59
|
-
tags,
|
|
60
|
-
test_id: testId,
|
|
61
|
-
time: test.timeMs,
|
|
62
|
-
title: testTitle,
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// just array with skipped tests titles, no any other info
|
|
67
|
-
for (const testTitle of skippedTests) {
|
|
68
|
-
client.addTestRun(STATUS.SKIPPED, {
|
|
69
|
-
suite_title: suiteTitle,
|
|
70
|
-
tags,
|
|
71
|
-
rid: `${testModule.uuid || ''}_${testTitle || ''}`,
|
|
72
|
-
title: testTitle,
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* @type {'passed' | 'failed' | 'finished'}
|
|
79
|
-
*/
|
|
80
|
-
let runStatus = 'finished';
|
|
81
|
-
if (results.failed) runStatus = 'failed';
|
|
82
|
-
else if (results.passed) runStatus = 'passed';
|
|
83
|
-
|
|
84
|
-
await client.updateRunStatus(runStatus);
|
|
85
|
-
|
|
86
|
-
done();
|
|
87
|
-
},
|
|
88
|
-
};
|