- revise testing of dashboard enpoints

- clean up testdata, serializers and responses
- add validators for dashboards
- revise documentation of dashboard endpoints for swaggo
- revise endpoint implementations
This commit is contained in:
Sonja Happ 2019-09-06 14:07:36 +02:00
parent e0ae839e96
commit dab027eef6
9 changed files with 434 additions and 160 deletions

View file

@ -2,13 +2,6 @@ package common
import "github.com/jinzhu/gorm/dialects/postgres"
type DashboardResponse struct {
ID uint `json:"id"`
Name string `json:"name"`
Grid int `json:"grid"`
ScenarioID uint `json:"scenarioID"`
}
type WidgetResponse struct {
ID uint `json:"id"`
Name string `json:"name"`
@ -59,14 +52,6 @@ type ResponseMsgSignal struct {
Signal SignalResponse `json:"signal"`
}
type ResponseMsgDashboards struct {
Dashboards []DashboardResponse `json:"dashboards"`
}
type ResponseMsgDashboard struct {
Dashboard DashboardResponse `json:"dashboard"`
}
type ResponseMsgWidgets struct {
Widgets []WidgetResponse `json:"widgets"`
}

View file

@ -4,38 +4,6 @@ import (
"github.com/gin-gonic/gin"
)
// Dashboard/s Serializers
type DashboardsSerializer struct {
Ctx *gin.Context
Dashboards []Dashboard
}
func (self *DashboardsSerializer) Response() []DashboardResponse {
response := []DashboardResponse{}
for _, dashboard := range self.Dashboards {
serializer := DashboardSerializer{self.Ctx, dashboard}
response = append(response, serializer.Response())
}
return response
}
type DashboardSerializer struct {
Ctx *gin.Context
Dashboard
}
func (self *DashboardSerializer) Response() DashboardResponse {
response := DashboardResponse{
Name: self.Name,
Grid: self.Grid,
ScenarioID: self.ScenarioID,
ID: self.ID,
}
return response
}
// Widget/s Serializers
type WidgetsSerializer struct {

View file

@ -196,14 +196,14 @@ var InSignalCUpdated_response = SignalResponse{
// Dashboards
var DashboardA = Dashboard{Name: "Dashboard_A", Grid: 15}
var DashboardA_response = DashboardResponse{ID: 1, Name: DashboardA.Name, Grid: DashboardA.Grid, ScenarioID: DashboardA.ScenarioID}
var DashboardB = Dashboard{Name: "Dashboard_B", Grid: 10}
var DashboardB_response = DashboardResponse{ID: 2, Name: DashboardB.Name, Grid: DashboardB.Grid, ScenarioID: DashboardB.ScenarioID}
var DashboardC = Dashboard{Name: "Dashboard_C", Grid: 25}
var DashboardC_response = DashboardResponse{ID: 3, Name: DashboardC.Name, Grid: DashboardC.Grid, ScenarioID: DashboardC.ScenarioID}
var DashboardCUpdated = Dashboard{Name: "Dashboard_Cupdated", Grid: 24}
var DashboardCUpdated_response = DashboardResponse{ID: 3, Name: DashboardCUpdated.Name, Grid: DashboardCUpdated.Grid, ScenarioID: DashboardCUpdated.ScenarioID}
var DashboardA = Dashboard{
Name: "Dashboard_A",
Grid: 15,
}
var DashboardB = Dashboard{
Name: "Dashboard_B",
Grid: 10,
}
// Files

View file

@ -48,3 +48,11 @@ type ResponseSimulationModels struct {
type ResponseSimulationModel struct {
model common.SimulationModel
}
type ResponseDashboards struct {
dashboards []common.Dashboard
}
type ResponseDashboard struct {
dashboard common.Dashboard
}

View file

@ -1,6 +1,7 @@
package dashboard
import (
"fmt"
"net/http"
"github.com/gin-gonic/gin"
@ -23,11 +24,10 @@ func RegisterDashboardEndpoints(r *gin.RouterGroup) {
// @ID getDashboards
// @Produce json
// @Tags dashboards
// @Success 200 {array} common.DashboardResponse "Array of dashboards to which belong to scenario"
// @Failure 401 "Unauthorized Access"
// @Failure 403 "Access forbidden."
// @Failure 404 "Not found"
// @Failure 500 "Internal server error"
// @Success 200 {object} docs.ResponseDashboards "Dashboards to which belong to scenario"
// @Failure 404 {object} docs.ResponseError "Not found"
// @Failure 422 {object} docs.ResponseError "Unprocessable entity"
// @Failure 500 {object} docs.ResponseError "Internal server error"
// @Param scenarioID query int true "Scenario ID"
// @Router /dashboards [get]
func getDashboards(c *gin.Context) {
@ -44,9 +44,8 @@ func getDashboards(c *gin.Context) {
return
}
serializer := common.DashboardsSerializer{c, dab}
c.JSON(http.StatusOK, gin.H{
"dashboards": serializer.Response(),
"dashboards": dab,
})
}
@ -56,44 +55,54 @@ func getDashboards(c *gin.Context) {
// @Accept json
// @Produce json
// @Tags dashboards
// @Param inputDab body common.ResponseMsgDashboard true "Dashboard to be added incl. ID of Scenario"
// @Success 200 "OK."
// @Failure 401 "Unauthorized Access"
// @Failure 403 "Access forbidden."
// @Failure 404 "Not found"
// @Failure 500 "Internal server error"
// @Param inputDab body dashboard.validNewDashboard true "Dashboard to be added incl. ID of Scenario"
// @Success 200 {object} docs.ResponseDashboard "Dashboards that was added"
// @Failure 400 {object} docs.ResponseError "Bad request"
// @Failure 404 {object} docs.ResponseError "Not found"
// @Failure 422 {object} docs.ResponseError "Unprocessable entity"
// @Failure 500 {object} docs.ResponseError "Internal server error"
// @Router /dashboards [post]
func addDashboard(c *gin.Context) {
var newDabData common.ResponseMsgDashboard
err := c.BindJSON(&newDabData)
if err != nil {
errormsg := "Bad request. Error binding form data to JSON: " + err.Error()
// bind request to JSON
var req addDashboardRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": errormsg,
"success": false,
"message": fmt.Sprintf("%v", err),
})
return
}
var newDab Dashboard
newDab.ID = newDabData.Dashboard.ID
newDab.Grid = newDabData.Dashboard.Grid
newDab.ScenarioID = newDabData.Dashboard.ScenarioID
newDab.Name = newDabData.Dashboard.Name
// Validate the request
if err := req.validate(); err != nil {
c.JSON(http.StatusUnprocessableEntity, gin.H{
"success": false,
"message": fmt.Sprintf("%v", err),
})
return
}
ok, _ := scenario.CheckPermissions(c, common.Create, "body", int(newDab.ScenarioID))
// Create the new dashboard from the request
newDashboard := req.createDashboard()
// Check if user is allowed to modify scenario specified in request
ok, _ := scenario.CheckPermissions(c, common.Create, "body", int(newDashboard.ScenarioID))
if !ok {
return
}
// add dashboard to DB and add association to scenario
err = newDab.addToScenario()
if common.ProvideErrorResponse(c, err) == false {
c.JSON(http.StatusOK, gin.H{
"message": "OK.",
})
err := newDashboard.addToScenario()
if err != nil {
common.ProvideErrorResponse(c, err)
return
}
c.JSON(http.StatusOK, gin.H{
"dashboard": newDashboard.Dashboard,
})
}
// updateDashboard godoc
@ -102,37 +111,59 @@ func addDashboard(c *gin.Context) {
// @Tags dashboards
// @Accept json
// @Produce json
// @Param inputDab body common.ResponseMsgDashboard true "Dashboard to be updated"
// @Success 200 "OK."
// @Failure 401 "Unauthorized Access"
// @Failure 403 "Access forbidden."
// @Failure 404 "Not found"
// @Failure 500 "Internal server error"
// @Param inputDab body dashboard.validUpdatedDashboard true "Dashboard to be updated"
// @Success 200 {object} docs.ResponseDashboard "Dashboards that was updated"
// @Failure 400 {object} docs.ResponseError "Bad request"
// @Failure 404 {object} docs.ResponseError "Not found"
// @Failure 422 {object} docs.ResponseError "Unprocessable entity"
// @Failure 500 {object} docs.ResponseError "Internal server error"
// @Param dashboardID path int true "Dashboard ID"
// @Router /dashboards/{dashboardID} [put]
func updateDashboard(c *gin.Context) {
ok, d := CheckPermissions(c, common.Update, "path", -1)
ok, oldDashboard := CheckPermissions(c, common.Update, "path", -1)
if !ok {
return
}
var modifiedDab common.ResponseMsgDashboard
err := c.BindJSON(&modifiedDab)
if err != nil {
errormsg := "Bad request. Error binding form data to JSON: " + err.Error()
var req updateDashboardRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": errormsg,
"success": false,
"message": fmt.Sprintf("%v", err),
})
return
}
err = d.update(modifiedDab.Dashboard)
if common.ProvideErrorResponse(c, err) == false {
c.JSON(http.StatusOK, gin.H{
"message": "OK.",
// Validate the request
if err := req.validate(); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"success": false,
"message": fmt.Sprintf("%v", err),
})
return
}
// Create the updatedScenario from oldScenario
updatedDashboard, err := req.updatedDashboard(oldDashboard)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"success": false,
"message": fmt.Sprintf("%v", err),
})
return
}
// update the dashboard in the DB
err = oldDashboard.update(updatedDashboard)
if err != nil {
common.ProvideErrorResponse(c, err)
return
}
c.JSON(http.StatusOK, gin.H{
"dashboard": updatedDashboard.Dashboard,
})
}
// getDashboard godoc
@ -140,11 +171,11 @@ func updateDashboard(c *gin.Context) {
// @ID getDashboard
// @Tags dashboards
// @Produce json
// @Success 200 {object} common.DashboardResponse "Requested dashboard."
// @Failure 401 "Unauthorized Access"
// @Failure 403 "Access forbidden."
// @Failure 404 "Not found"
// @Failure 500 "Internal server error"
// @Success 200 {object} docs.ResponseDashboard "Dashboards that was requested"
// @Failure 400 {object} docs.ResponseError "Bad request"
// @Failure 404 {object} docs.ResponseError "Not found"
// @Failure 422 {object} docs.ResponseError "Unprocessable entity"
// @Failure 500 {object} docs.ResponseError "Internal server error"
// @Param dashboardID path int true "Dashboard ID"
// @Router /dashboards/{dashboardID} [get]
func getDashboard(c *gin.Context) {
@ -154,9 +185,8 @@ func getDashboard(c *gin.Context) {
return
}
serializer := common.DashboardSerializer{c, dab.Dashboard}
c.JSON(http.StatusOK, gin.H{
"dashboard": serializer.Response(),
"dashboard": dab.Dashboard,
})
}
@ -165,11 +195,11 @@ func getDashboard(c *gin.Context) {
// @ID deleteDashboard
// @Tags dashboards
// @Produce json
// @Success 200 "OK."
// @Failure 401 "Unauthorized Access"
// @Failure 403 "Access forbidden."
// @Failure 404 "Not found"
// @Failure 500 "Internal server error"
// @Success 200 {object} docs.ResponseDashboard "Dashboards that was deleted"
// @Failure 400 {object} docs.ResponseError "Bad request"
// @Failure 404 {object} docs.ResponseError "Not found"
// @Failure 422 {object} docs.ResponseError "Unprocessable entity"
// @Failure 500 {object} docs.ResponseError "Internal server error"
// @Param dashboardID path int true "Dashboard ID"
// @Router /dashboards/{dashboardID} [delete]
func deleteDashboard(c *gin.Context) {
@ -184,6 +214,6 @@ func deleteDashboard(c *gin.Context) {
}
c.JSON(http.StatusOK, gin.H{
"message": "OK.",
"dashboard": dab.Dashboard,
})
}

View file

@ -1,8 +1,6 @@
package dashboard
import (
"fmt"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/scenario"
)
@ -21,7 +19,7 @@ func (d *Dashboard) ByID(id uint) error {
db := common.GetDB()
err := db.Find(d, id).Error
if err != nil {
return fmt.Errorf("Dashboard with id=%v does not exist", id)
return err
}
return nil
}
@ -46,10 +44,11 @@ func (d *Dashboard) addToScenario() error {
return err
}
func (d *Dashboard) update(modifiedDab common.DashboardResponse) error {
func (d *Dashboard) update(modifiedDab Dashboard) error {
db := common.GetDB()
// TODO do we allow to update scenarioID here as well?
err := db.Model(d).Updates(map[string]interface{}{
"Name": modifiedDab.Name,
"Grid": modifiedDab.Grid,

View file

@ -17,7 +17,10 @@ func CheckPermissions(c *gin.Context, operation common.CRUD, dabIDSource string,
err := common.ValidateRole(c, common.ModelDashboard, operation)
if err != nil {
c.JSON(http.StatusUnprocessableEntity, "Access denied (role validation failed).")
c.JSON(http.StatusUnprocessableEntity, gin.H{
"success": false,
"message": fmt.Sprintf("Access denied (role validation failed): %v", err),
})
return false, dab
}
@ -25,18 +28,18 @@ func CheckPermissions(c *gin.Context, operation common.CRUD, dabIDSource string,
if dabIDSource == "path" {
dabID, err = strconv.Atoi(c.Param("dashboardID"))
if err != nil {
errormsg := fmt.Sprintf("Bad request. No or incorrect format of dashboardID path parameter")
c.JSON(http.StatusBadRequest, gin.H{
"error": errormsg,
"success": false,
"message": fmt.Sprintf("Bad request. No or incorrect format of dashboardID path parameter"),
})
return false, dab
}
} else if dabIDSource == "query" {
dabID, err = strconv.Atoi(c.Request.URL.Query().Get("dashboardID"))
if err != nil {
errormsg := fmt.Sprintf("Bad request. No or incorrect format of dashboardID query parameter")
c.JSON(http.StatusBadRequest, gin.H{
"error": errormsg,
"success": false,
"message": fmt.Sprintf("Bad request. No or incorrect format of dashboardID query parameter"),
})
return false, dab
}

View file

@ -1,65 +1,277 @@
package dashboard
import (
"encoding/json"
"testing"
"github.com/gin-gonic/gin"
"fmt"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/scenario"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/user"
"github.com/gin-gonic/gin"
"github.com/jinzhu/gorm"
"github.com/jinzhu/gorm/dialects/postgres"
"github.com/stretchr/testify/assert"
"os"
"testing"
)
// Test /dashboards endpoints
func TestEndpoints(t *testing.T) {
var router *gin.Engine
var db *gorm.DB
var token string
type DashboardRequest struct {
Name string `json:"name,omitempty"`
Grid int `json:"grid,omitempty"`
ScenarioID uint `json:"scenarioID,omitempty"`
}
var myDashboards = []common.DashboardResponse{common.DashboardA_response, common.DashboardB_response}
var msgDashboards = common.ResponseMsgDashboards{Dashboards: myDashboards}
var msgDab = common.ResponseMsgDashboard{Dashboard: common.DashboardC_response}
var msgDabupdated = common.ResponseMsgDashboard{Dashboard: common.DashboardCUpdated_response}
type ScenarioRequest struct {
Name string `json:"name,omitempty"`
Running bool `json:"running,omitempty"`
StartParameters postgres.Jsonb `json:"startParameters,omitempty"`
}
db := common.DummyInitDB()
func addScenario(token string) (scenarioID uint) {
// POST $newScenario
newScenario := ScenarioRequest{
Name: common.ScenarioA.Name,
Running: common.ScenarioA.Running,
StartParameters: common.ScenarioA.StartParameters,
}
_, resp, _ := common.NewTestEndpoint(router, token,
"/api/scenarios", "POST", common.KeyModels{"scenario": newScenario})
// Read newScenario's ID from the response
newScenarioID, _ := common.GetResponseID(resp)
return uint(newScenarioID)
}
func TestMain(m *testing.M) {
db = common.DummyInitDB()
defer db.Close()
common.DummyPopulateDB(db)
router := gin.Default()
router = gin.Default()
api := router.Group("/api")
// All endpoints require authentication except when someone wants to
// login (POST /authenticate)
user.RegisterAuthenticate(api.Group("/authenticate"))
api.Use(user.Authentication(true))
RegisterDashboardEndpoints(api.Group("/dashboards"))
// scenario endpoints required here to first add a scenario to the DB
// that can be associated with a new dashboard
scenario.RegisterScenarioEndpoints(api.Group("/scenarios"))
credjson, _ := json.Marshal(common.CredUser)
msgOKjson, _ := json.Marshal(common.MsgOK)
msgDashboardsjson, _ := json.Marshal(msgDashboards)
msgDabjson, _ := json.Marshal(msgDab)
msgDabupdatedjson, _ := json.Marshal(msgDabupdated)
os.Exit(m.Run())
}
token = common.AuthenticateForTest(t, router, "/api/authenticate", "POST", credjson, 200)
func TestAddDashboard(t *testing.T) {
common.DropTables(db)
common.MigrateModels(db)
common.DummyAddOnlyUserTableWithAdminAndUsersDB(db)
// test GET dashboards
common.TestEndpoint(t, router, token, "/api/dashboards?scenarioID=1", "GET", nil, 200, msgDashboardsjson)
// authenticate as normal user
token, err := common.NewAuthenticateForTest(router,
"/api/authenticate", "POST", common.UserACredentials)
assert.NoError(t, err)
// test POST dashboards
common.TestEndpoint(t, router, token, "/api/dashboards", "POST", msgDabjson, 200, msgOKjson)
scenarioID := addScenario(token)
// test GET dashboards/:dashboardID to check if previous POST worked correctly
common.TestEndpoint(t, router, token, "/api/dashboards/3", "GET", nil, 200, msgDabjson)
// test POST dashboards/ $newDashboard
newDashboard := DashboardRequest{
Name: common.DashboardA.Name,
Grid: common.DashboardA.Grid,
ScenarioID: scenarioID,
}
code, resp, err := common.NewTestEndpoint(router, token,
"/api/dashboards", "POST", common.KeyModels{"dashboard": newDashboard})
assert.NoError(t, err)
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
// test PUT dashboards/:dashboardID
common.TestEndpoint(t, router, token, "/api/dashboards/3", "PUT", msgDabupdatedjson, 200, msgOKjson)
common.TestEndpoint(t, router, token, "/api/dashboards/3", "GET", nil, 200, msgDabupdatedjson)
// Compare POST's response with the newDashboard
err = common.CompareResponse(resp, common.KeyModels{"dashboard": newDashboard})
assert.NoError(t, err)
// test DELETE dashboards/:dashboardID
common.TestEndpoint(t, router, token, "/api/dashboards/3", "DELETE", nil, 200, msgOKjson)
common.TestEndpoint(t, router, token, "/api/dashboards?scenarioID=1", "GET", nil, 200, msgDashboardsjson)
// Read newDashboard's ID from the response
newDashbaordID, err := common.GetResponseID(resp)
assert.NoError(t, err)
// TODO add testing for other return codes
// Get the newDashboard
code, resp, err = common.NewTestEndpoint(router, token,
fmt.Sprintf("/api/dashboards/%v", newDashbaordID), "GET", nil)
assert.NoError(t, err)
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
// Compare GET's response with the newDashboard
err = common.CompareResponse(resp, common.KeyModels{"dashboard": newDashboard})
assert.NoError(t, err)
// try to POST a malformed dashboard
// Required fields are missing
malformedNewDashboard := DashboardRequest{
Name: "ThisIsAMalformedDashboard",
}
// this should NOT work and return a unprocessable entity 442 status code
code, resp, err = common.NewTestEndpoint(router, token,
"/api/dashboards", "POST", common.KeyModels{"dashboard": malformedNewDashboard})
assert.NoError(t, err)
assert.Equalf(t, 422, code, "Response body: \n%v\n", resp)
}
func TestUpdateDashboard(t *testing.T) {
common.DropTables(db)
common.MigrateModels(db)
common.DummyAddOnlyUserTableWithAdminAndUsersDB(db)
// authenticate as normal user
token, err := common.NewAuthenticateForTest(router,
"/api/authenticate", "POST", common.UserACredentials)
assert.NoError(t, err)
scenarioID := addScenario(token)
// test POST dashboards/ $newDashboard
newDashboard := DashboardRequest{
Name: common.DashboardA.Name,
Grid: common.DashboardA.Grid,
ScenarioID: scenarioID,
}
code, resp, err := common.NewTestEndpoint(router, token,
"/api/dashboards", "POST", common.KeyModels{"dashboard": newDashboard})
assert.NoError(t, err)
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
// Read newDashboard's ID from the response
newDashbaordID, err := common.GetResponseID(resp)
assert.NoError(t, err)
updatedDashboard := DashboardRequest{
Name: common.DashboardB.Name,
Grid: common.DashboardB.Grid,
}
code, resp, err = common.NewTestEndpoint(router, token,
fmt.Sprintf("/api/dashboards/%v", newDashbaordID), "PUT", common.KeyModels{"dashboard": updatedDashboard})
assert.NoError(t, err)
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
// Compare PUT's response with the updatedDashboard
err = common.CompareResponse(resp, common.KeyModels{"dashboard": updatedDashboard})
assert.NoError(t, err)
// Get the updatedDashboard
code, resp, err = common.NewTestEndpoint(router, token,
fmt.Sprintf("/api/dashboards/%v", newDashbaordID), "GET", nil)
assert.NoError(t, err)
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
// Compare GET's response with the updatedDashboard
err = common.CompareResponse(resp, common.KeyModels{"dashboard": updatedDashboard})
assert.NoError(t, err)
// try to update a dashboard that does not exist (should return not found 404 status code)
code, resp, err = common.NewTestEndpoint(router, token,
fmt.Sprintf("/api/dashboards/%v", newDashbaordID+1), "PUT", common.KeyModels{"dashboard": updatedDashboard})
assert.NoError(t, err)
assert.Equalf(t, 404, code, "Response body: \n%v\n", resp)
}
func TestDeleteDashboard(t *testing.T) {
common.DropTables(db)
common.MigrateModels(db)
common.DummyAddOnlyUserTableWithAdminAndUsersDB(db)
// authenticate as normal user
token, err := common.NewAuthenticateForTest(router,
"/api/authenticate", "POST", common.UserACredentials)
assert.NoError(t, err)
scenarioID := addScenario(token)
fmt.Println(scenarioID)
// test POST dashboards/ $newDashboard
newDashboard := DashboardRequest{
Name: common.DashboardA.Name,
Grid: common.DashboardA.Grid,
ScenarioID: scenarioID,
}
code, resp, err := common.NewTestEndpoint(router, token,
"/api/dashboards", "POST", common.KeyModels{"dashboard": newDashboard})
assert.NoError(t, err)
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
// Read newDashboard's ID from the response
newDashbaordID, err := common.GetResponseID(resp)
assert.NoError(t, err)
// Count the number of all the dashboards returned for scenario
initialNumber, err := common.LengthOfResponse(router, token,
fmt.Sprintf("/api/dashboards?scenarioID=%v", scenarioID), "GET", nil)
assert.NoError(t, err)
// Delete the added newDashboard
code, resp, err = common.NewTestEndpoint(router, token,
fmt.Sprintf("/api/dashboards/%v", newDashbaordID), "DELETE", nil)
assert.NoError(t, err)
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
// Compare DELETE's response with the newDashboard
err = common.CompareResponse(resp, common.KeyModels{"dashboard": newDashboard})
assert.NoError(t, err)
// Again count the number of all the dashboards returned for scenario
finalNumber, err := common.LengthOfResponse(router, token,
fmt.Sprintf("/api/dashboards?scenarioID=%v", scenarioID), "GET", nil)
assert.NoError(t, err)
assert.Equal(t, finalNumber, initialNumber-1)
}
func TestGetAllDashboardsOfScenario(t *testing.T) {
common.DropTables(db)
common.MigrateModels(db)
common.DummyAddOnlyUserTableWithAdminAndUsersDB(db)
// authenticate as normal user
token, err := common.NewAuthenticateForTest(router,
"/api/authenticate", "POST", common.UserACredentials)
assert.NoError(t, err)
scenarioID := addScenario(token)
fmt.Println(scenarioID)
// Count the number of all the dashboards returned for scenario
initialNumber, err := common.LengthOfResponse(router, token,
fmt.Sprintf("/api/dashboards?scenarioID=%v", scenarioID), "GET", nil)
assert.NoError(t, err)
// test POST dashboards/ $newDashboard
newDashboardA := DashboardRequest{
Name: common.DashboardA.Name,
Grid: common.DashboardA.Grid,
ScenarioID: scenarioID,
}
code, resp, err := common.NewTestEndpoint(router, token,
"/api/dashboards", "POST", common.KeyModels{"dashboard": newDashboardA})
assert.NoError(t, err)
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
// POST a second dashboard for the same scenario
newDashboardB := DashboardRequest{
Name: common.DashboardB.Name,
Grid: common.DashboardB.Grid,
ScenarioID: scenarioID,
}
code, resp, err = common.NewTestEndpoint(router, token,
"/api/dashboards", "POST", common.KeyModels{"dashboard": newDashboardB})
assert.NoError(t, err)
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
// Count again the number of all the dashboards returned for scenario
finalNumber, err := common.LengthOfResponse(router, token,
fmt.Sprintf("/api/dashboards?scenarioID=%v", scenarioID), "GET", nil)
assert.NoError(t, err)
assert.Equal(t, initialNumber+2, finalNumber)
}

View file

@ -0,0 +1,69 @@
package dashboard
import (
"gopkg.in/go-playground/validator.v9"
)
var validate *validator.Validate
type validNewDashboard struct {
Name string `form:"Name" validate:"required"`
Grid int `form:"Grid" validate:"required"`
ScenarioID uint `form:"ScenarioID" validate:"required"`
}
type validUpdatedDashboard struct {
Name string `form:"Name" validate:"omitempty"`
Grid int `form:"Grid" validate:"omitempty"`
ScenarioID uint `form:"ScenarioID" validate:"omitempty"`
}
type addDashboardRequest struct {
validNewDashboard `json:"dashboard"`
}
type updateDashboardRequest struct {
validUpdatedDashboard `json:"dashboard"`
}
func (r *addDashboardRequest) validate() error {
validate = validator.New()
errs := validate.Struct(r)
return errs
}
func (r *validUpdatedDashboard) validate() error {
validate = validator.New()
errs := validate.Struct(r)
return errs
}
func (r *addDashboardRequest) createDashboard() Dashboard {
var s Dashboard
s.Name = r.Name
s.Grid = r.Grid
s.ScenarioID = r.ScenarioID
return s
}
func (r *updateDashboardRequest) updatedDashboard(oldDashboard Dashboard) (Dashboard, error) {
// Use the old Dashboard as a basis for the updated Dashboard `s`
s := oldDashboard
if r.Name != "" {
s.Name = r.Name
}
if r.Grid != 0 {
s.Grid = r.Grid
}
if r.ScenarioID != 0 {
// TODO do we allow this case?
//s.ScenarioID = r.ScenarioID
}
return s, nil
}