package updatecheck import ( "context" "net/http" "net/http/httptest" "testing" ) func TestIsNewer(t *testing.T) { tests := []struct { name string current, latest string want bool }{ {"patch bump", "v1.0.85", "v1.0.86", true}, {"minor beats patch", "v1.0.99", "v1.1.0", true}, {"major bump", "v1.9.9", "v2.0.0", true}, {"numeric not lexical", "v1.0.9", "v1.0.10", true}, {"same", "v1.0.85", "v1.0.85", false}, {"older latest", "v1.0.86", "v1.0.85", false}, {"no v prefix", "1.0.1", "v1.0.2", true}, {"short version", "v1.0", "v1.0.1", true}, {"prerelease suffix ignored", "v1.0.1-rc1", "v1.0.2", true}, {"dev build", "dev", "v9.9.9", false}, {"commit hash", "abc1234", "v9.9.9", false}, {"empty current", "", "v1.0.0", false}, {"bad latest", "v1.0.0", "latest", false}, {"too many parts", "v1.0.0.0", "v1.0.1", false}, {"negative", "v1.-1.0", "v1.0.0", false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if got := IsNewer(tt.current, tt.latest); got != tt.want { t.Errorf("IsNewer(%q,%q) = %v, want %v", tt.current, tt.latest, got, tt.want) } }) } } func TestLatest(t *testing.T) { tests := []struct { name string status int body string wantTag string wantErr bool }{ {"ok", 200, `{"tag_name":"v1.2.3","html_url":"https://x/r","assets":[{"name":"a.exe","browser_download_url":"https://x/a.exe"}]}`, "v1.2.3", false}, {"not found", 404, `{}`, "", true}, {"bad json", 200, `{`, "", true}, {"missing tag", 200, `{"html_url":"u"}`, "", true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(tt.status) _, _ = w.Write([]byte(tt.body)) })) defer srv.Close() rel, err := Latest(context.Background(), nil, srv.URL) if (err != nil) != tt.wantErr { t.Fatalf("err = %v, wantErr %v", err, tt.wantErr) } if err == nil { if rel.Tag != tt.wantTag { t.Errorf("tag = %q", rel.Tag) } if a, ok := rel.FindAsset("a.exe"); !ok || a.URL != "https://x/a.exe" { t.Errorf("asset = %+v %v", a, ok) } if _, ok := rel.FindAsset("missing"); ok { t.Error("unexpected asset") } } }) } } func TestLatestUnreachable(t *testing.T) { srv := httptest.NewServer(http.NotFoundHandler()) url := srv.URL srv.Close() if _, err := Latest(context.Background(), nil, url); err == nil { t.Error("expected error for unreachable server") } } func TestLatestBadURL(t *testing.T) { if _, err := Latest(context.Background(), nil, "://bad"); err == nil { t.Error("expected error for bad URL") } }