diff --git a/packages/mocha-runner/src/stryker-mocha-reporter.ts b/packages/mocha-runner/src/stryker-mocha-reporter.ts index 000411c36b..1f7ef82c51 100644 --- a/packages/mocha-runner/src/stryker-mocha-reporter.ts +++ b/packages/mocha-runner/src/stryker-mocha-reporter.ts @@ -43,11 +43,11 @@ export class StrykerMochaReporter { this.timer.reset(); }); - this.runner.on('fail', (test: Mocha.Test, err: Error) => { - const title = test.fullTitle(); + this.runner.on('fail', (test: Mocha.Hook | Mocha.Test, err: Error) => { + const title = test.ctx?.currentTest?.fullTitle() ?? test.fullTitle(); const result: FailedTestResult = { id: title, - failureMessage: err.message, + failureMessage: (err.message || err.stack) ?? '', name: title, status: TestStatus.Failed, timeSpentMs: this.timer.elapsedMs(), diff --git a/packages/mocha-runner/test/integration/regession.it.spec.ts b/packages/mocha-runner/test/integration/regession.it.spec.ts new file mode 100644 index 0000000000..18316cae78 --- /dev/null +++ b/packages/mocha-runner/test/integration/regession.it.spec.ts @@ -0,0 +1,62 @@ +import { FailedTestResult, TestStatus } from '@stryker-mutator/api/test-runner'; +import { assertions, factory, testInjector } from '@stryker-mutator/test-helpers'; +import { expect } from 'chai'; + +import { createMochaTestRunnerFactory } from '../../src'; +import { MochaRunnerWithStrykerOptions } from '../../src/mocha-runner-with-stryker-options'; +import { resolveTestResource } from '../helpers/resolve-test-resource'; + +describe('regression integration tests', () => { + let options: MochaRunnerWithStrykerOptions; + + beforeEach(() => { + options = testInjector.options as MochaRunnerWithStrykerOptions; + options.mochaOptions = { 'no-config': true }; + }); + + describe('issue #2720', () => { + beforeEach(async () => { + process.chdir(resolveTestResource('regression', 'issue-2720')); + }); + + it('should have report correct failing test when "beforeEach" fails', async () => { + // Arrange + options.mochaOptions.spec = ['failing-before-each']; + const sut = testInjector.injector.injectFunction(createMochaTestRunnerFactory('__stryker2__')); + await sut.init(); + + // Act + const result = await sut.dryRun(factory.dryRunOptions({})); + + // Assert + assertions.expectCompleted(result); + const expected: Partial = { + name: 'suite should fail in beforeEach', + id: 'suite should fail in beforeEach', + status: TestStatus.Failed, + }; + expect(result.tests).lengthOf(1); + expect(result.tests[0]).deep.contains(expected); + }); + + it('should have report correct failing test when "afterEach" fails', async () => { + // Arrange + options.mochaOptions.spec = ['failing-after-each']; + const sut = testInjector.injector.injectFunction(createMochaTestRunnerFactory('__stryker2__')); + await sut.init(); + + // Act + const result = await sut.dryRun(factory.dryRunOptions({})); + + // Assert + assertions.expectCompleted(result); + const expected: Partial = { + name: 'suite2 should fail in afterEach', + id: 'suite2 should fail in afterEach', + status: TestStatus.Failed, + }; + expect(result.tests).lengthOf(2); + expect(result.tests[1]).deep.contains(expected); + }); + }); +}); diff --git a/packages/mocha-runner/testResources/regression/issue-2720/failing-after-each.js b/packages/mocha-runner/testResources/regression/issue-2720/failing-after-each.js new file mode 100644 index 0000000000..419bc74e39 --- /dev/null +++ b/packages/mocha-runner/testResources/regression/issue-2720/failing-after-each.js @@ -0,0 +1,10 @@ +describe('suite2', () => { + + afterEach(() => { + throw new Error(); + }); + + it('should fail in afterEach', () => { + // idle + }); +}); diff --git a/packages/mocha-runner/testResources/regression/issue-2720/failing-before-each.js b/packages/mocha-runner/testResources/regression/issue-2720/failing-before-each.js new file mode 100644 index 0000000000..de2818b862 --- /dev/null +++ b/packages/mocha-runner/testResources/regression/issue-2720/failing-before-each.js @@ -0,0 +1,10 @@ +describe('suite', () => { + + beforeEach(() => { + throw new Error(); + }); + + it('should fail in beforeEach', () => { + // idle + }); +});