Skip to content

Commit 4968916

Browse files
authored
test(site): add e2e tests for security (#12961)
1 parent 9a4703a commit 4968916

File tree

3 files changed

+103
-7
lines changed

3 files changed

+103
-7
lines changed
+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { expect, test, type Page } from "@playwright/test";
2+
import * as API from "api/api";
3+
import { setupApiCalls } from "../../api";
4+
5+
test("enabled security settings", async ({ page }) => {
6+
await setupApiCalls(page);
7+
8+
const config = await API.getDeploymentConfig();
9+
10+
await page.goto("/deployment/security", { waitUntil: "domcontentloaded" });
11+
12+
const flags = [
13+
"ssh-keygen-algorithm",
14+
"secure-auth-cookie",
15+
"disable-owner-workspace-access",
16+
17+
"tls-redirect-http-to-https",
18+
"strict-transport-security",
19+
"tls-address",
20+
"tls-allow-insecure-ciphers",
21+
"tls-client-auth",
22+
"tls-enable",
23+
"tls-min-version",
24+
];
25+
26+
for (const flag of flags) {
27+
await verifyConfigFlag(page, config, flag);
28+
}
29+
});
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+
};

site/src/components/Badges/Badges.tsx

+6-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,11 @@ const styles = {
4141
} satisfies Record<string, Interpolation<Theme>>;
4242

4343
export const EnabledBadge: FC = () => {
44-
return <span css={[styles.badge, styles.enabledBadge]}>Enabled</span>;
44+
return (
45+
<span css={[styles.badge, styles.enabledBadge]} className="option-enabled">
46+
Enabled
47+
</span>
48+
);
4549
};
4650

4751
export const EntitledBadge: FC = () => {
@@ -95,6 +99,7 @@ export const DisabledBadge: FC = forwardRef<
9599
color: theme.experimental.l1.text,
96100
}),
97101
]}
102+
className="option-disabled"
98103
>
99104
Disabled
100105
</span>

site/src/pages/DeploySettingsPage/Option.tsx

+26-6
Original file line numberDiff line numberDiff line change
@@ -34,19 +34,35 @@ export const OptionValue: FC<OptionValueProps> = (props) => {
3434
const theme = useTheme();
3535

3636
if (typeof value === "boolean") {
37-
return value ? <EnabledBadge /> : <DisabledBadge />;
37+
return (
38+
<div className="option-value-boolean">
39+
{value ? <EnabledBadge /> : <DisabledBadge />}
40+
</div>
41+
);
3842
}
3943

4044
if (typeof value === "number") {
41-
return <span css={styles.option}>{value}</span>;
45+
return (
46+
<span css={styles.option} className="option-value-number">
47+
{value}
48+
</span>
49+
);
4250
}
4351

4452
if (!value || value.length === 0) {
45-
return <span css={styles.option}>Not set</span>;
53+
return (
54+
<span css={styles.option} className="option-value-empty">
55+
Not set
56+
</span>
57+
);
4658
}
4759

4860
if (typeof value === "string") {
49-
return <span css={styles.option}>{value}</span>;
61+
return (
62+
<span css={styles.option} className="option-value-string">
63+
{value}
64+
</span>
65+
);
5066
}
5167

5268
if (typeof value === "object" && !Array.isArray(value)) {
@@ -94,7 +110,7 @@ export const OptionValue: FC<OptionValueProps> = (props) => {
94110

95111
if (Array.isArray(value)) {
96112
return (
97-
<ul css={{ listStylePosition: "inside" }}>
113+
<ul css={{ listStylePosition: "inside" }} className="option-array">
98114
{value.map((item) => (
99115
<li key={item} css={styles.option}>
100116
{item}
@@ -104,7 +120,11 @@ export const OptionValue: FC<OptionValueProps> = (props) => {
104120
);
105121
}
106122

107-
return <span css={styles.option}>{JSON.stringify(value)}</span>;
123+
return (
124+
<span css={styles.option} className="option-value-json">
125+
{JSON.stringify(value)}
126+
</span>
127+
);
108128
};
109129

110130
type OptionConfigProps = HTMLAttributes<HTMLDivElement> & { isSource: boolean };

0 commit comments

Comments
 (0)