testcafe-reporter-qase 2.0.3 → 2.0.5
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 +22 -17
- package/changelog.md +25 -0
- package/dist/factory.d.ts +1 -0
- package/dist/factory.js +3 -0
- package/dist/global.d.ts +16 -0
- package/dist/global.js +16 -0
- package/dist/qase.d.ts +30 -0
- package/dist/qase.js +182 -124
- package/dist/reporter.d.ts +6 -1
- package/dist/reporter.js +83 -62
- package/docs/usage.md +163 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -20,15 +20,28 @@ To update a test project using testcafe-reporter-qaser@v1 to version 2:
|
|
|
20
20
|
The TestCafe reporter has the ability to auto-generate test cases
|
|
21
21
|
and suites from your test data.
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
You can also annotate the tests with the IDs of existing test cases
|
|
24
|
+
from Qase.io before executing tests. It's a more reliable way to bind
|
|
25
|
+
autotests to test cases, that persists when you rename, move, or
|
|
26
|
+
parameterize your tests.
|
|
26
27
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
### Metadata
|
|
29
|
+
|
|
30
|
+
- `qase.title` - set the title of the test case
|
|
31
|
+
- `qase.fields` - set the fields of the test case
|
|
32
|
+
- `qase.suite` - set the suite of the test case
|
|
33
|
+
- `qase.comment` - set the comment of the test case
|
|
34
|
+
- `qase.parameters` - set the parameters of the test case
|
|
35
|
+
- `qase.groupParameters` - set the group parameters of the test case
|
|
36
|
+
- `qase.ignore` - ignore the test case in Qase. The test will be executed, but the results will not be sent to Qase.
|
|
37
|
+
- `qase.step` - create a step in the test case
|
|
38
|
+
- `qase.attach` - attach a file or content to the test case
|
|
39
|
+
|
|
40
|
+
For detailed instructions on using annotations and methods, refer to [Usage](docs/usage.md).
|
|
31
41
|
|
|
42
|
+
For example:
|
|
43
|
+
|
|
44
|
+
```js
|
|
32
45
|
const q = qase.id(1)
|
|
33
46
|
.title('Text typing basics')
|
|
34
47
|
.field({ 'severity': 'high' })
|
|
@@ -98,16 +111,8 @@ Example `qase.config.json` file:
|
|
|
98
111
|
}
|
|
99
112
|
```
|
|
100
113
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
- `QASE_MODE` - Same as `mode`
|
|
104
|
-
- `QASE_DEBUG` - Same as `debug`
|
|
105
|
-
- `QASE_ENVIRONMENT` - Same as `environment`
|
|
106
|
-
- `QASE_TESTOPS_API_TOKEN` - Same as `testops.api.token`
|
|
107
|
-
- `QASE_TESTOPS_PROJECT` - Same as `testops.project`
|
|
108
|
-
- `QASE_TESTOPS_RUN_ID` - Pass Run ID from ENV and override reporter option `testops.run.id`
|
|
109
|
-
- `QASE_TESTOPS_RUN_TITLE` - Same as `testops.run.title`
|
|
110
|
-
- `QASE_TESTOPS_RUN_DESCRIPTION` - Same as `testops.run.description`
|
|
114
|
+
Check out the example of configuration for multiple reporters in the
|
|
115
|
+
[demo project](../examples/testcafe/qase.config.json).
|
|
111
116
|
|
|
112
117
|
## Requirements
|
|
113
118
|
|
package/changelog.md
CHANGED
|
@@ -1,3 +1,28 @@
|
|
|
1
|
+
# qase-testcafe@2.0.4
|
|
2
|
+
|
|
3
|
+
## What's new
|
|
4
|
+
|
|
5
|
+
Support `step` and `attach` methods for test cases.
|
|
6
|
+
|
|
7
|
+
```javascript
|
|
8
|
+
import { qase } from 'testcafe-qase-reporter/qase';
|
|
9
|
+
|
|
10
|
+
test('test', async (t) => {
|
|
11
|
+
qase.attach({ name: 'attachment.txt', content: 'Hello, world!', contentType: 'text/plain' });
|
|
12
|
+
|
|
13
|
+
await qase.step('Step 1', async (s1) => {
|
|
14
|
+
await s1.step('Step 1.1', async (s11) => {
|
|
15
|
+
await s11.step('Step 1.1.1', async (s111) => {
|
|
16
|
+
s11.attach({ name: 'attachment.txt', content: 'Hello, world!', contentType: 'text/plain' });
|
|
17
|
+
await s111.expect(true).ok();
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
await t.expect(true).ok();
|
|
21
|
+
});
|
|
22
|
+
await t.expect(true).ok();
|
|
23
|
+
});
|
|
24
|
+
```
|
|
25
|
+
|
|
1
26
|
# qase-testcafe@2.0.3
|
|
2
27
|
|
|
3
28
|
## What's new
|
package/dist/factory.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export declare const factory: (options: TestcafeQaseOptionsType) => {
|
|
|
7
7
|
noColors: boolean;
|
|
8
8
|
reportTaskStart: () => void;
|
|
9
9
|
reportFixtureStart: () => void;
|
|
10
|
+
reportTestStart: () => void;
|
|
10
11
|
reportTestDone(name: string, testRunInfo: TestRunInfoType, meta: Record<string, string>): Promise<void>;
|
|
11
12
|
reportTaskDone: () => Promise<void>;
|
|
12
13
|
};
|
package/dist/factory.js
CHANGED
|
@@ -16,6 +16,9 @@ const factory = (options) => {
|
|
|
16
16
|
reportFixtureStart: () => {
|
|
17
17
|
/* empty */
|
|
18
18
|
},
|
|
19
|
+
reportTestStart: () => {
|
|
20
|
+
reporter.reportTestStart();
|
|
21
|
+
},
|
|
19
22
|
async reportTestDone(name, testRunInfo, meta) {
|
|
20
23
|
return reporter.reportTestDone(name, testRunInfo, meta,
|
|
21
24
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
package/dist/global.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { TestcafeQaseReporter } 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: TestcafeQaseReporter);
|
|
13
|
+
step(step: TestStepType): void;
|
|
14
|
+
attachment(attachment: Attachment): void;
|
|
15
|
+
}
|
|
16
|
+
export {};
|
package/dist/global.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
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
|
+
step(step) {
|
|
10
|
+
this.reporter.addStep(step);
|
|
11
|
+
}
|
|
12
|
+
attachment(attachment) {
|
|
13
|
+
this.reporter.addAttachment(attachment);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
exports.Qase = Qase;
|
package/dist/qase.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { StepFunction } from 'qase-javascript-commons';
|
|
1
2
|
export declare class qase {
|
|
2
3
|
private static _qaseID;
|
|
3
4
|
private static _qaseTitle;
|
|
@@ -70,6 +71,35 @@ export declare class qase {
|
|
|
70
71
|
* test.meta({userField: 123, ...q})('Test case title', async t => { ... });
|
|
71
72
|
*/
|
|
72
73
|
static ignore: () => typeof qase;
|
|
74
|
+
/**
|
|
75
|
+
* Add a step to the test case
|
|
76
|
+
* @param name
|
|
77
|
+
* @param body
|
|
78
|
+
* @example
|
|
79
|
+
* test.meta({userField: 123, ...q})('Test case title', async t => {
|
|
80
|
+
* await qase.step("Step", () => {
|
|
81
|
+
* expect(true).toBe(true);
|
|
82
|
+
* });
|
|
83
|
+
* expect(true).toBe(true);
|
|
84
|
+
* });
|
|
85
|
+
*/
|
|
86
|
+
static step: (name: string, body: StepFunction) => Promise<void>;
|
|
87
|
+
/**
|
|
88
|
+
* Add an attachment to the test case
|
|
89
|
+
* @param attach
|
|
90
|
+
* @example
|
|
91
|
+
* test.meta({userField: 123, ...q})('Test case title', async t => {
|
|
92
|
+
* qase.attach({ name: 'attachment.txt', content: 'Hello, world!', type: 'text/plain' });
|
|
93
|
+
* qase.attach({ paths: ['/path/to/file', '/path/to/another/file']});
|
|
94
|
+
* expect(true).toBe(true);
|
|
95
|
+
* });
|
|
96
|
+
*/
|
|
97
|
+
static attach: (attach: {
|
|
98
|
+
name?: string;
|
|
99
|
+
type?: string;
|
|
100
|
+
content?: string;
|
|
101
|
+
paths?: string[];
|
|
102
|
+
}) => void;
|
|
73
103
|
/**
|
|
74
104
|
* Create a Qase metadata
|
|
75
105
|
* Call this method after setting all the necessary parameters
|
package/dist/qase.js
CHANGED
|
@@ -1,131 +1,189 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
3
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
6
|
exports.qase = void 0;
|
|
5
7
|
// eslint-disable-next-line @typescript-eslint/no-extraneous-class
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const qase_javascript_commons_1 = require("qase-javascript-commons");
|
|
10
|
+
const uuid_1 = require("uuid");
|
|
6
11
|
class qase {
|
|
12
|
+
static _qaseID = '';
|
|
13
|
+
static _qaseTitle = '';
|
|
14
|
+
static _qaseFields = '';
|
|
15
|
+
static _qaseParameters = '';
|
|
16
|
+
static _qaseGroupParameters = '';
|
|
17
|
+
static _qaseIgnore = '';
|
|
18
|
+
/**
|
|
19
|
+
* Set a Qase ID for the test case
|
|
20
|
+
* Don't forget to call `create` method after setting all the necessary parameters
|
|
21
|
+
* @param {number | number[]} value
|
|
22
|
+
* @example
|
|
23
|
+
* const q = qase.id(1).create();
|
|
24
|
+
* test.meta(q)('Test case title', async t => { ... });
|
|
25
|
+
* or
|
|
26
|
+
* test.meta({userField: 123, ...q})('Test case title', async t => { ... });
|
|
27
|
+
*/
|
|
28
|
+
static id = (value) => {
|
|
29
|
+
this._qaseID = Array.isArray(value) ? value.join(',') : String(value);
|
|
30
|
+
return this;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Set a title for the test case
|
|
34
|
+
* Don't forget to call `create` method after setting all the necessary parameters
|
|
35
|
+
* @param {string} value
|
|
36
|
+
* @example
|
|
37
|
+
* const q = qase.title('Test case title').create();
|
|
38
|
+
* test.meta(q)('Test case title', async t => { ... });
|
|
39
|
+
* or
|
|
40
|
+
* test.meta({userField: 123, ...q})('Test case title', async t => { ... });
|
|
41
|
+
*/
|
|
42
|
+
static title = (value) => {
|
|
43
|
+
this._qaseTitle = value;
|
|
44
|
+
return this;
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Set a fields for the test case
|
|
48
|
+
* Don't forget to call `create` method after setting all the necessary parameters
|
|
49
|
+
* @param {Record<string, string>} values
|
|
50
|
+
* @example
|
|
51
|
+
* const q = qase.fields({ 'severity': 'high', 'priority': 'medium' }).create();
|
|
52
|
+
* test.meta(q)('Test case title', async t => { ... });
|
|
53
|
+
* or
|
|
54
|
+
* test.meta({userField: 123, ...q})('Test case title', async t => { ... });
|
|
55
|
+
*/
|
|
56
|
+
static fields = (values) => {
|
|
57
|
+
this._qaseFields = this.toNormalizeRecord(values);
|
|
58
|
+
return this;
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Set a parameters for the test case
|
|
62
|
+
* Don't forget to call `create` method after setting all the necessary parameters
|
|
63
|
+
* @param {Record<string, string>} values
|
|
64
|
+
* @example
|
|
65
|
+
* const q = qase.parameters({ 'severity': 'high', 'priority': 'medium' }).create();
|
|
66
|
+
* test.meta(q)('Test case title', async t => { ... });
|
|
67
|
+
* or
|
|
68
|
+
* test.meta({userField: 123, ...q})('Test case title', async t => { ... });
|
|
69
|
+
*/
|
|
70
|
+
static parameters = (values) => {
|
|
71
|
+
this._qaseParameters = this.toNormalizeRecord(values);
|
|
72
|
+
return this;
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* Set a group parameters for the test case
|
|
76
|
+
* Don't forget to call `create` method after setting all the necessary parameters
|
|
77
|
+
* @param {Record<string, string>} values
|
|
78
|
+
* @example
|
|
79
|
+
* const q = qase.groupParameters({ 'severity': 'high', 'priority': 'medium' }).create();
|
|
80
|
+
* test.meta(q)('Test case title', async t => { ... });
|
|
81
|
+
* or
|
|
82
|
+
* test.meta({userField: 123, ...q})('Test case title', async t => { ... });
|
|
83
|
+
*/
|
|
84
|
+
static groupParameters = (values) => {
|
|
85
|
+
this._qaseGroupParameters = this.toNormalizeRecord(values);
|
|
86
|
+
return this;
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* Set a ignore flag for the test case
|
|
90
|
+
* Don't forget to call `create` method after setting all the necessary parameters
|
|
91
|
+
* @example
|
|
92
|
+
* const q = qase.ignore().create();
|
|
93
|
+
* test.meta(q)('Test case title', async t => { ... });
|
|
94
|
+
* or
|
|
95
|
+
* test.meta({userField: 123, ...q})('Test case title', async t => { ... });
|
|
96
|
+
*/
|
|
97
|
+
static ignore = () => {
|
|
98
|
+
this._qaseIgnore = 'true';
|
|
99
|
+
return this;
|
|
100
|
+
};
|
|
101
|
+
/**
|
|
102
|
+
* Add a step to the test case
|
|
103
|
+
* @param name
|
|
104
|
+
* @param body
|
|
105
|
+
* @example
|
|
106
|
+
* test.meta({userField: 123, ...q})('Test case title', async t => {
|
|
107
|
+
* await qase.step("Step", () => {
|
|
108
|
+
* expect(true).toBe(true);
|
|
109
|
+
* });
|
|
110
|
+
* expect(true).toBe(true);
|
|
111
|
+
* });
|
|
112
|
+
*/
|
|
113
|
+
static step = async (name, body) => {
|
|
114
|
+
const runningStep = new qase_javascript_commons_1.QaseStep(name);
|
|
115
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
116
|
+
await runningStep.run(body, async (step) => global.Qase.step(step));
|
|
117
|
+
};
|
|
118
|
+
/**
|
|
119
|
+
* Add an attachment to the test case
|
|
120
|
+
* @param attach
|
|
121
|
+
* @example
|
|
122
|
+
* test.meta({userField: 123, ...q})('Test case title', async t => {
|
|
123
|
+
* qase.attach({ name: 'attachment.txt', content: 'Hello, world!', type: 'text/plain' });
|
|
124
|
+
* qase.attach({ paths: ['/path/to/file', '/path/to/another/file']});
|
|
125
|
+
* expect(true).toBe(true);
|
|
126
|
+
* });
|
|
127
|
+
*/
|
|
128
|
+
static attach = (attach) => {
|
|
129
|
+
if (attach.paths) {
|
|
130
|
+
for (const file of attach.paths) {
|
|
131
|
+
const attachmentName = path_1.default.basename(file);
|
|
132
|
+
const contentType = (0, qase_javascript_commons_1.getMimeTypes)(file);
|
|
133
|
+
global.Qase.attachment({
|
|
134
|
+
file_path: file,
|
|
135
|
+
size: 0,
|
|
136
|
+
id: (0, uuid_1.v4)(),
|
|
137
|
+
file_name: attachmentName,
|
|
138
|
+
mime_type: contentType,
|
|
139
|
+
content: '',
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
if (attach.content) {
|
|
145
|
+
global.Qase.attachment({
|
|
146
|
+
file_path: null,
|
|
147
|
+
size: attach.content.length,
|
|
148
|
+
id: (0, uuid_1.v4)(),
|
|
149
|
+
file_name: attach.name ?? 'attachment',
|
|
150
|
+
mime_type: attach.type ?? 'application/octet-stream',
|
|
151
|
+
content: attach.content,
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
/**
|
|
156
|
+
* Create a Qase metadata
|
|
157
|
+
* Call this method after setting all the necessary parameters
|
|
158
|
+
* @example
|
|
159
|
+
* const q = qase.id(1).title('Test case title').fields({ 'severity': 'high', 'priority': 'medium' }).create();
|
|
160
|
+
* test.meta(q)('Test case title', async t => { ... });
|
|
161
|
+
* or
|
|
162
|
+
* test.meta({userField: 123, ...q})('Test case title', async t => { ... });
|
|
163
|
+
*/
|
|
164
|
+
static create = () => {
|
|
165
|
+
const meta = {
|
|
166
|
+
QaseID: this._qaseID,
|
|
167
|
+
QaseTitle: this._qaseTitle,
|
|
168
|
+
QaseFields: this._qaseFields,
|
|
169
|
+
QaseParameters: this._qaseParameters,
|
|
170
|
+
QaseGroupParameters: this._qaseGroupParameters,
|
|
171
|
+
QaseIgnore: this._qaseIgnore,
|
|
172
|
+
};
|
|
173
|
+
this._qaseID = '';
|
|
174
|
+
this._qaseTitle = '';
|
|
175
|
+
this._qaseFields = '';
|
|
176
|
+
this._qaseParameters = '';
|
|
177
|
+
this._qaseGroupParameters = '';
|
|
178
|
+
this._qaseIgnore = '';
|
|
179
|
+
return meta;
|
|
180
|
+
};
|
|
181
|
+
static toNormalizeRecord = (record) => {
|
|
182
|
+
const stringRecord = {};
|
|
183
|
+
for (const [key, value] of Object.entries(record)) {
|
|
184
|
+
stringRecord[String(key)] = String(value);
|
|
185
|
+
}
|
|
186
|
+
return JSON.stringify(stringRecord);
|
|
187
|
+
};
|
|
7
188
|
}
|
|
8
189
|
exports.qase = qase;
|
|
9
|
-
_a = qase;
|
|
10
|
-
qase._qaseID = '';
|
|
11
|
-
qase._qaseTitle = '';
|
|
12
|
-
qase._qaseFields = '';
|
|
13
|
-
qase._qaseParameters = '';
|
|
14
|
-
qase._qaseGroupParameters = '';
|
|
15
|
-
qase._qaseIgnore = '';
|
|
16
|
-
/**
|
|
17
|
-
* Set a Qase ID for the test case
|
|
18
|
-
* Don't forget to call `create` method after setting all the necessary parameters
|
|
19
|
-
* @param {number | number[]} value
|
|
20
|
-
* @example
|
|
21
|
-
* const q = qase.id(1).create();
|
|
22
|
-
* test.meta(q)('Test case title', async t => { ... });
|
|
23
|
-
* or
|
|
24
|
-
* test.meta({userField: 123, ...q})('Test case title', async t => { ... });
|
|
25
|
-
*/
|
|
26
|
-
qase.id = (value) => {
|
|
27
|
-
_a._qaseID = Array.isArray(value) ? value.join(',') : String(value);
|
|
28
|
-
return _a;
|
|
29
|
-
};
|
|
30
|
-
/**
|
|
31
|
-
* Set a title for the test case
|
|
32
|
-
* Don't forget to call `create` method after setting all the necessary parameters
|
|
33
|
-
* @param {string} value
|
|
34
|
-
* @example
|
|
35
|
-
* const q = qase.title('Test case title').create();
|
|
36
|
-
* test.meta(q)('Test case title', async t => { ... });
|
|
37
|
-
* or
|
|
38
|
-
* test.meta({userField: 123, ...q})('Test case title', async t => { ... });
|
|
39
|
-
*/
|
|
40
|
-
qase.title = (value) => {
|
|
41
|
-
_a._qaseTitle = value;
|
|
42
|
-
return _a;
|
|
43
|
-
};
|
|
44
|
-
/**
|
|
45
|
-
* Set a fields for the test case
|
|
46
|
-
* Don't forget to call `create` method after setting all the necessary parameters
|
|
47
|
-
* @param {Record<string, string>} values
|
|
48
|
-
* @example
|
|
49
|
-
* const q = qase.fields({ 'severity': 'high', 'priority': 'medium' }).create();
|
|
50
|
-
* test.meta(q)('Test case title', async t => { ... });
|
|
51
|
-
* or
|
|
52
|
-
* test.meta({userField: 123, ...q})('Test case title', async t => { ... });
|
|
53
|
-
*/
|
|
54
|
-
qase.fields = (values) => {
|
|
55
|
-
_a._qaseFields = _a.toNormalizeRecord(values);
|
|
56
|
-
return _a;
|
|
57
|
-
};
|
|
58
|
-
/**
|
|
59
|
-
* Set a parameters for the test case
|
|
60
|
-
* Don't forget to call `create` method after setting all the necessary parameters
|
|
61
|
-
* @param {Record<string, string>} values
|
|
62
|
-
* @example
|
|
63
|
-
* const q = qase.parameters({ 'severity': 'high', 'priority': 'medium' }).create();
|
|
64
|
-
* test.meta(q)('Test case title', async t => { ... });
|
|
65
|
-
* or
|
|
66
|
-
* test.meta({userField: 123, ...q})('Test case title', async t => { ... });
|
|
67
|
-
*/
|
|
68
|
-
qase.parameters = (values) => {
|
|
69
|
-
_a._qaseParameters = _a.toNormalizeRecord(values);
|
|
70
|
-
return _a;
|
|
71
|
-
};
|
|
72
|
-
/**
|
|
73
|
-
* Set a group parameters for the test case
|
|
74
|
-
* Don't forget to call `create` method after setting all the necessary parameters
|
|
75
|
-
* @param {Record<string, string>} values
|
|
76
|
-
* @example
|
|
77
|
-
* const q = qase.groupParameters({ 'severity': 'high', 'priority': 'medium' }).create();
|
|
78
|
-
* test.meta(q)('Test case title', async t => { ... });
|
|
79
|
-
* or
|
|
80
|
-
* test.meta({userField: 123, ...q})('Test case title', async t => { ... });
|
|
81
|
-
*/
|
|
82
|
-
qase.groupParameters = (values) => {
|
|
83
|
-
_a._qaseGroupParameters = _a.toNormalizeRecord(values);
|
|
84
|
-
return _a;
|
|
85
|
-
};
|
|
86
|
-
/**
|
|
87
|
-
* Set a ignore flag for the test case
|
|
88
|
-
* Don't forget to call `create` method after setting all the necessary parameters
|
|
89
|
-
* @example
|
|
90
|
-
* const q = qase.ignore().create();
|
|
91
|
-
* test.meta(q)('Test case title', async t => { ... });
|
|
92
|
-
* or
|
|
93
|
-
* test.meta({userField: 123, ...q})('Test case title', async t => { ... });
|
|
94
|
-
*/
|
|
95
|
-
qase.ignore = () => {
|
|
96
|
-
_a._qaseIgnore = 'true';
|
|
97
|
-
return _a;
|
|
98
|
-
};
|
|
99
|
-
/**
|
|
100
|
-
* Create a Qase metadata
|
|
101
|
-
* Call this method after setting all the necessary parameters
|
|
102
|
-
* @example
|
|
103
|
-
* const q = qase.id(1).title('Test case title').fields({ 'severity': 'high', 'priority': 'medium' }).create();
|
|
104
|
-
* test.meta(q)('Test case title', async t => { ... });
|
|
105
|
-
* or
|
|
106
|
-
* test.meta({userField: 123, ...q})('Test case title', async t => { ... });
|
|
107
|
-
*/
|
|
108
|
-
qase.create = () => {
|
|
109
|
-
const meta = {
|
|
110
|
-
QaseID: _a._qaseID,
|
|
111
|
-
QaseTitle: _a._qaseTitle,
|
|
112
|
-
QaseFields: _a._qaseFields,
|
|
113
|
-
QaseParameters: _a._qaseParameters,
|
|
114
|
-
QaseGroupParameters: _a._qaseGroupParameters,
|
|
115
|
-
QaseIgnore: _a._qaseIgnore,
|
|
116
|
-
};
|
|
117
|
-
_a._qaseID = '';
|
|
118
|
-
_a._qaseTitle = '';
|
|
119
|
-
_a._qaseFields = '';
|
|
120
|
-
_a._qaseParameters = '';
|
|
121
|
-
_a._qaseGroupParameters = '';
|
|
122
|
-
_a._qaseIgnore = '';
|
|
123
|
-
return meta;
|
|
124
|
-
};
|
|
125
|
-
qase.toNormalizeRecord = (record) => {
|
|
126
|
-
const stringRecord = {};
|
|
127
|
-
for (const [key, value] of Object.entries(record)) {
|
|
128
|
-
stringRecord[String(key)] = String(value);
|
|
129
|
-
}
|
|
130
|
-
return JSON.stringify(stringRecord);
|
|
131
|
-
};
|
package/dist/reporter.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ConfigLoader, ConfigType } from 'qase-javascript-commons';
|
|
1
|
+
import { ConfigLoader, ConfigType, Attachment, TestStepType } from 'qase-javascript-commons';
|
|
2
2
|
interface CallsiteRecordType {
|
|
3
3
|
filename?: string;
|
|
4
4
|
lineNum?: number;
|
|
@@ -65,15 +65,20 @@ export declare class TestcafeQaseReporter {
|
|
|
65
65
|
* @private
|
|
66
66
|
*/
|
|
67
67
|
private reporter;
|
|
68
|
+
private steps;
|
|
69
|
+
private attachments;
|
|
68
70
|
/**
|
|
69
71
|
* @param {TestcafeQaseOptionsType} options
|
|
70
72
|
* @param {ConfigLoaderInterface} configLoader
|
|
71
73
|
*/
|
|
72
74
|
constructor(options: TestcafeQaseOptionsType, configLoader?: ConfigLoader<Partial<ConfigType> & Record<string, unknown>>);
|
|
75
|
+
addStep(step: TestStepType): void;
|
|
76
|
+
addAttachment(attachment: Attachment): void;
|
|
73
77
|
/**
|
|
74
78
|
* @returns {Promise<void>}
|
|
75
79
|
*/
|
|
76
80
|
startTestRun: () => void;
|
|
81
|
+
reportTestStart: () => void;
|
|
77
82
|
/**
|
|
78
83
|
* @param {string} title
|
|
79
84
|
* @param {TestRunInfoType} testRunInfo
|
package/dist/reporter.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.TestcafeQaseReporter = void 0;
|
|
4
4
|
const uuid_1 = require("uuid");
|
|
5
5
|
const qase_javascript_commons_1 = require("qase-javascript-commons");
|
|
6
|
+
const global_1 = require("./global");
|
|
6
7
|
var metadataEnum;
|
|
7
8
|
(function (metadataEnum) {
|
|
8
9
|
metadataEnum["id"] = "QaseID";
|
|
@@ -50,73 +51,18 @@ class TestcafeQaseReporter {
|
|
|
50
51
|
}
|
|
51
52
|
return attachments;
|
|
52
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* @type {ReporterInterface}
|
|
56
|
+
* @private
|
|
57
|
+
*/
|
|
58
|
+
reporter;
|
|
59
|
+
steps = [];
|
|
60
|
+
attachments = [];
|
|
53
61
|
/**
|
|
54
62
|
* @param {TestcafeQaseOptionsType} options
|
|
55
63
|
* @param {ConfigLoaderInterface} configLoader
|
|
56
64
|
*/
|
|
57
65
|
constructor(options, configLoader = new qase_javascript_commons_1.ConfigLoader()) {
|
|
58
|
-
/**
|
|
59
|
-
* @returns {Promise<void>}
|
|
60
|
-
*/
|
|
61
|
-
this.startTestRun = () => {
|
|
62
|
-
this.reporter.startTestRun();
|
|
63
|
-
};
|
|
64
|
-
/**
|
|
65
|
-
* @param {string} title
|
|
66
|
-
* @param {TestRunInfoType} testRunInfo
|
|
67
|
-
* @param {Record<string, string>} meta
|
|
68
|
-
* @param formatError
|
|
69
|
-
*/
|
|
70
|
-
this.reportTestDone = async (title, testRunInfo, meta, formatError) => {
|
|
71
|
-
const metadata = this.getMeta(meta);
|
|
72
|
-
if (metadata[metadataEnum.ignore]) {
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
const errorLog = testRunInfo.errs
|
|
76
|
-
.map((error, index) => formatError(error, `${index + 1} `).replace(
|
|
77
|
-
// eslint-disable-next-line no-control-regex
|
|
78
|
-
/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, ''))
|
|
79
|
-
.join('\n');
|
|
80
|
-
await this.reporter.addTestResult({
|
|
81
|
-
author: null,
|
|
82
|
-
execution: {
|
|
83
|
-
status: TestcafeQaseReporter.getStatus(testRunInfo),
|
|
84
|
-
start_time: null,
|
|
85
|
-
end_time: null,
|
|
86
|
-
duration: testRunInfo.durationMs,
|
|
87
|
-
stacktrace: errorLog,
|
|
88
|
-
thread: null,
|
|
89
|
-
},
|
|
90
|
-
fields: metadata[metadataEnum.fields],
|
|
91
|
-
message: errorLog ? errorLog.split('\n')[0] ?? '' : '',
|
|
92
|
-
muted: false,
|
|
93
|
-
params: metadata[metadataEnum.parameters],
|
|
94
|
-
group_params: metadata[metadataEnum.groupParameters],
|
|
95
|
-
relations: {
|
|
96
|
-
suite: {
|
|
97
|
-
data: [
|
|
98
|
-
{
|
|
99
|
-
title: testRunInfo.fixture.name,
|
|
100
|
-
public_id: null,
|
|
101
|
-
},
|
|
102
|
-
],
|
|
103
|
-
},
|
|
104
|
-
},
|
|
105
|
-
run_id: null,
|
|
106
|
-
signature: this.getSignature(testRunInfo.fixture, title, metadata[metadataEnum.id], metadata[metadataEnum.parameters]),
|
|
107
|
-
steps: [],
|
|
108
|
-
id: (0, uuid_1.v4)(),
|
|
109
|
-
testops_id: metadata[metadataEnum.id].length > 0 ? metadata[metadataEnum.id] : null,
|
|
110
|
-
title: metadata[metadataEnum.title] != undefined ? metadata[metadataEnum.title] : title,
|
|
111
|
-
attachments: TestcafeQaseReporter.transformAttachments(testRunInfo.screenshots),
|
|
112
|
-
});
|
|
113
|
-
};
|
|
114
|
-
/**
|
|
115
|
-
* @returns {Promise<void>}
|
|
116
|
-
*/
|
|
117
|
-
this.reportTaskDone = async () => {
|
|
118
|
-
await this.reporter.publish();
|
|
119
|
-
};
|
|
120
66
|
const config = configLoader.load();
|
|
121
67
|
this.reporter = qase_javascript_commons_1.QaseReporter.getInstance({
|
|
122
68
|
...(0, qase_javascript_commons_1.composeOptions)(options, config),
|
|
@@ -124,7 +70,82 @@ class TestcafeQaseReporter {
|
|
|
124
70
|
frameworkName: 'testcafe',
|
|
125
71
|
reporterName: 'testcafe-reporter-qase',
|
|
126
72
|
});
|
|
73
|
+
global.Qase = new global_1.Qase(this);
|
|
74
|
+
}
|
|
75
|
+
addStep(step) {
|
|
76
|
+
this.steps.push(step);
|
|
77
|
+
}
|
|
78
|
+
addAttachment(attachment) {
|
|
79
|
+
this.attachments.push(attachment);
|
|
127
80
|
}
|
|
81
|
+
/**
|
|
82
|
+
* @returns {Promise<void>}
|
|
83
|
+
*/
|
|
84
|
+
startTestRun = () => {
|
|
85
|
+
this.reporter.startTestRun();
|
|
86
|
+
};
|
|
87
|
+
reportTestStart = () => {
|
|
88
|
+
this.steps = [];
|
|
89
|
+
this.attachments = [];
|
|
90
|
+
};
|
|
91
|
+
/**
|
|
92
|
+
* @param {string} title
|
|
93
|
+
* @param {TestRunInfoType} testRunInfo
|
|
94
|
+
* @param {Record<string, string>} meta
|
|
95
|
+
* @param formatError
|
|
96
|
+
*/
|
|
97
|
+
reportTestDone = async (title, testRunInfo, meta, formatError) => {
|
|
98
|
+
const metadata = this.getMeta(meta);
|
|
99
|
+
if (metadata[metadataEnum.ignore]) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
const errorLog = testRunInfo.errs
|
|
103
|
+
.map((error, index) => formatError(error, `${index + 1} `).replace(
|
|
104
|
+
// eslint-disable-next-line no-control-regex
|
|
105
|
+
/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, ''))
|
|
106
|
+
.join('\n');
|
|
107
|
+
const attachments = TestcafeQaseReporter.transformAttachments(testRunInfo.screenshots);
|
|
108
|
+
attachments.push(...this.attachments);
|
|
109
|
+
await this.reporter.addTestResult({
|
|
110
|
+
author: null,
|
|
111
|
+
execution: {
|
|
112
|
+
status: TestcafeQaseReporter.getStatus(testRunInfo),
|
|
113
|
+
start_time: null,
|
|
114
|
+
end_time: null,
|
|
115
|
+
duration: testRunInfo.durationMs,
|
|
116
|
+
stacktrace: errorLog,
|
|
117
|
+
thread: null,
|
|
118
|
+
},
|
|
119
|
+
fields: metadata[metadataEnum.fields],
|
|
120
|
+
message: errorLog ? errorLog.split('\n')[0] ?? '' : '',
|
|
121
|
+
muted: false,
|
|
122
|
+
params: metadata[metadataEnum.parameters],
|
|
123
|
+
group_params: metadata[metadataEnum.groupParameters],
|
|
124
|
+
relations: {
|
|
125
|
+
suite: {
|
|
126
|
+
data: [
|
|
127
|
+
{
|
|
128
|
+
title: testRunInfo.fixture.name,
|
|
129
|
+
public_id: null,
|
|
130
|
+
},
|
|
131
|
+
],
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
run_id: null,
|
|
135
|
+
signature: this.getSignature(testRunInfo.fixture, title, metadata[metadataEnum.id], metadata[metadataEnum.parameters]),
|
|
136
|
+
steps: this.steps,
|
|
137
|
+
id: (0, uuid_1.v4)(),
|
|
138
|
+
testops_id: metadata[metadataEnum.id].length > 0 ? metadata[metadataEnum.id] : null,
|
|
139
|
+
title: metadata[metadataEnum.title] != undefined ? metadata[metadataEnum.title] : title,
|
|
140
|
+
attachments: attachments,
|
|
141
|
+
});
|
|
142
|
+
};
|
|
143
|
+
/**
|
|
144
|
+
* @returns {Promise<void>}
|
|
145
|
+
*/
|
|
146
|
+
reportTaskDone = async () => {
|
|
147
|
+
await this.reporter.publish();
|
|
148
|
+
};
|
|
128
149
|
getMeta(meta) {
|
|
129
150
|
const metadata = {
|
|
130
151
|
QaseID: [],
|
package/docs/usage.md
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# Qase Integration in TestCafe
|
|
2
|
+
|
|
3
|
+
This guide demonstrates how to integrate Qase with TestCafe, providing instructions on how to add Qase IDs, titles,
|
|
4
|
+
fields, suites, comments, and file attachments to your test cases.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Adding QaseID to a Test
|
|
9
|
+
|
|
10
|
+
To associate a QaseID with a test in TestCafe, use the `qase` function. This function accepts a single integer
|
|
11
|
+
representing the test's ID in Qase.
|
|
12
|
+
|
|
13
|
+
### Example:
|
|
14
|
+
|
|
15
|
+
```javascript
|
|
16
|
+
import { qase } from 'testcafe-qase-reporter/qase';
|
|
17
|
+
|
|
18
|
+
const q = qase.id(1).create();
|
|
19
|
+
test.meta(q)('simple test', async (t) => {
|
|
20
|
+
await t.expect(true).ok();
|
|
21
|
+
});
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Adding a Title to a Test
|
|
27
|
+
|
|
28
|
+
You can provide a title for your test using the `qase.title` function. The function accepts a string, which will be
|
|
29
|
+
used as the test's title in Qase. If no title is provided, the test method name will be used by default.
|
|
30
|
+
|
|
31
|
+
### Example:
|
|
32
|
+
|
|
33
|
+
```javascript
|
|
34
|
+
import { qase } from 'testcafe-qase-reporter/qase';
|
|
35
|
+
|
|
36
|
+
const q = qase.title('Some title').create();
|
|
37
|
+
test.meta(q)('simple test', async (t) => {
|
|
38
|
+
await t.expect(true).ok();
|
|
39
|
+
});
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Adding Fields to a Test
|
|
45
|
+
|
|
46
|
+
The `qase.fields` function allows you to add additional metadata to a test case. You can specify multiple fields to
|
|
47
|
+
enhance test case information in Qase.
|
|
48
|
+
|
|
49
|
+
### System Fields:
|
|
50
|
+
|
|
51
|
+
- `description` — Description of the test case.
|
|
52
|
+
- `preconditions` — Preconditions for the test case.
|
|
53
|
+
- `postconditions` — Postconditions for the test case.
|
|
54
|
+
- `severity` — Severity of the test case (e.g., `critical`, `major`).
|
|
55
|
+
- `priority` — Priority of the test case (e.g., `high`, `low`).
|
|
56
|
+
- `layer` — Test layer (e.g., `UI`, `API`).
|
|
57
|
+
|
|
58
|
+
### Example:
|
|
59
|
+
|
|
60
|
+
```javascript
|
|
61
|
+
import { qase } from 'testcafe-qase-reporter/qase';
|
|
62
|
+
|
|
63
|
+
const q = qase.fields({ 'severity': 'high', 'priority': 'medium' }).create();
|
|
64
|
+
test.meta(q)('simple test', async (t) => {
|
|
65
|
+
await t.expect(true).ok();
|
|
66
|
+
});
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## Ignoring a Test in Qase
|
|
72
|
+
|
|
73
|
+
To exclude a test from being reported to Qase (while still executing the test in TestCafe), use the `qase.ignore`
|
|
74
|
+
function. The test will run, but its result will not be sent to Qase.
|
|
75
|
+
|
|
76
|
+
### Example:
|
|
77
|
+
|
|
78
|
+
```javascript
|
|
79
|
+
import { qase } from 'testcafe-qase-reporter/qase';
|
|
80
|
+
|
|
81
|
+
const q = qase.ignore().create();
|
|
82
|
+
test.meta(q)('simple test', async (t) => {
|
|
83
|
+
await t.expect(true).ok();
|
|
84
|
+
});
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Attaching Files to a Test
|
|
90
|
+
|
|
91
|
+
To attach files to a test result, use the `qase.attach` function. This method supports attaching one or multiple files,
|
|
92
|
+
along with optional file names, comments, and file types.
|
|
93
|
+
|
|
94
|
+
### Example:
|
|
95
|
+
|
|
96
|
+
```javascript
|
|
97
|
+
import { qase } from 'testcafe-qase-reporter/qase';
|
|
98
|
+
|
|
99
|
+
test('test', async (t) => {
|
|
100
|
+
qase.attach({ name: 'attachment.txt', content: 'Hello, world!', contentType: 'text/plain' });
|
|
101
|
+
qase.attach({ paths: '/path/to/file' });
|
|
102
|
+
qase.attach({ paths: ['/path/to/file', '/path/to/another/file'] });
|
|
103
|
+
await t.expect(true).ok();
|
|
104
|
+
});
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Adding Parameters to a Test
|
|
110
|
+
|
|
111
|
+
You can add parameters to a test case using the `qase.parameters` function. This function accepts an object with
|
|
112
|
+
parameter names and values.
|
|
113
|
+
|
|
114
|
+
### Example:
|
|
115
|
+
|
|
116
|
+
```javascript
|
|
117
|
+
import { qase } from 'testcafe-qase-reporter/qase';
|
|
118
|
+
|
|
119
|
+
const q = qase.parameters({ param1: 'value1', param2: 'value2' }).create();
|
|
120
|
+
test.meta(q)('simple test', async (t) => {
|
|
121
|
+
await t.expect(true).ok();
|
|
122
|
+
});
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Adding Group Parameters to a Test
|
|
126
|
+
|
|
127
|
+
To add group parameters to a test case, use the `qase.groupParameters` function. This function accepts an list with
|
|
128
|
+
group parameter names.
|
|
129
|
+
|
|
130
|
+
### Example:
|
|
131
|
+
|
|
132
|
+
```javascript
|
|
133
|
+
import { qase } from 'testcafe-qase-reporter/qase';
|
|
134
|
+
|
|
135
|
+
const q = qase.parameters({ param1: 'value1', param2: 'value2' }).groupParameters(['param1']).create();
|
|
136
|
+
test.meta(q)('simple test', async (t) => {
|
|
137
|
+
await t.expect(true).ok();
|
|
138
|
+
});
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Adding Steps to a Test
|
|
142
|
+
|
|
143
|
+
You can add steps to a test case using the `qase.step` function. This function accepts a string, which will be used as
|
|
144
|
+
the step description in Qase.
|
|
145
|
+
|
|
146
|
+
### Example:
|
|
147
|
+
|
|
148
|
+
```javascript
|
|
149
|
+
import { qase } from 'testcafe-qase-reporter/qase';
|
|
150
|
+
|
|
151
|
+
test('test', async (t) => {
|
|
152
|
+
await qase.step('Step 1', async (s1) => {
|
|
153
|
+
await s1.step('Step 1.1', async (s11) => {
|
|
154
|
+
await s11.step('Step 1.1.1', async (s111) => {
|
|
155
|
+
s11.attach({ name: 'attachment.txt', content: 'Hello, world!', contentType: 'text/plain' });
|
|
156
|
+
await s111.expect(true).ok();
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
await t.expect(true).ok();
|
|
160
|
+
});
|
|
161
|
+
await t.expect(true).ok();
|
|
162
|
+
});
|
|
163
|
+
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "testcafe-reporter-qase",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.5",
|
|
4
4
|
"description": "Qase TMS TestCafe Reporter",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"author": "Qase Team <support@qase.io>",
|
|
41
41
|
"license": "Apache-2.0",
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"qase-javascript-commons": "~2.2.
|
|
43
|
+
"qase-javascript-commons": "~2.2.14",
|
|
44
44
|
"uuid": "^9.0.0"
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {
|