From 901da7fa3df331449e01d7d5f0061bbc1d44580e Mon Sep 17 00:00:00 2001 From: John Lonergan <836248+Johnlon@users.noreply.github.com> Date: Tue, 23 Jul 2024 17:22:51 +0100 Subject: [PATCH] fixed a bug where the attachments are extracted from the context too early, this prevented AfterStep from making attachments (#637) * fixed a bug where the attachments are extracted from the context too early, this prevented AfterStep from making attachments --- _examples/attachments/attachments_test.go | 13 +++++++ internal/formatters/fmt_output_test.go | 34 +++++++++++++++++-- .../cucumber/scenario_with_attachment | 10 ++++++ .../events/scenario_with_attachment | 2 ++ suite.go | 9 +++-- 5 files changed, 61 insertions(+), 7 deletions(-) diff --git a/_examples/attachments/attachments_test.go b/_examples/attachments/attachments_test.go index 9d699405..2f14b085 100644 --- a/_examples/attachments/attachments_test.go +++ b/_examples/attachments/attachments_test.go @@ -46,6 +46,19 @@ func TestFeatures(t *testing.T) { func InitializeScenario(ctx *godog.ScenarioContext) { + ctx.StepContext().Before(func(ctx context.Context, st *godog.Step) (context.Context, error) { + ctx = godog.Attach(ctx, + godog.Attachment{Body: []byte("BeforeStepAttachment"), FileName: "Data Attachment", MediaType: "text/plain"}, + ) + return ctx, nil + }) + ctx.StepContext().After(func(ctx context.Context, st *godog.Step, status godog.StepResultStatus, err error) (context.Context, error) { + ctx = godog.Attach(ctx, + godog.Attachment{Body: []byte("AfterStepAttachment"), FileName: "Data Attachment", MediaType: "text/plain"}, + ) + return ctx, nil + }) + ctx.Step(`^I have attached two documents in sequence$`, func(ctx context.Context) (context.Context, error) { // the attached bytes will be base64 encoded by the framework and placed in the embeddings section of the cuke report ctx = godog.Attach(ctx, diff --git a/internal/formatters/fmt_output_test.go b/internal/formatters/fmt_output_test.go index 41884fb3..2ab799af 100644 --- a/internal/formatters/fmt_output_test.go +++ b/internal/formatters/fmt_output_test.go @@ -63,6 +63,36 @@ func listFmtOutputTestsFeatureFiles() (featureFiles []string, err error) { func fmtOutputTest(fmtName, testName, featureFilePath string) func(*testing.T) { fmtOutputScenarioInitializer := func(ctx *godog.ScenarioContext) { + + ctx.StepContext().Before(func(ctx context.Context, st *godog.Step) (context.Context, error) { + att := godog.Attachments(ctx) + attCount := len(att) + if attCount > 0 { + assert.FailNow(tT, fmt.Sprintf("Unexpected Attachments found - should have been empty, found %d\n%+v", attCount, att)) + } + + if st.Text == "a step with multiple attachment calls" { + ctx = godog.Attach(ctx, + godog.Attachment{Body: []byte("BeforeStepAttachment"), FileName: "Data Attachment", MediaType: "text/plain"}, + ) + } + return ctx, nil + }) + ctx.StepContext().After(func(ctx context.Context, st *godog.Step, status godog.StepResultStatus, err error) (context.Context, error) { + + if st.Text == "a step with multiple attachment calls" { + att := godog.Attachments(ctx) + attCount := len(att) + if attCount != 3 { + assert.FailNow(tT, fmt.Sprintf("Expected 3 Attachments - 1 from the before step and 2 from the step, found %d\n%+v", attCount, att)) + } + ctx = godog.Attach(ctx, + godog.Attachment{Body: []byte("AfterStepAttachment"), FileName: "Data Attachment", MediaType: "text/plain"}, + ) + } + return ctx, nil + }) + ctx.Step(`^(?:a )?failing step`, failingStepDef) ctx.Step(`^(?:a )?pending step$`, pendingStepDef) ctx.Step(`^(?:a )?passing step$`, passingStepDef) @@ -144,8 +174,8 @@ func stepWithSingleAttachmentCall(ctx context.Context) (context.Context, error) return ctx, nil } func stepWithMultipleAttachmentCalls(ctx context.Context) (context.Context, error) { - if len(godog.Attachments(ctx)) > 0 { - assert.FailNow(tT, "Unexpected Attachments found - should have been empty") + if len(godog.Attachments(ctx)) != 1 { + assert.FailNow(tT, "Expected 1 Attachment that should have been inserted by before step") } ctx = godog.Attach(ctx, diff --git a/internal/formatters/formatter-tests/cucumber/scenario_with_attachment b/internal/formatters/formatter-tests/cucumber/scenario_with_attachment index 633efae6..4c207daa 100644 --- a/internal/formatters/formatter-tests/cucumber/scenario_with_attachment +++ b/internal/formatters/formatter-tests/cucumber/scenario_with_attachment @@ -51,6 +51,11 @@ "duration": 0 }, "embeddings": [ + { + "name": "Data Attachment", + "mime_type": "text/plain", + "data": "QmVmb3JlU3RlcEF0dGFjaG1lbnQ=" + }, { "name": "TheFilename1", "mime_type": "text/plain", @@ -60,6 +65,11 @@ "name": "TheFilename2", "mime_type": "text/plain", "data": "VGhlRGF0YTI=" + }, + { + "name": "Data Attachment", + "mime_type": "text/plain", + "data": "QWZ0ZXJTdGVwQXR0YWNobWVudA==" } ] } diff --git a/internal/formatters/formatter-tests/events/scenario_with_attachment b/internal/formatters/formatter-tests/events/scenario_with_attachment index 4faa1e2c..0751ec8b 100644 --- a/internal/formatters/formatter-tests/events/scenario_with_attachment +++ b/internal/formatters/formatter-tests/events/scenario_with_attachment @@ -8,8 +8,10 @@ {"event":"TestStepFinished","location":"formatter-tests/features/scenario_with_attachment.feature:7","timestamp":-6795364578871,"status":"passed"} {"event":"StepDefinitionFound","location":"formatter-tests/features/scenario_with_attachment.feature:8","definition_id":"fmt_output_test.go:XXX -\u003e github.com/cucumber/godog/internal/formatters_test.stepWithMultipleAttachmentCalls","arguments":[]} {"event":"TestStepStarted","location":"formatter-tests/features/scenario_with_attachment.feature:8","timestamp":-6795364578871} +{"event":"Attachment","location":"formatter-tests/features/scenario_with_attachment.feature:8","timestamp":-6795364578871,"contentEncoding":"BASE64","fileName":"Data Attachment","mimeType":"text/plain","body":"BeforeStepAttachment"} {"event":"Attachment","location":"formatter-tests/features/scenario_with_attachment.feature:8","timestamp":-6795364578871,"contentEncoding":"BASE64","fileName":"TheFilename1","mimeType":"text/plain","body":"TheData1"} {"event":"Attachment","location":"formatter-tests/features/scenario_with_attachment.feature:8","timestamp":-6795364578871,"contentEncoding":"BASE64","fileName":"TheFilename2","mimeType":"text/plain","body":"TheData2"} +{"event":"Attachment","location":"formatter-tests/features/scenario_with_attachment.feature:8","timestamp":-6795364578871,"contentEncoding":"BASE64","fileName":"Data Attachment","mimeType":"text/plain","body":"AfterStepAttachment"} {"event":"TestStepFinished","location":"formatter-tests/features/scenario_with_attachment.feature:8","timestamp":-6795364578871,"status":"passed"} {"event":"TestCaseFinished","location":"formatter-tests/features/scenario_with_attachment.feature:6","timestamp":-6795364578871,"status":"passed"} {"event":"TestRunFinished","status":"passed","timestamp":-6795364578871,"snippets":"","memory":""} diff --git a/suite.go b/suite.go index dcd1bb54..5628c03b 100644 --- a/suite.go +++ b/suite.go @@ -179,16 +179,15 @@ func (s *suite) runStep(ctx context.Context, pickle *Scenario, step *Step, scena status = StepPassed } - pickledAttachments := pickleAttachments(ctx) - ctx = clearAttach(ctx) - // Run after step handlers. rctx, err = s.runAfterStepHooks(ctx, step, status, err) - shouldFail := s.shouldFail(err) + // extract any accumulated attachments and clear them + pickledAttachments := pickleAttachments(rctx) + rctx = clearAttach(rctx) // Trigger after scenario on failing or last step to attach possible hook error to step. - if !s.shouldFail(scenarioErr) && (isLast || shouldFail) { + if !s.shouldFail(scenarioErr) && (isLast || s.shouldFail(err)) { rctx, err = s.runAfterScenarioHooks(rctx, pickle, err) }