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

374 lines
10 KiB
Go

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