Beispiel #1
0
 def setUp(self):
     self.now = timezone.now()
     self.member = UserFactory()
     self.group = GroupFactory(members=[self.member])
     self.store = StoreFactory(group=self.group)
     self.series = PickupDateSeriesFactory(max_collectors=3, store=self.store)
     self.series.update_pickup_dates(start=lambda: self.now)
class PickupDateSeriesReceiverTests(WSTestCase):
    def setUp(self):
        super().setUp()
        self.member = UserFactory()
        self.group = GroupFactory(members=[self.member])
        self.store = StoreFactory(group=self.group)

        # Create far in the future to generate no pickup dates
        # They would lead to interfering websocket messages
        self.series = PickupDateSeriesFactory(store=self.store, start_date=timezone.now() + relativedelta(months=2))

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

        date = faker.future_datetime(end_date='+30d', tzinfo=timezone.utc) + relativedelta(months=2)
        self.series.start_date = date
        self.series.save()

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

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

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

        id = self.series.id
        self.series.delete()

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

        self.assertEqual(len(self.client.messages), 1)
    def setUp(self):

        self.url = '/api/pickup-dates/'

        # pickup date for group with one member and one store
        self.member = UserFactory()
        self.group = GroupFactory(members=[
            self.member,
        ])
        self.store = StoreFactory(group=self.group)
        self.pickup = PickupDateFactory(store=self.store)

        # and another store + group + pick-update
        self.group2 = GroupFactory(members=[
            self.member,
        ])
        self.store2 = StoreFactory(group=self.group2)
        self.pickup2 = PickupDateFactory(store=self.store2)

        # a pickup date series
        self.series = PickupDateSeriesFactory(store=self.store)
        self.series.update_pickup_dates()

        # another pickup date series
        self.series2 = PickupDateSeriesFactory(store=self.store)
        self.series2.update_pickup_dates()
    def setUp(self):
        self.client = WSClient()
        self.member = UserFactory()
        self.group = GroupFactory(members=[self.member])
        self.store = StoreFactory(group=self.group)

        # Create far in the future to generate no pickup dates
        # They would lead to interfering websocket messages
        self.series = PickupDateSeriesFactory(store=self.store, start_date=timezone.now() + relativedelta(months=2))
    def setUp(self):

        self.now = timezone.now()
        self.url = '/api/stores/'
        self.member = UserFactory()
        self.group = GroupFactory(members=[self.member, ])
        self.store = StoreFactory(group=self.group)
        self.store_url = self.url + str(self.store.id) + '/'
        self.series = PickupDateSeriesFactory(max_collectors=3, store=self.store)
        self.series.update_pickup_dates(start=lambda: self.now)
class TestStoreChangesPickupDateSeriesAPI(APITestCase, ExtractPaginationMixin):
    def setUp(self):

        self.now = timezone.now()
        self.url = '/api/stores/'
        self.member = UserFactory()
        self.group = GroupFactory(members=[self.member, ])
        self.store = StoreFactory(group=self.group)
        self.store_url = self.url + str(self.store.id) + '/'
        self.series = PickupDateSeriesFactory(max_collectors=3, store=self.store)
        self.series.update_pickup_dates(start=lambda: self.now)

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

        url = '/api/pickup-dates/'
        response = self.get_results(url, {'series': self.series.id, 'date_0': self.now})
        self.assertEqual(response.status_code, status.HTTP_200_OK, response.data)

        response = self.client.patch(self.store_url, {'weeks_in_advance': 2})
        self.assertEqual(response.status_code, status.HTTP_200_OK, response.data)
        self.assertEqual(response.data['weeks_in_advance'], 2)

        url = '/api/pickup-dates/'
        response = self.get_results(url, {'series': self.series.id})
        self.assertEqual(response.status_code, status.HTTP_200_OK, response.data)
        for _ in response.data:
            self.assertLessEqual(parse(_['date']), self.now + relativedelta(weeks=2, hours=1))

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

        url = '/api/pickup-dates/'
        response = self.get_results(url, {'series': self.series.id, 'date_0': self.now})
        self.assertEqual(response.status_code, status.HTTP_200_OK, response.data)
        original_dates = [parse(_['date']) for _ in response.data]

        response = self.client.patch(self.store_url, {'weeks_in_advance': 10})
        self.assertEqual(response.status_code, status.HTTP_200_OK, response.data)
        self.assertEqual(response.data['weeks_in_advance'], 10)

        url = '/api/pickup-dates/'
        response = self.get_results(url, {'series': self.series.id})
        self.assertEqual(response.status_code, status.HTTP_200_OK, response.data)
        self.assertGreater(len(response.data), len(original_dates))
        for return_date in response.data:
            self.assertLessEqual(parse(return_date['date']), self.now + relativedelta(weeks=10))

    def test_set_weeks_to_invalid_value(self):
        self.client.force_login(user=self.member)
        response = self.client.patch(self.store_url, {'weeks_in_advance': 0})
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST, response.data)
Beispiel #7
0
    def test_delete(self):
        now = timezone.now()
        two_weeks_ago = now - relativedelta(weeks=2)
        with freeze_time(two_weeks_ago, tick=True):
            series = PickupDateSeriesFactory(store=self.store, start_date=two_weeks_ago)

        pickup_dates = series.pickup_dates.all()
        past_date_count = pickup_dates.filter(date__lt=now).count()
        self.assertGreater(pickup_dates.count(), 2)
        series.delete()
        upcoming_pickups = PickupDate.objects.filter(date__gte=now, is_disabled=False)
        self.assertEqual(upcoming_pickups.count(), 0, upcoming_pickups)
        self.assertEqual(PickupDate.objects.filter(date__lt=now).count(), past_date_count)
