コード例 #1
0
 def do_pickup(user, **kwargs):
     pickup = PickupDateFactory(place=place, date=to_range(timezone.now() - relativedelta(**kwargs)))
     pickup.add_collector(user)
コード例 #2
0
class TestFeedbackAPIFilter(APITestCase, ExtractPaginationMixin):
    def setUp(self):
        self.url = '/api/feedback/'

        # create a group with a user and two places
        self.collector = UserFactory()
        self.collector2 = UserFactory()
        self.group = GroupFactory(members=[self.collector, self.collector2])
        self.group2 = GroupFactory(members=[self.collector, self.collector2])
        self.place = PlaceFactory(group=self.group)
        self.place2 = PlaceFactory(group=self.group)
        self.pickup = PickupDateFactory(place=self.place,
                                        date=to_range(timezone.now() -
                                                      relativedelta(days=1)))
        self.pickup2 = PickupDateFactory(place=self.place2,
                                         date=to_range(timezone.now() -
                                                       relativedelta(days=1)))

        # create a feedback data
        self.feedback_get = {
            'given_by': self.collector,
            'about': self.pickup,
            'weight': 1,
            'comment': 'asfjk'
        }
        self.feedback_get2 = {
            'given_by': self.collector2,
            'about': self.pickup2,
            'weight': 2,
            'comment': 'bsfjk'
        }

        # create 2 instances of feedback
        self.feedback = Feedback.objects.create(**self.feedback_get)
        self.feedback2 = Feedback.objects.create(**self.feedback_get2)

        # transforms the user into a collector
        self.pickup.add_collector(self.collector)
        self.pickup2.add_collector(self.collector)
        self.pickup2.add_collector(self.collector2)

    def test_filter_by_about(self):
        """
        Filter the two feedbacks and return the one that is about 'pickup'
        """
        self.client.force_login(user=self.collector)
        response = self.get_results(self.url, {'about': self.pickup.id})
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data['feedback'][0]['about'], self.pickup.id,
                         response.data)
        self.assertEqual(len(response.data['feedback']), 1)

    def test_filter_by_given_by(self):
        """
        Filter the two feedbacks and return the one that is given_by 'collector'
        """
        self.client.force_login(user=self.collector)
        response = self.get_results(self.url, {'given_by': self.collector.id})
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data['feedback'][0]['given_by'],
                         self.collector.id)
        self.assertEqual(len(response.data['feedback']), 1)

    def test_filter_by_place(self):
        """
        Filter the two feedbacks and return the one that is about the pickup at 'place'
        """
        self.client.force_login(user=self.collector)
        response = self.get_results(self.url, {'place': self.place.id})
        self.assertEqual(response.data['feedback'][0]['id'], self.feedback.id)
        self.assertEqual(response.data['feedback'][0]['about'], self.pickup.id)
        self.assertEqual(len(response.data['feedback']), 1)

    def test_filter_by_place_2(self):
        """
        Filter the two feedbacks and return the one that is about the pickup at 'place2'
        """
        self.client.force_login(user=self.collector)
        response = self.get_results(self.url, {'place': self.place2.id})
        self.assertEqual(response.data['feedback'][0]['id'], self.feedback2.id)
        self.assertEqual(response.data['feedback'][0]['about'],
                         self.pickup2.id)
        self.assertEqual(len(response.data['feedback']), 1)
        self.assertEqual(response.status_code, status.HTTP_200_OK)

    def test_filter_by_group(self):
        """
        Filter the two feedbacks by the places' group
        """
        self.client.force_login(user=self.collector)
        response = self.get_results(self.url, {'group': self.group.id})
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(len(response.data['feedback']), 2)
        response = self.get_results(self.url, {'group': self.group2.id})
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(len(response.data['feedback']), 0)

    def test_filter_by_created_at(self):
        """
        Filter the two feedbacks by creation date
        """
        self.client.force_login(user=self.collector)
        # self.feedback is older than self.feedback2
        # first, get all that are newer than self.feedback
        response = self.get_results(
            self.url, {'created_at_min': self.feedback.created_at})
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(len(response.data['feedback']), 2)
        self.assertEqual(response.data['feedback'][0]['id'], self.feedback2.id)
        # second, get all that are older than self.feedback
        response = self.get_results(
            self.url, {'created_at_max': self.feedback.created_at})
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(len(response.data['feedback']), 1)
        self.assertEqual(response.data['feedback'][0]['id'], self.feedback.id)
