|
21 | 21 | get_provider, |
22 | 22 | ConstantPrior, |
23 | 23 | ExtendedExpirationCorpusBackend, |
| 24 | + CorpusApiGraphConfig, |
24 | 25 | ) |
25 | 26 | from merino.curated_recommendations.corpus_backends.protocol import Topic, ScheduledSurfaceId |
26 | 27 | from merino.curated_recommendations.engagement_backends.protocol import ( |
|
46 | 47 | ) |
47 | 48 | from merino.curated_recommendations.protocol import CuratedRecommendation |
48 | 49 | from merino.main import app |
| 50 | +from merino.providers.manifest import get_provider as get_manifest_provider |
| 51 | +from merino.providers.manifest.backends.protocol import Domain |
| 52 | +from merino.utils.metrics import get_metrics_client |
49 | 53 | from tests.integration.api.conftest import fakespot_feed |
50 | 54 |
|
51 | 55 |
|
@@ -121,6 +125,16 @@ def extended_expiration_corpus_backend( |
121 | 125 | ) |
122 | 126 |
|
123 | 127 |
|
| 128 | +@pytest.fixture(autouse=True) |
| 129 | +def setup_manifest_provider(manifest_provider): |
| 130 | + """Set up the manifest provider dependency""" |
| 131 | + app.dependency_overrides[get_manifest_provider] = lambda: manifest_provider |
| 132 | + yield |
| 133 | + # Clean up after test |
| 134 | + if get_manifest_provider in app.dependency_overrides: |
| 135 | + del app.dependency_overrides[get_manifest_provider] |
| 136 | + |
| 137 | + |
124 | 138 | @pytest.fixture(name="corpus_provider") |
125 | 139 | def provider( |
126 | 140 | corpus_backend: CorpusApiBackend, |
@@ -1529,3 +1543,94 @@ def mock_post_by_days_ago(*args, **kwargs): |
1529 | 1543 | else: |
1530 | 1544 | # Check that only today's items are returned if in control or not in the experiment. |
1531 | 1545 | assert set(days_ago_counter.keys()) == {0} |
| 1546 | + |
| 1547 | + |
| 1548 | +@pytest.mark.asyncio |
| 1549 | +async def test_curated_recommendations_enriched_with_icons( |
| 1550 | + manifest_provider, |
| 1551 | + corpus_http_client, |
| 1552 | + fixture_request_data, |
| 1553 | +): |
| 1554 | + """Test the enrichment of a curated recommendation with an added icon-url.""" |
| 1555 | + # Set up the manifest data first |
| 1556 | + manifest_provider.manifest_data.domains = [ |
| 1557 | + Domain( |
| 1558 | + rank=2, |
| 1559 | + title="Microsoft – AI, Cloud, Productivity, Computing, Gaming & Apps", |
| 1560 | + url="https://www.microsoft.com", |
| 1561 | + domain="microsoft", |
| 1562 | + icon="https://merino-images.services.mozilla.com/favicons/microsoft-icon.png", |
| 1563 | + categories=["Business", "Information Technology"], |
| 1564 | + serp_categories=[0], |
| 1565 | + ) |
| 1566 | + ] |
| 1567 | + manifest_provider.domain_lookup_table = {"microsoft": 0} |
| 1568 | + |
| 1569 | + backend = CorpusApiBackend( |
| 1570 | + http_client=corpus_http_client, |
| 1571 | + graph_config=CorpusApiGraphConfig(), |
| 1572 | + metrics_client=get_metrics_client(), |
| 1573 | + manifest_provider=manifest_provider, |
| 1574 | + ) |
| 1575 | + |
| 1576 | + provider_instance = CuratedRecommendationsProvider( |
| 1577 | + corpus_backend=backend, |
| 1578 | + extended_expiration_corpus_backend=ExtendedExpirationCorpusBackend( |
| 1579 | + backend=backend, engagement_backend=MockEngagementBackend() |
| 1580 | + ), |
| 1581 | + engagement_backend=MockEngagementBackend(), |
| 1582 | + prior_backend=ConstantPrior(), |
| 1583 | + fakespot_backend=MockFakespotBackend(), |
| 1584 | + ) |
| 1585 | + |
| 1586 | + app.dependency_overrides[get_provider] = lambda: provider_instance |
| 1587 | + |
| 1588 | + mocked_response = { |
| 1589 | + "data": { |
| 1590 | + "scheduledSurface": { |
| 1591 | + "items": [ |
| 1592 | + { |
| 1593 | + "id": "scheduledSurfaceItemId-ABC", |
| 1594 | + "corpusItem": { |
| 1595 | + "id": "corpusItemId-XYZ", |
| 1596 | + "url": "https://www.microsoft.com/some-article?utm_source=firefox-newtab-en-us", |
| 1597 | + "title": "Some MS Article", |
| 1598 | + "excerpt": "All about Microsoft something", |
| 1599 | + "topic": "tech", |
| 1600 | + "publisher": "ExamplePublisher", |
| 1601 | + "isTimeSensitive": False, |
| 1602 | + "imageUrl": "https://somewhere.com/test.jpg", |
| 1603 | + }, |
| 1604 | + } |
| 1605 | + ] |
| 1606 | + } |
| 1607 | + } |
| 1608 | + } |
| 1609 | + corpus_http_client.post.return_value = Response( |
| 1610 | + status_code=200, |
| 1611 | + json=mocked_response, |
| 1612 | + request=fixture_request_data, |
| 1613 | + ) |
| 1614 | + |
| 1615 | + async with AsyncClient(app=app, base_url="http://test") as ac: |
| 1616 | + response = await ac.post( |
| 1617 | + "/api/v1/curated-recommendations", |
| 1618 | + json={"locale": "en-US"}, |
| 1619 | + ) |
| 1620 | + assert response.status_code == 200 |
| 1621 | + |
| 1622 | + data = response.json() |
| 1623 | + items = data["data"] |
| 1624 | + assert len(items) == 1 |
| 1625 | + |
| 1626 | + item = items[0] |
| 1627 | + assert item["url"] == "https://www.microsoft.com/some-article?utm_source=firefox-newtab-en-us" |
| 1628 | + |
| 1629 | + assert "iconUrl" in item |
| 1630 | + assert ( |
| 1631 | + item["iconUrl"] == "https://merino-images.services.mozilla.com/favicons/microsoft-icon.png" |
| 1632 | + ) |
| 1633 | + |
| 1634 | + # Clean up |
| 1635 | + if get_provider in app.dependency_overrides: |
| 1636 | + del app.dependency_overrides[get_provider] |
0 commit comments