aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/tests/test_music_untagged.py
blob: b27b6a3e98ba834c22d073fa2d8198905f717e18 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
"""
A track with no artist tag is still music, and the grid has to say so.

The album grid drew `albums` and nothing else, so a track with no artist at all
— which belongs to no album — appeared nowhere in it. `empty` counted those
tracks, so it stayed false and no message was drawn either: a library nothing
has tagged rendered a toolbar over a blank page, with every one of its tracks a
mode-switch away and nothing on screen saying so. Found after a node restart,
where the index is briefly served before its tags have been re-read, and true
of a genuinely untagged library with no restart involved.

Measured rather than read: both halves of `music-app.js` are correct on their
own, and the fault is that they disagree about what "nothing" means.
"""
import json
import shutil
import subprocess
from pathlib import Path

import pytest

HARNESS = Path(__file__).parent / "harness" / "music_untagged_probe.py"
STATIC = Path(__file__).resolve().parents[1] / "src" / "meshbay_hub" / "static"

pytestmark = pytest.mark.skipif(
    shutil.which("google-chrome") is None or not (STATIC / "music-app.js").exists(),
    reason="Chrome or the SPA sources are not available")


@pytest.fixture(scope="module")
def cases():
    run = subprocess.run(["python3", str(HARNESS)], capture_output=True, timeout=240)
    assert run.returncode == 0, run.stderr.decode()[-2000:]
    return {c["name"]: c for c in json.loads(run.stdout.decode())}


def test_no_case_draws_a_blank_panel(cases):
    """The bug, stated once: a toolbar with nothing under it and nothing said."""
    for name, case in cases.items():
        assert "error" not in case, f"{name}: {case.get('error')}"
        assert case["cards"] or case["messages"], (
            f"{name}: the panel drew neither a card nor a message")


def test_untagged_tracks_reach_the_grid(cases):
    case = cases["nothing tagged"]
    assert len(case["cards"]) == 1, "seven untagged tracks are one card, not seven"
    assert case["messages"] == [], "there is music here — saying otherwise is the old lie"


def test_the_card_names_what_it_is(cases):
    """Not a real release, and it must not read like one."""
    card = cases["nothing tagged"]["cards"][0]
    assert card["title"] and card["sub"]
    assert card["title"] != card["sub"]


def test_the_pile_does_not_displace_real_albums(cases):
    case = cases["some tagged"]
    assert len(case["cards"]) == 4, "three tagged albums and one pile"
    # Last, not sorted in among the artists: it is not a name anybody chose.
    assert case["cards"][-1]["sub"] == cases["nothing tagged"]["cards"][0]["sub"]
    assert [c["title"] for c in case["cards"][:3]] == ["disque 1", "disque 2", "disque 3"]


def test_an_empty_library_still_says_so(cases):
    """The one case that really is empty. Widening `empty` would have broken this."""
    case = cases["no audio"]
    assert case["cards"] == []
    assert len(case["messages"]) == 1


def test_the_flat_list_still_lists_every_untagged_track(cases):
    """The grid reaching them must not cost the list what it always drew."""
    assert cases["nothing tagged"]["flatTracks"] == 7
    assert cases["some tagged"]["flatTracks"] == 4
    assert cases["some tagged"]["flatRows"] == 3, "the three tagged artists, as folders"


def test_no_cover_is_looked_up_for_an_album_this_page_invented(cases):
    """
    A third-party request, on the operator's connection, that cannot match
    anything: the release name is one the browser wrote. Seen in a live node's
    log, going out with a placeholder as both artist and release.
    """
    # The discriminating one: this card is drawn with or without the fix, so it
    # is the only case where the count says anything about the gate itself.
    assert cases["singletons only"]["cards"], "the folded card must still be drawn"
    assert cases["singletons only"]["musicMetaCalls"] == 0

    assert cases["nothing tagged"]["musicMetaCalls"] == 0
    assert cases["some tagged"]["musicMetaCalls"] == 3, (
        "the three real albums are still looked up — only the invented ones are not")