Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(chore)storage: add accessLevel unit tests to getProperties, getUrl apis #11962

Merged
merged 27 commits into from
Sep 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
45f0ca7
chore: add accessLevel tests for getProperties api
kvramyasri7 Sep 1, 2023
69b21da
chore: add getUrl accessLevel unit test case
kvramyasri7 Sep 1, 2023
0fb63f1
Merge branch 'next' into accesslevel-unittest
kvramyasri7 Sep 1, 2023
037ee6d
chore: wip
kvramyasri7 Sep 1, 2023
6dfe956
Merge branch 'next' into accesslevel-unittest
kvramyasri7 Sep 1, 2023
4b4b5e5
Merge branch 'next' into accesslevel-unittest
kvramyasri7 Sep 1, 2023
ebb4065
chore: increase bundle size
kvramyasri7 Sep 1, 2023
a91bdf7
Merge branch 'next' into accesslevel-unittest
kvramyasri7 Sep 1, 2023
e7187d8
Merge branch 'next' into accesslevel-unittest
kvramyasri7 Sep 1, 2023
5f37f5d
chore: getProperties use ir.each() method
kvramyasri7 Sep 1, 2023
462331e
chore: add getUrl it.each() method
kvramyasri7 Sep 1, 2023
39d2c55
chore: remove after each block
kvramyasri7 Sep 1, 2023
d162e94
chore: more clone up
kvramyasri7 Sep 2, 2023
2af8d4c
chore: change input options to it.each
kvramyasri7 Sep 3, 2023
9225918
Merge branch 'next' into accesslevel-unittest
kvramyasri7 Sep 5, 2023
bbed029
chore: remove common part for getProperties
kvramyasri7 Sep 5, 2023
b4b8248
chore: remove getUrl common part
kvramyasri7 Sep 5, 2023
65a9838
chore: address feedback
kvramyasri7 Sep 5, 2023
9a24d32
chore: take out common function for test
kvramyasri7 Sep 5, 2023
c3b3fc7
ignore __utils__while testing
kvramyasri7 Sep 5, 2023
b7ccdbc
chore: update tests with common method
kvramyasri7 Sep 5, 2023
0ef5e17
Merge branch 'next' into accesslevel-unittest
kvramyasri7 Sep 5, 2023
eb0120c
chore: remove fetchAuthSession old mocks
kvramyasri7 Sep 5, 2023
051abc9
chore: change input array
kvramyasri7 Sep 5, 2023
20c9d71
chore: update getUrl tests
kvramyasri7 Sep 5, 2023
293e30e
chore: add private without targetIdentityId
kvramyasri7 Sep 5, 2023
0616ab0
chore: remove util function
kvramyasri7 Sep 5, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions packages/storage/__tests__/providers/s3/apis/copy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { copy } from '../../../../src/providers/s3/apis';

