111 lines
3.8 KiB
Go
111 lines
3.8 KiB
Go
package handler
|
|
|
|
import (
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/DATA-DOG/go-sqlmock"
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
func TestPhaseOneAndLegacyRoutesAreRegistered(t *testing.T) {
|
|
gin.SetMode(gin.TestMode)
|
|
router := gin.New()
|
|
NewHandler().RegisterRoutes(router)
|
|
|
|
registered := make(map[string]bool)
|
|
for _, route := range router.Routes() {
|
|
registered[route.Method+" "+route.Path] = true
|
|
}
|
|
want := []string{
|
|
"GET /api/auth/organizations", "POST /api/auth/organization-context",
|
|
"GET /api/material-categories", "POST /api/material-categories", "PUT /api/material-categories/:id",
|
|
"GET /api/units", "POST /api/units", "PUT /api/units/:id",
|
|
"GET /api/code-rules", "POST /api/code-rules", "PUT /api/code-rules/:id",
|
|
"GET /api/code-rules/next",
|
|
"GET /api/organizations", "GET /api/roles",
|
|
"PUT /api/roles/:id", "GET /api/permissions",
|
|
"GET /api/partners", "POST /api/partners", "PUT /api/partners/:id",
|
|
"GET /api/warehouses", "POST /api/warehouses/:id/locations",
|
|
"POST /api/materials/:id/obsolete", "POST /api/materials/:id/restore",
|
|
"PUT /api/stock/:materialId/warning", "GET /api/stock/:materialId/details",
|
|
"POST /api/applications", "GET /api/logs",
|
|
}
|
|
for _, route := range want {
|
|
if !registered[route] {
|
|
t.Errorf("route not registered: %s", route)
|
|
}
|
|
}
|
|
if registered["DELETE /api/materials/:id"] {
|
|
t.Error("hard-delete material route must not be exposed")
|
|
}
|
|
}
|
|
|
|
func TestOrganizationBusinessRoutesRequireHeaderBeforeHandler(t *testing.T) {
|
|
gin.SetMode(gin.TestMode)
|
|
router := gin.New()
|
|
NewHandler().RegisterRoutes(router)
|
|
for _, route := range router.Routes() {
|
|
path := route.Path
|
|
if strings.HasPrefix(path, "/api/auth/") || strings.HasPrefix(path, "/api/users") || strings.HasPrefix(path, "/api/organizations") || strings.HasPrefix(path, "/api/roles") || strings.HasPrefix(path, "/api/permissions") || path == "/api/health" || strings.HasPrefix(path, "/api/upload") {
|
|
continue
|
|
}
|
|
t.Run(route.Method+" "+path, func(t *testing.T) {
|
|
mock := contextMock(t)
|
|
expectContextPrincipal(mock, "warehouse_admin")
|
|
for _, param := range []string{":id", ":materialId", ":locationId"} {
|
|
path = strings.ReplaceAll(path, param, "1")
|
|
}
|
|
req := httptest.NewRequest(route.Method, path, nil)
|
|
req.Header.Set("Authorization", "Bearer "+contextToken(t))
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
if w.Code != 400 || !strings.Contains(w.Body.String(), "X-Organization-ID") {
|
|
t.Fatalf("status=%d body=%s", w.Code, w.Body.String())
|
|
}
|
|
if err := mock.ExpectationsWereMet(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestOrganizationMasterDataReadAndWritePermissions(t *testing.T) {
|
|
for _, tc := range []struct{ path, query string }{
|
|
{"/api/material-categories", "SELECT id, organization_id, code, name"},
|
|
{"/api/units", "SELECT id, organization_id, code, name"},
|
|
{"/api/code-rules", "SELECT cr.id"},
|
|
} {
|
|
for _, method := range []string{"GET", "POST", "PUT"} {
|
|
t.Run(method+tc.path, func(t *testing.T) {
|
|
mock := contextMock(t)
|
|
expectContextPrincipal(mock, "warehouse_admin")
|
|
mock.ExpectQuery("SELECT EXISTS").WithArgs(int64(2), int64(7), int64(7)).WillReturnRows(sqlmock.NewRows([]string{"allowed"}).AddRow(true))
|
|
want := 403
|
|
if method == "GET" {
|
|
want = 200
|
|
mock.ExpectQuery(tc.query).WithArgs(int64(2)).WillReturnRows(sqlmock.NewRows([]string{"id"}))
|
|
}
|
|
path := tc.path
|
|
if method == "PUT" {
|
|
path += "/1"
|
|
}
|
|
router := gin.New()
|
|
NewHandler().RegisterRoutes(router)
|
|
req := httptest.NewRequest(method, path, nil)
|
|
req.Header.Set("Authorization", "Bearer "+contextToken(t))
|
|
req.Header.Set("X-Organization-ID", "2")
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
if w.Code != want {
|
|
t.Fatalf("status=%d body=%s", w.Code, w.Body.String())
|
|
}
|
|
if err := mock.ExpectationsWereMet(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
}
|