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>>;
|
} satisfies Record<string, Interpolation<Theme>>;
|
||||||
|
|
||||||
export const EnabledBadge: FC = () => {
|
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 = () => {
|
export const EntitledBadge: FC = () => {
|
||||||
|
@ -95,6 +99,7 @@ export const DisabledBadge: FC = forwardRef<
|
||||||
color: theme.experimental.l1.text,
|
color: theme.experimental.l1.text,
|
||||||
}),
|
}),
|
||||||
]}
|
]}
|
||||||
|
className="option-disabled"
|
||||||
>
|
>
|
||||||
Disabled
|
Disabled
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -34,19 +34,35 @@ export const OptionValue: FC<OptionValueProps> = (props) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
if (typeof value === "boolean") {
|
if (typeof value === "boolean") {
|
||||||
return value ? <EnabledBadge /> : <DisabledBadge />;
|
return (
|
||||||
|
<div className="option-value-boolean">
|
||||||
|
{value ? <EnabledBadge /> : <DisabledBadge />}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof value === "number") {
|
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) {
|
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") {
|
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)) {
|
if (typeof value === "object" && !Array.isArray(value)) {
|
||||||
|
@ -94,7 +110,7 @@ export const OptionValue: FC<OptionValueProps> = (props) => {
|
||||||
|
|
||||||
if (Array.isArray(value)) {
|
if (Array.isArray(value)) {
|
||||||
return (
|
return (
|
||||||
<ul css={{ listStylePosition: "inside" }}>
|
<ul css={{ listStylePosition: "inside" }} className="option-array">
|
||||||
{value.map((item) => (
|
{value.map((item) => (
|
||||||
<li key={item} css={styles.option}>
|
<li key={item} css={styles.option}>
|
||||||
{item}
|
{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 };
|
type OptionConfigProps = HTMLAttributes<HTMLDivElement> & { isSource: boolean };
|
||||||
|
|
Loading…
Reference in New Issue