refactor: migrate UI to Tailwind and unify chat with shadcn
This commit is contained in:
@@ -74,18 +74,18 @@ test("creates, switches, renames and deletes persisted deck profiles", async ({
|
||||
await page.getByRole("button", { name: "Create deck", exact: true }).click();
|
||||
await page.getByLabel("New deck name").fill("別の調査");
|
||||
await page.getByRole("button", { name: "Create", exact: true }).click();
|
||||
await expect(page.locator(".deck-column")).toHaveCount(0);
|
||||
await expect(page.locator("[data-testid='deck-column']")).toHaveCount(0);
|
||||
await addColumn(page, "別の観点", "second-deck", "alternate");
|
||||
await showDeckManagement(page);
|
||||
await page.getByLabel("Deck profile", { exact: true }).selectOption({ label: "最初の調査" });
|
||||
await closeMobileSidebar(page);
|
||||
await expect(page.locator(".deck-column h2")).toHaveText(["最初の観点"]);
|
||||
await expect(page.locator("[data-testid='deck-column'] h2")).toHaveText(["最初の観点"]);
|
||||
await page.reload();
|
||||
await expect(page.getByRole("heading", { level: 1 })).toHaveText("最初の調査");
|
||||
await showDeckManagement(page);
|
||||
await page.getByLabel("Deck profile", { exact: true }).selectOption({ label: "別の調査" });
|
||||
await closeMobileSidebar(page);
|
||||
await expect(page.locator(".deck-column h2")).toHaveText(["別の観点"]);
|
||||
await expect(page.locator("[data-testid='deck-column'] h2")).toHaveText(["別の観点"]);
|
||||
await showDeckManagement(page);
|
||||
await page.getByRole("button", { name: "Delete deck", exact: true }).click();
|
||||
await page.getByRole("button", { name: "Delete", exact: true }).click();
|
||||
@@ -108,11 +108,17 @@ test("reads user and list timelines within columns and reorders, deletes and res
|
||||
await expect(list.getByText("list page 2")).toBeVisible();
|
||||
await list.getByRole("button", { name: "Actions for リストの投稿" }).click();
|
||||
await page.getByRole("menuitem", { name: "Move リストの投稿 left" }).click();
|
||||
await expect(page.locator(".deck-column h2")).toHaveText(["リストの投稿", "アカウント"]);
|
||||
await expect(page.locator("[data-testid='deck-column'] h2")).toHaveText([
|
||||
"リストの投稿",
|
||||
"アカウント",
|
||||
]);
|
||||
await list.getByRole("button", { name: "Actions for リストの投稿" }).click();
|
||||
await page.getByRole("menuitem", { name: "Delete リストの投稿" }).click();
|
||||
await page.getByRole("button", { name: "Undo" }).click();
|
||||
await expect(page.locator(".deck-column h2")).toHaveText(["リストの投稿", "アカウント"]);
|
||||
await expect(page.locator("[data-testid='deck-column'] h2")).toHaveText([
|
||||
"リストの投稿",
|
||||
"アカウント",
|
||||
]);
|
||||
await page.reload();
|
||||
await expect(user.getByText("alternate profile page 1")).toBeVisible();
|
||||
await expect(list.getByText("list page 1")).toBeVisible();
|
||||
@@ -149,7 +155,7 @@ test("keeps the deck and editor accessible within narrow viewports", async ({
|
||||
expect(await page.evaluate(() => document.documentElement.scrollHeight <= innerHeight)).toBe(
|
||||
true,
|
||||
);
|
||||
const board = await page.locator(".deck-board").boundingBox();
|
||||
const board = await page.locator("[data-testid='deck-board']").boundingBox();
|
||||
expect(board).not.toBeNull();
|
||||
expect((board?.y ?? 0) + (board?.height ?? 0)).toBeLessThanOrEqual(901);
|
||||
}
|
||||
@@ -184,7 +190,7 @@ test("closes the column editor with Escape and restores focus without applying e
|
||||
await page.keyboard.press("Escape");
|
||||
await expect(page.getByRole("dialog", { name: "Add column", exact: true })).toHaveCount(0);
|
||||
await expect(opener).toBeFocused();
|
||||
await expect(page.locator(".deck-column")).toHaveCount(0);
|
||||
await expect(page.locator("[data-testid='deck-column']")).toHaveCount(0);
|
||||
await opener.click();
|
||||
await expect(page.getByLabel("Column name", { exact: true })).toHaveValue("");
|
||||
});
|
||||
|
||||
@@ -154,7 +154,7 @@ test("keeps completed actions in their original positions with visible outcomes"
|
||||
}, testInfo) => {
|
||||
await page.goto("/");
|
||||
await page.waitForLoadState("networkidle");
|
||||
const titles = page.locator(".execution-flow-title");
|
||||
const titles = page.locator("[data-testid='execution-flow-title']");
|
||||
const before = await titles.allTextContents();
|
||||
await page.getByRole("button", { name: "Complete Review the documents", exact: true }).click();
|
||||
await expect(
|
||||
|
||||
@@ -3,7 +3,7 @@ import { expect, test } from "../fixtures";
|
||||
test("selects articles and keeps the reader focused on their content", async ({ page }) => {
|
||||
await page.goto("/inbox");
|
||||
await page.waitForLoadState("networkidle");
|
||||
const rows = page.locator(".inbox-article-row");
|
||||
const rows = page.locator("[data-testid='inbox-article-row']");
|
||||
await expect(rows).toHaveCount(9);
|
||||
const articleTitle = "Context for an agent can be brief";
|
||||
await rows.filter({ hasText: articleTitle }).click();
|
||||
@@ -33,7 +33,7 @@ test("selects articles and keeps the reader focused on their content", async ({
|
||||
test("recovers from empty search and shares navigation with Research", async ({ page, a11y }) => {
|
||||
await page.goto("/inbox");
|
||||
await page.waitForLoadState("networkidle");
|
||||
const rows = page.locator(".inbox-article-row");
|
||||
const rows = page.locator("[data-testid='inbox-article-row']");
|
||||
await page.getByRole("textbox", { name: "Search articles" }).fill("nonexistent-query-xyz");
|
||||
await expect(rows).toHaveCount(0);
|
||||
await expect(page.getByText("No articles found", { exact: true })).toBeVisible();
|
||||
@@ -58,7 +58,7 @@ test("keeps article navigation readable without horizontal overflow", async ({
|
||||
await page.setViewportSize({ width, height: 850 });
|
||||
await expect(page.getByRole("textbox", { name: "Search articles" })).toBeVisible();
|
||||
expect(await page.evaluate(() => document.documentElement.scrollWidth)).toBe(width);
|
||||
await page.locator(".inbox-article-row").first().click();
|
||||
await page.locator("[data-testid='inbox-article-row']").first().click();
|
||||
const reader = page.getByRole("article", {
|
||||
name: "Thinking in the browser: a new workflow with AI agents",
|
||||
exact: true,
|
||||
|
||||
@@ -100,7 +100,7 @@ test("restores the conversation and growing temporary deck from reconnect snapsh
|
||||
"background-color",
|
||||
"rgba(0, 0, 0, 0)",
|
||||
);
|
||||
await expect(page.locator(".deck-column h2")).toHaveText(["最初の観点"]);
|
||||
await expect(page.locator("[data-testid='deck-column'] h2")).toHaveText(["最初の観点"]);
|
||||
run.deckVersion = 2;
|
||||
run.status = "complete";
|
||||
run.messages.push({
|
||||
@@ -124,7 +124,10 @@ test("restores the conversation and growing temporary deck from reconnect snapsh
|
||||
await showResearch(page);
|
||||
await expect(conversation).toContainText("既存の観点を使って調査して");
|
||||
await expect(conversation).toContainText("比較する観点を追加しました。");
|
||||
await expect(page.locator(".deck-column h2")).toHaveText(["最初の観点", "比較の観点"]);
|
||||
await expect(page.locator("[data-testid='deck-column'] h2")).toHaveText([
|
||||
"最初の観点",
|
||||
"比較の観点",
|
||||
]);
|
||||
await closeMobileSidebar(page);
|
||||
await expect(page.getByRole("button", { name: "Save as deck", exact: true })).toBeEnabled();
|
||||
await showResearch(page);
|
||||
@@ -260,15 +263,15 @@ test("renders Markdown and reveals an unloaded citation in an offscreen deck col
|
||||
await expect(page.getByText("AIが調査時に取得した引用本文", { exact: true })).toHaveCount(0);
|
||||
await chat.getByRole("link", { name: "根拠の投稿" }).click();
|
||||
const card = page.locator(
|
||||
'.research-post[data-post-url="https://twitter.com/author/status/123456789"]',
|
||||
'[data-testid="research-post"][data-post-url="https://twitter.com/author/status/123456789"]',
|
||||
);
|
||||
await expect(card).toBeVisible();
|
||||
await expect(card).toHaveClass(/citation-highlight/);
|
||||
await expect(card).toHaveAttribute("data-citation-highlight", "true");
|
||||
await expect(card).toBeFocused();
|
||||
await expect(card).toContainText("Post saved during research");
|
||||
await expect(card).toContainText("AIが調査時に取得した引用本文");
|
||||
expect(
|
||||
await page.locator(".deck-board").evaluate((element) => element.scrollLeft),
|
||||
await page.locator("[data-testid='deck-board']").evaluate((element) => element.scrollLeft),
|
||||
).toBeGreaterThan(0);
|
||||
expect(page.context().pages()).toHaveLength(1);
|
||||
await expect(page).toHaveURL(/citation=twitter%3A123456789/);
|
||||
@@ -283,7 +286,7 @@ test("renders Markdown and reveals an unloaded citation in an offscreen deck col
|
||||
await expect(card).toBeVisible();
|
||||
await expect(card).toHaveClass(/citation-highlight/);
|
||||
await expect(page).toHaveURL(/citation=twitter%3A123456789/);
|
||||
await expect(page.locator(".deck-column")).toHaveCount(3);
|
||||
await expect(page.locator("[data-testid='deck-column']")).toHaveCount(3);
|
||||
expect(submitted).toEqual([]);
|
||||
expect((await a11y().analyze()).violations).toEqual([]);
|
||||
});
|
||||
|
||||
@@ -9,16 +9,16 @@ test("reviews an edited reply and keeps the simulated result in history", async
|
||||
}) => {
|
||||
await page.goto("/support");
|
||||
await page.waitForLoadState("networkidle");
|
||||
const rows = page.locator(".support-row");
|
||||
const rows = page.locator("[data-testid='support-row']");
|
||||
await expect(rows).toHaveCount(3);
|
||||
await rows.filter({ hasText: reviewSubject }).click();
|
||||
await page.locator(".conversation-suggestions summary:visible").click();
|
||||
await page.locator("[data-testid='conversation-suggestions'] summary:visible").click();
|
||||
await page.getByRole("button", { name: /^Polite/ }).click();
|
||||
const reply = page.getByRole("textbox", { name: "Reply", exact: true });
|
||||
await expect(reply).toHaveValue(/Thank you for sharing/);
|
||||
const edited = "I reviewed the materials. Let’s discuss the first-time experience.";
|
||||
await reply.fill(edited);
|
||||
await page.locator(".conversation-scheduling summary:visible").click();
|
||||
await page.locator("[data-testid='conversation-scheduling'] summary:visible").click();
|
||||
const slot = "Mon, Oct 5, 14:00–14:30";
|
||||
await page.getByRole("combobox", { name: "Suggested times" }).selectOption(slot);
|
||||
await page.getByRole("button", { name: "Add to reply" }).click();
|
||||
@@ -37,15 +37,16 @@ test("reviews an edited reply and keeps the simulated result in history", async
|
||||
await expect(rows.filter({ hasText: reviewSubject })).toHaveCount(0);
|
||||
await page.getByRole("button", { name: "Archive", exact: true }).click();
|
||||
await rows.filter({ hasText: reviewSubject }).click();
|
||||
await expect(page.locator(".support-outcome")).toContainText(edited);
|
||||
await expect(page.locator(".support-outcome")).toContainText(slot);
|
||||
await expect(page.locator("[data-testid='support-outcome']")).toContainText(edited);
|
||||
await expect(page.locator("[data-testid='support-outcome']")).toContainText(slot);
|
||||
});
|
||||
|
||||
test("defers a conversation and restores it to the current queue", async ({ page }) => {
|
||||
await page.goto("/support");
|
||||
await page.waitForLoadState("networkidle");
|
||||
const rows = page.locator(".support-row");
|
||||
const rows = page.locator("[data-testid='support-row']");
|
||||
await rows.filter({ hasText: coffeeSubject }).click();
|
||||
await expect(rows.filter({ hasText: coffeeSubject })).toHaveAttribute("aria-current", "true");
|
||||
await page
|
||||
.getByRole("textbox", { name: "Reply", exact: true })
|
||||
.fill("土曜の予定を確認してから返事するね。");
|
||||
@@ -117,7 +118,7 @@ test("fits communication and journal interactions in narrow screens", async ({
|
||||
await page.goto("/support");
|
||||
await page.waitForLoadState("networkidle");
|
||||
expect(await page.evaluate(() => document.documentElement.scrollWidth)).toBe(width);
|
||||
await page.locator(".support-row").first().click();
|
||||
await page.locator("[data-testid='support-row']").first().click();
|
||||
await expect(page.getByRole("textbox", { name: "Reply", exact: true })).toBeVisible();
|
||||
expect(await page.evaluate(() => document.documentElement.scrollWidth)).toBe(width);
|
||||
if (width === 320) expect((await a11y().analyze()).violations).toEqual([]);
|
||||
|
||||
@@ -2,19 +2,22 @@ import { expect, test } from "../fixtures";
|
||||
|
||||
test("restores article selection with browser history and reload", async ({ page }) => {
|
||||
await page.goto("/inbox", { waitUntil: "networkidle" });
|
||||
const rows = page.locator(".inbox-article-row");
|
||||
const heading = await rows.nth(1).locator(".inbox-row-title").innerText();
|
||||
const rows = page.locator("[data-testid='inbox-article-row']");
|
||||
const heading = await rows.nth(1).locator("[data-testid='inbox-row-title']").innerText();
|
||||
await rows.nth(1).click();
|
||||
await expect(page.locator(".inbox-article-title")).toHaveText(heading);
|
||||
await expect(page.locator("[data-testid='inbox-article-title']")).toHaveText(heading);
|
||||
const selectedUrl = page.url();
|
||||
expect(new URL(selectedUrl).searchParams.get("article")).toBeTruthy();
|
||||
await page.reload({ waitUntil: "networkidle" });
|
||||
await expect(page.locator(".inbox-article-title")).toHaveText(heading ?? "");
|
||||
await expect(page.locator("[data-testid='inbox-article-title']")).toHaveText(heading ?? "");
|
||||
await page.goBack();
|
||||
await expect(page.locator(".inbox-workspace")).toHaveAttribute("data-reading", "false");
|
||||
await expect(page.locator("[data-testid='inbox-workspace']")).toHaveAttribute(
|
||||
"data-reading",
|
||||
"false",
|
||||
);
|
||||
await page.goForward();
|
||||
await expect(page).toHaveURL(selectedUrl);
|
||||
await expect(page.locator(".inbox-article-title")).toHaveText(heading ?? "");
|
||||
await expect(page.locator("[data-testid='inbox-article-title']")).toHaveText(heading ?? "");
|
||||
});
|
||||
|
||||
test("restores search and replaces typing history", async ({ page }) => {
|
||||
@@ -24,10 +27,10 @@ test("restores search and replaces typing history", async ({ page }) => {
|
||||
await search.pressSequentially("browser");
|
||||
await expect(search).toHaveValue("browser");
|
||||
await expect.poll(() => new URL(page.url()).searchParams.get("q")).toBe("browser");
|
||||
const count = await page.locator(".inbox-article-row").count();
|
||||
const count = await page.locator("[data-testid='inbox-article-row']").count();
|
||||
await page.reload({ waitUntil: "networkidle" });
|
||||
await expect(search).toHaveValue("browser");
|
||||
await expect(page.locator(".inbox-article-row")).toHaveCount(count);
|
||||
await expect(page.locator("[data-testid='inbox-article-row']")).toHaveCount(count);
|
||||
await page.goBack();
|
||||
await expect(page).toHaveURL("http://127.0.0.1:4173/");
|
||||
});
|
||||
@@ -47,16 +50,21 @@ test("restores account dialog without losing underlying article", async ({ page
|
||||
test("restores a message view and conversation from its URL", async ({ page }) => {
|
||||
await page.goto("/support", { waitUntil: "networkidle" });
|
||||
await page.getByRole("button", { name: "All", exact: true }).click();
|
||||
const row = page.locator(".support-row").nth(1);
|
||||
const row = page.locator("[data-testid='support-row']").nth(1);
|
||||
const heading = await row.locator("span").first().innerText();
|
||||
await row.click();
|
||||
await expect(page.locator(".support-toolbar > span").first()).toHaveText(heading);
|
||||
await expect(page.locator("[data-testid='support-toolbar'] > span").first()).toHaveText(heading);
|
||||
const url = page.url();
|
||||
expect(new URL(url).searchParams.get("view")).toBe("all");
|
||||
expect(new URL(url).searchParams.get("conversation")).toBeTruthy();
|
||||
await page.reload({ waitUntil: "networkidle" });
|
||||
await expect(page.locator(".support-toolbar > span").first()).toHaveText(heading ?? "");
|
||||
await expect(page.locator(".support-workspace")).toHaveAttribute("data-reading", "true");
|
||||
await expect(page.locator("[data-testid='support-toolbar'] > span").first()).toHaveText(
|
||||
heading ?? "",
|
||||
);
|
||||
await expect(page.locator("[data-testid='support-workspace']")).toHaveAttribute(
|
||||
"data-reading",
|
||||
"true",
|
||||
);
|
||||
});
|
||||
|
||||
test("keeps a deep link through login", async ({ page, context }) => {
|
||||
|
||||
@@ -4,7 +4,7 @@ test("filters body systems and opens lab history", async ({ page, a11y }) => {
|
||||
await page.goto("/vitals");
|
||||
await page.waitForLoadState("networkidle");
|
||||
await expect(page.getByRole("heading", { name: "Body", exact: true })).toBeVisible();
|
||||
const systems = page.locator(".vital-system-card");
|
||||
const systems = page.locator("[data-testid='vital-system-card']");
|
||||
await expect(systems).toHaveCount(8);
|
||||
await page
|
||||
.getByRole("group", { name: "Body systems", exact: true })
|
||||
@@ -24,11 +24,11 @@ test("filters body systems and opens lab history", async ({ page, a11y }) => {
|
||||
await expect(dialog).toBeVisible();
|
||||
await dialog.getByRole("button", { name: "Close", exact: true }).last().click();
|
||||
await page.getByRole("button", { name: "Lab history", exact: true }).click();
|
||||
await expect(page.locator(".vital-history")).toContainText("Jul 28");
|
||||
await expect(page.locator(".vital-history")).toContainText("93");
|
||||
await expect(page.locator("[data-testid='vital-history']")).toContainText("Jul 28");
|
||||
await expect(page.locator("[data-testid='vital-history']")).toContainText("93");
|
||||
await page.reload();
|
||||
await page.waitForLoadState("networkidle");
|
||||
await expect(page.locator(".vital-history")).toContainText("Jul 28");
|
||||
await expect(page.locator("[data-testid='vital-history']")).toContainText("Jul 28");
|
||||
await page.getByRole("button", { name: "Systems", exact: true }).click();
|
||||
await page
|
||||
.getByRole("group", { name: "Body systems", exact: true })
|
||||
@@ -61,7 +61,10 @@ test("explores environment charts and simulated climate controls", async ({ page
|
||||
await expect(
|
||||
page.getByRole("img", { name: "7D CO₂ simulated environmental readings" }),
|
||||
).toBeVisible();
|
||||
await page.locator(".vital-metric").filter({ hasText: "Room temperature" }).click();
|
||||
await page
|
||||
.locator("[data-testid='vital-metric']")
|
||||
.filter({ hasText: "Room temperature" })
|
||||
.click();
|
||||
const dialog = page.getByRole("dialog", { name: "Room temperature" });
|
||||
await expect(dialog).toContainText("64.0");
|
||||
await page.reload();
|
||||
|
||||
@@ -234,7 +234,7 @@ test("rejects invalid input without changing the active view", async ({ page })
|
||||
expect((await executeTool(page, "set_deck", { title: "変更しない", columns })).isError).toBe(
|
||||
true,
|
||||
);
|
||||
await expect(page.locator(".deck-column h2")).toHaveText(["残す観点"]);
|
||||
await expect(page.locator("[data-testid='deck-column'] h2")).toHaveText(["残す観点"]);
|
||||
}
|
||||
expect(savedCount()).toEqual({ count: 0 });
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user