Esempio n. 1
0
    def test_user_stats(self):
        self.maxDiff = None

        def update_member_activity(user, **kwargs):
            GroupMembership.objects.filter(user=user).update(
                lastseen_at=timezone.now() - relativedelta(**kwargs))

        def do_pickup(place, user, **kwargs):
            pickup = PickupDateFactory(place=place,
                                       date=to_range(timezone.now() -
                                                     relativedelta(**kwargs)))
            pickup.add_collector(user)

        # 9 verified users, 1 unverified user
        users = [VerifiedUserFactory() for _ in range(9)]
        users.insert(0, UserFactory())

        # 5 some users of varying levels of inactivity
        inactive_users = [VerifiedUserFactory() for _ in range(5)]
        inactive_group = GroupFactory(members=inactive_users)
        GroupMembership.objects.filter(group=inactive_group).update(
            inactive_at=timezone.now())
        update_member_activity(inactive_users[0], days=2)
        update_member_activity(inactive_users[1], days=8)
        update_member_activity(inactive_users[2], days=31)
        update_member_activity(inactive_users[3], days=61)
        update_member_activity(inactive_users[4], days=91)

        # 1 deleted user
        deleted_user = UserFactory()
        deleted_user.deleted = True
        deleted_user.save()

        # one user with bounced email
        bounce_user = users[0]
        for _ in range(5):
            EmailEvent.objects.create(created_at=timezone.now(),
                                      address=bounce_user.email,
                                      event='bounce',
                                      payload={})

        # one user with location
        location_user = users[1]
        location_user.latitude = 50.4
        location_user.longitude = 23.2
        location_user.save()

        # one user with mobile number
        mobile_number_user = users[2]
        mobile_number_user.mobile_number = '123'
        mobile_number_user.save()

        # five users without description
        def remove_description(user):
            user.description = ''
            user.save()

        [remove_description(u) for u in users[:5]]

        # one user with photo
        photo_user = users[4]
        photo_user.photo = 'photo.jpg'
        photo_user.save()

        # 2 groups where everybody is active, 1 where everybody is inactive
        group = GroupFactory(members=users[:9])
        GroupFactory(members=users[:9])
        group_all_inactive = GroupFactory(members=users[:9])
        GroupMembership.objects.filter(group=group_all_inactive).update(
            inactive_at=timezone.now())

        # do some pickups!
        place = PlaceFactory(group=group)
        do_pickup(place, users[0], days=2)
        do_pickup(place, users[1], days=8)
        do_pickup(place, users[2], days=31)
        do_pickup(place, users[3], days=61)
        do_pickup(place, users[4], days=91)

        points = stats.get_users_stats()

        self.assertEqual(
            points, {
                'active_count': 9,
                'active_unverified_count': 1,
                'active_ignored_email_count': 1,
                'active_with_location_count': 1,
                'active_with_mobile_number_count': 1,
                'active_with_description_count': 4,
                'active_with_photo_count': 1,
                'active_memberships_per_active_user_avg': 2.0,
                'no_membership_count': 1,
                'deleted_count': 1,
                'count_active_1d': 9,
                'count_active_7d': 10,
                'count_active_30d': 11,
                'count_active_60d': 12,
                'count_active_90d': 13,
                'count_pickup_active_1d': 0,
                'count_pickup_active_7d': 1,
                'count_pickup_active_30d': 2,
                'count_pickup_active_60d': 3,
                'count_pickup_active_90d': 4,
            })
