@@ -332,9 +332,86 @@ describe('setupUser validation', () => {
332332 vi . unstubAllEnvs ( ) ;
333333 } ) ;
334334
335- it ( 'should throw error if LoadCodeAssist returns ineligible tiers and no current tier' , async ( ) => {
335+ it ( 'should throw ineligible tier error when currentTier exists but no project ID available' , async ( ) => {
336+ vi . stubEnv ( 'GOOGLE_CLOUD_PROJECT' , '' ) ;
337+ mockLoad . mockResolvedValue ( {
338+ currentTier : mockPaidTier ,
339+ cloudaicompanionProject : undefined ,
340+ ineligibleTiers : [
341+ {
342+ reasonMessage : 'User is not eligible' ,
343+ reasonCode : 'INELIGIBLE_ACCOUNT' ,
344+ tierId : 'free-tier' ,
345+ tierName : 'free' ,
346+ } ,
347+ ] ,
348+ } ) ;
349+
350+ await expect ( setupUser ( { } as OAuth2Client ) ) . rejects . toThrow (
351+ 'User is not eligible' ,
352+ ) ;
353+ } ) ;
354+
355+ it ( 'should continue if LoadCodeAssist returns ineligible tiers but has allowed tiers' , async ( ) => {
356+ const mockOnboardUser = vi . fn ( ) . mockResolvedValue ( {
357+ done : true ,
358+ response : {
359+ cloudaicompanionProject : {
360+ id : 'server-project' ,
361+ } ,
362+ } ,
363+ } ) ;
364+ vi . mocked ( CodeAssistServer ) . mockImplementation (
365+ ( ) =>
366+ ( {
367+ loadCodeAssist : mockLoad ,
368+ onboardUser : mockOnboardUser ,
369+ } ) as unknown as CodeAssistServer ,
370+ ) ;
371+
372+ mockLoad . mockResolvedValue ( {
373+ currentTier : null ,
374+ allowedTiers : [ mockPaidTier ] ,
375+ ineligibleTiers : [
376+ {
377+ reasonMessage : 'Not eligible for free tier' ,
378+ reasonCode : 'INELIGIBLE_ACCOUNT' ,
379+ tierId : 'free-tier' ,
380+ tierName : 'free' ,
381+ } ,
382+ ] ,
383+ } ) ;
384+
385+ // Should not throw - should proceed to onboarding with the allowed tier
386+ const result = await setupUser ( { } as OAuth2Client ) ;
387+ expect ( result ) . toEqual ( {
388+ projectId : 'server-project' ,
389+ userTier : 'standard-tier' ,
390+ userTierName : 'paid' ,
391+ } ) ;
392+ expect ( mockOnboardUser ) . toHaveBeenCalled ( ) ;
393+ } ) ;
394+
395+ it ( 'should proceed to onboarding with LEGACY tier when no currentTier and no allowedTiers' , async ( ) => {
396+ const mockOnboardUser = vi . fn ( ) . mockResolvedValue ( {
397+ done : true ,
398+ response : {
399+ cloudaicompanionProject : {
400+ id : 'server-project' ,
401+ } ,
402+ } ,
403+ } ) ;
404+ vi . mocked ( CodeAssistServer ) . mockImplementation (
405+ ( ) =>
406+ ( {
407+ loadCodeAssist : mockLoad ,
408+ onboardUser : mockOnboardUser ,
409+ } ) as unknown as CodeAssistServer ,
410+ ) ;
411+
336412 mockLoad . mockResolvedValue ( {
337413 currentTier : null ,
414+ allowedTiers : undefined ,
338415 ineligibleTiers : [
339416 {
340417 reasonMessage : 'User is not eligible' ,
@@ -345,8 +422,63 @@ describe('setupUser validation', () => {
345422 ] ,
346423 } ) ;
347424
425+ // Should proceed to onboarding with LEGACY tier, ignoring ineligible tier errors
426+ const result = await setupUser ( { } as OAuth2Client ) ;
427+ expect ( result ) . toEqual ( {
428+ projectId : 'server-project' ,
429+ userTier : 'legacy-tier' ,
430+ userTierName : '' ,
431+ } ) ;
432+ expect ( mockOnboardUser ) . toHaveBeenCalledWith (
433+ expect . objectContaining ( {
434+ tierId : 'legacy-tier' ,
435+ } ) ,
436+ ) ;
437+ } ) ;
438+
439+ it ( 'should throw ValidationRequiredError even if allowed tiers exist' , async ( ) => {
440+ mockLoad . mockResolvedValue ( {
441+ currentTier : null ,
442+ allowedTiers : [ mockPaidTier ] ,
443+ ineligibleTiers : [
444+ {
445+ reasonMessage : 'Please verify your account' ,
446+ reasonCode : 'VALIDATION_REQUIRED' ,
447+ tierId : 'free-tier' ,
448+ tierName : 'free' ,
449+ validationUrl : 'https://example.com/verify' ,
450+ } ,
451+ ] ,
452+ } ) ;
453+
454+ await expect ( setupUser ( { } as OAuth2Client ) ) . rejects . toThrow (
455+ ValidationRequiredError ,
456+ ) ;
457+ } ) ;
458+
459+ it ( 'should combine multiple ineligible tier messages when currentTier exists but no project ID' , async ( ) => {
460+ vi . stubEnv ( 'GOOGLE_CLOUD_PROJECT' , '' ) ;
461+ mockLoad . mockResolvedValue ( {
462+ currentTier : mockPaidTier ,
463+ cloudaicompanionProject : undefined ,
464+ ineligibleTiers : [
465+ {
466+ reasonMessage : 'Not eligible for standard' ,
467+ reasonCode : 'INELIGIBLE_ACCOUNT' ,
468+ tierId : 'standard-tier' ,
469+ tierName : 'standard' ,
470+ } ,
471+ {
472+ reasonMessage : 'Not eligible for free' ,
473+ reasonCode : 'INELIGIBLE_ACCOUNT' ,
474+ tierId : 'free-tier' ,
475+ tierName : 'free' ,
476+ } ,
477+ ] ,
478+ } ) ;
479+
348480 await expect ( setupUser ( { } as OAuth2Client ) ) . rejects . toThrow (
349- 'User is not eligible' ,
481+ 'Not eligible for standard, Not eligible for free ' ,
350482 ) ;
351483 } ) ;
352484
0 commit comments