Skip to content

Commit

Permalink
Merge d4feeb9 into 79b359a
Browse files Browse the repository at this point in the history
  • Loading branch information
acsauk authored Feb 22, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
2 parents 79b359a + d4feeb9 commit e9a84be
Showing 17 changed files with 291 additions and 230 deletions.
102 changes: 63 additions & 39 deletions cypress/e2e/supporter/edit-member.cy.js
Original file line number Diff line number Diff line change
@@ -1,60 +1,84 @@
describe('Edit member', () => {
beforeEach(() => {
cy.visit("/fixtures/supporter?organisation=1&redirect=/manage-organisation/manage-team-members&members=1");
describe('admin', () => {
beforeEach(() => {
cy.visit("/fixtures/supporter?organisation=1&redirect=/manage-organisation/manage-team-members&members=1");

cy.url().should('contain', "/manage-organisation/manage-team-members");
cy.contains('a', "Alice Moxom").click()
cy.url().should('contain', "/manage-organisation/manage-team-members");
cy.contains('a', "Alice Moxom").click()

cy.url().should('contain', "/manage-organisation/manage-team-members/edit-team-member");
});
cy.url().should('contain', "/manage-organisation/manage-team-members/edit-team-member");
});

it('can edit a team members name', () => {
cy.checkA11yApp();
it('can edit a team members name', () => {
cy.checkA11yApp();

cy.get('#f-first-names').clear().type('John');
cy.get('#f-last-name').clear().type('Doe');
cy.get('#f-first-names').clear().type('John');
cy.get('#f-last-name').clear().type('Doe');

cy.contains('button', "Save").click()
cy.contains('button', "Save").click()

cy.url().should('contain', "/manage-organisation/manage-team-members");
cy.url().should('contain', "/manage-organisation/manage-team-members");

cy.contains('Team member’s name updated to John Doe');
cy.contains('a', "John Doe")
})
cy.contains('Team member’s name updated to John Doe');
cy.contains('a', "John Doe")
})

it('can edit own name', () => {
// TODO update to a full test when admins can set their own names during org creation
cy.visit("/supporter/manage-organisation/manage-team-members?nameUpdated=John+Doe&selfUpdated=1");
it('can edit own name', () => {
// TODO update to a full test when admins can set their own names during org creation
cy.visit("/supporter/manage-organisation/manage-team-members?nameUpdated=John+Doe&selfUpdated=1");

cy.contains('Your name has been updated to John Doe');
})
cy.contains('Your name has been updated to John Doe');
})

it('errors when empty', () => {
cy.get('#f-first-names').clear();
cy.get('#f-last-name').clear();

cy.contains('button', "Save").click()

cy.checkA11yApp();

cy.get('.govuk-error-summary').within(() => {
cy.contains('Enter first names');
cy.contains('Enter last name');
});

it('errors when empty', () => {
cy.get('#f-first-names').clear();
cy.get('#f-last-name').clear();
cy.contains('[for=f-first-names] + .govuk-error-message', 'Enter first names');
cy.contains('[for=f-last-name] + .govuk-error-message', 'Enter last name');
});

it('errors when names too long', () => {
cy.get('#f-first-names').invoke('val', 'a '.repeat(54));
cy.get('#f-last-name').invoke('val', 'b '.repeat(62));

cy.contains('button', "Save").click()
cy.contains('button', "Save").click()

cy.checkA11yApp();
cy.checkA11yApp();

cy.get('.govuk-error-summary').within(() => {
cy.contains('Enter first names');
cy.contains('Enter last name');
cy.contains('[for=f-first-names] + .govuk-error-message', 'First names must be 53 characters or less');
cy.contains('[for=f-last-name] + .govuk-error-message', 'Last name must be 61 characters or less');
});
})

describe('non-admin', () => {
it.only('can edit own name', () => {
cy.visit("/fixtures/supporter?organisation=1&redirect=/manage-organisation/manage-team-members&members=1&[email protected]");

cy.contains('[for=f-first-names] + .govuk-error-message', 'Enter first names');
cy.contains('[for=f-last-name] + .govuk-error-message', 'Enter last name');
});
cy.contains('a', 'Manage your details').click();
cy.url().should('contain', "/manage-organisation/manage-team-members/edit-team-member");

it('errors when names too long', () => {
cy.get('#f-first-names').invoke('val', 'a '.repeat(54));
cy.get('#f-last-name').invoke('val', 'b '.repeat(62));
cy.checkA11yApp();
cy.contains('Your name');

cy.contains('button', "Save").click()
cy.get('#f-first-names').clear ().type('John');
cy.get('#f-last-name').clear().type('Doe');

cy.checkA11yApp();
cy.contains('button', "Save").click()

cy.url().should('contain', "/dashboard");

cy.contains('Your name has been updated to John Doe');
})
})

cy.contains('[for=f-first-names] + .govuk-error-message', 'First names must be 53 characters or less');
cy.contains('[for=f-last-name] + .govuk-error-message', 'Last name must be 61 characters or less');
});
})
6 changes: 6 additions & 0 deletions internal/page/app_data.go
Original file line number Diff line number Diff line change
@@ -26,6 +26,8 @@ type AppData struct {
OrganisationName string
IsManageOrganisation bool
LoginSessionEmail string
Permission actor.Permission
SupporterMemberID string
}

func (d AppData) Redirect(w http.ResponseWriter, r *http.Request, url string) error {
@@ -58,3 +60,7 @@ func (d AppData) IsReplacementAttorney() bool {
func (d AppData) IsTrustCorporation() bool {
return d.ActorType == actor.TypeTrustCorporation || d.ActorType == actor.TypeReplacementTrustCorporation
}

func (d AppData) IsAdmin() bool {
return d.Permission.IsAdmin()
}
5 changes: 5 additions & 0 deletions internal/page/app_data_test.go
Original file line number Diff line number Diff line change
@@ -71,3 +71,8 @@ func TestIsTrustCorporation(t *testing.T) {
assert.False(t, AppData{ActorType: actor.TypeAttorney, AttorneyUID: actoruid.New()}.IsTrustCorporation())
assert.False(t, AppData{ActorType: actor.TypeReplacementAttorney, AttorneyUID: actoruid.New()}.IsTrustCorporation())
}

func TestAppDataIsAdmin(t *testing.T) {
assert.True(t, AppData{Permission: actor.Admin}.IsAdmin())
assert.False(t, AppData{}.IsAdmin())
}
31 changes: 22 additions & 9 deletions internal/page/fixtures/supporter.go
Original file line number Diff line number Diff line change
@@ -33,16 +33,17 @@ func Supporter(sessionStore sesh.Store, organisationStore OrganisationStore, don
members = r.FormValue("members")
organisation = r.FormValue("organisation")
redirect = r.FormValue("redirect")
asMember = r.FormValue("asMember")

supporterSub = random.String(16)
supporterSessionID = base64.StdEncoding.EncodeToString([]byte(supporterSub))
ctx = page.ContextWithSessionData(r.Context(), &page.SessionData{SessionID: supporterSessionID, Email: testEmail})
adminSub = random.String(16)
adminSessionID = base64.StdEncoding.EncodeToString([]byte(adminSub))
adminCtx = page.ContextWithSessionData(r.Context(), &page.SessionData{SessionID: adminSessionID, Email: testEmail})
)

loginSession := &sesh.LoginSession{Sub: supporterSub, Email: testEmail}
loginSession := &sesh.LoginSession{Sub: adminSub, Email: testEmail}

if organisation == "1" {
org, err := organisationStore.Create(ctx, random.String(12))
org, err := organisationStore.Create(adminCtx, random.String(12))
if err != nil {
return err
}
@@ -86,30 +87,42 @@ func Supporter(sessionStore sesh.Store, organisationStore OrganisationStore, don
}

if members != "" {
n, err := strconv.Atoi(members)
n, _ := strconv.Atoi(members)
memberEmailSub := make(map[string]string)

for i, member := range orgMemberNames {
if i == n {
break
}

email := strings.ToLower(fmt.Sprintf("%s-%[email protected]", member.Firstnames, member.Lastname))
sub := []byte(random.String(16))
memberCtx := page.ContextWithSessionData(r.Context(), &page.SessionData{SessionID: base64.StdEncoding.EncodeToString(sub), Email: email})

if err = memberStore.Create(
page.ContextWithSessionData(r.Context(), &page.SessionData{SessionID: random.String(12)}),
memberCtx,
&actor.MemberInvite{
PK: random.String(12),
SK: random.String(12),
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
OrganisationID: org.ID,
Email: strings.ToLower(fmt.Sprintf("%s-%[email protected]", member.Firstnames, member.Lastname)),
Email: email,
FirstNames: member.Firstnames,
LastName: member.Lastname,
Permission: actor.Admin,
Permission: actor.None,
ReferenceNumber: random.String(12),
},
); err != nil {
return err
}

memberEmailSub[email] = string(sub)
}

if sub, found := memberEmailSub[asMember]; found {
loginSession.Email = asMember
loginSession.Sub = sub
}
}
}
4 changes: 3 additions & 1 deletion internal/page/supporter/dashboard.go
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@ package supporter

import (
"net/http"
"net/url"

"github.com/ministryofjustice/opg-go-common/template"
"github.com/ministryofjustice/opg-modernising-lpa/internal/actor"
@@ -13,6 +14,7 @@ type dashboardData struct {
App page.AppData
Errors validation.List
Donors []actor.DonorProvidedDetails
Query url.Values
}

func Dashboard(tmpl template.Template, organisationStore OrganisationStore) Handler {
@@ -22,6 +24,6 @@ func Dashboard(tmpl template.Template, organisationStore OrganisationStore) Hand
return err
}

return tmpl(w, &dashboardData{App: appData, Donors: donors})
return tmpl(w, &dashboardData{App: appData, Donors: donors, Query: r.URL.Query()})
}
}
4 changes: 3 additions & 1 deletion internal/page/supporter/dashboard_test.go
Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@ package supporter
import (
"net/http"
"net/http/httptest"
"net/url"
"testing"

"github.com/ministryofjustice/opg-modernising-lpa/internal/actor"
@@ -11,7 +12,7 @@ import (

func TestGetDashboard(t *testing.T) {
w := httptest.NewRecorder()
r, _ := http.NewRequest(http.MethodGet, "/", nil)
r, _ := http.NewRequest(http.MethodGet, "/?a=b", nil)

donors := []actor.DonorProvidedDetails{{LpaID: "abc"}}

@@ -25,6 +26,7 @@ func TestGetDashboard(t *testing.T) {
Execute(w, &dashboardData{
App: testAppData,
Donors: donors,
Query: url.Values{"a": {"b"}},
}).
Return(expectedError)

7 changes: 6 additions & 1 deletion internal/page/supporter/edit_member.go
Original file line number Diff line number Diff line change
@@ -54,7 +54,12 @@ func EditMember(tmpl template.Template, memberStore MemberStore) Handler {
return err
}

return page.Paths.Supporter.ManageTeamMembers.RedirectQuery(w, r, appData, query)
redirect := page.Paths.Supporter.ManageTeamMembers
if !appData.IsAdmin() {
redirect = page.Paths.Supporter.Dashboard
}

return redirect.RedirectQuery(w, r, appData, query)
}
}

68 changes: 56 additions & 12 deletions internal/page/supporter/edit_member_test.go
Original file line number Diff line number Diff line change
@@ -87,45 +87,87 @@ func TestGetEditMemberWhenTemplateError(t *testing.T) {

func TestPostEditMember(t *testing.T) {
testcases := map[string]struct {
form url.Values
expectedQuery string
expectedMember *actor.Member
memberEmail string
form url.Values
expectedRedirect string
expectedMember *actor.Member
memberEmail string
userPermission actor.Permission
}{
"Team member name updated": {
"As Admin: Team member name updated": {
form: url.Values{
"first-names": {"c"},
"last-name": {"d"},
},
expectedQuery: "?nameUpdated=c+d",
expectedRedirect: page.Paths.Supporter.ManageTeamMembers.Format() + "?nameUpdated=c+d",
expectedMember: &actor.Member{
FirstNames: "c",
LastName: "d",
},
userPermission: actor.Admin,
},
"Self name updated": {
"As Admin: Self name updated": {
form: url.Values{
"first-names": {"c"},
"last-name": {"d"},
},
expectedQuery: "?nameUpdated=c+d&selfUpdated=1",
expectedRedirect: page.Paths.Supporter.ManageTeamMembers.Format() + "?nameUpdated=c+d&selfUpdated=1",
expectedMember: &actor.Member{
FirstNames: "c",
LastName: "d",
Email: "[email protected]",
},
memberEmail: "[email protected]",
userPermission: actor.Admin,
memberEmail: "[email protected]",
},
"no updates": {
"As Admin: no updates": {
form: url.Values{
"first-names": {"a"},
"last-name": {"b"},
},
expectedQuery: "?",
expectedRedirect: page.Paths.Supporter.ManageTeamMembers.Format() + "?",
expectedMember: &actor.Member{
FirstNames: "a",
LastName: "b",
},
userPermission: actor.Admin,
},
"As Non-Admin: Team member name updated": {
form: url.Values{
"first-names": {"c"},
"last-name": {"d"},
},
expectedRedirect: page.Paths.Supporter.Dashboard.Format() + "?nameUpdated=c+d",
expectedMember: &actor.Member{
FirstNames: "c",
LastName: "d",
},
userPermission: actor.None,
},
"As Non-Admin: Self name updated": {
form: url.Values{
"first-names": {"c"},
"last-name": {"d"},
},
expectedRedirect: page.Paths.Supporter.Dashboard.Format() + "?nameUpdated=c+d&selfUpdated=1",
expectedMember: &actor.Member{
FirstNames: "c",
LastName: "d",
Email: "[email protected]",
},
userPermission: actor.None,
memberEmail: "[email protected]",
},
"As Non-Admin: no updates": {
form: url.Values{
"first-names": {"a"},
"last-name": {"b"},
},
expectedRedirect: page.Paths.Supporter.Dashboard.Format() + "?",
expectedMember: &actor.Member{
FirstNames: "a",
LastName: "b",
},
userPermission: actor.None,
},
}

@@ -149,12 +191,14 @@ func TestPostEditMember(t *testing.T) {
Return(nil)

testAppData.LoginSessionEmail = "[email protected]"
testAppData.Permission = tc.userPermission

err := EditMember(nil, memberStore)(testAppData, w, r, &actor.Organisation{})
resp := w.Result()

assert.Nil(t, err)
assert.Equal(t, http.StatusFound, resp.StatusCode)
assert.Equal(t, page.Paths.Supporter.ManageTeamMembers.Format()+tc.expectedQuery, resp.Header.Get("Location"))
assert.Equal(t, tc.expectedRedirect, resp.Header.Get("Location"))
})
}
}
Loading

0 comments on commit e9a84be

Please sign in to comment.