package test import ( "RenewCMS/internal/domain/article" entity "RenewCMS/internal/infrastructure/persistence/models" persistence "RenewCMS/internal/infrastructure/persistence/repositories" "net/http" "slices" "testing" "gorm.io/gorm" ) func TestAccountExportDataReadsContract(t *testing.T) { backends := []contractBackend{ {name: "sqlite", open: openContractSQLite}, {name: "mysql", open: openContractMySQL}, {name: "postgres", open: openContractPostgres}, } for _, backend := range backends { t.Run(backend.name, func(t *testing.T) { t.Run("articles are those created by the user, drafts included, or published ones crediting the user's author, without soft-deleted ones", func(t *testing.T) { db := backend.open(t) seedExportRows(t, db) articles := persistence.NewArticleRepository(db) authorID := uint32(5) mine, err := articles.ListForAccount(7, nil) credited, creditedErr := articles.ListForAccount(7, &authorID) if err != nil || creditedErr != nil { t.Fatalf("errors %v %v", err, creditedErr) } if got := articleIDs(mine); !slices.Equal(got, []uint32{1, 8}) { t.Errorf("created by marta %v", got) } if got := articleIDs(credited); !slices.Equal(got, []uint32{1, 3, 8}) { t.Errorf("created or credited %v", got) } }) t.Run("entries are those created by the user", func(t *testing.T) { db := backend.open(t) seedExportRows(t, db) entries, err := persistence.NewEntryRepository(db).ListByCreator(7) if err != nil || len(entries) != 1 || entries[0].ID != 1 { t.Errorf("entries %+v %v", entries, err) } }) t.Run("images are those uploaded by the user without soft-deleted ones", func(t *testing.T) { db := backend.open(t) seedExportRows(t, db) images, err := persistence.NewImageRepository(db).ListByUploader(7) if err != nil || len(images) != 1 || images[0].ID != 1 { t.Errorf("images %+v %v", images, err) } }) }) } } func articleIDs(listed []article.Article) []uint32 { ids := make([]uint32, 0, len(listed)) for _, item := range listed { ids = append(ids, item.ID) } return ids } func seedExportRows(t *testing.T, db *gorm.DB) { t.Helper() rows := []any{ &entity.Article{ID: 1, Title: "Mine", Slug: "mine", CreatedBy: 7}, &entity.Article{ID: 2, Title: "Ines", Slug: "ines", CreatedBy: 8}, &entity.Article{ID: 3, Title: "Credited", Slug: "credited", CreatedBy: 8, IsOnline: true}, &entity.Article{ID: 7, Title: "Credited draft", Slug: "credited-draft", CreatedBy: 8}, &entity.Article{ID: 8, Title: "Mine draft", Slug: "mine-draft", CreatedBy: 7}, &entity.Article{ID: 4, Title: "Gone", Slug: "gone", CreatedBy: 7}, &entity.Article{ID: 6, Title: "Credited gone", Slug: "credited-gone", CreatedBy: 8, IsOnline: true}, &entity.ArticleAuthor{ArticleID: 3, AuthorID: 5}, &entity.ArticleAuthor{ArticleID: 7, AuthorID: 5}, &entity.ArticleAuthor{ArticleID: 6, AuthorID: 5}, &entity.Entry{ID: 1, ContentTypeID: 1, Data: "{}", CreatedBy: 7, UpdatedBy: 7}, &entity.Entry{ID: 2, ContentTypeID: 1, Data: "{}", CreatedBy: 8, UpdatedBy: 8}, &entity.Image{ID: 1, Path: "/a.png", Filename: "a.png", UploadedByID: 7}, &entity.Image{ID: 2, Path: "/b.png", Filename: "b.png", UploadedByID: 8}, &entity.Image{ID: 3, Path: "/c.png", Filename: "c.png", UploadedByID: 7}, } for _, row := range rows { if err := db.Create(row).Error; err != nil { t.Fatalf("seed %T: %v", row, err) } } for _, id := range []uint32{4, 6} { if err := db.Delete(&entity.Article{}, id).Error; err != nil { t.Fatalf("soft delete article %d: %v", id, err) } } if err := db.Delete(&entity.Image{}, 3).Error; err != nil { t.Fatalf("soft delete image: %v", err) } } func TestAccountExportDataFilenameHTTP(t *testing.T) { cases := map[string]string{ "Marta.Alves_2": "renewcms-export-marta-alves-2-2026-10-29.zip", "ÉLODIE": "renewcms-export-lodie-2026-10-29.zip", "***": "renewcms-export-user-2026-10-29.zip", "az09": "renewcms-export-az09-2026-10-29.zip", } for username, filename := range cases { t.Run(username, func(t *testing.T) { f := newExportFixture(t) stored := f.users.users[exportMartaID] stored.Username = username f.users.users[exportMartaID] = stored rec := f.export(t, exportMartaID) expected := `attachment; filename="` + filename + `"` if rec.Code != http.StatusOK || rec.Header().Get("Content-Disposition") != expected { t.Errorf("got %d %q, want %q", rec.Code, rec.Header().Get("Content-Disposition"), expected) } }) } }