Skip to content

Commit ee7dda8

Browse files
authored
refactor(site): verify deployment config flags in e2e tests (#12986)
1 parent 0c99356 commit ee7dda8

File tree

3 files changed

+134
-89
lines changed

3 files changed

+134
-89
lines changed

site/e2e/api.ts

+75-49
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { Page } from "@playwright/test";
22
import { expect } from "@playwright/test";
33
import * as API from "api/api";
4+
import type { SerpentOption } from "api/typesGenerated";
45
import { coderPort } from "./constants";
56
import { findSessionToken, randomName } from "./helpers";
67

@@ -49,67 +50,92 @@ export const createGroup = async (orgId: string) => {
4950
return group;
5051
};
5152

52-
export async function verifyConfigFlag(
53+
export async function verifyConfigFlagBoolean(
5354
page: Page,
5455
config: API.DeploymentConfig,
5556
flag: string,
5657
) {
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-
}
58+
const opt = findConfigOption(config, flag);
59+
const type = opt.value ? "option-enabled" : "option-disabled";
60+
const value = opt.value ? "Enabled" : "Disabled";
6261

63-
// Map option type to test class name.
64-
let type: string;
65-
let value = opt.value;
62+
const configOption = page.locator(
63+
`div.options-table .option-${flag} .${type}`,
64+
);
65+
await expect(configOption).toHaveText(value);
66+
}
6667

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-
}
68+
export async function verifyConfigFlagNumber(
69+
page: Page,
70+
config: API.DeploymentConfig,
71+
flag: string,
72+
) {
73+
const opt = findConfigOption(config, flag);
74+
const configOption = page.locator(
75+
`div.options-table .option-${flag} .option-value-number`,
76+
);
77+
await expect(configOption).toHaveText(String(opt.value));
78+
}
79+
80+
export async function verifyConfigFlagString(
81+
page: Page,
82+
config: API.DeploymentConfig,
83+
flag: string,
84+
) {
85+
const opt = findConfigOption(config, flag);
86+
87+
const configOption = page.locator(
88+
`div.options-table .option-${flag} .option-value-string`,
89+
);
90+
await expect(configOption).toHaveText(opt.value);
91+
}
92+
93+
export async function verifyConfigFlagArray(
94+
page: Page,
95+
config: API.DeploymentConfig,
96+
flag: string,
97+
) {
98+
const opt = findConfigOption(config, flag);
99+
const configOption = page.locator(
100+
`div.options-table .option-${flag} .option-array`,
101+
);
83102

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.
103+
// Verify array of options with simple dots
104+
for (const item of opt.value) {
105+
await expect(configOption.locator("li", { hasText: item })).toBeVisible();
88106
}
107+
}
89108

109+
export async function verifyConfigFlagEntries(
110+
page: Page,
111+
config: API.DeploymentConfig,
112+
flag: string,
113+
) {
114+
const opt = findConfigOption(config, flag);
90115
const configOption = page.locator(
91-
`div.options-table .option-${flag} .${type}`,
116+
`div.options-table .option-${flag} .option-array`,
92117
);
93118

94119
// 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;
120+
Object.entries(opt.value)
121+
.sort((a, b) => a[0].localeCompare(b[0]))
122+
.map(async ([item]) => {
123+
await expect(
124+
configOption.locator(`.option-array-item-${item}.option-enabled`, {
125+
hasText: item,
126+
}),
127+
).toBeVisible();
128+
});
129+
}
130+
131+
export function findConfigOption(
132+
config: API.DeploymentConfig,
133+
flag: string,
134+
): SerpentOption {
135+
const opt = config.options.find((option) => option.flag === flag);
136+
if (opt === undefined) {
137+
// must be undefined as `false` is expected
138+
throw new Error(`Option with env ${flag} has undefined value.`);
113139
}
114-
await expect(configOption).toHaveText(String(value));
140+
return opt;
115141
}
+36-17
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,47 @@
1-
import { test } from "@playwright/test";
1+
import type { Page } from "@playwright/test";
2+
import { expect, test } from "@playwright/test";
3+
import type * as API from "api/api";
24
import { getDeploymentConfig } from "api/api";
3-
import { setupApiCalls, verifyConfigFlag } from "../../api";
5+
import {
6+
findConfigOption,
7+
setupApiCalls,
8+
verifyConfigFlagBoolean,
9+
verifyConfigFlagNumber,
10+
verifyConfigFlagString,
11+
} from "../../api";
412

