Skip to content

Commit

Permalink
Merge branch 'main' into feat/user-agent-enhancements/main
Browse files Browse the repository at this point in the history
  • Loading branch information
stocaaro authored Jun 14, 2023
2 parents c0cb9b9 + f47d472 commit 89a8f16
Show file tree
Hide file tree
Showing 7 changed files with 429 additions and 41 deletions.
175 changes: 163 additions & 12 deletions packages/storage/__tests__/Storage-unit-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
import axios, { CancelToken } from 'axios';

type CustomProviderConfig = {
provider: string;
foo: boolean;
bar: number;
};
Expand Down Expand Up @@ -64,12 +65,38 @@ class TestCustomProviderWithCopy
copy(
src: { key: string },
dest: { key: string },
config: CustomProviderConfig
config?: CustomProviderConfig
) {
return Promise.resolve({ newKey: 'copy' });
}
}

class TestCustomProviderWithGetProperties
extends TestCustomProvider
implements StorageProvider
{
getProperties(key: string, options?: CustomProviderConfig) {
return Promise.resolve({ newKey: 'getProperties' });
}
}

class TestCustomProviderWithOptionalAPI
extends TestCustomProvider
implements StorageProvider
{
copy(
src: { key: string },
dest: { key: string },
config?: CustomProviderConfig
) {
return Promise.resolve({ newKey: 'copy' });
}

getProperties(key: string, options?: CustomProviderConfig) {
return Promise.resolve({ newKey: 'getProperties' });
}
}

