@@ -7,12 +7,13 @@ import { FormProvider, useForm } from 'react-hook-form';
77import { useNavigate , useParams } from 'react-router' ;
88import AutomlConfigure from '~/app/components/configure/AutomlConfigure' ;
99import type { Files } from '~/app/components/common/FileExplorer/FileExplorer' ;
10- import { useS3FileUploadMutation } from '~/app/hooks/mutations' ;
1110import { useS3GetFileSchemaQuery } from '~/app/hooks/queries' ;
1211import { createConfigureSchema , TASK_TYPES } from '~/app/schemas/configure.schema' ;
1312
1413const mockNotificationError = jest . fn ( ) ;
1514
15+ const mockS3MutateAsync = jest . fn ( ) . mockResolvedValue ( { uploaded : true , key : 'uploaded-key.csv' } ) ;
16+
1617jest . mock ( 'react-router' , ( ) => ( {
1718 ...jest . requireActual ( 'react-router' ) ,
1819 useNavigate : jest . fn ( ) ,
@@ -28,30 +29,18 @@ jest.mock('~/app/hooks/useNotification', () => ({
2829 } ) ,
2930} ) ) ;
3031
31- jest . mock ( '~/app/hooks/mutations' , ( ) => {
32- const mockS3MutateAsync = jest
33- . fn ( )
34- . mockResolvedValue ( { uploaded : true , key : 'uploaded-key.csv' } ) ;
35- const stableS3UploadMutation = {
32+ jest . mock ( '~/app/hooks/mutations' , ( ) => ( {
33+ ...jest . requireActual < typeof import ( '~/app/hooks/mutations' ) > ( '~/app/hooks/mutations' ) ,
34+ useS3FileUploadMutation : jest . fn ( ( ) => ( {
3635 mutateAsync : mockS3MutateAsync ,
3736 isPending : false ,
3837 reset : jest . fn ( ) ,
39- variables : undefined as { file : File } | undefined ,
40- } ;
41- return {
42- ...jest . requireActual < typeof import ( '~/app/hooks/mutations' ) > ( '~/app/hooks/mutations' ) ,
43- useS3FileUploadMutation : jest . fn ( ( ) => stableS3UploadMutation ) ,
44- } ;
45- } ) ;
38+ variables : undefined ,
39+ } ) ) ,
40+ } ) ) ;
4641
4742function getMockS3MutateAsync ( ) : jest . Mock {
48- const result = jest . mocked ( useS3FileUploadMutation ) . mock . results [ 0 ] ?. value as
49- | { mutateAsync : jest . Mock }
50- | undefined ;
51- if ( ! result ?. mutateAsync ) {
52- throw new Error ( 'useS3FileUploadMutation was not called; render AutomlConfigure first' ) ;
53- }
54- return result . mutateAsync ;
43+ return mockS3MutateAsync ;
5544}
5645
5746// Mock S3FileExplorer component
@@ -239,6 +228,8 @@ describe('AutomlConfigure', () => {
239228 } as unknown as ReturnType < typeof useS3GetFileSchemaQuery > ) ;
240229 mockUseNavigate . mockReturnValue ( jest . fn ( ) ) ;
241230 mockUseParams . mockReturnValue ( { namespace : 'test-namespace' } ) ;
231+ // Reset the S3 upload mock to default resolved value
232+ mockS3MutateAsync . mockResolvedValue ( { uploaded : true , key : 'uploaded-key.csv' } ) ;
242233 } ) ;
243234
244235 describe ( 'initial state - no secret selected' , ( ) => {
@@ -376,6 +367,30 @@ describe('AutomlConfigure', () => {
376367 expect ( mockNotificationError ) . not . toHaveBeenCalled ( ) ;
377368 } ) ;
378369
370+ it ( 'should show human-readable error for max collision attempts (409)' , async ( ) => {
371+ renderComponent ( ) ;
372+ fireEvent . click ( screen . getByTestId ( 'aws-secret-selector-select-secret-1' ) ) ;
373+ fireEvent . click ( screen . getByRole ( 'button' , { name : 'Upload file' } ) ) ;
374+
375+ const fileInput = document . querySelector ( 'input[type="file"]' ) as HTMLInputElement | null ;
376+ expect ( fileInput ) . not . toBeNull ( ) ;
377+
378+ const file = new File ( [ 'hello' ] , 'collision.csv' , { type : 'text/csv' } ) ;
379+ getMockS3MutateAsync ( ) . mockClear ( ) ;
380+ getMockS3MutateAsync ( ) . mockRejectedValue (
381+ new Error ( 'unable to find unique filename after 10 attempts' ) ,
382+ ) ;
383+
384+ fireEvent . change ( fileInput ! , { target : { files : [ file ] } } ) ;
385+
386+ await waitFor ( ( ) => {
387+ expect ( mockNotificationError ) . toHaveBeenCalledWith (
388+ 'Failed to upload file' ,
389+ 'A file with this name already exists and no unique name could be generated. Please rename your file or delete existing files with similar names.' ,
390+ ) ;
391+ } ) ;
392+ } ) ;
393+
379394 it ( 'should show the newly selected secret name when switching secrets' , ( ) => {
380395 renderComponent ( ) ;
381396
0 commit comments