package test import ( "RenewCMS/internal/domain/article" imageDomain "RenewCMS/internal/domain/image" "RenewCMS/internal/infrastructure/useCases" "errors" "sort" "testing" "gorm.io/gorm" ) type mockArticleRepo struct { articles map[uint32]article.Article images map[uint32]*imageDomain.Image nextID uint32 fail failSwitch } func newMockArticleRepo() *mockArticleRepo { return &mockArticleRepo{ articles: make(map[uint32]article.Article), images: make(map[uint32]*imageDomain.Image), } } func (m *mockArticleRepo) sortedIds() []uint32 { ids := make([]uint32, 0, len(m.articles)) for id := range m.articles { ids = append(ids, id) } sort.Slice(ids, func(i, j int) bool { return ids[i] < ids[j] }) return ids } func (m *mockArticleRepo) FindByFilters(filters article.Filters) ([]article.Article, error) { if err := m.fail.trigger("FindByFilters"); err != nil { return nil, err } result := make([]article.Article, 0) for _, id := range m.sortedIds() { a := m.articles[id] if filters.IsOnline != nil && a.IsOnline != *filters.IsOnline { continue } result = append(result, a) } return result, nil } func (m *mockArticleRepo) Get(id uint32) (article.Article, error) { if err := m.fail.trigger("Get"); err != nil { return article.Article{}, err } a, ok := m.articles[id] if !ok { return article.Article{}, gorm.ErrRecordNotFound } return a, nil } func (m *mockArticleRepo) GetByName(name string) (article.Article, error) { if err := m.fail.trigger("GetByName"); err != nil { return article.Article{}, err } for _, id := range m.sortedIds() { a := m.articles[id] if a.Title == name { return a, nil } } return article.Article{}, gorm.ErrRecordNotFound } func (m *mockArticleRepo) GetAll() []article.Article { result := make([]article.Article, 0) for _, id := range m.sortedIds() { result = append(result, m.articles[id]) } return result } func (m *mockArticleRepo) Create(a article.Article) (article.Article, error) { if err := m.fail.trigger("Create"); err != nil { return article.Article{}, err } m.nextID++ a.ID = m.nextID m.articles[a.ID] = a return a, nil } func (m *mockArticleRepo) UpdateBody(id uint32, body string) (article.Article, error) { if err := m.fail.trigger("UpdateBody"); err != nil { return article.Article{}, err } a, ok := m.articles[id] if !ok { return article.Article{}, gorm.ErrRecordNotFound } a.Body = body m.articles[id] = a return a, nil } func (m *mockArticleRepo) UpdateIsOnline(id uint32, isOnline bool) (article.Article, error) { if err := m.fail.trigger("UpdateIsOnline"); err != nil { return article.Article{}, err } a, ok := m.articles[id] if !ok { return article.Article{}, gorm.ErrRecordNotFound } a.IsOnline = isOnline m.articles[id] = a return a, nil } func (m *mockArticleRepo) Delete(id uint32) error { if err := m.fail.trigger("Delete"); err != nil { return err } delete(m.articles, id) return nil } func (m *mockArticleRepo) AddImage(articleId uint32, imageId uint32) error { if err := m.fail.trigger("AddImage"); err != nil { return err } a, ok := m.articles[articleId] if !ok { return gorm.ErrRecordNotFound } img, ok := m.images[imageId] if !ok { return gorm.ErrRecordNotFound } a.Images = append(a.Images, img) m.articles[articleId] = a return nil } var _ article.Repository = &mockArticleRepo{} func TestCreateArticle(t *testing.T) { repo := newMockArticleRepo() uc := useCases.NewCreateArticleUseCase(repo) t.Run("Valid Title", func(t *testing.T) { cmd := useCases.CreateArticleCommand{Title: "Valid Title", Body: "Content"} res, err := uc.CreateArticle(cmd) if err != nil { t.Fatalf("Expected no error, got %v", err) } if res.Title != cmd.Title { t.Errorf("Expected %s, got %s", cmd.Title, res.Title) } }) t.Run("Short Title", func(t *testing.T) { cmd := useCases.CreateArticleCommand{Title: "Ab", Body: "Content"} _, err := uc.CreateArticle(cmd) if !errors.Is(err, article.ErrInvalidTitle) { t.Errorf("Expected ErrInvalidTitle") } }) } func TestGetOnlineArticle(t *testing.T) { repo := newMockArticleRepo() repo.articles[1] = article.Article{ID: 1, IsOnline: true} repo.articles[2] = article.Article{ID: 2, IsOnline: false} uc := useCases.NewGetArticleUseCase(repo) t.Run("Article Online", func(t *testing.T) { _, err := uc.GetOnlineArticle(1) if err != nil { t.Errorf("Expected article to be found") } }) t.Run("Article Offline", func(t *testing.T) { _, err := uc.GetOnlineArticle(2) if !errors.Is(err, article.ErrArticleNotFound) { t.Errorf("Offline article should return not found") } }) }