summaryrefslogtreecommitdiff
path: root/internal/github/github_test.go
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-03-11 18:24:16 +0200
committerPaul Buetow <paul@buetow.org>2026-03-11 18:24:16 +0200
commit1c12325c64bb734dd0ae95a0c803de1ff45d2b4c (patch)
treee57c97d5b77e9b542dea887176bb11b533501b23 /internal/github/github_test.go
parent224d9059e5c51eaab9295ea5266c64c4dd7fa218 (diff)
fix(github): stop logging token diagnostics
Diffstat (limited to 'internal/github/github_test.go')
-rw-r--r--internal/github/github_test.go111
1 files changed, 111 insertions, 0 deletions
diff --git a/internal/github/github_test.go b/internal/github/github_test.go
new file mode 100644
index 0000000..a65e00a
--- /dev/null
+++ b/internal/github/github_test.go
@@ -0,0 +1,111 @@
+package github
+
+import (
+ "bytes"
+ "io"
+ "net/http"
+ "os"
+ "strings"
+ "testing"
+)
+
+type roundTripFunc func(*http.Request) (*http.Response, error)
+
+func (f roundTripFunc) RoundTrip(req *http.Request) (*http.Response, error) {
+ return f(req)
+}
+
+func TestNewClient_DoesNotLogTokenDetails(t *testing.T) {
+ t.Setenv("GITHUB_TOKEN", " test-token \n")
+
+ output := captureStdout(t, func() {
+ client := NewClient("", "snonux")
+ if !client.HasToken() {
+ t.Fatal("expected token to be loaded")
+ }
+ if client.token != "test-token" {
+ t.Fatalf("expected trimmed token, got %q", client.token)
+ }
+ })
+
+ if output != "" {
+ t.Fatalf("expected no stdout output, got %q", output)
+ }
+}
+
+func TestClientRepoExists_DoesNotLogAuthorizationHeaderOnUnauthorized(t *testing.T) {
+ const token = "super-secret-token"
+
+ originalTransport := http.DefaultTransport
+ http.DefaultTransport = roundTripFunc(func(req *http.Request) (*http.Response, error) {
+ if got := req.Header.Get("Authorization"); got != "Bearer "+token {
+ t.Fatalf("expected bearer token header, got %q", got)
+ }
+
+ return &http.Response{
+ StatusCode: http.StatusUnauthorized,
+ Body: io.NopCloser(strings.NewReader(`{"message":"bad credentials"}`)),
+ Header: make(http.Header),
+ }, nil
+ })
+ t.Cleanup(func() {
+ http.DefaultTransport = originalTransport
+ })
+
+ client := NewClient(token, "snonux")
+
+ output := captureStdout(t, func() {
+ exists, err := client.RepoExists("gitsyncer")
+ if err == nil {
+ t.Fatal("expected unauthorized error")
+ }
+ if exists {
+ t.Fatal("expected repo existence check to fail")
+ }
+ if !strings.Contains(err.Error(), "authentication failed (401)") {
+ t.Fatalf("expected 401 error, got %v", err)
+ }
+ })
+
+ if strings.Contains(output, token) {
+ t.Fatalf("expected output to omit token, got %q", output)
+ }
+ if strings.Contains(output, "Authorization header") {
+ t.Fatalf("expected output to omit authorization header log, got %q", output)
+ }
+}
+
+func captureStdout(t *testing.T, fn func()) string {
+ t.Helper()
+
+ originalStdout := os.Stdout
+ reader, writer, err := os.Pipe()
+ if err != nil {
+ t.Fatalf("failed to create pipe: %v", err)
+ }
+
+ os.Stdout = writer
+ defer func() {
+ os.Stdout = originalStdout
+ }()
+
+ outputCh := make(chan string, 1)
+ go func() {
+ var buffer bytes.Buffer
+ _, _ = io.Copy(&buffer, reader)
+ outputCh <- buffer.String()
+ }()
+
+ fn()
+
+ if err := writer.Close(); err != nil {
+ t.Fatalf("failed to close stdout writer: %v", err)
+ }
+
+ output := <-outputCh
+ if err := reader.Close(); err != nil {
+ t.Fatalf("failed to close stdout reader: %v", err)
+ }
+
+ return output
+}