package test import ( domainArticle "RenewCMS/internal/domain/article" domainSite "RenewCMS/internal/domain/site" persistence "RenewCMS/internal/infrastructure/persistence/repositories" "errors" "testing" ) func TestArticleRepositoryLocksOnlyWhenASiteIsInvolved(t *testing.T) { t.Run("Creating an article without a site does not look up a site", func(t *testing.T) { articles := persistence.NewArticleRepository(openContractSQLite(t)) created, err := articles.Create(newStorageArticle(0, "", "orphan", 0)) if err != nil { t.Fatalf("expected the siteless article to be created, got %v", err) } if created.ID == 0 || created.SiteID != 0 { t.Errorf("unexpected created article: %+v", created) } }) t.Run("Creating an article on a missing site fails", func(t *testing.T) { articles := persistence.NewArticleRepository(openContractSQLite(t)) _, err := articles.Create(newStorageArticle(9999, "", "ghost", 0)) if !errors.Is(err, domainSite.ErrSiteNotFound) { t.Errorf("expected ErrSiteNotFound, got %v", err) } }) t.Run("Updating the excerpt of a siteless article does not look up a site", func(t *testing.T) { articles := persistence.NewArticleRepository(openContractSQLite(t)) created, err := articles.Create(newStorageArticle(0, "", "orphan", 0)) if err != nil { t.Fatal(err) } updated, err := articles.Update(created.ID, domainArticle.Update{Excerpt: localeOf("Renamed")}) if err != nil || updated.Excerpt != "Renamed" { t.Errorf("expected the excerpt update to succeed, got %+v %v", updated, err) } }) t.Run("Moving a siteless article to a site while setting a slug locks only the target", func(t *testing.T) { db := openContractSQLite(t) articles := persistence.NewArticleRepository(db) site := storageDefaultSite(t, db) created, err := articles.Create(newStorageArticle(0, "", "orphan", 0)) if err != nil { t.Fatal(err) } updated, err := articles.Update(created.ID, domainArticle.Update{SiteID: &site.ID, Slug: localeOf("moved")}) if err != nil || updated.SiteID != site.ID || updated.Slug != "moved" { t.Errorf("expected the move to succeed, got %+v %v", updated, err) } if stored := storedArticle(t, db, created.ID); stored.SiteID != site.ID || stored.Slug != "moved" { t.Errorf("the move must be persisted, got site %d slug %q", stored.SiteID, stored.Slug) } }) t.Run("Setting a slug on a siteless article needs its site", func(t *testing.T) { articles := persistence.NewArticleRepository(openContractSQLite(t)) created, err := articles.Create(newStorageArticle(0, "", "orphan", 0)) if err != nil { t.Fatal(err) } _, err = articles.Update(created.ID, domainArticle.Update{Slug: localeOf("renamed")}) if !errors.Is(err, domainSite.ErrSiteNotFound) { t.Errorf("expected ErrSiteNotFound, got %v", err) } }) } func TestArticleRepositoryPersistsASlugChange(t *testing.T) { db := openContractSQLite(t) articles := persistence.NewArticleRepository(db) site := storageDefaultSite(t, db) created, err := articles.Create(newStorageArticle(site.ID, "", "before", 0)) if err != nil { t.Fatal(err) } updated, err := articles.Update(created.ID, domainArticle.Update{Slug: localeOf("after")}) if err != nil || updated.Slug != "after" { t.Fatalf("expected the slug change to succeed, got %+v %v", updated, err) } if stored := storedArticle(t, db, created.ID); stored.Slug != "after" { t.Errorf("the slug change must be persisted, got %q", stored.Slug) } }