aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/tests/test_search_files_unmerged.py
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-hub/tests/test_search_files_unmerged.py')
-rw-r--r--packages/meshbay-hub/tests/test_search_files_unmerged.py80
1 files changed, 80 insertions, 0 deletions
diff --git a/packages/meshbay-hub/tests/test_search_files_unmerged.py b/packages/meshbay-hub/tests/test_search_files_unmerged.py
new file mode 100644
index 0000000..6956dde
--- /dev/null
+++ b/packages/meshbay-hub/tests/test_search_files_unmerged.py
@@ -0,0 +1,80 @@
+"""
+The Files explorer in the Search view is not merged, and must not become so.
+
+The Search view folds a file several groups share into one entry, so a film
+shared by two groups is one poster instead of two. The Files tab is the one
+place where that would be wrong: there each group is a top-level folder, the
+two copies live in two different folders, and walking into one is how a member
+browses *that group*. Merging would silently delete one of the two branches of
+the tree.
+
+This is the guarantee a later refactor is most likely to break — the four entry
+lists in `search-page.js` are near-identical, and tidying them into one shared
+builder is the obvious cleanup. It would also be the last thing anyone tests by
+hand, because the Files tab looks unchanged until you notice a group's folder
+has fewer files in it than the group does.
+
+So: read the source, and refuse a build where `fileEntries` goes through the
+merge. Weak evidence, and the only kind available for the SPA — but the failure
+it guards against is a one-line edit, which is exactly what a source-reading
+test catches well.
+
+See docs/refactoring-search.md §6.1.
+"""
+
+import re
+from pathlib import Path
+
+import pytest
+
+STATIC = Path(__file__).resolve().parents[1] / "src" / "meshbay_hub" / "static"
+SEARCH_PAGE = STATIC / "search-page.js"
+
+pytestmark = pytest.mark.skipif(
+ not SEARCH_PAGE.exists(), reason="the SPA sources are not available")
+
+MERGE_CALL = "mergeUnitEntries"
+
+
+def _memo(name):
+ """The body of `const <name> = useMemo(() => { ... }, [...]);`."""
+ src = SEARCH_PAGE.read_text()
+ m = re.search(
+ r"^ const " + re.escape(name) + r" = useMemo\(\(\) => \{.*?^ \}, \[.*?\]\);",
+ src, re.M | re.S)
+ assert m, (
+ f"{name} is no longer a useMemo where this test reads it — the Files "
+ "explorer's exemption from the merge is untested until this is fixed")
+ return m.group(0)
+
+
+def test_the_files_list_is_not_merged():
+ body = _memo("fileEntries")
+ assert MERGE_CALL not in body, (
+ "fileEntries now goes through the source merge. The Files explorer "
+ "shows one folder per group and a member navigates into it; merging "
+ "two groups' copies of a file would remove it from one of those "
+ "folders. See docs/refactoring-search.md §6.1")
+
+
+@pytest.mark.parametrize("name", ["videoEntries", "musicEntries", "photoEntries"])
+def test_the_media_lists_are_merged(name):
+ """
+ The other half of the check. Without it, deleting the merge outright would
+ leave the test above passing and saying nothing.
+ """
+ assert MERGE_CALL in _memo(name), (
+ f"{name} no longer goes through the source merge — a file shared by "
+ "two groups is two entries again")
+
+
+def test_the_files_list_still_carries_one_group_per_entry():
+ """
+ What makes the explorer work: the path is prefixed with the group's name,
+ so the top level of the tree is the set of groups. A merged entry could not
+ be prefixed with anything, having several.
+ """
+ body = _memo("fileEntries")
+ assert "data.groupName + (e.path ? '/' + e.path : '')" in body, (
+ "fileEntries no longer prefixes paths with the group name — the "
+ "explorer's per-group top level is what this whole exemption is for")