aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/tests
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-hub/tests')
-rw-r--r--packages/meshbay-hub/tests/test_downloads.py13
-rw-r--r--packages/meshbay-hub/tests/test_spa_ordering.py30
2 files changed, 43 insertions, 0 deletions
diff --git a/packages/meshbay-hub/tests/test_downloads.py b/packages/meshbay-hub/tests/test_downloads.py
index cc4fdd1..cd0cded 100644
--- a/packages/meshbay-hub/tests/test_downloads.py
+++ b/packages/meshbay-hub/tests/test_downloads.py
@@ -95,3 +95,16 @@ say(await M.freeName('clip.mp4', async n => n === 'clip.mp4'));
def test_a_browser_without_the_api_reports_it(tmp_path):
"""`SUPPORTED` decides whether Settings offers a choice or an explanation."""
assert _run("say(M.SUPPORTED);", tmp_path) == [False]
+
+
+def test_the_open_action_reads_the_file_back(tmp_path):
+ """
+ "Open" is the browser being handed the bytes, not a desktop application
+ being started — no web page can do the second, and none can show a file
+ manager either. It is only offered for a file written into a granted folder,
+ since that is the one a page can read back.
+ """
+ src = DOWNLOADS.read_text()
+ target = src[src.index("export async function openTarget"):]
+ assert "getFile()" in target and "window.open(" in target
+ assert "revokeObjectURL" in target, "the blob URL must not be leaked"
diff --git a/packages/meshbay-hub/tests/test_spa_ordering.py b/packages/meshbay-hub/tests/test_spa_ordering.py
index 04c5159..79d7c9a 100644
--- a/packages/meshbay-hub/tests/test_spa_ordering.py
+++ b/packages/meshbay-hub/tests/test_spa_ordering.py
@@ -199,3 +199,33 @@ def test_the_files_panel_no_longer_carries_its_own_progress_bars():
app = APP.read_text()
for gone in ("setUlState", "setDlState", "dl-bar"):
assert gone not in app, f"{gone} survived the move to the transfer widget"
+
+
+# ── Downloading a selection ─────────────────────────────────────────────────
+
+def test_a_multi_file_download_waits_for_each_picker():
+ """
+ A browser allows one file picker at a time. Firing every download at once
+ meant the first opened a dialog and the rest were rejected — two files
+ selected, one file downloaded.
+ """
+ app = APP.read_text()
+ block = app[app.index("${selectedFiles.length > 0 && html`"):]
+ block = block[:block.index("`}")]
+ assert "await downloadFile(e)" in block, (
+ "downloads are fired without awaiting again; only the first will ask "
+ "for a save location and the others will be rejected")
+
+
+def test_links_in_chat_are_built_as_elements_not_markup():
+ """
+ A message is something another member wrote. It becomes an anchor element,
+ never HTML, and only for http(s) — otherwise javascript: would be one
+ message away from running here.
+ """
+ app = APP.read_text()
+ fn = app[app.index("function linkify("):]
+ fn = fn[:fn.index("\nfunction ", 1)]
+ assert "innerHTML" not in fn and "dangerouslySetInnerHTML" not in fn
+ assert 'rel="noopener noreferrer"' in fn
+ assert "https?" in app[app.index("const URL_RE"):app.index("function linkify(")]