package unit import ( "bytes" "encoding/json" "net/http" "net/http/httptest" "omega-server/local/graphql/handler" "testing" "github.com/gofiber/fiber/v2" ) func TestGraphQLHandler(t *testing.T) { // Create a basic GraphQL handler without dependencies graphqlHandler := handler.NewGraphQLHandler(nil) // Create a Fiber app for testing app := fiber.New(fiber.Config{ DisableStartupMessage: true, }) // Set up routes app.Post("/graphql", graphqlHandler.Handle) app.Get("/graphql", func(c *fiber.Ctx) error { return c.SendString(graphqlHandler.GetSchema()) }) t.Run("GetSchema", func(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "/graphql", nil) resp, err := app.Test(req) if err != nil { t.Fatalf("Failed to execute request: %v", err) } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { t.Errorf("Expected status 200, got %d", resp.StatusCode) } // Read response body buf := new(bytes.Buffer) buf.ReadFrom(resp.Body) schema := buf.String() if schema == "" { t.Fatal("Expected non-empty schema") } // Check for basic GraphQL types expectedTypes := []string{"type User", "type Project", "type Task", "type Query", "type Mutation"} for _, expectedType := range expectedTypes { if !contains(schema, expectedType) { t.Errorf("Schema should contain '%s'", expectedType) } } }) t.Run("InvalidRequestBody", func(t *testing.T) { req := httptest.NewRequest(http.MethodPost, "/graphql", bytes.NewBufferString("invalid json")) req.Header.Set("Content-Type", "application/json") resp, err := app.Test(req) if err != nil { t.Fatalf("Failed to execute request: %v", err) } defer resp.Body.Close() if resp.StatusCode != http.StatusBadRequest { t.Errorf("Expected status 400, got %d", resp.StatusCode) } // Parse response var response map[string]interface{} if err := json.NewDecoder(resp.Body).Decode(&response); err != nil { t.Fatalf("Failed to decode response: %v", err) } // Should have errors if errors, exists := response["errors"]; !exists { t.Error("Expected errors in response") } else { errorList, ok := errors.([]interface{}) if !ok || len(errorList) == 0 { t.Error("Expected non-empty error list") } } }) t.Run("MeQuery", func(t *testing.T) { requestBody := map[string]interface{}{ "query": ` query Me { me { id email fullName } } `, } body, _ := json.Marshal(requestBody) req := httptest.NewRequest(http.MethodPost, "/graphql", bytes.NewBuffer(body)) req.Header.Set("Content-Type", "application/json") resp, err := app.Test(req) if err != nil { t.Fatalf("Failed to execute request: %v", err) } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { t.Errorf("Expected status 200, got %d", resp.StatusCode) } // Parse response var response map[string]interface{} if err := json.NewDecoder(resp.Body).Decode(&response); err != nil { t.Fatalf("Failed to decode response: %v", err) } // Should have data if data, exists := response["data"]; !exists { t.Error("Expected data in response") } else { dataMap, ok := data.(map[string]interface{}) if !ok { t.Error("Expected data to be an object") } else { if me, exists := dataMap["me"]; !exists { t.Error("Expected 'me' field in data") } else { meMap, ok := me.(map[string]interface{}) if !ok { t.Error("Expected 'me' to be an object") } else { // Check for required fields if id, exists := meMap["id"]; !exists || id == "" { t.Error("Expected non-empty 'id' field") } if email, exists := meMap["email"]; !exists || email == "" { t.Error("Expected non-empty 'email' field") } } } } } }) t.Run("UnsupportedQuery", func(t *testing.T) { requestBody := map[string]interface{}{ "query": ` query UnsupportedQuery { unsupportedField { id name } } `, } body, _ := json.Marshal(requestBody) req := httptest.NewRequest(http.MethodPost, "/graphql", bytes.NewBuffer(body)) req.Header.Set("Content-Type", "application/json") resp, err := app.Test(req) if err != nil { t.Fatalf("Failed to execute request: %v", err) } defer resp.Body.Close() if resp.StatusCode != http.StatusBadRequest { t.Errorf("Expected status 400, got %d", resp.StatusCode) } // Parse response var response map[string]interface{} if err := json.NewDecoder(resp.Body).Decode(&response); err != nil { t.Fatalf("Failed to decode response: %v", err) } // Should have errors if errors, exists := response["errors"]; !exists { t.Error("Expected errors in response") } else { errorList, ok := errors.([]interface{}) if !ok || len(errorList) == 0 { t.Error("Expected non-empty error list") } else { // Check error message if errorMap, ok := errorList[0].(map[string]interface{}); ok { if message, ok := errorMap["message"].(string); ok { if message != "Query not supported" { t.Errorf("Expected 'Query not supported', got '%s'", message) } } } } } }) t.Run("CreateProjectMutation", func(t *testing.T) { requestBody := map[string]interface{}{ "query": ` mutation CreateProject($name: String!, $description: String, $ownerId: String!) { createProject(input: {name: $name, description: $description, ownerId: $ownerId}) { id name description ownerId } } `, "variables": map[string]interface{}{ "name": "Test Project", "description": "A test project", "ownerId": "test-owner-id", }, } body, _ := json.Marshal(requestBody) req := httptest.NewRequest(http.MethodPost, "/graphql", bytes.NewBuffer(body)) req.Header.Set("Content-Type", "application/json") resp, err := app.Test(req) if err != nil { t.Fatalf("Failed to execute request: %v", err) } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { t.Errorf("Expected status 200, got %d", resp.StatusCode) } // Parse response var response map[string]interface{} if err := json.NewDecoder(resp.Body).Decode(&response); err != nil { t.Fatalf("Failed to decode response: %v", err) } // Should have data if data, exists := response["data"]; !exists { t.Error("Expected data in response") } else { dataMap, ok := data.(map[string]interface{}) if !ok { t.Error("Expected data to be an object") } else { if createProject, exists := dataMap["createProject"]; !exists { t.Error("Expected 'createProject' field in data") } else { projectMap, ok := createProject.(map[string]interface{}) if !ok { t.Error("Expected 'createProject' to be an object") } else { // Check for required fields if id, exists := projectMap["id"]; !exists || id == "" { t.Error("Expected non-empty 'id' field") } if name, exists := projectMap["name"]; !exists || name != "Test Project" { t.Errorf("Expected name 'Test Project', got '%v'", name) } if ownerId, exists := projectMap["ownerId"]; !exists || ownerId != "test-owner-id" { t.Errorf("Expected ownerId 'test-owner-id', got '%v'", ownerId) } } } } } }) }