Skip to content

Commit 6300046

Browse files
committed
Add settings page test coverage
1 parent 872e208 commit 6300046

File tree

6 files changed

+157
-12
lines changed

6 files changed

+157
-12
lines changed

src/UnisonShare/ErrorDetails.elm

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,11 @@ view session error =
1717

1818
else
1919
UI.nothing
20+
21+
22+
23+
{- details []
24+
[ summary [] [ text "Error Details" ]
25+
, pre [] [ text (Util.httpErrorToString error) ]
26+
]
27+
-}

src/UnisonShare/Page/ProjectSettingsPage.elm

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ removeWebhook appContext projectRef webhook =
384384
pageTitle : PageTitle.PageTitle msg
385385
pageTitle =
386386
PageTitle.title "Project Settings"
387-
|> PageTitle.withDescription "Manage your project visibility and settings."
387+
|> PageTitle.withDescription "Manage your project. Collaborators, webhooks, and visibility."
388388

389389

390390
viewLoadingPage : PageLayout msg
@@ -413,8 +413,8 @@ viewLoadingPage =
413413
|> PageLayout.withSubduedBackground
414414

415415

416-
viewCollaborators : Model -> Html Msg
417-
viewCollaborators model =
416+
viewCollaborators : Session -> Model -> Html Msg
417+
viewCollaborators session model =
418418
let
419419
( collabs, addButton ) =
420420
case model.collaborators of
@@ -461,15 +461,16 @@ viewCollaborators model =
461461
in
462462
content
463463

464-
Failure _ ->
464+
Failure e ->
465465
( div [ class "collaborators_error" ]
466466
[ StatusBanner.bad "Could not load collaborators"
467+
, ErrorDetails.view session e
467468
]
468469
, UI.nothing
469470
)
470471

