cypress-qase-reporter 2.2.4 → 2.2.6
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 +61 -1
- package/changelog.md +12 -0
- package/dist/cucumber.d.ts +1 -0
- package/dist/cucumber.js +25 -0
- package/dist/fileSearcher.d.ts +4 -2
- package/dist/fileSearcher.js +30 -4
- package/dist/index.cjs.d.ts +1 -0
- package/dist/index.cjs.js +3 -1
- package/dist/metadata/manager.d.ts +1 -0
- package/dist/metadata/manager.js +19 -1
- package/dist/metadata/models.d.ts +1 -0
- package/dist/metadata.js +6 -0
- package/dist/reporter.d.ts +8 -1
- package/dist/reporter.js +80 -23
- package/dist/utils/tagParser.d.ts +7 -0
- package/dist/utils/tagParser.js +61 -0
- package/package.json +6 -2
package/README.md
CHANGED
|
@@ -165,7 +165,7 @@ the [Configuration reference](../qase-javascript-commons/README.md#configuration
|
|
|
165
165
|
|
|
166
166
|
Example `cypress.config.js` config:
|
|
167
167
|
|
|
168
|
-
```
|
|
168
|
+
```javascript
|
|
169
169
|
import cypress from 'cypress';
|
|
170
170
|
|
|
171
171
|
module.exports = cypress.defineConfig({
|
|
@@ -211,6 +211,66 @@ module.exports = cypress.defineConfig({
|
|
|
211
211
|
Check out the example of configuration for multiple reporters in the
|
|
212
212
|
[demo project](../examples/cypress/cypress.config.js).
|
|
213
213
|
|
|
214
|
+
If you use Cucumber, you need to add the following configuration in `cypress.config.js`:
|
|
215
|
+
|
|
216
|
+
```javascript
|
|
217
|
+
import cypress from 'cypress';
|
|
218
|
+
|
|
219
|
+
const cucumber = require('cypress-cucumber-preprocessor').default;
|
|
220
|
+
|
|
221
|
+
module.exports = cypress.defineConfig({
|
|
222
|
+
reporter: 'cypress-multi-reporters',
|
|
223
|
+
reporterOptions: {
|
|
224
|
+
reporterEnabled: 'cypress-mochawesome-reporter, cypress-qase-reporter',
|
|
225
|
+
cypressMochawesomeReporterReporterOptions: {
|
|
226
|
+
charts: true,
|
|
227
|
+
},
|
|
228
|
+
cypressQaseReporterReporterOptions: {
|
|
229
|
+
debug: true,
|
|
230
|
+
|
|
231
|
+
testops: {
|
|
232
|
+
api: {
|
|
233
|
+
token: 'api_key',
|
|
234
|
+
},
|
|
235
|
+
|
|
236
|
+
project: 'project_code',
|
|
237
|
+
uploadAttachments: true,
|
|
238
|
+
|
|
239
|
+
run: {
|
|
240
|
+
complete: true,
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
|
|
244
|
+
framework: {
|
|
245
|
+
cypress: {
|
|
246
|
+
screenshotsFolder: 'cypress/screenshots',
|
|
247
|
+
},
|
|
248
|
+
},
|
|
249
|
+
},
|
|
250
|
+
},
|
|
251
|
+
video: false,
|
|
252
|
+
e2e: {
|
|
253
|
+
setupNodeEvents(on, config) {
|
|
254
|
+
on('file:preprocessor', cucumber());
|
|
255
|
+
require('cypress-qase-reporter/plugin')(on, config);
|
|
256
|
+
require('cypress-qase-reporter/metadata')(on);
|
|
257
|
+
},
|
|
258
|
+
specPattern: 'cypress/e2e/*.feature',
|
|
259
|
+
},
|
|
260
|
+
});
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
And add the following lines in `support/e2e.js` file:
|
|
264
|
+
|
|
265
|
+
```javascript
|
|
266
|
+
import { enableCucumberSupport } from "cypress-qase-reporter";
|
|
267
|
+
|
|
268
|
+
enableCucumberSupport();
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
Check out the example of configuration for multiple reporters in the
|
|
272
|
+
[demo project](../examples/cypressCucumber/cypress.config.js).
|
|
273
|
+
|
|
214
274
|
## Requirements
|
|
215
275
|
|
|
216
276
|
We maintain the reporter on [LTS versions of Node](https://nodejs.org/en/about/releases/).
|
package/changelog.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
# cypress-qase-reporter@2.2.6
|
|
2
|
+
|
|
3
|
+
## What's new
|
|
4
|
+
|
|
5
|
+
Fixed an issue where screenshots for failed tests were not attached if the tests were located in subdirectories.
|
|
6
|
+
|
|
7
|
+
# cypress-qase-reporter@2.2.5
|
|
8
|
+
|
|
9
|
+
## What's new
|
|
10
|
+
|
|
11
|
+
Support Cucumber tests in Cypress with the `cypress-cucumber-preprocessor` plugin.
|
|
12
|
+
|
|
1
13
|
# cypress-qase-reporter@2.2.4
|
|
2
14
|
|
|
3
15
|
## What's new
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const enableCucumberSupport: () => void;
|
package/dist/cucumber.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.enableCucumberSupport = void 0;
|
|
4
|
+
const CUCUMBER_TASK_NAME = 'qaseCucumberStepStart';
|
|
5
|
+
const enableCucumberSupport = () => {
|
|
6
|
+
registerCypressEventListeners();
|
|
7
|
+
};
|
|
8
|
+
exports.enableCucumberSupport = enableCucumberSupport;
|
|
9
|
+
const registerCypressEventListeners = () => {
|
|
10
|
+
Cypress.on('log:added', handleLogAdded);
|
|
11
|
+
};
|
|
12
|
+
const handleLogAdded = (_, entry) => {
|
|
13
|
+
if (isCucumberStep(entry)) {
|
|
14
|
+
processCucumberStep(entry);
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
const isCucumberStep = ({ attributes: { name, event, instrument } }) => {
|
|
18
|
+
return instrument === 'command' && !event && name === 'step';
|
|
19
|
+
};
|
|
20
|
+
const processCucumberStep = ({ attributes: { displayName, message } }) => {
|
|
21
|
+
sendTaskMessage(`${displayName ?? ''} ${message}`);
|
|
22
|
+
};
|
|
23
|
+
const sendTaskMessage = (message) => {
|
|
24
|
+
cy.task(CUCUMBER_TASK_NAME, message, { log: false });
|
|
25
|
+
};
|
package/dist/fileSearcher.d.ts
CHANGED
|
@@ -3,9 +3,11 @@ export declare class FileSearcher {
|
|
|
3
3
|
* Finds all files in the given directory and its subdirectories
|
|
4
4
|
* that were created after the specified time.
|
|
5
5
|
*
|
|
6
|
-
* @param
|
|
6
|
+
* @param screenshotFolderPath Path to the folder with screenshots.
|
|
7
|
+
* @param specFileName Name of the spec file.
|
|
7
8
|
* @param time Time threshold as a Date object.
|
|
8
9
|
* @returns Array of absolute paths to the matching files.
|
|
9
10
|
*/
|
|
10
|
-
static findFilesBeforeTime(
|
|
11
|
+
static findFilesBeforeTime(screenshotFolderPath: string, specFileName: string, time: Date): string[];
|
|
12
|
+
private static findFolderByName;
|
|
11
13
|
}
|
package/dist/fileSearcher.js
CHANGED
|
@@ -31,13 +31,18 @@ class FileSearcher {
|
|
|
31
31
|
* Finds all files in the given directory and its subdirectories
|
|
32
32
|
* that were created after the specified time.
|
|
33
33
|
*
|
|
34
|
-
* @param
|
|
34
|
+
* @param screenshotFolderPath Path to the folder with screenshots.
|
|
35
|
+
* @param specFileName Name of the spec file.
|
|
35
36
|
* @param time Time threshold as a Date object.
|
|
36
37
|
* @returns Array of absolute paths to the matching files.
|
|
37
38
|
*/
|
|
38
|
-
static findFilesBeforeTime(
|
|
39
|
-
const absolutePath = path.resolve(process.cwd(),
|
|
39
|
+
static findFilesBeforeTime(screenshotFolderPath, specFileName, time) {
|
|
40
|
+
const absolutePath = path.resolve(process.cwd(), screenshotFolderPath);
|
|
40
41
|
const result = [];
|
|
42
|
+
const paths = this.findFolderByName(absolutePath, specFileName);
|
|
43
|
+
if (paths.length === 0) {
|
|
44
|
+
return result;
|
|
45
|
+
}
|
|
41
46
|
const searchFiles = (dir) => {
|
|
42
47
|
if (!fs.existsSync(dir)) {
|
|
43
48
|
return;
|
|
@@ -56,7 +61,28 @@ class FileSearcher {
|
|
|
56
61
|
}
|
|
57
62
|
}
|
|
58
63
|
};
|
|
59
|
-
|
|
64
|
+
for (const path of paths) {
|
|
65
|
+
searchFiles(path);
|
|
66
|
+
}
|
|
67
|
+
return result;
|
|
68
|
+
}
|
|
69
|
+
static findFolderByName(startPath, folderName) {
|
|
70
|
+
const result = [];
|
|
71
|
+
function searchDirectory(currentPath) {
|
|
72
|
+
const items = fs.readdirSync(currentPath, { withFileTypes: true });
|
|
73
|
+
for (const item of items) {
|
|
74
|
+
const itemPath = path.join(currentPath, item.name);
|
|
75
|
+
if (item.isDirectory()) {
|
|
76
|
+
if (item.name === folderName) {
|
|
77
|
+
result.push(itemPath);
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
searchDirectory(itemPath);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
searchDirectory(startPath);
|
|
60
86
|
return result;
|
|
61
87
|
}
|
|
62
88
|
}
|
package/dist/index.cjs.d.ts
CHANGED
package/dist/index.cjs.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.qase = void 0;
|
|
3
|
+
exports.enableCucumberSupport = exports.qase = void 0;
|
|
4
4
|
var mocha_1 = require("./mocha");
|
|
5
5
|
Object.defineProperty(exports, "qase", { enumerable: true, get: function () { return mocha_1.qase; } });
|
|
6
|
+
var cucumber_1 = require("./cucumber");
|
|
7
|
+
Object.defineProperty(exports, "enableCucumberSupport", { enumerable: true, get: function () { return cucumber_1.enableCucumberSupport; } });
|
|
@@ -6,6 +6,7 @@ export declare class MetadataManager {
|
|
|
6
6
|
static setIgnore(): void;
|
|
7
7
|
static addStepStart(name: string): void;
|
|
8
8
|
static addStepEnd(status: string): void;
|
|
9
|
+
static addCucumberStep(name: string): void;
|
|
9
10
|
static addAttach(attach: Attach): void;
|
|
10
11
|
static setSuite(suite: string): void;
|
|
11
12
|
static setComment(comment: string): void;
|
package/dist/metadata/manager.js
CHANGED
|
@@ -10,6 +10,7 @@ const path_1 = __importDefault(require("path"));
|
|
|
10
10
|
const qase_javascript_commons_1 = require("qase-javascript-commons");
|
|
11
11
|
// eslint-disable-next-line @typescript-eslint/no-extraneous-class
|
|
12
12
|
class MetadataManager {
|
|
13
|
+
static metadataPath = path_1.default.resolve(__dirname, 'qaseMetadata');
|
|
13
14
|
static getMetadata() {
|
|
14
15
|
if (!this.isExists()) {
|
|
15
16
|
return undefined;
|
|
@@ -23,6 +24,7 @@ class MetadataManager {
|
|
|
23
24
|
suite: undefined,
|
|
24
25
|
comment: undefined,
|
|
25
26
|
steps: [],
|
|
27
|
+
cucumberSteps: [],
|
|
26
28
|
currentStepId: undefined,
|
|
27
29
|
firstStepName: undefined,
|
|
28
30
|
attachments: [],
|
|
@@ -70,6 +72,23 @@ class MetadataManager {
|
|
|
70
72
|
metadata.currentStepId = parentId;
|
|
71
73
|
this.setMetadata(metadata);
|
|
72
74
|
}
|
|
75
|
+
static addCucumberStep(name) {
|
|
76
|
+
const metadata = this.getMetadata() ?? {};
|
|
77
|
+
if (metadata.firstStepName === name) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
if (!metadata.cucumberSteps) {
|
|
81
|
+
metadata.cucumberSteps = [];
|
|
82
|
+
}
|
|
83
|
+
const id = (0, uuid_1.v4)();
|
|
84
|
+
const parentId = metadata.currentStepId ?? undefined;
|
|
85
|
+
metadata.cucumberSteps.push({ timestamp: Date.now(), name, id: id, parentId: parentId });
|
|
86
|
+
metadata.currentStepId = id;
|
|
87
|
+
if (!metadata.firstStepName) {
|
|
88
|
+
metadata.firstStepName = name;
|
|
89
|
+
}
|
|
90
|
+
this.setMetadata(metadata);
|
|
91
|
+
}
|
|
73
92
|
static addAttach(attach) {
|
|
74
93
|
const metadata = this.getMetadata() ?? {};
|
|
75
94
|
if (!metadata.attachments) {
|
|
@@ -189,4 +208,3 @@ class MetadataManager {
|
|
|
189
208
|
}
|
|
190
209
|
}
|
|
191
210
|
exports.MetadataManager = MetadataManager;
|
|
192
|
-
MetadataManager.metadataPath = path_1.default.resolve(__dirname, 'qaseMetadata');
|
|
@@ -9,6 +9,7 @@ export interface Metadata {
|
|
|
9
9
|
suite?: string | undefined;
|
|
10
10
|
comment?: string | undefined;
|
|
11
11
|
steps?: (StepStart | StepEnd)[];
|
|
12
|
+
cucumberSteps?: StepStart[];
|
|
12
13
|
currentStepId?: string | undefined;
|
|
13
14
|
firstStepName?: string | undefined;
|
|
14
15
|
attachments?: Attachment[];
|
package/dist/metadata.js
CHANGED
package/dist/reporter.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="cypress" />
|
|
2
2
|
import { MochaOptions, reporters, Runner } from 'mocha';
|
|
3
|
-
import { ConfigLoader,
|
|
3
|
+
import { ConfigLoader, FrameworkOptionsType, TestStatusEnum } from 'qase-javascript-commons';
|
|
4
4
|
import { ReporterOptionsType } from './options';
|
|
5
5
|
type CypressState = 'failed' | 'passed' | 'pending';
|
|
6
6
|
export type CypressQaseOptionsType = Omit<MochaOptions, 'reporterOptions'> & {
|
|
@@ -71,6 +71,13 @@ export declare class CypressQaseReporter extends reporters.Base {
|
|
|
71
71
|
* @private
|
|
72
72
|
*/
|
|
73
73
|
private removeQaseIdsFromTitle;
|
|
74
|
+
/**
|
|
75
|
+
* Extracts numbers from @qaseid tags, regardless of case.
|
|
76
|
+
* @param tags - An array of tags to process.
|
|
77
|
+
* @returns An array of numbers extracted from the tags.
|
|
78
|
+
*/
|
|
79
|
+
private extractQaseIds;
|
|
80
|
+
private convertCypressMessages;
|
|
74
81
|
private getSteps;
|
|
75
82
|
}
|
|
76
83
|
export {};
|
package/dist/reporter.js
CHANGED
|
@@ -12,12 +12,25 @@ const qase_javascript_commons_1 = require("qase-javascript-commons");
|
|
|
12
12
|
const configSchema_1 = require("./configSchema");
|
|
13
13
|
const manager_1 = require("./metadata/manager");
|
|
14
14
|
const fileSearcher_1 = require("./fileSearcher");
|
|
15
|
+
const tagParser_1 = require("./utils/tagParser");
|
|
15
16
|
const { EVENT_TEST_FAIL, EVENT_TEST_PASS, EVENT_TEST_PENDING, EVENT_RUN_END, EVENT_TEST_BEGIN, } = mocha_1.Runner.constants;
|
|
16
17
|
/**
|
|
17
18
|
* @class CypressQaseReporter
|
|
18
19
|
* @extends reporters.Base
|
|
19
20
|
*/
|
|
20
21
|
class CypressQaseReporter extends mocha_1.reporters.Base {
|
|
22
|
+
/**
|
|
23
|
+
* @type {RegExp}
|
|
24
|
+
*/
|
|
25
|
+
static qaseIdRegExp = /\(Qase ID:? ([\d,]+)\)/;
|
|
26
|
+
/**
|
|
27
|
+
* @type {Record<CypressState, TestStatusEnum>}
|
|
28
|
+
*/
|
|
29
|
+
static statusMap = {
|
|
30
|
+
failed: qase_javascript_commons_1.TestStatusEnum.failed,
|
|
31
|
+
passed: qase_javascript_commons_1.TestStatusEnum.passed,
|
|
32
|
+
pending: qase_javascript_commons_1.TestStatusEnum.skipped,
|
|
33
|
+
};
|
|
21
34
|
/**
|
|
22
35
|
* @param {string} title
|
|
23
36
|
* @returns {number[]}
|
|
@@ -27,6 +40,18 @@ class CypressQaseReporter extends mocha_1.reporters.Base {
|
|
|
27
40
|
const [, ids] = title.match(CypressQaseReporter.qaseIdRegExp) ?? [];
|
|
28
41
|
return ids ? ids.split(',').map((id) => Number(id)) : [];
|
|
29
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* @type {string | undefined}
|
|
45
|
+
* @private
|
|
46
|
+
*/
|
|
47
|
+
screenshotsFolder;
|
|
48
|
+
/**
|
|
49
|
+
* @type {ReporterInterface}
|
|
50
|
+
* @private
|
|
51
|
+
*/
|
|
52
|
+
reporter;
|
|
53
|
+
testBeginTime = Date.now();
|
|
54
|
+
options;
|
|
30
55
|
/**
|
|
31
56
|
* @param {Runner} runner
|
|
32
57
|
* @param {CypressQaseOptionsType} options
|
|
@@ -34,7 +59,6 @@ class CypressQaseReporter extends mocha_1.reporters.Base {
|
|
|
34
59
|
*/
|
|
35
60
|
constructor(runner, options, configLoader = new qase_javascript_commons_1.ConfigLoader(configSchema_1.configSchema)) {
|
|
36
61
|
super(runner, options);
|
|
37
|
-
this.testBeginTime = Date.now();
|
|
38
62
|
const { reporterOptions } = options;
|
|
39
63
|
const config = configLoader.load();
|
|
40
64
|
const { framework, ...composedOptions } = (0, qase_javascript_commons_1.composeOptions)(reporterOptions, config);
|
|
@@ -58,6 +82,7 @@ class CypressQaseReporter extends mocha_1.reporters.Base {
|
|
|
58
82
|
runner.on(EVENT_TEST_FAIL, (test) => this.addTestResult(test));
|
|
59
83
|
runner.on(EVENT_TEST_BEGIN, () => {
|
|
60
84
|
this.testBeginTime = Date.now();
|
|
85
|
+
manager_1.MetadataManager.clear();
|
|
61
86
|
});
|
|
62
87
|
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
63
88
|
runner.once(EVENT_RUN_END, () => {
|
|
@@ -82,9 +107,9 @@ class CypressQaseReporter extends mocha_1.reporters.Base {
|
|
|
82
107
|
return;
|
|
83
108
|
}
|
|
84
109
|
const ids = CypressQaseReporter.getCaseId(test.title);
|
|
85
|
-
const
|
|
110
|
+
const testFileName = this.getTestFileName(test);
|
|
86
111
|
const files = this.screenshotsFolder ?
|
|
87
|
-
fileSearcher_1.FileSearcher.findFilesBeforeTime(
|
|
112
|
+
fileSearcher_1.FileSearcher.findFilesBeforeTime(this.screenshotsFolder, testFileName, new Date(this.testBeginTime))
|
|
88
113
|
: [];
|
|
89
114
|
const attachments = files.map((file) => ({
|
|
90
115
|
content: '',
|
|
@@ -122,15 +147,21 @@ class CypressQaseReporter extends mocha_1.reporters.Base {
|
|
|
122
147
|
},
|
|
123
148
|
};
|
|
124
149
|
}
|
|
125
|
-
let message =
|
|
126
|
-
if (metadata?.comment) {
|
|
127
|
-
message = metadata.comment;
|
|
128
|
-
}
|
|
150
|
+
let message = metadata?.comment ?? '';
|
|
129
151
|
if (test.err?.message) {
|
|
130
|
-
|
|
131
|
-
|
|
152
|
+
message += message ? `\n\n${test.err.message}` : test.err.message;
|
|
153
|
+
}
|
|
154
|
+
const steps = metadata?.steps ? this.getSteps(metadata.steps, metadata.stepAttachments ?? {}) : [];
|
|
155
|
+
// support for cucumber steps and metadata
|
|
156
|
+
if (metadata?.cucumberSteps && metadata.cucumberSteps.length > 0) {
|
|
157
|
+
steps.push(...this.convertCypressMessages(metadata.cucumberSteps, test.state ?? 'failed'));
|
|
158
|
+
if (test.parent) {
|
|
159
|
+
const file = this.getFile(test.parent);
|
|
160
|
+
if (file) {
|
|
161
|
+
const tags = (0, tagParser_1.extractTags)(file, test.title);
|
|
162
|
+
ids.push(...this.extractQaseIds(tags));
|
|
163
|
+
}
|
|
132
164
|
}
|
|
133
|
-
message += test.err.message;
|
|
134
165
|
}
|
|
135
166
|
const result = {
|
|
136
167
|
attachments: attachments ?? [],
|
|
@@ -143,7 +174,7 @@ class CypressQaseReporter extends mocha_1.reporters.Base {
|
|
|
143
174
|
relations: relations,
|
|
144
175
|
run_id: null,
|
|
145
176
|
signature: this.getSignature(test, ids),
|
|
146
|
-
steps:
|
|
177
|
+
steps: steps,
|
|
147
178
|
id: (0, uuid_1.v4)(),
|
|
148
179
|
execution: {
|
|
149
180
|
status: test.state
|
|
@@ -220,6 +251,44 @@ class CypressQaseReporter extends mocha_1.reporters.Base {
|
|
|
220
251
|
}
|
|
221
252
|
return title;
|
|
222
253
|
}
|
|
254
|
+
/**
|
|
255
|
+
* Extracts numbers from @qaseid tags, regardless of case.
|
|
256
|
+
* @param tags - An array of tags to process.
|
|
257
|
+
* @returns An array of numbers extracted from the tags.
|
|
258
|
+
*/
|
|
259
|
+
extractQaseIds(tags) {
|
|
260
|
+
const qaseIdRegex = /@qaseid\((\d+(?:,\d+)*)\)/i;
|
|
261
|
+
const qaseIds = [];
|
|
262
|
+
for (const tag of tags) {
|
|
263
|
+
const match = qaseIdRegex.exec(tag);
|
|
264
|
+
if (match) {
|
|
265
|
+
const ids = match[1]?.split(',').map(id => parseInt(id, 10));
|
|
266
|
+
if (ids) {
|
|
267
|
+
qaseIds.push(...ids);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
return qaseIds;
|
|
272
|
+
}
|
|
273
|
+
convertCypressMessages(messages, testStatus) {
|
|
274
|
+
const result = [];
|
|
275
|
+
const lastIndex = messages.length - 1;
|
|
276
|
+
for (const message of messages) {
|
|
277
|
+
const step = new qase_javascript_commons_1.TestStepType(qase_javascript_commons_1.StepType.TEXT);
|
|
278
|
+
step.id = message.id;
|
|
279
|
+
step.execution.status = qase_javascript_commons_1.StepStatusEnum.passed;
|
|
280
|
+
step.execution.start_time = message.timestamp;
|
|
281
|
+
step.data = {
|
|
282
|
+
action: message.name,
|
|
283
|
+
expected_result: null,
|
|
284
|
+
};
|
|
285
|
+
if (lastIndex === messages.indexOf(message) && testStatus !== 'passed') {
|
|
286
|
+
step.execution.status = qase_javascript_commons_1.StepStatusEnum.failed;
|
|
287
|
+
}
|
|
288
|
+
result.push(step);
|
|
289
|
+
}
|
|
290
|
+
return result;
|
|
291
|
+
}
|
|
223
292
|
getSteps(steps, attachments) {
|
|
224
293
|
const result = [];
|
|
225
294
|
const stepMap = new Map();
|
|
@@ -262,15 +331,3 @@ class CypressQaseReporter extends mocha_1.reporters.Base {
|
|
|
262
331
|
}
|
|
263
332
|
}
|
|
264
333
|
exports.CypressQaseReporter = CypressQaseReporter;
|
|
265
|
-
/**
|
|
266
|
-
* @type {RegExp}
|
|
267
|
-
*/
|
|
268
|
-
CypressQaseReporter.qaseIdRegExp = /\(Qase ID:? ([\d,]+)\)/;
|
|
269
|
-
/**
|
|
270
|
-
* @type {Record<CypressState, TestStatusEnum>}
|
|
271
|
-
*/
|
|
272
|
-
CypressQaseReporter.statusMap = {
|
|
273
|
-
failed: qase_javascript_commons_1.TestStatusEnum.failed,
|
|
274
|
-
passed: qase_javascript_commons_1.TestStatusEnum.passed,
|
|
275
|
-
pending: qase_javascript_commons_1.TestStatusEnum.skipped,
|
|
276
|
-
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extracts tags for a given scenario name from a Gherkin feature file.
|
|
3
|
+
* @param filePath - Path to the feature file.
|
|
4
|
+
* @param scenarioName - Name of the scenario to search for.
|
|
5
|
+
* @returns An array of tags found for the specified scenario.
|
|
6
|
+
*/
|
|
7
|
+
export declare function extractTags(filePath: string, scenarioName: string): string[];
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.extractTags = void 0;
|
|
27
|
+
const fs = __importStar(require("fs"));
|
|
28
|
+
/**
|
|
29
|
+
* Extracts tags for a given scenario name from a Gherkin feature file.
|
|
30
|
+
* @param filePath - Path to the feature file.
|
|
31
|
+
* @param scenarioName - Name of the scenario to search for.
|
|
32
|
+
* @returns An array of tags found for the specified scenario.
|
|
33
|
+
*/
|
|
34
|
+
function extractTags(filePath, scenarioName) {
|
|
35
|
+
// Read the file content
|
|
36
|
+
const fileContent = fs.readFileSync(filePath, 'utf-8');
|
|
37
|
+
// Split the content into lines
|
|
38
|
+
const lines = fileContent.split('\n');
|
|
39
|
+
let tags = [];
|
|
40
|
+
for (let i = 0; i < lines.length; i++) {
|
|
41
|
+
const trimmedLine = lines[i]?.trim(); // Ensure line exists and trim it
|
|
42
|
+
// Check if the line is a Scenario line and matches the provided name
|
|
43
|
+
if (trimmedLine?.startsWith('Scenario:') && trimmedLine === `Scenario: ${scenarioName}`) {
|
|
44
|
+
// Collect tags from preceding lines
|
|
45
|
+
for (let j = i - 1; j >= 0; j--) {
|
|
46
|
+
const previousLine = lines[j]?.trim(); // Ensure line exists and trim it
|
|
47
|
+
if (previousLine?.startsWith('@')) {
|
|
48
|
+
tags = previousLine.split(/\s+/).filter(tag => tag.startsWith('@'));
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
else if (previousLine === '' || previousLine?.startsWith('Feature:')) {
|
|
52
|
+
// Stop searching if an empty line or the start of a feature is reached
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
break; // Stop processing further as the scenario is found
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return tags;
|
|
60
|
+
}
|
|
61
|
+
exports.extractTags = extractTags;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cypress-qase-reporter",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.6",
|
|
4
4
|
"description": "Qase Cypress Reporter",
|
|
5
5
|
"homepage": "https://github.com/qase-tms/qase-javascript",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
"./package.json": "./package.json",
|
|
14
14
|
"./plugin": "./dist/plugin.js",
|
|
15
15
|
"./metadata": "./dist/metadata.js",
|
|
16
|
-
"./hooks": "./dist/hooks.js"
|
|
16
|
+
"./hooks": "./dist/hooks.js",
|
|
17
|
+
"./cucumber": "./dist/cucumber.js"
|
|
17
18
|
},
|
|
18
19
|
"typesVersions": {
|
|
19
20
|
"*": {
|
|
@@ -25,6 +26,9 @@
|
|
|
25
26
|
],
|
|
26
27
|
"reporter": [
|
|
27
28
|
"./dist/reporter.d.ts"
|
|
29
|
+
],
|
|
30
|
+
"cucumber": [
|
|
31
|
+
"./dist/cucumber.d.ts"
|
|
28
32
|
]
|
|
29
33
|
}
|
|
30
34
|
},
|