Test storing MozReview flags in db. (bug 1274371) r=glob draft
authorPiotr Zalewa <pzalewa@mozilla.com>
Thu, 19 Jan 2017 13:30:12 +0100
changeset 10244 eb7553a10799203e6cf31e57bb6c34bc67caeac1
parent 10215 e81e60faa054f1422db8f55f8acb30bb723d8a71
push id1486
push userbmo:pzalewa@mozilla.com
push dateThu, 26 Jan 2017 13:47:32 +0000
reviewersglob
bugs1274371
Test storing MozReview flags in db. (bug 1274371) r=glob This commit adds unittests. The goal is to test models and data flow. File `signal_handlers.py` is refactored to extract flag specific code from the `on_review_request_publishing` and `on_review_publishing` handlers. MozReview-Commit-ID: 4RDcwc1vgqv
pylib/mozreview/mozreview/tests/test_flags_in_db.py
new file mode 100644
--- /dev/null
+++ b/pylib/mozreview/mozreview/tests/test_flags_in_db.py
@@ -0,0 +1,259 @@
+import djblets
+import factory
+import json
+import pytest
+import unittest
+
+import reviewboard.testing
+
+from django.core.exceptions import ValidationError
+from django.db.models import signals
+from django.contrib.auth.models import User
+from mock import patch
+
+from reviewboard.reviews import models as rbmodels
+from mozreview import models as mrmodels
+from mozreview.extra_data import (
+    COMMITS_KEY,
+    IDENTIFIER_KEY,
+    REVIEW_FLAG_KEY,
+    is_parent,
+    is_pushed,
+)
+from mozreview.tests.helpers import BaseFactory, UserFactory
+from mozreview.signal_handlers import (
+    manage_flags_on_rr_publishing,
+    get_flag_value,
+    save_flag_on_review_publishing,
+)
+from mozreview.review_helpers import get_reviewers_status
+
+
+# Shut off reviewboard's post-review-creation signal hooks, which try to touch
+# the database.
+@factory.django.mute_signals(signals.post_init)
+class ReviewRequestFactory(BaseFactory):
+    class Meta:
+        model = rbmodels.ReviewRequest
+        strategy = factory.BUILD_STRATEGY
+
+    submitter = factory.SubFactory(UserFactory)
+    description = 'spam'
+
+    @factory.post_generation
+    def approved(review_request, create, extracted, **kwargs):
+        # The `_approved` property is a complex lazy calculation on
+        # ReviewRequest objects.  We'll short-circuit it here.
+
+        if extracted is None:
+            # No bool provided by caller, set a default value
+            extracted = True
+
+        review_request._approved = extracted
+
+
+class ReviewFactory(BaseFactory):
+    class Meta:
+        model = rbmodels.Review
+        strategy = factory.BUILD_STRATEGY
+
+    public = True
+    user = factory.SubFactory(UserFactory)
+    review_request = factory.SubFactory(ReviewRequestFactory)
+
+
+class MozReviewFlagTypeFactory(BaseFactory):
+    class Meta:
+        model = mrmodels.MozReviewFlagType
+        strategy = factory.BUILD_STRATEGY
+
+    name = 'review'
+    prefix = 'r'
+    values_json = '["+", "-", "?"]'
+
+# We need only one object of `MozReviewFlagType`
+review_flag_type = MozReviewFlagTypeFactory()
+
+
+class MozReviewFlagFactory(BaseFactory):
+    class Meta:
+        model = mrmodels.MozReviewFlag
+        strategy = factory.BUILD_STRATEGY
+
+    type = review_flag_type
+    review_request = factory.SubFactory(ReviewRequestFactory)
+    setter = factory.SubFactory(UserFactory)
+
+
+class TestModels(unittest.TestCase):
+    def test_get_value_from_wrong_prefix(self):
+        with self.assertRaises(ValueError):
+            review_flag_type.get_value_from_status('wrong')
+
+    def test_get_value_from_wrong_status(self):
+        with self.assertRaises(ValueError):
+            review_flag_type.get_value_from_status('r!')
+
+    def test_get_value_from_right_status(self):
+        for value in review_flag_type.values:
+            assert review_flag_type.get_value_from_status(
+                'r%s' % value) == value
+
+    def test_flag_status(self):
+        for value in review_flag_type.values:
+            flag = MozReviewFlagFactory(value=value)
+            assert flag.status == 'r%s' % value
+
+    def test_validation_wrong_value(self):
+        with self.assertRaises(ValidationError):
+            mrmodels.MozReviewFlag.validate_value('!', review_flag_type)
+
+    def test_validation_wrong_user(self):
+        # value ? is allowed for declared reviewers only
+        with self.assertRaises(ValidationError):
+            mrmodels.MozReviewFlag.validate_value('?', review_flag_type,
+                                                  ReviewFactory(),
+                                                  UserFactory(),
+                                                  [])
+
+    def test_validation_right_values(self):
+        for value in review_flag_type.values:
+            self.assertIsNone(mrmodels.MozReviewFlag.validate_value(
+                value, review_flag_type))
+
+    def test_validation_right_user(self):
+        user = UserFactory()
+        self.assertIsNone(mrmodels.MozReviewFlag.validate_value(
+            '?', review_flag_type, ReviewFactory(), user, [user]))
+
+
+@pytest.mark.django_db
+class TestFlagType(djblets.testing.testcases.TestModelsLoaderMixin,
+                 reviewboard.testing.TestCase):
+
+    tests_app = 'mozreview'
+
+    def test_get_flag_type_review(self):
+        ft = mrmodels.MozReviewFlagType.objects.get_review_type()
+        assert ft.name == 'review'
+        assert ft.values == ['+', '-', '?']
+
+
+@pytest.mark.django_db
+class TestOnReviewRequestPublishing(
+    djblets.testing.testcases.TestModelsLoaderMixin,
+    reviewboard.testing.TestCase):
+
+    tests_app = 'mozreview'
+    fixtures = ['test_users']
+
+    def _create_review_request_with_review(self, reviewer=None,
+                                           ship_it=True, status='r+'):
+        if not reviewer:
+            reviewer = self.reviewer
+        diffset = self.create_diffset(self.rr)
+        filediff = self.create_filediff(diffset)
+
+        # Create a review.
+        review = self.create_review(self.rr, user=reviewer, ship_it=ship_it)
+        # Add a flag to a review
+        review.extra_data = json.dumps({REVIEW_FLAG_KEY: status})
+        self.create_diff_comment(review, filediff, text='comment')
+        return review
+
+    def setUp(self):
+        super(TestOnReviewRequestPublishing, self).setUp()
+        self.user = User.objects.get(pk=1)
+        self.reviewer = User.objects.get(pk=2)
+        self.rr = self.create_review_request(submitter=self.user,
+                                             create_repository=True)
+        self.flag_type = mrmodels.MozReviewFlagType.objects.get_review_type()
+
+    def test_setting_flag_on_new_reviewer(self):
+        self.rr.target_people.add(self.reviewer)
+        rrd = rbmodels.ReviewRequestDraft.create(self.rr)
+        assert rrd.target_people.count() == self.rr.target_people.count()
+        manage_flags_on_rr_publishing(self.rr, rrd, self.reviewer, False)
+        assert self.reviewer.flags_set.count() == 1
+        assert self.reviewer.flags_set.all()[0].status == 'r?'
+
+    def test_setting_flag_on_reviewer_by_review_publishing(self):
+        self.rr.target_people.add(self.reviewer)
+        review = self._create_review_request_with_review()
+        value = get_flag_value('r+', review, self.flag_type, self.reviewer,
+                               [self.reviewer])
+        assert value == '+'
+        flag = save_flag_on_review_publishing('+', self.flag_type,
+                                              self.reviewer, review)
+        assert flag.value == '+'
+        assert flag.requestee == self.reviewer
+        assert flag.setter == self.reviewer
+        assert flag in review.flags.all()
+        reviewers_status = get_reviewers_status(self.rr)
+        assert self.reviewer.username in reviewers_status
+        assert reviewers_status[self.reviewer.username]['review_flag'] == 'r+'
+        assert reviewers_status[self.reviewer.username]['ship_it'] == True
+
+    def test_resetting_flag_on_rr_publishing(self):
+        self.rr.target_people.add(self.reviewer)
+        review = self._create_review_request_with_review()
+        rrd = rbmodels.ReviewRequestDraft.create(self.rr)
+        # manage flags with a diffset
+        manage_flags_on_rr_publishing(self.rr, rrd, self.user, True)
+        reviewers_status = get_reviewers_status(self.rr)
+        assert self.reviewer.username in reviewers_status
+        assert reviewers_status[self.reviewer.username]['review_flag'] == 'r?'
+        assert reviewers_status[self.reviewer.username]['ship_it'] == False
+        flag = self.reviewer.flags_requested.latest()
+        assert flag.setter == self.user
+        assert flag.requestee == self.reviewer
+
+    def test_removing_flag_on_rr_publishing(self):
+        review = self._create_review_request_with_review()
+        save_flag_on_review_publishing('+', self.flag_type,
+                                       self.reviewer, review)
+        flag = self.reviewer.flags_requested.latest()
+        assert flag.requestee == self.reviewer
+        assert flag.setter == self.reviewer
+        rrd = rbmodels.ReviewRequestDraft.create(self.rr)
+        manage_flags_on_rr_publishing(self.rr, rrd, self.user, True)
+        reviewers_status = get_reviewers_status(self.rr)
+        assert self.reviewer.username not in reviewers_status
+
+    def test_removing_requestee_from_flag_on_rr_publishing(self):
+        self.rr.target_people.add(self.reviewer)
+        review = self._create_review_request_with_review()
+        save_flag_on_review_publishing('+', self.flag_type,
+                                       self.reviewer, review)
+        rrd = rbmodels.ReviewRequestDraft.create(self.rr)
+        rrd.target_people.remove(self.reviewer)
+        manage_flags_on_rr_publishing(self.rr, rrd, self.user, False)
+        flag = self.reviewer.flags_set.latest()
+        assert flag.setter == self.reviewer
+        assert flag.requestee is None
+        assert flag.review == review
+        assert flag.status == 'r+'
+
+    def test_readding_requestee_to_flag_after_removed(self):
+        self.rr.target_people.add(self.reviewer)
+        review = self._create_review_request_with_review()
+        save_flag_on_review_publishing('+', self.flag_type,
+                                       self.reviewer, review)
+        rrd = rbmodels.ReviewRequestDraft.create(self.rr)
+        rrd.target_people.remove(self.reviewer)
+        manage_flags_on_rr_publishing(self.rr, rrd, self.user, False)
+        flag = self.reviewer.flags_set.latest()
+        assert flag.requestee is None
+        rrd.target_people.add(self.reviewer)
+        manage_flags_on_rr_publishing(self.rr, rrd, self.user, False)
+        flag = self.reviewer.flags_set.latest()
+        assert flag.requestee == self.reviewer
+
+    def test_adding_reviewer_to_target_people_on_rr_publishing(self):
+        rrd = rbmodels.ReviewRequestDraft.create(self.rr)
+        rrd.target_people.add(self.reviewer)
+        manage_flags_on_rr_publishing(self.rr, rrd, self.user, False)
+        flag = self.user.flags_set.latest()
+        assert flag.setter == self.user
+        assert flag.requestee == self.reviewer
+        assert flag.status == 'r?'