Esempio n. 2
0
class UserReceiverTest(WSTestCase):
    def setUp(self):
        super().setUp()
        self.member = UserFactory()
        self.other_member = UserFactory()
        self.unrelated_user = UserFactory()
        self.group = GroupFactory(members=[self.member, self.other_member])
        pathlib.Path(settings.MEDIA_ROOT).mkdir(exist_ok=True)
        copyfile(image_path, os.path.join(settings.MEDIA_ROOT, 'photo.jpg'))
        self.member.photo = 'photo.jpg'
        self.member.save()
        self.other_member.photo = 'photo.jpg'
        self.other_member.save()

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

        name = faker.name()
        self.member.display_name = name
        self.member.save()

        response = client.messages_by_topic.get('auth:user')[0]
        self.assertEqual(response['payload']['display_name'], name)
        self.assertTrue('current_group' in response['payload'])
        self.assertTrue(
            response['payload']['photo_urls']['full_size'].startswith(
                settings.HOSTNAME))

        self.assertEqual(len(client.messages), 1)

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

        name = faker.name()
        self.other_member.display_name = name
        self.other_member.save()

        response = client.messages_by_topic.get('users:user')[0]
        self.assertEqual(response['payload']['display_name'], name)
        self.assertTrue('current_group' not in response['payload'])
        self.assertTrue(
            response['payload']['photo_urls']['full_size'].startswith(
                settings.HOSTNAME))

        self.assertEqual(len(client.messages), 1)

    def test_do_not_send_too_many_updates(self):
        [
            GroupFactory(members=[self.member, self.other_member])
            for _ in range(3)
        ]

        client = self.connect_as(self.member)

        name = faker.name()
        self.other_member.display_name = name
        self.other_member.save()

        self.assertEqual(len(client.messages), 1)
        self.assertIn('users:user', client.messages_by_topic.keys())

    def test_unrelated_user_receives_no_changes(self):
        client = self.connect_as(self.unrelated_user)

        self.member.display_name = faker.name()
        self.member.save()

        self.assertEqual(len(client.messages), 0)
Esempio n. 3
0
    def test_user_stats(self):
        self.maxDiff = None

        # avoid test flakyness: remove leftover users from other tests
        get_user_model().objects.all().delete()

        def update_member_activity(user, **kwargs):
            GroupMembership.objects.filter(user=user).update(lastseen_at=timezone.now() - relativedelta(**kwargs))

        def do_activity(place, user, **kwargs):
            activity = ActivityFactory(place=place, date=to_range(timezone.now() - relativedelta(**kwargs)))
            activity.add_participant(user)

        # 9 verified users, 1 unverified user
        users = [VerifiedUserFactory() for _ in range(9)]
        users.insert(0, UserFactory())

        # 5 some users of varying levels of inactivity
        inactive_users = [VerifiedUserFactory() for _ in range(5)]
        inactive_group = GroupFactory(members=inactive_users)
        GroupMembership.objects.filter(group=inactive_group).update(inactive_at=timezone.now())
        update_member_activity(inactive_users[0], days=2)
        update_member_activity(inactive_users[1], days=8)
        update_member_activity(inactive_users[2], days=31)
        update_member_activity(inactive_users[3], days=61)
        update_member_activity(inactive_users[4], days=91)

        # 1 deleted user
        deleted_user = UserFactory()
        deleted_user.deleted = True
        deleted_user.save()

        # one user with location
        location_user = users[1]
        location_user.latitude = 50.4
        location_user.longitude = 23.2
        location_user.save()

        # one user with mobile number
        mobile_number_user = users[2]
        mobile_number_user.mobile_number = '123'
        mobile_number_user.save()

        # five users without description
        def remove_description(user):
            user.description = ''
            user.save()

        [remove_description(u) for u in users[:5]]

        # one user with photo
        photo_user = users[4]
        photo_user.photo = 'photo.jpg'
        photo_user.save()

        # 2 groups where everybody is active, 1 where everybody is inactive
        group = GroupFactory(members=users[:9])
        GroupFactory(members=users[:9])
        group_all_inactive = GroupFactory(members=users[:9])
        GroupMembership.objects.filter(group=group_all_inactive).update(inactive_at=timezone.now())

        # do some activities!
        place = PlaceFactory(group=group)
        do_activity(place, users[0], days=2)
        do_activity(place, users[1], days=8)
        do_activity(place, users[2], days=31)
        do_activity(place, users[3], days=61)
        do_activity(place, users[4], days=91)

        points = stats.get_users_stats()

        self.assertEqual(
            points, {
                'active_count': 9,
                'active_unverified_count': 1,
                'active_with_location_count': 1,
                'active_with_mobile_number_count': 1,
                'active_with_description_count': 4,
                'active_with_photo_count': 1,
                'active_memberships_per_active_user_avg': 2.0,
                'no_membership_count': 1,
                'deleted_count': 1,
                'count_active_1d': 9,
                'count_active_7d': 10,
                'count_active_30d': 11,
                'count_active_60d': 12,
                'count_active_90d': 13,
                'count_activity_active_1d': 0,
                'count_activity_active_7d': 1,
                'count_activity_active_30d': 2,
                'count_activity_active_60d': 3,
                'count_activity_active_90d': 4,
            }
        )
