@testomatio/reporter 1.0.13 → 1.0.14
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/_ArtifactStorageOld.js +1 -1
- package/lib/adapter/codecept.js +1 -1
- package/lib/adapter/cucumber/current.js +1 -1
- package/lib/adapter/cucumber/legacy.js +1 -1
- package/lib/adapter/cypress-plugin/index.js +1 -1
- package/lib/adapter/jasmine.js +1 -1
- package/lib/adapter/jest.js +1 -1
- package/lib/adapter/mocha.js +1 -1
- package/lib/adapter/playwright.js +1 -1
- package/lib/adapter/webdriver.js +1 -1
- package/lib/bin/startTest.js +25 -4
- package/lib/client.js +58 -0
- package/lib/dataStorage.js +2 -2
- package/lib/pipe/csv.js +4 -1
- package/lib/pipe/github.js +5 -16
- package/lib/pipe/gitlab.js +5 -16
- package/lib/pipe/testomatio.js +89 -37
- package/lib/utils/pipe_utils.js +135 -0
- package/lib/{util.js → utils/utils.js} +11 -1
- package/lib/xmlReader.js +3 -3
- package/package.json +2 -2
- package/Changelog.md +0 -322
|
@@ -4,7 +4,7 @@ const fs = require('fs');
|
|
|
4
4
|
const os = require('os');
|
|
5
5
|
const uuid = require('uuid');
|
|
6
6
|
const { TESTOMAT_ARTIFACT_SUFFIX } = require('./constants');
|
|
7
|
-
const { specificTestInfo } = require('./
|
|
7
|
+
const { specificTestInfo } = require('./utils/utils');
|
|
8
8
|
|
|
9
9
|
class ArtifactStorage {
|
|
10
10
|
|
package/lib/adapter/codecept.js
CHANGED
|
@@ -3,7 +3,7 @@ const chalk = require('chalk');
|
|
|
3
3
|
const TestomatClient = require('../client');
|
|
4
4
|
const { STATUS, APP_PREFIX, TESTOMAT_TMP_STORAGE } = require('../constants');
|
|
5
5
|
const upload = require('../fileUploader');
|
|
6
|
-
const { parseTest: getIdFromTestTitle, fileSystem } = require('../
|
|
6
|
+
const { parseTest: getIdFromTestTitle, fileSystem } = require('../utils/utils');
|
|
7
7
|
|
|
8
8
|
if (!global.codeceptjs) {
|
|
9
9
|
// eslint-disable-next-line global-require, import/no-extraneous-dependencies
|
|
@@ -5,7 +5,7 @@ const fs = require('fs');
|
|
|
5
5
|
const { STATUS, TESTOMAT_TMP_STORAGE } = require('../../constants');
|
|
6
6
|
const TestomatClient = require('../../client');
|
|
7
7
|
const logger = require('../../logger');
|
|
8
|
-
const { parseTest, fileSystem } = require('../../
|
|
8
|
+
const { parseTest, fileSystem } = require('../../utils/utils');
|
|
9
9
|
|
|
10
10
|
const { GherkinDocumentParser, PickleParser } = formatterHelpers;
|
|
11
11
|
const { getGherkinScenarioLocationMap, getGherkinStepMap } = GherkinDocumentParser;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
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 { parseTest, fileSystem } = require('../../
|
|
4
|
+
const { parseTest, fileSystem } = require('../../utils/utils');
|
|
5
5
|
const { STATUS, TESTOMAT_TMP_STORAGE } = require('../../constants');
|
|
6
6
|
const TestomatClient = require('../../client');
|
|
7
7
|
|
package/lib/adapter/jasmine.js
CHANGED
package/lib/adapter/jest.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const TestomatClient = require('../client');
|
|
2
2
|
const { STATUS, TESTOMAT_TMP_STORAGE } = require('../constants');
|
|
3
|
-
const { parseTest, ansiRegExp, fileSystem } = require('../
|
|
3
|
+
const { parseTest, ansiRegExp, fileSystem } = require('../utils/utils');
|
|
4
4
|
|
|
5
5
|
class JestReporter {
|
|
6
6
|
constructor(globalConfig, options) {
|
package/lib/adapter/mocha.js
CHANGED
|
@@ -4,7 +4,7 @@ const debug = require('debug')('@testomatio/reporter:adapter:mocha');
|
|
|
4
4
|
const chalk = require('chalk');
|
|
5
5
|
const TestomatClient = require('../client');
|
|
6
6
|
const { STATUS, TESTOMAT_TMP_STORAGE } = require('../constants');
|
|
7
|
-
const { parseTest, specificTestInfo, fileSystem } = require('../
|
|
7
|
+
const { parseTest, specificTestInfo, fileSystem } = require('../utils/utils');
|
|
8
8
|
const ArtifactStorage = require('../_ArtifactStorageOld');
|
|
9
9
|
|
|
10
10
|
const { EVENT_RUN_BEGIN, EVENT_RUN_END, EVENT_TEST_FAIL, EVENT_TEST_PASS, EVENT_TEST_PENDING } =
|
|
@@ -6,7 +6,7 @@ const fs = require('fs');
|
|
|
6
6
|
const { APP_PREFIX, STATUS: Status, TESTOMAT_TMP_STORAGE } = require('../constants');
|
|
7
7
|
const TestomatioClient = require('../client');
|
|
8
8
|
const { isArtifactsEnabled } = require('../fileUploader');
|
|
9
|
-
const { parseTest, fileSystem } = require('../
|
|
9
|
+
const { parseTest, fileSystem } = require('../utils/utils');
|
|
10
10
|
|
|
11
11
|
const reportTestPromises = [];
|
|
12
12
|
|
package/lib/adapter/webdriver.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// eslint-disable-next-line global-require, import/no-extraneous-dependencies
|
|
2
2
|
const WDIOReporter = require('@wdio/reporter').default;
|
|
3
3
|
const TestomatClient = require('../client');
|
|
4
|
-
const { parseTest } = require('../
|
|
4
|
+
const { parseTest } = require('../utils/utils');
|
|
5
5
|
|
|
6
6
|
class WebdriverReporter extends WDIOReporter {
|
|
7
7
|
constructor(options) {
|
package/lib/bin/startTest.js
CHANGED
|
@@ -13,9 +13,11 @@ program
|
|
|
13
13
|
.option('--launch', 'Start a new run and return its ID')
|
|
14
14
|
.option('--finish', 'Finish Run by its ID')
|
|
15
15
|
.option("--env-file <envfile>", "Load environment variables from env file")
|
|
16
|
-
.
|
|
16
|
+
.option("--filter <filter>", "Additional execution filter")
|
|
17
|
+
.action(async (opts) => {
|
|
18
|
+
const { launch, finish, filter } = opts;
|
|
19
|
+
let { command } = opts;
|
|
17
20
|
|
|
18
|
-
const { command, launch, finish } = opts;
|
|
19
21
|
if (opts.envFile) require('dotenv').config(opts.envFile); // eslint-disable-line
|
|
20
22
|
|
|
21
23
|
const apiKey = process.env['INPUT_TESTOMATIO-KEY'] || process.env.TESTOMATIO;
|
|
@@ -51,6 +53,27 @@ program
|
|
|
51
53
|
|
|
52
54
|
let exitCode = 0;
|
|
53
55
|
|
|
56
|
+
const client = new TestomatClient({ apiKey, title, parallel: true });
|
|
57
|
+
|
|
58
|
+
if(filter) {
|
|
59
|
+
const [pipe, ...optsArray] = filter.split(":");
|
|
60
|
+
const pipeOptions = optsArray.join(":");
|
|
61
|
+
|
|
62
|
+
try {
|
|
63
|
+
const tests = await client.prepareRun({pipe, pipeOptions});
|
|
64
|
+
|
|
65
|
+
if(!tests || tests.length === 0) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const grep = ` --grep (${tests.join('|')})`;
|
|
70
|
+
command += grep;
|
|
71
|
+
}
|
|
72
|
+
catch(err) {
|
|
73
|
+
console.log(APP_PREFIX, err);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
54
77
|
if (!command.split) {
|
|
55
78
|
process.exitCode = 255;
|
|
56
79
|
console.log(APP_PREFIX, `No command provided. Use -c option to launch a test runner.`);
|
|
@@ -73,8 +96,6 @@ program
|
|
|
73
96
|
return;
|
|
74
97
|
}
|
|
75
98
|
|
|
76
|
-
const client = new TestomatClient({ apiKey, title, parallel: true });
|
|
77
|
-
|
|
78
99
|
client.createRun().then(() => {
|
|
79
100
|
const cmd = spawn(testCmds[0], testCmds.slice(1), { stdio: 'inherit' });
|
|
80
101
|
|
package/lib/client.js
CHANGED
|
@@ -27,15 +27,71 @@ class Client {
|
|
|
27
27
|
this.queue = Promise.resolve();
|
|
28
28
|
this.totalUploaded = 0;
|
|
29
29
|
this.version = JSON.parse(fs.readFileSync(join(__dirname, '..', 'package.json')).toString()).version;
|
|
30
|
+
this.executionList = Promise.resolve();
|
|
31
|
+
|
|
30
32
|
console.log(APP_PREFIX, `Testomatio Reporter v${this.version}`);
|
|
31
33
|
}
|
|
32
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Asynchronously prepares the execution list for running tests through various pipes.
|
|
37
|
+
* Each pipe in the client is checked for enablement,
|
|
38
|
+
* and if all pipes are disabled, the function returns a resolved Promise.
|
|
39
|
+
* Otherwise, it executes the `prepareRun` method for each enabled pipe and collects the results.
|
|
40
|
+
* The results are then filtered to remove any undefined values.
|
|
41
|
+
* If no valid results are found, the function returns undefined.
|
|
42
|
+
* Otherwise, it returns the first non-empty array from the filtered results.
|
|
43
|
+
*
|
|
44
|
+
* @param {Object} params - The options for preparing the test execution list.
|
|
45
|
+
* @param {string} params.pipe - Name of the executed pipe.
|
|
46
|
+
* @param {string} params.pipeOptions - Filter option.
|
|
47
|
+
* @returns {Promise<any>} - A Promise that resolves to an
|
|
48
|
+
* array containing the prepared execution list,
|
|
49
|
+
* or resolves to undefined if no valid results are found or if all pipes are disabled.
|
|
50
|
+
*/
|
|
51
|
+
async prepareRun(params) {
|
|
52
|
+
const { pipe, pipeOptions } = params;
|
|
53
|
+
// all pipes disabled, skipping
|
|
54
|
+
if (!this.pipes.some(p => p.isEnabled)) {
|
|
55
|
+
return Promise.resolve();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
try {
|
|
59
|
+
const filterPipe = this.pipes.find(p => p.constructor.name.toLowerCase() === `${pipe.toLowerCase()}pipe`);
|
|
60
|
+
|
|
61
|
+
if (!filterPipe.isEnabled) {
|
|
62
|
+
// TODO:for the future for the another pipes
|
|
63
|
+
console.warn(
|
|
64
|
+
APP_PREFIX,
|
|
65
|
+
`At the moment processing is available only for the "testomatio" key. Example: "testomatio:tag-name=xxx"`
|
|
66
|
+
);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const results = await Promise.all(this.pipes.map(async p =>
|
|
71
|
+
({ pipe: p.toString(), result: await p.prepareRun(pipeOptions) })
|
|
72
|
+
));
|
|
73
|
+
|
|
74
|
+
const result = results.filter(p => p.pipe.includes('Testomatio'))[0]?.result;
|
|
75
|
+
|
|
76
|
+
if (!result || result.length === 0) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
debug('Execution tests list', result);
|
|
81
|
+
|
|
82
|
+
return result;
|
|
83
|
+
} catch (err) {
|
|
84
|
+
console.error(APP_PREFIX, err);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
33
88
|
/**
|
|
34
89
|
* Used to create a new Test run
|
|
35
90
|
*
|
|
36
91
|
* @returns {Promise<any>} - resolves to Run id which should be used to update / add test
|
|
37
92
|
*/
|
|
38
93
|
createRun() {
|
|
94
|
+
debug('Creating run...');
|
|
39
95
|
// all pipes disabled, skipping
|
|
40
96
|
if (!this.pipes?.filter(p => p.isEnabled).length) return Promise.resolve();
|
|
41
97
|
|
|
@@ -59,6 +115,7 @@ class Client {
|
|
|
59
115
|
* @returns {Promise<PipeResult[]>}
|
|
60
116
|
*/
|
|
61
117
|
async addTestRun(status, testData, storeArtifacts = []) {
|
|
118
|
+
debug('Adding test run for test', testData?.test_id || 'unknown test');
|
|
62
119
|
// all pipes disabled, skipping
|
|
63
120
|
if (!this.pipes?.filter(p => p.isEnabled).length) return [];
|
|
64
121
|
|
|
@@ -170,6 +227,7 @@ class Client {
|
|
|
170
227
|
* @returns {Promise<any>} - A Promise that resolves when finishes the run.
|
|
171
228
|
*/
|
|
172
229
|
updateRunStatus(status, isParallel = false) {
|
|
230
|
+
debug('Updating run status...');
|
|
173
231
|
// all pipes disabled, skipping
|
|
174
232
|
if (!this.pipes?.filter(p => p.isEnabled).length) return Promise.resolve();
|
|
175
233
|
|
package/lib/dataStorage.js
CHANGED
|
@@ -5,8 +5,8 @@ const os = require('os');
|
|
|
5
5
|
const { join } = require('path');
|
|
6
6
|
const JestReporter = require('./adapter/jest');
|
|
7
7
|
const { TESTOMAT_TMP_STORAGE } = require('./constants');
|
|
8
|
-
const { fileSystem } = require('./
|
|
9
|
-
const getTestIdFromTestTitle = require('./
|
|
8
|
+
const { fileSystem } = require('./utils/utils');
|
|
9
|
+
const getTestIdFromTestTitle = require('./utils/utils').parseTest;
|
|
10
10
|
|
|
11
11
|
class DataStorage {
|
|
12
12
|
/**
|
package/lib/pipe/csv.js
CHANGED
|
@@ -4,7 +4,7 @@ const fs = require('fs');
|
|
|
4
4
|
const csvWriter = require('csv-writer');
|
|
5
5
|
const chalk = require('chalk');
|
|
6
6
|
const merge = require('lodash.merge');
|
|
7
|
-
const { isSameTest, getCurrentDateTime } = require('../
|
|
7
|
+
const { isSameTest, getCurrentDateTime } = require('../utils/utils');
|
|
8
8
|
const { CSV_HEADERS } = require('../constants');
|
|
9
9
|
|
|
10
10
|
/**
|
|
@@ -40,6 +40,9 @@ class CsvPipe {
|
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
// TODO: to using SET opts as argument => prepareRun(opts)
|
|
44
|
+
async prepareRun() {}
|
|
45
|
+
|
|
43
46
|
async createRun() {
|
|
44
47
|
// empty
|
|
45
48
|
}
|
package/lib/pipe/github.js
CHANGED
|
@@ -5,7 +5,8 @@ const humanizeDuration = require('humanize-duration');
|
|
|
5
5
|
const merge = require('lodash.merge');
|
|
6
6
|
const { Octokit } = require('@octokit/rest');
|
|
7
7
|
const { APP_PREFIX } = require('../constants');
|
|
8
|
-
const { ansiRegExp, isSameTest } = require('../
|
|
8
|
+
const { ansiRegExp, isSameTest } = require('../utils/utils');
|
|
9
|
+
const { statusEmoji, fullName } = require('../utils/pipe_utils');
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* @typedef {import('../../types').Pipe} Pipe
|
|
@@ -37,6 +38,9 @@ class GitHubPipe {
|
|
|
37
38
|
debug('GitHub Pipe: Enabled');
|
|
38
39
|
}
|
|
39
40
|
|
|
41
|
+
// TODO: to using SET opts as argument => prepareRun(opts)
|
|
42
|
+
async prepareRun() {}
|
|
43
|
+
|
|
40
44
|
async createRun() {}
|
|
41
45
|
|
|
42
46
|
addTest(test) {
|
|
@@ -182,21 +186,6 @@ class GitHubPipe {
|
|
|
182
186
|
}
|
|
183
187
|
}
|
|
184
188
|
|
|
185
|
-
function statusEmoji(status) {
|
|
186
|
-
if (status === 'passed') return '🟢';
|
|
187
|
-
if (status === 'failed') return '🔴';
|
|
188
|
-
if (status === 'skipped') return '🟡';
|
|
189
|
-
return '';
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
function fullName(t) {
|
|
193
|
-
let line = '';
|
|
194
|
-
if (t.suite_title) line = `${t.suite_title}: `;
|
|
195
|
-
line += `**${t.title}**`;
|
|
196
|
-
if (t.example) line += ` \`[${Object.values(t.example)}]\``;
|
|
197
|
-
return line;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
189
|
async function deletePreviousReport(octokit, owner, repo, issue, hiddenCommentData) {
|
|
201
190
|
if (process.env.GH_KEEP_OUTDATED_REPORTS) return;
|
|
202
191
|
|
package/lib/pipe/gitlab.js
CHANGED
|
@@ -5,7 +5,8 @@ const humanizeDuration = require('humanize-duration');
|
|
|
5
5
|
const merge = require('lodash.merge');
|
|
6
6
|
const path = require('path');
|
|
7
7
|
const { APP_PREFIX } = require('../constants');
|
|
8
|
-
const { ansiRegExp, isSameTest } = require('../
|
|
8
|
+
const { ansiRegExp, isSameTest } = require('../utils/utils');
|
|
9
|
+
const { statusEmoji, fullName } = require('../utils/pipe_utils');
|
|
9
10
|
|
|
10
11
|
//! GITLAB_PAT environment variable is required for this functionality to work
|
|
11
12
|
//! and your pipeline trigger should be merge_request
|
|
@@ -46,6 +47,9 @@ class GitLabPipe {
|
|
|
46
47
|
debug('GitLab Pipe: Enabled');
|
|
47
48
|
}
|
|
48
49
|
|
|
50
|
+
// TODO: to using SET opts as argument => prepareRun(opts)
|
|
51
|
+
async prepareRun() {}
|
|
52
|
+
|
|
49
53
|
async createRun() {}
|
|
50
54
|
|
|
51
55
|
addTest(test) {
|
|
@@ -179,21 +183,6 @@ class GitLabPipe {
|
|
|
179
183
|
updateRun() {}
|
|
180
184
|
}
|
|
181
185
|
|
|
182
|
-
function statusEmoji(status) {
|
|
183
|
-
if (status === 'passed') return '🟢';
|
|
184
|
-
if (status === 'failed') return '🔴';
|
|
185
|
-
if (status === 'skipped') return '🟡';
|
|
186
|
-
return '';
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
function fullName(t) {
|
|
190
|
-
let line = '';
|
|
191
|
-
if (t.suite_title) line = `${t.suite_title}: `;
|
|
192
|
-
line += `**${t.title}**`;
|
|
193
|
-
if (t.example) line += ` \`[${Object.values(t.example)}]\``;
|
|
194
|
-
return line;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
186
|
async function deletePreviousReport(axiosInstance, commentsRequestURL, hiddenCommentData, token) {
|
|
198
187
|
if (process.env.GITLAB_KEEP_OUTDATED_REPORTS) return;
|
|
199
188
|
|
package/lib/pipe/testomatio.js
CHANGED
|
@@ -3,8 +3,8 @@ const chalk = require('chalk');
|
|
|
3
3
|
const axios = require('axios');
|
|
4
4
|
const JsonCycle = require('json-cycle');
|
|
5
5
|
const { APP_PREFIX, STATUS } = require('../constants');
|
|
6
|
-
const { isValidUrl } = require('../
|
|
7
|
-
const {
|
|
6
|
+
const { isValidUrl, foundedTestLog } = require('../utils/utils');
|
|
7
|
+
const { parseFilterParams, generateFilterRequestParams, setS3Credentials, } = require('../utils/pipe_utils');
|
|
8
8
|
|
|
9
9
|
const { TESTOMATIO_RUN } = process.env;
|
|
10
10
|
if (TESTOMATIO_RUN) {
|
|
@@ -33,7 +33,12 @@ class TestomatioPipe {
|
|
|
33
33
|
this.sharedRun = !!process.env.TESTOMATIO_SHARED_RUN;
|
|
34
34
|
this.groupTitle = params.groupTitle || process.env.TESTOMATIO_RUNGROUP_TITLE;
|
|
35
35
|
this.env = process.env.TESTOMATIO_ENV;
|
|
36
|
-
|
|
36
|
+
|
|
37
|
+
this.axios = axios.create({
|
|
38
|
+
baseURL: `${this.url.trim()}`,
|
|
39
|
+
timeout: 30000
|
|
40
|
+
});
|
|
41
|
+
|
|
37
42
|
this.isEnabled = true;
|
|
38
43
|
// do not finish this run (for parallel testing)
|
|
39
44
|
this.proceed = process.env.TESTOMATIO_PROCEED;
|
|
@@ -47,10 +52,52 @@ class TestomatioPipe {
|
|
|
47
52
|
}
|
|
48
53
|
}
|
|
49
54
|
|
|
55
|
+
/**
|
|
56
|
+
* Asynchronously prepares and retrieves the Testomat.io test grepList based on the provided options.
|
|
57
|
+
* @param {Object} opts - The options for preparing the test grepList.
|
|
58
|
+
* @returns {Promise<string[]>} - An array containing the retrieved
|
|
59
|
+
* test grepList, or an empty array if no tests are found or the request is disabled.
|
|
60
|
+
* @throws {Error} - Throws an error if there was a problem while making the request.
|
|
61
|
+
*/
|
|
62
|
+
async prepareRun(opts) {
|
|
63
|
+
if (!this.isEnabled) return [];
|
|
64
|
+
|
|
65
|
+
const { type, id } = parseFilterParams(opts);
|
|
66
|
+
|
|
67
|
+
try {
|
|
68
|
+
const q = generateFilterRequestParams({
|
|
69
|
+
type,
|
|
70
|
+
id,
|
|
71
|
+
apiKey: this.apiKey.trim()
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
if (!q) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const resp = await this.axios.get('/api/test_grep', q);
|
|
79
|
+
const { data } = resp;
|
|
80
|
+
|
|
81
|
+
if (Array.isArray(data?.tests) && data?.tests?.length > 0) {
|
|
82
|
+
foundedTestLog(APP_PREFIX, data.tests);
|
|
83
|
+
return data.tests;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
console.log(APP_PREFIX, `⛔ No tests found for your --filter --> ${type}=${id}`);
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
console.error(
|
|
90
|
+
APP_PREFIX,
|
|
91
|
+
`🚩 Error getting Testomat.io test grepList: ${err}`,
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
50
96
|
/**
|
|
51
97
|
* @returns Promise<void>
|
|
52
98
|
*/
|
|
53
99
|
async createRun() {
|
|
100
|
+
debug('Creating run...');
|
|
54
101
|
if (!this.isEnabled) return;
|
|
55
102
|
|
|
56
103
|
let buildUrl = process.env.BUILD_URL || process.env.CI_JOB_URL || process.env.CIRCLE_BUILD_URL;
|
|
@@ -58,7 +105,7 @@ class TestomatioPipe {
|
|
|
58
105
|
// GitHub Actions Url
|
|
59
106
|
if (!buildUrl && process.env.GITHUB_RUN_ID) {
|
|
60
107
|
// eslint-disable-next-line max-len
|
|
61
|
-
buildUrl = `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}
|
|
108
|
+
buildUrl = `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}`;
|
|
62
109
|
}
|
|
63
110
|
|
|
64
111
|
// Azure DevOps Url
|
|
@@ -83,17 +130,19 @@ class TestomatioPipe {
|
|
|
83
130
|
env: this.env,
|
|
84
131
|
title: this.title,
|
|
85
132
|
shared_run: this.sharedRun,
|
|
86
|
-
}).filter(([, value]) => !!value)
|
|
133
|
+
}).filter(([, value]) => !!value),
|
|
87
134
|
);
|
|
135
|
+
debug('Run params', JSON.stringify(runParams, null, 2));
|
|
88
136
|
|
|
89
137
|
if (this.runId) {
|
|
90
|
-
|
|
138
|
+
debug(`Run with id ${this.runId} already created, updating...`);
|
|
139
|
+
const resp = await this.axios.put(`/api/reporter/${this.runId}`, runParams);
|
|
91
140
|
if (resp.data.artifacts) setS3Credentials(resp.data.artifacts);
|
|
92
141
|
return;
|
|
93
142
|
}
|
|
94
143
|
|
|
95
144
|
try {
|
|
96
|
-
const resp = await this.axios.post(
|
|
145
|
+
const resp = await this.axios.post(`/api/reporter`, runParams, {
|
|
97
146
|
maxContentLength: Infinity,
|
|
98
147
|
maxBodyLength: Infinity,
|
|
99
148
|
});
|
|
@@ -106,27 +155,31 @@ class TestomatioPipe {
|
|
|
106
155
|
this.store.runId = this.runId;
|
|
107
156
|
console.log(APP_PREFIX, '📊 Report created. Report ID:', this.runId);
|
|
108
157
|
process.env.runId = this.runId;
|
|
158
|
+
debug('Run created', this.runId);
|
|
109
159
|
} catch (err) {
|
|
110
160
|
console.error(
|
|
111
161
|
APP_PREFIX,
|
|
112
162
|
'Error creating Testomat.io report, please check if your API key is valid. Skipping report',
|
|
163
|
+
err,
|
|
113
164
|
);
|
|
114
165
|
}
|
|
166
|
+
debug('"createRun" function finished');
|
|
115
167
|
}
|
|
116
168
|
|
|
117
169
|
/**
|
|
118
|
-
*
|
|
119
|
-
* @param testData data
|
|
120
|
-
* @returns
|
|
170
|
+
*
|
|
171
|
+
* @param testData data
|
|
172
|
+
* @returns
|
|
121
173
|
*/
|
|
122
174
|
addTest(data) {
|
|
175
|
+
debug('Adding test...');
|
|
123
176
|
if (!this.isEnabled) return;
|
|
124
177
|
if (!this.runId) return;
|
|
125
178
|
data.api_key = this.apiKey;
|
|
126
179
|
data.create = this.createNewTests;
|
|
127
180
|
const json = JsonCycle.stringify(data);
|
|
128
181
|
|
|
129
|
-
return this.axios.post(
|
|
182
|
+
return this.axios.post(`/api/reporter/${this.runId}/testrun`, json, {
|
|
130
183
|
maxContentLength: Infinity,
|
|
131
184
|
maxBodyLength: Infinity,
|
|
132
185
|
headers: {
|
|
@@ -134,7 +187,7 @@ class TestomatioPipe {
|
|
|
134
187
|
'Content-Type': 'application/json',
|
|
135
188
|
},
|
|
136
189
|
})
|
|
137
|
-
.catch(
|
|
190
|
+
.catch(err => {
|
|
138
191
|
if (err.response) {
|
|
139
192
|
if (err.response.status >= 400) {
|
|
140
193
|
const responseData = err.response.data || { message: '' };
|
|
@@ -145,11 +198,14 @@ class TestomatioPipe {
|
|
|
145
198
|
);
|
|
146
199
|
if (err.response.data.message.includes('could not be matched')) {
|
|
147
200
|
this.hasUnmatchedTests = true;
|
|
148
|
-
}
|
|
201
|
+
}
|
|
149
202
|
return;
|
|
150
203
|
}
|
|
151
|
-
|
|
152
|
-
|
|
204
|
+
console.log(
|
|
205
|
+
APP_PREFIX,
|
|
206
|
+
chalk.yellow(`Warning: ${data?.title || ''} (${err.response?.status})`),
|
|
207
|
+
`Report couldn't be processed: ${err?.response?.data?.message}`,
|
|
208
|
+
);
|
|
153
209
|
} else {
|
|
154
210
|
console.log(APP_PREFIX, chalk.blue(data?.title || ''), "Report couldn't be processed", err);
|
|
155
211
|
}
|
|
@@ -157,10 +213,11 @@ class TestomatioPipe {
|
|
|
157
213
|
}
|
|
158
214
|
|
|
159
215
|
/**
|
|
160
|
-
* @param {import('../../types').RunData} params
|
|
161
|
-
* @returns
|
|
216
|
+
* @param {import('../../types').RunData} params
|
|
217
|
+
* @returns
|
|
162
218
|
*/
|
|
163
219
|
async finishRun(params) {
|
|
220
|
+
debug('Finishing run...');
|
|
164
221
|
if (!this.isEnabled) return;
|
|
165
222
|
|
|
166
223
|
const { status, parallel } = params;
|
|
@@ -174,7 +231,7 @@ class TestomatioPipe {
|
|
|
174
231
|
|
|
175
232
|
try {
|
|
176
233
|
if (this.runId && !this.proceed) {
|
|
177
|
-
await this.axios.put(
|
|
234
|
+
await this.axios.put(`/api/reporter/${this.runId}`, {
|
|
178
235
|
api_key: this.apiKey,
|
|
179
236
|
status_event,
|
|
180
237
|
tests: params.tests,
|
|
@@ -185,7 +242,6 @@ class TestomatioPipe {
|
|
|
185
242
|
if (this.runPublicUrl) {
|
|
186
243
|
console.log(APP_PREFIX, '🌟 Public URL:', chalk.magenta(this.runPublicUrl));
|
|
187
244
|
}
|
|
188
|
-
|
|
189
245
|
}
|
|
190
246
|
if (this.runUrl && this.proceed) {
|
|
191
247
|
const notFinishedMessage = chalk.yellow.bold('Run was not finished because of $TESTOMATIO_PROCEED');
|
|
@@ -197,19 +253,30 @@ class TestomatioPipe {
|
|
|
197
253
|
// eslint-disable-next-line max-len
|
|
198
254
|
console.log(APP_PREFIX, chalk.yellow.bold('⚠️ Some reported tests were not found in Testomat.io project'));
|
|
199
255
|
// eslint-disable-next-line max-len
|
|
200
|
-
console.log(
|
|
256
|
+
console.log(
|
|
257
|
+
APP_PREFIX,
|
|
258
|
+
`If you use Testomat.io as a reporter only, please re-run tests using ${chalk.bold('TESTOMATIO_CREATE=1')}`,
|
|
259
|
+
);
|
|
201
260
|
// eslint-disable-next-line max-len
|
|
202
|
-
console.log(
|
|
261
|
+
console.log(
|
|
262
|
+
APP_PREFIX,
|
|
263
|
+
`But to keep your tests consistent it is recommended to ${chalk.bold('import tests first')}`,
|
|
264
|
+
);
|
|
203
265
|
console.log(APP_PREFIX, 'If tests were imported but still not matched, assign test IDs to your tests.');
|
|
204
266
|
console.log(APP_PREFIX, 'You can do that automatically via command line tools:');
|
|
205
267
|
console.log(APP_PREFIX, chalk.bold('npx check-tests ... --update-ids'), 'See: https://bit.ly/js-update-ids');
|
|
206
268
|
console.log(APP_PREFIX, 'or for Cucumber:');
|
|
207
269
|
// eslint-disable-next-line max-len
|
|
208
|
-
console.log(
|
|
270
|
+
console.log(
|
|
271
|
+
APP_PREFIX,
|
|
272
|
+
chalk.bold('npx check-cucumber ... --update-ids'),
|
|
273
|
+
'See: https://bit.ly/bdd-update-ids',
|
|
274
|
+
);
|
|
209
275
|
}
|
|
210
276
|
} catch (err) {
|
|
211
277
|
console.log(APP_PREFIX, 'Error updating status, skipping...', err);
|
|
212
278
|
}
|
|
279
|
+
debug('Run finished');
|
|
213
280
|
}
|
|
214
281
|
|
|
215
282
|
toString() {
|
|
@@ -218,18 +285,3 @@ class TestomatioPipe {
|
|
|
218
285
|
}
|
|
219
286
|
|
|
220
287
|
module.exports = TestomatioPipe;
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
function setS3Credentials(artifacts) {
|
|
224
|
-
if (!Object.keys(artifacts).length) return;
|
|
225
|
-
|
|
226
|
-
console.log(APP_PREFIX, 'S3 were credentials obtained from Testomat.io...');
|
|
227
|
-
|
|
228
|
-
if (artifacts.ACCESS_KEY_ID) process.env.S3_ACCESS_KEY_ID = artifacts.ACCESS_KEY_ID;
|
|
229
|
-
if (artifacts.SECRET_ACCESS_KEY) process.env.S3_SECRET_ACCESS_KEY = artifacts.SECRET_ACCESS_KEY;
|
|
230
|
-
if (artifacts.REGION) process.env.S3_REGION = artifacts.REGION;
|
|
231
|
-
if (artifacts.BUCKET) process.env.S3_BUCKET = artifacts.BUCKET;
|
|
232
|
-
if (artifacts.ENDPOINT) process.env.S3_ENDPOINT = artifacts.ENDPOINT;
|
|
233
|
-
if (artifacts.presign) process.env.TESTOMATIO_PRIVATE_ARTIFACTS = '1';
|
|
234
|
-
resetConfig();
|
|
235
|
-
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
const { resetConfig } = require('../fileUploader');
|
|
2
|
+
const { APP_PREFIX } = require('../constants');
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Set S3 credentials from the provided artifacts object.
|
|
6
|
+
* @param {Object} artifacts - The artifacts object containing S3 credentials.
|
|
7
|
+
*/
|
|
8
|
+
function setS3Credentials(artifacts) {
|
|
9
|
+
if (!Object.keys(artifacts).length) return;
|
|
10
|
+
|
|
11
|
+
console.log(APP_PREFIX, 'S3 were credentials obtained from Testomat.io...');
|
|
12
|
+
|
|
13
|
+
if (artifacts.ACCESS_KEY_ID) process.env.S3_ACCESS_KEY_ID = artifacts.ACCESS_KEY_ID;
|
|
14
|
+
if (artifacts.SECRET_ACCESS_KEY) process.env.S3_SECRET_ACCESS_KEY = artifacts.SECRET_ACCESS_KEY;
|
|
15
|
+
if (artifacts.REGION) process.env.S3_REGION = artifacts.REGION;
|
|
16
|
+
if (artifacts.BUCKET) process.env.S3_BUCKET = artifacts.BUCKET;
|
|
17
|
+
if (artifacts.ENDPOINT) process.env.S3_ENDPOINT = artifacts.ENDPOINT;
|
|
18
|
+
if (artifacts.presign) process.env.TESTOMATIO_PRIVATE_ARTIFACTS = '1';
|
|
19
|
+
resetConfig();
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Generates mode request parameters based on the input params.
|
|
23
|
+
* @param {Object} params - The input parameters for the request.
|
|
24
|
+
* @param {string} params.type - The type of the request (e.g., "tag").
|
|
25
|
+
* @param {string} params.id - The ID associated with the request.
|
|
26
|
+
* @param {string} params.apiKey - The API key for authentication.
|
|
27
|
+
* @returns {Object|null} - An object containing the generated request parameters, or null if the type is invalid.
|
|
28
|
+
*/
|
|
29
|
+
function generateFilterRequestParams(params) {
|
|
30
|
+
const { type, id, apiKey } = params;
|
|
31
|
+
|
|
32
|
+
if (!type) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (!id) {
|
|
37
|
+
console.error(APP_PREFIX, `Please make sure your settings "${type.toUpperCase()}"= "${id}" is correct!`);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
params: {
|
|
43
|
+
type,
|
|
44
|
+
id: encodeURIComponent(id),
|
|
45
|
+
api_key: apiKey
|
|
46
|
+
},
|
|
47
|
+
responseType: "json"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Parse filter parameters from a string in the format "type=id".
|
|
53
|
+
* @param {string} opts - The input string containing the filter parameters.
|
|
54
|
+
* @returns {Object} An object containing the parsed filter parameters.
|
|
55
|
+
* The object has properties "type" and "id".
|
|
56
|
+
*/
|
|
57
|
+
function parseFilterParams(opts) {
|
|
58
|
+
const [type, id] = opts.split("=");
|
|
59
|
+
const validType = updateFilterType(type);
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
type: validType,
|
|
63
|
+
id
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Update and validate the filter type.
|
|
69
|
+
* @param {string} type - The original filter type.
|
|
70
|
+
* @returns {string|undefined} The updated and validated filter type.
|
|
71
|
+
* Returns undefined if the type is not valid.
|
|
72
|
+
*/
|
|
73
|
+
function updateFilterType(type) {
|
|
74
|
+
const typeLowerCase = type.toLowerCase();
|
|
75
|
+
|
|
76
|
+
const filterTypes = [
|
|
77
|
+
"tag-name",
|
|
78
|
+
"plan-id",
|
|
79
|
+
"label",
|
|
80
|
+
"jira-ticket",
|
|
81
|
+
];
|
|
82
|
+
|
|
83
|
+
const filterApi = [
|
|
84
|
+
"tag",
|
|
85
|
+
"plan",
|
|
86
|
+
"label",
|
|
87
|
+
"jira",
|
|
88
|
+
// "ims-issue", //TODO: WIP
|
|
89
|
+
];
|
|
90
|
+
|
|
91
|
+
if (!filterTypes.includes(typeLowerCase)) {
|
|
92
|
+
console.log(APP_PREFIX, `❗❗❗ Invalid "filter=${type}" start settings! Available option list: ${filterTypes}`);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const index = filterTypes.indexOf(typeLowerCase);
|
|
97
|
+
|
|
98
|
+
return (index !== -1)
|
|
99
|
+
? filterApi[index]
|
|
100
|
+
: undefined
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Return an emoji based on the provided status.
|
|
105
|
+
* @param {string} status - The status value ('passed', 'failed', or 'skipped').
|
|
106
|
+
* @returns {string} - An emoji corresponding to the provided status.
|
|
107
|
+
*/
|
|
108
|
+
function statusEmoji(status) {
|
|
109
|
+
if (status === 'passed') return '🟢';
|
|
110
|
+
if (status === 'failed') return '🔴';
|
|
111
|
+
if (status === 'skipped') return '🟡';
|
|
112
|
+
return '';
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Generate a full name string based on the provided test object.
|
|
117
|
+
* @param {object} t - The test object.
|
|
118
|
+
* @returns {string} - A formatted full name string for the test object.
|
|
119
|
+
*/
|
|
120
|
+
function fullName(t) {
|
|
121
|
+
let line = '';
|
|
122
|
+
if (t.suite_title) line = `${t.suite_title}: `;
|
|
123
|
+
line += `**${t.title}**`;
|
|
124
|
+
if (t.example) line += ` \`[${Object.values(t.example)}]\``;
|
|
125
|
+
return line;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
module.exports = {
|
|
129
|
+
updateFilterType,
|
|
130
|
+
parseFilterParams,
|
|
131
|
+
generateFilterRequestParams,
|
|
132
|
+
setS3Credentials,
|
|
133
|
+
statusEmoji,
|
|
134
|
+
fullName
|
|
135
|
+
};
|
|
@@ -227,6 +227,15 @@ const fileSystem = {
|
|
|
227
227
|
},
|
|
228
228
|
};
|
|
229
229
|
|
|
230
|
+
|
|
231
|
+
const foundedTestLog = (app, tests) => {
|
|
232
|
+
const n = tests.length;
|
|
233
|
+
|
|
234
|
+
return (n === 1)
|
|
235
|
+
? console.log(app, `✅ We found one test!`)
|
|
236
|
+
: console.log(app, `✅ We found ${n} tests!`);
|
|
237
|
+
}
|
|
238
|
+
|
|
230
239
|
const humanize = text => {
|
|
231
240
|
text = decamelize(text);
|
|
232
241
|
return text
|
|
@@ -297,4 +306,5 @@ module.exports = {
|
|
|
297
306
|
parseSuite,
|
|
298
307
|
humanize,
|
|
299
308
|
removeColorCodes,
|
|
300
|
-
|
|
309
|
+
foundedTestLog
|
|
310
|
+
};
|
package/lib/xmlReader.js
CHANGED
|
@@ -8,12 +8,12 @@ const { fetchFilesFromStackTrace,
|
|
|
8
8
|
fetchIdFromOutput,
|
|
9
9
|
fetchSourceCode,
|
|
10
10
|
fetchSourceCodeFromStackTrace,
|
|
11
|
-
fetchIdFromCode
|
|
12
|
-
|
|
11
|
+
fetchIdFromCode,
|
|
12
|
+
humanize
|
|
13
|
+
} = require('./utils/utils');
|
|
13
14
|
const upload = require('./fileUploader');
|
|
14
15
|
const pipesFactory = require('./pipe');
|
|
15
16
|
const adapterFactory = require('./junit-adapter');
|
|
16
|
-
const { humanize } = require('./util')
|
|
17
17
|
|
|
18
18
|
const TESTOMATIO_URL = process.env.TESTOMATIO_URL || "https://app.testomat.io";
|
|
19
19
|
const TESTOMATIO = process.env.TESTOMATIO; // key?
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@testomatio/reporter",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.14",
|
|
4
4
|
"description": "Testomatio Reporter Client",
|
|
5
5
|
"main": "./lib/reporter.js",
|
|
6
6
|
"typings": "typings/index.d.ts",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"@redocly/cli": "^1.0.0-beta.125",
|
|
56
56
|
"@wdio/reporter": "^7.16.13",
|
|
57
57
|
"chai": "^4.3.6",
|
|
58
|
-
"codeceptjs": "
|
|
58
|
+
"codeceptjs": "latest",
|
|
59
59
|
"cucumber": "^6.0.7",
|
|
60
60
|
"eslint": "^8.7.0",
|
|
61
61
|
"eslint-config-airbnb-base": "^15.0.0",
|
package/Changelog.md
DELETED
|
@@ -1,322 +0,0 @@
|
|
|
1
|
-
<!-- pending release updates -->
|
|
2
|
-
# 1.0.13
|
|
3
|
-
|
|
4
|
-
* JUnit improvements
|
|
5
|
-
* Match test from source code by adding Test ID as a comment:
|
|
6
|
-
|
|
7
|
-
```java
|
|
8
|
-
// @T8acca9eb
|
|
9
|
-
```
|
|
10
|
-
* Match test from output by adding Test ID as output:
|
|
11
|
-
|
|
12
|
-
```java
|
|
13
|
-
System.out.println("tid://@T8acca9eb");
|
|
14
|
-
```
|
|
15
|
-
* Support for suite before and after output
|
|
16
|
-
* Improved support for artifacts
|
|
17
|
-
|
|
18
|
-
# 1.0.12
|
|
19
|
-
|
|
20
|
-
& Logger refactoring by @olexandr13 in #208
|
|
21
|
-
* fix undefined logs by @olexandr13 in #210
|
|
22
|
-
|
|
23
|
-
# 1.0.11
|
|
24
|
-
|
|
25
|
-
* fix steps duplication for codecept report by @olexandr13 in #209
|
|
26
|
-
|
|
27
|
-
# 1.0.10
|
|
28
|
-
|
|
29
|
-
* Added `TESTOMATIO_PUBLISH=1` variable to automatically publish run report
|
|
30
|
-
|
|
31
|
-
# 1.0.9
|
|
32
|
-
|
|
33
|
-
* Support XUnit format
|
|
34
|
-
* Improved support for parametrized Java tests
|
|
35
|
-
|
|
36
|
-
# 1.0.8
|
|
37
|
-
|
|
38
|
-
* Fixed `Can't read push of undefined` when logging steps
|
|
39
|
-
|
|
40
|
-
# 1.0.6
|
|
41
|
-
|
|
42
|
-
* Testomat.io. Auto-detect current build url and report it to Testomat.io. Manually url can be set with `BUILD_URL` variable:
|
|
43
|
-
|
|
44
|
-
```
|
|
45
|
-
BUILD_URL=https://.... TESTOMATIO=apiKey <actual test command>
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
# 1.0.5
|
|
49
|
-
|
|
50
|
-
* Fix "create tests" params processing for testomatio pipe
|
|
51
|
-
|
|
52
|
-
# 1.0.4
|
|
53
|
-
|
|
54
|
-
* Fixed parallel run
|
|
55
|
-
|
|
56
|
-
# 1.0.3
|
|
57
|
-
|
|
58
|
-
* Fixed reporting parallel runs
|
|
59
|
-
|
|
60
|
-
# 1.0.0
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
* Added [`TESTOMATIO_SHARED_RUN` option](https://github.com/testomatio/reporter/blob/master/docs/pipes.md#reporting-parallel-execution-to-to-same-run) to use a shared run for parallel executions
|
|
64
|
-
* Reworked [documentation](https://github.com/testomatio/reporter/tree/master#readme).
|
|
65
|
-
* Added an option to obtain [S3 configuration](https://github.com/testomatio/reporter/blob/master/docs/artifacts.md#configuration) from Testomat.io
|
|
66
|
-
* Introduced [pipes](https://github.com/testomatio/reporter/blob/master/docs/pipes.md):
|
|
67
|
-
* GitHub
|
|
68
|
-
* GitLab
|
|
69
|
-
* CSV Pipe
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
# 0.7.6
|
|
73
|
-
|
|
74
|
-
* Updated to use AWS S3 3.0 SDK for uploading
|
|
75
|
-
|
|
76
|
-
# 0.7.5
|
|
77
|
-
|
|
78
|
-
* Fixed reporting skipped tests in mocha
|
|
79
|
-
|
|
80
|
-
# 0.7.4
|
|
81
|
-
|
|
82
|
-
* Fixed parsing source code in JUnit files
|
|
83
|
-
|
|
84
|
-
# 0.7.3
|
|
85
|
-
|
|
86
|
-
* CodeceptJS: Upload all traces and videos from artifacts
|
|
87
|
-
* Fixed reporting skipped test in XML
|
|
88
|
-
* added `--timelimit` option to `report-xml` command line
|
|
89
|
-
|
|
90
|
-
# 0.7.2
|
|
91
|
-
|
|
92
|
-
* Fixed uploading non-existing file
|
|
93
|
-
|
|
94
|
-
# 0.7.1
|
|
95
|
-
|
|
96
|
-
* Support for NUnit XML v3 format
|
|
97
|
-
|
|
98
|
-
# 0.7.0
|
|
99
|
-
|
|
100
|
-
* Support for `@cucumber/cucumber` (>= 7.0) added
|
|
101
|
-
* Initial support for C# and NUnit
|
|
102
|
-
|
|
103
|
-
# 0.6.10
|
|
104
|
-
|
|
105
|
-
* Fixed uploading multilpe artifacts in Playwright
|
|
106
|
-
|
|
107
|
-
# 0.6.9
|
|
108
|
-
|
|
109
|
-
* Fixed pending tests reports for Cypress
|
|
110
|
-
|
|
111
|
-
# 0.6.8
|
|
112
|
-
# 0.6.7
|
|
113
|
-
|
|
114
|
-
* Pytest: fixed creating suites from reports
|
|
115
|
-
|
|
116
|
-
# 0.6.6
|
|
117
|
-
|
|
118
|
-
* JUnit reporter: prefer suite title over testcase classname in a report
|
|
119
|
-
|
|
120
|
-
# 0.6.5
|
|
121
|
-
|
|
122
|
-
* Fixed test statuses for runs in JUnit reporter
|
|
123
|
-
|
|
124
|
-
# 0.6.4
|
|
125
|
-
|
|
126
|
-
* Added `TESTOMATIO_PROCEED=1` param to not close current run
|
|
127
|
-
* Fixed priority of commands from `npx @testomatio/reporter`
|
|
128
|
-
|
|
129
|
-
# 0.6.3
|
|
130
|
-
|
|
131
|
-
* Fixed `npx start-test-run` to launch commands
|
|
132
|
-
|
|
133
|
-
# 0.6.2
|
|
134
|
-
|
|
135
|
-
* Added `--env-file` option to load env variables from env file
|
|
136
|
-
|
|
137
|
-
# 0.6.1
|
|
138
|
-
|
|
139
|
-
* Fixed creating RunGroup with JUnit reporter
|
|
140
|
-
|
|
141
|
-
# 0.6.0
|
|
142
|
-
|
|
143
|
-
* JUnit reporter support
|
|
144
|
-
|
|
145
|
-
# 0.5.10
|
|
146
|
-
|
|
147
|
-
* Fixed reporting Scenario Outline in Cypress-Cucumber
|
|
148
|
-
* Fixed error reports for Cypress when running in Chrome
|
|
149
|
-
|
|
150
|
-
# 0.5.9
|
|
151
|
-
|
|
152
|
-
* Added environment on Cypress report
|
|
153
|
-
|
|
154
|
-
# 0.5.8
|
|
155
|
-
|
|
156
|
-
* Fixed Cypress.io reporting
|
|
157
|
-
|
|
158
|
-
# 0.5.7
|
|
159
|
-
|
|
160
|
-
* Fixed webdriverio artifacts
|
|
161
|
-
|
|
162
|
-
# 0.5.6
|
|
163
|
-
|
|
164
|
-
* Unmark failed CodeceptJS tests as skipped
|
|
165
|
-
|
|
166
|
-
# 0.5.5
|
|
167
|
-
|
|
168
|
-
* Fixed `BeforeSuite` failures in CodeceptJS
|
|
169
|
-
|
|
170
|
-
# 0.5.4
|
|
171
|
-
|
|
172
|
-
Added `TESTOMATIO_CREATE=1` option to create unmatched tests on report
|
|
173
|
-
|
|
174
|
-
```
|
|
175
|
-
TESTOMATIO_CREATE=1 TESTOMATIO=apiKey npx codeceptjs run
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
# 0.5.3
|
|
179
|
-
|
|
180
|
-
* Fixed parsing suites
|
|
181
|
-
|
|
182
|
-
# 0.5.2
|
|
183
|
-
|
|
184
|
-
* Fixed multiple upload of artifacts in Cypress.io
|
|
185
|
-
|
|
186
|
-
# 0.5.1
|
|
187
|
-
|
|
188
|
-
* Fixed Cypress.io to report tests inside nested suites
|
|
189
|
-
|
|
190
|
-
# 0.5.0
|
|
191
|
-
|
|
192
|
-
* Added Cypress.io plugin
|
|
193
|
-
* Added artifacts upload to webdriverio
|
|
194
|
-
|
|
195
|
-
# 0.4.6
|
|
196
|
-
|
|
197
|
-
- Fixed CodeceptJS reporter to report tests failed in hooks
|
|
198
|
-
|
|
199
|
-
# 0.4.5
|
|
200
|
-
|
|
201
|
-
- Fixed "Total XX artifacts publicly uploaded to S3 bucket" when no S3 bucket is configured
|
|
202
|
-
- Improved S3 connection error messages
|
|
203
|
-
|
|
204
|
-
# 0.4.4
|
|
205
|
-
|
|
206
|
-
- Fixed returning 0 exit code when a process fails when running tests in parallel via `start-test-run`. Previously was using the last exit code returned by a process. Currently prefers the highest exit code that was returned by a process.
|
|
207
|
-
|
|
208
|
-
# 0.4.3
|
|
209
|
-
|
|
210
|
-
- Added `TESTOMATIO_DISABLE_ARTIFACTS` env variable to disable publishing artifacts.
|
|
211
|
-
|
|
212
|
-
# 0.4.2
|
|
213
|
-
|
|
214
|
-
- print version of reporter
|
|
215
|
-
- print number of uploaded artifacts
|
|
216
|
-
- print access mode for uploaded artifacts
|
|
217
|
-
|
|
218
|
-
# 0.4.1
|
|
219
|
-
|
|
220
|
-
Added `global.testomatioArtifacts = []` array which can be used to add arbitrary artifacts to a report.
|
|
221
|
-
|
|
222
|
-
```js
|
|
223
|
-
// inside a running test:
|
|
224
|
-
global.testomatioArtifacts.push('file/to/upload.png');
|
|
225
|
-
```
|
|
226
|
-
|
|
227
|
-
# 0.4.0
|
|
228
|
-
|
|
229
|
-
- Playwright: Introduced playwright/test support with screenshots and video artifacts
|
|
230
|
-
|
|
231
|
-
> Known issues: reporting using projects configured in Playwright does not work yet
|
|
232
|
-
|
|
233
|
-
- CodeceptJS: added video uploads
|
|
234
|
-
|
|
235
|
-
# 0.3.16
|
|
236
|
-
|
|
237
|
-
- CodeceptJS: fixed reporting tests with empty steps (on retry)
|
|
238
|
-
|
|
239
|
-
# 0.3.15
|
|
240
|
-
|
|
241
|
-
- Finish Run via API:
|
|
242
|
-
|
|
243
|
-
```
|
|
244
|
-
TESTOMATIO={apiKey} TESTOMATIO_RUN={runId} npx @testomatio/reporter@latest --finish
|
|
245
|
-
```
|
|
246
|
-
|
|
247
|
-
# 0.3.14
|
|
248
|
-
|
|
249
|
-
- Create an empty Run via API:
|
|
250
|
-
|
|
251
|
-
```
|
|
252
|
-
TESTOMATIO={apiKey} npx @testomatio/reporter@latest --launch
|
|
253
|
-
```
|
|
254
|
-
|
|
255
|
-
# 0.3.13
|
|
256
|
-
|
|
257
|
-
- Checking for a valid report URL
|
|
258
|
-
- Sending unlimited data on test report
|
|
259
|
-
|
|
260
|
-
# 0.3.12
|
|
261
|
-
|
|
262
|
-
- Fixed submitting arbitrary data on a test run
|
|
263
|
-
- Jest: fixed sending errors with stack traces
|
|
264
|
-
- Cypress: fixed sending reports
|
|
265
|
-
|
|
266
|
-
# 0.3.11
|
|
267
|
-
|
|
268
|
-
- Fixed circular JSON reference when submitting data to Testomatio
|
|
269
|
-
|
|
270
|
-
# 0.3.10
|
|
271
|
-
|
|
272
|
-
- Minor fixes
|
|
273
|
-
|
|
274
|
-
# 0.3.9
|
|
275
|
-
|
|
276
|
-
- Making all reporters to run without API key
|
|
277
|
-
|
|
278
|
-
# 0.3.8
|
|
279
|
-
|
|
280
|
-
- Fixed `npx start-test-run` to work with empty API keys
|
|
281
|
-
|
|
282
|
-
# 0.3.7
|
|
283
|
-
|
|
284
|
-
- Fixed release
|
|
285
|
-
|
|
286
|
-
# 0.3.6
|
|
287
|
-
|
|
288
|
-
- Update title and rungroup on start for scheduled runs.
|
|
289
|
-
|
|
290
|
-
# 0.3.5
|
|
291
|
-
|
|
292
|
-
- Added `TESTOMATIO_RUN` environment variable to pass id of a specific run to report
|
|
293
|
-
|
|
294
|
-
# 0.3.4
|
|
295
|
-
|
|
296
|
-
- Minor fixes
|
|
297
|
-
|
|
298
|
-
# 0.3.3
|
|
299
|
-
|
|
300
|
-
- [CodeceptJS] Fixed stack trace reporting
|
|
301
|
-
- [CodeceptJS] Fixed displaying of nested steps
|
|
302
|
-
- [CodeceptJS][mocha] Added assertion diff to report
|
|
303
|
-
|
|
304
|
-
# 0.3.2
|
|
305
|
-
|
|
306
|
-
- Fixed error message for S3 uploading
|
|
307
|
-
|
|
308
|
-
# 0.3.1
|
|
309
|
-
|
|
310
|
-
- [CodeceptJS] Better formatter for nested structures and BDD tests
|
|
311
|
-
|
|
312
|
-
# 0.3.0
|
|
313
|
-
|
|
314
|
-
- Added `TESTOMATIO_TITLE` env variable to set a name for Run
|
|
315
|
-
- Added `TESTOMATIO_RUNGROUP_TITLE` env variable to attach Run to RunGroup
|
|
316
|
-
- Added `TESTOMATIO_ENV` env variable to attach additional env values to report
|
|
317
|
-
- [CodeceptJS] **CodeceptJS v3 support**
|
|
318
|
-
- [CodeceptJS] Dropped support for CodeceptJS 2
|
|
319
|
-
- [CodeceptJS] Added support for before hooks
|
|
320
|
-
- [CodeceptJS] Log of steps
|
|
321
|
-
- [CodeceptJS] Upload screenshots of failed tests to S3
|
|
322
|
-
- [CodeceptJS] Updated to use with parallel execution
|