Initial commit.
Some checks are pending
Tests / ${{ matrix.session }} ${{ matrix.python }} / ${{ matrix.os }} (macos-latest, 3.10, tests) (push) Waiting to run
Tests / ${{ matrix.session }} ${{ matrix.python }} / ${{ matrix.os }} (ubuntu-latest, 3.10, docs-build) (push) Waiting to run
Tests / ${{ matrix.session }} ${{ matrix.python }} / ${{ matrix.os }} (ubuntu-latest, 3.10, mypy) (push) Waiting to run
Tests / ${{ matrix.session }} ${{ matrix.python }} / ${{ matrix.os }} (ubuntu-latest, 3.10, pre-commit) (push) Waiting to run
Tests / ${{ matrix.session }} ${{ matrix.python }} / ${{ matrix.os }} (ubuntu-latest, 3.10, safety) (push) Waiting to run
Tests / ${{ matrix.session }} ${{ matrix.python }} / ${{ matrix.os }} (ubuntu-latest, 3.10, tests) (push) Waiting to run
Tests / ${{ matrix.session }} ${{ matrix.python }} / ${{ matrix.os }} (ubuntu-latest, 3.10, typeguard) (push) Waiting to run
Tests / ${{ matrix.session }} ${{ matrix.python }} / ${{ matrix.os }} (ubuntu-latest, 3.10, xdoctest) (push) Waiting to run
Tests / ${{ matrix.session }} ${{ matrix.python }} / ${{ matrix.os }} (ubuntu-latest, 3.7, mypy) (push) Waiting to run
Tests / ${{ matrix.session }} ${{ matrix.python }} / ${{ matrix.os }} (ubuntu-latest, 3.7, tests) (push) Waiting to run
Tests / ${{ matrix.session }} ${{ matrix.python }} / ${{ matrix.os }} (ubuntu-latest, 3.8, mypy) (push) Waiting to run
Tests / ${{ matrix.session }} ${{ matrix.python }} / ${{ matrix.os }} (ubuntu-latest, 3.8, tests) (push) Waiting to run
Tests / ${{ matrix.session }} ${{ matrix.python }} / ${{ matrix.os }} (ubuntu-latest, 3.9, mypy) (push) Waiting to run
Tests / ${{ matrix.session }} ${{ matrix.python }} / ${{ matrix.os }} (ubuntu-latest, 3.9, tests) (push) Waiting to run
Tests / ${{ matrix.session }} ${{ matrix.python }} / ${{ matrix.os }} (windows-latest, 3.10, tests) (push) Waiting to run
Tests / coverage (push) Blocked by required conditions
Some checks are pending
Tests / ${{ matrix.session }} ${{ matrix.python }} / ${{ matrix.os }} (macos-latest, 3.10, tests) (push) Waiting to run
Tests / ${{ matrix.session }} ${{ matrix.python }} / ${{ matrix.os }} (ubuntu-latest, 3.10, docs-build) (push) Waiting to run
Tests / ${{ matrix.session }} ${{ matrix.python }} / ${{ matrix.os }} (ubuntu-latest, 3.10, mypy) (push) Waiting to run
Tests / ${{ matrix.session }} ${{ matrix.python }} / ${{ matrix.os }} (ubuntu-latest, 3.10, pre-commit) (push) Waiting to run
Tests / ${{ matrix.session }} ${{ matrix.python }} / ${{ matrix.os }} (ubuntu-latest, 3.10, safety) (push) Waiting to run
Tests / ${{ matrix.session }} ${{ matrix.python }} / ${{ matrix.os }} (ubuntu-latest, 3.10, tests) (push) Waiting to run
Tests / ${{ matrix.session }} ${{ matrix.python }} / ${{ matrix.os }} (ubuntu-latest, 3.10, typeguard) (push) Waiting to run
Tests / ${{ matrix.session }} ${{ matrix.python }} / ${{ matrix.os }} (ubuntu-latest, 3.10, xdoctest) (push) Waiting to run
Tests / ${{ matrix.session }} ${{ matrix.python }} / ${{ matrix.os }} (ubuntu-latest, 3.7, mypy) (push) Waiting to run
Tests / ${{ matrix.session }} ${{ matrix.python }} / ${{ matrix.os }} (ubuntu-latest, 3.7, tests) (push) Waiting to run
Tests / ${{ matrix.session }} ${{ matrix.python }} / ${{ matrix.os }} (ubuntu-latest, 3.8, mypy) (push) Waiting to run
Tests / ${{ matrix.session }} ${{ matrix.python }} / ${{ matrix.os }} (ubuntu-latest, 3.8, tests) (push) Waiting to run
Tests / ${{ matrix.session }} ${{ matrix.python }} / ${{ matrix.os }} (ubuntu-latest, 3.9, mypy) (push) Waiting to run
Tests / ${{ matrix.session }} ${{ matrix.python }} / ${{ matrix.os }} (ubuntu-latest, 3.9, tests) (push) Waiting to run
Tests / ${{ matrix.session }} ${{ matrix.python }} / ${{ matrix.os }} (windows-latest, 3.10, tests) (push) Waiting to run
Tests / coverage (push) Blocked by required conditions
Signed-off-by: Cliff Hill <xlorep@darkhelm.org>
This commit is contained in:
@@ -1 +1 @@
|
||||
"""Test suite for the playlist package."""
|
||||
"""Test suite for the xdh.playlist package."""
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
"""Tests for the playlist.data package."""
|
||||
@@ -1,55 +0,0 @@
|
||||
"""Tests for the playlist.data.base module."""
|
||||
import dataclasses
|
||||
import datetime
|
||||
import typing
|
||||
|
||||
import pytest
|
||||
|
||||
from playlist.data import base
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class Dummy(base.BaseData):
|
||||
"""Dummy class for tests."""
|
||||
|
||||
name: str
|
||||
some_id: int
|
||||
calc: float
|
||||
flag: bool
|
||||
modified: datetime.datetime
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def dummyobj() -> Dummy:
|
||||
"""Make a dummy object for testing."""
|
||||
return Dummy(
|
||||
name="Something",
|
||||
some_id=1,
|
||||
calc=0.1,
|
||||
flag=True,
|
||||
modified=datetime.datetime.now(),
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def dummydict(dummyobj: Dummy) -> dict[str, object]:
|
||||
"""Make a dummy dictionary for testing."""
|
||||
return {
|
||||
"name": dummyobj.name,
|
||||
"some_id": dummyobj.some_id,
|
||||
"calc": dummyobj.calc,
|
||||
"flag": dummyobj.flag,
|
||||
"modified": "T".join(str(dummyobj.modified).split(" ")),
|
||||
}
|
||||
|
||||
|
||||
def test_load(dummydict: dict[str, object], dummyobj: Dummy) -> None:
|
||||
"""Validate that <data class>.load() works."""
|
||||
result: Dummy = Dummy.load(dummydict)
|
||||
assert result == dummyobj
|
||||
|
||||
|
||||
def test_dump(dummydict: dict[str, typing.Any], dummyobj: Dummy) -> None:
|
||||
"""Validate that <data class instance>.dump() works."""
|
||||
result = dummyobj.dump()
|
||||
assert result == dummydict
|
||||
@@ -1,35 +0,0 @@
|
||||
"""Tests for validating the Settings object."""
|
||||
import base64
|
||||
import os
|
||||
import pathlib
|
||||
|
||||
import pytest
|
||||
|
||||
from playlist.data import settings
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def example_settings() -> settings.Settings:
|
||||
"""Make testable Settings object."""
|
||||
return settings.Settings(
|
||||
creds=settings.CredentialSettings(
|
||||
baseurl="http://nowhere.huh",
|
||||
token=base64.b64encode(os.urandom(8)).decode("utf-8"),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def settings_filepath(tmp_path: pathlib.Path) -> pathlib.Path:
|
||||
"""Get the path to use for the settings file."""
|
||||
return tmp_path / "fake_settings.yaml"
|
||||
|
||||
|
||||
def test_yaml(
|
||||
example_settings: settings.Settings,
|
||||
settings_filepath: pathlib.Path,
|
||||
) -> None:
|
||||
"""Test the YAML read/write operations."""
|
||||
example_settings.yaml_write(settings_filepath)
|
||||
result = example_settings.yaml_read(settings_filepath)
|
||||
assert result == example_settings
|
||||
@@ -1 +0,0 @@
|
||||
"""Tests for the playlist.plex package."""
|
||||
@@ -1,204 +0,0 @@
|
||||
"""Tests for the playlist.plex.server module."""
|
||||
import asyncio
|
||||
import datetime
|
||||
import unittest.mock
|
||||
|
||||
import pytest
|
||||
|
||||
from playlist.data import models
|
||||
from playlist.data import settings
|
||||
from playlist.plex import server
|
||||
|
||||
|
||||
def test_calc_delay(mocker): # type: ignore [no-untyped-def]
|
||||
"""Test the calc_delay function."""
|
||||
mock_settings = mocker.patch("playlist.plex.server.settings")
|
||||
mock_const = mocker.patch("playlist.plex.server.const")
|
||||
mock_s = mock_settings.modify.return_value.__enter__.return_value
|
||||
mock_const.MAX_PROCESSES = 1
|
||||
|
||||
times: list[float] = [100, 100, 100]
|
||||
weights: list[float] = [1, 1, 1]
|
||||
|
||||
server.calc_delay(times, weights)
|
||||
|
||||
result = mock_s.download.process_delay
|
||||
|
||||
assert result == 100
|
||||
|
||||
|
||||
def test_calc_duration(mocker): # type: ignore [no-untyped-def]
|
||||
"""Test the calc_duration function."""
|
||||
mock_settings = mocker.patch("playlist.plex.server.settings")
|
||||
durations = [100, 100, 100]
|
||||
mock_s = mock_settings.modify.return_value.__enter__.return_value
|
||||
mock_s.playlist.playtime.total_seconds.return_value = 300
|
||||
server.calc_duration(durations)
|
||||
result = mock_s.playlist.max_tracks
|
||||
assert result == 2
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_gen_tracks(mocker, fake_track): # type: ignore [no-untyped-def]
|
||||
"""Test the gen_tracks asynchronous generator."""
|
||||
mock_downloader = mocker.patch(
|
||||
"playlist.plex.server._downloader",
|
||||
new_callable=unittest.mock.AsyncMock,
|
||||
)
|
||||
mock_gen_batch_params = mocker.patch("playlist.plex.server._gen_batch_params")
|
||||
mock_models = mocker.patch("playlist.plex.server.models")
|
||||
mock_calc_delay = mocker.patch("playlist.plex.server.calc_delay")
|
||||
mock_calc_duration = mocker.patch("playlist.plex.server.calc_duration")
|
||||
mock_downloader.return_value = (1, [fake_track])
|
||||
|
||||
async def fake_gen_batch_params(*args): # type: ignore
|
||||
for item in [(0, 1), (1, 1)]:
|
||||
yield item
|
||||
|
||||
mock_gen_batch_params.side_effect = fake_gen_batch_params
|
||||
mock_models.Track.load.return_value.duration = 1
|
||||
|
||||
results = [item async for item in server.gen_tracks(batch_size=1)]
|
||||
|
||||
assert len(results) == 2
|
||||
assert mock_calc_delay.called
|
||||
assert mock_calc_duration.called
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_total_track_count(mocker): # type: ignore [no-untyped-def]
|
||||
"""Test the total_track_count coroutine."""
|
||||
mock_plexapi_server = mocker.patch("playlist.plex.server.plexapi.server")
|
||||
mock_server = mock_plexapi_server.PlexServer.return_value
|
||||
mock_total_view_size = mock_server.library.section.return_value.totalViewSize
|
||||
mock_total_view_size.return_value = 1
|
||||
|
||||
result = await server.total_track_count()
|
||||
|
||||
assert result == 1
|
||||
|
||||
|
||||
def test_get_creds(mocker): # type: ignore [no-untyped-def]
|
||||
"""Test the get_creds function."""
|
||||
mock_plexapi_myplex = mocker.patch("playlist.plex.server.plexapi.myplex")
|
||||
mock_input = mocker.patch("builtins.input")
|
||||
mock_getpass = mocker.patch("playlist.plex.server.getpass")
|
||||
mock_account = mock_plexapi_myplex.MyPlexAccount.return_value
|
||||
mock_plex = mock_account.resource.return_value.connect.return_value
|
||||
mock_plex._baseurl = "Not a valid URL"
|
||||
mock_plex._token = "Fake token"
|
||||
|
||||
expected = settings.CredentialSettings(
|
||||
baseurl=mock_plex._baseurl,
|
||||
token=mock_plex._token,
|
||||
)
|
||||
|
||||
result = server.get_creds()
|
||||
|
||||
assert result == expected
|
||||
assert mock_input.called
|
||||
assert mock_getpass.getpass.called
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_downloader(mocker): # type: ignore [no-untyped-def]
|
||||
"""Test the _downloader coroutine."""
|
||||
|
||||
async def fake_run_in_executor(*args): # type: ignore
|
||||
await asyncio.sleep(0.1)
|
||||
return "Fake batch"
|
||||
|
||||
mock_loop = unittest.mock.MagicMock()
|
||||
mock_loop.run_in_executor.side_effect = fake_run_in_executor
|
||||
|
||||
result = await server._downloader(1, 1, mock_loop)
|
||||
|
||||
process_time, batch = result
|
||||
|
||||
assert batch
|
||||
assert process_time >= 0.1
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def fake_track(fake_plextrack): # type: ignore [no-untyped-def]
|
||||
"""Make a fake track dict object."""
|
||||
return models.Track(
|
||||
plex_id=fake_plextrack.ratingKey,
|
||||
track_num=fake_plextrack.index,
|
||||
title=fake_plextrack.title,
|
||||
artist=fake_plextrack.artist().title,
|
||||
album_num=fake_plextrack.parentIndex,
|
||||
album=fake_plextrack.parentTitle,
|
||||
album_artist=fake_plextrack.grandparentTitle,
|
||||
duration=fake_plextrack.duration,
|
||||
rating=fake_plextrack.userRating,
|
||||
comments=fake_plextrack.summary,
|
||||
added=fake_plextrack.addedAt,
|
||||
play_count=fake_plextrack.viewCount,
|
||||
played=fake_plextrack.lastViewedAt,
|
||||
)
|
||||
|
||||
|
||||
def test_get_track_batch(mocker, fake_track): # type: ignore [no-untyped-def]
|
||||
"""Test _get_track_batch function."""
|
||||
mock_plexapi_server = mocker.patch("playlist.plex.server.plexapi.server")
|
||||
mock_server = mock_plexapi_server.PlexServer.return_value
|
||||
mock_search_tracks = mock_server.library.section.return_value.searchTracks
|
||||
mock_search_tracks.return_value = ["Not a track."]
|
||||
mock_track_dump = mocker.patch("playlist.plex.server._track_dump")
|
||||
mock_track_dump.return_value = fake_track
|
||||
|
||||
result = server._get_track_batch(1, 1)
|
||||
|
||||
assert len(result)
|
||||
assert mock_track_dump.called
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def fake_plextrack(): # type: ignore [no-untyped-def]
|
||||
"""Mock up a fake Plex track for testing."""
|
||||
mock_track = unittest.mock.MagicMock()
|
||||
mock_track.configure_mock(
|
||||
ratingKey=1,
|
||||
index=1,
|
||||
title="Nothing",
|
||||
parentIndex=1,
|
||||
parentTile="Nothing",
|
||||
grandparentTitle="Nothing",
|
||||
duration=1000,
|
||||
userRating=1,
|
||||
summary="Whatever",
|
||||
addedAt=datetime.datetime.now(),
|
||||
viewCount=1,
|
||||
lastViewedAt=None,
|
||||
)
|
||||
mock_track.artist.return_value.title = "Nothing"
|
||||
return mock_track
|
||||
|
||||
|
||||
def test_track_dump(fake_plextrack, fake_track): # type: ignore [no-untyped-def]
|
||||
"""Test the _track_dump function."""
|
||||
result = server._track_dump(fake_plextrack)
|
||||
|
||||
assert result == fake_track
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_gen_batch_params(mocker): # type: ignore [no-untyped-def]
|
||||
"""Test the _gen_batch_params asynchronous generator."""
|
||||
mock_total_track_count = mocker.patch(
|
||||
"playlist.plex.server.total_track_count",
|
||||
new_callable=unittest.mock.AsyncMock,
|
||||
)
|
||||
mock_total_track_count.return_value = 12
|
||||
mock_const = mocker.patch("playlist.plex.server.const")
|
||||
mock_const.MAX_PROCESSES = 10
|
||||
mocker.patch("playlist.plex.server.settings")
|
||||
mocker.patch(
|
||||
"playlist.plex.server.asyncio",
|
||||
new_callable=unittest.mock.AsyncMock,
|
||||
)
|
||||
|
||||
result = [item async for item in server._gen_batch_params(5)]
|
||||
|
||||
assert len(result) == 3
|
||||
@@ -1,8 +1,9 @@
|
||||
"""Test cases for the __main__ module."""
|
||||
|
||||
import pytest
|
||||
from click.testing import CliRunner
|
||||
|
||||
from playlist import __main__
|
||||
from xdh.playlist import __main__
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
||||
Reference in New Issue
Block a user