コード例 #3
0
class PickupDateReceiverTests(WSTestCase):
    def setUp(self):
        super().setUp()
        self.member = UserFactory()
        self.group = GroupFactory(members=[self.member])
        self.place = PlaceFactory(group=self.group)
        self.pickup = PickupDateFactory(place=self.place)

    def test_receive_pickup_changes(self):
        client = self.connect_as(self.member)

        # change property
        date = to_range(
            faker.future_datetime(end_date='+30d', tzinfo=timezone.utc))
        self.pickup.date = date
        self.pickup.save()

        response = client.messages_by_topic.get('pickups:pickupdate')[0]
        self.assertEqual(parse(response['payload']['date'][0]), date.start)

        # join
        client = self.connect_as(self.member)
        self.pickup.add_collector(self.member)

        response = client.messages_by_topic.get('pickups:pickupdate')[0]
        self.assertEqual(response['payload']['collectors'], [self.member.id])

        response = client.messages_by_topic.get(
            'conversations:conversation')[0]
        self.assertEqual(response['payload']['participants'], [self.member.id])

        # leave
        client = self.connect_as(self.member)
        self.pickup.remove_collector(self.member)

        response = client.messages_by_topic.get('pickups:pickupdate')[0]
        self.assertEqual(response['payload']['collectors'], [])

        self.assertIn('conversations:leave', client.messages_by_topic.keys())

    def test_mark_as_done(self):
        self.pickup.add_collector(self.member)
        Notification.objects.all().delete()
        client = self.connect_as(self.member)
        self.pickup.is_done = True
        self.pickup.save()

        messages = client.messages_by_topic
        self.assertEqual(len(messages['status']), 2, messages['status'])
        self.assertEqual(messages['status'][0]['payload'],
                         {'unseen_notification_count': 1})
        self.assertEqual(
            messages['status'][1]['payload'],
            {'groups': {
                self.group.id: {
                    'feedback_possible_count': 1
                }
            }})
        self.assertEqual(len(messages['notifications:notification']), 1,
                         messages['notifications:notification'])
        self.assertEqual(
            messages['notifications:notification'][0]['payload']['type'],
            'feedback_possible')

    def test_receive_pickup_delete(self):
        client = self.connect_as(self.member)

        pickup_id = self.pickup.id
        self.pickup.delete()

        response = client.messages_by_topic.get(
            'pickups:pickupdate_deleted')[0]
        self.assertEqual(response['payload']['id'], pickup_id)

        self.assertEqual(len(client.messages), 1)
