diff --git a/qase-cucumberjs/src/storage.ts b/qase-cucumberjs/src/storage.ts index 40151ff9..bfcc1639 100644 --- a/qase-cucumberjs/src/storage.ts +++ b/qase-cucumberjs/src/storage.ts @@ -234,7 +234,7 @@ export class Storage { params: {}, relations: relations, run_id: null, - signature: '', + signature: this.getSignature(pickle, metadata.ids), steps: this.convertSteps(pickle.steps, tc), testops_id: metadata.ids.length > 0 ? metadata.ids : null, id: tcs.id, @@ -353,4 +353,21 @@ export class Storage { return metadata; } + + /** + * @param {Pickle} pickle + * @param {number[]} ids + * @private + */ + private getSignature(pickle: Pickle, ids: number[]): string { + let signature = pickle.uri.split('/').join('::') + + '::' + + pickle.name.toLowerCase().replace(/\s/g, '_'); + + if (ids.length > 0) { + signature += '::' + ids.join('::'); + } + + return signature; + } } diff --git a/qase-cypress/src/reporter.ts b/qase-cypress/src/reporter.ts index e2546aeb..1def1e35 100644 --- a/qase-cypress/src/reporter.ts +++ b/qase-cypress/src/reporter.ts @@ -1,7 +1,7 @@ import path from 'path'; import { v4 as uuidv4 } from 'uuid'; -import { MochaOptions, reporters, Runner, Test } from 'mocha'; +import { MochaOptions, reporters, Runner, Suite, Test } from 'mocha'; import { ConfigLoader, @@ -194,7 +194,7 @@ export class CypressQaseReporter extends reporters.Base { params: {}, relations: relations, run_id: null, - signature: '', + signature: this.getSignature(test, ids), steps: [], id: test.id, execution: { @@ -211,6 +211,7 @@ export class CypressQaseReporter extends reporters.Base { title: test.title, }; + console.log(result.signature); void this.reporter.addTestResult(result); } @@ -225,4 +226,48 @@ export class CypressQaseReporter extends reporters.Base { process.exit = _exit; }; } + + /** + * @param {Test} test + * @param {number[]} ids + * @private + */ + private getSignature(test: Test, ids: number[]) { + let signature = ''; + const file = test.parent ? this.getFile(test.parent) : undefined; + + if (file) { + signature = file.split('/').join('::'); + } + + if (test.parent) { + for (const suite of test.parent.titlePath()) { + signature += '::' + suite.toLowerCase().replace(/\s/g, '_'); + } + } + + signature += '::' + test.title.toLowerCase().replace(/\s/g, '_'); + + if (ids.length > 0) { + signature += '::' + ids.join('::'); + } + + return signature; + } + + /** + * @param {Suite} suite + * @private + */ + private getFile(suite: Suite): string | undefined { + if (suite.file) { + return suite.file; + } + + if (suite.parent) { + return this.getFile(suite.parent); + } + + return undefined; + } } diff --git a/qase-jest/src/reporter.ts b/qase-jest/src/reporter.ts index 7b9bd8e9..5aa8c01e 100644 --- a/qase-jest/src/reporter.ts +++ b/qase-jest/src/reporter.ts @@ -1,16 +1,18 @@ import has from 'lodash.has'; import get from 'lodash.get'; import { v4 as uuidv4 } from 'uuid'; -import { Reporter, Test, TestResult, Config } from '@jest/reporters'; +import { Config, Reporter, Test, TestResult } from '@jest/reporters'; import { Status } from '@jest/test-result'; import { - QaseReporter, + composeOptions, + ConfigLoader, ConfigType, + QaseReporter, + Relation, ReporterInterface, + Suite, TestStatusEnum, - ConfigLoader, - composeOptions, } from 'qase-javascript-commons'; export type JestQaseOptionsType = ConfigType; @@ -89,16 +91,18 @@ export class JestQaseReporter implements Reporter { * @param {TestResult} result */ public onTestResult(_: Test, result: TestResult) { + console.log(result); result.testResults.forEach( ({ title, + fullName, + ancestorTitles, status, duration, failureMessages, failureDetails, }) => { let error; - if (status === 'failed') { error = new Error(failureDetails.map((item) => { if (has(item, 'matcherResult.message')) { @@ -112,6 +116,8 @@ export class JestQaseReporter implements Reporter { } const ids = JestQaseReporter.getCaseId(title); + const filePath = this.getCurrentTestPath(result.testFilePath); + void this.reporter.addTestResult({ attachments: [], author: null, @@ -127,14 +133,13 @@ export class JestQaseReporter implements Reporter { message: error?.message ?? null, muted: false, params: {}, - relations: {}, + relations: this.getRelations(filePath, ancestorTitles), run_id: null, - signature: '', + signature: this.getSignature(filePath, fullName, ids), steps: [], testops_id: ids.length > 0 ? ids : null, id: uuidv4(), title: title, - // suiteTitle: ancestorTitles, }); }, ); @@ -152,4 +157,61 @@ export class JestQaseReporter implements Reporter { public onRunComplete() { void this.reporter.publish(); } + + /** + * @param {string} filePath + * @param {string} fullName + * @param {number[]} ids + * @private + */ + private getSignature(filePath: string, fullName: string, ids: number[]) { + let signature = filePath.split('/').join('::'); + + signature += '::' + fullName.toLowerCase().replace(/\s/g, '_'); + + if (ids.length > 0) { + signature += '::' + ids.join('::'); + } + + return signature; + } + + /** + * @param {string} filePath + * @param {string[]} suites + * @private + */ + private getRelations(filePath: string, suites: string[]): Relation { + const suite: Suite = { + data: [], + }; + + for (const part of filePath.split('/')) { + suite.data.push({ + title: part, + public_id: null, + }); + } + + for (const part of suites) { + suite.data.push({ + title: part, + public_id: null, + }); + } + + return { + suite: suite, + }; + } + + /** + * @param {string} fullPath + * @private + */ + private getCurrentTestPath(fullPath: string) { + const executionPath = process.cwd() + '/'; + + return fullPath.replace(executionPath, ''); + } } diff --git a/qase-newman/src/reporter.ts b/qase-newman/src/reporter.ts index a37f3019..40230f1c 100644 --- a/qase-newman/src/reporter.ts +++ b/qase-newman/src/reporter.ts @@ -160,7 +160,7 @@ export class NewmanQaseReporter { params: {}, relations: relation, run_id: null, - signature: '', + signature: this.getSignature(suites, item.name, ids), steps: [], testops_id: ids.length > 0 ? ids : null, id: item.id, @@ -229,4 +229,26 @@ export class NewmanQaseReporter { }; } } + + /** + * @param {string[]} suites + * @param {string} title + * @param {number[]} ids + * @private + */ + private getSignature(suites: string[], title: string, ids: number[]) { + let signature = ''; + + for (const suite of suites) { + signature += suite.toLowerCase().replace(/\s/g, '_') + '::'; + } + + signature += title.toLowerCase().replace(/\s/g, '_'); + + if (ids.length > 0) { + signature += '::' + ids.join('::'); + } + + return signature; + } } diff --git a/qase-playwright/src/reporter.ts b/qase-playwright/src/reporter.ts index d6530ebb..3f812b55 100644 --- a/qase-playwright/src/reporter.ts +++ b/qase-playwright/src/reporter.ts @@ -367,7 +367,7 @@ export class PlaywrightQaseReporter implements Reporter { }, }, run_id: null, - signature: suites.join(':'), + signature: '', steps: this.transformSteps(result.steps, null), testops_id: null, title: testCaseMetadata.title === '' ? test.title : testCaseMetadata.title, @@ -394,6 +394,8 @@ export class PlaywrightQaseReporter implements Reporter { } } + testResult.signature = this.getSignature(suites, testCaseMetadata.parameters, testResult.testops_id ?? []); + await this.reporter.addTestResult(testResult); } @@ -435,4 +437,32 @@ export class PlaywrightQaseReporter implements Reporter { content: content, } as Attachment; } + + /** + * @param {string[]} suites + * @param {Record} parameters + * @param {number[]} ids + * @private + */ + private getSignature(suites: string[], parameters: Record, ids: number[]): string { + let signature = suites.map(suite => + suite.toLowerCase() + .replace('/', '::') + .replace(/\s/g, '_'), + ).join('::'); + + if (ids.length > 0) { + signature += '::' + ids.join('::'); + } + + if (Object.keys(parameters).length !== 0) { + signature += '::'; + } + + signature += Object.entries(parameters) + .map(([key, value]) => `{${key}:${value}}`) + .join('::'); + + return signature; + } } diff --git a/qase-testcafe/src/reporter.ts b/qase-testcafe/src/reporter.ts index a519af6b..dbfe23ab 100644 --- a/qase-testcafe/src/reporter.ts +++ b/qase-testcafe/src/reporter.ts @@ -170,7 +170,7 @@ export class TestcafeQaseReporter { * @returns {Promise} */ public startTestRun = (): void => { - this.reporter.startTestRun(); + this.reporter.startTestRun(); }; /** @@ -210,7 +210,7 @@ export class TestcafeQaseReporter { }, }, run_id: null, - signature: `${testRunInfo.fixture.name}::${title}`, + signature: this.getSignature(testRunInfo.fixture, title, metadata[metadataEnum.id], metadata[metadataEnum.parameters]), steps: [], id: uuidv4(), testops_id: metadata[metadataEnum.id].length > 0 ? metadata[metadataEnum.id] : null, @@ -260,4 +260,41 @@ export class TestcafeQaseReporter { return metadata; } + + /** + * @param {FixtureType} fixture + * @param {string} title + * @param {number[]} ids + * @param {Record} parameters + * @private + */ + private getSignature(fixture: FixtureType, title: string, ids: number[], parameters: Record) { + const executionPath = process.cwd() + '/'; + const path = fixture.path?.replace(executionPath, '') ?? ''; + let signature = ''; + + if (path != '') { + signature += path.split('/').join('::') + '::'; + } + + signature += fixture.name.toLowerCase() + .replace(/\s/g, '_') + + '::' + + title.toLowerCase() + .replace(/\s/g, '_'); + + if (ids.length > 0) { + signature += `::${ids.join('::')}`; + } + + if (Object.keys(parameters).length > 0) { + signature += '::'; + } + + signature += Object.entries(parameters) + .map(([key, value]) => `{${key}:${value}}`) + .join('::'); + + return signature; + } }