evOo-local/apps/web/e2e/routine-from-text.spec.ts
cynarAI dbf37f86a8
feat: show routines the bot sets up from chat as one quiet line (#133)
* feat: show routines the bot sets up from chat as one quiet line

When someone mentions something recurring in passing ("every Sunday I plan the
week"), the bot now creates the routine right away and the conversation shows a
single line with the schedule, Edit and Undo, on web and mobile.

- New `event` message block for routine lines, kept in history so later turns
  know what was set up or removed.
- schedule_create reuses an active repeating routine of the same name instead
  of adding a duplicate, caps a bot at 50 active schedules, and falls back to
  default times when none was given.
- Removing a routine (Undo, the editor, or schedule_cancel) marks its lines
  removed via the new routines.noticeMessageId column.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UmSCnoCgXqBp2fU3vwz4o1

* test: give the routine notice test a complete job publisher

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UmSCnoCgXqBp2fU3vwz4o1

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-04 20:36:53 +02:00

61 lines
2.3 KiB
TypeScript

import { expect, type Page, test } from "@playwright/test";
import type { Routine } from "@rakazo/contracts";
import {
activeBotId,
captureScreenshot,
completeOnboarding,
openUserSettings,
rpc,
signup,
} from "./helpers";
async function useAppearance(page: Page, appearance: "light" | "dark") {
const settings = await openUserSettings(page);
await settings.getByTestId(`ui-appearance-${appearance}`).click();
await expect(page.locator("html")).toHaveAttribute("data-theme", appearance);
await settings.getByRole("button", { name: "Close user settings" }).click();
await expect(settings).toBeHidden();
}
test("a routine said in passing becomes one quiet line with Edit and Undo", async ({
page,
}, testInfo) => {
const stamp = Date.now();
await signup(page, `routine-line-${stamp}@rakazo.test`, "password12", "Routine Line");
await completeOnboarding(page);
const botId = activeBotId(page);
await page.getByPlaceholder(/Message/).fill("Every Sunday I plan the week, keep me on it.");
await page.keyboard.press("Enter");
const line = page.getByTestId("routine-event-line");
await expect(line).toBeVisible({ timeout: 60_000 });
await expect(line).toContainText("Weekly plan");
await expect(line).toContainText("Every Sunday, 6:00 PM");
await expect(page.getByText("i will remind you every sunday at 6 pm.")).toBeVisible({
timeout: 30_000,
});
await useAppearance(page, "light");
await line.scrollIntoViewIfNeeded();
await captureScreenshot(page, testInfo, "routine-line-light");
await useAppearance(page, "dark");
await line.scrollIntoViewIfNeeded();
await captureScreenshot(page, testInfo, "routine-line-dark");
await line.getByRole("button", { name: "Edit" }).click();
await expect(page.getByPlaceholder("Name this routine")).toHaveValue("Weekly plan", {
timeout: 15_000,
});
await page.getByRole("button", { name: "Back" }).click();
await line.getByRole("button", { name: "Undo" }).click();
await expect(line).toContainText("Removed", { timeout: 15_000 });
await expect(line.getByRole("button", { name: "Undo" })).toHaveCount(0);
expect(await rpc<Routine[]>(page, "routines/list", { botId })).toEqual([]);
await page.reload({ waitUntil: "domcontentloaded" });
await expect(page.getByTestId("routine-event-line")).toContainText("Removed", {
timeout: 30_000,
});
});