@@ -13,7 +13,10 @@ import (
1313 "github.com/steipete/gogcli/internal/config"
1414)
1515
16- var errTestKeychain = errors .New ("test -25308 error" )
16+ var (
17+ errTestKeychain = errors .New ("test -25308 error" )
18+ errNoTTYForTest = errors .New ("no tty" )
19+ )
1720
1821func TestKeyringStore_ListDeleteDefault (t * testing.T ) {
1922 ring := keyring .NewArrayKeyring (nil )
@@ -126,6 +129,123 @@ func TestFileKeyringPasswordFuncFrom(t *testing.T) {
126129 if _ , err := fn ("prompt" ); err == nil || ! errors .Is (err , errNoTTY ) {
127130 t .Fatalf ("expected no TTY error, got: %v" , err )
128131 }
132+
133+ // No env var and TTY available uses terminal prompt function.
134+ origTerminalPrompt := terminalPromptFunc
135+ terminalPromptFunc = func (prompt string ) (string , error ) {
136+ return "typed:" + prompt , nil
137+ }
138+
139+ t .Cleanup (func () { terminalPromptFunc = origTerminalPrompt })
140+
141+ fn = fileKeyringPasswordFuncFrom ("" , false , true )
142+ if got , err := fn ("prompt" ); err != nil {
143+ t .Fatalf ("expected terminal prompt success, got err: %v" , err )
144+ } else if got != "typed:prompt" {
145+ t .Fatalf ("unexpected prompt value: %q" , got )
146+ }
147+ }
148+
149+ func TestKeyringPasswordFromEnvFrom (t * testing.T ) {
150+ tests := []struct {
151+ name string
152+ env map [string ]string
153+ wantValue string
154+ wantSet bool
155+ }{
156+ {
157+ name : "unset" ,
158+ env : map [string ]string {},
159+ wantValue : "" ,
160+ wantSet : false ,
161+ },
162+ {
163+ name : "canonical wins" ,
164+ env : map [string ]string {
165+ keyringPasswordEnv : "canon" ,
166+ keyringPasswordCompatEnv : "compat" ,
167+ keyringPasswordLegacyEnv : "legacy" ,
168+ },
169+ wantValue : "canon" ,
170+ wantSet : true ,
171+ },
172+ {
173+ name : "compat fallback" ,
174+ env : map [string ]string {
175+ keyringPasswordCompatEnv : "compat" ,
176+ keyringPasswordLegacyEnv : "legacy" ,
177+ },
178+ wantValue : "compat" ,
179+ wantSet : true ,
180+ },
181+ {
182+ name : "legacy fallback" ,
183+ env : map [string ]string {
184+ keyringPasswordLegacyEnv : "legacy" ,
185+ },
186+ wantValue : "legacy" ,
187+ wantSet : true ,
188+ },
189+ {
190+ name : "empty canonical is intentional" ,
191+ env : map [string ]string {
192+ keyringPasswordEnv : "" ,
193+ },
194+ wantValue : "" ,
195+ wantSet : true ,
196+ },
197+ }
198+
199+ for _ , tt := range tests {
200+ t .Run (tt .name , func (t * testing.T ) {
201+ gotValue , gotSet := keyringPasswordFromEnvFrom (func (k string ) (string , bool ) {
202+ v , ok := tt .env [k ]
203+ return v , ok
204+ })
205+ if gotValue != tt .wantValue || gotSet != tt .wantSet {
206+ t .Fatalf ("got (%q, %v), want (%q, %v)" , gotValue , gotSet , tt .wantValue , tt .wantSet )
207+ }
208+ })
209+ }
210+ }
211+
212+ func TestHasTerminalPromptInputFrom (t * testing.T ) {
213+ t .Run ("stdin tty" , func (t * testing.T ) {
214+ called := false
215+
216+ got := hasTerminalPromptInputFrom (true , func () error {
217+ called = true
218+ return nil
219+ })
220+ if ! got {
221+ t .Fatalf ("expected prompt input when stdin is tty" )
222+ }
223+
224+ if called {
225+ t .Fatalf ("did not expect openTTY call when stdin is tty" )
226+ }
227+ })
228+
229+ t .Run ("tty fallback works" , func (t * testing.T ) {
230+ got := hasTerminalPromptInputFrom (false , func () error { return nil })
231+ if ! got {
232+ t .Fatalf ("expected prompt input from tty fallback" )
233+ }
234+ })
235+
236+ t .Run ("tty fallback unavailable" , func (t * testing.T ) {
237+ got := hasTerminalPromptInputFrom (false , func () error { return errNoTTYForTest })
238+ if got {
239+ t .Fatalf ("expected no prompt input without tty" )
240+ }
241+ })
242+
243+ t .Run ("no open func" , func (t * testing.T ) {
244+ got := hasTerminalPromptInputFrom (false , nil )
245+ if got {
246+ t .Fatalf ("expected no prompt input without openTTY function" )
247+ }
248+ })
129249}
130250
131251func TestKeyringStoreSetTokenErrors (t * testing.T ) {
0 commit comments