""" This module holds the tests models of the ``likes`` app. """

from mtp.apps.likes.models import Like

from .tests_cases import BaseLikeTestCase


class LikeableModelTestCase(BaseLikeTestCase):
    """ Test case that tests the ``Likeable`` abstract model. """

    def test_like_attribution(self):
        """ Test like attribution on likeable model. """
        self.trainee1.like(self.proposition1, 5)
        self.trainee1.like(self.proposition2)

        self.trainee2.like(self.proposition2)

        self.trainee3.like(self.proposition1)
        self.trainee3.like(self.proposition2, -1)

        self.assertEqual(self.proposition1.likes.count(), 2)
        self.assertEqual(self.proposition2.likes.count(), 3)

        self.assertEqual(Like.objects.for_author(self.trainee1).count(), 2)
        self.assertEqual(Like.objects.for_author(self.trainee2).count(), 1)
        self.assertEqual(Like.objects.for_author(self.trainee3).count(), 2)

    def test_error_like_attribution(self):
        """ Test like attribution on non likeable model. """
        with self.assertRaises(ValueError):
            self.trainee1.like(self.comment1)

    def test_like_deletion(self):
        """ Test like deletion on likeable model. """
        self.trainee1.like(self.proposition1, -2)
        self.trainee3.like(self.proposition1)

        self.trainee1.unlike(self.proposition1)
        self.assertEqual(self.proposition1.likes.non_deleted().count(), 1)

        remaining_like = self.proposition1.likes.non_deleted().get()
        self.assertEqual(remaining_like.author, self.trainee3)

    def test_error_like_deletion(self):
        """ Test like deletion on non likeable model. """
        with self.assertRaises(ValueError):
            self.trainee1.unlike(self.comment1)

    def test_retrieving_users(self):
        """ Test retrieving users which have liked an object. """
        self.trainee1.like(self.proposition1, -2)
        self.trainee2.like(self.proposition1, 5)
        self.trainee3.like(self.proposition1)

        self.assertEqual(self.proposition1.liked_by().count(), 3)
        self.assertQuerysetEqual(
            self.proposition1.liked_by(),
            [repr(self.trainee1), repr(self.trainee2), repr(self.trainee3)],
            ordered=False
        )

        self.trainee1.unlike(self.proposition1)

        self.assertEqual(self.proposition1.liked_by().count(), 2)
        self.assertQuerysetEqual(
            self.proposition1.liked_by(),
            [repr(self.trainee2), repr(self.trainee3)],
            ordered=False
        )
