mirror of https://github.com/coder/coder.git
test(site): add e2e tests for security (#12961)
This commit is contained in:
parent
9a4703a311
commit
49689162bb
|
@ -0,0 +1,71 @@
|
|||
import { expect, test, type Page } from "@playwright/test";
|
||||
import * as API from "api/api";
|
||||
import { setupApiCalls } from "../../api";
|
||||
|
||||
test("enabled security settings", async ({ page }) => {
|
||||
await setupApiCalls(page);
|
||||
|
||||
const config = await API.getDeploymentConfig();
|
||||
|
||||
await page.goto("/deployment/security", { waitUntil: "domcontentloaded" });
|
||||
|
||||
const flags = [
|
||||
"ssh-keygen-algorithm",
|
||||
"secure-auth-cookie",
|
||||
"disable-owner-workspace-access",
|
||||
|
||||
"tls-redirect-http-to-https",
|
||||
"strict-transport-security",
|
||||
"tls-address",
|
||||
"tls-allow-insecure-ciphers",
|
||||
"tls-client-auth",
|
||||
"tls-enable",
|
||||
"tls-min-version",
|
||||
];
|
||||
|
||||
for (const flag of flags) {
|
||||
await verifyConfigFlag(page, config, flag);
|
||||
}
|
||||
});
|
||||
|
||||
const verifyConfigFlag = async (
|
||||
page: Page,
|
||||
config: API.DeploymentConfig,
|
||||
flag: string,
|
||||
) => {
|
||||
const opt = config.options.find((option) => option.flag === flag);
|
||||
if (opt === undefined) {
|
||||
throw new Error(`Option with env ${flag} has undefined value.`);
|
||||
}
|
||||
|
||||
// Map option type to test class name.
|
||||
let type = "",
|
||||
value = opt.value;
|
||||
if (typeof value === "boolean") {
|
||||
// Boolean options map to string (Enabled/Disabled).
|
||||
type = value ? "option-enabled" : "option-disabled";
|
||||
value = value ? "Enabled" : "Disabled";
|
||||
} else if (typeof value === "number") {
|
||||
type = "option-value-number";
|
||||
value = String(value);
|
||||
} else if (!value || value.length === 0) {
|
||||
type = "option-value-empty";
|
||||
} else if (typeof value === "string") {
|
||||
type = "option-value-string";
|
||||
} else if (typeof value === "object") {
|
||||
type = "object-array";
|
||||
} else {
|
||||
type = "option-value-json";
|
||||
}
|
||||
|
||||
// Special cases
|
||||
if (opt.flag === "strict-transport-security" && opt.value === 0) {
|
||||
type = "option-value-string";
|
||||
value = "Disabled"; // Display "Disabled" instead of zero seconds.
|
||||
}
|
||||
|
||||
const configOption = page.locator(
|
||||
`div.options-table .option-${flag} .${type}`,
|
||||
);
|
||||
await expect(configOption).toHaveText(String(value));
|
||||
};
|
|
@ -41,7 +41,11 @@ const styles = {
|
|||
} satisfies Record<string, Interpolation<Theme>>;
|
||||
|
||||
export const EnabledBadge: FC = () => {
|
||||
return <span css={[styles.badge, styles.enabledBadge]}>Enabled</span>;
|
||||
return (
|
||||
<span css={[styles.badge, styles.enabledBadge]} className="option-enabled">
|
||||
Enabled
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
export const EntitledBadge: FC = () => {
|
||||
|
@ -95,6 +99,7 @@ export const DisabledBadge: FC = forwardRef<
|
|||
color: theme.experimental.l1.text,
|
||||
}),
|
||||
]}
|
||||
className="option-disabled"
|
||||
>
|
||||
Disabled
|
||||
</span>
|
||||
|
|
|
@ -34,19 +34,35 @@ export const OptionValue: FC<OptionValueProps> = (props) => {
|
|||
const theme = useTheme();
|
||||
|
||||
if (typeof value === "boolean") {
|
||||
return value ? <EnabledBadge /> : <DisabledBadge />;
|
||||
return (
|
||||
<div className="option-value-boolean">
|
||||
{value ? <EnabledBadge /> : <DisabledBadge />}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (typeof value === "number") {
|
||||
return <span css={styles.option}>{value}</span>;
|
||||
return (
|
||||
<span css={styles.option} className="option-value-number">
|
||||
{value}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
if (!value || value.length === 0) {
|
||||
return <span css={styles.option}>Not set</span>;
|
||||
return (
|
||||
<span css={styles.option} className="option-value-empty">
|
||||
Not set
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
if (typeof value === "string") {
|
||||
return <span css={styles.option}>{value}</span>;
|
||||
return (
|
||||
<span css={styles.option} className="option-value-string">
|
||||
{value}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
if (typeof value === "object" && !Array.isArray(value)) {
|
||||
|
@ -94,7 +110,7 @@ export const OptionValue: FC<OptionValueProps> = (props) => {
|
|||
|
||||
if (Array.isArray(value)) {
|
||||
return (
|
||||
<ul css={{ listStylePosition: "inside" }}>
|
||||
<ul css={{ listStylePosition: "inside" }} className="option-array">
|
||||
{value.map((item) => (
|
||||
<li key={item} css={styles.option}>
|
||||
{item}
|
||||
|
@ -104,7 +120,11 @@ export const OptionValue: FC<OptionValueProps> = (props) => {
|
|||
);
|
||||
}
|
||||
|
||||
return <span css={styles.option}>{JSON.stringify(value)}</span>;
|
||||
return (
|
||||
<span css={styles.option} className="option-value-json">
|
||||
{JSON.stringify(value)}
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
type OptionConfigProps = HTMLAttributes<HTMLDivElement> & { isSource: boolean };
|
||||
|
|
Loading…
Reference in New Issue