dana-medical-site/internal/sberhealth/client_test.go
2026-10-14 13:33:13 +00:00

158 lines
5.7 KiB
Go

package sberhealth
import (
"bytes"
"context"
"io"
"net/http"
"net/http/httptest"
"reflect"
"strings"
"testing"
"time"
)
func sampleDates() (time.Time, time.Time) {
zone := time.FixedZone("Europe/Moscow", 10800)
return time.Date(2026, 9, 28, 0, 0, 0, 0, zone), time.Date(2026, 10, 5, 0, 0, 0, 0, zone)
}
func TestConfig(t *testing.T) {
c, err := New("", "")
if err != nil || c.Configured() {
t.Fatal("empty config must disable download")
}
for _, args := range [][2]string{{"", "294888"}, {"session=synthetic", ""}, {"Cookie", "294888"}, {"session=x\r\nInjected: x", "294888"}, {"session=x", "294888&other=1"}} {
if _, err := New(args[0], args[1]); err == nil {
t.Fatal("invalid config accepted")
}
}
}
func TestSuppliedURLFilters(t *testing.T) {
from, till := sampleDates()
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
want := map[string][]string{
"kind": {"doctor"}, "clinic_id": {"294888"}, "periodInput": {"week"}, "crDateFrom": {"28.09.2026"}, "crDateTill": {"05.10.2026"},
"page": {"1"}, "admissionStatus": {"-1"}, "sourceType": {"-1"}, "type": {"xls"},
}
if r.Method != "GET" || r.URL.Path != "/lk/requests/listOld" || !reflect.DeepEqual(map[string][]string(r.URL.Query()), want) || r.Header.Get("Cookie") != "session=synthetic" {
t.Error("request does not reproduce supplied URL")
}
_, _ = w.Write([]byte{0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1})
}))
defer s.Close()
c, _ := New("session=synthetic", "294888")
c.endpoint = s.URL + "/lk/requests/listOld"
export, err := c.Download(context.Background(), from, till, "week")
if err != nil || export.Format != "xls" {
t.Fatal("XLS detection failed", err)
}
}
func TestExportFormatDetectionAndLoginRejection(t *testing.T) {
from, till := sampleDates()
for _, tc := range []struct {
name, body, ct, disposition, format string
}{
{"xlsx", "PK\x03\x04placeholder", "application/octet-stream", "", "xlsx"},
{"html-xls", "<html><table><tr><td>synthetic</td></tr></table></html>", "text/html", `attachment; filename="requests.xls"`, "html"},
{"html-excel-mime", "<table><tr><td>synthetic</td></tr></table>", "application/vnd.ms-excel", "", "html"},
{"login-table", "<html><table>private-secret Login</table></html>", "text/html", "", ""},
{"login-attachment", "<html>private-secret Login</html>", "text/html", `attachment; filename="requests.xls"`, ""},
{"json-error", `{"error":"private-secret"}`, "application/json", "", ""},
} {
t.Run(tc.name, func(t *testing.T) {
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", tc.ct)
w.Header().Set("Content-Disposition", tc.disposition)
_, _ = io.WriteString(w, tc.body)
}))
defer s.Close()
c, _ := New("session=synthetic", "294888")
c.endpoint = s.URL
export, err := c.Download(context.Background(), from, till, "week")
if tc.format == "" {
if err == nil || strings.Contains(err.Error(), "private-secret") {
t.Fatal("unknown/login response accepted or leaked")
}
} else if err != nil || export.Format != tc.format {
t.Fatal("format detection incorrect", err)
}
})
}
}
func TestErrorsAndRedirects(t *testing.T) {
from, till := sampleDates()
redirected := 0
target := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { redirected++ }))
defer target.Close()
for _, status := range []int{302, 401, 403, 429, 500} {
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Location", target.URL)
w.WriteHeader(status)
_, _ = io.WriteString(w, "private-secret")
}))
c, _ := New("session=synthetic", "294888")
c.endpoint = s.URL
export, err := c.Download(context.Background(), from, till, "week")
s.Close()
if err == nil || len(export.Data) != 0 || strings.Contains(err.Error(), "private-secret") {
t.Fatal("missing or leaking error")
}
}
if redirected != 0 {
t.Fatal("redirect forwarded session")
}
}
func TestMonthlyFiltersAndInvalidDates(t *testing.T) {
zone := time.FixedZone("Europe/Moscow", 10800)
from, till := time.Date(2026, 10, 1, 0, 0, 0, 0, zone), time.Date(2026, 10, 31, 0, 0, 0, 0, zone)
requests := 0
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
requests++
q := r.URL.Query()
if q.Get("periodInput") != "month" || q.Get("crDateFrom") != "01.10.2026" || q.Get("crDateTill") != "31.10.2026" {
t.Error("monthly date filters incorrect")
}
_, _ = w.Write([]byte("PK\x03\x04placeholder"))
}))
defer s.Close()
c, _ := New("session=synthetic", "294888")
c.endpoint = s.URL
if _, err := c.Download(context.Background(), from, till, "month"); err != nil {
t.Fatal(err)
}
for _, args := range []struct {
from, till time.Time
mode string
}{{till, from, "week"}, {from.Add(time.Hour), till, "week"}, {from, till, "auto"}, {from, from.AddDate(2, 0, 0), "month"}} {
if _, err := c.Download(context.Background(), args.from, args.till, args.mode); err == nil {
t.Fatal("invalid filters accepted")
}
}
if requests != 1 {
t.Fatal("invalid filters reached server")
}
}
func TestSizeLimitAndCancellation(t *testing.T) {
from, till := sampleDates()
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
_, _ = w.Write(append([]byte("PK\x03\x04"), bytes.Repeat([]byte{'x'}, maxDownload)...))
}))
defer s.Close()
c, _ := New("session=synthetic", "294888")
c.endpoint = s.URL
if _, err := c.Download(context.Background(), from, till, "week"); err == nil {
t.Fatal("oversized download accepted")
}
ctx, cancel := context.WithCancel(context.Background())
cancel()
if _, err := c.Download(ctx, from, till, "week"); err != context.Canceled {
t.Fatal("cancellation lost", err)
}
}