import { expect, type Page, type Locator } from "@playwright/test"; export async function openMoreMenu(page: Page): Promise { const moreButton = page.getByTestId("tab-more"); await expect(moreButton).toBeVisible(); await moreButton.click(); return moreButton; } export async function expectModalVisible(modal: Locator): Promise { await expect(modal).toBeVisible(); await expect(modal).toHaveAttribute("aria-hidden", "false"); } export async function expectModalHidden(modal: Locator): Promise { await expect(modal).not.toBeVisible(); await expect(modal).toHaveAttribute("aria-hidden", "true"); } export async function editorClear(editor: Locator, iterations = 10): Promise { for (let i = 0; i < iterations; i++) { await editor.locator(".view-line").nth(0).click(); await editor.page().keyboard.press("ControlOrMeta+KeyA", { delay: 50 }); await editor.page().keyboard.press("Backspace", { delay: 50 }); } } export async function editorPaste(editor: Locator, page: Page, text: string): Promise { await editor.locator(".view-line").nth(0).click(); await page.evaluate((text) => navigator.clipboard.writeText(text), text); await page.keyboard.press("ControlOrMeta+KeyV", { delay: 100 }); } export enum LoadpointType { Charging = "charging", Heating = "heating", } export enum ChargerStatus { Disconnected = "A", Connected = "B", Charging = "C", } export async function addDemoCharger( page: Page, type: LoadpointType = LoadpointType.Charging, status?: ChargerStatus ): Promise { const lpModal = page.getByTestId("loadpoint-modal"); await lpModal .getByRole("button", { name: type === LoadpointType.Heating ? "Add heater" : "Add charger" }) .click(); const modal = page.getByTestId("charger-modal"); await expectModalVisible(modal); await modal .getByLabel("Manufacturer") .selectOption(type === LoadpointType.Heating ? "Demo heat pump" : "Demo charger"); if (status) { await modal.getByLabel("Charge status").selectOption(status); } await modal.getByRole("button", { name: "Save" }).click(); await expectModalHidden(modal); await expectModalVisible(lpModal); } export async function addDemoMeter(page: Page, power = "0"): Promise { const lpModal = page.getByTestId("loadpoint-modal"); await lpModal.getByRole("button", { name: "Add dedicated energy meter" }).click(); const modal = page.getByTestId("meter-modal"); await expectModalVisible(modal); await modal.getByLabel("Manufacturer").selectOption("Demo meter"); await modal.getByLabel("Power").fill(power); await modal.getByRole("button", { name: "Save" }).click(); await expectModalHidden(modal); await expectModalVisible(lpModal); } export async function addVehicle(page: Page, title: string): Promise { await page.getByRole("button", { name: "Add vehicle" }).click(); const modal = page.getByTestId("vehicle-modal"); await expectModalVisible(modal); await modal.getByLabel("Manufacturer").selectOption("Generic vehicle (without API)"); await modal.getByLabel("Title").fill(title); await modal.getByRole("button", { name: "Validate & save" }).click(); await expectModalHidden(modal); } export async function newLoadpoint( page: Page, title: string, type: LoadpointType = LoadpointType.Charging ): Promise { const lpModal = page.getByTestId("loadpoint-modal"); await page.getByRole("button", { name: "Add charger or heater" }).click(); await expectModalVisible(lpModal); await lpModal .getByRole("button", { name: type === LoadpointType.Heating ? "Add heating device" : "Add charging point", }) .click(); await lpModal.getByLabel("Title").fill(title); } export async function dragElement( page: Page, sourceElement: Locator, targetElement: Locator ): Promise { // hover() waits for animations to settle before grabbing the source — // avoids stale coordinates during the modal slide-in. await sourceElement.hover(); await page.mouse.down(); const targetBox = await targetElement.boundingBox(); if (!targetBox) throw new Error("dragElement: target has no bounding box"); await page.mouse.move(targetBox.x + targetBox.width / 2, targetBox.y + targetBox.height / 2, { steps: 10, }); await page.mouse.up(); } export async function getDatalistOptions(input: Locator): Promise { return input.evaluate((element: HTMLInputElement) => { const datalistId = element.getAttribute("list"); if (!datalistId) return []; const datalist = document.getElementById(datalistId); return Array.from(datalist?.querySelectorAll("option") || []).map((opt) => opt.value); }); }