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

Commitf518669

Browse files
authored
feat: enable editing of IDP sync configuration for groups and roles in the UI (#16098)
contributes to#15290 The goal of this PR is to port the work to implement CRUD in the UI forIDP organization sync settings and apply this to group and role IDP syncsettings.<img width="1143" alt="Screenshot 2025-01-16 at 20 25 21"src="https://github.com/user-attachments/assets/c5d09291-e98c-497c-8c23-a3cdcdccb90d"/><img width="1142" alt="Screenshot 2025-01-16 at 20 25 39"src="https://github.com/user-attachments/assets/1f569e1f-1474-49fa-8c80-aa8cf0d0e4db"/>
1 parent75c899f commitf518669

File tree

24 files changed

+1404
-587
lines changed

24 files changed

+1404
-587
lines changed

‎site/e2e/api.ts‎

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,13 +81,49 @@ export const createOrganizationSyncSettings = async () => {
8181
"fbd2116a-8961-4954-87ae-e4575bd29ce0",
8282
"13de3eb4-9b4f-49e7-b0f8-0c3728a0d2e2",
8383
],
84-
"idp-org-2":["fbd2116a-8961-4954-87ae-e4575bd29ce0"],
84+
"idp-org-2":["6b39f0f1-6ad8-4981-b2fc-d52aef53ff1b"],
8585
},
8686
organization_assign_default:true,
8787
});
8888
returnsettings;
8989
};
9090

