Merge pull request #9545 from diox/show-deleted-ratings-as-such
Add `is_deleted` property to ratings API
This commit is contained in:
Коммит
70a1407574
|
@ -279,3 +279,4 @@ v4 API changelog
|
|||
On addons-dev and addons stage enviroments the previous behavior is available as `api/v4dev`. The `v4dev` api is not available on AMO production server.
|
||||
https://github.com/mozilla/addons-server/issues/9467
|
||||
* 2018-10-04: added ``is_strict_compatibility_enabled`` to discovery API ``addons.current_version`` object. This change was also backported to the `v3` API. https://github.com/mozilla/addons-server/issues/9520
|
||||
* 2018-10-04: added ``is_deleted`` to the ratings API. This change was also backported to the `v3` API. https://github.com/mozilla/addons-server/issues/9371
|
||||
|
|
|
@ -64,6 +64,13 @@ Detail
|
|||
|
||||
This endpoint allows you to fetch a rating by its id.
|
||||
|
||||
.. note::
|
||||
|
||||
Users with ``Addons:Edit`` permission will be able to see deleted ratings.
|
||||
Use the ``is_deleted`` property to distinguish those from normal ratings
|
||||
everyone is able to see.
|
||||
|
||||
|
||||
.. http:get:: /api/v4/ratings/rating/(int:id)/
|
||||
|
||||
.. _rating-detail-object:
|
||||
|
@ -71,6 +78,7 @@ This endpoint allows you to fetch a rating by its id.
|
|||
:>json int id: The rating id.
|
||||
:>json object addon: A simplified :ref:`add-on <addon-detail-object>` object that contains only a few properties: ``id``, ``name``, ``icon_url`` and ``slug``.
|
||||
:>json string|null body: The text of the rating.
|
||||
:>json boolean is_deleted: Boolean indicating whether the rating has been deleted or not.
|
||||
:>json boolean is_latest: Boolean indicating whether the rating is the latest posted by the user on the same add-on.
|
||||
:>json int previous_count: The number of ratings posted by the user on the same add-on before this one.
|
||||
:>json int score: The score the user gave as part of the rating.
|
||||
|
|
|
@ -28,6 +28,7 @@ class RatingAddonSerializer(SimpleAddonSerializer):
|
|||
class BaseRatingSerializer(serializers.ModelSerializer):
|
||||
addon = RatingAddonSerializer(read_only=True)
|
||||
body = serializers.CharField(allow_null=True, required=False)
|
||||
is_deleted = serializers.BooleanField(read_only=True, source='deleted')
|
||||
is_developer_reply = serializers.SerializerMethodField()
|
||||
is_latest = serializers.BooleanField(read_only=True)
|
||||
previous_count = serializers.IntegerField(read_only=True)
|
||||
|
@ -35,8 +36,8 @@ class BaseRatingSerializer(serializers.ModelSerializer):
|
|||
|
||||
class Meta:
|
||||
model = Rating
|
||||
fields = ('id', 'addon', 'body', 'created', 'is_developer_reply',
|
||||
'is_latest', 'previous_count', 'user')
|
||||
fields = ('id', 'addon', 'body', 'created', 'is_deleted',
|
||||
'is_developer_reply', 'is_latest', 'previous_count', 'user')
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(BaseRatingSerializer, self).__init__(*args, **kwargs)
|
||||
|
|
|
@ -45,6 +45,7 @@ class TestBaseRatingSerializer(TestCase):
|
|||
assert result['body'] == unicode(self.rating.body)
|
||||
assert result['created'] == (
|
||||
self.rating.created.replace(microsecond=0).isoformat() + 'Z')
|
||||
assert result['is_deleted'] is False
|
||||
assert result['previous_count'] == int(self.rating.previous_count)
|
||||
assert result['is_developer_reply'] is False
|
||||
assert result['is_latest'] == self.rating.is_latest
|
||||
|
@ -67,6 +68,46 @@ class TestBaseRatingSerializer(TestCase):
|
|||
# Check the default, when DRF_API_GATES['ratings-title-shim'] isn't set
|
||||
assert 'title' not in result
|
||||
|
||||
def test_deleted_rating_but_view_allowing_it_to_be_shown(self):
|
||||
# We don't need to change self.view.should_access_deleted_ratings
|
||||
# because the serializer is not fetching the rating itself, it's just
|
||||
# serializing whatever instance we passed.
|
||||
addon = addon_factory()
|
||||
self.view.get_addon_object.return_value = addon
|
||||
self.rating = Rating.objects.create(
|
||||
addon=addon, user=self.user, rating=4,
|
||||
version=addon.current_version, body=u'This is my rëview. Like ît?')
|
||||
|
||||
self.rating.delete()
|
||||
result = self.serialize()
|
||||
|
||||
assert result['id'] == self.rating.pk
|
||||
assert result['addon'] == {
|
||||
'id': addon.pk,
|
||||
'slug': addon.slug,
|
||||
'name': {'en-US': addon.name},
|
||||
'icon_url': absolutify(addon.get_icon_url(64)),
|
||||
}
|
||||
assert result['body'] == unicode(self.rating.body)
|
||||
assert result['created'] == (
|
||||
self.rating.created.replace(microsecond=0).isoformat() + 'Z')
|
||||
assert result['is_deleted'] is True
|
||||
assert result['previous_count'] == int(self.rating.previous_count)
|
||||
assert result['is_developer_reply'] is False
|
||||
assert result['is_latest'] == self.rating.is_latest
|
||||
assert result['score'] == int(self.rating.rating)
|
||||
assert result['reply'] is None
|
||||
assert result['user'] == {
|
||||
'id': self.user.pk,
|
||||
'name': unicode(self.user.name),
|
||||
'url': None,
|
||||
'username': self.user.username,
|
||||
}
|
||||
assert result['version'] == {
|
||||
'id': self.rating.version.id,
|
||||
'version': self.rating.version.version
|
||||
}
|
||||
|
||||
@override_settings(DRF_API_GATES={None: ('ratings-rating-shim',)})
|
||||
def test_ratings_score_is_rating_with_gate(self):
|
||||
addon = addon_factory()
|
||||
|
@ -152,6 +193,7 @@ class TestBaseRatingSerializer(TestCase):
|
|||
assert data['body'] == unicode(reply.body)
|
||||
assert data['created'] == (
|
||||
reply.created.replace(microsecond=0).isoformat() + 'Z')
|
||||
assert data['is_deleted'] is False
|
||||
assert data['is_developer_reply'] is True
|
||||
assert data['user'] == {
|
||||
'id': reply_user.pk,
|
||||
|
@ -219,13 +261,14 @@ class TestBaseRatingSerializer(TestCase):
|
|||
reply_user = user_factory()
|
||||
addon = addon_factory(users=[reply_user])
|
||||
self.view.get_addon_object.return_value = addon
|
||||
self.view.should_access_deleted_reviews = True
|
||||
self.view.should_access_deleted_ratings = True
|
||||
self.rating = Rating.objects.create(
|
||||
addon=addon, user=self.user, version=addon.current_version,
|
||||
body=u'This is my rëview. Like ît ?')
|
||||
reply = Rating.objects.create(
|
||||
addon=addon, user=reply_user, version=addon.current_version,
|
||||
body=u'Thîs is a reply.', reply_to=self.rating)
|
||||
reply.delete()
|
||||
|
||||
result = self.serialize()
|
||||
|
||||
|
@ -236,6 +279,7 @@ class TestBaseRatingSerializer(TestCase):
|
|||
assert result['reply']['body'] == unicode(reply.body)
|
||||
assert result['reply']['created'] == (
|
||||
reply.created.replace(microsecond=0).isoformat() + 'Z')
|
||||
assert result['reply']['is_deleted'] is True
|
||||
assert result['reply']['user'] == {
|
||||
'id': reply_user.pk,
|
||||
'name': unicode(reply_user.name),
|
||||
|
|
Загрузка…
Ссылка в новой задаче