audio streaming app plyr.fm
38
fork

Configure Feed

Select the types of activity you want to include in your feed.

at 2026.0102.192555 142 lines 5.2 kB view raw
1"""tests for teal.fm scrobbling integration.""" 2 3from backend._internal.atproto.teal import ( 4 build_teal_play_record, 5 build_teal_status_record, 6) 7from backend.config import TealSettings, settings 8 9 10class TestBuildTealPlayRecord: 11 """tests for build_teal_play_record.""" 12 13 def test_builds_minimal_record(self): 14 """should build record with required fields only.""" 15 record = build_teal_play_record( 16 track_name="Test Track", 17 artist_name="Test Artist", 18 ) 19 20 assert record["$type"] == settings.teal.play_collection 21 assert record["trackName"] == "Test Track" 22 assert record["artists"] == [{"artistName": "Test Artist"}] 23 assert record["musicServiceBaseDomain"] == "plyr.fm" 24 assert record["submissionClientAgent"] == "plyr.fm/1.0" 25 assert "playedTime" in record 26 27 def test_includes_optional_fields(self): 28 """should include optional fields when provided.""" 29 record = build_teal_play_record( 30 track_name="Test Track", 31 artist_name="Test Artist", 32 duration=180, 33 album_name="Test Album", 34 origin_url="https://plyr.fm/track/123", 35 ) 36 37 assert record["duration"] == 180 38 assert record["releaseName"] == "Test Album" 39 assert record["originUrl"] == "https://plyr.fm/track/123" 40 41 42class TestBuildTealStatusRecord: 43 """tests for build_teal_status_record.""" 44 45 def test_builds_status_record(self): 46 """should build status record with item.""" 47 record = build_teal_status_record( 48 track_name="Now Playing", 49 artist_name="Cool Artist", 50 ) 51 52 assert record["$type"] == settings.teal.status_collection 53 assert "time" in record 54 assert "expiry" in record 55 assert "item" in record 56 57 item = record["item"] 58 assert item["trackName"] == "Now Playing" 59 assert item["artists"] == [{"artistName": "Cool Artist"}] 60 61 def test_expiry_is_after_time(self): 62 """should set expiry after time.""" 63 record = build_teal_status_record( 64 track_name="Test", 65 artist_name="Test", 66 ) 67 68 # expiry should be 10 minutes after time 69 assert record["expiry"] > record["time"] 70 71 72class TestTealSettings: 73 """tests for teal.fm settings configuration.""" 74 75 def test_default_play_collection(self): 76 """should have correct default teal play collection.""" 77 assert settings.teal.play_collection == "fm.teal.alpha.feed.play" 78 79 def test_default_status_collection(self): 80 """should have correct default teal status collection.""" 81 assert settings.teal.status_collection == "fm.teal.alpha.actor.status" 82 83 def test_default_enabled(self): 84 """should be enabled by default.""" 85 assert settings.teal.enabled is True 86 87 def test_resolved_scope_with_teal(self): 88 """should include teal scopes in extended scope.""" 89 scope = settings.atproto.resolved_scope_with_teal( 90 settings.teal.play_collection, settings.teal.status_collection 91 ) 92 93 assert "fm.teal.alpha.feed.play" in scope 94 assert "fm.teal.alpha.actor.status" in scope 95 # should also include base scopes 96 assert settings.atproto.track_collection in scope 97 98 def test_env_override_play_collection(self, monkeypatch): 99 """should allow overriding play collection via environment variable. 100 101 this proves we can adapt when teal.fm changes namespaces 102 (e.g., from alpha to stable: fm.teal.feed.play). 103 """ 104 monkeypatch.setenv("TEAL_PLAY_COLLECTION", "fm.teal.feed.play") 105 106 # create fresh settings to pick up env var 107 teal = TealSettings() 108 assert teal.play_collection == "fm.teal.feed.play" 109 110 def test_env_override_status_collection(self, monkeypatch): 111 """should allow overriding status collection via environment variable.""" 112 monkeypatch.setenv("TEAL_STATUS_COLLECTION", "fm.teal.actor.status") 113 114 teal = TealSettings() 115 assert teal.status_collection == "fm.teal.actor.status" 116 117 def test_env_override_enabled(self, monkeypatch): 118 """should allow disabling teal integration via environment variable.""" 119 monkeypatch.setenv("TEAL_ENABLED", "false") 120 121 teal = TealSettings() 122 assert teal.enabled is False 123 124 def test_scope_uses_configured_collections(self, monkeypatch): 125 """should use configured collections in OAuth scope. 126 127 when teal.fm graduates from alpha, we can update via env vars 128 without code changes. 129 """ 130 monkeypatch.setenv("TEAL_PLAY_COLLECTION", "fm.teal.feed.play") 131 monkeypatch.setenv("TEAL_STATUS_COLLECTION", "fm.teal.actor.status") 132 133 teal = TealSettings() 134 scope = settings.atproto.resolved_scope_with_teal( 135 teal.play_collection, teal.status_collection 136 ) 137 138 assert "fm.teal.feed.play" in scope 139 assert "fm.teal.actor.status" in scope 140 # alpha namespaces should NOT be in scope when overridden 141 assert "fm.teal.alpha.feed.play" not in scope 142 assert "fm.teal.alpha.actor.status" not in scope