Select Git revision
localizer_test.go

Anton Sattarov authored and
Pavel Antonov
committed
localizer_test.go 21.11 KiB
package localizer
import (
"testing"
"git.perx.ru/perxis/perxis-go/pkg/locales"
"git.perx.ru/perxis/perxis-go/pkg/schema"
"git.perx.ru/perxis/perxis-go/pkg/schema/field"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestLocalizer_localize(t *testing.T) {
s := schema.New(
"a", field.String(),
"b", field.Number(field.NumberFormatInt),
"c", field.String().SetSingleLocale(true),
"obj1", field.Object(
"a", field.String(),
"b", field.Number(field.NumberFormatInt),
"c", field.Number(field.NumberFormatInt).SetSingleLocale(true),
"obj2", field.Object(
"a", field.Number(field.NumberFormatInt),
"b", field.String(),
"c", field.String().SetSingleLocale(true),
),
),
"obj3", field.Object(
"a", field.String(),
).SetSingleLocale(true),
"slice", field.Array(field.String()),
"arr", field.Array(field.Object(
"num", field.Number(field.NumberFormatInt),
)),
)
tests := []struct {
fallback map[string]interface{}
target map[string]interface{}
want map[string]interface{}
name string
wantErr bool
}{
{
name: "Nil",
fallback: nil,
target: nil,
want: nil,
},
{
name: "Empty",
fallback: map[string]interface{}{},
target: map[string]interface{}{},
want: map[string]interface{}{},
},
{
name: "Target Empty",
fallback: map[string]interface{}{
"a": "en",
"b": 1,
"c": "single",
"obj1": map[string]interface{}{
"a": "obj1_en",
"b": 2,
"c": 20,
"obj2": map[string]interface{}{
"a": 3,
"b": "obj1_obj2_en",
"c": "obj1_obj2_single",
},
},
"obj3": map[string]interface{}{
"a": "obj3_en",
},
"slice": []interface{}{"en_s1", "en_s2"},
"arr": []interface{}{
map[string]interface{}{"num": 11},
map[string]interface{}{"num": 22},
},
},
target: map[string]interface{}{},
want: map[string]interface{}{
"a": "en",
"b": 1,
"c": "single",
"obj1": map[string]interface{}{
"a": "obj1_en",
"b": 2,
"c": 20,
"obj2": map[string]interface{}{
"a": 3,
"b": "obj1_obj2_en",
"c": "obj1_obj2_single",
},
},
"obj3": map[string]interface{}{
"a": "obj3_en",
},
"slice": []interface{}{"en_s1", "en_s2"},
"arr": []interface{}{
map[string]interface{}{"num": 11},
map[string]interface{}{"num": 22},
},
},
},
{
name: "Fallback Empty",
fallback: map[string]interface{}{},
target: map[string]interface{}{
"a": "en",
"b": 1,
"c": "single",
"obj1": map[string]interface{}{
"a": "obj1_en",
"b": 2,
"c": 20,
"obj2": map[string]interface{}{
"a": 3,
"b": "obj1_obj2_en",
"c": "obj1_obj2_single",
},
},
"obj3": map[string]interface{}{
"a": "obj3_en",
},
"slice": []interface{}{"en_s1", "en_s2"},
"arr": []interface{}{
map[string]interface{}{"num": 11},
map[string]interface{}{"num": 22},
},
},
want: map[string]interface{}{
"a": "en",
"b": 1,
"obj1": map[string]interface{}{
"a": "obj1_en",
"b": 2,
"obj2": map[string]interface{}{
"a": 3,
"b": "obj1_obj2_en",
},
},
"slice": []interface{}{"en_s1", "en_s2"},
"arr": []interface{}{
map[string]interface{}{"num": 11},
map[string]interface{}{"num": 22},
},
},
},
{
name: "Equal",
fallback: map[string]interface{}{
"a": "en",
"b": 1,
"c": "single",
"obj1": map[string]interface{}{
"a": "obj1_en",
"b": 2,
"c": 20,
"obj2": map[string]interface{}{
"a": 3,
"b": "obj1_obj2_en",
"c": "obj1_obj2_single",
},
},
"obj3": map[string]interface{}{
"a": "obj3_en",
},
"slice": []interface{}{"en_s1", "en_s2"},
"arr": []interface{}{
map[string]interface{}{"num": 11},
map[string]interface{}{"num": 22},
},
},
target: map[string]interface{}{
"a": "en",
"b": 1,
"c": "single",
"obj1": map[string]interface{}{
"a": "obj1_en",
"b": 2,
"c": 20,
"obj2": map[string]interface{}{
"a": 3,
"b": "obj1_obj2_en",
"c": "obj1_obj2_single",
},
},
"obj3": map[string]interface{}{
"a": "obj3_en",
},
"slice": []interface{}{"en_s1", "en_s2"},
"arr": []interface{}{
map[string]interface{}{"num": 11},
map[string]interface{}{"num": 22},
},
},
want: map[string]interface{}{
"a": "en",
"b": 1,
"c": "single",
"obj1": map[string]interface{}{
"a": "obj1_en",
"b": 2,
"c": 20,
"obj2": map[string]interface{}{
"a": 3,
"b": "obj1_obj2_en",
"c": "obj1_obj2_single",
},
},
"obj3": map[string]interface{}{
"a": "obj3_en",
},
"slice": []interface{}{"en_s1", "en_s2"},
"arr": []interface{}{
map[string]interface{}{"num": 11},
map[string]interface{}{"num": 22},
},
},
},
{
name: "Target no single",
fallback: map[string]interface{}{
"a": "en",
"b": 1,
"c": "single",
"obj1": map[string]interface{}{
"a": "obj1_en",
"b": 2,
"c": 20,
"obj2": map[string]interface{}{
"a": 3,
"b": "obj1_obj2_en",
"c": "obj1_obj2_single",
},
},
"obj3": map[string]interface{}{
"a": "obj3_en",
},
"slice": []interface{}{"en_s1", "en_s2"},
"arr": []interface{}{
map[string]interface{}{"num": 11},
map[string]interface{}{"num": 22},
},
},
target: map[string]interface{}{
"a": "en",
"b": 1,
"obj1": map[string]interface{}{
"a": "obj1_en",
"b": 2,
"obj2": map[string]interface{}{
"a": 3,
"b": "obj1_obj2_en",
},
},
"slice": []interface{}{"en_s1", "en_s2"},
"arr": []interface{}{
map[string]interface{}{"num": 11},
map[string]interface{}{"num": 22},
},
},
want: map[string]interface{}{
"a": "en",
"b": 1,
"c": "single",
"obj1": map[string]interface{}{
"a": "obj1_en",
"b": 2,
"c": 20,
"obj2": map[string]interface{}{
"a": 3,
"b": "obj1_obj2_en",
"c": "obj1_obj2_single",
},
},
"obj3": map[string]interface{}{
"a": "obj3_en",
},
"slice": []interface{}{"en_s1", "en_s2"},
"arr": []interface{}{
map[string]interface{}{"num": 11},
map[string]interface{}{"num": 22},
},
},
},
{
name: "Success",
fallback: map[string]interface{}{
"a": "en",
"b": 1,
"c": "single",
"obj1": map[string]interface{}{
"a": "obj1_en",
"b": 2,
"c": 20,
"obj2": map[string]interface{}{
"a": 3,
"b": "obj1_obj2_en",
"c": "obj1_obj2_single",
},
},
"obj3": map[string]interface{}{
"a": "obj3_en",
},
"slice": []interface{}{"en_s1", "en_s2"},
"arr": []interface{}{
map[string]interface{}{"num": 11},
map[string]interface{}{"num": 22},
},
},
target: map[string]interface{}{
"a": "ru",
"b": 11,
"obj1": map[string]interface{}{
"a": "obj1_ru",
"b": 22,
"obj2": map[string]interface{}{
"a": 33,
"b": "obj1_obj2_ru",
},
},
"slice": []interface{}{"ru_s3"},
"arr": []interface{}{
map[string]interface{}{"num": 1},
map[string]interface{}{"num": 2},
},
},
want: map[string]interface{}{
"a": "ru",
"b": 11,
"c": "single",
"obj1": map[string]interface{}{
"a": "obj1_ru",
"b": 22,
"c": 20,
"obj2": map[string]interface{}{
"a": 33,
"b": "obj1_obj2_ru",
"c": "obj1_obj2_single",
},
},
"obj3": map[string]interface{}{
"a": "obj3_en",
},
"slice": []interface{}{"ru_s3"},
"arr": []interface{}{
map[string]interface{}{"num": 1},
map[string]interface{}{"num": 2},
},
},
},
{
name: "Success singlelocale obj",
fallback: map[string]interface{}{
"obj3": map[string]interface{}{
"a": "obj3_en",
},
},
target: map[string]interface{}{
"obj3": map[string]interface{}{
"a": "obj3",
},
},
want: map[string]interface{}{
"obj3": map[string]interface{}{
"a": "obj3_en",
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := &Localizer{
schema: s,
}
got, err := l.localize(tt.target, tt.fallback)
if !tt.wantErr {
require.NoError(t, err)
assert.Equal(t, tt.want, got)
return
}
require.Error(t, err)
})
}
}
func TestLocalizer_extractTranslation(t *testing.T) {
s := schema.New(
"a", field.String(),
"b", field.Number(field.NumberFormatInt),
"c", field.String().SetSingleLocale(true),
"obj1", field.Object(
"a", field.String(),
"b", field.Number(field.NumberFormatInt),
"c", field.Number(field.NumberFormatInt).SetSingleLocale(true),
"obj2", field.Object(
"a", field.Number(field.NumberFormatInt),
"b", field.String(),
"c", field.String().SetSingleLocale(true),
),
),
"obj3", field.Object(
"a", field.String(),
).SetSingleLocale(true),
"slice", field.Array(field.String()),
"arr", field.Array(field.Object(
"num", field.Number(field.NumberFormatInt),
)),
)
tests := []struct {
fallback map[string]interface{}
target map[string]interface{}
want map[string]interface{}
name string
wantErr bool
}{
{
name: "Nil",
fallback: nil,
target: nil,
want: nil,
},
{
name: "Empty",
fallback: map[string]interface{}{},
target: map[string]interface{}{},
want: map[string]interface{}{},
},
{
name: "Target Empty",
fallback: map[string]interface{}{
"a": "en",
"b": 1,
"c": "single",
"obj1": map[string]interface{}{
"a": "obj1_en",
"b": 2,
"c": 20,
"obj2": map[string]interface{}{
"a": 3,
"b": "obj1_obj2_en",
"c": "obj1_obj2_single",
},
},
"obj3": map[string]interface{}{
"a": "obj3_en",
},
"slice": []interface{}{"en_s1", "en_s2"},
"arr": []interface{}{
map[string]interface{}{"num": 11},
map[string]interface{}{"num": 22},
},
},
target: map[string]interface{}{},
want: map[string]interface{}{},
},
{
name: "Fallback Empty",
fallback: map[string]interface{}{},
target: map[string]interface{}{
"a": "en",
"b": 1,
"c": "single",
"obj1": map[string]interface{}{
"a": "obj1_en",
"b": 2,
"c": 20,
"obj2": map[string]interface{}{
"a": 3,
"b": "obj1_obj2_en",
"c": "obj1_obj2_single",
},
},
"obj3": map[string]interface{}{
"a": "obj3_en",
},
"slice": []interface{}{"en_s1", "en_s2"},
"arr": []interface{}{
map[string]interface{}{"num": 11},
map[string]interface{}{"num": 22},
},
},
want: map[string]interface{}{
"a": "en",
"b": 1,
"obj1": map[string]interface{}{
"a": "obj1_en",
"b": 2,
"obj2": map[string]interface{}{
"a": 3,
"b": "obj1_obj2_en",
},
},
"slice": []interface{}{"en_s1", "en_s2"},
"arr": []interface{}{
map[string]interface{}{"num": 11},
map[string]interface{}{"num": 22},
},
},
},
{
name: "Equal",
fallback: map[string]interface{}{
"a": "en",
"b": 1,
"c": "single",
"obj1": map[string]interface{}{
"a": "obj1_en",
"b": 2,
"c": 20,
"obj2": map[string]interface{}{
"a": 3,
"b": "obj1_obj2_en",
"c": "obj1_obj2_single",
},
},
"obj3": map[string]interface{}{
"a": "obj3_en",
},
"slice": []interface{}{"en_s1", "en_s2"},
"arr": []interface{}{
map[string]interface{}{"num": 11},
map[string]interface{}{"num": 22},
},
},
target: map[string]interface{}{
"a": "en",
"b": 1,
"c": "single",
"obj1": map[string]interface{}{
"a": "obj1_en",
"b": 2,
"c": 20,
"obj2": map[string]interface{}{
"a": 3,
"b": "obj1_obj2_en",
"c": "obj1_obj2_single",
},
},
"obj3": map[string]interface{}{
"a": "obj3_en",
},
"slice": []interface{}{"en_s1", "en_s2"},
"arr": []interface{}{
map[string]interface{}{"num": 11},
map[string]interface{}{"num": 22},
},
},
want: map[string]interface{}{},
},
{
name: "Success",
fallback: map[string]interface{}{
"a": "en",
"b": 1,
"c": "single",
"obj1": map[string]interface{}{
"a": "obj1_en",
"b": 2,
"c": 20,
"obj2": map[string]interface{}{
"a": 3,
"b": "obj1_obj2_en",
"c": "obj1_obj2_single",
},
},
"obj3": map[string]interface{}{
"a": "obj3_en",
},
"slice": []interface{}{"en_s1", "en_s2"},
"arr": []interface{}{
map[string]interface{}{"num": 11},
map[string]interface{}{"num": 22},
},
},
target: map[string]interface{}{
"a": "ru",
"b": 11,
"obj1": map[string]interface{}{
"a": "obj1_ru",
"b": 22,
"obj2": map[string]interface{}{
"a": 33,
"b": "obj1_obj2_ru",
},
},
"slice": []interface{}{"ru_s3"},
"arr": []interface{}{
map[string]interface{}{"num": 1},
map[string]interface{}{"num": 2},
},
},
want: map[string]interface{}{
"a": "ru",
"b": 11,
"obj1": map[string]interface{}{
"a": "obj1_ru",
"b": 22,
"obj2": map[string]interface{}{
"a": 33,
"b": "obj1_obj2_ru",
},
},
"slice": []interface{}{"ru_s3"},
"arr": []interface{}{
map[string]interface{}{"num": 1},
map[string]interface{}{"num": 2},
},
},
},
{
name: "Success singlelocale obj",
fallback: map[string]interface{}{
"obj3": map[string]interface{}{
"a": "obj3_en",
},
},
target: map[string]interface{}{
"obj3": map[string]interface{}{
"a": "obj3_ru",
},
},
want: map[string]interface{}{},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := &Localizer{
schema: s,
}
got, err := l.extractTranslation(tt.target, tt.fallback)
if !tt.wantErr {
require.NoError(t, err)
assert.Equal(t, tt.want, got)
return
}
require.Error(t, err)
})
}
}
func TestLocalizer_getTargetAndFallBackLocales(t *testing.T) {
tests := []struct {
localizer *Localizer
wantTarget *locales.Locale
wantFallback *locales.Locale
name string
wantErr bool
}{
{
name: "Empty",
localizer: &Localizer{},
wantErr: true,
},
{
name: "Success",
localizer: &Localizer{
localeID: "en",
localesKV: map[string]*locales.Locale{
"en": {ID: "en"},
"default": {ID: "default"},
},
},
wantTarget: &locales.Locale{ID: "en"},
wantFallback: &locales.Locale{ID: "default"},
},
{
name: "Success fallback",
localizer: &Localizer{
localeID: "ru",
localesKV: map[string]*locales.Locale{
"en": {ID: "en"},
"ru": {ID: "ru", Fallback: "en"},
"default": {ID: "default"},
},
},
wantTarget: &locales.Locale{ID: "ru", Fallback: "en"},
wantFallback: &locales.Locale{ID: "en"},
},
{
name: "Success fallback no default",
localizer: &Localizer{
localeID: "ru",
localesKV: map[string]*locales.Locale{
"en": {ID: "en"},
"ru": {ID: "ru", Fallback: "en"},
},
},
wantTarget: &locales.Locale{ID: "ru", Fallback: "en"},
wantFallback: &locales.Locale{ID: "en"},
},
{
name: "Success fallback no fallback",
localizer: &Localizer{
localeID: "ru",
localesKV: map[string]*locales.Locale{
"ru": {ID: "ru", Fallback: "en"},
"default": {ID: "default"},
},
},
wantTarget: &locales.Locale{ID: "ru", Fallback: "en"},
wantFallback: &locales.Locale{ID: "default"},
},
{
name: "Fail fallback no fallback",
localizer: &Localizer{
localeID: "ru",
localesKV: map[string]*locales.Locale{
"ru": {ID: "ru", Fallback: "en"},
},
},
wantErr: true,
},
{
name: "Fail target nil",
localizer: &Localizer{
localeID: "ru",
localesKV: map[string]*locales.Locale{
"ru": nil,
},
},
wantErr: true,
},
{
name: "Fail target disabled",
localizer: &Localizer{
localeID: "ru",
localesKV: map[string]*locales.Locale{
"ru": {ID: "ru", Fallback: "en", Disabled: true},
"default": {ID: "default"},
},
},
wantErr: true,
},
{
name: "Success fallback disabled",
localizer: &Localizer{
localeID: "ru",
localesKV: map[string]*locales.Locale{
"en": {ID: "en", Disabled: true},
"ru": {ID: "ru", Fallback: "en"},
"default": {ID: "default"},
},
},
wantTarget: &locales.Locale{ID: "ru", Fallback: "en"},
wantFallback: &locales.Locale{ID: "default"},
},
{
name: "Fail target no publish",
localizer: &Localizer{
localeID: "ru",
localesKV: map[string]*locales.Locale{
"ru": {ID: "ru", Fallback: "en", NoPublish: true},
"default": {ID: "default"},
},
},
wantErr: true,
},
{
name: "Success fallback no publish",
localizer: &Localizer{
localeID: "ru",
localesKV: map[string]*locales.Locale{
"en": {ID: "en", NoPublish: true},
"ru": {ID: "ru", Fallback: "en"},
"default": {ID: "default"},
},
},
wantTarget: &locales.Locale{ID: "ru", Fallback: "en"},
wantFallback: &locales.Locale{ID: "en", NoPublish: true},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotTarget, gotFallback, err := tt.localizer.getTargetAndFallBackLocales()
if tt.wantErr {
require.Error(t, err)
return
}
require.NoError(t, err)
assert.Equal(t, tt.wantTarget, gotTarget)
assert.Equal(t, tt.wantFallback, gotFallback)
})
}
}
func TestLocalizer_ExtractTranslations(t *testing.T) {
s := schema.New(
"a", field.String(),
"b", field.String(),
)
tests := []struct {
data map[string]interface{}
translations map[string]map[string]interface{}
want map[string]interface{}
cfg Config
name string
wantErr bool
}{
{
name: "Extract default",
data: map[string]interface{}{"a": "bbb"},
translations: map[string]map[string]interface{}{"en": {"a": "bbb"}},
cfg: Config{
LocaleID: "en",
Schema: s,
Locales: []*locales.Locale{
{ID: "en"},
{ID: "default"},
},
},
want: map[string]interface{}{},
},
{
name: "Extract default not same",
data: map[string]interface{}{"a": "aaa"},
translations: map[string]map[string]interface{}{"en": {"a": "bbb"}},
cfg: Config{
LocaleID: "en",
Schema: s,
Locales: []*locales.Locale{
{ID: "en"},
{ID: "default"},
},
},
want: map[string]interface{}{"a": "bbb"},
},
{
name: "Extract default empty",
data: map[string]interface{}{"a": "aaa"},
translations: map[string]map[string]interface{}{"en": {}},
cfg: Config{
LocaleID: "en",
Schema: s,
Locales: []*locales.Locale{
{ID: "en"},
{ID: "default"},
},
},
want: map[string]interface{}{},
},
{
name: "Extract fallback",
data: map[string]interface{}{"a": "aaa"},
translations: map[string]map[string]interface{}{"ru": {"a": "bbb"}, "en": {"a": "bbb"}},
cfg: Config{
LocaleID: "ru",
Schema: s,
Locales: []*locales.Locale{
{ID: "ru", Fallback: "en"},
{ID: "en"},
{ID: "default"},
},
},
want: map[string]interface{}{},
},
{
name: "Extract fallback with extracted field",
data: map[string]interface{}{"a": "aaa"},
translations: map[string]map[string]interface{}{"ru": {"a": "bbb"}, "en": {}},
cfg: Config{
LocaleID: "ru",
Schema: s,
Locales: []*locales.Locale{
{ID: "ru", Fallback: "en"},
{ID: "en"},
{ID: "default"},
},
},
want: map[string]interface{}{"a": "bbb"},
},
{
name: "Extract fallback with empty field",
data: map[string]interface{}{"a": "aaa"},
translations: map[string]map[string]interface{}{"ru": {}, "en": {"a": "bbb"}},
cfg: Config{
LocaleID: "ru",
Schema: s,
Locales: []*locales.Locale{
{ID: "ru", Fallback: "en"},
{ID: "en"},
{ID: "default"},
},
},
want: map[string]interface{}{},
},
{
name: "Extract fallback with same as default",
data: map[string]interface{}{"a": "aaa"},
translations: map[string]map[string]interface{}{"ru": {"a": "aaa"}, "en": {"a": "bbb"}},
cfg: Config{
LocaleID: "ru",
Schema: s,
Locales: []*locales.Locale{
{ID: "ru", Fallback: "en"},
{ID: "en"},
{ID: "default"},
},
},
want: map[string]interface{}{"a": "aaa"},
},
{
name: "Extract fallback with same",
data: map[string]interface{}{"a": "aaa"},
translations: map[string]map[string]interface{}{"ru": {"a": "aaa"}, "en": {"a": "aaa", "b": "bbb"}},
cfg: Config{
LocaleID: "ru",
Schema: s,
Locales: []*locales.Locale{
{ID: "ru", Fallback: "en"},
{ID: "en"},
{ID: "default"},
},
},
want: map[string]interface{}{},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := NewLocalizer(tt.cfg)
got, err := l.ExtractTranslation(tt.data, tt.translations)
if !tt.wantErr {
require.NoError(t, err)
assert.Equal(t, tt.want, got)
return
}
require.Error(t, err)
})
}
}