Skip to content

Commit

Permalink
MLPAB-2225: Enforce check and send when making LPA changes after CP h…
Browse files Browse the repository at this point in the history
…as been contacted (#1369)
  • Loading branch information
acsauk authored Jul 25, 2024
1 parent 1341ef5 commit 2bc832c
Show file tree
Hide file tree
Showing 11 changed files with 139 additions and 27 deletions.
81 changes: 77 additions & 4 deletions cypress/e2e/donor/check-your-lpa.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ describe('Check the LPA', () => {
it('content is tailored for paper CPs, a details component is shown and nav redirects to payment', () => {
cy.visit('/fixtures?redirect=/check-your-lpa&progress=addCorrespondent&certificateProvider=paper');

cy.url().should('contain', '/check-your-lpa');
cy.get('label[for=f-checked-and-happy]').contains('I’ve checked this LPA and I’m happy to show it to my certificate provider, Charlie Cooper')
cy.get('details').contains('What happens if I need to make changes later?')

Expand All @@ -84,8 +85,18 @@ describe('Check the LPA', () => {

describe('on subsequent check when LPA has not been paid for', () => {
it('content is tailored for paper CPs, a warning component is shown and nav redirects to payment', () => {
cy.visit('/fixtures?redirect=/check-your-lpa&progress=checkAndSendToYourCertificateProvider&certificateProvider=paper');
cy.visit('/fixtures?redirect=/task-list&progress=checkAndSendToYourCertificateProvider&certificateProvider=paper');

cy.contains('li', 'Add a correspondent').should('contain', 'Completed').click();

cy.url().should('contain', '/add-correspondent');
cy.contains('label', 'No').click();
cy.contains('button', 'Save and continue').click();

cy.url().should('contain', '/task-list');
cy.contains('li', 'Check and send to your certificate provider').should('contain', 'In progress').click();

cy.url().should('contain', '/check-your-lpa');
cy.get('label[for=f-checked-and-happy]').contains('I’ve checked this LPA and I’m happy to show it to my certificate provider, Charlie Cooper')
cy.get('.govuk-warning-text').contains('Once you select the confirm button, your certificate provider will be sent a text telling them you have changed your LPA.')

Expand All @@ -104,8 +115,18 @@ describe('Check the LPA', () => {

describe('on subsequent check when LPA has been paid for', () => {
it('content is tailored for paper CPs, a warning component is shown and nav redirects to dashboard', () => {
cy.visit('/fixtures?redirect=/check-your-lpa&progress=payForTheLpa&certificateProvider=paper');
cy.visit('/fixtures?redirect=/task-list&progress=payForTheLpa&certificateProvider=paper');

cy.contains('li', 'Add a correspondent').should('contain', 'Completed').click();

cy.url().should('contain', '/add-correspondent');
cy.contains('label', 'No').click();
cy.contains('button', 'Save and continue').click();

cy.url().should('contain', '/task-list');
cy.contains('li', 'Check and send to your certificate provider').should('contain', 'In progress').click();

cy.url().should('contain', '/check-your-lpa');
cy.get('label[for=f-checked-and-happy]').contains('I’ve checked this LPA and I’m happy to show it to my certificate provider, Charlie Cooper')
cy.get('.govuk-warning-text').contains('Once you select the confirm button, your certificate provider will be sent a text telling them you have changed your LPA.')

Expand All @@ -128,6 +149,7 @@ describe('Check the LPA', () => {
it('content is tailored for online CPs, a details component is shown and nav redirects to payment', () => {
cy.visit('/fixtures?redirect=/check-your-lpa&progress=addCorrespondent');

cy.url().should('contain', '/check-your-lpa');
cy.get('label[for=f-checked-and-happy]').contains('I’ve checked this LPA and I’m happy for OPG to share it with my certificate provider, Charlie Cooper')
cy.get('details').contains('What happens if I need to make changes later?')

Expand All @@ -146,8 +168,18 @@ describe('Check the LPA', () => {

describe('on subsequent check when LPA has not been paid for', () => {
it('content is tailored for online CPs, a warning component is shown and nav redirects to payment', () => {
cy.visit('/fixtures?redirect=/check-your-lpa&progress=checkAndSendToYourCertificateProvider');
cy.visit('/fixtures?redirect=/task-list&progress=checkAndSendToYourCertificateProvider');

cy.contains('li', 'Add a correspondent').should('contain', 'Completed').click();

cy.url().should('contain', '/add-correspondent');
cy.contains('label', 'No').click();
cy.contains('button', 'Save and continue').click();

cy.url().should('contain', '/task-list');
cy.contains('li', 'Check and send to your certificate provider').should('contain', 'In progress').click();

cy.url().should('contain', '/check-your-lpa');
cy.get('label[for=f-checked-and-happy]').contains('I’ve checked this LPA and I’m happy for OPG to share it with my certificate provider, Charlie Cooper')
cy.get('.govuk-warning-text').contains('Once you select the confirm button, your certificate provider will be sent a text telling them you have changed your LPA.')

Expand All @@ -166,8 +198,18 @@ describe('Check the LPA', () => {

describe('on subsequent check when LPA has been paid for', () => {
it('content is tailored for online CPs, a warning component is shown and nav redirects to dashboard', () => {
cy.visit('/fixtures?redirect=/check-your-lpa&progress=payForTheLpa');
cy.visit('/fixtures?redirect=/task-list&progress=payForTheLpa');

cy.contains('li', 'Add a correspondent').should('contain', 'Completed').click();

cy.url().should('contain', '/add-correspondent');
cy.contains('label', 'No').click();
cy.contains('button', 'Save and continue').click();

cy.url().should('contain', '/task-list');
cy.contains('li', 'Check and send to your certificate provider').should('contain', 'In progress').click();

cy.url().should('contain', '/check-your-lpa');
cy.get('label[for=f-checked-and-happy]').contains('I’ve checked this LPA and I’m happy for OPG to share it with my certificate provider, Charlie Cooper')
cy.get('.govuk-warning-text').contains('Once you select the confirm button, your certificate provider will be sent a text telling them you have changed your LPA.')

Expand All @@ -185,6 +227,37 @@ describe('Check the LPA', () => {
})
})

it("must check and send again when making LPA changes after certificate provider is contacted", () => {
cy.visit('/fixtures?redirect=/task-list&progress=checkAndSendToYourCertificateProvider');

cy.url().should('contain', '/task-list');

cy.contains('li', 'Check and send to your certificate provider').should('contain', 'Completed');
cy.contains('li', 'Pay for the LPA').should('contain', 'Not started');
cy.contains('li', 'Add a correspondent').should('contain', 'Completed').click();

cy.url().should('contain', '/add-correspondent');
cy.contains('label', 'No').click();
cy.contains('button', 'Save and continue').click();

cy.url().should('contain', '/task-list');

cy.contains('li', 'Pay for the LPA').should('contain', 'Cannot start yet');
cy.contains('li', 'Check and send to your certificate provider').should('contain', 'In progress').click();

cy.get('#f-checked-and-happy').check({ force: true })
cy.contains('button', 'Confirm').click();

cy.url().should('contain', '/lpa-details-saved');

cy.contains('a', 'Continue').click();

cy.url().should('contain', '/task-list');

cy.contains('li', 'Check and send to your certificate provider').should('contain', 'Completed');
cy.contains('li', 'Pay for the LPA').should('contain', 'Not started');
})

it("errors when not selected", () => {
cy.visit('/fixtures?redirect=/check-your-lpa&progress=addCorrespondent');
cy.contains('button', 'Confirm').click();
Expand Down
6 changes: 5 additions & 1 deletion internal/actor/donor_provided.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ func (c toCheck) HashInclude(field string, _ any) (bool, error) {
// checked.
switch field {
case "CheckedAt",
"CreatedAt",
"Tasks",
"PaymentDetails",
"DonorIdentityUserData",
Expand All @@ -193,7 +194,10 @@ func (c toCheck) HashInclude(field string, _ any) (bool, error) {
"FeeType",
"EvidenceDelivery",
"PreviousApplicationNumber",
"PreviousFee":
"PreviousFee",
"RegisteringWithCourtOfProtection",
"WantVoucher",
"Voucher":
return false, nil
}

Expand Down
4 changes: 2 additions & 2 deletions internal/actor/donor_provided_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,13 +91,13 @@ func TestGenerateCheckedHash(t *testing.T) {
}

// DO change this value to match the updates
const modified uint64 = 0x4af298e82cc36153
const modified uint64 = 0x2a104a01bcc31f64

// DO NOT change these initial hash values. If a field has been added/removed
// you will need to handle the version gracefully by modifying
// toCheck.HashInclude and adding another testcase for the new version.
testcases := map[uint8]uint64{
0: 0x49f8cef460cf416e,
0: 0x52d72543cced8895,
}

for version, initial := range testcases {
Expand Down
11 changes: 8 additions & 3 deletions internal/app/donor_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ func (s *donorStore) GetAny(ctx context.Context) (*actor.DonorProvidedDetails, e
}

if data.LpaID == "" {
return nil, errors.New("donorStore.Get requires LpaID")
return nil, errors.New("donorStore.GetAny requires LpaID")
}

var sk dynamo.SK = dynamo.DonorKey("")
Expand Down Expand Up @@ -222,7 +222,7 @@ func (s *donorStore) Latest(ctx context.Context) (*actor.DonorProvidedDetails, e
}

if data.SessionID == "" {
return nil, errors.New("donorStore.Get requires SessionID")
return nil, errors.New("donorStore.Latest requires SessionID")
}

var donor *actor.DonorProvidedDetails
Expand Down Expand Up @@ -264,6 +264,11 @@ func (s *donorStore) Put(ctx context.Context, donor *actor.DonorProvidedDetails)
return nil
}

// Enforces donor to send notifications to certificate provider when LPA data has changed
if donor.CheckedHashChanged() && donor.Tasks.CheckYourLpa.Completed() {
donor.Tasks.CheckYourLpa = actor.TaskInProgress
}

if err := donor.UpdateHash(); err != nil {
return err
}
Expand Down Expand Up @@ -313,7 +318,7 @@ func (s *donorStore) Delete(ctx context.Context) error {
}

if data.SessionID == "" || data.LpaID == "" {
return errors.New("donorStore.Create requires SessionID and LpaID")
return errors.New("donorStore.Delete requires SessionID and LpaID")
}

keys, err := s.dynamoClient.AllKeysByPK(ctx, dynamo.LpaKey(data.LpaID))
Expand Down
15 changes: 15 additions & 0 deletions internal/app/donor_store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,21 @@ func TestDonorStorePutWhenNoChange(t *testing.T) {
assert.Nil(t, err)
}

func TestDonorStorePutWhenCheckChangeAndCheckCompleted(t *testing.T) {
saved := &actor.DonorProvidedDetails{PK: dynamo.LpaKey("5"), Hash: 5, CheckedHash: 5, SK: dynamo.LpaOwnerKey(dynamo.DonorKey("an-id")), LpaID: "5", HasSentApplicationUpdatedEvent: true, Donor: actor.Donor{FirstNames: "a", LastName: "b"}, Tasks: actor.DonorTasks{CheckYourLpa: actor.TaskInProgress}}
_ = saved.UpdateHash()

dynamoClient := newMockDynamoClient(t)
dynamoClient.EXPECT().
Put(ctx, saved).
Return(nil)

donorStore := &donorStore{dynamoClient: dynamoClient, now: testNowFn}

err := donorStore.Put(ctx, &actor.DonorProvidedDetails{PK: dynamo.LpaKey("5"), Hash: 5, CheckedHash: 5, SK: dynamo.LpaOwnerKey(dynamo.DonorKey("an-id")), LpaID: "5", HasSentApplicationUpdatedEvent: true, Donor: actor.Donor{FirstNames: "a", LastName: "b"}, Tasks: actor.DonorTasks{CheckYourLpa: actor.TaskCompleted}})
assert.Nil(t, err)
}

func TestDonorStorePutWhenError(t *testing.T) {
dynamoClient := newMockDynamoClient(t)
dynamoClient.EXPECT().Put(ctx, mock.Anything).Return(expectedError)
Expand Down
20 changes: 10 additions & 10 deletions internal/page/donor/check_your_lpa.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ import (
)

type checkYourLpaData struct {
App page.AppData
Errors validation.List
Donor *actor.DonorProvidedDetails
Form *checkYourLpaForm
Completed bool
CanContinue bool
App page.AppData
Errors validation.List
Donor *actor.DonorProvidedDetails
Form *checkYourLpaForm
CertificateProviderContacted bool
CanContinue bool
}

type checkYourLpaNotifier struct {
Expand Down Expand Up @@ -113,8 +113,8 @@ func CheckYourLpa(tmpl template.Template, donorStore DonorStore, shareCodeSender
Form: &checkYourLpaForm{
CheckedAndHappy: !donor.CheckedAt.IsZero(),
},
Completed: donor.Tasks.CheckYourLpa.Completed(),
CanContinue: donor.CheckedHashChanged(),
CertificateProviderContacted: !donor.CheckedAt.IsZero(),
CanContinue: donor.CheckedHashChanged(),
}

if r.Method == http.MethodPost && data.CanContinue {
Expand All @@ -128,15 +128,15 @@ func CheckYourLpa(tmpl template.Template, donorStore DonorStore, shareCodeSender
return err
}

if err := notifier.Notify(r.Context(), appData, donor, data.Completed); err != nil {
if err := notifier.Notify(r.Context(), appData, donor, data.CertificateProviderContacted); err != nil {
return err
}

if err := donorStore.Put(r.Context(), donor); err != nil {
return err
}

if !data.Completed {
if !data.CertificateProviderContacted {
return page.Paths.LpaDetailsSaved.RedirectQuery(w, r, appData, donor, url.Values{"firstCheck": {"1"}})
}

Expand Down
3 changes: 2 additions & 1 deletion internal/page/donor/check_your_lpa_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ func TestGetCheckYourLpaFromStore(t *testing.T) {
Form: &checkYourLpaForm{
CheckedAndHappy: true,
},
CertificateProviderContacted: true,
}).
Return(nil)

Expand Down Expand Up @@ -89,7 +90,7 @@ func TestPostCheckYourLpaWhenNotChanged(t *testing.T) {
Form: &checkYourLpaForm{
CheckedAndHappy: true,
},
Completed: true,
CertificateProviderContacted: true,
}).
Return(nil)

Expand Down
3 changes: 3 additions & 0 deletions internal/page/donor/one_login_identity_details.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ func OneLoginIdentityDetails(tmpl template.Template, donorStore DonorStore) Hand
donor.Donor.LastName = donor.DonorIdentityUserData.LastName
donor.Donor.DateOfBirth = donor.DonorIdentityUserData.DateOfBirth
donor.Donor.Address = donor.DonorIdentityUserData.CurrentAddress
if err := donor.UpdateCheckedHash(); err != nil {
return err
}

if err := donorStore.Put(r.Context(), donor); err != nil {
return err
Expand Down
12 changes: 8 additions & 4 deletions internal/page/donor/one_login_identity_details_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,16 @@ func TestPostOneLoginIdentityDetailsWhenYes(t *testing.T) {
existingDob := date.New("1", "2", "3")
identityDob := date.New("4", "5", "6")

updated := &actor.DonorProvidedDetails{
LpaID: "lpa-id",
Donor: actor.Donor{FirstNames: "b", LastName: "b", DateOfBirth: identityDob, Address: place.Address{Line1: "a"}},
DonorIdentityUserData: identity.UserData{FirstNames: "b", LastName: "b", DateOfBirth: identityDob, CurrentAddress: place.Address{Line1: "a"}},
}
updated.UpdateCheckedHash()

donorStore := newMockDonorStore(t)
donorStore.EXPECT().
Put(r.Context(), &actor.DonorProvidedDetails{
LpaID: "lpa-id",
Donor: actor.Donor{FirstNames: "b", LastName: "b", DateOfBirth: identityDob, Address: place.Address{Line1: "a"}},
DonorIdentityUserData: identity.UserData{FirstNames: "b", LastName: "b", DateOfBirth: identityDob, CurrentAddress: place.Address{Line1: "a"}}}).
Put(r.Context(), updated).
Return(nil)

err := OneLoginIdentityDetails(nil, donorStore)(testAppData, w, r, &actor.DonorProvidedDetails{
Expand Down
9 changes: 8 additions & 1 deletion internal/page/fixtures/donor.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ func Donor(

donorSessionID := base64.StdEncoding.EncodeToString([]byte(data.DonorSub))

if err := sessionStore.SetLogin(r, w, &sesh.LoginSession{Sub: data.DonorSub, Email: testEmail}); err != nil {
if err := sessionStore.SetLogin(r, w, &sesh.LoginSession{Sub: data.DonorSub, Email: data.DonorEmail}); err != nil {
return err
}

Expand All @@ -126,9 +126,16 @@ func Donor(

donorCtx := page.ContextWithSessionData(r.Context(), &page.SessionData{SessionID: donorSessionID, LpaID: donorDetails.LpaID})

if data.Progress >= slices.Index(progressValues, "checkAndSendToYourCertificateProvider") {
if err = donorDetails.UpdateCheckedHash(); err != nil {
return fmt.Errorf("problem updating checkedHash: %w", err)
}
}

if err := donorStore.Put(donorCtx, donorDetails); err != nil {
return err
}

if !donorDetails.SignedAt.IsZero() && donorDetails.LpaUID != "" {
if err := lpaStoreClient.SendLpa(donorCtx, donorDetails); err != nil {
return err
Expand Down
2 changes: 1 addition & 1 deletion web/template/donor/check_your_lpa.gohtml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
</div>
</div>

{{ if .Completed }}
{{ if .CertificateProviderContacted }}
{{ template "warning" (content .App "onceYouClickCertificateProviderWillBeSentText") }}
{{ else }}
{{ template "details" (details . "whatHappensIfIChange" "whatHappensIfIChangeDetails" false) }}
Expand Down

0 comments on commit 2bc832c

Please sign in to comment.