dana-medical-site/internal/api/onec_webhook_test.go

69 lines
2.5 KiB
Go

package api
import (
"net/http"
"net/http/httptest"
"strings"
"testing"
"dana/internal/onec"
)
func postEvent(a *API, key, body string) *httptest.ResponseRecorder {
req := httptest.NewRequest(http.MethodPost, "/api/v1/onec/events", strings.NewReader(body))
if key != "" {
req.Header.Set("X-Api-Key", key)
}
rec := httptest.NewRecorder()
a.onecEvents(rec, req)
return rec
}
func TestOnecEventsAuthAndValidation(t *testing.T) {
a := &API{limiter: newRateLimiter(), onec: onec.New("http://127.0.0.1:1", "k", "X-Api-Key")}
if rec := postEvent(a, "secret", `{"event":"schedule_changed"}`); rec.Code != http.StatusNotFound {
t.Fatalf("вебхук без ключа в настройках должен быть выключен, получили %d", rec.Code)
}
a.WithOneCWebhook("secret")
if rec := postEvent(a, "", `{"event":"schedule_changed"}`); rec.Code != http.StatusUnauthorized {
t.Fatalf("без ключа: %d", rec.Code)
}
if rec := postEvent(a, "wrong", `{"event":"schedule_changed"}`); rec.Code != http.StatusUnauthorized {
t.Fatalf("неверный ключ: %d", rec.Code)
}
if rec := postEvent(a, "secret", `{"event":"nope"}`); rec.Code != http.StatusBadRequest {
t.Fatalf("неизвестное событие: %d", rec.Code)
}
if rec := postEvent(a, "secret", `{"event":"appointment_status","appointment_id":"A-1","status":"weird"}`); rec.Code != http.StatusBadRequest {
t.Fatalf("неверный статус: %d", rec.Code)
}
if rec := postEvent(a, "secret", `{"event":"appointment_status","status":"cancelled"}`); rec.Code != http.StatusBadRequest {
t.Fatalf("нет номера записи: %d", rec.Code)
}
if rec := postEvent(a, "secret", `not json`); rec.Code != http.StatusBadRequest {
t.Fatalf("битый JSON: %d", rec.Code)
}
}
func TestOnecEventsBruteForceLimit(t *testing.T) {
a := &API{limiter: newRateLimiter(), onec: onec.New("http://127.0.0.1:1", "k", "X-Api-Key")}
a.WithOneCWebhook("secret")
var last int
for i := 0; i < 25; i++ {
last = postEvent(a, "guess", `{}`).Code
}
if last != http.StatusTooManyRequests {
t.Fatalf("перебор ключа должен упираться в лимит, получили %d", last)
}
}
func TestAutonomousWebhookValidationWithoutBridge(t *testing.T) {
a := &API{limiter: newRateLimiter()}
a.WithOneCWebhook("secret")
if rec := postEvent(a, "secret", `{"event":"unsupported"}`); rec.Code != http.StatusBadRequest {
t.Fatalf("bridge-free route disabled: %d", rec.Code)
}
}