jest-qase-reporter 2.0.2 → 2.0.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.
- package/README.md +39 -23
- package/changelog.md +44 -1
- package/dist/global.d.ts +23 -0
- package/dist/global.js +49 -0
- package/dist/jest.d.ts +102 -1
- package/dist/jest.js +144 -0
- package/dist/models.d.ts +12 -0
- package/dist/models.js +2 -0
- package/dist/reporter.d.ts +37 -3
- package/dist/reporter.js +180 -54
- package/dist/step.d.ts +16 -0
- package/dist/step.js +88 -0
- package/docs/usage.md +209 -0
- package/package.json +2 -2
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
|
-
|
|
83
|
-
const { qase } = require("jest-qase-reporter/jest");
|
|
81
|
+
### Metadata
|
|
84
82
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
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
|
-
|
|
91
|
-
|
|
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
|
-
|
|
99
|
-
|
|
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,10 +141,9 @@ 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
|
|
129
|
-
- *`testops.api.token` - Token for API access, you can
|
|
130
|
-
|
|
131
|
-
- *`testops.project` - Qase project code, for example, in https://app.qase.io/project/DEMO the code is `DEMO`
|
|
144
|
+
- `environment` - To execute with the sending of the envinroment information
|
|
145
|
+
- *`testops.api.token` - Token for API access, you can generate it [here](https://developers.qase.io/#authentication).
|
|
146
|
+
- *`testops.project` - [Your project's code](https://help.qase.io/en/articles/9787250-how-do-i-find-my-project-code)
|
|
132
147
|
- `testops.run.id` - Qase test run ID, used when the test run was created earlier using CLI or API call.
|
|
133
148
|
- `testops.run.title` - Set custom Run name, when new run is created
|
|
134
149
|
- `testops.run.description` - Set custom Run description, when new run is created
|
|
@@ -167,7 +182,7 @@ Supported ENV variables:
|
|
|
167
182
|
|
|
168
183
|
- `QASE_MODE` - Same as `mode`
|
|
169
184
|
- `QASE_DEBUG` - Same as `debug`
|
|
170
|
-
- `QASE_ENVIRONMENT` - Same as `environment`
|
|
185
|
+
- `QASE_ENVIRONMENT` - Same as `environment`
|
|
171
186
|
- `QASE_TESTOPS_API_TOKEN` - Same as `testops.api.token`
|
|
172
187
|
- `QASE_TESTOPS_PROJECT` - Same as `testops.project`
|
|
173
188
|
- `QASE_TESTOPS_RUN_ID` - Pass Run ID from ENV and override reporter option `testops.run.id`
|
|
@@ -176,7 +191,8 @@ Supported ENV variables:
|
|
|
176
191
|
|
|
177
192
|
## Requirements
|
|
178
193
|
|
|
179
|
-
We maintain the reporter on LTS versions of Node. You can find the current versions by following
|
|
194
|
+
We maintain the reporter on LTS versions of Node. You can find the current versions by following
|
|
195
|
+
the [link](https://nodejs.org/en/about/releases/)
|
|
180
196
|
|
|
181
197
|
`jest >= 28.0.0`
|
|
182
198
|
|
package/changelog.md
CHANGED
|
@@ -1,9 +1,52 @@
|
|
|
1
|
+
# jest-qase-reporter@2.0.4
|
|
2
|
+
|
|
3
|
+
## What's new
|
|
4
|
+
|
|
5
|
+
Improved test name processing: Qase IDs are now automatically removed when uploading results
|
|
6
|
+
|
|
7
|
+
# jest-qase-reporter@2.0.3
|
|
8
|
+
|
|
9
|
+
## What's new
|
|
10
|
+
|
|
11
|
+
Added the ability to specify a test metadata in tests:
|
|
12
|
+
|
|
13
|
+
- `qase.title` - set the test title
|
|
14
|
+
- `qase.fields` - set the test fields
|
|
15
|
+
- `qase.suite` - set the test suite
|
|
16
|
+
- `qase.comment` - set the test comment
|
|
17
|
+
- `qase.parameters` - set the test parameters
|
|
18
|
+
- `qase.groupParameters` - set the test group parameters
|
|
19
|
+
- `qase.ignore` - ignore the test in Qase
|
|
20
|
+
- `qase.attach` - attach a file to the test
|
|
21
|
+
- `qase.steps` - add the test steps
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
const { qase } = require('jest-qase-reporter/jest');
|
|
25
|
+
|
|
26
|
+
test('test', () => {
|
|
27
|
+
qase.title('Title');
|
|
28
|
+
qase.fields({ custom_field: 'value' });
|
|
29
|
+
qase.suite('Suite');
|
|
30
|
+
qase.comment('Comment');
|
|
31
|
+
qase.parameters({ param01: 'value' });
|
|
32
|
+
qase.groupParameters({ param02: 'value' });
|
|
33
|
+
qase.ignore();
|
|
34
|
+
qase.attach({ name: 'attachment.txt', content: 'Hello, world!', type: 'text/plain' });
|
|
35
|
+
|
|
36
|
+
qase.step('Step 1', () => {
|
|
37
|
+
expect(true).toBe(true);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
expect(true).toBe(true);
|
|
41
|
+
});
|
|
42
|
+
```
|
|
43
|
+
|
|
1
44
|
# jest-qase-reporter@2.0.1
|
|
2
45
|
|
|
3
46
|
## What's new
|
|
4
47
|
|
|
5
48
|
Fixed a bug when a test was marked as skipped.
|
|
6
|
-
This reporter has uploaded this test as blocked.
|
|
49
|
+
This reporter has uploaded this test as blocked.
|
|
7
50
|
Right now the reporter will upload this test as skipped.
|
|
8
51
|
|
|
9
52
|
# jest-qase-reporter@2.0.0
|
package/dist/global.d.ts
ADDED
|
@@ -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,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Qase = void 0;
|
|
4
|
+
class Qase {
|
|
5
|
+
reporter;
|
|
6
|
+
constructor(reporter) {
|
|
7
|
+
this.reporter = reporter;
|
|
8
|
+
}
|
|
9
|
+
title(title) {
|
|
10
|
+
this.reporter.addTitle(title);
|
|
11
|
+
}
|
|
12
|
+
ignore() {
|
|
13
|
+
this.reporter.addIgnore();
|
|
14
|
+
}
|
|
15
|
+
comment(value) {
|
|
16
|
+
this.reporter.addComment(value);
|
|
17
|
+
}
|
|
18
|
+
suite(value) {
|
|
19
|
+
this.reporter.addSuite(value);
|
|
20
|
+
}
|
|
21
|
+
fields(values) {
|
|
22
|
+
const stringRecord = {};
|
|
23
|
+
for (const [key, value] of Object.entries(values)) {
|
|
24
|
+
stringRecord[String(key)] = String(value);
|
|
25
|
+
}
|
|
26
|
+
this.reporter.addFields(stringRecord);
|
|
27
|
+
}
|
|
28
|
+
parameters(values) {
|
|
29
|
+
const stringRecord = {};
|
|
30
|
+
for (const [key, value] of Object.entries(values)) {
|
|
31
|
+
stringRecord[String(key)] = String(value);
|
|
32
|
+
}
|
|
33
|
+
this.reporter.addParameters(stringRecord);
|
|
34
|
+
}
|
|
35
|
+
groupParams(values) {
|
|
36
|
+
const stringRecord = {};
|
|
37
|
+
for (const [key, value] of Object.entries(values)) {
|
|
38
|
+
stringRecord[String(key)] = String(value);
|
|
39
|
+
}
|
|
40
|
+
this.reporter.addGroupParams(stringRecord);
|
|
41
|
+
}
|
|
42
|
+
step(step) {
|
|
43
|
+
this.reporter.addStep(step);
|
|
44
|
+
}
|
|
45
|
+
attachment(attachment) {
|
|
46
|
+
this.reporter.addAttachment(attachment);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
exports.Qase = Qase;
|
package/dist/jest.d.ts
CHANGED
|
@@ -1 +1,102 @@
|
|
|
1
|
-
|
|
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
|
+
};
|
package/dist/models.d.ts
ADDED
|
@@ -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
package/dist/reporter.d.ts
CHANGED
|
@@ -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 {
|
|
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,32 @@ 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;
|
|
99
|
+
/**
|
|
100
|
+
* @param {string} title
|
|
101
|
+
* @returns {string}
|
|
102
|
+
* @private
|
|
103
|
+
*/
|
|
104
|
+
private removeQaseIdsFromTitle;
|
|
71
105
|
}
|
package/dist/reporter.js
CHANGED
|
@@ -8,20 +8,47 @@ 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
|
|
14
15
|
*/
|
|
15
16
|
class JestQaseReporter {
|
|
17
|
+
/**
|
|
18
|
+
* @type {Record<Status, TestStatusEnum>}
|
|
19
|
+
*/
|
|
20
|
+
static statusMap = {
|
|
21
|
+
passed: qase_javascript_commons_1.TestStatusEnum.passed,
|
|
22
|
+
failed: qase_javascript_commons_1.TestStatusEnum.failed,
|
|
23
|
+
skipped: qase_javascript_commons_1.TestStatusEnum.skipped,
|
|
24
|
+
disabled: qase_javascript_commons_1.TestStatusEnum.disabled,
|
|
25
|
+
pending: qase_javascript_commons_1.TestStatusEnum.skipped,
|
|
26
|
+
todo: qase_javascript_commons_1.TestStatusEnum.disabled,
|
|
27
|
+
focused: qase_javascript_commons_1.TestStatusEnum.passed,
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* @type {RegExp}
|
|
31
|
+
*/
|
|
32
|
+
static qaseIdRegExp = /\(Qase ID: ([\d,]+)\)/;
|
|
16
33
|
/**
|
|
17
34
|
* @param {string} title
|
|
18
|
-
* @returns {
|
|
35
|
+
* @returns {number[]}
|
|
19
36
|
* @private
|
|
20
37
|
*/
|
|
21
38
|
static getCaseId(title) {
|
|
22
39
|
const [, ids] = title.match(JestQaseReporter.qaseIdRegExp) ?? [];
|
|
23
40
|
return ids ? ids.split(',').map((id) => Number(id)) : [];
|
|
24
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* @type {ReporterInterface}
|
|
44
|
+
* @private
|
|
45
|
+
*/
|
|
46
|
+
reporter;
|
|
47
|
+
/**
|
|
48
|
+
* @type {Metadata}
|
|
49
|
+
* @private
|
|
50
|
+
*/
|
|
51
|
+
metadata;
|
|
25
52
|
/**
|
|
26
53
|
* @param {Config.GlobalConfig} _
|
|
27
54
|
* @param {JestQaseOptionsType} options
|
|
@@ -36,6 +63,8 @@ class JestQaseReporter {
|
|
|
36
63
|
frameworkName: 'jest',
|
|
37
64
|
reporterName: 'jest-qase-reporter',
|
|
38
65
|
});
|
|
66
|
+
global.Qase = new global_1.Qase(this);
|
|
67
|
+
this.metadata = this.createEmptyMetadata();
|
|
39
68
|
}
|
|
40
69
|
/**
|
|
41
70
|
* @see {Reporter.onRunStart}
|
|
@@ -43,49 +72,59 @@ class JestQaseReporter {
|
|
|
43
72
|
onRunStart() {
|
|
44
73
|
void this.reporter.startTestRun();
|
|
45
74
|
}
|
|
75
|
+
onTestCaseResult(test, testCaseResult) {
|
|
76
|
+
if (this.metadata.ignore) {
|
|
77
|
+
this.cleanMetadata();
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const result = this.convertToResult(testCaseResult, test.path);
|
|
81
|
+
if (this.metadata.title) {
|
|
82
|
+
result.title = this.metadata.title;
|
|
83
|
+
}
|
|
84
|
+
if (this.metadata.comment) {
|
|
85
|
+
result.message = this.metadata.comment;
|
|
86
|
+
}
|
|
87
|
+
if (this.metadata.suite) {
|
|
88
|
+
result.relations = {
|
|
89
|
+
suite: {
|
|
90
|
+
data: [
|
|
91
|
+
{
|
|
92
|
+
title: this.metadata.suite,
|
|
93
|
+
public_id: null,
|
|
94
|
+
},
|
|
95
|
+
],
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
if (Object.keys(this.metadata.fields).length > 0) {
|
|
100
|
+
result.fields = this.metadata.fields;
|
|
101
|
+
}
|
|
102
|
+
if (Object.keys(this.metadata.parameters).length > 0) {
|
|
103
|
+
result.params = this.metadata.parameters;
|
|
104
|
+
}
|
|
105
|
+
if (Object.keys(this.metadata.groupParams).length > 0) {
|
|
106
|
+
result.group_params = this.metadata.groupParams;
|
|
107
|
+
}
|
|
108
|
+
if (this.metadata.steps.length > 0) {
|
|
109
|
+
result.steps = this.metadata.steps;
|
|
110
|
+
}
|
|
111
|
+
if (this.metadata.attachments.length > 0) {
|
|
112
|
+
result.attachments = this.metadata.attachments;
|
|
113
|
+
}
|
|
114
|
+
this.cleanMetadata();
|
|
115
|
+
void this.reporter.addTestResult(result);
|
|
116
|
+
}
|
|
46
117
|
/**
|
|
47
118
|
* @param {Test} _
|
|
48
119
|
* @param {TestResult} result
|
|
49
120
|
*/
|
|
50
121
|
onTestResult(_, result) {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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');
|
|
122
|
+
result.testResults.forEach((value) => {
|
|
123
|
+
if (value.status !== 'pending') {
|
|
124
|
+
return;
|
|
62
125
|
}
|
|
63
|
-
const
|
|
64
|
-
|
|
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
|
-
});
|
|
126
|
+
const model = this.convertToResult(value, result.testFilePath);
|
|
127
|
+
void this.reporter.addTestResult(model);
|
|
89
128
|
});
|
|
90
129
|
}
|
|
91
130
|
/**
|
|
@@ -146,21 +185,108 @@ class JestQaseReporter {
|
|
|
146
185
|
const executionPath = process.cwd() + '/';
|
|
147
186
|
return fullPath.replace(executionPath, '');
|
|
148
187
|
}
|
|
188
|
+
addTitle(title) {
|
|
189
|
+
this.metadata.title = title;
|
|
190
|
+
}
|
|
191
|
+
addComment(comment) {
|
|
192
|
+
this.metadata.comment = comment;
|
|
193
|
+
}
|
|
194
|
+
addSuite(suite) {
|
|
195
|
+
this.metadata.suite = suite;
|
|
196
|
+
}
|
|
197
|
+
addFields(fields) {
|
|
198
|
+
this.metadata.fields = fields;
|
|
199
|
+
}
|
|
200
|
+
addParameters(parameters) {
|
|
201
|
+
this.metadata.parameters = parameters;
|
|
202
|
+
}
|
|
203
|
+
addGroupParams(groupParams) {
|
|
204
|
+
this.metadata.groupParams = groupParams;
|
|
205
|
+
}
|
|
206
|
+
addIgnore() {
|
|
207
|
+
this.metadata.ignore = true;
|
|
208
|
+
}
|
|
209
|
+
addStep(step) {
|
|
210
|
+
this.metadata.steps.push(step);
|
|
211
|
+
}
|
|
212
|
+
addAttachment(attachment) {
|
|
213
|
+
this.metadata.attachments.push(attachment);
|
|
214
|
+
}
|
|
215
|
+
cleanMetadata() {
|
|
216
|
+
this.metadata = this.createEmptyMetadata();
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* @param {AssertionResult} value
|
|
220
|
+
* @param {string} path
|
|
221
|
+
* @private
|
|
222
|
+
* @returns {TestResultType}
|
|
223
|
+
*/
|
|
224
|
+
convertToResult(value, path) {
|
|
225
|
+
let error;
|
|
226
|
+
if (value.status === 'failed') {
|
|
227
|
+
error = new Error(value.failureDetails.map((item) => {
|
|
228
|
+
if ((0, lodash_has_1.default)(item, 'matcherResult.message')) {
|
|
229
|
+
return String((0, lodash_get_1.default)(item, 'matcherResult.message'));
|
|
230
|
+
}
|
|
231
|
+
return 'Runtime exception';
|
|
232
|
+
}).join('\n\n'));
|
|
233
|
+
error.stack = value.failureMessages.join('\n\n');
|
|
234
|
+
}
|
|
235
|
+
const ids = JestQaseReporter.getCaseId(value.title);
|
|
236
|
+
const filePath = this.getCurrentTestPath(path);
|
|
237
|
+
return {
|
|
238
|
+
attachments: [],
|
|
239
|
+
author: null,
|
|
240
|
+
execution: {
|
|
241
|
+
status: JestQaseReporter.statusMap[value.status],
|
|
242
|
+
start_time: null,
|
|
243
|
+
end_time: null,
|
|
244
|
+
duration: value.duration ?? 0,
|
|
245
|
+
stacktrace: error?.stack ?? null,
|
|
246
|
+
thread: null,
|
|
247
|
+
},
|
|
248
|
+
fields: {},
|
|
249
|
+
message: error?.message ?? null,
|
|
250
|
+
muted: false,
|
|
251
|
+
params: {},
|
|
252
|
+
group_params: {},
|
|
253
|
+
relations: this.getRelations(filePath, value.ancestorTitles),
|
|
254
|
+
run_id: null,
|
|
255
|
+
signature: this.getSignature(filePath, value.fullName, ids),
|
|
256
|
+
steps: [],
|
|
257
|
+
testops_id: ids.length > 0 ? ids : null,
|
|
258
|
+
id: (0, uuid_1.v4)(),
|
|
259
|
+
title: this.removeQaseIdsFromTitle(value.title),
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* @returns {Metadata}
|
|
264
|
+
* @private
|
|
265
|
+
*/
|
|
266
|
+
createEmptyMetadata() {
|
|
267
|
+
return {
|
|
268
|
+
title: undefined,
|
|
269
|
+
ignore: false,
|
|
270
|
+
comment: undefined,
|
|
271
|
+
suite: undefined,
|
|
272
|
+
fields: {},
|
|
273
|
+
parameters: {},
|
|
274
|
+
groupParams: {},
|
|
275
|
+
steps: [],
|
|
276
|
+
attachments: [],
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* @param {string} title
|
|
281
|
+
* @returns {string}
|
|
282
|
+
* @private
|
|
283
|
+
*/
|
|
284
|
+
removeQaseIdsFromTitle(title) {
|
|
285
|
+
const matches = title.match(/\(Qase ID: ([0-9,]+)\)$/i);
|
|
286
|
+
if (matches) {
|
|
287
|
+
return title.replace(matches[0], '').trimEnd();
|
|
288
|
+
}
|
|
289
|
+
return title;
|
|
290
|
+
}
|
|
149
291
|
}
|
|
150
292
|
exports.JestQaseReporter = JestQaseReporter;
|
|
151
|
-
/**
|
|
152
|
-
* @type {Record<Status, TestStatusEnum>}
|
|
153
|
-
*/
|
|
154
|
-
JestQaseReporter.statusMap = {
|
|
155
|
-
passed: qase_javascript_commons_1.TestStatusEnum.passed,
|
|
156
|
-
failed: qase_javascript_commons_1.TestStatusEnum.failed,
|
|
157
|
-
skipped: qase_javascript_commons_1.TestStatusEnum.skipped,
|
|
158
|
-
disabled: qase_javascript_commons_1.TestStatusEnum.disabled,
|
|
159
|
-
pending: qase_javascript_commons_1.TestStatusEnum.skipped,
|
|
160
|
-
todo: qase_javascript_commons_1.TestStatusEnum.disabled,
|
|
161
|
-
focused: qase_javascript_commons_1.TestStatusEnum.passed,
|
|
162
|
-
};
|
|
163
|
-
/**
|
|
164
|
-
* @type {RegExp}
|
|
165
|
-
*/
|
|
166
|
-
JestQaseReporter.qaseIdRegExp = /\(Qase ID: ([\d,]+)\)/;
|
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
|
+
name = '';
|
|
13
|
+
attachments = [];
|
|
14
|
+
steps = [];
|
|
15
|
+
constructor(name) {
|
|
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/docs/usage.md
ADDED
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
# Qase Syntax
|
|
2
|
+
|
|
3
|
+
> [**Click here**](../../examples/jest/test) to view Example tests for the following syntax.
|
|
4
|
+
|
|
5
|
+
Here is the complete list of syntax options available for the reporter:
|
|
6
|
+
- [Qase Id](#qase-id)
|
|
7
|
+
- [Qase Title](#qase-title)
|
|
8
|
+
- [Steps](#steps)
|
|
9
|
+
- [Fields](#fields)
|
|
10
|
+
- [Suite](#suite)
|
|
11
|
+
- [Parameters](#parameters)
|
|
12
|
+
- [Comment](#comment)
|
|
13
|
+
- [Attach](#attach)
|
|
14
|
+
- [Ignore](#ignore)
|
|
15
|
+
|
|
16
|
+
If you do not use any Qase syntax, the reporter uses the title from the `describe` and `test` functions as the Suite and Test case title respectively, when publishing results.
|
|
17
|
+
|
|
18
|
+
<br>
|
|
19
|
+
|
|
20
|
+
### Import Statement
|
|
21
|
+
---
|
|
22
|
+
Add the following statement at the beginning of your spec file, before any tests.
|
|
23
|
+
|
|
24
|
+
```javascript
|
|
25
|
+
const { qase } = require("jest-qase-reporter/jest");
|
|
26
|
+
```
|
|
27
|
+
<br>
|
|
28
|
+
|
|
29
|
+
### Qase ID
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
You can link one or more Qase Ids to a test.
|
|
33
|
+
|
|
34
|
+
```javascript
|
|
35
|
+
test(qase(1, "A test with Qase Id"), () => {
|
|
36
|
+
..
|
|
37
|
+
|
|
38
|
+
test(qase(['2', '3'], "A test with multiple Qase Ids"), () => {
|
|
39
|
+
..
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
<br>
|
|
43
|
+
|
|
44
|
+
### Qase Title
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
The `qase.title()` method is used to set the title of a test case, both when creating a new test case from the result, and when updating the title of an existing test case - *if used with `qase.id()`.*
|
|
48
|
+
|
|
49
|
+
```javascript
|
|
50
|
+
test("This won't appear in Qase", () => {
|
|
51
|
+
qase.title("This text will be the title of the test, in Qase");
|
|
52
|
+
// Test logic here
|
|
53
|
+
});
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
If you don’t explicitly set a title using this method, the title specified in the `test(..)` function will be used for creating new test cases. However, if this method is defined, it always takes precedence and overrides the title from the `test(..)` function.
|
|
57
|
+
|
|
58
|
+
<br>
|
|
59
|
+
|
|
60
|
+
### Steps
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
The reporter uses the title from the `test.step` function as the step title. By providing clear and descriptive step names, you make it easier to understand the test’s flow when reviewing the test case.
|
|
64
|
+
|
|
65
|
+
Additionally, these steps get their own result in the Qase Test run, offering a well-organized summary of the test flow. This helps quickly identify the cause of any failures.
|
|
66
|
+
|
|
67
|
+
```javascript
|
|
68
|
+
test('A Test case with steps, updated from code', async () => {
|
|
69
|
+
await test.step('Initialize the environment', async () => {
|
|
70
|
+
// Set up test environment
|
|
71
|
+
});
|
|
72
|
+
await test.step('Test Core Functionality of the app', async () => {
|
|
73
|
+
// Exercise core functionality
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
await test.step('Verify Expected Behavior of the app', async () => {
|
|
77
|
+
// Assert expected behavior
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
```
|
|
81
|
+
<br>
|
|
82
|
+
|
|
83
|
+
### Fields
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
You can define the `description`, `pre-conditions`, `post-conditions`, and fields such as `severity`, `priority`, and `layer` using this method, which enables you to specify and maintain the context of the case directly within your code.
|
|
87
|
+
|
|
88
|
+
```javascript
|
|
89
|
+
test('Maintain your test meta-data from code', async () => {
|
|
90
|
+
await qase.fields({
|
|
91
|
+
severity: 'high',
|
|
92
|
+
priority: 'medium',
|
|
93
|
+
layer: 'api',
|
|
94
|
+
precondition: 'add your precondition',
|
|
95
|
+
postcondition: 'add your postcondition',
|
|
96
|
+
description: `Code it quick, fix it slow,
|
|
97
|
+
Tech debt grows where shortcuts go,
|
|
98
|
+
Refactor later? Ha! We know.`
|
|
99
|
+
});
|
|
100
|
+
// test logic here
|
|
101
|
+
});
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
<br>
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
### Suite
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
You can use this method to nest the resulting test cases in a particular suite. There's something to note here – suites, unlike test cases, are not identified uniquely by the Reporter. Therefore, when defining an existing suite - the title of the suite is used for matching.
|
|
111
|
+
|
|
112
|
+
```js
|
|
113
|
+
test("Test with a defined suite", () => {
|
|
114
|
+
qase.suite("Suite defined with qase.suite()");
|
|
115
|
+
/*
|
|
116
|
+
* Or, nest multiple levels of suites.
|
|
117
|
+
* `\t` is used for dividing each suite name.
|
|
118
|
+
*/
|
|
119
|
+
|
|
120
|
+
test("Test with a nested suite", () => {
|
|
121
|
+
qase.suite("Application\tAuthentication\tLogin\tEdge_case");
|
|
122
|
+
// test logic here
|
|
123
|
+
});
|
|
124
|
+
```
|
|
125
|
+
<br>
|
|
126
|
+
|
|
127
|
+
### Parameters
|
|
128
|
+
---
|
|
129
|
+
Parameters are a great way to make your tests more dynamic, reusable, and data-driven. By defining parameters in this method, you can ensure only one test case with all the parameters is created in your Qase project, avoiding duplication.
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
```javascript
|
|
133
|
+
const testCases = [
|
|
134
|
+
{ browser: "Chromium", username: "@alice", password: "123" },
|
|
135
|
+
{ browser: "Firefox", username: "@bob", password: "456" },
|
|
136
|
+
{ browser: "Webkit", username: "@charlie", password: "789" },
|
|
137
|
+
];
|
|
138
|
+
|
|
139
|
+
testCases.forEach(({ browser, username, password, }) => {
|
|
140
|
+
test(`Test login with ${browser}`, async () => {
|
|
141
|
+
qase.title("Verify if page loads on all browsers");
|
|
142
|
+
|
|
143
|
+
qase.parameters({ Browser: browser }); // Single parameter
|
|
144
|
+
// test logic
|
|
145
|
+
|
|
146
|
+
testCases.forEach(({ username, password }) => {
|
|
147
|
+
test(`Test login with ${username} using qase.groupParameters`, () => {
|
|
148
|
+
qase.title("Verify if user is able to login with their username.");
|
|
149
|
+
|
|
150
|
+
qase.groupParameters({ // Group parameters
|
|
151
|
+
Username: username,
|
|
152
|
+
Password: password,
|
|
153
|
+
});
|
|
154
|
+
// test logic
|
|
155
|
+
```
|
|
156
|
+
<br>
|
|
157
|
+
|
|
158
|
+
### Comment
|
|
159
|
+
---
|
|
160
|
+
In addition to `test.step()`, this method can be used to provide any additional context to your test, it helps maintiain the code by clarifying the expected result of the test.
|
|
161
|
+
|
|
162
|
+
```js
|
|
163
|
+
test("A test case with qase.comment()", () => {
|
|
164
|
+
/*
|
|
165
|
+
* Please note, this comment is added to a Result, not to the Test case.
|
|
166
|
+
*/
|
|
167
|
+
qase.comment("This comment is added to the result");
|
|
168
|
+
// test logic here
|
|
169
|
+
});
|
|
170
|
+
```
|
|
171
|
+
<br>
|
|
172
|
+
|
|
173
|
+
### Attach
|
|
174
|
+
---
|
|
175
|
+
This method can help attach one, or more files to the test's result. You can also add the file's contents directly from code. For example:
|
|
176
|
+
|
|
177
|
+
```js
|
|
178
|
+
test('Test result with attachment', async () => {
|
|
179
|
+
|
|
180
|
+
test("Test result with attachment", async () => {
|
|
181
|
+
|
|
182
|
+
// To attach a single file
|
|
183
|
+
await qase.attach({
|
|
184
|
+
paths: "./attachments/test-file.txt",
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
// Add multiple attachments.
|
|
188
|
+
await qase.attach({ paths: ['/path/to/file', '/path/to/another/file'] });
|
|
189
|
+
|
|
190
|
+
// Upload file's contents directly from code.
|
|
191
|
+
await qase.attach({
|
|
192
|
+
name: "attachment.txt",
|
|
193
|
+
content: "Hello, world!",
|
|
194
|
+
contentType: "text/plain",
|
|
195
|
+
});
|
|
196
|
+
// test logic here
|
|
197
|
+
});
|
|
198
|
+
```
|
|
199
|
+
<br>
|
|
200
|
+
|
|
201
|
+
### Ignore
|
|
202
|
+
---
|
|
203
|
+
If this method is added, the reporter will exclude the test’s result from the report sent to Qase. While the test will still executed by jest, its result will not be considered by the reporter.
|
|
204
|
+
|
|
205
|
+
```js
|
|
206
|
+
test("This test is executed by jest; however, it is NOT reported to Qase", () => {
|
|
207
|
+
qase.ignore();
|
|
208
|
+
// test logic here
|
|
209
|
+
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jest-qase-reporter",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.4",
|
|
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.
|
|
48
|
+
"qase-javascript-commons": "~2.2.1",
|
|
49
49
|
"uuid": "^9.0.0"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|