qase-javascript-commons 2.6.2 → 2.6.4

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.
Files changed (44) hide show
  1. package/changelog.md +47 -0
  2. package/dist/client/clientV1.d.ts +6 -83
  3. package/dist/client/clientV1.js +15 -549
  4. package/dist/client/clientV2.d.ts +6 -24
  5. package/dist/client/clientV2.js +8 -255
  6. package/dist/client/services/api-error-handler.d.ts +10 -0
  7. package/dist/client/services/api-error-handler.js +44 -0
  8. package/dist/client/services/attachment-service.d.ts +16 -0
  9. package/dist/client/services/attachment-service.js +209 -0
  10. package/dist/client/services/configuration-service.d.ts +12 -0
  11. package/dist/client/services/configuration-service.js +110 -0
  12. package/dist/client/services/result-transformer.d.ts +23 -0
  13. package/dist/client/services/result-transformer.js +188 -0
  14. package/dist/client/services/run-service.d.ts +17 -0
  15. package/dist/client/services/run-service.js +114 -0
  16. package/dist/client/transport/api-config-builder.d.ts +8 -0
  17. package/dist/client/transport/api-config-builder.js +96 -0
  18. package/dist/formatter/index.d.ts +1 -0
  19. package/dist/formatter/index.js +3 -1
  20. package/dist/formatter/report-serializer.d.ts +20 -0
  21. package/dist/formatter/report-serializer.js +89 -0
  22. package/dist/qase/options-resolver.d.ts +19 -0
  23. package/dist/qase/options-resolver.js +47 -0
  24. package/dist/qase/reporter-factory.d.ts +19 -0
  25. package/dist/qase/reporter-factory.js +67 -0
  26. package/dist/qase/status-processor.d.ts +17 -0
  27. package/dist/qase/status-processor.js +48 -0
  28. package/dist/qase.d.ts +17 -85
  29. package/dist/qase.js +133 -415
  30. package/dist/reporters/report-reporter.d.ts +4 -35
  31. package/dist/reporters/report-reporter.js +6 -130
  32. package/dist/reporters/shared/fallback-coordinator.d.ts +47 -0
  33. package/dist/reporters/shared/fallback-coordinator.js +119 -0
  34. package/dist/reporters/shared/testops-constants.d.ts +5 -0
  35. package/dist/reporters/shared/testops-constants.js +8 -0
  36. package/dist/reporters/shared/testops-url.d.ts +9 -0
  37. package/dist/reporters/shared/testops-url.js +17 -0
  38. package/dist/reporters/testops-multi-reporter.d.ts +0 -1
  39. package/dist/reporters/testops-multi-reporter.js +4 -9
  40. package/dist/reporters/testops-reporter.d.ts +0 -6
  41. package/dist/reporters/testops-reporter.js +7 -17
  42. package/dist/utils/token-masker.d.ts +11 -0
  43. package/dist/utils/token-masker.js +26 -0
  44. package/package.json +1 -1
@@ -3,6 +3,7 @@ import { Attachment } from '../models';
3
3
  import { WriterInterface } from '../writer';
4
4
  import { LoggerInterface } from '../utils/logger';
5
5
  import { HostData } from '../models/host-data';
6
+ import { ReportSerializerInterface } from '../formatter/report-serializer';
6
7
  /**
7
8
  * @class ReportReporter
8
9
  * @extends AbstractReporter
@@ -15,6 +16,7 @@ export declare class ReportReporter extends AbstractReporter {
15
16
  private readonly runId;
16
17
  private readonly rootSuite;
17
18
  private readonly hostData;
19
+ private readonly serializer;
18
20
  private startTime;
19
21
  /**
20
22
  * @param {LoggerInterface} logger
@@ -25,8 +27,9 @@ export declare class ReportReporter extends AbstractReporter {
25
27
  * @param {string | undefined} rootSuite
26
28
  * @param {number | undefined} runId
27
29
  * @param {HostData | undefined} hostData
30
+ * @param {ReportSerializerInterface} serializer
28
31
  */