513
test("enabled security settings", async ({ page }) => {
614
await setupApiCalls(page);
715
const config = await getDeploymentConfig();
816

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

11-
const flags = [
12-
"ssh-keygen-algorithm",
13-
"secure-auth-cookie",
14-
"disable-owner-workspace-access",
19+
await verifyConfigFlagString(page, config, "ssh-keygen-algorithm");
20+
await verifyConfigFlagBoolean(page, config, "secure-auth-cookie");
21+
await verifyConfigFlagBoolean(page, config, "disable-owner-workspace-access");
1522

16-
"tls-redirect-http-to-https",
17-
"strict-transport-security",
18-
"tls-address",
19-
"tls-allow-insecure-ciphers",
20-
"tls-client-auth",
21-
"tls-enable",
22-
"tls-min-version",
23-
];
23+
await verifyConfigFlagBoolean(page, config, "tls-redirect-http-to-https");
24+
await verifyStrictTransportSecurity(page, config);
25+
await verifyConfigFlagString(page, config, "tls-address");
26+
await verifyConfigFlagBoolean(page, config, "tls-allow-insecure-ciphers");
27+
await verifyConfigFlagString(page, config, "tls-client-auth");
28+
await verifyConfigFlagBoolean(page, config, "tls-enable");
29+
await verifyConfigFlagString(page, config, "tls-min-version");
30+
});
2431

25-
for (const flag of flags) {
26-
await verifyConfigFlag(page, config, flag);
32+
async function verifyStrictTransportSecurity(
33+
page: Page,
34+
config: API.DeploymentConfig,
35+
) {
36+
const flag = "strict-transport-security";
37+
const opt = findConfigOption(config, flag);
38+
if (opt.value !== 0) {
39+
await verifyConfigFlagNumber(page, config, flag);
40+
return;
2741
}
28-
});
42+
43+
const configOption = page.locator(
44+
`div.options-table .option-${flag} .option-value-string`,
45+
);
46+
await expect(configOption).toHaveText("Disabled");
47+
}
+23-23
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,33 @@
11
import { test } from "@playwright/test";
22
import { getDeploymentConfig } from "api/api";
3-
import { setupApiCalls, verifyConfigFlag } from "../../api";
3+
import {
4+
setupApiCalls,
5+
verifyConfigFlagArray,
6+
verifyConfigFlagBoolean,
7+
verifyConfigFlagEntries,
8+
verifyConfigFlagString,
9+
} from "../../api";
410

511
test("login with OIDC", async ({ page }) => {
612
await setupApiCalls(page);
713
const config = await getDeploymentConfig();
814

915
await page.goto("/deployment/userauth", { waitUntil: "domcontentloaded" });
1016

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-
}
17+
await verifyConfigFlagBoolean(page, config, "oidc-group-auto-create");
18+
await verifyConfigFlagBoolean(page, config, "oidc-allow-signups");
19+
await verifyConfigFlagEntries(page, config, "oidc-auth-url-params");
20+
await verifyConfigFlagString(page, config, "oidc-client-id");
21+
await verifyConfigFlagArray(page, config, "oidc-email-domain");
22+
await verifyConfigFlagString(page, config, "oidc-email-field");
23+
await verifyConfigFlagEntries(page, config, "oidc-group-mapping");
24+
await verifyConfigFlagBoolean(page, config, "oidc-ignore-email-verified");
25+
await verifyConfigFlagBoolean(page, config, "oidc-ignore-userinfo");
26+
await verifyConfigFlagString(page, config, "oidc-issuer-url");
27+
await verifyConfigFlagString(page, config, "oidc-group-regex-filter");
28+
await verifyConfigFlagArray(page, config, "oidc-scopes");
29+
await verifyConfigFlagEntries(page, config, "oidc-user-role-mapping");
30+
await verifyConfigFlagString(page, config, "oidc-username-field");
31+
await verifyConfigFlagString(page, config, "oidc-sign-in-text");
32+
await verifyConfigFlagString(page, config, "oidc-icon-url");
3333
});

0 commit comments

Comments
 (0)