import { When, Then } from "@cucumber/cucumber"; import assert from "node:assert/strict"; import type { ActorSession } from "@pikku/cucumber/browser"; import type { AppWorld } from "../support/world.js"; import { config } from "../support/types.js"; When("the lifecycle cron runs", async function (this: AppWorld) { await this.runLifecycle(); }); Then( "the lifecycle cron sent {int} contracts", async function (this: AppWorld, count: number) { const result = await this.runLifecycle(); assert.equal(result.contractsSent, count); }, ); Then( "the lifecycle cron sent {int} reminders", async function (this: AppWorld, count: number) { const result = await this.runLifecycle(); assert.equal(result.reminders, count); }, ); Then( "the lifecycle cron completed {int} bookings", async function (this: AppWorld, count: number) { const result = await this.runLifecycle(); assert.equal(result.ended, count); }, ); When( "{actor} search(es) the bookings list for {string}", async function (this: AppWorld, actor: ActorSession, text: string) { await actor.page .getByPlaceholder(/suchen/i) .first() .fill(text); await actor.page.waitForTimeout(400); // debounce }, ); When( "{actor} trigger(s) booking action {string}", async function (this: AppWorld, actor: ActorSession, actionId: string) { const action = actor.page.getByTestId(actionId).first(); await action.waitFor({ state: "visible", timeout: config.responseTimeout }); await action.click({ timeout: config.responseTimeout }); const confirm = actor.page.getByTestId(`${actionId}-confirm`).first(); await confirm.waitFor({ state: "visible", timeout: config.responseTimeout }); await confirm.click({ timeout: config.responseTimeout }); await actor.page.waitForLoadState("networkidle", { timeout: 1000 }).catch(() => { // Persistent connections never go idle; the assertion below waits anyway. }); await actor.page.waitForTimeout(750); }, ); Then( "the audit log tab includes {string}", async function (this: AppWorld, entry: string) { const actor = await this.actor(undefined); await actor.page.getByRole("tab", { name: /protokoll|audit/i }).click(); await actor.page .getByText(entry, { exact: false }) .first() .waitFor({ state: "visible", timeout: config.responseTimeout }); }, ); When( "the admin approves the booking {string}", async function (this: AppWorld, bookingId: string) { const actor = await this.actor(undefined); await actor.gotoApp(`/admin/bookings/${bookingId}`); await actor.page.getByRole("button", { name: /reserv/i }).first().click(); await actor.page.waitForTimeout(500); }, ); When( "the admin records the deposit received for {string}", async function (this: AppWorld, bookingId: string) { const actor = await this.actor(undefined); await actor.gotoApp(`/admin/bookings/${bookingId}`); await actor.page.getByRole("button", { name: /anzahlung/i }).first().click(); await actor.page.waitForTimeout(500); }, ); Then( "the booking {string} has status {string}", async function (this: AppWorld, bookingId: string, status: string) { const actor = await this.actor(undefined); await actor.gotoApp(`/admin/bookings/${bookingId}`); await actor.expectText(status); }, ); Then( "the audit log for {string} includes {string}", async function (this: AppWorld, bookingId: string, entry: string) { const actor = await this.actor(undefined); await actor.gotoApp(`/admin/bookings/${bookingId}`); await actor.page.getByRole("tab", { name: /protokoll|audit/i }).click(); await actor.page .getByText(entry, { exact: false }) .first() .waitFor({ state: "visible", timeout: config.responseTimeout }); }, );