package integration import ( "omega-server/local/api" "omega-server/local/model" "omega-server/local/repository" "omega-server/local/service" "omega-server/tests" "testing" "github.com/gofiber/fiber/v2" ) func TestGraphQLIntegration(t *testing.T) { // Initialize test suite testSuite := tests.NewTestSuite() testSuite.Setup(t) defer testSuite.Teardown(t) // Skip if no test database testSuite.SkipIfNoTestDB(t) // Create Fiber app app := fiber.New(fiber.Config{ DisableStartupMessage: true, }) // Initialize services and repositories membershipRepo := repository.NewMembershipRepository(testSuite.DB) membershipService := service.NewMembershipService(membershipRepo) // Provide services to DI container err := testSuite.DI.Provide(func() *service.MembershipService { return membershipService }) if err != nil { t.Fatalf("Failed to provide membership service: %v", err) } // Initialize API routes api.Init(testSuite.DI, app) // Create integration test utils integrationUtils := NewIntegrationTestUtils(app, testSuite.DB, membershipService) t.Run("GraphQLSchemaEndpoint", func(t *testing.T) { req := TestRequest{ Method: "GET", URL: "/v1/graphql", } resp := integrationUtils.ExecuteRequest(t, req) integrationUtils.AssertStatusCode(t, resp, 200) integrationUtils.AssertResponseBody(t, resp, "type User") integrationUtils.AssertResponseBody(t, resp, "type Query") integrationUtils.AssertResponseBody(t, resp, "type Mutation") }) t.Run("GraphQLLoginMutation", func(t *testing.T) { // First create a user through the service user := &model.User{ Email: "graphql@example.com", FullName: "GraphQL User", } if err := user.SetPassword("password123"); err != nil { t.Fatalf("Failed to set password: %v", err) } _, err := membershipService.CreateUser( testSuite.TestContext(), user, []string{"user"}, ) if err != nil { t.Fatalf("Failed to create test user: %v", err) } // Test GraphQL login mutation req := TestRequest{ Method: "POST", URL: "/v1/graphql", Body: map[string]interface{}{ "query": ` mutation Login($email: String!, $password: String!) { login(input: {email: $email, password: $password}) { token user { id email fullName } } } `, "variables": map[string]interface{}{ "email": "graphql@example.com", "password": "password123", }, }, } resp := integrationUtils.ExecuteRequest(t, req) integrationUtils.AssertStatusCode(t, resp, 200) // Parse response and check for token data := integrationUtils.ParseJSONResponse(t, resp) if errors, exists := data["errors"]; exists { t.Fatalf("GraphQL returned errors: %v", errors) } loginData := integrationUtils.ExtractJSONField(t, resp, "data", "login") if loginData == nil { t.Fatal("Expected login data in response") } token := integrationUtils.ExtractStringField(t, resp, "data", "login", "token") if token == "" { t.Error("Expected non-empty token") } userEmail := integrationUtils.ExtractStringField(t, resp, "data", "login", "user", "email") if userEmail != "graphql@example.com" { t.Errorf("Expected email 'graphql@example.com', got '%s'", userEmail) } }) t.Run("GraphQLCreateUserMutation", func(t *testing.T) { req := TestRequest{ Method: "POST", URL: "/v1/graphql", Body: map[string]interface{}{ "query": ` mutation CreateUser($email: String!, $password: String!, $fullName: String!) { createUser(input: {email: $email, password: $password, fullName: $fullName}) { id email fullName createdAt updatedAt } } `, "variables": map[string]interface{}{ "email": "newuser@example.com", "password": "password123", "fullName": "New User", }, }, } resp := integrationUtils.ExecuteRequest(t, req) integrationUtils.AssertStatusCode(t, resp, 200) // Parse response and verify user creation data := integrationUtils.ParseJSONResponse(t, resp) if errors, exists := data["errors"]; exists { t.Fatalf("GraphQL returned errors: %v", errors) } userEmail := integrationUtils.ExtractStringField(t, resp, "data", "createUser", "email") if userEmail != "newuser@example.com" { t.Errorf("Expected email 'newuser@example.com', got '%s'", userEmail) } userFullName := integrationUtils.ExtractStringField(t, resp, "data", "createUser", "fullName") if userFullName != "New User" { t.Errorf("Expected full name 'New User', got '%s'", userFullName) } userID := integrationUtils.ExtractStringField(t, resp, "data", "createUser", "id") if userID == "" { t.Error("Expected non-empty user ID") } }) t.Run("GraphQLMeQuery", func(t *testing.T) { req := TestRequest{ Method: "POST", URL: "/v1/graphql", Body: map[string]interface{}{ "query": ` query Me { me { id email fullName createdAt updatedAt } } `, }, } resp := integrationUtils.ExecuteRequest(t, req) integrationUtils.AssertStatusCode(t, resp, 200) // Parse response data := integrationUtils.ParseJSONResponse(t, resp) if errors, exists := data["errors"]; exists { t.Fatalf("GraphQL returned errors: %v", errors) } userEmail := integrationUtils.ExtractStringField(t, resp, "data", "me", "email") if userEmail == "" { t.Error("Expected non-empty email") } userID := integrationUtils.ExtractStringField(t, resp, "data", "me", "id") if userID == "" { t.Error("Expected non-empty user ID") } }) t.Run("GraphQLInvalidQuery", func(t *testing.T) { req := TestRequest{ Method: "POST", URL: "/v1/graphql", Body: map[string]interface{}{ "query": "invalid query syntax {", }, } resp := integrationUtils.ExecuteRequest(t, req) integrationUtils.AssertStatusCode(t, resp, 400) // Should have errors in response data := integrationUtils.ParseJSONResponse(t, resp) if errors, exists := data["errors"]; !exists { t.Fatal("Expected errors in response for invalid query") } else { errorList, ok := errors.([]interface{}) if !ok || len(errorList) == 0 { t.Fatal("Expected non-empty error list") } } }) t.Run("GraphQLUnsupportedQuery", func(t *testing.T) { req := TestRequest{ Method: "POST", URL: "/v1/graphql", Body: map[string]interface{}{ "query": ` query UnsupportedQuery { unsupportedField { id name } } `, }, } resp := integrationUtils.ExecuteRequest(t, req) integrationUtils.AssertStatusCode(t, resp, 400) // Should return "Query not supported" error data := integrationUtils.ParseJSONResponse(t, resp) if errors, exists := data["errors"]; exists { errorList, ok := errors.([]interface{}) if ok && len(errorList) > 0 { 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' error, got '%s'", message) } } } } } }) t.Run("GraphQLCreateProjectMutation", func(t *testing.T) { req := TestRequest{ Method: "POST", URL: "/v1/graphql", Body: map[string]interface{}{ "query": ` mutation CreateProject($name: String!, $description: String, $ownerId: String!) { createProject(input: {name: $name, description: $description, ownerId: $ownerId}) { id name description ownerId createdAt updatedAt } } `, "variables": map[string]interface{}{ "name": "Integration Test Project", "description": "A project created during integration testing", "ownerId": "test-owner-id", }, }, } resp := integrationUtils.ExecuteRequest(t, req) integrationUtils.AssertStatusCode(t, resp, 200) // Parse response (should work since it's mocked) data := integrationUtils.ParseJSONResponse(t, resp) if errors, exists := data["errors"]; exists { t.Fatalf("GraphQL returned errors: %v", errors) } projectName := integrationUtils.ExtractStringField(t, resp, "data", "createProject", "name") if projectName != "Integration Test Project" { t.Errorf("Expected project name 'Integration Test Project', got '%s'", projectName) } projectID := integrationUtils.ExtractStringField(t, resp, "data", "createProject", "id") if projectID == "" { t.Error("Expected non-empty project ID") } }) t.Run("GraphQLCreateTaskMutation", func(t *testing.T) { req := TestRequest{ Method: "POST", URL: "/v1/graphql", Body: map[string]interface{}{ "query": ` mutation CreateTask($title: String!, $description: String, $status: String, $priority: String, $projectId: String!) { createTask(input: {title: $title, description: $description, status: $status, priority: $priority, projectId: $projectId}) { id title description status priority projectId createdAt updatedAt } } `, "variables": map[string]interface{}{ "title": "Integration Test Task", "description": "A task created during integration testing", "status": "todo", "priority": "medium", "projectId": "test-project-id", }, }, } resp := integrationUtils.ExecuteRequest(t, req) integrationUtils.AssertStatusCode(t, resp, 200) // Parse response (should work since it's mocked) data := integrationUtils.ParseJSONResponse(t, resp) if errors, exists := data["errors"]; exists { t.Fatalf("GraphQL returned errors: %v", errors) } taskTitle := integrationUtils.ExtractStringField(t, resp, "data", "createTask", "title") if taskTitle != "Integration Test Task" { t.Errorf("Expected task title 'Integration Test Task', got '%s'", taskTitle) } taskStatus := integrationUtils.ExtractStringField(t, resp, "data", "createTask", "status") if taskStatus != "todo" { t.Errorf("Expected task status 'todo', got '%s'", taskStatus) } taskID := integrationUtils.ExtractStringField(t, resp, "data", "createTask", "id") if taskID == "" { t.Error("Expected non-empty task ID") } }) }