@allurereport/plugin-testops 3.8.2 → 3.10.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 CHANGED
@@ -12,7 +12,26 @@
12
12
 
13
13
  ## Overview
14
14
 
15
- The plugin creates a new launch in Allure TestOps with all the tests data from the current report.
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, _TestOpsClient_oauthToken, _TestOpsClient_client, _TestOpsClient_launch, _TestOpsClient_session, _TestOpsClient_uploadInProgress, _TestOpsClient_uploadLimit, _TestOpsClient_namedEnvsIdsByEnv, _TestOpsClient_postTestResultsChunk, _TestOpsClient_uploadChunkAttachmentsAndFixtures, _TestOpsClient_uploadAttachmentsForResult, _TestOpsClient_uploadFixturesForResult;
13
- import axios, { AxiosError, isAxiosError } from "axios";
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, axios.create({
52
- baseURL: params.baseUrl,
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, _TestOpsClient_client, "f").defaults.baseURL).toString();
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 { data } = await __classPrivateFieldGet(this, _TestOpsClient_client, "f").post("/api/launch/category/bulk", body, {
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
- projectId: __classPrivateFieldGet(this, _TestOpsClient_projectId, "f"),
137
- ci: {
138
- name: ci.type,
139
- },
140
- job: {
141
- name: ci.jobUid,
142
- uid: ci.jobUid,
143
- },
144
- jobRun: {
145
- uid: ci.jobRunUid,
146
- },
147
- launch: {
148
- id: __classPrivateFieldGet(this, _TestOpsClient_launch, "f").id,
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
- jobRunUid: ci.jobRunUid,
160
- jobUid: ci.jobUid,
161
- projectId: __classPrivateFieldGet(this, _TestOpsClient_projectId, "f"),
162
- status,
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 { data } = await __classPrivateFieldGet(this, _TestOpsClient_client, "f").post("/api/launch", {
170
- name: launchName,
171
- projectId: __classPrivateFieldGet(this, _TestOpsClient_projectId, "f"),
172
- autoclose: true,
173
- external: true,
174
- tags: launchTags.map((tag) => ({ name: tag })),
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 { data } = await __classPrivateFieldGet(this, _TestOpsClient_client, "f").post("/api/upload/session", {
184
- launchId: __classPrivateFieldGet(this, _TestOpsClient_launch, "f").id,
185
- environment: Object.entries(environment).map(([key, value]) => ({
186
- key,
187
- value: String(value),
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 { data } = await __classPrivateFieldGet(this, _TestOpsClient_client, "f").post("/api/launch/named-env/bulk", {
215
- launchId: __classPrivateFieldGet(this, _TestOpsClient_launch, "f").id,
216
- items: environments.map(({ id, name }) => ({
217
- externalId: id,
218
- name,
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", formData, {
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
- launchId: __classPrivateFieldGet(this, _TestOpsClient_launch, "f").id,
276
- items: errors,
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
- launchId: __classPrivateFieldGet(this, _TestOpsClient_launch, "f").id,
349
- items,
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
- _TestOpsClient_logger = new WeakMap(), _TestOpsClient_accessToken = new WeakMap(), _TestOpsClient_projectId = new WeakMap(), _TestOpsClient_oauthToken = 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) {
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 { data } = await __classPrivateFieldGet(this, _TestOpsClient_client, "f").post("/api/upload/test-result", body, {
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`, formData, {
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`, body);
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", _Logger_isLogLevel).call(this, "silent")) {
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", _Logger_isLogLevel).call(this, "silent")) {
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 ciMode(): boolean | undefined;
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
@@ -1,43 +1,44 @@
1
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
2
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
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
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
5
+ };
1
6
  var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
2
7
  if (kind === "m") throw new TypeError("Private method is not writable");
3
8
  if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
4
9
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
5
10
  return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
6
11
  };
7
- var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
8
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
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
- return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
- };
12
- var _TestOpsPlugin_instances, _TestOpsPlugin_logger, _TestOpsPlugin_ci, _TestOpsPlugin_client, _TestOpsPlugin_enabled, _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;
12
+ var _TestOpsPlugin_instances, _TestOpsPlugin_logger, _TestOpsPlugin_ci, _TestOpsPlugin_client, _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
- import { detect } from "@allurereport/ci";
14
+ import { detect, isLocalCiDescriptor } from "@allurereport/ci";
15
15
  import { getWorstStatus } from "@allurereport/core-api";
16
16
  import { createPluginSummary } from "@allurereport/plugin-api";
17
17
  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 { toUploadCategory } from "./uploadCategory.js";
22
- import { uploadFilenameForLink } from "./uploaderDto.js";
23
- import { attachmentsResolverFactory, fixturesResolverFactory, resolvePluginOptions, unwrapStepsAttachments, } from "./utils.js";
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) {
27
27
  _TestOpsPlugin_instances.add(this);
28
28
  this.options = options;
29
29
  _TestOpsPlugin_logger.set(this, new Logger("TestOpsPlugin"));
30
- _TestOpsPlugin_ci.set(this, void 0);
30
+ _TestOpsPlugin_ci.set(this, detect());
31
31
  _TestOpsPlugin_client.set(this, void 0);
32
- _TestOpsPlugin_enabled.set(this, false);
33
32
  _TestOpsPlugin_launchName.set(this, "");
34
33
  _TestOpsPlugin_launchTags.set(this, []);
35
34
  _TestOpsPlugin_uploadedTestResultsIds.set(this, new Set());
36
- _TestOpsPlugin_autocloseLaunch.set(this, void 0);
35
+ _TestOpsPlugin_autocloseLaunch.set(this, false);
36
+ if (isLocalCiDescriptor(__classPrivateFieldGet(this, _TestOpsPlugin_ci, "f")) && !this.isOverridenByEnv) {
37
+ __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.`);
38
+ return;
39
+ }
37
40
  const { accessToken, endpoint, projectId, launchName, launchTags, autocloseLaunch = true, } = resolvePluginOptions(options);
38
- __classPrivateFieldSet(this, _TestOpsPlugin_ci, detect(), "f");
39
41
  if ([accessToken, endpoint, projectId].every(Boolean)) {
40
- __classPrivateFieldSet(this, _TestOpsPlugin_enabled, true, "f");
41
42
  __classPrivateFieldSet(this, _TestOpsPlugin_client, new TestOpsClient({
42
43
  baseUrl: endpoint,
43
44
  accessToken,
@@ -57,32 +58,50 @@ export class TestOpsPlugin {
57
58
  __classPrivateFieldGet(this, _TestOpsPlugin_logger, "f").warn(`Allure TestOps ${bold("project ID")} is missing. Please provide a valid project ID in the plugin options.`);
58
59
  }
59
60
  }
60
- get ciMode() {
61
- return __classPrivateFieldGet(this, _TestOpsPlugin_ci, "f") && __classPrivateFieldGet(this, _TestOpsPlugin_ci, "f").type !== "local";
61
+ get isOverridenByEnv() {
62
+ const isEnabled = (value) => {
63
+ if (!value) {
64
+ return false;
65
+ }
66
+ return ["true", "1"].includes(value);
67
+ };
68
+ return isEnabled(env.ALLURE_TESTOPS_ENABLED) || isEnabled(env.CI);
69
+ }
70
+ get enabled() {
71
+ if (!(__classPrivateFieldGet(this, _TestOpsPlugin_client, "f") instanceof TestOpsClient)) {
72
+ return false;
73
+ }
74
+ if (this.isOverridenByEnv) {
75
+ return true;
76
+ }
77
+ if (!__classPrivateFieldGet(this, _TestOpsPlugin_ci, "f") || __classPrivateFieldGet(this, _TestOpsPlugin_ci, "f").type === "local") {
78
+ return false;
79
+ }
80
+ return true;
62
81
  }
63
82
  async start(context, store) {
64
- if (!__classPrivateFieldGet(this, _TestOpsPlugin_enabled, "f")) {
83
+ if (!this.enabled) {
65
84
  return;
66
85
  }
67
86
  __classPrivateFieldGet(this, _TestOpsPlugin_logger, "f").verbose("Starting upload…");
68
87
  await __classPrivateFieldGet(this, _TestOpsPlugin_instances, "m", _TestOpsPlugin_startUpload).call(this);
69
- await __classPrivateFieldGet(this, _TestOpsPlugin_instances, "m", _TestOpsPlugin_upload).call(this, store, { issueNewToken: false, context, stage: "start" });
88
+ await __classPrivateFieldGet(this, _TestOpsPlugin_instances, "m", _TestOpsPlugin_upload).call(this, store, { context, stage: "start" });
70
89
  __classPrivateFieldGet(this, _TestOpsPlugin_logger, "f").info(`Allure TestOps Launch: ${__classPrivateFieldGet(this, _TestOpsPlugin_client, "f").launchUrl}`);
71
90
  }
72
91
  async update(context, store) {
73
- if (!__classPrivateFieldGet(this, _TestOpsPlugin_enabled, "f")) {
92
+ if (!this.enabled) {
74
93
  return;
75
94
  }
76
95
  __classPrivateFieldGet(this, _TestOpsPlugin_logger, "f").verbose("Updating (uploading new results)…");
77
96
  await __classPrivateFieldGet(this, _TestOpsPlugin_instances, "m", _TestOpsPlugin_upload).call(this, store, { context, stage: "update" });
78
97
  }
79
98
  async done(context, store) {
80
- if (!__classPrivateFieldGet(this, _TestOpsPlugin_enabled, "f")) {
99
+ if (!this.enabled) {
81
100
  return;
82
101
  }
83
102
  const allTrs = await store.allTestResults({
84
103
  filter: this.options.filter,
85
- includeHidden: false,
104
+ includeRetries: false,
86
105
  });
87
106
  const worstStatus = getWorstStatus(allTrs.map(({ status }) => status));
88
107
  __classPrivateFieldGet(this, _TestOpsPlugin_logger, "f").verbose("Finalizing upload…");
@@ -110,7 +129,7 @@ export class TestOpsPlugin {
110
129
  __classPrivateFieldGet(this, _TestOpsPlugin_logger, "f").info(`Upload finished. Allure TestOps Launch: ${__classPrivateFieldGet(this, _TestOpsPlugin_client, "f").launchUrl}`);
111
130
  }
112
131
  async info(context, store) {
113
- if (!__classPrivateFieldGet(this, _TestOpsPlugin_enabled, "f")) {
132
+ if (!this.enabled) {
114
133
  return undefined;
115
134
  }
116
135
  if (!__classPrivateFieldGet(this, _TestOpsPlugin_client, "f").launchUrl) {
@@ -131,7 +150,7 @@ export class TestOpsPlugin {
131
150
  return summary;
132
151
  }
133
152
  }
134
- _TestOpsPlugin_logger = new WeakMap(), _TestOpsPlugin_ci = new WeakMap(), _TestOpsPlugin_client = new WeakMap(), _TestOpsPlugin_enabled = 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) {
153
+ _TestOpsPlugin_logger = new WeakMap(), _TestOpsPlugin_ci = new WeakMap(), _TestOpsPlugin_client = 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
154
  const results = await store.qualityGateResults();
136
155
  const uniqueResults = uniqBy(results.filter(({ success }) => !success), ({ rule, environment }) => `${rule}-${environment}`);
137
156
  if (uniqueResults.length === 0) {
@@ -255,7 +274,7 @@ _TestOpsPlugin_logger = new WeakMap(), _TestOpsPlugin_ci = new WeakMap(), _TestO
255
274
  }
256
275
  __classPrivateFieldGet(this, _TestOpsPlugin_logger, "f").info(`Uploaded ${uploadedCount} ${uploadedCount > 1 ? "test results" : "test result"}`);
257
276
  }, _TestOpsPlugin_upload = async function _TestOpsPlugin_upload(store, options = {}) {
258
- const { issueNewToken = true, context, stage } = options;
277
+ const { context, stage } = options;
259
278
  const trsToUpload = await __classPrivateFieldGet(this, _TestOpsPlugin_instances, "m", _TestOpsPlugin_trsToUpload).call(this, store);
260
279
  if (trsToUpload.length === 0) {
261
280
  if (stage == "update") {
@@ -266,10 +285,6 @@ _TestOpsPlugin_logger = new WeakMap(), _TestOpsPlugin_ci = new WeakMap(), _TestO
266
285
  }
267
286
  return;
268
287
  }
269
- if (issueNewToken) {
270
- __classPrivateFieldGet(this, _TestOpsPlugin_logger, "f").verbose("Issuing new OAuth token");
271
- await __classPrivateFieldGet(this, _TestOpsPlugin_client, "f").issueOauthToken();
272
- }
273
288
  await __classPrivateFieldGet(this, _TestOpsPlugin_client, "f").createSession(env);
274
289
  await __classPrivateFieldGet(this, _TestOpsPlugin_instances, "m", _TestOpsPlugin_uploadGlobalAttachments).call(this, store);
275
290
  await __classPrivateFieldGet(this, _TestOpsPlugin_instances, "m", _TestOpsPlugin_uploadGlobalErrors).call(this, store);
@@ -289,7 +304,7 @@ _TestOpsPlugin_logger = new WeakMap(), _TestOpsPlugin_ci = new WeakMap(), _TestO
289
304
  }
290
305
  return filter(tr);
291
306
  },
292
- includeHidden: false,
307
+ includeRetries: false,
293
308
  });
294
309
  return filteredTrs;
295
310
  }, _TestOpsPlugin_enrichWithCategories = async function _TestOpsPlugin_enrichWithCategories(store, trs, contextCategories) {
@@ -378,15 +393,8 @@ _TestOpsPlugin_logger = new WeakMap(), _TestOpsPlugin_ci = new WeakMap(), _TestO
378
393
  }
379
394
  }
380
395
  }, _TestOpsPlugin_startUpload = async function _TestOpsPlugin_startUpload() {
381
- await __classPrivateFieldGet(this, _TestOpsPlugin_client, "f").issueOauthToken();
382
396
  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
397
  await __classPrivateFieldGet(this, _TestOpsPlugin_client, "f").startUpload(__classPrivateFieldGet(this, _TestOpsPlugin_ci, "f"));
387
398
  }, _TestOpsPlugin_stopUpload = async function _TestOpsPlugin_stopUpload(status) {
388
- if (!this.ciMode) {
389
- return;
390
- }
391
399
  await __classPrivateFieldGet(this, _TestOpsPlugin_client, "f").stopUpload(__classPrivateFieldGet(this, _TestOpsPlugin_ci, "f"), status);
392
400
  };
@@ -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 "./model.js";
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 "./model.js";
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 "./utils/categories.js";
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 "./model.js";
3
- import type { TestOpsFixtureResult, TestOpsPluginTestResult } from "./model.js";
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.8.2",
3
+ "version": "3.10.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.8.2",
36
- "@allurereport/core-api": "3.8.2",
37
- "@allurereport/plugin-api": "3.8.2",
38
- "@allurereport/reader-api": "3.8.2",
35
+ "@allurereport/ci": "3.10.0",
36
+ "@allurereport/core-api": "3.10.0",
37
+ "@allurereport/plugin-api": "3.10.0",
38
+ "@allurereport/reader-api": "3.10.0",
39
+ "@allurereport/service": "3.10.0",
39
40
  "axios": "^1.15.2",
40
41
  "form-data": "^4.0.5",
41
42
  "lodash-es": "^4.18.1",
@@ -46,13 +47,14 @@
46
47
  "devDependencies": {
47
48
  "@types/d3-shape": "^3.1.6",
48
49
  "@types/lodash-es": "^4",
49
- "@types/node": "^20.17.9",
50
+ "@types/node": "^20",
50
51
  "@types/progress": "^2",
51
- "@vitest/runner": "^2.1.9",
52
+ "@vitest/runner": "^2",
52
53
  "@vitest/snapshot": "^2.1.9",
53
- "allure-vitest": "^3.3.3",
54
- "rimraf": "^6.0.1",
55
- "typescript": "^5.6.3",
56
- "vitest": "^2.1.9"
54
+ "allure-js-commons": "^3",
55
+ "allure-vitest": "^3",
56
+ "rimraf": "^6",
57
+ "typescript": "^5",
58
+ "vitest": "^4.1.0"
57
59
  }
58
60
  }
File without changes
File without changes