From 9503263ac53c3e06409dbcc3ea8a041e1c28048e Mon Sep 17 00:00:00 2001 From: "ys.achinta" Date: Thu, 25 Jun 2020 10:33:29 +0530 Subject: [PATCH] test for list api --- cmd/service/service.go | 3 +- pkg/api/list.go | 14 +++++-- pkg/api/list_api_test.go | 86 ++++++++++++++++++++++++++++++++++++++++ pkg/api/lister.go | 4 ++ pkg/api/service_test.go | 33 ++++----------- 5 files changed, 109 insertions(+), 31 deletions(-) create mode 100644 pkg/api/list_api_test.go diff --git a/cmd/service/service.go b/cmd/service/service.go index 4221bf38d..eca782416 100644 --- a/cmd/service/service.go +++ b/cmd/service/service.go @@ -6,7 +6,6 @@ import ( "helm.sh/helm/v3/pkg/action" "helm.sh/helm/v3/pkg/api" - "helm.sh/helm/v3/pkg/api/list" "helm.sh/helm/v3/pkg/api/logger" "helm.sh/helm/v3/pkg/api/ping" "helm.sh/helm/v3/pkg/servercontext" @@ -30,7 +29,7 @@ func startServer() { api.NewList(action.NewList(app.ActionConfig))) router.Handle("/ping", ping.Handler()) - router.Handle("/list", list.Handler()) + router.Handle("/list", api.List(service)) router.Handle("/install", api.Install(service)) router.Handle("/upgrade", api.Upgrade(service)) diff --git a/pkg/api/list.go b/pkg/api/list.go index 782cde97c..496a28711 100644 --- a/pkg/api/list.go +++ b/pkg/api/list.go @@ -20,7 +20,7 @@ type HelmRelease struct { Namespace string `json:"namespace"` } -func Handler(svc Service) http.Handler { +func List(svc Service) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") @@ -29,9 +29,11 @@ func Handler(svc Service) http.Handler { decoder := json.NewDecoder(r.Body) decoder.UseNumber() if err := decoder.Decode(&request); err != nil { - response.Error = err.Error() logger.Errorf("[List] error decoding request: %v", err) + response.Error = err.Error() + payload, _ := json.Marshal(response) w.WriteHeader(http.StatusBadRequest) + w.Write(payload) return } defer r.Body.Close() @@ -42,9 +44,11 @@ func Handler(svc Service) http.Handler { res, err := svc.lister.Run() if err != nil { - response.Error = err.Error() logger.Errorf("[List] error while installing chart: %v", err) + response.Error = err.Error() + payload, _ := json.Marshal(response) w.WriteHeader(http.StatusInternalServerError) + w.Write(payload) return } @@ -56,9 +60,11 @@ func Handler(svc Service) http.Handler { response = ListResponse{"", helmReleases} payload, err := json.Marshal(response) if err != nil { - response.Error = err.Error() logger.Errorf("[List] error writing response %v", err) + response.Error = err.Error() + payload, _ := json.Marshal(response) w.WriteHeader(http.StatusInternalServerError) + w.Write(payload) return } diff --git a/pkg/api/list_api_test.go b/pkg/api/list_api_test.go new file mode 100644 index 000000000..69db484a6 --- /dev/null +++ b/pkg/api/list_api_test.go @@ -0,0 +1,86 @@ +package api_test + +import ( + "fmt" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + "gotest.tools/assert" + "helm.sh/helm/v3/pkg/api" + "helm.sh/helm/v3/pkg/api/logger" + "helm.sh/helm/v3/pkg/cli" + "helm.sh/helm/v3/pkg/release" + "io/ioutil" + "net/http" + "net/http/httptest" + "strings" + "testing" +) + +type ListTestSuite struct { + suite.Suite + recorder *httptest.ResponseRecorder + server *httptest.Server + mockInstall *api.MockInstall + mockChartLoader *api.MockChartLoader + mockList *api.MockList + appConfig *cli.EnvSettings +} + +func (s *ListTestSuite) SetupSuite() { + logger.Setup("default") +} + +func (s *ListTestSuite) SetupTest() { + s.recorder = httptest.NewRecorder() + s.mockInstall = new(api.MockInstall) + s.mockChartLoader = new(api.MockChartLoader) + s.mockList = new(api.MockList) + s.appConfig = &cli.EnvSettings{ + RepositoryConfig: "./testdata/helm", + PluginsDirectory: "./testdata/helm/plugin", + } + service := api.NewService(s.appConfig, s.mockChartLoader, s.mockInstall, s.mockList) + handler := api.List(service) + s.server = httptest.NewServer(handler) +} + +func (s *ListTestSuite) TestShouldReturnReleasesWhenSuccessfulAPICall() { + body := `{"request_id":"test-request-id"}` + req, _ := http.NewRequest("POST", fmt.Sprintf("%s/list", s.server.URL), strings.NewReader(body)) + + var releases []*release.Release + releases = append(releases, + &release.Release{Name: "test-release", + Namespace: "test-namespace", + Info: &release.Info{Status: release.StatusDeployed}}) + + s.mockList.On("SetStateMask") + s.mockList.On("Run").Return(releases, nil) + + resp, err := http.DefaultClient.Do(req) + + assert.Equal(s.T(), 200, resp.StatusCode) + expectedResponse := `{"Data":[{"release":"test-release","namespace":"test-namespace"}]}` + respBody, _ := ioutil.ReadAll(resp.Body) + assert.Equal(s.T(), expectedResponse, string(respBody)) + require.NoError(s.T(), err) + s.mockList.AssertExpectations(s.T()) +} + +func (s *ListTestSuite) TestShouldReturnBadRequestErrorIfItHasInvalidCharacter() { + body := `{"request_id":"test-request-id""""}` + req, _ := http.NewRequest("POST", fmt.Sprintf("%s/list", s.server.URL), strings.NewReader(body)) + + resp, err := http.DefaultClient.Do(req) + + assert.Equal(s.T(), 400, resp.StatusCode) + require.NoError(s.T(), err) +} + +func (s *ListTestSuite) TearDownTest() { + s.server.Close() +} + +func TestListAPI(t *testing.T) { + suite.Run(t, new(ListTestSuite)) +} \ No newline at end of file diff --git a/pkg/api/lister.go b/pkg/api/lister.go index 1abad4542..8530e6852 100644 --- a/pkg/api/lister.go +++ b/pkg/api/lister.go @@ -25,4 +25,8 @@ type MockList struct{ mock.Mock } func (m *MockList) Run() ([]*release.Release, error) { args := m.Called() return args.Get(0).([]*release.Release), args.Error(1) +} + +func (m *MockList) SetStateMask() { + m.Called() } \ No newline at end of file diff --git a/pkg/api/service_test.go b/pkg/api/service_test.go index 728f94287..b2be76aba 100644 --- a/pkg/api/service_test.go +++ b/pkg/api/service_test.go @@ -10,7 +10,6 @@ import ( "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" "helm.sh/helm/v3/pkg/api/logger" - "helm.sh/helm/v3/pkg/chart" "helm.sh/helm/v3/pkg/cli" "helm.sh/helm/v3/pkg/release" ) @@ -18,8 +17,9 @@ import ( type ServiceTestSuite struct { suite.Suite ctx context.Context - installer *mockInstaller - chartloader *mockChartLoader + installer *MockInstall + chartloader *MockChartLoader + lister *MockList svc Service settings *cli.EnvSettings } @@ -27,10 +27,11 @@ type ServiceTestSuite struct { func (s *ServiceTestSuite) SetupTest() { logger.Setup("") s.ctx = context.Background() - s.installer = new(mockInstaller) - s.chartloader = new(mockChartLoader) + s.installer = new(MockInstall) + s.lister = new(MockList) + s.chartloader = new(MockChartLoader) s.settings = &cli.EnvSettings{} - s.svc = NewService(s.settings, s.chartloader, s.installer) + s.svc = NewService(s.settings, s.chartloader, s.installer, s.lister) } func (s *ServiceTestSuite) TestInstallShouldReturnErrorOnInvalidChart() { @@ -100,22 +101,4 @@ func (s *ServiceTestSuite) TestInstallShouldReturnResultOnSuccess() { func TestServiceSuite(t *testing.T) { suite.Run(t, new(ServiceTestSuite)) -} - -type mockChartLoader struct{ mock.Mock } - -func (m *mockChartLoader) LocateChart(name string, settings *cli.EnvSettings) (string, error) { - args := m.Called(name, settings) - return args.String(0), args.Error(1) -} - -type mockInstaller struct{ mock.Mock } - -func (m *mockInstaller) SetConfig(cfg InstallConfig) { - m.Called(cfg) -} - -func (m *mockInstaller) Run(c *chart.Chart, vals map[string]interface{}) (*release.Release, error) { - args := m.Called(c, vals) - return args.Get(0).(*release.Release), args.Error(1) -} +} \ No newline at end of file