cypress-qase-reporter 3.0.2 → 3.1.0

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
@@ -138,6 +138,10 @@ parameterize your tests.
138
138
  - `qase.step` - create a step in the test case
139
139
  - `qase.attach` - attach a file or content to the test case
140
140
 
141
+ #### Cucumber-specific
142
+
143
+ - `addCucumberStep(stepName)` - manually add a Cucumber step to Qase report (useful for `@badeball/cypress-cucumber-preprocessor`)
144
+
141
145
  For detailed instructions on using annotations and methods, refer to [Usage](docs/usage.md).
142
146
 
143
147
  For example:
@@ -255,71 +259,23 @@ module.exports = cypress.defineConfig({
255
259
  Check out the example of configuration for multiple reporters in the
256
260
  [demo project](../examples/cypress/cypress.config.js).
257
261
 
258
- If you use Cucumber, you need to add the following configuration in `cypress.config.js`:
262
+ ## Cucumber/Gherkin Integration
259
263
 
260
- ```javascript
261
- import cypress from 'cypress';
262
- import { afterSpecHook } from 'cypress-qase-reporter/hooks';
263
-
264
- const cucumber = require('cypress-cucumber-preprocessor').default;
264
+ If you use Cucumber with Gherkin feature files in your Cypress tests, Qase reporter provides full support for both the legacy `cypress-cucumber-preprocessor` and the modern `@badeball/cypress-cucumber-preprocessor`.
265
265
 
266
- module.exports = cypress.defineConfig({
267
- reporter: 'cypress-multi-reporters',
268
- reporterOptions: {
269
- reporterEnabled: 'cypress-mochawesome-reporter, cypress-qase-reporter',
270
- cypressMochawesomeReporterReporterOptions: {
271
- charts: true,
272
- },
273
- cypressQaseReporterReporterOptions: {
274
- debug: true,
266
+ The reporter can automatically:
275
267
 
276
- testops: {
277
- api: {
278
- token: 'api_key',
279
- },
268
+ - Extract test cases from feature files
269
+ - Report individual Gherkin steps (Given/When/Then) with their execution status
270
+ - Link test results to Qase test cases using `@QaseID` tags
271
+ - Attach screenshots and videos to test results
280
272
 
281
- project: 'project_code',
282
- uploadAttachments: true,
273
+ **📚 For detailed instructions, configuration examples, and troubleshooting, see the [Cucumber Integration Guide](docs/cucumber.md).**
283
274
 
284
- run: {
285
- complete: true,
286
- },
287
- },
275
+ **Quick links:**
288
276
 
289
- framework: {
290
- cypress: {
291
- screenshotsFolder: 'cypress/screenshots',
292
- videosFolder: 'cypress/videos',
293
- uploadDelay: 10, // Delay in seconds before uploading video files (default: 10)
294
- },
295
- },
296
- },
297
- },
298
- video: false,
299
- e2e: {
300
- setupNodeEvents(on, config) {
301
- on('file:preprocessor', cucumber());
302
- require('cypress-qase-reporter/plugin')(on, config);
303
- require('cypress-qase-reporter/metadata')(on);
304
- on('after:spec', async (spec, results) => {
305
- await afterSpecHook(spec, config);
306
- });
307
- },
308
- specPattern: 'cypress/e2e/*.feature',
309
- },
310
- });
311
- ```
312
-
313
- And add the following lines in `support/e2e.js` file:
314
-
315
- ```javascript
316
- import { enableCucumberSupport } from "cypress-qase-reporter";
317
-
318
- enableCucumberSupport();
319
- ```
320
-
321
- Check out the example of configuration for multiple reporters in the
322
- [demo project](../examples/cypressCucumber/cypress.config.js).
277
+ - [Example project for @badeball/cypress-cucumber-preprocessor](../examples/cypressBadeballCucumber/)
278
+ - [Example project for cypress-cucumber-preprocessor (legacy)](../examples/cypressCucumber/)
323
279
 
324
280
  ## Requirements
325
281
 
package/changelog.md CHANGED
@@ -1,3 +1,17 @@
1
+ # cypress-qase-reporter@3.1.0
2
+
3
+ ## What's new
4
+
5
+ - Added support for Cucumber steps reporting for `@badeball/cypress-cucumber-preprocessor`.
6
+ - Added `addCucumberStep` function to manually add a Cucumber step to Qase report.
7
+
8
+ # cypress-qase-reporter@3.0.3
9
+
10
+ ## What's new
11
+
12
+ - Added support for status filter in the test run.
13
+ - Improved error handling.
14
+
1
15
  # cypress-qase-reporter@3.0.2
2
16
 
3
17
  ## What's new
@@ -1 +1,31 @@
1
+ /**
2
+ * Enable automatic Cucumber step reporting for cypress-cucumber-preprocessor (legacy).
3
+ * This function automatically captures Gherkin steps and reports them to Qase.
4
+ *
5
+ * @example
6
+ * ```javascript
7
+ * // In cypress/support/e2e.js
8
+ * import { enableCucumberSupport } from 'cypress-qase-reporter/cucumber';
9
+ *
10
+ * enableCucumberSupport();
11
+ * ```
12
+ */
1
13
  export declare const enableCucumberSupport: () => void;
14
+ /**
15
+ * Manually add a cucumber step to Qase report.
16
+ * Use this function in Before/After hooks or directly in step definitions
17
+ * when using @badeball/cypress-cucumber-preprocessor.
18
+ *
19
+ * @param stepName - The name of the step (e.g., "Given I am on the homepage")
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * import { Before } from '@badeball/cypress-cucumber-preprocessor';
24
+ * import { addCucumberStep } from 'cypress-qase-reporter/cucumber';
25
+ *
26
+ * Before(function() {
27
+ * addCucumberStep(this.pickle.name);
28
+ * });
29
+ * ```
30
+ */
31
+ export declare const addCucumberStep: (stepName: string) => void;
package/dist/cucumber.js CHANGED
@@ -1,25 +1,79 @@
1
1
  "use strict";
2
+ /// <reference types="cypress" />
2
3
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.enableCucumberSupport = void 0;
4
+ exports.addCucumberStep = exports.enableCucumberSupport = void 0;
4
5
  const CUCUMBER_TASK_NAME = 'qaseCucumberStepStart';
6
+ /**
7
+ * Enable automatic Cucumber step reporting for cypress-cucumber-preprocessor (legacy).
8
+ * This function automatically captures Gherkin steps and reports them to Qase.
9
+ *
10
+ * @example
11
+ * ```javascript
12
+ * // In cypress/support/e2e.js
13
+ * import { enableCucumberSupport } from 'cypress-qase-reporter/cucumber';
14
+ *
15
+ * enableCucumberSupport();
16
+ * ```
17
+ */
5
18
  const enableCucumberSupport = () => {
6
- registerCypressEventListeners();
7
- };
8
- exports.enableCucumberSupport = enableCucumberSupport;
9
- const registerCypressEventListeners = () => {
10
19
  Cypress.on('log:added', handleLogAdded);
11
20
  };
21
+ exports.enableCucumberSupport = enableCucumberSupport;
12
22
  const handleLogAdded = (_, entry) => {
13
23
  if (isCucumberStep(entry)) {
14
24
  processCucumberStep(entry);
15
25
  }
16
26
  };
17
- const isCucumberStep = ({ attributes: { name, event, instrument } }) => {
27
+ const isCucumberStep = (entry) => {
28
+ const { attributes: { name, event, instrument } } = entry;
18
29
  return instrument === 'command' && !event && name === 'step';
19
30
  };
20
- const processCucumberStep = ({ attributes: { displayName, message } }) => {
31
+ const processCucumberStep = (entry) => {
32
+ const { attributes: { displayName, message } } = entry;
21
33
  sendTaskMessage(`${displayName ?? ''} ${message}`);
22
34
  };
23
35
  const sendTaskMessage = (message) => {
24
36
  cy.task(CUCUMBER_TASK_NAME, message, { log: false });
25
37
  };
38
+ /**
39
+ * Manually add a cucumber step to Qase report.
40
+ * Use this function in Before/After hooks or directly in step definitions
41
+ * when using @badeball/cypress-cucumber-preprocessor.
42
+ *
43
+ * @param stepName - The name of the step (e.g., "Given I am on the homepage")
44
+ *
45
+ * @example
46
+ * ```typescript
47
+ * import { Before } from '@badeball/cypress-cucumber-preprocessor';
48
+ * import { addCucumberStep } from 'cypress-qase-reporter/cucumber';
49
+ *
50
+ * Before(function() {
51
+ * addCucumberStep(this.pickle.name);
52
+ * });
53
+ * ```
54
+ */
55
+ const addCucumberStep = (stepName) => {
56
+ // Use Cypress.log to avoid command queue issues
57
+ // The step will be collected by MetadataManager
58
+ try {
59
+ if (stepName && stepName.trim()) {
60
+ Cypress.log({
61
+ name: 'qase:step',
62
+ message: stepName,
63
+ consoleProps: () => ({
64
+ Step: stepName,
65
+ }),
66
+ });
67
+ // Also send to task for backend collection
68
+ // We need to wrap this in a way that doesn't interfere with command queue
69
+ cy.then(() => {
70
+ cy.task(CUCUMBER_TASK_NAME, stepName, { log: false });
71
+ });
72
+ }
73
+ }
74
+ catch (e) {
75
+ // Silently fail if Cypress is not available
76
+ console.debug('Failed to add cucumber step:', e);
77
+ }
78
+ };
79
+ exports.addCucumberStep = addCucumberStep;
@@ -15,13 +15,23 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
15
15
  }) : function(o, v) {
16
16
  o["default"] = v;
17
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
- };
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
25
35
  Object.defineProperty(exports, "__esModule", { value: true });
26
36
  exports.FileSearcher = void 0;
27
37
  const fs = __importStar(require("fs"));
package/dist/hooks.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- /// <reference types="cypress" />
2
1
  import PluginConfigOptions = Cypress.PluginConfigOptions;
3
2
  import Spec = Cypress.Spec;
4
3
  declare function beforeRunHook(options: PluginConfigOptions): Promise<void>;
package/dist/hooks.js CHANGED
@@ -4,7 +4,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  return (mod && mod.__esModule) ? mod : { "default": mod };
5
5
  };
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.afterSpecHook = exports.afterRunHook = exports.beforeRunHook = void 0;
7
+ exports.beforeRunHook = beforeRunHook;
8
+ exports.afterRunHook = afterRunHook;
9
+ exports.afterSpecHook = afterSpecHook;
8
10
  const qase_javascript_commons_1 = require("qase-javascript-commons");
9
11
  const configSchema_1 = require("./configSchema");
10
12
  const resultsManager_1 = require("./metadata/resultsManager");
@@ -28,7 +30,6 @@ async function beforeRunHook(options) {
28
30
  // eslint-disable-next-line @typescript-eslint/no-unsafe-call
29
31
  await reporter.startTestRunAsync();
30
32
  }
31
- exports.beforeRunHook = beforeRunHook;
32
33
  async function afterRunHook(options) {
33
34
  const configLoader = new qase_javascript_commons_1.ConfigLoader(configSchema_1.configSchema);
34
35
  const config = configLoader.load();
@@ -44,7 +45,6 @@ async function afterRunHook(options) {
44
45
  });
45
46
  await reporter.complete();
46
47
  }
