@testomatio/reporter 2.0.0-beta-esm → 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 +31 -24
- package/lib/adapter/cucumber/current.d.ts +14 -0
- package/lib/adapter/cucumber/legacy.d.ts +0 -0
- package/lib/adapter/cucumber.d.ts +2 -0
- package/lib/adapter/cypress-plugin/index.d.ts +2 -0
- package/lib/adapter/cypress-plugin/index.js +11 -9
- package/lib/adapter/jasmine.d.ts +11 -0
- package/lib/adapter/jest.d.ts +13 -0
- package/lib/adapter/mocha.d.ts +2 -0
- package/lib/adapter/mocha.js +4 -3
- package/lib/adapter/playwright.d.ts +14 -0
- package/lib/adapter/playwright.js +58 -33
- package/lib/adapter/vitest.d.ts +35 -0
- package/lib/adapter/vitest.js +6 -6
- package/lib/adapter/webdriver.d.ts +24 -0
- package/lib/adapter/webdriver.js +34 -6
- package/lib/bin/cli.d.ts +2 -0
- package/lib/bin/cli.js +228 -0
- package/lib/bin/reportXml.d.ts +2 -0
- package/lib/bin/reportXml.js +11 -9
- package/lib/bin/startTest.d.ts +2 -0
- package/lib/bin/startTest.js +9 -5
- package/lib/bin/uploadArtifacts.d.ts +2 -0
- package/lib/bin/uploadArtifacts.js +81 -0
- package/lib/client.d.ts +76 -0
- package/lib/client.js +111 -45
- package/lib/config.d.ts +1 -0
- package/lib/constants.d.ts +25 -0
- package/lib/constants.js +5 -1
- package/lib/data-storage.d.ts +34 -0
- package/lib/data-storage.js +2 -2
- package/lib/junit-adapter/adapter.d.ts +9 -0
- package/lib/junit-adapter/csharp.d.ts +4 -0
- package/lib/junit-adapter/index.d.ts +3 -0
- package/lib/junit-adapter/java.d.ts +5 -0
- package/lib/junit-adapter/javascript.d.ts +4 -0
- package/lib/junit-adapter/python.d.ts +5 -0
- package/lib/junit-adapter/ruby.d.ts +4 -0
- package/lib/output.d.ts +11 -0
- package/lib/package.json +3 -1
- package/lib/pipe/bitbucket.d.ts +23 -0
- package/lib/pipe/bitbucket.js +2 -2
- package/lib/pipe/csv.d.ts +47 -0
- package/lib/pipe/csv.js +2 -2
- package/lib/pipe/debug.d.ts +29 -0
- package/lib/pipe/debug.js +108 -0
- package/lib/pipe/github.d.ts +30 -0
- package/lib/pipe/github.js +2 -2
- package/lib/pipe/gitlab.d.ts +23 -0
- package/lib/pipe/gitlab.js +2 -2
- package/lib/pipe/html.d.ts +34 -0
- package/lib/pipe/html.js +8 -1
- package/lib/pipe/index.d.ts +1 -0
- package/lib/pipe/index.js +3 -3
- package/lib/pipe/testomatio.d.ts +70 -0
- package/lib/pipe/testomatio.js +50 -30
- package/lib/reporter-functions.d.ts +34 -0
- package/lib/reporter-functions.js +17 -7
- package/lib/reporter.d.ts +232 -0
- package/lib/reporter.js +19 -33
- package/lib/services/artifacts.d.ts +33 -0
- package/lib/services/index.d.ts +9 -0
- package/lib/services/key-values.d.ts +27 -0
- package/lib/services/key-values.js +1 -1
- package/lib/services/logger.d.ts +64 -0
- package/lib/template/testomatio.hbs +651 -1366
- package/lib/uploader.d.ts +60 -0
- package/lib/uploader.js +312 -0
- package/lib/utils/pipe_utils.d.ts +41 -0
- package/lib/utils/pipe_utils.js +3 -5
- package/lib/utils/utils.d.ts +45 -0
- package/lib/utils/utils.js +69 -2
- package/lib/xmlReader.d.ts +92 -0
- package/lib/xmlReader.js +22 -12
- package/package.json +15 -9
- package/src/adapter/codecept.js +30 -24
- package/src/adapter/cypress-plugin/index.js +5 -3
- package/src/adapter/mocha.cjs +1 -1
- package/src/adapter/mocha.js +4 -3
- package/src/adapter/playwright.js +59 -31
- package/src/adapter/vitest.js +6 -6
- package/src/adapter/webdriver.js +41 -10
- package/src/bin/cli.js +280 -0
- package/src/bin/reportXml.js +15 -8
- package/src/bin/startTest.js +7 -3
- package/src/bin/uploadArtifacts.js +90 -0
- package/src/client.js +137 -56
- package/src/constants.js +5 -1
- package/src/data-storage.js +2 -2
- package/src/pipe/bitbucket.js +2 -2
- package/src/pipe/csv.js +3 -3
- package/src/pipe/debug.js +104 -0
- package/src/pipe/github.js +2 -3
- package/src/pipe/gitlab.js +6 -6
- package/src/pipe/html.js +11 -3
- package/src/pipe/index.js +5 -7
- package/src/pipe/testomatio.js +72 -67
- package/src/reporter-functions.js +18 -7
- package/src/reporter.cjs_decprecated +21 -0
- package/src/reporter.js +20 -11
- package/src/services/key-values.js +1 -1
- package/src/services/logger.js +4 -2
- package/src/template/testomatio.hbs +651 -1366
- package/src/uploader.js +371 -0
- package/src/utils/pipe_utils.js +4 -12
- package/src/utils/utils.js +48 -6
- package/src/xmlReader.js +26 -15
- package/lib/adapter/jasmine/jasmine.js +0 -63
- package/lib/adapter/mocha/mocha.js +0 -125
- package/lib/fileUploader.js +0 -245
- package/lib/utils/chalk.js +0 -10
- package/src/fileUploader.js +0 -307
- package/src/reporter.cjs +0 -22
- package/src/utils/chalk.js +0 -13
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export default GitHubPipe;
|
|
2
|
+
export type Pipe = import("../../types/types.js").Pipe;
|
|
3
|
+
export type TestData = import("../../types/types.js").TestData;
|
|
4
|
+
/**
|
|
5
|
+
* @typedef {import('../../types/types.js').Pipe} Pipe
|
|
6
|
+
* @typedef {import('../../types/types.js').TestData} TestData
|
|
7
|
+
* @class GitHubPipe
|
|
8
|
+
* @implements {Pipe}
|
|
9
|
+
*/
|
|
10
|
+
declare class GitHubPipe implements Pipe {
|
|
11
|
+
constructor(params: any, store?: {});
|
|
12
|
+
isEnabled: boolean;
|
|
13
|
+
store: {};
|
|
14
|
+
tests: any[];
|
|
15
|
+
token: any;
|
|
16
|
+
ref: string;
|
|
17
|
+
repo: string;
|
|
18
|
+
jobKey: string;
|
|
19
|
+
hiddenCommentData: string;
|
|
20
|
+
issue: number;
|
|
21
|
+
start: Date;
|
|
22
|
+
prepareRun(): Promise<void>;
|
|
23
|
+
createRun(): Promise<void>;
|
|
24
|
+
addTest(test: any): void;
|
|
25
|
+
finishRun(runParams: any): Promise<void>;
|
|
26
|
+
octokit: import("@octokit/core").Octokit & {
|
|
27
|
+
paginate: import("@octokit/plugin-paginate-rest").PaginateInterface;
|
|
28
|
+
} & import("@octokit/plugin-rest-endpoint-methods/dist-types/generated/method-types.js").RestEndpointMethods & import("@octokit/plugin-rest-endpoint-methods/dist-types/types.js").Api;
|
|
29
|
+
toString(): string;
|
|
30
|
+
}
|
package/lib/pipe/github.js
CHANGED
|
@@ -14,8 +14,8 @@ const utils_js_1 = require("../utils/utils.js");
|
|
|
14
14
|
const pipe_utils_js_1 = require("../utils/pipe_utils.js");
|
|
15
15
|
const debug = (0, debug_1.default)('@testomatio/reporter:pipe:github');
|
|
16
16
|
/**
|
|
17
|
-
* @typedef {import('../../types').Pipe} Pipe
|
|
18
|
-
* @typedef {import('../../types').TestData} TestData
|
|
17
|
+
* @typedef {import('../../types/types.js').Pipe} Pipe
|
|
18
|
+
* @typedef {import('../../types/types.js').TestData} TestData
|
|
19
19
|
* @class GitHubPipe
|
|
20
20
|
* @implements {Pipe}
|
|
21
21
|
*/
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export default GitLabPipe;
|
|
2
|
+
export type Pipe = import("../../types/types.js").Pipe;
|
|
3
|
+
export type TestData = import("../../types/types.js").TestData;
|
|
4
|
+
/**
|
|
5
|
+
* @class GitLabPipe
|
|
6
|
+
* @typedef {import('../../types/types.js').Pipe} Pipe
|
|
7
|
+
* @typedef {import('../../types/types.js').TestData} TestData
|
|
8
|
+
*/
|
|
9
|
+
declare class GitLabPipe {
|
|
10
|
+
constructor(params: any, store?: {});
|
|
11
|
+
isEnabled: boolean;
|
|
12
|
+
ENV: NodeJS.ProcessEnv;
|
|
13
|
+
store: {};
|
|
14
|
+
tests: any[];
|
|
15
|
+
token: any;
|
|
16
|
+
hiddenCommentData: string;
|
|
17
|
+
prepareRun(): Promise<void>;
|
|
18
|
+
createRun(): Promise<void>;
|
|
19
|
+
addTest(test: any): void;
|
|
20
|
+
finishRun(runParams: any): Promise<void>;
|
|
21
|
+
toString(): string;
|
|
22
|
+
updateRun(): void;
|
|
23
|
+
}
|
package/lib/pipe/gitlab.js
CHANGED
|
@@ -17,8 +17,8 @@ const debug = (0, debug_1.default)('@testomatio/reporter:pipe:gitlab');
|
|
|
17
17
|
//! and your pipeline trigger should be merge_request
|
|
18
18
|
/**
|
|
19
19
|
* @class GitLabPipe
|
|
20
|
-
* @typedef {import('../../types').Pipe} Pipe
|
|
21
|
-
* @typedef {import('../../types').TestData} TestData
|
|
20
|
+
* @typedef {import('../../types/types.js').Pipe} Pipe
|
|
21
|
+
* @typedef {import('../../types/types.js').TestData} TestData
|
|
22
22
|
*/
|
|
23
23
|
class GitLabPipe {
|
|
24
24
|
constructor(params, store = {}) {
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export default HtmlPipe;
|
|
2
|
+
declare class HtmlPipe {
|
|
3
|
+
constructor(params: any, store?: {});
|
|
4
|
+
store: {};
|
|
5
|
+
title: any;
|
|
6
|
+
apiKey: any;
|
|
7
|
+
isHtml: string;
|
|
8
|
+
isEnabled: boolean;
|
|
9
|
+
htmlOutputPath: string;
|
|
10
|
+
fullHtmlOutputPath: string;
|
|
11
|
+
filenameMsg: string;
|
|
12
|
+
tests: any[];
|
|
13
|
+
htmlReportDir: string;
|
|
14
|
+
htmlReportName: string;
|
|
15
|
+
templateFolderPath: string;
|
|
16
|
+
templateHtmlPath: string;
|
|
17
|
+
createRun(): Promise<void>;
|
|
18
|
+
updateRun(): void;
|
|
19
|
+
/**
|
|
20
|
+
* Add test data to the result array for saving. As a result of this function, we get a result object to save.
|
|
21
|
+
* @param {import('../../types/types.js').RunData} test - object which includes each test entry.
|
|
22
|
+
*/
|
|
23
|
+
addTest(test: import("../../types/types.js").RunData): void;
|
|
24
|
+
finishRun(runParams: any): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Generates an HTML report based on provided test data and a template.
|
|
27
|
+
* @param {object} opts - Test options used to generate the HTML report:
|
|
28
|
+
* runParams, tests, outputPath, templatePath
|
|
29
|
+
* @returns {void} - This function does not return anything.
|
|
30
|
+
*/
|
|
31
|
+
buildReport(opts: object): void;
|
|
32
|
+
toString(): string;
|
|
33
|
+
#private;
|
|
34
|
+
}
|
package/lib/pipe/html.js
CHANGED
|
@@ -58,7 +58,7 @@ class HtmlPipe {
|
|
|
58
58
|
}
|
|
59
59
|
/**
|
|
60
60
|
* Add test data to the result array for saving. As a result of this function, we get a result object to save.
|
|
61
|
-
* @param {import('../../types').RunData} test - object which includes each test entry.
|
|
61
|
+
* @param {import('../../types/types.js').RunData} test - object which includes each test entry.
|
|
62
62
|
*/
|
|
63
63
|
addTest(test) {
|
|
64
64
|
if (!this.isEnabled)
|
|
@@ -106,6 +106,13 @@ class HtmlPipe {
|
|
|
106
106
|
console.log(picocolors_1.default.blue(msg));
|
|
107
107
|
}
|
|
108
108
|
tests.forEach(test => {
|
|
109
|
+
// steps could be an array or a string
|
|
110
|
+
test.steps = Array.isArray(test.steps)
|
|
111
|
+
? (test.steps = test.steps
|
|
112
|
+
.map(step => (0, utils_js_1.formatStep)(step))
|
|
113
|
+
.flat()
|
|
114
|
+
.join('\n'))
|
|
115
|
+
: test.steps;
|
|
109
116
|
if (!test.message?.trim()) {
|
|
110
117
|
test.message = "This test has no 'message' code";
|
|
111
118
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function pipesFactory(params: any, opts: any): Promise<any[]>;
|
package/lib/pipe/index.js
CHANGED
|
@@ -37,6 +37,7 @@ const gitlab_js_1 = __importDefault(require("./gitlab.js"));
|
|
|
37
37
|
const csv_js_1 = __importDefault(require("./csv.js"));
|
|
38
38
|
const html_js_1 = __importDefault(require("./html.js"));
|
|
39
39
|
const bitbucket_js_1 = require("./bitbucket.js");
|
|
40
|
+
const debug_js_1 = require("./debug.js");
|
|
40
41
|
async function pipesFactory(params, opts) {
|
|
41
42
|
const extraPipes = [];
|
|
42
43
|
// Add extra pipes into package.json file:
|
|
@@ -72,12 +73,11 @@ async function pipesFactory(params, opts) {
|
|
|
72
73
|
new csv_js_1.default(params, opts),
|
|
73
74
|
new html_js_1.default(params, opts),
|
|
74
75
|
new bitbucket_js_1.BitbucketPipe(params, opts),
|
|
76
|
+
new debug_js_1.DebugPipe(params, opts),
|
|
75
77
|
...extraPipes,
|
|
76
78
|
];
|
|
77
79
|
const pipesEnabled = pipes.filter(p => p.isEnabled);
|
|
78
|
-
console.log(constants_js_1.APP_PREFIX, picocolors_1.default.cyan('Pipes:'), picocolors_1.default.cyan(pipesEnabled
|
|
79
|
-
.map(p => p.toString())
|
|
80
|
-
.join(', ') || 'No pipes enabled'));
|
|
80
|
+
console.log(constants_js_1.APP_PREFIX, picocolors_1.default.cyan('Pipes:'), picocolors_1.default.cyan(pipesEnabled.map(p => p.toString()).join(', ') || 'No pipes enabled'));
|
|
81
81
|
if (!pipesEnabled.length) {
|
|
82
82
|
console.log(constants_js_1.APP_PREFIX, picocolors_1.default.dim('If you want to use Testomatio reporter, pass your token as TESTOMATIO env variable'));
|
|
83
83
|
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
export default TestomatioPipe;
|
|
2
|
+
export type Pipe = import("../../types/types.js").Pipe;
|
|
3
|
+
export type TestData = import("../../types/types.js").TestData;
|
|
4
|
+
/**
|
|
5
|
+
* @typedef {import('../../types/types.js').Pipe} Pipe
|
|
6
|
+
* @typedef {import('../../types/types.js').TestData} TestData
|
|
7
|
+
* @class TestomatioPipe
|
|
8
|
+
* @implements {Pipe}
|
|
9
|
+
*/
|
|
10
|
+
declare class TestomatioPipe implements Pipe {
|
|
11
|
+
constructor(params: any, store: any);
|
|
12
|
+
batch: {
|
|
13
|
+
isEnabled: any;
|
|
14
|
+
intervalFunction: any;
|
|
15
|
+
intervalTime: number;
|
|
16
|
+
tests: any[];
|
|
17
|
+
batchIndex: number;
|
|
18
|
+
numberOfTimesCalledWithoutTests: number;
|
|
19
|
+
};
|
|
20
|
+
retriesTimestamps: any[];
|
|
21
|
+
reportingCanceledDueToReqFailures: boolean;
|
|
22
|
+
notReportedTestsCount: number;
|
|
23
|
+
isEnabled: boolean;
|
|
24
|
+
url: any;
|
|
25
|
+
apiKey: any;
|
|
26
|
+
parallel: any;
|
|
27
|
+
store: any;
|
|
28
|
+
title: any;
|
|
29
|
+
sharedRun: boolean;
|
|
30
|
+
sharedRunTimeout: boolean;
|
|
31
|
+
groupTitle: any;
|
|
32
|
+
env: string;
|
|
33
|
+
label: string;
|
|
34
|
+
axios: any;
|
|
35
|
+
proceed: string;
|
|
36
|
+
jiraId: string;
|
|
37
|
+
runId: any;
|
|
38
|
+
createNewTests: any;
|
|
39
|
+
hasUnmatchedTests: boolean;
|
|
40
|
+
requestFailures: number;
|
|
41
|
+
/**
|
|
42
|
+
* Asynchronously prepares and retrieves the Testomat.io test grepList based on the provided options.
|
|
43
|
+
* @param {Object} opts - The options for preparing the test grepList.
|
|
44
|
+
* @returns {Promise<string[]>} - An array containing the retrieved
|
|
45
|
+
* test grepList, or an empty array if no tests are found or the request is disabled.
|
|
46
|
+
* @throws {Error} - Throws an error if there was a problem while making the request.
|
|
47
|
+
*/
|
|
48
|
+
prepareRun(opts: any): Promise<string[]>;
|
|
49
|
+
/**
|
|
50
|
+
* Creates a new run on Testomat.io
|
|
51
|
+
* @param {{isBatchEnabled?: boolean}} params
|
|
52
|
+
* @returns Promise<void>
|
|
53
|
+
*/
|
|
54
|
+
createRun(params?: {
|
|
55
|
+
isBatchEnabled?: boolean;
|
|
56
|
+
}): Promise<void>;
|
|
57
|
+
runUrl: string;
|
|
58
|
+
runPublicUrl: any;
|
|
59
|
+
/**
|
|
60
|
+
* Adds a test to the batch uploader (or reports a single test if batch uploading is disabled)
|
|
61
|
+
*/
|
|
62
|
+
addTest(data: any): void;
|
|
63
|
+
/**
|
|
64
|
+
* @param {import('../../types/types.js').RunData} params
|
|
65
|
+
* @returns
|
|
66
|
+
*/
|
|
67
|
+
finishRun(params: import("../../types/types.js").RunData): Promise<void>;
|
|
68
|
+
toString(): string;
|
|
69
|
+
#private;
|
|
70
|
+
}
|
package/lib/pipe/testomatio.js
CHANGED
|
@@ -19,8 +19,8 @@ if (process.env.TESTOMATIO_RUN) {
|
|
|
19
19
|
// process.env.runId = process.env.TESTOMATIO_RUN;
|
|
20
20
|
}
|
|
21
21
|
/**
|
|
22
|
-
* @typedef {import('../../types').Pipe} Pipe
|
|
23
|
-
* @typedef {import('../../types').TestData} TestData
|
|
22
|
+
* @typedef {import('../../types/types.js').Pipe} Pipe
|
|
23
|
+
* @typedef {import('../../types/types.js').TestData} TestData
|
|
24
24
|
* @class TestomatioPipe
|
|
25
25
|
* @implements {Pipe}
|
|
26
26
|
*/
|
|
@@ -59,11 +59,13 @@ class TestomatioPipe {
|
|
|
59
59
|
this.axios = axios_1.default.create({
|
|
60
60
|
baseURL: `${this.url.trim()}`,
|
|
61
61
|
timeout: constants_js_1.AXIOS_TIMEOUT,
|
|
62
|
-
proxy: proxy
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
62
|
+
proxy: proxy
|
|
63
|
+
? {
|
|
64
|
+
host: proxy.hostname,
|
|
65
|
+
port: parseInt(proxy.port, 10),
|
|
66
|
+
protocol: proxy.protocol,
|
|
67
|
+
}
|
|
68
|
+
: false,
|
|
67
69
|
});
|
|
68
70
|
// Pass the axios instance to the retry function
|
|
69
71
|
(0, axios_retry_1.default)(this.axios, {
|
|
@@ -97,6 +99,7 @@ class TestomatioPipe {
|
|
|
97
99
|
this.runId = params.runId || process.env.runId;
|
|
98
100
|
this.createNewTests = params.createNewTests ?? !!process.env.TESTOMATIO_CREATE;
|
|
99
101
|
this.hasUnmatchedTests = false;
|
|
102
|
+
this.requestFailures = 0;
|
|
100
103
|
if (!(0, utils_js_1.isValidUrl)(this.url.trim())) {
|
|
101
104
|
this.isEnabled = false;
|
|
102
105
|
console.error(constants_js_1.APP_PREFIX, picocolors_1.default.red(`Error creating report on Testomat.io, report url '${this.url}' is invalid`));
|
|
@@ -141,10 +144,9 @@ class TestomatioPipe {
|
|
|
141
144
|
*/
|
|
142
145
|
async createRun(params = {}) {
|
|
143
146
|
this.batch.isEnabled = params.isBatchEnabled ?? this.batch.isEnabled;
|
|
144
|
-
debug('Creating run...');
|
|
145
147
|
if (!this.isEnabled)
|
|
146
148
|
return;
|
|
147
|
-
if (this.batch.isEnabled)
|
|
149
|
+
if (this.batch.isEnabled && this.isEnabled)
|
|
148
150
|
this.batch.intervalFunction = setInterval(this.#batchUpload, this.batch.intervalTime);
|
|
149
151
|
let buildUrl = process.env.BUILD_URL || process.env.CI_JOB_URL || process.env.CIRCLE_BUILD_URL;
|
|
150
152
|
// GitHub Actions Url
|
|
@@ -177,12 +179,14 @@ class TestomatioPipe {
|
|
|
177
179
|
}).filter(([, value]) => !!value));
|
|
178
180
|
debug(' >>>>>> Run params', JSON.stringify(runParams, null, 2));
|
|
179
181
|
if (this.runId) {
|
|
182
|
+
this.store.runId = this.runId;
|
|
180
183
|
debug(`Run with id ${this.runId} already created, updating...`);
|
|
181
184
|
const resp = await this.axios.put(`/api/reporter/${this.runId}`, runParams);
|
|
182
185
|
if (resp.data.artifacts)
|
|
183
186
|
(0, pipe_utils_js_1.setS3Credentials)(resp.data.artifacts);
|
|
184
187
|
return;
|
|
185
188
|
}
|
|
189
|
+
debug('Creating run...');
|
|
186
190
|
try {
|
|
187
191
|
const resp = await this.axios.post(`/api/reporter`, runParams, {
|
|
188
192
|
maxContentLength: Infinity,
|
|
@@ -201,37 +205,39 @@ class TestomatioPipe {
|
|
|
201
205
|
debug('Run created', this.runId);
|
|
202
206
|
}
|
|
203
207
|
catch (err) {
|
|
204
|
-
|
|
208
|
+
const errorText = err.response?.data?.message || err.message;
|
|
209
|
+
console.log(errorText || err);
|
|
210
|
+
if (!this.apiKey)
|
|
211
|
+
console.error('Testomat.io API key is not set');
|
|
212
|
+
if (!this.apiKey?.startsWith('tstmt'))
|
|
213
|
+
console.error('Testomat.io API key is invalid');
|
|
214
|
+
console.error(constants_js_1.APP_PREFIX, 'Error creating Testomat.io report (see details above), please check if your API key is valid. Skipping report');
|
|
205
215
|
printCreateIssue(err);
|
|
206
216
|
}
|
|
207
217
|
debug('"createRun" function finished');
|
|
208
218
|
}
|
|
209
219
|
/**
|
|
210
220
|
* Decides whether to skip test reporting in case of too many request failures
|
|
211
|
-
* @param {TestData} testData
|
|
212
221
|
* @returns {boolean}
|
|
213
222
|
*/
|
|
214
|
-
#cancelTestReportingInCaseOfTooManyReqFailures(
|
|
215
|
-
if (
|
|
216
|
-
return
|
|
217
|
-
const
|
|
218
|
-
|
|
219
|
-
if (retriesCountWithinTime > constants_js_1.REPORTER_REQUEST_RETRIES.maxTotalRetries) {
|
|
220
|
-
const errorMessage = picocolors_1.default.yellow(`${retriesCountWithinTime} requests were failed within ${constants_js_1.REPORTER_REQUEST_RETRIES.withinTimeSeconds}s,\
|
|
221
|
-
reporting for test "${testData.title}" to Testomat is skipped`);
|
|
222
|
-
console.warn(`${constants_js_1.APP_PREFIX} ${errorMessage}`);
|
|
223
|
+
#cancelTestReportingInCaseOfTooManyReqFailures() {
|
|
224
|
+
if (!process.env.TESTOMATIO_MAX_REQUEST_FAILURES)
|
|
225
|
+
return;
|
|
226
|
+
const cancelReporting = this.requestFailures >= parseInt(process.env.TESTOMATIO_MAX_REQUEST_FAILURES, 10);
|
|
227
|
+
if (cancelReporting) {
|
|
223
228
|
this.reportingCanceledDueToReqFailures = true;
|
|
224
|
-
|
|
225
|
-
|
|
229
|
+
let errorMessage = `⚠️ ${process.env.TESTOMATIO_MAX_REQUEST_FAILURES}`;
|
|
230
|
+
errorMessage += ' requests were failed, reporting to Testomat aborted.';
|
|
231
|
+
console.warn(`${constants_js_1.APP_PREFIX} ${picocolors_1.default.yellow(errorMessage)}`);
|
|
226
232
|
}
|
|
227
|
-
return
|
|
233
|
+
return cancelReporting;
|
|
228
234
|
}
|
|
229
235
|
#uploadSingleTest = async (data) => {
|
|
230
236
|
if (!this.isEnabled)
|
|
231
237
|
return;
|
|
232
238
|
if (!this.runId)
|
|
233
239
|
return;
|
|
234
|
-
if (this.#cancelTestReportingInCaseOfTooManyReqFailures(
|
|
240
|
+
if (this.#cancelTestReportingInCaseOfTooManyReqFailures())
|
|
235
241
|
return;
|
|
236
242
|
data.api_key = this.apiKey;
|
|
237
243
|
data.create = this.createNewTests;
|
|
@@ -240,9 +246,9 @@ class TestomatioPipe {
|
|
|
240
246
|
}
|
|
241
247
|
const json = json_cycle_1.default.stringify(data);
|
|
242
248
|
debug('Adding test', json);
|
|
243
|
-
return this.axios
|
|
244
|
-
|
|
245
|
-
.
|
|
249
|
+
return this.axios.post(`/api/reporter/${this.runId}/testrun`, json, axiosAddTestrunRequestConfig).catch(err => {
|
|
250
|
+
this.requestFailures++;
|
|
251
|
+
this.notReportedTestsCount++;
|
|
246
252
|
if (err.response) {
|
|
247
253
|
if (err.response.status >= 400) {
|
|
248
254
|
const responseData = err.response.data || { message: '' };
|
|
@@ -266,6 +272,10 @@ class TestomatioPipe {
|
|
|
266
272
|
#batchUpload = async () => {
|
|
267
273
|
if (!this.batch.isEnabled)
|
|
268
274
|
return;
|
|
275
|
+
if (!this.batch.tests.length)
|
|
276
|
+
return;
|
|
277
|
+
if (this.#cancelTestReportingInCaseOfTooManyReqFailures())
|
|
278
|
+
return;
|
|
269
279
|
// prevent infinite loop
|
|
270
280
|
if (this.batch.numberOfTimesCalledWithoutTests > 10) {
|
|
271
281
|
debug('📨 Batch upload: no tests to send for 10 times, stopping batch');
|
|
@@ -284,6 +294,8 @@ class TestomatioPipe {
|
|
|
284
294
|
return this.axios
|
|
285
295
|
.post(`/api/reporter/${this.runId}/testrun`, { api_key: this.apiKey, tests: testsToSend, batch_index: this.batch.batchIndex }, axiosAddTestrunRequestConfig)
|
|
286
296
|
.catch(err => {
|
|
297
|
+
this.requestFailures++;
|
|
298
|
+
this.notReportedTestsCount += testsToSend.length;
|
|
287
299
|
if (err.response) {
|
|
288
300
|
if (err.response.status >= 400) {
|
|
289
301
|
const responseData = err.response.data || { message: '' };
|
|
@@ -323,15 +335,21 @@ class TestomatioPipe {
|
|
|
323
335
|
this.#batchUpload();
|
|
324
336
|
}
|
|
325
337
|
/**
|
|
326
|
-
* @param {import('../../types').RunData} params
|
|
338
|
+
* @param {import('../../types/types.js').RunData} params
|
|
327
339
|
* @returns
|
|
328
340
|
*/
|
|
329
341
|
async finishRun(params) {
|
|
330
342
|
if (!this.isEnabled)
|
|
331
343
|
return;
|
|
332
|
-
if (this.batch.intervalFunction)
|
|
333
|
-
clearInterval(this.batch.intervalFunction);
|
|
334
344
|
await this.#batchUpload();
|
|
345
|
+
if (this.batch.intervalFunction) {
|
|
346
|
+
clearInterval(this.batch.intervalFunction);
|
|
347
|
+
// this code is required in case test is added after run is finished
|
|
348
|
+
// (e.g. if test has artifacts, add test function will be invoked only after artifacts are uploaded)
|
|
349
|
+
// batch stops working after run is finished; thus, disable it to use single test uploading
|
|
350
|
+
this.batch.intervalFunction = null;
|
|
351
|
+
this.batch.isEnabled = false;
|
|
352
|
+
}
|
|
335
353
|
debug('Finishing run...');
|
|
336
354
|
if (this.reportingCanceledDueToReqFailures) {
|
|
337
355
|
const errorMessage = picocolors_1.default.red(`⚠️ Due to request failures, ${this.notReportedTestsCount} test(s) were not reported to Testomat.io`);
|
|
@@ -351,7 +369,9 @@ class TestomatioPipe {
|
|
|
351
369
|
if (this.runId && !this.proceed) {
|
|
352
370
|
await this.axios.put(`/api/reporter/${this.runId}`, {
|
|
353
371
|
api_key: this.apiKey,
|
|
372
|
+
duration: params.duration,
|
|
354
373
|
status_event,
|
|
374
|
+
detach: params.detach,
|
|
355
375
|
tests: params.tests,
|
|
356
376
|
});
|
|
357
377
|
if (this.runUrl) {
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
declare namespace _default {
|
|
2
|
+
export { saveArtifact as artifact };
|
|
3
|
+
export { logMessage as log };
|
|
4
|
+
export { addStep as step };
|
|
5
|
+
export { setKeyValue as keyValue };
|
|
6
|
+
}
|
|
7
|
+
export default _default;
|
|
8
|
+
/**
|
|
9
|
+
* Stores path to file as artifact and uploads it to the S3 storage
|
|
10
|
+
* @param {string | {path: string, type: string, name: string}} data - path to file or object with path, type and name
|
|
11
|
+
*/
|
|
12
|
+
declare function saveArtifact(data: string | {
|
|
13
|
+
path: string;
|
|
14
|
+
type: string;
|
|
15
|
+
name: string;
|
|
16
|
+
}, context?: any): void;
|
|
17
|
+
/**
|
|
18
|
+
* Attach log message(s) to the test report
|
|
19
|
+
* @param string
|
|
20
|
+
*/
|
|
21
|
+
declare function logMessage(...args: any[]): void;
|
|
22
|
+
/**
|
|
23
|
+
* Similar to "log" function but marks message in report as a step
|
|
24
|
+
* @param {string} message
|
|
25
|
+
*/
|
|
26
|
+
declare function addStep(message: string): void;
|
|
27
|
+
/**
|
|
28
|
+
* Add key-value pair(s) to the test report
|
|
29
|
+
* @param {{[key: string]: string} | string} keyValue object { key: value } (multiple props allowed) or key (string)
|
|
30
|
+
* @param {string?} value
|
|
31
|
+
*/
|
|
32
|
+
declare function setKeyValue(keyValue: {
|
|
33
|
+
[key: string]: string;
|
|
34
|
+
} | string, value?: string | null): void;
|
|
@@ -1,37 +1,47 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const index_js_1 = require("./services/index.js");
|
|
4
|
-
const playwright_js_1 = require("./adapter/playwright.js");
|
|
5
|
-
if (process.env.PLAYWRIGHT_TEST_BASE_URL)
|
|
6
|
-
(0, playwright_js_1.initPlaywrightForStorage)();
|
|
7
4
|
/**
|
|
8
5
|
* Stores path to file as artifact and uploads it to the S3 storage
|
|
9
6
|
* @param {string | {path: string, type: string, name: string}} data - path to file or object with path, type and name
|
|
10
7
|
*/
|
|
11
8
|
function saveArtifact(data, context = null) {
|
|
9
|
+
if (process.env.IS_PLAYWRIGHT)
|
|
10
|
+
throw new Error(`This function is not available in Playwright framework.
|
|
11
|
+
/Playwright supports artifacts out of the box`);
|
|
12
12
|
if (!data)
|
|
13
13
|
return;
|
|
14
14
|
index_js_1.services.artifacts.put(data, context);
|
|
15
15
|
}
|
|
16
16
|
/**
|
|
17
17
|
* Attach log message(s) to the test report
|
|
18
|
-
* @param
|
|
18
|
+
* @param string
|
|
19
19
|
*/
|
|
20
20
|
function logMessage(...args) {
|
|
21
|
+
if (process.env.IS_PLAYWRIGHT)
|
|
22
|
+
throw new Error('This function is not available in Playwright framework');
|
|
21
23
|
index_js_1.services.logger._templateLiteralLog(...args);
|
|
22
24
|
}
|
|
23
25
|
/**
|
|
24
26
|
* Similar to "log" function but marks message in report as a step
|
|
25
|
-
* @param {
|
|
27
|
+
* @param {string} message
|
|
26
28
|
*/
|
|
27
29
|
function addStep(message) {
|
|
30
|
+
if (process.env.IS_PLAYWRIGHT)
|
|
31
|
+
throw new Error('This function is not available in Playwright framework. Use playwright steps');
|
|
28
32
|
index_js_1.services.logger.step(message);
|
|
29
33
|
}
|
|
30
34
|
/**
|
|
31
35
|
* Add key-value pair(s) to the test report
|
|
32
|
-
* @param {
|
|
36
|
+
* @param {{[key: string]: string} | string} keyValue object { key: value } (multiple props allowed) or key (string)
|
|
37
|
+
* @param {string?} value
|
|
33
38
|
*/
|
|
34
|
-
function setKeyValue(keyValue) {
|
|
39
|
+
function setKeyValue(keyValue, value = null) {
|
|
40
|
+
if (process.env.IS_PLAYWRIGHT)
|
|
41
|
+
throw new Error('This function is not available in Playwright framework. Use test tag instead.');
|
|
42
|
+
if (typeof keyValue === 'string') {
|
|
43
|
+
keyValue = { [keyValue]: value };
|
|
44
|
+
}
|
|
35
45
|
index_js_1.services.keyValues.put(keyValue);
|
|
36
46
|
}
|
|
37
47
|
module.exports = {
|