package quikexport import ( "net/http" "net/http/httptest" "net/url" "os" "path/filepath" "slices" "strings" "testing" ) // Пакеты: набор таблиц, обратное определение пакетов, обязательный Portfolio. func TestQuikExportPackages(t *testing.T) { tabs := quikExportPackageTables([]string{"positions", "refs"}) for _, want := range []string{"Portfolio", "DepoLimits", "MoneyLimits", "Securities", "SecDepoAccount"} { if !slices.Contains(tabs, want) { t.Fatalf("нет %s в %v", want, tabs) } } if slices.Contains(tabs, "AllTrades") { t.Fatalf("лишняя таблица рынка: %v", tabs) } if got := quikExportPackageTables(nil); len(got) != 1 || got[0] != "Portfolio" { t.Fatalf("без пакетов остаётся только Portfolio: %v", got) } pk := quikExportPackagesOf(tabs) if !slices.Contains(pk, "positions") || !slices.Contains(pk, "refs") || !slices.Contains(pk, "risk") { t.Fatalf("обратное определение: %v", pk) } if slices.Contains(pk, "deals") { t.Fatalf("пакет сделок не выбран: %v", pk) } // Каждая таблица пакета есть в каталоге экспортёра. known := map[string]bool{} for _, tb := range quikExportTables { known[tb.Name] = true } for _, p := range quikExportPackages { for _, tb := range p.Tables { if !known[tb] { t.Errorf("пакет %s: таблицы %s нет в каталоге", p.Key, tb) } } } } // Старая настройка (preset=depo) переносится в пакеты. func TestQuikExportPresetMigration(t *testing.T) { s := QuikExportSettings{Preset: "depo"}.withDefaults() if s.Preset != "packages" || len(s.Packages) == 0 { t.Fatalf("миграция набора: %+v", s.Packages) } if !slices.Contains(s.Tables, "DepoLimits") || !slices.Contains(s.Tables, "Portfolio") { t.Fatalf("таблицы после миграции: %v", s.Tables) } } // Раздел настроек рисует пакеты и сохраняет выбор. func TestQuikExportPackagesSection(t *testing.T) { dir := t.TempDir() keyPath := filepath.Join(dir, "module.key") if err := os.WriteFile(keyPath, []byte(testKey+"\n"), 0o600); err != nil { t.Fatal(err) } srv, err := New(Config{StorePath: filepath.Join(dir, "settings.json"), SetupPath: filepath.Join(dir, "setup.json"), KeyPath: keyPath}) if err != nil { t.Fatal(err) } h := srv.Handler() req := httptest.NewRequest(http.MethodGet, "/section", nil) req.Header.Set("X-BJ-Module-Key", testKey) req.Header.Set("X-BJ-Licensed", "1") rec := httptest.NewRecorder() h.ServeHTTP(rec, req) if rec.Code != http.StatusOK { t.Fatalf("раздел: %d %s", rec.Code, rec.Body.String()) } for _, want := range []string{"Какие данные выгружаем", "Позиции и деньги клиента", "Цены для оценки портфеля", "Личный кабинет"} { if !strings.Contains(rec.Body.String(), want) { t.Errorf("в разделе нет %q", want) } } form := url.Values{"part": {"volume"}, "mode": {"packages"}, "packages": {"risk", "positions", "prices"}, "portfolio_period": {"60"}, "param_period": {"30"}, "limit_kinds": {"0, 1, 365"}, "debug_level": {"1"}} req = httptest.NewRequest(http.MethodPost, "/admin/setup/quikexport", strings.NewReader(form.Encode())) req.Header.Set("Content-Type", "application/x-www-form-urlencoded") req.Header.Set("X-BJ-Module-Key", testKey) rec = httptest.NewRecorder() h.ServeHTTP(rec, req) if rec.Code != http.StatusNoContent { t.Fatalf("сохранение: %d", rec.Code) } s := srv.store.Get() if s.Preset != "packages" || !slices.Contains(s.Tables, "DepoLimits") || !slices.Contains(s.Tables, "Params") { t.Fatalf("после сохранения: %v %v", s.Preset, s.Tables) } if slices.Contains(s.Tables, "Trades") { t.Fatalf("пакет сделок не выбирали: %v", s.Tables) } }