@testomatio/reporter 1.2.0-beta → 1.2.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/README.md +13 -9
- package/lib/_ArtifactStorageOld.js +1 -1
- package/lib/adapter/codecept.js +59 -39
- package/lib/adapter/cucumber/current.js +95 -59
- package/lib/adapter/cucumber/legacy.js +25 -11
- package/lib/adapter/cypress-plugin/index.js +1 -1
- package/lib/adapter/jasmine.js +1 -1
- package/lib/adapter/jest.js +18 -3
- package/lib/adapter/mocha.js +23 -23
- package/lib/adapter/playwright.js +18 -11
- package/lib/adapter/webdriver.js +1 -1
- package/lib/artifactStorage.js +2 -2
- package/lib/bin/reportXml.js +1 -0
- package/lib/bin/startTest.js +25 -4
- package/lib/client.js +102 -34
- package/lib/constants.js +7 -0
- package/lib/dataStorage.js +132 -72
- package/lib/junit-adapter/java.js +27 -9
- package/lib/logger.js +182 -164
- package/lib/pipe/csv.js +4 -1
- package/lib/pipe/github.js +24 -37
- package/lib/pipe/gitlab.js +5 -16
- package/lib/pipe/html.js +187 -0
- package/lib/pipe/index.js +2 -0
- package/lib/pipe/testomatio.js +138 -34
- package/lib/reporter.js +2 -1
- package/lib/template/real-data-example.js +47 -0
- package/lib/template/template.hbs +249 -0
- package/lib/template/testomatio.hbs +720 -0
- package/lib/utils/pipe_utils.js +135 -0
- package/lib/{util.js → utils/utils.js} +116 -10
- package/lib/xmlReader.js +132 -44
- package/package.json +10 -6
package/lib/adapter/mocha.js
CHANGED
|
@@ -3,55 +3,54 @@ const Mocha = require('mocha');
|
|
|
3
3
|
const debug = require('debug')('@testomatio/reporter:adapter:mocha');
|
|
4
4
|
const chalk = require('chalk');
|
|
5
5
|
const TestomatClient = require('../client');
|
|
6
|
-
const { STATUS } = require('../constants');
|
|
7
|
-
const { parseTest, specificTestInfo } = require('../
|
|
6
|
+
const { STATUS, TESTOMAT_TMP_STORAGE } = require('../constants');
|
|
7
|
+
const { parseTest, specificTestInfo, fileSystem } = require('../utils/utils');
|
|
8
8
|
const ArtifactStorage = require('../_ArtifactStorageOld');
|
|
9
9
|
|
|
10
|
-
const { EVENT_RUN_BEGIN, EVENT_RUN_END, EVENT_TEST_FAIL, EVENT_TEST_PASS, EVENT_TEST_PENDING } =
|
|
10
|
+
const { EVENT_RUN_BEGIN, EVENT_RUN_END, EVENT_TEST_FAIL, EVENT_TEST_PASS, EVENT_TEST_PENDING } =
|
|
11
|
+
Mocha.Runner.constants;
|
|
11
12
|
|
|
12
13
|
function MochaReporter(runner, opts) {
|
|
13
14
|
Mocha.reporters.Base.call(this, runner);
|
|
14
|
-
let passes = 0;
|
|
15
|
+
let passes = 0;
|
|
16
|
+
let failures = 0;
|
|
17
|
+
let skipped = 0;
|
|
15
18
|
let artifactStore;
|
|
16
19
|
|
|
17
20
|
const apiKey = opts?.reporterOptions?.apiKey || process.env.TESTOMATIO;
|
|
18
21
|
|
|
19
|
-
if (!apiKey) {
|
|
20
|
-
debug('TESTOMATIO key is empty, ignoring reports');
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
22
|
const client = new TestomatClient({ apiKey });
|
|
24
23
|
|
|
25
24
|
runner.on(EVENT_RUN_BEGIN, () => {
|
|
26
25
|
client.createRun();
|
|
27
26
|
|
|
28
|
-
const params = {
|
|
29
|
-
toFile: true
|
|
27
|
+
const params = {
|
|
28
|
+
toFile: true,
|
|
30
29
|
};
|
|
31
|
-
|
|
32
|
-
artifactStore = runner._workerReporter !== undefined
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
|
|
31
|
+
artifactStore = runner._workerReporter !== undefined ? new ArtifactStorage(params) : new ArtifactStorage();
|
|
32
|
+
|
|
33
|
+
fileSystem.clearDir(TESTOMAT_TMP_STORAGE.mainDir);
|
|
35
34
|
});
|
|
36
35
|
|
|
37
|
-
runner.on(EVENT_TEST_PASS, async
|
|
36
|
+
runner.on(EVENT_TEST_PASS, async test => {
|
|
38
37
|
passes += 1;
|
|
39
38
|
console.log(chalk.bold.green('✔'), test.fullTitle());
|
|
40
39
|
const testId = parseTest(test.title);
|
|
41
40
|
|
|
42
|
-
const specificTest =
|
|
41
|
+
const specificTest = specificTestInfo(test);
|
|
43
42
|
const content = await artifactStore.artifactByTestName(specificTest);
|
|
44
43
|
|
|
45
44
|
debug(`test=${specificTest} content = `, content);
|
|
46
45
|
|
|
47
46
|
client.addTestRun(
|
|
48
|
-
STATUS.PASSED,
|
|
47
|
+
STATUS.PASSED,
|
|
49
48
|
{
|
|
50
49
|
test_id: testId,
|
|
51
50
|
title: test.title,
|
|
52
51
|
time: test.duration,
|
|
53
52
|
},
|
|
54
|
-
content
|
|
53
|
+
content,
|
|
55
54
|
);
|
|
56
55
|
});
|
|
57
56
|
|
|
@@ -66,24 +65,25 @@ function MochaReporter(runner, opts) {
|
|
|
66
65
|
});
|
|
67
66
|
});
|
|
68
67
|
|
|
69
|
-
runner.on(EVENT_TEST_FAIL, async(test, err) => {
|
|
68
|
+
runner.on(EVENT_TEST_FAIL, async (test, err) => {
|
|
70
69
|
failures += 1;
|
|
71
70
|
console.log(chalk.bold.red('✖'), test.fullTitle(), chalk.gray(err.message));
|
|
72
71
|
const testId = parseTest(test.title);
|
|
73
72
|
|
|
74
|
-
const specificTest =
|
|
73
|
+
const specificTest = specificTestInfo(test);
|
|
75
74
|
const content = await artifactStore.artifactByTestName(specificTest);
|
|
76
75
|
|
|
77
76
|
debug(`fail test=${specificTest} content = `, content);
|
|
78
77
|
|
|
79
78
|
client.addTestRun(
|
|
80
|
-
STATUS.FAILED,
|
|
79
|
+
STATUS.FAILED,
|
|
80
|
+
{
|
|
81
81
|
error: err,
|
|
82
82
|
test_id: testId,
|
|
83
83
|
title: test.title,
|
|
84
84
|
time: test.duration,
|
|
85
|
-
},
|
|
86
|
-
content
|
|
85
|
+
},
|
|
86
|
+
content,
|
|
87
87
|
);
|
|
88
88
|
});
|
|
89
89
|
|
|
@@ -3,14 +3,14 @@ const crypto = require('crypto');
|
|
|
3
3
|
const os = require('os');
|
|
4
4
|
const path = require('path');
|
|
5
5
|
const fs = require('fs');
|
|
6
|
-
const { APP_PREFIX, STATUS: Status } = require('../constants');
|
|
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 } = require('../
|
|
9
|
+
const { parseTest, fileSystem } = require('../utils/utils');
|
|
10
10
|
|
|
11
11
|
const reportTestPromises = [];
|
|
12
12
|
|
|
13
|
-
class
|
|
13
|
+
class PlaywrightReporter {
|
|
14
14
|
constructor(config = {}) {
|
|
15
15
|
this.client = new TestomatioClient({ apiKey: config?.apiKey });
|
|
16
16
|
|
|
@@ -18,11 +18,17 @@ class TestomatioReporter {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
onBegin(_config, suite) {
|
|
21
|
+
// clean data storage
|
|
22
|
+
fileSystem.clearDir(TESTOMAT_TMP_STORAGE.mainDir);
|
|
21
23
|
if (!this.client) return;
|
|
22
24
|
this.suite = suite;
|
|
23
25
|
this.client.createRun();
|
|
24
26
|
}
|
|
25
27
|
|
|
28
|
+
// onTestBegin(test) {
|
|
29
|
+
// const testId = parseTest(test.title);
|
|
30
|
+
// }
|
|
31
|
+
|
|
26
32
|
onTestEnd(test, result) {
|
|
27
33
|
if (!this.client) return;
|
|
28
34
|
|
|
@@ -37,7 +43,9 @@ class TestomatioReporter {
|
|
|
37
43
|
for (const step of result.steps) {
|
|
38
44
|
appendStep(step, steps);
|
|
39
45
|
}
|
|
40
|
-
|
|
46
|
+
|
|
47
|
+
const logs = `\n\n${chalk.bold('Logs:')}\n${chalk.red(result.stderr.join(''))}\n${result.stdout.join('')}`;
|
|
48
|
+
|
|
41
49
|
const reportTestPromise = this.client.addTestRun(checkStatus(result.status), {
|
|
42
50
|
error,
|
|
43
51
|
test_id: testId,
|
|
@@ -45,13 +53,14 @@ class TestomatioReporter {
|
|
|
45
53
|
title,
|
|
46
54
|
steps: steps.join('\n'),
|
|
47
55
|
time: duration,
|
|
56
|
+
stack: logs,
|
|
48
57
|
}).then(pipes => {
|
|
49
|
-
testId = pipes
|
|
58
|
+
testId = pipes?.filter(p => p.pipe.includes('Testomatio'))[0]?.result?.data?.test_id;
|
|
50
59
|
|
|
51
60
|
this.uploads.push({
|
|
52
61
|
testId, title, suite_title, files: result.attachments.filter((a) => a.body || a.path)
|
|
53
|
-
})
|
|
54
|
-
})
|
|
62
|
+
});
|
|
63
|
+
});
|
|
55
64
|
|
|
56
65
|
reportTestPromises.push(reportTestPromise);
|
|
57
66
|
}
|
|
@@ -67,10 +76,9 @@ class TestomatioReporter {
|
|
|
67
76
|
const promises = [];
|
|
68
77
|
|
|
69
78
|
for (const upload of this.uploads) {
|
|
70
|
-
|
|
71
79
|
const { title, testId, suite_title } = upload;
|
|
72
80
|
|
|
73
|
-
const files = upload.files.map(
|
|
81
|
+
const files = upload.files.map(attachment => {
|
|
74
82
|
if (attachment.body) {
|
|
75
83
|
const fileName = tmpFile();
|
|
76
84
|
fs.writeFileSync(fileName, attachment.body);
|
|
@@ -78,7 +86,6 @@ class TestomatioReporter {
|
|
|
78
86
|
return { path: attachment.path, title, type: attachment.contentType };
|
|
79
87
|
});
|
|
80
88
|
|
|
81
|
-
|
|
82
89
|
promises.push(
|
|
83
90
|
this.client.addTestRun(undefined, {
|
|
84
91
|
test_id: testId,
|
|
@@ -124,4 +131,4 @@ function tmpFile(prefix = 'tmp.') {
|
|
|
124
131
|
return path.join(tmpdir, prefix + crypto.randomBytes(16).toString('hex'));
|
|
125
132
|
}
|
|
126
133
|
|
|
127
|
-
module.exports =
|
|
134
|
+
module.exports = PlaywrightReporter;
|
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/artifactStorage.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
const { DataStorage } = require('./dataStorage');
|
|
3
3
|
|
|
4
4
|
class ArtifactStorage {
|
|
5
|
-
constructor(
|
|
6
|
-
this.dataStorage = new DataStorage('artifact'
|
|
5
|
+
constructor() {
|
|
6
|
+
this.dataStorage = new DataStorage('artifact');
|
|
7
7
|
|
|
8
8
|
// singleton
|
|
9
9
|
if (!ArtifactStorage.instance) {
|
package/lib/bin/reportXml.js
CHANGED
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
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
const debug = require('debug')('@testomatio/reporter:client');
|
|
2
2
|
const createCallsiteRecord = require('callsite-record');
|
|
3
3
|
const { sep, join } = require('path');
|
|
4
|
+
const { minimatch } = require('minimatch')
|
|
4
5
|
const fs = require('fs');
|
|
5
6
|
const chalk = require('chalk');
|
|
6
7
|
const { randomUUID } = require('crypto');
|
|
7
8
|
const upload = require('./fileUploader');
|
|
8
9
|
const { APP_PREFIX } = require('./constants');
|
|
9
10
|
const pipesFactory = require('./pipe');
|
|
10
|
-
const logger = require('./logger');
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* @typedef {import('../types').TestData} TestData
|
|
14
14
|
* @typedef {import('../types').RunStatus} RunStatus
|
|
15
|
-
* @typedef {import('../types').PipeResult} PipeResult
|
|
15
|
+
* @typedef {import('../types').PipeResult} PipeResult
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
18
|
class Client {
|
|
@@ -22,39 +22,88 @@ class Client {
|
|
|
22
22
|
* @param {*} params
|
|
23
23
|
*/
|
|
24
24
|
constructor(params = {}) {
|
|
25
|
-
this.parallel = params.parallel;
|
|
26
25
|
const store = {};
|
|
27
26
|
this.uuid = randomUUID();
|
|
28
27
|
this.pipes = pipesFactory(params, store);
|
|
29
28
|
this.queue = Promise.resolve();
|
|
30
29
|
this.totalUploaded = 0;
|
|
31
30
|
this.version = JSON.parse(fs.readFileSync(join(__dirname, '..', 'package.json')).toString()).version;
|
|
31
|
+
this.executionList = Promise.resolve();
|
|
32
|
+
|
|
32
33
|
console.log(APP_PREFIX, `Testomatio Reporter v${this.version}`);
|
|
33
34
|
}
|
|
34
35
|
|
|
36
|
+
/**
|
|
37
|
+
* Asynchronously prepares the execution list for running tests through various pipes.
|
|
38
|
+
* Each pipe in the client is checked for enablement,
|
|
39
|
+
* and if all pipes are disabled, the function returns a resolved Promise.
|
|
40
|
+
* Otherwise, it executes the `prepareRun` method for each enabled pipe and collects the results.
|
|
41
|
+
* The results are then filtered to remove any undefined values.
|
|
42
|
+
* If no valid results are found, the function returns undefined.
|
|
43
|
+
* Otherwise, it returns the first non-empty array from the filtered results.
|
|
44
|
+
*
|
|
45
|
+
* @param {Object} params - The options for preparing the test execution list.
|
|
46
|
+
* @param {string} params.pipe - Name of the executed pipe.
|
|
47
|
+
* @param {string} params.pipeOptions - Filter option.
|
|
48
|
+
* @returns {Promise<any>} - A Promise that resolves to an
|
|
49
|
+
* array containing the prepared execution list,
|
|
50
|
+
* or resolves to undefined if no valid results are found or if all pipes are disabled.
|
|
51
|
+
*/
|
|
52
|
+
async prepareRun(params) {
|
|
53
|
+
const { pipe, pipeOptions } = params;
|
|
54
|
+
// all pipes disabled, skipping
|
|
55
|
+
if (!this.pipes.some(p => p.isEnabled)) {
|
|
56
|
+
return Promise.resolve();
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
try {
|
|
60
|
+
const filterPipe = this.pipes.find(p => p.constructor.name.toLowerCase() === `${pipe.toLowerCase()}pipe`);
|
|
61
|
+
|
|
62
|
+
if (!filterPipe.isEnabled) {
|
|
63
|
+
// TODO:for the future for the another pipes
|
|
64
|
+
console.warn(
|
|
65
|
+
APP_PREFIX,
|
|
66
|
+
`At the moment processing is available only for the "testomatio" key. Example: "testomatio:tag-name=xxx"`
|
|
67
|
+
);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const results = await Promise.all(this.pipes.map(async p =>
|
|
72
|
+
({ pipe: p.toString(), result: await p.prepareRun(pipeOptions) })
|
|
73
|
+
));
|
|
74
|
+
|
|
75
|
+
const result = results.filter(p => p.pipe.includes('Testomatio'))[0]?.result;
|
|
76
|
+
|
|
77
|
+
if (!result || result.length === 0) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
debug('Execution tests list', result);
|
|
82
|
+
|
|
83
|
+
return result;
|
|
84
|
+
} catch (err) {
|
|
85
|
+
console.error(APP_PREFIX, err);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
35
89
|
/**
|
|
36
90
|
* Used to create a new Test run
|
|
37
91
|
*
|
|
38
92
|
* @returns {Promise<any>} - resolves to Run id which should be used to update / add test
|
|
39
93
|
*/
|
|
40
94
|
createRun() {
|
|
95
|
+
debug('Creating run...');
|
|
41
96
|
// all pipes disabled, skipping
|
|
42
|
-
if (!this.pipes
|
|
43
|
-
|
|
44
|
-
const runParams = {
|
|
45
|
-
title: this.title,
|
|
46
|
-
parallel: this.parallel,
|
|
47
|
-
env: this.env,
|
|
48
|
-
};
|
|
97
|
+
if (!this.pipes?.filter(p => p.isEnabled).length) return Promise.resolve();
|
|
49
98
|
|
|
50
99
|
global.testomatioArtifacts = [];
|
|
51
|
-
|
|
100
|
+
if (!global.testomatioDataStore) global.testomatioDataStore = {};
|
|
52
101
|
|
|
53
102
|
this.queue = this.queue
|
|
54
|
-
.then(() => Promise.all(this.pipes.map(p => p.createRun(
|
|
103
|
+
.then(() => Promise.all(this.pipes.map(p => p.createRun())))
|
|
55
104
|
.catch(err => console.log(APP_PREFIX, err))
|
|
56
105
|
.then(() => undefined); // fixes return type
|
|
57
|
-
debug('Run', this.queue);
|
|
106
|
+
// debug('Run', this.queue);
|
|
58
107
|
return this.queue;
|
|
59
108
|
}
|
|
60
109
|
|
|
@@ -67,8 +116,9 @@ class Client {
|
|
|
67
116
|
* @returns {Promise<PipeResult[]>}
|
|
68
117
|
*/
|
|
69
118
|
async addTestRun(status, testData, storeArtifacts = []) {
|
|
119
|
+
debug('Adding test run for test', testData?.test_id || 'unknown test');
|
|
70
120
|
// all pipes disabled, skipping
|
|
71
|
-
if (!this.pipes
|
|
121
|
+
if (!this.pipes?.filter(p => p.isEnabled).length) return [];
|
|
72
122
|
|
|
73
123
|
if (!testData)
|
|
74
124
|
testData = {
|
|
@@ -103,9 +153,14 @@ class Client {
|
|
|
103
153
|
stack = this.formatSteps(stack, steps);
|
|
104
154
|
}
|
|
105
155
|
|
|
156
|
+
stack += testData.stack || '';
|
|
157
|
+
|
|
158
|
+
// in some cases (e.g. using cucumber) logger instance becomes empty object, if import at the top of the file
|
|
159
|
+
const logger = require('./logger');
|
|
106
160
|
const testLogs = logger.getLogs(test_id);
|
|
107
|
-
debug(`Test logs for ${test_id}:\n`, testLogs);
|
|
108
|
-
stack +=
|
|
161
|
+
// debug(`Test logs for ${test_id}:\n`, testLogs);
|
|
162
|
+
if (stack) stack += '\n\n';
|
|
163
|
+
stack += testLogs ? `${chalk.bold('Logs:')}\n${testLogs}` : '';
|
|
109
164
|
|
|
110
165
|
if (Array.isArray(storeArtifacts) && storeArtifacts.length) {
|
|
111
166
|
debug('CLIENT storeArtifact', storeArtifacts);
|
|
@@ -149,17 +204,19 @@ class Client {
|
|
|
149
204
|
artifacts,
|
|
150
205
|
};
|
|
151
206
|
|
|
152
|
-
this.queue = this.queue
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
207
|
+
this.queue = this.queue.then(() =>
|
|
208
|
+
Promise.all(
|
|
209
|
+
this.pipes.map(async p => {
|
|
210
|
+
try {
|
|
211
|
+
const result = await p.addTest(data);
|
|
212
|
+
return { pipe: p.toString(), result };
|
|
213
|
+
} catch (err) {
|
|
214
|
+
console.log(APP_PREFIX, p.toString(), err);
|
|
215
|
+
}
|
|
216
|
+
}),
|
|
217
|
+
),
|
|
218
|
+
);
|
|
219
|
+
|
|
163
220
|
return this.queue;
|
|
164
221
|
}
|
|
165
222
|
|
|
@@ -171,8 +228,9 @@ class Client {
|
|
|
171
228
|
* @returns {Promise<any>} - A Promise that resolves when finishes the run.
|
|
172
229
|
*/
|
|
173
230
|
updateRunStatus(status, isParallel = false) {
|
|
231
|
+
debug('Updating run status...');
|
|
174
232
|
// all pipes disabled, skipping
|
|
175
|
-
if (!this.pipes
|
|
233
|
+
if (!this.pipes?.filter(p => p.isEnabled).length) return Promise.resolve();
|
|
176
234
|
|
|
177
235
|
const runParams = { status, parallel: isParallel };
|
|
178
236
|
|
|
@@ -213,17 +271,21 @@ class Client {
|
|
|
213
271
|
stack += '\n\n';
|
|
214
272
|
}
|
|
215
273
|
|
|
274
|
+
const customFilter = process.env.TESTOMATIO_STACK_IGNORE;
|
|
275
|
+
|
|
216
276
|
try {
|
|
277
|
+
let hasFrame = false;
|
|
217
278
|
const record = createCallsiteRecord({
|
|
218
279
|
forError: error,
|
|
280
|
+
isCallsiteFrame: frame => {
|
|
281
|
+
if (customFilter && minimatch(frame.getFileName(), customFilter)) return false;
|
|
282
|
+
if (hasFrame) return false;
|
|
283
|
+
if (isNotInternalFrame(frame)) hasFrame = true;
|
|
284
|
+
return hasFrame;
|
|
285
|
+
}
|
|
219
286
|
});
|
|
220
287
|
if (record && !record.filename.startsWith('http')) {
|
|
221
|
-
stack += record.renderSync({
|
|
222
|
-
stackFilter: frame =>
|
|
223
|
-
frame.getFileName().indexOf(sep) > -1 &&
|
|
224
|
-
frame.getFileName().indexOf('node_modules') < 0 &&
|
|
225
|
-
frame.getFileName().indexOf('internal') < 0,
|
|
226
|
-
});
|
|
288
|
+
stack += record.renderSync({ stackFilter: isNotInternalFrame });
|
|
227
289
|
}
|
|
228
290
|
return stack;
|
|
229
291
|
} catch (e) {
|
|
@@ -232,4 +294,10 @@ class Client {
|
|
|
232
294
|
}
|
|
233
295
|
}
|
|
234
296
|
|
|
297
|
+
function isNotInternalFrame(frame) {
|
|
298
|
+
return frame.getFileName().includes(sep) &&
|
|
299
|
+
!frame.getFileName().includes('node_modules') &&
|
|
300
|
+
!frame.getFileName().includes('internal')
|
|
301
|
+
}
|
|
302
|
+
|
|
235
303
|
module.exports = Client;
|
package/lib/constants.js
CHANGED
|
@@ -21,6 +21,12 @@ const STATUS = {
|
|
|
21
21
|
SKIPPED: 'skipped',
|
|
22
22
|
FINISHED: 'finished',
|
|
23
23
|
};
|
|
24
|
+
// html pipe var
|
|
25
|
+
const HTML_REPORT = {
|
|
26
|
+
FOLDER: "html-report",
|
|
27
|
+
REPORT_DEFAULT_NAME: "testomatio-report.html",
|
|
28
|
+
TEMPLATE_NAME: 'testomatio.hbs'
|
|
29
|
+
};
|
|
24
30
|
|
|
25
31
|
module.exports = {
|
|
26
32
|
APP_PREFIX,
|
|
@@ -28,4 +34,5 @@ module.exports = {
|
|
|
28
34
|
TESTOMAT_TMP_STORAGE,
|
|
29
35
|
CSV_HEADERS,
|
|
30
36
|
STATUS,
|
|
37
|
+
HTML_REPORT
|
|
31
38
|
}
|