Files
honeyDueAPI/internal/services/lookup_i18n_test.go
T
Trey T 12de5a230a
Backend CI / Test (push) Has been cancelled
Backend CI / Contract Tests (push) Has been cancelled
Backend CI / Lint (push) Has been cancelled
Backend CI / Secret Scanning (push) Has been cancelled
Backend CI / Build (push) Has been cancelled
i18n: backend-localized lookups, suggestions, and static data (10 languages)
- suggestion_service: fix scorer (stringList unmarshal accepts scalar|array;
  anchor scoring on base universal score so bool matches no longer tie); add
  localizeReasons for human-readable, Accept-Language-localized match reasons
- lookup_i18n: localize lookup display names, home-profile options, document
  types/categories via internal/i18n
- static_data_handler: per-locale seeded-data response (display_name, home
  profile options, document types/categories) with per-locale cache + ETag
- settings_handler: invalidate per-locale seeded-data cache on lookup change
  instead of pre-warming a single non-localized blob
- cache_service: per-locale seeded-data keys + ETag
- DTOs: add DisplayName fields (task/residence/contractor)
- translations: add suggestion.reason.* and lookup.* keys across all 10 langs
- cmd/api: extract startup helpers + tests

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 20:54:54 -05:00

89 lines
3.2 KiB
Go

package services
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/treytartt/honeydue-api/internal/dto/responses"
"github.com/treytartt/honeydue-api/internal/i18n"
)
func init() {
// Load the embedded translation bundle for the localization tests.
_ = i18n.Init()
}
func TestLookupSlug(t *testing.T) {
cases := map[string]string{
"Pest Control": "pest_control",
"Bi-Weekly": "bi_weekly",
"Semi-Annually": "semi_annually",
"Mobile Home": "mobile_home",
"HVAC": "hvac",
"tank_gas": "tank_gas",
"Tankless (Gas)": "tankless_gas",
" Trailing/Punct ": "trailing_punct",
}
for in, want := range cases {
assert.Equalf(t, want, lookupSlug(in), "slug(%q)", in)
}
}
func TestLocalizeLookup_EnglishAndSpanish(t *testing.T) {
en := i18n.NewLocalizer("en")
es := i18n.NewLocalizer("es")
// Known value: localizes per locale.
assert.Equal(t, "Plumbing", localizeLookup(en, lookupKindTaskCategory, "Plumbing"))
assert.Equal(t, "Fontanería", localizeLookup(es, lookupKindTaskCategory, "Plumbing"))
// Frequency with separators (regression on the bi_weekly/semi_annually slug).
assert.Equal(t, "Bi-Weekly", localizeLookup(en, lookupKindTaskFrequency, "Bi-Weekly"))
assert.Equal(t, "Quincenal", localizeLookup(es, lookupKindTaskFrequency, "Bi-Weekly"))
}
func TestLocalizeLookup_NilLocalizerFallsBackToEnglish(t *testing.T) {
assert.Equal(t, "House", localizeLookup(nil, lookupKindResidenceType, "House"))
}
func TestLocalizeLookup_UnknownValueFallsBackToName(t *testing.T) {
// No translation key exists -> return the stable English name, never a key.
got := localizeLookup(i18n.NewLocalizer("es"), lookupKindTaskCategory, "Totally Unknown Value")
assert.Equal(t, "Totally Unknown Value", got)
}
func TestBuildHomeProfileOptions(t *testing.T) {
opts := BuildHomeProfileOptions(i18n.NewLocalizer("es"))
// All 7 fields present.
for _, field := range []string{"heating_type", "cooling_type", "water_heater_type", "roof_type", "exterior_type", "flooring_primary", "landscaping_type"} {
require.Containsf(t, opts, field, "missing field %s", field)
require.NotEmpty(t, opts[field])
}
// Values are stable; display_name is localized.
heating := opts["heating_type"]
assert.Equal(t, "gas_furnace", heating[0].Value)
assert.Equal(t, "Calefactor de gas", heating[0].DisplayName)
}
func TestLocalizeLookups_FillsDisplayName(t *testing.T) {
cats := []responses.TaskCategoryResponse{{Name: "Plumbing"}, {Name: "HVAC"}}
prios := []responses.TaskPriorityResponse{{Name: "High"}}
freqs := []responses.TaskFrequencyResponse{{Name: "Monthly"}}
specs := []responses.ContractorSpecialtyResponse{{Name: "Plumber"}}
types := []responses.ResidenceTypeResponse{{Name: "House"}}
LocalizeLookups(i18n.NewLocalizer("es"), types, cats, prios, freqs, specs)
assert.Equal(t, "Fontanería", cats[0].DisplayName)
assert.Equal(t, "Plumbing", cats[0].Name) // name stays stable
assert.Equal(t, "Climatización", cats[1].DisplayName)
assert.Equal(t, "Alta", prios[0].DisplayName)
assert.Equal(t, "Mensual", freqs[0].DisplayName)
assert.Equal(t, "Fontanero", specs[0].DisplayName)
assert.Equal(t, "Casa", types[0].DisplayName)
}