jest.mock('../../../../src/providers/s3/utils/client');
jest.mock('@aws-amplify/core', () => ({
fetchAuthSession: jest.fn(),
Amplify: {
getConfig: jest.fn(),
Auth: {
Expand Down Expand Up @@ -42,7 +41,7 @@ const copyObjectClientBaseParams = {

/**
* bucket is appended at start if it's a sourceKey
* guest: public/${targetIdentityId}/${key}`
* guest: public/${key}`
* private: private/${targetIdentityId}/${key}`
* protected: protected/${targetIdentityId}/${key}`
*/
Expand All @@ -51,6 +50,8 @@ const buildClientRequestKey = (
KeyType: 'source' | 'destination',
accessLevel: StorageAccessLevel
) => {
const targetIdentityId = 'targetIdentityId';
const bucket = 'bucket';
const finalAccessLevel = accessLevel == 'guest' ? 'public' : accessLevel;
let finalKey = KeyType == 'source' ? `${bucket}/` : '';
finalKey += `${finalAccessLevel}/`;
Expand Down
159 changes: 94 additions & 65 deletions packages/storage/__tests__/providers/s3/apis/getProperties.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import { headObject } from '../../../../src/providers/s3/utils/client';
import { getProperties } from '../../../../src/providers/s3';
import { Credentials } from '@aws-sdk/types';
import { Amplify } from '@aws-amplify/core';
import { StorageOptions } from '../../../../src/types';

jest.mock('../../../../src/providers/s3/utils/client');
jest.mock('@aws-amplify/core', () => ({
fetchAuthSession: jest.fn(),
Amplify: {
getConfig: jest.fn(),
Auth: {
Expand All @@ -28,87 +28,116 @@ const credentials: Credentials = {
secretAccessKey: 'secretAccessKey',
};
const targetIdentityId = 'targetIdentityId';
const identityId = 'identityId';

describe('getProperties test', () => {
beforeEach(() => {
jest.clearAllMocks();
});
mockFetchAuthSession.mockResolvedValue({
credentials,
identityId: targetIdentityId,
});
mockGetConfig.mockReturnValue({
Storage: {
S3: {
bucket,
region,
},
},
});
it('getProperties happy path case with private check', async () => {
expect.assertions(3);
mockHeadObject.mockReturnValueOnce({
ContentLength: '100',
ContentType: 'text/plain',
ETag: 'etag',
LastModified: 'last-modified',
Metadata: { key: 'value' },
VersionId: 'version-id',
describe('getProperties api', () => {
beforeAll(() => {
mockFetchAuthSession.mockResolvedValue({
credentials,
identityId,
});
const metadata = { key: 'value' };
expect(
await getProperties({
key: 'key',
options: {
targetIdentityId: 'targetIdentityId',
accessLevel: 'protected',
mockGetConfig.mockReturnValue({
Storage: {
S3: {
bucket,
region,
},
})
).toEqual({
},
});
});
describe('getProperties happy path ', () => {
const expected = {
key: 'key',
size: '100',
contentType: 'text/plain',
eTag: 'etag',
metadata,
metadata: { key: 'value' },
lastModified: 'last-modified',
versionId: 'version-id',
};
const config = {
credentials,
region: 'region',
};
const key = 'key';
beforeEach(() => {
mockHeadObject.mockReturnValueOnce({
ContentLength: '100',
ContentType: 'text/plain',
ETag: 'etag',
LastModified: 'last-modified',
Metadata: { key: 'value' },
VersionId: 'version-id',
});
});
afterEach(() => {
jest.clearAllMocks();
});
expect(headObject).toBeCalledTimes(1);
expect(headObject).toHaveBeenCalledWith(
it.each([
{
options: { accessLevel: 'guest' },
expectedKey: 'public/key',
},
{
credentials,
region: 'region',
options: { accessLevel: 'protected', targetIdentityId },
expectedKey: 'protected/targetIdentityId/key',
},
{
Bucket: 'bucket',
Key: 'protected/targetIdentityId/key',
options: { accessLevel: 'protected' },
expectedKey: 'protected/identityId/key',
},
{
options: { accessLevel: 'private' },
expectedKey: 'private/identityId/key',
},
])(
'getProperties api with $options.accessLevel',
async ({ options, expectedKey }) => {
const headObjectOptions = {
Bucket: 'bucket',
Key: expectedKey,
};
expect.assertions(3);
expect(
await getProperties({
key,
options: options as StorageOptions,
})
).toEqual(expected);
expect(headObject).toBeCalledTimes(1);
expect(headObject).toHaveBeenCalledWith(config, headObjectOptions);
}
);
});

it('getProperties should return a not found error', async () => {
mockHeadObject.mockRejectedValueOnce(
Object.assign(new Error(), {
$metadata: { httpStatusCode: 404 },
name: 'NotFound',
})
);
try {
await getProperties({ key: 'keyed' });
} catch (error) {
expect.assertions(3);
expect(headObject).toBeCalledTimes(1);
expect(headObject).toHaveBeenCalledWith(
{
credentials,
region: 'region',
},
{
Bucket: 'bucket',
Key: 'public/keyed',
}
describe('getProperties error path', () => {
afterEach(() => {
jest.clearAllMocks();
});
it('getProperties should return a not found error', async () => {
mockHeadObject.mockRejectedValueOnce(
Object.assign(new Error(), {
$metadata: { httpStatusCode: 404 },
name: 'NotFound',
})
);
expect(error.$metadata.httpStatusCode).toBe(404);
}
try {
await getProperties({ key: 'keyed' });
} catch (error) {
expect.assertions(3);
expect(headObject).toBeCalledTimes(1);
expect(headObject).toHaveBeenCalledWith(
{
credentials,
region: 'region',
},
{
Bucket: 'bucket',
Key: 'public/keyed',
}
);
expect(error.$metadata.httpStatusCode).toBe(404);
}
});
});
});
143 changes: 94 additions & 49 deletions packages/storage/__tests__/providers/s3/apis/getUrl.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ import {
getPresignedGetObjectUrl,
headObject,
} from '../../../../src/providers/s3/utils/client';
import { StorageOptions } from '../../../../src/types';

jest.mock('../../../../src/providers/s3/utils/client');
jest.mock('@aws-amplify/core', () => ({
fetchAuthSession: jest.fn(),
Amplify: {
getConfig: jest.fn(),
Auth: {
Expand All @@ -30,60 +30,105 @@ const credentials: Credentials = {
secretAccessKey: 'secretAccessKey',
};
const targetIdentityId = 'targetIdentityId';
const identityId = 'identityId';

describe('getProperties test', () => {
beforeEach(() => {
jest.clearAllMocks();
});
mockFetchAuthSession.mockResolvedValue({
credentials,
identityId: targetIdentityId,
});
mockGetConfig.mockReturnValue({
Storage: {
S3: {
bucket,
region,
describe('getUrl test', () => {
beforeAll(() => {
mockFetchAuthSession.mockResolvedValue({
credentials,
identityId,
});
mockGetConfig.mockReturnValue({
Storage: {
S3: {
bucket,
region,
},
},
},
});
it('get presigned url happy case', async () => {
expect.assertions(2);
(headObject as jest.Mock).mockImplementation(() => {
return {
Key: 'key',
ContentLength: '100',
ContentType: 'text/plain',
ETag: 'etag',
LastModified: 'last-modified',
Metadata: { key: 'value' },
};
});
(getPresignedGetObjectUrl as jest.Mock).mockReturnValueOnce({
url: new URL('https://google.com'),
});
describe('getUrl happy path', () => {
const config = {
credentials,
region: 'region',
};
const key = 'key';
beforeEach(() => {
(headObject as jest.Mock).mockImplementation(() => {
return {
Key: 'key',
ContentLength: '100',
ContentType: 'text/plain',
ETag: 'etag',
LastModified: 'last-modified',
Metadata: { key: 'value' },
};
});
(getPresignedGetObjectUrl as jest.Mock).mockReturnValueOnce({
url: new URL('https://google.com'),
});
});
const result = await getUrl({ key: 'key' });
expect(getPresignedGetObjectUrl).toBeCalledTimes(1);
expect(result.url).toEqual({
url: new URL('https://google.com'),
afterEach(() => {
jest.clearAllMocks();
});
});
test('Should return not found error when the object is not found', async () => {
(headObject as jest.Mock).mockImplementation(() =>
Object.assign(new Error(), {
$metadata: { httpStatusCode: 404 },
name: 'NotFound',
})
);
try {
await getUrl({
key: 'invalid_key',
options: { validateObjectExistence: true },
it.each([
{
options: { accessLevel: 'guest' },
expectedKey: 'public/key',
},
{
options: { accessLevel: 'protected', targetIdentityId },
expectedKey: 'protected/targetIdentityId/key',
},
{
options: { accessLevel: 'protected' },
expectedKey: 'protected/identityId/key',
},
{
options: { accessLevel: 'private' },
expectedKey: 'private/identityId/key',
},
])('getUrl with $options.accessLevel', async ({ options, expectedKey }) => {
const headObjectOptions = {
Bucket: 'bucket',
Key: expectedKey,
};
const optionsVal = { ...options, validateObjectExistence: true };

expect.assertions(4);
const result = await getUrl({
key,
options: optionsVal as StorageOptions,
});
} catch (error) {
expect.assertions(2);
expect(getPresignedGetObjectUrl).toBeCalledTimes(1);
expect(headObject).toBeCalledTimes(1);
expect(error.$metadata?.httpStatusCode).toBe(404);
}
expect(headObject).toHaveBeenCalledWith(config, headObjectOptions);
expect(result.url).toEqual({
url: new URL('https://google.com'),
});
});
});
describe('getUrl error path', () => {
afterAll(() => {
jest.clearAllMocks();
});
it('Should return not found error when the object is not found', async () => {
(headObject as jest.Mock).mockImplementation(() =>
Object.assign(new Error(), {
$metadata: { httpStatusCode: 404 },
name: 'NotFound',
})
);
try {
await getUrl({
key: 'invalid_key',
options: { validateObjectExistence: true },
});
} catch (error) {
expect.assertions(2);
expect(headObject).toBeCalledTimes(1);
expect(error.$metadata?.httpStatusCode).toBe(404);
}
});
});
});
1 change: 0 additions & 1 deletion packages/storage/__tests__/providers/s3/apis/list.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { list } from '../../../../src/providers/s3/apis';

jest.mock('../../../../src/providers/s3/utils/client');
jest.mock('@aws-amplify/core', () => ({
fetchAuthSession: jest.fn(),
Amplify: {
getConfig: jest.fn(),
Auth: {
Expand Down
Loading