diff options
Diffstat (limited to 'packages/meshbay-hub/tests')
| -rw-r--r-- | packages/meshbay-hub/tests/test_memory_ceiling.py | 63 | ||||
| -rw-r--r-- | packages/meshbay-hub/tests/test_streamed_download_reliability.py | 19 |
2 files changed, 71 insertions, 11 deletions
diff --git a/packages/meshbay-hub/tests/test_memory_ceiling.py b/packages/meshbay-hub/tests/test_memory_ceiling.py index d46cae3..1654825 100644 --- a/packages/meshbay-hub/tests/test_memory_ceiling.py +++ b/packages/meshbay-hub/tests/test_memory_ceiling.py @@ -90,9 +90,12 @@ const downloads = {{ // wrong failure entirely. lastStreamFailure: () => 'stubbed: no streamed target in this harness', getMode: () => {json.dumps(mode)}, - openTarget: async () => ({json.dumps(granted)} ? {{ name: 'g', writable: {{}} }} : null), + // `pausable` mirrors the real modules: a granted folder is a held-open file + // handle, a service-worker stream is a download the browser already owns. + openTarget: async () => + ({json.dumps(granted)} ? {{ name: 'g', writable: {{}}, pausable: true }} : null), openStreamedDownload: async () => - ({json.dumps(streamed)} ? {{ name: 's', writable: {{}} }} : null), + ({json.dumps(streamed)} ? {{ name: 's', writable: {{}}, pausable: false }} : null), }}; globalThis.window = {{}}; if ({json.dumps(picker)}) {{ @@ -115,7 +118,7 @@ try {{ {{ batched: {json.dumps(batched)} }}); outcome = r === null ? {{ kind: 'memory' }} : r === false ? {{ kind: 'cancelled' }} - : {{ kind: 'stream', name: r.name }}; + : {{ kind: 'stream', name: r.name, pausable: !!r.pausable }}; }} catch (err) {{ outcome = {{ kind: 'refused', name: err.name, message: err.message }}; }} @@ -164,17 +167,17 @@ def test_the_boundary_is_the_ceiling_itself(target_fn, tmp_path): def test_a_granted_folder_streams_whatever_the_size(target_fn, tmp_path): out = _run(target_fn, tmp_path, size=20 * GB, granted=True) - assert out == {"kind": "stream", "name": "g"} + assert (out["kind"], out["name"]) == ("stream", "g") def test_the_service_worker_streams_whatever_the_size(target_fn, tmp_path): out = _run(target_fn, tmp_path, size=20 * GB, streamed=True) - assert out == {"kind": "stream", "name": "s"} + assert (out["kind"], out["name"]) == ("stream", "s") def test_the_desktop_app_streams_whatever_the_size(target_fn, tmp_path): out = _run(target_fn, tmp_path, size=20 * GB, native=True) - assert out == {"kind": "stream", "name": "n"} + assert (out["kind"], out["name"]) == ("stream", "n") def test_a_browser_with_a_picker_is_offered_one_instead_of_being_refused( @@ -182,7 +185,7 @@ def test_a_browser_with_a_picker_is_offered_one_instead_of_being_refused( """Chrome/Edge: the file is large, nothing streamed yet, but Save As does. A refusal here would be this fix breaking a path that was never broken.""" out = _run(target_fn, tmp_path, size=20 * GB, picker=True) - assert out == {"kind": "stream", "name": "p"} + assert (out["kind"], out["name"]) == ("stream", "p") # ── One dialog per gesture, not one per file ──────────────────────────────── @@ -192,7 +195,7 @@ def test_the_first_of_a_batch_still_asks_where_to_save(target_fn, tmp_path): folder chooses it, for the download they actually clicked.""" out = _run(target_fn, tmp_path, size=20 * GB, mode="ask", picker=True, streamed=True) - assert out == {"kind": "stream", "name": "p"} + assert (out["kind"], out["name"]) == ("stream", "p") def test_the_rest_of_a_batch_stream_instead_of_asking(target_fn, tmp_path): @@ -207,7 +210,7 @@ def test_the_rest_of_a_batch_stream_instead_of_asking(target_fn, tmp_path): """ out = _run(target_fn, tmp_path, size=20 * GB, mode="ask", picker=True, streamed=True, batched=True) - assert out == {"kind": "stream", "name": "s"} + assert (out["kind"], out["name"]) == ("stream", "s") def test_a_batched_download_falls_back_to_the_dialog_rather_than_failing( @@ -218,7 +221,7 @@ def test_a_batched_download_falls_back_to_the_dialog_rather_than_failing( neither must the fix for one.""" out = _run(target_fn, tmp_path, size=20 * GB, mode="ask", picker=True, streamed=False, batched=True) - assert out == {"kind": "stream", "name": "p"} + assert (out["kind"], out["name"]) == ("stream", "p") def test_batching_never_pushes_a_large_file_into_memory(target_fn, tmp_path): @@ -277,7 +280,7 @@ def test_a_lost_gesture_streams_instead_of_failing(target_fn, tmp_path): """ out = _run(target_fn, tmp_path, size=20 * GB, picker="no-gesture", streamed=True, mode="ask") - assert out == {"kind": "stream", "name": "s"}, out + assert (out["kind"], out["name"]) == ("stream", "s"), out def test_a_lost_gesture_with_nothing_to_stream_to_still_refuses(target_fn, tmp_path): @@ -286,3 +289,41 @@ def test_a_lost_gesture_with_nothing_to_stream_to_still_refuses(target_fn, tmp_p out = _run(target_fn, tmp_path, size=20 * GB, picker="no-gesture", streamed=False, mode="ask") assert out["kind"] == "refused", out + + +# ── Which targets can be paused ───────────────────────────────────────────── +# +# `pausable` travels with the target rather than with the platform, because the +# same browser yields both answers on the same page: a granted folder is a +# held-open file, and a service-worker stream is a download the browser already +# owns. The widget draws its button from this and nothing else. + + +def test_a_granted_folder_can_be_paused(tmp_path, target_fn): + out = _run(target_fn, tmp_path, size=20 * GB, granted=True) + assert out["pausable"] is True + + +def test_a_save_dialog_can_be_paused(tmp_path, target_fn): + out = _run(target_fn, tmp_path, size=20 * GB, picker=True) + assert out["pausable"] is True + + +def test_the_desktop_sink_can_be_paused(tmp_path, target_fn): + out = _run(target_fn, tmp_path, size=20 * GB, native=True) + assert out["pausable"] is True + + +def test_a_service_worker_stream_cannot_be_paused(tmp_path, target_fn): + """Not a shortcoming of this code. The browser is already writing an HTTP + response into its own download folder: not feeding the stream stalls that + download where we can neither see nor resume it, and an idle worker is + terminated within seconds. Firefox and Safari have no other target, so they + get cancel and no pause — the browser's own download manager is where a + pause lives there, for as long as it works. + + This is also why Chrome shows no pause button until a download folder has + been granted: without one, "save automatically" means the service worker. + """ + out = _run(target_fn, tmp_path, size=20 * GB, streamed=True) + assert out["pausable"] is False diff --git a/packages/meshbay-hub/tests/test_streamed_download_reliability.py b/packages/meshbay-hub/tests/test_streamed_download_reliability.py index 355fbff..da745d0 100644 --- a/packages/meshbay-hub/tests/test_streamed_download_reliability.py +++ b/packages/meshbay-hub/tests/test_streamed_download_reliability.py @@ -501,3 +501,22 @@ def test_a_download_waits_for_the_self_test(tmp_path): """) assert out["target"] is True assert out["ms"] >= 1, "the download did not wait for priming at all" + + +def test_the_streamed_target_says_it_cannot_be_paused(tmp_path): + """The value the widget's pause button is drawn from, read off the real + module rather than a stub of it. + + It is false for a reason that is not about this code: the browser is already + writing an HTTP response into its own download folder, so not feeding the + stream stalls a download we can neither see nor resume, and an idle worker + is terminated within seconds. Firefox and Safari therefore get cancel and no + pause; Chrome gets one as soon as a download folder has been granted, which + yields a held-open file instead of this. + """ + out = _run(tmp_path, """ + const target = await M.openStreamedDownload('film.mkv', 20e9, FAST); + out.pausable = target && target.pausable; + if (target) await target.writable.close(); + """) + assert out["pausable"] is False |