mirror of https://github.com/coder/coder.git
refactor(site): verify deployment config flags in e2e tests (#12986)
This commit is contained in:
parent
0c993566dd
commit
ee7dda8111
134
site/e2e/api.ts
134
site/e2e/api.ts
|
@ -1,6 +1,7 @@
|
||||||
import type { Page } from "@playwright/test";
|
import type { Page } from "@playwright/test";
|
||||||
import { expect } from "@playwright/test";
|
import { expect } from "@playwright/test";
|
||||||
import * as API from "api/api";
|
import * as API from "api/api";
|
||||||
|
import type { SerpentOption } from "api/typesGenerated";
|
||||||
import { coderPort } from "./constants";
|
import { coderPort } from "./constants";
|
||||||
import { findSessionToken, randomName } from "./helpers";
|
import { findSessionToken, randomName } from "./helpers";
|
||||||
|
|
||||||
|
@ -49,67 +50,92 @@ export const createGroup = async (orgId: string) => {
|
||||||
return group;
|
return group;
|
||||||
};
|
};
|
||||||
|
|
||||||
export async function verifyConfigFlag(
|
export async function verifyConfigFlagBoolean(
|
||||||
page: Page,
|
page: Page,
|
||||||
config: API.DeploymentConfig,
|
config: API.DeploymentConfig,
|
||||||
flag: string,
|
flag: string,
|
||||||
) {
|
) {
|
||||||
|
const opt = findConfigOption(config, flag);
|
||||||
|
const type = opt.value ? "option-enabled" : "option-disabled";
|
||||||
|
const value = opt.value ? "Enabled" : "Disabled";
|
||||||
|
|
||||||
|
const configOption = page.locator(
|
||||||
|
`div.options-table .option-${flag} .${type}`,
|
||||||
|
);
|
||||||
|
await expect(configOption).toHaveText(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function verifyConfigFlagNumber(
|
||||||
|
page: Page,
|
||||||
|
config: API.DeploymentConfig,
|
||||||
|
flag: string,
|
||||||
|
) {
|
||||||
|
const opt = findConfigOption(config, flag);
|
||||||
|
const configOption = page.locator(
|
||||||
|
`div.options-table .option-${flag} .option-value-number`,
|
||||||
|
);
|
||||||
|
await expect(configOption).toHaveText(String(opt.value));
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function verifyConfigFlagString(
|
||||||
|
page: Page,
|
||||||
|
config: API.DeploymentConfig,
|
||||||
|
flag: string,
|
||||||
|
) {
|
||||||
|
const opt = findConfigOption(config, flag);
|
||||||
|
|
||||||
|
const configOption = page.locator(
|
||||||
|
`div.options-table .option-${flag} .option-value-string`,
|
||||||
|
);
|
||||||
|
await expect(configOption).toHaveText(opt.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function verifyConfigFlagArray(
|
||||||
|
page: Page,
|
||||||
|
config: API.DeploymentConfig,
|
||||||
|
flag: string,
|
||||||
|
) {
|
||||||
|
const opt = findConfigOption(config, flag);
|
||||||
|
const configOption = page.locator(
|
||||||
|
`div.options-table .option-${flag} .option-array`,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Verify array of options with simple dots
|
||||||
|
for (const item of opt.value) {
|
||||||
|
await expect(configOption.locator("li", { hasText: item })).toBeVisible();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function verifyConfigFlagEntries(
|
||||||
|
page: Page,
|
||||||
|
config: API.DeploymentConfig,
|
||||||
|
flag: string,
|
||||||
|
) {
|
||||||
|
const opt = findConfigOption(config, flag);
|
||||||
|
const configOption = page.locator(
|
||||||
|
`div.options-table .option-${flag} .option-array`,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Verify array of options with green marks.
|
||||||
|
Object.entries(opt.value)
|
||||||
|
.sort((a, b) => a[0].localeCompare(b[0]))
|
||||||
|
.map(async ([item]) => {
|
||||||
|
await expect(
|
||||||
|
configOption.locator(`.option-array-item-${item}.option-enabled`, {
|
||||||
|
hasText: item,
|
||||||
|
}),
|
||||||
|
).toBeVisible();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function findConfigOption(
|
||||||
|
config: API.DeploymentConfig,
|
||||||
|
flag: string,
|
||||||
|
): SerpentOption {
|
||||||
const opt = config.options.find((option) => option.flag === flag);
|
const opt = config.options.find((option) => option.flag === flag);
|
||||||
if (opt === undefined) {
|
if (opt === undefined) {
|
||||||
// must be undefined as `false` is expected
|
// must be undefined as `false` is expected
|
||||||
throw new Error(`Option with env ${flag} has undefined value.`);
|
throw new Error(`Option with env ${flag} has undefined value.`);
|
||||||
}
|
}
|
||||||
|
return opt;
|
||||||
// Map option type to test class name.
|
|
||||||
let type: string;
|
|
||||||
let 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 = "option-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}`,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Verify array of options with green marks.
|
|
||||||
if (typeof value === "object" && !Array.isArray(value)) {
|
|
||||||
Object.entries(value)
|
|
||||||
.sort((a, b) => a[0].localeCompare(b[0]))
|
|
||||||
.map(async ([item]) => {
|
|
||||||
await expect(
|
|
||||||
configOption.locator(`.option-array-item-${item}.option-enabled`, {
|
|
||||||
hasText: item,
|
|
||||||
}),
|
|
||||||
).toBeVisible();
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Verify array of options with simmple dots
|
|
||||||
if (Array.isArray(value)) {
|
|
||||||
for (const item of value) {
|
|
||||||
await expect(configOption.locator("li", { hasText: item })).toBeVisible();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
await expect(configOption).toHaveText(String(value));
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,14 @@
|
||||||
import { test } from "@playwright/test";
|
import type { Page } from "@playwright/test";
|
||||||
|
import { expect, test } from "@playwright/test";
|
||||||
|
import type * as API from "api/api";
|
||||||
import { getDeploymentConfig } from "api/api";
|
import { getDeploymentConfig } from "api/api";
|
||||||
import { setupApiCalls, verifyConfigFlag } from "../../api";
|
import {
|
||||||
|
findConfigOption,
|
||||||
|
setupApiCalls,
|
||||||
|
verifyConfigFlagBoolean,
|
||||||
|
verifyConfigFlagNumber,
|
||||||
|
verifyConfigFlagString,
|
||||||
|
} from "../../api";
|
||||||
|
|
||||||
test("enabled security settings", async ({ page }) => {
|
test("enabled security settings", async ({ page }) => {
|
||||||
await setupApiCalls(page);
|
await setupApiCalls(page);
|
||||||
|
@ -8,21 +16,32 @@ test("enabled security settings", async ({ page }) => {
|
||||||
|
|
||||||
await page.goto("/deployment/security", { waitUntil: "domcontentloaded" });
|
await page.goto("/deployment/security", { waitUntil: "domcontentloaded" });
|
||||||
|
|
||||||
const flags = [
|
await verifyConfigFlagString(page, config, "ssh-keygen-algorithm");
|
||||||
"ssh-keygen-algorithm",
|
await verifyConfigFlagBoolean(page, config, "secure-auth-cookie");
|
||||||
"secure-auth-cookie",
|
await verifyConfigFlagBoolean(page, config, "disable-owner-workspace-access");
|
||||||
"disable-owner-workspace-access",
|
|
||||||
|
|
||||||
"tls-redirect-http-to-https",
|
await verifyConfigFlagBoolean(page, config, "tls-redirect-http-to-https");
|
||||||
"strict-transport-security",
|
await verifyStrictTransportSecurity(page, config);
|
||||||
"tls-address",
|
await verifyConfigFlagString(page, config, "tls-address");
|
||||||
"tls-allow-insecure-ciphers",
|
await verifyConfigFlagBoolean(page, config, "tls-allow-insecure-ciphers");
|
||||||
"tls-client-auth",
|
await verifyConfigFlagString(page, config, "tls-client-auth");
|
||||||
"tls-enable",
|
await verifyConfigFlagBoolean(page, config, "tls-enable");
|
||||||
"tls-min-version",
|
await verifyConfigFlagString(page, config, "tls-min-version");
|
||||||
];
|
|
||||||
|
|
||||||
for (const flag of flags) {
|
|
||||||
await verifyConfigFlag(page, config, flag);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
async function verifyStrictTransportSecurity(
|
||||||
|
page: Page,
|
||||||
|
config: API.DeploymentConfig,
|
||||||
|
) {
|
||||||
|
const flag = "strict-transport-security";
|
||||||
|
const opt = findConfigOption(config, flag);
|
||||||
|
if (opt.value !== 0) {
|
||||||
|
await verifyConfigFlagNumber(page, config, flag);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const configOption = page.locator(
|
||||||
|
`div.options-table .option-${flag} .option-value-string`,
|
||||||
|
);
|
||||||
|
await expect(configOption).toHaveText("Disabled");
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
import { test } from "@playwright/test";
|
import { test } from "@playwright/test";
|
||||||
import { getDeploymentConfig } from "api/api";
|
import { getDeploymentConfig } from "api/api";
|
||||||
import { setupApiCalls, verifyConfigFlag } from "../../api";
|
import {
|
||||||
|
setupApiCalls,
|
||||||
|
verifyConfigFlagArray,
|
||||||
|
verifyConfigFlagBoolean,
|
||||||
|
verifyConfigFlagEntries,
|
||||||
|
verifyConfigFlagString,
|
||||||
|
} from "../../api";
|
||||||
|
|
||||||
test("login with OIDC", async ({ page }) => {
|
test("login with OIDC", async ({ page }) => {
|
||||||
await setupApiCalls(page);
|
await setupApiCalls(page);
|
||||||
|
@ -8,26 +14,20 @@ test("login with OIDC", async ({ page }) => {
|
||||||
|
|
||||||
await page.goto("/deployment/userauth", { waitUntil: "domcontentloaded" });
|
await page.goto("/deployment/userauth", { waitUntil: "domcontentloaded" });
|
||||||
|
|
||||||
const flags = [
|
await verifyConfigFlagBoolean(page, config, "oidc-group-auto-create");
|
||||||
"oidc-group-auto-create",
|
await verifyConfigFlagBoolean(page, config, "oidc-allow-signups");
|
||||||
"oidc-allow-signups",
|
await verifyConfigFlagEntries(page, config, "oidc-auth-url-params");
|
||||||
"oidc-auth-url-params",
|
await verifyConfigFlagString(page, config, "oidc-client-id");
|
||||||
"oidc-client-id",
|
await verifyConfigFlagArray(page, config, "oidc-email-domain");
|
||||||
"oidc-email-domain",
|
await verifyConfigFlagString(page, config, "oidc-email-field");
|
||||||
"oidc-email-field",
|
await verifyConfigFlagEntries(page, config, "oidc-group-mapping");
|
||||||
"oidc-group-mapping",
|
await verifyConfigFlagBoolean(page, config, "oidc-ignore-email-verified");
|
||||||
"oidc-ignore-email-verified",
|
await verifyConfigFlagBoolean(page, config, "oidc-ignore-userinfo");
|
||||||
"oidc-ignore-userinfo",
|
await verifyConfigFlagString(page, config, "oidc-issuer-url");
|
||||||
"oidc-issuer-url",
|
await verifyConfigFlagString(page, config, "oidc-group-regex-filter");
|
||||||
"oidc-group-regex-filter",
|
await verifyConfigFlagArray(page, config, "oidc-scopes");
|
||||||
"oidc-scopes",
|
await verifyConfigFlagEntries(page, config, "oidc-user-role-mapping");
|
||||||
"oidc-user-role-mapping",
|
await verifyConfigFlagString(page, config, "oidc-username-field");
|
||||||
"oidc-username-field",
|
await verifyConfigFlagString(page, config, "oidc-sign-in-text");
|
||||||
"oidc-sign-in-text",
|
await verifyConfigFlagString(page, config, "oidc-icon-url");
|
||||||
"oidc-icon-url",
|
|
||||||
];
|
|
||||||
|
|
||||||
for (const flag of flags) {
|
|
||||||
await verifyConfigFlag(page, config, flag);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue