61 lines
2.4 KiB
TypeScript
61 lines
2.4 KiB
TypeScript
import { When } from "@cucumber/cucumber";
|
|
import path from "node:path";
|
|
import type { ActorSession } from "@pikku/cucumber/browser";
|
|
import type { AppWorld } from "../support/world.js";
|
|
|
|
/**
|
|
* Project-specific invoice steps. Talk to the Invoices tab on the admin
|
|
* booking-detail page (Mantine form). Locale-aware: the form uses German
|
|
* labels by default in this app.
|
|
*/
|
|
|
|
When(
|
|
"{actor} create(s) an invoice numbered {string} for {float} €",
|
|
async function (this: AppWorld, actor: ActorSession, invoiceNumber: string, amountEuro: number) {
|
|
// The form sits in the "Neue Rechnung" panel — use data-testid hooks so we
|
|
// are not coupled to localized labels.
|
|
const numberField = actor.page
|
|
.getByTestId("invoice-create-form")
|
|
.locator('input[data-testid="invoice-number"], [data-testid="invoice-number"] input')
|
|
.first();
|
|
await numberField.fill(invoiceNumber);
|
|
const amount = actor.page
|
|
.getByTestId("invoice-create-form")
|
|
.locator('input[data-testid="invoice-amount"], [data-testid="invoice-amount"] input')
|
|
.first();
|
|
await amount.fill("");
|
|
await amount.fill(String(amountEuro.toFixed(2)));
|
|
await actor.page
|
|
.getByRole("button", { name: /rechnung erstellen|create invoice/i })
|
|
.click();
|
|
// Wait for the row to appear in the invoices table above the form.
|
|
await actor.page.getByText(invoiceNumber, { exact: false }).first().waitFor({
|
|
state: "visible",
|
|
});
|
|
},
|
|
);
|
|
|
|
When(
|
|
"{actor} attach(es) invoice PDF {string}",
|
|
async function (this: AppWorld, actor: ActorSession, filename: string) {
|
|
const filePath = path.resolve(process.cwd(), "tests", "fixtures", filename);
|
|
await actor.page.getByTestId("invoice-pdf").setInputFiles(filePath);
|
|
},
|
|
);
|
|
|
|
When(
|
|
"{actor} mark(s) invoice {string} as paid on {string}",
|
|
async function (this: AppWorld, actor: ActorSession, invoiceNumber: string, paidOn: string) {
|
|
// Stub the prompt before clicking — the UI uses window.prompt to collect
|
|
// the payment date.
|
|
await actor.page.evaluate((value) => {
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
(window as any).prompt = () => value;
|
|
}, paidOn);
|
|
|
|
const row = actor.page.getByRole("row", { name: new RegExp(invoiceNumber) });
|
|
await row.getByTestId(`invoice-mark-paid-${invoiceNumber}`).click();
|
|
await row.getByText(/bezahlt|paid/i).waitFor({ state: "visible" });
|
|
},
|
|
);
|