Beispiel #8
0
 def setUp(self):
     self.member = UserFactory()
     self.group = GroupFactory(members=[self.member])
     self.store = StoreFactory(group=self.group)
     self.pickup = PickupDateFactory(store=self.store)
     self.pickup_url = '/api/pickup-dates/{}/'.format(self.pickup.id)
     self.series = PickupDateSeriesFactory(store=self.store)
     self.series_url = '/api/pickup-date-series/{}/'.format(self.series.id)
Beispiel #9
0
 def setUp(self):
     self.url = '/api/pickup-date-series/'
     self.series = PickupDateSeriesFactory()
     self.series_url = '/api/pickup-date-series/{}/'.format(self.series.id)
     self.non_member = UserFactory()
     self.series_data = {
         'store': self.series.store.id,
         'rule': 'FREQ=WEEKLY',
         'start_date': timezone.now()
     }
Beispiel #10
0
    def test_create_all_pickup_dates_inactive_stores(self):
        self.store.status = StoreStatus.ARCHIVED.value
        self.store.save()

        start_date = self.store.group.timezone.localize(datetime.now().replace(2017, 3, 18, 15, 0, 0, 0))

        PickupDateSeriesFactory(store=self.store, start_date=start_date)

        PickupDate.objects.all().delete()
        PickupDateSeries.objects.update_pickups()
        self.assertEqual(PickupDate.objects.count(), 0)
Beispiel #11
0
    def test_daylight_saving_time_to_winter(self):
        start_date = self.store.group.timezone.localize(datetime.now().replace(2016, 10, 22, 15, 0, 0, 0))

        before_dst_switch = timezone.now().replace(2016, 10, 22, 4, 40, 13)
        with freeze_time(before_dst_switch, tick=True):
            series = PickupDateSeriesFactory(store=self.store, start_date=start_date)

        expected_dates = []
        for month, day in [(10, 22), (10, 29), (11, 5), (11, 12)]:
            expected_dates.append(self.store.group.timezone.localize(datetime(2016, month, day, 15, 0)))
        for actual_date, expected_date in zip(PickupDate.objects.filter(series=series), expected_dates):
            self.assertEqual(actual_date.date, expected_date)
Beispiel #12
0
class PickupDateSeriesReceiverTests(ChannelTestCase):
    def setUp(self):
        self.client = WSClient()
        self.member = UserFactory()
        self.group = GroupFactory(members=[self.member])
        self.store = StoreFactory(group=self.group)

        # Create far in the future to generate no pickup dates
        # They would lead to interfering websocket messages
        self.series = PickupDateSeriesFactory(store=self.store,
                                              start_date=timezone.now() +
                                              relativedelta(months=2))

    def test_receive_series_changes(self):
        self.client.force_login(self.member)
        self.client.send_and_consume('websocket.connect', path='/')

        date = faker.future_datetime(
            end_date='+30d', tzinfo=timezone.utc) + relativedelta(months=2)
        self.series.start_date = date
        self.series.save()

        response = self.client.receive(json=True)
        self.assertEqual(response['topic'], 'pickups:series')
        self.assertEqual(parse(response['payload']['start_date']), date)

        self.assertIsNone(self.client.receive(json=True))

    def test_receive_series_delete(self):
        self.client.force_login(self.member)
        self.client.send_and_consume('websocket.connect', path='/')

        id = self.series.id
        self.series.delete()

        response = self.client.receive(json=True)
        self.assertEqual(response['topic'], 'pickups:series_deleted')
        self.assertEqual(response['payload']['id'], id)

        self.assertIsNone(self.client.receive(json=True))
    def test_delete_stores_as_group_member(self):
        PickupDateSeriesFactory(store=self.store)
        PickupDateFactory(store=self.store)

        self.client.force_login(user=self.member)
        response = self.client.delete(self.store_url)
        self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
        response = self.client.get(self.url)
        self.assertEqual(len(response.data), 0)

        # should also delete pickup dates & series
        response = self.get_results('/api/pickup-dates/')
        self.assertEqual(len(response.data), 0)
        response = self.client.get('/api/pickup-date-series/')
        self.assertEqual(len(response.data), 0)
