qase-javascript-commons 2.2.18 → 2.3.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.
Files changed (41) hide show
  1. package/changelog.md +21 -15
  2. package/dist/client/clientV1.d.ts +31 -0
  3. package/dist/client/clientV1.js +177 -0
  4. package/dist/client/clientV2.d.ts +26 -0
  5. package/dist/client/clientV2.js +197 -0
  6. package/dist/client/dateUtils.d.ts +2 -0
  7. package/dist/client/dateUtils.js +21 -0
  8. package/dist/client/interface.d.ts +6 -0
  9. package/dist/client/interface.js +2 -0
  10. package/dist/config/config-validation-schema.js +0 -22
  11. package/dist/env/env-enum.d.ts +1 -2
  12. package/dist/env/env-enum.js +0 -1
  13. package/dist/env/env-to-config.js +0 -1
  14. package/dist/env/env-type.d.ts +2 -3
  15. package/dist/env/env-validation-schema.js +0 -4
  16. package/dist/formatter/json-formatter.d.ts +2 -2
  17. package/dist/formatter/jsonp-formatter.d.ts +2 -2
  18. package/dist/models/attachment.d.ts +2 -2
  19. package/dist/models/config/TestOpsOptionsType.d.ts +25 -0
  20. package/dist/models/config/TestOpsOptionsType.js +2 -0
  21. package/dist/models/execution-sum.d.ts +2 -2
  22. package/dist/models/host-data.d.ts +2 -1
  23. package/dist/models/report.d.ts +3 -3
  24. package/dist/models/short-result.d.ts +2 -2
  25. package/dist/models/stats.d.ts +2 -2
  26. package/dist/models/test-result.d.ts +6 -6
  27. package/dist/options/options-type.d.ts +2 -6
  28. package/dist/qase.d.ts +1 -0
  29. package/dist/qase.js +16 -53
  30. package/dist/reporters/index.d.ts +1 -1
  31. package/dist/reporters/testops-reporter.d.ts +8 -161
  32. package/dist/reporters/testops-reporter.js +24 -537
  33. package/dist/state/state.js +1 -0
  34. package/dist/steps/step.d.ts +1 -1
  35. package/dist/steps/step.js +2 -2
  36. package/dist/utils/hostData.js +6 -3
  37. package/dist/utils/logger.js +17 -23
  38. package/dist/writer/fs-writer.d.ts +3 -3
  39. package/package.json +3 -2
  40. package/dist/utils/custom-boundary.d.ts +0 -26
  41. package/dist/utils/custom-boundary.js +0 -30
@@ -4,13 +4,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.TestOpsReporter = void 0;
7
- const fs_1 = require("fs");
8
7
  const chalk_1 = __importDefault(require("chalk"));
9
- const qaseio_1 = require("qaseio");
10
8
  const abstract_reporter_1 = require("./abstract-reporter");
11
9
  const models_1 = require("../models");
12
- const qase_error_1 = require("../utils/qase-error");
13
- const axios_1 = require("axios");
14
10
  const state_1 = require("../state/state");
15
11
  const async_mutex_1 = require("async-mutex");
16
12
  const defaultChunkSize = 200;
