package gitea_test import ( "context" "net/http" "net/http/httptest" "sync/atomic" "testing" "git.d-ma.be/mathias/gitea-mcp/internal/gitea" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestClientGetsTokenInHeader(t *testing.T) { var gotAuth string srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { gotAuth = r.Header.Get("Authorization") w.Header().Set("Content-Type", "application/json") _, _ = w.Write([]byte(`{"ok":true}`)) })) defer srv.Close() c := gitea.NewClient(srv.URL, "test-token") body, status, err := c.GetJSON(context.Background(), "/api/v1/user") require.NoError(t, err) assert.Equal(t, 200, status) assert.Contains(t, string(body), `"ok":true`) assert.Equal(t, "token test-token", gotAuth) } func TestRetryOn5xxGetSucceedsOnSecondAttempt(t *testing.T) { var attempts int32 srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { n := atomic.AddInt32(&attempts, 1) if n == 1 { http.Error(w, "boom", http.StatusServiceUnavailable) return } w.Header().Set("Content-Type", "application/json") _, _ = w.Write([]byte(`{"ok":true}`)) })) defer srv.Close() c := gitea.NewClient(srv.URL, "tok") body, status, err := c.GetJSON(context.Background(), "/api/v1/test") require.NoError(t, err) assert.Equal(t, 200, status) assert.Contains(t, string(body), `"ok":true`) assert.Equal(t, int32(2), atomic.LoadInt32(&attempts)) } func TestClientPrefersTokenFromContextOverDefaultToken(t *testing.T) { var gotAuth string srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { gotAuth = r.Header.Get("Authorization") w.Header().Set("Content-Type", "application/json") _, _ = w.Write([]byte(`{"ok":true}`)) })) defer srv.Close() c := gitea.NewClient(srv.URL, "default-token") ctx := gitea.WithToken(context.Background(), "caller-token") _, status, err := c.GetJSON(ctx, "/api/v1/user") require.NoError(t, err) assert.Equal(t, 200, status) assert.Equal(t, "token caller-token", gotAuth) } func TestValidateTokenReturnsLoginOnSuccess(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, "token candidate-token", r.Header.Get("Authorization")) w.Header().Set("Content-Type", "application/json") _, _ = w.Write([]byte(`{"login":"alice"}`)) })) defer srv.Close() c := gitea.NewClient(srv.URL, "default-token") login, ok := c.ValidateToken(context.Background(), "candidate-token") assert.True(t, ok) assert.Equal(t, "alice", login) } func TestValidateTokenReturnsFalseOn401(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { http.Error(w, "unauthorized", http.StatusUnauthorized) })) defer srv.Close() c := gitea.NewClient(srv.URL, "default-token") login, ok := c.ValidateToken(context.Background(), "bad-token") assert.False(t, ok) assert.Empty(t, login) } func TestRetryOnPostNotRetried(t *testing.T) { var attempts int32 srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { atomic.AddInt32(&attempts, 1) http.Error(w, "boom", http.StatusServiceUnavailable) })) defer srv.Close() c := gitea.NewClient(srv.URL, "tok") _, _, _ = c.PostJSON(context.Background(), "/api/v1/test", []byte(`{}`)) assert.Equal(t, int32(1), atomic.LoadInt32(&attempts), "POST should not retry") }