@testomatio/reporter 1.6.13 → 2.0.1-beta-esm
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/adapter/codecept.d.ts +2 -0
- package/lib/adapter/codecept.js +295 -335
- package/lib/adapter/cucumber/current.d.ts +14 -0
- package/lib/adapter/cucumber/current.js +195 -203
- package/lib/adapter/cucumber/legacy.d.ts +0 -0
- package/lib/adapter/cucumber/legacy.js +130 -155
- package/lib/adapter/cucumber.d.ts +2 -0
- package/lib/adapter/cucumber.js +5 -16
- package/lib/adapter/cypress-plugin/index.d.ts +2 -0
- package/lib/adapter/cypress-plugin/index.js +93 -105
- package/lib/adapter/jasmine.d.ts +11 -0
- package/lib/adapter/jasmine.js +54 -53
- package/lib/adapter/jest.d.ts +13 -0
- package/lib/adapter/jest.js +97 -99
- package/lib/adapter/mocha.d.ts +2 -0
- package/lib/adapter/mocha.js +112 -140
- package/lib/adapter/playwright.d.ts +14 -0
- package/lib/adapter/playwright.js +195 -231
- package/lib/adapter/vitest.d.ts +35 -0
- package/lib/adapter/vitest.js +150 -149
- package/lib/adapter/webdriver.d.ts +24 -0
- package/lib/adapter/webdriver.js +134 -119
- package/lib/bin/cli.d.ts +2 -0
- package/lib/bin/cli.js +164 -211
- package/lib/bin/reportXml.d.ts +2 -0
- package/lib/bin/reportXml.js +49 -52
- package/lib/bin/startTest.d.ts +2 -0
- package/lib/bin/startTest.js +82 -95
- package/lib/bin/uploadArtifacts.d.ts +2 -0
- package/lib/bin/uploadArtifacts.js +55 -61
- package/lib/client.d.ts +76 -0
- package/lib/client.js +411 -465
- package/lib/config.d.ts +1 -0
- package/lib/config.js +16 -21
- package/lib/constants.d.ts +25 -0
- package/lib/constants.js +50 -44
- package/lib/data-storage.d.ts +34 -0
- package/lib/data-storage.js +206 -188
- package/lib/junit-adapter/adapter.d.ts +9 -0
- package/lib/junit-adapter/adapter.js +17 -20
- package/lib/junit-adapter/csharp.d.ts +4 -0
- package/lib/junit-adapter/csharp.js +18 -14
- package/lib/junit-adapter/index.d.ts +3 -0
- package/lib/junit-adapter/index.js +27 -25
- package/lib/junit-adapter/java.d.ts +5 -0
- package/lib/junit-adapter/java.js +41 -53
- package/lib/junit-adapter/javascript.d.ts +4 -0
- package/lib/junit-adapter/javascript.js +30 -27
- package/lib/junit-adapter/python.d.ts +5 -0
- package/lib/junit-adapter/python.js +38 -37
- package/lib/junit-adapter/ruby.d.ts +4 -0
- package/lib/junit-adapter/ruby.js +11 -8
- package/lib/output.d.ts +11 -0
- package/lib/output.js +44 -52
- package/lib/package.json +3 -0
- package/lib/pipe/bitbucket.d.ts +23 -0
- package/lib/pipe/bitbucket.js +210 -229
- package/lib/pipe/csv.d.ts +47 -0
- package/lib/pipe/csv.js +113 -126
- package/lib/pipe/debug.d.ts +29 -0
- package/lib/pipe/debug.js +104 -99
- package/lib/pipe/github.d.ts +30 -0
- package/lib/pipe/github.js +186 -213
- package/lib/pipe/gitlab.d.ts +23 -0
- package/lib/pipe/gitlab.js +166 -207
- package/lib/pipe/html.d.ts +34 -0
- package/lib/pipe/html.js +260 -319
- package/lib/pipe/index.d.ts +1 -0
- package/lib/pipe/index.js +84 -66
- package/lib/pipe/testomatio.d.ts +70 -0
- package/lib/pipe/testomatio.js +413 -462
- package/lib/reporter-functions.d.ts +34 -0
- package/lib/reporter-functions.js +28 -26
- package/lib/reporter.d.ts +232 -0
- package/lib/reporter.js +34 -29
- package/lib/services/artifacts.d.ts +33 -0
- package/lib/services/artifacts.js +55 -51
- package/lib/services/index.d.ts +9 -0
- package/lib/services/index.js +14 -12
- package/lib/services/key-values.d.ts +27 -0
- package/lib/services/key-values.js +56 -53
- package/lib/services/logger.d.ts +64 -0
- package/lib/services/logger.js +227 -245
- package/lib/template/testomatio.hbs +651 -1366
- package/lib/uploader.d.ts +60 -0
- package/lib/uploader.js +291 -360
- package/lib/utils/pipe_utils.d.ts +41 -0
- package/lib/utils/pipe_utils.js +89 -85
- package/lib/utils/utils.d.ts +45 -0
- package/lib/utils/utils.js +347 -307
- package/lib/xmlReader.d.ts +92 -0
- package/lib/xmlReader.js +490 -529
- package/package.json +57 -15
- package/src/adapter/codecept.js +375 -0
- package/src/adapter/cucumber/current.js +228 -0
- package/src/adapter/cucumber/legacy.js +158 -0
- package/src/adapter/cucumber.js +4 -0
- package/src/adapter/cypress-plugin/index.js +112 -0
- package/src/adapter/jasmine.js +60 -0
- package/src/adapter/jest.js +107 -0
- package/src/adapter/mocha.cjs +2 -0
- package/src/adapter/mocha.js +157 -0
- package/src/adapter/playwright.js +250 -0
- package/src/adapter/vitest.js +183 -0
- package/src/adapter/webdriver.js +142 -0
- package/src/bin/cli.js +280 -0
- package/src/bin/reportXml.js +74 -0
- package/src/bin/startTest.js +123 -0
- package/src/bin/uploadArtifacts.js +90 -0
- package/src/client.js +504 -0
- package/src/config.js +30 -0
- package/src/constants.js +53 -0
- package/src/data-storage.js +204 -0
- package/src/junit-adapter/adapter.js +23 -0
- package/src/junit-adapter/csharp.js +16 -0
- package/src/junit-adapter/index.js +28 -0
- package/src/junit-adapter/java.js +58 -0
- package/src/junit-adapter/javascript.js +31 -0
- package/src/junit-adapter/python.js +42 -0
- package/src/junit-adapter/ruby.js +10 -0
- package/src/output.js +57 -0
- package/src/pipe/bitbucket.js +254 -0
- package/src/pipe/csv.js +140 -0
- package/src/pipe/debug.js +104 -0
- package/src/pipe/github.js +233 -0
- package/src/pipe/gitlab.js +229 -0
- package/src/pipe/html.js +374 -0
- package/src/pipe/index.js +71 -0
- package/src/pipe/testomatio.js +503 -0
- package/src/reporter-functions.js +55 -0
- package/src/reporter.cjs_decprecated +21 -0
- package/src/reporter.js +33 -0
- package/src/services/artifacts.js +59 -0
- package/src/services/index.js +13 -0
- package/src/services/key-values.js +59 -0
- package/src/services/logger.js +316 -0
- package/src/template/emptyData.svg +23 -0
- package/src/template/testomatio.hbs +706 -0
- package/src/uploader.js +371 -0
- package/src/utils/pipe_utils.js +119 -0
- package/src/utils/utils.js +383 -0
- package/src/xmlReader.js +562 -0
package/lib/client.js
CHANGED
|
@@ -1,497 +1,443 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.Client = void 0;
|
|
30
|
+
const debug_1 = __importDefault(require("debug"));
|
|
31
|
+
const callsite_record_1 = __importDefault(require("callsite-record"));
|
|
32
|
+
const minimatch_1 = require("minimatch");
|
|
33
|
+
const fs_1 = __importDefault(require("fs"));
|
|
34
|
+
const picocolors_1 = __importDefault(require("picocolors"));
|
|
35
|
+
const crypto_1 = require("crypto");
|
|
36
|
+
const constants_js_1 = require("./constants.js");
|
|
37
|
+
const index_js_1 = require("./pipe/index.js");
|
|
38
|
+
const glob_1 = require("glob");
|
|
39
|
+
const path_1 = __importStar(require("path"));
|
|
40
|
+
const node_url_1 = require("node:url");
|
|
41
|
+
const uploader_js_1 = require("./uploader.js");
|
|
42
|
+
const utils_js_1 = require("./utils/utils.js");
|
|
43
|
+
const filesize_1 = require("filesize");
|
|
44
|
+
const debug = (0, debug_1.default)('@testomatio/reporter:client');
|
|
45
|
+
// removed __dirname usage, because:
|
|
46
|
+
// 1. replaced with ESM syntax (import.meta.url), but it throws an error on tsc compilation;
|
|
47
|
+
// 2. got error "__dirname already defined" in compiles js code (cjs dir)
|
|
16
48
|
let listOfTestFilesToExcludeFromReport = null;
|
|
17
|
-
|
|
18
49
|
/**
|
|
19
|
-
* @typedef {import('../types').TestData} TestData
|
|
20
|
-
* @typedef {import('../types').
|
|
21
|
-
* @typedef {import('../types').PipeResult} PipeResult
|
|
50
|
+
* @typedef {import('../types/types.js').TestData} TestData
|
|
51
|
+
* @typedef {import('../types/types.js').PipeResult} PipeResult
|
|
22
52
|
*/
|
|
23
|
-
|
|
24
53
|
class Client {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
* Otherwise, it executes the `prepareRun` method for each enabled pipe and collects the results.
|
|
47
|
-
* The results are then filtered to remove any undefined values.
|
|
48
|
-
* If no valid results are found, the function returns undefined.
|
|
49
|
-
* Otherwise, it returns the first non-empty array from the filtered results.
|
|
50
|
-
*
|
|
51
|
-
* @param {Object} params - The options for preparing the test execution list.
|
|
52
|
-
* @param {string} params.pipe - Name of the executed pipe.
|
|
53
|
-
* @param {string} params.pipeOptions - Filter option.
|
|
54
|
-
* @returns {Promise<any>} - A Promise that resolves to an
|
|
55
|
-
* array containing the prepared execution list,
|
|
56
|
-
* or resolves to undefined if no valid results are found or if all pipes are disabled.
|
|
57
|
-
*/
|
|
58
|
-
async prepareRun(params) {
|
|
59
|
-
const { pipe, pipeOptions } = params;
|
|
60
|
-
// all pipes disabled, skipping
|
|
61
|
-
if (!this.pipes.some(p => p.isEnabled)) {
|
|
62
|
-
return Promise.resolve();
|
|
54
|
+
/**
|
|
55
|
+
* Create a Testomat client instance
|
|
56
|
+
* @returns
|
|
57
|
+
*/
|
|
58
|
+
// eslint-disable-next-line
|
|
59
|
+
constructor(params = {}) {
|
|
60
|
+
this.paramsForPipesFactory = params;
|
|
61
|
+
this.pipeStore = {};
|
|
62
|
+
this.runId = (0, crypto_1.randomUUID)(); // will be replaced by real run id
|
|
63
|
+
this.queue = Promise.resolve();
|
|
64
|
+
// @ts-ignore this line will be removed in compiled code, because __dirname is defined in commonjs
|
|
65
|
+
const pathToPackageJSON = path_1.default.join(__dirname, '../package.json');
|
|
66
|
+
try {
|
|
67
|
+
this.version = JSON.parse(fs_1.default.readFileSync(pathToPackageJSON).toString()).version;
|
|
68
|
+
console.log(constants_js_1.APP_PREFIX, `Testomatio Reporter v${this.version}`);
|
|
69
|
+
}
|
|
70
|
+
catch (e) {
|
|
71
|
+
// do nothing
|
|
72
|
+
}
|
|
73
|
+
this.executionList = Promise.resolve();
|
|
74
|
+
this.uploader = new uploader_js_1.S3Uploader();
|
|
63
75
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
76
|
+
/**
|
|
77
|
+
* Asynchronously prepares the execution list for running tests through various pipes.
|
|
78
|
+
* Each pipe in the client is checked for enablement,
|
|
79
|
+
* and if all pipes are disabled, the function returns a resolved Promise.
|
|
80
|
+
* Otherwise, it executes the `prepareRun` method for each enabled pipe and collects the results.
|
|
81
|
+
* The results are then filtered to remove any undefined values.
|
|
82
|
+
* If no valid results are found, the function returns undefined.
|
|
83
|
+
* Otherwise, it returns the first non-empty array from the filtered results.
|
|
84
|
+
*
|
|
85
|
+
* @param {Object} params - The options for preparing the test execution list.
|
|
86
|
+
* @param {string} params.pipe - Name of the executed pipe.
|
|
87
|
+
* @param {string} params.pipeOptions - Filter option.
|
|
88
|
+
* @returns {Promise<any>} - A Promise that resolves to an
|
|
89
|
+
* array containing the prepared execution list,
|
|
90
|
+
* or resolves to undefined if no valid results are found or if all pipes are disabled.
|
|
91
|
+
*/
|
|
92
|
+
async prepareRun(params) {
|
|
93
|
+
this.pipes = await (0, index_js_1.pipesFactory)(params || this.paramsForPipesFactory || {}, this.pipeStore);
|
|
94
|
+
const { pipe, pipeOptions } = params;
|
|
95
|
+
// all pipes disabled, skipping
|
|
96
|
+
if (!this.pipes.some(p => p.isEnabled)) {
|
|
97
|
+
return Promise.resolve();
|
|
98
|
+
}
|
|
99
|
+
try {
|
|
100
|
+
const filterPipe = this.pipes.find(p => p.constructor.name.toLowerCase() === `${pipe.toLowerCase()}pipe`);
|
|
101
|
+
if (!filterPipe.isEnabled) {
|
|
102
|
+
// TODO:for the future for the another pipes
|
|
103
|
+
console.warn(constants_js_1.APP_PREFIX, `At the moment processing is available only for the "testomatio" key. Example: "testomatio:tag-name=xxx"`);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
const results = await Promise.all(this.pipes.map(async (p) => ({ pipe: p.toString(), result: await p.prepareRun(pipeOptions) })));
|
|
107
|
+
const result = results.filter(p => p.pipe.includes('Testomatio'))[0]?.result;
|
|
108
|
+
if (!result || result.length === 0) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
debug('Execution tests list', result);
|
|
112
|
+
return result;
|
|
113
|
+
}
|
|
114
|
+
catch (err) {
|
|
115
|
+
console.error(constants_js_1.APP_PREFIX, err);
|
|
116
|
+
}
|
|
92
117
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
// debug('Run', this.queue);
|
|
119
|
-
return this.queue;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Updates test status and its data
|
|
124
|
-
*
|
|
125
|
-
* @param {string|undefined} status
|
|
126
|
-
* @param {TestData} [testData]
|
|
127
|
-
* @returns {Promise<PipeResult[]>}
|
|
128
|
-
*/
|
|
129
|
-
async addTestRun(status, testData) {
|
|
130
|
-
// all pipes disabled, skipping
|
|
131
|
-
if (!this.pipes?.filter(p => p.isEnabled).length) return [];
|
|
132
|
-
|
|
133
|
-
if (isTestShouldBeExculedFromReport(testData)) return [];
|
|
134
|
-
|
|
135
|
-
if (status === STATUS.SKIPPED && process.env.TESTOMATIO_EXCLUDE_SKIPPED) {
|
|
136
|
-
debug('Skipping test from report', testData?.title);
|
|
137
|
-
return []; // do not log skipped tests
|
|
118
|
+
/**
|
|
119
|
+
* Used to create a new Test run
|
|
120
|
+
*
|
|
121
|
+
* @returns {Promise<any>} - resolves to Run id which should be used to update / add test
|
|
122
|
+
*/
|
|
123
|
+
async createRun(params) {
|
|
124
|
+
if (!this.pipes || !this.pipes.length)
|
|
125
|
+
this.pipes = await (0, index_js_1.pipesFactory)(params || this.paramsForPipesFactory || {}, this.pipeStore);
|
|
126
|
+
debug('Creating run...');
|
|
127
|
+
// all pipes disabled, skipping
|
|
128
|
+
if (!this.pipes?.filter(p => p.isEnabled).length)
|
|
129
|
+
return Promise.resolve();
|
|
130
|
+
this.queue = this.queue
|
|
131
|
+
.then(() => Promise.all(this.pipes.map(p => p.createRun())))
|
|
132
|
+
.catch(err => console.log(constants_js_1.APP_PREFIX, err))
|
|
133
|
+
.then(() => {
|
|
134
|
+
const runId = this.pipeStore?.runId;
|
|
135
|
+
if (runId)
|
|
136
|
+
this.runId = runId;
|
|
137
|
+
(0, utils_js_1.storeRunId)(this.runId);
|
|
138
|
+
})
|
|
139
|
+
.then(() => this.uploader.checkEnabled())
|
|
140
|
+
.then(() => undefined); // fixes return type
|
|
141
|
+
// debug('Run', this.queue);
|
|
142
|
+
return this.queue;
|
|
138
143
|
}
|
|
139
|
-
|
|
140
|
-
if (!testData)
|
|
141
|
-
testData = {
|
|
142
|
-
title: 'Unknown test',
|
|
143
|
-
suite_title: 'Unknown suite',
|
|
144
|
-
};
|
|
145
|
-
|
|
146
144
|
/**
|
|
147
|
-
*
|
|
145
|
+
* Updates test status and its data
|
|
146
|
+
*
|
|
147
|
+
* @param {string|undefined} status
|
|
148
|
+
* @param {TestData} [testData]
|
|
149
|
+
* @returns {Promise<PipeResult[]>}
|
|
148
150
|
*/
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
value = JSON.stringify(value);
|
|
174
|
-
} else if (typeof value !== 'string') {
|
|
151
|
+
async addTestRun(status, testData) {
|
|
152
|
+
// all pipes disabled, skipping
|
|
153
|
+
if (!this.pipes?.filter(p => p.isEnabled).length)
|
|
154
|
+
return [];
|
|
155
|
+
if (isTestShouldBeExculedFromReport(testData))
|
|
156
|
+
return [];
|
|
157
|
+
if (status === constants_js_1.STATUS.SKIPPED && process.env.TESTOMATIO_EXCLUDE_SKIPPED) {
|
|
158
|
+
debug('Skipping test from report', testData?.title);
|
|
159
|
+
return []; // do not log skipped tests
|
|
160
|
+
}
|
|
161
|
+
if (!testData)
|
|
162
|
+
testData = {
|
|
163
|
+
title: 'Unknown test',
|
|
164
|
+
suite_title: 'Unknown suite',
|
|
165
|
+
};
|
|
166
|
+
/**
|
|
167
|
+
* @type {TestData}
|
|
168
|
+
*/
|
|
169
|
+
const { rid, error = null, time = 0, example = null, files = [], filesBuffers = [], steps, code = null, title, file, suite_title, suite_id, test_id, manuallyAttachedArtifacts, } = testData;
|
|
170
|
+
let { message = '', meta = {} } = testData;
|
|
171
|
+
// stringify meta values and limit keys and values length to 255
|
|
172
|
+
meta = Object.entries(meta)
|
|
173
|
+
.filter(([, value]) => value !== null && value !== undefined)
|
|
174
|
+
.map(([key, value]) => {
|
|
175
175
|
try {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
176
|
+
if (typeof value === 'object') {
|
|
177
|
+
value = JSON.stringify(value);
|
|
178
|
+
}
|
|
179
|
+
else if (typeof value !== 'string') {
|
|
180
|
+
try {
|
|
181
|
+
value = value.toString();
|
|
182
|
+
}
|
|
183
|
+
catch (err) {
|
|
184
|
+
console.warn(constants_js_1.APP_PREFIX, `Can't convert meta value to string`, err);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
if (value?.length > 255) {
|
|
188
|
+
value = value.substring(0, 255);
|
|
189
|
+
debug(constants_js_1.APP_PREFIX, `Meta info value "${value}" is too long, trimmed to 255 characters`);
|
|
190
|
+
}
|
|
191
|
+
if (key?.length > 255) {
|
|
192
|
+
const newKey = key.substring(0, 255);
|
|
193
|
+
debug(constants_js_1.APP_PREFIX, `Meta info key "${key}" is too long, trimmed to 255 characters`);
|
|
194
|
+
return [newKey, value];
|
|
195
|
+
}
|
|
196
|
+
return [key, value];
|
|
179
197
|
}
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
} catch (err) {
|
|
195
|
-
debug(APP_PREFIX, `Error while processing meta info key ${key}`, err);
|
|
196
|
-
return [null, null];
|
|
198
|
+
catch (err) {
|
|
199
|
+
debug(constants_js_1.APP_PREFIX, `Error while processing meta info key ${key}`, err);
|
|
200
|
+
return [null, null];
|
|
201
|
+
}
|
|
202
|
+
})
|
|
203
|
+
.reduce((acc, [key, value]) => {
|
|
204
|
+
if (key)
|
|
205
|
+
acc[key] = value;
|
|
206
|
+
return acc;
|
|
207
|
+
}, {});
|
|
208
|
+
let errorFormatted = '';
|
|
209
|
+
if (error) {
|
|
210
|
+
errorFormatted += this.formatError(error) || '';
|
|
211
|
+
message = error?.message;
|
|
197
212
|
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
213
|
+
// Attach logs
|
|
214
|
+
const fullLogs = this.formatLogs({ error: errorFormatted, steps, logs: testData.logs });
|
|
215
|
+
// add artifacts
|
|
216
|
+
if (manuallyAttachedArtifacts?.length)
|
|
217
|
+
files.push(...manuallyAttachedArtifacts);
|
|
218
|
+
const uploadedFiles = [];
|
|
219
|
+
for (let f of files) {
|
|
220
|
+
if (!f)
|
|
221
|
+
continue; // f === null
|
|
222
|
+
if (typeof f === 'object') {
|
|
223
|
+
if (!f.path)
|
|
224
|
+
continue;
|
|
225
|
+
f = f.path;
|
|
226
|
+
}
|
|
227
|
+
uploadedFiles.push(this.uploader.uploadFileByPath(f, [this.runId, rid, path_1.default.basename(f)]));
|
|
228
|
+
}
|
|
229
|
+
for (const [idx, buffer] of filesBuffers.entries()) {
|
|
230
|
+
const fileName = `${idx + 1}-${title.replace(/\s+/g, '-')}`;
|
|
231
|
+
uploadedFiles.push(this.uploader.uploadFileAsBuffer(buffer, [this.runId, rid, fileName]));
|
|
232
|
+
}
|
|
233
|
+
const artifacts = (await Promise.all(uploadedFiles)).filter(n => !!n);
|
|
234
|
+
const data = {
|
|
235
|
+
rid,
|
|
236
|
+
files,
|
|
237
|
+
steps,
|
|
238
|
+
status,
|
|
239
|
+
stack: fullLogs,
|
|
240
|
+
example,
|
|
241
|
+
file,
|
|
242
|
+
code,
|
|
243
|
+
title,
|
|
244
|
+
suite_title,
|
|
245
|
+
suite_id,
|
|
246
|
+
test_id,
|
|
247
|
+
message,
|
|
248
|
+
run_time: typeof time === 'number' ? time : parseFloat(time),
|
|
249
|
+
artifacts,
|
|
250
|
+
meta,
|
|
251
|
+
};
|
|
252
|
+
// debug('Adding test run...', data);
|
|
253
|
+
// @ts-ignore
|
|
254
|
+
this.queue = this.queue.then(() => Promise.all(this.pipes.map(async (pipe) => {
|
|
255
|
+
try {
|
|
256
|
+
const result = await pipe.addTest(data);
|
|
257
|
+
return { pipe: pipe.toString(), result };
|
|
258
|
+
}
|
|
259
|
+
catch (err) {
|
|
260
|
+
console.log(constants_js_1.APP_PREFIX, pipe.toString(), err);
|
|
261
|
+
}
|
|
262
|
+
})));
|
|
263
|
+
// @ts-ignore
|
|
264
|
+
return this.queue;
|
|
228
265
|
}
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
266
|
+
/**
|
|
267
|
+
*
|
|
268
|
+
* Updates the status of the current test run and finishes the run.
|
|
269
|
+
* @param {'passed' | 'failed' | 'skipped' | 'finished'} status - The status of the current test run.
|
|
270
|
+
* Must be one of "passed", "failed", or "finished"
|
|
271
|
+
* @param {boolean} [isParallel] - Whether the current test run was executed in parallel with other tests.
|
|
272
|
+
* @returns {Promise<any>} - A Promise that resolves when finishes the run.
|
|
273
|
+
*/
|
|
274
|
+
updateRunStatus(status, isParallel = false) {
|
|
275
|
+
debug('Updating run status...');
|
|
276
|
+
// all pipes disabled, skipping
|
|
277
|
+
if (!this.pipes?.filter(p => p.isEnabled).length)
|
|
278
|
+
return Promise.resolve();
|
|
279
|
+
const runParams = { status, parallel: isParallel };
|
|
280
|
+
this.queue = this.queue
|
|
281
|
+
.then(() => Promise.all(this.pipes.map(p => p.finishRun(runParams))))
|
|
282
|
+
.then(() => {
|
|
283
|
+
if (!this.uploader.isEnabled)
|
|
284
|
+
return;
|
|
285
|
+
const filesizeStrMaxLength = 7;
|
|
286
|
+
if (this.uploader.successfulUploads.length) {
|
|
287
|
+
debug('\n', constants_js_1.APP_PREFIX, `🗄️ ${this.uploader.successfulUploads.length} artifacts uploaded to S3 bucket`);
|
|
288
|
+
const uploadedArtifacts = this.uploader.successfulUploads.map(file => ({
|
|
289
|
+
relativePath: file.path.replace(process.cwd(), ''),
|
|
290
|
+
link: file.link,
|
|
291
|
+
sizePretty: (0, filesize_1.filesize)(file.size, { round: 0 }).toString(),
|
|
292
|
+
}));
|
|
293
|
+
uploadedArtifacts.forEach(upload => {
|
|
294
|
+
debug(`🟢Uploaded artifact`, `${upload.relativePath},`, 'size:', `${upload.sizePretty},`, 'link:', `${upload.link}`);
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
if (this.uploader.failedUploads.length) {
|
|
298
|
+
console.log(constants_js_1.APP_PREFIX, `🗄️ ${this.uploader.failedUploads.length} artifacts 🔴${picocolors_1.default.bold('failed')} to upload`);
|
|
299
|
+
const failedUploads = this.uploader.failedUploads.map(file => ({
|
|
300
|
+
relativePath: file.path.replace(process.cwd(), ''),
|
|
301
|
+
sizePretty: (0, filesize_1.filesize)(file.size, { round: 0 }).toString(),
|
|
302
|
+
}));
|
|
303
|
+
const pathPadding = Math.max(...failedUploads.map(upload => upload.relativePath.length)) + 1;
|
|
304
|
+
failedUploads.forEach(upload => {
|
|
305
|
+
console.log(` ${picocolors_1.default.gray('|')} 🔴 ${upload.relativePath.padEnd(pathPadding)} ${picocolors_1.default.gray(`| ${upload.sizePretty.padStart(filesizeStrMaxLength)} |`)}`);
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
if (this.uploader.skippedUploads.length) {
|
|
309
|
+
console.log('\n', constants_js_1.APP_PREFIX, `🗄️ ${picocolors_1.default.bold(this.uploader.skippedUploads.length)} artifacts uploading 🟡${picocolors_1.default.bold('skipped')}`);
|
|
310
|
+
const skippedUploads = this.uploader.skippedUploads.map(file => ({
|
|
311
|
+
relativePath: file.path.replace(process.cwd(), ''),
|
|
312
|
+
sizePretty: file.size === null ? 'unknown' : (0, filesize_1.filesize)(file.size, { round: 0 }).toString(),
|
|
313
|
+
}));
|
|
314
|
+
const pathPadding = Math.max(...skippedUploads.map(upload => upload.relativePath.length)) + 1;
|
|
315
|
+
skippedUploads.forEach(upload => {
|
|
316
|
+
console.log(` ${picocolors_1.default.gray('|')} 🟡 ${upload.relativePath.padEnd(pathPadding)} ${picocolors_1.default.gray(`| ${upload.sizePretty.padStart(filesizeStrMaxLength)} |`)}`);
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
if (this.uploader.skippedUploads.length || this.uploader.failedUploads.length) {
|
|
320
|
+
const command = `TESTOMATIO=<your_api_key> TESTOMATIO_RUN=${this.runId} npx @testomatio/reporter upload-artifacts`;
|
|
321
|
+
const numberOfNotUploadedArtifacts = this.uploader.skippedUploads.length + this.uploader.failedUploads.length;
|
|
322
|
+
console.log(constants_js_1.APP_PREFIX, `${numberOfNotUploadedArtifacts} artifacts were not uploaded.
|
|
323
|
+
Run "${picocolors_1.default.magenta(command)}" with valid S3 credentials to upload skipped & failed artifacts`);
|
|
324
|
+
}
|
|
325
|
+
})
|
|
326
|
+
.catch(err => console.log(constants_js_1.APP_PREFIX, err));
|
|
327
|
+
return this.queue;
|
|
233
328
|
}
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
title,
|
|
247
|
-
suite_title,
|
|
248
|
-
suite_id,
|
|
249
|
-
test_id,
|
|
250
|
-
message,
|
|
251
|
-
run_time: typeof time === 'number' ? time : parseFloat(time),
|
|
252
|
-
artifacts,
|
|
253
|
-
meta,
|
|
254
|
-
};
|
|
255
|
-
|
|
256
|
-
// debug('Adding test run...', data);
|
|
257
|
-
|
|
258
|
-
this.queue = this.queue.then(() =>
|
|
259
|
-
Promise.all(
|
|
260
|
-
this.pipes.map(async pipe => {
|
|
261
|
-
try {
|
|
262
|
-
const result = await pipe.addTest(data);
|
|
263
|
-
return { pipe: pipe.toString(), result };
|
|
264
|
-
} catch (err) {
|
|
265
|
-
console.log(APP_PREFIX, pipe.toString(), err);
|
|
266
|
-
}
|
|
267
|
-
}),
|
|
268
|
-
),
|
|
269
|
-
);
|
|
270
|
-
|
|
271
|
-
return this.queue;
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
/**
|
|
275
|
-
*
|
|
276
|
-
* Updates the status of the current test run and finishes the run.
|
|
277
|
-
* @param {'passed' | 'failed' | 'skipped' | 'finished'} status - The status of the current test run.
|
|
278
|
-
* Must be one of "passed", "failed", or "finished"
|
|
279
|
-
* @param {boolean} [isParallel] - Whether the current test run was executed in parallel with other tests.
|
|
280
|
-
* @returns {Promise<any>} - A Promise that resolves when finishes the run.
|
|
281
|
-
*/
|
|
282
|
-
updateRunStatus(status, isParallel = false) {
|
|
283
|
-
debug('Updating run status...');
|
|
284
|
-
// all pipes disabled, skipping
|
|
285
|
-
if (!this.pipes?.filter(p => p.isEnabled).length) return Promise.resolve();
|
|
286
|
-
|
|
287
|
-
const runParams = { status, parallel: isParallel };
|
|
288
|
-
|
|
289
|
-
this.queue = this.queue
|
|
290
|
-
.then(() => Promise.all(this.pipes.map(p => p.finishRun(runParams))))
|
|
291
|
-
.then(() => {
|
|
292
|
-
if (!this.uploader.isEnabled) return;
|
|
293
|
-
|
|
294
|
-
if (this.uploader.successfulUploads.length) {
|
|
295
|
-
console.log(
|
|
296
|
-
APP_PREFIX,
|
|
297
|
-
`🗄️ ${this.uploader.successfulUploads.length} artifacts ${
|
|
298
|
-
process.env.TESTOMATIO_PRIVATE_ARTIFACTS ? 'privately' : chalk.bold('publicly')
|
|
299
|
-
} 🟢uploaded to S3 bucket`,
|
|
300
|
-
);
|
|
329
|
+
/**
|
|
330
|
+
* Returns the formatted stack including the stack trace, steps, and logs.
|
|
331
|
+
* @returns {string}
|
|
332
|
+
*/
|
|
333
|
+
formatLogs({ error, steps, logs }) {
|
|
334
|
+
error = error?.trim();
|
|
335
|
+
logs = logs?.trim();
|
|
336
|
+
if (Array.isArray(steps)) {
|
|
337
|
+
steps = steps
|
|
338
|
+
.map(step => (0, utils_js_1.formatStep)(step))
|
|
339
|
+
.flat()
|
|
340
|
+
.join('\n');
|
|
301
341
|
}
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
if (
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
342
|
+
let testLogs = '';
|
|
343
|
+
if (steps)
|
|
344
|
+
testLogs += `${picocolors_1.default.bold(picocolors_1.default.blue('################[ Steps ]################'))}\n${steps}\n\n`;
|
|
345
|
+
if (logs)
|
|
346
|
+
testLogs += `${picocolors_1.default.bold(picocolors_1.default.gray('################[ Logs ]################'))}\n${logs}\n\n`;
|
|
347
|
+
if (error)
|
|
348
|
+
testLogs += `${picocolors_1.default.bold(picocolors_1.default.red('################[ Failure ]################'))}\n${error}`;
|
|
349
|
+
return testLogs;
|
|
350
|
+
}
|
|
351
|
+
formatError(error, message) {
|
|
352
|
+
if (!message)
|
|
353
|
+
message = error.message;
|
|
354
|
+
if (error.inspect)
|
|
355
|
+
message = error.inspect() || '';
|
|
356
|
+
let stack = '';
|
|
357
|
+
if (error.name)
|
|
358
|
+
stack += `${picocolors_1.default.red(error.name)}`;
|
|
359
|
+
if (error.operator)
|
|
360
|
+
stack += ` (${picocolors_1.default.red(error.operator)})`;
|
|
361
|
+
// add new line if something was added to stack
|
|
362
|
+
if (stack)
|
|
363
|
+
stack += ': ';
|
|
364
|
+
stack += `${message}\n`;
|
|
365
|
+
if (error.diff) {
|
|
366
|
+
// diff for vitest
|
|
367
|
+
stack += error.diff;
|
|
368
|
+
stack += '\n\n';
|
|
323
369
|
}
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
'\n'
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
);
|
|
331
|
-
const failedUploads = this.uploader.failedUploads.map(file => ({
|
|
332
|
-
relativePath: file.path.replace(process.cwd(), ''),
|
|
333
|
-
sizePretty: prettyBytes(file.size, { round: 0 }).toString(),
|
|
334
|
-
}));
|
|
335
|
-
|
|
336
|
-
const pathPadding = Math.max(...failedUploads.map(upload => upload.relativePath.length)) + 1;
|
|
337
|
-
|
|
338
|
-
failedUploads.forEach(upload => {
|
|
339
|
-
console.log(
|
|
340
|
-
` ${chalk.gray('|')} 🔴 ${upload.relativePath.padEnd(pathPadding)} ${chalk.gray(
|
|
341
|
-
`| ${upload.sizePretty.padStart(filesizeStrMaxLength)} |`,
|
|
342
|
-
)}`,
|
|
343
|
-
);
|
|
344
|
-
});
|
|
370
|
+
else if (error.actual && error.expected && error.actual !== error.expected) {
|
|
371
|
+
// diffs for mocha, cypress, codeceptjs style
|
|
372
|
+
stack += `\n\n${picocolors_1.default.bold(picocolors_1.default.green('+ expected'))} ${picocolors_1.default.bold(picocolors_1.default.red('- actual'))}`;
|
|
373
|
+
stack += `\n${picocolors_1.default.green(`+ ${error.expected.toString().split('\n').join('\n+ ')}`)}`;
|
|
374
|
+
stack += `\n${picocolors_1.default.red(`- ${error.actual.toString().split('\n').join('\n- ')}`)}`;
|
|
375
|
+
stack += '\n\n';
|
|
345
376
|
}
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
377
|
+
const customFilter = process.env.TESTOMATIO_STACK_IGNORE;
|
|
378
|
+
try {
|
|
379
|
+
let hasFrame = false;
|
|
380
|
+
const record = (0, callsite_record_1.default)({
|
|
381
|
+
forError: error,
|
|
382
|
+
isCallsiteFrame: frame => {
|
|
383
|
+
if (customFilter && (0, minimatch_1.minimatch)(frame.fileName, customFilter))
|
|
384
|
+
return false;
|
|
385
|
+
if (hasFrame)
|
|
386
|
+
return false;
|
|
387
|
+
if (isNotInternalFrame(frame))
|
|
388
|
+
hasFrame = true;
|
|
389
|
+
return hasFrame;
|
|
390
|
+
},
|
|
391
|
+
});
|
|
392
|
+
// @ts-ignore
|
|
393
|
+
if (record && !record.filename.startsWith('http')) {
|
|
394
|
+
stack += record.renderSync({ stackFilter: isNotInternalFrame });
|
|
395
|
+
}
|
|
396
|
+
return stack;
|
|
365
397
|
}
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
const command = `TESTOMATIO=<your_api_key> TESTOMATIO_RUN=${
|
|
369
|
-
this.runId
|
|
370
|
-
} npx @testomatio/reporter upload-artifacts`;
|
|
371
|
-
console.log(
|
|
372
|
-
APP_PREFIX,
|
|
373
|
-
`Run "${chalk.magenta(command)}" with valid S3 credentials to upload skipped & failed artifacts`,
|
|
374
|
-
);
|
|
398
|
+
catch (e) {
|
|
399
|
+
console.log(e);
|
|
375
400
|
}
|
|
376
|
-
})
|
|
377
|
-
.catch(err => console.log(APP_PREFIX, err));
|
|
378
|
-
|
|
379
|
-
return this.queue;
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
/**
|
|
383
|
-
* Returns the formatted stack including the stack trace, steps, and logs.
|
|
384
|
-
* @returns {string}
|
|
385
|
-
*/
|
|
386
|
-
formatLogs({ error, steps, logs }) {
|
|
387
|
-
error = error?.trim();
|
|
388
|
-
logs = logs?.trim();
|
|
389
|
-
|
|
390
|
-
if (Array.isArray(steps)) {
|
|
391
|
-
steps = steps
|
|
392
|
-
.map(step => formatStep(step))
|
|
393
|
-
.flat()
|
|
394
|
-
.join('\n');
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
let testLogs = '';
|
|
398
|
-
if (steps) testLogs += `${chalk.bold.blue('################[ Steps ]################')}\n${steps}\n\n`;
|
|
399
|
-
if (logs) testLogs += `${chalk.bold.gray('################[ Logs ]################')}\n${logs}\n\n`;
|
|
400
|
-
if (error) testLogs += `${chalk.bold.red('################[ Failure ]################')}\n${error}`;
|
|
401
|
-
return testLogs;
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
formatError(error, message) {
|
|
405
|
-
if (!message) message = error.message;
|
|
406
|
-
if (error.inspect) message = error.inspect() || '';
|
|
407
|
-
|
|
408
|
-
let stack = '';
|
|
409
|
-
if (error.name) stack += `${chalk.red(error.name)}`;
|
|
410
|
-
if (error.operator) stack += ` (${chalk.red(error.operator)})`;
|
|
411
|
-
// add new line if something was added to stack
|
|
412
|
-
if (stack) stack += ': ';
|
|
413
|
-
|
|
414
|
-
stack += `${message}\n`;
|
|
415
|
-
|
|
416
|
-
if (error.diff) {
|
|
417
|
-
// diff for vitest
|
|
418
|
-
stack += error.diff;
|
|
419
|
-
stack += '\n\n';
|
|
420
|
-
} else if (error.actual && error.expected && error.actual !== error.expected) {
|
|
421
|
-
// diffs for mocha, cypress, codeceptjs style
|
|
422
|
-
stack += `\n\n${chalk.bold.green('+ expected')} ${chalk.bold.red('- actual')}`;
|
|
423
|
-
stack += `\n${chalk.green(`+ ${error.expected.toString().split('\n').join('\n+ ')}`)}`;
|
|
424
|
-
stack += `\n${chalk.red(`- ${error.actual.toString().split('\n').join('\n- ')}`)}`;
|
|
425
|
-
stack += '\n\n';
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
const customFilter = process.env.TESTOMATIO_STACK_IGNORE;
|
|
429
|
-
|
|
430
|
-
try {
|
|
431
|
-
let hasFrame = false;
|
|
432
|
-
const record = createCallsiteRecord({
|
|
433
|
-
forError: error,
|
|
434
|
-
isCallsiteFrame: frame => {
|
|
435
|
-
if (customFilter && minimatch(frame.getFileName(), customFilter)) return false;
|
|
436
|
-
if (hasFrame) return false;
|
|
437
|
-
if (isNotInternalFrame(frame)) hasFrame = true;
|
|
438
|
-
return hasFrame;
|
|
439
|
-
},
|
|
440
|
-
});
|
|
441
|
-
if (record && !record.filename.startsWith('http')) {
|
|
442
|
-
stack += record.renderSync({ stackFilter: isNotInternalFrame });
|
|
443
|
-
}
|
|
444
|
-
return stack;
|
|
445
|
-
} catch (e) {
|
|
446
|
-
console.log(e);
|
|
447
401
|
}
|
|
448
|
-
}
|
|
449
402
|
}
|
|
450
|
-
|
|
403
|
+
exports.Client = Client;
|
|
451
404
|
function isNotInternalFrame(frame) {
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
!frame.getFileName().includes('internal')
|
|
457
|
-
);
|
|
405
|
+
return (frame.getFileName() &&
|
|
406
|
+
frame.getFileName().includes(path_1.sep) &&
|
|
407
|
+
!frame.getFileName().includes('node_modules') &&
|
|
408
|
+
!frame.getFileName().includes('internal'));
|
|
458
409
|
}
|
|
459
|
-
|
|
460
410
|
/**
|
|
461
411
|
*
|
|
462
412
|
* @param {TestData} testData
|
|
463
413
|
* @returns boolean
|
|
464
414
|
*/
|
|
465
415
|
function isTestShouldBeExculedFromReport(testData) {
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
416
|
+
// const fileName = path.basename(test.location?.file || '');
|
|
417
|
+
const globExcludeFilesPattern = process.env.TESTOMATIO_EXCLUDE_FILES_FROM_REPORT_GLOB_PATTERN;
|
|
418
|
+
if (!globExcludeFilesPattern)
|
|
419
|
+
return false;
|
|
420
|
+
if (!testData.file) {
|
|
421
|
+
debug('No "file" property found for test ', testData.title);
|
|
422
|
+
return false;
|
|
423
|
+
}
|
|
424
|
+
const excludeParretnsList = globExcludeFilesPattern.split(';');
|
|
425
|
+
// as scanning files is time consuming operation, just save the result in variable to avoid multiple scans
|
|
426
|
+
if (!listOfTestFilesToExcludeFromReport) {
|
|
427
|
+
// list of files with relative paths
|
|
428
|
+
listOfTestFilesToExcludeFromReport = glob_1.glob.sync(excludeParretnsList, { ignore: '**/node_modules/**' });
|
|
429
|
+
debug('Tests from next files will not be reported:', listOfTestFilesToExcludeFromReport);
|
|
430
|
+
}
|
|
431
|
+
const testFileRelativePath = path_1.default.relative(process.cwd(), testData.file);
|
|
432
|
+
// no files found matching the exclusion pattern
|
|
433
|
+
if (!listOfTestFilesToExcludeFromReport.length)
|
|
434
|
+
return false;
|
|
435
|
+
if (listOfTestFilesToExcludeFromReport.includes(testFileRelativePath)) {
|
|
436
|
+
debug(`Excluding test '${testData.title}' <${testFileRelativePath}> from reporting`);
|
|
437
|
+
return true;
|
|
438
|
+
}
|
|
472
439
|
return false;
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
const excludeParretnsList = globExcludeFilesPattern.split(';');
|
|
476
|
-
|
|
477
|
-
// as scanning files is time consuming operation, just save the result in variable to avoid multiple scans
|
|
478
|
-
if (!listOfTestFilesToExcludeFromReport) {
|
|
479
|
-
// list of files with relative paths
|
|
480
|
-
listOfTestFilesToExcludeFromReport = glob.sync(excludeParretnsList, { ignore: '**/node_modules/**' });
|
|
481
|
-
debug('Tests from next files will not be reported:', listOfTestFilesToExcludeFromReport);
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
const testFileRelativePath = path.relative(process.cwd(), testData.file);
|
|
485
|
-
|
|
486
|
-
// no files found matching the exclusion pattern
|
|
487
|
-
if (!listOfTestFilesToExcludeFromReport.length) return false;
|
|
488
|
-
|
|
489
|
-
if (listOfTestFilesToExcludeFromReport.includes(testFileRelativePath)) {
|
|
490
|
-
debug(`Excluding test '${testData.title}' <${testFileRelativePath}> from reporting`);
|
|
491
|
-
return true;
|
|
492
|
-
}
|
|
493
|
-
return false;
|
|
494
440
|
}
|
|
495
|
-
|
|
496
441
|
module.exports = Client;
|
|
497
|
-
|
|
442
|
+
|
|
443
|
+
module.exports.Client = Client;
|