mocha-qase-reporter 1.1.7 → 1.2.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
@@ -67,6 +67,12 @@ A test run will be performed and available at:
67
67
  https://app.qase.io/run/QASE_PROJECT_CODE
68
68
  ```
69
69
 
70
+ ### Multi-Project Support
71
+
72
+ Qase Mocha Reporter supports sending test results to multiple Qase projects simultaneously. You can specify different test case IDs for each project using `qase.projects(mapping, name)`.
73
+
74
+ For detailed information, configuration, and examples, see the [Multi-Project Support Guide](docs/MULTI_PROJECT.md).
75
+
70
76
  ### Parallel execution
71
77
 
72
78
  The reporter supports parallel execution of tests.
package/changelog.md CHANGED
@@ -1,3 +1,15 @@
1
+ # qase-mocha@1.2.0
2
+
3
+ ## What's new
4
+
5
+ - Added support for multi-project support.
6
+
7
+ # qase-mocha@1.1.8
8
+
9
+ ## What's new
10
+
11
+ - Added support for expected results and data for steps.
12
+
1
13
  # qase-mocha@1.1.6
2
14
 
3
15
  ## What's new
package/dist/mocha.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ /** Project code → test case IDs for multi-project (testops_multi) mode. */
2
+ export type ProjectMapping = Record<string, number[]>;
1
3
  /**
2
4
  * Set IDs for the test case
3
5
  *
@@ -9,4 +11,7 @@
9
11
  * });
10
12
  * @returns {string}
11
13
  */
12
- export declare const qase: (caseId: number | string | number[] | string[], name: string) => string;
14
+ export declare const qase: {
15
+ (caseId: number | string | number[] | string[], name: string): string;
16
+ projects(mapping: ProjectMapping, name: string): string;
17
+ };
package/dist/mocha.js CHANGED
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.qase = void 0;
4
+ const qase_javascript_commons_1 = require("qase-javascript-commons");
4
5
  /**
5
6
  * Set IDs for the test case
6
7
  *
@@ -30,3 +31,12 @@ const qase = (caseId, name) => {
30
31
  return `${name} (Qase ID: ${caseIds.join(',')})`;
31
32
  };
32
33
  exports.qase = qase;
34
+ /**
35
+ * Build test name with multi-project markers (for testops_multi mode).
36
+ * @param mapping — e.g. { PROJ1: [1, 2], PROJ2: [3] }
37
+ * @param name — test title
38
+ * @example it(qase.projects({ PROJ1: [100], PROJ2: [200] }, 'Login flow'), function() { ... });
39
+ */
40
+ exports.qase.projects = (mapping, name) => {
41
+ return (0, qase_javascript_commons_1.formatTitleWithProjectMapping)(name, mapping);
42
+ };
@@ -66,7 +66,7 @@ export declare class MochaQaseReporter extends reporters.Base {
66
66
  contentType?: string;
67
67
  }) => void;
68
68
  comment: (message: string) => void;
69
- step: (title: string, func: () => void) => void;
69
+ step: (title: string, func: () => void, expectedResult?: string, data?: string) => void;
70
70
  /**
71
71
  * @param {string} title
72
72
  * @returns {string}
@@ -76,12 +76,14 @@ export declare class MochaQaseReporter extends reporters.Base {
76
76
  /**
77
77
  * @type {RegExp}
78
78
  */
79
+ /** @deprecated Use parseProjectMappingFromTitle from qase-javascript-commons for multi-project support. */
79
80
  static qaseIdRegExp: RegExp;
80
81
  /**
81
- * @param {string} title
82
- * @returns {number[]}
82
+ * Extract expected result and data from step title and return cleaned string
83
+ * @param {string} input
84
+ * @returns {{expectedResult: string | null, data: string | null, cleanedString: string}}
83
85
  * @private
84
86
  */
85
- private static getCaseId;
87
+ private extractAndCleanStep;
86
88
  }
87
89
  export {};
package/dist/reporter.js CHANGED
@@ -159,10 +159,12 @@ class MochaQaseReporter extends mocha_1.reporters.Base {
159
159
  this.currentTest = new currentTest();
160
160
  return;
161
161
  }
162
+ const fromTitle = (0, qase_javascript_commons_1.parseProjectMappingFromTitle)(test.title);
162
163
  const ids = this.getQaseId();
163
164
  if (ids.length === 0) {
164
- ids.push(...MochaQaseReporter.getCaseId(test.title));
165
+ ids.push(...fromTitle.legacyIds);
165
166
  }
167
+ const hasProjectMapping = Object.keys(fromTitle.projectMapping).length > 0;
166
168
  const suites = this.getSuites(test);
167
169
  let relations = {};
168
170
  if (suites.length > 0) {
@@ -193,7 +195,7 @@ class MochaQaseReporter extends mocha_1.reporters.Base {
193
195
  group_params: this.metadata.groupParameters ?? {},
194
196
  relations: relations,
195
197
  run_id: null,
196
- signature: this.getSignature(test, ids, this.metadata.parameters ?? {}),
198
+ signature: this.getSignature(test, hasProjectMapping ? [] : ids, this.metadata.parameters ?? {}),
197
199
  steps: this.currentTest.steps,
198
200
  id: (0, uuid_1.v4)(),
199
201
  execution: {
@@ -204,8 +206,9 @@ class MochaQaseReporter extends mocha_1.reporters.Base {
204
206
  stacktrace: test.err?.stack ?? null,
205
207
  thread: null,
206
208
  },
207
- testops_id: ids.length > 0 ? ids : null,
208
- title: this.metadata.title && this.metadata.title != '' ? this.metadata.title : this.removeQaseIdsFromTitle(test.title),
209
+ testops_id: hasProjectMapping ? null : (ids.length > 0 ? ids : null),
210
+ testops_project_mapping: hasProjectMapping ? fromTitle.projectMapping : null,
211
+ title: this.metadata.title && this.metadata.title != '' ? this.metadata.title : (fromTitle.cleanedTitle || this.removeQaseIdsFromTitle(test.title)),
209
212
  };
210
213
  void this.reporter.addTestResult(result);
211
214
  this.metadata.clear();
@@ -309,15 +312,19 @@ class MochaQaseReporter extends mocha_1.reporters.Base {
309
312
  comment = (message) => {
310
313
  this.metadata.addComment(message);
311
314
  };
312
- step = (title, func) => {
315
+ step = (title, func, expectedResult, data) => {
313
316
  const previousType = this.currentType;
314
317
  this.currentType = 'step';
318
+ const stepTitle = expectedResult || data
319
+ ? `${title} QaseExpRes:${expectedResult ? `: ${expectedResult}` : ''} QaseData:${data ? `: ${data}` : ''}`
320
+ : title;
321
+ const stepData = this.extractAndCleanStep(stepTitle);
315
322
  const step = {
316
323
  step_type: qase_javascript_commons_1.StepType.TEXT,
317
324
  data: {
318
- action: title,
319
- expected_result: null,
320
- data: null,
325
+ action: stepData.cleanedString,
326
+ expected_result: stepData.expectedResult,
327
+ data: stepData.data,
321
328
  },
322
329
  execution: {
323
330
  start_time: Date.now(),
@@ -356,15 +363,33 @@ class MochaQaseReporter extends mocha_1.reporters.Base {
356
363
  /**
357
364
  * @type {RegExp}
358
365
  */
366
+ /** @deprecated Use parseProjectMappingFromTitle from qase-javascript-commons for multi-project support. */
359
367
  static qaseIdRegExp = /\(Qase ID: ([\d,]+)\)/;
360
368
  /**
361
- * @param {string} title
362
- * @returns {number[]}
369
+ * Extract expected result and data from step title and return cleaned string
370
+ * @param {string} input
371
+ * @returns {{expectedResult: string | null, data: string | null, cleanedString: string}}
363
372
  * @private
364
373
  */
365
- static getCaseId(title) {
366
- const [, ids] = title.match(MochaQaseReporter.qaseIdRegExp) ?? [];
367
- return ids ? ids.split(',').map((id) => Number(id)) : [];
374
+ extractAndCleanStep(input) {
375
+ let expectedResult = null;
376
+ let data = null;
377
+ let cleanedString = input;
378
+ const hasExpectedResult = input.includes('QaseExpRes:');
379
+ const hasData = input.includes('QaseData:');
380
+ if (hasExpectedResult || hasData) {
381
+ const regex = /QaseExpRes:\s*:?\s*(.*?)\s*(?=QaseData:|$)QaseData:\s*:?\s*(.*)?/;
382
+ const match = input.match(regex);
383
+ if (match) {
384
+ expectedResult = match[1]?.trim() ?? null;
385
+ data = match[2]?.trim() ?? null;
386
+ cleanedString = input
387
+ .replace(/QaseExpRes:\s*:?\s*.*?(?=QaseData:|$)/, '')
388
+ .replace(/QaseData:\s*:?\s*.*/, '')
389
+ .trim();
390
+ }
391
+ }
392
+ return { expectedResult, data, cleanedString };
368
393
  }
369
394
  }
370
395
  exports.MochaQaseReporter = MochaQaseReporter;
package/dist/types.d.ts CHANGED
@@ -29,7 +29,7 @@ export interface Methods {
29
29
  contentType?: string;
30
30
  }): void;
31
31
  comment(message: string): void;
32
- step(title: string, func: () => void): void;
32
+ step(title: string, func: () => void, expectedResult?: string, data?: string): void;
33
33
  }
34
34
  export declare class Metadata {
35
35
  ids?: number[];
@@ -0,0 +1,53 @@
1
+ # Multi-Project Support in Mocha
2
+
3
+ Qase Mocha Reporter supports sending test results to multiple Qase projects simultaneously. This feature allows you to report the same test execution to different projects with different test case IDs, which is useful when:
4
+
5
+ * You need to report the same test to different projects
6
+ * Different projects track the same functionality with different test case IDs
7
+ * You want to maintain separate test runs for different environments or teams
8
+
9
+ ## Configuration
10
+
11
+ For detailed configuration options, refer to the [qase-javascript-commons README](../../qase-javascript-commons/README.md#multi-project-support).
12
+
13
+ ### Basic Multi-Project Configuration
14
+
15
+ Set `mode` to `testops_multi` in your Mocha reporter options (e.g. in `.mocharc.js` or `qase.config.json`) and add the `testops_multi` section with `default_project` and `projects`.
16
+
17
+ ## Using `qase.projects(mapping, name)`
18
+
19
+ Use `qase.projects(mapping, name)` to set the test title with multi-project markers. Use the returned string as the first argument to `it()`:
20
+
21
+ ```javascript
22
+ const { qase } = require('mocha-qase-reporter');
23
+
24
+ // Single project
25
+ it(qase(100, 'login flow'), function () { ... });
26
+
27
+ // Multi-project
28
+ it(qase.projects({ PROJ1: [100], PROJ2: [200] }, 'login flow'), function () { ... });
29
+
30
+ // Multiple IDs per project
31
+ it(qase.projects({ PROJ1: [10, 11], PROJ2: [20] }, 'checkout'), function () { ... });
32
+ ```
33
+
34
+ Project codes (e.g. `PROJ1`, `PROJ2`) must match `testops_multi.projects[].code` in your config.
35
+
36
+ ## Tests Without Project Mapping
37
+
38
+ Tests that do not use `qase.projects()` and have no `(Qase PROJ: ids)` in the title are sent to the `default_project`. If they use `qase(id, name)` (single-project), that ID is used for the default project.
39
+
40
+ ## Important Notes
41
+
42
+ 1. **Project codes must match**: Codes in `qase.projects({ PROJ1: [1], ... })` must match `testops_multi.projects[].code`.
43
+ 2. **Mode**: Set `mode` to `testops_multi` in reporter config.
44
+ 3. **Title format**: The helper produces a title like `Name (Qase PROJ1: 1,2) (Qase PROJ2: 3)` so the reporter can parse the mapping.
45
+
46
+ ## Examples
47
+
48
+ See the [multi-project Mocha example](../../examples/multiProject/mocha/) for a complete runnable setup.
49
+
50
+ ## Troubleshooting
51
+
52
+ * Verify `mode` is `testops_multi` and project codes in `qase.projects()` match the config.
53
+ * Ensure the first argument to `it()` is the string returned by `qase.projects(mapping, name)` (or an equivalent title with markers).
package/docs/usage.md CHANGED
@@ -184,7 +184,7 @@ describe('User Authentication', function() {
184
184
  ## Adding Steps to a Test
185
185
 
186
186
  You can add custom steps to your test cases using the `this.step()` method. Each step should
187
- have a title and optionally a function.
187
+ have a title and optionally a function. You can also provide an expected result and input data for each step, which will be displayed in Qase.
188
188
 
189
189
  ### Example
190
190
 
@@ -210,6 +210,26 @@ describe('User Authentication', function() {
210
210
  });
211
211
  ```
