From 599b7142c226dea2b4b05fc93223b69e0d809388 Mon Sep 17 00:00:00 2001 From: Maksym Pavlenko Date: Mon, 14 Aug 2017 16:38:59 -0700 Subject: [PATCH] Add server tests --- web/pkg/api/api.go | 8 +- web/pkg/server/server.go | 8 +- web/pkg/server/server_mock_test.go | 74 ++++++++++++++++ web/pkg/server/server_test.go | 130 +++++++++++++++++++++++++++++ 4 files changed, 209 insertions(+), 11 deletions(-) create mode 100644 web/pkg/server/server_mock_test.go create mode 100644 web/pkg/server/server_test.go diff --git a/web/pkg/api/api.go b/web/pkg/api/api.go index 3da918c..e1001ea 100644 --- a/web/pkg/api/api.go +++ b/web/pkg/api/api.go @@ -59,8 +59,8 @@ const ( ) type CreateFeedRequest struct { - URL string `json:"url"` - PageSize int `json:"page_size"` - Quality Quality `json:"quality"` - Format Format `json:"format"` + URL string `json:"url" binding:"url,required"` + PageSize int `json:"page_size" binding:"min=10,max=150,required"` + Quality Quality `json:"quality" binding:"eq=high|eq=low"` + Format Format `json:"format" binding:"eq=video|eq=audio"` } diff --git a/web/pkg/server/server.go b/web/pkg/server/server.go index bbb7550..b553f64 100644 --- a/web/pkg/server/server.go +++ b/web/pkg/server/server.go @@ -5,7 +5,6 @@ import ( "net/http" "github.com/gin-gonic/gin" - "github.com/gin-gonic/gin/binding" itunes "github.com/mxpv/podcast" "github.com/mxpv/podsync/web/pkg/api" "github.com/pkg/errors" @@ -33,11 +32,6 @@ func MakeHandlers(feed feed) http.Handler { return } - if err := binding.Validator.ValidateStruct(req); err != nil { - c.JSON(badRequest(err)) - return - } - hashId, err := feed.CreateFeed(c.Request.Context(), req) if err != nil { c.JSON(internalError(err)) @@ -47,7 +41,7 @@ func MakeHandlers(feed feed) http.Handler { c.JSON(http.StatusOK, gin.H{"id": hashId}) }) - r.GET("/:hashId", func(c *gin.Context) { + r.GET("/feed/:hashId", func(c *gin.Context) { hashId := c.Param("hashId") if hashId == "" || len(hashId) > 12 { c.JSON(badRequest(errors.New("invalid feed id"))) diff --git a/web/pkg/server/server_mock_test.go b/web/pkg/server/server_mock_test.go new file mode 100644 index 0000000..9524c26 --- /dev/null +++ b/web/pkg/server/server_mock_test.go @@ -0,0 +1,74 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: server.go + +package server + +import ( + context "context" + gomock "github.com/golang/mock/gomock" + podcast "github.com/mxpv/podcast" + api "github.com/mxpv/podsync/web/pkg/api" + reflect "reflect" +) + +// Mockfeed is a mock of feed interface +type Mockfeed struct { + ctrl *gomock.Controller + recorder *MockfeedMockRecorder +} + +// MockfeedMockRecorder is the mock recorder for Mockfeed +type MockfeedMockRecorder struct { + mock *Mockfeed +} + +// NewMockfeed creates a new mock instance +func NewMockfeed(ctrl *gomock.Controller) *Mockfeed { + mock := &Mockfeed{ctrl: ctrl} + mock.recorder = &MockfeedMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use +func (_m *Mockfeed) EXPECT() *MockfeedMockRecorder { + return _m.recorder +} + +// CreateFeed mocks base method +func (_m *Mockfeed) CreateFeed(ctx context.Context, req *api.CreateFeedRequest) (string, error) { + ret := _m.ctrl.Call(_m, "CreateFeed", ctx, req) + ret0, _ := ret[0].(string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// CreateFeed indicates an expected call of CreateFeed +func (_mr *MockfeedMockRecorder) CreateFeed(arg0, arg1 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "CreateFeed", reflect.TypeOf((*Mockfeed)(nil).CreateFeed), arg0, arg1) +} + +// GetFeed mocks base method +func (_m *Mockfeed) GetFeed(hashId string) (*podcast.Podcast, error) { + ret := _m.ctrl.Call(_m, "GetFeed", hashId) + ret0, _ := ret[0].(*podcast.Podcast) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetFeed indicates an expected call of GetFeed +func (_mr *MockfeedMockRecorder) GetFeed(arg0 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "GetFeed", reflect.TypeOf((*Mockfeed)(nil).GetFeed), arg0) +} + +// GetMetadata mocks base method +func (_m *Mockfeed) GetMetadata(hashId string) (*api.Feed, error) { + ret := _m.ctrl.Call(_m, "GetMetadata", hashId) + ret0, _ := ret[0].(*api.Feed) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetMetadata indicates an expected call of GetMetadata +func (_mr *MockfeedMockRecorder) GetMetadata(arg0 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "GetMetadata", reflect.TypeOf((*Mockfeed)(nil).GetMetadata), arg0) +} diff --git a/web/pkg/server/server_test.go b/web/pkg/server/server_test.go new file mode 100644 index 0000000..cf013be --- /dev/null +++ b/web/pkg/server/server_test.go @@ -0,0 +1,130 @@ +//go:generate mockgen -source=server.go -destination=server_mock_test.go -package=server + +package server + +import ( + "io/ioutil" + "net/http" + "net/http/httptest" + "strings" + "testing" + + "github.com/golang/mock/gomock" + itunes "github.com/mxpv/podcast" + "github.com/mxpv/podsync/web/pkg/api" + "github.com/stretchr/testify/require" +) + +func TestCreateFeed(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + req := &api.CreateFeedRequest{ + URL: "https://youtube.com/channel/123", + PageSize: 55, + Quality: api.LowQuality, + Format: api.AudioFormat, + } + + feed := NewMockfeed(ctrl) + feed.EXPECT().CreateFeed(gomock.Any(), gomock.Eq(req)).Times(1).Return("456", nil) + + srv := httptest.NewServer(MakeHandlers(feed)) + defer srv.Close() + + query := `{"url": "https://youtube.com/channel/123", "page_size": 55, "quality": "low", "format": "audio"}` + resp, err := http.Post(srv.URL+"/create", "application/json", strings.NewReader(query)) + require.NoError(t, err) + require.Equal(t, http.StatusOK, resp.StatusCode) + + require.JSONEq(t, `{"id": "456"}`, readBody(t, resp)) +} + +func TestCreateInvalidFeed(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + srv := httptest.NewServer(MakeHandlers(NewMockfeed(ctrl))) + defer srv.Close() + + query := `{}` + resp, err := http.Post(srv.URL+"/create", "application/json", strings.NewReader(query)) + require.NoError(t, err) + require.Equal(t, http.StatusBadRequest, resp.StatusCode) + + query = `{"url": "not a url", "page_size": 55, "quality": "low", "format": "audio"}` + resp, err = http.Post(srv.URL+"/create", "application/json", strings.NewReader(query)) + require.NoError(t, err) + require.Equal(t, http.StatusBadRequest, resp.StatusCode) + + query = `{"url": "https://youtube.com/channel/123", "page_size": 1, "quality": "low", "format": "audio"}` + resp, err = http.Post(srv.URL+"/create", "application/json", strings.NewReader(query)) + require.NoError(t, err) + require.Equal(t, http.StatusBadRequest, resp.StatusCode) + + query = `{"url": "https://youtube.com/channel/123", "page_size": 151, "quality": "low", "format": "audio"}` + resp, err = http.Post(srv.URL+"/create", "application/json", strings.NewReader(query)) + require.NoError(t, err) + require.Equal(t, http.StatusBadRequest, resp.StatusCode) + + query = `{"url": "https://youtube.com/channel/123", "page_size": 50, "quality": "xyz", "format": "audio"}` + resp, err = http.Post(srv.URL+"/create", "application/json", strings.NewReader(query)) + require.NoError(t, err) + require.Equal(t, http.StatusBadRequest, resp.StatusCode) + + query = `{"url": "https://youtube.com/channel/123", "page_size": 50, "quality": "low", "format": "xyz"}` + resp, err = http.Post(srv.URL+"/create", "application/json", strings.NewReader(query)) + require.NoError(t, err) + require.Equal(t, http.StatusBadRequest, resp.StatusCode) + + query = `{"url": "https://youtube.com/channel/123", "page_size": 50, "quality": "low", "format": ""}` + resp, err = http.Post(srv.URL+"/create", "application/json", strings.NewReader(query)) + require.NoError(t, err) + require.Equal(t, http.StatusBadRequest, resp.StatusCode) + + query = `{"url": "https://youtube.com/channel/123", "page_size": 50, "quality": "", "format": "audio"}` + resp, err = http.Post(srv.URL+"/create", "application/json", strings.NewReader(query)) + require.NoError(t, err) + require.Equal(t, http.StatusBadRequest, resp.StatusCode) +} + +func TestGetFeed(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + podcast := itunes.New("", "", "", nil, nil) + + feed := NewMockfeed(ctrl) + feed.EXPECT().GetFeed("123").Return(&podcast, nil) + + srv := httptest.NewServer(MakeHandlers(feed)) + defer srv.Close() + + resp, err := http.Get(srv.URL + "/feed/123") + require.NoError(t, err) + require.Equal(t, http.StatusOK, resp.StatusCode) +} + +func TestGetMetadata(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + feed := NewMockfeed(ctrl) + feed.EXPECT().GetMetadata("123").Times(1).Return(&api.Feed{}, nil) + + srv := httptest.NewServer(MakeHandlers(feed)) + defer srv.Close() + + resp, err := http.Get(srv.URL + "/metadata/123") + require.NoError(t, err) + require.Equal(t, http.StatusOK, resp.StatusCode) +} + +func readBody(t *testing.T, resp *http.Response) string { + buf, err := ioutil.ReadAll(resp.Body) + defer resp.Body.Close() + + require.NoError(t, err) + + return string(buf) +}