jest-qase-reporter 2.0.2 → 2.0.3

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
@@ -59,7 +59,6 @@ module.exports = {
59
59
  Now, run the Jest tests as usual.
60
60
  Test results will be reported to a new test run in Qase.
61
61
 
62
-
63
62
  ```console
64
63
  $ npx jest
65
64
  Determining test suites to run...
@@ -79,32 +78,49 @@ and suites from your test data.
79
78
  But if necessary, you can independently register the ID of already
80
79
  existing test cases from TMS before the executing tests. For example:
81
80
 
82
- ```typescript
83
- const { qase } = require("jest-qase-reporter/jest");
81
+ ### Metadata
84
82
 
85
- describe('My First Test', () => {
86
- test(qase([1,2], 'Several ids'), () => {
87
- expect(true).toBe(true);
88
- })
83
+ - `qase.title` - set the title of the test case
84
+ - `qase.fields` - set the fields of the test case
85
+ - `qase.suite` - set the suite of the test case
86
+ - `qase.comment` - set the comment of the test case
87
+ - `qase.parameters` - set the parameters of the test case
88
+ - `qase.groupParameters` - set the group parameters of the test case
89
+ - `qase.ignore` - ignore the test case in Qase. The test will be executed, but the results will not be sent to Qase.
90
+ - `qase.step` - create a step in the test case
91
+ - `qase.attach` - attach a file to the test case
89
92
 
90
- test(qase(3, 'Correct test'), () => {
91
- expect(true).toBe(true);
92
- })
93
-
94
- test.skip(qase("4", 'Skipped test'), () => {
95
- expect(true).toBe(true);
96
- })
93
+ ```typescript
94
+ const { qase } = require('jest-qase-reporter/jest');
97
95
 
98
- test(qase(["5", "6"], 'Failed test'), () => {
99
- expect(true).toBe(false);
100
- })
96
+ describe('My First Test', () => {
97
+ test(qase([1, 2], 'Several ids'), () => {
98
+ expect(true).toBe(true);
99
+ });
100
+
101
+ test(qase(3, 'Correct test'), () => {
102
+ qase.title('Title');
103
+ expect(true).toBe(true);
104
+ });
105
+
106
+ test.skip(qase('4', 'Skipped test'), () => {
107
+ expect(true).toBe(true);
108
+ });
109
+
110
+ test(qase(['5', '6'], 'Failed test'), () => {
111
+ expect(true).toBe(false);
112
+ });
101
113
  });
102
114
  ```
115
+
103
116
  To run tests and create a test run, execute the command (for example from folder examples):
117
+
104
118
  ```bash
105
119
  QASE_MODE=testops npx jest
106
120
  ```
121
+
107
122
  or
123
+
108
124
  ```bash
109
125
  npm test
110
126
  ```
@@ -125,7 +141,7 @@ Reporter options (* - required):
125
141
 
126
142
  - `mode` - `testops`/`off` Enables reporter, default - `off`
127
143
  - `debug` - Enables debug logging, default - `false`
128
- - `environment` - To execute with the sending of the envinroment information
144
+ - `environment` - To execute with the sending of the envinroment information
129
145
  - *`testops.api.token` - Token for API access, you can find more information
130
146
  [here](https://developers.qase.io/#authentication)
131
147
  - *`testops.project` - Qase project code, for example, in https://app.qase.io/project/DEMO the code is `DEMO`
@@ -167,7 +183,7 @@ Supported ENV variables:
167
183
 
168
184
  - `QASE_MODE` - Same as `mode`
169
185
  - `QASE_DEBUG` - Same as `debug`
170
- - `QASE_ENVIRONMENT` - Same as `environment`
186
+ - `QASE_ENVIRONMENT` - Same as `environment`
171
187
  - `QASE_TESTOPS_API_TOKEN` - Same as `testops.api.token`
172
188
  - `QASE_TESTOPS_PROJECT` - Same as `testops.project`
173
189
  - `QASE_TESTOPS_RUN_ID` - Pass Run ID from ENV and override reporter option `testops.run.id`
@@ -176,7 +192,8 @@ Supported ENV variables:
176
192
 
177
193
  ## Requirements
178
194
 
179
- We maintain the reporter on LTS versions of Node. You can find the current versions by following the [link](https://nodejs.org/en/about/releases/)
195
+ We maintain the reporter on LTS versions of Node. You can find the current versions by following
196
+ the [link](https://nodejs.org/en/about/releases/)
180
197
 
181
198
  `jest >= 28.0.0`
182
199
 
package/changelog.md CHANGED
@@ -1,9 +1,46 @@
1
+ # jest-qase-reporter@2.0.3
2
+
3
+ ## What's new
4
+
5
+ Added the ability to specify a test metadata in tests:
6
+
7
+ - `qase.title` - set the test title
8
+ - `qase.fields` - set the test fields
9
+ - `qase.suite` - set the test suite
10
+ - `qase.comment` - set the test comment
11
+ - `qase.parameters` - set the test parameters
12
+ - `qase.groupParameters` - set the test group parameters
13
+ - `qase.ignore` - ignore the test in Qase
14
+ - `qase.attach` - attach a file to the test
15
+ - `qase.steps` - add the test steps
16
+
17
+ ```ts
18
+ const { qase } = require('jest-qase-reporter/jest');
19
+
20
+ test('test', () => {
21
+ qase.title('Title');
22
+ qase.fields({ custom_field: 'value' });
23
+ qase.suite('Suite');
24
+ qase.comment('Comment');
25
+ qase.parameters({ param01: 'value' });
26
+ qase.groupParameters({ param02: 'value' });
27
+ qase.ignore();
28
+ qase.attach({ name: 'attachment.txt', content: 'Hello, world!', type: 'text/plain' });
29
+
30
+ qase.step('Step 1', () => {
31
+ expect(true).toBe(true);
32
+ });
33
+
34
+ expect(true).toBe(true);
35
+ });
36
+ ```
37
+
1
38
  # jest-qase-reporter@2.0.1
2
39
 
3
40
  ## What's new
4
41
 
5
42
  Fixed a bug when a test was marked as skipped.
6
- This reporter has uploaded this test as blocked.
43
+ This reporter has uploaded this test as blocked.
7
44
  Right now the reporter will upload this test as skipped.
8
45
 
9
46
  # jest-qase-reporter@2.0.0
@@ -0,0 +1,23 @@
1
+ import { JestQaseReporter } from './reporter';
2
+ import { Attachment, TestStepType } from 'qase-javascript-commons';
3
+ declare global {
4
+ namespace NodeJS {
5
+ interface Global {
6
+ Qase: Qase;
7
+ }
8
+ }
9
+ }
10
+ export declare class Qase {
11
+ private reporter;
12
+ constructor(reporter: JestQaseReporter);
13
+ title(title: string): void;
14
+ ignore(): void;
15
+ comment(value: string): void;
16
+ suite(value: string): void;
17
+ fields(values: Record<string, string>): void;
18
+ parameters(values: Record<string, string>): void;
19
+ groupParams(values: Record<string, string>): void;
20
+ step(step: TestStepType): void;
21
+ attachment(attachment: Attachment): void;
22
+ }
23
+ export {};
package/dist/global.js ADDED
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Qase = void 0;
4
+ class Qase {
5
+ constructor(reporter) {
6
+ this.reporter = reporter;
7
+ }
8
+ title(title) {
9
+ this.reporter.addTitle(title);
10
+ }
11
+ ignore() {
12
+ this.reporter.addIgnore();
13
+ }
14
+ comment(value) {
15
+ this.reporter.addComment(value);
16
+ }
17
+ suite(value) {
18
+ this.reporter.addSuite(value);
19
+ }
20
+ fields(values) {
21
+ const stringRecord = {};
22
+ for (const [key, value] of Object.entries(values)) {
23
+ stringRecord[String(key)] = String(value);
24
+ }
25
+ this.reporter.addFields(stringRecord);
26
+ }
27
+ parameters(values) {
28
+ const stringRecord = {};
29
+ for (const [key, value] of Object.entries(values)) {
30
+ stringRecord[String(key)] = String(value);
31
+ }
32
+ this.reporter.addParameters(stringRecord);
33
+ }
34
+ groupParams(values) {
35
+ const stringRecord = {};
36
+ for (const [key, value] of Object.entries(values)) {
37
+ stringRecord[String(key)] = String(value);
38
+ }
39
+ this.reporter.addGroupParams(stringRecord);
40
+ }
41
+ step(step) {
42
+ this.reporter.addStep(step);
43
+ }
44
+ attachment(attachment) {
45
+ this.reporter.addAttachment(attachment);
46
+ }
47
+ }
48
+ exports.Qase = Qase;
package/dist/jest.d.ts CHANGED
@@ -1 +1,102 @@
1
- export declare const qase: (caseId: number | string | number[] | string[], name: string) => string;
1
+ import { StepFunction } from './step';
2
+ export declare const qase: {
3
+ (caseId: number | string | number[] | string[], name: string): string;
4
+ /**
5
+ * Set a title for the test case
6
+ * @param {string} value
7
+ * @example
8
+ * test('test', () => {
9
+ * qase.title("Title");
10
+ * expect(true).toBe(true);
11
+ * });
12
+ */
13
+ title(value: string): void;
14
+ /**
15
+ * Ignore the test case
16
+ * @example
17
+ * test('test', () => {
18
+ * qase.ignore();
19
+ * expect(true).toBe(true);
20
+ * });
21
+ */
22
+ ignore(): void;
23
+ /**
24
+ * Add a comment to the test case
25
+ * @param {string} value
26
+ * @example
27
+ * test('test', () => {
28
+ * qase.comment("Comment");
29
+ * expect(true).toBe(true);
30
+ * });
31
+ */
32
+ comment(value: string): void;
33
+ /**
34
+ * Set a suite for the test case
35
+ * @param {string} value
36
+ * @example
37
+ * test('test', () => {
38
+ * qase.suite("Suite");
39
+ * expect(true).toBe(true);
40
+ * });
41
+ */
42
+ suite(value: string): void;
43
+ /**
44
+ * Set fields for the test case
45
+ * @param {Record<string, string>} values
46
+ * @example
47
+ * test('test', () => {
48
+ * qase.fields({field: "value"});
49
+ * expect(true).toBe(true);
50
+ * });
51
+ */
52
+ fields(values: Record<string, string>): void;
53
+ /**
54
+ * Set parameters for the test case
55
+ * @param {Record<string, string>} values
56
+ * @example
57
+ * test('test', () => {
58
+ * qase.parameters({param: "value"});
59
+ * expect(true).toBe(true);
60
+ * });
61
+ */
62
+ parameters(values: Record<string, string>): void;
63
+ /**
64
+ * Set group params for the test case
65
+ * @param {Record<string, string>} values
66
+ * @example
67
+ * test('test', () => {
68
+ * qase.groupParameters({param: "value"});
69
+ * expect(true).toBe(true);
70
+ * });
71
+ */
72
+ groupParameters(values: Record<string, string>): void;
73
+ /**
74
+ * Add a step to the test case
75
+ * @param name
76
+ * @param body
77
+ * @example
78
+ * test('test', () => {
79
+ * qase.step("Step", () => {
80
+ * expect(true).toBe(true);
81
+ * });
82
+ * expect(true).toBe(true);
83
+ * });
84
+ */
85
+ step(name: string, body: StepFunction): Promise<void>;
86
+ /**
87
+ * Add an attachment to the test case
88
+ * @param attach
89
+ * @example
90
+ * test('test', () => {
91
+ * qase.attach({ name: 'attachment.txt', content: 'Hello, world!', type: 'text/plain' });
92
+ * qase.attach({ paths: ['/path/to/file', '/path/to/another/file']});
93
+ * expect(true).toBe(true);
94
+ * });
95
+ */
96
+ attach(attach: {
97
+ name?: string;
98
+ type?: string;
99
+ content?: string;
100
+ paths?: string[];
101
+ }): void;
102
+ };
package/dist/jest.js CHANGED
@@ -1,8 +1,152 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.qase = void 0;
7
+ const step_1 = require("./step");
8
+ const path_1 = __importDefault(require("path"));
9
+ const qase_javascript_commons_1 = require("qase-javascript-commons");
10
+ const uuid_1 = require("uuid");
4
11
  const qase = (caseId, name) => {
5
12
  const caseIds = Array.isArray(caseId) ? caseId : [caseId];
6
13
  return `${name} (Qase ID: ${caseIds.join(',')})`;
7
14
  };
8
15
  exports.qase = qase;
16
+ /**
17
+ * Set a title for the test case
18
+ * @param {string} value
19
+ * @example
20
+ * test('test', () => {
21
+ * qase.title("Title");
22
+ * expect(true).toBe(true);
23
+ * });
24
+ */
25
+ exports.qase.title = (value) => {
26
+ global.Qase.title(value);
27
+ };
28
+ /**
29
+ * Ignore the test case
30
+ * @example
31
+ * test('test', () => {
32
+ * qase.ignore();
33
+ * expect(true).toBe(true);
34
+ * });
35
+ */
36
+ exports.qase.ignore = () => {
37
+ global.Qase.ignore();
38
+ };
39
+ /**
40
+ * Add a comment to the test case
41
+ * @param {string} value
42
+ * @example
43
+ * test('test', () => {
44
+ * qase.comment("Comment");
45
+ * expect(true).toBe(true);
46
+ * });
47
+ */
48
+ exports.qase.comment = (value) => {
49
+ global.Qase.comment(value);
50
+ };
51
+ /**
52
+ * Set a suite for the test case
53
+ * @param {string} value
54
+ * @example
55
+ * test('test', () => {
56
+ * qase.suite("Suite");
57
+ * expect(true).toBe(true);
58
+ * });
59
+ */
60
+ exports.qase.suite = (value) => {
61
+ global.Qase.suite(value);
62
+ };
63
+ /**
64
+ * Set fields for the test case
65
+ * @param {Record<string, string>} values
66
+ * @example
67
+ * test('test', () => {
68
+ * qase.fields({field: "value"});
69
+ * expect(true).toBe(true);
70
+ * });
71
+ */
72
+ exports.qase.fields = (values) => {
73
+ global.Qase.fields(values);
74
+ };
75
+ /**
76
+ * Set parameters for the test case
77
+ * @param {Record<string, string>} values
78
+ * @example
79
+ * test('test', () => {
80
+ * qase.parameters({param: "value"});
81
+ * expect(true).toBe(true);
82
+ * });
83
+ */
84
+ exports.qase.parameters = (values) => {
85
+ global.Qase.parameters(values);
86
+ };
87
+ /**
88
+ * Set group params for the test case
89
+ * @param {Record<string, string>} values
90
+ * @example
91
+ * test('test', () => {
92
+ * qase.groupParameters({param: "value"});
93
+ * expect(true).toBe(true);
94
+ * });
95
+ */
96
+ exports.qase.groupParameters = (values) => {
97
+ global.Qase.groupParams(values);
98
+ };
99
+ /**
100
+ * Add a step to the test case
101
+ * @param name
102
+ * @param body
103
+ * @example
104
+ * test('test', () => {
105
+ * qase.step("Step", () => {
106
+ * expect(true).toBe(true);
107
+ * });
108
+ * expect(true).toBe(true);
109
+ * });
110
+ */
111
+ exports.qase.step = async (name, body) => {
112
+ const runningStep = new step_1.QaseStep(name);
113
+ // eslint-disable-next-line @typescript-eslint/require-await
114
+ await runningStep.run(body, async (step) => global.Qase.step(step));
115
+ };
116
+ /**
117
+ * Add an attachment to the test case
118
+ * @param attach
119
+ * @example
120
+ * test('test', () => {
121
+ * qase.attach({ name: 'attachment.txt', content: 'Hello, world!', type: 'text/plain' });
122
+ * qase.attach({ paths: ['/path/to/file', '/path/to/another/file']});
123
+ * expect(true).toBe(true);
124
+ * });
125
+ */
126
+ exports.qase.attach = (attach) => {
127
+ if (attach.paths) {
128
+ for (const file of attach.paths) {
129
+ const attachmentName = path_1.default.basename(file);
130
+ const contentType = (0, qase_javascript_commons_1.getMimeTypes)(file);
131
+ global.Qase.attachment({
132
+ file_path: file,
133
+ size: 0,
134
+ id: (0, uuid_1.v4)(),
135
+ file_name: attachmentName,
136
+ mime_type: contentType,
137
+ content: '',
138
+ });
139
+ }
140
+ return;
141
+ }
142
+ if (attach.content) {
143
+ global.Qase.attachment({
144
+ file_path: null,
145
+ size: attach.content.length,
146
+ id: (0, uuid_1.v4)(),
147
+ file_name: attach.name ?? 'attachment',
148
+ mime_type: attach.type ?? 'application/octet-stream',
149
+ content: attach.content,
150
+ });
151
+ }
152
+ };
@@ -0,0 +1,12 @@
1
+ import { Attachment, TestStepType } from 'qase-javascript-commons';
2
+ export interface Metadata {
3
+ title: string | undefined;
4
+ ignore: boolean;
5
+ comment: string | undefined;
6
+ suite: string | undefined;
7
+ fields: Record<string, string>;
8
+ parameters: Record<string, string>;
9
+ groupParams: Record<string, string>;
10
+ steps: TestStepType[];
11
+ attachments: Attachment[];
12
+ }
package/dist/models.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,6 +1,6 @@
1
1
  import { Config, Reporter, Test, TestResult } from '@jest/reporters';
2
- import { Status } from '@jest/test-result';
3
- import { ConfigLoader, ConfigType, TestStatusEnum } from 'qase-javascript-commons';
2
+ import { Status, TestCaseResult } from '@jest/test-result';
3
+ import { Attachment, ConfigLoader, ConfigType, TestStatusEnum, TestStepType } from 'qase-javascript-commons';
4
4
  export type JestQaseOptionsType = ConfigType;
5
5
  /**
6
6
  * @class JestQaseReporter
@@ -17,7 +17,7 @@ export declare class JestQaseReporter implements Reporter {
17
17
  static qaseIdRegExp: RegExp;
18
18
  /**
19
19
  * @param {string} title
20
- * @returns {any}
20
+ * @returns {number[]}
21
21
  * @private
22
22
  */
23
23
  private static getCaseId;
@@ -26,6 +26,11 @@ export declare class JestQaseReporter implements Reporter {
26
26
  * @private
27
27
  */
28
28
  private reporter;
29
+ /**
30
+ * @type {Metadata}
31
+ * @private
32
+ */
33
+ private metadata;
29
34
  /**
30
35
  * @param {Config.GlobalConfig} _
31
36
  * @param {JestQaseOptionsType} options
@@ -37,6 +42,7 @@ export declare class JestQaseReporter implements Reporter {
37
42
  * @see {Reporter.onRunStart}
38
43
  */
39
44
  onRunStart(): void;
45
+ onTestCaseResult(test: Test, testCaseResult: TestCaseResult): void;
40
46
  /**
41
47
  * @param {Test} _
42
48
  * @param {TestResult} result
@@ -68,4 +74,26 @@ export declare class JestQaseReporter implements Reporter {
68
74
  * @private
69
75
  */
70
76
  private getCurrentTestPath;
77
+ addTitle(title: string): void;
78
+ addComment(comment: string): void;
79
+ addSuite(suite: string): void;
80
+ addFields(fields: Record<string, string>): void;
81
+ addParameters(parameters: Record<string, string>): void;
82
+ addGroupParams(groupParams: Record<string, string>): void;
83
+ addIgnore(): void;
84
+ addStep(step: TestStepType): void;
85
+ addAttachment(attachment: Attachment): void;
86
+ private cleanMetadata;
87
+ /**
88
+ * @param {AssertionResult} value
89
+ * @param {string} path
90
+ * @private
91
+ * @returns {TestResultType}
92
+ */
93
+ private convertToResult;
94
+ /**
95
+ * @returns {Metadata}
96
+ * @private
97
+ */
98
+ private createEmptyMetadata;
71
99
  }
package/dist/reporter.js CHANGED
@@ -8,6 +8,7 @@ const lodash_has_1 = __importDefault(require("lodash.has"));
8
8
  const lodash_get_1 = __importDefault(require("lodash.get"));
9
9
  const uuid_1 = require("uuid");
10
10
  const qase_javascript_commons_1 = require("qase-javascript-commons");
11
+ const global_1 = require("./global");
11
12
  /**
12
13
  * @class JestQaseReporter
13
14
  * @implements Reporter
@@ -15,7 +16,7 @@ const qase_javascript_commons_1 = require("qase-javascript-commons");
15
16
  class JestQaseReporter {
16
17
  /**
17
18
  * @param {string} title
18
- * @returns {any}
19
+ * @returns {number[]}
19
20
  * @private
20
21
  */
21
22
  static getCaseId(title) {
@@ -36,6 +37,8 @@ class JestQaseReporter {
36
37
  frameworkName: 'jest',
37
38
  reporterName: 'jest-qase-reporter',
38
39
  });
40
+ global.Qase = new global_1.Qase(this);
41
+ this.metadata = this.createEmptyMetadata();
39
42
  }
40
43
  /**
41
44
  * @see {Reporter.onRunStart}
@@ -43,49 +46,59 @@ class JestQaseReporter {
43
46
  onRunStart() {
44
47
  void this.reporter.startTestRun();
45
48
  }
49
+ onTestCaseResult(test, testCaseResult) {
50
+ if (this.metadata.ignore) {
51
+ this.cleanMetadata();
52
+ return;
53
+ }
54
+ const result = this.convertToResult(testCaseResult, test.path);
55
+ if (this.metadata.title) {
56
+ result.title = this.metadata.title;
57
+ }
58
+ if (this.metadata.comment) {
59
+ result.message = this.metadata.comment;
60
+ }
61
+ if (this.metadata.suite) {
62
+ result.relations = {
63
+ suite: {
64
+ data: [
65
+ {
66
+ title: this.metadata.suite,
67
+ public_id: null,
68
+ },
69
+ ],
70
+ },
71
+ };
72
+ }
73
+ if (Object.keys(this.metadata.fields).length > 0) {
74
+ result.fields = this.metadata.fields;
75
+ }
76
+ if (Object.keys(this.metadata.parameters).length > 0) {
77
+ result.params = this.metadata.parameters;
78
+ }
79
+ if (Object.keys(this.metadata.groupParams).length > 0) {
80
+ result.group_params = this.metadata.groupParams;
81
+ }
82
+ if (this.metadata.steps.length > 0) {
83
+ result.steps = this.metadata.steps;
84
+ }
85
+ if (this.metadata.attachments.length > 0) {
86
+ result.attachments = this.metadata.attachments;
87
+ }
88
+ this.cleanMetadata();
89
+ void this.reporter.addTestResult(result);
90
+ }
46
91
  /**
47
92
  * @param {Test} _
48
93
  * @param {TestResult} result
49
94
  */
50
95
  onTestResult(_, result) {
51
- console.log(result);
52
- result.testResults.forEach(({ title, fullName, ancestorTitles, status, duration, failureMessages, failureDetails, }) => {
53
- let error;
54
- if (status === 'failed') {
55
- error = new Error(failureDetails.map((item) => {
56
- if ((0, lodash_has_1.default)(item, 'matcherResult.message')) {
57
- return String((0, lodash_get_1.default)(item, 'matcherResult.message'));
58
- }
59
- return 'Runtime exception';
60
- }).join('\n\n'));
61
- error.stack = failureMessages.join('\n\n');
96
+ result.testResults.forEach((value) => {
97
+ if (value.status !== 'pending') {
98
+ return;
62
99
  }
63
- const ids = JestQaseReporter.getCaseId(title);
64
- const filePath = this.getCurrentTestPath(result.testFilePath);
65
- void this.reporter.addTestResult({
66
- attachments: [],
67
- author: null,
68
- execution: {
69
- status: JestQaseReporter.statusMap[status],
70
- start_time: null,
71
- end_time: null,
72
- duration: duration ?? 0,
73
- stacktrace: error?.stack ?? null,
74
- thread: null,
75
- },
76
- fields: {},
77
- message: error?.message ?? null,
78
- muted: false,
79
- params: {},
80
- group_params: {},
81
- relations: this.getRelations(filePath, ancestorTitles),
82
- run_id: null,
83
- signature: this.getSignature(filePath, fullName, ids),
84
- steps: [],
85
- testops_id: ids.length > 0 ? ids : null,
86
- id: (0, uuid_1.v4)(),
87
- title: title,
88
- });
100
+ const model = this.convertToResult(value, result.testFilePath);
101
+ void this.reporter.addTestResult(model);
89
102
  });
90
103
  }
91
104
  /**
@@ -146,6 +159,97 @@ class JestQaseReporter {
146
159
  const executionPath = process.cwd() + '/';
147
160
  return fullPath.replace(executionPath, '');
148
161
  }
162
+ addTitle(title) {
163
+ this.metadata.title = title;
164
+ }
165
+ addComment(comment) {
166
+ this.metadata.comment = comment;
167
+ }
168
+ addSuite(suite) {
169
+ this.metadata.suite = suite;
170
+ }
171
+ addFields(fields) {
172
+ this.metadata.fields = fields;
173
+ }
174
+ addParameters(parameters) {
175
+ this.metadata.parameters = parameters;
176
+ }
177
+ addGroupParams(groupParams) {
178
+ this.metadata.groupParams = groupParams;
179
+ }
180
+ addIgnore() {
181
+ this.metadata.ignore = true;
182
+ }
183
+ addStep(step) {
184
+ this.metadata.steps.push(step);
185
+ }
186
+ addAttachment(attachment) {
187
+ this.metadata.attachments.push(attachment);
188
+ }
189
+ cleanMetadata() {
190
+ this.metadata = this.createEmptyMetadata();
191
+ }
192
+ /**
193
+ * @param {AssertionResult} value
194
+ * @param {string} path
195
+ * @private
196
+ * @returns {TestResultType}
197
+ */
198
+ convertToResult(value, path) {
199
+ let error;
200
+ if (value.status === 'failed') {
201
+ error = new Error(value.failureDetails.map((item) => {
202
+ if ((0, lodash_has_1.default)(item, 'matcherResult.message')) {
203
+ return String((0, lodash_get_1.default)(item, 'matcherResult.message'));
204
+ }
205
+ return 'Runtime exception';
206
+ }).join('\n\n'));
207
+ error.stack = value.failureMessages.join('\n\n');
208
+ }
209
+ const ids = JestQaseReporter.getCaseId(value.title);
210
+ const filePath = this.getCurrentTestPath(path);
211
+ return {
212
+ attachments: [],
213
+ author: null,
214
+ execution: {
215
+ status: JestQaseReporter.statusMap[value.status],
216
+ start_time: null,
217
+ end_time: null,
218
+ duration: value.duration ?? 0,
219
+ stacktrace: error?.stack ?? null,
220
+ thread: null,
221
+ },
222
+ fields: {},
223
+ message: error?.message ?? null,
224
+ muted: false,
225
+ params: {},
226
+ group_params: {},
227
+ relations: this.getRelations(filePath, value.ancestorTitles),
228
+ run_id: null,
229
+ signature: this.getSignature(filePath, value.fullName, ids),
230
+ steps: [],
231
+ testops_id: ids.length > 0 ? ids : null,
232
+ id: (0, uuid_1.v4)(),
233
+ title: value.title,
234
+ };
235
+ }
236
+ /**
237
+ * @returns {Metadata}
238
+ * @private
239
+ */
240
+ createEmptyMetadata() {
241
+ return {
242
+ title: undefined,
243
+ ignore: false,
244
+ comment: undefined,
245
+ suite: undefined,
246
+ fields: {},
247
+ parameters: {},
248
+ groupParams: {},
249
+ steps: [],
250
+ attachments: [],
251
+ };
252
+ }
149
253
  }
150
254
  exports.JestQaseReporter = JestQaseReporter;
151
255
  /**
package/dist/step.d.ts ADDED
@@ -0,0 +1,16 @@
1
+ import { Attachment, TestStepType } from 'qase-javascript-commons';
2
+ export type StepFunction<T = any> = (this: QaseStep, step: QaseStep) => T | Promise<T>;
3
+ export declare class QaseStep {
4
+ name: string;
5
+ attachments: Attachment[];
6
+ steps: TestStepType[];
7
+ constructor(name: string);
8
+ attach(attach: {
9
+ name?: string;
10
+ type?: string;
11
+ content?: string;
12
+ paths?: string[] | string;
13
+ }): void;
14
+ step(name: string, body: StepFunction): Promise<void>;
15
+ run(body: StepFunction, messageEmitter: (step: TestStepType) => Promise<void>): Promise<void>;
16
+ }
package/dist/step.js ADDED
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.QaseStep = void 0;
7
+ const qase_javascript_commons_1 = require("qase-javascript-commons");
8
+ const uuid_1 = require("uuid");
9
+ const path_1 = __importDefault(require("path"));
10
+ // TODO: Move to common, because it's duplicated in qase-wdio/src/step.ts
11
+ class QaseStep {
12
+ constructor(name) {
13
+ this.name = '';
14
+ this.attachments = [];
15
+ this.steps = [];
16
+ this.name = name;
17
+ }
18
+ attach(attach) {
19
+ if (attach.paths) {
20
+ const files = Array.isArray(attach.paths) ? attach.paths : [attach.paths];
21
+ for (const file of files) {
22
+ const attachmentName = path_1.default.basename(file);
23
+ const contentType = 'application/octet-stream';
24
+ this.attachments.push({
25
+ id: (0, uuid_1.v4)(),
26
+ file_name: attachmentName,
27
+ mime_type: contentType,
28
+ content: '',
29
+ file_path: file,
30
+ size: 0,
31
+ });
32
+ }
33
+ return;
34
+ }
35
+ if (attach.content) {
36
+ const attachmentName = attach.name ?? 'attachment';
37
+ const contentType = attach.type ?? 'application/octet-stream';
38
+ this.attachments.push({
39
+ id: (0, uuid_1.v4)(),
40
+ file_name: attachmentName,
41
+ mime_type: contentType,
42
+ content: attach.content,
43
+ file_path: null,
44
+ size: attach.content.length,
45
+ });
46
+ }
47
+ }
48
+ async step(name, body) {
49
+ const childStep = new QaseStep(name);
50
+ // eslint-disable-next-line @typescript-eslint/require-await
51
+ await childStep.run(body, async (step) => {
52
+ this.steps.push(step);
53
+ });
54
+ }
55
+ async run(body, messageEmitter) {
56
+ const startDate = new Date().getTime();
57
+ const step = new qase_javascript_commons_1.TestStepType();
58
+ step.data = {
59
+ action: this.name,
60
+ expected_result: null,
61
+ };
62
+ try {
63
+ await body.call(this, this);
64
+ step.execution = {
65
+ start_time: startDate,
66
+ end_time: new Date().getTime(),
67
+ status: qase_javascript_commons_1.StepStatusEnum.passed,
68
+ duration: null,
69
+ };
70
+ step.attachments = this.attachments;
71
+ step.steps = this.steps;
72
+ await messageEmitter(step);
73
+ }
74
+ catch (e) {
75
+ step.execution = {
76
+ start_time: startDate,
77
+ end_time: new Date().getTime(),
78
+ status: qase_javascript_commons_1.StepStatusEnum.failed,
79
+ duration: null,
80
+ };
81
+ step.attachments = this.attachments;
82
+ step.steps = this.steps;
83
+ await messageEmitter(step);
84
+ throw e;
85
+ }
86
+ }
87
+ }
88
+ exports.QaseStep = QaseStep;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jest-qase-reporter",
3
- "version": "2.0.2",
3
+ "version": "2.0.3",
4
4
  "description": "Qase TMS Jest Reporter",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -45,7 +45,7 @@
45
45
  "dependencies": {
46
46
  "lodash.get": "^4.4.2",
47
47
  "lodash.has": "^4.5.2",
48
- "qase-javascript-commons": "~2.2.0",
48
+ "qase-javascript-commons": "~2.2.1",
49
49
  "uuid": "^9.0.0"
50
50
  },
51
51
  "devDependencies": {