@allurereport/plugin-testops 3.8.1 → 3.9.0
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 +22 -1
- package/dist/client.d.ts +0 -1
- package/dist/client.js +74 -75
- package/dist/logger.js +5 -3
- package/dist/plugin.d.ts +2 -1
- package/dist/plugin.js +41 -30
- package/dist/{utils.d.ts → utils/index.d.ts} +1 -1
- package/dist/{uploadCategory.d.ts → utils/uploadCategory.d.ts} +1 -1
- package/dist/{uploadCategory.js → utils/uploadCategory.js} +1 -1
- package/dist/{uploaderDto.d.ts → utils/uploaderDto.d.ts} +2 -2
- package/package.json +7 -5
- /package/dist/{utils.js → utils/index.js} +0 -0
- /package/dist/{uploaderDto.js → utils/uploaderDto.js} +0 -0
package/README.md
CHANGED
|
@@ -12,7 +12,26 @@
|
|
|
12
12
|
|
|
13
13
|
## Overview
|
|
14
14
|
|
|
15
|
-
The plugin
|
|
15
|
+
The plugin can create a new launch in Allure TestOps with all the tests data from the current report.
|
|
16
|
+
|
|
17
|
+
## CI and local runs
|
|
18
|
+
|
|
19
|
+
The plugin is intended to run in a **CI environment**. When a supported CI is detected, upload to TestOps starts automatically (as long as `accessToken`, `endpoint`, and `projectId` are configured).
|
|
20
|
+
|
|
21
|
+
On a **local machine** (no CI detected), upload is disabled by default.
|
|
22
|
+
|
|
23
|
+
To upload from your machine anyway, opt in with one of these environment variables set to a truthy value (`true` or `1`):
|
|
24
|
+
|
|
25
|
+
| Environment variable | Purpose |
|
|
26
|
+
|----------------------------|---------|
|
|
27
|
+
| `ALLURE_TESTOPS_ENABLED` | Explicitly enable TestOps upload outside CI |
|
|
28
|
+
| `CI` | Same effect; useful if your tooling already sets `CI` in non-CI workflows |
|
|
29
|
+
|
|
30
|
+
Example:
|
|
31
|
+
|
|
32
|
+
```shell
|
|
33
|
+
ALLURE_TESTOPS_ENABLED=true allure run ...
|
|
34
|
+
```
|
|
16
35
|
|
|
17
36
|
## Install
|
|
18
37
|
|
|
@@ -71,3 +90,5 @@ The plugin automatically reads the following environment variables and uses them
|
|
|
71
90
|
| `ALLURE_ENDPOINT` | `endpoint` |
|
|
72
91
|
| `ALLURE_LAUNCH_NAME` | `launchName` |
|
|
73
92
|
| `ALLURE_LAUNCH_TAGS` | `launchTags` |
|
|
93
|
+
|
|
94
|
+
`ALLURE_TESTOPS_ENABLED` and `CI` are not configuration options: they only control whether upload runs when no CI is detected. See [CI and local runs](#ci-and-local-runs).
|
package/dist/client.d.ts
CHANGED
|
@@ -23,7 +23,6 @@ export declare class TestOpsClient {
|
|
|
23
23
|
get launchId(): number | undefined;
|
|
24
24
|
closeLaunch(launchId: number): Promise<void>;
|
|
25
25
|
createLaunchCategoriesBulk(launchId: number, items: LaunchCategoryBulkItem[]): Promise<LaunchCategoryBulkResult[]>;
|
|
26
|
-
issueOauthToken(): Promise<void>;
|
|
27
26
|
startUpload(ci: CiDescriptor): Promise<void>;
|
|
28
27
|
stopUpload(ci: CiDescriptor, status: TestStatus): Promise<void>;
|
|
29
28
|
createLaunch(launchName: string, launchTags: string[]): Promise<void>;
|
package/dist/client.js
CHANGED
|
@@ -9,14 +9,15 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
9
9
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
10
10
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
11
|
};
|
|
12
|
-
var _TestOpsClient_instances, _TestOpsClient_logger, _TestOpsClient_accessToken, _TestOpsClient_projectId,
|
|
13
|
-
import
|
|
12
|
+
var _TestOpsClient_instances, _TestOpsClient_baseUrl, _TestOpsClient_logger, _TestOpsClient_accessToken, _TestOpsClient_projectId, _TestOpsClient_client, _TestOpsClient_launch, _TestOpsClient_session, _TestOpsClient_uploadInProgress, _TestOpsClient_uploadLimit, _TestOpsClient_namedEnvsIdsByEnv, _TestOpsClient_postTestResultsChunk, _TestOpsClient_uploadChunkAttachmentsAndFixtures, _TestOpsClient_uploadAttachmentsForResult, _TestOpsClient_uploadFixturesForResult;
|
|
13
|
+
import { createServiceHttpClient } from "@allurereport/service";
|
|
14
|
+
import { AxiosError, isAxiosError } from "axios";
|
|
14
15
|
import FormData from "form-data";
|
|
15
16
|
import { chunk } from "lodash-es";
|
|
16
17
|
import pLimit from "p-limit";
|
|
17
18
|
import { bold } from "yoctocolors";
|
|
18
19
|
import { Logger } from "./logger.js";
|
|
19
|
-
import { toUploadFixturesResultsDto, toUploadResultsDto } from "./uploaderDto.js";
|
|
20
|
+
import { toUploadFixturesResultsDto, toUploadResultsDto } from "./utils/uploaderDto.js";
|
|
20
21
|
class TestOpsClientError extends AxiosError {
|
|
21
22
|
}
|
|
22
23
|
const CHUNK_SIZE = 100;
|
|
@@ -24,10 +25,10 @@ const BULK_UPLOAD_CHUNK_SIZE = 1000;
|
|
|
24
25
|
export class TestOpsClient {
|
|
25
26
|
constructor(params) {
|
|
26
27
|
_TestOpsClient_instances.add(this);
|
|
28
|
+
_TestOpsClient_baseUrl.set(this, void 0);
|
|
27
29
|
_TestOpsClient_logger.set(this, new Logger("TestOpsClient"));
|
|
28
30
|
_TestOpsClient_accessToken.set(this, void 0);
|
|
29
31
|
_TestOpsClient_projectId.set(this, void 0);
|
|
30
|
-
_TestOpsClient_oauthToken.set(this, "");
|
|
31
32
|
_TestOpsClient_client.set(this, void 0);
|
|
32
33
|
_TestOpsClient_launch.set(this, void 0);
|
|
33
34
|
_TestOpsClient_session.set(this, void 0);
|
|
@@ -46,18 +47,12 @@ export class TestOpsClient {
|
|
|
46
47
|
if (params.limit && params.limit > 5) {
|
|
47
48
|
throw new Error("limit can't be greater than 5");
|
|
48
49
|
}
|
|
50
|
+
__classPrivateFieldSet(this, _TestOpsClient_baseUrl, params.baseUrl, "f");
|
|
49
51
|
__classPrivateFieldSet(this, _TestOpsClient_accessToken, params.accessToken, "f");
|
|
50
52
|
__classPrivateFieldSet(this, _TestOpsClient_projectId, params.projectId, "f");
|
|
51
|
-
__classPrivateFieldSet(this, _TestOpsClient_client,
|
|
52
|
-
|
|
53
|
-
validateStatus: (status) => status >= 200 && status < 400,
|
|
53
|
+
__classPrivateFieldSet(this, _TestOpsClient_client, createServiceHttpClient(params.baseUrl, {
|
|
54
|
+
apiToken: __classPrivateFieldGet(this, _TestOpsClient_accessToken, "f"),
|
|
54
55
|
}), "f");
|
|
55
|
-
__classPrivateFieldGet(this, _TestOpsClient_client, "f").interceptors.request.use((config) => {
|
|
56
|
-
if (__classPrivateFieldGet(this, _TestOpsClient_oauthToken, "f")) {
|
|
57
|
-
config.headers.set("Authorization", `Bearer ${__classPrivateFieldGet(this, _TestOpsClient_oauthToken, "f")}`);
|
|
58
|
-
}
|
|
59
|
-
return config;
|
|
60
|
-
});
|
|
61
56
|
if (params.limit) {
|
|
62
57
|
__classPrivateFieldSet(this, _TestOpsClient_uploadLimit, params.limit, "f");
|
|
63
58
|
}
|
|
@@ -71,7 +66,7 @@ export class TestOpsClient {
|
|
|
71
66
|
if (!__classPrivateFieldGet(this, _TestOpsClient_launch, "f")) {
|
|
72
67
|
return undefined;
|
|
73
68
|
}
|
|
74
|
-
return new URL(`launch/${__classPrivateFieldGet(this, _TestOpsClient_launch, "f").id}`, __classPrivateFieldGet(this,
|
|
69
|
+
return new URL(`launch/${__classPrivateFieldGet(this, _TestOpsClient_launch, "f").id}`, __classPrivateFieldGet(this, _TestOpsClient_baseUrl, "f")).toString();
|
|
75
70
|
}
|
|
76
71
|
get launchId() {
|
|
77
72
|
return __classPrivateFieldGet(this, _TestOpsClient_launch, "f")?.id;
|
|
@@ -95,8 +90,9 @@ export class TestOpsClient {
|
|
|
95
90
|
__classPrivateFieldGet(this, _TestOpsClient_logger, "f").debug(`POST /api/launch/category/bulk request (${currentRequestIndex + 1}/${totalChunks}, items: ${chunk.length})`);
|
|
96
91
|
}
|
|
97
92
|
__classPrivateFieldGet(this, _TestOpsClient_logger, "f").debug(body);
|
|
98
|
-
const
|
|
93
|
+
const data = await __classPrivateFieldGet(this, _TestOpsClient_client, "f").post("/api/launch/category/bulk", {
|
|
99
94
|
headers: { "Content-Type": "application/json" },
|
|
95
|
+
body,
|
|
100
96
|
});
|
|
101
97
|
if (Array.isArray(data)) {
|
|
102
98
|
results.push(...data);
|
|
@@ -115,37 +111,27 @@ export class TestOpsClient {
|
|
|
115
111
|
}
|
|
116
112
|
return results;
|
|
117
113
|
}
|
|
118
|
-
async issueOauthToken() {
|
|
119
|
-
const base = __classPrivateFieldGet(this, _TestOpsClient_client, "f").defaults.baseURL;
|
|
120
|
-
__classPrivateFieldGet(this, _TestOpsClient_logger, "f").debug(`Endpoint: ${base}`);
|
|
121
|
-
__classPrivateFieldGet(this, _TestOpsClient_logger, "f").verbose("Issuing OAuth token…");
|
|
122
|
-
const formData = new FormData();
|
|
123
|
-
formData.append("grant_type", "apitoken");
|
|
124
|
-
formData.append("scope", "openid");
|
|
125
|
-
formData.append("token", __classPrivateFieldGet(this, _TestOpsClient_accessToken, "f"));
|
|
126
|
-
const { data } = await __classPrivateFieldGet(this, _TestOpsClient_client, "f").post("/api/uaa/oauth/token", formData);
|
|
127
|
-
__classPrivateFieldSet(this, _TestOpsClient_oauthToken, data.access_token, "f");
|
|
128
|
-
__classPrivateFieldGet(this, _TestOpsClient_logger, "f").verbose("OAuth token received");
|
|
129
|
-
}
|
|
130
114
|
async startUpload(ci) {
|
|
131
115
|
if (!__classPrivateFieldGet(this, _TestOpsClient_launch, "f")) {
|
|
132
116
|
throw new Error("Launch isn't created! Call createLaunch first");
|
|
133
117
|
}
|
|
134
118
|
__classPrivateFieldGet(this, _TestOpsClient_logger, "f").verbose(`Starting CI upload (${ci.type})…`);
|
|
135
119
|
await __classPrivateFieldGet(this, _TestOpsClient_client, "f").post("/api/upload/start", {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
120
|
+
body: {
|
|
121
|
+
projectId: __classPrivateFieldGet(this, _TestOpsClient_projectId, "f"),
|
|
122
|
+
ci: {
|
|
123
|
+
name: ci.type,
|
|
124
|
+
},
|
|
125
|
+
job: {
|
|
126
|
+
name: ci.jobUid,
|
|
127
|
+
uid: ci.jobUid,
|
|
128
|
+
},
|
|
129
|
+
jobRun: {
|
|
130
|
+
uid: ci.jobRunUid,
|
|
131
|
+
},
|
|
132
|
+
launch: {
|
|
133
|
+
id: __classPrivateFieldGet(this, _TestOpsClient_launch, "f").id,
|
|
134
|
+
},
|
|
149
135
|
},
|
|
150
136
|
});
|
|
151
137
|
__classPrivateFieldSet(this, _TestOpsClient_uploadInProgress, true, "f");
|
|
@@ -156,22 +142,26 @@ export class TestOpsClient {
|
|
|
156
142
|
throw new Error("Upload isn't started! Call startUpload first");
|
|
157
143
|
}
|
|
158
144
|
await __classPrivateFieldGet(this, _TestOpsClient_client, "f").post("/api/upload/stop", {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
145
|
+
body: {
|
|
146
|
+
jobRunUid: ci.jobRunUid,
|
|
147
|
+
jobUid: ci.jobUid,
|
|
148
|
+
projectId: __classPrivateFieldGet(this, _TestOpsClient_projectId, "f"),
|
|
149
|
+
status,
|
|
150
|
+
},
|
|
163
151
|
});
|
|
164
152
|
__classPrivateFieldSet(this, _TestOpsClient_uploadInProgress, false, "f");
|
|
165
153
|
__classPrivateFieldGet(this, _TestOpsClient_logger, "f").verbose(`CI upload stopped (status: ${status})`);
|
|
166
154
|
}
|
|
167
155
|
async createLaunch(launchName, launchTags) {
|
|
168
156
|
__classPrivateFieldGet(this, _TestOpsClient_logger, "f").verbose("Creating launch…");
|
|
169
|
-
const
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
157
|
+
const data = await __classPrivateFieldGet(this, _TestOpsClient_client, "f").post("/api/launch", {
|
|
158
|
+
body: {
|
|
159
|
+
name: launchName,
|
|
160
|
+
projectId: __classPrivateFieldGet(this, _TestOpsClient_projectId, "f"),
|
|
161
|
+
autoclose: true,
|
|
162
|
+
external: true,
|
|
163
|
+
tags: launchTags.map((tag) => ({ name: tag })),
|
|
164
|
+
},
|
|
175
165
|
});
|
|
176
166
|
__classPrivateFieldSet(this, _TestOpsClient_launch, data, "f");
|
|
177
167
|
__classPrivateFieldGet(this, _TestOpsClient_logger, "f").debug(`Launch created: id=${bold(data.id.toString())}`);
|
|
@@ -180,13 +170,14 @@ export class TestOpsClient {
|
|
|
180
170
|
if (!__classPrivateFieldGet(this, _TestOpsClient_launch, "f")) {
|
|
181
171
|
throw new Error("Launch isn't created! Call createLaunch first");
|
|
182
172
|
}
|
|
183
|
-
const
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
key,
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
173
|
+
const data = await __classPrivateFieldGet(this, _TestOpsClient_client, "f").post("/api/upload/session", {
|
|
174
|
+
body: {
|
|
175
|
+
launchId: __classPrivateFieldGet(this, _TestOpsClient_launch, "f").id,
|
|
176
|
+
environment: Object.entries(environment).map(([key, value]) => ({
|
|
177
|
+
key,
|
|
178
|
+
value: String(value),
|
|
179
|
+
})),
|
|
180
|
+
},
|
|
190
181
|
params: {
|
|
191
182
|
manual: "true",
|
|
192
183
|
},
|
|
@@ -211,13 +202,14 @@ export class TestOpsClient {
|
|
|
211
202
|
if (!__classPrivateFieldGet(this, _TestOpsClient_launch, "f")) {
|
|
212
203
|
throw new Error("Launch isn't created! Call createLaunch first");
|
|
213
204
|
}
|
|
214
|
-
const
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
205
|
+
const data = await __classPrivateFieldGet(this, _TestOpsClient_client, "f").post("/api/launch/named-env/bulk", {
|
|
206
|
+
body: {
|
|
207
|
+
launchId: __classPrivateFieldGet(this, _TestOpsClient_launch, "f").id,
|
|
208
|
+
items: environments.map(({ id, name }) => ({
|
|
209
|
+
externalId: id,
|
|
210
|
+
name,
|
|
211
|
+
})),
|
|
212
|
+
},
|
|
221
213
|
headers: {
|
|
222
214
|
"Content-Type": "application/json",
|
|
223
215
|
},
|
|
@@ -254,7 +246,8 @@ export class TestOpsClient {
|
|
|
254
246
|
contentType: attachment.contentType,
|
|
255
247
|
});
|
|
256
248
|
}
|
|
257
|
-
await __classPrivateFieldGet(this, _TestOpsClient_client, "f").post("/api/launch/attachment",
|
|
249
|
+
await __classPrivateFieldGet(this, _TestOpsClient_client, "f").post("/api/launch/attachment", {
|
|
250
|
+
body: formData,
|
|
258
251
|
onUploadProgress(progressEvent) {
|
|
259
252
|
const total = progressEvent.total ?? 100;
|
|
260
253
|
const percent = total > 0 ? Math.min(100, Math.max(0, (progressEvent.loaded / total) * 100)) : 0;
|
|
@@ -272,9 +265,10 @@ export class TestOpsClient {
|
|
|
272
265
|
throw new Error("Launch isn't created! Call createLaunch first");
|
|
273
266
|
}
|
|
274
267
|
await __classPrivateFieldGet(this, _TestOpsClient_client, "f").post("/api/launch/error/bulk", {
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
268
|
+
body: {
|
|
269
|
+
launchId: __classPrivateFieldGet(this, _TestOpsClient_launch, "f").id,
|
|
270
|
+
items: errors,
|
|
271
|
+
},
|
|
278
272
|
onUploadProgress(progressEvent) {
|
|
279
273
|
const total = progressEvent.total ?? 100;
|
|
280
274
|
const percent = total > 0 ? Math.min(100, Math.max(0, (progressEvent.loaded / total) * 100)) : 0;
|
|
@@ -345,9 +339,10 @@ export class TestOpsClient {
|
|
|
345
339
|
return item;
|
|
346
340
|
});
|
|
347
341
|
await __classPrivateFieldGet(this, _TestOpsClient_client, "f").post("/api/launch/quality-gate/bulk", {
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
342
|
+
body: {
|
|
343
|
+
launchId: __classPrivateFieldGet(this, _TestOpsClient_launch, "f").id,
|
|
344
|
+
items,
|
|
345
|
+
},
|
|
351
346
|
onUploadProgress(progressEvent) {
|
|
352
347
|
const total = progressEvent.total ?? 100;
|
|
353
348
|
const percent = total > 0 ? Math.min(100, Math.max(0, (progressEvent.loaded / total) * 100)) : 0;
|
|
@@ -356,7 +351,7 @@ export class TestOpsClient {
|
|
|
356
351
|
});
|
|
357
352
|
}
|
|
358
353
|
}
|
|
359
|
-
|
|
354
|
+
_TestOpsClient_baseUrl = new WeakMap(), _TestOpsClient_logger = new WeakMap(), _TestOpsClient_accessToken = new WeakMap(), _TestOpsClient_projectId = new WeakMap(), _TestOpsClient_client = new WeakMap(), _TestOpsClient_launch = new WeakMap(), _TestOpsClient_session = new WeakMap(), _TestOpsClient_uploadInProgress = new WeakMap(), _TestOpsClient_uploadLimit = new WeakMap(), _TestOpsClient_namedEnvsIdsByEnv = new WeakMap(), _TestOpsClient_instances = new WeakSet(), _TestOpsClient_postTestResultsChunk = async function _TestOpsClient_postTestResultsChunk(trsChunk) {
|
|
360
355
|
const extendedChunk = trsChunk.map((testResult) => {
|
|
361
356
|
const extendedTestResult = {
|
|
362
357
|
...testResult,
|
|
@@ -376,7 +371,8 @@ _TestOpsClient_logger = new WeakMap(), _TestOpsClient_accessToken = new WeakMap(
|
|
|
376
371
|
return extendedTestResult;
|
|
377
372
|
});
|
|
378
373
|
const body = toUploadResultsDto(__classPrivateFieldGet(this, _TestOpsClient_session, "f").id, extendedChunk);
|
|
379
|
-
const
|
|
374
|
+
const data = await __classPrivateFieldGet(this, _TestOpsClient_client, "f").post("/api/upload/test-result", {
|
|
375
|
+
body,
|
|
380
376
|
headers: { "Content-Type": "application/json" },
|
|
381
377
|
});
|
|
382
378
|
const reportIdsToTestOpsIds = {};
|
|
@@ -409,7 +405,8 @@ _TestOpsClient_logger = new WeakMap(), _TestOpsClient_accessToken = new WeakMap(
|
|
|
409
405
|
});
|
|
410
406
|
}
|
|
411
407
|
try {
|
|
412
|
-
await __classPrivateFieldGet(this, _TestOpsClient_client, "f").post(`/api/upload/test-result/${testOpsResultId}/attachment`,
|
|
408
|
+
await __classPrivateFieldGet(this, _TestOpsClient_client, "f").post(`/api/upload/test-result/${testOpsResultId}/attachment`, {
|
|
409
|
+
body: formData,
|
|
413
410
|
headers: formData.getHeaders(),
|
|
414
411
|
});
|
|
415
412
|
}
|
|
@@ -430,5 +427,7 @@ _TestOpsClient_logger = new WeakMap(), _TestOpsClient_accessToken = new WeakMap(
|
|
|
430
427
|
if (fixtures.length === 0)
|
|
431
428
|
return;
|
|
432
429
|
const body = toUploadFixturesResultsDto(fixtures);
|
|
433
|
-
await __classPrivateFieldGet(this, _TestOpsClient_client, "f").post(`/api/upload/test-result/${testOpsResultId}/test-fixture-result`,
|
|
430
|
+
await __classPrivateFieldGet(this, _TestOpsClient_client, "f").post(`/api/upload/test-result/${testOpsResultId}/test-fixture-result`, {
|
|
431
|
+
body,
|
|
432
|
+
});
|
|
434
433
|
};
|
package/dist/logger.js
CHANGED
|
@@ -3,7 +3,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
3
3
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
4
4
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
5
5
|
};
|
|
6
|
-
var _Logger_instances, _Logger_level, _Logger_isLogLevel, _Logger_prefix;
|
|
6
|
+
var _Logger_instances, _Logger_level, _Logger_isLogLevel, _Logger_isSilent, _Logger_prefix;
|
|
7
7
|
import console from "node:console";
|
|
8
8
|
import { env } from "node:process";
|
|
9
9
|
import { inspect } from "node:util";
|
|
@@ -37,7 +37,7 @@ export class Logger {
|
|
|
37
37
|
_Logger_prefix.set(this, cyan(bold(`[${this.name}]:`)));
|
|
38
38
|
}
|
|
39
39
|
progressBarCounter(message, total) {
|
|
40
|
-
if (__classPrivateFieldGet(this, _Logger_instances, "m",
|
|
40
|
+
if (__classPrivateFieldGet(this, _Logger_instances, "m", _Logger_isSilent).call(this)) {
|
|
41
41
|
return {
|
|
42
42
|
tick: () => { },
|
|
43
43
|
update: () => { },
|
|
@@ -51,7 +51,7 @@ export class Logger {
|
|
|
51
51
|
return progressBar;
|
|
52
52
|
}
|
|
53
53
|
progressBar(message) {
|
|
54
|
-
if (__classPrivateFieldGet(this, _Logger_instances, "m",
|
|
54
|
+
if (__classPrivateFieldGet(this, _Logger_instances, "m", _Logger_isSilent).call(this)) {
|
|
55
55
|
return {
|
|
56
56
|
update: () => { },
|
|
57
57
|
terminate: () => { },
|
|
@@ -126,4 +126,6 @@ export class Logger {
|
|
|
126
126
|
}
|
|
127
127
|
_Logger_level = new WeakMap(), _Logger_prefix = new WeakMap(), _Logger_instances = new WeakSet(), _Logger_isLogLevel = function _Logger_isLogLevel(level) {
|
|
128
128
|
return logLevelsPriority[__classPrivateFieldGet(this, _Logger_level, "f")] <= logLevelsPriority[level];
|
|
129
|
+
}, _Logger_isSilent = function _Logger_isSilent() {
|
|
130
|
+
return __classPrivateFieldGet(this, _Logger_level, "f") === "silent";
|
|
129
131
|
};
|
package/dist/plugin.d.ts
CHANGED
|
@@ -4,7 +4,8 @@ export declare class TestOpsPlugin implements Plugin {
|
|
|
4
4
|
#private;
|
|
5
5
|
readonly options: TestOpsPluginOptions;
|
|
6
6
|
constructor(options: TestOpsPluginOptions);
|
|
7
|
-
get
|
|
7
|
+
get isOverridenByEnv(): boolean;
|
|
8
|
+
get enabled(): boolean;
|
|
8
9
|
start(context: PluginContext, store: AllureStore): Promise<void>;
|
|
9
10
|
update(context: PluginContext, store: AllureStore): Promise<void>;
|
|
10
11
|
done(context: PluginContext, store: AllureStore): Promise<void>;
|
package/dist/plugin.js
CHANGED
|
@@ -9,7 +9,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
9
9
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
10
10
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
11
|
};
|
|
12
|
-
var _TestOpsPlugin_instances, _TestOpsPlugin_logger, _TestOpsPlugin_ci, _TestOpsPlugin_client,
|
|
12
|
+
var _TestOpsPlugin_instances, _TestOpsPlugin_logger, _TestOpsPlugin_ci, _TestOpsPlugin_client, _TestOpsPlugin_clientConfigured, _TestOpsPlugin_launchName, _TestOpsPlugin_launchTags, _TestOpsPlugin_uploadedTestResultsIds, _TestOpsPlugin_autocloseLaunch, _TestOpsPlugin_uploadQualityGateResults, _TestOpsPlugin_uploadGlobalErrors, _TestOpsPlugin_uploadGlobalAttachments, _TestOpsPlugin_uploadTestResults, _TestOpsPlugin_upload, _TestOpsPlugin_trsToUpload, _TestOpsPlugin_enrichWithCategories, _TestOpsPlugin_syncLaunchCategories, _TestOpsPlugin_collectCategoryNamesByExternalId, _TestOpsPlugin_assignCreatedCategoryIds, _TestOpsPlugin_startUpload, _TestOpsPlugin_stopUpload;
|
|
13
13
|
import { env } from "node:process";
|
|
14
14
|
import { detect } from "@allurereport/ci";
|
|
15
15
|
import { getWorstStatus } from "@allurereport/core-api";
|
|
@@ -18,9 +18,9 @@ import { uniqBy, stubTrue } from "lodash-es";
|
|
|
18
18
|
import { bold } from "yoctocolors";
|
|
19
19
|
import { TestOpsClient } from "./client.js";
|
|
20
20
|
import { Logger } from "./logger.js";
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
21
|
+
import { attachmentsResolverFactory, fixturesResolverFactory, resolvePluginOptions, unwrapStepsAttachments, } from "./utils/index.js";
|
|
22
|
+
import { toUploadCategory } from "./utils/uploadCategory.js";
|
|
23
|
+
import { uploadFilenameForLink } from "./utils/uploaderDto.js";
|
|
24
24
|
const categoryDisplayName = (cat) => cat.name ?? cat.grouping?.[0]?.name ?? cat.grouping?.[0]?.value ?? cat.grouping?.[0]?.key ?? cat.externalId;
|
|
25
25
|
export class TestOpsPlugin {
|
|
26
26
|
constructor(options) {
|
|
@@ -29,15 +29,19 @@ export class TestOpsPlugin {
|
|
|
29
29
|
_TestOpsPlugin_logger.set(this, new Logger("TestOpsPlugin"));
|
|
30
30
|
_TestOpsPlugin_ci.set(this, void 0);
|
|
31
31
|
_TestOpsPlugin_client.set(this, void 0);
|
|
32
|
-
|
|
32
|
+
_TestOpsPlugin_clientConfigured.set(this, false);
|
|
33
33
|
_TestOpsPlugin_launchName.set(this, "");
|
|
34
34
|
_TestOpsPlugin_launchTags.set(this, []);
|
|
35
35
|
_TestOpsPlugin_uploadedTestResultsIds.set(this, new Set());
|
|
36
|
-
_TestOpsPlugin_autocloseLaunch.set(this,
|
|
37
|
-
const { accessToken, endpoint, projectId, launchName, launchTags, autocloseLaunch = true, } = resolvePluginOptions(options);
|
|
36
|
+
_TestOpsPlugin_autocloseLaunch.set(this, false);
|
|
38
37
|
__classPrivateFieldSet(this, _TestOpsPlugin_ci, detect(), "f");
|
|
38
|
+
if (!__classPrivateFieldGet(this, _TestOpsPlugin_ci, "f") || __classPrivateFieldGet(this, _TestOpsPlugin_ci, "f").type === "local") {
|
|
39
|
+
__classPrivateFieldGet(this, _TestOpsPlugin_logger, "f").info(`plugin is disabled - no CI environment detected. To enable, set ${bold("ALLURE_TESTOPS_ENABLED")}=true or ${bold("CI")}=true.`);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const { accessToken, endpoint, projectId, launchName, launchTags, autocloseLaunch = true, } = resolvePluginOptions(options);
|
|
39
43
|
if ([accessToken, endpoint, projectId].every(Boolean)) {
|
|
40
|
-
__classPrivateFieldSet(this,
|
|
44
|
+
__classPrivateFieldSet(this, _TestOpsPlugin_clientConfigured, true, "f");
|
|
41
45
|
__classPrivateFieldSet(this, _TestOpsPlugin_client, new TestOpsClient({
|
|
42
46
|
baseUrl: endpoint,
|
|
43
47
|
accessToken,
|
|
@@ -57,32 +61,50 @@ export class TestOpsPlugin {
|
|
|
57
61
|
__classPrivateFieldGet(this, _TestOpsPlugin_logger, "f").warn(`Allure TestOps ${bold("project ID")} is missing. Please provide a valid project ID in the plugin options.`);
|
|
58
62
|
}
|
|
59
63
|
}
|
|
60
|
-
get
|
|
61
|
-
|
|
64
|
+
get isOverridenByEnv() {
|
|
65
|
+
const isEnabled = (value) => {
|
|
66
|
+
if (!value) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
return ["true", "1"].includes(value);
|
|
70
|
+
};
|
|
71
|
+
return isEnabled(env.ALLURE_TESTOPS_ENABLED) || isEnabled(env.CI);
|
|
72
|
+
}
|
|
73
|
+
get enabled() {
|
|
74
|
+
if (!__classPrivateFieldGet(this, _TestOpsPlugin_clientConfigured, "f")) {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
if (this.isOverridenByEnv) {
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
if (!__classPrivateFieldGet(this, _TestOpsPlugin_ci, "f") || __classPrivateFieldGet(this, _TestOpsPlugin_ci, "f").type === "local") {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
return true;
|
|
62
84
|
}
|
|
63
85
|
async start(context, store) {
|
|
64
|
-
if (!
|
|
86
|
+
if (!this.enabled) {
|
|
65
87
|
return;
|
|
66
88
|
}
|
|
67
89
|
__classPrivateFieldGet(this, _TestOpsPlugin_logger, "f").verbose("Starting upload…");
|
|
68
90
|
await __classPrivateFieldGet(this, _TestOpsPlugin_instances, "m", _TestOpsPlugin_startUpload).call(this);
|
|
69
|
-
await __classPrivateFieldGet(this, _TestOpsPlugin_instances, "m", _TestOpsPlugin_upload).call(this, store, {
|
|
91
|
+
await __classPrivateFieldGet(this, _TestOpsPlugin_instances, "m", _TestOpsPlugin_upload).call(this, store, { context, stage: "start" });
|
|
70
92
|
__classPrivateFieldGet(this, _TestOpsPlugin_logger, "f").info(`Allure TestOps Launch: ${__classPrivateFieldGet(this, _TestOpsPlugin_client, "f").launchUrl}`);
|
|
71
93
|
}
|
|
72
94
|
async update(context, store) {
|
|
73
|
-
if (!
|
|
95
|
+
if (!this.enabled) {
|
|
74
96
|
return;
|
|
75
97
|
}
|
|
76
98
|
__classPrivateFieldGet(this, _TestOpsPlugin_logger, "f").verbose("Updating (uploading new results)…");
|
|
77
99
|
await __classPrivateFieldGet(this, _TestOpsPlugin_instances, "m", _TestOpsPlugin_upload).call(this, store, { context, stage: "update" });
|
|
78
100
|
}
|
|
79
101
|
async done(context, store) {
|
|
80
|
-
if (!
|
|
102
|
+
if (!this.enabled) {
|
|
81
103
|
return;
|
|
82
104
|
}
|
|
83
105
|
const allTrs = await store.allTestResults({
|
|
84
106
|
filter: this.options.filter,
|
|
85
|
-
|
|
107
|
+
includeRetries: false,
|
|
86
108
|
});
|
|
87
109
|
const worstStatus = getWorstStatus(allTrs.map(({ status }) => status));
|
|
88
110
|
__classPrivateFieldGet(this, _TestOpsPlugin_logger, "f").verbose("Finalizing upload…");
|
|
@@ -110,7 +132,7 @@ export class TestOpsPlugin {
|
|
|
110
132
|
__classPrivateFieldGet(this, _TestOpsPlugin_logger, "f").info(`Upload finished. Allure TestOps Launch: ${__classPrivateFieldGet(this, _TestOpsPlugin_client, "f").launchUrl}`);
|
|
111
133
|
}
|
|
112
134
|
async info(context, store) {
|
|
113
|
-
if (!
|
|
135
|
+
if (!this.enabled) {
|
|
114
136
|
return undefined;
|
|
115
137
|
}
|
|
116
138
|
if (!__classPrivateFieldGet(this, _TestOpsPlugin_client, "f").launchUrl) {
|
|
@@ -131,7 +153,7 @@ export class TestOpsPlugin {
|
|
|
131
153
|
return summary;
|
|
132
154
|
}
|
|
133
155
|
}
|
|
134
|
-
_TestOpsPlugin_logger = new WeakMap(), _TestOpsPlugin_ci = new WeakMap(), _TestOpsPlugin_client = new WeakMap(),
|
|
156
|
+
_TestOpsPlugin_logger = new WeakMap(), _TestOpsPlugin_ci = new WeakMap(), _TestOpsPlugin_client = new WeakMap(), _TestOpsPlugin_clientConfigured = new WeakMap(), _TestOpsPlugin_launchName = new WeakMap(), _TestOpsPlugin_launchTags = new WeakMap(), _TestOpsPlugin_uploadedTestResultsIds = new WeakMap(), _TestOpsPlugin_autocloseLaunch = new WeakMap(), _TestOpsPlugin_instances = new WeakSet(), _TestOpsPlugin_uploadQualityGateResults = async function _TestOpsPlugin_uploadQualityGateResults(store) {
|
|
135
157
|
const results = await store.qualityGateResults();
|
|
136
158
|
const uniqueResults = uniqBy(results.filter(({ success }) => !success), ({ rule, environment }) => `${rule}-${environment}`);
|
|
137
159
|
if (uniqueResults.length === 0) {
|
|
@@ -255,7 +277,7 @@ _TestOpsPlugin_logger = new WeakMap(), _TestOpsPlugin_ci = new WeakMap(), _TestO
|
|
|
255
277
|
}
|
|
256
278
|
__classPrivateFieldGet(this, _TestOpsPlugin_logger, "f").info(`Uploaded ${uploadedCount} ${uploadedCount > 1 ? "test results" : "test result"}`);
|
|
257
279
|
}, _TestOpsPlugin_upload = async function _TestOpsPlugin_upload(store, options = {}) {
|
|
258
|
-
const {
|
|
280
|
+
const { context, stage } = options;
|
|
259
281
|
const trsToUpload = await __classPrivateFieldGet(this, _TestOpsPlugin_instances, "m", _TestOpsPlugin_trsToUpload).call(this, store);
|
|
260
282
|
if (trsToUpload.length === 0) {
|
|
261
283
|
if (stage == "update") {
|
|
@@ -266,10 +288,6 @@ _TestOpsPlugin_logger = new WeakMap(), _TestOpsPlugin_ci = new WeakMap(), _TestO
|
|
|
266
288
|
}
|
|
267
289
|
return;
|
|
268
290
|
}
|
|
269
|
-
if (issueNewToken) {
|
|
270
|
-
__classPrivateFieldGet(this, _TestOpsPlugin_logger, "f").verbose("Issuing new OAuth token");
|
|
271
|
-
await __classPrivateFieldGet(this, _TestOpsPlugin_client, "f").issueOauthToken();
|
|
272
|
-
}
|
|
273
291
|
await __classPrivateFieldGet(this, _TestOpsPlugin_client, "f").createSession(env);
|
|
274
292
|
await __classPrivateFieldGet(this, _TestOpsPlugin_instances, "m", _TestOpsPlugin_uploadGlobalAttachments).call(this, store);
|
|
275
293
|
await __classPrivateFieldGet(this, _TestOpsPlugin_instances, "m", _TestOpsPlugin_uploadGlobalErrors).call(this, store);
|
|
@@ -289,7 +307,7 @@ _TestOpsPlugin_logger = new WeakMap(), _TestOpsPlugin_ci = new WeakMap(), _TestO
|
|
|
289
307
|
}
|
|
290
308
|
return filter(tr);
|
|
291
309
|
},
|
|
292
|
-
|
|
310
|
+
includeRetries: false,
|
|
293
311
|
});
|
|
294
312
|
return filteredTrs;
|
|
295
313
|
}, _TestOpsPlugin_enrichWithCategories = async function _TestOpsPlugin_enrichWithCategories(store, trs, contextCategories) {
|
|
@@ -378,15 +396,8 @@ _TestOpsPlugin_logger = new WeakMap(), _TestOpsPlugin_ci = new WeakMap(), _TestO
|
|
|
378
396
|
}
|
|
379
397
|
}
|
|
380
398
|
}, _TestOpsPlugin_startUpload = async function _TestOpsPlugin_startUpload() {
|
|
381
|
-
await __classPrivateFieldGet(this, _TestOpsPlugin_client, "f").issueOauthToken();
|
|
382
399
|
await __classPrivateFieldGet(this, _TestOpsPlugin_client, "f").createLaunch(__classPrivateFieldGet(this, _TestOpsPlugin_launchName, "f"), __classPrivateFieldGet(this, _TestOpsPlugin_launchTags, "f"));
|
|
383
|
-
if (!this.ciMode) {
|
|
384
|
-
return;
|
|
385
|
-
}
|
|
386
400
|
await __classPrivateFieldGet(this, _TestOpsPlugin_client, "f").startUpload(__classPrivateFieldGet(this, _TestOpsPlugin_ci, "f"));
|
|
387
401
|
}, _TestOpsPlugin_stopUpload = async function _TestOpsPlugin_stopUpload(status) {
|
|
388
|
-
if (!this.ciMode) {
|
|
389
|
-
return;
|
|
390
|
-
}
|
|
391
402
|
await __classPrivateFieldGet(this, _TestOpsPlugin_client, "f").stopUpload(__classPrivateFieldGet(this, _TestOpsPlugin_ci, "f"), status);
|
|
392
403
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { TestStepResult } from "@allurereport/core-api";
|
|
2
2
|
import { AllureStore } from "@allurereport/plugin-api";
|
|
3
|
-
import type { AttachmentsResolver, FixtureResolver, TestOpsPluginOptions } from "
|
|
3
|
+
import type { AttachmentsResolver, FixtureResolver, TestOpsPluginOptions } from "../model.js";
|
|
4
4
|
export declare const unwrapStepsAttachments: (steps: TestStepResult[]) => TestStepResult[];
|
|
5
5
|
export declare const resolvePluginOptions: (options: TestOpsPluginOptions) => Omit<TestOpsPluginOptions, "filter">;
|
|
6
6
|
export declare function attachmentsResolverFactory(store: AllureStore): AttachmentsResolver;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { CategoryDefinition } from "@allurereport/core-api";
|
|
2
|
-
import type { TestResultWithCategories, UploadCategory } from "
|
|
2
|
+
import type { TestResultWithCategories, UploadCategory } from "../model.js";
|
|
3
3
|
export declare const toUploadCategory: (tr: TestResultWithCategories, contextCategories: CategoryDefinition[]) => UploadCategory | undefined;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { buildUploadCategoryGrouping, toUploadCategoryFromContext } from "./
|
|
1
|
+
import { buildUploadCategoryGrouping, toUploadCategoryFromContext } from "./categories.js";
|
|
2
2
|
export const toUploadCategory = (tr, contextCategories) => {
|
|
3
3
|
const c = tr.categories?.[0];
|
|
4
4
|
if (c?.name) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { AttachmentLink } from "@allurereport/core-api";
|
|
2
|
-
import type { UploadAttachmentDto, UploadFixturesResultsDto, UploadResultsDto, UploadTestFixtureResultDto, UploadTestResultDto } from "
|
|
3
|
-
import type { TestOpsFixtureResult, TestOpsPluginTestResult } from "
|
|
2
|
+
import type { UploadAttachmentDto, UploadFixturesResultsDto, UploadResultsDto, UploadTestFixtureResultDto, UploadTestResultDto } from "../model.js";
|
|
3
|
+
import type { TestOpsFixtureResult, TestOpsPluginTestResult } from "../model.js";
|
|
4
4
|
export declare const uploadFilenameForLink: (link: AttachmentLink) => string | undefined;
|
|
5
5
|
export declare const toUploadAttachmentDto: (link: AttachmentLink) => UploadAttachmentDto;
|
|
6
6
|
export declare const toUploadTestResultDto: (tr: TestOpsPluginTestResult) => UploadTestResultDto;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@allurereport/plugin-testops",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.9.0",
|
|
4
4
|
"description": "Allure Plugin TestOps",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"allure",
|
|
@@ -32,10 +32,11 @@
|
|
|
32
32
|
"lint:fix": "oxlint --import-plugin --fix src test features stories"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@allurereport/ci": "3.
|
|
36
|
-
"@allurereport/core-api": "3.
|
|
37
|
-
"@allurereport/plugin-api": "3.
|
|
38
|
-
"@allurereport/reader-api": "3.
|
|
35
|
+
"@allurereport/ci": "3.9.0",
|
|
36
|
+
"@allurereport/core-api": "3.9.0",
|
|
37
|
+
"@allurereport/plugin-api": "3.9.0",
|
|
38
|
+
"@allurereport/reader-api": "3.9.0",
|
|
39
|
+
"@allurereport/service": "3.9.0",
|
|
39
40
|
"axios": "^1.15.2",
|
|
40
41
|
"form-data": "^4.0.5",
|
|
41
42
|
"lodash-es": "^4.18.1",
|
|
@@ -50,6 +51,7 @@
|
|
|
50
51
|
"@types/progress": "^2",
|
|
51
52
|
"@vitest/runner": "^2.1.9",
|
|
52
53
|
"@vitest/snapshot": "^2.1.9",
|
|
54
|
+
"allure-js-commons": "^3.3.3",
|
|
53
55
|
"allure-vitest": "^3.3.3",
|
|
54
56
|
"rimraf": "^6.0.1",
|
|
55
57
|
"typescript": "^5.6.3",
|
|
File without changes
|
|
File without changes
|