From 48f39e33c9bb983c58fcb4ab4e8cd1ccb4102cb5 Mon Sep 17 00:00:00 2001 From: David Goss Date: Sun, 29 May 2022 16:35:36 +0100 Subject: [PATCH 1/4] include willBeRetried in after hook again --- src/runtime/test_case_runner.ts | 7 +++- src/runtime/test_case_runner_spec.ts | 39 ++++++++++++++++++++++- src/support_code_library_builder/types.ts | 1 + 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/src/runtime/test_case_runner.ts b/src/runtime/test_case_runner.ts index 9b77ce904..4a00f06d8 100644 --- a/src/runtime/test_case_runner.ts +++ b/src/runtime/test_case_runner.ts @@ -175,6 +175,7 @@ export default class TestCaseRunner { async run(): Promise { for (let attempt = 0; attempt < this.maxAttempts; attempt++) { + const moreAttemptsRemaining = attempt + 1 < this.maxAttempts this.currentTestCaseStartedId = this.newId() const testCaseStarted: messages.Envelope = { testCaseStarted: { @@ -197,6 +198,9 @@ export default class TestCaseRunner { } if (didWeRunStepsYet) { hookParameter.result = this.getWorstStepResult() + hookParameter.willBeRetried = + this.getWorstStepResult().status === + messages.TestStepResultStatus.FAILED && moreAttemptsRemaining } return await this.runHook( findHookDefinition(testStep.hookId, this.supportCodeLibrary), @@ -213,9 +217,10 @@ export default class TestCaseRunner { } }) } + const willBeRetried = this.getWorstStepResult().status === - messages.TestStepResultStatus.FAILED && attempt + 1 < this.maxAttempts + messages.TestStepResultStatus.FAILED && moreAttemptsRemaining const testCaseFinished: messages.Envelope = { testCaseFinished: { testCaseStartedId: this.currentTestCaseStartedId, diff --git a/src/runtime/test_case_runner_spec.ts b/src/runtime/test_case_runner_spec.ts index 1d5b1594d..494429537 100644 --- a/src/runtime/test_case_runner_spec.ts +++ b/src/runtime/test_case_runner_spec.ts @@ -258,7 +258,6 @@ describe('TestCaseRunner', () => { describe('with a flaky step and a positive retries value', () => { it('emits the expected envelopes and returns a passing result', async () => { - // Arrange const supportCodeLibrary = buildSupportCodeLibrary(({ Given }) => { let willPass = false Given('a step', function () { @@ -359,6 +358,44 @@ describe('TestCaseRunner', () => { expect(envelopes).to.eql(expected) expect(result).to.eql(messages.TestStepResultStatus.PASSED) }) + + it('should provide the correctly willBeRetried value to the hook', async () => { + // Arrange + const hookStub = sinon.stub() + const supportCodeLibrary = buildSupportCodeLibrary( + ({ Given, After }) => { + let willPass = false + Given('a step', function () { + if (willPass) { + return + } + willPass = true + throw 'error' // eslint-disable-line @typescript-eslint/no-throw-literal + }) + After(hookStub) + } + ) + const { + gherkinDocument, + pickles: [pickle], + } = await parse({ + data: ['Feature: a', 'Scenario: b', 'Given a step'].join('\n'), + uri: 'a.feature', + }) + + // Act + await testRunner({ + gherkinDocument, + pickle, + retries: 1, + supportCodeLibrary, + }) + + // Assert + expect(hookStub).to.have.been.calledTwice() + expect(hookStub.args[0][0].willBeRetried).to.eq(true) + expect(hookStub.args[1][0].willBeRetried).to.eq(false) + }) }) describe('with a step when skipping', () => { diff --git a/src/support_code_library_builder/types.ts b/src/support_code_library_builder/types.ts index a33d2c56c..47e19d856 100644 --- a/src/support_code_library_builder/types.ts +++ b/src/support_code_library_builder/types.ts @@ -15,6 +15,7 @@ export interface ITestCaseHookParameter { gherkinDocument: messages.GherkinDocument pickle: messages.Pickle result?: messages.TestStepResult + willBeRetried?: boolean testCaseStartedId: string } From 3a6d3f0228d4af59e29a2d5df0fda4941a371176 Mon Sep 17 00:00:00 2001 From: David Goss Date: Mon, 30 May 2022 08:06:12 +0100 Subject: [PATCH 2/4] update documentation --- UPGRADING.md | 4 ++++ docs/support_files/api_reference.md | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/UPGRADING.md b/UPGRADING.md index 6f084607b..5469ac7f4 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -29,6 +29,10 @@ setDefinitionFunctionWrapper(function (fn) { }) ``` +### Accessing `willBeRetried` from hooks + +In the argument passed to your `After` hook function, the `result` no longer has a `willBeRetried` property; this is now available at the top level of the object. + ### Using `Cli` programmatically The `Cli` class is sometimes used to run Cucumber programmatically. We've had to make a few breaking changes: diff --git a/docs/support_files/api_reference.md b/docs/support_files/api_reference.md index dee006a94..abf64228d 100644 --- a/docs/support_files/api_reference.md +++ b/docs/support_files/api_reference.md @@ -38,7 +38,7 @@ Defines a hook which is run after each scenario. * `tags`: String tag expression used to apply this hook to only specific scenarios. See [cucumber-tag-expressions](https://docs.cucumber.io/tag-expressions/) for more information. * `timeout`: A hook-specific timeout, to override the default timeout. * `fn`: A function, defined as follows: - * The first argument will be an object of the form `{pickle, gherkinDocument, result, testCaseStartedId}` + * The first argument will be an object of the form `{pickle, gherkinDocument, result, willBeRetried, testCaseStartedId}` * The pickle object comes from the [gherkin](https://github.com/cucumber/cucumber/tree/gherkin/v15.0.2/gherkin) library. See `testdata/good/*.pickles.ndjson` for examples of its structure. * When using the asynchronous callback interface, have one final argument for the callback function. From 4579eb25c686bec0b7dc58b0bdf945975c3d20a0 Mon Sep 17 00:00:00 2001 From: David Goss Date: Mon, 30 May 2022 08:07:56 +0100 Subject: [PATCH 3/4] update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8942acbc5..f2f4c36fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). Please see [CONTRIBUTING.md](https://github.com/cucumber/cucumber/blob/master/CONTRIBUTING.md) on how to contribute to Cucumber. ## [Unreleased] +### Added +- Add `willBeRetried` to the parameter passed to `After` hook functions ([#2045](https://github.com/cucumber/cucumber-js/pull/2045)) ## [8.2.2] - 2022-05-27 ### Changed From 0044fc0f84ed142ba738f71aae2d25a95aa8266a Mon Sep 17 00:00:00 2001 From: David Goss Date: Mon, 6 Jun 2022 08:58:31 +0100 Subject: [PATCH 4/4] readd comment --- src/runtime/test_case_runner_spec.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/runtime/test_case_runner_spec.ts b/src/runtime/test_case_runner_spec.ts index 494429537..0447ea605 100644 --- a/src/runtime/test_case_runner_spec.ts +++ b/src/runtime/test_case_runner_spec.ts @@ -258,6 +258,7 @@ describe('TestCaseRunner', () => { describe('with a flaky step and a positive retries value', () => { it('emits the expected envelopes and returns a passing result', async () => { + // Arrange const supportCodeLibrary = buildSupportCodeLibrary(({ Given }) => { let willPass = false Given('a step', function () {