Skip to content

Commit

Permalink
release(required): Amplify JS release (#13862)
Browse files Browse the repository at this point in the history
  • Loading branch information
HuiSF authored Sep 30, 2024
2 parents 4dae76e + a0d1447 commit f2c8f5a
Show file tree
Hide file tree
Showing 16 changed files with 424 additions and 374 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

import { Identity, ResourcesConfig } from '@aws-amplify/core';

import { DefaultIdentityIdStore } from '../../../../src/providers/cognito/credentialsProvider/IdentityIdStore';

const mockKeyValueStorage = {
setItem: jest.fn(),
getItem: jest.fn(),
removeItem: jest.fn(),
clear: jest.fn(),
};

const validAuthConfig: ResourcesConfig = {
Auth: {
Cognito: {
userPoolId: 'us-east-1_test-id',
identityPoolId: 'us-east-1:test-id',
userPoolClientId: 'test-id',
allowGuestAccess: true,
},
},
};
const validAuthKey = {
identityId: `com.amplify.Cognito.${
validAuthConfig.Auth!.Cognito!.identityPoolId
}.identityId`,
};
const validGuestIdentityId: Identity = { type: 'guest', id: 'guest-id' };
const validPrimaryIdentityId: Identity = { type: 'primary', id: 'primary-id' };

const noIdentityPoolIdAuthConfig: ResourcesConfig = {
Auth: {
Cognito: {
userPoolId: 'us-east-1_test-id',
userPoolClientId: 'test-id',
},
},
};

describe('DefaultIdentityIdStore', () => {
const defaultIdStore = new DefaultIdentityIdStore(mockKeyValueStorage);
beforeAll(() => {
defaultIdStore.setAuthConfig(validAuthConfig.Auth!);
});

afterEach(() => {
mockKeyValueStorage.setItem.mockClear();
mockKeyValueStorage.getItem.mockClear();
mockKeyValueStorage.removeItem.mockClear();
mockKeyValueStorage.clear.mockClear();
});

it('should set the Auth config required to form the storage keys', async () => {
expect(defaultIdStore._authKeys).toEqual(validAuthKey);
});

it('should store guest identityId in keyValueStorage', async () => {
defaultIdStore.storeIdentityId(validGuestIdentityId);
expect(mockKeyValueStorage.setItem).toHaveBeenCalledWith(
validAuthKey.identityId,
validGuestIdentityId.id,
);
expect(defaultIdStore._primaryIdentityId).toBeUndefined();
expect(defaultIdStore._hasGuestIdentityId).toBe(true);
});

it('should load guest identityId from keyValueStorage', async () => {
mockKeyValueStorage.getItem.mockReturnValue(validGuestIdentityId.id);

expect(await defaultIdStore.loadIdentityId()).toEqual(validGuestIdentityId);
});

it('should store primary identityId in keyValueStorage', async () => {
defaultIdStore.storeIdentityId(validPrimaryIdentityId);
expect(mockKeyValueStorage.removeItem).toHaveBeenCalledWith(
validAuthKey.identityId,
);
expect(defaultIdStore._primaryIdentityId).toEqual(
validPrimaryIdentityId.id,
);
expect(defaultIdStore._hasGuestIdentityId).toBe(false);
});

it('should load primary identityId from keyValueStorage', async () => {
expect(await defaultIdStore.loadIdentityId()).toEqual(
validPrimaryIdentityId,
);
});

it('should clear the cached identityId', async () => {
defaultIdStore.clearIdentityId();
expect(mockKeyValueStorage.removeItem).toHaveBeenCalledWith(
validAuthKey.identityId,
);
expect(defaultIdStore._primaryIdentityId).toBeUndefined();
});

it('should throw when identityPoolId is not present while setting the auth config', async () => {
expect(() => {
defaultIdStore.setAuthConfig(noIdentityPoolIdAuthConfig.Auth!);
}).toThrow('Invalid identity pool id provided.');
});

it('should return null when the underlying keyValueStorage method returns null', async () => {
mockKeyValueStorage.getItem.mockReturnValue(null);
expect(await defaultIdStore.loadIdentityId()).toBeNull();
});

it('should return null when the underlying keyValueStorage method throws', async () => {
mockKeyValueStorage.getItem.mockRejectedValue(new Error('Error'));
expect(await defaultIdStore.loadIdentityId()).toBeNull();
});

it('should not call keyValueStorage.removeItem when there is no guest identityId to clear', async () => {
const refreshIdentityIdStore = new DefaultIdentityIdStore(
mockKeyValueStorage,
);
refreshIdentityIdStore.setAuthConfig(validAuthConfig.Auth!);

refreshIdentityIdStore.storeIdentityId(validPrimaryIdentityId);
expect(mockKeyValueStorage.removeItem).not.toHaveBeenCalled();
});
});
97 changes: 0 additions & 97 deletions packages/auth/__tests__/providers/cognito/identityIdStore.test.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ export class DefaultIdentityIdStore implements IdentityIdStore {
// Used as in-memory storage
_primaryIdentityId: string | undefined;
_authKeys: AuthKeys<string> = {};
_hasGuestIdentityId = false;

setAuthConfig(authConfigParam: AuthConfig) {
assertIdentityPoolIdConfig(authConfigParam.Cognito);
this.authConfig = authConfigParam;
Expand All @@ -48,7 +50,10 @@ export class DefaultIdentityIdStore implements IdentityIdStore {
const storedIdentityId = await this.keyValueStorage.getItem(
this._authKeys.identityId,
);

if (storedIdentityId) {
this._hasGuestIdentityId = true;

return {
id: storedIdentityId,
type: 'guest',
Expand All @@ -71,10 +76,14 @@ export class DefaultIdentityIdStore implements IdentityIdStore {
this.keyValueStorage.setItem(this._authKeys.identityId, identity.id);
// Clear in-memory storage of primary identityId
this._primaryIdentityId = undefined;
this._hasGuestIdentityId = true;
} else {
this._primaryIdentityId = identity.id;
// Clear locally stored guest id
this.keyValueStorage.removeItem(this._authKeys.identityId);
if (this._hasGuestIdentityId) {
this.keyValueStorage.removeItem(this._authKeys.identityId);
this._hasGuestIdentityId = false;
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class WebBrowserModule(
getCustomTabsPackageName(reactApplicationContext)?.let {
val customTabsIntent = CustomTabsIntent.Builder(connection?.getSession()).build()
customTabsIntent.intent.setPackage(it).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
customTabsIntent.intent.setPackage(it).addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
customTabsIntent.launchUrl(reactApplicationContext, Uri.parse(uriStr))
} ?: run {
promise.reject(Throwable("No eligible browser found on device"))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

import { byteLength } from '../../../../../src/providers/s3/apis/uploadData/byteLength';

describe('byteLength', () => {
it('returns 0 for null or undefined', () => {
expect(byteLength(undefined)).toBe(0);
expect(byteLength(null)).toBe(0);
});

it('calculates byte length correctly for ASCII strings', () => {
expect(byteLength('hello')).toBe(5);
});

it('calculates byte length correctly for multi-byte characters', () => {
expect(byteLength('èちは')).toBe(8);
});

it('handles Uint8Array correctly', () => {
const input = new Uint8Array([1, 2, 3]);
expect(byteLength(input)).toBe(3);
});

it('handles ArrayBuffer correctly', () => {
const buffer = new ArrayBuffer(8);
expect(byteLength(buffer)).toBe(8);
});

it('handles File object correctly', () => {
const file = new Blob(['hello']);
expect(byteLength(file)).toBe(5);
});

it('returns undefined for unsupported types', () => {
const input = { unsupportedType: true };
expect(byteLength(input)).toBeUndefined();
});
});
18 changes: 9 additions & 9 deletions packages/storage/__tests__/providers/s3/utils/md5.native.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,23 +69,23 @@ describe('calculateContentMd5 (native)', () => {
mockMd5.mockReset();
});

it('calculates MD5 for content type: string', async () => {
await calculateContentMd5(stringContent);
const [mockMd5Instance] = mockMd5.mock.instances;
expect(mockMd5Instance.update.mock.calls[0][0]).toBe(stringContent);
expect(mockToBase64).toHaveBeenCalled();
});

it.each([
{ type: 'string', content: stringContent },
{ type: 'ArrayBuffer view', content: new Uint8Array() },
{ type: 'ArrayBuffer', content: new ArrayBuffer(8) },
{ type: 'Blob', content: new Blob([stringContent]) },
])('calculates MD5 for content type: $type', async ({ content }) => {
await calculateContentMd5(content);
const [mockMd5Instance] = mockMd5.mock.instances;
expect(mockMd5Instance.update.mock.calls[0][0]).toBe(content);
expect(mockToBase64).toHaveBeenCalled();
});

it('calculates MD5 for content type: blob', async () => {
Object.defineProperty(global, 'FileReader', {
writable: true,
value: jest.fn(() => mockSuccessfulFileReader),
});
await calculateContentMd5(content);
await calculateContentMd5(new Blob([stringContent]));
const [mockMd5Instance] = mockMd5.mock.instances;
expect(mockMd5Instance.update.mock.calls[0][0]).toBe(fileReaderResult);
expect(mockSuccessfulFileReader.readAsArrayBuffer).toHaveBeenCalled();
Expand Down
18 changes: 9 additions & 9 deletions packages/storage/__tests__/providers/s3/utils/md5.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,23 +46,23 @@ describe('calculateContentMd5', () => {
mockMd5.mockReset();
});

it('calculates MD5 for content type: string', async () => {
await calculateContentMd5(stringContent);
const [mockMd5Instance] = mockMd5.mock.instances;
expect(mockMd5Instance.update.mock.calls[0][0]).toBe(stringContent);
expect(mockToBase64).toHaveBeenCalled();
});

it.each([
{ type: 'string', content: stringContent },
{ type: 'ArrayBuffer view', content: new Uint8Array() },
{ type: 'ArrayBuffer', content: new ArrayBuffer(8) },
{ type: 'Blob', content: new Blob([stringContent]) },
])('calculates MD5 for content type: $type', async ({ content }) => {
await calculateContentMd5(content);
const [mockMd5Instance] = mockMd5.mock.instances;
expect(mockMd5Instance.update.mock.calls[0][0]).toBe(content);
expect(mockToBase64).toHaveBeenCalled();
});

it('calculates MD5 for content type: blob', async () => {
Object.defineProperty(global, 'FileReader', {
writable: true,
value: jest.fn(() => mockSuccessfulFileReader),
});
await calculateContentMd5(content);
await calculateContentMd5(new Blob([stringContent]));
const [mockMd5Instance] = mockMd5.mock.instances;
expect(mockMd5Instance.update.mock.calls[0][0]).toBe(fileReaderResult);
expect(mockSuccessfulFileReader.readAsArrayBuffer).toHaveBeenCalled();
Expand Down
6 changes: 3 additions & 3 deletions packages/storage/src/providers/s3/apis/internal/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ import {
validateStorageOperationInputWithPrefix,
} from '../../utils';
import {
ListAllOptionsWithPath,
ListPaginateOptionsWithPath,
ListAllWithPathOptions,
ListPaginateWithPathOptions,
ResolvedS3Config,
} from '../../types/options';
import {
Expand Down Expand Up @@ -267,7 +267,7 @@ const mapCommonPrefixesToExcludedSubpaths = (
};

const getDelimiter = (
options?: ListAllOptionsWithPath | ListPaginateOptionsWithPath,
options?: ListAllWithPathOptions | ListPaginateWithPathOptions,
): string | undefined => {
if (options?.subpathStrategy?.strategy === 'exclude') {
return options?.subpathStrategy?.delimiter ?? DEFAULT_DELIMITER;
Expand Down
Loading

0 comments on commit f2c8f5a

Please sign in to comment.