test(desktop): add leadership E2E seed hook + screenshot spec

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
This commit is contained in:
npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7
2026-06-24 17:27:47 -04:00
co-authored by Will Pfleger
parent e8dc2ebf0f
commit b76b1813ef
4 changed files with 222 additions and 0 deletions
+1
View File
@@ -34,6 +34,7 @@ export default defineConfig({
"**/team-management-screenshots.spec.ts",
"**/active-turn-screenshots.spec.ts",
"**/active-turn-resilience-screenshots.spec.ts",
"**/leadership-screenshots.spec.ts",
"**/profile-active-turn-screenshots.spec.ts",
"**/file-attachment.spec.ts",
"**/video-attachment.spec.ts",
@@ -328,6 +328,31 @@ export function useManagedAgentObserverBridge(
}, [hasActiveAgent]);
}
// Test-only: inject synthetic `leadership_status` frames through the real
// ingest path (`appendAgentEvent`), so the cached-map rebuild the consumer
// reads is exercised — not a fake. Registers the agent as known so the row
// renders. Production ingest (`handleRelayObserverEvent`) is untouched.
export function seedLeadershipForTest(
agentPubkey: string,
instances: readonly { instanceId: string; isLeader: boolean }[],
) {
knownAgentPubkeys.add(normalizePubkey(agentPubkey));
let seq = Date.now();
for (const { instanceId, isLeader } of instances) {
seq += 1;
appendAgentEvent(agentPubkey, {
seq,
timestamp: new Date().toISOString(),
kind: LEADERSHIP_EVENT_KIND,
agentIndex: null,
channelId: null,
sessionId: null,
turnId: null,
payload: { instanceId, isLeader },
});
}
}
export function resetAgentObserverStore() {
generation += 1;
const unsubscribe = unsubscribeRelay;
+8
View File
@@ -8,6 +8,7 @@ import { relayClient } from "@/shared/api/relayClient";
import type { ConnectionState } from "@/shared/api/relayClientShared";
import type { RelayEvent } from "@/shared/api/types";
import { syncAgentTurnsFromEvents } from "@/features/agents/activeAgentTurnsStore";
import { seedLeadershipForTest } from "@/features/agents/observerRelayStore";
import {
CUSTOM_EMOJI_SET_D_TAG,
KIND_EMOJI_SET,
@@ -653,6 +654,10 @@ declare global {
channelId: string;
turnId: string;
}) => void;
__BUZZ_E2E_SEED_LEADERSHIP__?: (input: {
agentPubkey: string;
instances: { instanceId: string; isLeader: boolean }[];
}) => void;
__BUZZ_E2E_EMIT_MOCK_READ_STATE__?: (input: {
clientId: string;
contexts: Record<string, number>;
@@ -6339,6 +6344,9 @@ export function maybeInstallE2eTauriMocks() {
},
]);
};
window.__BUZZ_E2E_SEED_LEADERSHIP__ = ({ agentPubkey, instances }) => {
seedLeadershipForTest(agentPubkey, instances);
};
const meshNodeStatus = (
state: "off" | "running",
mode: "serve" | "client" | null,
@@ -0,0 +1,188 @@
import { expect, test } from "@playwright/test";
import { installMockBridge } from "../helpers/bridge";
const SHOTS = "test-results/leadership";
// Mock agent pubkeys (distinct from the relay agents seeded by default).
const AGENT_PAUL = "aa".repeat(32);
const AGENT_DUNCAN = "bb".repeat(32);
type LeadershipInstance = { instanceId: string; isLeader: boolean };
async function waitForBridge(page: import("@playwright/test").Page) {
await page.waitForFunction(
() =>
typeof (window as Window & { __BUZZ_E2E_SEED_LEADERSHIP__?: unknown })
.__BUZZ_E2E_SEED_LEADERSHIP__ === "function",
null,
{ timeout: 10_000 },
);
}
async function openAgentsView(page: import("@playwright/test").Page) {
await page.goto("/", { waitUntil: "domcontentloaded" });
await waitForBridge(page);
await page.getByTestId("open-agents-view").click();
await expect(page.getByTestId("unified-agents-groups")).toBeVisible({
timeout: 10_000,
});
}
// The freshest-leader rule selects max(lastSeen), tie-broken by seq. The seed
// hook seeds in array order with a monotonic seq, so list the intended leader
// LAST to make selection deterministic even when timestamps collide at ms.
async function seedLeadership(
page: import("@playwright/test").Page,
agentPubkey: string,
instances: LeadershipInstance[],
) {
await page.evaluate(
({ pubkey, frames }) => {
const win = window as Window & {
__BUZZ_E2E_SEED_LEADERSHIP__?: (input: {
agentPubkey: string;
instances: { instanceId: string; isLeader: boolean }[];
}) => void;
};
win.__BUZZ_E2E_SEED_LEADERSHIP__?.({
agentPubkey: pubkey,
instances: frames,
});
},
{ pubkey: agentPubkey, frames: instances },
);
}
const MANAGED_AGENTS = [
{
pubkey: AGENT_PAUL,
name: "Paul",
status: "running" as const,
channelNames: ["general", "engineering"],
},
{
pubkey: AGENT_DUNCAN,
name: "Duncan",
status: "running" as const,
channelNames: ["general", "design"],
},
];
async function openLeadershipSubmenu(
page: import("@playwright/test").Page,
agentPubkey: string,
) {
await page.getByTestId(`managed-agent-actions-${agentPubkey}`).click();
const submenuTrigger = page.getByRole("menuitem", { name: "Leadership" });
await expect(submenuTrigger).toBeVisible();
await submenuTrigger.hover();
// Settle the submenu open animation before capture.
await submenuTrigger.evaluate((el) =>
Promise.all(
el
.closest("[data-state]")
?.getAnimations()
.map((a) => a.finished) ?? [],
),
);
}
test.describe("leadership UI screenshots", () => {
test.use({ viewport: { width: 1280, height: 720 } });
test("01 — single instance shows Leader badge, no submenu", async ({
page,
}) => {
await installMockBridge(page, { managedAgents: MANAGED_AGENTS });
await openAgentsView(page);
await seedLeadership(page, AGENT_PAUL, [
{ instanceId: "4821-1718600000000000", isLeader: true },
]);
const row = page.getByTestId(`managed-agent-${AGENT_PAUL}`);
await expect(row).toContainText("Leader", { timeout: 5_000 });
await page.getByTestId(`managed-agent-actions-${AGENT_PAUL}`).click();
await expect(
page.getByRole("menuitem", { name: "Leadership" }),
).toHaveCount(0);
await page.keyboard.press("Escape");
await page.getByTestId("unified-agents-groups").screenshot({
path: `${SHOTS}/01-single-instance-leader.png`,
});
});
test("02 — multi-instance badge reflects the freshest leader", async ({
page,
}) => {
await installMockBridge(page, { managedAgents: MANAGED_AGENTS });
await openAgentsView(page);
// Leader seeded last → highest seq → wins the freshest-leader tie-break.
await seedLeadership(page, AGENT_PAUL, [
{ instanceId: "4821-1718600000000000", isLeader: false },
{ instanceId: "5190-1718600100000000", isLeader: false },
{ instanceId: "6033-1718600200000000", isLeader: true },
]);
const row = page.getByTestId(`managed-agent-${AGENT_PAUL}`);
await expect(row).toContainText("Leader", { timeout: 5_000 });
await page.getByTestId("unified-agents-groups").screenshot({
path: `${SHOTS}/02-multi-instance-badge.png`,
});
});
test("03 — leadership submenu lists each instance", async ({ page }) => {
await installMockBridge(page, { managedAgents: MANAGED_AGENTS });
await openAgentsView(page);
await seedLeadership(page, AGENT_PAUL, [
{ instanceId: "4821-1718600000000000", isLeader: false },
{ instanceId: "5190-1718600100000000", isLeader: false },
{ instanceId: "6033-1718600200000000", isLeader: true },
]);
const row = page.getByTestId(`managed-agent-${AGENT_PAUL}`);
await expect(row).toContainText("Leader", { timeout: 5_000 });
await openLeadershipSubmenu(page, AGENT_PAUL);
await expect(page.getByRole("menuitem", { name: /Leader/ })).toBeVisible();
await page.screenshot({
path: `${SHOTS}/03-leadership-submenu.png`,
clip: { x: 0, y: 0, width: 1280, height: 720 },
});
});
test("04 — Make leader action on a non-leader instance", async ({ page }) => {
await installMockBridge(page, { managedAgents: MANAGED_AGENTS });
await openAgentsView(page);
await seedLeadership(page, AGENT_PAUL, [
{ instanceId: "4821-1718600000000000", isLeader: false },
{ instanceId: "5190-1718600100000000", isLeader: false },
{ instanceId: "6033-1718600200000000", isLeader: true },
]);
const row = page.getByTestId(`managed-agent-${AGENT_PAUL}`);
await expect(row).toContainText("Leader", { timeout: 5_000 });
await openLeadershipSubmenu(page, AGENT_PAUL);
// A non-leader instance's item is the enabled cooperative-steal entry point.
const makeLeaderItem = page
.getByRole("menuitem")
.filter({ hasText: "4821" });
await expect(makeLeaderItem).toBeVisible();
await makeLeaderItem.hover();
await page.screenshot({
path: `${SHOTS}/04-make-leader-action.png`,
clip: { x: 0, y: 0, width: 1280, height: 720 },
});
});
});