tercul-backend/internal/adapters/graphql/integration_test.go

257 lines
7.0 KiB
Go

package graphql_test
import (
"bytes"
"context"
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"testing"
"tercul/internal/adapters/graphql"
"tercul/internal/testutil"
"github.com/99designs/gqlgen/graphql/handler"
"github.com/stretchr/testify/suite"
)
// GraphQLRequest represents a GraphQL request
type GraphQLRequest struct {
Query string `json:"query"`
OperationName string `json:"operationName,omitempty"`
Variables map[string]interface{} `json:"variables,omitempty"`
}
// GraphQLResponse represents a GraphQL response
type GraphQLResponse struct {
Data map[string]interface{} `json:"data,omitempty"`
Errors []map[string]interface{} `json:"errors,omitempty"`
}
// GraphQLIntegrationSuite is a test suite for GraphQL integration tests
type GraphQLIntegrationSuite struct {
testutil.SimpleTestSuite
server *httptest.Server
client *http.Client
}
// SetupSuite sets up the test suite
func (s *GraphQLIntegrationSuite) SetupSuite() {
// Use the simple test utilities
s.SimpleTestSuite.SetupSuite()
// Create GraphQL server with the test resolver
resolver := s.GetResolver()
srv := handler.NewDefaultServer(graph.NewExecutableSchema(graph.Config{Resolvers: resolver}))
s.server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
srv.ServeHTTP(w, r)
}))
s.client = s.server.Client()
}
// TearDownSuite tears down the test suite
func (s *GraphQLIntegrationSuite) TearDownSuite() {
s.server.Close()
}
// SetupTest sets up each test
func (s *GraphQLIntegrationSuite) SetupTest() {
s.SimpleTestSuite.SetupTest()
}
// executeGraphQL executes a GraphQL query
func (s *GraphQLIntegrationSuite) executeGraphQL(query string, variables map[string]interface{}) (*GraphQLResponse, error) {
// Create the request
request := GraphQLRequest{
Query: query,
Variables: variables,
}
// Marshal the request to JSON
requestBody, err := json.Marshal(request)
if err != nil {
return nil, err
}
// Create an HTTP request
req, err := http.NewRequest("POST", s.server.URL, bytes.NewBuffer(requestBody))
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "application/json")
// Execute the request
resp, err := s.client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
// Parse the response
var response GraphQLResponse
err = json.NewDecoder(resp.Body).Decode(&response)
if err != nil {
return nil, err
}
return &response, nil
}
// TestQueryWork tests the work query
func (s *GraphQLIntegrationSuite) TestQueryWork() {
// Create a test work with content
work := s.CreateTestWork("Test Work", "en", "Test content for work")
// Define the query
query := `
query GetWork($id: ID!) {
work(id: $id) {
id
name
language
content
}
}
`
// Define the variables
variables := map[string]interface{}{
"id": fmt.Sprintf("%d", work.ID),
}
// Execute the query
response, err := s.executeGraphQL(query, variables)
s.Require().NoError(err)
s.Require().NotNil(response)
s.Require().Nil(response.Errors, "GraphQL query should not return errors")
s.Require().NotNil(response.Data, "GraphQL query should return data")
// Verify the response
workData, ok := response.Data["work"].(map[string]interface{})
s.Require().True(ok, "GraphQL response should contain work data")
s.Equal("Test Work", workData["name"], "Work name should match")
s.Equal("Test content for work", workData["content"], "Work content should match")
s.Equal("en", workData["language"], "Work language should match")
}
// TestQueryWorks tests the works query
func (s *GraphQLIntegrationSuite) TestQueryWorks() {
// Create test works
work1 := s.CreateTestWork("Test Work 1", "en", "Test content for work 1")
work2 := s.CreateTestWork("Test Work 2", "en", "Test content for work 2")
work3 := s.CreateTestWork("Test Work 3", "fr", "Test content for work 3")
// Define the query
query := `
query GetWorks {
works {
id
name
language
content
}
}
`
// Execute the query
response, err := s.executeGraphQL(query, nil)
s.Require().NoError(err)
s.Require().NotNil(response)
s.Require().Nil(response.Errors, "GraphQL query should not return errors")
s.Require().NotNil(response.Data, "GraphQL query should return data")
// Verify the response
worksData, ok := response.Data["works"].([]interface{})
s.Require().True(ok, "GraphQL response should contain works data")
s.True(len(worksData) >= 3, "GraphQL response should contain at least 3 works")
// Verify each work
foundWork1 := false
foundWork2 := false
foundWork3 := false
for _, workData := range worksData {
work, ok := workData.(map[string]interface{})
s.Require().True(ok, "Work data should be a map")
name := work["name"].(string)
if name == "Test Work 1" {
foundWork1 = true
s.Equal("en", work["language"], "Work 1 language should match")
} else if name == "Test Work 2" {
foundWork2 = true
s.Equal("en", work["language"], "Work 2 language should match")
} else if name == "Test Work 3" {
foundWork3 = true
s.Equal("fr", work["language"], "Work 3 language should match")
}
}
s.True(foundWork1, "GraphQL response should contain work 1")
s.True(foundWork2, "GraphQL response should contain work 2")
s.True(foundWork3, "GraphQL response should contain work 3")
}
// TestCreateWork tests the createWork mutation
func (s *GraphQLIntegrationSuite) TestCreateWork() {
// Define the mutation
mutation := `
mutation CreateWork($input: WorkInput!) {
createWork(input: $input) {
id
name
language
content
}
}
`
// Define the variables
variables := map[string]interface{}{
"input": map[string]interface{}{
"name": "New Test Work",
"language": "en",
"content": "New test content",
},
}
// Execute the mutation
response, err := s.executeGraphQL(mutation, variables)
s.Require().NoError(err)
s.Require().NotNil(response)
s.Require().Nil(response.Errors, "GraphQL mutation should not return errors")
s.Require().NotNil(response.Data, "GraphQL mutation should return data")
// Verify the response
workData, ok := response.Data["createWork"].(map[string]interface{})
s.Require().True(ok, "GraphQL response should contain work data")
s.NotNil(workData["id"], "Work ID should not be nil")
s.Equal("New Test Work", workData["name"], "Work name should match")
s.Equal("en", workData["language"], "Work language should match")
s.Equal("New test content", workData["content"], "Work content should match")
// Verify that the work was created in the repository
// Since we're using the real repository interface, we can query it
works, err := s.WorkRepo.ListAll(context.Background())
s.Require().NoError(err)
var found bool
for _, w := range works {
if w.Title == "New Test Work" {
found = true
s.Equal("en", w.Language, "Work language should be set correctly")
break
}
}
s.True(found, "Work should be created in repository")
}
// TestGraphQLIntegrationSuite runs the test suite
func TestGraphQLIntegrationSuite(t *testing.T) {
testutil.SkipIfShort(t)
suite.Run(t, new(GraphQLIntegrationSuite))
}