From cbd1455c4208170afd0cc281df72449a8db73b45 Mon Sep 17 00:00:00 2001 From: Daniel Lee Date: Tue, 7 Feb 2017 22:15:52 +0100 Subject: [PATCH] fix(api): case insensitive sort for datasources The data source list is case sensitive when sorted. This changes the sort to be case insensitive. The test only tests the handler, not the routing or database query. --- pkg/api/datasources_test.go | 124 ++++++++++++++++++++++++++++++++++++ pkg/api/dtos/models.go | 2 +- 2 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 pkg/api/datasources_test.go diff --git a/pkg/api/datasources_test.go b/pkg/api/datasources_test.go new file mode 100644 index 00000000000..f04eb6076b2 --- /dev/null +++ b/pkg/api/datasources_test.go @@ -0,0 +1,124 @@ +package api + +import ( + "encoding/json" + "net/http" + "net/http/httptest" + "path/filepath" + "testing" + + m "github.com/grafana/grafana/pkg/models" + macaron "gopkg.in/macaron.v1" + + "github.com/go-macaron/session" + "github.com/grafana/grafana/pkg/bus" + "github.com/grafana/grafana/pkg/middleware" + . "github.com/smartystreets/goconvey/convey" +) + +const ( + TestOrgID = 1 + TestUserID = 1 +) + +func TestDataSourcesProxy(t *testing.T) { + Convey("Given a user is logged in", t, func() { + loggedInUserScenario("When calling GET on", "/api/datasources/", func(sc *scenarioContext) { + + // Stubs the database query + bus.AddHandler("test", func(query *m.GetDataSourcesQuery) error { + So(query.OrgId, ShouldEqual, TestOrgID) + query.Result = []*m.DataSource{ + {Name: "mmm"}, + {Name: "ZZZ"}, + {Name: "BBB"}, + {Name: "aaa"}, + } + return nil + }) + + // handler func being tested + sc.handlerFunc = GetDataSources + sc.fakeReq("GET", "/api/datasources").exec() + + respJSON := []map[string]interface{}{} + err := json.NewDecoder(sc.resp.Body).Decode(&respJSON) + So(err, ShouldBeNil) + + Convey("should return list of datasources for org sorted alphabetically and case insensitively", func() { + So(respJSON[0]["name"], ShouldEqual, "aaa") + So(respJSON[1]["name"], ShouldEqual, "BBB") + So(respJSON[2]["name"], ShouldEqual, "mmm") + So(respJSON[3]["name"], ShouldEqual, "ZZZ") + }) + }) + }) +} + +func loggedInUserScenario(desc string, url string, fn scenarioFunc) { + Convey(desc+" "+url, func() { + defer bus.ClearBusHandlers() + + sc := &scenarioContext{} + viewsPath, _ := filepath.Abs("../../public/views") + + sc.m = macaron.New() + sc.m.Use(macaron.Renderer(macaron.RenderOptions{ + Directory: viewsPath, + Delims: macaron.Delims{Left: "[[", Right: "]]"}, + })) + + sc.m.Use(middleware.GetContextHandler()) + sc.m.Use(middleware.Sessioner(&session.Options{})) + + sc.defaultHandler = func(c *middleware.Context) { + sc.context = c + sc.context.UserId = TestUserID + sc.context.OrgId = TestOrgID + sc.context.OrgRole = m.ROLE_EDITOR + if sc.handlerFunc != nil { + sc.handlerFunc(sc.context) + } + } + sc.m.SetAutoHead(true) + sc.m.Get(url, sc.defaultHandler) + + fn(sc) + }) +} + +func (sc *scenarioContext) fakeReq(method, url string) *scenarioContext { + sc.resp = httptest.NewRecorder() + req, err := http.NewRequest(method, url, nil) + So(err, ShouldBeNil) + sc.req = req + + return sc +} + +type scenarioContext struct { + m *macaron.Macaron + context *middleware.Context + resp *httptest.ResponseRecorder + apiKey string + authHeader string + handlerFunc handlerFunc + defaultHandler macaron.Handler + + req *http.Request +} + +func (sc *scenarioContext) exec() { + if sc.apiKey != "" { + sc.req.Header.Add("Authorization", "Bearer "+sc.apiKey) + } + + if sc.authHeader != "" { + sc.req.Header.Add("Authorization", sc.authHeader) + } + + sc.m.ServeHTTP(sc.resp, sc.req) +} + +type scenarioFunc func(c *scenarioContext) +type handlerFunc func(c *middleware.Context) diff --git a/pkg/api/dtos/models.go b/pkg/api/dtos/models.go index 13dbe4ea32a..564d86a25bf 100644 --- a/pkg/api/dtos/models.go +++ b/pkg/api/dtos/models.go @@ -91,7 +91,7 @@ func (slice DataSourceList) Len() int { } func (slice DataSourceList) Less(i, j int) bool { - return slice[i].Name < slice[j].Name + return strings.ToLower(slice[i].Name) < strings.ToLower(slice[j].Name) } func (slice DataSourceList) Swap(i, j int) {