471472
_ ->
472-
( div [ class "collaborators_loading" ]
473+
( div [ class "list_loading" ]
473474
[ Placeholder.text |> Placeholder.withLength Placeholder.Small |> Placeholder.view
474475
, Placeholder.text |> Placeholder.withLength Placeholder.Medium |> Placeholder.view
475476
, Placeholder.text |> Placeholder.withLength Placeholder.Huge |> Placeholder.view
@@ -479,7 +480,7 @@ viewCollaborators model =
479480
)
480481
in
481482
Card.card
482-
[ header [ class "project-settings_card_header" ] [ h2 [] [ text "Project Collaborators" ], addButton ]
483+
[ header [ class "project-settings_card_header" ] [ h2 [] [ text "Collaborators" ], addButton ]
483484
, collabs
484485
]
485486
|> Card.asContained
@@ -562,12 +563,12 @@ viewWebhooks session model =
562563
]
563564

564565
Failure e ->
565-
[ StatusBanner.bad "An unexpected error occurred, please try again."
566+
[ StatusBanner.bad "Could not load webhooks."
566567
, ErrorDetails.view session e
567568
]
568569

569570
_ ->
570-
[ div [ class "webhooks_loading" ]
571+
[ div [ class "list_loading" ]
571572
[ Placeholder.text |> Placeholder.withLength Placeholder.Small |> Placeholder.view
572573
, Placeholder.text |> Placeholder.withLength Placeholder.Medium |> Placeholder.view
573574
, Placeholder.text |> Placeholder.withLength Placeholder.Huge |> Placeholder.view
@@ -651,8 +652,13 @@ viewPageContent session project model =
651652
, StatusBanner.info "Changing visibility is not supported for public organizations."
652653
)
653654

654-
Failure _ ->
655-
( overlay_, StatusBanner.bad "An unexpected error occurred, please try again." )
655+
Failure e ->
656+
( overlay_
657+
, div []
658+
[ StatusBanner.bad "An unexpected error occurred, please try again."
659+
, ErrorDetails.view session e
660+
]
661+
)
656662
in
657663
Card.card
658664
[ h2 [] [ text "Project Visibility" ]
@@ -723,7 +729,7 @@ viewPageContent session project model =
723729

724730
collaborators =
725731
if Project.isPublic project || project.isPremiumProject then
726-
viewCollaborators model
732+
viewCollaborators session model
727733

728734
else
729735
UI.nothing

src/css/unison-share/page/project-settings-page.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@
8282
color: var(--u-color_icon_subdued);
8383
}
8484

85-
.project-settings-page .collaborators_loading {
85+
.project-settings-page .list_loading {
8686
display: flex;
8787
flex-direction: column;
8888
gap: 0.5rem;
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { test, expect } from "@playwright/test";
2+
import { button } from "./TestHelpers/Page";
3+
import * as API from "./TestHelpers/Api";
4+
5+
const projectRef = "@alice/html";
6+
7+
test.beforeEach(async ({ page }) => {
8+
await API.getWebsiteFeed(page);
9+
});
10+
11+
test.describe("without being signed in", () => {
12+
test.beforeEach(async ({ page }) => {
13+
await API.getAccount(page, "NOT_SIGNED_IN");
14+
await page.goto(`http://localhost:1234/${projectRef}/settings`);
15+
});
16+
17+
test("can *NOT* see the project settings page", async ({ page }) => {
18+
await expect(page.getByText("Project Settings")).not.toBeVisible();
19+
});
20+
});
21+
22+
test.describe("with the project:manage permission", () => {
23+
test.beforeEach(async ({ page }) => {
24+
await API.getAccount(page, "@alice");
25+
await API.getUserProfile(page, "@alice");
26+
await API.getProjectRoleAssignments(page, projectRef);
27+
await API.getProjectWebhooks(page, projectRef);
28+
await API.getProject(page, projectRef, {
29+
visibility: "public",
30+
permissions: ["project:manage"],
31+
});
32+
await page.goto(`http://localhost:1234/${projectRef}/settings`);
33+
});
34+
35+
test("The user can see the project settings page", async ({ page }) => {
36+
await expect(page.getByText("Project Settings")).toBeVisible();
37+
});
38+
39+
test("The user can see the the collaborators section", async ({ page }) => {
40+
await expect(page.locator(".collaborator")).toHaveCount(3);
41+
});
42+
43+
test("The user can see the the visibility section", async ({ page }) => {
44+
await expect(page.getByText("Project Visibility")).toBeVisible();
45+
});
46+
47+
test.describe("webhooks", () => {
48+
test("The user can see the webhooks section", async ({ page }) => {
49+
await expect(page.locator(".webhook")).toHaveCount(3);
50+
await expect(button(page, "Add a webhook")).toBeVisible();
51+
});
52+
53+
test("The user can see the add webhook modal", async ({ page }) => {
54+
await button(page, "Add a webhook").click();
55+
await expect(page.locator(".modal")).toBeVisible();
56+
});
57+
});
58+
});

tests/e2e/TestHelpers/Api.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import {
55
project,
66
type ContributionDiffConfig,
77
type Notification,
8+
projectRoleAssignment,
9+
projectWebhook,
810
contributionTimeline,
911
contributionDiff,
1012
ticket,
@@ -537,6 +539,53 @@ async function patchProjectTicket(
537539
});
538540
}
539541

542+
// -- /users/:handle/:project-ref/roles
543+
544+
async function getProjectRoleAssignments(
545+
page: Page,
546+
projectRef: string,
547+
resp?: { status: number },
548+
) {
549+
const [handle, projectSlug] = projectRef.split("/");
550+
551+
return get(page, {
552+
...{
553+
url: `/users/${handle.replace("@", "")}/projects/${projectSlug}/roles`,
554+
status: 200,
555+
data: {
556+
active: true,
557+
role_assignments: [
558+
projectRoleAssignment(),
559+
projectRoleAssignment(),
560+
projectRoleAssignment(),
561+
],
562+
},
563+
},
564+
...(resp || {}),
565+
});
566+
}
567+
568+
// -- /users/:handle/:project-ref/webhooks
569+
//
570+
async function getProjectWebhooks(
571+
page: Page,
572+
projectRef: string,
573+
resp?: { status: number },
574+
) {
575+
const [handle, projectSlug] = projectRef.split("/");
576+
577+
return get(page, {
578+
...{
579+
url: `/users/${handle.replace("@", "")}/projects/${projectSlug}/webhooks`,
580+
status: 200,
581+
data: {
582+
webhooks: [projectWebhook(), projectWebhook(), projectWebhook()],
583+
},
584+
},
585+
...(resp || {}),
586+
});
587+
}
588+
540589
// /users/:handle/notifications
541590

542591
type NotificationsHubData = {
@@ -677,6 +726,8 @@ export {
677726
getProject,
678727
getProject_,
679728
getProjectReadme,
729+
getProjectRoleAssignments,
730+
getProjectWebhooks,
680731
getProjectDependencies,
681732
getProjectContribution,
682733
getProjectContribution_,

tests/e2e/TestHelpers/Data.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -727,6 +727,26 @@ function userSearchMatch() {
727727
};
728728
}
729729

730+
function projectRoleAssignment() {
731+
return {
732+
roles: ["project_contributor"],
733+
subject: {
734+
data: user(),
735+
kind: "user",
736+
},
737+
};
738+
}
739+
740+
function projectWebhook() {
741+
return {
742+
notificationSubscriptionId: faker.string.uuid(),
743+
createdAt: faker.date.past(),
744+
updatedAt: faker.date.past(),
745+
uri: faker.internet.url(),
746+
topics: { type: "all" },
747+
};
748+
}
749+
730750
export {
731751
projectRef,
732752
project,
@@ -741,6 +761,8 @@ export {
741761
contribution,
742762
contributionTimeline,
743763
contributionStatusChangeEvent,
764+
projectRoleAssignment,
765+
projectWebhook,
744766
contributionDiff,
745767
notification,
746768
notificationEvent,

0 commit comments

Comments
 (0)