91+
exportconstcreateGroupSyncSettings=async(orgId:string)=>{
92+
constsettings=awaitAPI.patchGroupIdpSyncSettings(
93+
{
94+
field:"group-field-test",
95+
mapping:{
96+
"idp-group-1":[
97+
"fbd2116a-8961-4954-87ae-e4575bd29ce0",
98+
"13de3eb4-9b4f-49e7-b0f8-0c3728a0d2e2",
99+
],
100+
"idp-group-2":["6b39f0f1-6ad8-4981-b2fc-d52aef53ff1b"],
101+
},
102+
regex_filter:"@[a-zA-Z0-9]+",
103+
auto_create_missing_groups:true,
104+
},
105+
orgId,
106+
);
107+
returnsettings;
108+
};
109+
110+
exportconstcreateRoleSyncSettings=async(orgId:string)=>{
111+
constsettings=awaitAPI.patchRoleIdpSyncSettings(
112+
{
113+
field:"role-field-test",
114+
mapping:{
115+
"idp-role-1":[
116+
"fbd2116a-8961-4954-87ae-e4575bd29ce0",
117+
"13de3eb4-9b4f-49e7-b0f8-0c3728a0d2e2",
118+
],
119+
"idp-role-2":["6b39f0f1-6ad8-4981-b2fc-d52aef53ff1b"],
120+
},
121+
},
122+
orgId,
123+
);
124+
returnsettings;
125+
};
126+
91127
exportconstcreateCustomRole=async(
92128
orgId:string,
93129
name:string,

‎site/e2e/tests/deployment/idpOrgSync.spec.ts‎

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,22 @@ test.beforeEach(async ({ page }) => {
1616
});
1717

1818
test.describe("IdpOrgSyncPage",()=>{
19+
test("show empty table when no org mappings are present",async({
20+
page,
21+
})=>{
22+
requiresLicense();
23+
awaitpage.goto("/deployment/idp-org-sync",{
24+
waitUntil:"domcontentloaded",
25+
});
26+
27+
awaitexpect(
28+
page.getByRole("row",{name:"idp-org-1"}),
29+
).not.toBeVisible();
30+
awaitexpect(
31+
page.getByRole("heading",{name:"No organization mappings"}),
32+
).toBeVisible();
33+
});
34+
1935
test("add new IdP organization mapping with API",async({ page})=>{
2036
requiresLicense();
2137

@@ -29,14 +45,14 @@ test.describe("IdpOrgSyncPage", () => {
2945
page.getByRole("switch",{name:"Assign Default Organization"}),
3046
).toBeChecked();
3147

32-
awaitexpect(page.getByText("idp-org-1")).toBeVisible();
48+
awaitexpect(page.getByRole("row",{name:"idp-org-1"})).toBeVisible();
3349
awaitexpect(
34-
page.getByText("fbd2116a-8961-4954-87ae-e4575bd29ce0").first(),
50+
page.getByRole("row",{name:"fbd2116a-8961-4954-87ae-e4575bd29ce0"}),
3551
).toBeVisible();
3652

37-
awaitexpect(page.getByText("idp-org-2")).toBeVisible();
53+
awaitexpect(page.getByRole("row",{name:"idp-org-2"})).toBeVisible();
3854
awaitexpect(
39-
page.getByText("fbd2116a-8961-4954-87ae-e4575bd29ce0").last(),
55+
page.getByRole("row",{name:"6b39f0f1-6ad8-4981-b2fc-d52aef53ff1b"}),
4056
).toBeVisible();
4157
});
4258

@@ -47,12 +63,12 @@ test.describe("IdpOrgSyncPage", () => {
4763
waitUntil:"domcontentloaded",
4864
});
4965

50-
awaitexpect(page.getByText("idp-org-1")).toBeVisible();
51-
awaitpage
52-
.getByRole("button",{name:/delete/i})
53-
.first()
54-
.click();
55-
awaitexpect(page.getByText("idp-org-1")).not.toBeVisible();
66+
constrow=page.getByTestId("idp-org-idp-org-1");
67+
awaitexpect(row.getByRole("cell",{name:"idp-org-1"})).toBeVisible();
68+
awaitrow.getByRole("button",{name:/delete/i}).click();
69+
awaitexpect(
70+
row.getByRole("cell",{name:"idp-org-1"}),
71+
).not.toBeVisible();
5672
awaitexpect(
5773
page.getByText("Organization sync settings updated."),
5874
).toBeVisible();
@@ -67,7 +83,7 @@ test.describe("IdpOrgSyncPage", () => {
6783
constsyncField=page.getByRole("textbox",{
6884
name:"Organization sync field",
6985
});
70-
constsaveButton=page.getByRole("button",{name:/save/i}).first();
86+
constsaveButton=page.getByRole("button",{name:/save/i});
7187

7288
awaitexpect(saveButton).toBeDisabled();
7389

@@ -154,8 +170,10 @@ test.describe("IdpOrgSyncPage", () => {
154170
// Verify new mapping appears in table
155171
constnewRow=page.getByTestId("idp-org-new-idp-org");
156172
awaitexpect(newRow).toBeVisible();
157-
awaitexpect(newRow.getByText("new-idp-org")).toBeVisible();
158-
awaitexpect(newRow.getByText(orgName)).toBeVisible();
173+
awaitexpect(
174+
newRow.getByRole("cell",{name:"new-idp-org"}),
175+
).toBeVisible();
176+
awaitexpect(newRow.getByRole("cell",{name:orgName})).toBeVisible();
159177

160178
awaitexpect(
161179
page.getByText("Organization sync settings updated."),
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
import{expect,test}from"@playwright/test";
2+
import{
3+
createGroupSyncSettings,
4+
createOrganizationWithName,
5+
deleteOrganization,
6+
setupApiCalls,
7+
}from"../../api";
8+
import{randomName,requiresLicense}from"../../helpers";
9+
import{login}from"../../helpers";
10+
import{beforeCoderTest}from"../../hooks";
11+
12+
test.beforeEach(async({ page})=>{
13+
beforeCoderTest(page);
14+
awaitlogin(page);
15+
awaitsetupApiCalls(page);
16+
});
17+
18+
test.describe("IdpGroupSyncPage",()=>{
19+
test("show empty table when no group mappings are present",async({
20+
page,
21+
})=>{
22+
requiresLicense();
23+
constorg=awaitcreateOrganizationWithName(randomName());
24+
awaitpage.goto(`/organizations/${org.name}/idp-sync?tab=groups`,{
25+
waitUntil:"domcontentloaded",
26+
});
27+
28+
awaitexpect(
29+
page.getByRole("row",{name:"idp-group-1"}),
30+
).not.toBeVisible();
31+
awaitexpect(
32+
page.getByRole("heading",{name:"No group mappings"}),
33+
).toBeVisible();
34+
35+
awaitdeleteOrganization(org.name);
36+
});
37+
38+
test("add new IdP group mapping with API",async({ page})=>{
39+
requiresLicense();
40+
constorg=awaitcreateOrganizationWithName(randomName());
41+
awaitcreateGroupSyncSettings(org.id);
42+
43+
awaitpage.goto(`/organizations/${org.name}/idp-sync?tab=groups`,{
44+
waitUntil:"domcontentloaded",
45+
});
46+
47+
awaitexpect(
48+
page.getByRole("switch",{name:"Auto create missing groups"}),
49+
).toBeChecked();
50+
51+
awaitexpect(page.getByRole("row",{name:"idp-group-1"})).toBeVisible();
52+
awaitexpect(
53+
page.getByRole("row",{name:"fbd2116a-8961-4954-87ae-e4575bd29ce0"}),
54+
).toBeVisible();
55+
56+
awaitexpect(page.getByRole("row",{name:"idp-group-2"})).toBeVisible();
57+
awaitexpect(
58+
page.getByRole("row",{name:"6b39f0f1-6ad8-4981-b2fc-d52aef53ff1b"}),
59+
).toBeVisible();
60+
61+
awaitdeleteOrganization(org.name);
62+
});
63+
64+
test("delete a IdP group to coder group mapping row",async({ page})=>{
65+
requiresLicense();
66+
constorg=awaitcreateOrganizationWithName(randomName());
67+
awaitcreateGroupSyncSettings(org.id);
68+
69+
awaitpage.goto(`/organizations/${org.name}/idp-sync?tab=groups`,{
70+
waitUntil:"domcontentloaded",
71+
});
72+
73+
constrow=page.getByTestId("group-idp-group-1");
74+
awaitexpect(row.getByRole("cell",{name:"idp-group-1"})).toBeVisible();
75+
awaitrow.getByRole("button",{name:/delete/i}).click();
76+
awaitexpect(
77+
row.getByRole("cell",{name:"idp-group-1"}),
78+
).not.toBeVisible();
79+
awaitexpect(
80+
page.getByText("IdP Group sync settings updated."),
81+
).toBeVisible();
82+
});
83+
84+
test("update sync field",async({ page})=>{
85+
requiresLicense();
86+
constorg=awaitcreateOrganizationWithName(randomName());
87+
awaitpage.goto(`/organizations/${org.name}/idp-sync?tab=groups`,{
88+
waitUntil:"domcontentloaded",
89+
});
90+
91+
constsyncField=page.getByRole("textbox",{
92+
name:"Group sync field",
93+
});
94+
constsaveButton=page.getByRole("button",{name:/save/i});
95+
96+
awaitexpect(saveButton).toBeDisabled();
97+
98+
awaitsyncField.fill("test-field");
99+
awaitexpect(saveButton).toBeEnabled();
100+
101+
awaitpage.getByRole("button",{name:/save/i}).click();
102+
103+
awaitexpect(
104+
page.getByText("IdP Group sync settings updated."),
105+
).toBeVisible();
106+
});
107+
108+
test("toggle off auto create missing groups",async({ page})=>{
109+
requiresLicense();
110+
constorg=awaitcreateOrganizationWithName(randomName());
111+
awaitpage.goto(`/organizations/${org.name}/idp-sync?tab=groups`,{
112+
waitUntil:"domcontentloaded",
113+
});
114+
115+
consttoggle=page.getByRole("switch",{
116+
name:"Auto create missing groups",
117+
});
118+
awaittoggle.click();
119+
120+
awaitexpect(
121+
page.getByText("IdP Group sync settings updated."),
122+
).toBeVisible();
123+
124+
awaitexpect(toggle).toBeChecked();
125+
});
126+
127+
test("export policy button is enabled when sync settings are present",async({
128+
page,
129+
})=>{
130+
requiresLicense();
131+
constorg=awaitcreateOrganizationWithName(randomName());
132+
awaitcreateGroupSyncSettings(org.id);
133+
awaitpage.goto(`/organizations/${org.name}/idp-sync?tab=groups`,{
134+
waitUntil:"domcontentloaded",
135+
});
136+
137+
constexportButton=page.getByRole("button",{name:/ExportPolicy/i});
138+
awaitexpect(exportButton).toBeEnabled();
139+
awaitexportButton.click();
140+
});
141+
142+
test("add new IdP group mapping with UI",async({ page})=>{
143+
requiresLicense();
144+
constorgName=randomName();
145+
awaitcreateOrganizationWithName(orgName);
146+
147+
awaitpage.goto(`/organizations/${orgName}/idp-sync?tab=groups`,{
148+
waitUntil:"domcontentloaded",
149+
});
150+
151+
constidpOrgInput=page.getByLabel("IdP group name");
152+
constorgSelector=page.getByPlaceholder("Select group");
153+
constaddButton=page.getByRole("button",{
154+
name:/AddIdPgroup/i,
155+
});
156+
157+
awaitexpect(addButton).toBeDisabled();
158+
159+
awaitidpOrgInput.fill("new-idp-group");
160+
161+
// Select Coder organization from combobox
162+
awaitorgSelector.click();
163+
awaitpage.getByRole("option",{name:/Everyone/i}).click();
164+
165+
// Add button should now be enabled
166+
awaitexpect(addButton).toBeEnabled();
167+
168+
awaitaddButton.click();
169+
170+
// Verify new mapping appears in table
171+
constnewRow=page.getByTestId("group-new-idp-group");
172+
awaitexpect(newRow).toBeVisible();
173+
awaitexpect(
174+
newRow.getByRole("cell",{name:"new-idp-group"}),
175+
).toBeVisible();
176+
awaitexpect(newRow.getByRole("cell",{name:"Everyone"})).toBeVisible();
177+
178+
awaitexpect(
179+
page.getByText("IdP Group sync settings updated."),
180+
).toBeVisible();
181+
182+
awaitdeleteOrganization(orgName);
183+
});
184+
});

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp