Files
wehub-resource-sync 6db8fca185
docmd CI verification / verify (push) Failing after 0s
chore: import upstream snapshot with attribution
2026-07-13 12:31:55 +08:00

105 lines
3.4 KiB
TypeScript

/**
* Thread resolve/unresolve tests - adapted from old devtalk.e2e.spec.ts
* "thread behavior" block.
*
* Changes from old plugin:
* - No sidebar panel with visual resolve/unresolve buttons on server-rendered cards
* - Resolve functionality exists at API level (threads:resolve-thread)
* - Resolved threads get .threads-thread--resolved class (opacity: 0.55)
* - The Lit-rendered threads-thread component has Resolve/Unresolve buttons,
* but the current inline mode uses server-rendered HTML
*/
import { test, expect } from "@playwright/test";
import { Actor } from "./screenplay.ts";
import { cleanThreads, setAuthor, seedAndReload, waitForReload } from "./helpers.ts";
let user: Actor;
test.beforeEach(async ({ page }) => {
user = new Actor("TestUser", page);
await page.goto("/");
await page.waitForSelector("threads-app", { state: "attached", timeout: 10_000 });
await setAuthor(page, "TestUser");
await cleanThreads(page);
await waitForReload(page);
});
test.describe("resolve thread API", () => {
test("resolving a thread sets resolved state", async () => {
const { id: threadId } = await seedAndReload(user.page, {
body: "Thread to resolve",
});
// Resolve via API
const resolved = await user.page.evaluate(
async ({ threadId }) => {
const file = document.body.dataset["sourceFile"];
return docmd.call("threads:resolve-thread", {
file,
threadId,
resolved_by: "TestUser",
});
},
{ threadId },
);
expect(resolved.resolved).toBeTruthy();
// The resolve call wrote to the file, triggering hot-reload. Wait for it.
await waitForReload(user.page);
// Verify via re-fetch
const threads = await user.page.evaluate(async () => {
const file = document.body.dataset["sourceFile"];
return docmd.call("threads:get-threads", { file });
});
const thread = threads.find((t: any) => t.id === threadId);
expect(thread.resolved).toBeTruthy();
});
test("unresolving a thread toggles back to open", async () => {
// Seed a resolved thread
const { id: threadId } = await seedAndReload(user.page, {
body: "Resolved thread for unresolve test",
resolved: true,
});
// Unresolve by calling resolve-thread again (it toggles)
const unresolved = await user.page.evaluate(
async ({ threadId }) => {
const file = document.body.dataset["sourceFile"];
return docmd.call("threads:resolve-thread", {
file,
threadId,
resolved_by: "TestUser",
});
},
{ threadId },
);
expect(unresolved.resolved).toBeFalsy();
});
test("resolved thread gets --resolved CSS class on server render", async () => {
const { id: threadId } = await seedAndReload(user.page, {
body: "Thread for CSS test",
resolved: true,
});
// The resolved state requires an extra reload since seedThread does
// add-thread + resolve as separate file writes
await waitForReload(user.page);
const threadEl = user.page.locator(`.threads-thread[data-thread-id="${threadId}"]`);
await expect(threadEl).toBeAttached({ timeout: 5_000 });
// Server-rendered resolved threads should have the resolved class
const hasResolvedClass = await threadEl.evaluate((el) =>
el.classList.contains("threads-thread--resolved"),
);
expect(hasResolvedClass).toBe(true);
});
});