mirror of
https://github.com/sartoopjj/thefeed.git
synced 2026-05-19 06:34:35 +03:00
feat: ✨ media download with DNS query
This commit is contained in:
@@ -0,0 +1,174 @@
|
||||
package e2e_test
|
||||
|
||||
import (
|
||||
"io"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// createDefaultProfile spins up a dummy "active" profile so the auto-update
|
||||
// endpoints have somewhere to write. Returns the resulting profile id.
|
||||
func createDefaultProfile(t *testing.T, base string) string {
|
||||
t.Helper()
|
||||
body := `{"action":"create","profile":{"id":"","nickname":"AU","config":{"domain":"au.example","key":"k","resolvers":["127.0.0.1:9999"],"queryMode":"single","rateLimit":0}}}`
|
||||
resp := postJSON(t, base+"/api/profiles", body)
|
||||
resp.Body.Close()
|
||||
m := decodeJSON(t, getJSON(t, base+"/api/profiles"))
|
||||
profs, ok := m["profiles"].([]any)
|
||||
if !ok || len(profs) == 0 {
|
||||
t.Fatalf("profile not created, got %v", m["profiles"])
|
||||
}
|
||||
return profs[0].(map[string]any)["id"].(string)
|
||||
}
|
||||
|
||||
func TestE2E_AutoUpdate_GetEmpty(t *testing.T) {
|
||||
base, _ := startWebServer(t)
|
||||
createDefaultProfile(t, base)
|
||||
|
||||
resp := getJSON(t, base+"/api/auto-update")
|
||||
if resp.StatusCode != 200 {
|
||||
body, _ := io.ReadAll(resp.Body)
|
||||
t.Fatalf("expected 200, got %d body=%s", resp.StatusCode, body)
|
||||
}
|
||||
m := decodeJSON(t, resp)
|
||||
chans, _ := m["channels"].([]any)
|
||||
if len(chans) != 0 {
|
||||
t.Errorf("expected empty channels, got %v", chans)
|
||||
}
|
||||
if d, _ := m["defaultIntervalSeconds"].(float64); int(d) != 60 {
|
||||
t.Errorf("defaultIntervalSeconds = %v, want 60", m["defaultIntervalSeconds"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestE2E_AutoUpdate_ToggleAddsAndRemoves(t *testing.T) {
|
||||
base, _ := startWebServer(t)
|
||||
createDefaultProfile(t, base)
|
||||
|
||||
// First toggle: add.
|
||||
resp := postJSON(t, base+"/api/auto-update/toggle", `{"channel":"thefeed1"}`)
|
||||
if resp.StatusCode != 200 {
|
||||
body, _ := io.ReadAll(resp.Body)
|
||||
t.Fatalf("toggle add: %d body=%s", resp.StatusCode, body)
|
||||
}
|
||||
m := decodeJSON(t, resp)
|
||||
if m["enabled"] != true {
|
||||
t.Errorf("first toggle should set enabled=true, got %v", m["enabled"])
|
||||
}
|
||||
chans := m["channels"].([]any)
|
||||
if len(chans) != 1 || chans[0] != "thefeed1" {
|
||||
t.Errorf("channels after add = %v, want [thefeed1]", chans)
|
||||
}
|
||||
|
||||
// Second toggle: remove.
|
||||
resp2 := postJSON(t, base+"/api/auto-update/toggle", `{"channel":"thefeed1"}`)
|
||||
m2 := decodeJSON(t, resp2)
|
||||
if m2["enabled"] != false {
|
||||
t.Errorf("second toggle should set enabled=false, got %v", m2["enabled"])
|
||||
}
|
||||
chans2 := m2["channels"]
|
||||
if list, ok := chans2.([]any); !ok || len(list) != 0 {
|
||||
t.Errorf("channels after remove = %v, want []", chans2)
|
||||
}
|
||||
}
|
||||
|
||||
func TestE2E_AutoUpdate_TogglesAtSign(t *testing.T) {
|
||||
base, _ := startWebServer(t)
|
||||
createDefaultProfile(t, base)
|
||||
|
||||
// Add with "@chan" — server must store stripped form.
|
||||
postJSON(t, base+"/api/auto-update/toggle", `{"channel":"@chan"}`).Body.Close()
|
||||
|
||||
m := decodeJSON(t, getJSON(t, base+"/api/auto-update"))
|
||||
chans := m["channels"].([]any)
|
||||
if len(chans) != 1 || chans[0] != "chan" {
|
||||
t.Errorf("channels = %v, want [chan]", chans)
|
||||
}
|
||||
|
||||
// Toggle with bare form should remove the same entry.
|
||||
resp := postJSON(t, base+"/api/auto-update/toggle", `{"channel":"chan"}`)
|
||||
m2 := decodeJSON(t, resp)
|
||||
if m2["enabled"] != false {
|
||||
t.Errorf("expected enabled=false, got %v", m2["enabled"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestE2E_AutoUpdate_PostReplacesList(t *testing.T) {
|
||||
base, _ := startWebServer(t)
|
||||
createDefaultProfile(t, base)
|
||||
|
||||
// POST with normalisation cases: leading @, dupes, whitespace.
|
||||
body := `{"channels":["@a","b","@a"," c ",""],"intervalSeconds":120}`
|
||||
resp := postJSON(t, base+"/api/auto-update", body)
|
||||
if resp.StatusCode != 200 {
|
||||
body, _ := io.ReadAll(resp.Body)
|
||||
t.Fatalf("POST: %d body=%s", resp.StatusCode, body)
|
||||
}
|
||||
m := decodeJSON(t, resp)
|
||||
chans := m["channels"].([]any)
|
||||
want := []string{"a", "b", "c"}
|
||||
if len(chans) != len(want) {
|
||||
t.Fatalf("channels len = %d, want %d (%v)", len(chans), len(want), chans)
|
||||
}
|
||||
for i, w := range want {
|
||||
if chans[i] != w {
|
||||
t.Errorf("channels[%d] = %v, want %q", i, chans[i], w)
|
||||
}
|
||||
}
|
||||
if iv, _ := m["intervalSeconds"].(float64); int(iv) != 120 {
|
||||
t.Errorf("intervalSeconds = %v, want 120", m["intervalSeconds"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestE2E_AutoUpdate_IntervalFloor(t *testing.T) {
|
||||
base, _ := startWebServer(t)
|
||||
createDefaultProfile(t, base)
|
||||
|
||||
// Anything <60s gets bumped to the 60s floor; 0 stays 0 (means
|
||||
// "follow the server's nextFetch cadence with the built-in default").
|
||||
resp := postJSON(t, base+"/api/auto-update", `{"channels":["x"],"intervalSeconds":5}`)
|
||||
m := decodeJSON(t, resp)
|
||||
if iv, _ := m["intervalSeconds"].(float64); int(iv) != 60 {
|
||||
t.Errorf("intervalSeconds floor = %v, want 60", m["intervalSeconds"])
|
||||
}
|
||||
|
||||
resp2 := postJSON(t, base+"/api/auto-update", `{"channels":["x"],"intervalSeconds":0}`)
|
||||
m2 := decodeJSON(t, resp2)
|
||||
if iv, _ := m2["intervalSeconds"].(float64); int(iv) != 0 {
|
||||
t.Errorf("intervalSeconds zero = %v, want 0 (default)", m2["intervalSeconds"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestE2E_AutoUpdate_NoActiveProfile(t *testing.T) {
|
||||
base, _ := startWebServer(t)
|
||||
|
||||
// No profile created → no active profile → POST should fail with 400.
|
||||
resp := postJSON(t, base+"/api/auto-update/toggle", `{"channel":"x"}`)
|
||||
if resp.StatusCode != 400 {
|
||||
t.Fatalf("toggle without profile: expected 400, got %d", resp.StatusCode)
|
||||
}
|
||||
resp.Body.Close()
|
||||
|
||||
// GET should succeed and return empty channels.
|
||||
resp2 := getJSON(t, base+"/api/auto-update")
|
||||
if resp2.StatusCode != 200 {
|
||||
t.Fatalf("GET without profile: expected 200, got %d", resp2.StatusCode)
|
||||
}
|
||||
m := decodeJSON(t, resp2)
|
||||
chans, _ := m["channels"].([]any)
|
||||
if len(chans) != 0 {
|
||||
t.Errorf("expected empty channels with no profile, got %v", chans)
|
||||
}
|
||||
}
|
||||
|
||||
func TestE2E_AutoUpdate_PersistsAcrossGets(t *testing.T) {
|
||||
base, _ := startWebServer(t)
|
||||
createDefaultProfile(t, base)
|
||||
|
||||
postJSON(t, base+"/api/auto-update", `{"channels":["alpha","beta"]}`).Body.Close()
|
||||
|
||||
// Fresh GET should return the same list.
|
||||
m := decodeJSON(t, getJSON(t, base+"/api/auto-update"))
|
||||
chans := m["channels"].([]any)
|
||||
if len(chans) != 2 || chans[0] != "alpha" || chans[1] != "beta" {
|
||||
t.Errorf("channels persisted = %v, want [alpha beta]", chans)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user