374 lines
10 KiB
Go
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")
|
|
}
|
|
})
|
|
}
|