Skip to content

Commit

Permalink
Reverse some of the test logic. Better coverage and more realistic case.
Browse files Browse the repository at this point in the history
  • Loading branch information
jonathangreen committed Jun 14, 2024
1 parent 3406a96 commit 51b17ef
Show file tree
Hide file tree
Showing 2 changed files with 144 additions and 78 deletions.
17 changes: 8 additions & 9 deletions src/palace/manager/api/odl2.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,13 +218,6 @@ def _extract_publication_metadata(
feed, publication, data_source_name
)

if (
metadata.circulation.licenses_owned == 0
and metadata.circulation.licenses_available == 0
):
# This title is not available, so we don't need to process it.
return metadata

if not publication.licenses:
# This title is an open-access title, no need to process licenses.
return metadata
Expand All @@ -234,6 +227,9 @@ def _extract_publication_metadata(
medium = None

skipped_license_formats = set(self.settings.skipped_license_formats)
publication_availability = self._extract_availability(
publication.metadata.availability
)

for odl_license in publication.licenses:
identifier = odl_license.metadata.identifier
Expand Down Expand Up @@ -263,13 +259,16 @@ def _extract_publication_metadata(

if not license_info_document_link:
parsed_license = None

Check warning on line 261 in src/palace/manager/api/odl2.py

View check run for this annotation

Codecov / codecov/patch

src/palace/manager/api/odl2.py#L261

Added line #L261 was not covered by tests
elif not self._extract_availability(odl_license.metadata.availability):
elif (
not self._extract_availability(odl_license.metadata.availability)
or not publication_availability
):
# No need to fetch the license document, we already know that this title is not available.
parsed_license = LicenseData(
identifier=identifier,
checkout_url=None,
status_url=license_info_document_link,
status=LicenseStatus.get(odl_license.metadata.availability.state),
status=LicenseStatus.unavailable,
checkouts_available=0,
)
else:
Expand Down
205 changes: 136 additions & 69 deletions tests/manager/api/test_odl2.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import copy
import datetime
import functools
import json
import uuid

import pytest
from freezegun import freeze_time
Expand Down Expand Up @@ -398,74 +401,134 @@ def test_import_availability(
moby_dick_license_dict = feed_json["publications"][0]["licenses"][0]
test_book_license_dict = feed_json["publications"][2]["licenses"][0]

huck_finn_publication_dict = feed_json["publications"][1]
huck_finn_publication_dict["licenses"] = copy.deepcopy(
feed_json["publications"][0]["licenses"]
)
huck_finn_publication_dict["images"] = copy.deepcopy(
feed_json["publications"][0]["images"]
)
huck_finn_license_dict = huck_finn_publication_dict["licenses"][0]

MOBY_DICK_LICENSE_ID = "urn:uuid:f7847120-fc6f-11e3-8158-56847afe9799"
TEST_BOOK_LICENSE_ID = "urn:uuid:f7847120-fc6f-11e3-8158-56847afe9798"
HUCK_FINN_LICENSE_ID = f"urn:uuid:{uuid.uuid4()}"

moby_dick_license_dict["metadata"]["availability"] = {
"state": "unavailable",
}
test_book_license_dict["metadata"]["availability"] = {
"state": "unavailable",
"reason": "https://registry.opds.io/reason#preordered",
"until": "2016-01-20T00:00:00Z",
}
huck_finn_license_dict["metadata"]["identifier"] = HUCK_FINN_LICENSE_ID
huck_finn_publication_dict["metadata"][
"title"
] = "Adventures of Huckleberry Finn"

# Mock responses from license status server
def license_status_reply(
license_id: str,
concurrency: int = 10,
checkouts: int | None = 30,
expires: str | None = "2016-04-25T12:25:21+02:00",
) -> LicenseInfoHelper:
return LicenseInfoHelper(
license=LicenseHelper(
identifier=license_id,
concurrency=concurrency,
checkouts=checkouts,
expires=expires,
),
left=checkouts,
available=concurrency,
)

odl_mock_get.add(license_status_reply(MOBY_DICK_LICENSE_ID))
odl_mock_get.add(license_status_reply(HUCK_FINN_LICENSE_ID))

imported_editions, pools, works, failures = odl2_importer.import_from_feed(
json.dumps(feed_json)
)

assert isinstance(pools, list)
assert 2 == len(pools)

[moby_dick_pool, test_book_pool] = pools

assert moby_dick_pool.identifier.identifier == "978-3-16-148410-0"
assert moby_dick_pool.identifier.type == "ISBN"
assert moby_dick_pool.licenses_owned == 0
assert moby_dick_pool.licenses_available == 0
assert len(moby_dick_pool.licenses) == 1
[moby_dick_license] = moby_dick_pool.licenses
assert moby_dick_license.identifier == MOBY_DICK_LICENSE_ID
assert moby_dick_license.is_available_for_borrowing is False
assert moby_dick_license.status == LicenseStatus.unavailable

assert test_book_pool.identifier.identifier == "http://example.org/test-book"
assert test_book_pool.identifier.type == "URI"
assert test_book_pool.licenses_owned == 0
assert test_book_pool.licenses_available == 0
assert len(test_book_pool.licenses) == 1
[test_book_license] = test_book_pool.licenses
assert test_book_license.identifier == TEST_BOOK_LICENSE_ID
assert test_book_license.is_available_for_borrowing is False
assert test_book_license.status == LicenseStatus.unavailable
assert 3 == len(pools)

[moby_dick_pool, huck_finn_pool, test_book_pool] = pools

def assert_pool(
pool: LicensePool,
identifier: str,
identifier_type: str,
licenses_owned: int,
licenses_available: int,
license_id: str,
available_for_borrowing: bool,
license_status: LicenseStatus,
) -> None:
assert pool.identifier.identifier == identifier
assert pool.identifier.type == identifier_type
assert pool.licenses_owned == licenses_owned
assert pool.licenses_available == licenses_available
assert len(pool.licenses) == 1
[license_info] = pool.licenses
assert license_info.identifier == license_id
assert license_info.is_available_for_borrowing is available_for_borrowing
assert license_info.status == license_status

assert_moby_dick_pool = functools.partial(
assert_pool,
identifier="978-3-16-148410-0",
identifier_type="ISBN",
license_id=MOBY_DICK_LICENSE_ID,
)
assert_test_book_pool = functools.partial(
assert_pool,
identifier="http://example.org/test-book",
identifier_type="URI",
license_id=TEST_BOOK_LICENSE_ID,
)
assert_huck_finn_pool = functools.partial(
assert_pool,
identifier="9781234567897",
identifier_type="ISBN",
license_id=HUCK_FINN_LICENSE_ID,
)

assert_moby_dick_pool(
moby_dick_pool,
licenses_owned=30,
licenses_available=10,
available_for_borrowing=True,
license_status=LicenseStatus.available,
)

assert_test_book_pool(
test_book_pool,
licenses_owned=0,
licenses_available=0,
available_for_borrowing=False,
license_status=LicenseStatus.unavailable,
)

assert_huck_finn_pool(
huck_finn_pool,
licenses_owned=30,
licenses_available=10,
available_for_borrowing=True,
license_status=LicenseStatus.available,
)

# Harvest the feed again, but this time the status has changed
moby_dick_license_dict["metadata"]["availability"] = {
"state": "available",
"state": "unavailable",
}
del test_book_license_dict["metadata"]["availability"]
huck_finn_publication_dict["metadata"]["availability"] = {
"state": "unavailable",
}

# Mock responses from license status server
odl_mock_get.add(
LicenseInfoHelper(
license=LicenseHelper(
identifier=MOBY_DICK_LICENSE_ID,
concurrency=10,
checkouts=30,
expires="2016-04-25T12:25:21+02:00",
),
left=30,
available=10,
)
)
odl_mock_get.add(
LicenseInfoHelper(
license=LicenseHelper(
identifier=TEST_BOOK_LICENSE_ID,
concurrency=10,
),
available=10,
)
license_status_reply(TEST_BOOK_LICENSE_ID, checkouts=None, expires=None)
)

# Harvest the feed again
Expand All @@ -474,29 +537,33 @@ def test_import_availability(
)

assert isinstance(pools, list)
assert 2 == len(pools)

[moby_dick_pool, test_book_pool] = pools

assert moby_dick_pool.identifier.identifier == "978-3-16-148410-0"
assert moby_dick_pool.identifier.type == "ISBN"
assert moby_dick_pool.licenses_owned == 30
assert moby_dick_pool.licenses_available == 10
assert len(moby_dick_pool.licenses) == 1
[moby_dick_license] = moby_dick_pool.licenses
assert moby_dick_license.identifier == MOBY_DICK_LICENSE_ID
assert moby_dick_license.is_available_for_borrowing is True
assert moby_dick_license.status == LicenseStatus.available

assert test_book_pool.identifier.identifier == "http://example.org/test-book"
assert test_book_pool.identifier.type == "URI"
assert test_book_pool.licenses_owned == 10
assert test_book_pool.licenses_available == 10
assert len(test_book_pool.licenses) == 1
[test_book_license] = test_book_pool.licenses
assert test_book_license.identifier == TEST_BOOK_LICENSE_ID
assert test_book_license.is_available_for_borrowing is True
assert test_book_license.status == LicenseStatus.available
assert 3 == len(pools)

[moby_dick_pool, huck_finn_pool, test_book_pool] = pools

assert_moby_dick_pool(
moby_dick_pool,
licenses_owned=0,
licenses_available=0,
available_for_borrowing=False,
license_status=LicenseStatus.unavailable,
)

assert_test_book_pool(
test_book_pool,
licenses_owned=10,
licenses_available=10,
available_for_borrowing=True,
license_status=LicenseStatus.available,
)

assert_huck_finn_pool(
huck_finn_pool,
licenses_owned=0,
licenses_available=0,
available_for_borrowing=False,
license_status=LicenseStatus.unavailable,
)


class TestODL2API:
Expand Down

0 comments on commit 51b17ef

Please sign in to comment.