mirror of
https://git.rwth-aachen.de/acs/public/villas/web-backend-go/
synced 2025-03-30 00:00:12 +01:00
- Modify scenario testing
- Add scenario validators - Clean up responses and serializes with respect to scenario - Fix error handling and responses of scenario endpoints
This commit is contained in:
parent
46e84fc758
commit
2772bde5ee
8 changed files with 634 additions and 191 deletions
|
@ -5,11 +5,10 @@ import "github.com/jinzhu/gorm/dialects/postgres"
|
|||
type KeyModels map[string]interface{}
|
||||
|
||||
type Request struct {
|
||||
Username string `json:"username,omitempty"`
|
||||
Password string `json:"password,omitempty"`
|
||||
Mail string `json:"mail,omitempty"`
|
||||
Role string `json:"role,omitempty"`
|
||||
|
||||
Username string `json:"username,omitempty"`
|
||||
Password string `json:"password,omitempty"`
|
||||
Mail string `json:"mail,omitempty"`
|
||||
Role string `json:"role,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Running bool `json:"running,omitempty"`
|
||||
StartParameters postgres.Jsonb `json:"startParameters,omitempty"`
|
||||
|
|
|
@ -2,13 +2,6 @@ package common
|
|||
|
||||
import "github.com/jinzhu/gorm/dialects/postgres"
|
||||
|
||||
type ScenarioResponse struct {
|
||||
Name string `json:"name"`
|
||||
ID uint `json:"id"`
|
||||
Running bool `json:"running"`
|
||||
StartParameters postgres.Jsonb `json:"startParameters"`
|
||||
}
|
||||
|
||||
type SimulationModelResponse struct {
|
||||
ID uint `json:"id"`
|
||||
Name string `json:"name"`
|
||||
|
@ -80,14 +73,6 @@ type ResponseMsg struct {
|
|||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
type ResponseMsgScenarios struct {
|
||||
Scenarios []ScenarioResponse `json:"scenarios"`
|
||||
}
|
||||
|
||||
type ResponseMsgScenario struct {
|
||||
Scenario ScenarioResponse `json:"scenario"`
|
||||
}
|
||||
|
||||
type ResponseMsgSimulationModels struct {
|
||||
SimulationModels []SimulationModelResponse `json:"models"`
|
||||
}
|
||||
|
|
|
@ -4,37 +4,6 @@ import (
|
|||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// Scenario/s Serializers
|
||||
|
||||
type ScenariosSerializer struct {
|
||||
Ctx *gin.Context
|
||||
Scenarios []Scenario
|
||||
}
|
||||
|
||||
func (self *ScenariosSerializer) Response() []ScenarioResponse {
|
||||
response := []ScenarioResponse{}
|
||||
for _, so := range self.Scenarios {
|
||||
serializer := ScenarioSerializer{self.Ctx, so}
|
||||
response = append(response, serializer.Response())
|
||||
}
|
||||
return response
|
||||
}
|
||||
|
||||
type ScenarioSerializer struct {
|
||||
Ctx *gin.Context
|
||||
Scenario
|
||||
}
|
||||
|
||||
func (self *ScenarioSerializer) Response() ScenarioResponse {
|
||||
response := ScenarioResponse{
|
||||
Name: self.Name,
|
||||
ID: self.ID,
|
||||
Running: self.Running,
|
||||
StartParameters: self.StartParameters,
|
||||
}
|
||||
return response
|
||||
}
|
||||
|
||||
// Model/s Serializers
|
||||
|
||||
type SimulationModelsSerializer struct {
|
||||
|
|
|
@ -154,13 +154,7 @@ var startParametersB = json.RawMessage(`{"parameter1" : "testValue1B", "paramete
|
|||
var startParametersC = json.RawMessage(`{"parameter1" : "testValue1C", "parameter2" : "testValue2C", "parameter3" : 44}`)
|
||||
|
||||
var ScenarioA = Scenario{Name: "Scenario_A", Running: true, StartParameters: postgres.Jsonb{startParametersA}}
|
||||
var ScenarioA_response = ScenarioResponse{ID: 1, Name: ScenarioA.Name, Running: ScenarioA.Running, StartParameters: ScenarioA.StartParameters}
|
||||
var ScenarioB = Scenario{Name: "Scenario_B", Running: false, StartParameters: postgres.Jsonb{startParametersB}}
|
||||
var ScenarioB_response = ScenarioResponse{ID: 2, Name: ScenarioB.Name, Running: ScenarioB.Running, StartParameters: ScenarioB.StartParameters}
|
||||
var ScenarioC = Scenario{Name: "Scenario_C", Running: false, StartParameters: postgres.Jsonb{startParametersC}}
|
||||
var ScenarioC_response = ScenarioResponse{ID: 3, Name: ScenarioC.Name, Running: ScenarioC.Running, StartParameters: ScenarioC.StartParameters}
|
||||
var ScenarioCUpdated = Scenario{Name: "Scenario_Cupdated", Running: true, StartParameters: postgres.Jsonb{startParametersC}}
|
||||
var ScenarioCUpdated_response = ScenarioResponse{ID: 3, Name: ScenarioCUpdated.Name, Running: ScenarioCUpdated.Running, StartParameters: ScenarioCUpdated.StartParameters}
|
||||
|
||||
// Simulation Models
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package scenario
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
@ -64,9 +65,8 @@ func getScenarios(c *gin.Context) {
|
|||
}
|
||||
}
|
||||
// TODO return list of simulationModelIDs, dashboardIDs and userIDs per scenario
|
||||
serializer := common.ScenariosSerializer{c, scenarios}
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"scenarios": serializer.Response(),
|
||||
"scenarios": scenarios,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -98,35 +98,44 @@ func addScenario(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
var newScenarioData common.ResponseMsgScenario
|
||||
err = c.BindJSON(&newScenarioData)
|
||||
if err != nil {
|
||||
errormsg := "Bad request. Error binding form data to JSON: " + err.Error()
|
||||
var req addScenarioRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": errormsg,
|
||||
"success": false,
|
||||
"message": fmt.Sprintf("%v", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
var newScenario Scenario
|
||||
newScenario.ID = newScenarioData.Scenario.ID
|
||||
newScenario.StartParameters = newScenarioData.Scenario.StartParameters
|
||||
newScenario.Running = newScenarioData.Scenario.Running
|
||||
newScenario.Name = newScenarioData.Scenario.Name
|
||||
// Validate the request
|
||||
if err = req.validate(); err != nil {
|
||||
c.JSON(http.StatusUnprocessableEntity, gin.H{
|
||||
"success": false,
|
||||
"message": fmt.Sprintf("%v", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// save new scenario to DB
|
||||
// Create the new scenario from the request
|
||||
newScenario := req.createScenario()
|
||||
|
||||
// Save the new scenario in the DB
|
||||
err = newScenario.save()
|
||||
if common.ProvideErrorResponse(c, err) {
|
||||
if err != nil {
|
||||
common.ProvideErrorResponse(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
// add user to new scenario
|
||||
err = newScenario.addUser(&(u.User))
|
||||
if common.ProvideErrorResponse(c, err) == false {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": "OK.",
|
||||
})
|
||||
if err != nil {
|
||||
common.ProvideErrorResponse(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"scenario": newScenario.Scenario,
|
||||
})
|
||||
}
|
||||
|
||||
// updateScenario godoc
|
||||
|
@ -145,27 +154,50 @@ func addScenario(c *gin.Context) {
|
|||
// @Router /scenarios/{scenarioID} [put]
|
||||
func updateScenario(c *gin.Context) {
|
||||
|
||||
ok, so := CheckPermissions(c, common.Update, "path", -1)
|
||||
ok, oldScenario := CheckPermissions(c, common.Update, "path", -1)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
var modifiedScenarioData common.ResponseMsgScenario
|
||||
err := c.BindJSON(&modifiedScenarioData)
|
||||
if err != nil {
|
||||
errormsg := "Bad request. Error binding form data to JSON: " + err.Error()
|
||||
// Bind the (context) with the updateScenarioRequest struct
|
||||
var req updateScenarioRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": errormsg,
|
||||
"success": false,
|
||||
"message": fmt.Sprintf("%v", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
err = so.update(modifiedScenarioData.Scenario)
|
||||
if common.ProvideErrorResponse(c, err) == false {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": "OK.",
|
||||
// Validate the request based on struct updateScenarioRequest json tags
|
||||
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
|
||||
updatedScenario, err := req.updatedScenario(oldScenario)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"success": false,
|
||||
"message": fmt.Sprintf("%v", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// Finally update the scenario
|
||||
err = oldScenario.update(updatedScenario)
|
||||
if err != nil {
|
||||
common.ProvideErrorResponse(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"scenario": updatedScenario.Scenario,
|
||||
})
|
||||
}
|
||||
|
||||
// getScenario godoc
|
||||
|
@ -188,9 +220,8 @@ func getScenario(c *gin.Context) {
|
|||
}
|
||||
|
||||
// TODO return list of simulationModelIDs, dashboardIDs and userIDs per scenario
|
||||
serializer := common.ScenarioSerializer{c, so.Scenario}
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"scenario": serializer.Response(),
|
||||
"scenario": so.Scenario,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -214,11 +245,14 @@ func deleteScenario(c *gin.Context) {
|
|||
}
|
||||
|
||||
err := so.delete()
|
||||
if common.ProvideErrorResponse(c, err) == false {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": "OK.",
|
||||
})
|
||||
if err != nil {
|
||||
common.ProvideErrorResponse(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"scenario": so.Scenario,
|
||||
})
|
||||
}
|
||||
|
||||
// getUsersOfScenario godoc
|
||||
|
@ -283,7 +317,7 @@ func addUserToScenario(c *gin.Context) {
|
|||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": "OK.",
|
||||
"user": u.User,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -309,12 +343,18 @@ func deleteUserFromScenario(c *gin.Context) {
|
|||
|
||||
username := c.Request.URL.Query().Get("username")
|
||||
|
||||
err := so.deleteUser(username)
|
||||
var u user.User
|
||||
err := u.ByUsername(username)
|
||||
if common.ProvideErrorResponse(c, err) {
|
||||
return
|
||||
}
|
||||
|
||||
err = so.deleteUser(username)
|
||||
if common.ProvideErrorResponse(c, err) {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": "OK.",
|
||||
"user": u.User,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -2,9 +2,9 @@ package scenario
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"
|
||||
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/user"
|
||||
"github.com/jinzhu/gorm"
|
||||
)
|
||||
|
||||
type Scenario struct {
|
||||
|
@ -15,7 +15,7 @@ func (s *Scenario) ByID(id uint) error {
|
|||
db := common.GetDB()
|
||||
err := db.Find(s, id).Error
|
||||
if err != nil {
|
||||
return fmt.Errorf("scenario with id=%v does not exist", id)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -33,9 +33,15 @@ func (s *Scenario) save() error {
|
|||
return err
|
||||
}
|
||||
|
||||
func (s *Scenario) update(modifiedScenario common.ScenarioResponse) error {
|
||||
func (s *Scenario) update(updatedScenario Scenario) error {
|
||||
|
||||
// TODO: if the field is empty member shouldn't be updated
|
||||
s.Name = updatedScenario.Name
|
||||
s.Running = updatedScenario.Running
|
||||
s.StartParameters = updatedScenario.StartParameters
|
||||
|
||||
db := common.GetDB()
|
||||
err := db.Model(s).Update(modifiedScenario).Error
|
||||
err := db.Model(s).Update(updatedScenario).Error
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -69,7 +75,17 @@ func (s *Scenario) deleteUser(username string) error {
|
|||
return err
|
||||
}
|
||||
} else {
|
||||
return fmt.Errorf("cannot delete last user from scenario without deleting scenario itself, doing nothing")
|
||||
// There is only one associated user
|
||||
var remainingUser user.User
|
||||
err = db.Model(s).Related(&remainingUser, "Users").Error
|
||||
if remainingUser.Username == username {
|
||||
// if the remaining user is the one to be deleted
|
||||
return fmt.Errorf("cannot delete last user from scenario without deleting scenario itself, doing nothing")
|
||||
} else {
|
||||
// the remaining user is NOT the one to be deleted
|
||||
// that means the user to be deleted is not associated with the scenario
|
||||
return gorm.ErrRecordNotFound
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -1,115 +1,490 @@
|
|||
package scenario
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"
|
||||
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/user"
|
||||
)
|
||||
|
||||
// Test /scenarios endpoints
|
||||
func TestScenarioEndpoints(t *testing.T) {
|
||||
var router *gin.Engine
|
||||
var db *gorm.DB
|
||||
|
||||
var myScenarios = []common.ScenarioResponse{common.ScenarioA_response, common.ScenarioB_response}
|
||||
var msgScenarios = common.ResponseMsgScenarios{Scenarios: myScenarios}
|
||||
var msgScenario = common.ResponseMsgScenario{Scenario: common.ScenarioC_response}
|
||||
var msgScenarioUpdated = common.ResponseMsgScenario{Scenario: common.ScenarioCUpdated_response}
|
||||
func TestMain(m *testing.M) {
|
||||
|
||||
db := common.DummyInitDB()
|
||||
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))
|
||||
|
||||
RegisterScenarioEndpoints(api.Group("/scenarios"))
|
||||
|
||||
credjson, _ := json.Marshal(common.CredUser)
|
||||
|
||||
token := common.AuthenticateForTest(t, router, "/api/authenticate",
|
||||
"POST", credjson, 200)
|
||||
|
||||
// test GET scenarios/
|
||||
err := common.NewTestEndpoint(router, token, "/api/scenarios",
|
||||
"GET", nil, 200, msgScenarios)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// test POST scenarios/
|
||||
err = common.NewTestEndpoint(router, token, "/api/scenarios",
|
||||
"POST", msgScenario, 200, common.MsgOK)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// test GET scenarios/:ScenarioID
|
||||
err = common.NewTestEndpoint(router, token, "/api/scenarios/3",
|
||||
"GET", nil, 200, msgScenario)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// test PUT scenarios/:ScenarioID
|
||||
err = common.NewTestEndpoint(router, token, "/api/scenarios/3",
|
||||
"PUT", msgScenarioUpdated, 200, common.MsgOK)
|
||||
assert.NoError(t, err)
|
||||
err = common.NewTestEndpoint(router, token, "/api/scenarios/3",
|
||||
"GET", nil, 200, msgScenarioUpdated)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// test DELETE scenarios/:ScenarioID
|
||||
err = common.NewTestEndpoint(router, token, "/api/scenarios/3",
|
||||
"DELETE", nil, 200, common.MsgOK)
|
||||
assert.NoError(t, err)
|
||||
err = common.NewTestEndpoint(router, token, "/api/scenarios", "GET",
|
||||
nil, 200, msgScenarios)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// test GET scenarios/:ScenarioID/users
|
||||
err = common.NewTestEndpoint(router, token,
|
||||
"/api/scenarios/1/users", "GET", nil,
|
||||
200, common.KeyModels{"users": []common.User{common.UserA, common.UserB}})
|
||||
assert.NoError(t, err)
|
||||
|
||||
// test DELETE scenarios/:ScenarioID/user
|
||||
err = common.NewTestEndpoint(router, token,
|
||||
"/api/scenarios/1/user?username=User_B", "DELETE", nil, 200, common.MsgOK)
|
||||
assert.NoError(t, err)
|
||||
err = common.NewTestEndpoint(router, token,
|
||||
"/api/scenarios/1/users", "GET", nil,
|
||||
200, common.KeyModels{"users": []common.User{common.UserA}})
|
||||
assert.NoError(t, err)
|
||||
|
||||
// test PUT scenarios/:ScenarioID/user
|
||||
err = common.NewTestEndpoint(router, token,
|
||||
"/api/scenarios/1/user?username=User_B", "PUT", nil, 200, common.MsgOK)
|
||||
assert.NoError(t, err)
|
||||
err = common.NewTestEndpoint(router, token,
|
||||
"/api/scenarios/1/users", "GET", nil,
|
||||
200, common.KeyModels{"users": []common.User{common.UserA, common.UserB}})
|
||||
assert.NoError(t, err)
|
||||
|
||||
// test DELETE scenarios/:ScenarioID/user for logged in user User_A
|
||||
err = common.NewTestEndpoint(router, token,
|
||||
"/api/scenarios/1/user?username=User_A", "DELETE", nil, 200, common.MsgOK)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// test if deletion of user from scenario has worked
|
||||
w2 := httptest.NewRecorder()
|
||||
req2, _ := http.NewRequest("GET", "/api/scenarios/1/users", nil)
|
||||
req2.Header.Add("Authorization", "Bearer "+token)
|
||||
router.ServeHTTP(w2, req2)
|
||||
|
||||
assert.Equal(t, 422, w2.Code)
|
||||
fmt.Println(w2.Body.String())
|
||||
assert.Equal(t, "\"Access denied (for scenario ID).\"", w2.Body.String())
|
||||
|
||||
// TODO add tests for other return codes
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func TestAddScenario(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)
|
||||
|
||||
// test POST scenarios/ $newScenario
|
||||
newScenario := common.Request{
|
||||
Name: common.ScenarioA.Name,
|
||||
Running: common.ScenarioA.Running,
|
||||
StartParameters: common.ScenarioA.StartParameters,
|
||||
}
|
||||
code, resp, err := common.NewTestEndpoint(router, token,
|
||||
"/api/scenarios", "POST", common.KeyModels{"scenario": newScenario})
|
||||
assert.NoError(t, err)
|
||||
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// Compare POST's response with the newScenario
|
||||
err = common.CompareResponse(resp, common.KeyModels{"scenario": newScenario})
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Read newScenario's ID from the response
|
||||
newScenarioID, err := common.GetResponseID(resp)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Get the newScenario
|
||||
code, resp, err = common.NewTestEndpoint(router, token,
|
||||
fmt.Sprintf("/api/scenarios/%v", newScenarioID), "GET", nil)
|
||||
assert.NoError(t, err)
|
||||
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// Compare GET's response with the newScenario
|
||||
err = common.CompareResponse(resp, common.KeyModels{"scenario": newScenario})
|
||||
assert.NoError(t, err)
|
||||
|
||||
// try to POST a malformed scenario
|
||||
// Required field StartParameters is missing
|
||||
malformedNewScenario := common.Request{
|
||||
Username: "thisisnotneeded",
|
||||
}
|
||||
// this should NOT work and return a unprocessable entity 442 status code
|
||||
code, resp, err = common.NewTestEndpoint(router, token,
|
||||
"/api/scenarios", "POST", common.KeyModels{"scenario": malformedNewScenario})
|
||||
assert.NoError(t, err)
|
||||
assert.Equalf(t, 422, code, "Response body: \n%v\n", resp)
|
||||
}
|
||||
|
||||
func TestUpdateScenario(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)
|
||||
|
||||
// test POST scenarios/ $newScenario
|
||||
newScenario := common.Request{
|
||||
Name: common.ScenarioA.Name,
|
||||
Running: common.ScenarioA.Running,
|
||||
StartParameters: common.ScenarioA.StartParameters,
|
||||
}
|
||||
code, resp, err := common.NewTestEndpoint(router, token,
|
||||
"/api/scenarios", "POST", common.KeyModels{"scenario": newScenario})
|
||||
assert.NoError(t, err)
|
||||
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// Compare POST's response with the newScenario
|
||||
err = common.CompareResponse(resp, common.KeyModels{"scenario": newScenario})
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Read newScenario's ID from the response
|
||||
newScenarioID, err := common.GetResponseID(resp)
|
||||
assert.NoError(t, err)
|
||||
|
||||
updatedScenario := common.Request{
|
||||
Name: "Updated name",
|
||||
Running: !common.ScenarioA.Running,
|
||||
StartParameters: common.ScenarioA.StartParameters,
|
||||
}
|
||||
|
||||
code, resp, err = common.NewTestEndpoint(router, token,
|
||||
fmt.Sprintf("/api/scenarios/%v", newScenarioID), "PUT", common.KeyModels{"scenario": updatedScenario})
|
||||
assert.NoError(t, err)
|
||||
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// Compare PUT's response with the updatedScenario
|
||||
err = common.CompareResponse(resp, common.KeyModels{"scenario": updatedScenario})
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Get the updatedScenario
|
||||
code, resp, err = common.NewTestEndpoint(router, token,
|
||||
fmt.Sprintf("/api/scenarios/%v", newScenarioID), "GET", nil)
|
||||
assert.NoError(t, err)
|
||||
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// Compare GET's response with the newScenario
|
||||
err = common.CompareResponse(resp, common.KeyModels{"scenario": updatedScenario})
|
||||
assert.NoError(t, err)
|
||||
|
||||
// try to update a scenario that does not exist (should return not found 404 status code)
|
||||
code, resp, err = common.NewTestEndpoint(router, token,
|
||||
fmt.Sprintf("/api/scenarios/%v", newScenarioID+1), "PUT", common.KeyModels{"scenario": updatedScenario})
|
||||
assert.NoError(t, err)
|
||||
assert.Equalf(t, 404, code, "Response body: \n%v\n", resp)
|
||||
|
||||
}
|
||||
|
||||
func TestGetAllScenariosAsAdmin(t *testing.T) {
|
||||
|
||||
common.DropTables(db)
|
||||
common.MigrateModels(db)
|
||||
common.DummyAddOnlyUserTableWithAdminAndUsersDB(db)
|
||||
|
||||
// authenticate as admin
|
||||
token, err := common.NewAuthenticateForTest(router,
|
||||
"/api/authenticate", "POST", common.AdminCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// get the length of the GET all scenarios response for admin
|
||||
initialNumber, err := common.LengthOfResponse(router, token,
|
||||
"/api/scenarios", "GET", nil)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// authenticate as normal userB
|
||||
token, err = common.NewAuthenticateForTest(router,
|
||||
"/api/authenticate", "POST", common.UserBCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// test POST scenarios/ $newScenarioB
|
||||
newScenarioB := common.Request{
|
||||
Name: common.ScenarioB.Name,
|
||||
Running: common.ScenarioB.Running,
|
||||
StartParameters: common.ScenarioB.StartParameters,
|
||||
}
|
||||
code, resp, err := common.NewTestEndpoint(router, token,
|
||||
"/api/scenarios", "POST", common.KeyModels{"scenario": newScenarioB})
|
||||
assert.NoError(t, err)
|
||||
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as normal userA
|
||||
token, err = common.NewAuthenticateForTest(router,
|
||||
"/api/authenticate", "POST", common.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// test POST scenarios/ $newScenarioA
|
||||
newScenarioA := common.Request{
|
||||
Name: common.ScenarioA.Name,
|
||||
Running: common.ScenarioA.Running,
|
||||
StartParameters: common.ScenarioA.StartParameters,
|
||||
}
|
||||
code, resp, err = common.NewTestEndpoint(router, token,
|
||||
"/api/scenarios", "POST", common.KeyModels{"scenario": newScenarioA})
|
||||
assert.NoError(t, err)
|
||||
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as admin
|
||||
token, err = common.NewAuthenticateForTest(router,
|
||||
"/api/authenticate", "POST", common.AdminCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// get the length of the GET all scenarios response again
|
||||
finalNumber, err := common.LengthOfResponse(router, token,
|
||||
"/api/scenarios", "GET", nil)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, finalNumber, initialNumber+2)
|
||||
}
|
||||
|
||||
func TestGetAllScenariosAsUser(t *testing.T) {
|
||||
|
||||
common.DropTables(db)
|
||||
common.MigrateModels(db)
|
||||
common.DummyAddOnlyUserTableWithAdminAndUsersDB(db)
|
||||
|
||||
// authenticate as normal userB
|
||||
token, err := common.NewAuthenticateForTest(router,
|
||||
"/api/authenticate", "POST", common.UserBCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// get the length of the GET all scenarios response for userB
|
||||
initialNumber, err := common.LengthOfResponse(router, token,
|
||||
"/api/scenarios", "GET", nil)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// test POST scenarios/ $newScenarioB
|
||||
newScenarioB := common.Request{
|
||||
Name: common.ScenarioB.Name,
|
||||
Running: common.ScenarioB.Running,
|
||||
StartParameters: common.ScenarioB.StartParameters,
|
||||
}
|
||||
|
||||
code, resp, err := common.NewTestEndpoint(router, token,
|
||||
"/api/scenarios", "POST", common.KeyModels{"scenario": newScenarioB})
|
||||
assert.NoError(t, err)
|
||||
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as normal userA
|
||||
token, err = common.NewAuthenticateForTest(router,
|
||||
"/api/authenticate", "POST", common.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// test POST scenarios/ $newScenarioA
|
||||
newScenarioA := common.Request{
|
||||
Name: common.ScenarioA.Name,
|
||||
Running: common.ScenarioA.Running,
|
||||
StartParameters: common.ScenarioA.StartParameters,
|
||||
}
|
||||
code, resp, err = common.NewTestEndpoint(router, token,
|
||||
"/api/scenarios", "POST", common.KeyModels{"scenario": newScenarioA})
|
||||
assert.NoError(t, err)
|
||||
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as normal userB
|
||||
token, err = common.NewAuthenticateForTest(router,
|
||||
"/api/authenticate", "POST", common.UserBCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// get the length of the GET all scenarios response again
|
||||
finalNumber, err := common.LengthOfResponse(router, token,
|
||||
"/api/scenarios", "GET", nil)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, finalNumber, initialNumber+1)
|
||||
}
|
||||
|
||||
func TestDeleteScenario(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)
|
||||
|
||||
// test POST scenarios/ $newScenario
|
||||
newScenario := common.Request{
|
||||
Name: common.ScenarioA.Name,
|
||||
Running: common.ScenarioA.Running,
|
||||
StartParameters: common.ScenarioA.StartParameters,
|
||||
}
|
||||
code, resp, err := common.NewTestEndpoint(router, token,
|
||||
"/api/scenarios", "POST", common.KeyModels{"scenario": newScenario})
|
||||
assert.NoError(t, err)
|
||||
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// Read newScenario's ID from the response
|
||||
newScenarioID, err := common.GetResponseID(resp)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Count the number of all the scenarios returned for userA
|
||||
initialNumber, err := common.LengthOfResponse(router, token,
|
||||
"/api/scenarios", "GET", nil)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Delete the added newScenario
|
||||
code, resp, err = common.NewTestEndpoint(router, token,
|
||||
fmt.Sprintf("/api/scenarios/%v", newScenarioID), "DELETE", nil)
|
||||
assert.NoError(t, err)
|
||||
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// Compare DELETE's response with the newScenario
|
||||
err = common.CompareResponse(resp, common.KeyModels{"scenario": newScenario})
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Again count the number of all the users returned
|
||||
finalNumber, err := common.LengthOfResponse(router, token,
|
||||
"/api/scenarios", "GET", nil)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, finalNumber, initialNumber-1)
|
||||
}
|
||||
|
||||
func TestAddUserToScenario(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)
|
||||
|
||||
// test POST scenarios/ $newScenario
|
||||
newScenario := common.Request{
|
||||
Name: common.ScenarioA.Name,
|
||||
Running: common.ScenarioA.Running,
|
||||
StartParameters: common.ScenarioA.StartParameters,
|
||||
}
|
||||
code, resp, err := common.NewTestEndpoint(router, token,
|
||||
"/api/scenarios", "POST", common.KeyModels{"scenario": newScenario})
|
||||
assert.NoError(t, err)
|
||||
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// Read newScenario's ID from the response
|
||||
newScenarioID, err := common.GetResponseID(resp)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Count the number of all the users returned for newScenario
|
||||
initialNumber, err := common.LengthOfResponse(router, token,
|
||||
fmt.Sprintf("/api/scenarios/%v/users", newScenarioID), "GET", nil)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, initialNumber, 1)
|
||||
|
||||
// add userB to newScenario
|
||||
code, resp, err = common.NewTestEndpoint(router, token,
|
||||
fmt.Sprintf("/api/scenarios/%v/user?username=User_B", newScenarioID), "PUT", nil)
|
||||
assert.NoError(t, err)
|
||||
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// Compare resp to userB
|
||||
err = common.CompareResponse(resp, common.KeyModels{"user": common.UserB})
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Count AGAIN the number of all the users returned for newScenario
|
||||
finalNumber, err := common.LengthOfResponse(router, token,
|
||||
fmt.Sprintf("/api/scenarios/%v/users", newScenarioID), "GET", nil)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, finalNumber, initialNumber+1)
|
||||
|
||||
// try to add a non-existing user to newScenario, should return a not found 404
|
||||
code, resp, err = common.NewTestEndpoint(router, token,
|
||||
fmt.Sprintf("/api/scenarios/%v/user?username=User_C", newScenarioID), "PUT", nil)
|
||||
assert.NoError(t, err)
|
||||
assert.Equalf(t, 404, code, "Response body: \n%v\n", resp)
|
||||
}
|
||||
|
||||
func TestGetAllUsersOfScenario(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)
|
||||
|
||||
// test POST scenarios/ $newScenario
|
||||
newScenario := common.Request{
|
||||
Name: common.ScenarioA.Name,
|
||||
Running: common.ScenarioA.Running,
|
||||
StartParameters: common.ScenarioA.StartParameters,
|
||||
}
|
||||
code, resp, err := common.NewTestEndpoint(router, token,
|
||||
"/api/scenarios", "POST", common.KeyModels{"scenario": newScenario})
|
||||
assert.NoError(t, err)
|
||||
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// Read newScenario's ID from the response
|
||||
newScenarioID, err := common.GetResponseID(resp)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Count the number of all the users returned for newScenario
|
||||
initialNumber, err := common.LengthOfResponse(router, token,
|
||||
fmt.Sprintf("/api/scenarios/%v/users", newScenarioID), "GET", nil)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, initialNumber, 1)
|
||||
|
||||
// add userB to newScenario
|
||||
code, resp, err = common.NewTestEndpoint(router, token,
|
||||
fmt.Sprintf("/api/scenarios/%v/user?username=User_B", newScenarioID), "PUT", nil)
|
||||
assert.NoError(t, err)
|
||||
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// Count AGAIN the number of all the users returned for newScenario
|
||||
finalNumber, err := common.LengthOfResponse(router, token,
|
||||
fmt.Sprintf("/api/scenarios/%v/users", newScenarioID), "GET", nil)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, finalNumber, initialNumber+1)
|
||||
}
|
||||
|
||||
func TestRemoveUserFromScenario(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)
|
||||
|
||||
// test POST scenarios/ $newScenario
|
||||
newScenario := common.Request{
|
||||
Name: common.ScenarioA.Name,
|
||||
Running: common.ScenarioA.Running,
|
||||
StartParameters: common.ScenarioA.StartParameters,
|
||||
}
|
||||
code, resp, err := common.NewTestEndpoint(router, token,
|
||||
"/api/scenarios", "POST", common.KeyModels{"scenario": newScenario})
|
||||
assert.NoError(t, err)
|
||||
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// Read newScenario's ID from the response
|
||||
newScenarioID, err := common.GetResponseID(resp)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// add userB to newScenario
|
||||
code, resp, err = common.NewTestEndpoint(router, token,
|
||||
fmt.Sprintf("/api/scenarios/%v/user?username=User_B", newScenarioID), "PUT", nil)
|
||||
assert.NoError(t, err)
|
||||
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// Count the number of all the users returned for newScenario
|
||||
initialNumber, err := common.LengthOfResponse(router, token,
|
||||
fmt.Sprintf("/api/scenarios/%v/users", newScenarioID), "GET", nil)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 2, initialNumber)
|
||||
|
||||
// remove userB from newScenario
|
||||
code, resp, err = common.NewTestEndpoint(router, token,
|
||||
fmt.Sprintf("/api/scenarios/%v/user?username=User_B", newScenarioID), "DELETE", nil)
|
||||
assert.NoError(t, err)
|
||||
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// Compare DELETE's response with UserB
|
||||
err = common.CompareResponse(resp, common.KeyModels{"user": common.UserB})
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Count AGAIN the number of all the users returned for newScenario
|
||||
finalNumber, err := common.LengthOfResponse(router, token,
|
||||
fmt.Sprintf("/api/scenarios/%v/users", newScenarioID), "GET", nil)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, initialNumber-1, finalNumber)
|
||||
|
||||
// Try to remove userA from new scenario
|
||||
// This should fail since User_A is the last user of newScenario
|
||||
code, resp, err = common.NewTestEndpoint(router, token,
|
||||
fmt.Sprintf("/api/scenarios/%v/user?username=User_A", newScenarioID), "DELETE", nil)
|
||||
assert.NoError(t, err)
|
||||
assert.Equalf(t, 500, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// Try to remove a user that does not exist in DB
|
||||
// This should fail with not found 404 status code
|
||||
code, resp, err = common.NewTestEndpoint(router, token,
|
||||
fmt.Sprintf("/api/scenarios/%v/user?username=User_C", newScenarioID), "DELETE", nil)
|
||||
assert.NoError(t, err)
|
||||
assert.Equalf(t, 404, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// Try to remove an admin user that is not explicitly a user of the scenario
|
||||
// This should fail with not found 404 status code
|
||||
code, resp, err = common.NewTestEndpoint(router, token,
|
||||
fmt.Sprintf("/api/scenarios/%v/user?username=User_0", newScenarioID), "DELETE", nil)
|
||||
assert.NoError(t, err)
|
||||
assert.Equalf(t, 404, code, "Response body: \n%v\n", resp)
|
||||
|
||||
}
|
||||
|
|
65
routes/scenario/scenario_validators.go
Normal file
65
routes/scenario/scenario_validators.go
Normal file
|
@ -0,0 +1,65 @@
|
|||
package scenario
|
||||
|
||||
import (
|
||||
"github.com/jinzhu/gorm/dialects/postgres"
|
||||
"gopkg.in/go-playground/validator.v9"
|
||||
)
|
||||
|
||||
var validate *validator.Validate
|
||||
|
||||
type validNewScenario struct {
|
||||
Name string `form:"Name" validate:"required"`
|
||||
Running bool `form:"Running" validate:"omitempty"`
|
||||
StartParameters postgres.Jsonb `form:"StartParameters" validate:"required"`
|
||||
}
|
||||
|
||||
type validUpdatedScenario struct {
|
||||
Name string `form:"Name" validate:"omitempty"`
|
||||
Running bool `form:"Running" validate:"omitempty"`
|
||||
StartParameters postgres.Jsonb `form:"StartParameters" validate:"omitempty"`
|
||||
}
|
||||
|
||||
type addScenarioRequest struct {
|
||||
validNewScenario `json:"scenario"`
|
||||
}
|
||||
|
||||
type updateScenarioRequest struct {
|
||||
validUpdatedScenario `json:"scenario"`
|
||||
}
|
||||
|
||||
func (r *addScenarioRequest) validate() error {
|
||||
validate = validator.New()
|
||||
errs := validate.Struct(r)
|
||||
return errs
|
||||
}
|
||||
|
||||
func (r *validUpdatedScenario) validate() error {
|
||||
validate = validator.New()
|
||||
errs := validate.Struct(r)
|
||||
return errs
|
||||
}
|
||||
|
||||
func (r *addScenarioRequest) createScenario() Scenario {
|
||||
var s Scenario
|
||||
|
||||
s.Name = r.Name
|
||||
s.Running = r.Running
|
||||
s.StartParameters = r.StartParameters
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
func (r *updateScenarioRequest) updatedScenario(oldScenario Scenario) (Scenario, error) {
|
||||
// Use the old Scenario as a basis for the updated Scenario `s`
|
||||
s := oldScenario
|
||||
|
||||
if r.Name != "" {
|
||||
s.Name = r.Name
|
||||
}
|
||||
|
||||
s.Running = r.Running
|
||||
// TODO check for empty start parameters?
|
||||
s.StartParameters = r.StartParameters
|
||||
|
||||
return s, nil
|
||||
}
|
Loading…
Add table
Reference in a new issue