mirror of
https://git.rwth-aachen.de/acs/public/villas/web-backend-go/
synced 2025-03-30 00:00:12 +01:00
- 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:
parent
e0ae839e96
commit
dab027eef6
9 changed files with 434 additions and 160 deletions
|
@ -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"`
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
69
routes/dashboard/dashboard_validators.go
Normal file
69
routes/dashboard/dashboard_validators.go
Normal 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
|
||||
}
|
Loading…
Add table
Reference in a new issue