@testomatio/reporter 0.8.0-beta.9 → 0.8.2-beta.1
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/Changelog.md +251 -0
- package/README.md +77 -7
- package/lib/ArtifactStorage.js +131 -0
- package/lib/adapter/codecept.js +25 -24
- package/lib/adapter/cucumber/current.js +16 -12
- package/lib/adapter/cucumber/legacy.js +14 -10
- package/lib/adapter/cypress-plugin/index.js +7 -7
- package/lib/adapter/jasmine.js +5 -4
- package/lib/adapter/jest.js +7 -11
- package/lib/adapter/mocha.js +69 -18
- package/lib/adapter/playwright.js +28 -31
- package/lib/adapter/webdriver.js +2 -1
- package/lib/bin/reportXml.js +5 -2
- package/lib/bin/startTest.js +2 -2
- package/lib/client.js +73 -49
- package/lib/constants.js +17 -2
- package/lib/fileUploader.js +103 -64
- package/lib/junit-adapter/csharp.js +0 -1
- package/lib/junit-adapter/index.js +3 -2
- package/lib/pipe/csv.js +133 -0
- package/lib/pipe/github.js +137 -73
- package/lib/pipe/gitlab.js +229 -0
- package/lib/pipe/index.js +27 -12
- package/lib/pipe/testomatio.js +71 -44
- package/lib/reporter.js +2 -0
- package/lib/util.js +46 -13
- package/lib/xmlReader.js +47 -31
- package/package.json +12 -3
- package/testcafe/index.js +0 -61
- package/testcafe/package.json +0 -14
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
const { Formatter, formatterHelpers } = require("@cucumber/cucumber");
|
|
3
3
|
const chalk = require('chalk');
|
|
4
4
|
const fs = require('fs');
|
|
5
|
-
const {
|
|
5
|
+
const { STATUS } = require('../../constants');
|
|
6
|
+
const TestomatClient = require('../../client');
|
|
6
7
|
|
|
7
8
|
const { GherkinDocumentParser, PickleParser } = formatterHelpers
|
|
8
9
|
const {
|
|
@@ -19,7 +20,7 @@ class CucumberReporter extends Formatter {
|
|
|
19
20
|
this.cases = [];
|
|
20
21
|
|
|
21
22
|
this.client = new TestomatClient();
|
|
22
|
-
this.status =
|
|
23
|
+
this.status = STATUS.PASSED;
|
|
23
24
|
|
|
24
25
|
}
|
|
25
26
|
|
|
@@ -33,7 +34,8 @@ class CucumberReporter extends Formatter {
|
|
|
33
34
|
const testCaseAttempt = this.eventDataCollector.getTestCaseAttempt(testCaseFinished.testCaseStartedId);
|
|
34
35
|
|
|
35
36
|
let example;
|
|
36
|
-
|
|
37
|
+
|
|
38
|
+
let status = STATUS.PASSED;
|
|
37
39
|
let color = 'green';
|
|
38
40
|
let message;
|
|
39
41
|
|
|
@@ -41,22 +43,23 @@ class CucumberReporter extends Formatter {
|
|
|
41
43
|
|
|
42
44
|
if (testCaseAttempt.worstTestStepResult) {
|
|
43
45
|
if (testCaseAttempt.worstTestStepResult.status === 'SKIPPED') {
|
|
44
|
-
status =
|
|
46
|
+
status = STATUS.SKIPPED;
|
|
45
47
|
}
|
|
46
48
|
if (testCaseAttempt.worstTestStepResult.status === 'UNDEFINED') {
|
|
47
|
-
status =
|
|
49
|
+
status = STATUS.SKIPPED;
|
|
48
50
|
message = 'Undefined steps. Implement missing steps and rerun this scenario';
|
|
49
51
|
}
|
|
50
52
|
if (testCaseAttempt.worstTestStepResult.status === 'FAILED') {
|
|
51
53
|
message = testCaseAttempt?.worstTestStepResult?.message;
|
|
52
|
-
status =
|
|
54
|
+
status = STATUS.FAILED;
|
|
53
55
|
}
|
|
54
56
|
color = getStatusColor(testCaseAttempt.worstTestStepResult.status);
|
|
55
|
-
if (status !==
|
|
57
|
+
if (status !== STATUS.PASSED) this.failures.push(testCaseAttempt);
|
|
56
58
|
}
|
|
57
59
|
|
|
58
60
|
if (testCaseAttempt.pickle.astNodeIds.length > 1) {
|
|
59
61
|
example = getExample(testCaseAttempt);
|
|
62
|
+
// @ts-ignore
|
|
60
63
|
testCaseAttempt.example = example;
|
|
61
64
|
}
|
|
62
65
|
|
|
@@ -70,8 +73,8 @@ class CucumberReporter extends Formatter {
|
|
|
70
73
|
if (message) cliMessage += chalk.gray(message.split('\n')[0]);
|
|
71
74
|
console.log(cliMessage);
|
|
72
75
|
|
|
73
|
-
if (status !==
|
|
74
|
-
this.status =
|
|
76
|
+
if (status !== STATUS.PASSED && status !== STATUS.SKIPPED) {
|
|
77
|
+
this.status = STATUS.FAILED;
|
|
75
78
|
}
|
|
76
79
|
|
|
77
80
|
const time = Object.values(testCaseAttempt.stepResults)
|
|
@@ -80,12 +83,13 @@ class CucumberReporter extends Formatter {
|
|
|
80
83
|
|
|
81
84
|
if (!this.client) return;
|
|
82
85
|
|
|
83
|
-
this.client.addTestRun(
|
|
86
|
+
this.client.addTestRun(status, {
|
|
84
87
|
// error: testCaseAttempt.worstTestStepResult.message,
|
|
85
88
|
message,
|
|
86
89
|
steps: getSteps(testCaseAttempt).map(s => s.toString()).join('\n').trim(),
|
|
87
90
|
example: { ...example},
|
|
88
91
|
title: scenario,
|
|
92
|
+
test_id: testId,
|
|
89
93
|
time,
|
|
90
94
|
});
|
|
91
95
|
}
|
|
@@ -121,9 +125,9 @@ class CucumberReporter extends Formatter {
|
|
|
121
125
|
|
|
122
126
|
if (!this.client) return;
|
|
123
127
|
|
|
124
|
-
this.client.updateRunStatus(testRunFinished.success ?
|
|
128
|
+
this.client.updateRunStatus(testRunFinished.success ? STATUS.PASSED : STATUS.FAILED)
|
|
125
129
|
}
|
|
126
|
-
}
|
|
130
|
+
}
|
|
127
131
|
|
|
128
132
|
function getSteps(tc) {
|
|
129
133
|
const stepIds = Object.keys(tc.stepResults);
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
// eslint-disable-next-line import/no-unresolved
|
|
1
|
+
// eslint-disable-next-line global-require, import/no-extraneous-dependencies, import/no-unresolved
|
|
2
2
|
const { Formatter } = require('cucumber');
|
|
3
3
|
const chalk = require('chalk');
|
|
4
|
-
const { TestomatClient, TRConstants } = require('../../reporter');
|
|
5
4
|
const { parseTest } = require('../../util');
|
|
5
|
+
const { STATUS } = require('../../constants');
|
|
6
|
+
const TestomatClient = require('../../client');
|
|
6
7
|
|
|
7
8
|
const createTestomatFormatter = apiKey => {
|
|
8
9
|
if (!apiKey || apiKey === '') {
|
|
@@ -92,18 +93,18 @@ const createTestomatFormatter = apiKey => {
|
|
|
92
93
|
if (!apiKey) return;
|
|
93
94
|
|
|
94
95
|
this.client = new TestomatClient({ apiKey });
|
|
95
|
-
this.status =
|
|
96
|
+
this.status = STATUS.PASSED.toString();
|
|
96
97
|
|
|
97
98
|
options.eventBroadcaster.on('gherkin-document', addDocument);
|
|
98
|
-
options.eventBroadcaster.on('test-run-started', () => this
|
|
99
|
+
options.eventBroadcaster.on('test-run-started', () => this?.client?.createRun());
|
|
99
100
|
options.eventBroadcaster.on('test-case-finished', this.onTestCaseFinished.bind(this));
|
|
100
|
-
options.eventBroadcaster.on('test-run-finished', () => this
|
|
101
|
+
options.eventBroadcaster.on('test-run-finished', () => this?.client?.updateRunStatus(this.status));
|
|
101
102
|
}
|
|
102
103
|
|
|
103
104
|
onTestCaseFinished(event) {
|
|
104
105
|
const scenario = getScenario(event.sourceLocation);
|
|
105
106
|
const testId = getTestId(scenario);
|
|
106
|
-
const status = event.result.status === 'undefined' ?
|
|
107
|
+
const status = event.result.status === 'undefined' ? STATUS.SKIPPED : event.result.status;
|
|
107
108
|
|
|
108
109
|
let example = getDataTableMap(scenario, event.sourceLocation);
|
|
109
110
|
if (example) example = JSON.parse(example);
|
|
@@ -120,14 +121,17 @@ const createTestomatFormatter = apiKey => {
|
|
|
120
121
|
message = 'Undefined steps. Implement missing steps and rerun this scenario';
|
|
121
122
|
}
|
|
122
123
|
console.log(cliMessage);
|
|
123
|
-
if (status !==
|
|
124
|
-
this.status =
|
|
124
|
+
if (status !== STATUS.PASSED && status !== STATUS.SKIPPED) {
|
|
125
|
+
this.status = STATUS.FAILED;
|
|
125
126
|
}
|
|
126
|
-
|
|
127
|
-
|
|
127
|
+
|
|
128
|
+
this.client?.addTestRun(status, {
|
|
129
|
+
error: event.result.exception instanceof Error ? event.result.exception : undefined,
|
|
128
130
|
message,
|
|
129
131
|
example,
|
|
132
|
+
test_id: testId,
|
|
130
133
|
title: getTitle(scenario),
|
|
134
|
+
suite_title: getTitle(getFeature(event.sourceLocation.uri)),
|
|
131
135
|
});
|
|
132
136
|
}
|
|
133
137
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
1
|
+
const { STATUS } = require('../../constants');
|
|
2
2
|
const { parseTest, parseSuite } = require('../../util');
|
|
3
3
|
const TestomatClient = require('../../client');
|
|
4
4
|
|
|
@@ -57,16 +57,16 @@ const testomatioReporter = on => {
|
|
|
57
57
|
|
|
58
58
|
let state;
|
|
59
59
|
switch (test.state) {
|
|
60
|
-
case 'passed': state =
|
|
61
|
-
case 'failed': state =
|
|
60
|
+
case 'passed': state = STATUS.PASSED; break;
|
|
61
|
+
case 'failed': state = STATUS.FAILED; break;
|
|
62
62
|
case 'skipped':
|
|
63
63
|
case 'pending':
|
|
64
64
|
default:
|
|
65
|
-
state =
|
|
65
|
+
state = STATUS.SKIPPED;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
addSpecTestsPromises.push(client.addTestRun(
|
|
69
|
-
title, time, example, error, files, suite_title: suiteTitle, suite_id: suiteId
|
|
68
|
+
addSpecTestsPromises.push(client.addTestRun(state, {
|
|
69
|
+
title, time, example, error, files, suite_title: suiteTitle, test_id: testId, suite_id: suiteId
|
|
70
70
|
}));
|
|
71
71
|
}
|
|
72
72
|
|
|
@@ -74,7 +74,7 @@ const testomatioReporter = on => {
|
|
|
74
74
|
});
|
|
75
75
|
|
|
76
76
|
on('after:run', async results => {
|
|
77
|
-
const status = results.totalFailed ?
|
|
77
|
+
const status = results.totalFailed ? STATUS.FAILED : STATUS.PASSED;
|
|
78
78
|
await client.updateRunStatus(status);
|
|
79
79
|
});
|
|
80
80
|
};
|
package/lib/adapter/jasmine.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const TestomatClient = require('../client');
|
|
2
2
|
const { parseTest, ansiRegExp } = require('../util');
|
|
3
|
-
const {
|
|
3
|
+
const { STATUS } = require('../constants');
|
|
4
4
|
|
|
5
5
|
class JasmineReporter {
|
|
6
6
|
constructor(options) {
|
|
@@ -32,13 +32,14 @@ class JasmineReporter {
|
|
|
32
32
|
errorMessage = `${errorMessage}Failure: ${result.failedExpectations[i].message}\n`;
|
|
33
33
|
errorMessage = `${errorMessage}\n ${result.failedExpectations[i].stack}`;
|
|
34
34
|
}
|
|
35
|
-
console.log(`${title} : ${PASSED}`);
|
|
35
|
+
console.log(`${title} : ${STATUS.PASSED}`);
|
|
36
36
|
console.log(errorMessage);
|
|
37
37
|
const testId = parseTest(title);
|
|
38
38
|
errorMessage = errorMessage.replace(ansiRegExp(), '');
|
|
39
|
-
this.client.addTestRun(
|
|
39
|
+
this.client.addTestRun(status, {
|
|
40
40
|
error: result.failedExpectations[0],
|
|
41
41
|
message: errorMessage,
|
|
42
|
+
test_id: testId,
|
|
42
43
|
title,
|
|
43
44
|
time: this.getDuration(result),
|
|
44
45
|
});
|
|
@@ -48,7 +49,7 @@ class JasmineReporter {
|
|
|
48
49
|
if (!this.client) return;
|
|
49
50
|
|
|
50
51
|
const { overallStatus } = suiteInfo;
|
|
51
|
-
const status = overallStatus === 'failed' ? FAILED : PASSED;
|
|
52
|
+
const status = overallStatus === 'failed' ? STATUS.FAILED : STATUS.PASSED;
|
|
52
53
|
|
|
53
54
|
this.client.updateRunStatus(status).then(() => done);
|
|
54
55
|
}
|
package/lib/adapter/jest.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const TestomatClient = require('../client');
|
|
2
|
-
const
|
|
2
|
+
const { STATUS } = require('../constants');
|
|
3
3
|
const { parseTest, ansiRegExp } = require('../util');
|
|
4
4
|
|
|
5
5
|
class JestReporter {
|
|
@@ -16,26 +16,22 @@ class JestReporter {
|
|
|
16
16
|
|
|
17
17
|
const { testResults } = testResult;
|
|
18
18
|
for (const result of testResults) {
|
|
19
|
-
let error
|
|
20
|
-
let steps
|
|
19
|
+
let error;
|
|
20
|
+
let steps;
|
|
21
21
|
const { status, title, duration, failureMessages } = result;
|
|
22
22
|
if (failureMessages[0]) {
|
|
23
23
|
let errorMessage = failureMessages[0].replace(ansiRegExp(), '');
|
|
24
24
|
errorMessage = errorMessage.split('\n')[0];
|
|
25
|
-
error =
|
|
26
|
-
message: errorMessage,
|
|
27
|
-
};
|
|
25
|
+
error = new Error(errorMessage);
|
|
28
26
|
steps = failureMessages[0];
|
|
29
27
|
}
|
|
30
28
|
const testId = parseTest(title);
|
|
31
29
|
const deducedStatus = status === 'pending' ? 'skipped' : status;
|
|
32
|
-
|
|
33
|
-
const suite_title = result.ancestorTitles && result.ancestorTitles[result.ancestorTitles.length - 1];
|
|
34
30
|
// In jest if test is not matched with test name pattern it is considered as skipped.
|
|
35
31
|
// So adding a check if it is skipped for real or because of test pattern
|
|
36
32
|
if (!this._globalConfig.testNamePattern || deducedStatus !== 'skipped') {
|
|
37
|
-
this.client.addTestRun(
|
|
38
|
-
|
|
33
|
+
this.client.addTestRun(deducedStatus, {
|
|
34
|
+
test_id: testId,
|
|
39
35
|
error,
|
|
40
36
|
steps,
|
|
41
37
|
title,
|
|
@@ -49,7 +45,7 @@ class JestReporter {
|
|
|
49
45
|
if (!this.client) return;
|
|
50
46
|
|
|
51
47
|
const { numFailedTests } = results;
|
|
52
|
-
const status = numFailedTests === 0 ?
|
|
48
|
+
const status = numFailedTests === 0 ? STATUS.PASSED : STATUS.FAILED;
|
|
53
49
|
this.client.updateRunStatus(status);
|
|
54
50
|
}
|
|
55
51
|
}
|
package/lib/adapter/mocha.js
CHANGED
|
@@ -1,47 +1,98 @@
|
|
|
1
1
|
// eslint-disable-next-line global-require, import/no-extraneous-dependencies
|
|
2
2
|
const Mocha = require('mocha');
|
|
3
|
+
const debug = require('debug')('@testomatio/reporter:adapter:mocha');
|
|
4
|
+
const chalk = require('chalk');
|
|
3
5
|
const TestomatClient = require('../client');
|
|
4
|
-
const
|
|
5
|
-
const { parseTest } = require('../util');
|
|
6
|
+
const { STATUS } = require('../constants');
|
|
7
|
+
const { parseTest, specificTestInfo } = require('../util');
|
|
8
|
+
const ArtifactStorage = require('../ArtifactStorage');
|
|
6
9
|
|
|
7
|
-
const { EVENT_RUN_BEGIN, EVENT_RUN_END, EVENT_TEST_FAIL, EVENT_TEST_PASS } = Mocha.Runner.constants;
|
|
10
|
+
const { EVENT_RUN_BEGIN, EVENT_RUN_END, EVENT_TEST_FAIL, EVENT_TEST_PASS, EVENT_TEST_PENDING } = Mocha.Runner.constants;
|
|
8
11
|
|
|
9
12
|
function MochaReporter(runner, opts) {
|
|
10
13
|
Mocha.reporters.Base.call(this, runner);
|
|
11
|
-
let passes = 0;
|
|
12
|
-
let
|
|
14
|
+
let passes = 0; let failures = 0; let skipped = 0;
|
|
15
|
+
let artifactStore;
|
|
13
16
|
|
|
14
|
-
const
|
|
17
|
+
const apiKey = opts?.reporterOptions?.apiKey || process.env.TESTOMATIO;
|
|
18
|
+
|
|
19
|
+
if (!apiKey) {
|
|
20
|
+
debug('TESTOMATIO key is empty, ignoring reports');
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
const client = new TestomatClient({ apiKey });
|
|
15
24
|
|
|
16
25
|
runner.on(EVENT_RUN_BEGIN, () => {
|
|
17
26
|
client.createRun();
|
|
27
|
+
|
|
28
|
+
const params = {
|
|
29
|
+
toFile: true
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
artifactStore = runner._workerReporter !== undefined
|
|
33
|
+
? new ArtifactStorage(params)
|
|
34
|
+
: new ArtifactStorage();
|
|
18
35
|
});
|
|
19
36
|
|
|
20
|
-
runner.on(EVENT_TEST_PASS, test => {
|
|
37
|
+
runner.on(EVENT_TEST_PASS, async(test) => {
|
|
21
38
|
passes += 1;
|
|
22
|
-
console.log('
|
|
39
|
+
console.log(chalk.bold.green('✔'), test.fullTitle());
|
|
40
|
+
const testId = parseTest(test.title);
|
|
41
|
+
|
|
42
|
+
const specificTest = specificTestInfo(test);
|
|
43
|
+
const content = await artifactStore.artifactByTestName(specificTest);
|
|
44
|
+
|
|
45
|
+
debug(`test=${specificTest} content = `, content);
|
|
46
|
+
|
|
47
|
+
client.addTestRun(
|
|
48
|
+
STATUS.PASSED,
|
|
49
|
+
{
|
|
50
|
+
test_id: testId,
|
|
51
|
+
title: test.title,
|
|
52
|
+
time: test.duration,
|
|
53
|
+
},
|
|
54
|
+
content
|
|
55
|
+
);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
runner.on(EVENT_TEST_PENDING, test => {
|
|
59
|
+
skipped += 1;
|
|
60
|
+
console.log('skip: %s', test.fullTitle());
|
|
23
61
|
const testId = parseTest(test.title);
|
|
24
|
-
client.addTestRun(
|
|
62
|
+
client.addTestRun(STATUS.SKIPPED, {
|
|
25
63
|
title: test.title,
|
|
64
|
+
test_id: testId,
|
|
26
65
|
time: test.duration,
|
|
27
66
|
});
|
|
28
67
|
});
|
|
29
68
|
|
|
30
|
-
runner.on(EVENT_TEST_FAIL, (test, err) => {
|
|
69
|
+
runner.on(EVENT_TEST_FAIL, async(test, err) => {
|
|
31
70
|
failures += 1;
|
|
32
|
-
console.log('
|
|
71
|
+
console.log(chalk.bold.red('✖'), test.fullTitle(), chalk.gray(err.message));
|
|
33
72
|
const testId = parseTest(test.title);
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
});
|
|
73
|
+
|
|
74
|
+
const specificTest = specificTestInfo(test);
|
|
75
|
+
const content = await artifactStore.artifactByTestName(specificTest);
|
|
76
|
+
|
|
77
|
+
debug(`fail test=${specificTest} content = `, content);
|
|
78
|
+
|
|
79
|
+
client.addTestRun(
|
|
80
|
+
STATUS.FAILED, {
|
|
81
|
+
error: err,
|
|
82
|
+
test_id: testId,
|
|
83
|
+
title: test.title,
|
|
84
|
+
time: test.duration,
|
|
85
|
+
},
|
|
86
|
+
content
|
|
87
|
+
);
|
|
39
88
|
});
|
|
40
89
|
|
|
41
90
|
runner.on(EVENT_RUN_END, () => {
|
|
42
|
-
|
|
43
|
-
|
|
91
|
+
const status = failures === 0 ? STATUS.PASSED : STATUS.FAILED;
|
|
92
|
+
console.log(chalk.bold(status), `${passes} passed, ${failures} failed, ${skipped} skipped`);
|
|
44
93
|
client.updateRunStatus(status);
|
|
94
|
+
|
|
95
|
+
artifactStore.cleanup();
|
|
45
96
|
});
|
|
46
97
|
}
|
|
47
98
|
|
|
@@ -3,16 +3,17 @@ const crypto = require('crypto');
|
|
|
3
3
|
const os = require('os');
|
|
4
4
|
const path = require('path');
|
|
5
5
|
const fs = require('fs');
|
|
6
|
-
const Status = require('../constants');
|
|
6
|
+
const { APP_PREFIX, STATUS: Status } = require('../constants');
|
|
7
7
|
const TestomatioClient = require('../client');
|
|
8
|
-
const
|
|
8
|
+
const { isArtifactsEnabled } = require('../fileUploader');
|
|
9
9
|
const { parseTest } = require('../util');
|
|
10
10
|
|
|
11
|
+
|
|
11
12
|
class TestomatioReporter {
|
|
12
13
|
constructor(config = {}) {
|
|
13
14
|
this.client = new TestomatioClient({ apiKey: config?.apiKey });
|
|
14
15
|
|
|
15
|
-
this.
|
|
16
|
+
this.uploads = [];
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
onBegin(_config, suite) {
|
|
@@ -36,31 +37,15 @@ class TestomatioReporter {
|
|
|
36
37
|
appendStep(step, steps);
|
|
37
38
|
}
|
|
38
39
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
if (!attachment.body && !attachment.path) {
|
|
43
|
-
continue;
|
|
44
|
-
}
|
|
45
|
-
if (attachment.contentType && attachment.contentType.startsWith('video')) {
|
|
46
|
-
// video is post-processed
|
|
47
|
-
this.videos.push({ testId, attachment, title, suite_title });
|
|
48
|
-
continue;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
let fileName = attachment.path;
|
|
52
|
-
if (attachment.body) {
|
|
53
|
-
fileName = tmpFile();
|
|
54
|
-
fs.writeFileSync(fileName, attachment.body);
|
|
55
|
-
}
|
|
56
|
-
files.push({ path: fileName, type: attachment.contentType });
|
|
57
|
-
}
|
|
40
|
+
this.uploads.push({
|
|
41
|
+
testId, title, suite_title, files: result.attachments.filter((a) => a.body || a.path)
|
|
42
|
+
})
|
|
58
43
|
|
|
59
|
-
this.client.addTestRun(
|
|
44
|
+
this.client.addTestRun(checkStatus(result.status), {
|
|
60
45
|
error,
|
|
46
|
+
test_id: testId,
|
|
61
47
|
suite_title,
|
|
62
48
|
title,
|
|
63
|
-
files,
|
|
64
49
|
steps: steps.join('\n'),
|
|
65
50
|
time: duration,
|
|
66
51
|
});
|
|
@@ -69,18 +54,30 @@ class TestomatioReporter {
|
|
|
69
54
|
async onEnd(result) {
|
|
70
55
|
if (!this.client) return;
|
|
71
56
|
|
|
72
|
-
if (this.
|
|
73
|
-
console.log(
|
|
57
|
+
if (this.uploads.length && isArtifactsEnabled()) {
|
|
58
|
+
console.log(APP_PREFIX, `🎞️ Uploading ${this.uploads.length} files...`);
|
|
74
59
|
|
|
75
60
|
const promises = [];
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
61
|
+
|
|
62
|
+
for (const upload of this.uploads) {
|
|
63
|
+
|
|
64
|
+
const { title, testId, suite_title } = upload;
|
|
65
|
+
|
|
66
|
+
const files = upload.files.map((attachment) => {
|
|
67
|
+
if (attachment.body) {
|
|
68
|
+
const fileName = tmpFile();
|
|
69
|
+
fs.writeFileSync(fileName, attachment.body);
|
|
70
|
+
}
|
|
71
|
+
return { path: attachment.path, title, type: attachment.contentType };
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
|
|
79
75
|
promises.push(
|
|
80
|
-
this.client.addTestRun(
|
|
76
|
+
this.client.addTestRun(undefined, {
|
|
77
|
+
test_id: testId,
|
|
81
78
|
title,
|
|
82
79
|
suite_title,
|
|
83
|
-
files
|
|
80
|
+
files,
|
|
84
81
|
}),
|
|
85
82
|
);
|
|
86
83
|
}
|
package/lib/adapter/webdriver.js
CHANGED
|
@@ -43,9 +43,10 @@ class WebdriverReporter extends WDIOReporter {
|
|
|
43
43
|
.filter(el => el.endpoint === screenshotEndpoint && el.result && el.result.value)
|
|
44
44
|
.map(el => Buffer.from(el.result.value, 'base64'));
|
|
45
45
|
|
|
46
|
-
await this.client.addTestRun(
|
|
46
|
+
await this.client.addTestRun(state, {
|
|
47
47
|
error,
|
|
48
48
|
title,
|
|
49
|
+
test_id: testId,
|
|
49
50
|
time: duration,
|
|
50
51
|
filesBuffers: screenshotsBuffers,
|
|
51
52
|
});
|
package/lib/bin/reportXml.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
const program = require("commander");
|
|
3
3
|
const chalk = require("chalk");
|
|
4
4
|
const glob = require('glob');
|
|
5
|
-
|
|
5
|
+
const debug = require('debug')('@testomatio/reporter:xml-cli');
|
|
6
6
|
const { APP_PREFIX } = require('../constants');
|
|
7
7
|
const XmlReader = require("../xmlReader");
|
|
8
8
|
|
|
@@ -22,7 +22,10 @@ program
|
|
|
22
22
|
pattern += '.xml';
|
|
23
23
|
}
|
|
24
24
|
let { javaTests, lang } = opts;
|
|
25
|
-
if (opts.envFile)
|
|
25
|
+
if (opts.envFile) {
|
|
26
|
+
debug('Loading env file: %s', opts.envFile)
|
|
27
|
+
require('dotenv').config({ path: opts.envFile }); // eslint-disable-line
|
|
28
|
+
}
|
|
26
29
|
if (javaTests === true) javaTests = 'src/test/java';
|
|
27
30
|
lang = lang?.toLowerCase();
|
|
28
31
|
const runReader = new XmlReader({ javaTests, lang });
|
package/lib/bin/startTest.js
CHANGED
|
@@ -3,7 +3,7 @@ const { spawn } = require('child_process');
|
|
|
3
3
|
const program = require('commander');
|
|
4
4
|
const chalk = require('chalk');
|
|
5
5
|
const TestomatClient = require('../client');
|
|
6
|
-
const { APP_PREFIX,
|
|
6
|
+
const { APP_PREFIX, STATUS } = require('../constants');
|
|
7
7
|
const { version } = require('../../package.json');
|
|
8
8
|
|
|
9
9
|
console.log(chalk.cyan.bold(` 🤩 Testomat.io Reporter v${version}`));
|
|
@@ -42,7 +42,7 @@ program
|
|
|
42
42
|
|
|
43
43
|
const client = new TestomatClient({ apiKey });
|
|
44
44
|
|
|
45
|
-
client.updateRunStatus(FINISHED, true).then(() => {
|
|
45
|
+
client.updateRunStatus(STATUS.FINISHED, true).then(() => {
|
|
46
46
|
console.log(chalk.yellow(`Run ${process.env.TESTOMATIO_RUN} was finished`));
|
|
47
47
|
process.exit(0);
|
|
48
48
|
});
|