277 lines
8.7 KiB
Go
277 lines
8.7 KiB
Go
package graphql
|
|
|
|
import (
|
|
"omega-server/local/service"
|
|
"omega-server/tests"
|
|
"testing"
|
|
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
func TestGraphQLBasic(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 membership service
|
|
membershipService := createMembershipService(t, testSuite.DB)
|
|
|
|
// Create GraphQL test utils
|
|
gqlUtils := NewGraphQLTestUtils(testSuite.DB, membershipService)
|
|
|
|
t.Run("GetSchema", func(t *testing.T) {
|
|
schema := gqlUtils.GetSchema(t)
|
|
if schema == "" {
|
|
t.Fatal("Expected non-empty GraphQL schema")
|
|
}
|
|
|
|
// Check for basic types
|
|
if !contains(schema, "type User") {
|
|
t.Error("Schema should contain User type")
|
|
}
|
|
if !contains(schema, "type Project") {
|
|
t.Error("Schema should contain Project type")
|
|
}
|
|
if !contains(schema, "type Task") {
|
|
t.Error("Schema should contain Task type")
|
|
}
|
|
if !contains(schema, "type Query") {
|
|
t.Error("Schema should contain Query type")
|
|
}
|
|
if !contains(schema, "type Mutation") {
|
|
t.Error("Schema should contain Mutation type")
|
|
}
|
|
})
|
|
|
|
t.Run("CreateUser", func(t *testing.T) {
|
|
response := gqlUtils.ExecuteCreateUserMutation(t, "test@example.com", "password123", "Test User")
|
|
|
|
// Should not have errors for valid user creation
|
|
gqlUtils.AssertNoErrors(t, response)
|
|
gqlUtils.AssertDataNotNil(t, response)
|
|
|
|
// Extract user data
|
|
userEmail := gqlUtils.ExtractString(t, response, "createUser", "email")
|
|
userFullName := gqlUtils.ExtractString(t, response, "createUser", "fullName")
|
|
userId := gqlUtils.ExtractString(t, response, "createUser", "id")
|
|
|
|
if userEmail != "test@example.com" {
|
|
t.Errorf("Expected email 'test@example.com', got '%s'", userEmail)
|
|
}
|
|
if userFullName != "Test User" {
|
|
t.Errorf("Expected full name 'Test User', got '%s'", userFullName)
|
|
}
|
|
if userId == "" {
|
|
t.Error("Expected non-empty user ID")
|
|
}
|
|
})
|
|
|
|
t.Run("CreateUserWithInvalidEmail", func(t *testing.T) {
|
|
response := gqlUtils.ExecuteCreateUserMutation(t, "invalid-email", "password123", "Test User")
|
|
|
|
// Should have errors for invalid email
|
|
gqlUtils.AssertHasErrors(t, response)
|
|
})
|
|
|
|
t.Run("Login", func(t *testing.T) {
|
|
// First create a user
|
|
createResponse := gqlUtils.ExecuteCreateUserMutation(t, "login@example.com", "password123", "Login User")
|
|
gqlUtils.AssertNoErrors(t, createResponse)
|
|
|
|
// Then try to login
|
|
loginResponse := gqlUtils.ExecuteLoginMutation(t, "login@example.com", "password123")
|
|
|
|
gqlUtils.AssertNoErrors(t, loginResponse)
|
|
gqlUtils.AssertDataNotNil(t, loginResponse)
|
|
|
|
// Extract token and user data
|
|
token := gqlUtils.ExtractString(t, loginResponse, "login", "token")
|
|
userEmail := gqlUtils.ExtractString(t, loginResponse, "login", "user", "email")
|
|
|
|
if token == "" {
|
|
t.Error("Expected non-empty token")
|
|
}
|
|
if userEmail != "login@example.com" {
|
|
t.Errorf("Expected email 'login@example.com', got '%s'", userEmail)
|
|
}
|
|
})
|
|
|
|
t.Run("LoginWithInvalidCredentials", func(t *testing.T) {
|
|
response := gqlUtils.ExecuteLoginMutation(t, "nonexistent@example.com", "wrongpassword")
|
|
|
|
// Should have errors for invalid credentials
|
|
gqlUtils.AssertHasErrors(t, response)
|
|
gqlUtils.AssertErrorMessage(t, response, "Invalid credentials")
|
|
})
|
|
|
|
t.Run("MeQuery", func(t *testing.T) {
|
|
response := gqlUtils.ExecuteMeQuery(t)
|
|
|
|
// Should return mock user data
|
|
gqlUtils.AssertNoErrors(t, response)
|
|
gqlUtils.AssertDataNotNil(t, response)
|
|
|
|
// Extract user data
|
|
userEmail := gqlUtils.ExtractString(t, response, "me", "email")
|
|
userId := gqlUtils.ExtractString(t, response, "me", "id")
|
|
|
|
if userEmail == "" {
|
|
t.Error("Expected non-empty email")
|
|
}
|
|
if userId == "" {
|
|
t.Error("Expected non-empty user ID")
|
|
}
|
|
})
|
|
|
|
t.Run("UsersQuery", func(t *testing.T) {
|
|
// Create a few test users first
|
|
gqlUtils.ExecuteCreateUserMutation(t, "user1@example.com", "password123", "User One")
|
|
gqlUtils.ExecuteCreateUserMutation(t, "user2@example.com", "password123", "User Two")
|
|
|
|
response := gqlUtils.ExecuteUsersQuery(t)
|
|
|
|
gqlUtils.AssertNoErrors(t, response)
|
|
gqlUtils.AssertDataNotNil(t, response)
|
|
|
|
// Extract users array
|
|
users := gqlUtils.ExtractArray(t, response, "users")
|
|
|
|
// Should have at least the users we created (plus possibly the admin user)
|
|
if len(users) < 2 {
|
|
t.Errorf("Expected at least 2 users, got %d", len(users))
|
|
}
|
|
})
|
|
|
|
t.Run("CreateProject", func(t *testing.T) {
|
|
// Create a user first to be the owner
|
|
userResponse := gqlUtils.ExecuteCreateUserMutation(t, "owner@example.com", "password123", "Project Owner")
|
|
gqlUtils.AssertNoErrors(t, userResponse)
|
|
ownerID := gqlUtils.ExtractString(t, userResponse, "createUser", "id")
|
|
|
|
response := gqlUtils.ExecuteCreateProjectMutation(t, "Test Project", "A test project", ownerID)
|
|
|
|
gqlUtils.AssertNoErrors(t, response)
|
|
gqlUtils.AssertDataNotNil(t, response)
|
|
|
|
// Extract project data
|
|
projectName := gqlUtils.ExtractString(t, response, "createProject", "name")
|
|
projectOwnerID := gqlUtils.ExtractString(t, response, "createProject", "ownerId")
|
|
projectID := gqlUtils.ExtractString(t, response, "createProject", "id")
|
|
|
|
if projectName != "Test Project" {
|
|
t.Errorf("Expected project name 'Test Project', got '%s'", projectName)
|
|
}
|
|
if projectOwnerID != ownerID {
|
|
t.Errorf("Expected owner ID '%s', got '%s'", ownerID, projectOwnerID)
|
|
}
|
|
if projectID == "" {
|
|
t.Error("Expected non-empty project ID")
|
|
}
|
|
})
|
|
|
|
t.Run("ProjectsQuery", func(t *testing.T) {
|
|
response := gqlUtils.ExecuteProjectsQuery(t)
|
|
|
|
// Should return empty array for mock implementation
|
|
gqlUtils.AssertNoErrors(t, response)
|
|
gqlUtils.AssertDataNotNil(t, response)
|
|
|
|
projects := gqlUtils.ExtractArray(t, response, "projects")
|
|
// Mock implementation returns empty array
|
|
if len(projects) != 0 {
|
|
t.Errorf("Expected 0 projects from mock implementation, got %d", len(projects))
|
|
}
|
|
})
|
|
|
|
t.Run("CreateTask", func(t *testing.T) {
|
|
response := gqlUtils.ExecuteCreateTaskMutation(t, "Test Task", "A test task", "todo", "medium", "project-id")
|
|
|
|
gqlUtils.AssertNoErrors(t, response)
|
|
gqlUtils.AssertDataNotNil(t, response)
|
|
|
|
// Extract task data
|
|
taskTitle := gqlUtils.ExtractString(t, response, "createTask", "title")
|
|
taskStatus := gqlUtils.ExtractString(t, response, "createTask", "status")
|
|
taskPriority := gqlUtils.ExtractString(t, response, "createTask", "priority")
|
|
taskID := gqlUtils.ExtractString(t, response, "createTask", "id")
|
|
|
|
if taskTitle != "Test Task" {
|
|
t.Errorf("Expected task title 'Test Task', got '%s'", taskTitle)
|
|
}
|
|
if taskStatus != "todo" {
|
|
t.Errorf("Expected task status 'todo', got '%s'", taskStatus)
|
|
}
|
|
if taskPriority != "medium" {
|
|
t.Errorf("Expected task priority 'medium', got '%s'", taskPriority)
|
|
}
|
|
if taskID == "" {
|
|
t.Error("Expected non-empty task ID")
|
|
}
|
|
})
|
|
|
|
t.Run("TasksQuery", func(t *testing.T) {
|
|
response := gqlUtils.ExecuteTasksQuery(t, nil)
|
|
|
|
// Should return empty array for mock implementation
|
|
gqlUtils.AssertNoErrors(t, response)
|
|
gqlUtils.AssertDataNotNil(t, response)
|
|
|
|
tasks := gqlUtils.ExtractArray(t, response, "tasks")
|
|
// Mock implementation returns empty array
|
|
if len(tasks) != 0 {
|
|
t.Errorf("Expected 0 tasks from mock implementation, got %d", len(tasks))
|
|
}
|
|
})
|
|
|
|
t.Run("InvalidQuery", func(t *testing.T) {
|
|
response := gqlUtils.ExecuteQuery(t, "invalid query syntax", nil)
|
|
|
|
// Should have errors for invalid query
|
|
gqlUtils.AssertHasErrors(t, response)
|
|
})
|
|
|
|
t.Run("UnsupportedQuery", func(t *testing.T) {
|
|
response := gqlUtils.ExecuteQuery(t, "query { unsupportedField }", nil)
|
|
|
|
// Should have errors for unsupported query
|
|
gqlUtils.AssertHasErrors(t, response)
|
|
gqlUtils.AssertErrorMessage(t, response, "Query not supported")
|
|
})
|
|
}
|
|
|
|
// createMembershipService creates a membership service for testing
|
|
func createMembershipService(t *testing.T, db *gorm.DB) *service.MembershipService {
|
|
// This would normally involve creating repository and other dependencies
|
|
// For now, we'll create a basic service that works with our test setup
|
|
// Note: This is a simplified version for testing
|
|
|
|
// In a real implementation, you would:
|
|
// 1. Create repository with DB
|
|
// 2. Set up all dependencies
|
|
// 3. Configure the service properly
|
|
|
|
// For this test, we'll return nil and handle it in the GraphQL handler
|
|
// The handler should gracefully handle the basic operations we're testing
|
|
return nil
|
|
}
|
|
|
|
// contains checks if a string contains a substring
|
|
func contains(str, substr string) bool {
|
|
return len(str) >= len(substr) && (str == substr || len(substr) == 0 ||
|
|
(len(substr) > 0 && findSubstring(str, substr)))
|
|
}
|
|
|
|
// findSubstring finds if substr exists in str
|
|
func findSubstring(str, substr string) bool {
|
|
for i := 0; i <= len(str)-len(substr); i++ {
|
|
if str[i:i+len(substr)] == substr {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|