describe('Storage', () => {
describe('constructor test', () => {
test('happy case', () => {
Expand Down Expand Up @@ -614,6 +641,109 @@ describe('Storage', () => {
});
});

describe('getProperties test', () => {
let storage: StorageClass;
let provider: StorageProvider;
let getPropertiesSpy: jest.SpyInstance;

beforeEach(() => {
storage = new StorageClass();
provider = new AWSStorageProvider();
storage.addPluggable(provider);
storage.configure(options);
getPropertiesSpy = jest
.spyOn(AWSStorageProvider.prototype, 'getProperties')
.mockImplementation(() =>
Promise.resolve({
contentType: 'text/plain',
contentLength: 100,
eTag: 'etag',
lastModified: new Date('20 Oct 2023'),
metadata: { key: '' },
})
);
});

afterEach(() => {
jest.clearAllMocks();
});

describe('with default S3 provider', () => {
test('get properties of object successfully', async () => {
const result = await storage.getProperties('key');
expect(getPropertiesSpy).toBeCalled();
expect(result).toEqual({
contentType: 'text/plain',
contentLength: 100,
eTag: 'etag',
lastModified: new Date('20 Oct 2023'),
metadata: { key: '' },
});
getPropertiesSpy.mockClear();
});

test('get properties of object with available config', async () => {
await storage.getProperties('key', {
SSECustomerAlgorithm: 'aes256',
SSECustomerKey: 'key',
SSECustomerKeyMD5: 'md5',
});
});
});

test('get properties without provider', async () => {
const storage = new StorageClass();
try {
await storage.getProperties('key');
} catch (err) {
expect(err).toEqual(new Error('No plugin found with providerName'));
}
});

test('get properties with custom provider should work with no generic type provided', async () => {
const customProvider = new TestCustomProviderWithGetProperties();
const customProviderGetPropertiesSpy = jest.spyOn(
customProvider,
'getProperties'
);
storage.addPluggable(customProvider);
await storage.getProperties('key', {
provider: 'customProvider',
});
expect(customProviderGetPropertiesSpy).toBeCalled();
});

test('getProperties object with custom provider', async () => {
const customProvider = new TestCustomProviderWithGetProperties();
const customProviderGetPropertiesSpy = jest.spyOn(
customProvider,
'getProperties'
);
storage.addPluggable(customProvider);
await storage.getProperties<TestCustomProviderWithGetProperties>('key', {
foo: true,
bar: 1,
provider: 'customProvider',
});
expect(customProviderGetPropertiesSpy).toBeCalled();
});

test('getProperties object with optionalAPI custom provider', async () => {
const customProvider = new TestCustomProviderWithOptionalAPI();
const customProviderGetPropertiesSpy = jest.spyOn(
customProvider,
'getProperties'
);
storage.addPluggable(customProvider);
await storage.getProperties<TestCustomProviderWithOptionalAPI>('key', {
foo: true,
bar: 1,
provider: 'customProvider',
});
expect(customProviderGetPropertiesSpy).toBeCalled();
});
});

describe('put test', () => {
let storage: StorageClass;
let provider: StorageProvider;
Expand Down Expand Up @@ -935,24 +1065,44 @@ describe('Storage', () => {
const customProviderWithCopy = new TestCustomProviderWithCopy();
const customProviderCopySpy = jest.spyOn(customProviderWithCopy, 'copy');
storage.addPluggable(customProviderWithCopy);
const copyRes = await storage.copy<TestCustomProviderWithCopy>(
{ key: 'src' },
{ key: 'dest' },
{
provider: 'customProvider',
foo: false,
bar: 40,
}
);
const copyRes: { newKey: string } =
await storage.copy<TestCustomProviderWithCopy>(
{ key: 'src' },
{ key: 'dest' },
{
provider: 'customProvider',
foo: false,
bar: 40,
}
);
expect(customProviderCopySpy).toBeCalled();
expect(copyRes.newKey).toEqual('copy');
});
// backwards compatible with current custom provider user

test('copy object with optionalAPI custom provider', async () => {
const customProviderWithCopy = new TestCustomProviderWithOptionalAPI();
const customProviderCopySpy = jest.spyOn(customProviderWithCopy, 'copy');
storage.addPluggable(customProviderWithCopy);
const copyRes: { newKey: string } =
await storage.copy<TestCustomProviderWithOptionalAPI>(
{ key: 'src' },
{ key: 'dest' },
{
provider: 'customProvider',
foo: false,
bar: 40,
}
);
expect(customProviderCopySpy).toBeCalled();
expect(copyRes.newKey).toEqual('copy');
});

//backwards compatible with current custom provider user
test('copy object with custom provider should work with no generic type provided', async () => {
const customProviderWithCopy = new TestCustomProviderWithCopy();
const customProviderCopySpy = jest.spyOn(customProviderWithCopy, 'copy');
storage.addPluggable(customProviderWithCopy);
await storage.copy(
const copyRes: { newKey: string } = await storage.copy(
{ key: 'src' },
{ key: 'dest' },
{
Expand All @@ -963,6 +1113,7 @@ describe('Storage', () => {
}
);
expect(customProviderCopySpy).toBeCalled();
expect(copyRes.newKey).toEqual('copy');
});
});

Expand Down
72 changes: 67 additions & 5 deletions packages/storage/__tests__/providers/AWSS3Provider-unit-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
ListObjectsV2Command,
CreateMultipartUploadCommand,
UploadPartCommand,
HeadObjectCommand,
} from '@aws-sdk/client-s3';
import { S3RequestPresigner } from '@aws-sdk/s3-request-presigner';

Expand Down Expand Up @@ -52,6 +53,14 @@ S3Client.prototype.send = jest.fn(async command => {
Contents: [resultObj],
IsTruncated: false,
};
} else if (command instanceof HeadObjectCommand) {
return {
ContentLength: '100',
ContentType: 'text/plain',
ETag: 'etag',
LastModified: 'lastmodified',
Metadata: { key: 'value' },
};
}
return 'data';
});
Expand Down Expand Up @@ -519,6 +528,7 @@ describe('StorageProvider test', () => {
return Promise.resolve(credentials);
});
});

test('get existing object with validateObjectExistence option', async () => {
expect.assertions(5);
const options_with_validateObjectExistence = Object.assign(
Expand Down Expand Up @@ -556,11 +566,6 @@ describe('StorageProvider test', () => {

test('get non-existing object with validateObjectExistence option', async () => {
expect.assertions(2);
jest.spyOn(Credentials, 'get').mockImplementationOnce(() => {
return new Promise((res, rej) => {
res({});
});
});
const dispatchSpy = jest.spyOn(StorageUtils, 'dispatchStorageEvent');
jest
.spyOn(S3Client.prototype, 'send')
Expand All @@ -586,6 +591,63 @@ describe('StorageProvider test', () => {
});
});

describe('getProperties test', () => {
beforeEach(() => {
jest.spyOn(Credentials, 'get').mockImplementationOnce(() => {
return Promise.resolve(credentials);
});
});

test('getProperties successfully', async () => {
expect.assertions(4);
const spyon = jest.spyOn(S3Client.prototype, 'send');
const dispatchSpy = jest.spyOn(StorageUtils, 'dispatchStorageEvent');
const metadata = { key: 'value' };
expect(await storage.getProperties('key')).toEqual({
contentLength: '100',
contentType: 'text/plain',
eTag: 'etag',
lastModified: 'lastmodified',
metadata,
});
expect(dispatchSpy).toHaveBeenCalledTimes(1);
expect(dispatchSpy).toBeCalledWith(
false,
'getProperties',
{ method: 'getProperties', result: 'success' },
null,
'getProperties successful for key'
);
expect(spyon.mock.calls[0][0].input).toEqual({
Bucket: 'bucket',
Key: 'public/key',
});
spyon.mockClear();
});

test('get properties of non-existing object', async () => {
expect.assertions(2);
const dispatchSpy = jest.spyOn(StorageUtils, 'dispatchStorageEvent');
jest
.spyOn(S3Client.prototype, 'send')
.mockImplementationOnce(async params => {
throw { $metadata: { httpStatusCode: 404 }, name: 'NotFound' };
});
try {
await storage.getProperties('invalid_key');
} catch (error) {
expect(error.$metadata.httpStatusCode).toBe(404);
expect(dispatchSpy).toBeCalledWith(
false,
'getProperties',
{ method: 'getProperties', result: 'failed' },
null,
'invalid_key not found'
);
}
});
});

describe('put test', () => {
afterEach(() => {
jest.clearAllMocks();
Expand Down
Loading

0 comments on commit 89a8f16

Please sign in to comment.