コード例 #4
0
class FeedbackTest(APITestCase, ExtractPaginationMixin):
    def setUp(self):
        self.url = '/api/feedback/'

        self.member = UserFactory()
        self.collector = UserFactory()
        self.collector2 = UserFactory()
        self.collector3 = UserFactory()
        self.evil_collector = UserFactory()
        self.group = GroupFactory(members=[
            self.member, self.collector, self.evil_collector, self.collector2,
            self.collector3
        ])
        self.place = PlaceFactory(group=self.group)
        self.pickup = PickupDateFactory(
            place=self.place,
            date=to_range(timezone.now() + relativedelta(days=1)),
            collectors=[self.collector, self.collector2, self.collector3],
        )

        # not a member of the group
        self.user = UserFactory()

        # past pickup date
        self.past_pickup = PickupDateFactory(
            place=self.place,
            date=to_range(timezone.now() - relativedelta(days=1)),
            collectors=[
                self.collector, self.evil_collector, self.collector2,
                self.collector3
            ],
        )

        # old pickup date with feedback
        self.old_pickup = PickupDateFactory(
            place=self.place,
            date=to_range(timezone.now() - relativedelta(
                days=settings.FEEDBACK_POSSIBLE_DAYS + 2)),
            collectors=[
                self.collector3,
            ])
        self.old_feedback = FeedbackFactory(about=self.old_pickup,
                                            given_by=self.collector3)

        # create feedback for POST method
        self.feedback_post = {
            'about': self.past_pickup.id,
            'weight': 2,
            'comment': 'asfjk'
        }

        # create feedback for POST method without weight and comment
        self.feedback_without_weight_comment = {
            'about': self.past_pickup.id,
        }

        # create feedback to future pickup
        self.future_feedback_post = {
            'about': self.pickup.id,
            'weight': 2,
            'comment': 'asfjk'
        }

        # create feedback for an old pickup
        self.feedback_for_old_pickup = {
            'about': self.old_pickup.id,
            'weight': 5,
            'comment': 'this is long ago'
        }

        # create feedback for GET method
        self.feedback_get = {
            'given_by': self.collector,
            'about': self.past_pickup,
            'weight': 2,
            'comment': 'asfjk2'
        }

        self.feedback_get_2 = {
            'given_by': self.collector2,
            'about': self.past_pickup,
            'weight': 2,
            'comment': 'asfjk'
        }

        # create 2 instances of feedback for GET method
        self.feedback = Feedback.objects.create(**self.feedback_get)
        Feedback.objects.create(**self.feedback_get_2)

        self.feedback_url = self.url + str(self.feedback.id) + '/'
        self.old_feedback_url = self.url + str(self.old_feedback.id) + '/'

    def test_create_feedback_fails_as_non_user(self):
        """
        Non-User is not allowed to give feedback.
        """
        response = self.client.post(self.url,
                                    self.feedback_post,
                                    format='json')
        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN,
                         response.data)

    def test_create_feedback_fails_as_non_group_member(self):
        """
        User is not allowed to give feedback when not a member of the place's group.
        """
        self.client.force_login(user=self.user)
        response = self.client.post(self.url,
                                    self.feedback_post,
                                    format='json')
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST,
                         response.data)
        self.assertEqual(
            response.data,
            {'about': ['You are not member of the place\'s group.']})

    def test_create_feedback_fails_as_non_collector(self):
        """
        Group Member is not allowed to give feedback when he is not assigned to the pickup.
        """
        self.client.force_login(user=self.member)
        response = self.client.post(self.url,
                                    self.feedback_post,
                                    format='json')
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST,
                         response.data)
        self.assertEqual(response.data,
                         {'about': ['You aren\'t assigned to the pickup.']})

    def test_create_feedback_works_as_collector(self):
        """
        Editor is allowed to give feedback when he is assigned to the Pickup.
        """
        self.client.force_login(user=self.collector3)
        response = self.client.post(self.url,
                                    self.feedback_post,
                                    format='json')
        self.assertEqual(response.status_code, status.HTTP_201_CREATED,
                         response.data)

    def test_create_feedback_as_newcomer_collector(self):
        """
        Newcomer is allowed to give feedback when he is assigned to the Pickup.
        """
        newcomer = UserFactory()
        self.group.groupmembership_set.create(user=newcomer)
        self.past_pickup.add_collector(newcomer)
        self.client.force_login(user=newcomer)
        response = self.client.post(self.url,
                                    self.feedback_post,
                                    format='json')
        self.assertEqual(response.status_code, status.HTTP_201_CREATED,
                         response.data)

    def test_create_feedback_activates_group(self):
        self.group.status = GroupStatus.INACTIVE.value
        self.group.save()
        self.client.force_login(user=self.collector3)
        self.client.post(self.url, self.feedback_post, format='json')
        self.group.refresh_from_db()
        self.assertEqual(self.group.status, GroupStatus.ACTIVE.value)

    def test_create_feedback_twice_fails_for_one_pickup(self):
        """
        Collector is not allowed to give feedback more than one time to the Pickup.
        """
        self.client.force_login(user=self.collector3)
        response = self.client.post(self.url,
                                    self.feedback_post,
                                    format='json')
        self.assertEqual(response.status_code, status.HTTP_201_CREATED,
                         response.data)
        response = self.client.post(self.url,
                                    self.feedback_post,
                                    format='json')
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST,
                         response.data)
        self.assertEqual(
            response.data, {
                'non_field_errors':
                ['The fields about, given_by must make a unique set.']
            })

    def test_create_feedback_fails_for_old_pickup(self):
        """
        Collector is not allowed to give feedback for old Pickups.
        """
        self.client.force_login(user=self.collector3)
        response = self.client.post(self.url,
                                    self.feedback_for_old_pickup,
                                    format='json')
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST,
                         response.data)
        self.assertEqual(
            response.data, {
                'about': [
                    'You can\'t give feedback for pickups more than {} days ago.'
                    .format(settings.FEEDBACK_POSSIBLE_DAYS)
                ]
            })

    def test_create_feedback_without_weight(self):
        """
        Weight field can be empty
        """
        self.client.force_login(user=self.collector3)
        response = self.client.post(
            self.url,
            {k: v
             for (k, v) in self.feedback_post.items() if k != 'weight'})
        self.assertEqual(response.status_code, status.HTTP_201_CREATED,
                         response.data)
        self.assertIsNone(response.data['weight'])

    def test_create_feedback_without_comment(self):
        """
        Comment field can be empty
        """
        self.client.force_login(user=self.collector3)
        response = self.client.post(
            self.url,
            {k: v
             for (k, v) in self.feedback_post.items() if k != 'comment'})
        self.assertEqual(response.status_code, status.HTTP_201_CREATED,
                         response.data)
        self.assertEqual(response.data['comment'], '')

    def test_weight_and_comment_is_null_fails(self):
        """
        Both comment and weight cannot be empty
        """
        self.client.force_login(user=self.collector3)
        response = self.client.post(self.url,
                                    self.feedback_without_weight_comment,
                                    format='json')
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST,
                         response.data)
        self.assertEqual(
            response.data,
            {'non_field_errors': ['Both comment and weight cannot be blank.']})

    def test_list_feedback_fails_as_non_user(self):
        """
        Non-User is NOT allowed to see list of feedback
        """
        response = self.get_results(self.url)
        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN,
                         response.data)

    def test_list_feedback_works_as_non_group_member(self):
        """
        Non-Member doesn't see feedback but an empty list
        """
        self.client.force_login(user=self.user)
        response = self.get_results(self.url)
        self.assertEqual(response.status_code, status.HTTP_200_OK,
                         response.data)
        self.assertEqual(len(response.data['feedback']), 0)

    def test_list_feedback_works_as_group_member(self):
        """
        Member is allowed to see list of feedback
        """
        self.client.force_login(user=self.member)
        with self.assertNumQueries(4):
            response = self.get_results(self.url)
        self.assertEqual(response.status_code, status.HTTP_200_OK,
                         response.data)
        feedback = response.data['feedback']
        self.assertEqual(len(feedback), 3)

        # check related data
        pickup_ids = set(f['about'] for f in feedback)
        self.assertEqual(len(response.data['pickups']), len(pickup_ids))
        self.assertEqual(set(p['id'] for p in response.data['pickups']),
                         pickup_ids)

    def test_list_feedback_works_as_collector(self):
        """
        Collector is allowed to see list of feedback
        """
        self.client.force_login(user=self.collector)
        response = self.get_results(self.url)
        self.assertEqual(response.status_code, status.HTTP_200_OK,
                         response.data)
        self.assertEqual(len(response.data['feedback']), 3)

    def test_retrieve_feedback_fails_as_non_user(self):
        """
        Non-User is NOT allowed to see single feedback
        """
        response = self.get_results(self.feedback_url)
        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN,
                         response.data)

    def test_retrieve_feedback_fails_as_non_group_member(self):
        """
        Non-Member is NOT allowed to see single feedback
        """
        self.client.force_login(user=self.user)
        response = self.get_results(self.feedback_url)
        self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND,
                         response.data)

    def test_retrieve_feedback_works_as_group_member(self):
        """
        Member is allowed to see single feedback
        """
        self.client.force_login(user=self.member)
        response = self.get_results(self.feedback_url)
        self.assertEqual(response.status_code, status.HTTP_200_OK,
                         response.data)

    def test_retrieve_feedback_works_as_collector(self):
        """
        Collector is allowed to see list of feedback
        """
        self.client.force_login(user=self.collector)
        response = self.get_results(self.feedback_url)
        self.assertEqual(response.status_code, status.HTTP_200_OK,
                         response.data)

    def test_create_future_feedback_fails_as_collector(self):
        """
        Collector is NOT allowed to leave feedback for future pickup
        """
        self.client.force_login(user=self.collector3)
        response = self.client.post(self.url, self.future_feedback_post)
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST,
                         response.data)
        self.assertEqual(response.data,
                         {'about': ['The pickup is not done yet']})

    def test_patch_feedback_fails_as_non_user(self):
        """
        Non-user is not allowed to change feedback
        """
        response = self.client.patch(self.feedback_url,
                                     self.feedback_post,
                                     format='json')
        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN,
                         response.data)

    def test_patch_feedback_fails_as_user(self):
        """
        User is not allowed to change feedback
        """
        self.client.force_login(user=self.user)
        response = self.client.patch(self.feedback_url,
                                     self.feedback_post,
                                     format='json')
        self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND,
                         response.data)

    def test_patch_feedback_fails_as_group_member(self):
        """
        Group member is not allowed to change feedback
        """
        self.client.force_login(user=self.member)
        response = self.client.patch(self.feedback_url,
                                     self.feedback_post,
                                     format='json')
        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN,
                         response.data)

    def test_patch_feedback_fails_as_evil_collector(self):
        """
        A collector is not allowed to change feedback if he didn't created it
        """
        self.client.force_login(user=self.evil_collector)
        response = self.client.patch(self.feedback_url, {'weight': 3},
                                     format='json')
        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN,
                         response.data)

    def test_patch_feedback_works_as_collector(self):
        """
        Collector is allowed to change feedback
        """
        self.client.force_login(user=self.collector)
        response = self.client.patch(self.feedback_url, {'weight': 3},
                                     format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK,
                         response.data)
        self.assertEqual(response.data['weight'], 3)

    def test_patch_feedback_activates_group(self):
        self.group.status = GroupStatus.INACTIVE.value
        self.group.save()
        self.client.force_login(user=self.collector)
        self.client.patch(self.feedback_url, {'weight': 3}, format='json')
        self.group.refresh_from_db()
        self.assertEqual(self.group.status, GroupStatus.ACTIVE.value)

    def test_patch_weight_to_negative_value_fails(self):
        """
        Collector cannot change weight to negative value
        """
        self.client.force_login(user=self.collector)
        response = self.client.patch(self.feedback_url, {'weight': -1},
                                     format='json')
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST,
                         response.data)

    def test_patch_feedback_fails_if_pickup_too_old(self):
        self.client.force_login(user=self.collector3)
        response = self.client.patch(self.old_feedback_url, {'weight': 499},
                                     format='json')
        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN,
                         response.data)
        self.assertEqual(
            response.data['detail'],
            'You can\'t give feedback for pickups more than {} days ago.'.
            format(settings.FEEDBACK_POSSIBLE_DAYS))

    def test_patch_feedback_to_remove_weight(self):
        self.client.force_login(user=self.collector)
        response = self.client.patch(self.feedback_url, {'weight': None},
                                     format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK,
                         response.data)
        self.assertEqual(response.data['weight'], None)

    def test_patch_feedback_to_remove_weight_fails_if_comment_is_empty(self):
        self.client.force_login(user=self.collector)
        self.feedback.comment = ''
        self.feedback.save()
        response = self.client.patch(self.feedback_url, {'weight': None},
                                     format='json')
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST,
                         response.data)
        self.assertEqual(
            response.data,
            {'non_field_errors': ['Both comment and weight cannot be blank.']})

    def test_patch_feedback_to_remove_comment(self):
        self.client.force_login(user=self.collector)
        response = self.client.patch(self.feedback_url, {'comment': ''},
                                     format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK,
                         response.data)
        self.assertEqual(response.data['comment'], '')

    def test_patch_feedback_to_remove_comment_fails_if_weight_is_empty(self):
        self.client.force_login(user=self.collector)
        self.feedback.weight = None
        self.feedback.save()
        response = self.client.patch(self.feedback_url, {'comment': ''},
                                     format='json')
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST,
                         response.data)
        self.assertEqual(
            response.data,
            {'non_field_errors': ['Both comment and weight cannot be blank.']})

    def test_patch_feedback_to_remove_comment_and_weight_fails(self):
        self.client.force_login(user=self.collector)
        response = self.client.patch(self.feedback_url, {
            'comment': '',
            'weight': None
        },
                                     format='json')
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST,
                         response.data)
        self.assertEqual(
            response.data,
            {'non_field_errors': ['Both comment and weight cannot be blank.']})
