-
Notifications
You must be signed in to change notification settings - Fork 5
Feat/update practitioner email #877
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
Merged
isabeleliassen
merged 21 commits into
csg-org:development
from
InspiringApps:feat/update-practitioner-email
Jul 8, 2025
Merged
Changes from all commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
3dde8a1
Add optional email fields to provider record
landonshumway-ia 0004751
Add email endpoints with api models
landonshumway-ia e97a509
Implement logic to verify and change practitioner emails
landonshumway-ia 4852c55
Add email templates to notification service
landonshumway-ia 68fca56
sync API model to latest provider detail api response
landonshumway-ia 5168fcf
PR feedback - use secrets module for code generation
landonshumway-ia 8d34511
Add smoke test for email update flow
landonshumway-ia e0fc024
Improve formatting of verification code email
landonshumway-ia 4e0a3d9
Improve formatting of email messages for verification
landonshumway-ia 88228a7
linter/format
landonshumway-ia 4fa1a06
Update API spec to latest
landonshumway-ia 42eb7d9
rename smoke test file
landonshumway-ia 59de4a8
update postman collection
landonshumway-ia 4b862b1
Add missing NPDB categories
landonshumway-ia cc72962
PR feedback
landonshumway-ia 483a015
Update registration to check new live field
landonshumway-ia c30f1f7
Use new insertBody method to center text
landonshumway-ia 3a1cf9d
rollback cognito if dynamo fails to update user record
landonshumway-ia cfd47ff
PR feedback - combine node tests into one
landonshumway-ia be0c68f
PR feedback - add check in smoke test for invalid code
landonshumway-ia 9c4998a
PR feedback - add wrapper for cognito call
landonshumway-ia File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
8,102 changes: 4,310 additions & 3,792 deletions
8,102
backend/compact-connect/docs/api-specification/latest-oas30.json
Large diffs are not rendered by default.
Oops, something went wrong.
954 changes: 609 additions & 345 deletions
954
backend/compact-connect/docs/postman/postman-collection.json
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1174,4 +1174,147 @@ describe('EmailNotificationServiceLambda', () => { | |
.toThrow('Missing required jurisdiction field for privilegeEncumbranceLiftingStateNotification template.'); | ||
}); | ||
}); | ||
|
||
describe('Provider Email Verification Code', () => { | ||
const SAMPLE_PROVIDER_EMAIL_VERIFICATION_CODE_EVENT: EmailNotificationEvent = { | ||
template: 'providerEmailVerificationCode', | ||
recipientType: 'SPECIFIC', | ||
compact: 'aslp', | ||
specificEmails: ['[email protected]'], | ||
templateVariables: { | ||
verificationCode: '1234' | ||
} | ||
}; | ||
|
||
it('should successfully send provider email verification code email', async () => { | ||
const response = await lambda.handler(SAMPLE_PROVIDER_EMAIL_VERIFICATION_CODE_EVENT, {} as any); | ||
|
||
expect(response).toEqual({ | ||
message: 'Email message sent' | ||
}); | ||
|
||
// Verify email was sent | ||
expect(mockSESClient).toHaveReceivedCommandWith(SendEmailCommand, { | ||
Destination: { | ||
ToAddresses: ['[email protected]'] | ||
}, | ||
Message: { | ||
Body: { | ||
Html: { | ||
Charset: 'UTF-8', | ||
Data: expect.any(String) | ||
} | ||
}, | ||
Subject: { | ||
Charset: 'UTF-8', | ||
Data: 'Verify Your New Email Address - Compact Connect' | ||
} | ||
}, | ||
Source: 'Compact Connect <[email protected]>' | ||
}); | ||
|
||
// Get the actual HTML content for detailed validation | ||
const emailCall = mockSESClient.commandCalls(SendEmailCommand)[0]; | ||
const htmlContent = emailCall.args[0].input.Message?.Body?.Html?.Data; | ||
|
||
expect(htmlContent).toBeDefined(); | ||
expect(htmlContent).toContain('Please use the following verification code to complete your email address change'); | ||
expect(htmlContent).toContain('<h2>1234</h2>'); | ||
expect(htmlContent).toContain('This code will expire in 15 minutes'); | ||
expect(htmlContent).toContain('If you did not request this email change, please contact support immediately'); | ||
expect(htmlContent).toContain('Email Update Verification'); | ||
}); | ||
|
||
it('should throw error when no recipients found', async () => { | ||
const eventWithNoRecipients: EmailNotificationEvent = { | ||
...SAMPLE_PROVIDER_EMAIL_VERIFICATION_CODE_EVENT, | ||
specificEmails: [] | ||
}; | ||
|
||
await expect(lambda.handler(eventWithNoRecipients, {} as any)) | ||
.rejects | ||
.toThrow('No recipients found for provider email verification code email'); | ||
}); | ||
|
||
it('should throw error when verification code is missing', async () => { | ||
const eventWithMissingCode: EmailNotificationEvent = { | ||
...SAMPLE_PROVIDER_EMAIL_VERIFICATION_CODE_EVENT, | ||
templateVariables: {} | ||
}; | ||
|
||
await expect(lambda.handler(eventWithMissingCode, {} as any)) | ||
.rejects | ||
.toThrow('Missing required template variables for providerEmailVerificationCode template'); | ||
}); | ||
}); | ||
|
||
describe('Provider Email Change Notification', () => { | ||
const SAMPLE_PROVIDER_EMAIL_CHANGE_NOTIFICATION_EVENT: EmailNotificationEvent = { | ||
template: 'providerEmailChangeNotification', | ||
recipientType: 'SPECIFIC', | ||
compact: 'aslp', | ||
specificEmails: ['[email protected]'], | ||
templateVariables: { | ||
newEmailAddress: '[email protected]' | ||
} | ||
}; | ||
|
||
it('should successfully send provider email change notification email', async () => { | ||
const response = await lambda.handler(SAMPLE_PROVIDER_EMAIL_CHANGE_NOTIFICATION_EVENT, {} as any); | ||
|
||
expect(response).toEqual({ | ||
message: 'Email message sent' | ||
}); | ||
|
||
// Verify email was sent with correct parameters | ||
expect(mockSESClient).toHaveReceivedCommandWith(SendEmailCommand, { | ||
Destination: { | ||
ToAddresses: ['[email protected]'] | ||
}, | ||
Message: { | ||
Body: { | ||
Html: { | ||
Charset: 'UTF-8', | ||
Data: expect.any(String) | ||
} | ||
}, | ||
Subject: { | ||
Charset: 'UTF-8', | ||
Data: 'Email Address Changed - Compact Connect' | ||
} | ||
}, | ||
Source: 'Compact Connect <[email protected]>' | ||
}); | ||
|
||
// Get the actual HTML content for detailed validation | ||
const emailCall = mockSESClient.commandCalls(SendEmailCommand)[0]; | ||
const htmlContent = emailCall.args[0].input.Message?.Body?.Html?.Data; | ||
|
||
expect(htmlContent).toBeDefined(); | ||
expect(htmlContent).toContain('This is to notify you that your Compact Connect account email address has been changed to the following:'); | ||
expect(htmlContent).toContain('[email protected]'); | ||
}); | ||
|
||
it('should throw error when no recipients found', async () => { | ||
const eventWithNoRecipients: EmailNotificationEvent = { | ||
...SAMPLE_PROVIDER_EMAIL_CHANGE_NOTIFICATION_EVENT, | ||
specificEmails: [] | ||
}; | ||
|
||
await expect(lambda.handler(eventWithNoRecipients, {} as any)) | ||
.rejects | ||
.toThrow('No recipients found for provider email change notification email'); | ||
}); | ||
|
||
it('should throw error when new email address is missing', async () => { | ||
const eventWithMissingEmail: EmailNotificationEvent = { | ||
...SAMPLE_PROVIDER_EMAIL_CHANGE_NOTIFICATION_EVENT, | ||
templateVariables: {} | ||
}; | ||
|
||
await expect(lambda.handler(eventWithMissingEmail, {} as any)) | ||
.rejects | ||
.toThrow('Missing required template variables for providerEmailChangeNotification template'); | ||
}); | ||
}); | ||
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -698,4 +698,88 @@ describe('EmailNotificationService', () => { | |
)).rejects.toThrow('No recipients found'); | ||
}); | ||
}); | ||
|
||
describe('Provider Email Verification Code', () => { | ||
it('should send email verification code with all expected content', async () => { | ||
const verificationCode = '1234'; | ||
|
||
await emailService.sendProviderEmailVerificationCode( | ||
'aslp', | ||
'[email protected]', | ||
verificationCode | ||
); | ||
|
||
// Check overall email structure and each content piece | ||
// Verify email was sent | ||
expect(mockSESClient).toHaveReceivedCommandWith(SendEmailCommand, { | ||
Destination: { | ||
ToAddresses: ['[email protected]'] | ||
}, | ||
Message: { | ||
Body: { | ||
Html: { | ||
Charset: 'UTF-8', | ||
Data: expect.any(String) | ||
} | ||
}, | ||
Subject: { | ||
Charset: 'UTF-8', | ||
Data: 'Verify Your New Email Address - Compact Connect' | ||
} | ||
}, | ||
Source: 'Compact Connect <[email protected]>' | ||
}); | ||
|
||
// Get the actual HTML content for detailed validation | ||
const emailCall = mockSESClient.commandCalls(SendEmailCommand)[0]; | ||
const htmlContent = emailCall.args[0].input.Message?.Body?.Html?.Data; | ||
|
||
expect(htmlContent).toBeDefined(); | ||
expect(htmlContent).toContain('Please use the following verification code to complete your email address change'); | ||
expect(htmlContent).toContain(`<h2>${verificationCode}</h2>`); | ||
expect(htmlContent).toContain('This code will expire in 15 minutes'); | ||
expect(htmlContent).toContain('If you did not request this email change, please contact support immediately'); | ||
expect(htmlContent).toContain('Email Update Verification'); | ||
}); | ||
}); | ||
|
||
describe('Provider Email Change Notification', () => { | ||
it('should send email change notification with all expected content', async () => { | ||
await emailService.sendProviderEmailChangeNotification( | ||
'aslp', | ||
'[email protected]', | ||
'[email protected]' | ||
); | ||
|
||
// Verify email was sent | ||
expect(mockSESClient).toHaveReceivedCommandWith(SendEmailCommand, { | ||
Destination: { | ||
ToAddresses: ['[email protected]'] | ||
}, | ||
Message: { | ||
Body: { | ||
Html: { | ||
Charset: 'UTF-8', | ||
Data: expect.any(String) | ||
} | ||
}, | ||
Subject: { | ||
Charset: 'UTF-8', | ||
Data: 'Email Address Changed - Compact Connect' | ||
} | ||
}, | ||
Source: 'Compact Connect <[email protected]>' | ||
}); | ||
|
||
// Get the actual HTML content for detailed validation | ||
const emailCall = mockSESClient.commandCalls(SendEmailCommand)[0]; | ||
const htmlContent = emailCall.args[0].input.Message?.Body?.Html?.Data; | ||
|
||
expect(htmlContent).toBeDefined(); | ||
expect(htmlContent).toContain('Please use the new email address to login to your account from now on.'); | ||
expect(htmlContent).toContain('If you did not make this change, please contact support immediately.'); | ||
expect(htmlContent).toContain('Email Address Changed'); | ||
expect(htmlContent).toContain('[email protected]'); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.