Skip to content

Commit 26ccfe3

Browse files
committed
feat: add e2e tests for group and role sync
1 parent 6030922 commit 26ccfe3

File tree

3 files changed

+344
-0
lines changed

3 files changed

+344
-0
lines changed

site/e2e/api.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,42 @@ export const createOrganizationSyncSettings = async () => {
8888
return settings;
8989
};
9090

91+
export const createGroupSyncSettings = async (orgId: string) => {
92+
const settings = await API.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": ["fbd2116a-8961-4954-87ae-e4575bd29ce0"],
101+
},
102+
regex_filter: "@[a-zA-Z0-9]+",
103+
auto_create_missing_groups: true,
104+
},
105+
orgId,
106+
);
107+
return settings;
108+
};
109+
110+
export const createRoleSyncSettings = async (orgId: string) => {
111+
const settings = await API.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": ["fbd2116a-8961-4954-87ae-e4575bd29ce0"],
120+
},
121+
},
122+
orgId,
123+
);
124+
return settings;
125+
};
126+
91127
export const createCustomRole = async (
92128
orgId: string,
93129
name: string,
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
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+
await login(page);
15+
await setupApiCalls(page);
16+
});
17+
18+
test.describe("IdpGroupSyncPage", () => {
19+
test("add new IdP group mapping with API", async ({ page }) => {
20+
requiresLicense();
21+
const org = await createOrganizationWithName(randomName());
22+
await createGroupSyncSettings(org.id);
23+
24+
await page.goto(`/organizations/${org.name}/idp-sync?tab=groups`, {
25+
waitUntil: "domcontentloaded",
26+
});
27+
28+
await expect(
29+
page.getByRole("switch", { name: "Auto create missing groups" }),
30+
).toBeChecked();
31+
32+
await expect(page.getByText("idp-group-1")).toBeVisible();
33+
await expect(
34+
page.getByText("fbd2116a-8961-4954-87ae-e4575bd29ce0").first(),
35+
).toBeVisible();
36+
37+
await expect(page.getByText("idp-group-2")).toBeVisible();
38+
await expect(
39+
page.getByText("fbd2116a-8961-4954-87ae-e4575bd29ce0").last(),
40+
).toBeVisible();
41+
42+
await deleteOrganization(org.name);
43+
});
44+
45+
test("delete a IdP group to coder group mapping row", async ({ page }) => {
46+
requiresLicense();
47+
const org = await createOrganizationWithName(randomName());
48+
await createGroupSyncSettings(org.id);
49+
50+
await page.goto(`/organizations/${org.name}/idp-sync?tab=groups`, {
51+
waitUntil: "domcontentloaded",
52+
});
53+
54+
await expect(page.getByText("idp-group-1")).toBeVisible();
55+
await page
56+
.getByRole("button", { name: /delete/i })
57+
.first()
58+
.click();
59+
await expect(page.getByText("idp-group-1")).not.toBeVisible();
60+
await expect(
61+
page.getByText("IdP Group sync settings updated."),
62+
).toBeVisible();
63+
});
64+
65+
test("update sync field", async ({ page }) => {
66+
requiresLicense();
67+
const org = await createOrganizationWithName(randomName());
68+
await page.goto(`/organizations/${org.name}/idp-sync?tab=groups`, {
69+
waitUntil: "domcontentloaded",
70+
});
71+
72+
const syncField = page.getByRole("textbox", {
73+
name: "Group sync field",
74+
});
75+
const saveButton = page.getByRole("button", { name: /save/i }).first();
76+
77+
await expect(saveButton).toBeDisabled();
78+
79+
await syncField.fill("test-field");
80+
await expect(saveButton).toBeEnabled();
81+
82+
await page.getByRole("button", { name: /save/i }).click();
83+
84+
await expect(
85+
page.getByText("IdP Group sync settings updated."),
86+
).toBeVisible();
87+
});
88+
89+
test("toggle off auto create missing groups", async ({ page }) => {
90+
requiresLicense();
91+
const org = await createOrganizationWithName(randomName());
92+
await page.goto(`/organizations/${org.name}/idp-sync?tab=groups`, {
93+
waitUntil: "domcontentloaded",
94+
});
95+
96+
const toggle = page.getByRole("switch", {
97+
name: "Auto create missing groups",
98+
});
99+
await toggle.click();
100+
101+
await expect(
102+
page.getByText("IdP Group sync settings updated."),
103+
).toBeVisible();
104+
105+
await expect(toggle).toBeChecked();
106+
});
107+
108+
test("export policy button is enabled when sync settings are present", async ({
109+
page,
110+
}) => {
111+
requiresLicense();
112+
const org = await createOrganizationWithName(randomName());
113+
await createGroupSyncSettings(org.id);
114+
await page.goto(`/organizations/${org.name}/idp-sync?tab=groups`, {
115+
waitUntil: "domcontentloaded",
116+
});
117+
118+
const exportButton = page.getByRole("button", { name: /Export Policy/i });
119+
await expect(exportButton).toBeEnabled();
120+
await exportButton.click();
121+
});
122+
123+
test("add new IdP group mapping with UI", async ({ page }) => {
124+
requiresLicense();
125+
const orgName = randomName();
126+
await createOrganizationWithName(orgName);
127+
128+
await page.goto(`/organizations/${orgName}/idp-sync?tab=groups`, {
129+
waitUntil: "domcontentloaded",
130+
});
131+
132+
const idpOrgInput = page.getByLabel("IdP group name");
133+
const orgSelector = page.getByPlaceholder("Select group");
134+
const addButton = page.getByRole("button", {
135+
name: /Add IdP group/i,
136+
});
137+
138+
await expect(addButton).toBeDisabled();
139+
140+
await idpOrgInput.fill("new-idp-group");
141+
142+
// Select Coder organization from combobox
143+
await orgSelector.click();
144+
await page.getByRole("option", { name: /Everyone/i }).click();
145+
146+
// Add button should now be enabled
147+
await expect(addButton).toBeEnabled();
148+
149+
await addButton.click();
150+
151+
// Verify new mapping appears in table
152+
const newRow = page.getByTestId("group-new-idp-group");
153+
await expect(newRow).toBeVisible();
154+
await expect(newRow.getByText("new-idp-group")).toBeVisible();
155+
await expect(newRow.getByText("Everyone")).toBeVisible();
156+
157+
await expect(
158+
page.getByText("IdP Group sync settings updated."),
159+
).toBeVisible();
160+
161+
await deleteOrganization(orgName);
162+
});
163+
});
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
import { expect, test } from "@playwright/test";
2+
import {
3+
createOrganizationWithName,
4+
createRoleSyncSettings,
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+
await login(page);
15+
await setupApiCalls(page);
16+
});
17+
18+
test.describe("IdpRoleSyncPage", () => {
19+
test("add new IdP role mapping with API", async ({ page }) => {
20+
requiresLicense();
21+
const org = await createOrganizationWithName(randomName());
22+
await createRoleSyncSettings(org.id);
23+
24+
await page.goto(`/organizations/${org.name}/idp-sync?tab=roles`, {
25+
waitUntil: "domcontentloaded",
26+
});
27+
28+
await expect(page.getByText("idp-role-1")).toBeVisible();
29+
await expect(
30+
page.getByText("fbd2116a-8961-4954-87ae-e4575bd29ce0").first(),
31+
).toBeVisible();
32+
33+
await expect(page.getByText("idp-role-2")).toBeVisible();
34+
await expect(
35+
page.getByText("fbd2116a-8961-4954-87ae-e4575bd29ce0").last(),
36+
).toBeVisible();
37+
38+
await deleteOrganization(org.name);
39+
});
40+
41+
test("delete a IdP role to coder role mapping row", async ({ page }) => {
42+
requiresLicense();
43+
const org = await createOrganizationWithName(randomName());
44+
await createRoleSyncSettings(org.id);
45+
46+
await page.goto(`/organizations/${org.name}/idp-sync?tab=roles`, {
47+
waitUntil: "domcontentloaded",
48+
});
49+
50+
await expect(page.getByText("idp-role-1")).toBeVisible();
51+
await page
52+
.getByRole("button", { name: /delete/i })
53+
.first()
54+
.click();
55+
await expect(page.getByText("idp-role-1")).not.toBeVisible();
56+
await expect(
57+
page.getByText("IdP Role sync settings updated."),
58+
).toBeVisible();
59+
60+
await deleteOrganization(org.name);
61+
});
62+
63+
test("update sync field", async ({ page }) => {
64+
requiresLicense();
65+
const org = await createOrganizationWithName(randomName());
66+
await page.goto(`/organizations/${org.name}/idp-sync?tab=roles`, {
67+
waitUntil: "domcontentloaded",
68+
});
69+
70+
const syncField = page.getByRole("textbox", {
71+
name: "Role sync field",
72+
});
73+
const saveButton = page.getByRole("button", { name: /save/i }).first();
74+
75+
await expect(saveButton).toBeDisabled();
76+
77+
await syncField.fill("test-field");
78+
await expect(saveButton).toBeEnabled();
79+
80+
await page.getByRole("button", { name: /save/i }).click();
81+
82+
await expect(
83+
page.getByText("IdP Role sync settings updated."),
84+
).toBeVisible();
85+
86+
await deleteOrganization(org.name);
87+
});
88+
89+
test("export policy button is enabled when sync settings are present", async ({
90+
page,
91+
}) => {
92+
requiresLicense();
93+
const org = await createOrganizationWithName(randomName());
94+
await page.goto(`/organizations/${org.name}/idp-sync?tab=roles`, {
95+
waitUntil: "domcontentloaded",
96+
});
97+
98+
const exportButton = page.getByRole("button", { name: /Export Policy/i });
99+
await createRoleSyncSettings(org.id);
100+
101+
await expect(exportButton).toBeEnabled();
102+
await exportButton.click();
103+
});
104+
105+
test("add new IdP role mapping with UI", async ({ page }) => {
106+
requiresLicense();
107+
const orgName = randomName();
108+
await createOrganizationWithName(orgName);
109+
110+
await page.goto(`/organizations/${orgName}/idp-sync?tab=roles`, {
111+
waitUntil: "domcontentloaded",
112+
});
113+
114+
const idpOrgInput = page.getByLabel("IdP role name");
115+
const roleSelector = page.getByPlaceholder("Select role");
116+
const addButton = page.getByRole("button", {
117+
name: /Add IdP role/i,
118+
});
119+
120+
await expect(addButton).toBeDisabled();
121+
122+
await idpOrgInput.fill("new-idp-role");
123+
124+
// Select Coder role from combobox
125+
await roleSelector.click();
126+
await page.getByRole("option", { name: /Organization Admin/i }).click();
127+
128+
// Add button should now be enabled
129+
await expect(addButton).toBeEnabled();
130+
131+
await addButton.click();
132+
133+
// Verify new mapping appears in table
134+
const newRow = page.getByTestId("role-new-idp-role");
135+
await expect(newRow).toBeVisible();
136+
await expect(newRow.getByText("new-idp-role")).toBeVisible();
137+
await expect(newRow.getByText("organization-admin")).toBeVisible();
138+
139+
await expect(
140+
page.getByText("IdP Role sync settings updated."),
141+
).toBeVisible();
142+
143+
await deleteOrganization(orgName);
144+
});
145+
});

0 commit comments

Comments
 (0)