aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-node/tests/test_musicbrainz.py
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-08-29 11:15:54 +0200
committerChristophe Besson <cbesson@gmail.com>2026-08-29 11:15:54 +0200
commitb7733e812fadd6007976d262bd1d793572a36ba7 (patch)
tree52e2ac07c9ba4929fa50b6ba8d19f94f86e8b304 /packages/meshbay-node/tests/test_musicbrainz.py
parent09a007937f03fad04a390323f3817f1ae7d7c2a9 (diff)
downloadmeshbay-b7733e812fadd6007976d262bd1d793572a36ba7.tar.gz
feat: node workflow redesign — wizard auto-config, reset, MusicBrainz contact
Wizard (Electron): - Auto-provisions node config (hub URL + username) from logged-in user - node:start handles both cold start and restart of misconfigured daemon - Waits for daemon to reach 'running', auto-links node key on hub - probeNode accepts intermediate states for wizard progress feedback Reset (meshbay-node reset): - Unlinks node key from hub (DELETE /me/node_key, best-effort) - Stops and disables daemon (systemctl --user disable --now) - Erases ~/.config/meshbay, ~/.local/share/meshbay, ~/.local/state/meshbay MusicBrainz contact: - Resolved from owner's hub email instead of per-node roster config - Removed musicbrainz_contact UI and WebRTC handshake field - Removed set_musicbrainz_contact/musicbrainz_contact from roster Node pairing: - Added operator pairing banner on NodePage - Added operator_paired flag to list_groups Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-node/tests/test_musicbrainz.py')
-rw-r--r--packages/meshbay-node/tests/test_musicbrainz.py33
1 files changed, 12 insertions, 21 deletions
diff --git a/packages/meshbay-node/tests/test_musicbrainz.py b/packages/meshbay-node/tests/test_musicbrainz.py
index 4d075d3..843a691 100644
--- a/packages/meshbay-node/tests/test_musicbrainz.py
+++ b/packages/meshbay-node/tests/test_musicbrainz.py
@@ -7,14 +7,6 @@ import pytest
from meshbay_node.musicbrainz import _MIN_INTERVAL_SECS, MusicBrainzClient, _escape_lucene
-class FakeRoster:
- def __init__(self, contact: str | None = "operator@example.invalid"):
- self._contact = contact
-
- async def musicbrainz_contact(self):
- return self._contact
-
-
def _handler(response_map):
def handle(request: httpx.Request) -> httpx.Response:
path = request.url.path
@@ -30,7 +22,7 @@ async def test_search_release_returns_top_result_and_confidence():
body = {"releases": [{"id": "abc-123", "title": "The Great Album",
"artist-credit": [{"name": "Some Artist"}]}]}
client = MusicBrainzClient(
- roster=FakeRoster(),
+ owner_email="operator@example.invalid",
transport=httpx.MockTransport(_handler({"release": body})),
)
result, ratio = await client.search_release("Some Artist", "The Great Album")
@@ -44,7 +36,7 @@ async def test_search_release_returns_top_result_and_confidence():
@pytest.mark.asyncio
async def test_no_results_returns_none_and_zero_confidence():
client = MusicBrainzClient(
- roster=FakeRoster(),
+ owner_email="operator@example.invalid",
transport=httpx.MockTransport(_handler({"release": {"releases": []}})),
)
result, ratio = await client.search_release("Nobody", "Nonexistent Obscure Album")
@@ -80,7 +72,7 @@ async def test_strict_match_does_not_pay_for_a_second_request():
})
client = MusicBrainzClient(
- roster=FakeRoster(),
+ owner_email="operator@example.invalid",
transport=httpx.MockTransport(handle),
)
await client.search_release("Some Artist", "The Great Album")
@@ -112,7 +104,7 @@ async def test_falls_back_to_a_loose_query_when_the_strict_one_finds_nothing():
})
client = MusicBrainzClient(
- roster=FakeRoster(),
+ owner_email="operator@example.invalid",
transport=httpx.MockTransport(handle),
)
result, ratio = await client.search_release("Groundation", "Hebron Gate (2003)")
@@ -139,7 +131,7 @@ async def test_confidence_reflects_a_wrong_artist_on_a_same_titled_release():
})
client = MusicBrainzClient(
- roster=FakeRoster(),
+ owner_email="operator@example.invalid",
transport=httpx.MockTransport(handle),
)
result, ratio = await client.search_release("Groundation", "Live")
@@ -150,8 +142,7 @@ async def test_confidence_reflects_a_wrong_artist_on_a_same_titled_release():
@pytest.mark.asyncio
-async def test_no_contact_configured_makes_no_request(monkeypatch):
- monkeypatch.delenv("MESHBAY_MUSICBRAINZ_CONTACT_DEFAULT", raising=False)
+async def test_no_contact_configured_makes_no_request():
calls = []
def handle(request: httpx.Request) -> httpx.Response:
@@ -159,7 +150,7 @@ async def test_no_contact_configured_makes_no_request(monkeypatch):
return httpx.Response(200, json={"releases": []})
client = MusicBrainzClient(
- roster=FakeRoster(contact=None),
+ owner_email="",
transport=httpx.MockTransport(handle),
)
result, ratio = await client.search_release("Anyone", "Anything")
@@ -178,7 +169,7 @@ async def test_the_configured_contact_is_sent_as_user_agent():
return httpx.Response(200, json={"releases": []})
client = MusicBrainzClient(
- roster=FakeRoster(contact="operator@example.invalid"),
+ owner_email="operator@example.invalid",
transport=httpx.MockTransport(handle),
)
await client.search_release("Anyone", "Anything")
@@ -193,7 +184,7 @@ async def test_http_error_returns_none_gracefully():
return httpx.Response(500, json={"error": "server error"})
client = MusicBrainzClient(
- roster=FakeRoster(),
+ owner_email="operator@example.invalid",
transport=httpx.MockTransport(handle),
)
result, ratio = await client.search_release("Anyone", "Anything")
@@ -209,7 +200,7 @@ async def test_cover_art_missing_returns_none_not_an_error():
return httpx.Response(404)
client = MusicBrainzClient(
- roster=FakeRoster(),
+ owner_email="operator@example.invalid",
transport=httpx.MockTransport(handle),
)
content = await client.fetch_cover_art("abc-123")
@@ -224,7 +215,7 @@ async def test_cover_art_found_returns_bytes():
return httpx.Response(200, content=b"\xff\xd8fake-jpeg-bytes")
client = MusicBrainzClient(
- roster=FakeRoster(),
+ owner_email="operator@example.invalid",
transport=httpx.MockTransport(handle),
)
content = await client.fetch_cover_art("abc-123")
@@ -245,7 +236,7 @@ async def test_calls_are_paced_at_least_min_interval_apart():
return httpx.Response(200, json={"releases": []})
client = MusicBrainzClient(
- roster=FakeRoster(),
+ owner_email="operator@example.invalid",
transport=httpx.MockTransport(handle),
)
start = time.monotonic()