Skip to content

Commit

Permalink
Update content on progress tracker
Browse files Browse the repository at this point in the history
  • Loading branch information
hawx committed Oct 9, 2023
1 parent a6ccef8 commit d5bbb04
Show file tree
Hide file tree
Showing 33 changed files with 1,043 additions and 405 deletions.
4 changes: 2 additions & 2 deletions cypress/e2e/donor/application-reason.cy.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
describe('Application reason', () => {
it('can be submitted', () => {
cy.visit('/testing-start?redirect=/application-reason&lpa.yourDetails=1');
cy.visit('/fixtures?redirect=/application-reason&progress=provideYourDetails');
cy.checkA11yApp();

cy.contains('label', 'noneOfTheAbove').click();
Expand All @@ -10,7 +10,7 @@ describe('Application reason', () => {
});

it('errors when unselected', () => {
cy.visit('/testing-start?redirect=/application-reason');
cy.visit('/fixtures?redirect=/application-reason&progress=provideYourDetails');

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

Expand Down
2 changes: 1 addition & 1 deletion cypress/e2e/donor/certificate-provider.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {

describe('Certificate provider task', () => {
beforeEach(() => {
cy.visit('/testing-start?redirect=/task-list&lpa.yourDetails=1&lpa.attorneys=1');
cy.visit('/fixtures?redirect=/task-list&progress=chooseYourAttorneys');
});

it('can be a professional', () => {
Expand Down
41 changes: 19 additions & 22 deletions cypress/e2e/donor/lpa-progress.cy.js
Original file line number Diff line number Diff line change
@@ -1,40 +1,37 @@
describe('LPA progress', () => {
it('when nothing completed', () => {
cy.visit('/testing-start?redirect=/progress');

cy.checkA11yApp();

cy.contains('li', 'LPA signed In progress');
cy.contains('li', 'Certificate provider has made their declaration Not started');
cy.contains('li', 'Attorneys have made their declaration Not started');
cy.contains('li', 'LPA submitted to the OPG Not started');
cy.contains('li', 'Statutory waiting period Not started');
cy.contains('li', 'LPA registered Not started');
cy.contains('li', 'You’ve signed your LPA In progress');
cy.contains('li', 'Your certificate provider has provided their certificate Not started');
cy.contains('li', 'Your attorneys have signed your LPA Not started');
cy.contains('li', 'We have received your LPA Not started');
cy.contains('li', 'Your 4-week waiting period has started Not started');
cy.contains('li', 'Your LPA has been registered Not started');
})

it('when LPA submitted', () => {
cy.visit('/testing-start?redirect=/progress&lpa.complete=1');

cy.checkA11yApp();

cy.contains('li', 'LPA signed Completed');
cy.contains('li', 'Certificate provider has made their declaration In progress');
cy.contains('li', 'Attorneys have made their declaration Not started');
cy.contains('li', 'LPA submitted to the OPG Not started');
cy.contains('li', 'Statutory waiting period Not started');
cy.contains('li', 'LPA registered Not started');
cy.contains('li', 'You’ve signed your LPA Completed');
cy.contains('li', 'Charlie Cooper has provided their certificate In progress');
cy.contains('li', 'Your attorneys have signed your LPA Not started');
cy.contains('li', 'We have received your LPA Not started');
cy.contains('li', 'Your 4-week waiting period has started Not started');
cy.contains('li', 'Your LPA has been registered Not started');
})

it('when certificate provided', () => {
cy.visit('/testing-start?redirect=/progress&lpa.complete=1&asCertificateProvider=certified&asDonor=1');

cy.visit('/fixtures?redirect=/progress&progress=signedByCertificateProvider');
cy.checkA11yApp();

cy.contains('li', 'LPA signed Completed');
cy.contains('li', 'Certificate provider has made their declaration Completed');
cy.contains('li', 'Attorneys have made their declaration In progress');
cy.contains('li', 'LPA submitted to the OPG Not started');
cy.contains('li', 'Statutory waiting period Not started');
cy.contains('li', 'LPA registered Not started');
cy.contains('li', 'You’ve signed your LPA Completed');
cy.contains('li', 'Charlie Cooper has provided their certificate Completed');
cy.contains('li', 'Your attorneys have signed your LPA In progress');
cy.contains('li', 'We have received your LPA Not started');
cy.contains('li', 'Your 4-week waiting period has started Not started');
cy.contains('li', 'Your LPA has been registered Not started');
})
});
12 changes: 8 additions & 4 deletions internal/actor/attorney_provided.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,23 @@ type AttorneyProvidedDetails struct {
Tasks AttorneyTasks
}

func (d AttorneyProvidedDetails) Signed() bool {
func (d AttorneyProvidedDetails) Signed(after time.Time) bool {
if after.IsZero() {
return false
}

if d.IsTrustCorporation {
switch d.WouldLikeSecondSignatory {
case form.Yes:
return !d.AuthorisedSignatories[0].Confirmed.IsZero() && !d.AuthorisedSignatories[1].Confirmed.IsZero()
return d.AuthorisedSignatories[0].Confirmed.After(after) && d.AuthorisedSignatories[1].Confirmed.After(after)
case form.No:
return !d.AuthorisedSignatories[0].Confirmed.IsZero()
return d.AuthorisedSignatories[0].Confirmed.After(after)
default:
return false
}
}

return !d.Confirmed.IsZero()
return d.Confirmed.After(after)
}

type AttorneyTasks struct {
Expand Down
51 changes: 42 additions & 9 deletions internal/actor/attorney_provided_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,37 +9,70 @@ import (
)

func TestAttorneyProvidedDetailsSigned(t *testing.T) {
certificateProviderSignedAt := time.Now()
signedAfter := certificateProviderSignedAt.Add(time.Second)

testcases := map[string]struct {
details AttorneyProvidedDetails
signed bool
}{
"unsigned": {},
"signed": {
details: AttorneyProvidedDetails{Confirmed: time.Now()},
details: AttorneyProvidedDetails{Confirmed: signedAfter},
signed: true,
},
"signed before": {
details: AttorneyProvidedDetails{Confirmed: certificateProviderSignedAt},
},
"trust corporation unsigned": {
details: AttorneyProvidedDetails{Confirmed: time.Now(), IsTrustCorporation: true},
details: AttorneyProvidedDetails{Confirmed: signedAfter, IsTrustCorporation: true},
},
"trust corporation single signatory": {
details: AttorneyProvidedDetails{IsTrustCorporation: true, WouldLikeSecondSignatory: form.No, AuthorisedSignatories: [2]TrustCorporationSignatory{{Confirmed: time.Now()}, {}}},
signed: true,
details: AttorneyProvidedDetails{
IsTrustCorporation: true,
WouldLikeSecondSignatory: form.No,
AuthorisedSignatories: [2]TrustCorporationSignatory{{Confirmed: signedAfter}, {}},
},
signed: true,
},
"trust corporation signle signatory unsigned": {
details: AttorneyProvidedDetails{IsTrustCorporation: true, WouldLikeSecondSignatory: form.No, AuthorisedSignatories: [2]TrustCorporationSignatory{{}, {}}},
details: AttorneyProvidedDetails{
IsTrustCorporation: true,
WouldLikeSecondSignatory: form.No,
AuthorisedSignatories: [2]TrustCorporationSignatory{{}, {}},
},
},
"trust corporation double signatory": {
details: AttorneyProvidedDetails{IsTrustCorporation: true, WouldLikeSecondSignatory: form.Yes, AuthorisedSignatories: [2]TrustCorporationSignatory{{Confirmed: time.Now()}, {Confirmed: time.Now()}}},
signed: true,
details: AttorneyProvidedDetails{
IsTrustCorporation: true,
WouldLikeSecondSignatory: form.Yes,
AuthorisedSignatories: [2]TrustCorporationSignatory{{Confirmed: signedAfter}, {Confirmed: signedAfter}},
},
signed: true,
},
"trust corporation double signatory unsigned": {
details: AttorneyProvidedDetails{IsTrustCorporation: true, WouldLikeSecondSignatory: form.Yes, AuthorisedSignatories: [2]TrustCorporationSignatory{{Confirmed: time.Now()}, {}}},
details: AttorneyProvidedDetails{
IsTrustCorporation: true,
WouldLikeSecondSignatory: form.Yes,
AuthorisedSignatories: [2]TrustCorporationSignatory{{Confirmed: signedAfter}, {}},
},
},
"trust corporation double signatory signed before": {
details: AttorneyProvidedDetails{
IsTrustCorporation: true,
WouldLikeSecondSignatory: form.Yes,
AuthorisedSignatories: [2]TrustCorporationSignatory{{Confirmed: certificateProviderSignedAt}, {Confirmed: signedAfter}},
},
},
}

for name, tc := range testcases {
t.Run(name, func(t *testing.T) {
assert.Equal(t, tc.signed, tc.details.Signed())
assert.Equal(t, tc.signed, tc.details.Signed(certificateProviderSignedAt))
})
}
}

func TestAttorneyProvidedDetailsSignedWhenPreviousActorNotSigned(t *testing.T) {
assert.False(t, AttorneyProvidedDetails{Confirmed: time.Now()}.Signed(time.Time{}))
}
4 changes: 4 additions & 0 deletions internal/actor/certificate_provider_provided.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ type CertificateProviderProvidedDetails struct {
Tasks CertificateProviderTasks
}

func (c CertificateProviderProvidedDetails) Signed(after time.Time) bool {
return c.Certificate.Agreed.After(after)
}

func (c *CertificateProviderProvidedDetails) CertificateProviderIdentityConfirmed(firstNames, lastName string) bool {
return c.IdentityUserData.OK && c.IdentityUserData.Provider != identity.UnknownOption &&
c.IdentityUserData.MatchName(firstNames, lastName) &&
Expand Down
10 changes: 10 additions & 0 deletions internal/actor/certificate_provider_provided_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package actor

import (
"testing"
"time"

"github.com/ministryofjustice/opg-modernising-lpa/internal/identity"
"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -54,3 +55,12 @@ func TestCertificateProviderProvidedIdentityConfirmed(t *testing.T) {
})
}
}

func TestCertificateProviderProvidedSigned(t *testing.T) {
now := time.Now()
assert := assert.New(t)

assert.False(CertificateProviderProvidedDetails{}.Signed(now))
assert.False(CertificateProviderProvidedDetails{Certificate: Certificate{Agreed: now}}.Signed(now))
assert.True(CertificateProviderProvidedDetails{Certificate: Certificate{Agreed: now.Add(time.Second)}}.Signed(now))
}
4 changes: 3 additions & 1 deletion internal/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ type Logger interface {
type DynamoClient interface {
One(ctx context.Context, pk, sk string, v interface{}) error
OneByPartialSk(ctx context.Context, pk, partialSk string, v interface{}) error
AllByPartialSk(ctx context.Context, pk, partialSk string, v interface{}) error
LatestForActor(ctx context.Context, sk string, v interface{}) error
AllForActor(ctx context.Context, sk string, v interface{}) error
AllByKeys(ctx context.Context, pks []dynamo.Key) ([]map[string]types.AttributeValue, error)
Expand Down Expand Up @@ -109,7 +110,7 @@ func App(
handleRoot(paths.SignOut, None,
page.SignOut(logger, sessionStore, oneLoginClient, appPublicURL))
handleRoot(paths.Fixtures, None,
fixtures.Donor(tmpls.Get("fixtures.gohtml")))
fixtures.Donor(tmpls.Get("fixtures.gohtml"), sessionStore, donorStore, certificateProviderStore, attorneyStore))
handleRoot(paths.CertificateProviderFixtures, None,
fixtures.CertificateProvider(tmpls.Get("certificate_provider_fixtures.gohtml"), sessionStore, shareCodeSender, donorStore, certificateProviderStore))
handleRoot(paths.AttorneyFixtures, None,
Expand Down Expand Up @@ -171,6 +172,7 @@ func App(
errorHandler,
notFoundHandler,
certificateProviderStore,
attorneyStore,
notifyClient,
evidenceReceivedStore,
s3Client,
Expand Down
16 changes: 16 additions & 0 deletions internal/app/attorney_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,22 @@ func (s *attorneyStore) Get(ctx context.Context) (*actor.AttorneyProvidedDetails
return &attorney, err
}

func (s *attorneyStore) GetAny(ctx context.Context) ([]*actor.AttorneyProvidedDetails, error) {
data, err := page.SessionDataFromContext(ctx)
if err != nil {
return nil, err
}

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

var attorneys []*actor.AttorneyProvidedDetails
err = s.dynamoClient.AllByPartialSk(ctx, lpaKey(data.LpaID), "#ATTORNEY#", &attorneys)

return attorneys, err
}

func (s *attorneyStore) Put(ctx context.Context, attorney *actor.AttorneyProvidedDetails) error {
attorney.UpdatedAt = s.now()
return s.dynamoClient.Put(ctx, attorney)
Expand Down
33 changes: 33 additions & 0 deletions internal/app/attorney_store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,39 @@ func TestAttorneyStoreGetOnError(t *testing.T) {
assert.Equal(t, expectedError, err)
}

func TestAttorneyStoreGetAny(t *testing.T) {
ctx := page.ContextWithSessionData(context.Background(), &page.SessionData{LpaID: "123"})

dynamoClient := newMockDynamoClient(t)
dynamoClient.
ExpectAllByPartialSk(ctx, "LPA#123", "#ATTORNEY#",
[]*actor.AttorneyProvidedDetails{{LpaID: "123"}}, nil)

attorneyStore := &attorneyStore{dynamoClient: dynamoClient}

attorney, err := attorneyStore.GetAny(ctx)
assert.Nil(t, err)
assert.Equal(t, []*actor.AttorneyProvidedDetails{{LpaID: "123"}}, attorney)
}

func TestAttorneyStoreGetAnyWhenSessionMissing(t *testing.T) {
ctx := context.Background()

attorneyStore := &attorneyStore{}

_, err := attorneyStore.GetAny(ctx)
assert.Equal(t, page.SessionMissingError{}, err)
}

func TestAttorneyStoreGetAnyMissingLpaIDInSessionData(t *testing.T) {
ctx := page.ContextWithSessionData(context.Background(), &page.SessionData{})

attorneyStore := &attorneyStore{}

_, err := attorneyStore.GetAny(ctx)
assert.Equal(t, errors.New("attorneyStore.GetAny requires LpaID"), err)
}

func TestAttorneyStorePut(t *testing.T) {
ctx := context.Background()
now := time.Now()
Expand Down
10 changes: 10 additions & 0 deletions internal/app/donor_store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,16 @@ func (m *mockDynamoClient) ExpectOneByPartialSk(ctx, pk, partialSk, data interfa
})
}

func (m *mockDynamoClient) ExpectAllByPartialSk(ctx, pk, partialSk, data interface{}, err error) {
m.
On("AllByPartialSk", ctx, pk, partialSk, mock.Anything).
Return(func(ctx context.Context, pk, partialSk string, v interface{}) error {
b, _ := json.Marshal(data)
json.Unmarshal(b, v)
return err
})
}

func (m *mockDynamoClient) ExpectAllForActor(ctx, sk, data interface{}, err error) {
m.
On("AllForActor", ctx, sk, mock.Anything).
Expand Down
14 changes: 14 additions & 0 deletions internal/app/mock_DynamoClient_test.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions internal/dynamo/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,23 @@ func (c *Client) OneByPartialSk(ctx context.Context, pk, partialSk string, v int
return attributevalue.UnmarshalMap(response.Items[0], v)
}

func (c *Client) AllByPartialSk(ctx context.Context, pk, partialSk string, v interface{}) error {
response, err := c.svc.Query(ctx, &dynamodb.QueryInput{
TableName: aws.String(c.table),
ExpressionAttributeNames: map[string]string{"#PK": "PK", "#SK": "SK"},
ExpressionAttributeValues: map[string]types.AttributeValue{
":PK": &types.AttributeValueMemberS{Value: pk},
":SK": &types.AttributeValueMemberS{Value: partialSk},
},
KeyConditionExpression: aws.String("#PK = :PK and begins_with(#SK, :SK)"),
})
if err != nil {
return err
}

return attributevalue.UnmarshalListOfMaps(response.Items, v)
}

func (c *Client) Put(ctx context.Context, v interface{}) error {
item, err := attributevalue.MarshalMap(v)
if err != nil {
Expand Down
Loading

0 comments on commit d5bbb04

Please sign in to comment.