package apis import ( "clortho/lib/db" "clortho/lib/systems" "encoding/json" "fmt" "github.com/gin-gonic/gin" "github.com/stretchr/testify/assert" "net/http" "net/http/httptest" "strings" "testing" ) func setupSystemsTest(t *testing.T) (*db.User, *db.User) { // Create an admin user adminUser, err := InitUser("admin_test", "password") if err != nil { t.Fatal(err) } adminUser.Admin = true db.Connection.Save(&adminUser) // Create a non-admin user regularUser, err := InitUser("regular_test", "password") if err != nil { t.Fatal(err) } regularUser.Admin = false db.Connection.Save(®ularUser) // Clear existing systems db.Connection.Exec("DELETE FROM systems") return adminUser, regularUser } func TestGetSystems(t *testing.T) { adminUser, regularUser := setupSystemsTest(t) // Create test systems system1, _ := systems.CreateSystem("System 1") system2, _ := systems.CreateSystem("System 2") // Test with admin user t.Run("Admin user can get systems", func(t *testing.T) { router := gin.New() router.Use(MockAuthMiddleware(*adminUser)) group := router.Group("/gui") InitSystemsEndpoints(group) w := httptest.NewRecorder() req, _ := http.NewRequest("GET", "/gui/systems/", nil) router.ServeHTTP(w, req) assert.Equal(t, http.StatusOK, w.Code) var systems []db.System err := json.Unmarshal(w.Body.Bytes(), &systems) assert.NoError(t, err) assert.Len(t, systems, 2) // Verify systems are returned correctly foundSystem1 := false foundSystem2 := false for _, s := range systems { if s.ID == system1.ID { assert.Equal(t, "System 1", s.Name) foundSystem1 = true } if s.ID == system2.ID { assert.Equal(t, "System 2", s.Name) foundSystem2 = true } } assert.True(t, foundSystem1) assert.True(t, foundSystem2) }) // Test with non-admin user t.Run("Non-admin user cannot get systems", func(t *testing.T) { router := gin.New() router.Use(MockAuthMiddleware(*regularUser)) group := router.Group("/gui") InitSystemsEndpoints(group) w := httptest.NewRecorder() req, _ := http.NewRequest("GET", "/gui/systems/", nil) router.ServeHTTP(w, req) assert.Equal(t, http.StatusForbidden, w.Code) assert.Contains(t, w.Body.String(), "admin access required") }) // Test with no session t.Run("Unauthenticated user cannot get systems", func(t *testing.T) { router := gin.New() group := router.Group("/gui") InitSystemsEndpoints(group) w := httptest.NewRecorder() req, _ := http.NewRequest("GET", "/gui/systems/", nil) router.ServeHTTP(w, req) assert.Equal(t, http.StatusUnauthorized, w.Code) assert.Contains(t, w.Body.String(), "unauthorized") }) } func TestGetSystem(t *testing.T) { adminUser, regularUser := setupSystemsTest(t) // Create a test system system, _ := systems.CreateSystem("Test System") // Test with admin user t.Run("Admin user can get a system", func(t *testing.T) { router := gin.New() router.Use(MockAuthMiddleware(*adminUser)) group := router.Group("/gui") InitSystemsEndpoints(group) w := httptest.NewRecorder() req, _ := http.NewRequest("GET", fmt.Sprintf("/gui/systems/%d", system.ID), nil) router.ServeHTTP(w, req) assert.Equal(t, http.StatusOK, w.Code) var returnedSystem db.System err := json.Unmarshal(w.Body.Bytes(), &returnedSystem) assert.NoError(t, err) assert.Equal(t, system.ID, returnedSystem.ID) assert.Equal(t, "Test System", returnedSystem.Name) }) // Test with non-admin user t.Run("Non-admin user cannot get a system", func(t *testing.T) { router := gin.New() router.Use(MockAuthMiddleware(*regularUser)) group := router.Group("/gui") InitSystemsEndpoints(group) w := httptest.NewRecorder() req, _ := http.NewRequest("GET", fmt.Sprintf("/gui/systems/%d", system.ID), nil) router.ServeHTTP(w, req) assert.Equal(t, http.StatusForbidden, w.Code) assert.Contains(t, w.Body.String(), "admin access required") }) // Test with invalid ID t.Run("Invalid ID returns bad request", func(t *testing.T) { router := gin.New() router.Use(MockAuthMiddleware(*adminUser)) group := router.Group("/gui") InitSystemsEndpoints(group) w := httptest.NewRecorder() req, _ := http.NewRequest("GET", "/gui/systems/invalid", nil) router.ServeHTTP(w, req) assert.Equal(t, http.StatusBadRequest, w.Code) assert.Contains(t, w.Body.String(), "Invalid ID format") }) // Test with non-existent ID t.Run("Non-existent ID returns not found", func(t *testing.T) { router := gin.New() router.Use(MockAuthMiddleware(*adminUser)) group := router.Group("/gui") InitSystemsEndpoints(group) w := httptest.NewRecorder() req, _ := http.NewRequest("GET", "/gui/systems/9999", nil) router.ServeHTTP(w, req) assert.Equal(t, http.StatusNotFound, w.Code) assert.Contains(t, w.Body.String(), "System not found") }) } func TestCreateSystem(t *testing.T) { adminUser, regularUser := setupSystemsTest(t) // Test with admin user t.Run("Admin user can create a system", func(t *testing.T) { router := gin.New() router.Use(MockAuthMiddleware(*adminUser)) group := router.Group("/gui") InitSystemsEndpoints(group) reqBody := systemRequest{Name: "New System"} strReqBody, _ := json.Marshal(reqBody) w := httptest.NewRecorder() req, _ := http.NewRequest("POST", "/gui/systems/", strings.NewReader(string(strReqBody))) req.Header.Set("Content-Type", "application/json") router.ServeHTTP(w, req) assert.Equal(t, http.StatusCreated, w.Code) var createdSystem db.System err := json.Unmarshal(w.Body.Bytes(), &createdSystem) assert.NoError(t, err) assert.NotZero(t, createdSystem.ID) assert.Equal(t, "New System", createdSystem.Name) }) // Test with non-admin user t.Run("Non-admin user cannot create a system", func(t *testing.T) { router := gin.New() router.Use(MockAuthMiddleware(*regularUser)) group := router.Group("/gui") InitSystemsEndpoints(group) reqBody := systemRequest{Name: "New System"} strReqBody, _ := json.Marshal(reqBody) w := httptest.NewRecorder() req, _ := http.NewRequest("POST", "/gui/systems/", strings.NewReader(string(strReqBody))) req.Header.Set("Content-Type", "application/json") router.ServeHTTP(w, req) assert.Equal(t, http.StatusForbidden, w.Code) assert.Contains(t, w.Body.String(), "admin access required") }) // Test with invalid request body t.Run("Invalid request body returns bad request", func(t *testing.T) { router := gin.New() router.Use(MockAuthMiddleware(*adminUser)) group := router.Group("/gui") InitSystemsEndpoints(group) reqBody := `{"invalid": "json"` w := httptest.NewRecorder() req, _ := http.NewRequest("POST", "/gui/systems/", strings.NewReader(reqBody)) req.Header.Set("Content-Type", "application/json") router.ServeHTTP(w, req) assert.Equal(t, http.StatusBadRequest, w.Code) }) // Test with missing required field t.Run("Missing required field returns bad request", func(t *testing.T) { router := gin.New() router.Use(MockAuthMiddleware(*adminUser)) group := router.Group("/gui") InitSystemsEndpoints(group) reqBody := `{}` w := httptest.NewRecorder() req, _ := http.NewRequest("POST", "/gui/systems/", strings.NewReader(reqBody)) req.Header.Set("Content-Type", "application/json") router.ServeHTTP(w, req) assert.Equal(t, http.StatusBadRequest, w.Code) }) } func TestUpdateSystem(t *testing.T) { adminUser, regularUser := setupSystemsTest(t) // Create a test system system, _ := systems.CreateSystem("Test System") // Test with admin user t.Run("Admin user can update a system", func(t *testing.T) { router := gin.New() router.Use(MockAuthMiddleware(*adminUser)) group := router.Group("/gui") InitSystemsEndpoints(group) reqBody := systemRequest{Name: "Updated System"} strReqBody, _ := json.Marshal(reqBody) w := httptest.NewRecorder() req, _ := http.NewRequest("PUT", fmt.Sprintf("/gui/systems/%d", system.ID), strings.NewReader(string(strReqBody))) req.Header.Set("Content-Type", "application/json") router.ServeHTTP(w, req) assert.Equal(t, http.StatusOK, w.Code) var updatedSystem db.System err := json.Unmarshal(w.Body.Bytes(), &updatedSystem) assert.NoError(t, err) assert.Equal(t, system.ID, updatedSystem.ID) assert.Equal(t, "Updated System", updatedSystem.Name) }) // Test with non-admin user t.Run("Non-admin user cannot update a system", func(t *testing.T) { router := gin.New() router.Use(MockAuthMiddleware(*regularUser)) group := router.Group("/gui") InitSystemsEndpoints(group) reqBody := systemRequest{Name: "Updated System"} strReqBody, _ := json.Marshal(reqBody) w := httptest.NewRecorder() req, _ := http.NewRequest("PUT", fmt.Sprintf("/gui/systems/%d", system.ID), strings.NewReader(string(strReqBody))) req.Header.Set("Content-Type", "application/json") router.ServeHTTP(w, req) assert.Equal(t, http.StatusForbidden, w.Code) assert.Contains(t, w.Body.String(), "admin access required") }) // Test with invalid ID t.Run("Invalid ID returns bad request", func(t *testing.T) { router := gin.New() router.Use(MockAuthMiddleware(*adminUser)) group := router.Group("/gui") InitSystemsEndpoints(group) reqBody := systemRequest{Name: "Updated System"} strReqBody, _ := json.Marshal(reqBody) w := httptest.NewRecorder() req, _ := http.NewRequest("PUT", "/gui/systems/invalid", strings.NewReader(string(strReqBody))) req.Header.Set("Content-Type", "application/json") router.ServeHTTP(w, req) assert.Equal(t, http.StatusBadRequest, w.Code) assert.Contains(t, w.Body.String(), "Invalid ID format") }) // Test with invalid request body t.Run("Invalid request body returns bad request", func(t *testing.T) { router := gin.New() router.Use(MockAuthMiddleware(*adminUser)) group := router.Group("/gui") InitSystemsEndpoints(group) reqBody := `{"invalid": "json"` w := httptest.NewRecorder() req, _ := http.NewRequest("PUT", fmt.Sprintf("/gui/systems/%d", system.ID), strings.NewReader(reqBody)) req.Header.Set("Content-Type", "application/json") router.ServeHTTP(w, req) assert.Equal(t, http.StatusBadRequest, w.Code) }) } func TestDeleteSystem(t *testing.T) { adminUser, regularUser := setupSystemsTest(t) // Test with admin user t.Run("Admin user can delete a system", func(t *testing.T) { // Create a system to delete system, _ := systems.CreateSystem("System to Delete") router := gin.New() router.Use(MockAuthMiddleware(*adminUser)) group := router.Group("/gui") InitSystemsEndpoints(group) w := httptest.NewRecorder() req, _ := http.NewRequest("DELETE", fmt.Sprintf("/gui/systems/%d", system.ID), nil) router.ServeHTTP(w, req) assert.Equal(t, http.StatusOK, w.Code) assert.Contains(t, w.Body.String(), "System deleted successfully") // Verify the system is deleted deletedSystem, err := systems.GetSystem(system.ID) assert.Error(t, err) assert.Nil(t, deletedSystem) }) // Test with non-admin user t.Run("Non-admin user cannot delete a system", func(t *testing.T) { // Create a system to delete system, _ := systems.CreateSystem("System to Not Delete") router := gin.New() router.Use(MockAuthMiddleware(*regularUser)) group := router.Group("/gui") InitSystemsEndpoints(group) w := httptest.NewRecorder() req, _ := http.NewRequest("DELETE", fmt.Sprintf("/gui/systems/%d", system.ID), nil) router.ServeHTTP(w, req) assert.Equal(t, http.StatusForbidden, w.Code) assert.Contains(t, w.Body.String(), "admin access required") // Verify the system is not deleted existingSystem, err := systems.GetSystem(system.ID) assert.NoError(t, err) assert.NotNil(t, existingSystem) }) // Test with invalid ID t.Run("Invalid ID returns bad request", func(t *testing.T) { router := gin.New() router.Use(MockAuthMiddleware(*adminUser)) group := router.Group("/gui") InitSystemsEndpoints(group) w := httptest.NewRecorder() req, _ := http.NewRequest("DELETE", "/gui/systems/invalid", nil) router.ServeHTTP(w, req) assert.Equal(t, http.StatusBadRequest, w.Code) assert.Contains(t, w.Body.String(), "Invalid ID format") }) }