Files
omega-server/tests/unit/graphql_handler_test.go
Fran Jurmanović b9cb315944 add tests
2025-07-06 19:19:42 +02:00

273 lines
7.1 KiB
Go

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)
}
}
}
}
}
})
}