Beispiel #14
0
class TestPickupdatesAPIFilter(APITestCase, ExtractPaginationMixin):
    def setUp(self):

        self.url = '/api/pickup-dates/'

        # pickup date for group with one member and one store
        self.member = UserFactory()
        self.group = GroupFactory(members=[self.member])
        self.store = StoreFactory(group=self.group)
        self.pickup = PickupDateFactory(store=self.store)

        # and another store + group + pick-update
        self.group2 = GroupFactory(members=[self.member])
        self.store2 = StoreFactory(group=self.group2)
        self.pickup2 = PickupDateFactory(store=self.store2)

        # a pickup date series
        self.series = PickupDateSeriesFactory(store=self.store)
        self.series.update_pickup_dates()

        # another pickup date series
        self.series2 = PickupDateSeriesFactory(store=self.store)
        self.series2.update_pickup_dates()

    def test_filter_by_store(self):
        self.client.force_login(user=self.member)
        response = self.get_results(self.url, {'store': self.store.id})
        self.assertEqual(response.status_code, status.HTTP_200_OK, response.data)
        for _ in response.data:
            self.assertEqual(_['store'], self.store.id)
        self.assertEqual(len(response.data), self.store.pickup_dates.count())

    def test_filter_by_group(self):
        self.client.force_login(user=self.member)
        response = self.get_results(self.url, {'group': self.group.id})
        self.assertEqual(response.status_code, status.HTTP_200_OK, response.data)
        store_ids = [_.id for _ in self.group.store.all()]
        for _ in response.data:
            self.assertTrue(_['store'] in store_ids)
        self.assertEqual(len(response.data), sum([store.pickup_dates.count() for store in self.group.store.all()]))

    def test_filter_by_series(self):
        self.client.force_login(user=self.member)
        response = self.get_results(self.url, {'series': self.series.id})
        self.assertEqual(response.status_code, status.HTTP_200_OK, response.data)
        for _ in response.data:
            self.assertEqual(_['series'], self.series.id)
        self.assertEqual(len(response.data), self.series.pickup_dates.count())

    def test_filter_after_date(self):
        self.client.force_login(user=self.member)
        query_date = self.pickup.date + timedelta(days=1)
        response = self.get_results(self.url, {'date_min': query_date})
        self.assertEqual(response.status_code, status.HTTP_200_OK, response.data)
        for _ in response.data:
            self.assertGreater(parse(_['date']), query_date)
        selected_pickups = PickupDateModel.objects.filter(store__group__members=self.member) \
            .filter(date__gte=query_date)
        self.assertEqual(len(response.data), selected_pickups.count())

    def test_filter_before_date(self):
        self.client.force_login(user=self.member)
        query_date = self.pickup.date + timedelta(days=10)
        response = self.get_results(self.url, {'date_max': query_date})
        self.assertEqual(response.status_code, status.HTTP_200_OK, response.data)
        for _ in response.data:
            self.assertLess(parse(_['date']), query_date)
        selected_pickups = PickupDateModel.objects.filter(store__group__members=self.member) \
            .filter(date__lte=query_date)
        self.assertEqual(len(response.data), selected_pickups.count())
 def setUp(self):
     self.url = '/api/pickup-date-series/'
     self.series = PickupDateSeriesFactory()
     self.series_url = '/api/pickup-date-series/{}/'.format(self.series.id)
     self.non_member = UserFactory()
