diff --git a/qase-wdio/README.md b/qase-wdio/README.md index 67a4bfbf..d5e6d12c 100644 --- a/qase-wdio/README.md +++ b/qase-wdio/README.md @@ -117,6 +117,7 @@ Also, you need to configure the reporter using the `wdio.conf.ts` file: // wdio.conf.ts import WDIOQaseReporter from 'wdio-qase-reporter'; import type { Options } from '@wdio/types'; +import { afterRunHook, beforeRunHook } from 'wdio-qase-reporter'; export const config: Options.Testrunner = { reporters: [[WDIOQaseReporter, { @@ -124,6 +125,17 @@ export const config: Options.Testrunner = { disableWebdriverScreenshotsReporting: true, useCucumber: false, }]], + + // ... + // ===== + // Hooks + // ===== + onPrepare: async function() { + await beforeRunHook(); + }, + onComplete: async function() { + await afterRunHook(); + }, // ... other options }; ``` diff --git a/qase-wdio/changelog.md b/qase-wdio/changelog.md index 01b011b2..869c4e1e 100644 --- a/qase-wdio/changelog.md +++ b/qase-wdio/changelog.md @@ -1,3 +1,53 @@ +# qase-wdio@1.0.0-beta.3 + +## What's new + +- Fix an issue with `cucumber` steps. Now, the reporter will correctly handle the `cucumber` steps and will report them + to the Qase TMS. +- Fix an issue with duplicate test runs. Now, the reporter will correctly handle the test runs and will not create + duplicate test runs in the Qase TMS. + + You need to add `beforeRunHook` hook to the `onPrepare` and `afterRunHook` hook to the `onComplete` in the + `wdio.conf.ts` configuration file: + + ```ts + import type { Options } from '@wdio/types' + import WDIOQaseReporter from "wdio-qase-reporter"; + import { afterRunHook, beforeRunHook } from "wdio-qase-reporter"; + + export const config: Options.Testrunner = { + // ... + // + // ===== + // Hooks + // ===== + // WebdriverIO provides several hooks you can use to interfere with the test process in order to enhance + // it and to build services around it. You can either apply a single function or an array of + // methods to it. If one of them returns with a promise, WebdriverIO will wait until that promise got + // resolved to continue. + /** + * Gets executed once before all workers get launched. + * @param {object} config wdio configuration object + * @param {Array.} capabilities list of capabilities details + */ + onPrepare: async function() { + await beforeRunHook(); + }, + + /** + * Gets executed after all workers got shut down and the process is about to exit. An error + * thrown in the onComplete hook will result in the test run failing. + * @param {object} exitCode 0 - success, 1 - fail + * @param {object} config wdio configuration object + * @param {Array.} capabilities list of capabilities details + * @param {} results object containing test results + */ + onComplete: async function() { + await afterRunHook(); + }, + } + ``` + # qase-wdio@1.0.0-beta.2 ## What's new diff --git a/qase-wdio/package.json b/qase-wdio/package.json index db421b35..afbf9ec9 100644 --- a/qase-wdio/package.json +++ b/qase-wdio/package.json @@ -1,6 +1,6 @@ { "name": "wdio-qase-reporter", - "version": "1.0.0-beta.2", + "version": "1.0.0-beta.3", "description": "Qase WebDriverIO Reporter", "homepage": "https://github.com/qase-tms/qase-javascript", "sideEffects": false, diff --git a/qase-wdio/src/hooks.ts b/qase-wdio/src/hooks.ts new file mode 100644 index 00000000..b0333d80 --- /dev/null +++ b/qase-wdio/src/hooks.ts @@ -0,0 +1,32 @@ +import { ConfigLoader, QaseReporter } from 'qase-javascript-commons'; + +export async function beforeRunHook() { + const configLoader = new ConfigLoader(); + const config = configLoader.load(); + + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument + const reporter = QaseReporter.getInstance({ + ...config, + frameworkPackage: 'wdio', + frameworkName: 'wdio', + reporterName: 'wdio-qase-reporter', + }); + + // eslint-disable-next-line @typescript-eslint/no-unsafe-call + await reporter.startTestRunAsync(); +} + +export async function afterRunHook() { + const configLoader = new ConfigLoader(); + const config = configLoader.load(); + + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument + const reporter = QaseReporter.getInstance({ + ...config, + frameworkPackage: 'wdio', + frameworkName: 'wdio', + reporterName: 'wdio-qase-reporter', + }); + + await reporter.complete(); +} diff --git a/qase-wdio/src/index.ts b/qase-wdio/src/index.ts index a6ecef51..dd143ee0 100644 --- a/qase-wdio/src/index.ts +++ b/qase-wdio/src/index.ts @@ -1,4 +1,5 @@ import WDIOQaseReporter from './reporter.js'; export * from './wdio'; +export * from './hooks'; export default WDIOQaseReporter; diff --git a/qase-wdio/src/reporter.ts b/qase-wdio/src/reporter.ts index fe7413b1..1b495f36 100644 --- a/qase-wdio/src/reporter.ts +++ b/qase-wdio/src/reporter.ts @@ -97,7 +97,7 @@ export default class WDIOQaseReporter extends WDIOReporter { override onRunnerStart(runner: RunnerStats) { this._isMultiremote = runner.isMultiremote; - this.reporter.startTestRun(); + // this.reporter.startTestRun(); this.isSync = false; } @@ -135,20 +135,6 @@ export default class WDIOQaseReporter extends WDIOReporter { case '@suite': this.addSuite({ suite: tagData.value }); break; - // case 'parameters': - // const params = tagData.value.split(',').map((param) => { - // const [key, value] = param.split(':'); - // return { key, value }; - // }); - // process.emit(events.addParameters, { records: params }); - // break; - // case 'fields': - // const fields = tagData.value.split(',').map((field) => { - // const [key, value] = field.split(':'); - // return { key, value }; - // }); - // process.emit(events.addFields, { records: fields }); - // break; } } @@ -200,7 +186,7 @@ export default class WDIOQaseReporter extends WDIOReporter { } override async onRunnerEnd(_: RunnerStats) { - await this.reporter.publish(); + await this.reporter.sendResults(); this.isSync = true; } @@ -238,14 +224,51 @@ export default class WDIOQaseReporter extends WDIOReporter { return err; } - override async onTestEnd(test: TestStats) { + override async onTestPass() { + if (this._options.useCucumber) { + this._endStep(); + return; + } + + await this._endTest(TestStatusEnum.passed, null); + } + + override async onTestRetry(test: TestStats) { + const error = test.errors ? WDIOQaseReporter.transformError(test.errors) : null; + + if (this._options.useCucumber) { + this._endStep(error ? TestStatusEnum.failed : TestStatusEnum.passed); + return; + } + + await this._endTest(WDIOQaseReporter.statusMap[test.state] ?? TestStatusEnum.skipped, + error, + test.end ? test.end.valueOf() / 1000 : Date.now().valueOf() / 1000); + } + + override async onTestFail(test: TestStats) { const error = test.errors ? WDIOQaseReporter.transformError(test.errors) : null; + if (this._options.useCucumber) { + this._endStep(TestStatusEnum.failed); + return; + } + await this._endTest(WDIOQaseReporter.statusMap[test.state] ?? TestStatusEnum.skipped, error, test.end ? test.end.valueOf() / 1000 : Date.now().valueOf() / 1000); } + override async onTestSkip(test: TestStats) { + if (this._options.useCucumber) { + this._endStep(TestStatusEnum.skipped); + return; + } + + await this._endTest(WDIOQaseReporter.statusMap[test.state] ?? TestStatusEnum.skipped, + null); + } + private async _endTest(status: TestStatusEnum, err: CompoundError | null, end_time: number = Date.now().valueOf() / 1000) { const testResult = this.storage.getCurrentTest(); if (testResult === undefined || this.storage.ignore) { @@ -275,18 +298,9 @@ export default class WDIOQaseReporter extends WDIOReporter { null : err.message === undefined ? null : err.message; - console.log(testResult); await this.reporter.addTestResult(testResult); } - override onHookStart() { - console.log('Hook started'); - } - - override onHookEnd() { - console.log('Hook ended'); - } - override onBeforeCommand(command: BeforeCommandArgs) { if (!this.storage.getLastItem()) { return;