* docs: add Home Assistant 0.4.0 hardening roadmap * fix: protect media credentials and resume state * feat: authenticate RelayTV API operations * fix: make targeting and media state reliable * test: add Home Assistant integration CI * fix: validate API credentials during setup * release: prepare HACS 0.4.0 * fix: align pytest dependency pin * fix: close URL sanitizer gaps and correct player state reporting Sync the sensitive-query-key list with the RelayTV server (adds auth, exp, jwt, X-Emby-Token, X-Jellyfin-Token), filter query credentials from relative URLs instead of returning them verbatim, and preserve brackets around IPv6 literal hosts. Also report volume on RelayTV's 0-100 scale unconditionally (a raw 1 is 1%, not full volume) and give the coordinator its own position_updated_at stamp — the base DataUpdateCoordinator has no last_update_success_time, so media_position_updated_at silently fell back to now() on every read and the seek bar never extrapolated. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
27 lines
975 B
Python
27 lines
975 B
Python
"""Tests for RelayTV resume-storage migration."""
|
|
|
|
from custom_components.relaytv import MAX_RESUME_POSITIONS, _migrate_resume_positions
|
|
|
|
|
|
def test_resume_migration_removes_credentials_and_deduplicates() -> None:
|
|
value = {
|
|
"https://media.example/watch?v=123&api_key=first": 120.0,
|
|
"https://MEDIA.example/watch?api_key=second&v=123": 150.0,
|
|
"https://media.example/invalid": "not-a-position",
|
|
}
|
|
|
|
result = _migrate_resume_positions(value)
|
|
|
|
assert result == {"https://media.example/watch?v=123": 150.0}
|
|
assert "api_key" not in repr(result)
|
|
|
|
|
|
def test_resume_migration_caps_oldest_entries() -> None:
|
|
value = {f"https://media.example/watch/{index}": index for index in range(MAX_RESUME_POSITIONS + 5)}
|
|
|
|
result = _migrate_resume_positions(value)
|
|
|
|
assert len(result) == MAX_RESUME_POSITIONS
|
|
assert "https://media.example/watch/0" not in result
|
|
assert f"https://media.example/watch/{MAX_RESUME_POSITIONS + 4}" in result
|