package lkgateway import ( "context" "path/filepath" "strings" "testing" "time" ) func TestLKDepoRejectText(t *testing.T) { res := depoResult{Ran: true, Recommend: "reject", Secs: []depoSecResult{{ Security: "RU0009029540", Checks: []depoCheck{ {Name: "Российский выпуск (RU-ISIN)", OK: true, Code: "M2M01"}, {Name: "Остаток ≥ количеству (98070.04)", OK: false, Code: "QTY", Detail: "на торговом счёте ВТНКЦ00000001: 0 шт., списываем 10 — недостаточно"}, {Name: "Задолженность по комиссиям", OK: true, Warn: true}, }, }}} code, short, text := lkDepoRejectText(res) if code != "QTY" { t.Errorf("код %q, ожидали QTY", code) } if short != "Отказ по результатам проверки депозитария: "+m2mCodeLabel("QTY") || strings.Contains(short, "Причина") { t.Errorf("короткий текст для ЛК: %q", short) } for _, want := range []string{"Отказ по результатам проверки депозитария", "(QTY)", "Причина: Остаток ≥ количеству (98070.04): на торговом счёте"} { if !strings.Contains(text, want) { t.Errorf("в тексте нет %q: %s", want, text) } } if strings.Contains(text, "Российский выпуск") || strings.Contains(text, "комиссиям") { t.Errorf("пройденные проверки не должны попадать в причину: %s", text) } } func TestLKEmulateNSD(t *testing.T) { rc, err := NewRuntimeConfig(filepath.Join(t.TempDir(), "setup.json")) if err != nil { t.Fatal(err) } s := rc.Snapshot() s.LK.ActiveEnv, s.NSD.Profile = "prod", "test3-gost" if err := rc.UpdateLK(s.LK); err != nil { t.Fatal(err) } if err := rc.UpdateNSD(s.NSD); err != nil { t.Fatal(err) } if on, why := lkEmulateNSD(rc); !on || !strings.Contains(why, "тестовом контуре НРД") { t.Errorf("боевой ЛК + тестовый ИШ: ожидали имитацию, получили %v %q", on, why) } s.LK.ActiveEnv = "test" _ = rc.UpdateLK(s.LK) if on, _ := lkEmulateNSD(rc); on { t.Error("тестовый ЛК без флага: имитации быть не должно") } s.LK.EmulateNSD = true _ = rc.UpdateLK(s.LK) if on, _ := lkEmulateNSD(rc); on { t.Error("флаг в настройках без режима разработки не действует") } devModeForced = true defer func() { devModeForced = false }() if on, why := lkEmulateNSD(rc); !on || why != "включена в настройках" { t.Errorf("флаг в настройках: %v %q", on, why) } } // applyNSDEmuSettings переносит настройки со страницы «Эмуляторы» в конфиг работающего // сендера: исход и код отказа меняются без пересоздания (канал решений тот же). func TestApplyNSDEmuSettings(t *testing.T) { old := lkEmuSender lkEmuSender = newLKEmuSender() defer func() { lkEmuSender.Stop(); lkEmuSender = old }() rc, err := NewRuntimeConfig(filepath.Join(t.TempDir(), "setup.json")) if err != nil { t.Fatal(err) } if err := rc.UpdateNSDEmu(NSDEmuSettings{DelaySec: 1, Outcome: "reject", RejectCode: "18"}); err != nil { t.Fatal(err) } applyNSDEmuSettings(rc) if _, err := lkEmuSender.Send(context.Background(), sendFailRequest()); err != nil { t.Fatal(err) } select { case d := <-lkEmuSender.Decisions(): rej := d.Data.Securities[0].TransferDecision.Rejection if rej == nil { t.Fatal("ожидался отказ (outcome=reject)") } if len(rej.Codes) != 1 || rej.Codes[0] != "18" { t.Errorf("код отказа %v, ожидался 18", rej.Codes) } case <-time.After(3 * time.Second): t.Fatal("решение не пришло — задержка из настроек не применилась") } }