29
- constructor(logger: LoggerInterface, writer: WriterInterface, frameworkName: string, reporterName: string, environment?: string, rootSuite?: string, runId?: number, hostData?: HostData);
32
+ constructor(logger: LoggerInterface, writer: WriterInterface, frameworkName: string, reporterName: string, environment?: string, rootSuite?: string, runId?: number, hostData?: HostData, serializer?: ReportSerializerInterface);
30
33
  /**
31
34
  * @returns {Promise<void>}
32
35
  */
@@ -44,38 +47,4 @@ export declare class ReportReporter extends AbstractReporter {
44
47
  * @returns {TestStepType[]}
45
48
  */
46
49
  private copyStepAttachments;
47
- /**
48
- * Serialize a test result to spec-compliant JSON format.
49
- * Transforms internal model fields to match the Qase Report specification.
50
- * @private
51
- */
52
- private serializeResultForReport;
53
- /**
54
- * Transform group_params Record to param_groups array of arrays.
55
- * Same logic as clientV2.ts transformGroupParams.
56
- * @private
57
- */
58
- private transformGroupParams;
59
- /**
60
- * Serialize attachment for report output (exclude size and content fields).
61
- * @private
62
- */
63
- private serializeAttachment;
64
- /**
65
- * Serialize steps recursively, transforming:
66
- * - data.data -> data.input_data (STEP-01)
67
- * - attachments -> execution.attachments (STEP-02)
68
- * @private
69
- */
70
- private serializeSteps;
71
- /**
72
- * Serialize a single step to spec-compliant format.
73
- * @private
74
- */
75
- private serializeStep;
76
- /**
77
- * Serialize step data, transforming data.data -> data.input_data for text steps.
78
- * @private
79
- */
80
- private serializeStepData;
81
50
  }
@@ -4,6 +4,7 @@ exports.ReportReporter = void 0;
4
4
  const abstract_reporter_1 = require("./abstract-reporter");
5
5
  const models_1 = require("../models");
6
6
  const hostData_1 = require("../utils/hostData");
7
+ const report_serializer_1 = require("../formatter/report-serializer");
7
8
  /**
8
9
  * @class ReportReporter
9
10
  * @extends AbstractReporter
@@ -16,6 +17,7 @@ class ReportReporter extends abstract_reporter_1.AbstractReporter {
16
17
  runId;
17
18
  rootSuite;
18
19
  hostData;
20
+ serializer;
19
21
  startTime = Date.now();
20
22
  /**
21
23
  * @param {LoggerInterface} logger
@@ -26,8 +28,9 @@ class ReportReporter extends abstract_reporter_1.AbstractReporter {
26
28
  * @param {string | undefined} rootSuite
27
29
  * @param {number | undefined} runId
28
30
  * @param {HostData | undefined} hostData
31
+ * @param {ReportSerializerInterface} serializer
29
32
  */
