aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/tests/test_zip_size_limit.py
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-09-09 01:54:10 +0200
committerChristophe Besson <cbesson@gmail.com>2026-09-09 01:54:10 +0200
commitd6c4808d9a3ef6bc740cda7892508f15ee9ea030 (patch)
treeb9420bd6cc86ac0a72aef09d5ca0ee7e25a3533f /packages/meshbay-hub/tests/test_zip_size_limit.py
parenta0b070e5fd382bb4a4262637836cb8d4b268fbf7 (diff)
downloadmeshbay-d6c4808d9a3ef6bc740cda7892508f15ee9ea030.tar.gz
fix(spa): one save dialog per batch, not one per file
Selecting four files on Chrome produced a Save As dialog for the first, then one for the second only after that file had finished, while the last two timed out; on a later attempt the three remaining transfers appeared frozen. Two things were going on. Opening the target inside `prepare` had removed the accidental serialisation that `for (…) await downloadFile(e)` used to provide, so `_openTargetInTurn` now queues the openings — but a queue whose head is an unanswered dialog is a head-of-line block, which is what the "freeze" was. The code already recovered from a picker with no gesture behind it by streaming instead, on the `SecurityError` Chrome throws. That branch was never reached: Chrome does not throw, it shows the dialog anyway and waits for a human. So anything that has to wait its turn is now marked `batched`, and a batched opening prefers the streamed path whatever the download mode says. The first file of a batch — the one actually holding the gesture — still gets its dialog, so the preference is honoured where it can be. For the rest there is no gesture left to spend and nothing is lost by streaming: the file still lands on disk, in the browser's own download folder. Only the choice of folder goes, and it was not on offer. If the worker does not answer, a batched download falls back to the dialog rather than failing. Also logs which path led to a dialog. A dialog is the one outcome nobody can diagnose after the fact — it looks the same whether it was asked for or fallen back to — and the report this fixes needed three test cycles to narrow. The two harnesses that lift `_openDownloadTarget` as text now route console.info to stderr, since they parse stdout as JSON. Measured against the deployed hub in Chrome 152: the streamed path serves the hidden iframe in 2-3 ms on a normal load, after a hard reload (via the `mbdl-claim` recovery already in `_claimController`), and twice in the same document. Hub suite 824 passed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HCGdheDLxGReuKHga3BtST
Diffstat (limited to 'packages/meshbay-hub/tests/test_zip_size_limit.py')
-rw-r--r--packages/meshbay-hub/tests/test_zip_size_limit.py4
1 files changed, 4 insertions, 0 deletions
diff --git a/packages/meshbay-hub/tests/test_zip_size_limit.py b/packages/meshbay-hub/tests/test_zip_size_limit.py
index 28e3a0c..9471b8a 100644
--- a/packages/meshbay-hub/tests/test_zip_size_limit.py
+++ b/packages/meshbay-hub/tests/test_zip_size_limit.py
@@ -60,6 +60,10 @@ globalThis.localStorage = {{
// Node 22 defines `navigator` itself, so it is left alone; `window` is what
// platform.js reaches for to decide it is not running in the desktop app.
globalThis.window = globalThis;
+// stdout carries the outcome and nothing else, so file-utils' own logging goes
+// to stderr -- where it is still shown when a case fails. It logs before every
+// save dialog, which is exactly what this harness provokes.
+console.info = (...a) => console.error(...a);
const out = {{ errors: [], started: 0, asked: 0, dropped: 0 }};
// Reached only once the size check has passed: with no File System Access API
// under Node, downloadDirectory falls through to its build-in-memory path and