diff --git a/desktop/playwright.config.ts b/desktop/playwright.config.ts index 5c5bdbc566..776ad2e8c3 100644 --- a/desktop/playwright.config.ts +++ b/desktop/playwright.config.ts @@ -85,6 +85,7 @@ export default defineConfig({ "**/relay-connectivity.spec.ts", "**/unread-pill.spec.ts", "**/sidebar-more-unread-overlap.spec.ts", + "**/sidebar-community-rail-insets.spec.ts", "**/sidebar-snapshot.spec.ts", "**/home-collapsed-top-chrome.spec.ts", "**/top-chrome-zoom-clearance.spec.ts", diff --git a/desktop/src/features/sidebar/ui/AppSidebar.tsx b/desktop/src/features/sidebar/ui/AppSidebar.tsx index 9c7f3cf166..0838707feb 100644 --- a/desktop/src/features/sidebar/ui/AppSidebar.tsx +++ b/desktop/src/features/sidebar/ui/AppSidebar.tsx @@ -503,13 +503,12 @@ export function AppSidebar({ variant="sidebar" >
1 ? "md:-ml-[11px] md:w-[calc(100%+11px)]" : "" - }`} + className="relative flex min-h-0 flex-1 flex-col overflow-hidden" data-sidebar-background data-testid="app-sidebar-scroll-anchor" > 1 ? "md:-ml-2" : undefined} channelLabels={dmChannelLabels} currentPubkey={currentPubkey} currentChannelId={ diff --git a/desktop/src/features/sidebar/ui/AppSidebarPinnedHeader.tsx b/desktop/src/features/sidebar/ui/AppSidebarPinnedHeader.tsx index a9bf7058eb..4a360577f9 100644 --- a/desktop/src/features/sidebar/ui/AppSidebarPinnedHeader.tsx +++ b/desktop/src/features/sidebar/ui/AppSidebarPinnedHeader.tsx @@ -4,6 +4,7 @@ import { TopbarSearch } from "@/features/search/ui/TopbarSearch"; import { SidebarProjectsSection } from "@/features/sidebar/ui/SidebarProjectsSection"; import { FeatureGate } from "@/shared/features"; import type { Channel, SearchHit } from "@/shared/api/types"; +import { cn } from "@/shared/lib/cn"; import { SidebarHeader, SidebarMenu, @@ -24,6 +25,7 @@ type SidebarSelectedView = type AppSidebarPinnedHeaderProps = { channelLabels: Record; + className?: string; currentChannelId?: string | null; currentPubkey?: string; onBrowseChannels?: () => void; @@ -51,6 +53,7 @@ type AppSidebarPrimaryMenuProps = { export function AppSidebarPinnedHeader({ channelLabels, + className, currentChannelId, currentPubkey, onBrowseChannels, @@ -66,7 +69,7 @@ export function AppSidebarPinnedHeader({ }: AppSidebarPinnedHeaderProps) { return (
{ + window.localStorage.setItem( + "buzz-communities", + JSON.stringify(communities), + ); + window.localStorage.setItem("buzz-active-community-id", "ws-a"); + }, COMMUNITIES); +} + +async function showUpdateCard(page: Page) { + await page.evaluate(() => { + const testWindow = window as Window & { + __BUZZ_E2E__?: { mock?: { updateAvailable?: boolean } }; + }; + testWindow.__BUZZ_E2E__ = { + ...(testWindow.__BUZZ_E2E__ ?? {}), + mock: { + ...(testWindow.__BUZZ_E2E__?.mock ?? {}), + updateAvailable: true, + }, + }; + }); + + await page.getByTestId("sidebar-profile-card").click(); + await page.getByTestId("profile-popover-settings").click(); + await page.getByTestId("settings-nav-updates").click(); + await page.getByRole("button", { name: "Check for Updates" }).click(); + await expect(page.getByTestId("settings-panel-updates")).toContainText( + "Update downloaded. Click to apply.", + ); + await page.getByTestId("settings-back-to-app").click(); +} + +async function settleElementAnimations(locator: Locator) { + await locator.evaluate((element) => + Promise.allSettled( + element.getAnimations().map((animation) => animation.finished), + ), + ); +} + +test("keeps sidebar cards and drag surfaces inset beside the community rail", async ({ + page, +}) => { + await installMockBridge(page, undefined, { skipCommunitySeed: true }); + await seedCommunities(page); + await page.goto("/"); + await expect(page.getByTestId("community-rail")).toBeVisible(); + + await showUpdateCard(page); + + const sidebar = page.getByTestId("app-sidebar"); + const updateCard = page.getByTestId("sidebar-update-card"); + await expect(updateCard).toBeVisible(); + await settleElementAnimations(updateCard); + const [sidebarBox, updateCardBox] = await Promise.all([ + sidebar.boundingBox(), + updateCard.boundingBox(), + ]); + expect(sidebarBox).not.toBeNull(); + expect(updateCardBox).not.toBeNull(); + expect((updateCardBox?.x ?? 0) - (sidebarBox?.x ?? 0)).toBeCloseTo(8, 0); + + const channelRow = page.getByTestId("channel-general"); + await expect(channelRow).toBeVisible(); + const channelRowBox = await channelRow.boundingBox(); + expect(channelRowBox).not.toBeNull(); + expect((channelRowBox?.x ?? 0) - (sidebarBox?.x ?? 0)).toBeCloseTo(11, 0); + if (!channelRowBox) return; + + await page.mouse.move( + channelRowBox.x + channelRowBox.width / 2, + channelRowBox.y + channelRowBox.height / 2, + ); + await page.mouse.down(); + await page.mouse.move( + channelRowBox.x + channelRowBox.width / 2, + channelRowBox.y + channelRowBox.height / 2 + 8, + { steps: 5 }, + ); + + const dragOverlay = page.getByTestId("sidebar-channel-drag-overlay"); + await expect(dragOverlay).toBeVisible(); + const dragOverlayBox = await dragOverlay.boundingBox(); + expect(dragOverlayBox).not.toBeNull(); + expect( + (dragOverlayBox?.x ?? 0) - (sidebarBox?.x ?? 0), + ).toBeGreaterThanOrEqual(10); + await page.mouse.up(); +});