Files
buzz/desktop/tests/e2e/huddle-transcription.spec.ts
Wes 7b11c6147d test: fix recurring CI flakes in desktop and Postgres lanes (#8343)
Fixes the CI flakes that failed most often across `main` and unrelated
branches from Oct 5 to Oct 14. The counts come from 150 failed `CI`
runs. Every change except the nextest config is test-only.

| Flake | Runs hit | Root cause | Fix |
|---|---|---|---|
| `probe_codex_acp_version_…descendant_holds_pipe_open` | 5 | The test
writes its script in-process and then execs it. If a sibling test spawns
a process in that window, the child inherits the open write fd and Linux
rejects the exec with `ETXTBSY`. The probe swallows that error as
`None`. | Write probe scripts from a short-lived `/bin/sh`
(`write_executable_script`) |
| `empty-edit-delete.spec.ts` (`:51`, `:74`, `:95`) | 11 | The seeded
`mock-general-welcome` id isn't hex, so `formatTimelineMessages` can't
overlay its edit. The post-subscribe window refetch then reverts the
row. | Emit a per-test message with a real id after the exact channel
subscription is live |
| `huddle-transcription.spec.ts:798` | 9 | The composer's delayed
initial autofocus (TipTap `focus()` runs in rAF) lands after the voice
popover opens and dismisses it. | Wait for `message-input` focus before
opening the popover |
| `voice-note.spec.ts:906` | 6 | The fixture `ping.mp3` is about 1s
long, so playback can end before `paused === false` is observed. | Loop
the fixture audio |
| `workflows.spec.ts:291` | 5 | The `Message text` fill runs before the
inspector swaps to the new step, so it fills the trigger's condition
instead. | Scope the fill to the step inspector after its `Action` menu
appears |
| `cluster_global_probe_commits_tokens_and_sessions_prove_coverage` | 3
| The `max-threads = 1` group only serializes these tests with each
other. Other tests' sessions still mask cluster-wide `pg_stat_activity`
(`MaskedActivity`). | `threads-required = "num-test-threads"` |
| `test_usage_metrics_lock_has_single_owner_and_releases_on_drop` | 1
(this PR) | The test retries the lock right after dropping the leader.
Postgres releases a session advisory lock only after the backend notices
the disconnect, so the retry can run first. | Poll for the successor,
bounded at 5s |

### Validation
- **ETXTBSY:** a Linux experiment with Rust 1.95 using the same
write→chmod→spawn pattern under concurrent spawns hit `ETXTBSY` 4–7% of
the time. Using the `sh` writer, it hit 0 of 6,000. I did not catch it
inside the full suite locally, so this fix is based on the mechanism,
not an in-suite repro. All 11 probe tests pass on Linux and macOS.
- **empty-edit-delete:** the baseline failed 16 of 45 runs
(`--repeat-each`, 6 workers, no retries). The spec fix alone brings that
to 4/45. The remaining failures come from a separate product race,
described below.
- **huddle:** the baseline failed 5 of 10 runs. With the fix, 60 of 60
passed without retries.
- **nextest:** checked with a throwaway crate on 0.9.136. A grouped test
with `num-test-threads` ran alone, even with `max-threads = 1`.
- I have not stress-run the voice-note and workflows fixes; they rely on
CI.

### Not in this PR
- **Product bug in `useChannelLinks`:** the debounced `#channel`
autocomplete close lets Enter accept a stale suggestion for about 120ms.
That accounts for the remaining `empty-edit-delete` failures, and it
affects users too. With the spec fix plus a synchronous close, the spec
passed 120 of 120 runs. This needs a product decision, so it's held for
a separate PR.
- **Composer autofocus race:** the delayed autofocus can close an
overlay the user just opened. The real fix is to revalidate when the
delayed focus runs. Overlaps #6530.
- **`thread-head-stale-edit.spec.ts:55`:** a forced click on a
pointer-events-none action bar is suspected, but I couldn't reproduce
it.
- **Remaining ETXTBSY exposure:** about 40 other Rust tests write and
then exec scripts, and 17 specs still edit the non-hex seed message.

Root-cause lanes by Princess Donut, Mongo and Mordecai. Carl integrated
and verified them.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Co-authored-by: Carl <32a2e2c9d428ee08902cab75d956da2c1d235a22d4766b0dd4138bf6e2e5db1d@buzz.block.builderlab.xyz>
Co-authored-by: Princess Donut <5d97ac8c272fa949af56c71e586146b1706e5c4c3daa125db5b4625e12e0686c@buzz.block.builderlab.xyz>
Co-authored-by: Mongo <81cabd2ca1792494372ed410283c00770c0cf35afca052e940fa522883212b45@buzz.block.builderlab.xyz>
Co-authored-by: Mordecai <f314b6033b6e13df94c8e9e1187d3666b6b9ce54e66ee986e31cdaa909e8dcbc@buzz.block.builderlab.xyz>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 20:32:00 -06:00

1898 lines
60 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { expect, test } from "@playwright/test";
import {
KIND_HUDDLE_ENDED,
KIND_HUDDLE_STARTED,
} from "../../src/shared/constants/kinds";
import { truncateNpub } from "../../src/shared/lib/pubkey";
import { ROUNDED_SQUIRCLE_PATH } from "../../src/shared/ui/AvatarClipPaths";
import { waitForAnimations } from "../helpers/animations";
import { installMockBridge, TEST_IDENTITIES } from "../helpers/bridge";
const HUDDLE_CHANNEL_ID = "11111111-1111-4111-8111-111111111111";
const HUDDLE_PARENT_ID = "9a1657ac-f7aa-5db0-b632-d8bbeb6dfb50";
const HUDDLE_THREAD_ROOT_ID = "mock-general-welcome";
/**
* Initials a key-fallback avatar shows: the two characters just before the
* compact npub label's visible tail — the fragment `getInitials` reads from
* a key label, whose unit suite pins the derivation itself.
*/
function keyTailInitials(pubkey: string) {
return truncateNpub(pubkey).slice(-4, -2).toUpperCase();
}
async function waitForMockLiveSubscription(
page: import("@playwright/test").Page,
channelName: string,
kind?: number,
) {
await expect
.poll(() =>
page.evaluate(
({ kind, name }) =>
window.__BUZZ_E2E_HAS_MOCK_LIVE_SUBSCRIPTION__?.({
channelName: name,
kind,
}) ?? false,
{ kind, name: channelName },
),
)
.toBe(true);
}
async function setHuddleSnapshot(
page: import("@playwright/test").Page,
members: Array<{
pubkey: string;
role: "member" | "bot";
}>,
transcriptionEnabled: boolean,
) {
await page.evaluate(
async ({ nextMembers, nextTranscriptionEnabled }) => {
const setSnapshot = (
window as Window & {
__BUZZ_E2E_SET_MOCK_HUDDLE_SNAPSHOT__?: (input: {
members: Array<{
pubkey: string;
role: "member" | "bot";
}>;
transcriptionEnabled: boolean;
}) => Promise<void>;
}
).__BUZZ_E2E_SET_MOCK_HUDDLE_SNAPSHOT__;
if (!setSnapshot) {
throw new Error("Mock huddle snapshot control is not installed.");
}
await setSnapshot({
members: nextMembers,
transcriptionEnabled: nextTranscriptionEnabled,
});
},
{ nextMembers: members, nextTranscriptionEnabled: transcriptionEnabled },
);
}
async function installFakeHuddleMicrophone(
page: import("@playwright/test").Page,
) {
await page.addInitScript(() => {
const mediaDevices = navigator.mediaDevices ?? ({} as MediaDevices);
if (!navigator.mediaDevices) {
Object.defineProperty(navigator, "mediaDevices", {
configurable: true,
value: mediaDevices,
});
}
Object.defineProperty(mediaDevices, "enumerateDevices", {
configurable: true,
value: async () => [
{
deviceId: "mock-huddle-microphone",
groupId: "mock-huddle-audio",
kind: "audioinput",
label: "Mock Huddle Microphone",
toJSON() {
return this;
},
} as MediaDeviceInfo,
],
});
Object.defineProperty(mediaDevices, "getUserMedia", {
configurable: true,
value: async () => {
const context = new AudioContext({ sampleRate: 48_000 });
const oscillator = context.createOscillator();
const gain = context.createGain();
const destination = context.createMediaStreamDestination();
gain.gain.value = 0;
oscillator.connect(gain);
gain.connect(destination);
oscillator.start();
return destination.stream;
},
});
});
}
test("keeps the drawer open until the huddle is expanded", async ({ page }) => {
await page.addInitScript(() => {
window.localStorage.setItem("buzz-theme", "buzz-dark");
});
await installMockBridge(page, {
huddle: {
parentChannelId: HUDDLE_PARENT_ID,
ephemeralChannelId: HUDDLE_CHANNEL_ID,
members: [
{ pubkey: TEST_IDENTITIES.tyler.pubkey, role: "member" },
{ pubkey: TEST_IDENTITIES.alice.pubkey, role: "bot" },
],
transcriptionEnabled: true,
},
});
await page.goto("/");
const gradientUnderlay = page.locator(".buzz-theme-gradient-underlay");
const openGradient = await gradientUnderlay.evaluate(
(element) => getComputedStyle(element).backgroundImage,
);
expect(openGradient).not.toBe("none");
const transcriptButton = page.getByRole("button", {
name: "Stop transcript",
});
await expect(transcriptButton).toBeVisible();
const huddleShell = page.locator(".buzz-huddle-shell");
await expect(huddleShell).toHaveAttribute("data-huddle-open", "true");
const huddleBackdrop = page.locator(".buzz-huddle-drawer-backdrop");
await expect(huddleBackdrop).toHaveClass(/buzz-huddle-drawer-backdrop-open/);
const [huddleBackdropColor, huddleDrawerColor] = await Promise.all([
huddleBackdrop.evaluate(
(element) => getComputedStyle(element).backgroundColor,
),
page
.locator(".buzz-huddle-drawer")
.first()
.evaluate((element) => getComputedStyle(element).backgroundColor),
]);
expect(huddleBackdropColor).toBe(huddleDrawerColor);
await expect
.poll(() =>
huddleBackdrop.evaluate((element) => {
const shell = element.parentElement;
const appSurface = shell?.querySelector(".buzz-huddle-app-surface");
if (!appSurface) return false;
const backdropStyle = getComputedStyle(element);
const appStyle = getComputedStyle(appSurface);
return Number(backdropStyle.zIndex) < Number(appStyle.zIndex);
}),
)
.toBe(true);
const drawerAgentMenu = page.getByRole("button", {
name: "Voice settings for alice",
});
await expect(
drawerAgentMenu.getByTestId("huddle-participant-avatar"),
).toBeVisible();
await drawerAgentMenu.click();
await expect(
page.getByText("Agent text-to-speech", { exact: true }),
).toBeVisible();
await expect(page.getByText("Agent voice", { exact: true })).toBeVisible();
await expect(
page.getByRole("button", { name: "Remove alice from huddle" }),
).toBeVisible();
await page.keyboard.press("Escape");
await expect(page.getByTestId("profile-huddle-control")).toHaveCount(0);
await page
.getByRole("button", { name: "Open huddle in a new window" })
.click();
await expect
.poll(() =>
page.evaluate(
() =>
(window.__BUZZ_E2E_COMMAND_LOG__ ?? []).filter(
(entry) => entry.command === "open_huddle_window",
).length,
),
)
.toBe(1);
const huddleControl = page.getByTestId("profile-huddle-control");
await expect(huddleControl).toBeVisible();
const mainContentSurface = page.locator(
"[data-buzz-content-surface]:not([data-buzz-content-unframed])",
);
await expect(mainContentSurface).toBeVisible();
const [mainContentColor, huddleCardColor] = await Promise.all([
mainContentSurface.evaluate(
(element) => getComputedStyle(element).backgroundColor,
),
huddleControl.evaluate(
(element) => getComputedStyle(element).backgroundColor,
),
]);
expect(huddleCardColor).toBe(mainContentColor);
await expect(huddleControl).toHaveCSS("border-top-width", "1px");
await expect(huddleControl).toContainText("In a huddle");
await expect(huddleControl).toContainText("#general");
const compactMicButton = huddleControl.getByRole("button", {
name: /microphone/i,
});
await expect(compactMicButton).toBeVisible();
await expect(compactMicButton).toHaveClass(/bg-destructive\/15/);
await expect(compactMicButton).toHaveClass(/text-destructive/);
await expect(
huddleControl.getByRole("button", { name: "Audio settings" }),
).not.toHaveClass(/bg-destructive\/15/);
const [micContainerRadius, micHoverRadius] = await Promise.all([
compactMicButton
.locator("..")
.evaluate((element) => getComputedStyle(element).borderTopLeftRadius),
compactMicButton.evaluate(
(element) => getComputedStyle(element).borderTopLeftRadius,
),
]);
expect(micHoverRadius).toBe(micContainerRadius);
await expect(huddleControl).toContainText("Leave");
await expect(
huddleControl.getByRole("button", { name: /huddle speaker/i }),
).toHaveCount(0);
await expect(transcriptButton).toHaveCount(0);
await huddleControl
.getByRole("button", { name: "Open huddle window" })
.click();
await expect
.poll(() =>
page.evaluate(
() =>
(window.__BUZZ_E2E_COMMAND_LOG__ ?? []).filter(
(entry) => entry.command === "open_huddle_window",
).length,
),
)
.toBe(2);
await huddleControl.getByRole("button", { name: "Leave huddle" }).click();
await expect
.poll(() =>
page.evaluate(
() =>
(window.__BUZZ_E2E_COMMAND_LOG__ ?? []).filter(
(entry) => entry.command === "leave_huddle",
).length,
),
)
.toBe(1);
await expect(page.locator(".buzz-huddle-shell")).toHaveAttribute(
"data-huddle-open",
"false",
);
const closedGradient = await gradientUnderlay.evaluate(
(element) => getComputedStyle(element).backgroundImage,
);
expect(closedGradient).toBe(openGradient);
});
test("floats the in-app huddle tray over the glass background", async ({
page,
}) => {
await page.addInitScript(() => {
window.localStorage.setItem("buzz-theme", "buzz-dark");
window.localStorage.setItem("buzz-glass-background", "true");
(window as typeof window & { isTauri?: boolean }).isTauri = true;
Object.defineProperty(navigator, "platform", {
configurable: true,
get: () => "MacIntel",
});
});
await installMockBridge(page, {
huddle: {
parentChannelId: HUDDLE_PARENT_ID,
ephemeralChannelId: HUDDLE_CHANNEL_ID,
members: [
{ pubkey: TEST_IDENTITIES.tyler.pubkey, role: "member" },
{ pubkey: TEST_IDENTITIES.alice.pubkey, role: "bot" },
],
transcriptionEnabled: true,
},
});
await page.goto("/");
const root = page.locator("html");
const shell = page.locator('.buzz-huddle-shell[data-huddle-window="false"]');
const slot = shell.locator(".buzz-huddle-drawer-slot");
const drawer = slot.locator(":scope > .buzz-huddle-drawer");
const backdrop = shell.locator(".buzz-huddle-drawer-backdrop");
const transcriptButton = drawer.getByRole("button", {
name: "Stop transcript",
});
await expect(root).toHaveAttribute("data-glass-background", "");
await expect(shell).toHaveAttribute("data-huddle-open", "true");
await expect(shell).toHaveCSS("background-color", "rgba(0, 0, 0, 0)");
await expect(backdrop).toHaveCSS("background-color", "rgba(0, 0, 0, 0)");
await expect(drawer).toHaveCSS("border-top-left-radius", "16px");
await expect(drawer).toHaveCSS("border-top-right-radius", "16px");
await expect(drawer).toHaveCSS("border-bottom-right-radius", "16px");
await expect(drawer).toHaveCSS("border-bottom-left-radius", "16px");
await expect(drawer).toHaveCSS("padding-top", "8px");
await expect(drawer).toHaveCSS("padding-right", "8px");
await expect(drawer).toHaveCSS("padding-bottom", "8px");
await expect(drawer).toHaveCSS("padding-left", "8px");
const geometry = await Promise.all([
slot.boundingBox(),
drawer.boundingBox(),
transcriptButton.boundingBox(),
]);
const [slotBox, drawerBox, transcriptButtonBox] = geometry;
expect(slotBox).not.toBeNull();
expect(drawerBox).not.toBeNull();
expect(transcriptButtonBox).not.toBeNull();
if (!slotBox || !drawerBox || !transcriptButtonBox) return;
expect(drawerBox.x - slotBox.x).toBe(8);
expect(drawerBox.y - slotBox.y).toBe(8);
expect(slotBox.x + slotBox.width - (drawerBox.x + drawerBox.width)).toBe(8);
expect(slotBox.y + slotBox.height - (drawerBox.y + drawerBox.height)).toBe(8);
expect(
Math.abs(
transcriptButtonBox.y +
transcriptButtonBox.height / 2 -
(drawerBox.y + drawerBox.height / 2),
),
).toBeLessThanOrEqual(1);
});
test("keeps the popped-out huddle dock full-width over glass", async ({
page,
}) => {
await page.addInitScript(() => {
window.localStorage.setItem("buzz-theme", "buzz-dark");
window.localStorage.setItem("buzz-glass-background", "true");
(window as typeof window & { isTauri?: boolean }).isTauri = true;
Object.defineProperty(navigator, "platform", {
configurable: true,
get: () => "MacIntel",
});
});
await installMockBridge(page, {
windowLabel: `huddle-${HUDDLE_CHANNEL_ID}`,
huddle: {
parentChannelId: HUDDLE_PARENT_ID,
ephemeralChannelId: HUDDLE_CHANNEL_ID,
members: [
{ pubkey: TEST_IDENTITIES.tyler.pubkey, role: "member" },
{ pubkey: TEST_IDENTITIES.alice.pubkey, role: "bot" },
],
transcriptionEnabled: true,
},
});
await page.goto("/");
const root = page.locator("html");
const shell = page.locator('.buzz-huddle-shell[data-huddle-window="true"]');
const slot = shell.locator(".buzz-huddle-drawer-slot");
const drawer = slot.locator(":scope > .buzz-huddle-drawer");
await expect(root).toHaveAttribute("data-glass-background", "");
await expect(shell).toHaveAttribute("data-huddle-open", "true");
await expect(shell).not.toHaveCSS("background-color", "rgba(0, 0, 0, 0)");
await expect(slot).toHaveCSS("padding-top", "0px");
await expect(drawer).toHaveCSS("border-top-left-radius", "0px");
await expect(drawer).toHaveCSS("border-top-right-radius", "0px");
});
test("shows speaker identity on every huddle chat message", async ({
page,
}) => {
await installMockBridge(page, {
windowLabel: `huddle-${HUDDLE_CHANNEL_ID}`,
huddle: {
parentChannelId: HUDDLE_PARENT_ID,
ephemeralChannelId: HUDDLE_CHANNEL_ID,
huddleThreadEventId: HUDDLE_THREAD_ROOT_ID,
members: [
{ pubkey: TEST_IDENTITIES.tyler.pubkey, role: "member" },
{ pubkey: TEST_IDENTITIES.alice.pubkey, role: "bot" },
],
transcriptionEnabled: true,
},
mock: { threadRepliesDelayMs: 1_500 },
});
await page.goto("/");
await expect
.poll(() =>
page.evaluate(
() => window.__TAURI_INTERNALS__?.metadata.currentWindow.label,
),
)
.toBe(`huddle-${HUDDLE_CHANNEL_ID}`);
await expect(page.getByTestId("huddle-transcript-intro")).toBeVisible();
await expect(page.getByTestId("message-thread-replies-loading")).toHaveCount(
0,
);
const transcriptTopGap = await page.evaluate(() => {
const participantStrip = document.querySelector(
'[data-testid="huddle-participant-strip"]',
);
const participantTray = participantStrip?.closest("header");
const transcriptIntro = document.querySelector(
'[data-testid="huddle-transcript-intro"]',
);
if (!participantTray || !transcriptIntro) return null;
return Math.round(
transcriptIntro.getBoundingClientRect().top -
participantTray.getBoundingClientRect().bottom,
);
});
expect(transcriptTopGap).toBe(16);
await waitForMockLiveSubscription(page, "huddle");
await page.evaluate(() => {
const threadRoot = window.__BUZZ_E2E_EMIT_MOCK_MESSAGE__?.({
channelName: "huddle",
content: "First huddle message",
});
window.__BUZZ_E2E_EMIT_MOCK_MESSAGE__?.({
channelName: "huddle",
content: "Second huddle message",
});
if (!threadRoot) throw new Error("Failed to create Huddle thread root.");
window.__BUZZ_E2E_EMIT_MOCK_MESSAGE__?.({
channelName: "huddle",
content: "Agent response flattened into the huddle chat",
parentEventId: threadRoot.id,
pubkey: "deadbeef".repeat(8),
});
});
for (const content of [
"First huddle message",
"Second huddle message",
"Agent response flattened into the huddle chat",
]) {
const row = page.getByTestId("message-row").filter({ hasText: content });
await expect(row).toBeVisible();
await expect(row.locator('[data-testid^="message-avatar-"]')).toBeVisible();
await expect(row.getByTestId("message-author")).toBeVisible();
await expect(row.getByTestId("message-timestamp")).toBeVisible();
}
await expect(page.getByTestId("message-thread-panel")).toHaveCount(0);
});
test("ignores persisted community onboarding in the huddle room", async ({
page,
}) => {
const persistedTransaction = {
id: "main-window-community-transaction",
source: "deep-link-join",
stage: "claiming",
relayUrl: "wss://other.example",
inviteCode: "main-window-invite",
communityName: "Other community",
createdAt: "2026-08-03T20:00:00.000Z",
updatedAt: "2026-08-03T20:00:00.000Z",
};
await page.addInitScript((transaction) => {
window.localStorage.setItem(
"buzz-community-onboarding-transaction.v1",
JSON.stringify(transaction),
);
}, persistedTransaction);
const claimRequests: string[] = [];
page.on("request", (request) => {
if (request.url().includes("/api/invites/claim")) {
claimRequests.push(request.url());
}
});
await installMockBridge(page, {
windowLabel: `huddle-${HUDDLE_CHANNEL_ID}`,
huddle: {
parentChannelId: HUDDLE_PARENT_ID,
ephemeralChannelId: HUDDLE_CHANNEL_ID,
members: [{ pubkey: TEST_IDENTITIES.tyler.pubkey, role: "member" }],
},
});
for (let load = 0; load < 2; load += 1) {
await page.goto("/");
await expect(page.getByTestId("huddle-transcript-intro")).toBeVisible();
await expect(
page.getByText("Setting up your community", { exact: true }),
).toHaveCount(0);
await expect
.poll(() =>
page.evaluate(() => {
const raw = window.localStorage.getItem(
"buzz-community-onboarding-transaction.v1",
);
return raw ? JSON.parse(raw) : null;
}),
)
.toEqual(persistedTransaction);
await expect
.poll(() =>
page.evaluate(() =>
JSON.parse(window.localStorage.getItem("buzz-communities") ?? "[]"),
),
)
.not.toContainEqual(
expect.objectContaining({ relayUrl: persistedTransaction.relayUrl }),
);
expect(claimRequests).toHaveLength(0);
}
});
test("keeps main-app shortcuts from navigating the huddle room", async ({
page,
}) => {
await installMockBridge(page, {
windowLabel: `huddle-${HUDDLE_CHANNEL_ID}`,
huddle: {
parentChannelId: HUDDLE_PARENT_ID,
ephemeralChannelId: HUDDLE_CHANNEL_ID,
members: [{ pubkey: TEST_IDENTITIES.tyler.pubkey, role: "member" }],
},
pendingCommunityDeepLinks: [
{
id: "companion-must-not-consume",
kind: "connect",
relayUrl: "wss://other.example",
},
],
});
await page.goto("/");
await expect(page).toHaveURL(
new RegExp(`/channels/${HUDDLE_CHANNEL_ID.replaceAll("-", "\\-")}`),
);
const huddleUrl = page.url();
const primaryModifier = process.platform === "darwin" ? "Meta" : "Control";
for (const shortcut of ["Shift+K", "Shift+A", "Comma"]) {
await page.keyboard.press(`${primaryModifier}+${shortcut}`);
await expect.poll(() => page.url()).toBe(huddleUrl);
await expect(page.getByTestId("settings-view")).toHaveCount(0);
}
await page.evaluate(async (channelId) => {
await window.__BUZZ_E2E_EMIT_TAURI_EVENT__?.("deep-link-message", {
channelId,
messageId: "mock-general-welcome",
threadRootId: null,
});
}, HUDDLE_PARENT_ID);
await expect.poll(() => page.url()).toBe(huddleUrl);
const pendingCommunityLink = {
code: null,
id: "companion-must-not-consume",
kind: "connect" as const,
name: null,
relayUrl: "wss://other.example",
};
await page.evaluate(async () => {
await window.__BUZZ_E2E_EMIT_TAURI_EVENT__?.("deep-link-connect", null);
});
await expect
.poll(() =>
page.evaluate(async () =>
window.__BUZZ_E2E_INVOKE_MOCK_COMMAND__?.(
"take_pending_community_deep_link",
),
),
)
.toEqual(pendingCommunityLink);
});
test("speaks the first eligible agent reply with its participant identity", async ({
page,
}) => {
await installMockBridge(page, {
huddle: {
parentChannelId: HUDDLE_PARENT_ID,
ephemeralChannelId: HUDDLE_CHANNEL_ID,
members: [
{ pubkey: TEST_IDENTITIES.tyler.pubkey, role: "member" },
{ pubkey: TEST_IDENTITIES.alice.pubkey, role: "bot" },
],
ttsEnabled: true,
},
});
await page.goto("/");
await waitForMockLiveSubscription(page, "huddle");
await page.evaluate((agentPubkey) => {
window.__BUZZ_E2E_EMIT_MOCK_MESSAGE__?.({
channelName: "huddle",
content: "This first reply should be spoken.",
pubkey: agentPubkey,
});
}, TEST_IDENTITIES.alice.pubkey);
await expect
.poll(() =>
page.evaluate(
() =>
(window.__BUZZ_E2E_COMMAND_LOG__ ?? []).find(
(entry) => entry.command === "speak_agent_message",
)?.payload,
),
)
.toMatchObject({
text: "This first reply should be spoken.",
speakerPubkey: TEST_IDENTITIES.alice.pubkey,
});
await expect(
page.getByRole("img", {
name: "Anyone can send instructions to this agent",
}),
).toHaveCount(0);
});
test("animates the responding agent with the shared speaker ring", async ({
page,
}) => {
await installMockBridge(page, {
windowLabel: `huddle-${HUDDLE_CHANNEL_ID}`,
huddle: {
parentChannelId: HUDDLE_PARENT_ID,
ephemeralChannelId: HUDDLE_CHANNEL_ID,
members: [
{ pubkey: TEST_IDENTITIES.tyler.pubkey, role: "member" },
{ pubkey: TEST_IDENTITIES.alice.pubkey, role: "bot" },
],
},
});
await page.goto("/");
const agentAvatar = page
.getByTestId("huddle-participant-strip")
.locator(".buzz-huddle-speaking-avatar")
.nth(1);
await expect(agentAvatar).toBeVisible();
await page.evaluate(async (pubkey) => {
await window.__BUZZ_E2E_EMIT_MOCK_HUDDLE_TTS_SPEAKER__?.({
pubkey,
level: 0.8,
});
}, TEST_IDENTITIES.alice.pubkey);
await expect
.poll(() =>
agentAvatar.evaluate((element) =>
element.style.getPropertyValue("--buzz-huddle-speaker-opacity"),
),
)
.toBe("0.890");
await expect(agentAvatar).toHaveCSS("clip-path", "none");
await expect(agentAvatar).not.toHaveClass(/rounded-squircle/);
await expect(agentAvatar).toHaveClass(/buzz-huddle-speaking-avatar-agent/);
const speakingRing = agentAvatar.getByTestId("huddle-agent-speaking-ring");
await expect(speakingRing).toBeVisible();
await expect(speakingRing.locator("path")).toHaveAttribute(
"d",
ROUNDED_SQUIRCLE_PATH,
);
await expect(speakingRing.locator("path")).toHaveAttribute("fill", "none");
await expect(speakingRing.locator("path")).toHaveAttribute(
"stroke-width",
"2",
);
await expect(speakingRing.locator("path")).toHaveAttribute(
"vector-effect",
"non-scaling-stroke",
);
await expect(speakingRing).toHaveCSS("opacity", "0.89");
await expect(agentAvatar.locator(".rounded-squircle")).toHaveCSS(
"clip-path",
/rounded-squircle-clip/,
);
const voiceMenuTrigger = page.getByTestId("huddle-agent-voice-menu-trigger");
await voiceMenuTrigger.focus();
await expect(voiceMenuTrigger).toBeFocused();
await expect(voiceMenuTrigger).toHaveCSS("clip-path", "none");
await page.evaluate(async () => {
await window.__BUZZ_E2E_EMIT_MOCK_HUDDLE_TTS_SPEAKER__?.({
pubkey: null,
level: 0,
});
});
await expect
.poll(() =>
agentAvatar.evaluate((element) =>
element.style.getPropertyValue("--buzz-huddle-speaker-opacity"),
),
)
.toBe("0");
});
test("stops the speaking agent from the huddle controls", async ({ page }) => {
await installMockBridge(page, {
windowLabel: `huddle-${HUDDLE_CHANNEL_ID}`,
huddle: {
parentChannelId: HUDDLE_PARENT_ID,
ephemeralChannelId: HUDDLE_CHANNEL_ID,
members: [
{ pubkey: TEST_IDENTITIES.tyler.pubkey, role: "member" },
{ pubkey: TEST_IDENTITIES.alice.pubkey, role: "bot" },
],
},
});
await page.goto("/");
const roomMicButton = page.getByRole("button", {
name: "Microphone unavailable",
});
await expect(roomMicButton).toHaveClass(/bg-destructive\/35/);
await expect(roomMicButton).toHaveClass(/text-destructive/);
await expect(
page.getByRole("button", { name: "Audio settings" }),
).not.toHaveClass(/bg-destructive\/35/);
const roomSpeakerButton = page.getByRole("button", {
name: "Unmute agent speech",
});
await expect(roomSpeakerButton).toHaveClass(/bg-destructive\/35/);
await expect(roomSpeakerButton).toHaveClass(/text-destructive/);
await expect(
page.getByRole("button", { name: "Speaker settings" }),
).not.toHaveClass(/bg-destructive\/35/);
await waitForAnimations(page);
const agentTile = page
.getByTestId("huddle-participant-strip")
.getByTestId("huddle-participant-tile")
.nth(1);
const agentAvatar = page
.getByTestId("huddle-participant-strip")
.locator(".buzz-huddle-speaking-avatar")
.nth(1);
const labelSlots = page.getByTestId("huddle-participant-label-slot");
await expect(agentAvatar).toBeVisible();
await waitForAnimations(page);
const idleTileHeight = await agentTile.evaluate(
(element) => element.offsetHeight,
);
const idleAgentLabelBox = await labelSlots.nth(1).boundingBox();
const humanLabelBox = await labelSlots.nth(0).boundingBox();
expect(humanLabelBox?.y).toBe(idleAgentLabelBox?.y);
expect(humanLabelBox?.height).toBe(idleAgentLabelBox?.height);
expect(humanLabelBox?.width).toBe(idleAgentLabelBox?.width);
await page.evaluate(async (pubkey) => {
await window.__BUZZ_E2E_EMIT_MOCK_HUDDLE_TTS_SPEAKER__?.({
pubkey,
level: 0.8,
});
}, TEST_IDENTITIES.alice.pubkey);
await expect
.poll(() =>
agentAvatar.evaluate((element) =>
element.style.getPropertyValue("--buzz-huddle-speaker-opacity"),
),
)
.toBe("0.890");
const stopButton = page.getByRole("button", { name: /^Stop .* speaking$/ });
await expect(stopButton).toBeVisible();
await expect(stopButton).toHaveClass(/bg-destructive\/15/);
expect(await labelSlots.nth(1).boundingBox()).toEqual(idleAgentLabelBox);
expect(await agentTile.evaluate((element) => element.offsetHeight)).toBe(
idleTileHeight,
);
await stopButton.click();
await expect
.poll(() =>
page.evaluate(
() =>
(window.__BUZZ_E2E_COMMAND_LOG__ ?? []).findLast(
(entry) => entry.command === "interrupt_huddle_speech",
)?.payload ?? null,
),
)
.toEqual({ agentPubkey: TEST_IDENTITIES.alice.pubkey });
});
test("assigns distinct agent voices and exposes compact per-agent controls", async ({
page,
}) => {
await installMockBridge(page, {
windowLabel: `huddle-${HUDDLE_CHANNEL_ID}`,
ttsSettings: {
version: 1,
agentTextToSpeech: true,
voicePreferences: ["pocket:vera"],
},
huddle: {
parentChannelId: HUDDLE_PARENT_ID,
ephemeralChannelId: HUDDLE_CHANNEL_ID,
members: [
{ pubkey: TEST_IDENTITIES.tyler.pubkey, role: "member" },
{ pubkey: TEST_IDENTITIES.alice.pubkey, role: "bot" },
{ pubkey: TEST_IDENTITIES.bob.pubkey, role: "bot" },
],
ttsEnabled: true,
},
});
await page.goto("/");
const voiceMenus = page.getByTestId("huddle-agent-voice-menu-trigger");
await expect(voiceMenus).toHaveCount(2);
await expect
.poll(async () => {
const state = (await page.evaluate(() =>
window.__BUZZ_E2E_INVOKE_MOCK_COMMAND__?.("get_huddle_state"),
)) as {
agent_voice_settings: Record<
string,
{ enabled: boolean; voice_key: string }
>;
};
return state.agent_voice_settings;
})
.toMatchObject({
[TEST_IDENTITIES.alice.pubkey]: {
enabled: true,
voice_key: "pocket:vera",
},
});
const assignedVoices = await page.evaluate(async () => {
const state = (await window.__BUZZ_E2E_INVOKE_MOCK_COMMAND__?.(
"get_huddle_state",
)) as {
agent_voice_settings: Record<string, { voice_key: string }>;
};
return Object.values(state.agent_voice_settings).map(
(settings) => settings.voice_key,
);
});
expect(new Set(assignedVoices).size).toBe(2);
// Let the huddle chat finish mounting and autofocus before opening an
// overlay; a late composer focus would dismiss the popover.
await expect(page.getByTestId("message-input")).toBeFocused();
await page.getByRole("button", { name: "Voice settings for alice" }).click();
await waitForAnimations(page);
const voiceMenu = page.locator(
'[data-testid="huddle-agent-voice-menu-content"][data-state="open"]',
);
await expect(voiceMenu).toBeVisible();
await expect(
voiceMenu.getByText("Agent text-to-speech", { exact: true }),
).toBeVisible();
const ttsToggle = voiceMenu.getByTestId("huddle-agent-tts-toggle");
await expect(ttsToggle).toBeChecked();
await expect(
voiceMenu.getByTestId("huddle-agent-voice-selector"),
).toContainText("Vera");
await ttsToggle.click();
await expect(
voiceMenu.getByTestId("huddle-agent-voice-selector"),
).toHaveCount(0);
await ttsToggle.click();
await expect(ttsToggle).toBeChecked();
const voiceSelector = voiceMenu.getByTestId("huddle-agent-voice-selector");
await expect(voiceSelector).toBeEnabled();
await voiceSelector.click();
await page.getByRole("menuitemradio", { name: "Jane" }).click();
await expect
.poll(() =>
page.evaluate(() => {
const updates = (window.__BUZZ_E2E_COMMAND_LOG__ ?? []).filter(
(entry) => entry.command === "set_huddle_agent_voice",
);
return updates.at(-1)?.payload ?? null;
}),
)
.toMatchObject({
agentPubkey: TEST_IDENTITIES.alice.pubkey,
voiceKey: "pocket:jane",
});
});
test("adds channel-mentioned agents to the live huddle roster", async ({
page,
}) => {
await installMockBridge(page, {
windowLabel: `huddle-${HUDDLE_CHANNEL_ID}`,
huddle: {
parentChannelId: HUDDLE_PARENT_ID,
ephemeralChannelId: HUDDLE_CHANNEL_ID,
members: [
{ pubkey: TEST_IDENTITIES.tyler.pubkey, role: "member" },
{ pubkey: TEST_IDENTITIES.alice.pubkey, role: "bot" },
],
},
});
await page.goto("/");
const participantTiles = page.getByTestId("huddle-participant-tile");
await expect(participantTiles).toHaveCount(2);
const result = await page.evaluate(
async ({ channelId, pubkey }) =>
window.__BUZZ_E2E_INVOKE_MOCK_COMMAND__?.(
"sync_agents_to_active_huddle",
{
channelId,
agentPubkeys: [pubkey],
},
),
{
channelId: HUDDLE_PARENT_ID,
pubkey: TEST_IDENTITIES.bob.pubkey,
},
);
expect(result).toEqual({
matched_active_huddle: true,
added: [TEST_IDENTITIES.bob.pubkey],
changed_channel_ids: [HUDDLE_CHANNEL_ID],
error: null,
});
await expect(participantTiles).toHaveCount(3);
await expect(
page.getByRole("button", { name: "Voice settings for Bob" }),
).toBeVisible();
});
test("does not enroll available agents when sending an ordinary message", async ({
page,
}) => {
await installMockBridge(page, {
windowLabel: `huddle-${HUDDLE_CHANNEL_ID}`,
huddle: {
parentChannelId: HUDDLE_PARENT_ID,
ephemeralChannelId: HUDDLE_CHANNEL_ID,
members: [{ pubkey: TEST_IDENTITIES.tyler.pubkey, role: "member" }],
},
managedAgents: [
{
pubkey: TEST_IDENTITIES.alice.pubkey,
name: "alice",
status: "running",
},
{
pubkey: TEST_IDENTITIES.bob.pubkey,
name: "bob",
status: "running",
},
],
});
await page.goto("/");
const participantTiles = page.getByTestId("huddle-participant-tile");
await expect(participantTiles).toHaveCount(1);
await page.getByTestId("message-input").fill("A message for the room");
await page.getByTestId("send-message").click();
await expect(
page
.getByTestId("message-row")
.filter({ hasText: "A message for the room" }),
).toBeVisible();
await expect(participantTiles).toHaveCount(1);
expect(
await page.evaluate(
() =>
(window.__BUZZ_E2E_COMMAND_LOG__ ?? []).filter(
(entry) => entry.command === "sync_agents_to_active_huddle",
).length,
),
).toBe(0);
});
test("keeps the colored startup surface while huddle controls connect", async ({
page,
}) => {
await installMockBridge(page, {
windowLabel: `huddle-${HUDDLE_CHANNEL_ID}`,
huddle: {
parentChannelId: HUDDLE_PARENT_ID,
ephemeralChannelId: HUDDLE_CHANNEL_ID,
phase: "connected",
members: [{ pubkey: TEST_IDENTITIES.tyler.pubkey, role: "member" }],
},
});
await page.goto("/");
await expect(page.getByTestId("huddle-starting-view")).toBeVisible();
await expect(
page.getByRole("status", { name: "Starting huddle" }),
).toBeVisible();
await expect(
page.getByTestId("huddle-starting-view").locator(".bee-sprite"),
).toBeVisible();
await expect(page.getByTestId("setup-grainient-background")).toBeVisible();
await expect(
page.getByRole("button", { name: "Leave huddle" }),
).toBeVisible();
await expect(page.getByTestId("message-thread-loading")).toHaveCount(0);
await expect(page.getByTestId("huddle-participant-strip")).toHaveCount(0);
await expect(page.getByTestId("huddle-transcript-intro")).toHaveCount(0);
});
test("returns the companion transcript to the same channel in the main app", async ({
page,
}) => {
await installMockBridge(page, {
huddle: {
parentChannelId: HUDDLE_PARENT_ID,
ephemeralChannelId: HUDDLE_CHANNEL_ID,
huddleThreadEventId: HUDDLE_THREAD_ROOT_ID,
members: [{ pubkey: TEST_IDENTITIES.tyler.pubkey, role: "member" }],
transcriptionEnabled: true,
},
});
await page.goto("/");
await expect(page.locator(".buzz-huddle-shell")).toHaveAttribute(
"data-huddle-open",
"true",
);
await page.evaluate(() => {
const threadRoot = window.__BUZZ_E2E_EMIT_MOCK_MESSAGE__?.({
channelName: "huddle",
content: "Transcript written while the companion is open",
});
if (!threadRoot) throw new Error("Failed to create Huddle thread root.");
window.__BUZZ_E2E_EMIT_MOCK_MESSAGE__?.({
channelName: "huddle",
content: "Agent reply preserved across the Huddle handoff",
parentEventId: threadRoot.id,
pubkey: "deadbeef".repeat(8),
});
});
await page
.getByRole("button", { name: "Open huddle in a new window" })
.click();
await expect(page.locator(".buzz-huddle-shell")).toHaveAttribute(
"data-huddle-open",
"false",
);
await page.evaluate(async () => {
await window.__BUZZ_E2E_INVOKE_MOCK_COMMAND__?.("close_huddle_companion");
});
await expect(page).toHaveURL(
new RegExp(`/channels/${HUDDLE_CHANNEL_ID.replaceAll("-", "\\-")}`),
);
await expect(
page
.getByTestId("message-row")
.filter({ hasText: "Transcript written while the companion is open" }),
).toBeVisible();
await expect(
page
.getByTestId("message-row")
.filter({ hasText: "Agent reply preserved across the Huddle handoff" }),
).toBeVisible();
await expect(page.getByTestId("message-thread-panel")).toHaveCount(0);
await page
.getByRole("button", { name: "Open huddle in a new window" })
.click();
await expect(page).toHaveURL(
new RegExp(`/channels/${HUDDLE_PARENT_ID.replaceAll("-", "\\-")}`),
);
await expect(
page.locator(`[data-channel-id="${HUDDLE_CHANNEL_ID}"]`),
).toHaveCount(0);
});
test("returns to the parent channel when leaving a huddle channel in view", async ({
page,
}) => {
await installMockBridge(page, {
huddle: {
parentChannelId: HUDDLE_PARENT_ID,
ephemeralChannelId: HUDDLE_CHANNEL_ID,
members: [{ pubkey: TEST_IDENTITIES.tyler.pubkey, role: "member" }],
},
});
await page.goto("/");
await expect(page.locator(".buzz-huddle-shell")).toHaveAttribute(
"data-huddle-open",
"true",
);
await page.evaluate(async () => {
await window.__BUZZ_E2E_INVOKE_MOCK_COMMAND__?.("close_huddle_companion");
});
await expect(page).toHaveURL(
new RegExp(`/channels/${HUDDLE_CHANNEL_ID.replaceAll("-", "\\-")}`),
);
await page.getByRole("button", { name: "Leave huddle" }).click();
await expect(page).toHaveURL(
new RegExp(`/channels/${HUDDLE_PARENT_ID.replaceAll("-", "\\-")}`),
);
await expect(
page.locator(`[data-channel-id="${HUDDLE_CHANNEL_ID}"]`),
).toHaveCount(0);
});
test("keeps the huddle avatar strip compact and exposes the full roster", async ({
page,
}) => {
// One named member plus ten key-only members (hex 01..0a + "a"×62), with
// the last as the huddle bot. The generated keys' npub tails are what
// key-fallback avatars abbreviate: 01… → npub1qx4…x2tc → X2,
// 02… → npub1q24…levs → LE, 0a… → npub1p24…sqjt → SQ.
const namedMember = "77".repeat(32);
const unnamedMembers = Array.from({ length: 10 }, (_, index) => ({
pubkey: `${(index + 1).toString(16).padStart(2, "0")}${"a".repeat(62)}`,
role: index === 9 ? ("bot" as const) : ("member" as const),
}));
const members = [
{ pubkey: namedMember, role: "member" as const },
...unnamedMembers,
];
await installMockBridge(page, {
huddle: {
parentChannelId: HUDDLE_PARENT_ID,
ephemeralChannelId: HUDDLE_CHANNEL_ID,
members,
},
searchProfiles: [{ pubkey: namedMember, displayName: "Ada Lovelace" }],
});
await page.goto("/");
const participantStrip = page.getByTestId("huddle-participant-strip");
const participantTrigger = page.getByRole("button", {
name: "Show all huddle participants (11)",
});
await expect(participantTrigger).toBeVisible();
await expect(
participantStrip.getByTestId("huddle-participant-avatar"),
).toHaveCount(9);
await expect(participantTrigger).toContainText("+2");
await expect(page.getByTestId("profile-huddle-control")).toHaveCount(0);
// Strip avatars stay distinct: the named member keeps name initials
// (AL), and a key-only participant shows its npub's tail (X2), never the
// word initials of the "Participant npub1…" label (PN).
const stripAvatars = participantStrip.getByTestId(
"huddle-participant-avatar",
);
await expect(stripAvatars.first()).toHaveText("AL");
await expect(stripAvatars.nth(1)).toHaveText(
keyTailInitials(unnamedMembers[0].pubkey),
);
await participantTrigger.click();
const roster = page
.getByRole("dialog")
.filter({ has: page.getByRole("heading", { name: "Participants" }) });
await expect(
page.getByRole("heading", { name: "Participants" }),
).toBeVisible();
const rosterRows = roster.getByRole("listitem");
// Visible labels keep their generated forms alongside the avatar initials.
await expect(rosterRows.filter({ hasText: "Ada Lovelace" })).toHaveCount(1);
await expect(
rosterRows.filter({
hasText: `Participant ${truncateNpub(unnamedMembers[0].pubkey)}`,
}),
).toHaveCount(1);
const agentRow = rosterRows.filter({
hasText: `Agent ${truncateNpub(unnamedMembers[9].pubkey)}`,
});
await expect(agentRow).toHaveCount(1);
await expect(
page.getByRole("button", { name: /Remove Agent .* from huddle/ }),
).toHaveCount(1);
// The roster's agent avatar abbreviates its key tail (SQ), never the
// "Agent" word initials of the prefixed label (AN).
await expect(agentRow.getByTestId("huddle-participant-avatar")).toHaveText(
keyTailInitials(unnamedMembers[9].pubkey),
);
});
test("removes an agent from its menu without showing an extra participant control", async ({
page,
}) => {
await installMockBridge(page, {
windowLabel: `huddle-${HUDDLE_CHANNEL_ID}`,
huddle: {
parentChannelId: HUDDLE_PARENT_ID,
ephemeralChannelId: HUDDLE_CHANNEL_ID,
members: [
{ pubkey: TEST_IDENTITIES.tyler.pubkey, role: "member" },
{ pubkey: TEST_IDENTITIES.alice.pubkey, role: "bot" },
],
},
});
await page.goto("/");
await expect(
page.getByRole("button", { name: "Manage huddle participants" }),
).toHaveCount(0);
await page.getByTestId("huddle-agent-voice-menu-trigger").click();
const removeButton = page.getByRole("button", {
name: "Remove alice from huddle",
});
await expect(removeButton).toBeVisible();
page.once("dialog", (dialog) => dialog.accept());
await removeButton.click({ force: true });
await expect
.poll(() =>
page.evaluate(() =>
(window.__BUZZ_E2E_COMMAND_LOG__ ?? []).some(
(entry) => entry.command === "remove_agent_from_huddle",
),
),
)
.toBe(true);
await expect(page.getByTestId("huddle-agent-voice-menu-trigger")).toHaveCount(
0,
);
});
test("keeps a newer huddle event over a delayed hydration snapshot", async ({
page,
}) => {
await installMockBridge(page, {
huddle: {
parentChannelId: HUDDLE_PARENT_ID,
ephemeralChannelId: HUDDLE_CHANNEL_ID,
members: [
{ pubkey: TEST_IDENTITIES.tyler.pubkey, role: "member" },
{ pubkey: TEST_IDENTITIES.alice.pubkey, role: "bot" },
],
transcriptionEnabled: true,
},
huddleStateReadDelayMs: 250,
});
await page.goto("/");
await expect
.poll(() =>
page.evaluate(() =>
(window.__BUZZ_E2E_COMMAND_LOG__ ?? []).some(
(entry) => entry.command === "get_huddle_state",
),
),
)
.toBe(true);
await setHuddleSnapshot(
page,
[{ pubkey: TEST_IDENTITIES.tyler.pubkey, role: "member" }],
false,
);
await expect(
page
.getByTestId("huddle-participant-strip")
.getByTestId("huddle-participant-avatar"),
).toHaveCount(1);
await expect(
page.getByRole("button", { name: /Show all huddle participants/ }),
).toHaveCount(0);
await expect(
page.getByRole("button", { name: "Start transcript" }),
).toHaveAttribute("aria-pressed", "false");
await page.waitForTimeout(300);
await expect(
page
.getByTestId("huddle-participant-strip")
.getByTestId("huddle-participant-avatar"),
).toHaveCount(1);
});
test("keeps a starting huddle in the drawer after its companion closes", async ({
page,
}) => {
await installFakeHuddleMicrophone(page);
await installMockBridge(page, {
openHuddleWindowDelayMs: 500,
startHuddleReturnDelayMs: 1_500,
});
await page.goto("/");
await page.getByTestId("channel-alice-tyler").click();
await page.getByTestId("channel-start-huddle-trigger").click();
await expect
.poll(() =>
page.evaluate(
() =>
(window.__BUZZ_E2E_COMMAND_LOG__ ?? []).filter(
(entry) => entry.command === "open_huddle_window",
).length,
),
)
.toBe(1);
const ephemeralChannelId = await page.evaluate(async () => {
const state = (await window.__BUZZ_E2E_INVOKE_MOCK_COMMAND__?.(
"get_huddle_state",
)) as { ephemeral_channel_id: string };
return state.ephemeral_channel_id;
});
await page.evaluate(async () => {
await window.__BUZZ_E2E_INVOKE_MOCK_COMMAND__?.("close_huddle_companion");
});
await expect(page.locator(".buzz-huddle-shell")).toHaveAttribute(
"data-huddle-open",
"true",
);
await expect(page).toHaveURL(
new RegExp(`/channels/${ephemeralChannelId.replaceAll("-", "\\-")}`),
);
await expect
.poll(() =>
page.evaluate(async () => {
const state = (await window.__BUZZ_E2E_INVOKE_MOCK_COMMAND__?.(
"get_huddle_state",
)) as { phase: string };
return state.phase;
}),
)
.toBe("active");
await expect
.poll(() =>
page.evaluate(
() =>
(window.__BUZZ_E2E_COMMAND_LOG__ ?? []).filter(
(entry) => entry.command === "open_huddle_window",
).length,
),
)
.toBe(1);
await expect(page.locator(".buzz-huddle-shell")).toHaveAttribute(
"data-huddle-open",
"true",
);
await expect(page.getByTestId("profile-huddle-control")).toHaveCount(0);
await expect(
page.locator(`[data-channel-id="${ephemeralChannelId}"]`),
).toBeVisible();
});
test("starts muted with Push to Talk while preserving manual microphone control", async ({
page,
}) => {
await installFakeHuddleMicrophone(page);
await installMockBridge(page, {
openHuddleWindowDelayMs: 10_000,
startHuddleReturnDelayMs: 1_500,
});
await page.goto("/");
await page.getByTestId("channel-alice-tyler").click();
await page.getByTestId("channel-start-huddle-trigger").click();
// Push to Talk huddles start muted (matching the Rust
// manual_mic_unmuted default) so nothing is hot until the user opts in.
const muteButton = page.getByRole("button", { name: "Mute microphone" });
const unmuteButton = page.getByRole("button", {
name: "Unmute microphone",
});
await expect(unmuteButton).toBeVisible();
await expect(unmuteButton).toHaveClass(/bg-destructive\/15/);
await expect(unmuteButton).toHaveClass(/text-destructive/);
// Manually unmuting hands the mic back to the user.
await unmuteButton.click();
await expect(muteButton).toBeVisible();
await expect(muteButton).not.toHaveClass(/bg-destructive\/15/);
await expect(
page.getByRole("button", { name: "Audio settings" }),
).not.toHaveClass(/bg-destructive\/15/);
await expect
.poll(() =>
page.evaluate(
() =>
(window.__BUZZ_E2E_COMMAND_LOG__ ?? []).findLast(
(entry) => entry.command === "set_huddle_manual_mic_unmuted",
)?.payload,
),
)
.toEqual({ enabled: true });
await muteButton.click();
await expect(unmuteButton).toBeVisible();
await expect(unmuteButton).toHaveClass(/bg-destructive\/15/);
await expect(unmuteButton).toHaveClass(/text-destructive/);
await expect
.poll(() =>
page.evaluate(
() =>
(window.__BUZZ_E2E_COMMAND_LOG__ ?? []).findLast(
(entry) => entry.command === "set_huddle_manual_mic_unmuted",
)?.payload,
),
)
.toEqual({ enabled: false });
await page.mouse.move(0, 0);
await unmuteButton.hover();
await expect(page.getByRole("tooltip")).toHaveAccessibleName(
/Click to unmute or hold .*Space/,
);
await page.evaluate(async () => {
await window.__BUZZ_E2E_EMIT_TAURI_EVENT__?.("ptt-state", true);
});
await expect(muteButton).toBeVisible();
await muteButton.click();
await expect
.poll(() =>
page.evaluate(
() =>
(window.__BUZZ_E2E_COMMAND_LOG__ ?? []).findLast(
(entry) => entry.command === "set_huddle_manual_mic_unmuted",
)?.payload,
),
)
.toEqual({ enabled: false });
await page.evaluate(async () => {
await window.__BUZZ_E2E_EMIT_TAURI_EVENT__?.("ptt-state", false);
});
await expect(unmuteButton).toBeVisible();
await page.getByRole("button", { name: "Audio settings" }).click();
await page.getByRole("button", { name: "Turn off Push to Talk" }).click();
await page.evaluate(async () => {
await window.__BUZZ_E2E_EMIT_TAURI_EVENT__?.("ptt-state", true);
});
await expect(unmuteButton).toBeVisible();
await page.getByRole("button", { name: "Turn on Push to Talk" }).click();
await expect(unmuteButton).toBeVisible();
await page.evaluate(async () => {
await window.__BUZZ_E2E_EMIT_TAURI_EVENT__?.("ptt-state", true);
});
await expect(muteButton).toBeVisible();
await page.evaluate(async () => {
await window.__BUZZ_E2E_EMIT_TAURI_EVENT__?.("ptt-state", false);
});
await expect(unmuteButton).toBeVisible();
await unmuteButton.click();
await expect(muteButton).toBeVisible();
await expect
.poll(() =>
page.evaluate(
() =>
(window.__BUZZ_E2E_COMMAND_LOG__ ?? []).findLast(
(entry) => entry.command === "set_huddle_manual_mic_unmuted",
)?.payload,
),
)
.toEqual({ enabled: true });
});
test("toggles the current channel huddle with Control+Shift+Space", async ({
page,
}) => {
await installFakeHuddleMicrophone(page);
await installMockBridge(page, {
openHuddleWindowDelayMs: 10_000,
});
await page.goto("/");
await page.getByTestId("channel-alice-tyler").click();
await expect(page.getByTestId("channel-start-huddle-trigger")).toBeEnabled();
const pressHuddleShortcut = () =>
page.evaluate(() => {
window.dispatchEvent(
new KeyboardEvent("keydown", {
bubbles: true,
code: "Space",
ctrlKey: true,
key: " ",
shiftKey: true,
}),
);
});
await pressHuddleShortcut();
await expect
.poll(() =>
page.evaluate(
() =>
(window.__BUZZ_E2E_COMMAND_LOG__ ?? []).filter(
(entry) => entry.command === "start_huddle",
).length,
),
)
.toBe(1);
await expect
.poll(() =>
page.evaluate(async () => {
const state = (await window.__BUZZ_E2E_INVOKE_MOCK_COMMAND__?.(
"get_huddle_state",
)) as { phase: string };
return state.phase;
}),
)
.toBe("active");
await pressHuddleShortcut();
await expect
.poll(() =>
page.evaluate(
() =>
(window.__BUZZ_E2E_COMMAND_LOG__ ?? []).filter(
(entry) => entry.command === "leave_huddle",
).length,
),
)
.toBe(1);
});
test("starts an agent DM huddle and hides its backing channel after it ends", async ({
page,
}) => {
await installFakeHuddleMicrophone(page);
await installMockBridge(page, {
openHuddleWindowDelayMs: 500,
startHuddleReturnDelayMs: 1_500,
});
await page.goto("/");
await page.getByTestId("channel-alice-tyler").click();
await expect(page.getByTestId("chat-title")).toHaveText("alice-tyler");
await expect
.poll(() =>
page.evaluate(
(pubkey) =>
window.__BUZZ_E2E_HAS_MOCK_OWNER_KIND_SUBSCRIPTION__?.({
ownerPubkey: pubkey,
kind: 44100,
}) ?? false,
"deadbeef".repeat(8),
),
)
.toBe(true);
const channelReadsBeforeStart = await page.evaluate(
() =>
(window.__BUZZ_E2E_COMMAND_LOG__ ?? []).filter(
(entry) => entry.command === "get_channels",
).length,
);
const startButton = page.getByTestId("channel-start-huddle-trigger");
await expect(startButton).toBeEnabled();
await startButton.click();
await expect
.poll(() =>
page.evaluate(
() =>
(window.__BUZZ_E2E_COMMAND_LOG__ ?? []).find(
(entry) => entry.command === "start_huddle",
)?.payload,
),
)
.toMatchObject({
memberPubkeys: [TEST_IDENTITIES.alice.pubkey],
parentChannelId: "f48efb06-0c93-5025-aac9-2e646bb6bfa8",
});
await expect
.poll(() =>
page.evaluate(
() =>
(window.__BUZZ_E2E_COMMAND_LOG__ ?? []).filter(
(entry) => entry.command === "open_huddle_window",
).length,
),
)
.toBe(1);
const startingState = await page.evaluate(async () =>
window.__BUZZ_E2E_INVOKE_MOCK_COMMAND__?.("get_huddle_state"),
);
expect(startingState).toMatchObject({ phase: "creating" });
await expect
.poll(() =>
page.evaluate(
() =>
(window.__BUZZ_E2E_COMMAND_LOG__ ?? []).filter(
(entry) => entry.command === "get_channels",
).length,
),
)
.toBeGreaterThan(channelReadsBeforeStart);
const pendingEphemeralChannelId = await page.evaluate(async () => {
const state = (await window.__BUZZ_E2E_INVOKE_MOCK_COMMAND__?.(
"get_huddle_state",
)) as { ephemeral_channel_id: string };
return state.ephemeral_channel_id;
});
await expect(
page.locator(`[data-channel-id="${pendingEphemeralChannelId}"]`),
).toHaveCount(0);
await expect(page.locator(".buzz-huddle-shell")).toHaveAttribute(
"data-huddle-open",
"false",
);
await expect
.poll(() =>
page.evaluate(
() =>
(window.__BUZZ_E2E_COMMAND_LOG__ ?? []).filter(
(entry) => entry.command === "open_huddle_window",
).length,
),
)
.toBe(1);
await expect(page.getByTestId("profile-huddle-control")).toBeVisible();
await expect(page.locator(".buzz-huddle-shell")).toHaveAttribute(
"data-huddle-open",
"false",
);
const ephemeralChannelId = await page.evaluate(async () => {
const state = (await window.__BUZZ_E2E_INVOKE_MOCK_COMMAND__?.(
"get_huddle_state",
)) as { ephemeral_channel_id: string };
return state.ephemeral_channel_id;
});
const huddleSidebarChannel = page.locator(
`[data-channel-id="${ephemeralChannelId}"]`,
);
await expect(huddleSidebarChannel).toHaveCount(0);
await page.evaluate(async () => {
await window.__BUZZ_E2E_INVOKE_MOCK_COMMAND__?.("close_huddle_companion");
});
await expect(page.locator(".buzz-huddle-shell")).toHaveAttribute(
"data-huddle-open",
"true",
);
await expect(page.getByTestId("profile-huddle-control")).toHaveCount(0);
await expect(page).toHaveURL(
new RegExp(`/channels/${ephemeralChannelId.replaceAll("-", "\\-")}`),
);
await expect(huddleSidebarChannel).toBeVisible();
await page
.getByRole("button", { name: "Open huddle in a new window" })
.click();
await expect(huddleSidebarChannel).toHaveCount(0);
await expect(page.locator(".buzz-huddle-shell")).toHaveAttribute(
"data-huddle-open",
"false",
);
await expect(page.getByTestId("profile-huddle-control")).toBeVisible();
await page.getByRole("button", { name: "Leave huddle" }).click();
await expect(huddleSidebarChannel).toHaveCount(0);
await expect(page.locator(".buzz-huddle-shell")).toHaveAttribute(
"data-huddle-open",
"false",
);
await waitForMockLiveSubscription(page, "alice-tyler");
const lifecycleCreatedAt = Math.floor(Date.now() / 1000);
await page.evaluate(
({ createdAt, ephemeralChannelId, kind }) => {
window.__BUZZ_E2E_EMIT_MOCK_MESSAGE__?.({
channelName: "alice-tyler",
content: JSON.stringify({ ephemeral_channel_id: ephemeralChannelId }),
createdAt,
id: "3".repeat(64),
kind,
});
},
{
createdAt: lifecycleCreatedAt,
ephemeralChannelId,
kind: KIND_HUDDLE_STARTED,
},
);
await expect(page.getByTestId("huddle-attachment")).toBeVisible();
await waitForMockLiveSubscription(page, "alice-tyler", KIND_HUDDLE_ENDED);
await page.evaluate(
({ createdAt, ephemeralChannelId, kind }) => {
window.__BUZZ_E2E_EMIT_MOCK_MESSAGE__?.({
channelName: "alice-tyler",
content: JSON.stringify({ ephemeral_channel_id: ephemeralChannelId }),
createdAt,
id: "4".repeat(64),
kind,
});
},
{
createdAt: lifecycleCreatedAt + 1,
ephemeralChannelId,
kind: KIND_HUDDLE_ENDED,
},
);
const endedHuddle = page
.getByTestId("huddle-attachment")
.filter({ hasText: "Huddle · Ended" });
await expect(endedHuddle).toBeVisible();
await endedHuddle.getByRole("button", { name: "View huddle" }).click();
await expect(page).toHaveURL(
new RegExp(`/channels/${ephemeralChannelId.replaceAll("-", "\\-")}`),
);
await expect(huddleSidebarChannel).toBeVisible();
await expect(page.getByTestId("message-thread-panel")).toHaveCount(0);
});
test("closes add-agent dialog when parent membership is already satisfied", async ({
page,
}) => {
await installMockBridge(page, {
addAgentToHuddleResult: {
ephemeral_added: true,
parent_added: true,
parent_error: null,
},
huddle: {
parentChannelId: HUDDLE_PARENT_ID,
ephemeralChannelId: HUDDLE_CHANNEL_ID,
members: [{ pubkey: TEST_IDENTITIES.tyler.pubkey, role: "member" }],
},
managedAgents: [
{
pubkey: TEST_IDENTITIES.bob.pubkey,
name: "bob",
status: "running",
},
],
});
await page.goto("/");
await page.getByRole("button", { name: "Add agent to huddle" }).click();
const dialog = page.getByRole("dialog", { name: "Add agents" });
await expect(dialog).toBeVisible();
await dialog.getByRole("button", { name: /bob/i }).click();
await expect(dialog).toHaveCount(0);
await expect(
page.getByText("Added to huddle, but parent channel failed:"),
).toHaveCount(0);
});
test("starts an available stopped agent before adding it to the huddle", async ({
page,
}) => {
await installMockBridge(page, {
addAgentToHuddleResult: {
ephemeral_added: true,
parent_added: true,
parent_error: null,
},
huddle: {
parentChannelId: HUDDLE_PARENT_ID,
ephemeralChannelId: HUDDLE_CHANNEL_ID,
members: [{ pubkey: TEST_IDENTITIES.tyler.pubkey, role: "member" }],
},
managedAgents: [
{
avatarUrl: "https://example.com/bob.png",
pubkey: TEST_IDENTITIES.bob.pubkey,
name: "bob",
status: "stopped",
},
],
});
await page.goto("/");
await page.getByRole("button", { name: "Add agent to huddle" }).click();
const dialog = page.getByRole("dialog", { name: "Add agents" });
await expect(dialog).toBeVisible();
await expect(dialog).toHaveClass(/data-\[state=open\]:animate-in/);
await expect(dialog).toHaveClass(/data-\[state=open\]:fade-in-0/);
await expect(dialog).toHaveClass(/data-\[state=open\]:zoom-in-95/);
await expect(dialog).toHaveClass(/duration-200/);
await expect(dialog).toHaveClass(/motion-reduce:animate-none/);
await expect(
dialog.getByText("Choose an agent to join this huddle.", { exact: true }),
).toBeVisible();
await expect(dialog.getByText("stopped", { exact: true })).toHaveCount(0);
await dialog.getByRole("button", { name: /bob/i }).click();
await expect
.poll(() =>
page.evaluate(() =>
(window.__BUZZ_E2E_COMMAND_LOG__ ?? [])
.filter(
(entry) =>
entry.command === "start_managed_agent" ||
entry.command === "add_agent_to_huddle",
)
.map((entry) => entry.command),
),
)
.toEqual(["start_managed_agent", "add_agent_to_huddle"]);
await expect(dialog).toHaveCount(0);
});
test("stops an agent started solely for a failed huddle add", async ({
page,
}) => {
await installMockBridge(page, {
addAgentToHuddleError: "membership publish rejected",
huddle: {
parentChannelId: HUDDLE_PARENT_ID,
ephemeralChannelId: HUDDLE_CHANNEL_ID,
members: [{ pubkey: TEST_IDENTITIES.tyler.pubkey, role: "member" }],
},
managedAgents: [
{
avatarUrl: "https://example.com/bob.png",
pubkey: TEST_IDENTITIES.bob.pubkey,
name: "bob",
status: "stopped",
},
],
});
await page.goto("/");
await page.getByRole("button", { name: "Add agent to huddle" }).click();
const dialog = page.getByRole("dialog", { name: "Add agents" });
await dialog.getByRole("button", { name: /bob/i }).click();
await expect(dialog.getByText(/Failed to add agent:/)).toBeVisible();
await expect
.poll(() =>
page.evaluate(() =>
(window.__BUZZ_E2E_COMMAND_LOG__ ?? [])
.filter((entry) =>
[
"start_managed_agent",
"add_agent_to_huddle",
"stop_managed_agent",
].includes(entry.command),
)
.map((entry) => entry.command),
),
)
.toEqual([
"start_managed_agent",
"add_agent_to_huddle",
"stop_managed_agent",
]);
});
test("does not deploy a provider agent when its huddle add fails", async ({
page,
}) => {
await installMockBridge(page, {
addAgentToHuddleError: "membership publish rejected",
huddle: {
parentChannelId: HUDDLE_PARENT_ID,
ephemeralChannelId: HUDDLE_CHANNEL_ID,
members: [{ pubkey: TEST_IDENTITIES.tyler.pubkey, role: "member" }],
},
managedAgents: [
{
avatarUrl: "https://example.com/bob.png",
backend: { type: "provider", id: "mock", config: {} },
pubkey: TEST_IDENTITIES.bob.pubkey,
name: "bob",
status: "not_deployed",
},
],
});
await page.goto("/");
await page.getByRole("button", { name: "Add agent to huddle" }).click();
const dialog = page.getByRole("dialog", { name: "Add agents" });
await dialog.getByRole("button", { name: /bob/i }).click();
await expect(dialog.getByText(/Failed to add agent:/)).toBeVisible();
await expect
.poll(() =>
page.evaluate(() =>
(window.__BUZZ_E2E_COMMAND_LOG__ ?? [])
.filter((entry) =>
[
"start_managed_agent",
"add_agent_to_huddle",
"stop_managed_agent",
].includes(entry.command),
)
.map((entry) => entry.command),
),
)
.toEqual(["add_agent_to_huddle"]);
});