aws-sdk-client-mock icon indicating copy to clipboard operation
aws-sdk-client-mock copied to clipboard

S3 Presign

Open kochie opened this issue 3 years ago • 14 comments

S3 presign is done using a helper library @aws-sdk/s3-request-presigner this seems like something that would need a helper library or additional documentation to mock properly.

It would be good to see a way to mock presign requests. I'm happy to help with this.

kochie avatar Nov 09 '21 06:11 kochie

I looked at it and I think mocking it is not (easily) possible right now with the lib.

Presign is done by a middleware. getSignedUrl() is creating the middleware and makes the send() call. Middleware intercepts the command, generates signed URL, and returns the result instead of proceeding with actually sending the command to AWS. See: https://github.com/aws/aws-sdk-js-v3/blob/main/packages/s3-request-presigner/src/getSignedUrl.ts

The mocking lib does not mock middlewares, but only client send() command. Mocking middleware can be especially hard in this case, since it's created locally in the getSignedUrl() function.

I think the way to go is to mock the whole getSignedUrl() function.

Feel free to submit a PR for this!

m-radzikowski avatar Nov 10 '21 16:11 m-radzikowski

Yeah so at the moment my strategy has been to mock getSignedUrl() and this works but it's a pretty basic mock. I'll look into it but might take some time. I'll post here if I have any updates.

kochie avatar Nov 11 '21 05:11 kochie

Yeah, this functionality would be great.

arunachalamN avatar Dec 17 '21 14:12 arunachalamN

An alternative solution is to mock your URL command to return a {presigned: require('url').parse('http://url')}. At least, it worked for me on PutObject.

ShogunPanda avatar Feb 17 '22 13:02 ShogunPanda

The best solution I've found is from the referenced issue:

const presigner = require('@aws-sdk/s3-request-presigner/dist-cjs/getSignedUrl') // eslint-disable-line @typescript-eslint/no-var-requires, @typescript-eslint/no-unsafe-assignment

sinon.stub(presigner, 'getSignedUrl').resolves('https://s3.amazonaws.com/path/to/object')

jhecking avatar Jun 01 '23 03:06 jhecking

I get an error with this (sinon.stub)

TypeError: Descriptor for property getSignedUrl is non-configurable and non-writable

pagameba avatar Oct 19 '23 19:10 pagameba

This is how I've done using jest:

const presigner = require('@aws-sdk/s3-request-presigner/dist-cjs/getSignedUrl')
jest.spyOn(presigner, 'getSignedUrl').mockResolvedValueOnce(signedUrlMockValue)

Thanks for the simple solution @jhecking 🙌

Roger13 avatar Jan 02 '24 17:01 Roger13

This is how I've done using jest:

const presigner = require('@aws-sdk/s3-request-presigner/dist-cjs/getSignedUrl')
jest.spyOn(presigner, 'getSignedUrl').mockResolvedValueOnce(signedUrlMockValue)

Thanks for the simple solution @jhecking 🙌

This works great, but you need to expose (fake) AWS credentials, or otherwise it will complain.

CredentialsProviderError: Could not load credentials from any providers

major-mayer avatar Mar 04 '24 15:03 major-mayer

Similar behaviour can be achieved for createPresignedPost from s3-presigned-post.

const postPresigner = require('@aws-sdk/s3-presigned-post/dist-cjs/createPresignedPost.js')
jest.spyOn(postPresigner, 'createPresignedPost').mockResolvedValue({ url: 'mockValue',
	fields: {
		key: 'mockValue',
		Policy: 'mockValue',
		'X-Amz-Signature': 'mockValue',
		'X-Amz-Security-Token': 'mockValue',
		bucket: 'mockValue',
		'X-Amz-Algorithm': 'mockValue',
		'X-Amz-Credential': 'mockValue',
		'X-Amz-Date': 'mockValue',
	} })

major-mayer avatar Mar 04 '24 18:03 major-mayer

This is how I've done using jest:

const presigner = require('@aws-sdk/s3-request-presigner/dist-cjs/getSignedUrl')
jest.spyOn(presigner, 'getSignedUrl').mockResolvedValueOnce(signedUrlMockValue)

Thanks for the simple solution @jhecking 🙌

Thank you. I had to change it, but your approach helped me.

My solution:

jest.mock("@aws-sdk/s3-request-presigner", () => {
  return {
    getSignedUrl: jest.fn().mockResolvedValueOnce(signedUrlMockValue),
  };
});

Ribosom avatar Mar 28 '24 07:03 Ribosom

This is how I've done using jest:

const presigner = require('@aws-sdk/s3-request-presigner/dist-cjs/getSignedUrl')
jest.spyOn(presigner, 'getSignedUrl').mockResolvedValueOnce(signedUrlMockValue)

Thanks for the simple solution @jhecking 🙌

This solution doesn't work anymore starting from SDK v3.495.0 unfortunately.

garysassano avatar Apr 10 '24 20:04 garysassano

Is there any PR open to support getSignedUrl mock ? I am completely blocked as work around discussed above as well not working with new version of sdk

Krrish92 avatar Apr 30 '24 14:04 Krrish92