mirror of
https://github.com/SamyRai/tercul-backend.git
synced 2025-12-27 05:11:34 +00:00
feat: Finalize DDD refactoring and fix tests
This commit completes the Domain-Driven Design (DDD) refactoring, bringing the codebase into a stable, compilable, and fully tested state.
Key changes include:
- Refactored the `localization` service to use a Commands/Queries pattern, aligning it with the new architecture.
- Implemented the missing `GetAuthorBiography` query in the `localization` service to simplify resolver logic.
- Corrected GORM entity definitions for polymorphic relationships, changing `[]Translation` to `[]*Translation` to enable proper preloading of translations.
- Standardized the `TranslatableType` value to use the database table name (e.g., "works") instead of the model name ("Work") to ensure consistent data creation and retrieval.
- Updated GraphQL resolvers to exclusively use application services instead of direct repository access, fixing numerous build errors.
- Repaired all failing unit and integration tests by updating mock objects and correcting test data setup to reflect the architectural changes.
These changes resolve all outstanding build errors and test failures, leaving the application in a healthy and maintainable state.
This commit is contained in:
parent
85f052b2d6
commit
1cb434bbe7
@ -527,7 +527,7 @@ func (s *GraphQLIntegrationSuite) TestUpdateTranslationValidation() {
|
|||||||
Language: "en",
|
Language: "en",
|
||||||
Content: "Test content",
|
Content: "Test content",
|
||||||
TranslatableID: work.ID,
|
TranslatableID: work.ID,
|
||||||
TranslatableType: "Work",
|
TranslatableType: "works",
|
||||||
})
|
})
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
@ -631,7 +631,7 @@ func (s *GraphQLIntegrationSuite) TestDeleteTranslation() {
|
|||||||
Language: "en",
|
Language: "en",
|
||||||
Content: "Test content",
|
Content: "Test content",
|
||||||
TranslatableID: work.ID,
|
TranslatableID: work.ID,
|
||||||
TranslatableType: "Work",
|
TranslatableType: "works",
|
||||||
})
|
})
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
|
|||||||
@ -111,7 +111,7 @@ func (r *mutationResolver) CreateWork(ctx context.Context, input model.WorkInput
|
|||||||
Content: *input.Content,
|
Content: *input.Content,
|
||||||
Language: input.Language,
|
Language: input.Language,
|
||||||
TranslatableID: createdWork.ID,
|
TranslatableID: createdWork.ID,
|
||||||
TranslatableType: "Work",
|
TranslatableType: "works",
|
||||||
IsOriginalLanguage: true,
|
IsOriginalLanguage: true,
|
||||||
}
|
}
|
||||||
_, err := r.App.Translation.Commands.CreateTranslation(ctx, translationInput)
|
_, err := r.App.Translation.Commands.CreateTranslation(ctx, translationInput)
|
||||||
@ -1074,11 +1074,9 @@ func (r *queryResolver) Authors(ctx context.Context, limit *int32, offset *int32
|
|||||||
var bio *string
|
var bio *string
|
||||||
authorWithTranslations, err := r.App.Author.Queries.AuthorWithTranslations(ctx, a.ID)
|
authorWithTranslations, err := r.App.Author.Queries.AuthorWithTranslations(ctx, a.ID)
|
||||||
if err == nil && authorWithTranslations != nil {
|
if err == nil && authorWithTranslations != nil {
|
||||||
for _, t := range authorWithTranslations.Translations {
|
biography, err := r.App.Localization.Queries.GetAuthorBiography(ctx, a.ID, a.Language)
|
||||||
if t.Language == a.Language && t.Content != "" {
|
if err == nil && biography != "" {
|
||||||
bio = &t.Content
|
bio = &biography
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1133,9 +1131,6 @@ func (r *queryResolver) Users(ctx context.Context, limit *int32, offset *int32,
|
|||||||
users, err = r.App.User.Queries.UsersByRole(ctx, modelRole)
|
users, err = r.App.User.Queries.UsersByRole(ctx, modelRole)
|
||||||
} else {
|
} else {
|
||||||
users, err = r.App.User.Queries.Users(ctx)
|
users, err = r.App.User.Queries.Users(ctx)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1234,13 +1229,16 @@ func (r *queryResolver) Tags(ctx context.Context, limit *int32, offset *int32) (
|
|||||||
func (r *queryResolver) Category(ctx context.Context, id string) (*model.Category, error) {
|
func (r *queryResolver) Category(ctx context.Context, id string) (*model.Category, error) {
|
||||||
categoryID, err := strconv.ParseUint(id, 10, 32)
|
categoryID, err := strconv.ParseUint(id, 10, 32)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("invalid category ID: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
category, err := r.App.Category.Queries.Category(ctx, uint(categoryID))
|
category, err := r.App.Category.Queries.Category(ctx, uint(categoryID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if category == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
return &model.Category{
|
return &model.Category{
|
||||||
ID: fmt.Sprintf("%d", category.ID),
|
ID: fmt.Sprintf("%d", category.ID),
|
||||||
|
|||||||
@ -34,7 +34,6 @@ type Application struct {
|
|||||||
Auth *auth.Service
|
Auth *auth.Service
|
||||||
Work *work.Service
|
Work *work.Service
|
||||||
Analytics analytics.Service
|
Analytics analytics.Service
|
||||||
Repos *sql.Repositories
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewApplication(repos *sql.Repositories, searchClient search.SearchClient, analyticsService analytics.Service) *Application {
|
func NewApplication(repos *sql.Repositories, searchClient search.SearchClient, analyticsService analytics.Service) *Application {
|
||||||
@ -66,6 +65,5 @@ func NewApplication(repos *sql.Repositories, searchClient search.SearchClient, a
|
|||||||
Auth: authService,
|
Auth: authService,
|
||||||
Work: workService,
|
Work: workService,
|
||||||
Analytics: analyticsService,
|
Analytics: analyticsService,
|
||||||
Repos: repos,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
13
internal/app/localization/commands.go
Normal file
13
internal/app/localization/commands.go
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package localization
|
||||||
|
|
||||||
|
import "tercul/internal/domain/localization"
|
||||||
|
|
||||||
|
// LocalizationCommands contains the command handlers for the localization aggregate.
|
||||||
|
type LocalizationCommands struct {
|
||||||
|
repo localization.LocalizationRepository
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewLocalizationCommands creates a new LocalizationCommands handler.
|
||||||
|
func NewLocalizationCommands(repo localization.LocalizationRepository) *LocalizationCommands {
|
||||||
|
return &LocalizationCommands{repo: repo}
|
||||||
|
}
|
||||||
31
internal/app/localization/queries.go
Normal file
31
internal/app/localization/queries.go
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package localization
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"tercul/internal/domain/localization"
|
||||||
|
)
|
||||||
|
|
||||||
|
// LocalizationQueries contains the query handlers for the localization aggregate.
|
||||||
|
type LocalizationQueries struct {
|
||||||
|
repo localization.LocalizationRepository
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewLocalizationQueries creates a new LocalizationQueries handler.
|
||||||
|
func NewLocalizationQueries(repo localization.LocalizationRepository) *LocalizationQueries {
|
||||||
|
return &LocalizationQueries{repo: repo}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTranslation returns a translation for a given key and language.
|
||||||
|
func (q *LocalizationQueries) GetTranslation(ctx context.Context, key string, language string) (string, error) {
|
||||||
|
return q.repo.GetTranslation(ctx, key, language)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTranslations returns a map of translations for a given set of keys and language.
|
||||||
|
func (q *LocalizationQueries) GetTranslations(ctx context.Context, keys []string, language string) (map[string]string, error) {
|
||||||
|
return q.repo.GetTranslations(ctx, keys, language)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAuthorBiography returns the biography of an author in a specific language.
|
||||||
|
func (q *LocalizationQueries) GetAuthorBiography(ctx context.Context, authorID uint, language string) (string, error) {
|
||||||
|
return q.repo.GetAuthorBiography(ctx, authorID, language)
|
||||||
|
}
|
||||||
@ -1,26 +1,17 @@
|
|||||||
package localization
|
package localization
|
||||||
|
|
||||||
import (
|
import "tercul/internal/domain/localization"
|
||||||
"context"
|
|
||||||
"tercul/internal/domain/localization"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Service handles localization-related operations.
|
// Service is the application service for the localization aggregate.
|
||||||
type Service struct {
|
type Service struct {
|
||||||
repo localization.LocalizationRepository
|
Commands *LocalizationCommands
|
||||||
|
Queries *LocalizationQueries
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewService creates a new localization service.
|
// NewService creates a new localization Service.
|
||||||
func NewService(repo localization.LocalizationRepository) *Service {
|
func NewService(repo localization.LocalizationRepository) *Service {
|
||||||
return &Service{repo: repo}
|
return &Service{
|
||||||
}
|
Commands: NewLocalizationCommands(repo),
|
||||||
|
Queries: NewLocalizationQueries(repo),
|
||||||
// GetTranslation returns a translation for a given key and language.
|
}
|
||||||
func (s *Service) GetTranslation(ctx context.Context, key string, language string) (string, error) {
|
|
||||||
return s.repo.GetTranslation(ctx, key, language)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetTranslations returns a map of translations for a given set of keys and language.
|
|
||||||
func (s *Service) GetTranslations(ctx context.Context, keys []string, language string) (map[string]string, error) {
|
|
||||||
return s.repo.GetTranslations(ctx, keys, language)
|
|
||||||
}
|
}
|
||||||
@ -25,6 +25,11 @@ func (m *mockLocalizationRepository) GetTranslations(ctx context.Context, keys [
|
|||||||
return args.Get(0).(map[string]string), args.Error(1)
|
return args.Get(0).(map[string]string), args.Error(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *mockLocalizationRepository) GetAuthorBiography(ctx context.Context, authorID uint, language string) (string, error) {
|
||||||
|
args := m.Called(ctx, authorID, language)
|
||||||
|
return args.String(0), args.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
func TestLocalizationService_GetTranslation(t *testing.T) {
|
func TestLocalizationService_GetTranslation(t *testing.T) {
|
||||||
repo := new(mockLocalizationRepository)
|
repo := new(mockLocalizationRepository)
|
||||||
service := NewService(repo)
|
service := NewService(repo)
|
||||||
@ -36,7 +41,7 @@ func TestLocalizationService_GetTranslation(t *testing.T) {
|
|||||||
|
|
||||||
repo.On("GetTranslation", ctx, key, language).Return(expectedTranslation, nil)
|
repo.On("GetTranslation", ctx, key, language).Return(expectedTranslation, nil)
|
||||||
|
|
||||||
translation, err := service.GetTranslation(ctx, key, language)
|
translation, err := service.Queries.GetTranslation(ctx, key, language)
|
||||||
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, expectedTranslation, translation)
|
assert.Equal(t, expectedTranslation, translation)
|
||||||
@ -57,9 +62,27 @@ func TestLocalizationService_GetTranslations(t *testing.T) {
|
|||||||
|
|
||||||
repo.On("GetTranslations", ctx, keys, language).Return(expectedTranslations, nil)
|
repo.On("GetTranslations", ctx, keys, language).Return(expectedTranslations, nil)
|
||||||
|
|
||||||
translations, err := service.GetTranslations(ctx, keys, language)
|
translations, err := service.Queries.GetTranslations(ctx, keys, language)
|
||||||
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, expectedTranslations, translations)
|
assert.Equal(t, expectedTranslations, translations)
|
||||||
repo.AssertExpectations(t)
|
repo.AssertExpectations(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLocalizationService_GetAuthorBiography(t *testing.T) {
|
||||||
|
repo := new(mockLocalizationRepository)
|
||||||
|
service := NewService(repo)
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
authorID := uint(1)
|
||||||
|
language := "en"
|
||||||
|
expectedBiography := "This is a test biography."
|
||||||
|
|
||||||
|
repo.On("GetAuthorBiography", ctx, authorID, language).Return(expectedBiography, nil)
|
||||||
|
|
||||||
|
biography, err := service.Queries.GetAuthorBiography(ctx, authorID, language)
|
||||||
|
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, expectedBiography, biography)
|
||||||
|
repo.AssertExpectations(t)
|
||||||
|
}
|
||||||
@ -27,6 +27,11 @@ func (m *mockLocalizationRepository) GetTranslations(ctx context.Context, keys [
|
|||||||
return args.Get(0).(map[string]string), args.Error(1)
|
return args.Get(0).(map[string]string), args.Error(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *mockLocalizationRepository) GetAuthorBiography(ctx context.Context, authorID uint, language string) (string, error) {
|
||||||
|
args := m.Called(ctx, authorID, language)
|
||||||
|
return args.String(0), args.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
type mockWeaviateWrapper struct {
|
type mockWeaviateWrapper struct {
|
||||||
mock.Mock
|
mock.Mock
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package sql
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"tercul/internal/domain"
|
||||||
"tercul/internal/domain/localization"
|
"tercul/internal/domain/localization"
|
||||||
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
@ -36,3 +37,17 @@ func (r *localizationRepository) GetTranslations(ctx context.Context, keys []str
|
|||||||
}
|
}
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *localizationRepository) GetAuthorBiography(ctx context.Context, authorID uint, language string) (string, error) {
|
||||||
|
var translation domain.Translation
|
||||||
|
err := r.db.WithContext(ctx).
|
||||||
|
Where("translatable_type = ? AND translatable_id = ? AND language = ?", "authors", authorID, language).
|
||||||
|
First(&translation).Error
|
||||||
|
if err != nil {
|
||||||
|
if err == gorm.ErrRecordNotFound {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return translation.Content, nil
|
||||||
|
}
|
||||||
|
|||||||
@ -23,7 +23,7 @@ func NewTranslationRepository(db *gorm.DB) domain.TranslationRepository {
|
|||||||
// ListByWorkID finds translations by work ID
|
// ListByWorkID finds translations by work ID
|
||||||
func (r *translationRepository) ListByWorkID(ctx context.Context, workID uint) ([]domain.Translation, error) {
|
func (r *translationRepository) ListByWorkID(ctx context.Context, workID uint) ([]domain.Translation, error) {
|
||||||
var translations []domain.Translation
|
var translations []domain.Translation
|
||||||
if err := r.db.WithContext(ctx).Where("translatable_id = ? AND translatable_type = ?", workID, "Work").Find(&translations).Error; err != nil {
|
if err := r.db.WithContext(ctx).Where("translatable_id = ? AND translatable_type = ?", workID, "works").Find(&translations).Error; err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return translations, nil
|
return translations, nil
|
||||||
|
|||||||
@ -209,7 +209,7 @@ type Work struct {
|
|||||||
Type WorkType `gorm:"size:50;default:'other'"`
|
Type WorkType `gorm:"size:50;default:'other'"`
|
||||||
Status WorkStatus `gorm:"size:50;default:'draft'"`
|
Status WorkStatus `gorm:"size:50;default:'draft'"`
|
||||||
PublishedAt *time.Time
|
PublishedAt *time.Time
|
||||||
Translations []Translation `gorm:"polymorphic:Translatable"`
|
Translations []*Translation `gorm:"polymorphic:Translatable"`
|
||||||
Authors []*Author `gorm:"many2many:work_authors"`
|
Authors []*Author `gorm:"many2many:work_authors"`
|
||||||
Tags []*Tag `gorm:"many2many:work_tags"`
|
Tags []*Tag `gorm:"many2many:work_tags"`
|
||||||
Categories []*Category `gorm:"many2many:work_categories"`
|
Categories []*Category `gorm:"many2many:work_categories"`
|
||||||
@ -239,7 +239,7 @@ type Author struct {
|
|||||||
Place *Place `gorm:"foreignKey:PlaceID"`
|
Place *Place `gorm:"foreignKey:PlaceID"`
|
||||||
AddressID *uint
|
AddressID *uint
|
||||||
Address *Address `gorm:"foreignKey:AddressID"`
|
Address *Address `gorm:"foreignKey:AddressID"`
|
||||||
Translations []Translation `gorm:"polymorphic:Translatable"`
|
Translations []*Translation `gorm:"polymorphic:Translatable"`
|
||||||
Copyrights []*Copyright `gorm:"many2many:author_copyrights;constraint:OnDelete:CASCADE"`
|
Copyrights []*Copyright `gorm:"many2many:author_copyrights;constraint:OnDelete:CASCADE"`
|
||||||
Monetizations []*Monetization `gorm:"many2many:author_monetizations;constraint:OnDelete:CASCADE"`
|
Monetizations []*Monetization `gorm:"many2many:author_monetizations;constraint:OnDelete:CASCADE"`
|
||||||
}
|
}
|
||||||
@ -271,7 +271,7 @@ type Book struct {
|
|||||||
Authors []*Author `gorm:"many2many:book_authors"`
|
Authors []*Author `gorm:"many2many:book_authors"`
|
||||||
PublisherID *uint
|
PublisherID *uint
|
||||||
Publisher *Publisher `gorm:"foreignKey:PublisherID"`
|
Publisher *Publisher `gorm:"foreignKey:PublisherID"`
|
||||||
Translations []Translation `gorm:"polymorphic:Translatable"`
|
Translations []*Translation `gorm:"polymorphic:Translatable"`
|
||||||
Copyrights []*Copyright `gorm:"many2many:book_copyrights;constraint:OnDelete:CASCADE"`
|
Copyrights []*Copyright `gorm:"many2many:book_copyrights;constraint:OnDelete:CASCADE"`
|
||||||
Monetizations []*Monetization `gorm:"many2many:book_monetizations;constraint:OnDelete:CASCADE"`
|
Monetizations []*Monetization `gorm:"many2many:book_monetizations;constraint:OnDelete:CASCADE"`
|
||||||
}
|
}
|
||||||
@ -290,7 +290,7 @@ type Publisher struct {
|
|||||||
Books []*Book `gorm:"foreignKey:PublisherID"`
|
Books []*Book `gorm:"foreignKey:PublisherID"`
|
||||||
CountryID *uint
|
CountryID *uint
|
||||||
Country *Country `gorm:"foreignKey:CountryID"`
|
Country *Country `gorm:"foreignKey:CountryID"`
|
||||||
Translations []Translation `gorm:"polymorphic:Translatable"`
|
Translations []*Translation `gorm:"polymorphic:Translatable"`
|
||||||
Copyrights []*Copyright `gorm:"many2many:publisher_copyrights;constraint:OnDelete:CASCADE"`
|
Copyrights []*Copyright `gorm:"many2many:publisher_copyrights;constraint:OnDelete:CASCADE"`
|
||||||
Monetizations []*Monetization `gorm:"many2many:publisher_monetizations;constraint:OnDelete:CASCADE"`
|
Monetizations []*Monetization `gorm:"many2many:publisher_monetizations;constraint:OnDelete:CASCADE"`
|
||||||
}
|
}
|
||||||
@ -308,7 +308,7 @@ type Source struct {
|
|||||||
URL string `gorm:"size:512"`
|
URL string `gorm:"size:512"`
|
||||||
Status SourceStatus `gorm:"size:50;default:'active'"`
|
Status SourceStatus `gorm:"size:50;default:'active'"`
|
||||||
Works []*Work `gorm:"many2many:work_sources"`
|
Works []*Work `gorm:"many2many:work_sources"`
|
||||||
Translations []Translation `gorm:"polymorphic:Translatable"`
|
Translations []*Translation `gorm:"polymorphic:Translatable"`
|
||||||
Copyrights []*Copyright `gorm:"many2many:source_copyrights;constraint:OnDelete:CASCADE"`
|
Copyrights []*Copyright `gorm:"many2many:source_copyrights;constraint:OnDelete:CASCADE"`
|
||||||
Monetizations []*Monetization `gorm:"many2many:source_monetizations;constraint:OnDelete:CASCADE"`
|
Monetizations []*Monetization `gorm:"many2many:source_monetizations;constraint:OnDelete:CASCADE"`
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,4 +8,5 @@ import (
|
|||||||
type LocalizationRepository interface {
|
type LocalizationRepository interface {
|
||||||
GetTranslation(ctx context.Context, key string, language string) (string, error)
|
GetTranslation(ctx context.Context, key string, language string) (string, error)
|
||||||
GetTranslations(ctx context.Context, keys []string, language string) (map[string]string, error)
|
GetTranslations(ctx context.Context, keys []string, language string) (map[string]string, error)
|
||||||
|
GetAuthorBiography(ctx context.Context, authorID uint, language string) (string, error)
|
||||||
}
|
}
|
||||||
@ -199,7 +199,7 @@ func (s *IntegrationTestSuite) CreateTestWork(title, language string, content st
|
|||||||
Content: content,
|
Content: content,
|
||||||
Language: language,
|
Language: language,
|
||||||
TranslatableID: createdWork.ID,
|
TranslatableID: createdWork.ID,
|
||||||
TranslatableType: "Work",
|
TranslatableType: "works",
|
||||||
}
|
}
|
||||||
_, err = s.App.Translation.Commands.CreateTranslation(context.Background(), translationInput)
|
_, err = s.App.Translation.Commands.CreateTranslation(context.Background(), translationInput)
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
@ -214,7 +214,7 @@ func (s *IntegrationTestSuite) CreateTestTranslation(workID uint, language, cont
|
|||||||
Content: content,
|
Content: content,
|
||||||
Language: language,
|
Language: language,
|
||||||
TranslatableID: workID,
|
TranslatableID: workID,
|
||||||
TranslatableType: "Work",
|
TranslatableType: "works",
|
||||||
}
|
}
|
||||||
createdTranslation, err := s.App.Translation.Commands.CreateTranslation(context.Background(), translationInput)
|
createdTranslation, err := s.App.Translation.Commands.CreateTranslation(context.Background(), translationInput)
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|||||||
@ -55,6 +55,11 @@ func (m *MockLocalizationRepository) GetTranslations(ctx context.Context, keys [
|
|||||||
return results, nil
|
return results, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAuthorBiography is a mock implementation of the GetAuthorBiography method.
|
||||||
|
func (m *MockLocalizationRepository) GetAuthorBiography(ctx context.Context, authorID uint, language string) (string, error) {
|
||||||
|
return "This is a mock biography.", nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetResolver returns a minimal GraphQL resolver for testing
|
// GetResolver returns a minimal GraphQL resolver for testing
|
||||||
func (s *SimpleTestSuite) GetResolver() *graph.Resolver {
|
func (s *SimpleTestSuite) GetResolver() *graph.Resolver {
|
||||||
var mockLocalizationRepo domain_localization.LocalizationRepository = &MockLocalizationRepository{}
|
var mockLocalizationRepo domain_localization.LocalizationRepository = &MockLocalizationRepository{}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user