Include hero shelves in /shelves/ response (#16317)
* Include hero shelves in /shelves/ response * add test for both hero and defined shelves in a single response
This commit is contained in:
Родитель
1470c06866
Коммит
8808d2d670
|
@ -87,16 +87,19 @@ Homepage Shelves
|
|||
|
||||
.. _homepage-shelves:
|
||||
|
||||
This endpoint returns the enabled shelves displayed on the AMO Homepage below the hero area.
|
||||
This endpoint returns the shelves to display on the AMO Homepage.
|
||||
A single, randomly selected, primary hero shelf and a single, randomly selected secondary
|
||||
hero shelf is returned, along with the enabled shelves.
|
||||
|
||||
|
||||
.. http:get:: /api/v5/shelves/
|
||||
|
||||
:query int page_size: Maximum number of results to return for the requested page. Defaults to 25.
|
||||
:query int page_count: The number of pages available in the pagination.
|
||||
:query int count: The number of results for this query.
|
||||
:query string next: The URL of the next page of results.
|
||||
:query string previous: The URL of the previous page of results.
|
||||
:query string lang: Activate translations in the specific language for that query. (See :ref:`translated fields <api-overview-translations>`)
|
||||
:>query int page_count: The number of pages available in the pagination.
|
||||
:>json int count: The number of results for this query.
|
||||
:>json string next: The URL of the next page of results.
|
||||
:>json string previous: The URL of the previous page of results.
|
||||
:>json array results: The array of shelves displayed on the AMO Homepage.
|
||||
:>json string results[].title: The title of the shelf.
|
||||
:>json string results[].url: The configured URL using the shelf's endpoint and criteria; links to the shelf's returned add-ons.
|
||||
|
@ -105,6 +108,8 @@ This endpoint returns the enabled shelves displayed on the AMO Homepage below th
|
|||
:>json string|null results[].footer_text: The optional text in the footer of the shelf.
|
||||
:>json string|null results[].footer_pathname: The optional pathname of the URL for the footer's text.
|
||||
:>json array results[].addons: An array of :ref:`add-ons <addon-detail-object>` or :ref:`collections <collection-detail-object>`.
|
||||
:>json object primary: A :ref:`primary hero shelf <primary-hero-shelf>`.
|
||||
:>json object secondary: A :ref:`secondary hero shelf <secondary-hero-shelf>`.
|
||||
|
||||
---------------
|
||||
Sponsored Shelf
|
||||
|
|
|
@ -361,6 +361,7 @@ class TestSecondaryHeroShelfViewSet(TestCase):
|
|||
assert len(response.json()['results']) == 3
|
||||
|
||||
|
||||
# If we delete HeroShelvesView move all these tests to TestShelfViewSet
|
||||
class TestHeroShelvesView(TestCase):
|
||||
def setUp(self):
|
||||
self.url = reverse_ns('hero-shelves', api_version='v5')
|
||||
|
@ -403,9 +404,7 @@ class TestHeroShelvesView(TestCase):
|
|||
cta_text='go here!',
|
||||
enabled=True,
|
||||
)
|
||||
response = self.client.get(
|
||||
self.url, {'lang': 'en-US', 'wrap_outgoing_links': ''}
|
||||
)
|
||||
response = self.client.get(self.url, {'lang': 'en-US'})
|
||||
assert 'outgoing.' in json.dumps(response.json()['primary'])
|
||||
assert 'outgoing.' in json.dumps(response.json()['secondary'])
|
||||
|
||||
|
@ -444,8 +443,6 @@ class TestHeroShelvesView(TestCase):
|
|||
enabled=False,
|
||||
)
|
||||
# No SecondaryHero at all
|
||||
response = self.client.get(
|
||||
self.url, {'lang': 'en-US', 'wrap_outgoing_links': ''}
|
||||
)
|
||||
response = self.client.get(self.url, {'lang': 'en-US'})
|
||||
assert response.json()['primary'] is None
|
||||
assert response.json()['secondary'] is None
|
||||
|
|
|
@ -18,6 +18,11 @@ from olympia.amo.tests import (
|
|||
)
|
||||
from olympia.bandwagon.models import CollectionAddon
|
||||
from olympia.constants.promoted import RECOMMENDED, SPONSORED, VERIFIED
|
||||
from olympia.hero.models import PrimaryHero, SecondaryHero, SecondaryHeroModule
|
||||
from olympia.hero.serializers import (
|
||||
PrimaryHeroShelfSerializer,
|
||||
SecondaryHeroShelfSerializer,
|
||||
)
|
||||
from olympia.promoted.models import PromotedAddon
|
||||
from olympia.shelves.models import Shelf, ShelfManagement
|
||||
from olympia.users.models import UserProfile
|
||||
|
@ -78,7 +83,7 @@ class TestShelfViewSet(ESTestCase):
|
|||
cls.refresh()
|
||||
|
||||
def setUp(self):
|
||||
self.url = reverse_ns('shelves-list')
|
||||
self.url = reverse_ns('shelves-list', api_version='v5')
|
||||
|
||||
shelf_a = Shelf.objects.create(
|
||||
title='Recommended extensions',
|
||||
|
@ -103,10 +108,13 @@ class TestShelfViewSet(ESTestCase):
|
|||
self.hpshelf_b = ShelfManagement.objects.create(shelf=shelf_b, position=2)
|
||||
ShelfManagement.objects.create(shelf=shelf_c, position=1)
|
||||
|
||||
self.search_url = reverse_ns('addon-search') + shelf_a.criteria
|
||||
self.search_url = (
|
||||
reverse_ns('addon-search', api_version='v5') + shelf_a.criteria
|
||||
)
|
||||
|
||||
self.collections_url = reverse_ns(
|
||||
'collection-addon-list',
|
||||
api_version='v5',
|
||||
kwargs={
|
||||
'user_pk': settings.TASK_USER_ID,
|
||||
'collection_slug': shelf_b.criteria,
|
||||
|
@ -123,6 +131,8 @@ class TestShelfViewSet(ESTestCase):
|
|||
'page_size': 25,
|
||||
'previous': None,
|
||||
'results': [],
|
||||
'primary': None,
|
||||
'secondary': None,
|
||||
}
|
||||
|
||||
def test_only_enabled_shelves_in_view(self):
|
||||
|
@ -168,6 +178,71 @@ class TestShelfViewSet(ESTestCase):
|
|||
)
|
||||
assert result['results'][1]['addons'][0]['type'] == 'extension'
|
||||
|
||||
# If we delete HeroShelvesView move all the TestHeroShelvesView tests here
|
||||
def test_only_hero_shelves_in_response(self):
|
||||
phero = PrimaryHero.objects.create(
|
||||
promoted_addon=PromotedAddon.objects.create(addon=addon_factory()),
|
||||
enabled=True,
|
||||
)
|
||||
shero = SecondaryHero.objects.create(
|
||||
headline='headline', description='description', enabled=True
|
||||
)
|
||||
SecondaryHeroModule.objects.create(shelf=shero)
|
||||
SecondaryHeroModule.objects.create(shelf=shero)
|
||||
SecondaryHeroModule.objects.create(shelf=shero)
|
||||
|
||||
with self.assertNumQueries(14):
|
||||
# 14 queries:
|
||||
# - 1 to get the shelves
|
||||
# - 11 as TestPrimaryHeroShelfViewSet.test_basic
|
||||
# - 2 as TestSecondaryHeroShelfViewSet.test_basic
|
||||
response = self.client.get(self.url, {'lang': 'en-US'})
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {
|
||||
'count': 0,
|
||||
'next': None,
|
||||
'page_count': 1,
|
||||
'page_size': 25,
|
||||
'previous': None,
|
||||
'results': [],
|
||||
'primary': PrimaryHeroShelfSerializer(instance=phero).data,
|
||||
'secondary': SecondaryHeroShelfSerializer(instance=shero).data,
|
||||
}
|
||||
|
||||
def test_full_response(self):
|
||||
phero = PrimaryHero.objects.create(
|
||||
promoted_addon=PromotedAddon.objects.create(addon=addon_factory()),
|
||||
enabled=True,
|
||||
)
|
||||
shero = SecondaryHero.objects.create(
|
||||
headline='headline', description='description', enabled=True
|
||||
)
|
||||
SecondaryHeroModule.objects.create(shelf=shero)
|
||||
SecondaryHeroModule.objects.create(shelf=shero)
|
||||
SecondaryHeroModule.objects.create(shelf=shero)
|
||||
|
||||
self.hpshelf_a.update(enabled=True)
|
||||
|
||||
with self.assertNumQueries(17):
|
||||
# 17 queries:
|
||||
# - 4 to get the shelves
|
||||
# - 11 as TestPrimaryHeroShelfViewSet.test_basic
|
||||
# - 2 as TestSecondaryHeroShelfViewSet.test_basic
|
||||
response = self.client.get(self.url)
|
||||
assert response.status_code == 200
|
||||
|
||||
result = json.loads(response.content)
|
||||
|
||||
assert len(result['results']) == 1
|
||||
|
||||
assert result['results'][0]['title'] == 'Recommended extensions'
|
||||
assert result['results'][0]['addons'][0]['name']['en-US'] == (
|
||||
'test addon test03'
|
||||
)
|
||||
|
||||
assert result['primary'] == PrimaryHeroShelfSerializer(instance=phero).data
|
||||
assert result['secondary'] == SecondaryHeroShelfSerializer(instance=shero).data
|
||||
|
||||
|
||||
class TestSponsoredShelfViewSet(ESTestCase):
|
||||
client_class = APITestClient
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
from django.db.transaction import non_atomic_requests
|
||||
from django.utils.decorators import classonlymethod
|
||||
|
||||
from django_statsd.clients import statsd
|
||||
from elasticsearch_dsl import Q, query
|
||||
|
@ -11,6 +12,7 @@ import olympia.core.logger
|
|||
from olympia.addons.views import AddonSearchView
|
||||
from olympia.api.pagination import ESPageNumberPagination
|
||||
from olympia.constants.promoted import PROMOTED_GROUPS
|
||||
from olympia.hero.views import PrimaryHeroShelfViewSet, SecondaryHeroShelfViewSet
|
||||
from olympia.search.filters import ReviewedContentFilter
|
||||
|
||||
from .models import Shelf
|
||||
|
@ -36,6 +38,21 @@ class ShelfViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
|
|||
permission_classes = []
|
||||
serializer_class = ShelfSerializer
|
||||
|
||||
def list(self, request, *args, **kwargs):
|
||||
response = super().list(request, *args, **kwargs)
|
||||
response.data['primary'] = PrimaryHeroShelfViewSet(
|
||||
request=request
|
||||
).get_one_random_data()
|
||||
response.data['secondary'] = SecondaryHeroShelfViewSet(
|
||||
request=request
|
||||
).get_one_random_data()
|
||||
return response
|
||||
|
||||
@classonlymethod
|
||||
def as_view(cls, *args, **initkwargs):
|
||||
view = super().as_view(*args, **initkwargs)
|
||||
return non_atomic_requests(view)
|
||||
|
||||
|
||||
class SponsoredShelfPagination(ESPageNumberPagination):
|
||||
page_size = 6
|
||||
|
|
Загрузка…
Ссылка в новой задаче