From e05fbb2fe925e88826a527a42e811ffcad84f02c Mon Sep 17 00:00:00 2001 From: Stefan Hildebrandt <695494+hildebrandttk@users.noreply.github.com> Date: Tue, 7 Jul 2026 23:36:37 +0200 Subject: [PATCH] test(integration): All Mail, message actions, and shared-folder sync MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extend the integration suite (now 22 tests) to cover: - All Mail view (04): single-account merge of Inbox + custom folders with Junk excluded, and cross-account aggregation across every logged-in account. - Message actions from the list context menu (05): mark read/unread, delete (→ Trash), mark-as-spam (→ Junk) and not-spam round-trip, verified on both the UI counters/row state and the server mailbox the message ends up in. - Shared/delegated folders (06): a delegated folder (+ Trash/Junk) shared alice→carol; the shared folder renders with its counter, and read/unread/ delete/spam performed there land correctly (server-verified). Hooks added: data-testid on context-menu delete/spam/read-unread items (via a testId prop on ContextMenuItem), data-shared on folder rows, and testId/data-expanded on sidebar section headers to drive the Shared section. Observations surfaced by the suite (asserted server-side / with a reconcile): - mark-as-spam doesn't optimistically decrement the *source* counter the way delete does; a visibility reconcile settles it. - shared *destination* counters (shared Trash/Junk) don't refresh live — forceSync reconciles the active account only, not shared accounts. --- components/email/email-context-menu.tsx | 3 + components/layout/sidebar.tsx | 11 ++ components/ui/context-menu.tsx | 4 + integration/tests/04-all-mail.spec.ts | 97 ++++++++++++++ integration/tests/05-actions.spec.ts | 117 +++++++++++++++++ integration/tests/06-shared-folders.spec.ts | 134 ++++++++++++++++++++ integration/tests/helpers/app.ts | 87 +++++++++++-- integration/tests/helpers/jmap.ts | 91 ++++++++++++- 8 files changed, 529 insertions(+), 15 deletions(-) create mode 100644 integration/tests/04-all-mail.spec.ts create mode 100644 integration/tests/05-actions.spec.ts create mode 100644 integration/tests/06-shared-folders.spec.ts diff --git a/components/email/email-context-menu.tsx b/components/email/email-context-menu.tsx index f8229ca1..cf095762 100644 --- a/components/email/email-context-menu.tsx +++ b/components/email/email-context-menu.tsx @@ -295,6 +295,7 @@ export function EmailContextMenu({ handleAction(showBatchActions ? onBatchDelete! : onDelete!) } @@ -410,6 +411,7 @@ export function EmailContextMenu({ handleAction( showBatchActions @@ -429,6 +431,7 @@ export function EmailContextMenu({ handleAction(() => showBatchActions diff --git a/components/layout/sidebar.tsx b/components/layout/sidebar.tsx index 3d1d25c7..122a4bdb 100644 --- a/components/layout/sidebar.tsx +++ b/components/layout/sidebar.tsx @@ -259,6 +259,7 @@ interface SidebarRowProps { testRole?: string | null; testName?: string; testMailboxId?: string; + testShared?: boolean; } function SidebarRow({ @@ -282,6 +283,7 @@ function SidebarRow({ testRole, testName, testMailboxId, + testShared, }: SidebarRowProps) { const t = useTranslations('sidebar'); const leftPad = isCollapsed ? 0 : ROW_PX_BASE + depth * INDENT_STEP; @@ -294,6 +296,7 @@ function SidebarRow({ data-folder-role={testRole ?? undefined} data-folder-name={testName ?? undefined} data-mailbox-id={testMailboxId ?? undefined} + data-shared={testShared ? 'true' : undefined} style={{ paddingBlock: 'var(--density-sidebar-py)' }} className={cn( "group w-full flex items-center max-lg:min-h-[44px] text-sm transition-colors duration-150", @@ -373,6 +376,7 @@ function SidebarSectionHeader({ first, icon, sub, + testId, }: { label: string; expanded: boolean; @@ -383,6 +387,7 @@ function SidebarSectionHeader({ first?: boolean; icon?: ReactNode; sub?: boolean; + testId?: string; }) { if (isCollapsed) { return first ? null :
; @@ -397,6 +402,9 @@ function SidebarSectionHeader({ return (