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 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
- But if necessary, you can independently register the ID of already
24
- existing test cases from TMS before the executing tests. Meta key should be `CID`.
25
- You should assign list of case IDs to it, e.g.:
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
- ```js
28
- test.meta('CID', [1])('Text typing basics', async (t) => {
29
- await t;
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
- Supported ENV variables:
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
@@ -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 _a;
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
- };
@@ -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",
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.0",
43
+ "qase-javascript-commons": "~2.2.14",
44
44
  "uuid": "^9.0.0"
45
45
  },
46
46
  "peerDependencies": {