Skip to content

Commit

Permalink
feat(api): signUp delivers message using auto verified attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
jagregory committed Nov 27, 2021
1 parent d49aa80 commit 64280e8
Show file tree
Hide file tree
Showing 2 changed files with 341 additions and 73 deletions.
304 changes: 256 additions & 48 deletions src/targets/signUp.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { ClockFake } from "../__tests__/clockFake";
import { newMockCognitoService } from "../__tests__/mockCognitoService";
import { MockLogger } from "../__tests__/mockLogger";
import { newMockMessageDelivery } from "../__tests__/mockMessageDelivery";
import { newMockMessages } from "../__tests__/mockMessages";
import { newMockUserPoolService } from "../__tests__/mockUserPoolService";
import { UUID } from "../__tests__/patterns";
import * as TDB from "../__tests__/testDataBuilder";
import { UsernameExistsError } from "../errors";
import { InvalidParameterError, UsernameExistsError } from "../errors";
import { MessageDelivery, Messages, UserPoolService } from "../services";
import { SignUp, SignUpTarget } from "./signUp";

Expand All @@ -28,16 +27,13 @@ describe("SignUp target", () => {
emailSubject: "Mock message",
});
mockOtp = jest.fn();
signUp = SignUp(
{
cognito: newMockCognitoService(mockUserPoolService),
clock: new ClockFake(now),
messageDelivery: mockMessageDelivery,
messages: mockMessages,
otp: mockOtp,
},
MockLogger
);
signUp = SignUp({
cognito: newMockCognitoService(mockUserPoolService),
clock: new ClockFake(now),
messageDelivery: mockMessageDelivery,
messages: mockMessages,
otp: mockOtp,
});
});

it("throws if user already exists", async () => {
Expand Down Expand Up @@ -82,45 +78,257 @@ describe("SignUp target", () => {
});
});

