From cfa16e1bc22ea6754c8b4be84af70a6ac1593a67 Mon Sep 17 00:00:00 2001 From: VasilisNtovolos Date: Tue, 20 Oct 2026 15:49:05 +0300 Subject: [PATCH] docs: clarify message drag routing verification --- hooks/__tests__/use-email-drag-routing.md | 155 ++++++---------------- 1 file changed, 43 insertions(+), 112 deletions(-) diff --git a/hooks/__tests__/use-email-drag-routing.md b/hooks/__tests__/use-email-drag-routing.md index 32b78c3fd..8b78ea796 100644 --- a/hooks/__tests__/use-email-drag-routing.md +++ b/hooks/__tests__/use-email-drag-routing.md @@ -1,125 +1,56 @@ -# Message drag blob routing +# Message drag regression tests -- Worktree: `/home/billy/work/bulwark-deploy/bulwark-drag-out` -- Branch: `fix/message-drag-blob-routing` -- Audited base and unchanged HEAD: `640d4b8c2e44bcb61b099a5511e06dbd5d7ca537`. +The maintained drag tests use synthetic JMAP sessions and message bytes with real +JMAP URL expansion, authentication and blob-fetch code. They verify: -Read repository guidance in `CONTRIBUTING.md`; no applicable `AGENTS.md` was -present. The worktree was clean before adding these changes. Before editing the -hook, verified that single-message prefetch and ZIP retrieval used the active -client without an owner account, and that cache keys omitted routing identity. +- Primary, directly shared and secondary-login message routing; each mixed-owner + ZIP entry uses its originating client and owner, including colliding IDs. +- Account-aware selection and expanded-thread members, filenames and drag payloads. +- Pointer entry on actual message rows and thread headers prepares drag content + while retaining working hover actions. +- Cache identity across clients, owners, messages and blobs; stable-context + pending fetches can warm a retry after dragend, while changed contexts and + unmounted rows cannot publish stale content. Retired object URLs retain the + 60-second cleanup grace period. -The hook now reuses `resolveEmailBlobContext` for each originating message. -Selections use the existing account-aware selection resolver, including loaded -expanded-thread members. Cache identity includes the authenticated client object, -login, owning JMAP account, message identity, blob ID and filename. Drag start -checks that identity again; obsolete asynchronous completions cannot replace the -current entry and their URLs receive the existing 60-second cleanup grace period. - -`use-email-drag-routing.test.tsx` uses synthetic JMAP sessions and RFC 822 bytes -with the real JMAP connection, URL expansion, authentication and blob-fetch code. -Both logins use the same synthetic server to exercise authentication collisions. -The tests inspect single-message bytes and ZIP entry contents/counts. No real -messages or mail server are used. The existing `use-email-drag.test.tsx` assertions -are retained unchanged. - -Run the maintained drag regressions with: +Run from the repository root with dependencies installed: ```sh -./node_modules/.bin/vitest run hooks/__tests__/use-email-drag.test.tsx hooks/__tests__/use-email-drag-routing.test.tsx --maxWorkers=1 --no-file-parallelism --reporter=verbose +./node_modules/.bin/vitest run \ + hooks/__tests__/use-email-drag.test.tsx \ + hooks/__tests__/use-email-drag-routing.test.tsx ``` -Dependencies were installed from the existing lockfile using `npm ci --cache -/tmp/bulwark-drag-out-npm-cache --no-audit --no-fund --ignore-scripts`. Dependencies, -Vitest caches and Next build outputs belong to this worktree; no sibling -worktree or cache was modified. +## Limitations -## Row hover and lifecycle correction +`DownloadURL` must be available synchronously at dragstart. Hover preparation or +a later attempt may be necessary when the cache is cold. Fetch completion never +adds a file to a drag already in progress. Ready single-message caches are +retired on dragend, so another hover may be needed before a later attempt. -Single-message rows and thread headers now call both the existing hover-action -handler and the hook's hover-prefetch handler. The maintained tests render the -real `ThreadListItem` and its real hover actions and drag hook, using synthetic -network responses with real JMAP URL/authentication code. +ZIP export silently omits failed fetches, messages without blob IDs and messages +whose source login is unavailable. An archive can contain fewer entries than its +filename suggests, or be empty if every eligible fetch fails. Partial or failed +bundle builds remain cached until their cache key changes; the same selection +is not automatically retried. -A single-message fetch that is still pending when dragend fires can finish into -the cache for a later drag. Completion checks both the current cache entry and -its freshly resolved client/owner/message identity. Navigation to another owner -or login, message/blob changes, and unmount cannot publish obsolete bytes. -Already-ready single-message URLs retain the existing dragend retirement and -60-second revocation grace period. ZIP caches still survive dragend. +## Manual desktop verification -## Remaining cold-cache limitation +DataTransfer, object URLs and browser user agents are mocked under jsdom. Tests +check payload construction, synthetic message/ZIP bytes and URL lifetime; these +assertions do not establish native desktop file creation. -`DownloadURL` is written only synchronously during dragstart when the matching -cache is ready. A cold first drag can still show the email preview and support -internal mailbox dragging while providing no desktop file. Fetch completion -never changes that drag's DataTransfer. If the pending request finishes after -dragend in the same context, the next drag can use it synchronously. If it -finishes before dragend, dragend retires that ready cache as before, so another -hover-prefetch must warm the row before a later attempt. No asynchronous -DataTransfer updates or native desktop delivery guarantees were added. +1. In a supported desktop Chromium browser, hover a message row, confirm its + hover actions still work, then drag its sender/subject area to the desktop. + Confirm that an `.eml` file is created. Repeat for primary, shared and + secondary-login messages using controlled test data. +2. Try a cold-cache drag. If no file is created, allow preparation to complete, + hover again and retry. Check file creation separately from the drag preview + and successful network responses. +3. Select controlled messages from multiple clients/owners, allow preparation, + and drag them to the desktop. Confirm that a ZIP file is created; separately + inspect its expected entry count and message contents. -## Remaining failure-handling gap - -ZIP retrieval still silently skips failed entries, messages without blob IDs and -messages whose source login is unavailable. An archive can contain fewer entries -than the selection count in its filename; if every eligible fetch fails it can -be empty. Failed/partial bundle builds remain cached until the selection/routing -key changes. The regression suite explicitly retains the existing partial-failure -behavior. No failure UI or unrelated export behavior was redesigned. - -DataTransfer, object URLs and browser user agents are mocked under jsdom. These -checks verify payload construction, routing, archive bytes and URL retirement; -native browser/desktop drag-to-filesystem behavior has not been verified. - -## Initial routing validation - -- Exact final regression tests with only the hook replaced by the audited base: - **20 failed, 4 passed**. Direct shared-folder requests used the primary owner; - secondary-login requests used primary credentials; mixed ZIP contents were - incorrect. The fixed hook was restored byte-for-byte after the replay. -- With the fix: **24/24 drag tests passed**, including the retained original test. - The broader focused drag/blob/account-selection/thread run passed **138/138** - tests across seven files. -- `npm run typecheck`: passed. -- `npm run lint`: passed; 16 warnings in unchanged files. Targeted lint on the - changed hook/test passed without warnings. -- `npm run build`: passed; 16 filesystem-tracing warnings in unchanged files. -- `git diff --check`, plus whitespace checks on both new files: passed. -- `vitest run --maxWorkers=2`: **8,377 passed, 2 skipped, 1 failed**, across 783 - test files. The sole failure is `lib/__tests__/idn.test.ts:39`, where - `toAsciiDomain('xn--zz.de')` returns the input instead of `null`. It also fails - in isolation. Both the test and `lib/idn.ts` are byte-identical to the audited - base; neither imports the drag hook. This unrelated behavior was left unchanged. - -Session logs are in `/tmp/bulwark-drag-out-base-final-tests.log`, -`/tmp/bulwark-drag-out-focused.log`, `/tmp/bulwark-drag-out-unit-tests.log`, -`/tmp/bulwark-drag-out-final-drag-and-idn.log`, and the corresponding -`bulwark-drag-out-{typecheck,lint,build}.log` files. No integration suite, real -mailbox operation or native desktop drag verification was run. Nothing was -staged, committed, pushed or published. - -## Row/lifecycle validation - -Before correcting the current uncommitted routing patch, the extended routing -suite had **5 failures and 28 passes**. The failures were: - -- Single-message row pointer entry did not start blob prefetch. -- Thread-header pointer entry did not start ZIP prefetch. -- Pointer entry on a selected real row did not prefetch the mixed-owner ZIP. -- A pending cold drag could not supply `DownloadURL` on a retry after dragend and - fetch completion, both through direct hook handlers and through the real row. - -After correction, the drag suites passed **34/34** tests, including all retained -original assertions. The focused row/drag/routing/selection/thread/context/JMAP -run passed **262/262** tests across **17 files**. `npm run typecheck` passed; -`npm run lint` passed with 16 warnings in unchanged files. Whitespace checks -passed. The prior full-suite and build results above describe the initial -routing validation; those broader checks were not repeated for this correction. - -The before/after evidence is in `/tmp/bulwark-drag-out-lifecycle-before.log` and -`/tmp/bulwark-drag-out-lifecycle-after.log`; the focused, typecheck and lint logs -use the same prefix. The existing proxy, Next configuration, environment files, -package manifest and lockfile were preserved byte-for-byte. Dependencies were -unchanged. Native Chrome-to-Windows desktop file creation remains unverified -until manually tested. Nothing was staged, committed or pushed. +Record the browser version, operating system, file-creation results and whether +ZIP entry contents were actually inspected. Observing a payload or a successful +GET alone is not a successful native desktop check.