class TestPickupDateSeriesChangeAPI(APITestCase, ExtractPaginationMixin):
    """
    This is an integration test for the pickup-date-series API with pre-created series
    """
    def setUp(self):
        self.now = timezone.now()
        self.member = UserFactory()
        self.group = GroupFactory(members=[
            self.member,
        ])
        self.store = StoreFactory(group=self.group)
        self.series = PickupDateSeriesFactory(max_collectors=3,
                                              store=self.store)
        self.series.update_pickup_dates(start=lambda: self.now)

    def test_change_max_collectors_for_series(self):
        "should change all future instances (except for individually changed ones), but not past ones"
        url = '/api/pickup-date-series/{}/'.format(self.series.id)
        self.client.force_login(user=self.member)
        response = self.client.patch(url, {'max_collectors': 99})
        self.assertEqual(response.status_code, status.HTTP_200_OK,
                         response.data)
        self.assertEqual(response.data['max_collectors'], 99)

        url = '/api/pickup-dates/'
        response = self.get_results(url, {
            'series': self.series.id,
            'date_0': self.now
        })
        self.assertEqual(response.status_code, status.HTTP_200_OK,
                         response.data)
        for _ in response.data:
            self.assertEqual(_['max_collectors'], 99)

    def test_change_series_activates_group(self):
        self.group.status = GroupStatus.INACTIVE.value
        self.group.save()
        url = '/api/pickup-date-series/{}/'.format(self.series.id)
        self.client.force_login(user=self.member)
        self.client.patch(url, {'max_collectors': 99})
        self.group.refresh_from_db()
        self.assertEqual(self.group.status, GroupStatus.ACTIVE.value)

    def test_change_start_time(self):
        self.client.force_login(user=self.member)
        # get original times
        url = '/api/pickup-dates/'
        response = self.get_results(url, {
            'series': self.series.id,
            'date_0': self.now
        })
        self.assertEqual(response.status_code, status.HTTP_200_OK,
                         response.data)
        original_dates = [parse(_['date']) for _ in response.data]

        # change times
        url = '/api/pickup-date-series/{}/'.format(self.series.id)
        new_startdate = shift_date_in_local_time(
            self.series.start_date, relativedelta(hours=2, minutes=20),
            self.group.timezone)
        response = self.client.patch(url,
                                     {'start_date': new_startdate.isoformat()})
        self.assertEqual(response.status_code, status.HTTP_200_OK,
                         response.data)
        self.assertEqual(parse(response.data['start_date']), new_startdate)

        # compare resulting pickups
        url = '/api/pickup-dates/'
        response = self.get_results(url, {
            'series': self.series.id,
            'date_0': self.now
        })
        self.assertEqual(response.status_code, status.HTTP_200_OK,
                         response.data)
        for response_pickup, old_date in zip(response.data, original_dates):
            self.assertEqual(
                parse(response_pickup['date']),
                shift_date_in_local_time(old_date,
                                         relativedelta(hours=2, minutes=20),
                                         self.group.timezone))

    def test_change_start_date_to_future(self):
        self.client.force_login(user=self.member)
        # get original dates
        url = '/api/pickup-dates/'
        response = self.get_results(url, {
            'series': self.series.id,
            'date_0': self.now
        })
        self.assertEqual(response.status_code, status.HTTP_200_OK,
                         response.data)
        original_dates = [parse(_['date']) for _ in response.data]

        # change dates
        url = '/api/pickup-date-series/{}/'.format(self.series.id)
        new_startdate = shift_date_in_local_time(self.series.start_date,
                                                 relativedelta(days=5),
                                                 self.group.timezone)
        response = self.client.patch(url,
                                     {'start_date': new_startdate.isoformat()})
        self.assertEqual(response.status_code, status.HTTP_200_OK,
                         response.data)
        self.assertEqual(parse(response.data['start_date']), new_startdate)

        # compare resulting pickups
        url = '/api/pickup-dates/'
        response = self.get_results(url, {
            'series': self.series.id,
            'date_0': self.now
        })
        self.assertEqual(response.status_code, status.HTTP_200_OK,
                         response.data)
        for response_pickup, old_date in zip_longest(response.data,
                                                     original_dates):
            self.assertEqual(
                parse(response_pickup['date']),
                shift_date_in_local_time(old_date, relativedelta(days=5),
                                         self.group.timezone))

    def test_change_start_date_to_past(self):
        self.client.force_login(user=self.member)
        # get original dates
        url = '/api/pickup-dates/'
        response = self.get_results(url, {
            'series': self.series.id,
            'date_0': self.now
        })
        self.assertEqual(response.status_code, status.HTTP_200_OK,
                         response.data)
        original_dates = [parse(_['date']) for _ in response.data]

        # change dates
        url = '/api/pickup-date-series/{}/'.format(self.series.id)
        new_startdate = shift_date_in_local_time(self.series.start_date,
                                                 relativedelta(days=-5),
                                                 self.group.timezone)
        response = self.client.patch(url,
                                     {'start_date': new_startdate.isoformat()})
        self.assertEqual(response.status_code, status.HTTP_200_OK,
                         response.data)
        self.assertEqual(parse(response.data['start_date']), new_startdate)

        # compare resulting pickups
        url = '/api/pickup-dates/'
        response = self.get_results(url, {
            'series': self.series.id,
            'date_0': self.now
        })
        self.assertEqual(response.status_code, status.HTTP_200_OK,
                         response.data)

        # shifting 5 days to the past is similar to shifting 2 days to the future
        for response_pickup, old_date in zip_longest(response.data,
                                                     original_dates):
            new_date = shift_date_in_local_time(old_date,
                                                relativedelta(days=2),
                                                self.group.timezone)
            if new_date > self.now + relativedelta(
                    weeks=self.store.weeks_in_advance):
                # date too far in future
                self.assertIsNone(response_pickup)
            else:
                self.assertEqual(parse(response_pickup['date']), new_date)

    def test_set_end_date(self):
        self.client.force_login(user=self.member)
        # change rule
        url = '/api/pickup-date-series/{}/'.format(self.series.id)
        rule = rrulestr(self.series.rule, dtstart=self.now) \
            .replace(until=self.now + relativedelta(days=8))
        response = self.client.patch(url, {'rule': str(rule)})
        self.assertEqual(response.status_code, status.HTTP_200_OK,
                         response.data)
        self.assertEqual(response.data['rule'], str(rule))

        # compare resulting pickups
        url = '/api/pickup-dates/'
        response = self.get_results(url, {
            'series': self.series.id,
            'date_0': self.now
        })
        self.assertEqual(response.status_code, status.HTTP_200_OK,
                         response.data)
        self.assertEqual(len(response.data), 2, response.data)

    def test_set_end_date_with_users_have_joined_pickup(self):
        self.client.force_login(user=self.member)
        self.series.pickup_dates.last().collectors.add(self.member)
        # change rule
        url = '/api/pickup-date-series/{}/'.format(self.series.id)
        rule = rrulestr(self.series.rule, dtstart=self.now) \
            .replace(until=self.now)
        response = self.client.patch(url, {'rule': str(rule)})
        self.assertEqual(response.status_code, status.HTTP_200_OK,
                         response.data)
        self.assertEqual(response.data['rule'], str(rule))

        # compare resulting pickups
        url = '/api/pickup-dates/'
        response = self.get_results(url, {
            'series': self.series.id,
            'date_0': self.now
        })
        self.assertEqual(response.status_code, status.HTTP_200_OK,
                         response.data)
        self.assertEqual(len(response.data), 1, response.data)

    def test_delete_pickup_series(self):
        "the series should get removed, as well as all upcoming pickups if they don't have collectors"
        self.client.force_login(user=self.member)
        joined_pickup = self.series.pickup_dates.last()
        joined_pickup.collectors.add(self.member)

        url = '/api/pickup-date-series/{}/'.format(self.series.id)
        response = self.client.delete(url)
        self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT,
                         response.data)

        url = '/api/pickup-dates/'
        response = self.get_results(url, {
            'series': self.series.id,
            'date_0': self.now
        })
        self.assertEqual(response.status_code, status.HTTP_200_OK,
                         response.data)
        self.assertEqual(len(response.data), 0, response.data)

        url = '/api/pickup-dates/{}/'.format(joined_pickup.id)
        response = self.client.get(url)
        self.assertEqual(response.status_code, status.HTTP_200_OK,
                         response.data)
        self.assertEqual(response.data['collector_ids'], [
            self.member.id,
        ])

    def test_change_max_collectors_to_invalid_number_fails(self):
        self.client.force_login(user=self.member)
        url = '/api/pickup-date-series/{}/'.format(self.series.id)
        response = self.client.patch(url, {'max_collectors': -1})
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST,
                         response.data)

    def test_set_invalid_store_fails(self):
        unrelated_store = StoreFactory()

        self.client.force_login(user=self.member)
        url = '/api/pickup-date-series/{}/'.format(self.series.id)
        response = self.client.patch(url, {'store': unrelated_store.id})
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST,
                         response.data)
        self.assertEqual(
            response.data,
            {'store': ["You are not member of the store's group."]})

    def test_set_multiple_rules_fails(self):
        self.client.force_login(user=self.member)
        url = '/api/pickup-date-series/{}/'.format(self.series.id)
        response = self.client.patch(
            url, {'rule': 'RRULE:FREQ=WEEKLY;BYDAY=MO\nRRULE:FREQ=MONTHLY'})
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST,
                         response.data)
        self.assertEqual(
            response.data,
            {'rule': ['Only single recurrence rules are allowed.']})

    def test_keep_changes_to_max_collectors(self):
        self.client.force_login(user=self.member)
        pickup_under_test = self.series.pickup_dates.first()
        url = '/api/pickup-dates/{}/'.format(pickup_under_test.id)

        # change setting of pickup
        response = self.client.patch(url, {'max_collectors': 666})
        self.assertEqual(response.status_code, status.HTTP_200_OK,
                         response.data)
        self.assertEqual(response.data['max_collectors'], 666)

        # run regular update command of series
        self.series.update_pickup_dates()

        # check if changes persist
        url = '/api/pickup-dates/{}/'.format(pickup_under_test.id)
        response = self.client.get(url)
        self.assertEqual(response.status_code, status.HTTP_200_OK,
                         response.data)
        self.assertEqual(response.data['max_collectors'], 666)

    def test_keep_changes_to_date(self):
        self.client.force_login(user=self.member)
        pickup_under_test = self.series.pickup_dates.first()
        url = '/api/pickup-dates/{}/'.format(pickup_under_test.id)

        # change setting of pickup
        target_date = timezone.now() + relativedelta(hours=2)
        response = self.client.patch(url, {'date': target_date})
        self.assertEqual(response.status_code, status.HTTP_200_OK,
                         response.data)
        self.assertEqual(parse(response.data['date']), target_date)

        # run regular update command of series
        self.series.update_pickup_dates()

        # check if changes persist
        url = '/api/pickup-dates/{}/'.format(pickup_under_test.id)
        response = self.client.get(url)
        self.assertEqual(response.status_code, status.HTTP_200_OK,
                         response.data)
        self.assertEqual(parse(response.data['date']), target_date)

    def test_keep_changes_to_description(self):
        self.client.force_login(user=self.member)
        pickup_under_test = self.series.pickup_dates.first()
        url = '/api/pickup-dates/{}/'.format(pickup_under_test.id)

        # change setting of pickup
        response = self.client.patch(url, {'description': 'asdf'})
        self.assertEqual(response.status_code, status.HTTP_200_OK,
                         response.data)
        self.assertEqual(response.data['description'], 'asdf')

        # run regular update command of series
        self.series.update_pickup_dates()

        # check if changes persist
        url = '/api/pickup-dates/{}/'.format(pickup_under_test.id)
        response = self.client.get(url)
        self.assertEqual(response.status_code, status.HTTP_200_OK,
                         response.data)
        self.assertEqual(response.data['description'], 'asdf')

    def test_dont_mark_as_changed_if_data_is_equal(self):
        self.client.force_login(user=self.member)
        pickup_under_test = self.series.pickup_dates.first()
        url = '/api/pickup-dates/{}/'.format(pickup_under_test.id)

        # change setting of pickup
        response = self.client.patch(
            url, {
                'date': pickup_under_test.date,
                'max_collectors': pickup_under_test.max_collectors
            })
        self.assertEqual(response.status_code, status.HTTP_200_OK,
                         response.data)

        pickup_under_test = PickupDate.objects.get(id=pickup_under_test.id)

        self.assertFalse(pickup_under_test.is_max_collectors_changed)
        self.assertFalse(pickup_under_test.is_date_changed)

    def test_keep_date_if_pickup_has_collectors(self):
        """
        https://github.com/yunity/foodsaving-frontend/issues/596
        It's unexpected if the date changes automatically when people have joined
        """
        self.client.force_login(user=self.member)
        pickup_under_test = self.series.pickup_dates.first()
        url = '/api/pickup-dates/{}/add/'.format(pickup_under_test.id)

        # join pickup
        response = self.client.post(url)
        self.assertEqual(response.status_code, status.HTTP_200_OK,
                         response.data)
        original_date = pickup_under_test.date

        # change series date
        url = '/api/pickup-date-series/{}/'.format(self.series.id)
        response = self.client.patch(
            url,
            {'start_date': self.series.start_date + relativedelta(hours=1)})
        self.assertEqual(response.status_code, status.HTTP_200_OK,
                         response.data)

        # check if time of pickup is the same
        url = '/api/pickup-dates/{}/'.format(pickup_under_test.id)
        response = self.client.get(url)
        self.assertEqual(response.status_code, status.HTTP_200_OK,
                         response.data)
        self.assertEqual(parse(response.data['date']), original_date,
                         "time shouldn't change!")

    def test_invalid_rule_fails(self):
        url = '/api/pickup-date-series/{}/'.format(self.series.id)
        self.client.force_login(user=self.member)
        response = self.client.patch(url, {'rule': 'FREQ=WEEKLY;BYDAY='})
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST,
                         response.data)
