@@ -164,6 +164,67 @@ describe('runConfigure', () => {
164164 ) . rejects . toMatchObject ( { code : 'VALIDATION_ERROR' , exitCode : 5 } ) ;
165165 } ) ;
166166
167+ it ( 'rejects a malformed endpoint before key validation fetch' , async ( ) => {
168+ const { capture, deps } = makeCapture ( ) ;
169+ const fetchImpl = vi . fn ( ) ;
170+
171+ await expect (
172+ runConfigure (
173+ {
174+ profile : 'default' ,
175+ output : 'json' ,
176+ debug : false ,
177+ fromEnv : true ,
178+ endpointUrl : 'not-a-url' ,
179+ } ,
180+ {
181+ ...deps ,
182+ env : { TESTSPRITE_API_KEY : 'sk' } ,
183+ credentialsPath,
184+ fetchImpl : fetchImpl as unknown as AuthDeps [ 'fetchImpl' ] ,
185+ } ,
186+ ) ,
187+ ) . rejects . toMatchObject ( {
188+ code : 'VALIDATION_ERROR' ,
189+ exitCode : 5 ,
190+ details : { field : 'endpoint-url' } ,
191+ } ) ;
192+
193+ expect ( fetchImpl ) . not . toHaveBeenCalled ( ) ;
194+ expect ( readProfile ( 'default' , { path : credentialsPath } ) ) . toBeUndefined ( ) ;
195+ expect ( capture . stderr . join ( '\n' ) ) . not . toContain ( 'API key rejected' ) ;
196+ } ) ;
197+
198+ it ( 'rejects a non-http endpoint before key validation fetch' , async ( ) => {
199+ const { deps } = makeCapture ( ) ;
200+ const fetchImpl = vi . fn ( ) ;
201+
202+ await expect (
203+ runConfigure (
204+ {
205+ profile : 'default' ,
206+ output : 'json' ,
207+ debug : false ,
208+ fromEnv : true ,
209+ endpointUrl : 'ftp://example.com' ,
210+ } ,
211+ {
212+ ...deps ,
213+ env : { TESTSPRITE_API_KEY : 'sk' } ,
214+ credentialsPath,
215+ fetchImpl : fetchImpl as unknown as AuthDeps [ 'fetchImpl' ] ,
216+ } ,
217+ ) ,
218+ ) . rejects . toMatchObject ( {
219+ code : 'VALIDATION_ERROR' ,
220+ exitCode : 5 ,
221+ details : { field : 'endpoint-url' } ,
222+ } ) ;
223+
224+ expect ( fetchImpl ) . not . toHaveBeenCalled ( ) ;
225+ expect ( readProfile ( 'default' , { path : credentialsPath } ) ) . toBeUndefined ( ) ;
226+ } ) ;
227+
167228 it ( 'prompts only for the API key (never the endpoint) and defaults to prod' , async ( ) => {
168229 const { capture, deps } = makeCapture ( ) ;
169230 // Prompt object exposes ONLY `secret`. If runConfigure tried to prompt for
0 commit comments