mirror of
https://github.com/AmanTahiliani/box-box.git
synced 2026-08-07 11:54:59 -04:00
87 lines
3.4 KiB
Go
87 lines
3.4 KiB
Go
package web
|
|
|
|
import (
|
|
"database/sql"
|
|
"fmt"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/AmanTahiliani/box-box/internal/api"
|
|
_ "modernc.org/sqlite"
|
|
)
|
|
|
|
type fakeStaleReporter bool
|
|
|
|
func (f fakeStaleReporter) LastResponseWasStale() bool { return bool(f) }
|
|
|
|
func TestStaleFreshnessTakesPrecedenceOverPartialAndLimited(t *testing.T) {
|
|
for _, fallback := range []string{"partial", "limited"} {
|
|
recorder := httptest.NewRecorder()
|
|
markOpenF1Availability(recorder, fakeStaleReporter(true), fallback)
|
|
if recorder.Header().Get(dataFreshnessHeader) != "stale" {
|
|
t.Fatalf("fallback %q overrode stale: %q", fallback, recorder.Header().Get(dataFreshnessHeader))
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestOpenF1HandlerReportsFreshThenStaleSuccess(t *testing.T) {
|
|
year := time.Now().Year()
|
|
upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
_, _ = fmt.Fprintf(w, `[{"meeting_key":1,"meeting_name":"British Grand Prix","year":%d}]`, year)
|
|
}))
|
|
client := api.NewOpenF1Client(upstream.URL, time.Second)
|
|
t.Cleanup(func() { _ = client.Close() })
|
|
server := NewServer(client, 0, nil)
|
|
cacheKey := fmt.Sprintf("%s/v1/meetings?year=%d", upstream.URL, year)
|
|
requestURL := fmt.Sprintf("/api/v1/meetings?year=%d&source=openf1", year)
|
|
defer func() {
|
|
// Keep the shared application cache clean even if this test fails.
|
|
db, err := sql.Open("sqlite", api.DefaultCacheDBPath()+"?_busy_timeout=5000")
|
|
if err == nil {
|
|
_, _ = db.Exec(`DELETE FROM cache WHERE key = ?`, cacheKey)
|
|
_ = db.Close()
|
|
}
|
|
}()
|
|
|
|
fresh := httptest.NewRecorder()
|
|
server.handleMeetings(fresh, httptest.NewRequest(http.MethodGet, requestURL, nil))
|
|
if fresh.Code != http.StatusOK || fresh.Header().Get(dataSourceHeader) != "openf1" || fresh.Header().Get(dataFreshnessHeader) != "fresh" {
|
|
t.Fatalf("fresh response status/metadata = %d %q/%q body=%s", fresh.Code, fresh.Header().Get(dataSourceHeader), fresh.Header().Get(dataFreshnessHeader), fresh.Body.String())
|
|
}
|
|
|
|
db, err := sql.Open("sqlite", api.DefaultCacheDBPath()+"?_busy_timeout=5000")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := db.Exec(`UPDATE cache SET created_at = ? WHERE key = ?`, time.Now().Add(-48*time.Hour).Unix(), cacheKey); err != nil {
|
|
_ = db.Close()
|
|
t.Fatal(err)
|
|
}
|
|
_ = db.Close()
|
|
upstream.Close()
|
|
|
|
stale := httptest.NewRecorder()
|
|
server.handleMeetings(stale, httptest.NewRequest(http.MethodGet, requestURL, nil))
|
|
if stale.Code != http.StatusOK || stale.Header().Get(dataSourceHeader) != "openf1" || stale.Header().Get(dataFreshnessHeader) != "stale" {
|
|
t.Fatalf("stale response status/metadata = %d %q/%q body=%s", stale.Code, stale.Header().Get(dataSourceHeader), stale.Header().Get(dataFreshnessHeader), stale.Body.String())
|
|
}
|
|
}
|
|
|
|
func TestFreshnessHeadersAreExposedToBrowserClients(t *testing.T) {
|
|
handler := withCORS(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
|
markDataResponse(w, "local", "partial")
|
|
writeJSON(w, map[string]bool{"ok": true})
|
|
}))
|
|
recorder := httptest.NewRecorder()
|
|
handler.ServeHTTP(recorder, httptest.NewRequest(http.MethodGet, "/api/v1/test", nil))
|
|
|
|
if got := recorder.Header().Get("Access-Control-Expose-Headers"); got != dataSourceHeader+", "+dataFreshnessHeader {
|
|
t.Fatalf("exposed headers = %q", got)
|
|
}
|
|
if recorder.Header().Get(dataSourceHeader) != "local" || recorder.Header().Get(dataFreshnessHeader) != "partial" {
|
|
t.Fatalf("data metadata = %q/%q", recorder.Header().Get(dataSourceHeader), recorder.Header().Get(dataFreshnessHeader))
|
|
}
|
|
}
|