Esempio n. 4
0
class TestInviteCreate(APITestCase):
    def setUp(self):
        self.member = UserFactory()
        self.member2 = UserFactory()
        self.newcomer = UserFactory()
        self.group = GroupFactory(members=[self.member, self.member2],
                                  newcomers=[self.newcomer])
        self.group2 = GroupFactory(members=[self.member])

        # effectively disable throttling
        from karrot.invitations.api import InvitesPerDayThrottle
        InvitesPerDayThrottle.rate = '1000/min'

    def test_invite_same_email_twice(self):
        self.client.force_login(self.member)
        response = self.client.post(base_url, {
            'email': '*****@*****.**',
            'group': self.group.id
        })
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
        response = self.client.post(base_url, {
            'email': '*****@*****.**',
            'group': self.group.id
        })
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)

    def test_invite_again_after_one_hour(self):
        self.client.force_login(self.member)
        response = self.client.post(base_url, {
            'email': '*****@*****.**',
            'group': self.group.id
        })

        # make invitation get one hour behind the timezone to allow resending email
        i = Invitation.objects.get(id=response.data['id'])
        i.created_at = i.created_at - relativedelta(hours=1)
        i.save()

        response = self.client.post(base_url + str(i.id) + '/resend/')
        self.assertEqual(response.status_code, status.HTTP_200_OK)

    def test_cannot_invite_again_in_less_then_one_hour(self):
        # make invitation.created_at back to timezone.now() to not allow resend the email
        self.client.force_login(self.member)
        response = self.client.post(base_url, {
            'email': '*****@*****.**',
            'group': self.group.id
        })

        i = Invitation.objects.get(id=response.data['id'])

        response = self.client.post(base_url + str(i.id) + '/resend/')
        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)

    def test_invite_again_when_expired(self):
        self.client.force_login(self.member)
        response = self.client.post(base_url, {
            'email': '*****@*****.**',
            'group': self.group.id
        })
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)

        # make invitation expire
        i = Invitation.objects.get(id=response.data['id'])
        i.expires_at = timezone.now() - relativedelta(days=1)
        i.save()

        # delete expired invitations
        Invitation.objects.delete_expired_invitations()

        response = self.client.post(base_url, {
            'email': '*****@*****.**',
            'group': self.group.id
        })
        self.assertEqual(response.status_code, status.HTTP_201_CREATED,
                         response.data)

    def test_invite_same_email_to_different_groups(self):
        self.client.force_login(self.member)
        response = self.client.post(base_url, {
            'email': '*****@*****.**',
            'group': self.group.id
        })
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
        response = self.client.post(base_url, {
            'email': '*****@*****.**',
            'group': self.group2.id
        })
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)

    def test_invite_existing_user_but_not_member(self):
        self.client.force_login(self.member)
        response = self.client.post(base_url, {
            'email': self.member2.email,
            'group': self.group2.id
        })
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)

    def test_invite_existing_member(self):
        self.client.force_login(self.member)
        response = self.client.post(base_url, {
            'email': self.member2.email,
            'group': self.group.id
        })
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)

    def test_invite_to_invalid_group(self):
        self.client.force_login(self.member)
        response = self.client.post(base_url, {
            'email': '*****@*****.**',
            'group': 345236
        })
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)

    def test_invite_with_invalid_email(self):
        self.client.force_login(self.member)
        response = self.client.post(base_url, {
            'email': 'pleasehä',
            'group': self.group.id
        })
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)

    @patch('karrot.utils.email_utils.AnymailMessage.send')
    def test_invite_with_rejected_email(self, send):
        send.side_effect = AnymailAPIError()
        self.client.force_login(self.member)
        response = self.client.post(base_url, {
            'email': '*****@*****.**',
            'group': self.group.id
        })
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
        self.assertEqual(Invitation.objects.count(), 0)

    def test_invite_when_inviting_user_is_not_member_of_group(self):
        self.client.force_login(self.member2)
        response = self.client.post(base_url, {
            'email': '*****@*****.**',
            'group': self.group2.id
        })
        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)

    def test_invite_as_newcomer_fails(self):
        self.client.force_login(self.newcomer)
        response = self.client.post(base_url, {
            'email': '*****@*****.**',
            'group': self.group2.id
        })
        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)

    def test_invite_with_different_invited_by_language(self):
        self.member.language = 'fr'
        self.member.save()
        self.client.force_login(self.member)
        response = self.client.post(base_url, {
            'email': '*****@*****.**',
            'group': self.group.id
        })
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
        expected = f'[{settings.SITE_NAME}] Invitation de joinde {self.group.name}'
        self.assertEqual(mail.outbox[-1].subject, expected)
