tercul-backend/internal/app/copyright/commands_integration_test.go
google-labs-jules[bot] c2e9a118e2 feat(testing): Increase test coverage and fix authz bugs
This commit significantly increases the test coverage across the application and fixes several underlying bugs that were discovered while writing the new tests.

The key changes include:

- **New Tests:** Added extensive integration and unit tests for GraphQL resolvers, application services, and data repositories, substantially increasing the test coverage for packages like `graphql`, `user`, `translation`, and `analytics`.

- **Authorization Bug Fixes:**
  - Fixed a critical bug where a user creating a `Work` was not correctly associated as its author, causing subsequent permission failures.
  - Corrected the authorization logic in `authz.Service` to properly check for entity ownership by non-admin users.

- **Test Refactoring:**
  - Refactored numerous test suites to use `testify/mock` instead of manual mocks, improving test clarity and maintainability.
  - Isolated integration tests by creating a fresh admin user and token for each test run, eliminating test pollution.
  - Centralized domain errors into `internal/domain/errors.go` and updated repositories to use them, making error handling more consistent.

- **Code Quality Improvements:**
  - Replaced manual mock implementations with `testify/mock` for better consistency.
  - Cleaned up redundant and outdated test files.

These changes stabilize the test suite, improve the overall quality of the codebase, and move the project closer to the goal of 80% test coverage.
2025-10-09 07:03:45 +00:00

240 lines
8.6 KiB
Go