Beispiel #17
0
 def setUp(self):
     self.series = PickupDateSeriesFactory()
class TestPickupDateSeriesChangeAPI(APITestCase, ExtractPaginationMixin):
    """
    This is an integration test for the pickup-date-series API with pre-created series
    """

    def setUp(self):
        self.now = timezone.now()
        self.member = UserFactory()
        self.group = GroupFactory(members=[self.member])
        self.store = StoreFactory(group=self.group)
        self.series = PickupDateSeriesFactory(max_collectors=3, store=self.store)

    def test_change_max_collectors_for_series(self):
        "should change all future instances (except for individually changed ones), but not past ones"
        url = '/api/pickup-date-series/{}/'.format(self.series.id)
        self.client.force_login(user=self.member)
        response = self.client.patch(url, {'max_collectors': 99})
        self.assertEqual(response.status_code, status.HTTP_200_OK, response.data)
        self.assertEqual(response.data['max_collectors'], 99)

        url = '/api/pickup-dates/'
        response = self.get_results(url, {'series': self.series.id, 'date_min': self.now})
        self.assertEqual(response.status_code, status.HTTP_200_OK, response.data)
        for _ in response.data:
            self.assertEqual(_['max_collectors'], 99)

    def test_change_series_activates_group(self):
        self.group.status = GroupStatus.INACTIVE.value
        self.group.save()
        url = '/api/pickup-date-series/{}/'.format(self.series.id)
        self.client.force_login(user=self.member)
        self.client.patch(url, {'max_collectors': 99})
        self.group.refresh_from_db()
        self.assertEqual(self.group.status, GroupStatus.ACTIVE.value)

    def test_change_start_time(self):
        self.client.force_login(user=self.member)
        # get original times
        url = '/api/pickup-dates/'
        response = self.get_results(url, {'series': self.series.id, 'date_min': self.now})
        self.assertEqual(response.status_code, status.HTTP_200_OK, response.data)
        original_dates = [parse(_['date']) for _ in response.data]

        # change times
        url = '/api/pickup-date-series/{}/'.format(self.series.id)
        new_startdate = shift_date_in_local_time(
            self.series.start_date, relativedelta(hours=2, minutes=20), self.group.timezone
        )
        response = self.client.patch(url, {'start_date': new_startdate.isoformat()})
        self.assertEqual(response.status_code, status.HTTP_200_OK, response.data)
        self.assertEqual(parse(response.data['start_date']), new_startdate)

        # compare resulting pickups
        url = '/api/pickup-dates/'
        response = self.get_results(url, {'series': self.series.id, 'date_min': self.now})
        self.assertEqual(response.status_code, status.HTTP_200_OK, response.data)
        for response_pickup, old_date in zip(response.data, original_dates):
            self.assertEqual(
                parse(response_pickup['date']),
                shift_date_in_local_time(old_date, relativedelta(hours=2, minutes=20), self.group.timezone)
            )

    def test_change_start_date_to_future(self):
        self.client.force_login(user=self.member)
        # get original dates
        url = '/api/pickup-dates/'
        response = self.get_results(url, {'series': self.series.id, 'date_min': self.now})
        self.assertEqual(response.status_code, status.HTTP_200_OK, response.data)
        original_dates = [parse(_['date']) for _ in response.data]

        # change dates
        url = '/api/pickup-date-series/{}/'.format(self.series.id)
        new_startdate = shift_date_in_local_time(self.series.start_date, relativedelta(days=5), self.group.timezone)
        response = self.client.patch(url, {'start_date': new_startdate.isoformat()})
        self.assertEqual(response.status_code, status.HTTP_200_OK, response.data)
        self.assertEqual(parse(response.data['start_date']), new_startdate)

        # compare resulting pickups
        url = '/api/pickup-dates/'
        response = self.get_results(url, {'series': self.series.id, 'date_min': self.now})
        self.assertEqual(response.status_code, status.HTTP_200_OK, response.data)
        for response_pickup, old_date in zip_longest(response.data, original_dates):
            self.assertEqual(
                parse(response_pickup['date']),
                shift_date_in_local_time(old_date, relativedelta(days=5), self.group.timezone)
            )

    def test_change_start_date_to_past(self):
        self.client.force_login(user=self.member)
        # get original dates
        url = '/api/pickup-dates/'
        response = self.get_results(url, {'series': self.series.id, 'date_min': self.now})
        self.assertEqual(response.status_code, status.HTTP_200_OK, response.data)
        original_dates = [parse(_['date']) for _ in response.data]

        # change dates
        url = '/api/pickup-date-series/{}/'.format(self.series.id)
        new_startdate = shift_date_in_local_time(self.series.start_date, relativedelta(days=-5), self.group.timezone)
        response = self.client.patch(url, {'start_date': new_startdate.isoformat()})
        self.assertEqual(response.status_code, status.HTTP_200_OK, response.data)
        self.assertEqual(parse(response.data['start_date']), new_startdate)

        # compare resulting pickups
        url = '/api/pickup-dates/'
        response = self.get_results(url, {'series': self.series.id, 'date_min': self.now})
        self.assertEqual(response.status_code, status.HTTP_200_OK, response.data)

        # shifting 5 days to the past is similar to shifting 2 days to the future
        for response_pickup, old_date in zip_longest(response.data, original_dates):
            new_date = shift_date_in_local_time(old_date, relativedelta(days=2), self.group.timezone)
            if new_date > self.now + relativedelta(weeks=self.store.weeks_in_advance):
                # date too far in future
                self.assertIsNone(response_pickup)
            else:
                self.assertEqual(parse(response_pickup['date']), new_date)

    def test_set_end_date(self):
        self.client.force_login(user=self.member)
        # change rule
        url = '/api/pickup-date-series/{}/'.format(self.series.id)
        rule = rrulestr(self.series.rule, dtstart=self.now) \
            .replace(until=self.now + relativedelta(days=8))
        response = self.client.patch(url, {'rule': str(rule)})
        self.assertEqual(response.status_code, status.HTTP_200_OK, response.data)
        self.assertEqual(response.data['rule'], str(rule))

        # compare resulting pickups
        url = '/api/pickup-dates/'
        response = self.get_results(url, {'series': self.series.id, 'date_min': self.now})
        self.assertEqual(response.status_code, status.HTTP_200_OK, response.data)
        self.assertEqual(len(response.data), 2, response.data)

    def test_set_end_date_with_users_have_joined_pickup(self):
        self.client.force_login(user=self.member)
        self.series.pickup_dates.last().add_collector(self.member)
        # change rule
        url = '/api/pickup-date-series/{}/'.format(self.series.id)
        rule = rrulestr(self.series.rule, dtstart=self.now) \
            .replace(until=self.now)
        response = self.client.patch(url, {
            'rule': str(rule),
        })
        self.assertEqual(response.status_code, status.HTTP_200_OK, response.data)
        self.assertEqual(response.data['rule'], str(rule))

        # compare resulting pickups
        url = '/api/pickup-dates/'
        response = self.get_results(url, {'series': self.series.id, 'date_min': self.now})
        self.assertEqual(response.status_code, status.HTTP_200_OK, response.data)
        self.assertEqual(len(response.data), 1, response.data)

    def test_disable_pickup_series(self):
        "the series should get removed, empty upcoming pickups disabled, non-empty pickups kept"
        self.client.force_login(user=self.member)
        joined_pickup = self.series.pickup_dates.last()
        joined_pickup.add_collector(self.member)

        url = '/api/pickup-date-series/{}/'.format(self.series.id)
        response = self.client.delete(url)
        self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT, response.data)

        url = '/api/pickup-dates/'
        response = self.get_results(url, {'date_min': self.now})
        self.assertEqual(response.status_code, status.HTTP_200_OK, response.data)
        empty_pickups = [p for p in response.data if len(p['collector_ids']) == 0]
        self.assertEqual(empty_pickups, [])

        url = '/api/pickup-dates/{}/'.format(joined_pickup.id)
        response = self.client.get(url)
        self.assertEqual(response.status_code, status.HTTP_200_OK, response.data)
        self.assertEqual(response.data['collector_ids'], [self.member.id])
        self.assertFalse(response.data['is_disabled'])

    def test_change_max_collectors_to_invalid_number_fails(self):
        self.client.force_login(user=self.member)
        url = '/api/pickup-date-series/{}/'.format(self.series.id)
        response = self.client.patch(url, {'max_collectors': -1})
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST, response.data)

    def test_set_invalid_store_fails(self):
        original_store = self.series.store
        unrelated_store = StoreFactory()

        self.client.force_login(user=self.member)
        url = '/api/pickup-date-series/{}/'.format(self.series.id)
        response = self.client.patch(url, {'store': unrelated_store.id})
        self.assertEqual(response.status_code, status.HTTP_200_OK, response.data)
        self.assertEqual(response.data['store'], original_store.id)
        self.series.refresh_from_db()
        self.assertEqual(self.series.store.id, original_store.id)

    def test_set_multiple_rules_fails(self):
        self.client.force_login(user=self.member)
        url = '/api/pickup-date-series/{}/'.format(self.series.id)
        response = self.client.patch(url, {'rule': 'RRULE:FREQ=WEEKLY;BYDAY=MO\nRRULE:FREQ=MONTHLY'})
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST, response.data)
        self.assertEqual(response.data, {'rule': ['Only single recurrence rules are allowed.']})

    def test_keep_changes_to_max_collectors(self):
        self.client.force_login(user=self.member)
        pickup_under_test = self.series.pickup_dates.first()
        url = '/api/pickup-dates/{}/'.format(pickup_under_test.id)

        # change setting of pickup
        response = self.client.patch(url, {'max_collectors': 666})
        self.assertEqual(response.status_code, status.HTTP_200_OK, response.data)
        self.assertEqual(response.data['max_collectors'], 666)

        # run regular update command of series
        self.series.update_pickups()

        # check if changes persist
        url = '/api/pickup-dates/{}/'.format(pickup_under_test.id)
        response = self.client.get(url)
        self.assertEqual(response.status_code, status.HTTP_200_OK, response.data)
        self.assertEqual(response.data['max_collectors'], 666)

        # modify series max_collectors
        series_url = '/api/pickup-date-series/{}/'.format(self.series.id)
        response = self.client.patch(series_url, {'max_collectors': 20})
        self.assertEqual(response.status_code, status.HTTP_200_OK, response.data)

        # check if changes persist
        url = '/api/pickup-dates/{}/'.format(pickup_under_test.id)
        response = self.client.get(url)
        self.assertEqual(response.status_code, status.HTTP_200_OK, response.data)
        self.assertEqual(response.data['max_collectors'], 666)

    def test_keep_changes_to_description(self):
        self.client.force_login(user=self.member)
        pickup_under_test = self.series.pickup_dates.first()
        url = '/api/pickup-dates/{}/'.format(pickup_under_test.id)

        # change setting of pickup
        response = self.client.patch(url, {'description': 'asdf'})
        self.assertEqual(response.status_code, status.HTTP_200_OK, response.data)
        self.assertEqual(response.data['description'], 'asdf')

        # run regular update command of series
        self.series.update_pickups()

        # check if changes persist
        url = '/api/pickup-dates/{}/'.format(pickup_under_test.id)
        response = self.client.get(url)
        self.assertEqual(response.status_code, status.HTTP_200_OK, response.data)
        self.assertEqual(response.data['description'], 'asdf')

        # modify series description
        series_url = '/api/pickup-date-series/{}/'.format(self.series.id)
        response = self.client.patch(series_url, {'description': 'new series description'})
        self.assertEqual(response.status_code, status.HTTP_200_OK, response.data)

        # check if changes persist
        url = '/api/pickup-dates/{}/'.format(pickup_under_test.id)
        response = self.client.get(url)
        self.assertEqual(response.status_code, status.HTTP_200_OK, response.data)
        self.assertEqual(response.data['description'], 'asdf')

    def test_invalid_rule_fails(self):
        url = '/api/pickup-date-series/{}/'.format(self.series.id)
        self.client.force_login(user=self.member)
        response = self.client.patch(url, {'rule': 'FREQ=WEEKLY;BYDAY='})
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST, response.data)

    def test_keeps_joined_pickups(self):
        # join pickups
        [p.add_collector(self.member) for p in self.series.pickup_dates.all()]

        # change series rule to add another day
        recurrence = rrule.rrule(
            freq=rrule.WEEKLY,
            byweekday=[
                self.now.weekday(),
                (self.now + relativedelta(days=1)).weekday(),
            ],
        )
        series_url = '/api/pickup-date-series/{}/'.format(self.series.id)
        self.client.force_login(user=self.member)
        response = self.client.patch(series_url, {
            'rule': str(recurrence),
        })
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.series.refresh_from_db()

        response = self.client.get('/api/pickup-dates/?series={}'.format(self.series.id))
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual([parse(p['date']) for p in response.data['results']], [
            shift_date_in_local_time(self.series.start_date, delta, self.group.timezone) for delta in (
                relativedelta(days=0),
                relativedelta(days=1),
                relativedelta(days=7),
                relativedelta(days=8),
                relativedelta(days=14),
                relativedelta(days=15),
                relativedelta(days=21),
                relativedelta(days=22),
            )
        ])
        self.assertEqual(
            [p['collector_ids'] for p in response.data['results']],
            list(interleave(
                [[self.member.id] for _ in range(4)],
                [[] for _ in range(4)],
            )),
        )

    def test_removes_empty_leftover_pickups_when_reducing_weeks_in_advance(self):
        # join one pickup
        joined_pickup = self.series.pickup_dates.first()
        joined_pickup.add_collector(self.member)

        # change weeks_in_advance
        store_url = '/api/stores/{}/'.format(self.store.id)
        self.client.force_login(user=self.member)
        response = self.client.patch(store_url, {
            'weeks_in_advance': 1,
        })
        self.assertEqual(response.status_code, status.HTTP_200_OK)

        response = self.get_results('/api/pickup-dates/?series={}'.format(self.series.id))
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(len(response.data), 1)
        self.assertEqual(response.data[0]['id'], joined_pickup.id)
        self.assertEqual(response.data[0]['collector_ids'], [self.member.id])

    def test_cannot_move_pickups_in_a_series(self):
        self.client.force_login(user=self.member)
        pickup = self.series.pickup_dates.last()

        response = self.client.patch(
            '/api/pickup-dates/{}/'.format(pickup.id), {'date': pickup.date + relativedelta(weeks=7)}
        )

        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
        self.assertIn('You can\'t move pickups', response.data['date'][0])