Files
canvas-frontend/qa/_assistant_test.mjs
canvas-bot 9cbee11756
build-and-publish / test (push) Has been cancelled
build-and-publish / image (push) Has been cancelled
fix: studio createDraft split, llm fallback offers tools, topbar a11y pass
Three Oracle-flagged gaps:

1. Studio createDraft 500 (was masked by retries). Empirical curl
   reproducer proved POST /api/ea2/flow returns 201 with the minimal
   shape but intermittently 500s when config.wizard.* is in the
   initial body. Split: POST creates the draft minimally, then a
   follow-up PUT attaches the wizard config best-effort. Draft
   creation now lands reliably.

2. LLM 'temporarily unavailable' was a dead end for the user. Now
   the assistant returns ok:true with a concrete menu of tools the
   user CAN use right now ('list processes', 'start <name>',
   'open <hub>', 'tell <name> that ...', 'remember ...', 'recall ...').
   The reply renders as a normal assistant message, not a red error.

3. Topbar UI/UX Pro Max pass:
   - Added aria-label to the ⌘K and avatar buttons (icon-only a11y)
   - Removed the duplicate topbar-mid chips on Mission (Mission scene
     already shows family/defName/version inline). Cleaner topbar.
   - Added focus-visible outlines (2px amber, 2px offset) on all
     topbar action buttons + user-menu items
   - Hover/active scale on the avatar (1.04 / 0.97) with 160ms ease
   - Tabular numerals for the ⌘K kbd and notification badge
   - prefers-reduced-motion respected

30/30 vitest pass. tsc + vite build green.
2026-06-15 20:04:59 +04:00

41 lines
1.6 KiB
JavaScript

// Tight assistant test
import { chromium } from "playwright";
const b = await chromium.launch({ headless: true });
const ctx = await b.newContext({ viewport: { width: 1440, height: 900 } });
const p = await ctx.newPage();
await ctx.addInitScript(() => localStorage.setItem("fm.canvas.tour.seen", String(Date.now())));
await p.goto("https://canvas.flow-master.ai/", { waitUntil: "domcontentloaded" });
await p.waitForTimeout(2500);
await p.locator(".persona-chip").filter({ hasText: /Mariana/ }).click();
await p.waitForSelector(".topbar", { timeout: 30000 });
await p.waitForTimeout(2000);
console.log("on mission, navigating to Assistant");
await p.locator(".tab").filter({ hasText: /Assistant/i }).first().click();
await p.waitForTimeout(3500);
const textarea = p.locator(".agent-composer textarea").first();
const textareaPresent = await textarea.count() > 0;
console.log("textarea present:", textareaPresent);
if (textareaPresent) {
await textarea.fill("list processes");
await textarea.press("Enter");
await p.waitForTimeout(8000);
// Try different selectors for the reply
const turns = await p.evaluate(() => {
const t = Array.from(document.querySelectorAll(".agent-turn, .agent-msg, [class*='turn'], [class*='msg']"));
return t.map(el => ({ class: el.className.slice(0, 50), text: el.textContent?.slice(0, 200) }));
});
console.log("turns:", JSON.stringify(turns, null, 2));
const sceneText = await p.evaluate(() => document.querySelector(".scene")?.innerText?.slice(-800));
console.log("scene tail:", sceneText);
}
await p.screenshot({ path: "/tmp/canvas-evidence/assistant-test.png" });
await b.close();