diff --git a/packages/stryker/src/ScoreResultCalculator.ts b/packages/stryker/src/ScoreResultCalculator.ts index fe30d7d037..8b8723b8c0 100644 --- a/packages/stryker/src/ScoreResultCalculator.ts +++ b/packages/stryker/src/ScoreResultCalculator.ts @@ -5,11 +5,11 @@ import { MutationScoreThresholds } from 'stryker-api/core'; import { MutantResult, MutantStatus, ScoreResult } from 'stryker-api/report'; import { freezeRecursively, setExitCode } from './utils/objectUtils'; - export default class ScoreResultCalculator { static calculate(results: MutantResult[]): ScoreResult { - return this.calculateScoreResult(results, ''); + const scoreResult = this.calculateScoreResult(results, ''); + return this.wrapIfSingleFileScoreResult(scoreResult); } static determineExitCode(score: ScoreResult, thresholds: MutationScoreThresholds | undefined) { @@ -28,12 +28,28 @@ export default class ScoreResultCalculator { } } + private static wrapIfSingleFileScoreResult(scoreResult: ScoreResult): ScoreResult { + if (scoreResult.representsFile) { + return this.copy(scoreResult, { + name: path.dirname(scoreResult.name), childResults: [ + this.copy(scoreResult, { name: path.basename(scoreResult.name) }) + ] + }); + } else { + return scoreResult; + } + } + private static calculateScoreResult(results: MutantResult[], basePath: string): ScoreResult { const numbers = this.countNumbers(results); const facts = this.determineFacts(basePath, results); return freezeRecursively(_.assign(numbers, facts)); } + private static copy(defaults: ScoreResult, overrides: Partial): ScoreResult { + return Object.assign({}, defaults, overrides); + } + private static determineFacts(basePath: string, results: MutantResult[]) { const name = this.determineCommonBasePath(results, basePath); const childResults = this.calculateChildScores(results, name, basePath); @@ -41,7 +57,7 @@ export default class ScoreResultCalculator { name, path: path.join(basePath, name), childResults, - representsFile: childResults.length === 0 + representsFile: childResults.length === 0 && results.length > 0 }; } diff --git a/packages/stryker/test/unit/ScoreResultCalculatorSpec.ts b/packages/stryker/test/unit/ScoreResultCalculatorSpec.ts index 83507c991b..4cc1b81b5c 100644 --- a/packages/stryker/test/unit/ScoreResultCalculatorSpec.ts +++ b/packages/stryker/test/unit/ScoreResultCalculatorSpec.ts @@ -22,18 +22,31 @@ describe('ScoreResult', () => { mutantResult({ status: MutantStatus.Killed, sourceFilePath: fileName }), mutantResult({ status: MutantStatus.TimedOut, sourceFilePath: fileName }), ]); - expect(actual.name).to.eq(fileName); - expect(actual.killed, 'killed').to.eq(2); - expect(actual.survived, 'survived').to.eq(1); - expect(actual.noCoverage, 'noCoverage').to.eq(1); - expect(actual.timedOut, 'timedOut').to.eq(1); - expect(actual.totalCovered, 'totalCovered').to.eq(4); - expect(actual.totalDetected, 'detected').to.eq(3); - expect(actual.totalMutants, 'mutants').to.eq(5); - expect(actual.totalUndetected, 'undetected').to.eq(2); - expect(actual.mutationScoreBasedOnCoveredCode, 'percentageBasedOnCoveredCode').to.eq(75); - expect(actual.mutationScore, 'mutationScore').to.eq(60); - expect(actual.childResults).to.have.lengthOf(0); + expect(actual.name).to.eq('base'); + function assertNumbers(actual: ScoreResult) { + expect(actual.killed, 'killed').to.eq(2); + expect(actual.survived, 'survived').to.eq(1); + expect(actual.noCoverage, 'noCoverage').to.eq(1); + expect(actual.timedOut, 'timedOut').to.eq(1); + expect(actual.totalCovered, 'totalCovered').to.eq(4); + expect(actual.totalDetected, 'detected').to.eq(3); + expect(actual.totalMutants, 'mutants').to.eq(5); + expect(actual.totalUndetected, 'undetected').to.eq(2); + expect(actual.mutationScoreBasedOnCoveredCode, 'percentageBasedOnCoveredCode').to.eq(75); + expect(actual.mutationScore, 'mutationScore').to.eq(60); + } + assertNumbers(actual); + assertNumbers(actual.childResults[0]); + }); + + it('should wrap a single result in its base directory', () => { + const fileName = path.join('base', 'something'); + const actual = ScoreResultCalculator.calculate([ + mutantResult({ status: MutantStatus.Error, sourceFilePath: fileName }) + ]); + expect(actual.name).eq('base'); + expect(actual.childResults).lengthOf(1); + expect(actual.childResults[0].name).eq('something'); }); it('should count results of multiple files', () => {