Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitc92f480

Browse files
authored
chore: add e2e test for org groups (#15853)
1 parent50ff06c commitc92f480

File tree

8 files changed

+163
-25
lines changed

8 files changed

+163
-25
lines changed

‎site/e2e/api.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,15 @@ export const getCurrentOrgId = async (): Promise<string> => {
2828
returncurrentOrgId;
2929
};
3030

31-
exportconstcreateUser=async(orgId:string)=>{
31+
exportconstcreateUser=async(...orgIds:string[])=>{
3232
constname=randomName();
3333
constuser=awaitAPI.createUser({
3434
email:`${name}@coder.com`,
3535
username:name,
3636
name:name,
3737
password:"s3cure&password!",
3838
login_type:"password",
39-
organization_ids:[orgId],
39+
organization_ids:orgIds,
4040
user_status:null,
4141
});
4242
returnuser;

‎site/e2e/helpers.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,3 +1037,25 @@ export async function createUser(
10371037
awaitpage.goto(returnTo,{waitUntil:"domcontentloaded"});
10381038
return{ name, username, email, password};
10391039
}
1040+
1041+
exportasyncfunctioncreateOrganization(page:Page):Promise<{
1042+
name:string;
1043+
displayName:string;
1044+
description:string;
1045+
}>{
1046+
// Create a new organization to test
1047+
awaitpage.goto("/organizations/new",{waitUntil:"domcontentloaded"});
1048+
constname=randomName();
1049+
awaitpage.getByLabel("Slug").fill(name);
1050+
constdisplayName=`Org${name}`;
1051+
awaitpage.getByLabel("Display name").fill(displayName);
1052+
constdescription=`Org description${name}`;
1053+
awaitpage.getByLabel("Description").fill(description);
1054+
awaitpage.getByLabel("Icon",{exact:true}).fill("/emojis/1f957.png");
1055+
awaitpage.getByRole("button",{name:"Submit"}).click();
1056+
1057+
awaitexpectUrl(page).toHavePathName(`/organizations/${name}`);
1058+
awaitexpect(page.getByText("Organization created.")).toBeVisible();
1059+
1060+
return{ name, displayName, description};
1061+
}
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import{expect,test}from"@playwright/test";
2+
import{
3+
createGroup,
4+
createOrganization,
5+
createUser,
6+
setupApiCalls,
7+
}from"../api";
8+
import{expectUrl}from"../expectUrl";
9+
import{randomName,requiresLicense}from"../helpers";
10+
import{beforeCoderTest}from"../hooks";
11+
12+
test.beforeEach(async({ page})=>{
13+
awaitbeforeCoderTest(page);
14+
awaitsetupApiCalls(page);
15+
});
16+
17+
test("create group",async({ page})=>{
18+
requiresLicense();
19+
20+
// Create a new organization
21+
constorg=awaitcreateOrganization();
22+
awaitpage.goto(`/organizations/${org.name}`);
23+
24+
// Navigate to groups page
25+
awaitpage.getByText("Groups").click();
26+
awaitexpect(page).toHaveTitle(`Groups - Org${org.name} - Coder`);
27+
28+
// Create a new group
29+
awaitpage.getByText("Create group").click();
30+
awaitexpect(page).toHaveTitle("Create Group - Coder");
31+
constname=randomName();
32+
awaitpage.getByLabel("Name",{exact:true}).fill(name);
33+
constdisplayName=`Group${name}`;
34+
awaitpage.getByLabel("Display Name").fill(displayName);
35+
awaitpage.getByLabel("Avatar URL").fill("/emojis/1f60d.png");
36+
awaitpage.getByRole("button",{name:"Submit"}).click();
37+
38+
awaitexpectUrl(page).toHavePathName(
39+
`/organizations/${org.name}/groups/${name}`,
40+
);
41+
awaitexpect(page).toHaveTitle(`${displayName} - Coder`);
42+
awaitexpect(page.getByText("No members yet")).toBeVisible();
43+
awaitexpect(page.getByText(displayName)).toBeVisible();
44+
45+
// Add a user to the group
46+
constpersonToAdd=awaitcreateUser(org.id);
47+
awaitpage.getByPlaceholder("User email or username").fill(personToAdd.email);
48+
awaitpage.getByRole("option",{name:personToAdd.email}).click();
49+
awaitpage.getByRole("button",{name:"Add user"}).click();
50+
constaddedRow=page.locator("tr",{hasText:personToAdd.email});
51+
awaitexpect(addedRow).toBeVisible();
52+
53+
// Ensure we can't add a user who isn't in the org
54+
constotherOrg=awaitcreateOrganization();
55+
constpersonToReject=awaitcreateUser(otherOrg.id);
56+
awaitpage
57+
.getByPlaceholder("User email or username")
58+
.fill(personToReject.email);
59+
awaitexpect(page.getByText("No users found")).toBeVisible();
60+
61+
// Remove someone from the group
62+
awaitaddedRow.getByLabel("More options").click();
63+
awaitpage.getByText("Remove").click();
64+
awaitexpect(addedRow).not.toBeVisible();
65+
66+
// Delete the group
67+
awaitpage.getByRole("button",{name:"Delete"}).click();
68+
constdialog=page.getByTestId("dialog");
69+
awaitdialog.getByLabel("Name of the group to delete").fill(name);
70+
awaitdialog.getByRole("button",{name:"Delete"}).click();
71+
awaitexpect(page.getByText("Group deleted successfully.")).toBeVisible();
72+
73+
awaitexpectUrl(page).toHavePathName(`/organizations/${org.name}/groups`);
74+
awaitexpect(page).toHaveTitle(`Groups - Org${org.name} - Coder`);
75+
});
76+
77+
test("change quota settings",async({ page})=>{
78+
requiresLicense();
79+
80+
// Create a new organization and group
81+
constorg=awaitcreateOrganization();
82+
constgroup=awaitcreateGroup(org.id);
83+
84+
// Go to settings
85+
awaitpage.goto(`/organizations/${org.name}/groups/${group.name}`);
86+
awaitpage.getByRole("button",{name:"Settings"}).click();
87+
expectUrl(page).toHavePathName(
88+
`/organizations/${org.name}/groups/${group.name}/settings`,
89+
);
90+
91+
// Update Quota
92+
awaitpage.getByLabel("Quota Allowance").fill("100");
93+
awaitpage.getByRole("button",{name:"Submit"}).click();
94+
95+
// We should get sent back to the group page afterwards
96+
expectUrl(page).toHavePathName(
97+
`/organizations/${org.name}/groups/${group.name}`,
98+
);
99+
100+
// ...and that setting should persist if we go back
101+
awaitpage.getByRole("button",{name:"Settings"}).click();
102+
awaitexpect(page.getByLabel("Quota Allowance")).toHaveValue("100");
103+
});

‎site/e2e/tests/organizationMembers.spec.ts

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import{expect,test}from"@playwright/test";
22
import{setupApiCalls}from"../api";
3-
import{expectUrl}from"../expectUrl";
4-
import{createUser,randomName,requiresLicense}from"../helpers";
3+
import{createOrganization,createUser,requiresLicense}from"../helpers";
54
import{beforeCoderTest}from"../hooks";
65

76
test.beforeEach(async({ page})=>{
@@ -12,19 +11,12 @@ test.beforeEach(async ({ page }) => {
1211
test("add and remove organization member",async({ page})=>{
1312
requiresLicense();
1413

15-
// Create a new organization to test
16-
awaitpage.goto("/organizations/new",{waitUntil:"domcontentloaded"});
17-
constname=randomName();
18-
awaitpage.getByLabel("Slug").fill(name);
19-
awaitpage.getByLabel("Display name").fill(`Org${name}`);
20-
awaitpage.getByLabel("Description").fill(`Org description${name}`);
21-
awaitpage.getByLabel("Icon",{exact:true}).fill("/emojis/1f957.png");
22-
awaitpage.getByRole("button",{name:"Submit"}).click();
14+
// Create a new organization
15+
const{ displayName}=awaitcreateOrganization(page);
2316

2417
// Navigate to members page
25-
awaitexpectUrl(page).toHavePathName(`/organizations/${name}`);
26-
awaitexpect(page.getByText("Organization created.")).toBeVisible();
2718
awaitpage.getByText("Members").click();
19+
awaitexpect(page).toHaveTitle(`Members -${displayName} - Coder`);
2820

2921
// Add a user to the org
3022
constpersonToAdd=awaitcreateUser(page);

‎site/src/pages/ManagementSettingsPage/GroupsPage/GroupPage.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,10 @@ export const GroupPage: FC = () => {
111111
{canUpdateGroup&&(
112112
<Stackdirection="row"spacing={2}>
113113
<Button
114+
role="button"
115+
component={RouterLink}
114116
startIcon={<SettingsOutlined/>}
115117
to="settings"
116-
component={RouterLink}
117118
>
118119
Settings
119120
</Button>

‎site/src/pages/ManagementSettingsPage/GroupsPage/GroupsPage.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,9 @@ export const GroupsPage: FC = () => {
6969
return(
7070
<>
7171
<Helmet>
72-
<title>{pageTitle("Groups")}</title>
72+
<title>
73+
{pageTitle("Groups",organization.display_name||organization.name)}
74+
</title>
7375
</Helmet>
7476

7577
<Stack

‎site/src/pages/ManagementSettingsPage/OrganizationMembersPage.tsx

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@ import { Stack } from "components/Stack/Stack";
1717
import{useAuthenticated}from"contexts/auth/RequireAuth";
1818
import{useManagementSettings}from"modules/management/ManagementSettingsLayout";
1919
import{typeFC,useState}from"react";
20+
import{Helmet}from"react-helmet-async";
2021
import{useMutation,useQuery,useQueryClient}from"react-query";
2122
import{useParams}from"react-router-dom";
23+
import{pageTitle}from"utils/page";
2224
import{OrganizationMembersPageView}from"./OrganizationMembersPageView";
2325

2426
constOrganizationMembersPage:FC=()=>{
@@ -50,8 +52,7 @@ const OrganizationMembersPage: FC = () => {
5052
updateOrganizationMemberRoles(queryClient,organizationName),
5153
);
5254

53-
const{ organizations}=useManagementSettings();
54-
constorganization=organizations?.find((o)=>o.name===organizationName);
55+
const{ organization}=useManagementSettings();
5556
constpermissionsQuery=useQuery(organizationPermissions(organization?.id));
5657

5758
const[memberToDelete,setMemberToDelete]=
@@ -62,8 +63,17 @@ const OrganizationMembersPage: FC = () => {
6263
return<Loader/>;
6364
}
6465

66+
consthelmet=organization&&(
67+
<Helmet>
68+
<title>
69+
{pageTitle("Members",organization.display_name||organization.name)}
70+
</title>
71+
</Helmet>
72+
);
73+
6574
return(
6675
<>
76+
{helmet}
6777
<OrganizationMembersPageView
6878
allAvailableRoles={organizationRolesQuery.data}
6979
canEditMembers={permissions.editMembers}

‎site/src/pages/ManagementSettingsPage/OrganizationProvisionersPage.tsx

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import{buildInfo}from"api/queries/buildInfo";
22
import{provisionerDaemonGroups}from"api/queries/organizations";
3-
importtype{Organization}from"api/typesGenerated";
43
import{EmptyState}from"components/EmptyState/EmptyState";
54
import{useEmbeddedMetadata}from"hooks/useEmbeddedMetadata";
65
import{useDashboard}from"modules/dashboard/useDashboard";
76
import{useManagementSettings}from"modules/management/ManagementSettingsLayout";
87
importtype{FC}from"react";
8+
import{Helmet}from"react-helmet-async";
99
import{useQuery}from"react-query";
1010
import{useParams}from"react-router-dom";
11+
import{pageTitle}from"utils/page";
1112
import{OrganizationProvisionersPageView}from"./OrganizationProvisionersPageView";
1213

1314
constOrganizationProvisionersPage:FC=()=>{
@@ -25,12 +26,19 @@ const OrganizationProvisionersPage: FC = () => {
2526
}
2627

2728
return(
28-
<OrganizationProvisionersPageView
29-
showPaywall={!entitlements.features.multiple_organizations.enabled}
30-
error={provisionersQuery.error}
31-
buildInfo={buildInfoQuery.data}
32-
provisioners={provisionersQuery.data}
33-
/>
29+
<>
30+
<Helmet>
31+
<title>
32+
{pageTitle("Members",organization.display_name||organization.name)}
33+
</title>
34+
</Helmet>
35+
<OrganizationProvisionersPageView
36+
showPaywall={!entitlements.features.multiple_organizations.enabled}
37+
error={provisionersQuery.error}
38+
buildInfo={buildInfoQuery.data}
39+
provisioners={provisionersQuery.data}
40+
/>
41+
</>
3442
);
3543
};
3644

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp