@@ -4,25 +4,13 @@ import { Command } from "commander";
44const mockGetValidAccessToken = vi . fn ( ) ;
55const mockClearTokens = vi . fn ( ) ;
66const mockSaveTokens = vi . fn ( ) ;
7- const mockGeneratePKCE = vi . fn ( ) ;
8- const mockGenerateState = vi . fn ( ) ;
9- const mockCreateCallbackServer = vi . fn ( ) ;
10- const mockExchangeCodeForTokens = vi . fn ( ) ;
11- const mockBuildAuthorizationUrl = vi . fn ( ) ;
12- const mockShouldUseDeviceFlow = vi . fn ( ( ..._args : unknown [ ] ) => false ) ;
137const mockStartDeviceAuthorization = vi . fn ( ) ;
148const mockPollDeviceToken = vi . fn ( ) ;
159
1610vi . mock ( "../utils/auth.js" , ( ) => ( {
1711 getValidAccessToken : ( ...args : unknown [ ] ) => mockGetValidAccessToken ( ...args ) ,
1812 clearTokens : ( ...args : unknown [ ] ) => mockClearTokens ( ...args ) ,
1913 saveTokens : ( ...args : unknown [ ] ) => mockSaveTokens ( ...args ) ,
20- generatePKCE : ( ...args : unknown [ ] ) => mockGeneratePKCE ( ...args ) ,
21- generateState : ( ...args : unknown [ ] ) => mockGenerateState ( ...args ) ,
22- createCallbackServer : ( ...args : unknown [ ] ) => mockCreateCallbackServer ( ...args ) ,
23- exchangeCodeForTokens : ( ...args : unknown [ ] ) => mockExchangeCodeForTokens ( ...args ) ,
24- buildAuthorizationUrl : ( ...args : unknown [ ] ) => mockBuildAuthorizationUrl ( ...args ) ,
25- shouldUseDeviceFlow : ( ...args : unknown [ ] ) => mockShouldUseDeviceFlow ( ...args ) ,
2614 startDeviceAuthorization : ( ...args : unknown [ ] ) => mockStartDeviceAuthorization ( ...args ) ,
2715 pollDeviceToken : ( ...args : unknown [ ] ) => mockPollDeviceToken ( ...args ) ,
2816 DEFAULT_DEVICE_POLL_INTERVAL_SECONDS : 5 ,
@@ -47,7 +35,7 @@ vi.mock("open", () => ({ default: (...args: unknown[]) => mockOpen(...args) }));
4735vi . mock ( "../constants.js" , ( ) => ( { CLI_CLIENT_ID : "test-client-id" } ) ) ;
4836vi . mock ( "../utils/api.js" , ( ) => ( { getBaseUrl : ( ) => "https://test.context7.com" } ) ) ;
4937
50- import { registerAuthCommands , performLogin , performDeviceLogin } from "../commands/auth.js" ;
38+ import { registerAuthCommands , performLogin } from "../commands/auth.js" ;
5139import { trackEvent } from "../utils/tracking.js" ;
5240
5341let logOutput : string [ ] ;
@@ -104,15 +92,7 @@ describe("login command", () => {
10492 test ( "calls process.exit(1) when login fails" , async ( ) => {
10593 mockGetValidAccessToken . mockResolvedValue ( null ) ;
10694 mockClearTokens . mockReturnValue ( false ) ;
107- // Mock performLogin to fail by making createCallbackServer reject
108- mockGeneratePKCE . mockReturnValue ( { codeVerifier : "v" , codeChallenge : "c" } ) ;
109- mockGenerateState . mockReturnValue ( "state" ) ;
110- mockCreateCallbackServer . mockReturnValue ( {
111- port : Promise . resolve ( 52417 ) ,
112- result : Promise . reject ( new Error ( "timeout" ) ) ,
113- close : vi . fn ( ) ,
114- } ) ;
115- mockBuildAuthorizationUrl . mockReturnValue ( "https://example.com/auth" ) ;
95+ mockStartDeviceAuthorization . mockRejectedValue ( new Error ( "network down" ) ) ;
11696
11797 await runCommand ( "login" ) . catch ( ( ) => { } ) ;
11898 expect ( process . exit ) . toHaveBeenCalledWith ( 1 ) ;
@@ -190,128 +170,6 @@ describe("whoami command", () => {
190170} ) ;
191171
192172describe ( "performLogin" , ( ) => {
193- test ( "returns access_token on success" , async ( ) => {
194- const mockClose = vi . fn ( ) ;
195- mockGeneratePKCE . mockReturnValue ( { codeVerifier : "verifier" , codeChallenge : "challenge" } ) ;
196- mockGenerateState . mockReturnValue ( "state" ) ;
197- mockCreateCallbackServer . mockReturnValue ( {
198- port : Promise . resolve ( 52417 ) ,
199- result : Promise . resolve ( { code : "auth-code" , state : "state" } ) ,
200- close : mockClose ,
201- } ) ;
202- mockBuildAuthorizationUrl . mockReturnValue ( "https://example.com/auth" ) ;
203- mockExchangeCodeForTokens . mockResolvedValue ( {
204- access_token : "new-token" ,
205- token_type : "bearer" ,
206- } ) ;
207-
208- const result = await performLogin ( ) ;
209- expect ( result ) . toBe ( "new-token" ) ;
210- expect ( mockSaveTokens ) . toHaveBeenCalled ( ) ;
211- expect ( mockClose ) . toHaveBeenCalled ( ) ;
212- } ) ;
213-
214- test ( "opens browser by default" , async ( ) => {
215- mockGeneratePKCE . mockReturnValue ( { codeVerifier : "v" , codeChallenge : "c" } ) ;
216- mockGenerateState . mockReturnValue ( "s" ) ;
217- mockCreateCallbackServer . mockReturnValue ( {
218- port : Promise . resolve ( 52417 ) ,
219- result : Promise . resolve ( { code : "code" , state : "s" } ) ,
220- close : vi . fn ( ) ,
221- } ) ;
222- mockBuildAuthorizationUrl . mockReturnValue ( "https://example.com/auth" ) ;
223- mockExchangeCodeForTokens . mockResolvedValue ( {
224- access_token : "tok" ,
225- token_type : "bearer" ,
226- } ) ;
227-
228- await performLogin ( true ) ;
229- expect ( mockOpen ) . toHaveBeenCalledWith ( "https://example.com/auth" ) ;
230- } ) ;
231-
232- test ( "skips browser open when openBrowser=false" , async ( ) => {
233- mockGeneratePKCE . mockReturnValue ( { codeVerifier : "v" , codeChallenge : "c" } ) ;
234- mockGenerateState . mockReturnValue ( "s" ) ;
235- mockCreateCallbackServer . mockReturnValue ( {
236- port : Promise . resolve ( 52417 ) ,
237- result : Promise . resolve ( { code : "code" , state : "s" } ) ,
238- close : vi . fn ( ) ,
239- } ) ;
240- mockBuildAuthorizationUrl . mockReturnValue ( "https://example.com/auth" ) ;
241- mockExchangeCodeForTokens . mockResolvedValue ( {
242- access_token : "tok" ,
243- token_type : "bearer" ,
244- } ) ;
245-
246- await performLogin ( false ) ;
247- expect ( mockOpen ) . not . toHaveBeenCalled ( ) ;
248- } ) ;
249-
250- test ( "returns null on callback failure" , async ( ) => {
251- const mockClose = vi . fn ( ) ;
252- mockGeneratePKCE . mockReturnValue ( { codeVerifier : "v" , codeChallenge : "c" } ) ;
253- mockGenerateState . mockReturnValue ( "s" ) ;
254- mockCreateCallbackServer . mockReturnValue ( {
255- port : Promise . resolve ( 52417 ) ,
256- result : Promise . reject ( new Error ( "User cancelled" ) ) ,
257- close : mockClose ,
258- } ) ;
259- mockBuildAuthorizationUrl . mockReturnValue ( "https://example.com/auth" ) ;
260-
261- const result = await performLogin ( ) ;
262- expect ( result ) . toBeNull ( ) ;
263- expect ( mockClose ) . toHaveBeenCalled ( ) ;
264- } ) ;
265-
266- test ( "uses device flow when forceDevice=true" , async ( ) => {
267- mockStartDeviceAuthorization . mockResolvedValue ( {
268- device_code : "dc" ,
269- user_code : "ABCD-EFGH" ,
270- verification_uri : "https://t/oauth/device" ,
271- verification_uri_complete : "https://t/oauth/device?user_code=ABCD-EFGH" ,
272- expires_in : 600 ,
273- interval : 0 ,
274- } ) ;
275- mockPollDeviceToken . mockResolvedValue ( {
276- status : "approved" ,
277- tokens : { access_token : "ctx7sk-x" , token_type : "bearer" } ,
278- } ) ;
279- vi . stubGlobal (
280- "fetch" ,
281- vi . fn ( ) . mockResolvedValue ( { ok : false , json : ( ) => Promise . resolve ( { } ) } )
282- ) ;
283-
284- const result = await performLogin ( false , true ) ;
285- expect ( result ) . toBe ( "ctx7sk-x" ) ;
286- expect ( mockCreateCallbackServer ) . not . toHaveBeenCalled ( ) ;
287- } ) ;
288-
289- test ( "uses device flow when shouldUseDeviceFlow returns true" , async ( ) => {
290- mockShouldUseDeviceFlow . mockReturnValueOnce ( true ) ;
291- mockStartDeviceAuthorization . mockResolvedValue ( {
292- device_code : "dc" ,
293- user_code : "X" ,
294- verification_uri : "https://t" ,
295- verification_uri_complete : undefined ,
296- expires_in : 600 ,
297- interval : 0 ,
298- } ) ;
299- mockPollDeviceToken . mockResolvedValue ( {
300- status : "approved" ,
301- tokens : { access_token : "tok" , token_type : "bearer" } ,
302- } ) ;
303- vi . stubGlobal (
304- "fetch" ,
305- vi . fn ( ) . mockResolvedValue ( { ok : false , json : ( ) => Promise . resolve ( { } ) } )
306- ) ;
307-
308- const result = await performLogin ( false ) ;
309- expect ( result ) . toBe ( "tok" ) ;
310- expect ( mockStartDeviceAuthorization ) . toHaveBeenCalled ( ) ;
311- } ) ;
312- } ) ;
313-
314- describe ( "performDeviceLogin" , ( ) => {
315173 const authorization = {
316174 device_code : "dc" ,
317175 user_code : "ABCD-EFGH" ,
@@ -336,7 +194,7 @@ describe("performDeviceLogin", () => {
336194 tokens : { access_token : "ctx7sk-x" , token_type : "bearer" } ,
337195 } ) ;
338196
339- const result = await performDeviceLogin ( false ) ;
197+ const result = await performLogin ( false ) ;
340198 expect ( result ) . toBe ( "ctx7sk-x" ) ;
341199 expect ( mockSaveTokens ) . toHaveBeenCalledWith ( {
342200 access_token : "ctx7sk-x" ,
@@ -348,15 +206,15 @@ describe("performDeviceLogin", () => {
348206 mockStartDeviceAuthorization . mockResolvedValue ( authorization ) ;
349207 mockPollDeviceToken . mockResolvedValue ( { status : "denied" } ) ;
350208
351- expect ( await performDeviceLogin ( false ) ) . toBeNull ( ) ;
209+ expect ( await performLogin ( false ) ) . toBeNull ( ) ;
352210 expect ( mockSaveTokens ) . not . toHaveBeenCalled ( ) ;
353211 } ) ;
354212
355213 test ( "returns null on expired" , async ( ) => {
356214 mockStartDeviceAuthorization . mockResolvedValue ( authorization ) ;
357215 mockPollDeviceToken . mockResolvedValue ( { status : "expired" } ) ;
358216
359- expect ( await performDeviceLogin ( false ) ) . toBeNull ( ) ;
217+ expect ( await performLogin ( false ) ) . toBeNull ( ) ;
360218 expect ( mockSaveTokens ) . not . toHaveBeenCalled ( ) ;
361219 } ) ;
362220
@@ -372,7 +230,7 @@ describe("performDeviceLogin", () => {
372230 tokens : { access_token : "t" , token_type : "bearer" } ,
373231 } ) ;
374232
375- const pending = performDeviceLogin ( false ) ;
233+ const pending = performLogin ( false ) ;
376234 // transient bumps the interval by 5s (mirroring slow_down), so the
377235 // 2nd and 3rd polls each need a 5s wait. Advance enough to cover both.
378236 await vi . advanceTimersByTimeAsync ( 11_000 ) ;
@@ -393,7 +251,7 @@ describe("performDeviceLogin", () => {
393251 tokens : { access_token : "t" , token_type : "bearer" } ,
394252 } ) ;
395253
396- const pending = performDeviceLogin ( false ) ;
254+ const pending = performLogin ( false ) ;
397255 // First poll fires after the initial 0ms interval; slow_down then
398256 // bumps the interval by 5000ms before the second poll.
399257 await vi . advanceTimersByTimeAsync ( 5500 ) ;
@@ -408,7 +266,7 @@ describe("performDeviceLogin", () => {
408266 test ( "returns null when start request throws" , async ( ) => {
409267 mockStartDeviceAuthorization . mockRejectedValue ( new Error ( "network down" ) ) ;
410268
411- expect ( await performDeviceLogin ( false ) ) . toBeNull ( ) ;
269+ expect ( await performLogin ( false ) ) . toBeNull ( ) ;
412270 expect ( mockPollDeviceToken ) . not . toHaveBeenCalled ( ) ;
413271 } ) ;
414272
@@ -422,7 +280,7 @@ describe("performDeviceLogin", () => {
422280 tokens : { access_token : "t" , token_type : "bearer" } ,
423281 } ) ;
424282
425- await performDeviceLogin ( true ) ;
283+ await performLogin ( true ) ;
426284 expect ( mockOpen ) . toHaveBeenCalledWith ( authorization . verification_uri_complete ) ;
427285 } finally {
428286 Object . defineProperty ( process . stdin , "isTTY" , { value : originalIsTTY , configurable : true } ) ;
@@ -436,7 +294,7 @@ describe("performDeviceLogin", () => {
436294 tokens : { access_token : "t" , token_type : "bearer" } ,
437295 } ) ;
438296
439- await performDeviceLogin ( false ) ;
297+ await performLogin ( false ) ;
440298 expect ( mockOpen ) . not . toHaveBeenCalled ( ) ;
441299 } ) ;
442300
@@ -449,7 +307,7 @@ describe("performDeviceLogin", () => {
449307 tokens : { access_token : "t" , token_type : "bearer" } ,
450308 } ) ;
451309
452- const pending = performDeviceLogin ( false ) ;
310+ const pending = performLogin ( false ) ;
453311 // Two 5s polls.
454312 await vi . advanceTimersByTimeAsync ( 11_000 ) ;
455313 const result = await pending ;
0 commit comments