packages.wenpai.net/internal/wporg/client_test.go
Ben Word 7cb8fef01b
WP Packages rename (#42)
* Update all import paths

* Rename directory cmd/wpcomposer/ → cmd/wppackages/

* Rename import alias wpcomposergo → wppackagesgo in main.go and migrate_test.go

* Makefile — binary name wpcomposer → wppackages

* Update Air path

* Global replace repo.wp-composer.com → repo.wp-packages.org

* Global replace cdn.wp-composer.com → cdn.wp-packages.org

* Global replace wp-composer.com → wp-packages.org (remaining)

* Composer repo key in templates/docs: repositories.wp-composer → repositories.wp-packages

* Rename columns on the existing schema

* Update all Go code referencing these column names

* Routes & SEO

* Templates & front-end

* Admin UI

* Documentation

* CI/CD

* Config defaults

* Rename role directory

* Rename all systemd template files inside the role

* Update contents of all .j2 templates — service names, binary paths, descriptions

* Update tasks/main.yml and handlers/main.yml in the role

* Update deploy/ansible/roles/app/tasks/main.yml and deploy.yml

* Update deploy/ansible/group_vars/production/main.yml

* Additional renames/fixes

* Additional renames/fixes

* Additional renames/fixes

* not needed
2026-03-19 11:50:12 -05:00

131 lines
3.4 KiB
Go

package wporg
import (
"context"
"fmt"
"log/slog"
"net/http"
"net/http/httptest"
"sync/atomic"
"testing"
"github.com/roots/wp-packages/internal/config"
)
func testClient(handler http.Handler) (*Client, *httptest.Server) {
srv := httptest.NewServer(handler)
cfg := config.DiscoveryConfig{
APITimeoutS: 5,
MaxRetries: 3,
RetryDelayMs: 10, // fast retries for tests
}
c := NewClient(cfg, slog.Default())
c.http = srv.Client()
return c, srv
}
func TestFetchJSON_Success(t *testing.T) {
c, srv := testClient(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
_, _ = fmt.Fprint(w, `{"slug":"akismet","name":"Akismet","version":"5.0"}`)
}))
defer srv.Close()
data, err := c.fetchJSON(context.Background(), srv.URL)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if data["slug"] != "akismet" {
t.Errorf("got slug=%v, want akismet", data["slug"])
}
}
func TestFetchJSON_404(t *testing.T) {
c, srv := testClient(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNotFound)
}))
defer srv.Close()
_, err := c.fetchJSON(context.Background(), srv.URL)
if err == nil {
t.Fatal("expected error for 404")
}
}
func TestFetchJSON_APIError(t *testing.T) {
c, srv := testClient(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
_, _ = fmt.Fprint(w, `{"error":"Plugin not found.","slug":"nonexistent"}`)
}))
defer srv.Close()
_, err := c.fetchJSON(context.Background(), srv.URL)
if err == nil {
t.Fatal("expected error for API error response")
}
}
func TestFetchJSON_RetryOnServerError(t *testing.T) {
var attempts atomic.Int32
c, srv := testClient(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
n := attempts.Add(1)
if n < 3 {
w.WriteHeader(http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
_, _ = fmt.Fprint(w, `{"slug":"test"}`)
}))
defer srv.Close()
data, err := c.fetchJSON(context.Background(), srv.URL)
if err != nil {
t.Fatalf("unexpected error after retries: %v", err)
}
if data["slug"] != "test" {
t.Errorf("got slug=%v, want test", data["slug"])
}
if attempts.Load() != 3 {
t.Errorf("expected 3 attempts, got %d", attempts.Load())
}
}
func TestFetchJSON_AllRetriesFail(t *testing.T) {
c, srv := testClient(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusInternalServerError)
}))
defer srv.Close()
_, err := c.fetchJSON(context.Background(), srv.URL)
if err == nil {
t.Fatal("expected error when all retries fail")
}
}
func TestFetchJSON_ContextCancelled(t *testing.T) {
c, srv := testClient(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusInternalServerError)
}))
defer srv.Close()
ctx, cancel := context.WithCancel(context.Background())
cancel() // cancel immediately
_, err := c.fetchJSON(ctx, srv.URL)
if err == nil {
t.Fatal("expected error for cancelled context")
}
}
func TestFetchJSON_InvalidJSON(t *testing.T) {
c, srv := testClient(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
_, _ = fmt.Fprint(w, `not json`)
}))
defer srv.Close()
_, err := c.fetchJSON(context.Background(), srv.URL)
if err == nil {
t.Fatal("expected error for invalid JSON")
}
}