test(site): add e2e tests for experiments (#12940)

This commit is contained in:
Marcin Tojek 2024-04-12 10:42:27 +02:00 committed by GitHub
parent b163bc7f01
commit dcf1d3a9ae
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 61 additions and 5 deletions

View File

@ -37,3 +37,7 @@ export const requireEnterpriseTests = Boolean(
process.env.CODER_E2E_REQUIRE_ENTERPRISE_TESTS, process.env.CODER_E2E_REQUIRE_ENTERPRISE_TESTS,
); );
export const enterpriseLicense = process.env.CODER_E2E_ENTERPRISE_LICENSE ?? ""; export const enterpriseLicense = process.env.CODER_E2E_ENTERPRISE_LICENSE ?? "";
// Fake experiments to verify that site presents them as enabled.
export const e2eFakeExperiment1 = "e2e-fake-experiment-1";
export const e2eFakeExperiment2 = "e2e-fake-experiment-2";

View File

@ -1,6 +1,13 @@
import { defineConfig } from "@playwright/test"; import { defineConfig } from "@playwright/test";
import * as path from "path"; import * as path from "path";
import { coderMain, coderPort, coderdPProfPort, gitAuth } from "./constants"; import {
coderMain,
coderPort,
coderdPProfPort,
e2eFakeExperiment1,
e2eFakeExperiment2,
gitAuth,
} from "./constants";
export const wsEndpoint = process.env.CODER_E2E_WS_ENDPOINT; export const wsEndpoint = process.env.CODER_E2E_WS_ENDPOINT;
@ -22,7 +29,7 @@ export default defineConfig({
testMatch: /.*\.spec\.ts/, testMatch: /.*\.spec\.ts/,
dependencies: ["testsSetup"], dependencies: ["testsSetup"],
use: { storageState }, use: { storageState },
timeout: 20_000, timeout: 50_000,
}, },
], ],
reporter: [["./reporter.ts"]], reporter: [["./reporter.ts"]],
@ -60,6 +67,8 @@ export default defineConfig({
.join(" "), .join(" "),
env: { env: {
...process.env, ...process.env,
// Otherwise, the runner fails on Mac with: could not determine kind of name for C.uuid_string_t
CGO_ENABLED: "0",
// This is the test provider for git auth with devices! // This is the test provider for git auth with devices!
CODER_GITAUTH_0_ID: gitAuth.deviceProvider, CODER_GITAUTH_0_ID: gitAuth.deviceProvider,
@ -101,6 +110,7 @@ export default defineConfig({
gitAuth.validatePath, gitAuth.validatePath,
), ),
CODER_PPROF_ADDRESS: "127.0.0.1:" + coderdPProfPort, CODER_PPROF_ADDRESS: "127.0.0.1:" + coderdPProfPort,
CODER_EXPERIMENTS: e2eFakeExperiment1 + "," + e2eFakeExperiment2,
}, },
reuseExistingServer: false, reuseExistingServer: false,
}, },

View File

@ -0,0 +1,39 @@
import { expect, test } from "@playwright/test";
import * as API from "api/api";
import { setupApiCalls } from "../../api";
import { e2eFakeExperiment1, e2eFakeExperiment2 } from "../../constants";
test("experiments", async ({ page }) => {
await setupApiCalls(page);
// Load experiments from backend API
const availableExperiments = await API.getAvailableExperiments();
// Verify if the site lists the same experiments
await page.goto("/deployment/general", { waitUntil: "networkidle" });
const experimentsLocator = page.locator(
"div.options-table tr.option-experiments ul.option-array",
);
await expect(experimentsLocator).toBeVisible();
// Firstly, check if all enabled experiments are listed
expect(
experimentsLocator.locator(
`li.option-array-item-${e2eFakeExperiment1}.option-enabled`,
),
).toBeVisible;
expect(
experimentsLocator.locator(
`li.option-array-item-${e2eFakeExperiment2}.option-enabled`,
),
).toBeVisible;
// Secondly, check if available experiments are listed
for (const experiment of availableExperiments.safe) {
const experimentLocator = experimentsLocator.locator(
`li.option-array-item-${experiment}`,
);
await expect(experimentLocator).toBeVisible();
}
});

View File

@ -51,7 +51,7 @@ export const OptionValue: FC<OptionValueProps> = (props) => {
if (typeof value === "object" && !Array.isArray(value)) { if (typeof value === "object" && !Array.isArray(value)) {
return ( return (
<ul css={{ listStyle: "none" }}> <ul css={{ listStyle: "none" }} className="option-array">
{Object.entries(value) {Object.entries(value)
.sort((a, b) => a[0].localeCompare(b[0])) .sort((a, b) => a[0].localeCompare(b[0]))
.map(([option, isEnabled]) => ( .map(([option, isEnabled]) => (
@ -64,6 +64,9 @@ export const OptionValue: FC<OptionValueProps> = (props) => {
color: theme.palette.text.disabled, color: theme.palette.text.disabled,
}, },
]} ]}
className={`option-array-item-${option} ${
isEnabled ? "option-enabled" : "option-disabled"
}`}
> >
<div <div
css={{ css={{

View File

@ -27,7 +27,7 @@ const OptionsTable: FC<OptionsTableProps> = ({ options, additionalValues }) => {
} }
return ( return (
<TableContainer> <TableContainer className="options-table">
<Table <Table
css={css` css={css`
& td { & td {
@ -57,7 +57,7 @@ const OptionsTable: FC<OptionsTableProps> = ({ options, additionalValues }) => {
return null; return null;
} }
return ( return (
<TableRow key={option.flag}> <TableRow key={option.flag} className={"option-" + option.flag}>
<TableCell> <TableCell>
<OptionName>{option.name}</OptionName> <OptionName>{option.name}</OptionName>
<OptionDescription>{option.description}</OptionDescription> <OptionDescription>{option.description}</OptionDescription>