refactor(site): verify deployment config flags in e2e tests (#12986)

This commit is contained in:
Marcin Tojek 2024-04-17 13:51:55 +02:00 committed by GitHub
parent 0c993566dd
commit ee7dda8111
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 140 additions and 95 deletions

View File

@ -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));
} }

View File

@ -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");
}

View File

@ -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);
}
}); });