mirror of
https://github.com/SamyRai/tercul-backend.git
synced 2025-12-27 02:51:34 +00:00
The integration tests for admin-only mutations were failing due to an authorization issue. The root cause was that the JWT token used in the tests did not reflect the user's admin role, which was being set directly in the database. This commit fixes the issue by: 1. Updating the `CreateAuthenticatedUser` test helper to generate a new JWT token after a user's role is changed. This ensures the token contains the correct, up-to-date role. 2. Removing all uses of `auth.ContextWithAdminUser` from the integration tests, making the JWT token the single source of truth for authorization. This change also removes unused imports and variables that were causing build failures after the refactoring. All integration tests now pass.
241 lines
6.0 KiB
Go
241 lines
6.0 KiB
Go
package graphql_test
|
|
|
|
import (
|
|
"tercul/internal/adapters/graphql/model"
|
|
"tercul/internal/domain"
|
|
)
|
|
|
|
type CreateBookResponse struct {
|
|
CreateBook model.Book `json:"createBook"`
|
|
}
|
|
|
|
type GetBookResponse struct {
|
|
Book model.Book `json:"book"`
|
|
}
|
|
|
|
type GetBooksResponse struct {
|
|
Books []model.Book `json:"books"`
|
|
}
|
|
|
|
type UpdateBookResponse struct {
|
|
UpdateBook model.Book `json:"updateBook"`
|
|
}
|
|
|
|
func (s *GraphQLIntegrationSuite) TestBookMutations() {
|
|
// Create users for testing authorization
|
|
_, readerToken := s.CreateAuthenticatedUser("bookreader", "bookreader@test.com", domain.UserRoleReader)
|
|
_, adminToken := s.CreateAuthenticatedUser("bookadmin", "bookadmin@test.com", domain.UserRoleAdmin)
|
|
|
|
var bookID string
|
|
|
|
s.Run("a reader can create a book", func() {
|
|
// Define the mutation
|
|
mutation := `
|
|
mutation CreateBook($input: BookInput!) {
|
|
createBook(input: $input) {
|
|
id
|
|
name
|
|
description
|
|
language
|
|
isbn
|
|
}
|
|
}
|
|
`
|
|
|
|
// Define the variables
|
|
variables := map[string]interface{}{
|
|
"input": map[string]interface{}{
|
|
"name": "My New Book",
|
|
"description": "A book about something.",
|
|
"language": "en",
|
|
"isbn": "978-3-16-148410-0",
|
|
},
|
|
}
|
|
|
|
// Execute the mutation
|
|
response, err := executeGraphQL[CreateBookResponse](s, mutation, variables, &readerToken)
|
|
s.Require().NoError(err)
|
|
s.Require().NotNil(response)
|
|
s.Require().Nil(response.Errors, "GraphQL mutation should not return errors")
|
|
|
|
// Verify the response
|
|
s.NotNil(response.Data.CreateBook.ID, "Book ID should not be nil")
|
|
bookID = response.Data.CreateBook.ID
|
|
s.Equal("My New Book", response.Data.CreateBook.Name)
|
|
s.Equal("A book about something.", *response.Data.CreateBook.Description)
|
|
s.Equal("en", response.Data.CreateBook.Language)
|
|
s.Equal("978-3-16-148410-0", *response.Data.CreateBook.Isbn)
|
|
})
|
|
|
|
s.Run("a reader is forbidden from updating a book", func() {
|
|
// Define the mutation
|
|
mutation := `
|
|
mutation UpdateBook($id: ID!, $input: BookInput!) {
|
|
updateBook(id: $id, input: $input) {
|
|
id
|
|
}
|
|
}
|
|
`
|
|
|
|
// Define the variables
|
|
variables := map[string]interface{}{
|
|
"id": bookID,
|
|
"input": map[string]interface{}{
|
|
"name": "Updated Book Name",
|
|
"language": "en",
|
|
},
|
|
}
|
|
|
|
// Execute the mutation with the reader's token
|
|
response, err := executeGraphQL[any](s, mutation, variables, &readerToken)
|
|
s.Require().NoError(err)
|
|
s.Require().NotNil(response.Errors)
|
|
})
|
|
|
|
s.Run("an admin can update a book", func() {
|
|
// Define the mutation
|
|
mutation := `
|
|
mutation UpdateBook($id: ID!, $input: BookInput!) {
|
|
updateBook(id: $id, input: $input) {
|
|
id
|
|
name
|
|
}
|
|
}
|
|
`
|
|
|
|
// Define the variables
|
|
variables := map[string]interface{}{
|
|
"id": bookID,
|
|
"input": map[string]interface{}{
|
|
"name": "Updated Book Name by Admin",
|
|
"language": "en",
|
|
},
|
|
}
|
|
|
|
// Execute the mutation with the admin's token
|
|
response, err := executeGraphQL[UpdateBookResponse](s, mutation, variables, &adminToken)
|
|
s.Require().NoError(err)
|
|
s.Require().NotNil(response)
|
|
s.Require().Nil(response.Errors, "GraphQL mutation should not return errors")
|
|
})
|
|
|
|
s.Run("a reader is forbidden from deleting a book", func() {
|
|
// Define the mutation
|
|
mutation := `
|
|
mutation DeleteBook($id: ID!) {
|
|
deleteBook(id: $id)
|
|
}
|
|
`
|
|
|
|
// Define the variables
|
|
variables := map[string]interface{}{
|
|
"id": bookID,
|
|
}
|
|
|
|
// Execute the mutation with the reader's token
|
|
response, err := executeGraphQL[any](s, mutation, variables, &readerToken)
|
|
s.Require().NoError(err)
|
|
s.Require().NotNil(response.Errors)
|
|
})
|
|
|
|
s.Run("an admin can delete a book", func() {
|
|
// Define the mutation
|
|
mutation := `
|
|
mutation DeleteBook($id: ID!) {
|
|
deleteBook(id: $id)
|
|
}
|
|
`
|
|
|
|
// Define the variables
|
|
variables := map[string]interface{}{
|
|
"id": bookID,
|
|
}
|
|
|
|
// Execute the mutation with the admin's token
|
|
response, err := executeGraphQL[any](s, mutation, variables, &adminToken)
|
|
s.Require().NoError(err)
|
|
s.Require().Nil(response.Errors)
|
|
s.True(response.Data.(map[string]interface{})["deleteBook"].(bool))
|
|
})
|
|
}
|
|
|
|
func (s *GraphQLIntegrationSuite) TestBookQueries() {
|
|
// Create a book to query
|
|
_, adminToken := s.CreateAuthenticatedUser("bookadmin2", "bookadmin2@test.com", domain.UserRoleAdmin)
|
|
createMutation := `
|
|
mutation CreateBook($input: BookInput!) {
|
|
createBook(input: $input) {
|
|
id
|
|
}
|
|
}
|
|
`
|
|
createVariables := map[string]interface{}{
|
|
"input": map[string]interface{}{
|
|
"name": "Queryable Book",
|
|
"description": "A book to be queried.",
|
|
"language": "en",
|
|
"isbn": "978-0-306-40615-7",
|
|
},
|
|
}
|
|
createResponse, err := executeGraphQL[CreateBookResponse](s, createMutation, createVariables, &adminToken)
|
|
s.Require().NoError(err)
|
|
bookID := createResponse.Data.CreateBook.ID
|
|
|
|
s.Run("should get a book by ID", func() {
|
|
// Define the query
|
|
query := `
|
|
query GetBook($id: ID!) {
|
|
book(id: $id) {
|
|
id
|
|
name
|
|
description
|
|
}
|
|
}
|
|
`
|
|
|
|
// Define the variables
|
|
variables := map[string]interface{}{
|
|
"id": bookID,
|
|
}
|
|
|
|
// Execute the query
|
|
response, err := executeGraphQL[GetBookResponse](s, query, variables, nil)
|
|
s.Require().NoError(err)
|
|
s.Require().NotNil(response)
|
|
s.Require().Nil(response.Errors, "GraphQL query should not return errors")
|
|
|
|
// Verify the response
|
|
s.Equal(bookID, response.Data.Book.ID)
|
|
s.Equal("Queryable Book", response.Data.Book.Name)
|
|
s.Equal("A book to be queried.", *response.Data.Book.Description)
|
|
})
|
|
|
|
s.Run("should get a list of books", func() {
|
|
// Define the query
|
|
query := `
|
|
query GetBooks {
|
|
books {
|
|
id
|
|
name
|
|
}
|
|
}
|
|
`
|
|
|
|
// Execute the query
|
|
response, err := executeGraphQL[GetBooksResponse](s, query, nil, nil)
|
|
s.Require().NoError(err)
|
|
s.Require().NotNil(response)
|
|
s.Require().Nil(response.Errors, "GraphQL query should not return errors")
|
|
|
|
// Verify the response
|
|
s.True(len(response.Data.Books) >= 1)
|
|
foundBook := false
|
|
for _, book := range response.Data.Books {
|
|
if book.ID == bookID {
|
|
foundBook = true
|
|
break
|
|
}
|
|
}
|
|
s.True(foundBook, "The created book should be in the list")
|
|
})
|
|
} |