Skip to content

Commit

Permalink
fix(auth): signUp should always return a userId (#13181)
Browse files Browse the repository at this point in the history
* fix(auth): signup should always return a userId

* add unit tests

* Update packages/auth/__tests__/providers/cognito/signUp.test.ts

Co-authored-by: Chris F <5827964+cshfang@users.noreply.github.com>

* address feedback

---------

Co-authored-by: Ashwin Kumar <ashwsrir@amazon.com>
Co-authored-by: Chris F <5827964+cshfang@users.noreply.github.com>
  • Loading branch information
3 people committed Mar 27, 2024
1 parent d4a48f1 commit 962179b
Show file tree
Hide file tree
Showing 2 changed files with 173 additions and 66 deletions.
237 changes: 171 additions & 66 deletions packages/auth/__tests__/providers/cognito/signUp.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ jest.mock(
'../../../src/providers/cognito/utils/clients/CognitoIdentityProvider',
);

const userId = '1234567890';

describe('signUp', () => {
const { user1 } = authAPITestParams;
// assert mocks
Expand All @@ -32,81 +34,184 @@ describe('signUp', () => {
setUpGetConfig(Amplify);
});

beforeEach(() => {
mockSignUp.mockResolvedValue(authAPITestParams.signUpHttpCallResult);
});
describe('Happy Path Cases:', () => {
beforeEach(() => {
mockSignUp.mockResolvedValue(authAPITestParams.signUpHttpCallResult);
});

afterEach(() => {
mockSignUp.mockReset();
});
afterEach(() => {
mockSignUp.mockReset();
});

it('should call SignUp service client with correct params', async () => {
await signUp({
username: user1.username,
password: user1.password,
options: {
userAttributes: { email: user1.email },
},
});
expect(mockSignUp).toHaveBeenCalledWith(
{
region: 'us-west-2',
userAgentValue: expect.any(String),
},
{
ClientMetadata: undefined,
Password: user1.password,
UserAttributes: [{ Name: 'email', Value: user1.email }],
Username: user1.username,
ValidationData: undefined,
ClientId: '111111-aaaaa-42d8-891d-ee81a1549398',
},
);
expect(mockSignUp).toHaveBeenCalledTimes(1);
});

it('should call signUp and return a result', async () => {
const result = await signUp({
username: user1.username,
password: user1.password,
options: {
userAttributes: { email: user1.email },
},
it('should return `CONFIRM_SIGN_UP` step when user isn`t confirmed yet', async () => {
const result = await signUp({
username: user1.username,
password: user1.password,
options: {
userAttributes: { email: user1.email },
},
});
expect(result).toEqual({
isSignUpComplete: false,
nextStep: {
signUpStep: 'CONFIRM_SIGN_UP',
codeDeliveryDetails: {
destination: user1.email,
deliveryMedium: 'EMAIL',
attributeName: 'email',
},
},
userId,
});
});
expect(result).toEqual({
isSignUpComplete: false,
nextStep: {
signUpStep: 'CONFIRM_SIGN_UP',
codeDeliveryDetails: {
destination: user1.email,
deliveryMedium: 'EMAIL',
attributeName: 'email',

it('should return `DONE` step when user is confirmed', async () => {
mockSignUp.mockResolvedValue({
UserConfirmed: true,
UserSub: userId,
});
const result = await signUp({
username: user1.username,
password: user1.password,
options: {
userAttributes: { email: user1.email },
},
});
expect(result).toEqual({
isSignUpComplete: true,
nextStep: {
signUpStep: 'DONE',
},
},
userId: '1234567890',
userId,
});
});
expect(mockSignUp).toHaveBeenCalledWith(
{
region: 'us-west-2',
userAgentValue: expect.any(String),
},
{
ClientMetadata: undefined,
Password: user1.password,
UserAttributes: [{ Name: 'email', Value: user1.email }],
Username: user1.username,
ValidationData: undefined,
ClientId: '111111-aaaaa-42d8-891d-ee81a1549398',
},
);
expect(mockSignUp).toHaveBeenCalledTimes(1);
});

it('should throw an error when username is empty', async () => {
expect.assertions(2);
try {
await signUp({ username: '', password: user1.password });
} catch (error: any) {
expect(error).toBeInstanceOf(AuthError);
expect(error.name).toBe(AuthValidationErrorCode.EmptySignUpUsername);
}
});
it('should return `COMPLETE_AUTO_SIGN_IN` step with `isSignUpComplete` false when autoSignIn is enabled and user isn`t confirmed yet', async () => {
// set up signUpVerificationMethod as link in auth config
(Amplify.getConfig as any).mockReturnValue({
Auth: {
Cognito: {
userPoolClientId: '111111-aaaaa-42d8-891d-ee81a1549398',
userPoolId: 'us-west-2_zzzzz',
identityPoolId: 'us-west-2:xxxxxx',
signUpVerificationMethod: 'link',
},
},
});

it('should throw an error when password is empty', async () => {
expect.assertions(2);
try {
await signUp({ username: user1.username, password: '' });
} catch (error: any) {
expect(error).toBeInstanceOf(AuthError);
expect(error.name).toBe(AuthValidationErrorCode.EmptySignUpPassword);
}
const result = await signUp({
username: user1.username,
password: user1.password,
options: {
userAttributes: { email: user1.email },
autoSignIn: true,
},
});

expect(result).toEqual({
isSignUpComplete: false,
nextStep: {
signUpStep: 'COMPLETE_AUTO_SIGN_IN',
codeDeliveryDetails: {
destination: user1.email,
deliveryMedium: 'EMAIL',
attributeName: 'email',
},
},
userId,
});
});

it('should return `COMPLETE_AUTO_SIGN_IN` step with `isSignUpComplete` true when autoSignIn is enabled and user is confirmed', async () => {
mockSignUp.mockResolvedValue({
UserConfirmed: true,
UserSub: userId,
});

const result = await signUp({
username: user1.username,
password: user1.password,
options: {
userAttributes: { email: user1.email },
autoSignIn: true,
},
});

expect(result).toEqual({
isSignUpComplete: true,
nextStep: {
signUpStep: 'COMPLETE_AUTO_SIGN_IN',
},
userId,
});
});
});

it('should throw an error when service returns an error response', async () => {
expect.assertions(2);
mockSignUp.mockImplementation(() => {
throw getMockError(SignUpException.InvalidParameterException);
describe('Error Path Cases:', () => {
beforeEach(() => {
mockSignUp.mockResolvedValue(authAPITestParams.signUpHttpCallResult);
});

afterEach(() => {
mockSignUp.mockReset();
});

it('should throw an error when username is empty', async () => {
expect.assertions(2);
try {
await signUp({ username: '', password: user1.password });
} catch (error: any) {
expect(error).toBeInstanceOf(AuthError);
expect(error.name).toBe(AuthValidationErrorCode.EmptySignUpUsername);
}
});

it('should throw an error when password is empty', async () => {
expect.assertions(2);
try {
await signUp({ username: user1.username, password: '' });
} catch (error: any) {
expect(error).toBeInstanceOf(AuthError);
expect(error.name).toBe(AuthValidationErrorCode.EmptySignUpPassword);
}
});

it('should throw an error when service returns an error response', async () => {
expect.assertions(2);
mockSignUp.mockImplementation(() => {
throw getMockError(SignUpException.InvalidParameterException);
});
try {
await signUp({ username: user1.username, password: user1.password });
} catch (error: any) {
expect(error).toBeInstanceOf(AuthError);
expect(error.name).toBe(SignUpException.InvalidParameterException);
}
});
try {
await signUp({ username: user1.username, password: user1.password });
} catch (error: any) {
expect(error).toBeInstanceOf(AuthError);
expect(error.name).toBe(SignUpException.InvalidParameterException);
}
});
});
2 changes: 2 additions & 0 deletions packages/auth/src/providers/cognito/apis/signUp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,15 @@ export async function signUp(input: SignUpInput): Promise<SignUpOutput> {
nextStep: {
signUpStep: 'COMPLETE_AUTO_SIGN_IN',
},
userId: UserSub,
};
} else if (isSignUpComplete(clientOutput) && !isAutoSignInStarted()) {
return {
isSignUpComplete: true,
nextStep: {
signUpStep: 'DONE',
},
userId: UserSub,
};
} else if (
!isSignUpComplete(clientOutput) &&
Expand Down

0 comments on commit 962179b

Please sign in to comment.