influxdb/server/cells_test.go

278 lines
6.1 KiB
Go

package server_test
import (
"context"
"encoding/json"
"net/http"
"net/http/httptest"
"net/url"
"strings"
"testing"
"github.com/bouk/httprouter"
"github.com/google/go-cmp/cmp"
"github.com/influxdata/chronograf"
"github.com/influxdata/chronograf/mocks"
"github.com/influxdata/chronograf/server"
)
func Test_Cells_CorrectAxis(t *testing.T) {
t.Parallel()
axisTests := []struct {
name string
cell *chronograf.DashboardCell
shouldFail bool
}{
{
"correct axes",
&chronograf.DashboardCell{
Axes: map[string]chronograf.Axis{
"x": chronograf.Axis{
Bounds: []string{"0", "100"},
},
"y": chronograf.Axis{
Bounds: []string{"0", "100"},
},
"y2": chronograf.Axis{
Bounds: []string{"0", "100"},
},
},
},
false,
},
{
"invalid axes present",
&chronograf.DashboardCell{
Axes: map[string]chronograf.Axis{
"axis of evil": chronograf.Axis{
Bounds: []string{"666", "666"},
},
"axis of awesome": chronograf.Axis{
Bounds: []string{"1337", "31337"},
},
},
},
true,
},
{
"linear scale value",
&chronograf.DashboardCell{
Axes: map[string]chronograf.Axis{
"x": chronograf.Axis{
Scale: "linear",
Bounds: []string{"0", "100"},
},
},
},
false,
},
{
"log scale value",
&chronograf.DashboardCell{
Axes: map[string]chronograf.Axis{
"x": chronograf.Axis{
Scale: "log",
Bounds: []string{"0", "100"},
},
},
},
false,
},
{
"invalid scale value",
&chronograf.DashboardCell{
Axes: map[string]chronograf.Axis{
"x": chronograf.Axis{
Scale: "potatoes",
Bounds: []string{"0", "100"},
},
},
},
true,
},
{
"base 10 axis",
&chronograf.DashboardCell{
Axes: map[string]chronograf.Axis{
"x": chronograf.Axis{
Base: "10",
Bounds: []string{"0", "100"},
},
},
},
false,
},
{
"base 2 axis",
&chronograf.DashboardCell{
Axes: map[string]chronograf.Axis{
"x": chronograf.Axis{
Base: "2",
Bounds: []string{"0", "100"},
},
},
},
false,
},
{
"invalid base",
&chronograf.DashboardCell{
Axes: map[string]chronograf.Axis{
"x": chronograf.Axis{
Base: "all your base are belong to us",
Bounds: []string{"0", "100"},
},
},
},
true,
},
}
for _, test := range axisTests {
t.Run(test.name, func(tt *testing.T) {
if err := server.HasCorrectAxes(test.cell); err != nil && !test.shouldFail {
t.Errorf("%q: Unexpected error: err: %s", test.name, err)
} else if err == nil && test.shouldFail {
t.Errorf("%q: Expected error and received none", test.name)
}
})
}
}
func Test_Service_DashboardCells(t *testing.T) {
cellsTests := []struct {
name string
reqURL *url.URL
ctxParams map[string]string
mockResponse []chronograf.DashboardCell
expected []chronograf.DashboardCell
expectedCode int
}{
{
"happy path",
&url.URL{
Path: "/chronograf/v1/dashboards/1/cells",
},
map[string]string{
"id": "1",
},
[]chronograf.DashboardCell{},
[]chronograf.DashboardCell{},
http.StatusOK,
},
{
"cell axes should always be \"x\", \"y\", and \"y2\"",
&url.URL{
Path: "/chronograf/v1/dashboards/1/cells",
},
map[string]string{
"id": "1",
},
[]chronograf.DashboardCell{
{
ID: "3899be5a-f6eb-4347-b949-de2f4fbea859",
X: 0,
Y: 0,
W: 4,
H: 4,
Name: "CPU",
Type: "bar",
Queries: []chronograf.DashboardQuery{},
Axes: map[string]chronograf.Axis{},
},
},
[]chronograf.DashboardCell{
{
ID: "3899be5a-f6eb-4347-b949-de2f4fbea859",
X: 0,
Y: 0,
W: 4,
H: 4,
Name: "CPU",
Type: "bar",
Queries: []chronograf.DashboardQuery{},
Axes: map[string]chronograf.Axis{
"x": chronograf.Axis{
Bounds: []string{},
},
"y": chronograf.Axis{
Bounds: []string{},
},
"y2": chronograf.Axis{
Bounds: []string{},
},
},
},
},
http.StatusOK,
},
}
for _, test := range cellsTests {
t.Run(test.name, func(t *testing.T) {
t.Parallel()
// setup context with params
ctx := context.Background()
params := httprouter.Params{}
for k, v := range test.ctxParams {
params = append(params, httprouter.Param{k, v})
}
ctx = httprouter.WithParams(ctx, params)
// setup response recorder and request
rr := httptest.NewRecorder()
req := httptest.NewRequest("GET", test.reqURL.RequestURI(), strings.NewReader("")).WithContext(ctx)
// setup mock DashboardCells store and logger
tlog := &mocks.TestLogger{}
svc := &server.Service{
DashboardsStore: &mocks.DashboardsStore{
GetF: func(ctx context.Context, id chronograf.DashboardID) (chronograf.Dashboard, error) {
return chronograf.Dashboard{
ID: chronograf.DashboardID(1),
Cells: test.mockResponse,
Templates: []chronograf.Template{},
Name: "empty dashboard",
}, nil
},
},
Logger: tlog,
}
// invoke DashboardCell handler
svc.DashboardCells(rr, req)
// setup frame to decode response into
respFrame := []struct {
chronograf.DashboardCell
Links json.RawMessage `json:"links"` // ignore links
}{}
// decode response
resp := rr.Result()
if resp.StatusCode != test.expectedCode {
tlog.Dump(t)
t.Fatalf("%q - Status codes do not match. Want %d (%s), Got %d (%s)", test.name, test.expectedCode, http.StatusText(test.expectedCode), resp.StatusCode, http.StatusText(resp.StatusCode))
}
if err := json.NewDecoder(resp.Body).Decode(&respFrame); err != nil {
t.Fatalf("%q - Error unmarshaling response body: err: %s", test.name, err)
}
// extract actual
actual := []chronograf.DashboardCell{}
for _, rsp := range respFrame {
actual = append(actual, rsp.DashboardCell)
}
// compare actual and expected
if !cmp.Equal(actual, test.expected) {
t.Fatalf("%q - Dashboard Cells do not match: diff: %s", test.name, cmp.Diff(actual, test.expected))
}
})
}
}