def test_groups_marked_inactive(self): recent_treshold = timezone.now() - timedelta( days=settings.NUMBER_OF_DAYS_UNTIL_GROUP_INACTIVE) group_without_recent_activity = GroupFactory( last_active_at=recent_treshold - timedelta(days=3)) group_with_recent_activity = GroupFactory( last_active_at=recent_treshold + timedelta(days=3)) mark_inactive_groups() group_without_recent_activity.refresh_from_db() group_with_recent_activity.refresh_from_db() self.assertEqual(group_without_recent_activity.status, GroupStatus.INACTIVE.value) self.assertEqual(group_with_recent_activity.status, GroupStatus.ACTIVE.value)
class TestWallMessagesUpdateStatus(APITestCase): def setUp(self): self.user = UserFactory() self.group = GroupFactory(members=[self.user]) self.conversation = Conversation.objects.get_or_create_for_target( self.group) self.conversation.join(self.user) def test_wall_message_activates_inactive_group(self): self.group.status = GroupStatus.INACTIVE.value self.group.save() self.client.force_login(user=self.user) data = { 'conversation': self.conversation.id, 'content': 'a nice message' } response = self.client.post('/api/messages/', data, format='json') self.assertEqual(response.status_code, status.HTTP_201_CREATED, response.data) self.assertEqual(response.data['content'], data['content']) self.group.refresh_from_db() self.assertEqual(self.group.status, GroupStatus.ACTIVE.value)
class TestActivitySeriesCreationAPI(APITestCase, ExtractPaginationMixin): """ This is an integration test for the activity-series API """ def setUp(self): self.maxDiff = None self.member = UserFactory() self.group = GroupFactory(members=[self.member]) self.place = PlaceFactory(group=self.group) self.activity_type = ActivityTypeFactory(group=self.group) self.archived_activity_type = ActivityTypeFactory(group=self.group, status='archived') def test_create_and_get_recurring_series(self): self.maxDiff = None url = '/api/activity-series/' recurrence = rrule.rrule( freq=rrule.WEEKLY, byweekday=[0, 1] # Monday and Tuesday ) start_date = self.group.timezone.localize(datetime.now().replace(hour=20, minute=0)) activity_series_data = { 'activity_type': self.activity_type.id, 'max_participants': 5, 'place': self.place.id, 'rule': str(recurrence), 'start_date': start_date } start_date = start_date.replace(second=0, microsecond=0) self.client.force_login(user=self.member) response = self.client.post(url, activity_series_data, format='json') self.assertEqual(response.status_code, status.HTTP_201_CREATED, response.data) series_id = response.data['id'] self.assertEqual(parse(response.data['start_date']), start_date) del response.data['id'] del response.data['start_date'] del response.data['dates_preview'] expected_series_data = { 'activity_type': self.activity_type.id, 'max_participants': 5, 'place': self.place.id, 'rule': str(recurrence), 'description': '', 'duration': None, } self.assertEqual(response.data, expected_series_data) response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) for _ in response.data: self.assertEqual(parse(_['start_date']), start_date) del _['id'] del _['start_date'] del _['dates_preview'] self.assertEqual(response.data, [expected_series_data]) response = self.client.get(url + str(series_id) + '/') self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(parse(response.data['start_date']), start_date) del response.data['id'] del response.data['start_date'] del response.data['dates_preview'] self.assertEqual(response.data, expected_series_data) url = '/api/activities/' created_activities = [] # do recurrence calculation in local time to avoid daylight saving time problems tz = self.group.timezone dates_list = recurrence.replace( dtstart=timezone.now().astimezone(tz).replace(hour=20, minute=0, second=0, microsecond=0, tzinfo=None) ).between( timezone.now().astimezone(tz).replace(tzinfo=None), timezone.now().astimezone(tz).replace(tzinfo=None) + relativedelta(weeks=4) ) dates_list = [tz.localize(d) for d in dates_list] response = self.get_results(url) self.assertEqual(response.status_code, status.HTTP_200_OK) # verify date field for response_data_item, expected_date in zip(response.data, dates_list): self.assertEqual(parse(response_data_item['date'][0]), expected_date, response_data_item['date']) # verify non-date fields, don't need parsing for _ in response.data: del _['id'] del _['date'] del _['feedback_due'] for _ in dates_list: created_activities.append({ 'activity_type': self.activity_type.id, 'max_participants': 5, 'series': series_id, 'participants': [], 'place': self.place.id, 'description': '', 'feedback_given_by': [], 'feedback_dismissed_by': [], 'is_disabled': False, 'has_duration': False, 'is_done': False, }) self.assertEqual(response.data, created_activities, response.data) def test_activity_series_create_activates_group(self): url = '/api/activity-series/' recurrence = rrule.rrule( freq=rrule.WEEKLY, byweekday=[0, 1] # Monday and Tuesday ) start_date = self.group.timezone.localize(datetime.now().replace(hour=20, minute=0)) activity_series_data = { 'activity_type': self.activity_type.id, 'max_participants': 5, 'place': self.place.id, 'rule': str(recurrence), 'start_date': start_date } self.group.status = GroupStatus.INACTIVE.value self.group.save() self.client.force_login(user=self.member) self.client.post(url, activity_series_data, format='json') self.group.refresh_from_db() self.assertEqual(self.group.status, GroupStatus.ACTIVE.value) def test_create_series_for_archived_type_fails(self): url = '/api/activity-series/' recurrence = rrule.rrule( freq=rrule.WEEKLY, byweekday=[0, 1] # Monday and Tuesday ) start_date = self.group.timezone.localize(datetime.now().replace(hour=20, minute=0)) self.client.force_login(user=self.member) response = self.client.post( url, { 'activity_type': self.archived_activity_type.id, 'max_participants': 5, 'place': self.place.id, 'rule': str(recurrence), 'start_date': start_date }, format='json' ) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST, response.data)
class TestActivitySeriesChangeAPI(APITestCase, ExtractPaginationMixin): """ This is an integration test for the activity-series API with pre-created series """ def setUp(self): self.now = timezone.now() self.member = UserFactory() self.group = GroupFactory(members=[self.member]) self.place = PlaceFactory(group=self.group) self.series = ActivitySeriesFactory(max_participants=3, place=self.place) def test_change_max_participants_for_series(self): "should change all future instances (except for individually changed ones), but not past ones" url = '/api/activity-series/{}/'.format(self.series.id) self.client.force_login(user=self.member) response = self.client.patch(url, {'max_participants': 99}) self.assertEqual(response.status_code, status.HTTP_200_OK, response.data) self.assertEqual(response.data['max_participants'], 99) url = '/api/activities/' 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_participants'], 99) def test_change_series_activates_group(self): self.group.status = GroupStatus.INACTIVE.value self.group.save() url = '/api/activity-series/{}/'.format(self.series.id) self.client.force_login(user=self.member) self.client.patch(url, {'max_participants': 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/activities/' 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'][0]) for _ in response.data] # change times url = '/api/activity-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 activities url = '/api/activities/' 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_activity, old_date in zip(response.data, original_dates): self.assertEqual( parse(response_activity['date'][0]), 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/activities/' 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'][0]) for _ in response.data] # change dates url = '/api/activity-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 activities url = '/api/activities/' 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_activity, old_date in zip_longest(response.data, original_dates): self.assertEqual( parse(response_activity['date'][0]), 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/activities/' 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'][0]) for _ in response.data] # change dates url = '/api/activity-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 activities url = '/api/activities/' 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_activity, 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.place.weeks_in_advance): # date too far in future self.assertIsNone(response_activity) else: self.assertEqual(parse(response_activity['date'][0]), new_date) def test_set_end_date(self): self.client.force_login(user=self.member) # change rule url = '/api/activity-series/{}/'.format(self.series.id) rule = 'FREQ=WEEKLY;UNTIL={}'.format((self.now + relativedelta(days=8)).strftime('%Y%m%dT%H%M%S')) response = self.client.patch(url, {'rule': rule}) self.assertEqual(response.status_code, status.HTTP_200_OK, response.data) self.assertEqual(response.data['rule'], rule) # compare resulting activities url = '/api/activities/' 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_timezone(self): self.client.force_login(user=self.member) url = '/api/activity-series/{}/'.format(self.series.id) rule = 'FREQ=WEEKLY;UNTIL={}+0100'.format((self.now + relativedelta(days=8)).strftime('%Y%m%dT%H%M%S')) response = self.client.patch(url, {'rule': rule}) self.assertEqual(response.status_code, status.HTTP_200_OK, response.data) def test_set_end_date_with_users_have_joined_activity(self): self.client.force_login(user=self.member) self.series.activities.last().add_participant(self.member) # change rule url = '/api/activity-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 activities url = '/api/activities/' 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_activity_series(self): "the series should get removed, empty upcoming activities disabled, non-empty activities kept" self.client.force_login(user=self.member) joined_activity = self.series.activities.last() joined_activity.add_participant(self.member) url = '/api/activity-series/{}/'.format(self.series.id) response = self.client.delete(url) self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT, response.data) url = '/api/activities/' response = self.get_results(url, {'date_min': self.now}) self.assertEqual(response.status_code, status.HTTP_200_OK, response.data) empty_activities = [p for p in response.data if len(p['participants']) == 0] self.assertEqual(empty_activities, []) url = '/api/activities/{}/'.format(joined_activity.id) response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK, response.data) self.assertEqual(response.data['participants'], [self.member.id]) self.assertFalse(response.data['is_disabled']) def test_change_max_participants_to_invalid_number_fails(self): self.client.force_login(user=self.member) url = '/api/activity-series/{}/'.format(self.series.id) response = self.client.patch(url, {'max_participants': -1}) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST, response.data) def test_set_invalid_place_fails(self): original_place = self.series.place unrelated_place = PlaceFactory() self.client.force_login(user=self.member) url = '/api/activity-series/{}/'.format(self.series.id) response = self.client.patch(url, {'place': unrelated_place.id}) self.assertEqual(response.status_code, status.HTTP_200_OK, response.data) self.assertEqual(response.data['place'], original_place.id) self.series.refresh_from_db() self.assertEqual(self.series.place.id, original_place.id) def test_set_multiple_rules_fails(self): self.client.force_login(user=self.member) url = '/api/activity-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_participants(self): self.client.force_login(user=self.member) activity_under_test = self.series.activities.first() url = '/api/activities/{}/'.format(activity_under_test.id) # change setting of activity response = self.client.patch(url, {'max_participants': 666}) self.assertEqual(response.status_code, status.HTTP_200_OK, response.data) self.assertEqual(response.data['max_participants'], 666) # run regular update command of series self.series.update_activities() # check if changes persist url = '/api/activities/{}/'.format(activity_under_test.id) response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK, response.data) self.assertEqual(response.data['max_participants'], 666) # modify series max_participants series_url = '/api/activity-series/{}/'.format(self.series.id) response = self.client.patch(series_url, {'max_participants': 20}) self.assertEqual(response.status_code, status.HTTP_200_OK, response.data) # check if changes persist url = '/api/activities/{}/'.format(activity_under_test.id) response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK, response.data) self.assertEqual(response.data['max_participants'], 666) def test_keep_changes_to_description(self): self.client.force_login(user=self.member) activity_under_test = self.series.activities.first() url = '/api/activities/{}/'.format(activity_under_test.id) # change setting of activity 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_activities() # check if changes persist url = '/api/activities/{}/'.format(activity_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/activity-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/activities/{}/'.format(activity_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/activity-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_activities(self): # join activities [p.add_participant(self.member) for p in self.series.activities.all()] # change series rule to add another day today = self.now.astimezone(self.group.timezone).weekday() tomorrow = shift_date_in_local_time(self.now, relativedelta(days=1), self.group.timezone).astimezone(self.group.timezone).weekday() recurrence = rrule.rrule( freq=rrule.WEEKLY, byweekday=[ today, tomorrow, ], ) series_url = '/api/activity-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/activities/?series={}'.format(self.series.id)) self.assertEqual(response.status_code, status.HTTP_200_OK) # self.assertEqual([parse(p['date'][0]) 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['participants'] for p in response.data['results']], list(interleave( [[self.member.id] for _ in range(4)], [[] for _ in range(4)], )), ) def test_removes_empty_leftover_activities_when_reducing_weeks_in_advance(self): # join one activity joined_activity = self.series.activities.first() joined_activity.add_participant(self.member) # change weeks_in_advance place_url = '/api/places/{}/'.format(self.place.id) self.client.force_login(user=self.member) response = self.client.patch(place_url, { 'weeks_in_advance': 1, }) self.assertEqual(response.status_code, status.HTTP_200_OK) response = self.get_results('/api/activities/?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_activity.id) self.assertEqual(response.data[0]['participants'], [self.member.id]) def test_cannot_move_activities_in_a_series(self): self.client.force_login(user=self.member) activity = self.series.activities.last() response = self.client.patch( '/api/activities/{}/'.format(activity.id), { 'date': (activity.date + relativedelta(weeks=7)).as_list(), }, format='json', ) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertIn('You can\'t move activities', response.data['date'][0]) def test_cannot_change_activity_has_duration_in_a_series(self): self.client.force_login(user=self.member) activity = self.series.activities.last() response = self.client.patch( '/api/activities/{}/'.format(activity.id), {'has_duration': True}, format='json', ) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertEqual( 'You cannot modify the duration of activities that are part of a series', response.data['has_duration'][0] )
class TestPlacesAPI(APITestCase, ExtractPaginationMixin): def setUp(self): self.url = '/api/places/' # group with two members and one place self.member = UserFactory() self.member2 = UserFactory() self.group = GroupFactory(members=[self.member, self.member2]) self.place = PlaceFactory(group=self.group) self.place_url = self.url + str(self.place.id) + '/' # not a member self.user = UserFactory() # another place for above group self.place_data = { 'name': faker.name(), 'description': faker.name(), 'group': self.group.id, 'address': faker.address(), 'latitude': faker.latitude(), 'longitude': faker.longitude() } # another group self.different_group = GroupFactory(members=[self.member2]) def test_create_place(self): response = self.client.post(self.url, self.place_data, format='json') self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) def test_create_place_as_user(self): self.client.force_login(user=self.user) response = self.client.post(self.url, self.place_data, format='json') self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) def test_create_place_as_group_member(self): self.client.force_login(user=self.member) response = self.client.post(self.url, self.place_data, format='json') self.assertEqual(response.status_code, status.HTTP_201_CREATED) self.assertEqual(response.data['name'], self.place_data['name']) def test_create_place_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.place_data, format='json') self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) def test_create_place_activates_group(self): self.group.status = GroupStatus.INACTIVE.value self.group.save() self.client.force_login(user=self.member) self.client.post(self.url, self.place_data, format='json') self.group.refresh_from_db() self.assertEqual(self.group.status, GroupStatus.ACTIVE.value) def test_create_place_with_short_name_fails(self): self.client.force_login(user=self.member) data = deepcopy(self.place_data) data['name'] = 's' response = self.client.post(self.url, data, format='json') self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_list_places(self): response = self.client.get(self.url) self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) def test_list_places_as_user(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), 0) def test_list_places_as_group_member(self): self.client.force_login(user=self.member) response = self.client.get(self.url) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(response.data), 1) def test_retrieve_places(self): response = self.client.get(self.place_url) self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) def test_retrieve_places_as_user(self): self.client.force_login(user=self.user) response = self.client.get(self.place_url) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) def test_retrieve_places_as_group_member(self): self.client.force_login(user=self.member) response = self.client.get(self.place_url) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_patch_place(self): response = self.client.patch(self.place_url, self.place_data, format='json') self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) def test_patch_place_as_user(self): self.client.force_login(user=self.user) response = self.client.patch(self.place_url, self.place_data, format='json') self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) def test_patch_place_as_group_member(self): self.client.force_login(user=self.member) response = self.client.patch(self.place_url, self.place_data, format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) def test_edit_place_as_newcomer_fails(self): newcomer = UserFactory() self.group.groupmembership_set.create(user=newcomer) self.client.force_login(user=newcomer) response = self.client.patch(self.place_url, self.place_data, format='json') self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) def test_patch_place_activates_group(self): self.group.status = GroupStatus.INACTIVE.value self.group.save() self.client.force_login(user=self.member) self.client.patch(self.place_url, self.place_data, format='json') self.group.refresh_from_db() self.assertEqual(self.group.status, GroupStatus.ACTIVE.value) def test_valid_status(self): self.client.force_login(user=self.member) response = self.client.patch(self.place_url, {'status': 'active'}, format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) def test_invalid_status(self): self.client.force_login(user=self.member) response = self.client.patch(self.place_url, {'status': 'foobar'}, format='json') self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_change_group_as_member_in_one(self): self.client.force_login(user=self.member) response = self.client.patch(self.place_url, {'group': self.different_group.id}, format='json') self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) def test_change_group_as_member_in_both(self): self.client.force_login(user=self.member2) response = self.client.patch(self.place_url, {'group': self.different_group.id}, format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) response = self.client.patch(self.place_url, {'group': self.group.id}, format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) def test_delete_places(self): response = self.client.delete(self.place_url) self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) def test_delete_places_as_user(self): self.client.force_login(user=self.user) response = self.client.delete(self.place_url) self.assertEqual(response.status_code, status.HTTP_405_METHOD_NOT_ALLOWED) def test_delete_places_as_group_member(self): self.client.force_login(user=self.member) response = self.client.delete(self.place_url) self.assertEqual(response.status_code, status.HTTP_405_METHOD_NOT_ALLOWED) def test_subscribe_and_get_conversation(self): self.client.force_login(user=self.member) response = self.client.post('/api/places/{}/subscription/'.format( self.place.id)) self.assertEqual(response.status_code, status.HTTP_201_CREATED, response.data) response = self.client.get('/api/places/{}/conversation/'.format( self.place.id)) self.assertEqual(response.status_code, status.HTTP_200_OK, response.data) self.assertIn(self.member.id, response.data['participants']) self.assertEqual(response.data['type'], 'place') self.assertEqual(len(response.data['participants']), 1) # post message in conversation data = { 'conversation': response.data['id'], 'content': 'a nice message' } response = self.client.post('/api/messages/', data, format='json') self.assertEqual(response.status_code, status.HTTP_201_CREATED) def test_unsubscribe(self): self.place.placesubscription_set.create(user=self.member) self.client.force_login(user=self.member) response = self.client.delete('/api/places/{}/subscription/'.format( self.place.id)) self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT, response.data) # conversation participant also gets deleted response = self.client.get('/api/places/{}/conversation/'.format( self.place.id)) self.assertEqual(response.status_code, status.HTTP_200_OK, response.data) self.assertNotIn(self.member.id, response.data['participants'])
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.']})
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)