feat: Sites feature backend
This commit is contained in:
1 parent
45fcbd890d
commit
a11338094e
98 files changed
+5365
-214
No files matched your search
@@ -0,0 +1,140 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"RenewCMS/internal/domain/article"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type mediaListBody struct {
|
||||
Items []struct {
|
||||
ID uint32 `json:"id"`
|
||||
UsedIn int `json:"used_in"`
|
||||
} `json:"items"`
|
||||
Counts struct {
|
||||
Unused int `json:"unused"`
|
||||
} `json:"counts"`
|
||||
}
|
||||
|
||||
func (e *siteEnv) useImageOnSite(siteID uint32, imageID uint32) {
|
||||
s := e.sites.sites[siteID]
|
||||
s.DefaultSocialImageID = idPointer(imageID)
|
||||
e.sites.sites[siteID] = s
|
||||
}
|
||||
|
||||
func (e *siteEnv) seedDuplicates() {
|
||||
e.seedBanner(5, "banner.png", "samehash")
|
||||
e.seedBanner(6, "banner-copy.png", "samehash")
|
||||
}
|
||||
|
||||
func TestSitesMediaUsage(t *testing.T) {
|
||||
t.Run("An image used as a default social image is counted as used", func(t *testing.T) {
|
||||
e := newSiteEnvWithShop(t)
|
||||
e.seedBanner(5, "banner.png", "hash")
|
||||
e.useImageOnSite(siteShopID, 5)
|
||||
|
||||
rec := e.owner(t, http.MethodGet, "/v1/media/", "")
|
||||
unused := e.owner(t, http.MethodGet, "/v1/media/?filter=unused", "")
|
||||
|
||||
var list, unusedList mediaListBody
|
||||
_ = json.Unmarshal(rec.Body.Bytes(), &list)
|
||||
_ = json.Unmarshal(unused.Body.Bytes(), &unusedList)
|
||||
if len(list.Items) != 1 || list.Items[0].UsedIn != 1 || list.Counts.Unused != 0 || len(unusedList.Items) != 0 {
|
||||
t.Errorf("list %s, unused %s", rec.Body.String(), unused.Body.String())
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Deleting the image clears the site's field", func(t *testing.T) {
|
||||
e := newSiteEnvWithShop(t)
|
||||
e.seedBanner(5, "banner.png", "hash")
|
||||
e.useImageOnSite(siteShopID, 5)
|
||||
|
||||
rec := e.owner(t, http.MethodDelete, "/v1/media/5", "")
|
||||
|
||||
if rec.Code != http.StatusNoContent || e.sites.sites[siteShopID].DefaultSocialImageID != nil {
|
||||
t.Errorf("status %d, image %v", rec.Code, e.sites.sites[siteShopID].DefaultSocialImageID)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("A failed image deletion keeps the site's field", func(t *testing.T) {
|
||||
e := newSiteEnvWithShop(t)
|
||||
e.seedBanner(5, "banner.png", "hash")
|
||||
e.useImageOnSite(siteShopID, 5)
|
||||
e.images.failDeleteFor = map[uint32]error{5: errRepositoryFailure}
|
||||
|
||||
rec := e.owner(t, http.MethodDelete, "/v1/media/5", "")
|
||||
|
||||
if rec.Code != http.StatusInternalServerError || e.sites.sites[siteShopID].DefaultSocialImageID == nil {
|
||||
t.Errorf("status %d, image %v", rec.Code, e.sites.sites[siteShopID].DefaultSocialImageID)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Merging copies repoints the site", func(t *testing.T) {
|
||||
e := newSiteEnvWithShop(t)
|
||||
e.seedDuplicates()
|
||||
e.useImageOnSite(siteShopID, 6)
|
||||
|
||||
rec := e.owner(t, http.MethodPost, "/v1/media/merge", `{"keep_id": 5, "merge_ids": [6]}`)
|
||||
|
||||
var body map[string]int
|
||||
_ = json.Unmarshal(rec.Body.Bytes(), &body)
|
||||
kept := e.sites.sites[siteShopID].DefaultSocialImageID
|
||||
if rec.Code != http.StatusOK || body["sites_updated"] != 1 || kept == nil || *kept != 5 {
|
||||
t.Errorf("status %d, body %s, image %v", rec.Code, rec.Body.String(), kept)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Purge repoints sites the same way", func(t *testing.T) {
|
||||
e := newSiteEnvWithShop(t)
|
||||
e.seedDuplicates()
|
||||
e.articles.articles[1] = articleUsingImage(5)
|
||||
e.useImageOnSite(siteShopID, 6)
|
||||
|
||||
rec := e.owner(t, http.MethodPost, "/v1/media/purge", "")
|
||||
|
||||
var body map[string]int
|
||||
_ = json.Unmarshal(rec.Body.Bytes(), &body)
|
||||
kept := e.sites.sites[siteShopID].DefaultSocialImageID
|
||||
if rec.Code != http.StatusOK || body["sites_updated"] != 1 || kept == nil || *kept != 5 {
|
||||
t.Errorf("status %d, body %s, image %v", rec.Code, rec.Body.String(), kept)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("A failed purge group leaves the site pointing at an existing image", func(t *testing.T) {
|
||||
e := newSiteEnvWithShop(t)
|
||||
e.seedDuplicates()
|
||||
e.articles.articles[1] = articleUsingImage(5)
|
||||
e.useImageOnSite(siteShopID, 6)
|
||||
e.images.failDeleteFor = map[uint32]error{6: errRepositoryFailure}
|
||||
|
||||
rec := e.owner(t, http.MethodPost, "/v1/media/purge", "")
|
||||
|
||||
referenced := e.sites.sites[siteShopID].DefaultSocialImageID
|
||||
if rec.Code != http.StatusOK || referenced == nil {
|
||||
t.Fatalf("status %d, image %v", rec.Code, referenced)
|
||||
}
|
||||
if _, exists := e.images.images[*referenced]; !exists {
|
||||
t.Errorf("the site points at the missing image %d", *referenced)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("The usage lookup array shape is unchanged", func(t *testing.T) {
|
||||
e := newSiteEnvWithShop(t)
|
||||
e.seedBanner(5, "banner.png", "hash")
|
||||
e.useImageOnSite(siteShopID, 5)
|
||||
e.articles.articles[1] = articleUsingImage(5)
|
||||
|
||||
rec := e.owner(t, http.MethodGet, "/v1/media/5/usage", "")
|
||||
|
||||
if rec.Code != http.StatusOK || !strings.HasPrefix(rec.Body.String(), `[{"id":1,"title":`) || strings.Contains(rec.Body.String(), "site") {
|
||||
t.Errorf("status %d, body %s", rec.Code, rec.Body.String())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func articleUsingImage(imageID uint32) article.Article {
|
||||
return article.Article{ID: 1, Title: "Spring release", Body: `<img src="` + producersBannerPath + strconv.Itoa(int(imageID)) + `.png">`, IsOnline: true, SiteID: siteMainID}
|
||||
}
|
||||
Reference in new issue
Block a user