# Path: app/reviews/factories.py
# class ReviewFactory(TimestampFactory):
#     """Review model factory."""
# 
#     class Meta:
#         model = models.Review
# 
#     user = factory.SubFactory(UserFactory)
#     serving = factory.SubFactory(ServingFactory)
#     value = 4
#     comment = 'Fresh and Delicious!'
#     anonymity_id = 'somerandomid'
# 
# Path: app/reviews/models.py
# class Review(TimestampMixin):
#     """Model representing ratings and comments on served menu items."""
# 
#     EXCELLENT = 5
#     GOOD = 4
#     FAIR = 3
#     POOR = 2
#     TERRIBLE = 1
# 
#     RATINGS = (
#         (EXCELLENT, 'EXCELLENT'),
#         (GOOD, 'GOOD'),
#         (FAIR, 'FAIR'),
#         (POOR, 'POOR'),
#         (TERRIBLE, 'TERRIBLE')
#     )
# 
#     # Make nullable for anonymity of reviewers.
#     user = models.ForeignKey(
#         User, on_delete=models.SET_NULL, blank=True, null=True
#     )
#     # anonymity_id is just a hashed unique identifier for the reviewer used
#     # as a check prevent multiple reviews from one person
#     anonymity_id = models.CharField(blank=True, null=True, max_length=250)
#     serving = models.ForeignKey(Serving, on_delete=models.CASCADE)
#     value = models.PositiveSmallIntegerField(choices=RATINGS)
#     comment = models.TextField(blank=True)
# 
#     def __str__(self):
#         return '{}\'s review of {}'.format(
#             self.user or self.anonymity_id, self.serving
#         )
# 
#     def clean(self):
#         if self.user:
#             if self.__class__.objects.filter(
#                 user=self.user, serving=self.serving
#             ).exists():
#                 raise ValidationError(_('user and serving must be unique'))
#         if self.anonymity_id:
#             if self.__class__.objects.filter(
#                 anonymity_id=self.anonymity_id, serving=self.serving
#             ).exists():
#                 raise ValidationError(
#                     _('anonymity_id and serving must be unique')
#                 )
#         super().clean()
# 
#     def save(self, *args, **kwargs):
#         self.clean()
#         return super().save(*args, **kwargs)


from django.core.exceptions import ValidationError
from django.test import TestCase
from app.reviews.factories import ReviewFactory
from app.reviews.models import Review
    def setUp(self):
        self.review = ReviewFactory()

    def test_enforcement_of_one_review_per_serviving_per_user(self):
        review_new = Review(
            user=self.review.user,
            serving=self.review.serving,
            value=2,
            comment=''
        )

        self.assertRaises(ValidationError, review_new.save)

    def test_enforcement_of_one_review_per_serviving_per_anonymous_user(self):
        review_new = Review(
            anonymity_id=self.review.anonymity_id,
            serving=self.review.serving,
            value=2,
            comment=''
        )

        self.assertRaises(ValidationError, review_new.save)

    def test_multiple_reviews_without_user_and_anonymity_id(self):
        review_one = Review.objects.create(
            serving=self.review.serving,
            value=2,
            comment=''
        )


# Path: app/reviews/factories.py
# class ReviewFactory(TimestampFactory):
#     """Review model factory."""
# 
#     class Meta:
#         model = models.Review
# 
#     user = factory.SubFactory(UserFactory)
#     serving = factory.SubFactory(ServingFactory)
#     value = 4
#     comment = 'Fresh and Delicious!'
#     anonymity_id = 'somerandomid'
# 
# Path: app/reviews/models.py
# class Review(TimestampMixin):
#     """Model representing ratings and comments on served menu items."""
# 
#     EXCELLENT = 5
#     GOOD = 4
#     FAIR = 3
#     POOR = 2
#     TERRIBLE = 1
# 
#     RATINGS = (
#         (EXCELLENT, 'EXCELLENT'),
#         (GOOD, 'GOOD'),
#         (FAIR, 'FAIR'),
#         (POOR, 'POOR'),
#         (TERRIBLE, 'TERRIBLE')
#     )
# 
#     # Make nullable for anonymity of reviewers.
#     user = models.ForeignKey(
#         User, on_delete=models.SET_NULL, blank=True, null=True
#     )
#     # anonymity_id is just a hashed unique identifier for the reviewer used
#     # as a check prevent multiple reviews from one person
#     anonymity_id = models.CharField(blank=True, null=True, max_length=250)
#     serving = models.ForeignKey(Serving, on_delete=models.CASCADE)
#     value = models.PositiveSmallIntegerField(choices=RATINGS)
#     comment = models.TextField(blank=True)
# 
#     def __str__(self):
#         return '{}\'s review of {}'.format(
#             self.user or self.anonymity_id, self.serving
#         )
# 
#     def clean(self):
#         if self.user:
#             if self.__class__.objects.filter(
#                 user=self.user, serving=self.serving
#             ).exists():
#                 raise ValidationError(_('user and serving must be unique'))
#         if self.anonymity_id:
#             if self.__class__.objects.filter(
#                 anonymity_id=self.anonymity_id, serving=self.serving
#             ).exists():
#                 raise ValidationError(
#                     _('anonymity_id and serving must be unique')
#                 )
#         super().clean()
# 
#     def save(self, *args, **kwargs):
#         self.clean()
#         return super().save(*args, **kwargs)


# Path: app/reviews/tests/test_models.py
from django.core.exceptions import ValidationError
from django.test import TestCase
from app.reviews.factories import ReviewFactory
from app.reviews.models import Review

    def setUp(self):
        self.review = ReviewFactory()

    def test_enforcement_of_one_review_per_serviving_per_user(self):
        review_new = Review(
            user=self.review.user,
            serving=self.review.serving,
            value=2,
            comment=''
        )

        self.assertRaises(ValidationError, review_new.save)

    def test_enforcement_of_one_review_per_serviving_per_anonymous_user(self):
        review_new = Review(
            anonymity_id=self.review.anonymity_id,
            serving=self.review.serving,
            value=2,
            comment=''
        )

        self.assertRaises(ValidationError, review_new.save)

    def test_multiple_reviews_without_user_and_anonymity_id(self):
        review_one = Review.objects.create(
            serving=self.review.serving,
            value=2,
            comment=''
        )


        review_two = Review.objects.create(