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..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" @@ -128,4 +132,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..bf21a50 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) @@ -220,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) @@ -553,6 +555,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 +743,40 @@ 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 { + return l.contains(ctx, received, bodyDoc) + }) + }) +} + +func (l *LocalClient) iShouldHaveOtherResponsesWithBodyThatContains(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.ExpectOtherResponsesBodyCallback(func(received []byte) error { + return l.contains(ctx, received, bodyDoc) + }) + }) +} + func (l *LocalClient) iShouldHaveResponseWithBodyFromFile(ctx context.Context, service, filePath string) (context.Context, error) { ctx = l.VS.PrepareContext(ctx)