//go:build integration
package copyright_test
import (
"context"
"testing"
"tercul/internal/app/copyright"
"tercul/internal/domain"
"tercul/internal/testutil"
"github.com/stretchr/testify/suite"
)
type CopyrightCommandsTestSuite struct {
testutil.IntegrationTestSuite
commands *copyright.CopyrightCommands
}
func (s *CopyrightCommandsTestSuite) SetupSuite() {
s.IntegrationTestSuite.SetupSuite(testutil.DefaultTestConfig())
s.commands = copyright.NewCopyrightCommands(s.CopyrightRepo)
}
func (s *CopyrightCommandsTestSuite) TestAddCopyrightToWork() {
s.Run("should add a copyright to a work", func() {
// Arrange
work := s.CreateTestWork(s.AdminCtx, "Test Work", "en", "Test content")
copyright := &domain.Copyright{Name: "Test Copyright", Identificator: "TC-123"}
s.Require().NoError(s.CopyrightRepo.Create(context.Background(), copyright))
// Act
err := s.commands.AddCopyrightToWork(context.Background(), work.ID, copyright.ID)
// Assert
s.Require().NoError(err)
// Verify that the association was created in the database
var foundWork domain.Work
err = s.DB.Preload("Copyrights").First(&foundWork, work.ID).Error
s.Require().NoError(err)
s.Require().Len(foundWork.Copyrights, 1)
s.Equal(copyright.ID, foundWork.Copyrights[0].ID)
})
}
func (s *CopyrightCommandsTestSuite) TestRemoveCopyrightFromWork() {
s.Run("should remove a copyright from a work", func() {
// Arrange
work := s.CreateTestWork(s.AdminCtx, "Test Work", "en", "Test content")
copyright := &domain.Copyright{Name: "Test Copyright", Identificator: "TC-123"}
s.Require().NoError(s.CopyrightRepo.Create(context.Background(), copyright))
s.Require().NoError(s.commands.AddCopyrightToWork(context.Background(), work.ID, copyright.ID))
// Act
err := s.commands.RemoveCopyrightFromWork(context.Background(), work.ID, copyright.ID)
// Assert
s.Require().NoError(err)
// Verify that the association was removed from the database
var foundWork domain.Work
err = s.DB.Preload("Copyrights").First(&foundWork, work.ID).Error
s.Require().NoError(err)
s.Require().Len(foundWork.Copyrights, 0)
})
}
func (s *CopyrightCommandsTestSuite) TestAddCopyrightToAuthor() {
s.Run("should add a copyright to an author", func() {
// Arrange
author := &domain.Author{Name: "Test Author"}
s.Require().NoError(s.AuthorRepo.Create(context.Background(), author))
copyright := &domain.Copyright{Name: "Test Copyright", Identificator: "TC-123"}
s.Require().NoError(s.CopyrightRepo.Create(context.Background(), copyright))
// Act
err := s.commands.AddCopyrightToAuthor(context.Background(), author.ID, copyright.ID)
// Assert
s.Require().NoError(err)
var foundAuthor domain.Author
err = s.DB.Preload("Copyrights").First(&foundAuthor, author.ID).Error
s.Require().NoError(err)
s.Require().Len(foundAuthor.Copyrights, 1)
s.Equal(copyright.ID, foundAuthor.Copyrights[0].ID)
})
}
func (s *CopyrightCommandsTestSuite) TestRemoveCopyrightFromAuthor() {
s.Run("should remove a copyright from an author", func() {
// Arrange
author := &domain.Author{Name: "Test Author"}
s.Require().NoError(s.AuthorRepo.Create(context.Background(), author))
copyright := &domain.Copyright{Name: "Test Copyright", Identificator: "TC-123"}
s.Require().NoError(s.CopyrightRepo.Create(context.Background(), copyright))
s.Require().NoError(s.commands.AddCopyrightToAuthor(context.Background(), author.ID, copyright.ID))
// Act
err := s.commands.RemoveCopyrightFromAuthor(context.Background(), author.ID, copyright.ID)
// Assert
s.Require().NoError(err)
var foundAuthor domain.Author
err = s.DB.Preload("Copyrights").First(&foundAuthor, author.ID).Error
s.Require().NoError(err)
s.Require().Len(foundAuthor.Copyrights, 0)
})
}
func (s *CopyrightCommandsTestSuite) TestAddCopyrightToBook() {
s.Run("should add a copyright to a book", func() {
// Arrange
book := &domain.Book{Title: "Test Book"}
s.Require().NoError(s.BookRepo.Create(context.Background(), book))
copyright := &domain.Copyright{Name: "Test Copyright", Identificator: "TC-123"}
s.Require().NoError(s.CopyrightRepo.Create(context.Background(), copyright))
// Act
err := s.commands.AddCopyrightToBook(context.Background(), book.ID, copyright.ID)
// Assert
s.Require().NoError(err)
var foundBook domain.Book
err = s.DB.Preload("Copyrights").First(&foundBook, book.ID).Error
s.Require().NoError(err)
s.Require().Len(foundBook.Copyrights, 1)
s.Equal(copyright.ID, foundBook.Copyrights[0].ID)
})
}
func (s *CopyrightCommandsTestSuite) TestRemoveCopyrightFromBook() {
s.Run("should remove a copyright from a book", func() {
// Arrange
book := &domain.Book{Title: "Test Book"}
s.Require().NoError(s.BookRepo.Create(context.Background(), book))
copyright := &domain.Copyright{Name: "Test Copyright", Identificator: "TC-123"}
s.Require().NoError(s.CopyrightRepo.Create(context.Background(), copyright))
s.Require().NoError(s.commands.AddCopyrightToBook(context.Background(), book.ID, copyright.ID))
// Act
err := s.commands.RemoveCopyrightFromBook(context.Background(), book.ID, copyright.ID)
// Assert
s.Require().NoError(err)
var foundBook domain.Book
err = s.DB.Preload("Copyrights").First(&foundBook, book.ID).Error
s.Require().NoError(err)
s.Require().Len(foundBook.Copyrights, 0)
})
}
func (s *CopyrightCommandsTestSuite) TestAddCopyrightToPublisher() {
s.Run("should add a copyright to a publisher", func() {
// Arrange
publisher := &domain.Publisher{Name: "Test Publisher"}
s.Require().NoError(s.PublisherRepo.Create(context.Background(), publisher))
copyright := &domain.Copyright{Name: "Test Copyright", Identificator: "TC-123"}
s.Require().NoError(s.CopyrightRepo.Create(context.Background(), copyright))
// Act
err := s.commands.AddCopyrightToPublisher(context.Background(), publisher.ID, copyright.ID)
// Assert
s.Require().NoError(err)
var foundPublisher domain.Publisher
err = s.DB.Preload("Copyrights").First(&foundPublisher, publisher.ID).Error
s.Require().NoError(err)
s.Require().Len(foundPublisher.Copyrights, 1)
s.Equal(copyright.ID, foundPublisher.Copyrights[0].ID)
})
}
func (s *CopyrightCommandsTestSuite) TestRemoveCopyrightFromPublisher() {
s.Run("should remove a copyright from a publisher", func() {
// Arrange
publisher := &domain.Publisher{Name: "Test Publisher"}
s.Require().NoError(s.PublisherRepo.Create(context.Background(), publisher))
copyright := &domain.Copyright{Name: "Test Copyright", Identificator: "TC-123"}
s.Require().NoError(s.CopyrightRepo.Create(context.Background(), copyright))
s.Require().NoError(s.commands.AddCopyrightToPublisher(context.Background(), publisher.ID, copyright.ID))
// Act
err := s.commands.RemoveCopyrightFromPublisher(context.Background(), publisher.ID, copyright.ID)
// Assert
s.Require().NoError(err)
var foundPublisher domain.Publisher
err = s.DB.Preload("Copyrights").First(&foundPublisher, publisher.ID).Error
s.Require().NoError(err)
s.Require().Len(foundPublisher.Copyrights, 0)
})
}
func (s *CopyrightCommandsTestSuite) TestAddCopyrightToSource() {
s.Run("should add a copyright to a source", func() {
// Arrange
source := &domain.Source{Name: "Test Source"}
s.Require().NoError(s.SourceRepo.Create(context.Background(), source))
copyright := &domain.Copyright{Name: "Test Copyright", Identificator: "TC-123"}
s.Require().NoError(s.CopyrightRepo.Create(context.Background(), copyright))
// Act
err := s.commands.AddCopyrightToSource(context.Background(), source.ID, copyright.ID)
// Assert
s.Require().NoError(err)
var foundSource domain.Source
err = s.DB.Preload("Copyrights").First(&foundSource, source.ID).Error
s.Require().NoError(err)
s.Require().Len(foundSource.Copyrights, 1)
s.Equal(copyright.ID, foundSource.Copyrights[0].ID)
})
}
func (s *CopyrightCommandsTestSuite) TestRemoveCopyrightFromSource() {
s.Run("should remove a copyright from a source", func() {
// Arrange
source := &domain.Source{Name: "Test Source"}
s.Require().NoError(s.SourceRepo.Create(context.Background(), source))
copyright := &domain.Copyright{Name: "Test Copyright", Identificator: "TC-123"}
s.Require().NoError(s.CopyrightRepo.Create(context.Background(), copyright))
s.Require().NoError(s.commands.AddCopyrightToSource(context.Background(), source.ID, copyright.ID))
// Act
err := s.commands.RemoveCopyrightFromSource(context.Background(), source.ID, copyright.ID)
// Assert
s.Require().NoError(err)
var foundSource domain.Source
err = s.DB.Preload("Copyrights").First(&foundSource, source.ID).Error
s.Require().NoError(err)
s.Require().Len(foundSource.Copyrights, 0)
})
}
func TestCopyrightCommands(t *testing.T) {
suite.Run(t, new(CopyrightCommandsTestSuite))
}