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

Signed-off-by: Cliff Hill <xlorep@darkhelm.org>
This commit is contained in:
2024-09-19 14:15:00 -04:00
parent e90abe3698
commit 6be20af94f
59 changed files with 2501 additions and 4757 deletions

View File

@@ -1 +1 @@
"""Test suite for the playlist package."""
"""Test suite for the xdh.playlist package."""

View File

@@ -1 +0,0 @@
"""Tests for the playlist.data package."""

View File

@@ -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

View File

@@ -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

View File

@@ -1 +0,0 @@
"""Tests for the playlist.plex package."""

View File

@@ -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

View File

@@ -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