47
- exports.afterRunHook = afterRunHook;
48
48
  async function afterSpecHook(spec, options) {
49
49
  const results = resultsManager_1.ResultsManager.getResults();
50
50
  if (results) {
@@ -131,4 +131,3 @@ async function afterSpecHook(spec, options) {
131
131
  }
132
132
  resultsManager_1.ResultsManager.clear();
133
133
  }
134
- exports.afterSpecHook = afterSpecHook;
@@ -1,3 +1,3 @@
1
1
  export { qase } from './mocha';
2
- export { enableCucumberSupport } from './cucumber';
2
+ export { enableCucumberSupport, addCucumberStep } from './cucumber';
3
3
  export { ResultsManager } from './metadata/resultsManager';
package/dist/index.cjs.js CHANGED
@@ -1,9 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ResultsManager = exports.enableCucumberSupport = exports.qase = void 0;
3
+ exports.ResultsManager = exports.addCucumberStep = 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
6
  var cucumber_1 = require("./cucumber");
7
7
  Object.defineProperty(exports, "enableCucumberSupport", { enumerable: true, get: function () { return cucumber_1.enableCucumberSupport; } });
8
+ Object.defineProperty(exports, "addCucumberStep", { enumerable: true, get: function () { return cucumber_1.addCucumberStep; } });
8
9
  var resultsManager_1 = require("./metadata/resultsManager");
9
10
  Object.defineProperty(exports, "ResultsManager", { enumerable: true, get: function () { return resultsManager_1.ResultsManager; } });
@@ -1,4 +1,3 @@
1
- /// <reference types="node" />
2
1
  import { Attachment } from 'qase-javascript-commons';
3
2
  export interface Metadata {
4
3
  title?: string | undefined;
package/dist/metadata.js CHANGED
@@ -68,4 +68,10 @@ module.exports = function (on) {
68
68
  return null;
69
69
  },
70
70
  });
71
+ on('task', {
72
+ log(message) {
73
+ console.log(message);
74
+ return null;
75
+ },
76
+ });
71
77
  };
package/dist/mocha.d.ts CHANGED
@@ -1,104 +1,14 @@
1
- /// <reference types="cypress" />
2
- /// <reference types="cypress" />
3
- /// <reference types="cypress" />
4
- /// <reference types="cypress" />
5
- /// <reference types="node" />
6
1
  import { Test } from 'mocha';
7
2
  export declare const qase: {
8
3
  (caseId: number | string | number[] | string[], test: Test): Test;
9
- /**
10
- * Set a title for the test case
11
- * @param {string} value
12
- * @example
13
- * it('test', () => {
14
- * qase.title("Title");
15
- * cy.visit('https://example.com');
16
- * });
17
- */
18
4
  title(value: string): Cypress.Chainable<JQuery<void>>;
19
- /**
20
- * Set fields for the test case
21
- * @param {Record<string, string>} values
22
- * @example
23
- * it('test', () => {
24
- * qase.fields({description: "Description"});
25
- * cy.visit('https://example.com');
26
- * });
27
- */
28
5
  fields(values: Record<string, string>): Cypress.Chainable<JQuery<void>>;
29
- /**
30
- * Ignore the test case result in Qase
31
- * @example
32
- * it('test', () => {
33
- * qase.ignore();
34
- * cy.visit('https://example.com');
35
- * });
36
- */
37
6
  ignore(): Cypress.Chainable<JQuery<void>>;
38
- /**
39
- * Set parameters for the test case
40
- * @param {Record<string, string>} values
41
- * @example
42
- * it('test', () => {
43
- * qase.parameters({param01: "value01"});
44
- * cy.visit('https://example.com');
45
- * });
46
- */
47
7
  parameters(values: Record<string, string>): Cypress.Chainable<JQuery<void>>;
48
- /**
49
- * Set group parameters for the test case
50
- * @param {Record<string, string>} values
51
- * @example
52
- * it('test', () => {
53
- * qase.groupParameters({param01: "value01"});
54
- * cy.visit('https://example.com');
55
- * });
56
- */
57
8
  groupParameters(values: Record<string, string>): Cypress.Chainable<JQuery<void>>;
58
- /**
59
- * Set a suite for the test case
60
- * @param {string} value
61
- * @example
62
- * it('test', () => {
63
- * qase.suite("Suite 01");
64
- * cy.visit('https://example.com');
65
- * });
66
- */
67
9
  suite(value: string): Cypress.Chainable<JQuery<void>>;
68
- /**
69
- * Set a comment for the test case
70
- * @param {string} value
71
- * @example
72
- * it('test', () => {
73
- * qase.comment("Some comment");
74
- * cy.visit('https://example.com');
75
- * });
76
- */
77
10
  comment(value: string): Cypress.Chainable<JQuery<void>>;
78
- /**
79
- * Add a step to the test case
80
- * @param {string} name
81
- * @param {() => T | PromiseLike<T>} body
82
- * @example
83
- * it('test', () => {
84
- * qase.step("Some step", () => {
85
- * // some actions
86
- * });
87
- * cy.visit('https://example.com');
88
- * });
89
- */
90
11
  step<T = void>(name: string, body: () => T | PromiseLike<T>): Cypress.Chainable<JQuery<void>>;
91
- /**
92
- * Attach a file to the test case or the step
93
- * @param attach
94
- * @example
95
- * it('test', () => {
96
- * qase.attach({ name: 'attachment.txt', content: 'Hello, world!', contentType: 'text/plain' });
97
- * qase.attach({ paths: '/path/to/file'});
98
- * qase.attach({ paths: ['/path/to/file', '/path/to/another/file']});
99
- * cy.visit('https://example.com');
100
- * });
101
- */
102
12
  attach(attach: {
103
13
  name?: string;
104
14
  paths?: string | string[];
@@ -1,4 +1,3 @@
1
- /// <reference types="cypress" />
2
1
  import { MochaOptions, reporters, Runner } from 'mocha';
3
2
  import { ConfigLoader, TestStatusEnum } from 'qase-javascript-commons';
4
3
  import { ReporterOptionsType } from './options';
package/dist/reporter.js CHANGED
@@ -198,9 +198,7 @@ class CypressQaseReporter extends mocha_1.reporters.Base {
198
198
  steps: steps,
199
199
  id: (0, uuid_1.v4)(),
200
200
  execution: {
201
- status: test.state
202
- ? CypressQaseReporter.statusMap[test.state]
203
- : qase_javascript_commons_1.TestStatusEnum.invalid,
201
+ status: (0, qase_javascript_commons_1.determineTestStatus)(test.err || null, test.state || 'failed'),
204
202
  start_time: this.testBeginTime / 1000,
205
203
  end_time: end_time / 1000,
206
204
  duration: duration,
@@ -15,15 +15,25 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
15
15
  }) : function(o, v) {
16
16
  o["default"] = v;
17
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
- };
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
25
35
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.extractTags = void 0;
36
+ exports.extractTags = extractTags;
27
37
  const fs = __importStar(require("fs"));
28
38
  /**
29
39
  * Extracts tags for a given scenario name from a Gherkin feature file.
@@ -58,4 +68,3 @@ function extractTags(filePath, scenarioName) {
58
68
  }
59
69
  return tags;
60
70
  }
61
- exports.extractTags = extractTags;
@@ -0,0 +1,329 @@
1
+ # Cucumber/Gherkin Integration with Qase Reporter
2
+
3
+ This guide explains how to integrate Qase reporter with Cucumber/Gherkin tests in Cypress using either the legacy `cypress-cucumber-preprocessor` or the newer `@badeball/cypress-cucumber-preprocessor`.
4
+
5
+ ---
6
+
7
+ ## Table of Contents
8
+
9
+ - [Choosing a Preprocessor](#choosing-a-preprocessor)
10
+ - [Configuration for @badeball/cypress-cucumber-preprocessor (Recommended)](#configuration-for-badeballcypress-cucumber-preprocessor-recommended)
11
+ - [Configuration for cypress-cucumber-preprocessor (Legacy)](#configuration-for-cypress-cucumber-preprocessor-legacy)
12
+ - [Cucumber Steps Reporting](#cucumber-steps-reporting)
13
+ - [Examples](#examples)
14
+
15
+ ---
16
+
17
+ ## Choosing a Preprocessor
18
+
19
+ There are two Cucumber preprocessors available for Cypress:
20
+
21
+ - **`@badeball/cypress-cucumber-preprocessor`** (Recommended) - Actively maintained, modern implementation
22
+ - **`cypress-cucumber-preprocessor`** (Legacy) - Original implementation, now deprecated
23
+
24
+ This guide covers both, but we recommend using `@badeball/cypress-cucumber-preprocessor` for new projects.
25
+
26
+ ---
27
+
28
+ ## Configuration for @badeball/cypress-cucumber-preprocessor (Recommended)
29
+
30
+ ### Installation
31
+
32
+ ```bash
33
+ npm install -D @badeball/cypress-cucumber-preprocessor
34
+ npm install -D @bahmutov/cypress-esbuild-preprocessor
35
+ npm install -D cypress-qase-reporter
36
+ ```
37
+
38
+ ### Cypress Configuration
39
+
40
+ Update your `cypress.config.js`:
41
+
42
+ ```javascript
43
+ import cypress from 'cypress';
44
+ import { afterSpecHook } from 'cypress-qase-reporter/hooks';
45
+ const createBundler = require('@bahmutov/cypress-esbuild-preprocessor');
46
+ const addCucumberPreprocessorPlugin = require('@badeball/cypress-cucumber-preprocessor').addCucumberPreprocessorPlugin;
47
+ const createEsbuildPlugin = require('@badeball/cypress-cucumber-preprocessor/esbuild').createEsbuildPlugin;
48
+
49
+ module.exports = cypress.defineConfig({
50
+ reporter: 'cypress-multi-reporters',
51
+ reporterOptions: {
52
+ reporterEnabled: 'cypress-qase-reporter',
53
+ cypressQaseReporterReporterOptions: {
54
+ debug: true,
55
+ testops: {
56
+ api: {
57
+ token: 'api_token',
58
+ },
59
+ project: 'project_code',
60
+ uploadAttachments: true,
61
+ run: {
62
+ complete: true,
63
+ },
64
+ },
65
+ framework: {
66
+ cypress: {
67
+ screenshotsFolder: 'cypress/screenshots',
68
+ },
69
+ },
70
+ },
71
+ },
72
+ video: false,
73
+ e2e: {
74
+ specPattern: 'cypress/e2e/**/*.feature',
75
+ async setupNodeEvents(on, config) {
76
+ // 1. Set up the Cucumber preprocessor FIRST
77
+ await addCucumberPreprocessorPlugin(on, config);
78
+ on(
79
+ 'file:preprocessor',
80
+ createBundler({
81
+ plugins: [createEsbuildPlugin(config)],
82
+ })
83
+ );
84
+
85
+ // 2. Set up the Qase reporter plugin
86
+ require('cypress-qase-reporter/plugin')(on, config);
87
+ require('cypress-qase-reporter/metadata')(on);
88
+
89
+ // 3. Register the after:spec hook
90
+ on('after:spec', async (spec, results) => {
91
+ await afterSpecHook(spec, config);
92
+ });
93
+
94
+ return config;
95
+ },
96
+ },
97
+ });
98
+ ```
99
+
100
+ ### Cucumber Steps Reporting
101
+
102
+ To automatically capture and report Gherkin steps to Qase, create a hooks file.
103
+
104
+ Create `cypress/support/step_definitions/hooks.js`:
105
+
106
+ ```javascript
107
+ import { BeforeStep } from '@badeball/cypress-cucumber-preprocessor';
108
+ import { addCucumberStep } from 'cypress-qase-reporter/cucumber';
109
+
110
+ // Automatically report each Gherkin step to Qase
111
+ BeforeStep(function({ pickleStep }) {
112
+ const keyword = pickleStep.keyword || '';
113
+ const stepText = `${keyword}${pickleStep.text}`;
114
+ addCucumberStep(stepText);
115
+ });
116
+ ```
117
+
118
+ This hook will automatically:
119
+ - Capture each Gherkin step (Given/When/Then/And/But)
120
+ - Report it to Qase with the correct execution status (passed/failed)
121
+ - Include step details in your test results
122
+
123
+ **Note:** Step reporting is optional. If you only need test-level results without individual step details, you can skip this configuration.
124
+
125
+ ### Manual Step Reporting (Alternative)
126
+
127
+ If you prefer more control, you can manually add steps in your step definitions:
128
+
129
+ ```javascript
130
+ import { Given, When, Then } from '@badeball/cypress-cucumber-preprocessor';
131
+ import { addCucumberStep } from 'cypress-qase-reporter/cucumber';
132
+
133
+ Given('I am on the homepage', () => {
134
+ addCucumberStep('Given I am on the homepage');
135
+ cy.visit('https://example.com');
136
+ });
137
+
138
+ When('I click the button', () => {
139
+ addCucumberStep('When I click the button');
140
+ cy.get('button').click();
141
+ });
142
+
143
+ Then('I should see the result', () => {
144
+ addCucumberStep('Then I should see the result');
145
+ cy.get('.result').should('be.visible');
146
+ });
147
+ ```
148
+
149
+ ---
150
+
151
+ ## Configuration for cypress-cucumber-preprocessor (Legacy)
152
+
153
+ ### Installation
154
+
155
+ ```bash
156
+ npm install -D cypress-cucumber-preprocessor
157
+ npm install -D cypress-qase-reporter
158
+ ```
159
+
160
+ ### Cypress Configuration
161
+
162
+ Update your `cypress.config.js`:
163
+
164
+ ```javascript
165
+ import cypress from 'cypress';
166
+ import { afterSpecHook } from 'cypress-qase-reporter/hooks';
167
+
168
+ module.exports = cypress.defineConfig({
169
+ reporter: 'cypress-multi-reporters',
170
+ reporterOptions: {
171
+ reporterEnabled: 'cypress-qase-reporter',
172
+ cypressQaseReporterReporterOptions: {
173
+ debug: true,
174
+ testops: {
175
+ api: {
176
+ token: 'api_token',
177
+ },
178
+ project: 'project_code',
179
+ uploadAttachments: true,
180
+ run: {
181
+ complete: true,
182
+ },
183
+ },
184
+ framework: {
185
+ cypress: {
186
+ screenshotsFolder: 'cypress/screenshots',
187
+ },
188
+ },
189
+ },
190
+ },
191
+ video: false,
192
+ e2e: {
193
+ specPattern: '**/*.feature',
194
+ async setupNodeEvents(on, config) {
195
+ require('cypress-qase-reporter/plugin')(on, config);
196
+ require('cypress-qase-reporter/metadata')(on);
197
+
198
+ on('after:spec', async (spec, results) => {
199
+ await afterSpecHook(spec, config);
200
+ });
201
+
202
+ return config;
203
+ },
204
+ },
205
+ });
206
+ ```
207
+
208
+ ### Cucumber Steps Reporting
209
+
210
+ For the legacy preprocessor, add the following to your `cypress/support/e2e.js` file:
211
+
212
+ ```javascript
213
+ import { enableCucumberSupport } from 'cypress-qase-reporter/cucumber';
214
+
215
+ enableCucumberSupport();
216
+ ```
217
+
218
+ This will automatically capture all Gherkin steps and report them to Qase. No additional configuration is needed.
219
+
220
+ ---
221
+
222
+ ## Cucumber Steps Reporting
223
+
224
+ ### What Gets Reported
225
+
226
+ When you enable Cucumber steps reporting, the following information is sent to Qase for each step:
227
+
228
+ - **Step text** - The full Gherkin step (e.g., "Given I am on the homepage")
229
+ - **Step status** - Whether the step passed or failed
230
+ - **Step timing** - When the step started execution
231
+ - **Step attachments** - Any screenshots or files attached during the step
232
+
233
+ ### Example Feature File
234
+
235
+ ```gherkin
236
+ Feature: User Login
237
+
238
+ @QaseID(1)
239
+ Scenario: Successful login
240
+ Given I am on the login page
241
+ When I enter valid credentials
242
+ And I click the login button
243
+ Then I should see the dashboard
244
+ And I should see my username
245
+
246
+ @QaseID(2)
247
+ Scenario: Failed login
248
+ Given I am on the login page
249
+ When I enter invalid credentials
250
+ And I click the login button
251
+ Then I should see an error message
252
+ ```
253
+
254
+ ### Adding Qase IDs
255
+
256
+ You can associate Qase test case IDs with your scenarios using tags:
257
+
258
+ - Single ID: `@QaseID(123)`
259
+ - Multiple IDs: `@QaseID(123,456)`
260
+
261
+ The Qase reporter will automatically extract these IDs and link the test results to the corresponding test cases in Qase.
262
+
263
+ ---
264
+
265
+ ## Examples
266
+
267
+ ### Complete Working Examples
268
+
269
+ Check out our example projects:
270
+
271
+ - **[@badeball/cypress-cucumber-preprocessor Example](../../examples/cypressBadeballCucumber/)** - Modern implementation with automatic step reporting
272
+ - **[cypress-cucumber-preprocessor Example](../../examples/cypressCucumber/)** - Legacy implementation
273
+
274
+ Each example includes:
275
+ - Complete Cypress configuration
276
+ - Feature files with Gherkin scenarios
277
+ - Step definitions
278
+ - Qase reporter integration
279
+ - Automatic step reporting setup
280
+
281
+ ### Running the Examples
282
+
283
+ ```bash
284
+ # Navigate to the example directory
285
+ cd examples/cypressBadeballCucumber
286
+
287
+ # Install dependencies
288
+ npm install
289
+
290
+ # Set your Qase credentials in cypress.config.js
291
+
292
+ # Run tests
293
+ npm test
294
+ ```
295
+
296
+ ---
297
+
298
+ ## Troubleshooting
299
+
300
+ ### Steps are not being reported
301
+
302
+ **For @badeball/cypress-cucumber-preprocessor:**
303
+ - Ensure you've created the `hooks.js` file with the `BeforeStep` hook
304
+ - Verify the file is in `cypress/support/step_definitions/` directory
305
+ - Check that you're importing `addCucumberStep` from `'cypress-qase-reporter/cucumber'`
306
+
307
+ **For cypress-cucumber-preprocessor (legacy):**
308
+ - Verify you've called `enableCucumberSupport()` in `cypress/support/e2e.js`
309
+ - Ensure you're importing from `'cypress-qase-reporter/cucumber'`
310
+
311
+ ### Cypress command queue errors
312
+
313
+ If you see errors like "Cypress detected that you returned a promise from a command", make sure you're using the provided `addCucumberStep` function, which properly handles the Cypress command queue.
314
+
315
+ ### Test results not appearing in Qase
316
+
317
+ - Verify your API token is correct in `cypress.config.js`
318
+ - Check that your project code matches your Qase project
319
+ - Enable `debug: true` in reporter options to see detailed logs
320
+ - Ensure `mode: 'testops'` is set in your configuration
321
+
322
+ ---
323
+
324
+ ## Additional Resources
325
+
326
+ - [Qase Reporter Configuration](../README.md#configuration)
327
+ - [Qase Reporter Usage Guide](./usage.md)
328
+ - [@badeball/cypress-cucumber-preprocessor Documentation](https://github.com/badeball/cypress-cucumber-preprocessor)
329
+ - [Cypress Documentation](https://docs.cypress.io/)
package/docs/usage.md CHANGED
@@ -194,3 +194,65 @@ it('test', () => {
194
194
  cy.visit('https://example.com');
195
195
  });
196
196
  ```
