@testomatio/reporter 0.4.6 → 0.5.0-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/.eslintrc.js +18 -22
- package/.github/workflows/node.js.yml +2 -1
- package/.prettierrc.js +12 -0
- package/Changelog.md +18 -18
- package/README.md +122 -93
- package/example/codecept/codecept.conf.js +7 -7
- package/example/codecept/index_test.js +8 -8
- package/example/codecept/sample_test.js +4 -4
- package/example/codecept/steps.d.ts +1 -1
- package/example/codecept/steps_file.js +4 -2
- package/example/core/index.js +6 -6
- package/example/jest/index.test.js +3 -3
- package/example/jest/jest.config.js +1 -1
- package/example/jest/sample.test.js +4 -4
- package/example/mocha/test/index.test.js +5 -5
- package/lib/adapter/codecept.js +62 -67
- package/lib/adapter/cucumber.js +35 -52
- package/lib/adapter/cypress-plugin/index.js +42 -0
- package/lib/adapter/jasmine.js +15 -6
- package/lib/adapter/jest.js +9 -10
- package/lib/adapter/mocha.js +17 -14
- package/lib/adapter/playwright.js +25 -25
- package/lib/adapter/webdriver.js +3 -3
- package/lib/bin/startTest.js +56 -60
- package/lib/client.js +58 -110
- package/lib/constants.js +6 -6
- package/lib/fileUploader.js +17 -16
- package/lib/output.js +6 -8
- package/lib/reporter.js +2 -2
- package/lib/util.js +18 -5
- package/package.json +27 -15
- package/testcafe/index.js +11 -14
- package/tests/adapter/config/index.js +10 -0
- package/tests/adapter/examples/codecept/codecept.conf.js +33 -0
- package/tests/adapter/examples/codecept/index_test.js +11 -0
- package/tests/adapter/examples/codecept/jsconfig.json +5 -0
- package/tests/adapter/examples/codecept/output/Test_for_suite_2_@Tc2171bd2.failed.png +0 -0
- package/tests/adapter/examples/codecept/output/Test_issue_for_suite_1_@Tca70c8c4.failed.png +0 -0
- package/tests/adapter/examples/codecept/sample_test.js +7 -0
- package/tests/adapter/examples/codecept/steps_file.js +10 -0
- package/tests/adapter/examples/jasmine/index.test.js +11 -0
- package/tests/adapter/examples/jasmine/passReporterOpts.sh +8 -0
- package/tests/adapter/examples/jest/index.test.js +11 -0
- package/tests/adapter/examples/jest/jest.config.js +4 -0
- package/tests/adapter/examples/mocha/index.test.js +13 -0
- package/tests/adapter/examples/mocha/mocha.config.js +4 -0
- package/tests/adapter/index.test.js +136 -0
- package/tests/adapter/utils/index.js +40 -0
- package/.prettierrc.json +0 -1
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
const chalk = require(
|
|
1
|
+
const chalk = require('chalk');
|
|
2
2
|
const crypto = require('crypto');
|
|
3
3
|
const os = require('os');
|
|
4
4
|
const path = require('path');
|
|
5
5
|
const fs = require('fs');
|
|
6
6
|
const Status = require('../constants');
|
|
7
|
-
const TestomatioClient = require(
|
|
8
|
-
const upload = require(
|
|
7
|
+
const TestomatioClient = require('../client');
|
|
8
|
+
const upload = require('../fileUploader');
|
|
9
9
|
const { parseTest } = require('../util');
|
|
10
10
|
|
|
11
11
|
class TestomatioReporter {
|
|
12
|
-
|
|
13
12
|
constructor(config = {}) {
|
|
14
13
|
const { apiKey } = config;
|
|
15
14
|
|
|
@@ -22,7 +21,7 @@ class TestomatioReporter {
|
|
|
22
21
|
this.videos = [];
|
|
23
22
|
}
|
|
24
23
|
|
|
25
|
-
onBegin(
|
|
24
|
+
onBegin(_config, suite) {
|
|
26
25
|
if (!this.client) return;
|
|
27
26
|
this.suite = suite;
|
|
28
27
|
this.client.createRun();
|
|
@@ -38,7 +37,7 @@ class TestomatioReporter {
|
|
|
38
37
|
|
|
39
38
|
const suite_title = test.parent ? test.parent.title : null;
|
|
40
39
|
|
|
41
|
-
|
|
40
|
+
const steps = [];
|
|
42
41
|
for (const step of result.steps) {
|
|
43
42
|
appendStep(step, steps);
|
|
44
43
|
}
|
|
@@ -79,15 +78,17 @@ class TestomatioReporter {
|
|
|
79
78
|
if (this.videos.length && upload.isEnabled()) {
|
|
80
79
|
console.log(Status.APP_PREFIX, `🎞️ Uploading ${this.videos.length} videos...`);
|
|
81
80
|
|
|
82
|
-
|
|
81
|
+
const promises = [];
|
|
83
82
|
for (const video of this.videos) {
|
|
84
83
|
const { testId, title, attachment, suite_title } = video;
|
|
85
|
-
const file =
|
|
86
|
-
promises.push(
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
84
|
+
const file = { path: attachment.path, title, type: attachment.contentType };
|
|
85
|
+
promises.push(
|
|
86
|
+
this.client.addTestRun(testId, undefined, {
|
|
87
|
+
title,
|
|
88
|
+
suite_title,
|
|
89
|
+
files: [file],
|
|
90
|
+
}),
|
|
91
|
+
);
|
|
91
92
|
}
|
|
92
93
|
await Promise.all(promises);
|
|
93
94
|
}
|
|
@@ -97,25 +98,24 @@ class TestomatioReporter {
|
|
|
97
98
|
}
|
|
98
99
|
|
|
99
100
|
function checkStatus(status) {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
return Status.PASSED;
|
|
108
|
-
}
|
|
109
|
-
return Status.FAILED;
|
|
101
|
+
return (
|
|
102
|
+
{
|
|
103
|
+
skipped: Status.SKIPPED,
|
|
104
|
+
timedOut: Status.FAILED,
|
|
105
|
+
passed: Status.PASSED,
|
|
106
|
+
}[status] || Status.FAILED
|
|
107
|
+
);
|
|
110
108
|
}
|
|
111
109
|
|
|
112
110
|
function appendStep(step, steps = [], shift = 0) {
|
|
113
111
|
const prefix = ' '.repeat(shift);
|
|
112
|
+
|
|
114
113
|
if (step.error) {
|
|
115
|
-
steps.push(`${prefix}${chalk.red(step.title)} ${chalk.gray(`${step.duration}ms`)}`)
|
|
114
|
+
steps.push(`${prefix}${chalk.red(step.title)} ${chalk.gray(`${step.duration}ms`)}`);
|
|
116
115
|
} else {
|
|
117
|
-
steps.push(`${prefix}${step.title} ${chalk.gray(`${step.duration}ms`)}`)
|
|
116
|
+
steps.push(`${prefix}${step.title} ${chalk.gray(`${step.duration}ms`)}`);
|
|
118
117
|
}
|
|
118
|
+
|
|
119
119
|
for (const child of step.steps || []) {
|
|
120
120
|
appendStep(child, steps, shift + 2);
|
|
121
121
|
}
|
package/lib/adapter/webdriver.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
const WDIOReporter = require(
|
|
2
|
-
const TestomatClient = require(
|
|
3
|
-
const { parseTest } = require(
|
|
1
|
+
const WDIOReporter = require('@wdio/reporter').default;
|
|
2
|
+
const TestomatClient = require('../client');
|
|
3
|
+
const { parseTest } = require('../util');
|
|
4
4
|
|
|
5
5
|
class WebdriverReporter extends WDIOReporter {
|
|
6
6
|
constructor(options) {
|
package/lib/bin/startTest.js
CHANGED
|
@@ -1,86 +1,82 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
const { spawn } = require(
|
|
3
|
-
const program = require(
|
|
4
|
-
const chalk = require(
|
|
5
|
-
const TestomatClient = require(
|
|
6
|
-
const { APP_PREFIX, FINISHED } = require(
|
|
2
|
+
const { spawn } = require('child_process');
|
|
3
|
+
const program = require('commander');
|
|
4
|
+
const chalk = require('chalk');
|
|
5
|
+
const TestomatClient = require('../client');
|
|
6
|
+
const { APP_PREFIX, FINISHED } = require('../constants');
|
|
7
7
|
|
|
8
|
-
const apiKey = process.env[
|
|
8
|
+
const apiKey = process.env['INPUT_TESTOMATIO-KEY'] || process.env.TESTOMATIO;
|
|
9
9
|
const title = process.env.TESTOMATIO_TITLE;
|
|
10
10
|
|
|
11
11
|
program
|
|
12
|
-
.option(
|
|
12
|
+
.option('-c, --command <cmd>', 'Test runner command')
|
|
13
13
|
.option('--launch', 'Start a new run and return its ID')
|
|
14
14
|
.option('--finish', 'Finish Run by its ID')
|
|
15
|
-
.action(
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
if (finish) {
|
|
30
|
-
if (!process.env.TESTOMATIO_RUN) {
|
|
31
|
-
console.log('TESTOMATIO_RUN environment variable must be set.');
|
|
32
|
-
return process.exit(1);
|
|
15
|
+
.action(opts => {
|
|
16
|
+
const { command, launch, finish } = opts;
|
|
17
|
+
|
|
18
|
+
if (launch) {
|
|
19
|
+
console.log('Starting a new Run on Testomat.io...');
|
|
20
|
+
const client = new TestomatClient({ apiKey });
|
|
21
|
+
|
|
22
|
+
client.createRun().then(() => {
|
|
23
|
+
console.log(process.env.runId);
|
|
24
|
+
process.exit(0);
|
|
25
|
+
});
|
|
26
|
+
return;
|
|
33
27
|
}
|
|
34
28
|
|
|
35
|
-
|
|
29
|
+
if (finish) {
|
|
30
|
+
if (!process.env.TESTOMATIO_RUN) {
|
|
31
|
+
console.log('TESTOMATIO_RUN environment variable must be set.');
|
|
32
|
+
return process.exit(1);
|
|
33
|
+
}
|
|
36
34
|
|
|
37
|
-
|
|
35
|
+
console.log('Finishing Run on Testomat.io...');
|
|
38
36
|
|
|
39
|
-
|
|
40
|
-
console.log(chalk.yellow(`Run ${process.env.TESTOMATIO_RUN} was finished`));
|
|
41
|
-
process.exit(0);
|
|
42
|
-
});
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
37
|
+
const client = new TestomatClient({ apiKey });
|
|
45
38
|
|
|
46
|
-
|
|
39
|
+
client.updateRunStatus(FINISHED, true).then(() => {
|
|
40
|
+
console.log(chalk.yellow(`Run ${process.env.TESTOMATIO_RUN} was finished`));
|
|
41
|
+
process.exit(0);
|
|
42
|
+
});
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
47
45
|
|
|
48
|
-
|
|
49
|
-
console.log(APP_PREFIX, `🚀 Running`, chalk.green(command));
|
|
46
|
+
let exitCode = 0;
|
|
50
47
|
|
|
51
|
-
|
|
52
|
-
|
|
48
|
+
const testCmds = command.split(' ');
|
|
49
|
+
console.log(APP_PREFIX, `🚀 Running`, chalk.green(command));
|
|
53
50
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
APP_PREFIX,
|
|
57
|
-
"⚠️ ",
|
|
58
|
-
`Runner exited with ${chalk.bold(code)}, report is ignored`
|
|
59
|
-
);
|
|
51
|
+
if (!apiKey) {
|
|
52
|
+
const cmd = spawn(testCmds[0], testCmds.slice(1), { stdio: 'inherit' });
|
|
60
53
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
54
|
+
cmd.on('close', code => {
|
|
55
|
+
console.log(APP_PREFIX, '⚠️ ', `Runner exited with ${chalk.bold(code)}, report is ignored`);
|
|
56
|
+
|
|
57
|
+
if (code > exitCode) exitCode = code;
|
|
58
|
+
process.exitCode = exitCode;
|
|
59
|
+
});
|
|
64
60
|
|
|
65
|
-
|
|
66
|
-
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
67
63
|
|
|
68
|
-
|
|
64
|
+
const client = new TestomatClient({ apiKey, title, parallel: true });
|
|
69
65
|
|
|
70
|
-
|
|
71
|
-
|
|
66
|
+
client.createRun().then(() => {
|
|
67
|
+
const cmd = spawn(testCmds[0], testCmds.slice(1), { stdio: 'inherit' });
|
|
72
68
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
69
|
+
cmd.on('close', code => {
|
|
70
|
+
const emoji = code === 0 ? '🟢' : '🔴';
|
|
71
|
+
console.log(APP_PREFIX, emoji, `Runner exited with ${chalk.bold(code)}`);
|
|
72
|
+
const status = code === 0 ? 'passed' : 'failed';
|
|
73
|
+
client.updateRunStatus(status, true);
|
|
78
74
|
|
|
79
|
-
|
|
80
|
-
|
|
75
|
+
if (code > exitCode) exitCode = code;
|
|
76
|
+
process.exitCode = exitCode;
|
|
77
|
+
});
|
|
81
78
|
});
|
|
82
79
|
});
|
|
83
|
-
});
|
|
84
80
|
|
|
85
81
|
if (process.argv.length <= 2) {
|
|
86
82
|
program.outputHelp();
|
package/lib/client.js
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
const axios = require(
|
|
2
|
-
const JsonCycle = require(
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const { PASSED, FAILED, FINISHED, APP_PREFIX } = require(
|
|
10
|
-
|
|
11
|
-
const TESTOMAT_URL = process.env.TESTOMATIO_URL ||
|
|
12
|
-
const { TESTOMATIO_RUNGROUP_TITLE, TESTOMATIO_ENV, TESTOMATIO_RUN } =
|
|
13
|
-
process.env;
|
|
1
|
+
const axios = require('axios');
|
|
2
|
+
const JsonCycle = require('json-cycle');
|
|
3
|
+
const createCallsiteRecord = require('callsite-record');
|
|
4
|
+
const { sep, join } = require('path');
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const chalk = require('chalk');
|
|
7
|
+
const upload = require('./fileUploader');
|
|
8
|
+
const { isValidUrl } = require('./util');
|
|
9
|
+
const { PASSED, FAILED, FINISHED, APP_PREFIX } = require('./constants');
|
|
10
|
+
|
|
11
|
+
const TESTOMAT_URL = process.env.TESTOMATIO_URL || 'https://app.testomat.io';
|
|
12
|
+
const { TESTOMATIO_RUNGROUP_TITLE, TESTOMATIO_ENV, TESTOMATIO_RUN } = process.env;
|
|
14
13
|
|
|
15
14
|
if (TESTOMATIO_RUN) {
|
|
16
15
|
process.env.runId = TESTOMATIO_RUN;
|
|
@@ -54,44 +53,28 @@ class TestomatClient {
|
|
|
54
53
|
if (!isValidUrl(TESTOMAT_URL.trim())) {
|
|
55
54
|
console.log(
|
|
56
55
|
APP_PREFIX,
|
|
57
|
-
chalk.red(
|
|
58
|
-
`Error creating report on Testomat.io, report url '${TESTOMAT_URL}' is invalid`
|
|
59
|
-
)
|
|
56
|
+
chalk.red(`Error creating report on Testomat.io, report url '${TESTOMAT_URL}' is invalid`),
|
|
60
57
|
);
|
|
61
58
|
return;
|
|
62
59
|
}
|
|
63
60
|
|
|
64
61
|
if (runId) {
|
|
65
62
|
this.runId = runId;
|
|
66
|
-
this.queue = this.queue.then(() =>
|
|
67
|
-
axios.put(`${TESTOMAT_URL.trim()}/api/reporter/${runId}`, runParams)
|
|
68
|
-
);
|
|
63
|
+
this.queue = this.queue.then(() => axios.put(`${TESTOMAT_URL.trim()}/api/reporter/${runId}`, runParams));
|
|
69
64
|
return Promise.resolve(runId);
|
|
70
65
|
}
|
|
71
66
|
|
|
72
67
|
this.queue = this.queue
|
|
73
|
-
.then(() =>
|
|
74
|
-
this.
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
.split("/")
|
|
80
|
-
.splice(3)
|
|
81
|
-
.join("/")}`;
|
|
82
|
-
console.log(
|
|
83
|
-
APP_PREFIX,
|
|
84
|
-
"📊 Report created. Report ID:",
|
|
85
|
-
this.runId,
|
|
86
|
-
chalk.gray(`v${this.version}`)
|
|
87
|
-
);
|
|
88
|
-
process.env.runId = this.runId;
|
|
89
|
-
})
|
|
90
|
-
)
|
|
68
|
+
.then(() => this.axios.post(`${TESTOMAT_URL.trim()}/api/reporter`, runParams).then(resp => {
|
|
69
|
+
this.runId = resp.data.uid;
|
|
70
|
+
this.runUrl = `${TESTOMAT_URL}/${resp.data.url.split('/').splice(3).join('/')}`;
|
|
71
|
+
console.log(APP_PREFIX, '📊 Report created. Report ID:', this.runId, chalk.gray(`v${this.version}`));
|
|
72
|
+
process.env.runId = this.runId;
|
|
73
|
+
}))
|
|
91
74
|
.catch(() => {
|
|
92
75
|
console.log(
|
|
93
76
|
APP_PREFIX,
|
|
94
|
-
|
|
77
|
+
'Error creating report Testomat.io, please check if your API key is valid. Skipping report',
|
|
95
78
|
);
|
|
96
79
|
});
|
|
97
80
|
|
|
@@ -104,10 +87,9 @@ class TestomatClient {
|
|
|
104
87
|
* @returns {Promise}
|
|
105
88
|
*/
|
|
106
89
|
async addTestRun(testId, status, testData = {}) {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
time = "",
|
|
90
|
+
const {
|
|
91
|
+
error = '',
|
|
92
|
+
time = '',
|
|
111
93
|
example = null,
|
|
112
94
|
files = [],
|
|
113
95
|
steps,
|
|
@@ -116,12 +98,13 @@ class TestomatClient {
|
|
|
116
98
|
suite_id,
|
|
117
99
|
test_id,
|
|
118
100
|
} = testData;
|
|
101
|
+
let { message = '' } = testData;
|
|
119
102
|
|
|
120
103
|
const uploadedFiles = [];
|
|
121
104
|
|
|
122
105
|
if (testId) testData.test_id = testId;
|
|
123
106
|
|
|
124
|
-
let stack =
|
|
107
|
+
let stack = '';
|
|
125
108
|
|
|
126
109
|
if (error) {
|
|
127
110
|
stack = this.formatError(error);
|
|
@@ -148,7 +131,7 @@ class TestomatClient {
|
|
|
148
131
|
|
|
149
132
|
global.testomatioArtifacts = [];
|
|
150
133
|
|
|
151
|
-
this.totalUploaded += uploadedFiles.filter(
|
|
134
|
+
this.totalUploaded += uploadedFiles.filter(n => n).length;
|
|
152
135
|
|
|
153
136
|
const json = JsonCycle.stringify({
|
|
154
137
|
api_key: this.apiKey,
|
|
@@ -165,42 +148,29 @@ class TestomatClient {
|
|
|
165
148
|
run_time: time,
|
|
166
149
|
artifacts: await Promise.all(uploadedFiles),
|
|
167
150
|
});
|
|
168
|
-
return this.axios.post(
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
{
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
"Content-Type": "application/json",
|
|
177
|
-
},
|
|
178
|
-
}
|
|
179
|
-
);
|
|
151
|
+
return this.axios.post(`${TESTOMAT_URL}/api/reporter/${this.runId}/testrun`, json, {
|
|
152
|
+
maxContentLength: Infinity,
|
|
153
|
+
maxBodyLength: Infinity,
|
|
154
|
+
headers: {
|
|
155
|
+
// Overwrite Axios's automatically set Content-Type
|
|
156
|
+
'Content-Type': 'application/json',
|
|
157
|
+
},
|
|
158
|
+
});
|
|
180
159
|
})
|
|
181
|
-
.catch(
|
|
160
|
+
.catch(err => {
|
|
182
161
|
if (err.response) {
|
|
183
162
|
if (err.response.status >= 400) {
|
|
184
|
-
const data = err.response.data || { message:
|
|
163
|
+
const data = err.response.data || { message: '' };
|
|
185
164
|
console.log(
|
|
186
165
|
APP_PREFIX,
|
|
187
166
|
chalk.blue(title),
|
|
188
|
-
`Report couldn't be processed: (${err.response.status}) ${data.message}
|
|
167
|
+
`Report couldn't be processed: (${err.response.status}) ${data.message}`,
|
|
189
168
|
);
|
|
190
169
|
return;
|
|
191
170
|
}
|
|
192
|
-
console.log(
|
|
193
|
-
APP_PREFIX,
|
|
194
|
-
chalk.blue(title),
|
|
195
|
-
`Report couldn't be processed: ${err.response.data.message}`
|
|
196
|
-
);
|
|
171
|
+
console.log(APP_PREFIX, chalk.blue(title), `Report couldn't be processed: ${err.response.data.message}`);
|
|
197
172
|
} else {
|
|
198
|
-
console.log(
|
|
199
|
-
APP_PREFIX,
|
|
200
|
-
chalk.blue(title),
|
|
201
|
-
"Report couldn't be processed",
|
|
202
|
-
err
|
|
203
|
-
);
|
|
173
|
+
console.log(APP_PREFIX, chalk.blue(title), "Report couldn't be processed", err);
|
|
204
174
|
}
|
|
205
175
|
});
|
|
206
176
|
|
|
@@ -217,43 +187,37 @@ class TestomatClient {
|
|
|
217
187
|
.then(async () => {
|
|
218
188
|
if (this.runId) {
|
|
219
189
|
let statusEvent;
|
|
220
|
-
if (status === FINISHED) statusEvent =
|
|
221
|
-
if (status === PASSED) statusEvent =
|
|
222
|
-
if (status === FAILED) statusEvent =
|
|
223
|
-
if (isParallel) statusEvent +=
|
|
190
|
+
if (status === FINISHED) statusEvent = 'finish';
|
|
191
|
+
if (status === PASSED) statusEvent = 'pass';
|
|
192
|
+
if (status === FAILED) statusEvent = 'fail';
|
|
193
|
+
if (isParallel) statusEvent += '_parallel';
|
|
224
194
|
await this.axios.put(`${TESTOMAT_URL}/api/reporter/${this.runId}`, {
|
|
225
195
|
api_key: this.apiKey,
|
|
226
196
|
status_event: statusEvent,
|
|
227
197
|
status,
|
|
228
198
|
});
|
|
229
199
|
if (this.runUrl) {
|
|
230
|
-
console.log(
|
|
231
|
-
APP_PREFIX,
|
|
232
|
-
"📊 Report Saved. Report URL:",
|
|
233
|
-
chalk.magenta(this.runUrl)
|
|
234
|
-
);
|
|
200
|
+
console.log(APP_PREFIX, '📊 Report Saved. Report URL:', chalk.magenta(this.runUrl));
|
|
235
201
|
}
|
|
236
202
|
|
|
237
203
|
if (upload.isEnabled() && this.totalUploaded > 0) {
|
|
238
204
|
console.log(
|
|
239
205
|
APP_PREFIX,
|
|
240
206
|
`🗄️ Total ${this.totalUploaded} artifacts ${
|
|
241
|
-
upload.isPrivate ?
|
|
242
|
-
} uploaded to S3 bucket
|
|
207
|
+
upload.isPrivate ? 'privately' : chalk.bold('publicly')
|
|
208
|
+
} uploaded to S3 bucket `,
|
|
243
209
|
);
|
|
244
210
|
}
|
|
245
211
|
}
|
|
246
212
|
})
|
|
247
|
-
.catch(
|
|
248
|
-
console.log(APP_PREFIX,
|
|
213
|
+
.catch(err => {
|
|
214
|
+
console.log(APP_PREFIX, 'Error updating status, skipping...', err);
|
|
249
215
|
});
|
|
250
216
|
return this.queue;
|
|
251
217
|
}
|
|
252
218
|
|
|
253
219
|
formatSteps(stack, steps) {
|
|
254
|
-
return stack
|
|
255
|
-
? `${steps}\n\n${chalk.bold.red("################[ Failure ]################")}\n${stack}`
|
|
256
|
-
: steps;
|
|
220
|
+
return stack ? `${steps}\n\n${chalk.bold.red('################[ Failure ]################')}\n${stack}` : steps;
|
|
257
221
|
}
|
|
258
222
|
|
|
259
223
|
formatError(error, message) {
|
|
@@ -264,28 +228,21 @@ class TestomatClient {
|
|
|
264
228
|
|
|
265
229
|
// diffs for mocha, cypress, codeceptjs style
|
|
266
230
|
if (error.actual && error.expected) {
|
|
267
|
-
stack += `\n\n${chalk.bold.green(
|
|
268
|
-
|
|
269
|
-
)}`;
|
|
270
|
-
stack +=
|
|
271
|
-
`- ${error.actual.toString().split("\n").join("\n- ")}`
|
|
272
|
-
)}`;
|
|
273
|
-
stack += `\n${chalk.green(
|
|
274
|
-
`+ ${error.expected.toString().split("\n").join("\n+ ")}`
|
|
275
|
-
)}`;
|
|
276
|
-
stack += "\n\n";
|
|
231
|
+
stack += `\n\n${chalk.bold.green('+ expected')} ${chalk.bold.red('- actual')}`;
|
|
232
|
+
stack += `\n${chalk.red(`- ${error.actual.toString().split('\n').join('\n- ')}`)}`;
|
|
233
|
+
stack += `\n${chalk.green(`+ ${error.expected.toString().split('\n').join('\n+ ')}`)}`;
|
|
234
|
+
stack += '\n\n';
|
|
277
235
|
}
|
|
278
236
|
|
|
279
237
|
try {
|
|
280
238
|
const record = createCallsiteRecord({
|
|
281
239
|
forError: error,
|
|
282
240
|
});
|
|
283
|
-
if (record) {
|
|
241
|
+
if (record && !record.filename.startsWith('http')) {
|
|
284
242
|
stack += record.renderSync({
|
|
285
|
-
stackFilter: (
|
|
286
|
-
frame.getFileName().indexOf(
|
|
287
|
-
frame.getFileName().indexOf(
|
|
288
|
-
frame.getFileName().indexOf("internal") < 0,
|
|
243
|
+
stackFilter: frame => frame.getFileName().indexOf(sep) > -1 &&
|
|
244
|
+
frame.getFileName().indexOf('node_modules') < 0 &&
|
|
245
|
+
frame.getFileName().indexOf('internal') < 0,
|
|
289
246
|
});
|
|
290
247
|
}
|
|
291
248
|
return stack;
|
|
@@ -296,12 +253,3 @@ class TestomatClient {
|
|
|
296
253
|
}
|
|
297
254
|
|
|
298
255
|
module.exports = TestomatClient;
|
|
299
|
-
|
|
300
|
-
function isValidUrl(s) {
|
|
301
|
-
try {
|
|
302
|
-
new URL(s); // eslint-disable-line
|
|
303
|
-
return true;
|
|
304
|
-
} catch (err) {
|
|
305
|
-
return false;
|
|
306
|
-
}
|
|
307
|
-
}
|
package/lib/constants.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
const chalk = require(
|
|
1
|
+
const chalk = require('chalk');
|
|
2
2
|
|
|
3
|
-
const APP_PREFIX = chalk.gray(
|
|
3
|
+
const APP_PREFIX = chalk.gray('[TESTOMATIO]');
|
|
4
4
|
|
|
5
5
|
module.exports = Object.freeze({
|
|
6
|
-
PASSED:
|
|
7
|
-
FAILED:
|
|
8
|
-
SKIPPED:
|
|
9
|
-
FINISHED:
|
|
6
|
+
PASSED: 'passed',
|
|
7
|
+
FAILED: 'failed',
|
|
8
|
+
SKIPPED: 'skipped',
|
|
9
|
+
FINISHED: 'finished',
|
|
10
10
|
APP_PREFIX,
|
|
11
11
|
});
|
package/lib/fileUploader.js
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
|
-
const AWS = require(
|
|
2
|
-
const fs = require(
|
|
3
|
-
const path = require(
|
|
4
|
-
const chalk = require(
|
|
5
|
-
const { APP_PREFIX } = require(
|
|
1
|
+
const AWS = require('aws-sdk');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const chalk = require('chalk');
|
|
5
|
+
const { APP_PREFIX } = require('./constants');
|
|
6
6
|
|
|
7
7
|
const isPrivate = process.env.TESTOMATIO_PRIVATE_ARTIFACTS;
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
return process.env.S3_BUCKET && !process.env.TESTOMATIO_DISABLE_ARTIFACTS;
|
|
11
|
-
}
|
|
9
|
+
const isEnabled = () => process.env.S3_BUCKET && !process.env.TESTOMATIO_DISABLE_ARTIFACTS;
|
|
12
10
|
|
|
13
11
|
const uploadUsingS3 = async (filePath, runId) => {
|
|
14
12
|
const region = process.env.S3_REGION;
|
|
@@ -37,7 +35,7 @@ const uploadUsingS3 = async (filePath, runId) => {
|
|
|
37
35
|
const file = fs.readFileSync(filePath);
|
|
38
36
|
|
|
39
37
|
fileName = `${runId}/${fileName || path.basename(filePath)}`;
|
|
40
|
-
const acl = isPrivate ?
|
|
38
|
+
const acl = isPrivate ? 'private' : 'public-read';
|
|
41
39
|
|
|
42
40
|
try {
|
|
43
41
|
const out = await s3
|
|
@@ -57,16 +55,19 @@ const uploadUsingS3 = async (filePath, runId) => {
|
|
|
57
55
|
region,
|
|
58
56
|
bucket,
|
|
59
57
|
acl,
|
|
60
|
-
endpoint: process.env.S3_ENDPOINT
|
|
61
|
-
})
|
|
58
|
+
endpoint: process.env.S3_ENDPOINT,
|
|
59
|
+
});
|
|
62
60
|
|
|
63
|
-
console.log(APP_PREFIX, `To ${chalk.bold('disable')} artifact uploads set: TESTOMATIO_DISABLE_ARTIFACTS=1`)
|
|
61
|
+
console.log(APP_PREFIX, `To ${chalk.bold('disable')} artifact uploads set: TESTOMATIO_DISABLE_ARTIFACTS=1`);
|
|
64
62
|
if (!isPrivate) {
|
|
65
|
-
console.log(APP_PREFIX, `To enable ${chalk.bold('PRIVATE')} uploads set: TESTOMATIO_PRIVATE_ARTIFACTS=1`)
|
|
63
|
+
console.log(APP_PREFIX, `To enable ${chalk.bold('PRIVATE')} uploads set: TESTOMATIO_PRIVATE_ARTIFACTS=1`);
|
|
66
64
|
} else {
|
|
67
|
-
console.log(
|
|
65
|
+
console.log(
|
|
66
|
+
APP_PREFIX,
|
|
67
|
+
`To enable ${chalk.bold('PUBLIC')} uploads remove TESTOMATIO_PRIVATE_ARTIFACTS env variable`,
|
|
68
|
+
);
|
|
68
69
|
}
|
|
69
|
-
console.log(APP_PREFIX, '---------------')
|
|
70
|
+
console.log(APP_PREFIX, '---------------');
|
|
70
71
|
return null;
|
|
71
72
|
}
|
|
72
73
|
};
|
|
@@ -77,7 +78,7 @@ const uploadFile = async (filePath, runId) => {
|
|
|
77
78
|
return uploadUsingS3(filePath, runId);
|
|
78
79
|
}
|
|
79
80
|
} catch (e) {
|
|
80
|
-
console.error(chalk.red(
|
|
81
|
+
console.error(chalk.red('Error occurred while uploading artifacts'), e);
|
|
81
82
|
}
|
|
82
83
|
return null;
|
|
83
84
|
};
|
package/lib/output.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
const
|
|
1
|
+
const { format } = require('util');
|
|
2
2
|
|
|
3
3
|
const consoleLog = console.log;
|
|
4
4
|
const consoleError = console.error;
|
|
5
5
|
|
|
6
|
+
const formatArgs = args => format.apply(format, Array.prototype.slice.call(args));
|
|
7
|
+
|
|
6
8
|
class Output {
|
|
7
9
|
constructor(opts = {}) {
|
|
8
10
|
this.filterFn = opts.filterFn || (() => true);
|
|
@@ -17,7 +19,7 @@ class Output {
|
|
|
17
19
|
start() {
|
|
18
20
|
const { filterFn } = this;
|
|
19
21
|
const self = this;
|
|
20
|
-
console.log =
|
|
22
|
+
console.log = (...args) => {
|
|
21
23
|
const obj = {};
|
|
22
24
|
Error.captureStackTrace(obj);
|
|
23
25
|
const logString = formatArgs(args);
|
|
@@ -27,7 +29,7 @@ class Output {
|
|
|
27
29
|
consoleLog(logString);
|
|
28
30
|
};
|
|
29
31
|
|
|
30
|
-
console.error =
|
|
32
|
+
console.error = (...args) => {
|
|
31
33
|
const obj = {};
|
|
32
34
|
Error.captureStackTrace(obj);
|
|
33
35
|
const logString = formatArgs(args);
|
|
@@ -43,7 +45,7 @@ class Output {
|
|
|
43
45
|
}
|
|
44
46
|
|
|
45
47
|
text() {
|
|
46
|
-
return this.log.join(
|
|
48
|
+
return this.log.join('\n');
|
|
47
49
|
}
|
|
48
50
|
|
|
49
51
|
stop() {
|
|
@@ -53,7 +55,3 @@ class Output {
|
|
|
53
55
|
}
|
|
54
56
|
|
|
55
57
|
module.exports = Output;
|
|
56
|
-
|
|
57
|
-
function formatArgs(args) {
|
|
58
|
-
return util.format.apply(util.format, Array.prototype.slice.call(args));
|
|
59
|
-
}
|
package/lib/reporter.js
CHANGED