@@ -21,120 +17,29 @@ const defaultChunkSize = 200;
21
17
  class TestOpsReporter extends abstract_reporter_1.AbstractReporter {
22
18
  api;
23
19
  withState;
24
- /**
25
- * @type {Record<TestStatusEnum, string>}
26
- */
27
- static statusMap = {
28
- [models_1.TestStatusEnum.passed]: 'passed',
29
- [models_1.TestStatusEnum.failed]: 'failed',
30
- [models_1.TestStatusEnum.skipped]: 'skipped',
31
- [models_1.TestStatusEnum.disabled]: 'disabled',
32
- [models_1.TestStatusEnum.blocked]: 'blocked',
33
- [models_1.TestStatusEnum.invalid]: 'invalid',
34
- };
35
- /**
36
- * @type {Record<StepStatusEnum, ResultStepStatus>}
37
- */
38
- static stepStatusMap = {
39
- [models_1.StepStatusEnum.passed]: qaseio_1.ResultStepStatus.PASSED,
40
- [models_1.StepStatusEnum.failed]: qaseio_1.ResultStepStatus.FAILED,
41
- [models_1.StepStatusEnum.blocked]: qaseio_1.ResultStepStatus.BLOCKED,
42
- [models_1.StepStatusEnum.skipped]: qaseio_1.ResultStepStatus.SKIPPED,
43
- };
44
- /**
45
- * @type {Record<StepStatusEnum, ResultStepStatus>}
46
- */
47
- static stepStatusMapV1 = {
48
- [models_1.StepStatusEnum.passed]: qaseio_1.TestStepResultCreateStatusEnum.PASSED,
49
- [models_1.StepStatusEnum.failed]: qaseio_1.TestStepResultCreateStatusEnum.FAILED,
50
- [models_1.StepStatusEnum.blocked]: qaseio_1.TestStepResultCreateStatusEnum.BLOCKED,
51
- [models_1.StepStatusEnum.skipped]: qaseio_1.TestStepResultCreateStatusEnum.BLOCKED,
52
- };
53
- /**
54
- * @type {string}
55
- * @private
56
- */
57
- baseUrl;
58
- /**
59
- * @type {string}
60
- * @private
61
- */
62
20
  projectCode;
63
- /**
64
- * @type {boolean | undefined}
65
- * @private
66
- */
67
- isUploadAttachments;
68
- /**
69
- * @type {TestOpsRunType}
70
- * @private
71
- */
72
- run;
73
- /**
74
- * @type { string | undefined}
75
- * @private
76
- */
77
- environment;
78
- /**
79
- * @type { number | undefined}
80
- * @private
81
- */
82
- planId;
83
- /**
84
- * @type {TestResultType[]}
85
- * @private
86
- */
21
+ baseUrl;
87
22
  batchSize;
88
- /**
89
- * @type {boolean | undefined}
90
- * @private
91
- */
92
- useV2;
93
- /**
94
- * @type {boolean | undefined}
95
- * @private
96
- */
97
- defect;
98
- /**
99
- * @type {string | undefined}
100
- * @private
101
- */
102
- rootSuite;
103
- /**
104
- * @type {number}
105
- * @private
106
- */
23
+ runId;
107
24
  firstIndex = 0;
108
- /**
109
- * @type {boolean}
110
- * @private
111
- */
112
25
  isTestRunReady = false;
113
26
  mutex = new async_mutex_1.Mutex();
114
27
  /**
115
28
  * @param {LoggerInterface} logger
116
- * @param {ReporterOptionsType & TestOpsOptionsType} options
117
- * @param {QaseApiInterface} api
29
+ * @param {IClient} api
118
30
  * @param {boolean} withState
119
- * @param {string | undefined} environment
120
- * @param {string | undefined} rootSuite
31
+ * @param {string} projectCode
121
32
  * @param {string | undefined} baseUrl
33
+ * @param {number | undefined} batchSize
122
34
  */
123
- constructor(logger, options, api, withState, environment, rootSuite, baseUrl) {
124
- const { project, uploadAttachments, run, plan, } = options;
35
+ constructor(logger, api, withState, projectCode, baseUrl, batchSize, runId) {
125
36
  super(logger);
126
37
  this.api = api;
127
38
  this.withState = withState;
39
+ this.projectCode = projectCode;
128
40
  this.baseUrl = this.getBaseUrl(baseUrl);
129
- this.projectCode = project;
130
- this.isUploadAttachments = uploadAttachments;
131
- this.run = { complete: true, ...run };
132
- this.environment = environment;
133
- this.planId = plan.id;
134
- this.batchSize = options.batch?.size ?? defaultChunkSize;
135
- this.useV2 = options.useV2 ?? true;
136
- this.defect = options.defect ?? false;
137
- this.rootSuite = rootSuite;
41
+ this.batchSize = batchSize ?? defaultChunkSize;
42
+ this.runId = runId;
138
43
  }
139
44
  /**
140
45
  * @returns {Promise<void>}
@@ -174,33 +79,11 @@ class TestOpsReporter extends abstract_reporter_1.AbstractReporter {
174
79
  * @returns {Promise<void>}
175
80
  */
176
81
  async checkOrCreateTestRun() {
177
- if (this.run.id !== undefined) {
178
- this.isTestRunReady = true;
179
- return;
180
- }
181
- this.logger.logDebug('Creating test run');
182
- let environmentId;
183
- if (this.environment != undefined) {
184
- try {
185
- const { data } = await this.api.environment.getEnvironments(this.projectCode, undefined, this.environment, 100);
186
- const env = data.result?.entities?.find((env) => env.slug === this.environment);
187
- if (env) {
188
- environmentId = env.id;
189
- }
190
- }
191
- catch (error) {
192
- throw this.processError(error, 'Error on getting environments');
193
- }
194
- }
195
- const { result } = await this.createRun(this.run.title, this.run.description, environmentId);
196
- if (!result?.id) {
197
- throw new Error('Cannot create run.');
198
- }
199
- this.logger.logDebug(`Test run created: ${result.id}`);
200
- this.run.id = result.id;
201
- process.env['QASE_TESTOPS_RUN_ID'] = String(result.id);
82
+ const runId = await this.api.createRun();
83
+ this.runId = runId;
84
+ process.env['QASE_TESTOPS_RUN_ID'] = String(runId);
202
85
  if (this.withState) {
203
- state_1.StateManager.setRunId(result.id);
86
+ state_1.StateManager.setRunId(runId);
204
87
  }
205
88
  this.isTestRunReady = true;
206
89
  }
@@ -210,36 +93,10 @@ class TestOpsReporter extends abstract_reporter_1.AbstractReporter {
210
93
  * @private
211
94
  */
212
95
  async publishResults(testResults) {
213
- if (this.useV2) {
214
- const results = [];
215
- for (const result of testResults) {
216
- const resultCreateV2 = await this.transformTestResult(result);
217
- results.push(resultCreateV2);
218
- }
219
- try {
220
- await this.api.result.createResultsV2(this.projectCode, this.run.id, {
221
- results: results,
222
- });
223
- }
224
- catch (error) {
225
- throw this.processError(error, 'Error on uploading results', results);
226
- }
227
- }
228
- else {
229
- const results = [];
230
- for (const result of testResults) {
231
- const resultCreate = await this.transformTestResultV1(result);
232
- results.push(resultCreate);
233
- }
234
- try {
235
- await this.api.results.createResultBulk(this.projectCode, this.run.id, {
236
- results: results,
237
- });
238
- }
239
- catch (error) {
240
- throw this.processError(error, 'Error on uploading results', results);
241
- }
96
+ if (!this.runId) {
97
+ throw new Error('Run ID is not set');
242
98
  }
99
+ await this.api.uploadResults(this.runId, testResults);
243
100
  this.logger.logDebug(`Results sent to Qase: ${testResults.length}`);
244
101
  }
245
102
  /**
@@ -280,384 +137,11 @@ class TestOpsReporter extends abstract_reporter_1.AbstractReporter {
280
137
  * @returns {Promise<void>}
281
138
  */
282
139
  async complete() {
283
- if (!this.run.complete) {
284
- return;
285
- }
286
- try {
287
- await this.api.runs.completeRun(this.projectCode, this.run.id);
288
- this.logger.log((0, chalk_1.default) `{green Run ${this.run.id} completed}`);
289
- }
290
- catch (error) {
291
- throw this.processError(error, 'Error on completing run');
292
- }
293
- const runUrl = `${this.baseUrl}/run/${this.projectCode}/dashboard/${this.run.id}`;
294
- this.logger.log((0, chalk_1.default) `{blue Test run link: ${runUrl}}`);
295
- }
296
- /**
297
- * @param {TestResultType} result
298
- * @returns Promise<ResultCreateV2>
299
- * @private
300
- */
301
- async transformTestResult(result) {
302
- const attachments = await this.uploadAttachments(result.attachments);
303
- const steps = await this.transformSteps(result.steps, result.title);
304
- const param = {};
305
- for (const key in result.params) {
306
- const value = result.params[key];
307
- if (!value) {
308
- continue;
309
- }
310
- param[key] = value;
311
- }
312
- const group_params = [];
313
- const keys = Object.keys(result.group_params);
314
- if (keys.length > 0) {
315
- group_params.push(keys);
316
- }
317
- for (const key in result.group_params) {
318
- const value = result.group_params[key];
319
- if (!value) {
320
- continue;
321
- }
322
- param[key] = value;
323
- }
324
- const model = {
325
- title: result.title,
326
- execution: this.getExecution(result.execution),
327
- testops_id: Array.isArray(result.testops_id) ? null : result.testops_id,
328
- attachments: attachments,
329
- steps: steps,
330
- params: param,
331
- param_groups: group_params,
332
- relations: this.getRelation(result.relations),
333
- message: result.message,
334
- fields: result.fields,
335
- defect: this.defect,
336
- };
337
- this.logger.logDebug(`Transformed result: ${JSON.stringify(model)}`);
338
- return model;
339
- }
340
- /**
341
- * @param {TestResultType} result
342
- * @returns Promise<ResultCreate>
343
- * @private
344
- */
345
- async transformTestResultV1(result) {
346
- const attachments = await this.uploadAttachments(result.attachments);
347
- const steps = await this.transformStepsV1(result.steps, result.title);
348
- const param = {};
349
- for (const key in result.params) {
350
- const value = result.params[key];
351
- if (!value) {
352
- continue;
353
- }
354
- param[key] = value;
355
- }
356
- const group_params = [];
357
- const keys = Object.keys(result.group_params);
358
- if (keys.length > 0) {
359
- group_params.push(keys);
360
- }
361
- for (const key in result.group_params) {
362
- const value = result.group_params[key];
363
- if (!value) {
364
- continue;
365
- }
366
- param[key] = value;
367
- }
368
- const resultCreate = {
369
- attachments: attachments,
370
- comment: result.message,
371
- defect: this.defect,
372
- param: param,
373
- param_groups: group_params,
374
- stacktrace: result.execution.stacktrace,
375
- start_time: result.execution.start_time ? result.execution.start_time | 0 : null,
376
- status: result.execution.status,
377
- steps: steps,
378
- time: result.execution.end_time,
379
- time_ms: result.execution.duration,
380
- };
381
- const id = Array.isArray(result.testops_id) ? null : result.testops_id;
382
- if (id) {
383
- resultCreate.case_id = id;
384
- }
385
- const rootSuite = this.rootSuite ? `${this.rootSuite}\t` : '';
386
- resultCreate.case = {
387
- title: result.title,
388
- suite_title: result.relations?.suite ? `${rootSuite}${result.relations.suite.data.map((suite) => suite.title).join('\t')}` : rootSuite,
389
- description: result.fields['description'] ?? null,
390
- postconditions: result.fields['postconditions'] ?? null,
391
- preconditions: result.fields['preconditions'] ?? null,
392
- };
393
- if (result.fields['severity']) {
394
- resultCreate.case.severity = result.fields['severity'];
395
- }
396
- if (result.fields['priority']) {
397
- resultCreate.case.priority = result.fields['priority'];
398
- }
399
- if (result.fields['layer']) {
400
- resultCreate.case.layer = result.fields['layer'];
401
- }
402
- if (result.fields['author']) {
403
- const resp = await this.api.authors.getAuthors(result.fields['author']);
404
- if (resp.data.result?.entities && resp.data.result.entities.length > 0) {
405
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
406
- resultCreate.author_id = resp.data.result.entities[0]?.author_id ?? null;
407
- }
408
- }
409
- this.logger.logDebug(`Transformed result: ${JSON.stringify(resultCreate)}`);
410
- return resultCreate;
411
- }
412
- /**
413
- * @returns {ResultExecution}
414
- * @private
415
- * @param {TestExecution} exec
416
- */
417
- getExecution(exec) {
418
- return {
419
- status: TestOpsReporter.statusMap[exec.status],
420
- start_time: exec.start_time,
421
- end_time: exec.end_time,
422
- duration: exec.duration,
423
- stacktrace: exec.stacktrace,
424
- thread: exec.thread,
425
- };
426
- }
427
- /**
428
- * @param {Relation | null} relation
429
- * @returns {ResultRelations}
430
- * @private
431
- */
432
- getRelation(relation) {
433
- if (!relation?.suite) {
434
- if (this.rootSuite == undefined) {
435
- return {};
436
- }
437
- return {
438
- suite: {
439
- data: [
440
- {
441
- public_id: null,
442
- title: this.rootSuite,
443
- },
444
- ],
445
- },
446
- };
447
- }
448
- const suiteData = [];
449
- if (this.rootSuite != undefined) {
450
- suiteData.push({
451
- public_id: null,
452
- title: this.rootSuite,
453
- });
140
+ if (!this.runId) {
141
+ throw new Error('Run ID is not set');
454
142
  }
455
- for (const data of relation.suite.data) {
456
- suiteData.push({
457
- public_id: null,
458
- title: data.title,
459
- });
460
- }
461
- return {
462
- suite: {
463
- data: suiteData,
464
- },
465
- };
466
- }
467
- /**
468
- * @param {TestStepType[]} steps
469
- * @param testTitle
470
- * @returns Promise<ResultStep[]>
471
- * @private
472
- */
473
- async transformSteps(steps, testTitle) {
474
- const resultsSteps = [];
475
- for (const step of steps) {
476
- const attachmentHashes = await this.uploadAttachments(step.attachments);
477
- const resultStep = {
478
- data: {
479
- action: '',
480
- },
481
- execution: {
482
- status: TestOpsReporter.stepStatusMap[step.execution.status],
483
- attachments: attachmentHashes,
484
- },
485
- };
486
- if (step.step_type === models_1.StepType.TEXT) {
487
- if ('action' in step.data && resultStep.data != undefined) {
488
- if (step.data.action === '') {
489
- this.logEmptyStep(testTitle);
490
- resultStep.data.action = 'Unnamed step';
491
- }
492
- else {
493
- resultStep.data.action = step.data.action;
494
- }
495
- }
496
- if ('expected_result' in step.data && resultStep.data != undefined && step.data.expected_result != null) {
497
- resultStep.data.expected_result = step.data.expected_result;
498
- }
499
- if ('data' in step.data && resultStep.data != undefined && step.data.data != null) {
500
- resultStep.data.input_data = step.data.data;
501
- }
502
- }
503
- if (step.step_type === models_1.StepType.GHERKIN) {
504
- if ('keyword' in step.data && resultStep.data != undefined) {
505
- resultStep.data.action = step.data.keyword;
506
- }
507
- }
508
- if (step.steps.length > 0) {
509
- resultStep.steps = await this.transformSteps(step.steps, testTitle);
510
- }
511
- resultsSteps.push(resultStep);
512
- }
513
- return resultsSteps;
514
- }
515
- /**
516
- * @param {TestStepType[]} steps
517
- * @param testTitle
518
- * @returns Promise<TestStepResultCreate[]>
519
- * @private
520
- */
521
- async transformStepsV1(steps, testTitle) {
522
- const resultsSteps = [];
523
- for (const step of steps) {
524
- const attachmentHashes = await this.uploadAttachments(step.attachments);
525
- const resultStep = {
526
- status: TestOpsReporter.stepStatusMapV1[step.execution.status],
527
- attachments: attachmentHashes,
528
- };
529
- if (step.step_type === models_1.StepType.TEXT) {
530
- if ('action' in step.data) {
531
- if (step.data.action === '') {
532
- this.logEmptyStep(testTitle);
533
- resultStep.action = 'Unnamed step';
534
- }
535
- else {
536
- resultStep.action = step.data.action;
537
- }
538
- }
539
- }
540
- if (step.step_type === models_1.StepType.GHERKIN) {
541
- if ('keyword' in step.data) {
542
- resultStep.action = step.data.keyword;
543
- }
544
- }
545
- if (step.steps.length > 0) {
546
- resultStep.steps = await this.transformStepsV1(step.steps, testTitle);
547
- }
548
- resultsSteps.push(resultStep);
549
- }
550
- return resultsSteps;
551
- }
552
- logEmptyStep(testTitle) {
553
- this.logger.log((0, chalk_1.default) `{magenta Test '${testTitle}' has empty action in step. The reporter will mark this step as unnamed step.}`);
554
- }
555
- /**
556
- * @param {string} title
557
- * @param {string} description
558
- * @param {number | undefined} environment
559
- * @returns {Promise<IdResponse>}
560
- * @private
561
- */
562
- async createRun(title, description, environment) {
563
- try {
564
- const runObject = {
565
- title,
566
- description,
567
- is_autotest: true,
568
- cases: [],
569
- start_time: this.getDate(),
570
- };
571
- if (environment !== undefined) {
572
- runObject.environment_id = environment;
573
- }
574
- if (this.planId) {
575
- runObject.plan_id = this.planId;
576
- }
577
- const { data } = await this.api.runs.createRun(this.projectCode, runObject);
578
- return data;
579
- }
580
- catch (error) {
581
- throw this.processError(error, 'Error on creating run');
582
- }
583
- }
584
- /**
585
- * @returns {string}
586
- * @private
587
- */
588
- getDate() {
589
- const date = new Date();
590
- date.setSeconds(-10);
591
- const year = date.getUTCFullYear();
592
- const month = ('0' + (date.getUTCMonth() + 1).toString()).slice(-2); // Months are zero indexed, so we add 1
593
- const day = ('0' + date.getUTCDate().toString()).slice(-2);
594
- const hours = ('0' + date.getUTCHours().toString()).slice(-2);
595
- const minutes = ('0' + date.getUTCMinutes().toString()).slice(-2);
596
- const seconds = ('0' + date.getUTCSeconds().toString()).slice(-2);
597
- return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
598
- }
599
- /**
600
- * @returns {Promise<void>}
601
- * @private
602
- */
603
- async uploadAttachments(attachments) {
604
- if (!this.isUploadAttachments) {
605
- return [];
606
- }
607
- const acc = [];
608
- for (const attachment of attachments) {
609
- this.logger.logDebug(`Uploading attachment: ${attachment.file_path ?? attachment.file_name}`);
610
- try {
611
- let data;
612
- if (attachment.file_path) {
613
- data = { name: attachment.file_name, value: (0, fs_1.createReadStream)(attachment.file_path) };
614
- }
615
- else {
616
- if (typeof attachment.content === 'string') {
617
- data = { name: attachment.file_name, value: Buffer.from(attachment.content) };
618
- }
619
- else {
620
- data = { name: attachment.file_name, value: attachment.content };
621
- }
622
- }
623
- const response = await this.api.attachments.uploadAttachment(this.projectCode, [data]);
624
- if (response.data.result?.[0]?.hash != undefined) {
625
- acc.push(response.data.result[0].hash);
626
- }
627
- }
628
- catch (error) {
629
- this.logger.logError('Cannot upload attachment:', error);
630
- }
631
- }
632
- return acc;
633
- }
634
- /**
635
- * Process error and throw QaseError
636
- * @param {Error | AxiosError} error
637
- * @param {string} message
638
- * @param {object} model
639
- * @private
640
- */
641
- processError(error, message, model) {
642
- if (!(0, axios_1.isAxiosError)(error)) {
643
- return new qase_error_1.QaseError(message, { cause: error });
644
- }
645
- const err = error;
646
- if (err.response?.status === 401) {
647
- return new qase_error_1.QaseError(message + ': \n Unauthorized. Please check your API token. Maybe it is expired or invalid.');
648
- }
649
- if (err.response?.status === 404) {
650
- return new qase_error_1.QaseError(message + ': Not found.');
651
- }
652
- if (err.response?.status === 403) {
653
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access,@typescript-eslint/restrict-template-expressions
654
- return new qase_error_1.QaseError(`${message}: ${error.response?.data?.errorMessage}`);
655
- }
656
- if (err.response?.status === 400 || err.response?.status === 422) {
657
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access,@typescript-eslint/restrict-template-expressions
658
- return new qase_error_1.QaseError(message + ': \n Bad request: \n' + `${JSON.stringify(err.response?.data)}` + '. \n Body: \n ' + JSON.stringify(model));
659
- }
660
- return new qase_error_1.QaseError(message, { cause: err });
143
+ await this.api.completeRun(this.runId);
144
+ this.logger.log((0, chalk_1.default) `{green Run ${this.runId} completed}`);
661
145
  }
662
146
  /**
663
147
  * @param {string | undefined} url
@@ -677,7 +161,10 @@ class TestOpsReporter extends abstract_reporter_1.AbstractReporter {
677
161
  * @private
678
162
  */
679
163
  prepareFailedTestLink(id, title) {
680
- const baseLink = `${this.baseUrl}/run/${this.projectCode}/dashboard/${this.run.id}?source=logs&status=%5B2%5D&search=`;
164
+ if (!this.runId) {
165
+ throw new Error('Run ID is not set');
166
+ }
167
+ const baseLink = `${this.baseUrl}/run/${this.projectCode}/dashboard/${this.runId}?source=logs&status=%5B2%5D&search=`;
681
168
  if (id) {
682
169
  return `${baseLink}${id}`;
683
170
  }
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.StateManager = void 0;
7
7
  const fs_1 = require("fs");
8
8
  const path_1 = __importDefault(require("path"));
9
+ // eslint-disable-next-line @typescript-eslint/no-extraneous-class
9
10
  class StateManager {
10
11
  static statePath = path_1.default.resolve(__dirname, 'reporterState.json');
11
12
  static getState() {
@@ -1,5 +1,5 @@
1
1
  import { Attachment, TestStepType } from '../models';
2
- export type StepFunction<T = any> = (this: QaseStep, step: QaseStep) => T | Promise<T>;
2
+ export type StepFunction<T = unknown> = (this: QaseStep, step: QaseStep) => T | Promise<T>;
3
3
  export declare class QaseStep {
4
4
  name: string;
5
5
  attachments: Attachment[];
@@ -71,7 +71,7 @@ class QaseStep {
71
71
  step.steps = this.steps;
72
72
  await messageEmitter(step);
73
73
  }
74
- catch (e) {
74
+ catch (error) {
75
75
  step.execution = {
76
76
  start_time: startDate,
77
77
  end_time: new Date().getTime(),
@@ -81,7 +81,7 @@ class QaseStep {
81
81
  step.attachments = this.attachments;
82
82
  step.steps = this.steps;
83
83
  await messageEmitter(step);
84
- throw e;
84
+ throw error;
85
85
  }
86
86
  }
87
87
  }
@@ -28,6 +28,7 @@ const os = __importStar(require("os"));
28
28
  const cp = __importStar(require("child_process"));
29
29
  const fs = __importStar(require("fs"));
30
30
  const path = __importStar(require("path"));
31
+ const child_process_1 = require("child_process");
31
32
  /**
32
33
  * Gets detailed OS information based on the platform
33
34
  * @returns {string} Detailed OS information
@@ -121,7 +122,7 @@ function getPackageVersion(packageName) {
121
122
  // Try using npm list as fallback with recursive search
122
123
  let output = null;
123
124
  try {
124
- output = execCommand(`npm list --depth=10 --json`);
125
+ output = (0, child_process_1.execSync)(`npm list --depth=10 --json`, { stdio: "pipe" }).toString();
125
126
  if (!output)
126
127
  return null;
127
128
  }
@@ -166,7 +167,8 @@ function getHostInfo(framework, reporterName) {
166
167
  framework: getPackageVersion(framework) ?? '',
167
168
  reporter: getPackageVersion(reporterName) ?? '',
168
169
  commons: getPackageVersion('qase-javascript-commons') ?? '',
169
- apiClient: getPackageVersion('qaseio') ?? '',
170
+ apiClientV1: getPackageVersion('qase-api-client') ?? '',
171
+ apiClientV2: getPackageVersion('qase-api-v2-client') ?? '',
170
172
  };
171
173
  }
172
174
  catch (error) {
@@ -181,7 +183,8 @@ function getHostInfo(framework, reporterName) {
181
183
  framework: '',
182
184
  reporter: '',
183
185
  commons: '',
184
- apiClient: '',
186
+ apiClientV1: '',
187
+ apiClientV2: '',
185
188
  };
186
189
  }
187
190
  }