コード例 #5
0
class TestPickupDatesAPI(APITestCase, ExtractPaginationMixin):
    def setUp(self):
        self.url = '/api/pickup-dates/'

        # pickup date for group with one member and one place
        self.member = UserFactory()
        self.second_member = UserFactory()
        self.group = GroupFactory(members=[self.member, self.second_member])
        self.place = PlaceFactory(group=self.group)
        self.pickup = PickupDateFactory(place=self.place)
        self.pickup_url = self.url + str(self.pickup.id) + '/'
        self.join_url = self.pickup_url + 'add/'
        self.leave_url = self.pickup_url + 'remove/'
        self.conversation_url = self.pickup_url + 'conversation/'

        # not a member of the group
        self.user = UserFactory()

        # another pickup date for above place
        self.pickup_data = {
            'date': to_range(timezone.now() + relativedelta(days=2)).as_list(),
            'max_collectors': 5,
            'place': self.place.id
        }

        # past pickup date
        self.past_pickup_data = {
            'date': to_range(timezone.now() - relativedelta(days=1)).as_list(),
            'max_collectors': 5,
            'place': self.place.id
        }
        self.past_pickup = PickupDateFactory(
            place=self.place,
            date=to_range(timezone.now() - relativedelta(days=1)))
        self.past_pickup_url = self.url + str(self.past_pickup.id) + '/'
        self.past_join_url = self.past_pickup_url + 'add/'
        self.past_leave_url = self.past_pickup_url + 'remove/'

    def test_create_pickup(self):
        response = self.client.post(self.url, self.pickup_data, format='json')
        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN,
                         response.data)

    def test_create_pickup_as_user(self):
        self.client.force_login(user=self.user)
        response = self.client.post(self.url, self.pickup_data, format='json')
        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN,
                         response.data)

    def test_create_pickup_as_group_member(self):
        self.client.force_login(user=self.member)
        response = self.client.post(self.url, self.pickup_data, format='json')
        self.assertEqual(response.status_code, status.HTTP_201_CREATED,
                         response.data)

    def test_create_pickup_as_group_member_activates_group(self):
        self.client.force_login(user=self.member)
        self.group.status = GroupStatus.INACTIVE.value
        self.group.save()
        self.client.post(self.url, self.pickup_data, format='json')
        self.group.refresh_from_db()
        self.assertEqual(self.group.status, GroupStatus.ACTIVE.value)

    def test_create_past_pickup_date_fails(self):
        self.client.force_login(user=self.member)
        response = self.client.post(self.url,
                                    self.past_pickup_data,
                                    format='json')
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST,
                         response.data)

    def test_create_pickup_as_newcomer_fails(self):
        newcomer = UserFactory()
        self.group.groupmembership_set.create(user=newcomer)
        self.client.force_login(user=newcomer)
        response = self.client.post(self.url, self.pickup_data, format='json')
        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN,
                         response.data)

    def test_list_pickups(self):
        response = self.get_results(self.url)
        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN,
                         response.data)

    def test_list_pickups_as_user(self):
        self.client.force_login(user=self.user)
        response = self.get_results(self.url)
        self.assertEqual(response.status_code, status.HTTP_200_OK,
                         response.data)
        self.assertEqual(len(response.data), 0)

    def test_list_pickups_as_group_member(self):
        self.client.force_login(user=self.member)
        response = self.get_results(self.url)
        self.assertEqual(response.status_code, status.HTTP_200_OK,
                         response.data)
        self.assertEqual(len(response.data), 2)

    def test_retrieve_pickups(self):
        response = self.client.get(self.pickup_url)
        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN,
                         response.data)

    def test_retrieve_pickups_as_user(self):
        self.client.force_login(user=self.user)
        response = self.client.get(self.pickup_url)
        self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND,
                         response.data)

    def test_retrieve_pickups_as_group_member(self):
        self.client.force_login(user=self.member)
        response = self.client.get(self.pickup_url)
        self.assertEqual(response.status_code, status.HTTP_200_OK,
                         response.data)

    def test_patch_pickup(self):
        response = self.client.patch(self.pickup_url,
                                     self.pickup_data,
                                     format='json')
        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN,
                         response.data)

    def test_patch_pickup_as_user(self):
        self.client.force_login(user=self.user)
        response = self.client.patch(self.pickup_url,
                                     self.pickup_data,
                                     format='json')
        self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND,
                         response.data)

    def test_patch_pickup_as_group_member(self):
        self.client.force_login(user=self.member)
        response = self.client.patch(self.pickup_url,
                                     self.pickup_data,
                                     format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK,
                         response.data)

    def test_patch_pickup_as_group_member_activates_group(self):
        self.client.force_login(user=self.member)
        self.group.status = GroupStatus.INACTIVE.value
        self.group.save()
        self.client.patch(self.pickup_url, self.pickup_data, format='json')
        self.group.refresh_from_db()
        self.assertEqual(self.group.status, GroupStatus.ACTIVE.value)

    def test_patch_max_collectors_to_negative_value_fails(self):
        self.client.force_login(user=self.member)
        response = self.client.patch(self.pickup_url, {'max_collectors': -1})
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST,
                         response.data)

    def test_patch_past_pickup_fails(self):
        self.client.force_login(user=self.member)
        response = self.client.patch(self.past_pickup_url,
                                     self.pickup_data,
                                     format='json')
        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN,
                         response.data)

    def test_patch_as_newcomer_fails(self):
        newcomer = UserFactory()
        self.group.groupmembership_set.create(user=newcomer)
        self.client.force_login(user=newcomer)
        response = self.client.patch(self.pickup_url, {'max_collectors': 1},
                                     format='json')
        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN,
                         response.data)

    def test_join_pickup(self):
        response = self.client.post(self.join_url)
        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN,
                         response.data)

    def test_join_pickup_as_user(self):
        self.client.force_login(user=self.user)
        response = self.client.post(self.join_url)
        self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND,
                         response.data)

    def test_join_pickup_as_member(self):
        self.client.force_login(user=self.member)
        response = self.client.post(self.join_url)
        self.assertEqual(response.status_code, status.HTTP_200_OK,
                         response.data)

        # should have access to chat
        response = self.client.get(self.conversation_url)
        self.assertEqual(response.status_code, status.HTTP_200_OK)

    def test_join_pickup_order_by_sign_up(self):
        self.client.force_login(user=self.second_member)
        response = self.client.post(self.join_url)
        self.assertEqual(response.status_code, status.HTTP_200_OK)

        self.client.force_login(user=self.member)
        response = self.client.post(self.join_url)
        self.assertEqual(response.status_code, status.HTTP_200_OK)

        collector_order = [self.second_member.id, self.member.id]
        response = self.client.get(self.pickup_url)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data['collectors'], collector_order)

        response = self.get_results(self.url)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        pickup = next(p for p in response.data if p['id'] == self.pickup.id)
        self.assertEqual(pickup['collectors'], collector_order)

        # reverse order
        collector = self.pickup.pickupdatecollector_set.earliest('created_at')
        collector.created_at = timezone.now()
        collector.save()
        collector_order = [self.member.id, self.second_member.id]

        response = self.client.get(self.pickup_url)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data['collectors'], collector_order)

        response = self.get_results(self.url)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        pickup = next(p for p in response.data if p['id'] == self.pickup.id)
        self.assertEqual(pickup['collectors'], collector_order)

    def test_join_pickup_as_newcomer(self):
        newcomer = UserFactory()
        self.group.groupmembership_set.create(user=newcomer)
        self.client.force_login(user=newcomer)
        response = self.client.post(self.join_url)
        self.assertEqual(response.status_code, status.HTTP_200_OK,
                         response.data)

    def test_join_pickup_as_member_activates_group(self):
        self.client.force_login(user=self.member)
        self.group.status = GroupStatus.INACTIVE.value
        self.group.save()
        self.client.post(self.join_url)
        self.group.refresh_from_db()
        self.assertEqual(self.group.status, GroupStatus.ACTIVE.value)

    def test_join_pickup_without_max_collectors_as_member(self):
        self.client.force_login(user=self.member)
        p = PickupDateFactory(max_collectors=None, place=self.place)
        response = self.client.post('/api/pickup-dates/{}/add/'.format(p.id))
        self.assertEqual(response.status_code, status.HTTP_200_OK,
                         response.data)

    def test_join_full_pickup_fails(self):
        self.client.force_login(user=self.member)
        self.pickup.max_collectors = 1
        self.pickup.save()
        u2 = UserFactory()
        GroupMembership.objects.create(group=self.group, user=u2)
        self.pickup.add_collector(u2)
        response = self.client.post(self.join_url)
        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN,
                         response.data)
        self.assertEqual(response.data['detail'],
                         'Pickup date is already full.')

    def test_join_past_pickup_fails(self):
        self.client.force_login(user=self.member)
        response = self.client.post(self.past_join_url)
        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN,
                         response.data)

    def test_leave_pickup(self):
        response = self.client.post(self.leave_url)
        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN,
                         response.data)

    def test_leave_pickup_as_user(self):
        self.client.force_login(user=self.user)
        response = self.client.post(self.leave_url)
        self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND,
                         response.data)

    def test_leave_pickup_as_member(self):
        self.client.force_login(user=self.member)
        self.pickup.add_collector(self.member)
        response = self.client.post(self.leave_url)
        self.assertEqual(response.status_code, status.HTTP_200_OK,
                         response.data)

        # should be removed from chat
        response = self.client.get(self.conversation_url)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data['notifications'],
                         ConversationNotificationStatus.NONE.value)

    def test_leave_pickup_as_newcomer(self):
        newcomer = UserFactory()
        self.group.groupmembership_set.create(user=newcomer)
        self.pickup.add_collector(newcomer)
        self.client.force_login(user=newcomer)
        response = self.client.post(self.leave_url)
        self.assertEqual(response.status_code, status.HTTP_200_OK,
                         response.data)

    def test_leave_pickup_activates_group(self):
        self.client.force_login(user=self.member)
        self.pickup.add_collector(self.member)
        self.group.status = GroupStatus.INACTIVE.value
        self.group.save()
        self.client.post(self.leave_url)
        self.group.refresh_from_db()
        self.assertEqual(self.group.status, GroupStatus.ACTIVE.value)

    def test_leave_past_pickup_fails(self):
        self.client.force_login(user=self.member)
        self.past_pickup.add_collector(self.member)
        response = self.client.post(self.past_leave_url)
        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN,
                         response.data)

    def test_get_conversation_as_collector(self):
        self.client.force_login(user=self.member)
        self.pickup.add_collector(self.member)

        # can get via pickup
        response = self.client.get(self.conversation_url)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertIn(self.member.id, response.data['participants'])
        self.assertEqual(response.data['type'], 'pickup')

        # can get via conversations
        conversation_id = self.pickup.conversation.id
        response = self.client.get(
            '/api/conversations/{}/'.format(conversation_id))
        self.assertEqual(response.status_code, status.HTTP_200_OK)

        # can write a message
        response = self.client.post('/api/messages/', {
            'conversation': response.data['id'],
            'content': 'hey',
        })
        self.assertEqual(response.status_code, status.HTTP_201_CREATED,
                         response.data)

    def test_can_participate_in_conversation_as_noncollector(self):
        self.client.force_login(user=self.member)

        # can get via pickup
        response = self.client.get(self.conversation_url)
        self.assertEqual(response.status_code, status.HTTP_200_OK)

        # can get via conversation
        conversation_id = self.pickup.conversation.id
        response = self.client.get(
            '/api/conversations/{}/'.format(conversation_id))
        self.assertEqual(response.status_code, status.HTTP_200_OK)

        # can write a message
        response = self.client.post('/api/messages/', {
            'conversation': response.data['id'],
            'content': 'hey',
        })
        self.assertEqual(response.status_code, status.HTTP_201_CREATED,
                         response.data)

    def test_cannot_get_conversation_as_nonmember(self):
        self.client.force_login(user=self.user)

        # cannot get via pickup
        response = self.client.get(self.conversation_url)
        self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)

        # cannot get via conversation info
        conversation_id = self.pickup.conversation.id
        response = self.client.get(
            '/api/conversations/{}/'.format(conversation_id))
        self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)

        # cannot write a message
        conversation_id = self.pickup.conversation.id
        response = self.client.post('/api/messages/', {
            'conversation': conversation_id,
            'content': 'hey',
        })
        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN,
                         response.data)
        self.assertEqual(response.data['detail'],
                         'You are not in this conversation')

    def test_patch_date(self):
        self.client.force_login(user=self.member)
        start = timezone.now() + timedelta(hours=1)
        end = timezone.now() + timedelta(hours=2)
        response = self.client.patch(self.pickup_url, {
            'date': [start, end],
        },
                                     format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK,
                         response.data)
        self.pickup.refresh_from_db()
        self.assertEqual(self.pickup.date, CustomDateTimeTZRange(start, end))

    def test_patch_start_date_only_uses_default_duration(self):
        self.client.force_login(user=self.member)
        start = timezone.now() + timedelta(hours=1)
        response = self.client.patch(self.pickup_url, {
            'date': [start],
        },
                                     format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK,
                         response.data)
        self.pickup.refresh_from_db()
        self.assertEqual(self.pickup.date.end, start + timedelta(minutes=30))

    def test_patch_date_with_single_date_fails(self):
        self.client.force_login(user=self.member)
        response = self.client.patch(self.pickup_url, {
            'date': timezone.now(),
        },
                                     format='json')
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST,
                         response.data)

    def test_patch_end_date_only_fails(self):
        self.client.force_login(user=self.member)
        response = self.client.patch(self.pickup_url, {
            'date': [None, timezone.now()],
        },
                                     format='json')
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST,
                         response.data)

    def test_cannot_mark_as_done(self):
        # This is just temporarily - if we need this feature at some point, we should enable it
        # Make sure to create history entries!
        self.client.force_login(user=self.member)
        self.assertEqual(self.pickup.is_done, False)
        response = self.client.patch(self.pickup_url, {'is_done': True},
                                     format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK,
                         response.data)
        self.pickup.refresh_from_db()
        self.assertFalse(self.pickup.is_done, False)