feat: site languages, setup and site URL settings
This commit is contained in:
1 parent
0806733d5c
commit
d9158025d4
106 files changed
+10184
-56
No files matched your search
@@ -0,0 +1,485 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"RenewCMS/internal/domain/localization"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"slices"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var languagesReadKeys = []string{"available", "default", "languages", "needs_setup", "revision"}
|
||||
|
||||
func TestSiteLanguagesReading(t *testing.T) {
|
||||
t.Run("Read the languages", func(t *testing.T) {
|
||||
e := newLocalizationEnv(t)
|
||||
e.seedJournal()
|
||||
|
||||
rec := e.as(t, readerUserID, http.MethodGet, "/v1/site/journal/languages", "")
|
||||
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("status %d: %s", rec.Code, rec.Body)
|
||||
}
|
||||
if keys := keysOf(decodeFields(t, rec)); !reflect.DeepEqual(keys, languagesReadKeys) {
|
||||
t.Errorf("keys = %v", keys)
|
||||
}
|
||||
view := decodeLanguagesView(t, rec)
|
||||
if view.Revision == "" || view.Default == nil || *view.Default != "en" || view.NeedsSetup {
|
||||
t.Errorf("header = %+v", view)
|
||||
}
|
||||
if !reflect.DeepEqual(view.tags(), []string{"en", "ar", "de", "fr", "en-US", "es"}) {
|
||||
t.Errorf("order = %v", view.tags())
|
||||
}
|
||||
counts := map[string][2]int{"en": {7, 6}, "fr": {4, 2}, "de": {4, 3}, "ar": {1, 0}, "es": {1, 0}, "en-US": {0, 0}}
|
||||
for _, entry := range view.Languages {
|
||||
if got := [2]int{entry.VersionCount, entry.PublishedCount}; got != counts[entry.Lang] {
|
||||
t.Errorf("%s counts = %v", entry.Lang, got)
|
||||
}
|
||||
}
|
||||
if available := view.Available; len(available) == 0 || !slices.ContainsFunc(available, func(o struct {
|
||||
Lang string `json:"lang"`
|
||||
Substitute *string `json:"substitute"`
|
||||
}) bool {
|
||||
return o.Lang == "pt-PT" && o.Substitute != nil && *o.Substitute == "pt"
|
||||
}) {
|
||||
t.Errorf("available = %+v", available)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Read access", func(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
user uint32
|
||||
key string
|
||||
status int
|
||||
}{
|
||||
{"an anonymous client", 0, "journal", http.StatusUnauthorized},
|
||||
{"a reader", readerUserID, "journal", http.StatusOK},
|
||||
{"an owner", apiKeyOwnerId, "journal", http.StatusOK},
|
||||
{"an owner on an unknown site", apiKeyOwnerId, "nowhere", http.StatusNotFound},
|
||||
}
|
||||
for _, c := range cases {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
e := newLocalizationEnv(t)
|
||||
e.seedJournal()
|
||||
rec := e.as(t, c.user, http.MethodGet, "/v1/site/"+c.key+"/languages", "")
|
||||
if rec.Code != c.status {
|
||||
t.Fatalf("status %d: %s", rec.Code, rec.Body)
|
||||
}
|
||||
if c.status == http.StatusNotFound && bodyText(rec) != "site_not_found" {
|
||||
t.Errorf("body = %q", bodyText(rec))
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Social locale states", func(t *testing.T) {
|
||||
e := newLocalizationEnv(t)
|
||||
e.sites.seed(5, "Atelier", "atelier", false)
|
||||
fr := "fr_FR"
|
||||
e.seedRows(5,
|
||||
localization.Row{Tag: "en", IsDefault: true, Enabled: true, Confirmed: true},
|
||||
localization.Row{Tag: "en-GB", Enabled: true},
|
||||
localization.Row{Tag: "fr", Enabled: true, SocialLocale: &fr},
|
||||
localization.Row{Tag: "pt-BR", Enabled: true},
|
||||
)
|
||||
cases := []struct {
|
||||
lang string
|
||||
state string
|
||||
explicit *string
|
||||
effective *string
|
||||
}{
|
||||
{"en-GB", "derived", nil, localeOf("en_GB")},
|
||||
{"pt-BR", "derived", nil, localeOf("pt_BR")},
|
||||
{"fr", "set", &fr, &fr},
|
||||
{"en", "not_set", nil, nil},
|
||||
}
|
||||
rec := e.owner(t, http.MethodGet, "/v1/site/atelier/languages", "")
|
||||
view := decodeLanguagesView(t, rec)
|
||||
for _, c := range cases {
|
||||
t.Run(c.lang, func(t *testing.T) {
|
||||
for _, entry := range view.Languages {
|
||||
if entry.Lang != c.lang {
|
||||
continue
|
||||
}
|
||||
if entry.State != c.state || !sameText(entry.SocialLocale, c.explicit) {
|
||||
t.Errorf("entry = %+v", entry)
|
||||
}
|
||||
row := localization.Row{Tag: entry.Lang, SocialLocale: entry.SocialLocale}
|
||||
if !sameText(localization.EffectiveSocialLocale(row), c.effective) {
|
||||
t.Errorf("effective = %v", localization.EffectiveSocialLocale(row))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Only the explicit value and the tag's own region resolve the social locale", func(t *testing.T) {
|
||||
e := newLocalizationEnv(t)
|
||||
e.sites.seed(5, "Atelier", "atelier", false)
|
||||
gb := "en-GB"
|
||||
stored := e.sites.sites[5]
|
||||
stored.Locale = &gb
|
||||
e.sites.sites[5] = stored
|
||||
e.seedRows(5, localization.Row{Tag: "en", IsDefault: true, Enabled: true, Confirmed: true})
|
||||
|
||||
view := decodeLanguagesView(t, e.owner(t, http.MethodGet, "/v1/site/atelier/languages", ""))
|
||||
|
||||
if view.Languages[0].State != "not_set" {
|
||||
t.Errorf("state = %q", view.Languages[0].State)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("A site that still needs setup", func(t *testing.T) {
|
||||
e := newLocalizationEnv(t)
|
||||
e.sites.seed(2, "Notes", "notes", false)
|
||||
before := e.store.replaceCalls
|
||||
|
||||
view := decodeLanguagesView(t, e.as(t, readerUserID, http.MethodGet, "/v1/site/notes/languages", ""))
|
||||
put := e.owner(t, http.MethodPut, "/v1/site/notes/languages", languagesBody("any", "en", entryJSON("en", true, "null")))
|
||||
|
||||
if !view.NeedsSetup {
|
||||
t.Errorf("needs_setup = false")
|
||||
}
|
||||
expectSiteStatusAndBody(t, put, http.StatusConflict, "setup_required")
|
||||
if e.store.replaceCalls != before {
|
||||
t.Errorf("something was stored")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Sites created after the migration have no language row", func(t *testing.T) {
|
||||
e := newLocalizationEnv(t)
|
||||
e.sites.seed(2, "Fresh", "fresh", false)
|
||||
|
||||
view := decodeLanguagesView(t, e.owner(t, http.MethodGet, "/v1/site/fresh/languages", ""))
|
||||
|
||||
if !view.NeedsSetup || len(view.Languages) != 0 || view.Default != nil {
|
||||
t.Errorf("view = %+v", view)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func sameText(left *string, right *string) bool {
|
||||
if left == nil || right == nil {
|
||||
return left == right
|
||||
}
|
||||
return *left == *right
|
||||
}
|
||||
|
||||
func TestSiteLanguagesWriting(t *testing.T) {
|
||||
put := func(e *localizationEnv, t *testing.T, defaultTag string, entries []string) (string, string) {
|
||||
t.Helper()
|
||||
revision := e.revision(t, "journal")
|
||||
rec := e.owner(t, http.MethodPut, "/v1/site/journal/languages", languagesBody(revision, defaultTag, entries...))
|
||||
return rec.Body.String(), http.StatusText(rec.Code)
|
||||
}
|
||||
_ = put
|
||||
|
||||
changes := []struct {
|
||||
name string
|
||||
def string
|
||||
entries []string
|
||||
check func(t *testing.T, view languagesView)
|
||||
}{
|
||||
{"fr added with enabled true", "en", journalEntries(map[string]string{"fr": entryJSON("fr", true, `"fr_FR"`)}), func(t *testing.T, v languagesView) {
|
||||
if countTag(v, "fr") != 1 || !findLanguage(t, v, "fr").Enabled {
|
||||
t.Errorf("fr = %+v", v.tags())
|
||||
}
|
||||
}},
|
||||
{"pt-br added (lowercase) as enabled", "en", append(journalEntries(nil), entryJSON("pt-br", true, "null")), func(t *testing.T, v languagesView) {
|
||||
if countTag(v, "pt-BR") != 1 || countTag(v, "pt-br") != 0 {
|
||||
t.Errorf("tags = %v", v.tags())
|
||||
}
|
||||
}},
|
||||
{"default fr", "fr", journalEntries(nil), func(t *testing.T, v languagesView) {
|
||||
if !findLanguage(t, v, "fr").IsDefault || findLanguage(t, v, "en").IsDefault || !findLanguage(t, v, "en").Enabled {
|
||||
t.Errorf("view = %+v", v.Languages)
|
||||
}
|
||||
}},
|
||||
{"de enabled false", "en", journalEntries(map[string]string{"de": entryJSON("de", false, "null")}), func(t *testing.T, v languagesView) {
|
||||
de := findLanguage(t, v, "de")
|
||||
if de.Enabled || de.VersionCount != 4 || de.PublishedCount != 3 {
|
||||
t.Errorf("de = %+v", de)
|
||||
}
|
||||
}},
|
||||
{"es enabled true", "en", journalEntries(map[string]string{"es": entryJSON("es", true, "null")}), func(t *testing.T, v languagesView) {
|
||||
es := findLanguage(t, v, "es")
|
||||
if !es.Enabled || es.VersionCount != 1 {
|
||||
t.Errorf("es = %+v", es)
|
||||
}
|
||||
}},
|
||||
{"en-US omitted", "en", journalEntries(nil, "en-US"), func(t *testing.T, v languagesView) {
|
||||
if countTag(v, "en-US") != 0 {
|
||||
t.Errorf("tags = %v", v.tags())
|
||||
}
|
||||
}},
|
||||
{"fr social_locale fr_CA", "en", journalEntries(map[string]string{"fr": entryJSON("fr", true, `"fr_CA"`)}), func(t *testing.T, v languagesView) {
|
||||
fr := findLanguage(t, v, "fr")
|
||||
if fr.State != "set" || fr.SocialLocale == nil || *fr.SocialLocale != "fr_CA" {
|
||||
t.Errorf("fr = %+v", fr)
|
||||
}
|
||||
}},
|
||||
{"fr social_locale null", "en", journalEntries(map[string]string{"fr": entryJSON("fr", true, "null")}), func(t *testing.T, v languagesView) {
|
||||
if findLanguage(t, v, "fr").State != "not_set" {
|
||||
t.Errorf("fr = %+v", findLanguage(t, v, "fr"))
|
||||
}
|
||||
}},
|
||||
}
|
||||
for _, c := range changes {
|
||||
t.Run("Changing the set/"+c.name, func(t *testing.T) {
|
||||
e := newLocalizationEnv(t)
|
||||
e.seedJournal()
|
||||
articlesBefore := len(e.articles.articles)
|
||||
revision := e.revision(t, "journal")
|
||||
|
||||
rec := e.owner(t, http.MethodPut, "/v1/site/journal/languages", languagesBody(revision, c.def, c.entries...))
|
||||
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("status %d: %s", rec.Code, rec.Body)
|
||||
}
|
||||
c.check(t, decodeLanguagesView(t, rec))
|
||||
if len(e.articles.articles) != articlesBefore {
|
||||
t.Errorf("articles changed")
|
||||
}
|
||||
for _, stored := range e.articles.articles {
|
||||
if stored.Lang == "" {
|
||||
t.Errorf("an article lost its language")
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
rejections := []struct {
|
||||
name string
|
||||
def string
|
||||
entries func() []string
|
||||
status int
|
||||
code string
|
||||
}{
|
||||
{"default en with en enabled false", "en", func() []string {
|
||||
return journalEntries(map[string]string{"en": entryJSON("en", false, "null")})
|
||||
}, 422, "default_not_enabled"},
|
||||
{"default ja", "ja", func() []string { return journalEntries(nil) }, 422, "default_not_enabled"},
|
||||
{"every language enabled false", "en", func() []string {
|
||||
entries := []string{}
|
||||
for _, tag := range []string{"en", "fr", "de", "ar", "es", "en-US"} {
|
||||
entries = append(entries, entryJSON(tag, false, "null"))
|
||||
}
|
||||
return entries
|
||||
}, 422, "no_enabled_language"},
|
||||
{"languages []", "en", func() []string { return nil }, 422, "no_enabled_language"},
|
||||
{"es omitted (1 version)", "en", func() []string { return journalEntries(nil, "es") }, 409, "language_in_use"},
|
||||
{"ar omitted (1 draft or offline version)", "en", func() []string { return journalEntries(nil, "ar") }, 409, "language_in_use"},
|
||||
{"en omitted", "en", func() []string { return journalEntries(nil, "en") }, 422, "default_not_enabled"},
|
||||
{"a language english", "en", func() []string { return append(journalEntries(nil), entryJSON("english", true, "null")) }, 422, "invalid_language"},
|
||||
{"a language xx", "en", func() []string { return append(journalEntries(nil), entryJSON("xx", true, "null")) }, 422, "unsupported_language"},
|
||||
{"a language pt-PT", "en", func() []string { return append(journalEntries(nil), entryJSON("pt-PT", true, "null")) }, 422, "unsupported_language"},
|
||||
{"the same tag twice", "en", func() []string {
|
||||
return append(journalEntries(nil), entryJSON("fr", true, "null"), entryJSON("FR", true, "null"))
|
||||
}, 422, "duplicate_language"},
|
||||
{"fr social_locale fr-FR", "en", func() []string { return socialOnFrench(`"fr-FR"`) }, 422, "invalid_social_locale"},
|
||||
{"fr social_locale fr", "en", func() []string { return socialOnFrench(`"fr"`) }, 422, "invalid_social_locale"},
|
||||
{"fr social_locale empty", "en", func() []string { return socialOnFrench(`""`) }, 422, "invalid_social_locale"},
|
||||
{"fr social_locale pt_BR", "en", func() []string { return socialOnFrench(`"pt_BR"`) }, 422, "invalid_social_locale"},
|
||||
{"fr default, de disabled and es omitted", "fr", func() []string {
|
||||
return journalEntries(map[string]string{"de": entryJSON("de", false, "null")}, "es")
|
||||
}, 409, "language_in_use"},
|
||||
}
|
||||
for _, c := range rejections {
|
||||
t.Run("Rules that reject a change/"+c.name, func(t *testing.T) {
|
||||
e := newLocalizationEnv(t)
|
||||
e.seedJournal()
|
||||
rowsBefore, articlesBefore := e.store.snapshot()
|
||||
revision := e.revision(t, "journal")
|
||||
|
||||
rec := e.owner(t, http.MethodPut, "/v1/site/journal/languages", languagesBody(revision, c.def, c.entries()...))
|
||||
|
||||
expectSiteStatusAndBody(t, rec, c.status, c.code)
|
||||
rowsAfter, articlesAfter := e.store.snapshot()
|
||||
if !reflect.DeepEqual(rowsBefore, rowsAfter) || !reflect.DeepEqual(articlesBefore, articlesAfter) || e.store.replaceCalls != 0 {
|
||||
t.Errorf("something was stored")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
t.Run("Rules that reject a change/no revision key", func(t *testing.T) {
|
||||
e := newLocalizationEnv(t)
|
||||
e.seedJournal()
|
||||
rec := e.owner(t, http.MethodPut, "/v1/site/journal/languages", `{"default":"en","languages":[`+entryJSON("en", true, "null")+`]}`)
|
||||
expectSiteStatusAndBody(t, rec, http.StatusBadRequest, "The request cannot be processed due to a mismatch in the format of the body.")
|
||||
})
|
||||
|
||||
t.Run("Rules that reject a change/malformed JSON", func(t *testing.T) {
|
||||
e := newLocalizationEnv(t)
|
||||
e.seedJournal()
|
||||
rec := e.owner(t, http.MethodPut, "/v1/site/journal/languages", `{not json`)
|
||||
expectSiteStatusAndBody(t, rec, http.StatusBadRequest, "The request cannot be processed due to a mismatch in the format of the body.")
|
||||
})
|
||||
|
||||
t.Run("Social locale format and language part", func(t *testing.T) {
|
||||
cases := []struct {
|
||||
tag string
|
||||
social string
|
||||
valid bool
|
||||
}{
|
||||
{"fr", "fr_FR", true},
|
||||
{"fr", "fr_CA", true},
|
||||
{"fr", "pt_BR", false},
|
||||
{"fr-CA", "fr_CA", true},
|
||||
{"ar", "ara_EG", false},
|
||||
{"fr", "fr_F", false},
|
||||
{"fr", "fr__FR", false},
|
||||
{"fr", "fr_F1", false},
|
||||
}
|
||||
for _, c := range cases {
|
||||
social := c.social
|
||||
_, err := localization.NormalizeSocialLocale(c.tag, &social)
|
||||
if (err == nil) != c.valid {
|
||||
t.Errorf("%s on %s: err = %v", c.social, c.tag, err)
|
||||
}
|
||||
}
|
||||
if normalized, err := localization.NormalizeSocialLocale("fr", localeOf("fr_fr")); err != nil || *normalized != "fr_FR" {
|
||||
t.Errorf("normalized = %v, %v", normalized, err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("A stale revision is refused", func(t *testing.T) {
|
||||
e := newLocalizationEnv(t)
|
||||
e.seedJournal()
|
||||
stale := e.revision(t, "journal")
|
||||
other := e.owner(t, http.MethodPut, "/v1/site/journal/languages", languagesBody(stale, "en", journalEntries(map[string]string{"fr": entryJSON("fr", true, `"fr_CA"`)})...))
|
||||
if other.Code != http.StatusOK {
|
||||
t.Fatalf("other owner: %d %s", other.Code, other.Body)
|
||||
}
|
||||
rowsBefore, _ := e.store.snapshot()
|
||||
|
||||
refused := e.owner(t, http.MethodPut, "/v1/site/journal/languages", languagesBody(stale, "fr", journalEntries(nil)...))
|
||||
|
||||
expectSiteStatusAndBody(t, refused, http.StatusConflict, "languages_changed")
|
||||
if rowsAfter, _ := e.store.snapshot(); !reflect.DeepEqual(rowsBefore, rowsAfter) {
|
||||
t.Errorf("rows changed")
|
||||
}
|
||||
retry := e.owner(t, http.MethodPut, "/v1/site/journal/languages", languagesBody(e.revision(t, "journal"), "fr", journalEntries(nil)...))
|
||||
if retry.Code != http.StatusOK {
|
||||
t.Errorf("retry: %d %s", retry.Code, retry.Body)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Sending the same state again is a no-op", func(t *testing.T) {
|
||||
e := newLocalizationEnv(t)
|
||||
e.seedJournal()
|
||||
first := e.owner(t, http.MethodPut, "/v1/site/journal/languages", languagesBody(e.revision(t, "journal"), "fr", journalEntries(nil)...))
|
||||
r2 := decodeLanguagesView(t, first).Revision
|
||||
calls := e.store.replaceCalls
|
||||
rowsBefore, _ := e.store.snapshot()
|
||||
|
||||
again := e.owner(t, http.MethodPut, "/v1/site/journal/languages", languagesBody(r2, "fr", journalEntries(nil)...))
|
||||
|
||||
if again.Code != http.StatusOK || decodeLanguagesView(t, again).Revision != r2 {
|
||||
t.Fatalf("again: %d %s", again.Code, again.Body)
|
||||
}
|
||||
if rowsAfter, _ := e.store.snapshot(); e.store.replaceCalls != calls || !reflect.DeepEqual(rowsBefore, rowsAfter) {
|
||||
t.Errorf("rows were written again")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Only an owner can write", func(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
user uint32
|
||||
status int
|
||||
}{
|
||||
{"an anonymous client", 0, http.StatusUnauthorized},
|
||||
{"a reader", readerUserID, http.StatusForbidden},
|
||||
}
|
||||
for _, c := range cases {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
e := newLocalizationEnv(t)
|
||||
e.seedJournal()
|
||||
revision := e.revision(t, "journal")
|
||||
rec := e.as(t, c.user, http.MethodPut, "/v1/site/journal/languages", languagesBody(revision, "fr", journalEntries(nil)...))
|
||||
if rec.Code != c.status || e.store.replaceCalls != 0 {
|
||||
t.Errorf("status %d, writes %d", rec.Code, e.store.replaceCalls)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Removing a language is decided under the site lock", func(t *testing.T) {
|
||||
e := newLocalizationEnv(t)
|
||||
e.seedJournal()
|
||||
e.owner(t, http.MethodPut, "/v1/site/journal/languages", languagesBody(e.revision(t, "journal"), "en", journalEntries(nil, "en-US")...))
|
||||
if !slices.Equal(e.sites.lockedSites, []uint32{journalSiteID}) || e.transactor.runs != 1 {
|
||||
t.Errorf("locks %v, transactions %d", e.sites.lockedSites, e.transactor.runs)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func socialOnFrench(social string) []string {
|
||||
return journalEntries(map[string]string{"fr": entryJSON("fr", true, social)})
|
||||
}
|
||||
|
||||
func countTag(view languagesView, tag string) int {
|
||||
total := 0
|
||||
for _, entry := range view.Languages {
|
||||
if entry.Lang == tag {
|
||||
total++
|
||||
}
|
||||
}
|
||||
return total
|
||||
}
|
||||
|
||||
type languageEntryView = struct {
|
||||
Lang string `json:"lang"`
|
||||
Enabled bool `json:"enabled"`
|
||||
IsDefault bool `json:"is_default"`
|
||||
VersionCount int `json:"version_count"`
|
||||
PublishedCount int `json:"published_count"`
|
||||
SocialLocale *string `json:"social_locale"`
|
||||
State string `json:"social_locale_state"`
|
||||
}
|
||||
|
||||
func findLanguage(t *testing.T, view languagesView, tag string) languageEntryView {
|
||||
t.Helper()
|
||||
for _, entry := range view.Languages {
|
||||
if entry.Lang == tag {
|
||||
return entry
|
||||
}
|
||||
}
|
||||
t.Fatalf("language %s missing from %v", tag, view.tags())
|
||||
return languageEntryView{}
|
||||
}
|
||||
|
||||
func TestSiteLanguagesRevision(t *testing.T) {
|
||||
base := []localization.Row{{Tag: "en", IsDefault: true, Enabled: true}, {Tag: "fr", Enabled: true}}
|
||||
other := func(change func(rows []localization.Row)) string {
|
||||
rows := slices.Clone(base)
|
||||
change(rows)
|
||||
return localization.Revision(rows)
|
||||
}
|
||||
reference := localization.Revision(base)
|
||||
|
||||
t.Run("the same rows give the same revision whatever the order", func(t *testing.T) {
|
||||
if localization.Revision([]localization.Row{base[1], base[0]}) != reference {
|
||||
t.Errorf("order changed the revision")
|
||||
}
|
||||
})
|
||||
t.Run("any change of lang, default, enabled or social_locale gives another one", func(t *testing.T) {
|
||||
changes := map[string]func(rows []localization.Row){
|
||||
"lang": func(rows []localization.Row) { rows[1].Tag = "de" },
|
||||
"default": func(rows []localization.Row) { rows[1].IsDefault = true },
|
||||
"enabled": func(rows []localization.Row) { rows[1].Enabled = false },
|
||||
"social": func(rows []localization.Row) { rows[1].SocialLocale = localeOf("fr_FR") },
|
||||
}
|
||||
for name, change := range changes {
|
||||
if other(change) == reference {
|
||||
t.Errorf("%s did not change the revision", name)
|
||||
}
|
||||
}
|
||||
})
|
||||
t.Run("confirmed flags do not change the revision", func(t *testing.T) {
|
||||
if other(func(rows []localization.Row) { rows[0].Confirmed = true }) != reference {
|
||||
t.Errorf("confirmed changed the revision")
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in new issue
Block a user