cucumber-html-report-generator
Version:
Generate beautiful cucumberjs html reports for multiple instances (browsers / devices)
128 lines (110 loc) • 6.61 kB
text/typescript
import * as CommonFunctions from '../../common-functions/common-functions';
import * as Messages from '../../helpers/console-messages';
import * as Models from '../../models/models';
import * as messages from '@cucumber/messages';
import { FeatureFormatter } from './feature-formatter';
import { v4 as uuidv4 } from 'uuid';
import GherkinDocument = messages.GherkinDocument;
import IFeature = messages.Feature;
export class SuiteFactory {
private readonly userProperties: Models.ReportGeneration;
private readonly suite: Models.ExtendedReport;
public constructor( userProperies: Models.ReportGeneration ) {
this.userProperties = userProperies;
this.suite = this.initializeSuite();
}
public async parseJsons ( collectedJsons: Models.Feature[], providedFeatures: GherkinDocument[] | null ): Promise<Models.ExtendedReport> {
const features = await Promise.all(
collectedJsons.map( jsonFeature => {
const gherkinFeature = this.getGherkinFeature( providedFeatures, jsonFeature.name );
const feature = new FeatureFormatter( gherkinFeature, jsonFeature ).parseFeature();
this.updateSuiteStadistics( feature );
if ( !feature.elements?.length ) {
console.log( Messages.featureRemoved( feature.name ) );
return null;
}
return feature;
} )
);
this.suite.features = features.flatMap( feature => feature ? [ feature ] : [] );
this.updateSuiteProperties();
this.suite.results.overview.result = [ ...new Map( this.suite.results.overview.result.map( item => [ item.status, item ] ) ).values() ];
this.suite.results.overview.resultStatusesJoined = this.suite.results.overview.result.map( ( value ) => value.status.toString() ).sort().join( ';' );
if ( this.suite.features.some( feature => feature.metadata?.length ) ) {
this.suite.haveFeaturesMetadata = true;
}
if ( this.userProperties.saveEnrichedJSON ) {
await this.saveEnrichedJson();
}
return this.suite;
}
private updateSuiteProperties (): void {
this.suite.features = this.suite.features.sort( ( firstFeature, secondFeature ) => ( firstFeature.id! > secondFeature.id! ? 1 : -1 ) );
this.addMissingMetadataToFeatures();
this.suite.results.overview.durationHHMMSS = CommonFunctions.convertTimeFromNanoSecondsToHHMMSS( this.suite.results.overview.duration );
this.suite.metadata = CommonFunctions.isMetadata( this.userProperties.reportMetadata ) ? this.userProperties.reportMetadata : <Models.Metadata[]>[];
this.suite.features = this.setUniqueIdForEachFeature( this.suite.features );
}
private async saveEnrichedJson (): Promise<void> {
await CommonFunctions.saveJsonFile( this.userProperties.reportPath, 'enriched-output.json', this.suite );
}
private getGherkinFeature ( providedFeatures: GherkinDocument[] | null, jsonFeatureName: string ): IFeature | null | undefined {
return providedFeatures?.length ? providedFeatures.filter( document => document.feature?.name === jsonFeatureName )[ 0 ]?.feature : null;
}
private updateSuiteStadistics ( feature: Models.Feature ): void {
const overview = feature.results.overview;
this.suite.results.overview.duration += overview.duration;
this.suite.results.features.passed += overview.result.filter( result => result.status === Models.Status.passed ).length === overview.result.length && overview.result.length ? 1 : 0;
this.suite.results.features.failed += overview.result.filter( result => result.status === Models.Status.failed ).length === overview.result.length && overview.result.length ? 1 : 0;
this.suite.results.features.pending += overview.result.filter( result => result.status === Models.Status.pending ).length === overview.result.length && overview.result.length ? 1 : 0;
this.suite.results.features.skipped += overview.result.filter( result => result.status === Models.Status.skipped ).length === overview.result.length && overview.result.length ? 1 : 0;
this.suite.results.features.ambiguous += overview.result.filter( result => result.status === Models.Status.ambiguous ).length === overview.result.length && overview.result.length ? 1 : 0;
this.suite.results.features.undefined += overview.result.filter( result => result.status === Models.Status.undefined ).length === overview.result.length && overview.result.length ? 1 : 0;
this.suite.results.features.various += Number( [ ... new Set( overview.result ) ].length > 1 );
this.suite.results.features.total++;
this.suite.results.scenarios = CommonFunctions.updateResultsAndPercentages( this.suite.results.scenarios, feature.results.scenarios );
this.suite.results.steps = CommonFunctions.updateResultsAndPercentages( this.suite.results.steps, feature.results.steps );
this.suite.results.features = <Models.FeatureModuleResults>CommonFunctions.updatePercentages( this.suite.results.features );
this.suite.results.overview.result.push( ...feature.results.overview.result );
}
private initializeSuite (): Models.ExtendedReport {
const suite = <Models.ExtendedReport>{};
suite.results = Models.reportResultsInitializer();
suite.metadata = <Models.Metadata[]>[];
suite.metadataTitle = this.userProperties.reportMetadataTitle;
suite.reportTitle = this.userProperties.reportTitle;
suite.haveFeaturesMetadata = false;
return suite;
}
private setUniqueIdForEachFeature ( features: Models.Feature[] ): Models.Feature[] {
const seen = new Set();
const modifiedFeatures = features.map( feature => {
if ( seen.size === seen.add( feature.id ).size ) {
feature.id += uuidv4();
}
return feature;
} );
return modifiedFeatures;
}
private addMissingMetadataToFeatures (): void {
const allMetadata: Models.Metadata[] = [];
this.suite.features.forEach( feature => {
if ( feature.metadata?.length ) {
feature.metadata.forEach( metadataElement => {
if ( !allMetadata.filter( metadataObject => metadataObject.name === metadataElement.name ).length ) {
allMetadata.push( metadataElement );
}
} );
}
} );
this.suite.results.overview.metadata = allMetadata;
this.suite.features.forEach( feature => {
allMetadata.forEach( metadataElement => {
const featureMetadataName = feature.metadata?.filter( featureMetadataElement => featureMetadataElement.name === metadataElement.name );
if ( !featureMetadataName?.length ) {
feature.metadata!.push( { name: metadataElement.name, value: '' } );
}
} );
} );
}
}