Skip to content

Commit b598aef

Browse files
authored
test(site): add e2e tests for user auth (#12971)
1 parent 407e61e commit b598aef

File tree

4 files changed

+112
-47
lines changed

4 files changed

+112
-47
lines changed

site/e2e/api.ts

+66
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { Page } from "@playwright/test";
2+
import { expect } from "@playwright/test";
23
import * as API from "api/api";
34
import { coderPort } from "./constants";
45
import { findSessionToken, randomName } from "./helpers";
@@ -47,3 +48,68 @@ export const createGroup = async (orgId: string) => {
4748
});
4849
return group;
4950
};
51+
52+
export async function verifyConfigFlag(
53+
page: Page,
54+
config: API.DeploymentConfig,
55+
flag: string,
56+
) {
57+
const opt = config.options.find((option) => option.flag === flag);
58+
if (opt === undefined) {
59+
// must be undefined as `false` is expected
60+
throw new Error(`Option with env ${flag} has undefined value.`);
61+
}
62+
63+
// Map option type to test class name.
64+
let type: string;
65+
let value = opt.value;
66+
67+
if (typeof value === "boolean") {
68+
// Boolean options map to string (Enabled/Disabled).
69+
type = value ? "option-enabled" : "option-disabled";
70+
value = value ? "Enabled" : "Disabled";
71+
} else if (typeof value === "number") {
72+
type = "option-value-number";
73+
value = String(value);
74+
} else if (!value || value.length === 0) {
75+
type = "option-value-empty";
76+
} else if (typeof value === "string") {
77+
type = "option-value-string";
78+
} else if (typeof value === "object") {
79+
type = "option-array";
80+
} else {
81+
type = "option-value-json";
82+
}
83+
84+
// Special cases
85+
if (opt.flag === "strict-transport-security" && opt.value === 0) {
86+
type = "option-value-string";
87+
value = "Disabled"; // Display "Disabled" instead of zero seconds.
88+
}
89+
90+
const configOption = page.locator(
91+
`div.options-table .option-${flag} .${type}`,
92+
);
93+
94+
// Verify array of options with green marks.
95+
if (typeof value === "object" && !Array.isArray(value)) {
96+
Object.entries(value)
97+
.sort((a, b) => a[0].localeCompare(b[0]))
98+
.map(async ([item]) => {
99+
await expect(
100+
configOption.locator(`.option-array-item-${item}.option-enabled`, {
101+
hasText: item,
102+
}),
103+
).toBeVisible();
104+
});
105+
return;
106+
}
107+
// Verify array of options with simmple dots
108+
if (Array.isArray(value)) {
109+
for (const item of value) {
110+
await expect(configOption.locator("li", { hasText: item })).toBeVisible();
111+
}
112+
return;
113+
}
114+
await expect(configOption).toHaveText(String(value));
115+
}

site/e2e/playwright.config.ts

+9
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,15 @@ export default defineConfig({
111111
),
112112
CODER_PPROF_ADDRESS: "127.0.0.1:" + coderdPProfPort,
113113
CODER_EXPERIMENTS: e2eFakeExperiment1 + "," + e2eFakeExperiment2,
114+
115+
// Tests for Deployment / User Authentication / OIDC
116+
CODER_OIDC_ISSUER_URL: "https://accounts.google.com",
117+
CODER_OIDC_EMAIL_DOMAIN: "coder.com",
118+
CODER_OIDC_CLIENT_ID: "1234567890", // FIXME: https://github.com/coder/coder/issues/12585
119+
CODER_OIDC_CLIENT_SECRET: "1234567890Secret",
120+
CODER_OIDC_ALLOW_SIGNUPS: "false",
121+
CODER_OIDC_SIGN_IN_TEXT: "Hello",
122+
CODER_OIDC_ICON_URL: "/icon/google.svg",
114123
},
115124
reuseExistingServer: false,
116125
},
+4-47
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
import { expect, test, type Page } from "@playwright/test";
2-
import * as API from "api/api";
3-
import { setupApiCalls } from "../../api";
1+
import { test } from "@playwright/test";
2+
import { getDeploymentConfig } from "api/api";
3+
import { setupApiCalls, verifyConfigFlag } from "../../api";
44

55
test("enabled security settings", async ({ page }) => {
66
await setupApiCalls(page);
7-
8-
const config = await API.getDeploymentConfig();
7+
const config = await getDeploymentConfig();
98

109
await page.goto("/deployment/security", { waitUntil: "domcontentloaded" });
1110

@@ -27,45 +26,3 @@ test("enabled security settings", async ({ page }) => {
2726
await verifyConfigFlag(page, config, flag);
2827
}
2928
});
30-
31-
const verifyConfigFlag = async (
32-
page: Page,
33-
config: API.DeploymentConfig,
34-
flag: string,
35-
) => {
36-
const opt = config.options.find((option) => option.flag === flag);
37-
if (opt === undefined) {
38-
throw new Error(`Option with env ${flag} has undefined value.`);
39-
}
40-
41-
// Map option type to test class name.
42-
let type = "",
43-
value = opt.value;
44-
if (typeof value === "boolean") {
45-
// Boolean options map to string (Enabled/Disabled).
46-
type = value ? "option-enabled" : "option-disabled";
47-
value = value ? "Enabled" : "Disabled";
48-
} else if (typeof value === "number") {
49-
type = "option-value-number";
50-
value = String(value);
51-
} else if (!value || value.length === 0) {
52-
type = "option-value-empty";
53-
} else if (typeof value === "string") {
54-
type = "option-value-string";
55-
} else if (typeof value === "object") {
56-
type = "object-array";
57-
} else {
58-
type = "option-value-json";
59-
}
60-
61-
// Special cases
62-
if (opt.flag === "strict-transport-security" && opt.value === 0) {
63-
type = "option-value-string";
64-
value = "Disabled"; // Display "Disabled" instead of zero seconds.
65-
}
66-
67-
const configOption = page.locator(
68-
`div.options-table .option-${flag} .${type}`,
69-
);
70-
await expect(configOption).toHaveText(String(value));
71-
};
+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { test } from "@playwright/test";
2+
import { getDeploymentConfig } from "api/api";
3+
import { setupApiCalls, verifyConfigFlag } from "../../api";
4+
5+
test("login with OIDC", async ({ page }) => {
6+
await setupApiCalls(page);
7+
const config = await getDeploymentConfig();
8+
9+
await page.goto("/deployment/userauth", { waitUntil: "domcontentloaded" });
10+
11+
const flags = [
12+
"oidc-group-auto-create",
13+
"oidc-allow-signups",
14+
"oidc-auth-url-params",
15+
"oidc-client-id",
16+
"oidc-email-domain",
17+
"oidc-email-field",
18+
"oidc-group-mapping",
19+
"oidc-ignore-email-verified",
20+
"oidc-ignore-userinfo",
21+
"oidc-issuer-url",
22+
"oidc-group-regex-filter",
23+
"oidc-scopes",
24+
"oidc-user-role-mapping",
25+
"oidc-username-field",
26+
"oidc-sign-in-text",
27+
"oidc-icon-url",
28+
];
29+
30+
for (const flag of flags) {
31+
await verifyConfigFlag(page, config, flag);
32+
}
33+
});

0 commit comments

Comments
 (0)