197
+
198
+ ---
199
+
200
+ ## Cucumber Steps Reporting
201
+
202
+ ### For @badeball/cypress-cucumber-preprocessor
203
+
204
+ When using `@badeball/cypress-cucumber-preprocessor`, you can automatically report Cucumber/Gherkin steps to Qase using the `addCucumberStep` function in a `BeforeStep` hook.
205
+
206
+ #### Automatic Step Reporting
207
+
208
+ Create a file `cypress/support/step_definitions/hooks.js`:
209
+
210
+ ```javascript
211
+ import { BeforeStep } from '@badeball/cypress-cucumber-preprocessor';
212
+ import { addCucumberStep } from 'cypress-qase-reporter/cucumber';
213
+
214
+ // Automatically report each Gherkin step to Qase
215
+ BeforeStep(function({ pickleStep }) {
216
+ const keyword = pickleStep.keyword || '';
217
+ const stepText = `${keyword}${pickleStep.text}`;
218
+ addCucumberStep(stepText);
219
+ });
220
+ ```
221
+
222
+ This will automatically capture each step (Given/When/Then/And/But) and report it to Qase with its execution status.
223
+
224
+ #### Manual Step Reporting
225
+
226
+ Alternatively, you can manually add steps in your step definitions:
227
+
228
+ ```javascript
229
+ import { Given, When, Then } from '@badeball/cypress-cucumber-preprocessor';
230
+ import { addCucumberStep } from 'cypress-qase-reporter/cucumber';
231
+
232
+ Given('I am on the homepage', () => {
233
+ addCucumberStep('Given I am on the homepage');
234
+ cy.visit('https://example.com');
235
+ });
236
+
237
+ When('I click the button', () => {
238
+ addCucumberStep('When I click the button');
239
+ cy.get('button').click();
240
+ });
241
+
242
+ Then('I should see the result', () => {
243
+ addCucumberStep('Then I should see the result');
244
+ cy.get('.result').should('be.visible');
245
+ });
246
+ ```
247
+
248
+ ### For cypress-cucumber-preprocessor (legacy)
249
+
250
+ For the legacy `cypress-cucumber-preprocessor`, steps are automatically captured. Add the following to your `support/e2e.js` file:
251
+
252
+ ```javascript
253
+ import { enableCucumberSupport } from 'cypress-qase-reporter/cucumber';
254
+
255
+ enableCucumberSupport();
256
+ ```
257
+
258
+ No additional configuration is needed - all Gherkin steps will be automatically reported to Qase.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cypress-qase-reporter",
3
- "version": "3.0.2",
3
+ "version": "3.1.0",
4
4
  "description": "Qase Cypress Reporter",
5
5
  "homepage": "https://github.com/qase-tms/qase-javascript",
6
6
  "sideEffects": false,
@@ -51,7 +51,7 @@
51
51
  "author": "Qase Team <support@qase.io>",
52
52
  "license": "Apache-2.0",
53
53
  "dependencies": {
54
- "qase-javascript-commons": "~2.4.1",
54
+ "qase-javascript-commons": "~2.4.5",
55
55
  "uuid": "^9.0.1"
56
56
  },
57
57
  "peerDependencies": {