mirror of
https://github.com/beetbox/beets.git
synced 2026-01-13 19:52:48 +01:00
142 lines
4.6 KiB
Python
142 lines
4.6 KiB
Python
import re
|
|
import uuid
|
|
from contextlib import nullcontext as does_not_raise
|
|
|
|
import pytest
|
|
|
|
from beets.library import Album
|
|
from beets.test.helper import PluginMixin, TestHelper
|
|
from beets.ui import UserError
|
|
from beetsplug import mbcollection
|
|
|
|
|
|
class TestMbCollectionPlugin(PluginMixin, TestHelper):
|
|
"""Tests for the MusicBrainzCollectionPlugin class methods."""
|
|
|
|
plugin = "mbcollection"
|
|
|
|
COLLECTION_ID = str(uuid.uuid4())
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def setup_config(self):
|
|
self.config["musicbrainz"]["user"] = "testuser"
|
|
self.config["musicbrainz"]["pass"] = "testpass"
|
|
self.config["mbcollection"]["collection"] = self.COLLECTION_ID
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def helper(self):
|
|
self.setup_beets()
|
|
|
|
yield self
|
|
|
|
self.teardown_beets()
|
|
|
|
@pytest.mark.parametrize(
|
|
"user_collections,expectation",
|
|
[
|
|
(
|
|
[],
|
|
pytest.raises(
|
|
UserError, match=r"no collections exist for user"
|
|
),
|
|
),
|
|
(
|
|
[{"id": "c1", "entity-type": "event"}],
|
|
pytest.raises(UserError, match=r"No release collection found."),
|
|
),
|
|
(
|
|
[{"id": "c1", "entity-type": "release"}],
|
|
pytest.raises(UserError, match=r"invalid collection ID"),
|
|
),
|
|
(
|
|
[{"id": COLLECTION_ID, "entity-type": "release"}],
|
|
does_not_raise(),
|
|
),
|
|
],
|
|
ids=["no collections", "no release collections", "invalid ID", "valid"],
|
|
)
|
|
def test_get_collection_validation(
|
|
self, requests_mock, user_collections, expectation
|
|
):
|
|
requests_mock.get(
|
|
"/ws/2/collection", json={"collections": user_collections}
|
|
)
|
|
|
|
with expectation:
|
|
mbcollection.MusicBrainzCollectionPlugin().collection
|
|
|
|
def test_mbupdate(self, helper, requests_mock, monkeypatch):
|
|
"""Verify mbupdate sync of a MusicBrainz collection with the library.
|
|
|
|
This test ensures that the command:
|
|
- fetches collection releases using paginated requests,
|
|
- submits releases that exist locally but are missing from the remote
|
|
collection
|
|
- and removes releases from the remote collection that are not in the
|
|
local library. Small chunk sizes are forced to exercise pagination and
|
|
batching logic.
|
|
"""
|
|
for mb_albumid in [
|
|
# already present in remote collection
|
|
"in_collection1",
|
|
"in_collection2",
|
|
# two new albums not in remote collection
|
|
"00000000-0000-0000-0000-000000000001",
|
|
"00000000-0000-0000-0000-000000000002",
|
|
]:
|
|
helper.lib.add(Album(mb_albumid=mb_albumid))
|
|
|
|
# The relevant collection
|
|
requests_mock.get(
|
|
"/ws/2/collection",
|
|
json={
|
|
"collections": [
|
|
{
|
|
"id": self.COLLECTION_ID,
|
|
"entity-type": "release",
|
|
"release-count": 3,
|
|
}
|
|
]
|
|
},
|
|
)
|
|
|
|
collection_releases = f"/ws/2/collection/{self.COLLECTION_ID}/releases"
|
|
# Force small fetch chunk to require multiple paged requests.
|
|
monkeypatch.setattr(
|
|
"beetsplug.mbcollection.MBCollection.FETCH_CHUNK_SIZE", 2
|
|
)
|
|
# 3 releases are fetched in two pages.
|
|
requests_mock.get(
|
|
re.compile(rf".*{collection_releases}\b.*&offset=0.*"),
|
|
json={
|
|
"releases": [{"id": "in_collection1"}, {"id": "not_in_library"}]
|
|
},
|
|
)
|
|
requests_mock.get(
|
|
re.compile(rf".*{collection_releases}\b.*&offset=2.*"),
|
|
json={"releases": [{"id": "in_collection2"}]},
|
|
)
|
|
|
|
# Force small submission chunk
|
|
monkeypatch.setattr(
|
|
"beetsplug.mbcollection.MBCollection.SUBMISSION_CHUNK_SIZE", 1
|
|
)
|
|
# so that releases are added using two requests
|
|
requests_mock.put(
|
|
re.compile(
|
|
rf".*{collection_releases}/00000000-0000-0000-0000-000000000001"
|
|
)
|
|
)
|
|
requests_mock.put(
|
|
re.compile(
|
|
rf".*{collection_releases}/00000000-0000-0000-0000-000000000002"
|
|
)
|
|
)
|
|
# and finally, one release is removed
|
|
requests_mock.delete(
|
|
re.compile(rf".*{collection_releases}/not_in_library")
|
|
)
|
|
|
|
helper.run_command("mbupdate", "--remove")
|
|
|
|
assert requests_mock.call_count == 6
|