sync: migrate ai-operator to Gitea (2026-08-10)
This commit is contained in:
@@ -0,0 +1,193 @@
|
||||
package region
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"ai-operator/internal/dialogue/state"
|
||||
)
|
||||
|
||||
func TestCatalogCountsAndNames(t *testing.T) {
|
||||
r := NewDefaultResolver()
|
||||
if got := len(r.ListEnabled()); got != 20 {
|
||||
t.Fatalf("enabled=%d", got)
|
||||
}
|
||||
if got := len(r.ListDisabled()); got != 1 {
|
||||
t.Fatalf("disabled=%d", got)
|
||||
}
|
||||
city, oblast := 0, 0
|
||||
seen := map[string]bool{}
|
||||
for _, reg := range r.ListEnabled() {
|
||||
if reg.Code == "" || seen[reg.Code] {
|
||||
t.Fatalf("bad code %q", reg.Code)
|
||||
}
|
||||
seen[reg.Code] = true
|
||||
if reg.DisplayNameRU == "" || reg.DisplayNameKK == "" {
|
||||
t.Fatalf("missing display names for %s", reg.Code)
|
||||
}
|
||||
switch reg.Type {
|
||||
case RegionTypeRepublicCity:
|
||||
city++
|
||||
case RegionTypeOblast:
|
||||
oblast++
|
||||
}
|
||||
}
|
||||
if city != 3 || oblast != 17 {
|
||||
t.Fatalf("city=%d oblast=%d", city, oblast)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNormalizer(t *testing.T) {
|
||||
cases := map[string]string{
|
||||
" Г. Алматы! ": "город алматы",
|
||||
"Алматинская обл.": "алматинская обл",
|
||||
"Нұр-Сұлтан": "нұр сұлтан",
|
||||
"Восточно-Казахстанская": "восточно казахстанская",
|
||||
"Қазақша, Астана": "қазақша астана",
|
||||
}
|
||||
for input, want := range cases {
|
||||
if got := Normalize(input); got != want {
|
||||
t.Fatalf("Normalize(%q)=%q want %q", input, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRepublicCityDetection(t *testing.T) {
|
||||
r := NewDefaultResolver()
|
||||
cases := map[string]string{
|
||||
"астана": "astana_city",
|
||||
"город астана": "astana_city",
|
||||
"астана қаласы": "astana_city",
|
||||
"astana": "astana_city",
|
||||
"нурсултан": "astana_city",
|
||||
"нұр-сұлтан": "astana_city",
|
||||
"город алматы": "almaty_city",
|
||||
"алматы қаласы": "almaty_city",
|
||||
"шымкент": "shymkent_city",
|
||||
"шимкент": "shymkent_city",
|
||||
"shymkent": "shymkent_city",
|
||||
}
|
||||
for input, want := range cases {
|
||||
got := r.Resolve(input, SourceCLI)
|
||||
if got.RegionCode != want || got.Confidence < MediumConfidence {
|
||||
t.Fatalf("%q => %+v want %s", input, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestOblastDetection(t *testing.T) {
|
||||
r := NewDefaultResolver()
|
||||
cases := map[string]string{
|
||||
"Акмолинская область": "akmola_region",
|
||||
"Ақмола облысы": "akmola_region",
|
||||
"Актюбинская область": "aktobe_region",
|
||||
"Ақтөбе облысы": "aktobe_region",
|
||||
"Алматинская область": "almaty_region",
|
||||
"Алматы облысы": "almaty_region",
|
||||
"Атырауская область": "atyrau_region",
|
||||
"Атырау облысы": "atyrau_region",
|
||||
"Восточно-Казахстанская область": "east_kazakhstan_region",
|
||||
"Шығыс Қазақстан облысы": "east_kazakhstan_region",
|
||||
"Жамбылская область": "zhambyl_region",
|
||||
"Жамбыл облысы": "zhambyl_region",
|
||||
"Западно-Казахстанская область": "west_kazakhstan_region",
|
||||
"Батыс Қазақстан облысы": "west_kazakhstan_region",
|
||||
"Карагандинская область": "karaganda_region",
|
||||
"Қарағанды облысы": "karaganda_region",
|
||||
"Костанайская область": "kostanay_region",
|
||||
"Қостанай облысы": "kostanay_region",
|
||||
"Кызылординская область": "kyzylorda_region",
|
||||
"Қызылорда облысы": "kyzylorda_region",
|
||||
"Мангистауская область": "mangystau_region",
|
||||
"Маңғыстау облысы": "mangystau_region",
|
||||
"Павлодарская область": "pavlodar_region",
|
||||
"Павлодар облысы": "pavlodar_region",
|
||||
"Северо-Казахстанская область": "north_kazakhstan_region",
|
||||
"Солтүстік Қазақстан облысы": "north_kazakhstan_region",
|
||||
"Туркестанская область": "turkistan_region",
|
||||
"Түркістан облысы": "turkistan_region",
|
||||
"область Абай": "abai_region",
|
||||
"Абай облысы": "abai_region",
|
||||
"область Жетісу": "jetisu_region",
|
||||
"Жетісу облысы": "jetisu_region",
|
||||
"область Ұлытау": "ulytau_region",
|
||||
"Ұлытау облысы": "ulytau_region",
|
||||
}
|
||||
for input, want := range cases {
|
||||
got := r.Resolve(input, SourceCLI)
|
||||
if got.RegionCode != want || got.Confidence < MediumConfidence {
|
||||
t.Fatalf("%q => %+v want %s", input, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAbbreviations(t *testing.T) {
|
||||
r := NewDefaultResolver()
|
||||
cases := map[string]string{"ВКО": "east_kazakhstan_region", "ЗКО": "west_kazakhstan_region", "СКО": "north_kazakhstan_region", "vko": "east_kazakhstan_region", "zko": "west_kazakhstan_region", "sko": "north_kazakhstan_region"}
|
||||
for input, want := range cases {
|
||||
if got := r.Resolve(input, SourceCLI); got.RegionCode != want || got.ReasonCode != "abbreviation" {
|
||||
t.Fatalf("%q => %+v want %s", input, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAlmatyAmbiguityAndClarification(t *testing.T) {
|
||||
r := NewDefaultResolver()
|
||||
for _, input := range []string{"Алматы", "almaty", "Алматы тарифы"} {
|
||||
got := r.Resolve(input, SourceCLI)
|
||||
if !got.NeedsClarification || got.ReasonCode != "ambiguous_almaty" || len(got.Candidates) != 2 {
|
||||
t.Fatalf("%q => %+v", input, got)
|
||||
}
|
||||
}
|
||||
pending := []string{"almaty_city", "almaty_region"}
|
||||
if got := r.ResolvePending(pending, "город", SourceCLI); got.RegionCode != "almaty_city" {
|
||||
t.Fatalf("city clarification: %+v", got)
|
||||
}
|
||||
if got := r.ResolvePending(pending, "қала", SourceCLI); got.RegionCode != "almaty_city" {
|
||||
t.Fatalf("kk city clarification: %+v", got)
|
||||
}
|
||||
if got := r.ResolvePending(pending, "область", SourceCLI); got.RegionCode != "almaty_region" {
|
||||
t.Fatalf("region clarification: %+v", got)
|
||||
}
|
||||
if got := r.ResolvePending(pending, "облыс", SourceCLI); got.RegionCode != "almaty_region" {
|
||||
t.Fatalf("kk region clarification: %+v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFalsePositivesAndDisabled(t *testing.T) {
|
||||
r := NewDefaultResolver()
|
||||
for _, input := range []string{"Казахтелеком", "Казахстан", "область", "город", "мой тариф", "астана балет", "карагандинский уголь", "у меня вопрос по шымкентскому номеру", "алматинский район"} {
|
||||
got := r.Resolve(input, SourceCLI)
|
||||
if got.RegionCode != "" {
|
||||
t.Fatalf("false positive %q => %+v", input, got)
|
||||
}
|
||||
}
|
||||
got := r.Resolve("Байконур", SourceCLI)
|
||||
if got.Intent != IntentUnsupported || got.ReasonCode != "disabled_region" {
|
||||
t.Fatalf("disabled: %+v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSelectionPolicy(t *testing.T) {
|
||||
r := NewDefaultResolver()
|
||||
astana := r.Resolve("Астана", SourceCLI)
|
||||
if d := ShouldApplyRegionResolution(SelectionContext{CurrentState: state.StateLanguageSelection, CurrentLanguage: state.LanguageUnknown}, astana); d.Apply || d.ReasonCode != "language_required" {
|
||||
t.Fatalf("language selection applied region: %+v", d)
|
||||
}
|
||||
if d := ShouldApplyRegionResolution(SelectionContext{CurrentState: state.StateRegionSelection, CurrentLanguage: state.LanguageRU}, astana); !d.Apply || d.RegionCode != "astana_city" {
|
||||
t.Fatalf("region selection did not apply: %+v", d)
|
||||
}
|
||||
amb := r.Resolve("Алматы", SourceCLI)
|
||||
if d := ShouldApplyRegionResolution(SelectionContext{CurrentState: state.StateRegionSelection, CurrentLanguage: state.LanguageRU}, amb); !d.NeedsClarification {
|
||||
t.Fatalf("ambiguous not clarified: %+v", d)
|
||||
}
|
||||
if d := ShouldApplyRegionResolution(SelectionContext{CurrentState: state.StateReadyToHelp, CurrentLanguage: state.LanguageRU, CurrentRegionCode: "astana_city", AllowChange: true}, astana); d.Apply {
|
||||
t.Fatalf("random mention switched: %+v", d)
|
||||
}
|
||||
astana.Intent = IntentRegionChange
|
||||
if d := ShouldApplyRegionResolution(SelectionContext{CurrentState: state.StateReadyToHelp, CurrentLanguage: state.LanguageRU, CurrentRegionCode: "shymkent_city", AllowChange: true}, astana); !d.Apply {
|
||||
t.Fatalf("explicit change not applied: %+v", d)
|
||||
}
|
||||
if d := ShouldApplyRegionResolution(SelectionContext{CurrentState: state.StateEnded, CurrentLanguage: state.LanguageRU}, astana); d.Apply {
|
||||
t.Fatalf("ended applied: %+v", d)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user