it("sends a confirmation code to the user's email address", async () => {
mockUserPoolService.getUserByUsername.mockResolvedValue(null);
mockOtp.mockReturnValue("1234");
describe("messages", () => {
describe("UserPool.AutoVerifiedAttributes=default", () => {
beforeEach(() => {
mockUserPoolService.config.AutoVerifiedAttributes = undefined;
});

await signUp({
ClientId: "clientId",
Password: "pwd",
Username: "user-supplied",
UserAttributes: [{ Name: "email", Value: "[email protected]" }],
it.todo("does not send a confirmation code");
});

const createdUser = {
Attributes: [
{ Name: "sub", Value: expect.stringMatching(UUID) },
{ Name: "email", Value: "[email protected]" },
],
Enabled: true,
Password: "pwd",
UserCreateDate: now,
UserLastModifiedDate: now,
UserStatus: "UNCONFIRMED",
Username: "user-supplied",
};

expect(mockMessages.signUp).toHaveBeenCalledWith(
"clientId",
"test",
createdUser,
"1234"
);
expect(mockMessageDelivery.deliver).toHaveBeenCalledWith(
createdUser,
{
AttributeName: "email",
DeliveryMedium: "EMAIL",
Destination: "[email protected]",
},
{ emailSubject: "Mock message" }
);
describe("UserPool.AutoVerifiedAttributes=email", () => {
beforeEach(() => {
mockUserPoolService.config.AutoVerifiedAttributes = ["email"];
});

it("sends a confirmation code to the user's email address", async () => {
mockUserPoolService.getUserByUsername.mockResolvedValue(null);
mockOtp.mockReturnValue("1234");

await signUp({
ClientId: "clientId",
Password: "pwd",
Username: "user-supplied",
UserAttributes: [{ Name: "email", Value: "[email protected]" }],
});

const createdUser = {
Attributes: [
{ Name: "sub", Value: expect.stringMatching(UUID) },
{ Name: "email", Value: "[email protected]" },
],
Enabled: true,
Password: "pwd",
UserCreateDate: now,
UserLastModifiedDate: now,
UserStatus: "UNCONFIRMED",
Username: "user-supplied",
};

expect(mockMessages.signUp).toHaveBeenCalledWith(
"clientId",
"test",
createdUser,
"1234"
);
expect(mockMessageDelivery.deliver).toHaveBeenCalledWith(
createdUser,
{
AttributeName: "email",
DeliveryMedium: "EMAIL",
Destination: "[email protected]",
},
{ emailSubject: "Mock message" }
);
});

it("fails if user doesn't have an email", async () => {
await expect(
signUp({
ClientId: "clientId",
Password: "pwd",
Username: "user-supplied",
UserAttributes: [],
})
).rejects.toEqual(
new InvalidParameterError(
"User has no attribute matching desired auto verified attributes"
)
);

expect(mockMessages.signUp).not.toHaveBeenCalled();
expect(mockMessageDelivery.deliver).not.toHaveBeenCalled();
});
});

describe("UserPool.AutoVerifiedAttributes=phone_number", () => {
beforeEach(() => {
mockUserPoolService.config.AutoVerifiedAttributes = ["phone_number"];
});

it("sends a confirmation code to the user's phone number", async () => {
mockUserPoolService.getUserByUsername.mockResolvedValue(null);
mockOtp.mockReturnValue("1234");

await signUp({
ClientId: "clientId",
Password: "pwd",
Username: "user-supplied",
UserAttributes: [{ Name: "phone_number", Value: "0400000000" }],
});

const createdUser = {
Attributes: [
{ Name: "sub", Value: expect.stringMatching(UUID) },
{ Name: "phone_number", Value: "0400000000" },
],
Enabled: true,
Password: "pwd",
UserCreateDate: now,
UserLastModifiedDate: now,
UserStatus: "UNCONFIRMED",
Username: "user-supplied",
};

expect(mockMessages.signUp).toHaveBeenCalledWith(
"clientId",
"test",
createdUser,
"1234"
);
expect(mockMessageDelivery.deliver).toHaveBeenCalledWith(
createdUser,
{
AttributeName: "phone_number",
DeliveryMedium: "SMS",
Destination: "0400000000",
},
{ emailSubject: "Mock message" }
);
});

it("fails if user doesn't have a phone_number", async () => {
await expect(
signUp({
ClientId: "clientId",
Password: "pwd",
Username: "user-supplied",
UserAttributes: [],
})
).rejects.toEqual(
new InvalidParameterError(
"User has no attribute matching desired auto verified attributes"
)
);

expect(mockMessages.signUp).not.toHaveBeenCalled();
expect(mockMessageDelivery.deliver).not.toHaveBeenCalled();
});
});

describe("UserPool.AutoVerifiedAttributes=phone_number and email", () => {
beforeEach(() => {
mockUserPoolService.config.AutoVerifiedAttributes = [
"email",
"phone_number",
];
});

it("sends a confirmation code to the user's phone number if they have both attributes", async () => {
mockUserPoolService.getUserByUsername.mockResolvedValue(null);
mockOtp.mockReturnValue("1234");

await signUp({
ClientId: "clientId",
Password: "pwd",
Username: "user-supplied",
UserAttributes: [
{ Name: "email", Value: "[email protected]" },
{ Name: "phone_number", Value: "0400000000" },
],
});

const createdUser = {
Attributes: [
{ Name: "sub", Value: expect.stringMatching(UUID) },
{ Name: "email", Value: "[email protected]" },
{ Name: "phone_number", Value: "0400000000" },
],
Enabled: true,
Password: "pwd",
UserCreateDate: now,
UserLastModifiedDate: now,
UserStatus: "UNCONFIRMED",
Username: "user-supplied",
};

expect(mockMessages.signUp).toHaveBeenCalledWith(
"clientId",
"test",
createdUser,
"1234"
);
expect(mockMessageDelivery.deliver).toHaveBeenCalledWith(
createdUser,
{
AttributeName: "phone_number",
DeliveryMedium: "SMS",
Destination: "0400000000",
},
{ emailSubject: "Mock message" }
);
});

it("sends a confirmation code to the user's email if they only have an email", async () => {
mockUserPoolService.getUserByUsername.mockResolvedValue(null);
mockOtp.mockReturnValue("1234");

await signUp({
ClientId: "clientId",
Password: "pwd",
Username: "user-supplied",
UserAttributes: [{ Name: "email", Value: "[email protected]" }],
});

const createdUser = {
Attributes: [
{ Name: "sub", Value: expect.stringMatching(UUID) },
{ Name: "email", Value: "[email protected]" },
],
Enabled: true,
Password: "pwd",
UserCreateDate: now,
UserLastModifiedDate: now,
UserStatus: "UNCONFIRMED",
Username: "user-supplied",
};

expect(mockMessages.signUp).toHaveBeenCalledWith(
"clientId",
"test",
createdUser,
"1234"
);
expect(mockMessageDelivery.deliver).toHaveBeenCalledWith(
createdUser,
{
AttributeName: "email",
DeliveryMedium: "EMAIL",
Destination: "[email protected]",
},
{ emailSubject: "Mock message" }
);
});

it("fails if user doesn't have a phone_number or an email", async () => {
await expect(
signUp({
ClientId: "clientId",
Password: "pwd",
Username: "user-supplied",
UserAttributes: [],
})
).rejects.toEqual(
new InvalidParameterError(
"User has no attribute matching desired auto verified attributes"
)
);

expect(mockMessages.signUp).not.toHaveBeenCalled();
expect(mockMessageDelivery.deliver).not.toHaveBeenCalled();
});
});
});

it("saves the confirmation code on the user for comparison when confirming", async () => {
Expand Down
Loading

0 comments on commit 64280e8

Please sign in to comment.