Files
multica/e2e/comments.spec.ts
f0c361ebca feat(ui): Multica icons, roomier menus and typography pass (MUL-8334, MUL-8338) (#9640)
* refactor(ui): add @multica/ui/icons as the single icon entry point (MUL-8334)

Co-authored-by: Cursor <[email protected]>
Co-authored-by: multica-agent <[email protected]>

* refactor: import icons from @multica/ui/icons instead of lucide-react (MUL-8334)

Co-authored-by: Cursor <[email protected]>
Co-authored-by: multica-agent <[email protected]>

* chore(lint): ban direct lucide-react imports outside @multica/ui/icons (MUL-8334)

Co-authored-by: Cursor <[email protected]>
Co-authored-by: multica-agent <[email protected]>

* feat(ui): draw Multica icons and enlarge primitive icon sizes (MUL-8334)

Co-authored-by: Cursor <[email protected]>
Co-authored-by: multica-agent <[email protected]>

* feat(ui): roomier menu and sidebar rhythm (MUL-8334)

Co-authored-by: Cursor <[email protected]>
Co-authored-by: multica-agent <[email protected]>

* feat(ui): mark body and detail layers in icon glyphs (MUL-8334)

Co-authored-by: Cursor <[email protected]>
Co-authored-by: multica-agent <[email protected]>

* feat(ui): Inter optical sizing, lighter titles, CJK leading and zh-TW font stack (MUL-8338)

Co-authored-by: Cursor <[email protected]>
Co-authored-by: multica-agent <[email protected]>

* feat(ui): 13px for in-place reading text, regular weight for descriptive labels (MUL-8338)

Issue detail timeline, comment headers, properties panel, wakeup and PR rows
move from 12px to 13px; sub-issue identifiers match list/board (12px regular);
sidebar group labels drop to regular weight; board card titles get more
leading under a CJK UI via a new cjk: variant.

Co-authored-by: Cursor <[email protected]>
Co-authored-by: multica-agent <[email protected]>

* feat(ui): tint the active sidebar icon's body with a light fill (MUL-8334)

Co-authored-by: Cursor <[email protected]>
Co-authored-by: multica-agent <[email protected]>

* feat(ui): draw every remaining icon and drop lucide-react (MUL-8334)

All 286 icon names now render Multica drawings. The drawings, their
construction helpers and the generator live in packages/ui/icons/drawings;
glyphs.ts and index.ts are generated and a test fails when they drift.
Search loses its lens highlight and Inbox its arrow.

Co-authored-by: Cursor <[email protected]>
Co-authored-by: multica-agent <[email protected]>

* chore: guard against icon libraries and document drawing new icons (MUL-8334)

Lint bans the common React icon libraries, AGENTS.md points to a new
multica-icons skill, route icons must mark a body for the active tint,
and comments no longer describe product icons as Lucide.

Co-authored-by: Cursor <[email protected]>
Co-authored-by: multica-agent <[email protected]>

* feat(ui): fill the active sidebar icon solid with its details knocked out (MUL-8334)

Co-authored-by: Cursor <[email protected]>
Co-authored-by: multica-agent <[email protected]>

* fix(lint): ban icon library subpaths too (MUL-8334)

Co-authored-by: Cursor <[email protected]>
Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: Cursor <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-10-28 23:52:28 +08:00

71 lines
2.6 KiB
TypeScript

import { test, expect } from "@playwright/test";
import { createTestApi, loginAsDefault, waitForPageText } from "./helpers";
import type { TestApiClient } from "./fixtures";
test.describe("Comments", () => {
let api: TestApiClient;
let issueId: string;
let issueTitle: string;
let workspaceSlug: string;
test.beforeEach(async ({ page }) => {
api = await createTestApi();
issueTitle = "E2E Comment Test " + Date.now();
const issue = await api.createIssue(issueTitle);
issueId = issue.id;
workspaceSlug = await loginAsDefault(page);
});
test.afterEach(async () => {
if (api) {
await api.cleanup();
}
});
test("can add a comment on an issue", async ({ page }) => {
await page.goto(`/${workspaceSlug}/issues/${issueId}`, { waitUntil: "domcontentloaded" });
await waitForPageText(page, issueTitle);
// Wait for issue detail to load
await expect(page.locator("text=Properties")).toBeVisible();
// The composer renders as a static shell until clicked (readonly-first);
// clicking it mounts and focuses the real ProseMirror editor.
const shell = page.getByTestId("comment-composer-shell");
await expect(shell).toBeVisible();
await shell.click();
// Type a comment
const commentText = "E2E comment " + Date.now();
const editor = page
.locator('.ProseMirror[data-placeholder="Leave a comment..."], .ProseMirror:has([data-placeholder="Leave a comment..."])')
.first();
await expect(editor).toBeVisible();
await editor.click({ force: true });
await editor.fill(commentText);
await page.keyboard.press("ControlOrMeta+Enter");
// Comment should appear in the activity section
await expect(page.locator(`text=${commentText}`)).toBeVisible({
timeout: 5000,
});
});
test("comment submit button is disabled when empty", async ({ page }) => {
await page.goto(`/${workspaceSlug}/issues/${issueId}`, { waitUntil: "domcontentloaded" });
await waitForPageText(page, issueTitle);
await expect(page.locator("text=Properties")).toBeVisible();
// Submit button should be disabled when input is empty. The composer is a
// static shell until clicked (readonly-first) — the disabled state must
// hold in shell form too, no activation needed.
const shell = page.getByTestId("comment-composer-shell");
await expect(shell).toBeVisible();
const composer = shell.locator("xpath=ancestor::div[contains(@class, 'rounded-lg')][1]");
const submitBtn = composer.locator("button:has(svg.icon-arrow-up)").last();
await expect(submitBtn).toBeDisabled();
});
});