package sql_test import ( "context" "database/sql/driver" "testing" "tercul/internal/data/sql" "tercul/internal/domain" "tercul/internal/platform/config" "time" "github.com/DATA-DOG/go-sqlmock" "github.com/stretchr/testify/suite" "gorm.io/driver/postgres" "gorm.io/gorm" ) // AnyTime is used to match any time.Time value in sqlmock. type AnyTime struct{} // Match satisfies sqlmock.Argument interface func (a AnyTime) Match(v driver.Value) bool { _, ok := v.(time.Time) return ok } // CopyrightRepositoryTestSuite is the test suite for CopyrightRepository. type CopyrightRepositoryTestSuite struct { suite.Suite db *gorm.DB mock sqlmock.Sqlmock repo domain.CopyrightRepository } // SetupTest sets up the test environment. func (s *CopyrightRepositoryTestSuite) SetupTest() { db, mock, err := sqlmock.New() s.Require().NoError(err) gormDB, err := gorm.Open(postgres.New(postgres.Config{Conn: db}), &gorm.Config{}) s.Require().NoError(err) s.db = gormDB s.mock = mock cfg, err := config.LoadConfig() s.Require().NoError(err) s.repo = sql.NewCopyrightRepository(s.db, cfg) } // TearDownTest checks if all expectations were met. func (s *CopyrightRepositoryTestSuite) TearDownTest() { s.Require().NoError(s.mock.ExpectationsWereMet()) } // TestCopyrightRepositoryTestSuite runs the test suite. func TestCopyrightRepositoryTestSuite(t *testing.T) { suite.Run(t, new(CopyrightRepositoryTestSuite)) } func (s *CopyrightRepositoryTestSuite) TestNewCopyrightRepository() { s.Run("should create a new repository", func() { s.NotNil(s.repo) }) } func (s *CopyrightRepositoryTestSuite) TestAddTranslation() { s.Run("should add a translation", func() { translation := &domain.CopyrightTranslation{ CopyrightID: 1, LanguageCode: "en", Message: "Test message", Description: "", } s.mock.ExpectBegin() s.mock.ExpectQuery(`INSERT INTO "copyright_translations" \("created_at","updated_at","copyright_id","language_code","message","description"\) VALUES \(\$1,\$2,\$3,\$4,\$5,\$6\) RETURNING "id"`). WithArgs(AnyTime{}, AnyTime{}, translation.CopyrightID, translation.LanguageCode, translation.Message, translation.Description). WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(1)) s.mock.ExpectCommit() err := s.repo.AddTranslation(context.Background(), translation) s.Require().NoError(err) }) } func (s *CopyrightRepositoryTestSuite) TestGetTranslations() { s.Run("should get all translations for a copyright", func() { copyrightID := uint(1) rows := sqlmock.NewRows([]string{"id", "copyright_id", "language_code", "message"}). AddRow(1, copyrightID, "en", "English message"). AddRow(2, copyrightID, "es", "Spanish message") s.mock.ExpectQuery(`SELECT \* FROM "copyright_translations" WHERE copyright_id = \$1`). WithArgs(copyrightID). WillReturnRows(rows) translations, err := s.repo.GetTranslations(context.Background(), copyrightID) s.Require().NoError(err) s.Require().Len(translations, 2) }) } func (s *CopyrightRepositoryTestSuite) TestGetTranslationByLanguage() { s.Run("should get a specific translation by language code", func() { copyrightID := uint(1) languageCode := "en" rows := sqlmock.NewRows([]string{"id", "copyright_id", "language_code", "message"}). AddRow(1, copyrightID, languageCode, "English message") s.mock.ExpectQuery(`SELECT \* FROM "copyright_translations" WHERE copyright_id = \$1 AND language_code = \$2 ORDER BY "copyright_translations"\."id" LIMIT \$3`). WithArgs(copyrightID, languageCode, 1). WillReturnRows(rows) translation, err := s.repo.GetTranslationByLanguage(context.Background(), copyrightID, languageCode) s.Require().NoError(err) s.Require().NotNil(translation) s.Require().Equal(languageCode, translation.LanguageCode) }) s.Run("should return ErrEntityNotFound for non-existent translation", func() { copyrightID := uint(1) languageCode := "en" s.mock.ExpectQuery(`SELECT \* FROM "copyright_translations" WHERE copyright_id = \$1 AND language_code = \$2 ORDER BY "copyright_translations"\."id" LIMIT \$3`). WithArgs(copyrightID, languageCode, 1). WillReturnError(gorm.ErrRecordNotFound) _, err := s.repo.GetTranslationByLanguage(context.Background(), copyrightID, languageCode) s.Require().Error(err) s.Require().Equal(sql.ErrEntityNotFound, err) }) } func (s *CopyrightRepositoryTestSuite) TestAddCopyrightToWork() { s.Run("should add a copyright to a work", func() { workID, copyrightID := uint(1), uint(1) s.mock.ExpectExec(`INSERT INTO work_copyrights \(work_id, copyright_id\) VALUES \(\$1, \$2\) ON CONFLICT DO NOTHING`). WithArgs(workID, copyrightID). WillReturnResult(sqlmock.NewResult(1, 1)) err := s.repo.AddCopyrightToWork(context.Background(), workID, copyrightID) s.Require().NoError(err) }) } func (s *CopyrightRepositoryTestSuite) TestRemoveCopyrightFromWork() { s.Run("should remove a copyright from a work", func() { workID, copyrightID := uint(1), uint(1) s.mock.ExpectExec(`DELETE FROM work_copyrights WHERE work_id = \$1 AND copyright_id = \$2`). WithArgs(workID, copyrightID). WillReturnResult(sqlmock.NewResult(1, 1)) err := s.repo.RemoveCopyrightFromWork(context.Background(), workID, copyrightID) s.Require().NoError(err) }) } func (s *CopyrightRepositoryTestSuite) TestAddCopyrightToAuthor() { s.Run("should add a copyright to an author", func() { authorID, copyrightID := uint(1), uint(1) s.mock.ExpectExec(`INSERT INTO author_copyrights \(author_id, copyright_id\) VALUES \(\$1, \$2\) ON CONFLICT DO NOTHING`). WithArgs(authorID, copyrightID). WillReturnResult(sqlmock.NewResult(1, 1)) err := s.repo.AddCopyrightToAuthor(context.Background(), authorID, copyrightID) s.Require().NoError(err) }) } func (s *CopyrightRepositoryTestSuite) TestRemoveCopyrightFromAuthor() { s.Run("should remove a copyright from an author", func() { authorID, copyrightID := uint(1), uint(1) s.mock.ExpectExec(`DELETE FROM author_copyrights WHERE author_id = \$1 AND copyright_id = \$2`). WithArgs(authorID, copyrightID). WillReturnResult(sqlmock.NewResult(1, 1)) err := s.repo.RemoveCopyrightFromAuthor(context.Background(), authorID, copyrightID) s.Require().NoError(err) }) } func (s *CopyrightRepositoryTestSuite) TestAddCopyrightToBook() { s.Run("should add a copyright to a book", func() { bookID, copyrightID := uint(1), uint(1) s.mock.ExpectExec(`INSERT INTO book_copyrights \(book_id, copyright_id\) VALUES \(\$1, \$2\) ON CONFLICT DO NOTHING`). WithArgs(bookID, copyrightID). WillReturnResult(sqlmock.NewResult(1, 1)) err := s.repo.AddCopyrightToBook(context.Background(), bookID, copyrightID) s.Require().NoError(err) }) } func (s *CopyrightRepositoryTestSuite) TestRemoveCopyrightFromBook() { s.Run("should remove a copyright from a book", func() { bookID, copyrightID := uint(1), uint(1) s.mock.ExpectExec(`DELETE FROM book_copyrights WHERE book_id = \$1 AND copyright_id = \$2`). WithArgs(bookID, copyrightID). WillReturnResult(sqlmock.NewResult(1, 1)) err := s.repo.RemoveCopyrightFromBook(context.Background(), bookID, copyrightID) s.Require().NoError(err) }) } func (s *CopyrightRepositoryTestSuite) TestAddCopyrightToPublisher() { s.Run("should add a copyright to a publisher", func() { publisherID, copyrightID := uint(1), uint(1) s.mock.ExpectExec(`INSERT INTO publisher_copyrights \(publisher_id, copyright_id\) VALUES \(\$1, \$2\) ON CONFLICT DO NOTHING`). WithArgs(publisherID, copyrightID). WillReturnResult(sqlmock.NewResult(1, 1)) err := s.repo.AddCopyrightToPublisher(context.Background(), publisherID, copyrightID) s.Require().NoError(err) }) } func (s *CopyrightRepositoryTestSuite) TestRemoveCopyrightFromPublisher() { s.Run("should remove a copyright from a publisher", func() { publisherID, copyrightID := uint(1), uint(1) s.mock.ExpectExec(`DELETE FROM publisher_copyrights WHERE publisher_id = \$1 AND copyright_id = \$2`). WithArgs(publisherID, copyrightID). WillReturnResult(sqlmock.NewResult(1, 1)) err := s.repo.RemoveCopyrightFromPublisher(context.Background(), publisherID, copyrightID) s.Require().NoError(err) }) } func (s *CopyrightRepositoryTestSuite) TestAddCopyrightToSource() { s.Run("should add a copyright to a source", func() { sourceID, copyrightID := uint(1), uint(1) s.mock.ExpectExec(`INSERT INTO source_copyrights \(source_id, copyright_id\) VALUES \(\$1, \$2\) ON CONFLICT DO NOTHING`). WithArgs(sourceID, copyrightID). WillReturnResult(sqlmock.NewResult(1, 1)) err := s.repo.AddCopyrightToSource(context.Background(), sourceID, copyrightID) s.Require().NoError(err) }) } func (s *CopyrightRepositoryTestSuite) TestRemoveCopyrightFromSource() { s.Run("should remove a copyright from a source", func() { sourceID, copyrightID := uint(1), uint(1) s.mock.ExpectExec(`DELETE FROM source_copyrights WHERE source_id = \$1 AND copyright_id = \$2`). WithArgs(sourceID, copyrightID). WillReturnResult(sqlmock.NewResult(1, 1)) err := s.repo.RemoveCopyrightFromSource(context.Background(), sourceID, copyrightID) s.Require().NoError(err) }) }