"""The ON AIR metadata line: who is on the desk, and no lone artwork glyph.""" from __future__ import annotations import types import pytest from beefy_player.app import BeefyPlayerApp from beefy_player.models import Song, Station from beefy_player.providers.somafm import SomaFMProvider from beefy_player.providers.tilderadio import TilderadioProvider, api from beefy_player.widgets.stage import StageInfo def details(station: Station, song: Song | None, width: int = 90) -> list[str]: app = types.SimpleNamespace(playing_state="playing", notice="") return [line.plain for line in StageInfo()._details(app, station, song, width)] def test_somafm_still_prefixes_a_dj_name() -> None: station = Station(id="gs", title="Groove Salad", dj="SomaFM", provider="somafm") lines = details(station, Song(artist="A", title="T", album="Album")) assert any("Album" in line and "dj SomaFM" in line for line in lines) def test_lone_artwork_glyph_is_not_drawn() -> None: """No album, no presenter: the ▣ would be a box with nothing to mark.""" station = Station(id="x", title="X", provider="somafm") lines = details(station, Song(artist="A", title="T", art_url="https://a/1.jpg")) assert not any("▣" in line for line in lines) def test_artwork_glyph_rides_along_with_real_information() -> None: station = Station(id="x", title="X", dj="Someone", provider="somafm") lines = details(station, Song(artist="A", title="T", art_url="https://a/1.jpg")) assert any("dj Someone" in line and "▣" in line for line in lines) def test_tilderadio_shows_the_rotation_when_nothing_is_live() -> None: payload = { "station": {"name": "tilderadio", "shortcode": "tilderadio"}, "is_live": False, } station = api.station_from_now(payload) assert station is not None assert station.presenter_label == "auto dj · library rotation" lines = details(station, Song(artist="A", title="T", art_url="https://a/1.jpg")) assert any("auto dj · library rotation" in line for line in lines) def test_tilderadio_shows_the_live_dj_instead() -> None: payload = { "station": {"name": "tilderadio", "shortcode": "tilderadio"}, "is_live": True, "dj": "dokuja", } station = api.station_from_now(payload) assert station is not None assert station.presenter_label == "dj dokuja" assert "auto dj" not in station.presenter_label def test_presenter_label_falls_back_to_the_dj_then_nothing() -> None: assert Station(id="a", title="A").presenter_label == "" assert Station(id="a", title="A", dj="kexp").presenter_label == "dj kexp" assert ( Station(id="a", title="A", dj="kexp", presenter="guest host").presenter_label == "guest host" ) def test_tilderadio_opts_out_of_bandcamp_lookups() -> None: assert TilderadioProvider().bandcamp is False assert SomaFMProvider().bandcamp is True @pytest.mark.asyncio async def test_no_bandcamp_worker_is_started_for_tilderadio(monkeypatch) -> None: calls: list[tuple] = [] async def fake_find(client, artist, album, title): calls.append((artist, album, title)) return "https://bandcamp.test/track" monkeypatch.setattr("beefy_player.bandcamp.find_track", fake_find) app = BeefyPlayerApp( provider="tilderadio", autoplay=False, offline=True, audio=False ) async with app.run_test(size=(100, 40)) as pilot: await pilot.pause() station = app.current assert station is not None station.now_playing = Song(artist="A", title="T") app._update_bandcamp() await pilot.pause() assert calls == [] assert station.now_playing.bandcamp_url == "" @pytest.mark.asyncio async def test_a_stale_bandcamp_link_is_cleared_when_the_catalogue_does_not_want_one() -> None: app = BeefyPlayerApp( provider="tilderadio", autoplay=False, offline=True, audio=False ) async with app.run_test(size=(100, 40)) as pilot: await pilot.pause() station = app.current assert station is not None station.now_playing = Song( artist="A", title="T", bandcamp_url="https://bandcamp.test/old" ) app._update_bandcamp() assert station.now_playing.bandcamp_url == ""