163 lines
4.3 KiB
Go
163 lines
4.3 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestLoadLatestPollDefaults(t *testing.T) {
|
|
for _, k := range []string{
|
|
"LATEST_CHAPTER_POLL_ENABLED", "LATEST_CHAPTER_POLL_COOLDOWN",
|
|
"LATEST_CHAPTER_POLL_INTERVAL", "LATEST_CHAPTER_POLL_STAGGER",
|
|
"LATEST_CHAPTER_POLL_BATCH",
|
|
} {
|
|
t.Setenv(k, "")
|
|
}
|
|
|
|
got := loadLatestPoll()
|
|
want := LatestPoll{
|
|
Enabled: true,
|
|
Cooldown: time.Hour,
|
|
Interval: 10 * time.Minute,
|
|
Stagger: 20 * time.Second,
|
|
Batch: 14,
|
|
}
|
|
if got != want {
|
|
t.Fatalf("loadLatestPoll() = %+v, want %+v", got, want)
|
|
}
|
|
}
|
|
|
|
func TestLoadLatestPollEnabledParsing(t *testing.T) {
|
|
tests := []struct {
|
|
raw string
|
|
want bool
|
|
}{
|
|
{"", true}, {"1", true}, {"true", true}, {"TRUE", true}, {"yes", true}, {"on", true},
|
|
{"0", false}, {"false", false}, {"False", false}, {"no", false}, {"off", false},
|
|
{"maybe", true}, // unparseable falls back to the default
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run("raw="+tt.raw, func(t *testing.T) {
|
|
t.Setenv("LATEST_CHAPTER_POLL_ENABLED", tt.raw)
|
|
if got := loadLatestPoll().Enabled; got != tt.want {
|
|
t.Fatalf("Enabled = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestLoadLatestPollClampsAndFallsBack(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
env map[string]string
|
|
wantFrom func(LatestPoll) any
|
|
want any
|
|
}{
|
|
{
|
|
name: "cooldown below the floor is clamped up",
|
|
env: map[string]string{"LATEST_CHAPTER_POLL_COOLDOWN": "1m"},
|
|
wantFrom: func(p LatestPoll) any { return p.Cooldown },
|
|
want: 15 * time.Minute,
|
|
},
|
|
{
|
|
name: "cooldown at the floor is kept",
|
|
env: map[string]string{"LATEST_CHAPTER_POLL_COOLDOWN": "15m"},
|
|
wantFrom: func(p LatestPoll) any { return p.Cooldown },
|
|
want: 15 * time.Minute,
|
|
},
|
|
{
|
|
name: "a valid override is honoured",
|
|
env: map[string]string{"LATEST_CHAPTER_POLL_INTERVAL": "5m"},
|
|
wantFrom: func(p LatestPoll) any { return p.Interval },
|
|
want: 5 * time.Minute,
|
|
},
|
|
{
|
|
name: "an unparseable duration falls back",
|
|
env: map[string]string{"LATEST_CHAPTER_POLL_INTERVAL": "ten minutes"},
|
|
wantFrom: func(p LatestPoll) any { return p.Interval },
|
|
want: 10 * time.Minute,
|
|
},
|
|
{
|
|
name: "a zero duration falls back",
|
|
env: map[string]string{"LATEST_CHAPTER_POLL_STAGGER": "0s"},
|
|
wantFrom: func(p LatestPoll) any { return p.Stagger },
|
|
want: 20 * time.Second,
|
|
},
|
|
{
|
|
name: "a valid batch is honoured",
|
|
env: map[string]string{"LATEST_CHAPTER_POLL_BATCH": "30"},
|
|
wantFrom: func(p LatestPoll) any { return p.Batch },
|
|
want: 30,
|
|
},
|
|
{
|
|
name: "a negative batch falls back",
|
|
env: map[string]string{"LATEST_CHAPTER_POLL_BATCH": "-5"},
|
|
wantFrom: func(p LatestPoll) any { return p.Batch },
|
|
want: 14,
|
|
},
|
|
{
|
|
name: "a non-numeric batch falls back",
|
|
env: map[string]string{"LATEST_CHAPTER_POLL_BATCH": "lots"},
|
|
wantFrom: func(p LatestPoll) any { return p.Batch },
|
|
want: 14,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
for k, v := range tt.env {
|
|
t.Setenv(k, v)
|
|
}
|
|
if got := tt.wantFrom(loadLatestPoll()); got != tt.want {
|
|
t.Fatalf("got %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestPutStatusValidation(t *testing.T) {
|
|
cases := []struct {
|
|
name string
|
|
status string
|
|
want int
|
|
}{
|
|
{"empty is no opinion", "", http.StatusOK},
|
|
{"reading", "reading", http.StatusOK},
|
|
{"archived", "archived", http.StatusOK},
|
|
{"finished is web-only", "finished", http.StatusBadRequest},
|
|
{"garbage", "dropped", http.StatusBadRequest},
|
|
}
|
|
for _, tc := range cases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
srv := newTestServer(t)
|
|
body := fmt.Sprintf(`{"title":"Solo","status":%q}`, tc.status)
|
|
req := auth(httptest.NewRequest(http.MethodPut, "/bookmarks/asura:solo",
|
|
strings.NewReader(body)))
|
|
rr := httptest.NewRecorder()
|
|
srv.ServeHTTP(rr, req)
|
|
|
|
if rr.Code != tc.want {
|
|
t.Fatalf("status = %d, want %d (body %s)", rr.Code, tc.want, rr.Body.String())
|
|
}
|
|
if tc.want != http.StatusOK {
|
|
return
|
|
}
|
|
var got Bookmark
|
|
if err := json.Unmarshal(rr.Body.Bytes(), &got); err != nil {
|
|
t.Fatalf("decode: %v", err)
|
|
}
|
|
want := tc.status
|
|
if want == "" {
|
|
want = "reading"
|
|
}
|
|
if got.Status != want {
|
|
t.Fatalf("stored status = %q, want %q", got.Status, want)
|
|
}
|
|
})
|
|
}
|
|
}
|