@@ -2,7 +2,7 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'
22
33import { ForbiddenError } from '@/errors/graphql-errors'
44import { generateMockContext } from '@/graphql/__tests__/mutations/tiles/table.mock'
5- import generatePresignedUrl from '@/graphql/mutations/generate-presigned-url '
5+ import generatePresignedPost from '@/graphql/mutations/generate-presigned-post '
66import Flow from '@/models/flow'
77import Context from '@/types/express/context'
88
@@ -12,59 +12,76 @@ const VALID_PARAMS = {
1212 fileType : 'text/plain' ,
1313 size : 100 ,
1414 updatedAt : new Date ( ) . toISOString ( ) ,
15- manualUpload : true ,
1615}
1716
18- const mocks = vi . hoisted ( ( ) => ( {
19- getSignedUrl : vi . fn ( ) ,
17+ // Mock the s3 helpers module
18+ vi . mock ( '@/helpers/s3' , ( ) => ( {
19+ getPresignedPost : vi . fn ( ) ,
20+ COMMON_S3_BUCKET : 'test-bucket' ,
21+ COMMON_S3_MOCK_FOLDER_PREFIX : 's3:test-bucket:mock/' ,
22+ parseS3Id : vi . fn ( ) ,
23+ MAX_FILE_SIZE : 1024 * 1024 * 2 ,
24+ ACCEPTED_FILE_TYPES : [ 'text/plain' ] ,
25+ validateObjectKey : vi . fn ( ( objectKey ) => {
26+ const invalidCharacters = / [ \\ { } ^ ` % ~ # < > | [ \] ] /
27+ if ( invalidCharacters . test ( objectKey ) ) {
28+ return false
29+ }
30+
31+ // validate length of object key
32+ const byteLength = Buffer . byteLength ( objectKey , 'utf-8' )
33+ return byteLength <= 1024
34+ } ) ,
2035} ) )
2136
22- vi . mock ( '@aws-sdk/s3-request-presigner' , ( ) => ( {
23- getSignedUrl : mocks . getSignedUrl ,
24- } ) )
37+ import { COMMON_S3_BUCKET , getPresignedPost } from '@/helpers/s3'
2538
26- describe ( 'generatePresignedUrl ' , ( ) => {
39+ describe ( 'generatePresignedPost ' , ( ) => {
2740 let context : Context
2841 beforeEach ( async ( ) => {
2942 context = await generateMockContext ( )
43+ vi . clearAllMocks ( )
3044 } )
3145
3246 it ( 'should generate a presigned url' , async ( ) => {
33- const expectedUrl = 'https://presigned-url.example.com'
34- mocks . getSignedUrl . mockResolvedValueOnce ( expectedUrl )
35-
3647 await Flow . query ( ) . insert ( {
3748 id : VALID_PARAMS . flowId ,
3849 name : 'Test Flow' ,
3950 userId : context . currentUser . id ,
4051 } )
4152
42- const result = await generatePresignedUrl (
43- null ,
44- { input : VALID_PARAMS } ,
45- context ,
53+ await generatePresignedPost ( null , { input : VALID_PARAMS } , context )
54+ expect ( getPresignedPost ) . toHaveBeenCalledWith (
55+ COMMON_S3_BUCKET ,
56+ expect . stringMatching (
57+ new RegExp (
58+ `^${ VALID_PARAMS . flowId } /[a-f0-9-]+/${ VALID_PARAMS . filename } $` ,
59+ ) ,
60+ ) ,
61+ VALID_PARAMS . fileType ,
62+ {
63+ flowId : VALID_PARAMS . flowId ,
64+ filename : VALID_PARAMS . filename ,
65+ size : VALID_PARAMS . size . toString ( ) ,
66+ updatedAt : VALID_PARAMS . updatedAt ,
67+ } ,
4668 )
47- const expectedKeys = [ 'url' , 's3Id' ]
48- expect ( Object . keys ( result ) ) . toEqual ( expectedKeys )
49- expect ( result . s3Id ) . toContain ( VALID_PARAMS . flowId )
5069 } )
5170
5271 it ( 'should throw an error if the user does not have access to the flow' , async ( ) => {
53- vi . fn ( )
54- . mockRejectedValue ( Flow . hasAccess )
55- . mockRejectedValue (
56- new ForbiddenError ( 'You do not have access to this flow' ) ,
57- )
72+ const otherUserContext = await generateMockContext ( )
73+ await Flow . query ( )
74+ . patch ( {
75+ userId : otherUserContext . currentUser . id ,
76+ } )
77+ . where ( 'id' , VALID_PARAMS . flowId )
5878
5979 await expect (
60- generatePresignedUrl ( null , { input : VALID_PARAMS } , context ) ,
80+ generatePresignedPost ( null , { input : VALID_PARAMS } , context ) ,
6181 ) . rejects . toThrow ( ForbiddenError )
6282 } )
6383
6484 it ( 'should throw an error if the file size is too large' , async ( ) => {
65- const expectedUrl = 'https://presigned-url.example.com'
66- mocks . getSignedUrl . mockResolvedValueOnce ( expectedUrl )
67-
6885 await Flow . query ( ) . insert ( {
6986 id : VALID_PARAMS . flowId ,
7087 name : 'Test Flow' ,
@@ -73,7 +90,7 @@ describe('generatePresignedUrl', () => {
7390
7491 const tooLargeParams = { ...VALID_PARAMS , size : 2 * 1024 * 1024 + 1 }
7592 await expect (
76- generatePresignedUrl ( null , { input : tooLargeParams } , context ) ,
93+ generatePresignedPost ( null , { input : tooLargeParams } , context ) ,
7794 ) . rejects . toThrow ( 'Size of attachment exceeds 2MB' )
7895 } )
7996
@@ -85,9 +102,6 @@ describe('generatePresignedUrl', () => {
85102 ] ) (
86103 'should throw an error if the file type is not supported: %s' ,
87104 async ( fileType ) => {
88- const expectedUrl = 'https://presigned-url.example.com'
89- mocks . getSignedUrl . mockResolvedValueOnce ( expectedUrl )
90-
91105 await Flow . query ( ) . insert ( {
92106 id : VALID_PARAMS . flowId ,
93107 name : 'Test Flow' ,
@@ -100,7 +114,7 @@ describe('generatePresignedUrl', () => {
100114 }
101115
102116 await expect (
103- generatePresignedUrl ( null , { input : unsupportedParams } , context ) ,
117+ generatePresignedPost ( null , { input : unsupportedParams } , context ) ,
104118 ) . rejects . toThrow ( 'Unsupported file type' )
105119 } ,
106120 )
0 commit comments