Esempio n. 5
0
class TestUsersAPI(APITestCase):
    def setUp(self):
        self.user = UserFactory()
        self.user.photo = 'photo.jpg'
        self.user.save()
        self.user2 = UserFactory()
        self.url = '/api/users/'
        self.user_data = {
            'email': faker.email(),
            'password': faker.name(),
            'display_name': faker.name(),
            'address': faker.address(),
            'latitude': faker.latitude(),
            'longitude': faker.longitude()
        }
        self.group = GroupFactory(members=[self.user, self.user2])
        self.another_common_group = GroupFactory(members=[self.user, self.user2])
        self.user_in_another_group = UserFactory()
        self.another_group = GroupFactory(members=[self.user_in_another_group])
        mail.outbox = []

    def test_list_users_forbidden(self):
        response = self.client.get(self.url)
        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)

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

    def test_retrieve_user_forbidden(self):
        url = self.url + str(self.user.id) + '/'
        response = self.client.get(url)
        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)

    def test_retrieve_user_allowed(self):
        self.client.force_login(user=self.user2)
        url = self.url + str(self.user.id) + '/'
        response = self.client.get(url)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertIn('photo_urls', response.data)
        self.assertNotIn('description', response.data)

    def test_retrieve_user_profile(self):
        self.client.force_login(user=self.user2)
        url = self.url + str(self.user.id) + '/profile/'
        response = self.client.get(url)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data['description'], self.user.description)
        self.assertEqual(set(response.data['groups']), set([self.group.id, self.another_common_group.id]))
        self.assertTrue(response.data['photo_urls']['full_size'].startswith('http'))

    def test_retrieve_user_in_another_group_fails(self):
        self.client.force_login(user=self.user2)
        url = self.url + str(self.user_in_another_group.id) + '/'
        response = self.client.get(url)
        self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)

    def test_get_conversation(self):
        self.client.force_login(user=self.user)
        response = self.client.get('/api/users/{}/conversation/'.format(self.user2.id))
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertIn(self.user.id, response.data['participants'])
        self.assertIn(self.user2.id, response.data['participants'])
        self.assertEqual(len(response.data['participants']), 2)

    def test_get_conversation_for_yourself_fails(self):
        self.client.force_login(user=self.user)
        response = self.client.get('/api/users/{}/conversation/'.format(self.user.id))
        self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)