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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy