Skip to content

Commit

Permalink
Add collection name and distributor facets to the crawlable feed. (Th…
Browse files Browse the repository at this point in the history
  • Loading branch information
jonathangreen authored Dec 1, 2023
1 parent 487c97f commit 14aac24
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 15 deletions.
8 changes: 5 additions & 3 deletions api/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -1047,11 +1047,13 @@ def _crawlable_feed(
if isinstance(search_engine, ProblemDetail):
return search_engine

annotator = annotator or self.manager.annotator(worklist)

# A crawlable feed has only one possible set of Facets,
# so library settings are irrelevant.
facets = CrawlableFacets.default(None)
facets = self.manager.load_facets_from_request(
worklist=worklist,
base_class=CrawlableFacets,
)
annotator = annotator or self.manager.annotator(worklist, facets=facets)

return feed_class.page(
_db=self._db,
Expand Down
10 changes: 9 additions & 1 deletion api/lanes.py
Original file line number Diff line number Diff line change
Expand Up @@ -1361,7 +1361,15 @@ class CrawlableFacets(Facets):

@classmethod
def available_facets(cls, config, facet_group_name):
return [cls.SETTINGS[facet_group_name]]
facets = [cls.SETTINGS[facet_group_name]]

if (
facet_group_name == Facets.DISTRIBUTOR_FACETS_GROUP_NAME
or facet_group_name == Facets.COLLECTION_NAME_FACETS_GROUP_NAME
) and config is not None:
facets.extend(config.enabled_facets(facet_group_name))

return facets

@classmethod
def default_facet(cls, config, facet_group_name):
Expand Down
12 changes: 10 additions & 2 deletions tests/api/test_controller_crawlfeed.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ def works(self, _db, facets, pagination, *args, **kwargs):

# Good pagination data -> feed_class.page() is called.
sort_key = ["sort", "pagination", "key"]
with circulation_fixture.app.test_request_context(
with circulation_fixture.request_context_with_library(
"/?size=23&key=%s" % json.dumps(sort_key)
):
response = circulation_fixture.manager.opds_feeds._crawlable_feed(
Expand Down Expand Up @@ -288,7 +288,7 @@ def works(self, _db, facets, pagination, *args, **kwargs):
# If a custom Annotator is passed in to _crawlable_feed, it's
# propagated to the page() call.
mock_annotator = object()
with circulation_fixture.app.test_request_context("/"):
with circulation_fixture.request_context_with_library("/"):
response = circulation_fixture.manager.opds_feeds._crawlable_feed(
annotator=mock_annotator, **in_kwargs
)
Expand All @@ -306,3 +306,11 @@ def works(self, _db, facets, pagination, *args, **kwargs):
# There is one entry with the expected title.
[entry] = feed["entries"]
assert entry["title"] == work.title

# The feed has the expected facet groups.
facet_groups = {
l["facetgroup"]
for l in feed["feed"]["links"]
if l["rel"] == "http://opds-spec.org/facet"
}
assert facet_groups == {"Collection Name", "Distributor"}
79 changes: 70 additions & 9 deletions tests/api/test_lanes.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from collections import Counter
from typing import List
from unittest.mock import MagicMock, patch

import pytest
Expand Down Expand Up @@ -31,7 +32,14 @@
from core.external_search import Filter
from core.lane import DefaultSortOrderFacets, Facets, FeaturedFacets, Lane, WorkList
from core.metadata_layer import ContributorData, Metadata
from core.model import Contributor, DataSource, Edition, ExternalIntegration, create
from core.model import (
Contributor,
DataSource,
Edition,
ExternalIntegration,
Library,
create,
)
from tests.fixtures.database import DatabaseTransactionFixture
from tests.fixtures.library import LibraryFixture
from tests.fixtures.search import ExternalSearchFixtureFake
Expand Down Expand Up @@ -908,14 +916,67 @@ def test_overview_facets(self, lane_fixture: LaneFixture):
class TestCrawlableFacets:
def test_default(self, db: DatabaseTransactionFixture):
facets = CrawlableFacets.default(db.default_library())
assert CrawlableFacets.COLLECTION_FULL == facets.collection
assert CrawlableFacets.AVAILABLE_ALL == facets.availability
assert CrawlableFacets.ORDER_LAST_UPDATE == facets.order
assert False == facets.order_ascending

# There's only one enabled value for each facet group.
for group in facets.enabled_facets:
assert 1 == len(group)
assert facets.collection == CrawlableFacets.COLLECTION_FULL
assert facets.availability == CrawlableFacets.AVAILABLE_ALL
assert facets.order == CrawlableFacets.ORDER_LAST_UPDATE
assert facets.order_ascending is False

[
order,
availability,
collection,
distributor,
collectionName,
] = facets.enabled_facets

# The default facets are the only ones enabled.
for facet in [order, availability, collection]:
assert len(facet) == 1

# Except for distributor and collectionName, which have the default
# and data for each collection in the library.
for facet in [distributor, collectionName]:
assert len(facet) == 1 + len(db.default_library().collections)

@pytest.mark.parametrize(
"group_name, expected",
[
(Facets.ORDER_FACET_GROUP_NAME, Facets.ORDER_LAST_UPDATE),
(Facets.AVAILABILITY_FACET_GROUP_NAME, Facets.AVAILABLE_ALL),
(Facets.COLLECTION_FACET_GROUP_NAME, Facets.COLLECTION_FULL),
(Facets.DISTRIBUTOR_FACETS_GROUP_NAME, Facets.DISTRIBUTOR_ALL),
(Facets.COLLECTION_NAME_FACETS_GROUP_NAME, Facets.COLLECTION_NAME_ALL),
],
)
def test_available_none(self, group_name: str, expected: List[str]) -> None:
assert CrawlableFacets.available_facets(None, group_name) == [expected]

@pytest.mark.parametrize(
"group_name, expected",
[
(Facets.ORDER_FACET_GROUP_NAME, [Facets.ORDER_LAST_UPDATE]),
(Facets.AVAILABILITY_FACET_GROUP_NAME, [Facets.AVAILABLE_ALL]),
(Facets.COLLECTION_FACET_GROUP_NAME, [Facets.COLLECTION_FULL]),
(Facets.DISTRIBUTOR_FACETS_GROUP_NAME, [Facets.DISTRIBUTOR_ALL, "foo"]),
(
Facets.COLLECTION_NAME_FACETS_GROUP_NAME,
[Facets.COLLECTION_NAME_ALL, "foo"],
),
],
)
def test_available(self, group_name: str, expected: List[str]):
mock = MagicMock(spec=Library)
mock.enabled_facets = MagicMock(return_value=["foo"])

assert CrawlableFacets.available_facets(mock, group_name) == expected

if group_name in [
Facets.DISTRIBUTOR_FACETS_GROUP_NAME,
Facets.COLLECTION_NAME_FACETS_GROUP_NAME,
]:
assert mock.enabled_facets.call_count == 1
else:
assert mock.enabled_facets.call_count == 0


class TestCrawlableCollectionBasedLane:
Expand Down

0 comments on commit 14aac24

Please sign in to comment.