Skip to content

Commit c761599

Browse files
committed
test: add regression test for supplying auth from auth config
1 parent c3a1bad commit c761599

3 files changed

Lines changed: 124 additions & 0 deletions

File tree

pkg/cmd/auth.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ var authLogin = cli.Command{
3434
Value: defaultClientID,
3535
Usage: "OAuth client ID",
3636
},
37+
&cli.BoolFlag{
38+
Name: "browser",
39+
Usage: "Open browser for authentication (use --browser=false to skip)",
40+
},
3741
},
3842
Before: before,
3943
Action: handleAuthLogin,

pkg/cmd/auth_test.go

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
package cmd
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"net/http"
7+
"net/http/httptest"
8+
"os"
9+
"path/filepath"
10+
"testing"
11+
12+
"github.com/stretchr/testify/assert"
13+
"github.com/stretchr/testify/require"
14+
)
15+
16+
func TestAuthLogin(t *testing.T) {
17+
tokenCallCount := 0
18+
19+
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
20+
switch r.URL.Path {
21+
case "/api/oauth/device":
22+
w.Header().Set("Content-Type", "application/json")
23+
json.NewEncoder(w).Encode(map[string]any{
24+
"device_code": "test_device_code",
25+
"user_code": "TEST-CODE",
26+
"verification_uri": "https://example.com/activate",
27+
"verification_uri_complete": "https://example.com/activate?code=TEST-CODE",
28+
"expires_in": 300,
29+
"interval": 1,
30+
})
31+
case "/v0/oauth/token":
32+
tokenCallCount++
33+
if tokenCallCount == 1 {
34+
// First poll returns authorization_pending
35+
w.Header().Set("Content-Type", "application/json")
36+
w.WriteHeader(http.StatusBadRequest)
37+
json.NewEncoder(w).Encode(map[string]string{
38+
"error": "authorization_pending",
39+
})
40+
return
41+
}
42+
w.Header().Set("Content-Type", "application/json")
43+
json.NewEncoder(w).Encode(map[string]string{
44+
"access_token": "test_access_token",
45+
"refresh_token": "test_refresh_token",
46+
"token_type": "bearer",
47+
})
48+
default:
49+
http.NotFound(w, r)
50+
}
51+
}))
52+
defer server.Close()
53+
54+
// Use a temp dir as HOME so auth config doesn't touch real config
55+
tmpHome := t.TempDir()
56+
t.Setenv("HOME", tmpHome)
57+
t.Setenv("XDG_CONFIG_HOME", "")
58+
// Ensure no env API key so the device flow is triggered
59+
t.Setenv("STAINLESS_API_KEY", "")
60+
61+
err := Command.Run(context.Background(), []string{
62+
"stl", "auth", "login",
63+
"--base-url", server.URL,
64+
"--browser=false",
65+
})
66+
require.NoError(t, err)
67+
68+
// Verify the auth config was saved
69+
configPath := filepath.Join(tmpHome, ".config", "stainless", "auth.json")
70+
data, err := os.ReadFile(configPath)
71+
require.NoError(t, err, "auth config file should exist")
72+
73+
var saved AuthConfig
74+
require.NoError(t, json.Unmarshal(data, &saved))
75+
assert.Equal(t, "test_access_token", saved.AccessToken)
76+
assert.Equal(t, "test_refresh_token", saved.RefreshToken)
77+
assert.Equal(t, "bearer", saved.TokenType)
78+
79+
// Verify the token endpoint was polled at least twice (once pending, once success)
80+
assert.GreaterOrEqual(t, tokenCallCount, 2)
81+
}
82+
83+
func TestAuthLoad(t *testing.T) {
84+
var gotAuthHeader string
85+
86+
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
87+
gotAuthHeader = r.Header.Get("Authorization")
88+
w.Header().Set("Content-Type", "application/json")
89+
w.Write([]byte(`{"email":"test@example.com"}`))
90+
}))
91+
defer server.Close()
92+
93+
// Set up a temp HOME with a pre-existing auth config
94+
tmpHome := t.TempDir()
95+
configDir := filepath.Join(tmpHome, ".config", "stainless")
96+
require.NoError(t, os.MkdirAll(configDir, 0755))
97+
98+
configData, _ := json.Marshal(AuthConfig{
99+
AccessToken: "saved_test_token",
100+
RefreshToken: "saved_refresh_token",
101+
TokenType: "bearer",
102+
})
103+
require.NoError(t, os.WriteFile(filepath.Join(configDir, "auth.json"), configData, 0644))
104+
105+
t.Setenv("HOME", tmpHome)
106+
t.Setenv("XDG_CONFIG_HOME", "")
107+
t.Setenv("STAINLESS_API_KEY", "")
108+
109+
err := Command.Run(context.Background(), []string{
110+
"stl", "user", "retrieve",
111+
"--base-url", server.URL,
112+
})
113+
require.NoError(t, err)
114+
115+
assert.Equal(t, "Bearer saved_test_token", gotAuthHeader)
116+
}

pkg/console/print.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,10 @@ func (g Group) Confirm(cmd *cli.Command, flagName, title, description string, de
175175
return cmd.Bool(flagName), Group{prefix: "✱", indent: g.indent + 1}, nil
176176
}
177177

178+
if !term.IsTerminal(int(os.Stderr.Fd())) {
179+
return defaultValue, Group{prefix: "✱", indent: g.indent + 1}, nil
180+
}
181+
178182
foreground := lipgloss.Color("15")
179183
cyanBright := lipgloss.Color("6")
180184

0 commit comments

Comments
 (0)