From 5f3b77106c8b49779241c5ce5d2c4cdfcfe1a648 Mon Sep 17 00:00:00 2001 From: Ahmed Abouzied Date: Mon, 18 Nov 2024 18:09:43 +0100 Subject: [PATCH 1/2] Add support for body contains assertion Signed-off-by: Ahmed Abouzied --- _testdata/Dynamic.feature | 6 +++++- _testdata/LocalClient.feature | 5 +++++ local_client.go | 22 ++++++++++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/_testdata/Dynamic.feature b/_testdata/Dynamic.feature index ee83fa8..ebc0cf9 100644 --- a/_testdata/Dynamic.feature +++ b/_testdata/Dynamic.feature @@ -19,6 +19,10 @@ Feature: Dynamic data is used in steps "created_at":"","updated_at": "" } """ + And I should have response with body, that contains + """ + "id":"$user_id" + """ # Creating an order for that user with $user_id. When I request HTTP endpoint with method "POST" and URI "/order/$user_id/?user_id=$user_id" @@ -43,4 +47,4 @@ Feature: Dynamic data is used in steps "user_id":"$user_id", "prefixed_user": "static_prefix::$user" } - """ \ No newline at end of file + """ diff --git a/_testdata/LocalClient.feature b/_testdata/LocalClient.feature index a34da03..2dfffb6 100644 --- a/_testdata/LocalClient.feature +++ b/_testdata/LocalClient.feature @@ -128,4 +128,9 @@ Feature: HTTP Service """ And I should have "some-service" response with header "Content-Type: application/json" + And I should have "some-service" response with body, that contains + """ + some + """ + diff --git a/local_client.go b/local_client.go index d3d30bb..0641dd4 100644 --- a/local_client.go +++ b/local_client.go @@ -212,6 +212,7 @@ func (l *LocalClient) RegisterSteps(s *godog.ScenarioContext) { s.Step(`^I should have(.*) response with body from file$`, l.iShouldHaveResponseWithBodyFromFile) s.Step(`^I should have(.*) response with body$`, l.iShouldHaveResponseWithBody) + s.Step(`^I should have(.*) response with body, that contains$`, l.iShouldHaveResponseWithBodyThatContains) s.Step(`^I should have(.*) response with body, that matches JSON from file$`, l.iShouldHaveResponseWithBodyThatMatchesJSONFromFile) s.Step(`^I should have(.*) response with body, that matches JSON$`, l.iShouldHaveResponseWithBodyThatMatchesJSON) s.Step(`^I should have(.*) response with body, that matches JSON paths$`, l.iShouldHaveResponseWithBodyThatMatchesJSONPaths) @@ -553,6 +554,7 @@ const ( errUnexpectedExpectations = sentinelError("unexpected existing expectations") errInvalidNumberOfColumns = sentinelError("invalid number of columns") errUnexpectedBody = sentinelError("unexpected body") + errDoesNotContain = sentinelError("does not contain") ) func statusCode(statusOrCode string) (int, error) { @@ -740,6 +742,26 @@ func (l *LocalClient) iShouldHaveResponseWithBody(ctx context.Context, service, }) } +func (l *LocalClient) iShouldHaveResponseWithBodyThatContains(ctx context.Context, service, bodyDoc string) (context.Context, error) { + ctx = l.VS.PrepareContext(ctx) + + return l.expectResponse(ctx, service, func(c *httpmock.Client) error { + return c.ExpectResponseBodyCallback(func(received []byte) error { + ctx, rv, err := l.VS.Replace(ctx, []byte(bodyDoc)) + if err != nil { + return err + } + + s, substr := string(received), string(rv) + if !strings.Contains(s, substr) { + return augmentBodyErr(ctx, fmt.Errorf("%w %q in %q", errDoesNotContain, substr, s)) + } + + return nil + }) + }) +} + func (l *LocalClient) iShouldHaveResponseWithBodyFromFile(ctx context.Context, service, filePath string) (context.Context, error) { ctx = l.VS.PrepareContext(ctx) From 82de43a6525d1b0699eb8f44310d5591ef50f496 Mon Sep 17 00:00:00 2001 From: Ahmed Abouzied Date: Mon, 18 Nov 2024 18:34:23 +0100 Subject: [PATCH 2/2] Add support for other responses assert contains Signed-off-by: Ahmed Abouzied --- _testdata/LocalClient.feature | 4 ++++ local_client.go | 33 ++++++++++++++++++++++++--------- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/_testdata/LocalClient.feature b/_testdata/LocalClient.feature index 2dfffb6..67ec124 100644 --- a/_testdata/LocalClient.feature +++ b/_testdata/LocalClient.feature @@ -63,6 +63,10 @@ Feature: HTTP Service And I should have other responses with body, that matches JSON paths | $.status | "failed" | | $.error | "foo" | + And I should have other responses with body, that contains + """ + "status":"failed" + """ And I should have other responses with header "Content-Type: application/json" diff --git a/local_client.go b/local_client.go index 0641dd4..bf21a50 100644 --- a/local_client.go +++ b/local_client.go @@ -221,6 +221,7 @@ func (l *LocalClient) RegisterSteps(s *godog.ScenarioContext) { s.Step(`^I should have(.*) other responses with header "([^"]*): ([^"]*)"$`, l.iShouldHaveOtherResponsesWithHeader) s.Step(`^I should have(.*) other responses with headers$`, l.iShouldHaveOtherResponsesWithHeaders) s.Step(`^I should have(.*) other responses with body$`, l.iShouldHaveOtherResponsesWithBody) + s.Step(`^I should have(.*) other responses with body, that contains$`, l.iShouldHaveOtherResponsesWithBodyThatContains) s.Step(`^I should have(.*) other responses with body from file$`, l.iShouldHaveOtherResponsesWithBodyFromFile) s.Step(`^I should have(.*) other responses with body, that matches JSON$`, l.iShouldHaveOtherResponsesWithBodyThatMatchesJSON) s.Step(`^I should have(.*) other responses with body, that matches JSON from file$`, l.iShouldHaveOtherResponsesWithBodyThatMatchesJSONFromFile) @@ -742,22 +743,36 @@ func (l *LocalClient) iShouldHaveResponseWithBody(ctx context.Context, service, }) } +func (l *LocalClient) contains(ctx context.Context, received []byte, bodyDoc string) error { + ctx, rv, err := l.VS.Replace(ctx, []byte(bodyDoc)) + if err != nil { + return err + } + + s, substr := string(received), string(rv) + if !strings.Contains(s, substr) { + return augmentBodyErr(ctx, fmt.Errorf("%w %q in %q", errDoesNotContain, substr, s)) + } + + return nil +} + func (l *LocalClient) iShouldHaveResponseWithBodyThatContains(ctx context.Context, service, bodyDoc string) (context.Context, error) { ctx = l.VS.PrepareContext(ctx) return l.expectResponse(ctx, service, func(c *httpmock.Client) error { return c.ExpectResponseBodyCallback(func(received []byte) error { - ctx, rv, err := l.VS.Replace(ctx, []byte(bodyDoc)) - if err != nil { - return err - } + return l.contains(ctx, received, bodyDoc) + }) + }) +} - s, substr := string(received), string(rv) - if !strings.Contains(s, substr) { - return augmentBodyErr(ctx, fmt.Errorf("%w %q in %q", errDoesNotContain, substr, s)) - } +func (l *LocalClient) iShouldHaveOtherResponsesWithBodyThatContains(ctx context.Context, service, bodyDoc string) (context.Context, error) { + ctx = l.VS.PrepareContext(ctx) - return nil + return l.expectResponse(ctx, service, func(c *httpmock.Client) error { + return c.ExpectOtherResponsesBodyCallback(func(received []byte) error { + return l.contains(ctx, received, bodyDoc) }) }) }