package dashboard import ( "fmt" "html" "net/http" "net/url" "regexp" "strconv" "strings" "testing" "time" ) // Tests for the scale features: background scan panel, server-side // pagination/filters on /ips and /registry, bulk selection by filter, and the // bounded overview. func ipRowLink(ip string) string { return `href="/ips/` + ip + `"` } func countRows(body string) int { return strings.Count(body, `name="addresses" value="`) } func hasHXTriggerEvery(body string) bool { return strings.Contains(body, `hx-trigger="every 2s"`) } var hrefRe = regexp.MustCompile(`href="([^"]*)"[^>]*rel="(prev|next)"`) // pagerLink extracts the (unescaped, parsed) prev/next link of the pager. func pagerLink(t *testing.T, body, rel string) *url.URL { t.Helper() for _, m := range hrefRe.FindAllStringSubmatch(body, -1) { if m[2] == rel { u, err := url.Parse(html.UnescapeString(m[1])) if err != nil { t.Fatalf("parse pager link %q: %v", m[1], err) } return u } } return nil } func TestIPsScan(t *testing.T) { fake, caURL := newFakeControlAPI(t) fake.scanFreeAddresses = []string{"5.5.5.5", "5.5.5.6"} fake.scanRunPolls = 2 ts := newTestServer(t, caURL) // Start: answers at once with the panel; it polls itself, the scan // buttons are disabled and nothing is queued yet. resp, body := doReq(t, ts, reqOpts{method: http.MethodPost, path: "/ips/scan"}) if resp.StatusCode != http.StatusOK { t.Fatalf("status = %d, want 200", resp.StatusCode) } for _, want := range []string{ `id="scan-progress"`, `hx-get="/ips/scan/status"`, `hx-trigger="every 2s"`, "читаются страницы", ``, ` disabled`, } { if !strings.Contains(body, want) { t.Fatalf("expected %q in the running panel, got:\n%s", want, body) } } if resp.Header.Get("HX-Trigger") != "" { t.Fatalf("a running scan must not fire scan-finished, got %q", resp.Header.Get("HX-Trigger")) } if len(fake.ips) != 0 { t.Fatalf("nothing should be queued before the job finishes, got %+v", fake.ips) } // First poll: still running, keeps polling. resp, body = doReq(t, ts, reqOpts{path: "/ips/scan/status"}) if !hasHXTriggerEvery(body) || resp.Header.Get("HX-Trigger") != "" { t.Fatalf("expected a still-polling panel without HX-Trigger, got %q:\n%s", resp.Header.Get("HX-Trigger"), body) } // Second poll: finished — no polling trigger, HX-Trigger tells the table to reload. resp, body = doReq(t, ts, reqOpts{path: "/ips/scan/status"}) if hasHXTriggerEvery(body) || strings.Contains(body, `hx-get="/ips/scan/status"`) { t.Fatalf("a finished panel must stop polling, got:\n%s", body) } if got := resp.Header.Get("HX-Trigger"); got != "scan-finished" { t.Fatalf("HX-Trigger = %q, want scan-finished", got) } for _, want := range []string{"готово", "
добавлено
2
", `прочитано страниц
33
"} { if !strings.Contains(page, want) { t.Fatalf("expected %q in the page, got:\n%s", want, page) } } if strings.Index(page, `id="scan-progress"`) > strings.Index(page, `