@@ -14,14 +14,28 @@ import { Session } from '../../../../amazonqFeatureDev/session/session'
1414import { Prompter } from '../../../../shared/ui/prompter'
1515import { assertTelemetry , toFile } from '../../../testUtil'
1616import {
17+ CodeIterationLimitError ,
18+ ContentLengthError ,
19+ createUserFacingErrorMessage ,
20+ denyListedErrors ,
21+ FeatureDevServiceError ,
22+ MonthlyConversationLimitError ,
1723 NoChangeRequiredException ,
24+ PrepareRepoFailedError ,
25+ PromptRefusalException ,
1826 SelectedFolderNotInWorkspaceFolderError ,
27+ TabIdNotFoundError ,
28+ UploadCodeError ,
1929 UploadURLExpired ,
30+ UserMessageNotFoundError ,
31+ ZipFileError ,
2032} from '../../../../amazonqFeatureDev/errors'
2133import { CodeGenState , PrepareCodeGenState } from '../../../../amazonqFeatureDev/session/sessionState'
2234import { FeatureDevClient } from '../../../../amazonqFeatureDev/client/featureDev'
2335import { createAmazonQUri } from '../../../../amazonq/commons/diff'
2436import { AuthUtil } from '../../../../codewhisperer'
37+ import { featureName , messageWithConversationId } from '../../../../amazonqFeatureDev'
38+ import { i18n } from '../../../../shared/i18n-helper'
2539
2640let mockGetCodeGeneration : sinon . SinonStub
2741describe ( 'Controller' , ( ) => {
@@ -210,7 +224,6 @@ describe('Controller', () => {
210224 } )
211225
212226 it ( 'accepts valid source folders under a workspace root' , async ( ) => {
213- const controllerSetup = await createController ( )
214227 sinon . stub ( controllerSetup . sessionStorage , 'getSession' ) . resolves ( session )
215228 sinon . stub ( vscode . workspace , 'getWorkspaceFolder' ) . returns ( controllerSetup . workspaceFolder )
216229 const expectedSourceRoot = path . join ( controllerSetup . workspaceFolder . uri . fsPath , 'src' )
@@ -386,33 +399,257 @@ describe('Controller', () => {
386399 }
387400
388401 describe ( 'processErrorChatMessage' , function ( ) {
389- async function verifyException ( error : Error , message ?: string ) {
402+ async function fireException ( error : Error ) {
390403 sinon . stub ( session , 'preloader' ) . throws ( error )
391- const sendAnswerSpy = sinon . stub ( controllerSetup . messenger , 'sendAnswer' )
392404
393405 await fireChatMessage ( )
406+ }
394407
395- assert . strictEqual (
396- sendAnswerSpy . calledWith ( {
397- type : 'answer' ,
398- tabID,
399- message : message ?? error . message ,
400- canBeVoted : true ,
401- } ) ,
402- true
403- )
408+ function createTestErrorMessage ( message : string ) {
409+ return createUserFacingErrorMessage ( `${ featureName } request failed: ${ message } ` )
404410 }
405411
406412 it ( 'should handle NoChangeRequiredException' , async function ( ) {
413+ const sendAnswerSpy = sinon . stub ( controllerSetup . messenger , 'sendAnswer' )
407414 const noChangeRequiredException = new NoChangeRequiredException ( )
408415
409- await verifyException ( noChangeRequiredException )
416+ await fireException ( noChangeRequiredException )
417+
418+ assert . ok (
419+ sendAnswerSpy . calledWith ( {
420+ type : 'answer' ,
421+ tabID,
422+ message : noChangeRequiredException . message ,
423+ canBeVoted : true ,
424+ } )
425+ )
410426 } )
411427
412428 it ( 'should handle UploadURLExpired' , async function ( ) {
429+ const sendAnswerSpy = sinon . stub ( controllerSetup . messenger , 'sendAnswer' )
413430 const uploadURLExpired = new UploadURLExpired ( )
414431
415- await verifyException ( uploadURLExpired )
432+ await fireException ( uploadURLExpired )
433+
434+ assert . ok (
435+ sendAnswerSpy . calledWith ( {
436+ type : 'answer' ,
437+ tabID,
438+ message : uploadURLExpired . message ,
439+ canBeVoted : true ,
440+ } )
441+ )
442+ } )
443+
444+ it ( 'should handle ContentLengthError' , async function ( ) {
445+ const sendAnswerSpy = sinon . stub ( controllerSetup . messenger , 'sendAnswer' )
446+ const contentLengthError = new ContentLengthError ( )
447+ const message = contentLengthError . message + messageWithConversationId ( session ?. conversationIdUnsafe )
448+
449+ await fireException ( contentLengthError )
450+
451+ assert . ok (
452+ sendAnswerSpy . calledWith ( {
453+ type : 'answer' ,
454+ tabID,
455+ message,
456+ canBeVoted : true ,
457+ } )
458+ )
459+ } )
460+
461+ it ( 'should handle MonthlyConversationLimitError' , async function ( ) {
462+ const sendMonthlyLimitErrorSpy = sinon . stub ( controllerSetup . messenger , 'sendMonthlyLimitError' )
463+ const monthlyConversationLimitError = new MonthlyConversationLimitError ( 'Service Quota Exceeded' )
464+
465+ await fireException ( monthlyConversationLimitError )
466+
467+ assert . ok ( sendMonthlyLimitErrorSpy . calledWith ( tabID ) )
468+ } )
469+
470+ it ( 'should handle FeatureDevServiceError' , async function ( ) {
471+ const sendErrorMessageSpy = sinon . stub ( controllerSetup . messenger , 'sendErrorMessage' )
472+ const featureDevServiceError = new FeatureDevServiceError (
473+ i18n ( 'AWS.amazonq.featureDev.error.codeGen.default' ) ,
474+ 'GuardrailsException'
475+ )
476+
477+ await fireException ( featureDevServiceError )
478+
479+ assert . ok (
480+ sendErrorMessageSpy . calledWith (
481+ createTestErrorMessage ( featureDevServiceError . message ) ,
482+ tabID ,
483+ session ?. retries ,
484+ session ?. conversationIdUnsafe
485+ )
486+ )
487+ } )
488+
489+ it ( 'should handle UploadCodeError' , async function ( ) {
490+ const sendErrorMessageSpy = sinon . stub ( controllerSetup . messenger , 'sendErrorMessage' )
491+ const uploadCodeError = new UploadCodeError ( '403: Forbiden' )
492+
493+ await fireException ( uploadCodeError )
494+
495+ assert . ok (
496+ sendErrorMessageSpy . calledWith (
497+ createTestErrorMessage ( uploadCodeError . message ) ,
498+ tabID ,
499+ session ?. retries ,
500+ session ?. conversationIdUnsafe
501+ )
502+ )
503+ } )
504+
505+ it ( 'should handle UserMessageNotFoundError' , async function ( ) {
506+ const sendErrorMessageSpy = sinon . stub ( controllerSetup . messenger , 'sendErrorMessage' )
507+ const userMessageNotFoundError = new UserMessageNotFoundError ( )
508+
509+ await fireException ( userMessageNotFoundError )
510+
511+ assert . ok (
512+ sendErrorMessageSpy . calledWith (
513+ createTestErrorMessage ( userMessageNotFoundError . message ) ,
514+ tabID ,
515+ session ?. retries ,
516+ session ?. conversationIdUnsafe
517+ )
518+ )
519+ } )
520+
521+ it ( 'should handle TabIdNotFoundError' , async function ( ) {
522+ const sendErrorMessageSpy = sinon . stub ( controllerSetup . messenger , 'sendErrorMessage' )
523+ const tabIdNotFoundError = new TabIdNotFoundError ( )
524+
525+ await fireException ( tabIdNotFoundError )
526+
527+ assert . ok (
528+ sendErrorMessageSpy . calledWith (
529+ createTestErrorMessage ( tabIdNotFoundError . message ) ,
530+ tabID ,
531+ session ?. retries ,
532+ session ?. conversationIdUnsafe
533+ )
534+ )
535+ } )
536+
537+ it ( 'should handle PrepareRepoFailedError' , async function ( ) {
538+ const sendErrorMessageSpy = sinon . stub ( controllerSetup . messenger , 'sendErrorMessage' )
539+ const prepareRepoFailedError = new PrepareRepoFailedError ( )
540+
541+ await fireException ( prepareRepoFailedError )
542+
543+ assert . ok (
544+ sendErrorMessageSpy . calledWith (
545+ createTestErrorMessage ( prepareRepoFailedError . message ) ,
546+ tabID ,
547+ session ?. retries ,
548+ session ?. conversationIdUnsafe
549+ )
550+ )
551+ } )
552+
553+ it ( 'should handle PromptRefusalException' , async function ( ) {
554+ const sendErrorMessageSpy = sinon . stub ( controllerSetup . messenger , 'sendErrorMessage' )
555+ const promptRefusalException = new PromptRefusalException ( )
556+
557+ await fireException ( promptRefusalException )
558+
559+ assert . ok (
560+ sendErrorMessageSpy . calledWith (
561+ createTestErrorMessage ( promptRefusalException . message ) ,
562+ tabID ,
563+ 0 ,
564+ session ?. conversationIdUnsafe ,
565+ true
566+ )
567+ )
568+ } )
569+
570+ it ( 'should handle ZipFileError' , async function ( ) {
571+ const sendErrorMessageSpy = sinon . stub ( controllerSetup . messenger , 'sendErrorMessage' )
572+ const zipFileError = new ZipFileError ( )
573+
574+ await fireException ( zipFileError )
575+
576+ assert . ok (
577+ sendErrorMessageSpy . calledWith (
578+ createTestErrorMessage ( zipFileError . message ) ,
579+ tabID ,
580+ 0 ,
581+ session ?. conversationIdUnsafe ,
582+ true
583+ )
584+ )
585+ } )
586+
587+ it ( 'should handle CodeIterationLimitError' , async function ( ) {
588+ const sendAnswerSpy = sinon . stub ( controllerSetup . messenger , 'sendAnswer' )
589+ const codeIterationLimitError = new CodeIterationLimitError ( )
590+
591+ await fireException ( codeIterationLimitError )
592+
593+ assert . ok (
594+ sendAnswerSpy . calledWith ( {
595+ type : 'answer' ,
596+ tabID,
597+ message : codeIterationLimitError . message ,
598+ canBeVoted : true ,
599+ } )
600+ )
601+ } )
602+
603+ it ( 'should handle DenyListedError' , async function ( ) {
604+ const sendErrorMessageSpy = sinon . stub ( controllerSetup . messenger , 'sendErrorMessage' )
605+ const denyListedError = new Error ( denyListedErrors [ 0 ] )
606+
607+ await fireException ( denyListedError )
608+
609+ assert . ok (
610+ sendErrorMessageSpy . calledWith (
611+ i18n ( 'AWS.amazonq.featureDev.error.codeGen.denyListedError' ) ,
612+ tabID ,
613+ session ?. retries ,
614+ session ?. conversationIdUnsafe ,
615+ true
616+ )
617+ )
618+ } )
619+
620+ it ( 'should handle retris remaining 0' , async function ( ) {
621+ sinon . stub ( session , 'retries' ) . value ( 0 )
622+ const sendErrorMessageSpy = sinon . stub ( controllerSetup . messenger , 'sendErrorMessage' )
623+ const error = new Error ( )
624+
625+ await fireException ( error )
626+
627+ assert . ok (
628+ sendErrorMessageSpy . calledWith (
629+ i18n ( 'AWS.amazonq.featureDev.error.codeGen.denyListedError' ) ,
630+ tabID ,
631+ session ?. retries ,
632+ session ?. conversationIdUnsafe ,
633+ true
634+ )
635+ )
636+ } )
637+
638+ it ( 'should handle default errors' , async function ( ) {
639+ const sendErrorMessageSpy = sinon . stub ( controllerSetup . messenger , 'sendErrorMessage' )
640+ const error = new Error ( )
641+
642+ await fireException ( error )
643+
644+ assert . ok (
645+ sendErrorMessageSpy . calledWith (
646+ i18n ( 'AWS.amazonq.featureDev.error.codeGen.default' ) ,
647+ tabID ,
648+ session ?. retries ,
649+ session ?. conversationIdUnsafe ,
650+ true
651+ )
652+ )
416653 } )
417654 } )
418655 } )
0 commit comments