Files
RenewCMS/test/article_localization_storage_http_test.go
T

123 lines
5.1 KiB
Go

package test
import (
domainArticle "RenewCMS/internal/domain/article"
"encoding/json"
"net/http"
"testing"
)
const (
localizedArticleID = 12
localizedArticleStory = 5
)
var legacyListItemKeys = []string{"id", "title", "body", "body_format", "is_online", "site_id", "authors", "created_at", "updated_at", "excerpt", "slug", "seo_status", "seo_suggestions"}
var legacyArticleKeys = []string{"id", "title", "body", "is_online", "site_id", "authors", "slug", "excerpt", "seo_title", "seo_description", "cover_image_id", "cover_image_alt", "social_title", "social_description", "social_image_id", "canonical_url", "noindex", "seo_dismissed", "created_at", "updated_at"}
func localizedArticle(lang string, online bool) domainArticle.Article {
return domainArticle.Article{ID: localizedArticleID, Title: "Bonjour le monde", IsOnline: online, CreatedBy: createdByWriterID, Lang: lang, StoryID: localizedArticleStory}
}
func TestArticleLocalizationStorageHTTP(t *testing.T) {
assertFields := func(t *testing.T, fields map[string]string, lang string, legacyKeys []string) {
t.Helper()
if fields["lang"] != `"`+lang+`"` || fields["story_id"] != "5" {
t.Errorf(`expected lang %q and story_id 5, got lang=%s story_id=%s`, lang, fields["lang"], fields["story_id"])
}
for _, key := range legacyKeys {
if _, present := fields[key]; !present {
t.Errorf("legacy key %q is missing", key)
}
}
}
readers := []struct {
name string
lang string
path string
auth bool
list bool
on bool
}{
{"GET /v1/article/12 with a valid jwt", "fr-CA", "/v1/article/12", true, false, false},
{"GET /v1/article/12 with a valid jwt and no language", "", "/v1/article/12", true, false, false},
{"GET /v1/article/ list item", "fr-CA", "/v1/article/", true, true, false},
{"public article read of an online article", "fr-CA", "/v1/article/12", false, false, true},
}
for _, reader := range readers {
t.Run("Article reads expose lang and story_id "+reader.name, func(t *testing.T) {
e, router := newCreatedByEnv(t)
e.articles.articles[localizedArticleID] = localizedArticle(reader.lang, reader.on)
var options []activityRequest
if reader.auth {
options = append(options, asUser(e, activityOwnerID))
}
rec := sendCreatedBy(router, http.MethodGet, reader.path, "", options...)
if rec.Code != http.StatusOK {
t.Fatalf("status %d: %s", rec.Code, rec.Body)
}
var fields map[string]string
if reader.list {
for _, item := range decodeArticleItems(t, rec.Body.Bytes()) {
if string(item["id"]) == "12" {
fields = rawFields(item)
}
}
} else {
fields = rawFields(decodeArticleFields(t, rec.Body.Bytes()))
}
if fields == nil {
t.Fatalf("article 12 not found in %s", rec.Body)
}
legacyKeys := legacyArticleKeys
if reader.list {
legacyKeys = legacyListItemKeys
}
assertFields(t, fields, reader.lang, legacyKeys)
})
}
t.Run("Article write payloads cannot set lang or story_id", func(t *testing.T) {
e, router := newCreatedByEnv(t)
e.articles.articles[localizedArticleID] = localizedArticle("fr-CA", false)
created := sendCreatedBy(router, http.MethodPost, "/v1/article/", `{"title":"Fresh draft title","body":"","lang":"en","story_id":99}`, asUser(e, createdByWriterID))
patched := sendCreatedBy(router, http.MethodPatch, "/v1/article/12", `{"excerpt":"Short","lang":"en","story_id":99}`, asUser(e, activityOwnerID))
if created.Code != http.StatusCreated || patched.Code != http.StatusOK {
t.Fatalf("statuses %d and %d: %s %s", created.Code, patched.Code, created.Body, patched.Body)
}
createdFields := rawFields(decodeArticleFields(t, created.Body.Bytes()))
if createdFields["lang"] == `"en"` || createdFields["story_id"] == "99" {
t.Errorf("the create payload set lang or story_id: %v", createdFields)
}
assertFields(t, rawFields(decodeArticleFields(t, patched.Body.Bytes())), "fr-CA", legacyArticleKeys)
if stored := e.articles.articles[localizedArticleID]; stored.Lang != "fr-CA" || stored.StoryID != localizedArticleStory {
t.Errorf("the stored language or story changed: %+v", stored)
}
})
t.Run("A patch carrying only lang and story_id is refused like a patch with no updatable field", func(t *testing.T) {
e, router := newCreatedByEnv(t)
e.articles.articles[localizedArticleID] = localizedArticle("fr-CA", false)
empty := sendCreatedBy(router, http.MethodPatch, "/v1/article/12", `{}`, asUser(e, activityOwnerID))
localizationOnly := sendCreatedBy(router, http.MethodPatch, "/v1/article/12", `{"lang":"en","story_id":99}`, asUser(e, activityOwnerID))
if empty.Code != http.StatusBadRequest || localizationOnly.Code != empty.Code {
t.Fatalf("expected both to be refused with 400, got %d and %d", empty.Code, localizationOnly.Code)
}
if stored := e.articles.articles[localizedArticleID]; stored.Lang != "fr-CA" || stored.StoryID != localizedArticleStory {
t.Errorf("the stored language or story changed: %+v", stored)
}
})
}
func rawFields(object map[string]json.RawMessage) map[string]string {
flat := make(map[string]string, len(object))
for key, value := range object {
flat[key] = string(value)
}
return flat
}