import type { Page } from "@playwright/test"; import { expect } from "@playwright/test"; import { API, type DeploymentConfig } from "api/api"; import type { SerpentOption } from "api/typesGenerated"; import { formatDuration, intervalToDuration } from "date-fns"; import { coderPort } from "./constants"; import { findSessionToken, randomName } from "./helpers"; let currentOrgId: string; export const setupApiCalls = async (page: Page) => { try { const token = await findSessionToken(page); API.setSessionToken(token); } catch { // If this fails, we have an unauthenticated client. } API.setHost(`http://127.0.0.1:${coderPort}`); }; export const getCurrentOrgId = async (): Promise => { if (currentOrgId) { return currentOrgId; } const currentUser = await API.getAuthenticatedUser(); currentOrgId = currentUser.organization_ids[0]; return currentOrgId; }; export const createUser = async (orgId: string) => { const name = randomName(); const user = await API.createUser({ email: `${name}@coder.com`, username: name, name: name, password: "s3cure&password!", login_type: "password", organization_ids: [orgId], }); return user; }; export const createGroup = async (orgId: string) => { const name = randomName(); const group = await API.createGroup(orgId, { name, display_name: `Display ${name}`, avatar_url: "/emojis/1f60d.png", quota_allowance: 0, }); return group; }; export const createOrganization = async () => { const name = randomName(); const org = await API.createOrganization({ name, display_name: `Org ${name}`, description: `Org description ${name}`, icon: "/emojis/1f957.png", }); return org; }; export async function verifyConfigFlagBoolean( page: Page, config: DeploymentConfig, 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: 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: 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 verifyConfigFlagEmpty(page: Page, flag: string) { const configOption = page.locator( `div.options-table .option-${flag} .option-value-empty`, ); await expect(configOption).toHaveText("Not set"); } export async function verifyConfigFlagArray( page: Page, config: 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: 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 async function verifyConfigFlagDuration( page: Page, config: DeploymentConfig, flag: string, ) { const opt = findConfigOption(config, flag); const configOption = page.locator( `div.options-table .option-${flag} .option-value-string`, ); await expect(configOption).toHaveText( formatDuration( // intervalToDuration takes ms, so convert nanoseconds to ms intervalToDuration({ start: 0, end: (opt.value as number) / 1e6, }), ), ); } export function findConfigOption( config: DeploymentConfig, flag: string, ): SerpentOption { const opt = config.options.find((option) => option.flag === flag); if (opt === undefined) { // must be undefined as `false` is expected throw new Error(`Option with env ${flag} has undefined value.`); } return opt; }