From ea09c5d8fbca678273cd760690a4c0aebbec5f15 Mon Sep 17 00:00:00 2001 From: kkumar-gcc Date: Fri, 1 Nov 2024 21:51:11 +0530 Subject: [PATCH 01/10] add all http request method for testing --- contracts/testing/assertable_json.go | 5 ++++ contracts/testing/test_request.go | 12 ++++++++ testing/assertable_json_string.go | 29 +++++++++++++++++++ testing/test_request.go | 43 ++++++++++++++++++++++++---- testing/test_response.go | 35 +++++++++++++++++++++- 5 files changed, 117 insertions(+), 7 deletions(-) create mode 100644 contracts/testing/assertable_json.go create mode 100644 testing/assertable_json_string.go diff --git a/contracts/testing/assertable_json.go b/contracts/testing/assertable_json.go new file mode 100644 index 000000000..be71cc91f --- /dev/null +++ b/contracts/testing/assertable_json.go @@ -0,0 +1,5 @@ +package testing + +type AssertableJSON interface { + Json() map[string]any +} diff --git a/contracts/testing/test_request.go b/contracts/testing/test_request.go index 51182f6d9..bb0027bd1 100644 --- a/contracts/testing/test_request.go +++ b/contracts/testing/test_request.go @@ -1,10 +1,22 @@ package testing +import ( + "context" + "io" +) + type TestRequest interface { WithHeaders(headers map[string]string) TestRequest WithHeader(key, value string) TestRequest WithoutHeader(key string) TestRequest WithCookies(cookies map[string]string) TestRequest WithCookie(key, value string) TestRequest + WithContext(ctx context.Context) TestRequest Get(uri string) (TestResponse, error) + Post(uri string, body io.Reader) (TestResponse, error) + Put(uri string, body io.Reader) (TestResponse, error) + Patch(uri string, body io.Reader) (TestResponse, error) + Delete(uri string, body io.Reader) (TestResponse, error) + Head(uri string, body io.Reader) (TestResponse, error) + Options(uri string) (TestResponse, error) } diff --git a/testing/assertable_json_string.go b/testing/assertable_json_string.go new file mode 100644 index 000000000..2c10c54bb --- /dev/null +++ b/testing/assertable_json_string.go @@ -0,0 +1,29 @@ +package testing + +import ( + "encoding/json" + + contractstesting "github.com/goravel/framework/contracts/testing" +) + +type AssertableJSONString struct { + json string + decoded map[string]any +} + +func NewAssertableJSONString(jsonAble string) (contractstesting.AssertableJSON, error) { + var decoded = make(map[string]any) + err := json.Unmarshal([]byte(jsonAble), &decoded) + if err != nil { + return nil, err + } + + return &AssertableJSONString{ + json: jsonAble, + decoded: decoded, + }, nil +} + +func (r *AssertableJSONString) Json() map[string]any { + return r.decoded +} diff --git a/testing/test_request.go b/testing/test_request.go index 740815baa..ddc4c719c 100644 --- a/testing/test_request.go +++ b/testing/test_request.go @@ -1,7 +1,10 @@ package testing import ( + "context" + "io" "net/http" + "net/http/httptest" "testing" contractstesting "github.com/goravel/framework/contracts/testing" @@ -12,6 +15,7 @@ import ( type TestRequest struct { t *testing.T + ctx context.Context defaultHeaders map[string]string defaultCookies map[string]string } @@ -19,6 +23,7 @@ type TestRequest struct { func NewTestRequest(t *testing.T) contractstesting.TestRequest { return &TestRequest{ t: t, + ctx: context.Background(), defaultHeaders: make(map[string]string), defaultCookies: make(map[string]string), } @@ -49,15 +54,41 @@ func (r *TestRequest) WithCookie(key, value string) contractstesting.TestRequest return r } +func (r *TestRequest) WithContext(ctx context.Context) contractstesting.TestRequest { + r.ctx = ctx + return r +} + func (r *TestRequest) Get(uri string) (contractstesting.TestResponse, error) { - return r.call(http.MethodGet, uri) + return r.call(http.MethodGet, uri, nil) } -func (r *TestRequest) call(method string, uri string) (contractstesting.TestResponse, error) { - req, err := http.NewRequest(method, uri, nil) - if err != nil { - return nil, err - } +func (r *TestRequest) Post(uri string, body io.Reader) (contractstesting.TestResponse, error) { + return r.call(http.MethodPost, uri, body) +} + +func (r *TestRequest) Put(uri string, body io.Reader) (contractstesting.TestResponse, error) { + return r.call(http.MethodPut, uri, body) +} + +func (r *TestRequest) Patch(uri string, body io.Reader) (contractstesting.TestResponse, error) { + return r.call(http.MethodPatch, uri, body) +} + +func (r *TestRequest) Delete(uri string, body io.Reader) (contractstesting.TestResponse, error) { + return r.call(http.MethodDelete, uri, body) +} + +func (r *TestRequest) Head(uri string, body io.Reader) (contractstesting.TestResponse, error) { + return r.call(http.MethodHead, uri, body) +} + +func (r *TestRequest) Options(uri string) (contractstesting.TestResponse, error) { + return r.call(http.MethodOptions, uri, nil) +} + +func (r *TestRequest) call(method string, uri string, body io.Reader) (contractstesting.TestResponse, error) { + req := httptest.NewRequestWithContext(r.ctx, method, uri, body) for key, value := range r.defaultHeaders { req.Header.Set(key, value) diff --git a/testing/test_response.go b/testing/test_response.go index 554def405..31414522f 100644 --- a/testing/test_response.go +++ b/testing/test_response.go @@ -2,6 +2,7 @@ package testing import ( "fmt" + "io" "net/http" "testing" "time" @@ -22,6 +23,20 @@ func NewTestResponse(t *testing.T, response *http.Response) contractstesting.Tes return &TestResponseImpl{t: t, response: response} } +func (r *TestResponseImpl) Json() (map[string]any, error) { + content, err := r.getContent() + if err != nil { + return nil, err + } + + testAble, err := NewAssertableJSONString(content) + if err != nil { + return nil, err + } + + return testAble.Json(), nil +} + func (r *TestResponseImpl) AssertStatus(status int) contractstesting.TestResponse { actual := r.getStatusCode() assert.Equal(r.t, status, actual, fmt.Sprintf("Expected response status code [%d] but received %d.", status, actual)) @@ -48,7 +63,9 @@ func (r *TestResponseImpl) AssertNoContent(status ...int) contractstesting.TestR r.AssertStatus(expectedStatus) - assert.Empty(r.t, r.content) + content, err := r.getContent() + assert.Nil(r.t, err) + assert.Empty(r.t, content) return r } @@ -198,6 +215,22 @@ func (r *TestResponseImpl) getStatusCode() int { return r.response.StatusCode } +func (r *TestResponseImpl) getContent() (string, error) { + if r.content != "" { + return r.content, nil + } + + defer r.response.Body.Close() + + content, err := io.ReadAll(r.response.Body) + if err != nil { + return "", err + } + + r.content = string(content) + return r.content, nil +} + func (r *TestResponseImpl) getCookie(name string) *http.Cookie { for _, c := range r.response.Cookies() { if c.Name == name { From a5ac993e014e69495d58cda78a58fc4d1429c694 Mon Sep 17 00:00:00 2001 From: kkumar-gcc Date: Fri, 1 Nov 2024 16:22:43 +0000 Subject: [PATCH 02/10] chore: update mocks --- mocks/testing/AssertableJSON.go | 79 +++++++ mocks/testing/TestRequest.go | 407 +++++++++++++++++++++++++++++++- 2 files changed, 485 insertions(+), 1 deletion(-) create mode 100644 mocks/testing/AssertableJSON.go diff --git a/mocks/testing/AssertableJSON.go b/mocks/testing/AssertableJSON.go new file mode 100644 index 000000000..11cb15168 --- /dev/null +++ b/mocks/testing/AssertableJSON.go @@ -0,0 +1,79 @@ +// Code generated by mockery. DO NOT EDIT. + +package testing + +import mock "github.com/stretchr/testify/mock" + +// AssertableJSON is an autogenerated mock type for the AssertableJSON type +type AssertableJSON struct { + mock.Mock +} + +type AssertableJSON_Expecter struct { + mock *mock.Mock +} + +func (_m *AssertableJSON) EXPECT() *AssertableJSON_Expecter { + return &AssertableJSON_Expecter{mock: &_m.Mock} +} + +// Json provides a mock function with given fields: +func (_m *AssertableJSON) Json() map[string]any { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Json") + } + + var r0 map[string]any + if rf, ok := ret.Get(0).(func() map[string]any); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(map[string]any) + } + } + + return r0 +} + +// AssertableJSON_Json_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Json' +type AssertableJSON_Json_Call struct { + *mock.Call +} + +// Json is a helper method to define mock.On call +func (_e *AssertableJSON_Expecter) Json() *AssertableJSON_Json_Call { + return &AssertableJSON_Json_Call{Call: _e.mock.On("Json")} +} + +func (_c *AssertableJSON_Json_Call) Run(run func()) *AssertableJSON_Json_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *AssertableJSON_Json_Call) Return(_a0 map[string]any) *AssertableJSON_Json_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *AssertableJSON_Json_Call) RunAndReturn(run func() map[string]any) *AssertableJSON_Json_Call { + _c.Call.Return(run) + return _c +} + +// NewAssertableJSON creates a new instance of AssertableJSON. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewAssertableJSON(t interface { + mock.TestingT + Cleanup(func()) +}) *AssertableJSON { + mock := &AssertableJSON{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/mocks/testing/TestRequest.go b/mocks/testing/TestRequest.go index cfc406640..5ecd55709 100644 --- a/mocks/testing/TestRequest.go +++ b/mocks/testing/TestRequest.go @@ -3,8 +3,12 @@ package testing import ( - testing "github.com/goravel/framework/contracts/testing" + context "context" + io "io" + mock "github.com/stretchr/testify/mock" + + testing "github.com/goravel/framework/contracts/testing" ) // TestRequest is an autogenerated mock type for the TestRequest type @@ -20,6 +24,65 @@ func (_m *TestRequest) EXPECT() *TestRequest_Expecter { return &TestRequest_Expecter{mock: &_m.Mock} } +// Delete provides a mock function with given fields: uri, body +func (_m *TestRequest) Delete(uri string, body io.Reader) (testing.TestResponse, error) { + ret := _m.Called(uri, body) + + if len(ret) == 0 { + panic("no return value specified for Delete") + } + + var r0 testing.TestResponse + var r1 error + if rf, ok := ret.Get(0).(func(string, io.Reader) (testing.TestResponse, error)); ok { + return rf(uri, body) + } + if rf, ok := ret.Get(0).(func(string, io.Reader) testing.TestResponse); ok { + r0 = rf(uri, body) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(testing.TestResponse) + } + } + + if rf, ok := ret.Get(1).(func(string, io.Reader) error); ok { + r1 = rf(uri, body) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// TestRequest_Delete_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Delete' +type TestRequest_Delete_Call struct { + *mock.Call +} + +// Delete is a helper method to define mock.On call +// - uri string +// - body io.Reader +func (_e *TestRequest_Expecter) Delete(uri interface{}, body interface{}) *TestRequest_Delete_Call { + return &TestRequest_Delete_Call{Call: _e.mock.On("Delete", uri, body)} +} + +func (_c *TestRequest_Delete_Call) Run(run func(uri string, body io.Reader)) *TestRequest_Delete_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string), args[1].(io.Reader)) + }) + return _c +} + +func (_c *TestRequest_Delete_Call) Return(_a0 testing.TestResponse, _a1 error) *TestRequest_Delete_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *TestRequest_Delete_Call) RunAndReturn(run func(string, io.Reader) (testing.TestResponse, error)) *TestRequest_Delete_Call { + _c.Call.Return(run) + return _c +} + // Get provides a mock function with given fields: uri func (_m *TestRequest) Get(uri string) (testing.TestResponse, error) { ret := _m.Called(uri) @@ -78,6 +141,348 @@ func (_c *TestRequest_Get_Call) RunAndReturn(run func(string) (testing.TestRespo return _c } +// Head provides a mock function with given fields: uri, body +func (_m *TestRequest) Head(uri string, body io.Reader) (testing.TestResponse, error) { + ret := _m.Called(uri, body) + + if len(ret) == 0 { + panic("no return value specified for Head") + } + + var r0 testing.TestResponse + var r1 error + if rf, ok := ret.Get(0).(func(string, io.Reader) (testing.TestResponse, error)); ok { + return rf(uri, body) + } + if rf, ok := ret.Get(0).(func(string, io.Reader) testing.TestResponse); ok { + r0 = rf(uri, body) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(testing.TestResponse) + } + } + + if rf, ok := ret.Get(1).(func(string, io.Reader) error); ok { + r1 = rf(uri, body) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// TestRequest_Head_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Head' +type TestRequest_Head_Call struct { + *mock.Call +} + +// Head is a helper method to define mock.On call +// - uri string +// - body io.Reader +func (_e *TestRequest_Expecter) Head(uri interface{}, body interface{}) *TestRequest_Head_Call { + return &TestRequest_Head_Call{Call: _e.mock.On("Head", uri, body)} +} + +func (_c *TestRequest_Head_Call) Run(run func(uri string, body io.Reader)) *TestRequest_Head_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string), args[1].(io.Reader)) + }) + return _c +} + +func (_c *TestRequest_Head_Call) Return(_a0 testing.TestResponse, _a1 error) *TestRequest_Head_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *TestRequest_Head_Call) RunAndReturn(run func(string, io.Reader) (testing.TestResponse, error)) *TestRequest_Head_Call { + _c.Call.Return(run) + return _c +} + +// Options provides a mock function with given fields: uri +func (_m *TestRequest) Options(uri string) (testing.TestResponse, error) { + ret := _m.Called(uri) + + if len(ret) == 0 { + panic("no return value specified for Options") + } + + var r0 testing.TestResponse + var r1 error + if rf, ok := ret.Get(0).(func(string) (testing.TestResponse, error)); ok { + return rf(uri) + } + if rf, ok := ret.Get(0).(func(string) testing.TestResponse); ok { + r0 = rf(uri) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(testing.TestResponse) + } + } + + if rf, ok := ret.Get(1).(func(string) error); ok { + r1 = rf(uri) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// TestRequest_Options_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Options' +type TestRequest_Options_Call struct { + *mock.Call +} + +// Options is a helper method to define mock.On call +// - uri string +func (_e *TestRequest_Expecter) Options(uri interface{}) *TestRequest_Options_Call { + return &TestRequest_Options_Call{Call: _e.mock.On("Options", uri)} +} + +func (_c *TestRequest_Options_Call) Run(run func(uri string)) *TestRequest_Options_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string)) + }) + return _c +} + +func (_c *TestRequest_Options_Call) Return(_a0 testing.TestResponse, _a1 error) *TestRequest_Options_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *TestRequest_Options_Call) RunAndReturn(run func(string) (testing.TestResponse, error)) *TestRequest_Options_Call { + _c.Call.Return(run) + return _c +} + +// Patch provides a mock function with given fields: uri, body +func (_m *TestRequest) Patch(uri string, body io.Reader) (testing.TestResponse, error) { + ret := _m.Called(uri, body) + + if len(ret) == 0 { + panic("no return value specified for Patch") + } + + var r0 testing.TestResponse + var r1 error + if rf, ok := ret.Get(0).(func(string, io.Reader) (testing.TestResponse, error)); ok { + return rf(uri, body) + } + if rf, ok := ret.Get(0).(func(string, io.Reader) testing.TestResponse); ok { + r0 = rf(uri, body) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(testing.TestResponse) + } + } + + if rf, ok := ret.Get(1).(func(string, io.Reader) error); ok { + r1 = rf(uri, body) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// TestRequest_Patch_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Patch' +type TestRequest_Patch_Call struct { + *mock.Call +} + +// Patch is a helper method to define mock.On call +// - uri string +// - body io.Reader +func (_e *TestRequest_Expecter) Patch(uri interface{}, body interface{}) *TestRequest_Patch_Call { + return &TestRequest_Patch_Call{Call: _e.mock.On("Patch", uri, body)} +} + +func (_c *TestRequest_Patch_Call) Run(run func(uri string, body io.Reader)) *TestRequest_Patch_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string), args[1].(io.Reader)) + }) + return _c +} + +func (_c *TestRequest_Patch_Call) Return(_a0 testing.TestResponse, _a1 error) *TestRequest_Patch_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *TestRequest_Patch_Call) RunAndReturn(run func(string, io.Reader) (testing.TestResponse, error)) *TestRequest_Patch_Call { + _c.Call.Return(run) + return _c +} + +// Post provides a mock function with given fields: uri, body +func (_m *TestRequest) Post(uri string, body io.Reader) (testing.TestResponse, error) { + ret := _m.Called(uri, body) + + if len(ret) == 0 { + panic("no return value specified for Post") + } + + var r0 testing.TestResponse + var r1 error + if rf, ok := ret.Get(0).(func(string, io.Reader) (testing.TestResponse, error)); ok { + return rf(uri, body) + } + if rf, ok := ret.Get(0).(func(string, io.Reader) testing.TestResponse); ok { + r0 = rf(uri, body) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(testing.TestResponse) + } + } + + if rf, ok := ret.Get(1).(func(string, io.Reader) error); ok { + r1 = rf(uri, body) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// TestRequest_Post_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Post' +type TestRequest_Post_Call struct { + *mock.Call +} + +// Post is a helper method to define mock.On call +// - uri string +// - body io.Reader +func (_e *TestRequest_Expecter) Post(uri interface{}, body interface{}) *TestRequest_Post_Call { + return &TestRequest_Post_Call{Call: _e.mock.On("Post", uri, body)} +} + +func (_c *TestRequest_Post_Call) Run(run func(uri string, body io.Reader)) *TestRequest_Post_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string), args[1].(io.Reader)) + }) + return _c +} + +func (_c *TestRequest_Post_Call) Return(_a0 testing.TestResponse, _a1 error) *TestRequest_Post_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *TestRequest_Post_Call) RunAndReturn(run func(string, io.Reader) (testing.TestResponse, error)) *TestRequest_Post_Call { + _c.Call.Return(run) + return _c +} + +// Put provides a mock function with given fields: uri, body +func (_m *TestRequest) Put(uri string, body io.Reader) (testing.TestResponse, error) { + ret := _m.Called(uri, body) + + if len(ret) == 0 { + panic("no return value specified for Put") + } + + var r0 testing.TestResponse + var r1 error + if rf, ok := ret.Get(0).(func(string, io.Reader) (testing.TestResponse, error)); ok { + return rf(uri, body) + } + if rf, ok := ret.Get(0).(func(string, io.Reader) testing.TestResponse); ok { + r0 = rf(uri, body) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(testing.TestResponse) + } + } + + if rf, ok := ret.Get(1).(func(string, io.Reader) error); ok { + r1 = rf(uri, body) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// TestRequest_Put_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Put' +type TestRequest_Put_Call struct { + *mock.Call +} + +// Put is a helper method to define mock.On call +// - uri string +// - body io.Reader +func (_e *TestRequest_Expecter) Put(uri interface{}, body interface{}) *TestRequest_Put_Call { + return &TestRequest_Put_Call{Call: _e.mock.On("Put", uri, body)} +} + +func (_c *TestRequest_Put_Call) Run(run func(uri string, body io.Reader)) *TestRequest_Put_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string), args[1].(io.Reader)) + }) + return _c +} + +func (_c *TestRequest_Put_Call) Return(_a0 testing.TestResponse, _a1 error) *TestRequest_Put_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *TestRequest_Put_Call) RunAndReturn(run func(string, io.Reader) (testing.TestResponse, error)) *TestRequest_Put_Call { + _c.Call.Return(run) + return _c +} + +// WithContext provides a mock function with given fields: ctx +func (_m *TestRequest) WithContext(ctx context.Context) testing.TestRequest { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for WithContext") + } + + var r0 testing.TestRequest + if rf, ok := ret.Get(0).(func(context.Context) testing.TestRequest); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(testing.TestRequest) + } + } + + return r0 +} + +// TestRequest_WithContext_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WithContext' +type TestRequest_WithContext_Call struct { + *mock.Call +} + +// WithContext is a helper method to define mock.On call +// - ctx context.Context +func (_e *TestRequest_Expecter) WithContext(ctx interface{}) *TestRequest_WithContext_Call { + return &TestRequest_WithContext_Call{Call: _e.mock.On("WithContext", ctx)} +} + +func (_c *TestRequest_WithContext_Call) Run(run func(ctx context.Context)) *TestRequest_WithContext_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *TestRequest_WithContext_Call) Return(_a0 testing.TestRequest) *TestRequest_WithContext_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *TestRequest_WithContext_Call) RunAndReturn(run func(context.Context) testing.TestRequest) *TestRequest_WithContext_Call { + _c.Call.Return(run) + return _c +} + // WithCookie provides a mock function with given fields: key, value func (_m *TestRequest) WithCookie(key string, value string) testing.TestRequest { ret := _m.Called(key, value) From 7421ff6b3449e1d7eeaddc5d249e4125f5dbdc79 Mon Sep 17 00:00:00 2001 From: kkumar-gcc Date: Sat, 2 Nov 2024 07:00:01 +0530 Subject: [PATCH 03/10] add Don't See method --- contracts/testing/test_response.go | 15 +++++++--- testing/test_response.go | 48 ++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 4 deletions(-) diff --git a/contracts/testing/test_response.go b/contracts/testing/test_response.go index 82930ffbe..c1c5262c1 100644 --- a/contracts/testing/test_response.go +++ b/contracts/testing/test_response.go @@ -1,6 +1,10 @@ package testing type TestResponse interface { + IsSuccessful() bool + IsServerError() bool + Content() (string, error) + Json() (map[string]any, error) AssertStatus(status int) TestResponse AssertOk() TestResponse AssertCreated() TestResponse @@ -27,9 +31,12 @@ type TestResponse interface { AssertInternalServerError() TestResponse AssertServiceUnavailable() TestResponse AssertHeader(headerName, value string) TestResponse - AssertHeaderMissing(headerName string) TestResponse + AssertHeaderMissing(string) TestResponse AssertCookie(name, value string) TestResponse - AssertCookieExpired(name string) TestResponse - AssertCookieNotExpired(name string) TestResponse - AssertCookieMissing(name string) TestResponse + AssertCookieExpired(string) TestResponse + AssertCookieNotExpired(string) TestResponse + AssertCookieMissing(string) TestResponse + AssertSuccessful() TestResponse + AssertServerError() TestResponse + AssertDontSee([]string, ...bool) TestResponse } diff --git a/testing/test_response.go b/testing/test_response.go index 31414522f..3aa98e272 100644 --- a/testing/test_response.go +++ b/testing/test_response.go @@ -2,6 +2,7 @@ package testing import ( "fmt" + "html" "io" "net/http" "testing" @@ -37,6 +38,20 @@ func (r *TestResponseImpl) Json() (map[string]any, error) { return testAble.Json(), nil } +func (r *TestResponseImpl) IsSuccessful() bool { + statusCode := r.getStatusCode() + return statusCode >= 200 && statusCode < 300 +} + +func (r *TestResponseImpl) IsServerError() bool { + statusCode := r.getStatusCode() + return statusCode >= 500 && statusCode < 600 +} + +func (r *TestResponseImpl) Content() (string, error) { + return r.getContent() +} + func (r *TestResponseImpl) AssertStatus(status int) contractstesting.TestResponse { actual := r.getStatusCode() assert.Equal(r.t, status, actual, fmt.Sprintf("Expected response status code [%d] but received %d.", status, actual)) @@ -211,6 +226,39 @@ func (r *TestResponseImpl) AssertCookieMissing(name string) contractstesting.Tes return r } +func (r *TestResponseImpl) AssertSuccessful() contractstesting.TestResponse { + assert.True(r.t, r.IsSuccessful(), fmt.Sprintf("Expected response status code >=200, <300 but received %d.", r.getStatusCode())) + + return r +} + +func (r *TestResponseImpl) AssertServerError() contractstesting.TestResponse { + assert.True(r.t, r.IsServerError(), fmt.Sprintf("Expected response status code >=500, <600 but received %d.", r.getStatusCode())) + + return r +} + +func (r *TestResponseImpl) AssertDontSee(value []string, escaped ...bool) contractstesting.TestResponse { + content, err := r.getContent() + assert.Nil(r.t, err) + + shouldEscape := true + if len(escaped) > 0 { + shouldEscape = escaped[0] + } + + for _, v := range value { + checkValue := v + if shouldEscape { + checkValue = html.EscapeString(v) + } + + assert.NotContains(r.t, content, checkValue, fmt.Sprintf("Response should not contain '%s', but it was found.", checkValue)) + } + + return r +} + func (r *TestResponseImpl) getStatusCode() int { return r.response.StatusCode } From 06f147718c3bae86258295cd47678a255260d1dd Mon Sep 17 00:00:00 2001 From: kkumar-gcc Date: Sat, 2 Nov 2024 01:31:38 +0000 Subject: [PATCH 04/10] chore: update mocks --- mocks/testing/TestResponse.go | 423 +++++++++++++++++++++++++++++++--- 1 file changed, 391 insertions(+), 32 deletions(-) diff --git a/mocks/testing/TestResponse.go b/mocks/testing/TestResponse.go index ebd0f38e3..c44e9bf53 100644 --- a/mocks/testing/TestResponse.go +++ b/mocks/testing/TestResponse.go @@ -210,9 +210,9 @@ func (_c *TestResponse_AssertCookie_Call) RunAndReturn(run func(string, string) return _c } -// AssertCookieExpired provides a mock function with given fields: name -func (_m *TestResponse) AssertCookieExpired(name string) testing.TestResponse { - ret := _m.Called(name) +// AssertCookieExpired provides a mock function with given fields: _a0 +func (_m *TestResponse) AssertCookieExpired(_a0 string) testing.TestResponse { + ret := _m.Called(_a0) if len(ret) == 0 { panic("no return value specified for AssertCookieExpired") @@ -220,7 +220,7 @@ func (_m *TestResponse) AssertCookieExpired(name string) testing.TestResponse { var r0 testing.TestResponse if rf, ok := ret.Get(0).(func(string) testing.TestResponse); ok { - r0 = rf(name) + r0 = rf(_a0) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(testing.TestResponse) @@ -236,12 +236,12 @@ type TestResponse_AssertCookieExpired_Call struct { } // AssertCookieExpired is a helper method to define mock.On call -// - name string -func (_e *TestResponse_Expecter) AssertCookieExpired(name interface{}) *TestResponse_AssertCookieExpired_Call { - return &TestResponse_AssertCookieExpired_Call{Call: _e.mock.On("AssertCookieExpired", name)} +// - _a0 string +func (_e *TestResponse_Expecter) AssertCookieExpired(_a0 interface{}) *TestResponse_AssertCookieExpired_Call { + return &TestResponse_AssertCookieExpired_Call{Call: _e.mock.On("AssertCookieExpired", _a0)} } -func (_c *TestResponse_AssertCookieExpired_Call) Run(run func(name string)) *TestResponse_AssertCookieExpired_Call { +func (_c *TestResponse_AssertCookieExpired_Call) Run(run func(_a0 string)) *TestResponse_AssertCookieExpired_Call { _c.Call.Run(func(args mock.Arguments) { run(args[0].(string)) }) @@ -258,9 +258,9 @@ func (_c *TestResponse_AssertCookieExpired_Call) RunAndReturn(run func(string) t return _c } -// AssertCookieMissing provides a mock function with given fields: name -func (_m *TestResponse) AssertCookieMissing(name string) testing.TestResponse { - ret := _m.Called(name) +// AssertCookieMissing provides a mock function with given fields: _a0 +func (_m *TestResponse) AssertCookieMissing(_a0 string) testing.TestResponse { + ret := _m.Called(_a0) if len(ret) == 0 { panic("no return value specified for AssertCookieMissing") @@ -268,7 +268,7 @@ func (_m *TestResponse) AssertCookieMissing(name string) testing.TestResponse { var r0 testing.TestResponse if rf, ok := ret.Get(0).(func(string) testing.TestResponse); ok { - r0 = rf(name) + r0 = rf(_a0) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(testing.TestResponse) @@ -284,12 +284,12 @@ type TestResponse_AssertCookieMissing_Call struct { } // AssertCookieMissing is a helper method to define mock.On call -// - name string -func (_e *TestResponse_Expecter) AssertCookieMissing(name interface{}) *TestResponse_AssertCookieMissing_Call { - return &TestResponse_AssertCookieMissing_Call{Call: _e.mock.On("AssertCookieMissing", name)} +// - _a0 string +func (_e *TestResponse_Expecter) AssertCookieMissing(_a0 interface{}) *TestResponse_AssertCookieMissing_Call { + return &TestResponse_AssertCookieMissing_Call{Call: _e.mock.On("AssertCookieMissing", _a0)} } -func (_c *TestResponse_AssertCookieMissing_Call) Run(run func(name string)) *TestResponse_AssertCookieMissing_Call { +func (_c *TestResponse_AssertCookieMissing_Call) Run(run func(_a0 string)) *TestResponse_AssertCookieMissing_Call { _c.Call.Run(func(args mock.Arguments) { run(args[0].(string)) }) @@ -306,9 +306,9 @@ func (_c *TestResponse_AssertCookieMissing_Call) RunAndReturn(run func(string) t return _c } -// AssertCookieNotExpired provides a mock function with given fields: name -func (_m *TestResponse) AssertCookieNotExpired(name string) testing.TestResponse { - ret := _m.Called(name) +// AssertCookieNotExpired provides a mock function with given fields: _a0 +func (_m *TestResponse) AssertCookieNotExpired(_a0 string) testing.TestResponse { + ret := _m.Called(_a0) if len(ret) == 0 { panic("no return value specified for AssertCookieNotExpired") @@ -316,7 +316,7 @@ func (_m *TestResponse) AssertCookieNotExpired(name string) testing.TestResponse var r0 testing.TestResponse if rf, ok := ret.Get(0).(func(string) testing.TestResponse); ok { - r0 = rf(name) + r0 = rf(_a0) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(testing.TestResponse) @@ -332,12 +332,12 @@ type TestResponse_AssertCookieNotExpired_Call struct { } // AssertCookieNotExpired is a helper method to define mock.On call -// - name string -func (_e *TestResponse_Expecter) AssertCookieNotExpired(name interface{}) *TestResponse_AssertCookieNotExpired_Call { - return &TestResponse_AssertCookieNotExpired_Call{Call: _e.mock.On("AssertCookieNotExpired", name)} +// - _a0 string +func (_e *TestResponse_Expecter) AssertCookieNotExpired(_a0 interface{}) *TestResponse_AssertCookieNotExpired_Call { + return &TestResponse_AssertCookieNotExpired_Call{Call: _e.mock.On("AssertCookieNotExpired", _a0)} } -func (_c *TestResponse_AssertCookieNotExpired_Call) Run(run func(name string)) *TestResponse_AssertCookieNotExpired_Call { +func (_c *TestResponse_AssertCookieNotExpired_Call) Run(run func(_a0 string)) *TestResponse_AssertCookieNotExpired_Call { _c.Call.Run(func(args mock.Arguments) { run(args[0].(string)) }) @@ -401,6 +401,69 @@ func (_c *TestResponse_AssertCreated_Call) RunAndReturn(run func() testing.TestR return _c } +// AssertDontSee provides a mock function with given fields: _a0, _a1 +func (_m *TestResponse) AssertDontSee(_a0 []string, _a1 ...bool) testing.TestResponse { + _va := make([]interface{}, len(_a1)) + for _i := range _a1 { + _va[_i] = _a1[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for AssertDontSee") + } + + var r0 testing.TestResponse + if rf, ok := ret.Get(0).(func([]string, ...bool) testing.TestResponse); ok { + r0 = rf(_a0, _a1...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(testing.TestResponse) + } + } + + return r0 +} + +// TestResponse_AssertDontSee_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AssertDontSee' +type TestResponse_AssertDontSee_Call struct { + *mock.Call +} + +// AssertDontSee is a helper method to define mock.On call +// - _a0 []string +// - _a1 ...bool +func (_e *TestResponse_Expecter) AssertDontSee(_a0 interface{}, _a1 ...interface{}) *TestResponse_AssertDontSee_Call { + return &TestResponse_AssertDontSee_Call{Call: _e.mock.On("AssertDontSee", + append([]interface{}{_a0}, _a1...)...)} +} + +func (_c *TestResponse_AssertDontSee_Call) Run(run func(_a0 []string, _a1 ...bool)) *TestResponse_AssertDontSee_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]bool, len(args)-1) + for i, a := range args[1:] { + if a != nil { + variadicArgs[i] = a.(bool) + } + } + run(args[0].([]string), variadicArgs...) + }) + return _c +} + +func (_c *TestResponse_AssertDontSee_Call) Return(_a0 testing.TestResponse) *TestResponse_AssertDontSee_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *TestResponse_AssertDontSee_Call) RunAndReturn(run func([]string, ...bool) testing.TestResponse) *TestResponse_AssertDontSee_Call { + _c.Call.Return(run) + return _c +} + // AssertForbidden provides a mock function with given fields: func (_m *TestResponse) AssertForbidden() testing.TestResponse { ret := _m.Called() @@ -591,9 +654,9 @@ func (_c *TestResponse_AssertHeader_Call) RunAndReturn(run func(string, string) return _c } -// AssertHeaderMissing provides a mock function with given fields: headerName -func (_m *TestResponse) AssertHeaderMissing(headerName string) testing.TestResponse { - ret := _m.Called(headerName) +// AssertHeaderMissing provides a mock function with given fields: _a0 +func (_m *TestResponse) AssertHeaderMissing(_a0 string) testing.TestResponse { + ret := _m.Called(_a0) if len(ret) == 0 { panic("no return value specified for AssertHeaderMissing") @@ -601,7 +664,7 @@ func (_m *TestResponse) AssertHeaderMissing(headerName string) testing.TestRespo var r0 testing.TestResponse if rf, ok := ret.Get(0).(func(string) testing.TestResponse); ok { - r0 = rf(headerName) + r0 = rf(_a0) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(testing.TestResponse) @@ -617,12 +680,12 @@ type TestResponse_AssertHeaderMissing_Call struct { } // AssertHeaderMissing is a helper method to define mock.On call -// - headerName string -func (_e *TestResponse_Expecter) AssertHeaderMissing(headerName interface{}) *TestResponse_AssertHeaderMissing_Call { - return &TestResponse_AssertHeaderMissing_Call{Call: _e.mock.On("AssertHeaderMissing", headerName)} +// - _a0 string +func (_e *TestResponse_Expecter) AssertHeaderMissing(_a0 interface{}) *TestResponse_AssertHeaderMissing_Call { + return &TestResponse_AssertHeaderMissing_Call{Call: _e.mock.On("AssertHeaderMissing", _a0)} } -func (_c *TestResponse_AssertHeaderMissing_Call) Run(run func(headerName string)) *TestResponse_AssertHeaderMissing_Call { +func (_c *TestResponse_AssertHeaderMissing_Call) Run(run func(_a0 string)) *TestResponse_AssertHeaderMissing_Call { _c.Call.Run(func(args mock.Arguments) { run(args[0].(string)) }) @@ -1170,6 +1233,53 @@ func (_c *TestResponse_AssertRequestTimeout_Call) RunAndReturn(run func() testin return _c } +// AssertServerError provides a mock function with given fields: +func (_m *TestResponse) AssertServerError() testing.TestResponse { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for AssertServerError") + } + + var r0 testing.TestResponse + if rf, ok := ret.Get(0).(func() testing.TestResponse); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(testing.TestResponse) + } + } + + return r0 +} + +// TestResponse_AssertServerError_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AssertServerError' +type TestResponse_AssertServerError_Call struct { + *mock.Call +} + +// AssertServerError is a helper method to define mock.On call +func (_e *TestResponse_Expecter) AssertServerError() *TestResponse_AssertServerError_Call { + return &TestResponse_AssertServerError_Call{Call: _e.mock.On("AssertServerError")} +} + +func (_c *TestResponse_AssertServerError_Call) Run(run func()) *TestResponse_AssertServerError_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *TestResponse_AssertServerError_Call) Return(_a0 testing.TestResponse) *TestResponse_AssertServerError_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *TestResponse_AssertServerError_Call) RunAndReturn(run func() testing.TestResponse) *TestResponse_AssertServerError_Call { + _c.Call.Return(run) + return _c +} + // AssertServiceUnavailable provides a mock function with given fields: func (_m *TestResponse) AssertServiceUnavailable() testing.TestResponse { ret := _m.Called() @@ -1265,6 +1375,53 @@ func (_c *TestResponse_AssertStatus_Call) RunAndReturn(run func(int) testing.Tes return _c } +// AssertSuccessful provides a mock function with given fields: +func (_m *TestResponse) AssertSuccessful() testing.TestResponse { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for AssertSuccessful") + } + + var r0 testing.TestResponse + if rf, ok := ret.Get(0).(func() testing.TestResponse); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(testing.TestResponse) + } + } + + return r0 +} + +// TestResponse_AssertSuccessful_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AssertSuccessful' +type TestResponse_AssertSuccessful_Call struct { + *mock.Call +} + +// AssertSuccessful is a helper method to define mock.On call +func (_e *TestResponse_Expecter) AssertSuccessful() *TestResponse_AssertSuccessful_Call { + return &TestResponse_AssertSuccessful_Call{Call: _e.mock.On("AssertSuccessful")} +} + +func (_c *TestResponse_AssertSuccessful_Call) Run(run func()) *TestResponse_AssertSuccessful_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *TestResponse_AssertSuccessful_Call) Return(_a0 testing.TestResponse) *TestResponse_AssertSuccessful_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *TestResponse_AssertSuccessful_Call) RunAndReturn(run func() testing.TestResponse) *TestResponse_AssertSuccessful_Call { + _c.Call.Return(run) + return _c +} + // AssertTemporaryRedirect provides a mock function with given fields: func (_m *TestResponse) AssertTemporaryRedirect() testing.TestResponse { ret := _m.Called() @@ -1500,6 +1657,208 @@ func (_c *TestResponse_AssertUnsupportedMediaType_Call) RunAndReturn(run func() return _c } +// Content provides a mock function with given fields: +func (_m *TestResponse) Content() (string, error) { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Content") + } + + var r0 string + var r1 error + if rf, ok := ret.Get(0).(func() (string, error)); ok { + return rf() + } + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(string) + } + + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// TestResponse_Content_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Content' +type TestResponse_Content_Call struct { + *mock.Call +} + +// Content is a helper method to define mock.On call +func (_e *TestResponse_Expecter) Content() *TestResponse_Content_Call { + return &TestResponse_Content_Call{Call: _e.mock.On("Content")} +} + +func (_c *TestResponse_Content_Call) Run(run func()) *TestResponse_Content_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *TestResponse_Content_Call) Return(_a0 string, _a1 error) *TestResponse_Content_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *TestResponse_Content_Call) RunAndReturn(run func() (string, error)) *TestResponse_Content_Call { + _c.Call.Return(run) + return _c +} + +// IsServerError provides a mock function with given fields: +func (_m *TestResponse) IsServerError() bool { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for IsServerError") + } + + var r0 bool + if rf, ok := ret.Get(0).(func() bool); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(bool) + } + + return r0 +} + +// TestResponse_IsServerError_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'IsServerError' +type TestResponse_IsServerError_Call struct { + *mock.Call +} + +// IsServerError is a helper method to define mock.On call +func (_e *TestResponse_Expecter) IsServerError() *TestResponse_IsServerError_Call { + return &TestResponse_IsServerError_Call{Call: _e.mock.On("IsServerError")} +} + +func (_c *TestResponse_IsServerError_Call) Run(run func()) *TestResponse_IsServerError_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *TestResponse_IsServerError_Call) Return(_a0 bool) *TestResponse_IsServerError_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *TestResponse_IsServerError_Call) RunAndReturn(run func() bool) *TestResponse_IsServerError_Call { + _c.Call.Return(run) + return _c +} + +// IsSuccessful provides a mock function with given fields: +func (_m *TestResponse) IsSuccessful() bool { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for IsSuccessful") + } + + var r0 bool + if rf, ok := ret.Get(0).(func() bool); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(bool) + } + + return r0 +} + +// TestResponse_IsSuccessful_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'IsSuccessful' +type TestResponse_IsSuccessful_Call struct { + *mock.Call +} + +// IsSuccessful is a helper method to define mock.On call +func (_e *TestResponse_Expecter) IsSuccessful() *TestResponse_IsSuccessful_Call { + return &TestResponse_IsSuccessful_Call{Call: _e.mock.On("IsSuccessful")} +} + +func (_c *TestResponse_IsSuccessful_Call) Run(run func()) *TestResponse_IsSuccessful_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *TestResponse_IsSuccessful_Call) Return(_a0 bool) *TestResponse_IsSuccessful_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *TestResponse_IsSuccessful_Call) RunAndReturn(run func() bool) *TestResponse_IsSuccessful_Call { + _c.Call.Return(run) + return _c +} + +// Json provides a mock function with given fields: +func (_m *TestResponse) Json() (map[string]any, error) { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Json") + } + + var r0 map[string]any + var r1 error + if rf, ok := ret.Get(0).(func() (map[string]any, error)); ok { + return rf() + } + if rf, ok := ret.Get(0).(func() map[string]any); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(map[string]any) + } + } + + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// TestResponse_Json_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Json' +type TestResponse_Json_Call struct { + *mock.Call +} + +// Json is a helper method to define mock.On call +func (_e *TestResponse_Expecter) Json() *TestResponse_Json_Call { + return &TestResponse_Json_Call{Call: _e.mock.On("Json")} +} + +func (_c *TestResponse_Json_Call) Run(run func()) *TestResponse_Json_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *TestResponse_Json_Call) Return(_a0 map[string]any, _a1 error) *TestResponse_Json_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *TestResponse_Json_Call) RunAndReturn(run func() (map[string]any, error)) *TestResponse_Json_Call { + _c.Call.Return(run) + return _c +} + // NewTestResponse creates a new instance of TestResponse. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. // The first argument is typically a *testing.T value. func NewTestResponse(t interface { From c057dfdaf8b5e31b3ec0eeec31e7fe8e19d85dcc Mon Sep 17 00:00:00 2001 From: kkumar-gcc Date: Sat, 2 Nov 2024 07:07:03 +0530 Subject: [PATCH 05/10] add AssertSee --- contracts/testing/test_response.go | 2 ++ testing/test_response.go | 46 ++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/contracts/testing/test_response.go b/contracts/testing/test_response.go index c1c5262c1..d030e6703 100644 --- a/contracts/testing/test_response.go +++ b/contracts/testing/test_response.go @@ -39,4 +39,6 @@ type TestResponse interface { AssertSuccessful() TestResponse AssertServerError() TestResponse AssertDontSee([]string, ...bool) TestResponse + AssertSee([]string, ...bool) TestResponse + AssertSeeInOrder([]string, ...bool) TestResponse } diff --git a/testing/test_response.go b/testing/test_response.go index 3aa98e272..dfa10babd 100644 --- a/testing/test_response.go +++ b/testing/test_response.go @@ -5,6 +5,7 @@ import ( "html" "io" "net/http" + "strings" "testing" "time" @@ -259,6 +260,51 @@ func (r *TestResponseImpl) AssertDontSee(value []string, escaped ...bool) contra return r } +func (r *TestResponseImpl) AssertSee(value []string, escaped ...bool) contractstesting.TestResponse { + content, err := r.getContent() + assert.Nil(r.t, err) + + shouldEscape := true + if len(escaped) > 0 { + shouldEscape = escaped[0] + } + + for _, v := range value { + checkValue := v + if shouldEscape { + checkValue = html.EscapeString(v) + } + + assert.Contains(r.t, content, checkValue, fmt.Sprintf("Expected to see '%s' in response, but it was not found.", checkValue)) + } + + return r +} + +func (r *TestResponseImpl) AssertSeeInOrder(value []string, escaped ...bool) contractstesting.TestResponse { + content, err := r.getContent() + assert.Nil(r.t, err) + + shouldEscape := true + if len(escaped) > 0 { + shouldEscape = escaped[0] + } + + previousIndex := -1 + for _, v := range value { + checkValue := v + if shouldEscape { + checkValue = html.EscapeString(v) + } + + currentIndex := strings.Index(content[previousIndex+1:], checkValue) + assert.GreaterOrEqual(r.t, currentIndex, 0, fmt.Sprintf("Expected to see '%s' in response in the correct order, but it was not found.", checkValue)) + previousIndex += currentIndex + len(checkValue) + } + + return r +} + func (r *TestResponseImpl) getStatusCode() int { return r.response.StatusCode } From e0d80c7c24b3972729f89618ded6ccddb0c34dc4 Mon Sep 17 00:00:00 2001 From: kkumar-gcc Date: Sat, 2 Nov 2024 01:37:48 +0000 Subject: [PATCH 06/10] chore: update mocks --- mocks/testing/TestResponse.go | 126 ++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) diff --git a/mocks/testing/TestResponse.go b/mocks/testing/TestResponse.go index c44e9bf53..9d6257b67 100644 --- a/mocks/testing/TestResponse.go +++ b/mocks/testing/TestResponse.go @@ -1233,6 +1233,132 @@ func (_c *TestResponse_AssertRequestTimeout_Call) RunAndReturn(run func() testin return _c } +// AssertSee provides a mock function with given fields: _a0, _a1 +func (_m *TestResponse) AssertSee(_a0 []string, _a1 ...bool) testing.TestResponse { + _va := make([]interface{}, len(_a1)) + for _i := range _a1 { + _va[_i] = _a1[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for AssertSee") + } + + var r0 testing.TestResponse + if rf, ok := ret.Get(0).(func([]string, ...bool) testing.TestResponse); ok { + r0 = rf(_a0, _a1...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(testing.TestResponse) + } + } + + return r0 +} + +// TestResponse_AssertSee_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AssertSee' +type TestResponse_AssertSee_Call struct { + *mock.Call +} + +// AssertSee is a helper method to define mock.On call +// - _a0 []string +// - _a1 ...bool +func (_e *TestResponse_Expecter) AssertSee(_a0 interface{}, _a1 ...interface{}) *TestResponse_AssertSee_Call { + return &TestResponse_AssertSee_Call{Call: _e.mock.On("AssertSee", + append([]interface{}{_a0}, _a1...)...)} +} + +func (_c *TestResponse_AssertSee_Call) Run(run func(_a0 []string, _a1 ...bool)) *TestResponse_AssertSee_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]bool, len(args)-1) + for i, a := range args[1:] { + if a != nil { + variadicArgs[i] = a.(bool) + } + } + run(args[0].([]string), variadicArgs...) + }) + return _c +} + +func (_c *TestResponse_AssertSee_Call) Return(_a0 testing.TestResponse) *TestResponse_AssertSee_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *TestResponse_AssertSee_Call) RunAndReturn(run func([]string, ...bool) testing.TestResponse) *TestResponse_AssertSee_Call { + _c.Call.Return(run) + return _c +} + +// AssertSeeInOrder provides a mock function with given fields: _a0, _a1 +func (_m *TestResponse) AssertSeeInOrder(_a0 []string, _a1 ...bool) testing.TestResponse { + _va := make([]interface{}, len(_a1)) + for _i := range _a1 { + _va[_i] = _a1[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for AssertSeeInOrder") + } + + var r0 testing.TestResponse + if rf, ok := ret.Get(0).(func([]string, ...bool) testing.TestResponse); ok { + r0 = rf(_a0, _a1...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(testing.TestResponse) + } + } + + return r0 +} + +// TestResponse_AssertSeeInOrder_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AssertSeeInOrder' +type TestResponse_AssertSeeInOrder_Call struct { + *mock.Call +} + +// AssertSeeInOrder is a helper method to define mock.On call +// - _a0 []string +// - _a1 ...bool +func (_e *TestResponse_Expecter) AssertSeeInOrder(_a0 interface{}, _a1 ...interface{}) *TestResponse_AssertSeeInOrder_Call { + return &TestResponse_AssertSeeInOrder_Call{Call: _e.mock.On("AssertSeeInOrder", + append([]interface{}{_a0}, _a1...)...)} +} + +func (_c *TestResponse_AssertSeeInOrder_Call) Run(run func(_a0 []string, _a1 ...bool)) *TestResponse_AssertSeeInOrder_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]bool, len(args)-1) + for i, a := range args[1:] { + if a != nil { + variadicArgs[i] = a.(bool) + } + } + run(args[0].([]string), variadicArgs...) + }) + return _c +} + +func (_c *TestResponse_AssertSeeInOrder_Call) Return(_a0 testing.TestResponse) *TestResponse_AssertSeeInOrder_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *TestResponse_AssertSeeInOrder_Call) RunAndReturn(run func([]string, ...bool) testing.TestResponse) *TestResponse_AssertSeeInOrder_Call { + _c.Call.Return(run) + return _c +} + // AssertServerError provides a mock function with given fields: func (_m *TestResponse) AssertServerError() testing.TestResponse { ret := _m.Called() From 3a67c23769df20d06cf13275f1661e95528f5ec3 Mon Sep 17 00:00:00 2001 From: kkumar-gcc Date: Sat, 2 Nov 2024 16:36:26 +0530 Subject: [PATCH 07/10] add test cases for new response methods --- testing/test_response_test.go | 55 +++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/testing/test_response_test.go b/testing/test_response_test.go index 1bd0ab128..5eed0806c 100644 --- a/testing/test_response_test.go +++ b/testing/test_response_test.go @@ -1,7 +1,10 @@ package testing import ( + "html" + "io" "net/http" + "strings" "testing" "time" ) @@ -26,6 +29,8 @@ func TestAssertAccepted(t *testing.T) { func TestAssertNoContent(t *testing.T) { res := createTestResponse(http.StatusNoContent) + res.Body = http.NoBody + r := NewTestResponse(t, res) r.AssertNoContent() } @@ -200,6 +205,56 @@ func TestAssertCookieMissing(t *testing.T) { r.AssertCookieMissing("session_id") } +func TestAssertSee(t *testing.T) { + res := createTestResponse(http.StatusOK) + res.Body = io.NopCloser(strings.NewReader("Hello, World! This is a test response.")) + + r := NewTestResponse(t, res) + r.AssertSee([]string{"Hello", "test"}) +} + +func TestAssertSeeEscaped(t *testing.T) { + res := createTestResponse(http.StatusOK) + escapedContent := html.EscapeString("
Hello, World!
") + res.Body = io.NopCloser(strings.NewReader(escapedContent)) + + r := NewTestResponse(t, res) + r.AssertSee([]string{"
Hello, World!
"}, true) +} + +func TestAssertDontSee(t *testing.T) { + res := createTestResponse(http.StatusOK) + res.Body = io.NopCloser(strings.NewReader("This is a safe response.")) + + r := NewTestResponse(t, res) + r.AssertDontSee([]string{"error", "failure"}) +} + +func TestAssertDontSeeEscaped(t *testing.T) { + res := createTestResponse(http.StatusOK) + res.Body = io.NopCloser(strings.NewReader("
Unauthorized access
")) + + r := NewTestResponse(t, res) + r.AssertDontSee([]string{"
Unauthorized access
"}, true) +} + +func TestAssertSeeInOrder(t *testing.T) { + res := createTestResponse(http.StatusOK) + res.Body = io.NopCloser(strings.NewReader("Hello, this is a test for seeing values in order.")) + + r := NewTestResponse(t, res) + r.AssertSeeInOrder([]string{"Hello", "test", "values"}) +} + +func TestAssertSeeInOrderWithEscape(t *testing.T) { + res := createTestResponse(http.StatusOK) + escapedContent := html.EscapeString("Hello,
ordered
values") + res.Body = io.NopCloser(strings.NewReader(escapedContent)) + + r := NewTestResponse(t, res) + r.AssertSeeInOrder([]string{"Hello,", "
ordered
"}, true) +} + func createTestResponse(statusCode int) *http.Response { return &http.Response{ StatusCode: statusCode, From b26d506cfc53dba1662646b18732e55019cf40d9 Mon Sep 17 00:00:00 2001 From: kkumar-gcc Date: Sat, 2 Nov 2024 16:41:31 +0530 Subject: [PATCH 08/10] . --- contracts/testing/test_request.go | 2 +- testing/assertable_json_string.go | 8 ++++---- testing/test_request.go | 4 ++-- testing/test_response.go | 5 +++++ 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/contracts/testing/test_request.go b/contracts/testing/test_request.go index bb0027bd1..d382b33e0 100644 --- a/contracts/testing/test_request.go +++ b/contracts/testing/test_request.go @@ -17,6 +17,6 @@ type TestRequest interface { Put(uri string, body io.Reader) (TestResponse, error) Patch(uri string, body io.Reader) (TestResponse, error) Delete(uri string, body io.Reader) (TestResponse, error) - Head(uri string, body io.Reader) (TestResponse, error) + Head(uri string) (TestResponse, error) Options(uri string) (TestResponse, error) } diff --git a/testing/assertable_json_string.go b/testing/assertable_json_string.go index 2c10c54bb..6c5599d3e 100644 --- a/testing/assertable_json_string.go +++ b/testing/assertable_json_string.go @@ -11,15 +11,15 @@ type AssertableJSONString struct { decoded map[string]any } -func NewAssertableJSONString(jsonAble string) (contractstesting.AssertableJSON, error) { - var decoded = make(map[string]any) - err := json.Unmarshal([]byte(jsonAble), &decoded) +func NewAssertableJSONString(jsonStr string) (contractstesting.AssertableJSON, error) { + var decoded map[string]any + err := json.Unmarshal([]byte(jsonStr), &decoded) if err != nil { return nil, err } return &AssertableJSONString{ - json: jsonAble, + json: jsonStr, decoded: decoded, }, nil } diff --git a/testing/test_request.go b/testing/test_request.go index ddc4c719c..7726672bd 100644 --- a/testing/test_request.go +++ b/testing/test_request.go @@ -79,8 +79,8 @@ func (r *TestRequest) Delete(uri string, body io.Reader) (contractstesting.TestR return r.call(http.MethodDelete, uri, body) } -func (r *TestRequest) Head(uri string, body io.Reader) (contractstesting.TestResponse, error) { - return r.call(http.MethodHead, uri, body) +func (r *TestRequest) Head(uri string) (contractstesting.TestResponse, error) { + return r.call(http.MethodHead, uri, nil) } func (r *TestRequest) Options(uri string) (contractstesting.TestResponse, error) { diff --git a/testing/test_response.go b/testing/test_response.go index dfa10babd..423637d62 100644 --- a/testing/test_response.go +++ b/testing/test_response.go @@ -6,6 +6,7 @@ import ( "io" "net/http" "strings" + "sync" "testing" "time" @@ -17,6 +18,7 @@ import ( type TestResponseImpl struct { t *testing.T + mu sync.Mutex response *http.Response content string } @@ -310,6 +312,9 @@ func (r *TestResponseImpl) getStatusCode() int { } func (r *TestResponseImpl) getContent() (string, error) { + r.mu.Lock() + defer r.mu.Unlock() + if r.content != "" { return r.content, nil } From 6b4c1ea1f6051780c27a045d35c062fe2d124fe5 Mon Sep 17 00:00:00 2001 From: kkumar-gcc Date: Sat, 2 Nov 2024 11:12:12 +0000 Subject: [PATCH 09/10] chore: update mocks --- mocks/testing/TestRequest.go | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/mocks/testing/TestRequest.go b/mocks/testing/TestRequest.go index 5ecd55709..ce16817da 100644 --- a/mocks/testing/TestRequest.go +++ b/mocks/testing/TestRequest.go @@ -141,9 +141,9 @@ func (_c *TestRequest_Get_Call) RunAndReturn(run func(string) (testing.TestRespo return _c } -// Head provides a mock function with given fields: uri, body -func (_m *TestRequest) Head(uri string, body io.Reader) (testing.TestResponse, error) { - ret := _m.Called(uri, body) +// Head provides a mock function with given fields: uri +func (_m *TestRequest) Head(uri string) (testing.TestResponse, error) { + ret := _m.Called(uri) if len(ret) == 0 { panic("no return value specified for Head") @@ -151,19 +151,19 @@ func (_m *TestRequest) Head(uri string, body io.Reader) (testing.TestResponse, e var r0 testing.TestResponse var r1 error - if rf, ok := ret.Get(0).(func(string, io.Reader) (testing.TestResponse, error)); ok { - return rf(uri, body) + if rf, ok := ret.Get(0).(func(string) (testing.TestResponse, error)); ok { + return rf(uri) } - if rf, ok := ret.Get(0).(func(string, io.Reader) testing.TestResponse); ok { - r0 = rf(uri, body) + if rf, ok := ret.Get(0).(func(string) testing.TestResponse); ok { + r0 = rf(uri) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(testing.TestResponse) } } - if rf, ok := ret.Get(1).(func(string, io.Reader) error); ok { - r1 = rf(uri, body) + if rf, ok := ret.Get(1).(func(string) error); ok { + r1 = rf(uri) } else { r1 = ret.Error(1) } @@ -178,14 +178,13 @@ type TestRequest_Head_Call struct { // Head is a helper method to define mock.On call // - uri string -// - body io.Reader -func (_e *TestRequest_Expecter) Head(uri interface{}, body interface{}) *TestRequest_Head_Call { - return &TestRequest_Head_Call{Call: _e.mock.On("Head", uri, body)} +func (_e *TestRequest_Expecter) Head(uri interface{}) *TestRequest_Head_Call { + return &TestRequest_Head_Call{Call: _e.mock.On("Head", uri)} } -func (_c *TestRequest_Head_Call) Run(run func(uri string, body io.Reader)) *TestRequest_Head_Call { +func (_c *TestRequest_Head_Call) Run(run func(uri string)) *TestRequest_Head_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(io.Reader)) + run(args[0].(string)) }) return _c } @@ -195,7 +194,7 @@ func (_c *TestRequest_Head_Call) Return(_a0 testing.TestResponse, _a1 error) *Te return _c } -func (_c *TestRequest_Head_Call) RunAndReturn(run func(string, io.Reader) (testing.TestResponse, error)) *TestRequest_Head_Call { +func (_c *TestRequest_Head_Call) RunAndReturn(run func(string) (testing.TestResponse, error)) *TestRequest_Head_Call { _c.Call.Return(run) return _c } From f239f8a8202b356acf8aad359bb78a2cc272ad24 Mon Sep 17 00:00:00 2001 From: kkumar-gcc Date: Sat, 2 Nov 2024 19:20:03 +0530 Subject: [PATCH 10/10] . --- testing/test_request.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/test_request.go b/testing/test_request.go index 7726672bd..13a93b265 100644 --- a/testing/test_request.go +++ b/testing/test_request.go @@ -88,7 +88,7 @@ func (r *TestRequest) Options(uri string) (contractstesting.TestResponse, error) } func (r *TestRequest) call(method string, uri string, body io.Reader) (contractstesting.TestResponse, error) { - req := httptest.NewRequestWithContext(r.ctx, method, uri, body) + req := httptest.NewRequest(method, uri, body).WithContext(r.ctx) for key, value := range r.defaultHeaders { req.Header.Set(key, value)