30
- constructor(logger, writer, frameworkName, reporterName, environment, rootSuite, runId, hostData) {
33
+ constructor(logger, writer, frameworkName, reporterName, environment, rootSuite, runId, hostData, serializer = new report_serializer_1.ReportSerializer()) {
31
34
  super(logger);
32
35
  this.writer = writer;
33
36
  this.frameworkName = frameworkName;
@@ -36,6 +39,7 @@ class ReportReporter extends abstract_reporter_1.AbstractReporter {
36
39
  this.runId = runId;
37
40
  this.rootSuite = rootSuite;
38
41
  this.hostData = hostData;
42
+ this.serializer = serializer;
39
43
  }
40
44
  /**
41
45
  * @returns {Promise<void>}
@@ -80,7 +84,7 @@ class ReportReporter extends abstract_reporter_1.AbstractReporter {
80
84
  };
81
85
  }
82
86
  // Serialize to spec-compliant format before writing
83
- const serialized = this.serializeResultForReport(result);
87
+ const serialized = this.serializer.serializeResult(result);
84
88
  await this.writer.writeTestResult(serialized);
85
89
  }
86
90
  }
@@ -158,133 +162,5 @@ class ReportReporter extends abstract_reporter_1.AbstractReporter {
158
162
  }
159
163
  return steps;
160
164
  }
161
- /**
162
- * Serialize a test result to spec-compliant JSON format.
163
- * Transforms internal model fields to match the Qase Report specification.
164
- * @private
165
- */
166
- serializeResultForReport(result) {
167
- // Transform testops_id -> testops_ids (RSLT-01)
168
- let testopsIds = null;
169
- if (result.testops_id !== null) {
170
- testopsIds = Array.isArray(result.testops_id)
171
- ? result.testops_id
172
- : [result.testops_id];
173
- }
174
- // Transform group_params -> param_groups (RSLT-02)
175
- const paramGroups = this.transformGroupParams(result.group_params);
176
- // Serialize attachments (exclude size and content fields)
177
- const attachments = result.attachments.map(att => this.serializeAttachment(att));
178
- // Serialize steps (handle data.data -> data.input_data and attachments -> execution.attachments)
179
- const steps = this.serializeSteps(result.steps);
180
- // Build spec-compliant result object
181
- const serialized = {
182
- id: result.id,
183
- title: result.title,
184
- signature: result.signature,
185
- execution: result.execution,
186
- fields: result.fields,
187
- attachments: attachments,
188
- steps: steps,
189
- params: result.params,
190
- param_groups: paramGroups,
191
- testops_ids: testopsIds,
192
- relations: result.relations,
193
- muted: result.muted,
194
- message: result.message,
195
- tags: result.tags,
196
- };
197
- // Internal-only fields are excluded: testops_id, group_params, run_id, author, testops_project_mapping, preparedAttachments
198
- return serialized;
199
- }
200
- /**
201
- * Transform group_params Record to param_groups array of arrays.
202
- * Same logic as clientV2.ts transformGroupParams.
203
- * @private
204
- */
205
- transformGroupParams(groupParams) {
206
- const keys = Object.keys(groupParams);
207
- if (keys.length === 0) {
208
- return [];
209
- }
210
- return [keys];
211
- }
212
- /**
213
- * Serialize attachment for report output (exclude size and content fields).
214
- * @private
215
- */
216
- serializeAttachment(att) {
217
- return {
218
- id: att.id,
219
- file_name: att.file_name,
220
- mime_type: att.mime_type,
221
- file_path: att.file_path,
222
- };
223
- }
224
- /**
225
- * Serialize steps recursively, transforming:
226
- * - data.data -> data.input_data (STEP-01)
227
- * - attachments -> execution.attachments (STEP-02)
228
- * @private
229
- */
230
- serializeSteps(steps) {
231
- return steps.map(step => this.serializeStep(step));
232
- }
233
- /**
234
- * Serialize a single step to spec-compliant format.
235
- * @private
236
- */
237
- serializeStep(step) {
238
- // Transform step data (handle data.data -> data.input_data for text steps)
239
- const data = this.serializeStepData(step);
240
- // Serialize step attachments
241
- const attachments = step.attachments.map(att => this.serializeAttachment(att));
242
- // Move attachments into execution.attachments (STEP-02)
243
- const execution = {
244
- ...step.execution,
245
- attachments: attachments,
246
- };
247
- // Recursively serialize nested steps
248
- const nestedSteps = this.serializeSteps(step.steps);
249
- return {
250
- id: step.id,
251
- step_type: step.step_type,
252
- data: data,
253
- parent_id: step.parent_id,
254
- execution: execution,
255
- steps: nestedSteps,
256
- // Note: attachments field is NOT at top-level in serialized output
257
- };
258
- }
259
- /**
260
- * Serialize step data, transforming data.data -> data.input_data for text steps.
261
- * @private
262
- */
263
- serializeStepData(step) {
264
- const data = { ...step.data };
265
- // For text steps, rename data.data to data.input_data (STEP-01)
266
- if (step.step_type === models_1.StepType.TEXT && 'data' in data) {
267
- const textData = data;
268
- return {
269
- action: textData.action,
270
- expected_result: textData.expected_result,
271
- input_data: textData.data, // Rename: data -> input_data
272
- };
273
- }
274
- // For gherkin steps, convert to text format (STEP-03)
275
- if (step.step_type === models_1.StepType.GHERKIN && 'keyword' in data && 'name' in data) {
276
- const gherkinData = data;
277
- return {
278
- action: `${gherkinData.keyword} ${gherkinData.name}`,
279
- expected_result: null,
280
- input_data: null, // JS GherkinData has no data field
281
- };
282
- }
283
- // For request steps, pass raw fields through (all 7 StepRequestData fields are preserved)
284
- if (step.step_type === models_1.StepType.REQUEST && 'request_method' in data) {
285
- return data;
286
- }
287
- return data;
288
- }
289
165
  }
290
166
  exports.ReportReporter = ReportReporter;
@@ -0,0 +1,47 @@
1
+ import { InternalReporterInterface } from '../abstract-reporter';
2
+ import { LoggerInterface } from '../../utils/logger';
3
+ export interface FallbackCoordinatorCallbacks {
4
+ onUpstreamFailure?: () => void;
5
+ onFallbackFailure?: () => void;
6
+ onFallbackActivated?: () => void;
7
+ onDisabled?: () => void;
8
+ }
9
+ /**
10
+ * Encapsulates the upstream → fallback → disabled cascade used across all
11
+ * `QaseReporter` lifecycle methods. Keeps both reporters' state (useFallback
12
+ * / disabled) in one place instead of spreading try/catch blocks everywhere.
13
+ */
14
+ export declare class FallbackCoordinator {
15
+ private readonly logger;
16
+ private readonly upstream;
17
+ private readonly fallback;
18
+ private readonly callbacks;
19
+ private useFallback;
20
+ private disabled;
21
+ private onDisabledFired;
22
+ constructor(logger: LoggerInterface, upstream: InternalReporterInterface | undefined, fallback: InternalReporterInterface | undefined, callbacks?: FallbackCoordinatorCallbacks);
23
+ isDisabled(): boolean;
24
+ isUsingFallback(): boolean;
25
+ setDisabled(value: boolean): void;
26
+ setUseFallback(value: boolean): void;
27
+ getUpstream(): InternalReporterInterface | undefined;
28
+ getFallback(): InternalReporterInterface | undefined;
29
+ /**
30
+ * Clear the disabled / useFallback flags so the coordinator can be reused
31
+ * for a fresh test run. Does not re-arm the `onDisabled` callback — it
32
+ * only fires once per coordinator lifetime regardless of resets.
33
+ */
34
+ reset(): void;
35
+ /**
36
+ * Run `op` on the currently active reporter. On upstream failure, switch to
37
+ * the fallback (copying accumulated results over once) and retry. On
38
+ * fallback failure, disable the coordinator.
39
+ *
40
+ * Returns the operation's result, or `undefined` if the coordinator is
41
+ * disabled or the operation produced no value.
42
+ */
43
+ run<T>(op: (reporter: InternalReporterInterface) => Promise<T>, opName: string): Promise<T | undefined>;
44
+ private disable;
45
+ private activateFallback;
46
+ private runOnFallback;
47
+ }
@@ -0,0 +1,119 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FallbackCoordinator = void 0;
4
+ /**
5
+ * Encapsulates the upstream → fallback → disabled cascade used across all
6
+ * `QaseReporter` lifecycle methods. Keeps both reporters' state (useFallback
7
+ * / disabled) in one place instead of spreading try/catch blocks everywhere.
8
+ */
9
+ class FallbackCoordinator {
10
+ logger;
11
+ upstream;
12
+ fallback;
13
+ callbacks;
14
+ useFallback = false;
15
+ disabled = false;
16
+ onDisabledFired = false;
17
+ constructor(logger, upstream, fallback, callbacks = {}) {
18
+ this.logger = logger;
19
+ this.upstream = upstream;
20
+ this.fallback = fallback;
21
+ this.callbacks = callbacks;
22
+ }
23
+ isDisabled() {
24
+ return this.disabled;
25
+ }
26
+ isUsingFallback() {
27
+ return this.useFallback;
28
+ }
29
+ setDisabled(value) {
30
+ this.disabled = value;
31
+ }
32
+ setUseFallback(value) {
33
+ this.useFallback = value;
34
+ }
35
+ getUpstream() {
36
+ return this.upstream;
37
+ }
38
+ getFallback() {
39
+ return this.fallback;
40
+ }
41
+ /**
42
+ * Clear the disabled / useFallback flags so the coordinator can be reused
43
+ * for a fresh test run. Does not re-arm the `onDisabled` callback — it
44
+ * only fires once per coordinator lifetime regardless of resets.
45
+ */
46
+ reset() {
47
+ this.disabled = false;
48
+ this.useFallback = false;
49
+ }
50
+ /**
51
+ * Run `op` on the currently active reporter. On upstream failure, switch to
52
+ * the fallback (copying accumulated results over once) and retry. On
53
+ * fallback failure, disable the coordinator.
54
+ *
55
+ * Returns the operation's result, or `undefined` if the coordinator is
56
+ * disabled or the operation produced no value.
57
+ */
58
+ async run(op, opName) {
59
+ if (this.disabled)
60
+ return undefined;
61
+ if (this.useFallback) {
62
+ return this.runOnFallback(op, opName);
63
+ }
64
+ if (!this.upstream) {
65
+ // No upstream configured — route directly to fallback without
66
+ // copying results (there are none to copy).
67
+ if (!this.fallback)
68
+ return undefined;
69
+ this.useFallback = true;
70
+ return this.runOnFallback(op, opName);
71
+ }
72
+ try {
73
+ return await op(this.upstream);
74
+ }
75
+ catch (error) {
76
+ this.logger.logError(`Unable to ${opName} in the upstream reporter:`, error);
77
+ this.callbacks.onUpstreamFailure?.();
78
+ if (!this.fallback) {
79
+ this.disable();
80
+ return undefined;
81
+ }
82
+ this.activateFallback();
83
+ return this.runOnFallback(op, opName);
84
+ }
85
+ }
86
+ disable() {
87
+ if (this.disabled)
88
+ return;
89
+ this.disabled = true;
90
+ if (!this.onDisabledFired) {
91
+ this.onDisabledFired = true;
92
+ this.callbacks.onDisabled?.();
93
+ }
94
+ }
95
+ activateFallback() {
96
+ if (this.useFallback)
97
+ return;
98
+ const results = this.upstream?.getTestResults() ?? [];
99
+ this.fallback?.setTestResults(results);
100
+ this.useFallback = true;
101
+ this.callbacks.onFallbackActivated?.();
102
+ }
103
+ async runOnFallback(op, opName) {
104
+ if (!this.fallback) {
105
+ this.disable();
106
+ return undefined;
107
+ }
108
+ try {
109
+ return await op(this.fallback);
110
+ }
111
+ catch (error) {
112
+ this.logger.logError(`Unable to ${opName} in the fallback reporter:`, error);
113
+ this.callbacks.onFallbackFailure?.();
114
+ this.disable();
115
+ return undefined;
116
+ }
117
+ }
118
+ }
119
+ exports.FallbackCoordinator = FallbackCoordinator;
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Default number of test results per upload batch.
3
+ * Used by TestOpsReporter and TestOpsMultiReporter when no explicit batch size is configured.
4
+ */
5
+ export declare const DEFAULT_BATCH_SIZE = 200;
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEFAULT_BATCH_SIZE = void 0;
4
+ /**
5
+ * Default number of test results per upload batch.
6
+ * Used by TestOpsReporter and TestOpsMultiReporter when no explicit batch size is configured.
7
+ */
8
+ exports.DEFAULT_BATCH_SIZE = 200;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Resolve the TestOps app URL from an API host.
3
+ *
4
+ * Rules:
5
+ * - undefined / empty / "qase.io" → "https://app.qase.io"
6
+ * - "api.domain" → "https://app.domain"
7
+ * - anything else → "https://<host>"
8
+ */
9
+ export declare function resolveTestOpsBaseUrl(host: string | undefined): string;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveTestOpsBaseUrl = resolveTestOpsBaseUrl;
4
+ /**
5
+ * Resolve the TestOps app URL from an API host.
6
+ *
7
+ * Rules:
8
+ * - undefined / empty / "qase.io" → "https://app.qase.io"
9
+ * - "api.domain" → "https://app.domain"
10
+ * - anything else → "https://<host>"
11
+ */
12
+ function resolveTestOpsBaseUrl(host) {
13
+ if (!host || host === 'qase.io') {
14
+ return 'https://app.qase.io';
15
+ }
16
+ return `https://${host.replace('api', 'app')}`;
17
+ }
@@ -45,6 +45,5 @@ export declare class TestOpsMultiReporter extends AbstractReporter {
45
45
  publish(): Promise<void>;
46
46
  complete(): Promise<void>;
47
47
  uploadAttachment(attachment: Attachment): Promise<string>;
48
- private getBaseUrl;
49
48
  private showLink;
50
49
  }
@@ -10,7 +10,8 @@ const abstract_reporter_1 = require("./abstract-reporter");
10
10
  const models_1 = require("../models");
11
11
  const async_mutex_1 = require("async-mutex");
12
12
  const clientV2_1 = require("../client/clientV2");
13
- const defaultChunkSize = 200;
13
+ const testops_constants_1 = require("./shared/testops-constants");
14
+ const testops_url_1 = require("./shared/testops-url");
14
15
  /**
15
16
  * Multi-project TestOps reporter. Sends test results to multiple Qase projects
16
17
  * with different test case IDs per project. Each project gets its own run.
@@ -33,8 +34,8 @@ class TestOpsMultiReporter extends abstract_reporter_1.AbstractReporter {
33
34
  showPublicReportLink;
34
35
  constructor(logger, testopsOptions, multiConfig, withState, hostData, reporterName, frameworkPackage, environment, baseUrl, batchSize, showPublicReportLink) {
35
36
  super(logger);
36
- this.baseUrl = this.getBaseUrl(baseUrl ?? testopsOptions.api?.host);
37
- this.batchSize = batchSize ?? testopsOptions.batch?.size ?? defaultChunkSize;
37
+ this.baseUrl = (0, testops_url_1.resolveTestOpsBaseUrl)(baseUrl ?? testopsOptions.api?.host);
38
+ this.batchSize = batchSize ?? testopsOptions.batch?.size ?? testops_constants_1.DEFAULT_BATCH_SIZE;
38
39
  this.showPublicReportLink = showPublicReportLink ?? testopsOptions.showPublicReportLink;
39
40
  this.defaultProject =
40
41
  multiConfig.default_project ??
@@ -288,12 +289,6 @@ class TestOpsMultiReporter extends abstract_reporter_1.AbstractReporter {
288
289
  }
289
290
  return '';
290
291
  }
291
- getBaseUrl(url) {
292
- if (!url || url === 'qase.io') {
293
- return 'https://app.qase.io';
294
- }
295
- return `https://${url.replace('api', 'app')}`;
296
- }
297
292
  showLink(projectCode, id, title) {
298
293
  const runId = this.runIds.get(projectCode);
299
294
  if (runId === undefined)
@@ -62,12 +62,6 @@ export declare class TestOpsReporter extends AbstractReporter {
62
62
  * @returns {Promise<void>}
63
63
  */
64
64
  complete(): Promise<void>;
65
- /**
66
- * @param {string | undefined} url
67
- * @return string
68
- * @private
69
- */
70
- private getBaseUrl;
71
65
  /**
72
66
  * @param {number | null} id
73
67
  * @param {string} title
@@ -9,7 +9,8 @@ const abstract_reporter_1 = require("./abstract-reporter");
9
9
  const models_1 = require("../models");
10
10
  const state_1 = require("../state/state");
11
11
  const async_mutex_1 = require("async-mutex");
12
- const defaultChunkSize = 200;
12
+ const testops_constants_1 = require("./shared/testops-constants");
13
+ const testops_url_1 = require("./shared/testops-url");
13
14
  /**
14
15
  * @class TestOpsReporter
15
16
  * @extends AbstractReporter
@@ -39,8 +40,8 @@ class TestOpsReporter extends abstract_reporter_1.AbstractReporter {
39
40
  this.withState = withState;
40
41
  this.projectCode = projectCode;
41
42
  this.showPublicReportLink = showPublicReportLink;
42
- this.baseUrl = this.getBaseUrl(baseUrl);
43
- this.batchSize = batchSize ?? defaultChunkSize;
43
+ this.baseUrl = (0, testops_url_1.resolveTestOpsBaseUrl)(baseUrl);
44
+ this.batchSize = batchSize ?? testops_constants_1.DEFAULT_BATCH_SIZE;
44
45
  this.runId = runId;
45
46
  }
46
47
  /**
@@ -128,12 +129,12 @@ class TestOpsReporter extends abstract_reporter_1.AbstractReporter {
128
129
  }
129
130
  const remainingResults = this.results.slice(this.firstIndex);
130
131
  if (this.firstIndex < this.results.length) {
131
- if (remainingResults.length <= defaultChunkSize) {
132
+ if (remainingResults.length <= testops_constants_1.DEFAULT_BATCH_SIZE) {
132
133
  await this.publishResults(remainingResults);
133
134
  return;
134
135
  }
135
- for (let i = 0; i < remainingResults.length; i += defaultChunkSize) {
136
- await this.publishResults(remainingResults.slice(i, i + defaultChunkSize));
136
+ for (let i = 0; i < remainingResults.length; i += testops_constants_1.DEFAULT_BATCH_SIZE) {
137
+ await this.publishResults(remainingResults.slice(i, i + testops_constants_1.DEFAULT_BATCH_SIZE));
137
138
  }
138
139
  }
139
140
  // Clear results because we don't need to send them again then we use Cypress reporter
@@ -164,17 +165,6 @@ class TestOpsReporter extends abstract_reporter_1.AbstractReporter {
164
165
  }
165
166
  this.logger.log((0, chalk_1.default) `{green Run ${this.runId} completed}`);
166
167
  }
167
- /**
168
- * @param {string | undefined} url
169
- * @return string
170
- * @private
171
- */
172
- getBaseUrl(url) {
173
- if (!url || url === 'qase.io') {
174
- return 'https://app.qase.io';
175
- }
176
- return `https://${url.replace('api', 'app')}`;
177
- }
178
168
  /**
179
169
  * @param {number | null} id
180
170
  * @param {string} title
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Mask a token for safe logging.
3
+ * Tokens with 7 chars or fewer are fully masked. Longer tokens expose only
4
+ * the first 3 and last 4 characters.
5
+ */
6
+ export declare function maskToken(token: string): string;
7
+ /**
8
+ * Produce a deep-cloned copy of options with `testops.api.token` masked.
9
+ * Safe to log — never mutates the input.
10
+ */
11
+ export declare function sanitizeOptionsForLog<T>(options: T): T;
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.maskToken = maskToken;
4
+ exports.sanitizeOptionsForLog = sanitizeOptionsForLog;
5
+ /**
6
+ * Mask a token for safe logging.
7
+ * Tokens with 7 chars or fewer are fully masked. Longer tokens expose only
8
+ * the first 3 and last 4 characters.
9
+ */
10
+ function maskToken(token) {
11
+ if (token.length <= 7) {
12
+ return '*'.repeat(token.length);
13
+ }
14
+ return `${token.slice(0, 3)}****${token.slice(-4)}`;
15
+ }
16
+ /**
17
+ * Produce a deep-cloned copy of options with `testops.api.token` masked.
18
+ * Safe to log — never mutates the input.
19
+ */
20
+ function sanitizeOptionsForLog(options) {
21
+ const sanitized = JSON.parse(JSON.stringify(options));
22
+ if (sanitized.testops?.api?.token) {
23
+ sanitized.testops.api.token = maskToken(sanitized.testops.api.token);
24
+ }
25
+ return sanitized;
26
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qase-javascript-commons",
3
- "version": "2.6.2",
3
+ "version": "2.6.4",
4
4
  "description": "Qase JS Reporters",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",