dana-medical-site/internal/api/onec_all_dates_test.go
2026-10-21 12:38:59 +00:00

96 lines
3.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package api
import (
"bytes"
"context"
"encoding/json"
"fmt"
"net/http/httptest"
"os"
"testing"
"time"
"dana/internal/onec"
"dana/internal/storage"
)
// Uses only a disposable database; no real 1C calls or patient records.
func TestAutonomousAllActualFutureDates(t *testing.T) {
dsn := os.Getenv("DANA_AUTONOMY_TEST_DSN")
if dsn == "" {
t.Skip("requires disposable autonomy DB")
}
ctx := context.Background()
st, err := storage.New(ctx, dsn)
if err != nil {
t.Fatal(err)
}
defer st.Close()
if err = st.Migrate(ctx); err != nil {
t.Fatal(err)
}
app := &API{store: st, limiter: newRateLimiter(), onecHook: "all-dates-test"}
mux := app.Routes()
call := func(method, path string, body any, want int) *httptest.ResponseRecorder {
t.Helper()
b, _ := json.Marshal(body)
r := httptest.NewRequest(method, path, bytes.NewReader(b))
r.Header.Set("X-Api-Key", "all-dates-test")
w := httptest.NewRecorder()
mux.ServeHTTP(w, r)
if w.Code != want {
t.Fatalf("%s %s: %d, want %d: %s", method, path, w.Code, want, w.Body.String())
}
return w
}
doctor := fmt.Sprintf("all-dates-%d", time.Now().UnixNano())
var doctorID int64
if err = st.Pool().QueryRow(ctx, `INSERT INTO doctors(slug,last_name,first_name,booking_provider) VALUES($1,'Тест','Все даты','native') RETURNING id`, doctor).Scan(&doctorID); err != nil {
t.Fatal(err)
}
if _, err = st.Pool().Exec(ctx, `INSERT INTO onec_doctors(onec_id,full_name,doctor_id) VALUES($1,'Тест Все даты',$2)`, doctor, doctorID); err != nil {
t.Fatal(err)
}
if err = st.SetBookingSettings(ctx, storage.BookingSettings{}); err != nil {
t.Fatal(err)
}
from := time.Now().UTC().Truncate(time.Hour)
far := from.AddDate(0, 0, 90)
end := far.Add(30 * time.Minute)
to := end.Add(time.Hour)
slot := onec.Slot{DoctorID: doctor, BranchID: "branch", Start: far, End: end, Status: "free"}
payload := onecSyncPayload{From: &from, To: &to, Branches: []onec.Branch{}, Doctors: []onec.Doctor{}, Services: []onecDoctorServices{}, Slots: []onec.Slot{slot}}
call("POST", "/api/v1/onec/sync/all", payload, 200)
shown := call("GET", "/api/v1/doctors/"+doctor+"/slots", nil, 200)
var result struct {
Data struct {
Enabled bool `json:"enabled"`
Slots []storage.OnecSlot `json:"slots"`
} `json:"data"`
}
if err = json.Unmarshal(shown.Body.Bytes(), &result); err != nil {
t.Fatal(err)
}
if !result.Data.Enabled || len(result.Data.Slots) != 1 || !result.Data.Slots[0].Start.Equal(far) {
t.Fatalf("actual distant slot hidden: %s", shown.Body.String())
}
creation := appointmentInput{DoctorSlug: doctor, Start: far.Format(time.RFC3339), Name: "Test", Phone: "79990000001", Consent: true, RequestID: doctor}
made := call("POST", "/api/v1/appointments", creation, 201)
if !bytes.Contains(made.Body.Bytes(), []byte(`"mode":"pending"`)) {
t.Fatal("distant actual slot not queued")
}
// A push claiming free must not reopen the pending reservation.
call("POST", "/api/v1/onec/sync/all", payload, 200)
hidden := call("GET", "/api/v1/doctors/"+doctor+"/slots", nil, 200)
if err = json.Unmarshal(hidden.Body.Bytes(), &result); err != nil {
t.Fatal(err)
}
if len(result.Data.Slots) != 0 {
t.Fatal("reserved distant slot reopened")
}
// Removing the calendar cutoff must not permit invented dates.
creation.Start = far.Add(time.Hour).Format(time.RFC3339)
creation.RequestID = doctor + "-invented"
call("POST", "/api/v1/appointments", creation, 409)
}