From fad87cc18e8339fbc2b881c45d905f00ca25e156 Mon Sep 17 00:00:00 2001 From: Dmitrii Gridnev Date: Mon, 16 Sep 2024 16:17:37 +0200 Subject: [PATCH 1/6] feature: the ability to specify a test metadata in tests - `qase.title` - set the test title - `qase.fields` - set the test fields - `qase.suite` - set the test suite - `qase.comment` - set the test comment - `qase.parameters` - set the test parameters - `qase.groupParameters` - set the test group parameters - `qase.ignore` - ignore the test in Qase ```ts it('test', () => { qase.title('Title'); qase.fields({ field: 'value' }); qase.suite('Suite'); qase.comment('Comment'); qase.parameters({ param: 'value' }); qase.groupParameters({ group: { param: 'value' } }); qase.ignore(); cy.visit('https://example.com'); }); --- package-lock.json | 24 +++++- qase-cypress/README.md | 39 +++++++-- qase-cypress/changelog.md | 34 +++++++- qase-cypress/package.json | 3 +- qase-cypress/src/metadata.js | 52 ++++++++++++ qase-cypress/src/metadata/manager.ts | 101 +++++++++++++++++++++++ qase-cypress/src/metadata/models.ts | 9 +++ qase-cypress/src/mocha.ts | 117 +++++++++++++++++++++++++++ qase-cypress/src/reporter.ts | 44 ++++++++-- 9 files changed, 404 insertions(+), 19 deletions(-) create mode 100644 qase-cypress/src/metadata.js create mode 100644 qase-cypress/src/metadata/manager.ts create mode 100644 qase-cypress/src/metadata/models.ts diff --git a/package-lock.json b/package-lock.json index 1eda35d7..883315d5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -56,6 +56,22 @@ "eslint-plugin-cypress": "^2.13.3" } }, + "examples/cypress/node_modules/cypress-qase-reporter": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/cypress-qase-reporter/-/cypress-qase-reporter-2.1.1.tgz", + "integrity": "sha512-0eiAEp9dLpkCdfrI860StR6bNtmyD8FTVua79XBnUGEimdLZgBCPV0Mj/8fvelyN8R8bKvpgu9Uzr7yuO+u02A==", + "dev": true, + "dependencies": { + "qase-javascript-commons": "~2.2.0", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "cypress": ">=8.0.0" + } + }, "examples/jest": { "name": "examples-jest", "devDependencies": { @@ -15189,7 +15205,7 @@ }, "qase-cypress": { "name": "cypress-qase-reporter", - "version": "2.1.1", + "version": "2.2.0-beta.1", "license": "Apache-2.0", "dependencies": { "qase-javascript-commons": "~2.2.0", @@ -15360,7 +15376,7 @@ }, "qase-playwright": { "name": "playwright-qase-reporter", - "version": "2.0.12", + "version": "2.0.13", "license": "Apache-2.0", "dependencies": { "chalk": "^4.1.2", @@ -15382,7 +15398,7 @@ }, "qase-testcafe": { "name": "testcafe-reporter-qase", - "version": "2.0.1", + "version": "2.0.2", "license": "Apache-2.0", "dependencies": { "qase-javascript-commons": "~2.2.0", @@ -15403,7 +15419,7 @@ }, "qase-wdio": { "name": "wdio-qase-reporter", - "version": "1.0.0-beta.2", + "version": "1.0.0-beta.4", "license": "Apache-2.0", "dependencies": { "@types/node": "^20.1.0", diff --git a/qase-cypress/README.md b/qase-cypress/README.md index 62cc6387..46724ecb 100644 --- a/qase-cypress/README.md +++ b/qase-cypress/README.md @@ -4,7 +4,7 @@ Publish results simple and easy. ## Installation -To install the latest release version (2.0.x), run: +To install the latest release version (2.1.x), run: ```sh npm install -D cypress-qase-reporter @@ -13,7 +13,7 @@ npm install -D cypress-qase-reporter -To install the latest beta version (2.1.x), run: +To install the latest beta version (2.2.x), run: ```sh npm install -D cypress-qase-reporter@beta @@ -30,7 +30,7 @@ run the following steps: - import { qase } from 'cypress-qase-reporter/dist/mocha' + import { qase } from 'cypress-qase-reporter/mocha' ``` - + 2. Update reporter configuration in `cypress.config.js` and/or environment variables — see the [configuration reference](#configuration) below. @@ -68,6 +68,23 @@ run the following steps: ... ``` +## Updating from v2.1 to v2.2 + +To update an existing test project using Qase reporter from version 2.1 to version 2.2, +run the following steps: + +1. Add a metadata in the `e2e` section of `cypress.config.js` + + ```diff + ... + e2e: { + setupNodeEvents(on, config) { + require('cypress-qase-reporter/plugin')(on, config) + + require('cypress-qase-reporter/metadata')(on) + } + } + ... + ## Getting started The Cypress reporter can auto-generate test cases @@ -80,6 +97,16 @@ from Qase.io before executing tests. It's a more reliable way to bind autotests to test cases, that persists when you rename, move, or parameterize your tests. +### Metadata + +- `qase.title` - set the title of the test case +- `qase.fields` - set the fields of the test case +- `qase.suite` - set the suite of the test case +- `qase.comment` - set the comment of the test case +- `qase.parameters` - set the parameters of the test case +- `qase.groupParameters` - set the group parameters of the test case +- `qase.ignore` - ignore the test case in Qase. The test will be executed, but the results will not be sent to Qase. + For example: ```typescript @@ -88,6 +115,7 @@ import { qase } from 'cypress-qase-reporter/mocha'; describe('My First Test', () => { qase(1, it('Several ids', () => { + qase.title('My title'); expect(true).to.equal(true); }) ); @@ -145,8 +173,6 @@ Example `cypress.config.js` config: ```js import cypress from 'cypress'; -import plugins from './cypress/plugins/index.js'; - module.exports = cypress.defineConfig({ reporter: 'cypress-multi-reporters', reporterOptions: { @@ -180,7 +206,8 @@ module.exports = cypress.defineConfig({ video: false, e2e: { setupNodeEvents(on, config) { - return plugins(on, config); + require('cypress-qase-reporter/plugin')(on, config) + require('cypress-qase-reporter/metadata')(on) }, }, }); diff --git a/qase-cypress/changelog.md b/qase-cypress/changelog.md index 65e960f2..035a781f 100644 --- a/qase-cypress/changelog.md +++ b/qase-cypress/changelog.md @@ -1,3 +1,31 @@ +# cypress-qase-reporter@2.2.0-beta.1 + +## What's new + +Added the ability to specify a test metadata in tests: + +- `qase.title` - set the test title +- `qase.fields` - set the test fields +- `qase.suite` - set the test suite +- `qase.comment` - set the test comment +- `qase.parameters` - set the test parameters +- `qase.groupParameters` - set the test group parameters +- `qase.ignore` - ignore the test in Qase + +```ts +it('test', () => { + qase.title('Title'); + qase.fields({ field: 'value' }); + qase.suite('Suite'); + qase.comment('Comment'); + qase.parameters({ param: 'value' }); + qase.groupParameters({ param: 'value' }); + qase.ignore(); + + cy.visit('https://example.com'); +}); +``` + # cypress-qase-reporter@2.1.0 ## What's new @@ -40,8 +68,8 @@ The reporter will wait for all results to be sent to Qase and will not block the ## What's new -1. Cypress kills the process after the last tests. -The reporter will wait for all results to be sent to Qase and will not block the process after sending. +1. Cypress kills the process after the last tests. + The reporter will wait for all results to be sent to Qase and will not block the process after sending. 2. The reporter will collect suites and add them to results. @@ -66,7 +94,7 @@ For more information about the new features and a guide for migration from v1, r # cypress-qase-reporter@2.0.0-beta.3 -Fixed an issue with multiple test runs created when Cypress is running +Fixed an issue with multiple test runs created when Cypress is running multiple tests in parallel. # cypress-qase-reporter@2.0.0-beta.2 diff --git a/qase-cypress/package.json b/qase-cypress/package.json index 7bf505c1..69d46daf 100644 --- a/qase-cypress/package.json +++ b/qase-cypress/package.json @@ -1,6 +1,6 @@ { "name": "cypress-qase-reporter", - "version": "2.1.1", + "version": "2.2.0-beta.1", "description": "Qase Cypress Reporter", "homepage": "https://github.com/qase-tms/qase-javascript", "sideEffects": false, @@ -12,6 +12,7 @@ "./reporter": "./dist/reporter.js", "./package.json": "./package.json", "./plugin": "./dist/plugin.js", + "./metadata": "./dist/metadata.js", "./hooks": "./dist/hooks.js" }, "typesVersions": { diff --git a/qase-cypress/src/metadata.js b/qase-cypress/src/metadata.js new file mode 100644 index 00000000..c94c62e8 --- /dev/null +++ b/qase-cypress/src/metadata.js @@ -0,0 +1,52 @@ +import { MetadataManager } from './metadata/manager'; + +module.exports = function(on) { + on('task', { + qaseTitle(value) { + MetadataManager.setTitle(value); + return null; + }, + }); + + on('task', { + qaseFields(value) { + MetadataManager.setFields(value); + return null; + }, + }); + + on('task', { + qaseIgnore() { + MetadataManager.setIgnore(); + return null; + }, + }); + + on('task', { + qaseParameters(value) { + MetadataManager.setParameters(value); + return null; + }, + }); + + on('task', { + qaseGroupParameters(value) { + MetadataManager.setGroupParams(value); + return null; + }, + }); + + on('task', { + qaseSuite(value) { + MetadataManager.setSuite(value); + return null; + }, + }); + + on('task', { + qaseComment(value) { + MetadataManager.setComment(value); + return null; + }, + }); +}; diff --git a/qase-cypress/src/metadata/manager.ts b/qase-cypress/src/metadata/manager.ts new file mode 100644 index 00000000..871ae3f4 --- /dev/null +++ b/qase-cypress/src/metadata/manager.ts @@ -0,0 +1,101 @@ +import { Metadata } from './models'; +import { readFileSync, existsSync, unlinkSync, writeFileSync } from 'fs'; + +const metadataPath = 'qaseMetadata'; + +// eslint-disable-next-line @typescript-eslint/no-extraneous-class +export class MetadataManager { + public static getMetadata(): Metadata | undefined { + if (!this.isExists()) { + return undefined; + } + + let metadata: Metadata = { + title: undefined, + fields: {}, + parameters: {}, + groupParams: {}, + ignore: false, + suite: undefined, + comment: undefined, + }; + + try { + const data = readFileSync(metadataPath, 'utf8'); + metadata = JSON.parse(data) as Metadata; + + return metadata; + } catch (err) { + console.error('Error reading metadata file:', err); + } + + return undefined; + } + + public static setIgnore(): void { + const metadata = this.getMetadata() ?? {}; + metadata.ignore = true; + this.setMetadata(metadata); + } + + public static setSuite(suite: string): void { + const metadata = this.getMetadata() ?? {}; + metadata.suite = suite; + this.setMetadata(metadata); + } + + public static setComment(comment: string): void { + const metadata = this.getMetadata() ?? {}; + metadata.comment = comment; + this.setMetadata(metadata); + } + + public static setTitle(title: string): void { + const metadata = this.getMetadata() ?? {}; + metadata.title = title; + this.setMetadata(metadata); + } + + public static setFields(fields: Record): void { + const metadata = this.getMetadata() ?? {}; + metadata.fields = fields; + this.setMetadata(metadata); + } + + public static setParameters(parameters: Record): void { + const metadata = this.getMetadata() ?? {}; + metadata.parameters = parameters; + this.setMetadata(metadata); + } + + public static setGroupParams(groupParams: Record): void { + const metadata = this.getMetadata() ?? {}; + metadata.groupParams = groupParams; + this.setMetadata(metadata); + } + + private static setMetadata(metadata: Metadata): void { + try { + const data = JSON.stringify(metadata); + writeFileSync(metadataPath, data); + } catch (err) { + console.error('Error writing metadata file:', err); + } + } + + public static clear() { + if (!this.isExists()) { + return; + } + + try { + unlinkSync(metadataPath); + } catch (err) { + console.error('Error clearing state file:', err); + } + } + + static isExists(): boolean { + return existsSync(metadataPath); + } +} diff --git a/qase-cypress/src/metadata/models.ts b/qase-cypress/src/metadata/models.ts new file mode 100644 index 00000000..ec4c9f80 --- /dev/null +++ b/qase-cypress/src/metadata/models.ts @@ -0,0 +1,9 @@ +export interface Metadata { + title?: string | undefined; + fields?: Record; + parameters?: Record; + groupParams?: Record; + ignore?: boolean; + suite?: string | undefined; + comment?: string | undefined; +} diff --git a/qase-cypress/src/mocha.ts b/qase-cypress/src/mocha.ts index cab30740..ab9a7141 100644 --- a/qase-cypress/src/mocha.ts +++ b/qase-cypress/src/mocha.ts @@ -10,3 +10,120 @@ export const qase = ( return test; }; + +/** + * Set a title for the test case + * @param {string} value + * @example + * it('test', () => { + * qase.title("Title"); + * cy.visit('https://example.com'); + * }); + */ +qase.title = ( + value: string, +) => { + cy.task('qaseTitle', value).then(() => { + // + }); +}; + + +/** + * Set fields for the test case + * @param {Record} values + * @example + * it('test', () => { + * qase.fields({description: "Description"}); + * cy.visit('https://example.com'); + * }); + */ +qase.fields = ( + values: Record, +) => { + cy.task('qaseFields', values).then(() => { + // + }); +}; + +/** + * Ignore the test case result in Qase + * @example + * it('test', () => { + * qase.ignore(); + * cy.visit('https://example.com'); + * }); + */ +qase.ignore = () => { + cy.task('qaseIgnore').then(() => { + // + }); +}; + +/** + * Set parameters for the test case + * @param {Record} values + * @example + * it('test', () => { + * qase.parameters({param01: "value01"}); + * cy.visit('https://example.com'); + * }); + */ +qase.parameters = ( + values: Record, +) => { + cy.task('qaseParameters', values).then(() => { + // + }); +}; + +/** + * Set group parameters for the test case + * @param {Record} values + * @example + * it('test', () => { + * qase.groupParameters({param01: "value01"}); + * cy.visit('https://example.com'); + * }); + */ +qase.groupParameters = ( + values: Record, +) => { + cy.task('qaseGroupParameters', values).then(() => { + // + }); +}; + +/** + * Set a suite for the test case + * @param {string} value + * @example + * it('test', () => { + * qase.suite("Suite 01"); + * cy.visit('https://example.com'); + * }); + */ +qase.suite = ( + value: string, +) => { + cy.task('qaseSuite', value).then(() => { + // + }); +}; + +/** + * Set a comment for the test case + * @param {string} value + * @example + * it('test', () => { + * qase.comment("Some comment"); + * cy.visit('https://example.com'); + * }); + */ +qase.comment = ( + value: string, +) => { + cy.task('qaseComment', value).then(() => { + // + }); +}; diff --git a/qase-cypress/src/reporter.ts b/qase-cypress/src/reporter.ts index 18b5657a..dd65176c 100644 --- a/qase-cypress/src/reporter.ts +++ b/qase-cypress/src/reporter.ts @@ -19,6 +19,7 @@ import { import { traverseDir } from './utils/traverse-dir'; import { configSchema } from './configSchema'; import { ReporterOptionsType } from './options'; +import { MetadataManager } from './metadata/manager'; const { EVENT_TEST_FAIL, @@ -166,6 +167,13 @@ export class CypressQaseReporter extends reporters.Base { * @private */ private addTestResult(test: Test) { + const metadata = MetadataManager.getMetadata(); + + if (metadata?.ignore) { + MetadataManager.clear(); + return; + } + const ids = CypressQaseReporter.getCaseId(test.title); const attachments = this.screenshotsFolder @@ -189,14 +197,38 @@ export class CypressQaseReporter extends reporters.Base { }; } + if (metadata?.suite) { + relations = { + suite: { + data: [ + { + title: metadata.suite, + public_id: null, + }, + ], + }, + }; + } + + let message: string | null = null; + if (metadata?.comment) { + message = metadata.comment; + } + if (test.err?.message) { + if (message) { + message += '\n\n'; + } + message += test.err.message; + } + const result: TestResultType = { attachments: attachments ?? [], author: null, - fields: {}, - message: test.err?.message ?? null, + fields: metadata?.fields ?? {}, + message: message, muted: false, - params: {}, - group_params: {}, + params: metadata?.parameters ?? {}, + group_params: metadata?.groupParams ?? {}, relations: relations, run_id: null, signature: this.getSignature(test, ids), @@ -213,10 +245,12 @@ export class CypressQaseReporter extends reporters.Base { thread: null, }, testops_id: ids.length > 0 ? ids : null, - title: test.title, + title: metadata?.title ?? test.title, }; void this.reporter.addTestResult(result); + + MetadataManager.clear(); } /** From 333bbd17fc12c86844a04beba84854c775657712 Mon Sep 17 00:00:00 2001 From: Dmitrii Gridnev Date: Tue, 17 Sep 2024 14:20:28 +0200 Subject: [PATCH 2/6] feature: the ability to add steps in tests - `qase.step` - add a step to the test ```ts it('test', () => { qase.step('Step 1', () => { cy.visit('https://example.com'); }); }); ``` --- qase-cypress/README.md | 5 ++-- qase-cypress/changelog.md | 16 ++++++++++ qase-cypress/package.json | 2 +- qase-cypress/src/metadata.js | 14 +++++++++ qase-cypress/src/metadata/manager.ts | 39 +++++++++++++++++++++++- qase-cypress/src/metadata/models.ts | 16 ++++++++++ qase-cypress/src/mocha.ts | 22 ++++++++++++++ qase-cypress/src/reporter.ts | 45 +++++++++++++++++++++++++++- 8 files changed, 154 insertions(+), 5 deletions(-) diff --git a/qase-cypress/README.md b/qase-cypress/README.md index 46724ecb..03ddce7a 100644 --- a/qase-cypress/README.md +++ b/qase-cypress/README.md @@ -106,6 +106,7 @@ parameterize your tests. - `qase.parameters` - set the parameters of the test case - `qase.groupParameters` - set the group parameters of the test case - `qase.ignore` - ignore the test case in Qase. The test will be executed, but the results will not be sent to Qase. +- `qase.step` - create a step in the test case For example: @@ -206,8 +207,8 @@ module.exports = cypress.defineConfig({ video: false, e2e: { setupNodeEvents(on, config) { - require('cypress-qase-reporter/plugin')(on, config) - require('cypress-qase-reporter/metadata')(on) + require('cypress-qase-reporter/plugin')(on, config) + require('cypress-qase-reporter/metadata')(on) }, }, }); diff --git a/qase-cypress/changelog.md b/qase-cypress/changelog.md index 035a781f..eb3435cb 100644 --- a/qase-cypress/changelog.md +++ b/qase-cypress/changelog.md @@ -1,3 +1,19 @@ +# cypress-qase-reporter@2.2.0-beta.2 + +## What's new + +Added the ability to add steps in tests: + +- `qase.step` - add a step to the test + +```ts +it('test', () => { + qase.step('Step 1', () => { + cy.visit('https://example.com'); + }); +}); +``` + # cypress-qase-reporter@2.2.0-beta.1 ## What's new diff --git a/qase-cypress/package.json b/qase-cypress/package.json index 69d46daf..8478ec4f 100644 --- a/qase-cypress/package.json +++ b/qase-cypress/package.json @@ -1,6 +1,6 @@ { "name": "cypress-qase-reporter", - "version": "2.2.0-beta.1", + "version": "2.2.0-beta.2", "description": "Qase Cypress Reporter", "homepage": "https://github.com/qase-tms/qase-javascript", "sideEffects": false, diff --git a/qase-cypress/src/metadata.js b/qase-cypress/src/metadata.js index c94c62e8..40c09c04 100644 --- a/qase-cypress/src/metadata.js +++ b/qase-cypress/src/metadata.js @@ -49,4 +49,18 @@ module.exports = function(on) { return null; }, }); + + on('task', { + qaseStepStart(value) { + MetadataManager.addStepStart(value); + return null; + }, + }); + + on('task', { + qaseStepEnd(value) { + MetadataManager.addStepEnd(value); + return null; + }, + }); }; diff --git a/qase-cypress/src/metadata/manager.ts b/qase-cypress/src/metadata/manager.ts index 871ae3f4..3a56ef12 100644 --- a/qase-cypress/src/metadata/manager.ts +++ b/qase-cypress/src/metadata/manager.ts @@ -1,5 +1,6 @@ -import { Metadata } from './models'; +import { Metadata, StepStart } from './models'; import { readFileSync, existsSync, unlinkSync, writeFileSync } from 'fs'; +import { v4 as uuidv4 } from 'uuid'; const metadataPath = 'qaseMetadata'; @@ -18,6 +19,9 @@ export class MetadataManager { ignore: false, suite: undefined, comment: undefined, + steps: [], + currentStepId: undefined, + firstStepName: undefined, }; try { @@ -38,6 +42,39 @@ export class MetadataManager { this.setMetadata(metadata); } + public static addStepStart(name: string): void { + const metadata = this.getMetadata() ?? {}; + + if (metadata.firstStepName === name) { + return; + } + + if (!metadata.steps) { + metadata.steps = []; + } + const id = uuidv4(); + const parentId = metadata.currentStepId ?? undefined; + metadata.steps.push({ timestamp: Date.now(), name, id: id, parentId: parentId }); + metadata.currentStepId = id; + + if (!metadata.firstStepName) { + metadata.firstStepName = name; + } + + this.setMetadata(metadata); + } + + public static addStepEnd(status: string): void { + const metadata = this.getMetadata() ?? {}; + if (!metadata.steps || !metadata.currentStepId) { + return; + } + const parentId = metadata.steps.reverse().find((step): step is StepStart => step.id === metadata.currentStepId)?.parentId; + metadata.steps.push({ timestamp: Date.now(), status, id: metadata.currentStepId }); + metadata.currentStepId = parentId; + this.setMetadata(metadata); + } + public static setSuite(suite: string): void { const metadata = this.getMetadata() ?? {}; metadata.suite = suite; diff --git a/qase-cypress/src/metadata/models.ts b/qase-cypress/src/metadata/models.ts index ec4c9f80..d4284b1a 100644 --- a/qase-cypress/src/metadata/models.ts +++ b/qase-cypress/src/metadata/models.ts @@ -6,4 +6,20 @@ export interface Metadata { ignore?: boolean; suite?: string | undefined; comment?: string | undefined; + steps?: (StepStart | StepEnd)[]; + currentStepId?: string | undefined; + firstStepName?: string | undefined; +} + +export interface StepStart { + id: string; + timestamp: number; + name: string; + parentId: string | undefined; +} + +export interface StepEnd { + id: string; + timestamp: number; + status: string; } diff --git a/qase-cypress/src/mocha.ts b/qase-cypress/src/mocha.ts index ab9a7141..4149e36b 100644 --- a/qase-cypress/src/mocha.ts +++ b/qase-cypress/src/mocha.ts @@ -127,3 +127,25 @@ qase.comment = ( // }); }; + +/** + * Add a step to the test case + * @param {string} name + * @param {() => T | PromiseLike} body + * @example + * it('test', () => { + * qase.step("Some step", () => { + * // some actions + * }); + * cy.visit('https://example.com'); + * }); + */ +qase.step = (name: string, body: () => T | PromiseLike) => { + return cy.task('qaseStepStart', name).then(() => { + return Cypress.Promise.resolve(body()); + }).then(() => { + cy.task('qaseStepEnd', 'passed').then(() => { + // + }); + }); +}; diff --git a/qase-cypress/src/reporter.ts b/qase-cypress/src/reporter.ts index dd65176c..001595b3 100644 --- a/qase-cypress/src/reporter.ts +++ b/qase-cypress/src/reporter.ts @@ -14,12 +14,15 @@ import { Attachment, FrameworkOptionsType, ConfigType, + TestStepType, + StepStatusEnum, } from 'qase-javascript-commons'; import { traverseDir } from './utils/traverse-dir'; import { configSchema } from './configSchema'; import { ReporterOptionsType } from './options'; import { MetadataManager } from './metadata/manager'; +import { StepEnd, StepStart } from './metadata/models'; const { EVENT_TEST_FAIL, @@ -232,7 +235,7 @@ export class CypressQaseReporter extends reporters.Base { relations: relations, run_id: null, signature: this.getSignature(test, ids), - steps: [], + steps: metadata?.steps ? this.getSteps(metadata.steps) : [], id: uuidv4(), execution: { status: test.state @@ -296,4 +299,44 @@ export class CypressQaseReporter extends reporters.Base { return undefined; } + + private getSteps(steps: (StepStart | StepEnd)[]): TestStepType[] { + const result: TestStepType[] = []; + const stepMap = new Map(); + + for (const step of steps.sort((a, b) => a.timestamp - b.timestamp)) { + if (!('status' in step)) { + const newStep = new TestStepType(); + newStep.id = step.id; + newStep.execution.status = StepStatusEnum.failed; + newStep.execution.start_time = step.timestamp; + newStep.execution.end_time = Date.now(); + newStep.data = { + action: step.name, + expected_result: null, + }; + + const parentId = step.parentId; + if (parentId) { + newStep.parent_id = parentId; + const parent = stepMap.get(parentId); + if (parent) { + parent.steps.push(newStep); + } + } else { + result.push(newStep); + } + + stepMap.set(step.id, newStep); + } else { + const stepType = stepMap.get(step.id); + if (stepType) { + stepType.execution.status = step.status as StepStatusEnum; + stepType.execution.end_time = step.timestamp; + } + } + } + + return result; + } } From 9b8ee1050bc456e2301838705c702d5a40c92310 Mon Sep 17 00:00:00 2001 From: Dmitrii Gridnev Date: Thu, 19 Sep 2024 12:45:00 +0200 Subject: [PATCH 3/6] feature: ability to add attachments to tests or steps - `qase.attach` - add an attachment to test or step ```ts it('test', () => { qase.attach({ paths: '/path/to/file' }); qase.step('Step 1', () => { cy.visit('https://example.com'); qase.attach({ name: 'attachment.txt', content: 'Hello, world!', contentType: 'text/plain' }); }); }); ``` --- qase-cypress/changelog.md | 18 +++++++ qase-cypress/package.json | 2 +- qase-cypress/src/metadata.js | 7 +++ qase-cypress/src/metadata/manager.ts | 73 +++++++++++++++++++++++++++- qase-cypress/src/metadata/models.ts | 12 +++++ qase-cypress/src/mocha.ts | 36 +++++++++++--- qase-cypress/src/reporter.ts | 10 +++- 7 files changed, 147 insertions(+), 11 deletions(-) diff --git a/qase-cypress/changelog.md b/qase-cypress/changelog.md index eb3435cb..5ae978e3 100644 --- a/qase-cypress/changelog.md +++ b/qase-cypress/changelog.md @@ -1,3 +1,21 @@ +# cypress-qase-reporter@2.2.0-beta.3 + +## What's new + +Added the ability to add attachments to tests or steps: + +- `qase.attach` - add an attachment to test or step + +```ts +it('test', () => { + qase.attach({ paths: '/path/to/file' }); + qase.step('Step 1', () => { + cy.visit('https://example.com'); + qase.attach({ name: 'attachment.txt', content: 'Hello, world!', contentType: 'text/plain' }); + }); +}); +``` + # cypress-qase-reporter@2.2.0-beta.2 ## What's new diff --git a/qase-cypress/package.json b/qase-cypress/package.json index 8478ec4f..15c2e2f4 100644 --- a/qase-cypress/package.json +++ b/qase-cypress/package.json @@ -1,6 +1,6 @@ { "name": "cypress-qase-reporter", - "version": "2.2.0-beta.2", + "version": "2.2.0-beta.3", "description": "Qase Cypress Reporter", "homepage": "https://github.com/qase-tms/qase-javascript", "sideEffects": false, diff --git a/qase-cypress/src/metadata.js b/qase-cypress/src/metadata.js index 40c09c04..984bb96d 100644 --- a/qase-cypress/src/metadata.js +++ b/qase-cypress/src/metadata.js @@ -63,4 +63,11 @@ module.exports = function(on) { return null; }, }); + + on('task', { + qaseAttach(value) { + MetadataManager.addAttach(value); + return null; + }, + }); }; diff --git a/qase-cypress/src/metadata/manager.ts b/qase-cypress/src/metadata/manager.ts index 3a56ef12..7f81ad55 100644 --- a/qase-cypress/src/metadata/manager.ts +++ b/qase-cypress/src/metadata/manager.ts @@ -1,6 +1,8 @@ -import { Metadata, StepStart } from './models'; +import { Attach, Metadata, StepStart } from './models'; import { readFileSync, existsSync, unlinkSync, writeFileSync } from 'fs'; import { v4 as uuidv4 } from 'uuid'; +import path from 'path'; +import { Attachment, getMimeTypes } from 'qase-javascript-commons'; const metadataPath = 'qaseMetadata'; @@ -22,6 +24,8 @@ export class MetadataManager { steps: [], currentStepId: undefined, firstStepName: undefined, + attachments: [], + stepAttachments: {}, }; try { @@ -75,6 +79,31 @@ export class MetadataManager { this.setMetadata(metadata); } + public static addAttach(attach: Attach) { + const metadata = this.getMetadata() ?? {}; + + if (!metadata.attachments) { + metadata.attachments = []; + } + if (!metadata.stepAttachments) { + metadata.stepAttachments = {}; + } + + const attachments = this.prepareAttach(attach); + + if (metadata.currentStepId) { + if (metadata.stepAttachments[metadata.currentStepId] === undefined) { + metadata.stepAttachments[metadata.currentStepId] = attachments; + } else { + metadata.stepAttachments[metadata.currentStepId]?.push(...attachments); + } + } else { + metadata.attachments.push(...attachments); + } + + this.setMetadata(metadata); + } + public static setSuite(suite: string): void { const metadata = this.getMetadata() ?? {}; metadata.suite = suite; @@ -135,4 +164,46 @@ export class MetadataManager { static isExists(): boolean { return existsSync(metadataPath); } + + static prepareAttach(attach: Attach): Attachment[] { + const attachments: Attachment[] = []; + if (attach.paths) { + if (Array.isArray(attach.paths)) { + attach.paths.forEach((file) => { + const attachmentName = path.basename(file); + const contentType: string = getMimeTypes(file); + attachments.push({ + file_name: attachmentName, + mime_type: contentType, + file_path: file, + content: '', + size: 0, + id: uuidv4(), + }); + }); + } else { + const attachmentName = path.basename(attach.paths); + const contentType: string = getMimeTypes(attach.paths); + attachments.push({ + file_name: attachmentName, + mime_type: contentType, + file_path: attach.paths, + content: '', + size: 0, + id: uuidv4(), + }); + } + } else if (attach.content) { + attachments.push({ + file_name: attach.name ?? 'attachment', + mime_type: attach.contentType ?? 'application/octet-stream', + file_path: null, + content: attach.content, + size: 0, + id: uuidv4(), + }); + } + + return attachments; + } } diff --git a/qase-cypress/src/metadata/models.ts b/qase-cypress/src/metadata/models.ts index d4284b1a..e7184a18 100644 --- a/qase-cypress/src/metadata/models.ts +++ b/qase-cypress/src/metadata/models.ts @@ -1,3 +1,5 @@ +import { Attachment } from 'qase-javascript-commons'; + export interface Metadata { title?: string | undefined; fields?: Record; @@ -9,6 +11,8 @@ export interface Metadata { steps?: (StepStart | StepEnd)[]; currentStepId?: string | undefined; firstStepName?: string | undefined; + attachments?: Attachment[]; + stepAttachments?: Record; } export interface StepStart { @@ -23,3 +27,11 @@ export interface StepEnd { timestamp: number; status: string; } + + +export interface Attach { + name?: string; + paths?: string | string[]; + content?: Buffer | string; + contentType?: string; +} diff --git a/qase-cypress/src/mocha.ts b/qase-cypress/src/mocha.ts index 4149e36b..a60b73d8 100644 --- a/qase-cypress/src/mocha.ts +++ b/qase-cypress/src/mocha.ts @@ -23,7 +23,7 @@ export const qase = ( qase.title = ( value: string, ) => { - cy.task('qaseTitle', value).then(() => { + return cy.task('qaseTitle', value).then(() => { // }); }; @@ -41,7 +41,7 @@ qase.title = ( qase.fields = ( values: Record, ) => { - cy.task('qaseFields', values).then(() => { + return cy.task('qaseFields', values).then(() => { // }); }; @@ -55,7 +55,7 @@ qase.fields = ( * }); */ qase.ignore = () => { - cy.task('qaseIgnore').then(() => { + return cy.task('qaseIgnore').then(() => { // }); }; @@ -72,7 +72,7 @@ qase.ignore = () => { qase.parameters = ( values: Record, ) => { - cy.task('qaseParameters', values).then(() => { + return cy.task('qaseParameters', values).then(() => { // }); }; @@ -89,7 +89,7 @@ qase.parameters = ( qase.groupParameters = ( values: Record, ) => { - cy.task('qaseGroupParameters', values).then(() => { + return cy.task('qaseGroupParameters', values).then(() => { // }); }; @@ -106,7 +106,7 @@ qase.groupParameters = ( qase.suite = ( value: string, ) => { - cy.task('qaseSuite', value).then(() => { + return cy.task('qaseSuite', value).then(() => { // }); }; @@ -123,7 +123,7 @@ qase.suite = ( qase.comment = ( value: string, ) => { - cy.task('qaseComment', value).then(() => { + return cy.task('qaseComment', value).then(() => { // }); }; @@ -149,3 +149,25 @@ qase.step = (name: string, body: () => T | PromiseLike) => { }); }); }; + +/** + * Attach a file to the test case or the step + * @param attach + * @example + * it('test', () => { + * qase.attach({ name: 'attachment.txt', content: 'Hello, world!', contentType: 'text/plain' }); + * qase.attach({ paths: '/path/to/file'}); + * qase.attach({ paths: ['/path/to/file', '/path/to/another/file']}); + * cy.visit('https://example.com'); + * }); + */ +qase.attach = (attach: { + name?: string, + paths?: string | string[], + content?: Buffer | string, + contentType?: string, +}) => { + return cy.task('qaseAttach', attach).then(() => { + // + }); +}; diff --git a/qase-cypress/src/reporter.ts b/qase-cypress/src/reporter.ts index 001595b3..33a4173e 100644 --- a/qase-cypress/src/reporter.ts +++ b/qase-cypress/src/reporter.ts @@ -183,6 +183,8 @@ export class CypressQaseReporter extends reporters.Base { ? CypressQaseReporter.findAttachments(ids, this.screenshotsFolder) : undefined; + attachments?.push(...(metadata?.attachments ?? [])); + let relations = {}; if (test.parent !== undefined) { const data = []; @@ -235,7 +237,7 @@ export class CypressQaseReporter extends reporters.Base { relations: relations, run_id: null, signature: this.getSignature(test, ids), - steps: metadata?.steps ? this.getSteps(metadata.steps) : [], + steps: metadata?.steps ? this.getSteps(metadata.steps, metadata.stepAttachments ?? {}) : [], id: uuidv4(), execution: { status: test.state @@ -300,7 +302,7 @@ export class CypressQaseReporter extends reporters.Base { return undefined; } - private getSteps(steps: (StepStart | StepEnd)[]): TestStepType[] { + private getSteps(steps: (StepStart | StepEnd)[], attachments: Record): TestStepType[] { const result: TestStepType[] = []; const stepMap = new Map(); @@ -316,6 +318,10 @@ export class CypressQaseReporter extends reporters.Base { expected_result: null, }; + if (attachments[step.id]) { + newStep.attachments = attachments[step.id] ?? []; + } + const parentId = step.parentId; if (parentId) { newStep.parent_id = parentId; From 56a750514b25321647587f8b0fec2f5b3954d2e6 Mon Sep 17 00:00:00 2001 From: Dmitrii Gridnev Date: Mon, 23 Sep 2024 12:38:45 +0200 Subject: [PATCH 4/6] docs: update Newman readme Update the configuration section --- qase-newman/README.md | 53 ++++++++++++++++--------------------------- 1 file changed, 19 insertions(+), 34 deletions(-) diff --git a/qase-newman/README.md b/qase-newman/README.md index 7ef85716..0746604c 100644 --- a/qase-newman/README.md +++ b/qase-newman/README.md @@ -23,11 +23,13 @@ Example: //qase: 10 // Qase: 1, 2, 3 // qase: 4 5 6 14 -pm.test('expect response be 200', function () { - pm.response.to.be.info +pm.test('expect response be 200', function() { + pm.response.to.be.info }) ``` + ### Execute rom CLI: + ``` QASE_MODE=testops newman run ./sample-collection.json -r qase ``` @@ -48,53 +50,36 @@ https://app.qase.io/run/QASE_PROJECT_CODE ## Configuration -Qase reporter supports passing parameters using two ways: -using `.qaserc`/`qase.config.json` file and using ENV variables. - -`.qaserc` parameters, (* - required): -- `mode` - `testops`/`off` Enables reporter, default - `off` -- `debug` - Enables debug logging, defaule - `false` -- `environment` - To execute with the sending of the envinroment information -- *`testops.api.token` - Token for API access, you can find more information - [here](https://developers.qase.io/#authentication) -- *`testops.project` - Code of your project (can be extracted from main - page of your project: `https://app.qase.io/project/DEMOTR` - - `DEMOTR` is project code here) -- `testops.run.id` - Pass Run ID -- `testops.run.title` - Set custom Run name, when new run is created -- `testops.run.description` - Set custom Run description, when new run is created -- `testops.run.complete` - Whether the run should be completed - -Example configuration file: +Qase Newman reporter can be configured in multiple ways: + +- using a separate config file `qase.config.json`, +- using environment variables (they override the values from the configuration files). + +For a full list of configuration options, see +the [Configuration reference](../qase-javascript-commons/README.md#configuration). + +Example `qase.config.json` config: ```json { "mode": "testops", "debug": true, - "environment": 1, "testops": { "api": { "token": "api_key" }, - "project": "project_code" + "project": "project_code", + "run": { + "complete": true + } } } ``` -Supported ENV variables: - -- `QASE_MODE` - Same as `mode` -- `QASE_DEBUG` - Same as `debug` -- `QASE_ENVIRONMENT` - Same as `environment` -- `QASE_TESTOPS_API_TOKEN` - Same as `testops.api.token` -- `QASE_TESTOPS_PROJECT` - Same as `testops.project` -- `QASE_TESTOPS_RUN_ID` - Pass Run ID from ENV and override reporter option `testops.run.id` -- `QASE_TESTOPS_RUN_TITLE` - Same as `testops.run.title` -- `QASE_TESTOPS_RUN_DESCRIPTION` - Same as `testops.run.description` - ## Requirements -We maintain the reporter on LTS versions of Node. You can find the current versions by following the [link](https://nodejs.org/en/about/releases/) +We maintain the reporter on LTS versions of Node. You can find the current versions by following +the [link](https://nodejs.org/en/about/releases/) `newman >= 5.3.0` From ff53ddf9436dfd706f1d08a1cd295462b1ee3f04 Mon Sep 17 00:00:00 2001 From: Dmitrii Gridnev Date: Mon, 23 Sep 2024 15:00:32 +0200 Subject: [PATCH 5/6] feature: support `QaseIgnore` tag - Support `QaseIgnore` tag. If the test case has the `QaseIgnore` tag, the reporter will not send the result to the Qase TMS. ```cucumber @QaseIgnore Scenario: simple test ``` - Improved error handling. --- qase-cucumberjs/changelog.md | 14 ++++++++++++ qase-cucumberjs/package.json | 2 +- qase-cucumberjs/src/models.ts | 8 +++---- qase-cucumberjs/src/storage.ts | 39 +++++++++++++++++++++++++++------- 4 files changed, 50 insertions(+), 13 deletions(-) diff --git a/qase-cucumberjs/changelog.md b/qase-cucumberjs/changelog.md index 24d9f46c..7d0e9148 100644 --- a/qase-cucumberjs/changelog.md +++ b/qase-cucumberjs/changelog.md @@ -1,3 +1,17 @@ +# qase-cucumberjs@2.0.2 + +## What's new + +- Support `QaseIgnore` tag. If the test case has the `QaseIgnore` tag, the reporter will not send the result to the Qase + TMS. + + ```cucumber + @QaseIgnore + Scenario: simple test + ``` + +- Improved error handling. + # qase-cucumberjs@2.0.0 ## What's new diff --git a/qase-cucumberjs/package.json b/qase-cucumberjs/package.json index 3e8ded13..27c42ac3 100644 --- a/qase-cucumberjs/package.json +++ b/qase-cucumberjs/package.json @@ -1,6 +1,6 @@ { "name": "cucumberjs-qase-reporter", - "version": "2.0.1", + "version": "2.0.2", "description": "Qase TMS CucumberJS Reporter", "homepage": "https://github.com/qase-tms/qase-javascript", "main": "./dist/index.js", diff --git a/qase-cucumberjs/src/models.ts b/qase-cucumberjs/src/models.ts index dc84d1ed..54321442 100644 --- a/qase-cucumberjs/src/models.ts +++ b/qase-cucumberjs/src/models.ts @@ -1,6 +1,6 @@ - interface TestMetadata { - ids : number[]; - fields : Record; - title : string | null; + ids: number[]; + fields: Record; + title: string | null; + isIgnore: boolean; } diff --git a/qase-cucumberjs/src/storage.ts b/qase-cucumberjs/src/storage.ts index 6bb9882c..09927a2d 100644 --- a/qase-cucumberjs/src/storage.ts +++ b/qase-cucumberjs/src/storage.ts @@ -9,7 +9,7 @@ import { TestStepFinished, } from '@cucumber/messages'; import { - Attachment, + Attachment, CompoundError, Relation, StepStatusEnum, StepType, @@ -26,6 +26,7 @@ const qaseIdRegExp = /^@[Qq]-?(\d+)$/g; const newQaseIdRegExp = /^@[Qq]ase[Ii][Dd]=(\d+)$/g; const qaseTitleRegExp = /^@[Qq]ase[Tt]itle=(.+)$/g; const qaseFieldsRegExp = /^@[Qq]ase[Ff]ields:(.+?)=(.+)$/g; +const qaseIgnoreRegExp = /^@[Qq]ase[Ii][Gg][Nn][Oo][Rr][Ee]$/g; export class Storage { /** @@ -195,11 +196,14 @@ export class Storage { return undefined; } - let error: Error | undefined; + const metadata = this.parseTags(pickle.tags); - if (this.testCaseStartedErrors[tcs.id]?.length) { - error = new Error(this.testCaseStartedErrors[tcs.id]?.join('\n\n')); + if (metadata.isIgnore) { + return undefined; } + + const error = this.getError(tcs.id); + let relations: Relation | null = null; const nodeId = pickle.astNodeIds[pickle.astNodeIds.length - 1]; if (nodeId != undefined && this.scenarios[nodeId] != undefined) { @@ -215,8 +219,6 @@ export class Storage { }; } - const metadata = this.parseTags(pickle.tags); - return { attachments: [], author: null, @@ -225,11 +227,11 @@ export class Storage { start_time: null, end_time: null, duration: Math.abs(testCase.timestamp.seconds - tcs.timestamp.seconds), - stacktrace: error?.stack ?? null, + stacktrace: error?.stacktrace ?? null, thread: null, }, fields: metadata.fields, - message: null, + message: error?.message ?? null, muted: false, params: {}, group_params: {}, @@ -322,6 +324,7 @@ export class Storage { ids: [], fields: {}, title: null, + isIgnore: false, }; for (const tag of tags) { @@ -350,6 +353,10 @@ export class Storage { // do nothing } } + + if (qaseIgnoreRegExp.test(tag.name)) { + metadata.isIgnore = true; + } } return metadata; @@ -371,4 +378,20 @@ export class Storage { return signature; } + + private getError(testCaseId: string): CompoundError | undefined { + const testErrors = this.testCaseStartedErrors[testCaseId]; + + if (!testErrors) { + return undefined; + } + + const error = new CompoundError(); + testErrors.forEach((message) => { + error.addMessage(message); + error.addStacktrace(message); + }); + + return error; + } } From 8a37e107471a2fd7165d8184cc27a53c6dce25dc Mon Sep 17 00:00:00 2001 From: Dmitrii Gridnev Date: Mon, 23 Sep 2024 16:04:10 +0200 Subject: [PATCH 6/6] feature: support `ignore` metadata If the test case has the `ignore` tag, the reporter will not send the result to the Qase TMS. ```ts const q = qase.ignore().create(); test.meta({ ...q })( 'test', async (t) => { await t; }, ); ``` --- qase-testcafe/changelog.md | 20 +++++++++++++++++++- qase-testcafe/package.json | 2 +- qase-testcafe/src/qase.ts | 21 +++++++++++++++++++-- qase-testcafe/src/reporter.ts | 18 +++++++++++++++++- 4 files changed, 56 insertions(+), 5 deletions(-) diff --git a/qase-testcafe/changelog.md b/qase-testcafe/changelog.md index 74c48844..9e15bb6a 100644 --- a/qase-testcafe/changelog.md +++ b/qase-testcafe/changelog.md @@ -1,3 +1,20 @@ +# qase-testcafe@2.0.3 + +## What's new + +Support `ignore` metadata for test cases. If the test case has the `ignore` tag, the reporter will not send the result to the Qase +TMS. + +```ts +const q = qase.ignore().create(); +test.meta({ ...q })( + 'test', + async (t) => { + await t; + }, +); +``` + # qase-testcafe@2.0.2 ## What's new @@ -8,7 +25,8 @@ Improved error collection. The error stack trace contains more useful debugging ## What's new -Support group parameters for test cases. You can specify the group parameters in the test case using the following format: +Support group parameters for test cases. You can specify the group parameters in the test case using the following +format: ```ts const q = qase.groupParameters({ 'param01': 'value01', 'param02': 'value02' }).create(); diff --git a/qase-testcafe/package.json b/qase-testcafe/package.json index 48393930..a7cc12ee 100644 --- a/qase-testcafe/package.json +++ b/qase-testcafe/package.json @@ -1,6 +1,6 @@ { "name": "testcafe-reporter-qase", - "version": "2.0.2", + "version": "2.0.3", "description": "Qase TMS TestCafe Reporter", "main": "./dist/index.js", "types": "./dist/index.d.ts", diff --git a/qase-testcafe/src/qase.ts b/qase-testcafe/src/qase.ts index c811c085..1dacd853 100644 --- a/qase-testcafe/src/qase.ts +++ b/qase-testcafe/src/qase.ts @@ -5,6 +5,7 @@ export class qase { private static _qaseFields = ''; private static _qaseParameters = ''; private static _qaseGroupParameters = ''; + private static _qaseIgnore = ''; /** * Set a Qase ID for the test case @@ -71,16 +72,30 @@ export class qase { * Don't forget to call `create` method after setting all the necessary parameters * @param {Record} values * @example - * const q = qase.group_parameters({ 'severity': 'high', 'priority': 'medium' }).create(); + * const q = qase.groupParameters({ 'severity': 'high', 'priority': 'medium' }).create(); * test.meta(q)('Test case title', async t => { ... }); * or * test.meta({userField: 123, ...q})('Test case title', async t => { ... }); */ - public static group_parameters = (values: Record) => { + public static groupParameters = (values: Record) => { this._qaseGroupParameters = this.toNormalizeRecord(values); return this; }; + /** + * Set a ignore flag for the test case + * Don't forget to call `create` method after setting all the necessary parameters + * @example + * const q = qase.ignore().create(); + * test.meta(q)('Test case title', async t => { ... }); + * or + * test.meta({userField: 123, ...q})('Test case title', async t => { ... }); + */ + public static ignore = () => { + this._qaseIgnore = 'true'; + return this; + }; + /** * Create a Qase metadata * Call this method after setting all the necessary parameters @@ -97,6 +112,7 @@ export class qase { QaseFields: this._qaseFields, QaseParameters: this._qaseParameters, QaseGroupParameters: this._qaseGroupParameters, + QaseIgnore: this._qaseIgnore, }; this._qaseID = ''; @@ -104,6 +120,7 @@ export class qase { this._qaseFields = ''; this._qaseParameters = ''; this._qaseGroupParameters = ''; + this._qaseIgnore = ''; return meta; }; diff --git a/qase-testcafe/src/reporter.ts b/qase-testcafe/src/reporter.ts index 2085fe59..e2936f58 100644 --- a/qase-testcafe/src/reporter.ts +++ b/qase-testcafe/src/reporter.ts @@ -54,6 +54,7 @@ enum metadataEnum { parameters = 'QaseParameters', groupParameters = 'QaseGroupParameters', oldID = 'CID', + ignore = 'QaseIgnore', } interface MetadataType { @@ -62,6 +63,7 @@ interface MetadataType { [metadataEnum.fields]: Record; [metadataEnum.parameters]: Record; [metadataEnum.groupParameters]: Record; + [metadataEnum.ignore]: boolean; } export interface TestRunInfoType { @@ -162,6 +164,12 @@ export class TestcafeQaseReporter { meta: Record, formatError: (error: any, prefix: string) => string, ) => { + const metadata = this.getMeta(meta); + + if (metadata[metadataEnum.ignore]) { + return; + } + const errorLog = testRunInfo.errs .map((error, index) => formatError(error, `${index + 1} `).replace( // eslint-disable-next-line no-control-regex @@ -170,7 +178,6 @@ export class TestcafeQaseReporter { )) .join('\n'); - const metadata = this.getMeta(meta); await this.reporter.addTestResult({ author: null, execution: { @@ -222,6 +229,7 @@ export class TestcafeQaseReporter { QaseFields: {}, QaseParameters: {}, QaseGroupParameters: {}, + QaseIgnore: false, }; if (meta[metadataEnum.oldID] !== undefined && meta[metadataEnum.oldID] !== '') { @@ -246,6 +254,14 @@ export class TestcafeQaseReporter { metadata.QaseParameters = JSON.parse(meta[metadataEnum.parameters]) as Record; } + if (meta[metadataEnum.groupParameters] !== undefined && meta[metadataEnum.groupParameters] !== '') { + metadata.QaseGroupParameters = JSON.parse(meta[metadataEnum.groupParameters]) as Record; + } + + if (meta[metadataEnum.ignore] !== undefined && meta[metadataEnum.ignore] !== '') { + metadata.QaseIgnore = meta[metadataEnum.ignore] === 'true'; + } + return metadata; }