170 lines
5.1 KiB
Python
170 lines
5.1 KiB
Python
import json
|
|
import logging
|
|
import re
|
|
from datetime import datetime, timedelta, timezone
|
|
from pathlib import Path
|
|
from typing import Any, Generator, Tuple
|
|
|
|
import pytest
|
|
|
|
from sublime.adapters.subsonic import (
|
|
api_objects as SubsonicAPI,
|
|
SubsonicAdapter,
|
|
)
|
|
|
|
MOCK_DATA_FILES = Path(__file__).parent.joinpath("mock_data")
|
|
|
|
|
|
@pytest.fixture
|
|
def adapter(tmp_path: Path):
|
|
adapter = SubsonicAdapter(
|
|
{
|
|
"server_address": "http://subsonic.example.com",
|
|
"username": "test",
|
|
"password": "testpass",
|
|
},
|
|
tmp_path,
|
|
)
|
|
adapter._is_mock = True
|
|
yield adapter
|
|
|
|
|
|
def mock_data_files(
|
|
request_name: str, mode: str = "r"
|
|
) -> Generator[Tuple[Path, Any], None, None]:
|
|
"""
|
|
Yields all of the files in the mock_data directory that start with ``request_name``.
|
|
"""
|
|
for file in MOCK_DATA_FILES.iterdir():
|
|
if file.name.split("-")[0] in request_name:
|
|
with open(file, mode) as f:
|
|
yield file, f.read()
|
|
|
|
|
|
def mock_json(**obj: Any) -> str:
|
|
return json.dumps(
|
|
{"subsonic-response": {"status": "ok", "version": "1.15.0", **obj}}
|
|
)
|
|
|
|
|
|
def camel_to_snake(name: str) -> str:
|
|
name = re.sub("(.)([A-Z][a-z]+)", r"\1_\2", name)
|
|
return re.sub("([a-z0-9])([A-Z])", r"\1_\2", name).lower()
|
|
|
|
|
|
def test_request_making_methods(adapter: SubsonicAdapter):
|
|
expected = {
|
|
"u": "test",
|
|
"p": "testpass",
|
|
"c": "Sublime Music",
|
|
"f": "json",
|
|
"v": "1.15.0",
|
|
}
|
|
assert sorted(expected.items()) == sorted(adapter._get_params().items())
|
|
|
|
assert adapter._make_url("foo") == "http://subsonic.example.com/rest/foo.view"
|
|
|
|
|
|
def test_can_service_requests(adapter: SubsonicAdapter):
|
|
# Mock a connection error
|
|
adapter._set_mock_data(Exception())
|
|
assert adapter.can_service_requests is False
|
|
|
|
# Simulate some sort of ping error
|
|
for filename, data in mock_data_files("ping_failed"):
|
|
logging.info(filename)
|
|
logging.debug(data)
|
|
adapter._set_mock_data(data)
|
|
assert adapter.can_service_requests is False
|
|
|
|
# Simulate valid ping
|
|
adapter._set_mock_data(mock_json())
|
|
assert adapter.can_service_requests is True
|
|
|
|
|
|
def test_get_playlists(adapter: SubsonicAdapter):
|
|
expected = [
|
|
SubsonicAPI.Playlist(
|
|
id="2",
|
|
name="Test",
|
|
song_count=132,
|
|
duration=timedelta(seconds=33072),
|
|
created=datetime(2020, 3, 27, 5, 38, 45, 0, tzinfo=timezone.utc),
|
|
changed=datetime(2020, 4, 9, 16, 3, 26, 0, tzinfo=timezone.utc),
|
|
comment="Foo",
|
|
owner="foo",
|
|
public=True,
|
|
cover_art="pl-2",
|
|
),
|
|
SubsonicAPI.Playlist(
|
|
id="3",
|
|
name="Bar",
|
|
song_count=23,
|
|
duration=timedelta(seconds=847),
|
|
created=datetime(2020, 3, 27, 5, 39, 4, 0, tzinfo=timezone.utc),
|
|
changed=datetime(2020, 3, 27, 5, 45, 23, 0, tzinfo=timezone.utc),
|
|
comment="",
|
|
owner="foo",
|
|
public=False,
|
|
cover_art="pl-3",
|
|
),
|
|
]
|
|
|
|
for filename, data in mock_data_files("get_playlists"):
|
|
logging.info(filename)
|
|
logging.debug(data)
|
|
adapter._set_mock_data(data)
|
|
assert adapter.get_playlists() == expected
|
|
|
|
# When playlists is null, expect an empty list.
|
|
adapter._set_mock_data(mock_json())
|
|
assert adapter.get_playlists() == []
|
|
|
|
|
|
def test_get_playlist_details(adapter: SubsonicAdapter):
|
|
for filename, data in mock_data_files("get_playlist_details"):
|
|
logging.info(filename)
|
|
logging.debug(data)
|
|
adapter._set_mock_data(data)
|
|
|
|
playlist_details = adapter.get_playlist_details("2")
|
|
|
|
# Make sure that the song count is correct even if it's not provided.
|
|
# Old versions of Subsonic don't have these properties.
|
|
assert len(playlist_details.songs) == 2
|
|
assert playlist_details.duration == timedelta(seconds=470)
|
|
|
|
# Make sure that at least the first song got decoded properly.
|
|
assert playlist_details.songs[0] == SubsonicAPI.Song(
|
|
id="202",
|
|
parent="318",
|
|
title="What a Beautiful Name",
|
|
album="What a Beautiful Name - Single",
|
|
artist="Hillsong Worship",
|
|
track=1,
|
|
year=2016,
|
|
genre="Christian & Gospel",
|
|
cover_art="318",
|
|
size=8381640,
|
|
content_type="audio/mp4",
|
|
suffix="m4a",
|
|
transcoded_content_type="audio/mpeg",
|
|
transcoded_suffix="mp3",
|
|
duration=timedelta(seconds=238),
|
|
bit_rate=256,
|
|
path="/".join(
|
|
(
|
|
"Hillsong Worship",
|
|
"What a Beautiful Name - Single",
|
|
"01 What a Beautiful Name.m4a",
|
|
)
|
|
),
|
|
is_video=False,
|
|
play_count=20,
|
|
disc_number=1,
|
|
created=datetime(2020, 3, 27, 5, 17, 7, tzinfo=timezone.utc),
|
|
album_id="48",
|
|
artist_id="38",
|
|
type=SubsonicAPI.SublimeAPI.MediaType.MUSIC,
|
|
)
|