- Fix Nodes.First() panic on empty slice (return nil) - Fix ticker leak in archive.go (create once, defer Stop) - Fix cookie path matching for empty and root paths - Fix lost query params in google.go (u.Query().Set was discarded) - Fix type assertion panic in useragents.go - Fix dropped date parse error in powerball.go - Remove unreachable dead code in megamillions.go and powerball.go - Simplify document.go WaitForNetworkIdle, remove unused root field - Remove debug fmt.Println calls across codebase - Replace panic(err) with stderr+exit in all cmd/ programs - Fix duckduckgo cmd: remove useless defer, return error on bad safesearch - Fix archive cmd: ToConfig returns error instead of panicking - Add 39+ unit tests across 6 new test files - Add Gitea Actions CI workflow (build, test, vet in parallel) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
190 lines
4.8 KiB
Go
190 lines
4.8 KiB
Go
package extractor
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func writeTempCookieFile(t *testing.T, content string) string {
|
|
t.Helper()
|
|
dir := t.TempDir()
|
|
path := filepath.Join(dir, "cookies.txt")
|
|
if err := os.WriteFile(path, []byte(content), 0644); err != nil {
|
|
t.Fatalf("failed to write temp cookie file: %v", err)
|
|
}
|
|
return path
|
|
}
|
|
|
|
func TestLoadCookiesFile_Valid(t *testing.T) {
|
|
content := ".example.com\tTRUE\t/\tFALSE\t1700000000\tsession\tabc123\n"
|
|
path := writeTempCookieFile(t, content)
|
|
|
|
jar, err := LoadCookiesFile(path)
|
|
if err != nil {
|
|
t.Fatalf("LoadCookiesFile() error: %v", err)
|
|
}
|
|
|
|
cookies, _ := jar.GetAll()
|
|
if len(cookies) != 1 {
|
|
t.Fatalf("expected 1 cookie, got %d", len(cookies))
|
|
}
|
|
|
|
c := cookies[0]
|
|
if c.Host != ".example.com" {
|
|
t.Errorf("Host = %q, want %q", c.Host, ".example.com")
|
|
}
|
|
if !c.HttpOnly {
|
|
t.Error("HttpOnly = false, want true")
|
|
}
|
|
if c.Path != "/" {
|
|
t.Errorf("Path = %q, want %q", c.Path, "/")
|
|
}
|
|
if c.Secure {
|
|
t.Error("Secure = true, want false")
|
|
}
|
|
if c.Name != "session" {
|
|
t.Errorf("Name = %q, want %q", c.Name, "session")
|
|
}
|
|
if c.Value != "abc123" {
|
|
t.Errorf("Value = %q, want %q", c.Value, "abc123")
|
|
}
|
|
if c.Expires.Unix() != 1700000000 {
|
|
t.Errorf("Expires = %d, want 1700000000", c.Expires.Unix())
|
|
}
|
|
}
|
|
|
|
func TestLoadCookiesFile_Comments(t *testing.T) {
|
|
content := "# This is a comment\n.example.com\tTRUE\t/\tFALSE\t1700000000\tsession\tabc123\n"
|
|
path := writeTempCookieFile(t, content)
|
|
|
|
jar, err := LoadCookiesFile(path)
|
|
if err != nil {
|
|
t.Fatalf("LoadCookiesFile() error: %v", err)
|
|
}
|
|
|
|
cookies, _ := jar.GetAll()
|
|
if len(cookies) != 1 {
|
|
t.Errorf("expected 1 cookie (comment skipped), got %d", len(cookies))
|
|
}
|
|
}
|
|
|
|
func TestLoadCookiesFile_EmptyLines(t *testing.T) {
|
|
content := "\n\n.example.com\tTRUE\t/\tFALSE\t1700000000\tsession\tabc123\n\n"
|
|
path := writeTempCookieFile(t, content)
|
|
|
|
jar, err := LoadCookiesFile(path)
|
|
if err != nil {
|
|
t.Fatalf("LoadCookiesFile() error: %v", err)
|
|
}
|
|
|
|
cookies, _ := jar.GetAll()
|
|
if len(cookies) != 1 {
|
|
t.Errorf("expected 1 cookie (empty lines skipped), got %d", len(cookies))
|
|
}
|
|
}
|
|
|
|
func TestLoadCookiesFile_ShortLines(t *testing.T) {
|
|
content := "too\tfew\tfields\n.example.com\tTRUE\t/\tFALSE\t1700000000\tsession\tabc123\n"
|
|
path := writeTempCookieFile(t, content)
|
|
|
|
jar, err := LoadCookiesFile(path)
|
|
if err != nil {
|
|
t.Fatalf("LoadCookiesFile() error: %v", err)
|
|
}
|
|
|
|
cookies, _ := jar.GetAll()
|
|
if len(cookies) != 1 {
|
|
t.Errorf("expected 1 cookie (short line skipped), got %d", len(cookies))
|
|
}
|
|
}
|
|
|
|
func TestLoadCookiesFile_InvalidExpiry(t *testing.T) {
|
|
content := ".example.com\tTRUE\t/\tFALSE\tnotanumber\tsession\tabc123\n"
|
|
path := writeTempCookieFile(t, content)
|
|
|
|
jar, err := LoadCookiesFile(path)
|
|
if err != nil {
|
|
t.Fatalf("LoadCookiesFile() error: %v", err)
|
|
}
|
|
|
|
cookies, _ := jar.GetAll()
|
|
if len(cookies) != 1 {
|
|
t.Fatalf("expected 1 cookie, got %d", len(cookies))
|
|
}
|
|
|
|
// Should have a default expiry ~180 days from now
|
|
now := time.Now()
|
|
expected := now.Add(180 * 24 * time.Hour)
|
|
diff := cookies[0].Expires.Sub(expected)
|
|
if diff < -time.Minute || diff > time.Minute {
|
|
t.Errorf("invalid expiry default: got %v, expected ~%v", cookies[0].Expires, expected)
|
|
}
|
|
}
|
|
|
|
func TestLoadCookiesFile_HttpOnly(t *testing.T) {
|
|
content := ".example.com\tTRUE\t/\tFALSE\t1700000000\ta\t1\n.other.com\tFALSE\t/\tFALSE\t1700000000\tb\t2\n"
|
|
path := writeTempCookieFile(t, content)
|
|
|
|
jar, err := LoadCookiesFile(path)
|
|
if err != nil {
|
|
t.Fatalf("LoadCookiesFile() error: %v", err)
|
|
}
|
|
|
|
cookies, _ := jar.GetAll()
|
|
if len(cookies) != 2 {
|
|
t.Fatalf("expected 2 cookies, got %d", len(cookies))
|
|
}
|
|
|
|
if !cookies[0].HttpOnly {
|
|
t.Error("first cookie HttpOnly = false, want true")
|
|
}
|
|
if cookies[1].HttpOnly {
|
|
t.Error("second cookie HttpOnly = true, want false")
|
|
}
|
|
}
|
|
|
|
func TestLoadCookiesFile_Secure(t *testing.T) {
|
|
content := ".example.com\tFALSE\t/\tTRUE\t1700000000\ta\t1\n.other.com\tFALSE\t/\tFALSE\t1700000000\tb\t2\n"
|
|
path := writeTempCookieFile(t, content)
|
|
|
|
jar, err := LoadCookiesFile(path)
|
|
if err != nil {
|
|
t.Fatalf("LoadCookiesFile() error: %v", err)
|
|
}
|
|
|
|
cookies, _ := jar.GetAll()
|
|
if len(cookies) != 2 {
|
|
t.Fatalf("expected 2 cookies, got %d", len(cookies))
|
|
}
|
|
|
|
if !cookies[0].Secure {
|
|
t.Error("first cookie Secure = false, want true")
|
|
}
|
|
if cookies[1].Secure {
|
|
t.Error("second cookie Secure = true, want false")
|
|
}
|
|
}
|
|
|
|
func TestLoadCookiesFile_NonexistentFile(t *testing.T) {
|
|
_, err := LoadCookiesFile("/nonexistent/path/cookies.txt")
|
|
if err == nil {
|
|
t.Error("expected error for nonexistent file")
|
|
}
|
|
}
|
|
|
|
func TestLoadCookiesFile_Empty(t *testing.T) {
|
|
path := writeTempCookieFile(t, "")
|
|
|
|
jar, err := LoadCookiesFile(path)
|
|
if err != nil {
|
|
t.Fatalf("LoadCookiesFile() error: %v", err)
|
|
}
|
|
|
|
cookies, _ := jar.GetAll()
|
|
if len(cookies) != 0 {
|
|
t.Errorf("expected 0 cookies from empty file, got %d", len(cookies))
|
|
}
|
|
}
|