Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions desktop/playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export default defineConfig({
name: "smoke",
testMatch: [
"**/smoke.spec.ts",
"**/dm-hide-failure.spec.ts",
"**/owned-agent-discovery.spec.ts",
"**/thread-head-stale-edit.spec.ts",
"**/sidebar-offcanvas-rail.spec.ts",
Expand Down
8 changes: 7 additions & 1 deletion desktop/src/app/AppShell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as React from "react";
import { ProtectedGlobalOverlay } from "@protected-feature-components";
import { useQueryClient } from "@tanstack/react-query";
import { Outlet, useLocation } from "@tanstack/react-router";
import { toast } from "sonner";
import { deriveShellRoute, markAllReadSources } from "@/app/AppShell.helpers";
import { useTerminalContext } from "@/app/useTerminalContext";
import { AppShellProvider } from "@/app/AppShellContext";
Expand Down Expand Up @@ -625,7 +626,12 @@ export function AppShell() {
async (channelId: string) => {
try {
await hideDmMutation.mutateAsync(channelId);
} catch {
} catch (error) {
toast.error(
error instanceof Error
? error.message
: "Failed to close direct message",
);
return;
}

Expand Down
7 changes: 7 additions & 0 deletions desktop/src/testing/e2eBridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1364,6 +1364,8 @@ declare global {
__BUZZ_E2E_UNSUPPORTED_PROJECT_ANNOUNCEMENTS__?: boolean;
/** Project event kinds accepted once but reported as failed to test lost acknowledgements. */
__BUZZ_E2E_FAIL_PROJECT_EVENT_ACK_KINDS__?: number[];
/** Makes hiding a DM fail, to exercise the error path of the sidebar close action. */
__BUZZ_E2E_FAIL_HIDE_DM__?: string;
/**
* Extra project events appended to the mock store on first access.
* Use to seed standalone repositories (kind 30617) or other project-scoped
Expand Down Expand Up @@ -7401,6 +7403,11 @@ async function handleHideDm(
args: { channelId: string },
config: E2eConfig | undefined,
) {
const forcedFailure = window.__BUZZ_E2E_FAIL_HIDE_DM__;
if (forcedFailure) {
throw new Error(forcedFailure);
}

const identity = getIdentity(config);
if (!identity) {
const index = mockChannels.findIndex(
Expand Down
30 changes: 30 additions & 0 deletions desktop/tests/e2e/dm-hide-failure.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { expect, test } from "@playwright/test";

import { installMockBridge } from "../helpers/bridge";

const DM_NAME = "alice-tyler";
const RELAY_ERROR = "relay error 400: forbidden: not a member of this DM";

test("a rejected DM close reports the relay error and keeps the row", async ({
page,
}) => {
await page.addInitScript((message) => {
window.__BUZZ_E2E_FAIL_HIDE_DM__ = message;
}, RELAY_ERROR);
await installMockBridge(page);
await page.goto("/", { waitUntil: "domcontentloaded" });

const dmRow = page.getByTestId(`channel-${DM_NAME}`);
await expect(dmRow).toBeVisible();

await dmRow.hover();
await page.getByTestId(`hide-dm-${DM_NAME}`).click();

await expect(
page.locator("[data-sonner-toast]").filter({ hasText: RELAY_ERROR }),
).toBeVisible();

// The optimistic removal must roll back: the conversation is still there,
// so the sidebar must not claim it went away.
await expect(dmRow).toBeVisible();
});