212
212
 
213
+ ### Example with Expected Result and Data
214
+
215
+ ```javascript
216
+ const { qase } = require('mocha-qase-reporter/mocha');
217
+
218
+ describe('User Authentication', function() {
219
+ it('test with steps including expected results and data', function() {
220
+ this.step('Click button', function() {
221
+ // Click action
222
+ }, 'Button should be clicked', 'Button data');
223
+
224
+ this.step('Fill form', function() {
225
+ // Form filling action
226
+ }, 'Form should be filled', 'Form input data');
227
+
228
+ expect(true).to.equal(true);
229
+ });
230
+ });
231
+ ```
232
+
213
233
  ---
214
234
 
215
235
  ## Attaching Files to a Test
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mocha-qase-reporter",
3
- "version": "1.1.7",
3
+ "version": "1.2.0",
4
4
  "description": "Mocha Cypress Reporter",
5
5
  "homepage": "https://github.com/qase-tms/qase-javascript",
6
6
  "sideEffects": false,
@@ -43,7 +43,7 @@
43
43
  "dependencies": {
44
44
  "mocha": "^11.7.5",
45
45
  "deasync-promise": "^1.0.1",
46
- "qase-javascript-commons": "~2.4.10",
46
+ "qase-javascript-commons": "~2.5.0",
47
47
  "uuid": "^9.0.1"
48
48
  },
49
49
  "devDependencies": {