def testLaunchAt(self): e1 = Event(slug="test-event1", host=Organization.objects.first()) e2 = Event( slug="test-event2", host=Organization.objects.first(), start=date.today() + timedelta(days=7), end=date.today() + timedelta(days=8), ) e3 = Event( slug="test-event3", host=Organization.objects.first(), start=date.today() + timedelta(days=-8), end=date.today() + timedelta(days=-7), ) e4 = Event( slug="test-event4", host=Organization.objects.first(), start=date.today() + timedelta(days=70), end=date.today() + timedelta(days=71), ) # case 1: no context event a1 = RecruitHelpersAction(trigger=Trigger(action="test-action", template=EmailTemplate()), ) self.assertEqual(a1.get_launch_at(), timedelta(days=-21)) # case 2: event with no start date a2 = RecruitHelpersAction( trigger=Trigger(action="test-action", template=EmailTemplate()), objects=dict(event=e1), ) self.assertEqual(a2.get_launch_at(), timedelta(days=-21)) # case 3: event with near start date a3 = RecruitHelpersAction( trigger=Trigger(action="test-action", template=EmailTemplate()), objects=dict(event=e2), ) self.assertEqual(a3.get_launch_at(), timedelta(hours=1)) # case 4: event with negative start date a4 = RecruitHelpersAction( trigger=Trigger(action="test-action", template=EmailTemplate()), objects=dict(event=e3), ) self.assertEqual(a4.get_launch_at(), timedelta(hours=1)) # case 5: event with start date in 10 weeks a5 = RecruitHelpersAction( trigger=Trigger(action="test-action", template=EmailTemplate()), objects=dict(event=e4), ) self.assertEqual(a5.get_launch_at(), timedelta(days=49, hours=1))
def event_edit(request, event_ident): try: event = Event.get_by_ident(event_ident) tasks = event.task_set.order_by('role__name') except ObjectDoesNotExist: raise Http404("No event found matching the query.") if request.method == 'GET': event_form = EventForm(prefix='event', instance=event) task_form = TaskForm(prefix='task', initial={'event': event}) elif request.method == 'POST': event_form = EventForm(request.POST, prefix='event', instance=event) task_form = TaskForm(request.POST, prefix='task', initial={'event': event}) if "submit" in request.POST and event_form.is_valid(): event_form.save() return redirect(event) if "add" in request.POST and task_form.is_valid(): task_form.save() context = {'title': 'Edit Event {0}'.format(event.get_ident()), 'event_form': event_form, 'object': event, 'model': Event, 'tasks': tasks, 'task_form': task_form, 'form_helper': bootstrap_helper_without_form} return render(request, 'workshops/event_edit_form.html', context)
def validate_event(request, event_ident): '''Check the event's home page *or* the specified URL (for testing).''' page_url, error_messages = None, [] event = Event.get_by_ident(event_ident) github_url = request.GET.get('url', None) # for manual override if github_url is None: github_url = event.url if github_url is not None: page_url = github_url.replace( 'github.com', 'raw.githubusercontent.com').rstrip('/') + '/gh-pages/index.html' response = requests.get(page_url) if response.status_code != 200: error_messages.append( 'Request for {0} returned status code {1}'.format( page_url, response.status_code)) else: valid, error_messages = check_file(page_url, response.text) context = { 'title': 'Validate Event {0}'.format(event), 'event': event, 'page': page_url, 'error_messages': error_messages } return render(request, 'workshops/validate_event.html', context)
def event_details(request, event_ident): '''List details of a particular event.''' event = Event.get_by_ident(event_ident) tasks = Task.objects.filter(event__id=event.id).order_by('role__name') context = {'title' : 'Event {0}'.format(event), 'event' : event, 'tasks' : tasks} return render(request, 'workshops/event.html', context)
def testLaunchAt(self): e1 = Event( slug="test-event1", host=Organization.objects.first(), ) e2 = Event( slug="test-event2", host=Organization.objects.first(), start=date.today() + timedelta(days=7), end=date.today() + timedelta(days=8), ) e3 = Event( slug="test-event3", host=Organization.objects.first(), start=date.today() + timedelta(days=-8), end=date.today() + timedelta(days=-7), ) # case 1: no context event a1 = PostWorkshopAction( trigger=Trigger(action="test-action", template=EmailTemplate()), ) self.assertEqual(a1.get_launch_at(), timedelta(days=7)) # case 2: event with no end date a2 = PostWorkshopAction( trigger=Trigger(action="test-action", template=EmailTemplate()), objects=dict(event=e1), ) self.assertEqual(a2.get_launch_at(), timedelta(days=7)) # case 3: event with end date a3 = PostWorkshopAction( trigger=Trigger(action="test-action", template=EmailTemplate()), objects=dict(event=e2), ) self.assertEqual(a3.get_launch_at(), timedelta(days=8 + 7)) # case 4: event with negative end date a4 = PostWorkshopAction( trigger=Trigger(action="test-action", template=EmailTemplate()), objects=dict(event=e3), ) self.assertEqual(a4.get_launch_at(), timedelta(days=7))
def event_delete(request, event_ident): """Mark event as deleted. Additionally mark tasks pointing at that event as deleted, too.""" try: event = Event.get_by_ident(event_ident) tasks = event.task_set except ObjectDoesNotExist: raise Http404("No event found matching the query.") tasks.update(deleted=True) event.deleted = True event.save() return redirect(reverse('all_events'))
def validate_event(request, event_ident): '''Check the event's home page *or* the specified URL (for testing).''' page_url, error_messages = None, [] event = Event.get_by_ident(event_ident) github_url = request.GET.get('url', None) # for manual override if github_url is None: github_url = event.url if github_url is not None: page_url = github_url.replace('github.com', 'raw.githubusercontent.com').rstrip('/') + '/gh-pages/index.html' response = requests.get(page_url) if response.status_code != 200: error_messages.append('Request for {0} returned status code {1}'.format(page_url, response.status_code)) else: error_messages = check_file(page_url, response.text) context = {'title' : 'Validate Event {0}'.format(event), 'event' : event, 'page' : page_url, 'error_messages' : error_messages} return render(request, 'workshops/validate_event.html', context)
def setUp(self): # admin self.admin = Person.objects.create_superuser(username="******", personal="Super", family="User", email="*****@*****.**", password='******') self.admin.data_privacy_agreement = True self.admin.save() # some roles don't exist self.learner = Role.objects.create(name='learner', verbose_name='Learner') Role.objects.create(name='helper', verbose_name='Helper') # some tags don't exist either self.ttt = Tag.objects.create(name='TTT', details='Training') # first training request (pending) self.tr1 = TrainingRequest( state='p', person=None, review_process='preapproved', group_name='GummiBears', personal='Zummi', middle='', family='Gummi-Glen', email='*****@*****.**', github=None, occupation='', occupation_other='Magician', affiliation='Gummi-Glen', location='Forest', country='US', underresourced=True, domains_other='Magic', underrepresented='yes', underrepresented_details='LGBTQ', nonprofit_teaching_experience='None', previous_training='none', previous_training_other='', previous_training_explanation='I have no formal education', previous_experience='hours', previous_experience_other='', previous_experience_explanation='I taught other Gummies', programming_language_usage_frequency='not-much', teaching_frequency_expectation='monthly', teaching_frequency_expectation_other='', max_travelling_frequency='not-at-all', max_travelling_frequency_other='', reason='I hope to pass on the Gummi Wisdom one day, and to do that' ' I must know how to do it efficiently.', user_notes='', training_completion_agreement=True, workshop_teaching_agreement=True, data_privacy_agreement=True, code_of_conduct_agreement=True, ) self.tr1.save() self.tr1.domains.set( KnowledgeDomain.objects.filter(name__in=['Chemistry', 'Medicine'])) # no previous involvement self.tr1.previous_involvement.clear() # second training request (accepted) self.tr2 = TrainingRequest( state='a', person=self.admin, review_process='preapproved', group_name='GummiBears', personal='Grammi', middle='', family='Gummi-Glen', email='*****@*****.**', secondary_email='*****@*****.**', github=None, occupation='', occupation_other='Cook', affiliation='Gummi-Glen', location='Forest', country='US', underresourced=True, domains_other='Cooking', underrepresented='no', underrepresented_details='Male', nonprofit_teaching_experience='None', previous_training='none', previous_training_other='', previous_training_explanation='I have no formal education', previous_experience='hours', previous_experience_other='', previous_experience_explanation='I taught other Gummies', programming_language_usage_frequency='not-much', teaching_frequency_expectation='monthly', teaching_frequency_expectation_other='', max_travelling_frequency='not-at-all', max_travelling_frequency_other='', reason='I need to pass on the Gummiberry juice recipe one day, and' ' to do that I must know how to do it efficiently.', user_notes='', training_completion_agreement=True, workshop_teaching_agreement=True, data_privacy_agreement=True, code_of_conduct_agreement=True, ) self.tr2.save() self.tr2.domains.set( KnowledgeDomain.objects.filter(name__in=['Chemistry'])) self.tr2.previous_involvement.set( Role.objects.filter(name__in=['learner', 'helper'])) # add TTT event self.admin was matched to self.ttt_event = Event( slug='2018-07-12-TTT-event', host=Organization.objects.first(), ) self.ttt_event.save() self.ttt_event.tags.set(Tag.objects.filter(name='TTT')) self.admin.task_set.create(role=self.learner, event=self.ttt_event) # add some badges self.admin.award_set.create( badge=Badge.objects.get(name='swc-instructor'), awarded=datetime.date(2018, 7, 12)) self.admin.award_set.create( badge=Badge.objects.get(name='dc-instructor'), awarded=datetime.date(2018, 7, 12)) current_tz = timezone.get_current_timezone() # prepare expecting dataset self.expecting = [ { # due to "strange feature" in DRF, the DateTimeField serialized # representation gets rid of '+00:00' and changes it to 'Z' # if the representation is in UTC 'created_at': self.tr1.created_at.astimezone(current_tz).isoformat().replace( "+00:00", "Z"), 'last_updated_at': self.tr1.last_updated_at.astimezone( current_tz).isoformat().replace("+00:00", "Z"), 'state': 'Pending', 'person': None, 'person_id': None, 'awards': '', 'training_tasks': '', 'review_process': 'preapproved', 'group_name': 'GummiBears', 'personal': 'Zummi', 'middle': '', 'family': 'Gummi-Glen', 'email': '*****@*****.**', 'secondary_email': '', 'github': None, 'underrepresented': 'yes', 'underrepresented_details': 'LGBTQ', 'occupation': '', 'occupation_other': 'Magician', 'affiliation': 'Gummi-Glen', 'location': 'Forest', 'country': 'US', 'underresourced': True, 'domains': 'Chemistry, Medicine', 'domains_other': 'Magic', 'nonprofit_teaching_experience': 'None', 'previous_involvement': '', 'previous_training': 'None', 'previous_training_other': '', 'previous_training_explanation': 'I have no formal education', 'previous_experience': 'A few hours', 'previous_experience_other': '', 'previous_experience_explanation': 'I taught other Gummies', 'programming_language_usage_frequency': 'Never or almost never', 'teaching_frequency_expectation': 'Several times a year', 'teaching_frequency_expectation_other': '', 'max_travelling_frequency': 'Not at all', 'max_travelling_frequency_other': '', 'reason': 'I hope to pass on the Gummi Wisdom one day, and to do ' 'that I must know how to do it efficiently.', 'user_notes': '', 'training_completion_agreement': True, 'workshop_teaching_agreement': True, 'data_privacy_agreement': True, 'code_of_conduct_agreement': True, }, { # due to "strange feature" in DRF, the DateTimeField serialized # representation gets rid of '+00:00' and changes it to 'Z' # if the representation is in UTC 'created_at': self.tr2.created_at.astimezone(current_tz).isoformat().replace( "+00:00", "Z"), 'last_updated_at': self.tr2.last_updated_at.astimezone( current_tz).isoformat().replace("+00:00", "Z"), 'state': 'Accepted', 'person': 'Super User', 'person_id': self.admin.pk, 'awards': 'swc-instructor 2018-07-12, ' 'dc-instructor 2018-07-12', 'training_tasks': '2018-07-12-TTT-event', 'review_process': 'preapproved', 'group_name': 'GummiBears', 'personal': 'Grammi', 'middle': '', 'family': 'Gummi-Glen', 'email': '*****@*****.**', 'secondary_email': '*****@*****.**', 'github': None, 'underrepresented': 'no', 'underrepresented_details': 'Male', 'occupation': '', 'occupation_other': 'Cook', 'affiliation': 'Gummi-Glen', 'location': 'Forest', 'country': 'US', 'underresourced': True, 'domains': 'Chemistry', 'domains_other': 'Cooking', 'nonprofit_teaching_experience': 'None', 'previous_involvement': 'learner, helper', 'previous_training': 'None', 'previous_training_other': '', 'previous_training_explanation': 'I have no formal education', 'previous_experience': 'A few hours', 'previous_experience_other': '', 'previous_experience_explanation': 'I taught other Gummies', 'programming_language_usage_frequency': 'Never or almost never', 'teaching_frequency_expectation': 'Several times a year', 'teaching_frequency_expectation_other': '', 'max_travelling_frequency': 'Not at all', 'max_travelling_frequency_other': '', 'reason': 'I need to pass on the Gummiberry juice recipe one day,' ' and to do that I must know how to do it efficiently.', 'user_notes': '', 'training_completion_agreement': True, 'workshop_teaching_agreement': True, 'data_privacy_agreement': True, 'code_of_conduct_agreement': True, }, ]
class TestListingTrainingRequests(APITestBase): view = TrainingRequests url = 'api:training-requests' maxDiff = None def setUp(self): # admin self.admin = Person.objects.create_superuser(username="******", personal="Super", family="User", email="*****@*****.**", password='******') self.admin.data_privacy_agreement = True self.admin.save() # some roles don't exist self.learner = Role.objects.create(name='learner', verbose_name='Learner') Role.objects.create(name='helper', verbose_name='Helper') # some tags don't exist either self.ttt = Tag.objects.create(name='TTT', details='Training') # first training request (pending) self.tr1 = TrainingRequest( state='p', person=None, review_process='preapproved', group_name='GummiBears', personal='Zummi', middle='', family='Gummi-Glen', email='*****@*****.**', github=None, occupation='', occupation_other='Magician', affiliation='Gummi-Glen', location='Forest', country='US', underresourced=True, domains_other='Magic', underrepresented='yes', underrepresented_details='LGBTQ', nonprofit_teaching_experience='None', previous_training='none', previous_training_other='', previous_training_explanation='I have no formal education', previous_experience='hours', previous_experience_other='', previous_experience_explanation='I taught other Gummies', programming_language_usage_frequency='not-much', teaching_frequency_expectation='monthly', teaching_frequency_expectation_other='', max_travelling_frequency='not-at-all', max_travelling_frequency_other='', reason='I hope to pass on the Gummi Wisdom one day, and to do that' ' I must know how to do it efficiently.', user_notes='', training_completion_agreement=True, workshop_teaching_agreement=True, data_privacy_agreement=True, code_of_conduct_agreement=True, ) self.tr1.save() self.tr1.domains.set( KnowledgeDomain.objects.filter(name__in=['Chemistry', 'Medicine'])) # no previous involvement self.tr1.previous_involvement.clear() # second training request (accepted) self.tr2 = TrainingRequest( state='a', person=self.admin, review_process='preapproved', group_name='GummiBears', personal='Grammi', middle='', family='Gummi-Glen', email='*****@*****.**', secondary_email='*****@*****.**', github=None, occupation='', occupation_other='Cook', affiliation='Gummi-Glen', location='Forest', country='US', underresourced=True, domains_other='Cooking', underrepresented='no', underrepresented_details='Male', nonprofit_teaching_experience='None', previous_training='none', previous_training_other='', previous_training_explanation='I have no formal education', previous_experience='hours', previous_experience_other='', previous_experience_explanation='I taught other Gummies', programming_language_usage_frequency='not-much', teaching_frequency_expectation='monthly', teaching_frequency_expectation_other='', max_travelling_frequency='not-at-all', max_travelling_frequency_other='', reason='I need to pass on the Gummiberry juice recipe one day, and' ' to do that I must know how to do it efficiently.', user_notes='', training_completion_agreement=True, workshop_teaching_agreement=True, data_privacy_agreement=True, code_of_conduct_agreement=True, ) self.tr2.save() self.tr2.domains.set( KnowledgeDomain.objects.filter(name__in=['Chemistry'])) self.tr2.previous_involvement.set( Role.objects.filter(name__in=['learner', 'helper'])) # add TTT event self.admin was matched to self.ttt_event = Event( slug='2018-07-12-TTT-event', host=Organization.objects.first(), ) self.ttt_event.save() self.ttt_event.tags.set(Tag.objects.filter(name='TTT')) self.admin.task_set.create(role=self.learner, event=self.ttt_event) # add some badges self.admin.award_set.create( badge=Badge.objects.get(name='swc-instructor'), awarded=datetime.date(2018, 7, 12)) self.admin.award_set.create( badge=Badge.objects.get(name='dc-instructor'), awarded=datetime.date(2018, 7, 12)) current_tz = timezone.get_current_timezone() # prepare expecting dataset self.expecting = [ { # due to "strange feature" in DRF, the DateTimeField serialized # representation gets rid of '+00:00' and changes it to 'Z' # if the representation is in UTC 'created_at': self.tr1.created_at.astimezone(current_tz).isoformat().replace( "+00:00", "Z"), 'last_updated_at': self.tr1.last_updated_at.astimezone( current_tz).isoformat().replace("+00:00", "Z"), 'state': 'Pending', 'person': None, 'person_id': None, 'awards': '', 'training_tasks': '', 'review_process': 'preapproved', 'group_name': 'GummiBears', 'personal': 'Zummi', 'middle': '', 'family': 'Gummi-Glen', 'email': '*****@*****.**', 'secondary_email': '', 'github': None, 'underrepresented': 'yes', 'underrepresented_details': 'LGBTQ', 'occupation': '', 'occupation_other': 'Magician', 'affiliation': 'Gummi-Glen', 'location': 'Forest', 'country': 'US', 'underresourced': True, 'domains': 'Chemistry, Medicine', 'domains_other': 'Magic', 'nonprofit_teaching_experience': 'None', 'previous_involvement': '', 'previous_training': 'None', 'previous_training_other': '', 'previous_training_explanation': 'I have no formal education', 'previous_experience': 'A few hours', 'previous_experience_other': '', 'previous_experience_explanation': 'I taught other Gummies', 'programming_language_usage_frequency': 'Never or almost never', 'teaching_frequency_expectation': 'Several times a year', 'teaching_frequency_expectation_other': '', 'max_travelling_frequency': 'Not at all', 'max_travelling_frequency_other': '', 'reason': 'I hope to pass on the Gummi Wisdom one day, and to do ' 'that I must know how to do it efficiently.', 'user_notes': '', 'training_completion_agreement': True, 'workshop_teaching_agreement': True, 'data_privacy_agreement': True, 'code_of_conduct_agreement': True, }, { # due to "strange feature" in DRF, the DateTimeField serialized # representation gets rid of '+00:00' and changes it to 'Z' # if the representation is in UTC 'created_at': self.tr2.created_at.astimezone(current_tz).isoformat().replace( "+00:00", "Z"), 'last_updated_at': self.tr2.last_updated_at.astimezone( current_tz).isoformat().replace("+00:00", "Z"), 'state': 'Accepted', 'person': 'Super User', 'person_id': self.admin.pk, 'awards': 'swc-instructor 2018-07-12, ' 'dc-instructor 2018-07-12', 'training_tasks': '2018-07-12-TTT-event', 'review_process': 'preapproved', 'group_name': 'GummiBears', 'personal': 'Grammi', 'middle': '', 'family': 'Gummi-Glen', 'email': '*****@*****.**', 'secondary_email': '*****@*****.**', 'github': None, 'underrepresented': 'no', 'underrepresented_details': 'Male', 'occupation': '', 'occupation_other': 'Cook', 'affiliation': 'Gummi-Glen', 'location': 'Forest', 'country': 'US', 'underresourced': True, 'domains': 'Chemistry', 'domains_other': 'Cooking', 'nonprofit_teaching_experience': 'None', 'previous_involvement': 'learner, helper', 'previous_training': 'None', 'previous_training_other': '', 'previous_training_explanation': 'I have no formal education', 'previous_experience': 'A few hours', 'previous_experience_other': '', 'previous_experience_explanation': 'I taught other Gummies', 'programming_language_usage_frequency': 'Never or almost never', 'teaching_frequency_expectation': 'Several times a year', 'teaching_frequency_expectation_other': '', 'max_travelling_frequency': 'Not at all', 'max_travelling_frequency_other': '', 'reason': 'I need to pass on the Gummiberry juice recipe one day,' ' and to do that I must know how to do it efficiently.', 'user_notes': '', 'training_completion_agreement': True, 'workshop_teaching_agreement': True, 'data_privacy_agreement': True, 'code_of_conduct_agreement': True, }, ] @patch.object(TrainingRequests, 'request', query_params=QueryDict(), create=True) def test_serialization(self, mock_request): # we're mocking a request here because it's not possible to create # a fake request context for the view serializer_class = self.view().get_serializer_class() response = serializer_class(self.view().get_queryset(), many=True) self.assertEqual(len(response.data), 2) self.assertEqual(response.data[0], self.expecting[0]) self.assertEqual(response.data[1], self.expecting[1]) def test_CSV_renderer(self): """Test columns order and labels in the resulting CSV file.""" url = reverse(self.url) # get CSV-formatted output self.client.login(username='******', password='******') response = self.client.get(url, {'format': 'csv'}) content = response.content.decode('utf-8') self.assertEqual(response.status_code, status.HTTP_200_OK) firstline = content.splitlines()[0] expected_firstline = ( 'Created at,Last updated at,State,Matched Trainee,' 'Matched Trainee ID,Badges,Training Tasks,' 'Application Type,Registration Code,' 'Personal,Middle,Family,Email,Secondary email,GitHub username,' 'Underrepresented,' 'Underrepresented (reason),Occupation,Occupation (other),' 'Affiliation,Location,Country,Underresourced institution,' 'Expertise areas,Expertise areas (other),' 'Non-profit teaching experience,Previous Involvement,' 'Previous Training in Teaching,Previous Training (other),' 'Previous Training (explanation),Previous Experience in Teaching,' 'Previous Experience (other),Previous Experience (explanation),' 'Programming Language Usage,Teaching Frequency Expectation,' 'Teaching Frequency Expectation (other),Max Travelling Frequency,' 'Max Travelling Frequency (other),Reason for undertaking training,' 'User notes,Training completion agreement (yes/no),' 'Workshop teaching agreement (yes/no),' 'Data privacy agreement (yes/no),' 'Code of Conduct agreement (yes/no)') self.assertEqual(firstline, expected_firstline) @patch.object(TrainingRequests, 'request', query_params=QueryDict(), create=True) def test_M2M_columns(self, mock_request): """Some columns are M2M fields, but should be displayed as a string, not array /list/.""" # the same mocking as in test_serialization serializer_class = self.view().get_serializer_class() response = serializer_class(self.view().get_queryset(), many=True) self.assertEqual(len(response.data), 2) self.assertEqual(response.data[0]['domains'], 'Chemistry, Medicine') self.assertEqual(response.data[1]['previous_involvement'], 'learner, helper') def test_selected_ids(self): """Test if filtering by IDs works properly.""" url = reverse(self.url) self.client.login(username='******', password='******') response = self.client.get(url, {'ids': '{}'.format(self.tr2.pk)}) self.assertEqual(response.status_code, status.HTTP_200_OK) json = response.json() self.assertEqual(len(json), 1) self.assertEqual(json[0], self.expecting[1])
def testCheckConditions(self): e = Event(slug="test-event1", host=Organization.objects.first()) with self.assertRaises(NotImplementedError): GenericAction.check(e)
def setUpTasks(self): # create a couple of workshops that span outside of agreement duration self_organized_admin = Organization.objects.get( domain="self-organized") data = [ [self.agreement_start - timedelta(days=180), self_organized_admin], [self.agreement_start - timedelta(days=1), self.dc], [self.agreement_start - timedelta(days=1), self_organized_admin], [self.agreement_end + timedelta(days=1), self.dc], ] events = [ Event( slug="event-outside-agreement-range-{}".format(i), host=self.org_beta, # create each event starts roughly month later start=start_date, end=start_date + timedelta(days=1), administrator=admin, ) for i, (start_date, admin) in enumerate(data) ] Event.objects.bulk_create(events) self_org_events = [ Event( slug="event-self-org-{}".format(i), host=self.org_beta, # create each event starts roughly month later start=self.agreement_start + i * self.workshop_interval, end=self.agreement_start_next_day + i * self.workshop_interval, administrator=self_organized_admin, ) for i in range(10) ] no_fee_events = [ Event( slug="event-no-fee-{}".format(i), host=self.org_beta, # create each event starts roughly month later start=self.agreement_start + i * self.workshop_interval, end=self.agreement_start_next_day + i * self.workshop_interval, # just to satisfy the criteria administrator=self.dc, ) for i in range(10) ] cancelled_events = [ Event( slug="event-cancelled-{}".format(i), host=self.org_beta, # create each event starts roughly month later start=self.agreement_start + i * self.workshop_interval, end=self.agreement_start_next_day + i * self.workshop_interval, # just to satisfy the criteria administrator=self.dc, ) for i in range(10) ] self_org_events = Event.objects.bulk_create(self_org_events) no_fee_events = Event.objects.bulk_create(no_fee_events) cancelled_events = Event.objects.bulk_create(cancelled_events) self.TTT.event_set.set(self_org_events + no_fee_events) self.cancelled.event_set.set(cancelled_events) tasks = [ Task( event=e, person=self.admin, role=self.learner, seat_membership=self.current, ) for e in self_org_events[:5] ] Task.objects.bulk_create(tasks)
def setUp(self): # admin self.admin = Person.objects.create_superuser( username="******", personal="Super", family="User", email="*****@*****.**", password='******') self.admin.data_privacy_agreement = True self.admin.save() # some roles don't exist self.learner = Role.objects.create(name='learner', verbose_name='Learner') Role.objects.create(name='helper', verbose_name='Helper') # some tags don't exist either self.ttt = Tag.objects.create(name='TTT', details='Training') # first training request (pending) self.tr1 = TrainingRequest( state='p', person=None, group_name='GummiBears', personal='Zummi', middle='', family='Gummi-Glen', email='*****@*****.**', github=None, occupation='', occupation_other='Magician', affiliation='Gummi-Glen', location='Forest', country='US', underresourced=True, domains_other='Magic', underrepresented='yes', underrepresented_details='LGBTQ', nonprofit_teaching_experience='None', previous_training='none', previous_training_other='', previous_training_explanation='I have no formal education', previous_experience='hours', previous_experience_other='', previous_experience_explanation='I taught other Gummies', programming_language_usage_frequency='not-much', teaching_frequency_expectation='monthly', teaching_frequency_expectation_other='', max_travelling_frequency='not-at-all', max_travelling_frequency_other='', reason='I hope to pass on the Gummi Wisdom one day, and to do that' ' I must know how to do it efficiently.', user_notes='', training_completion_agreement=True, workshop_teaching_agreement=True, data_privacy_agreement=True, code_of_conduct_agreement=True, ) self.tr1.save() self.tr1.domains.set( KnowledgeDomain.objects.filter(name__in=['Chemistry', 'Medicine']) ) # no previous involvement self.tr1.previous_involvement.clear() # second training request (accepted) self.tr2 = TrainingRequest( state='a', person=self.admin, group_name='GummiBears', personal='Grammi', middle='', family='Gummi-Glen', email='*****@*****.**', github=None, occupation='', occupation_other='Cook', affiliation='Gummi-Glen', location='Forest', country='US', underresourced=True, domains_other='Cooking', underrepresented='no', underrepresented_details='Male', nonprofit_teaching_experience='None', previous_training='none', previous_training_other='', previous_training_explanation='I have no formal education', previous_experience='hours', previous_experience_other='', previous_experience_explanation='I taught other Gummies', programming_language_usage_frequency='not-much', teaching_frequency_expectation='monthly', teaching_frequency_expectation_other='', max_travelling_frequency='not-at-all', max_travelling_frequency_other='', reason='I need to pass on the Gummiberry juice recipe one day, and' ' to do that I must know how to do it efficiently.', user_notes='', training_completion_agreement=True, workshop_teaching_agreement=True, data_privacy_agreement=True, code_of_conduct_agreement=True, ) self.tr2.save() self.tr2.domains.set( KnowledgeDomain.objects.filter(name__in=['Chemistry']) ) self.tr2.previous_involvement.set( Role.objects.filter(name__in=['learner', 'helper']) ) # add TTT event self.admin was matched to self.ttt_event = Event( slug='2018-07-12-TTT-event', host=Organization.objects.first(), ) self.ttt_event.save() self.ttt_event.tags.set(Tag.objects.filter(name='TTT')) self.admin.task_set.create(role=self.learner, event=self.ttt_event) # add some badges self.admin.award_set.create( badge=Badge.objects.get(name='swc-instructor'), awarded=datetime.date(2018, 7, 12) ) self.admin.award_set.create( badge=Badge.objects.get(name='dc-instructor'), awarded=datetime.date(2018, 7, 12) ) current_tz = timezone.get_current_timezone() # prepare expecting dataset self.expecting = [ { # due to "strange feature" in DRF, the DateTimeField serialized # representation gets rid of '+00:00' and changes it to 'Z' # if the representation is in UTC 'created_at': self.tr1.created_at.astimezone(current_tz).isoformat() .replace("+00:00", "Z"), 'last_updated_at': self.tr1.last_updated_at.astimezone(current_tz).isoformat() .replace("+00:00", "Z"), 'state': 'Pending', 'person': None, 'person_id': None, 'awards': '', 'training_tasks': '', 'group_name': 'GummiBears', 'personal': 'Zummi', 'middle': '', 'family': 'Gummi-Glen', 'email': '*****@*****.**', 'github': None, 'underrepresented': 'yes', 'underrepresented_details': 'LGBTQ', 'occupation': '', 'occupation_other': 'Magician', 'affiliation': 'Gummi-Glen', 'location': 'Forest', 'country': 'US', 'underresourced': True, 'domains': 'Chemistry, Medicine', 'domains_other': 'Magic', 'nonprofit_teaching_experience': 'None', 'previous_involvement': '', 'previous_training': 'None', 'previous_training_other': '', 'previous_training_explanation': 'I have no formal education', 'previous_experience': 'A few hours', 'previous_experience_other': '', 'previous_experience_explanation': 'I taught other Gummies', 'programming_language_usage_frequency': 'Never or almost never', 'teaching_frequency_expectation': 'Several times a year', 'teaching_frequency_expectation_other': '', 'max_travelling_frequency': 'Not at all', 'max_travelling_frequency_other': '', 'reason': 'I hope to pass on the Gummi Wisdom one day, and to do ' 'that I must know how to do it efficiently.', 'user_notes': '', 'training_completion_agreement': True, 'workshop_teaching_agreement': True, 'data_privacy_agreement': True, 'code_of_conduct_agreement': True, }, { # due to "strange feature" in DRF, the DateTimeField serialized # representation gets rid of '+00:00' and changes it to 'Z' # if the representation is in UTC 'created_at': self.tr2.created_at.astimezone(current_tz).isoformat() .replace("+00:00", "Z"), 'last_updated_at': self.tr2.last_updated_at.astimezone(current_tz).isoformat() .replace("+00:00", "Z"), 'state': 'Accepted', 'person': 'Super User', 'person_id': self.admin.pk, 'awards': 'swc-instructor 2018-07-12, ' 'dc-instructor 2018-07-12', 'training_tasks': '2018-07-12-TTT-event', 'group_name': 'GummiBears', 'personal': 'Grammi', 'middle': '', 'family': 'Gummi-Glen', 'email': '*****@*****.**', 'github': None, 'underrepresented': 'no', 'underrepresented_details': 'Male', 'occupation': '', 'occupation_other': 'Cook', 'affiliation': 'Gummi-Glen', 'location': 'Forest', 'country': 'US', 'underresourced': True, 'domains': 'Chemistry', 'domains_other': 'Cooking', 'nonprofit_teaching_experience': 'None', 'previous_involvement': 'learner, helper', 'previous_training': 'None', 'previous_training_other': '', 'previous_training_explanation': 'I have no formal education', 'previous_experience': 'A few hours', 'previous_experience_other': '', 'previous_experience_explanation': 'I taught other Gummies', 'programming_language_usage_frequency': 'Never or almost never', 'teaching_frequency_expectation': 'Several times a year', 'teaching_frequency_expectation_other': '', 'max_travelling_frequency': 'Not at all', 'max_travelling_frequency_other': '', 'reason': 'I need to pass on the Gummiberry juice recipe one day,' ' and to do that I must know how to do it efficiently.', 'user_notes': '', 'training_completion_agreement': True, 'workshop_teaching_agreement': True, 'data_privacy_agreement': True, 'code_of_conduct_agreement': True, }, ]
class TestListingTrainingRequests(APITestBase): view = TrainingRequests url = 'api:training-requests' maxDiff = None def setUp(self): # admin self.admin = Person.objects.create_superuser( username="******", personal="Super", family="User", email="*****@*****.**", password='******') self.admin.data_privacy_agreement = True self.admin.save() # some roles don't exist self.learner = Role.objects.create(name='learner', verbose_name='Learner') Role.objects.create(name='helper', verbose_name='Helper') # some tags don't exist either self.ttt = Tag.objects.create(name='TTT', details='Training') # first training request (pending) self.tr1 = TrainingRequest( state='p', person=None, group_name='GummiBears', personal='Zummi', middle='', family='Gummi-Glen', email='*****@*****.**', github=None, occupation='', occupation_other='Magician', affiliation='Gummi-Glen', location='Forest', country='US', underresourced=True, domains_other='Magic', underrepresented='yes', underrepresented_details='LGBTQ', nonprofit_teaching_experience='None', previous_training='none', previous_training_other='', previous_training_explanation='I have no formal education', previous_experience='hours', previous_experience_other='', previous_experience_explanation='I taught other Gummies', programming_language_usage_frequency='not-much', teaching_frequency_expectation='monthly', teaching_frequency_expectation_other='', max_travelling_frequency='not-at-all', max_travelling_frequency_other='', reason='I hope to pass on the Gummi Wisdom one day, and to do that' ' I must know how to do it efficiently.', user_notes='', training_completion_agreement=True, workshop_teaching_agreement=True, data_privacy_agreement=True, code_of_conduct_agreement=True, ) self.tr1.save() self.tr1.domains.set( KnowledgeDomain.objects.filter(name__in=['Chemistry', 'Medicine']) ) # no previous involvement self.tr1.previous_involvement.clear() # second training request (accepted) self.tr2 = TrainingRequest( state='a', person=self.admin, group_name='GummiBears', personal='Grammi', middle='', family='Gummi-Glen', email='*****@*****.**', github=None, occupation='', occupation_other='Cook', affiliation='Gummi-Glen', location='Forest', country='US', underresourced=True, domains_other='Cooking', underrepresented='no', underrepresented_details='Male', nonprofit_teaching_experience='None', previous_training='none', previous_training_other='', previous_training_explanation='I have no formal education', previous_experience='hours', previous_experience_other='', previous_experience_explanation='I taught other Gummies', programming_language_usage_frequency='not-much', teaching_frequency_expectation='monthly', teaching_frequency_expectation_other='', max_travelling_frequency='not-at-all', max_travelling_frequency_other='', reason='I need to pass on the Gummiberry juice recipe one day, and' ' to do that I must know how to do it efficiently.', user_notes='', training_completion_agreement=True, workshop_teaching_agreement=True, data_privacy_agreement=True, code_of_conduct_agreement=True, ) self.tr2.save() self.tr2.domains.set( KnowledgeDomain.objects.filter(name__in=['Chemistry']) ) self.tr2.previous_involvement.set( Role.objects.filter(name__in=['learner', 'helper']) ) # add TTT event self.admin was matched to self.ttt_event = Event( slug='2018-07-12-TTT-event', host=Organization.objects.first(), ) self.ttt_event.save() self.ttt_event.tags.set(Tag.objects.filter(name='TTT')) self.admin.task_set.create(role=self.learner, event=self.ttt_event) # add some badges self.admin.award_set.create( badge=Badge.objects.get(name='swc-instructor'), awarded=datetime.date(2018, 7, 12) ) self.admin.award_set.create( badge=Badge.objects.get(name='dc-instructor'), awarded=datetime.date(2018, 7, 12) ) current_tz = timezone.get_current_timezone() # prepare expecting dataset self.expecting = [ { # due to "strange feature" in DRF, the DateTimeField serialized # representation gets rid of '+00:00' and changes it to 'Z' # if the representation is in UTC 'created_at': self.tr1.created_at.astimezone(current_tz).isoformat() .replace("+00:00", "Z"), 'last_updated_at': self.tr1.last_updated_at.astimezone(current_tz).isoformat() .replace("+00:00", "Z"), 'state': 'Pending', 'person': None, 'person_id': None, 'awards': '', 'training_tasks': '', 'group_name': 'GummiBears', 'personal': 'Zummi', 'middle': '', 'family': 'Gummi-Glen', 'email': '*****@*****.**', 'github': None, 'underrepresented': 'yes', 'underrepresented_details': 'LGBTQ', 'occupation': '', 'occupation_other': 'Magician', 'affiliation': 'Gummi-Glen', 'location': 'Forest', 'country': 'US', 'underresourced': True, 'domains': 'Chemistry, Medicine', 'domains_other': 'Magic', 'nonprofit_teaching_experience': 'None', 'previous_involvement': '', 'previous_training': 'None', 'previous_training_other': '', 'previous_training_explanation': 'I have no formal education', 'previous_experience': 'A few hours', 'previous_experience_other': '', 'previous_experience_explanation': 'I taught other Gummies', 'programming_language_usage_frequency': 'Never or almost never', 'teaching_frequency_expectation': 'Several times a year', 'teaching_frequency_expectation_other': '', 'max_travelling_frequency': 'Not at all', 'max_travelling_frequency_other': '', 'reason': 'I hope to pass on the Gummi Wisdom one day, and to do ' 'that I must know how to do it efficiently.', 'user_notes': '', 'training_completion_agreement': True, 'workshop_teaching_agreement': True, 'data_privacy_agreement': True, 'code_of_conduct_agreement': True, }, { # due to "strange feature" in DRF, the DateTimeField serialized # representation gets rid of '+00:00' and changes it to 'Z' # if the representation is in UTC 'created_at': self.tr2.created_at.astimezone(current_tz).isoformat() .replace("+00:00", "Z"), 'last_updated_at': self.tr2.last_updated_at.astimezone(current_tz).isoformat() .replace("+00:00", "Z"), 'state': 'Accepted', 'person': 'Super User', 'person_id': self.admin.pk, 'awards': 'swc-instructor 2018-07-12, ' 'dc-instructor 2018-07-12', 'training_tasks': '2018-07-12-TTT-event', 'group_name': 'GummiBears', 'personal': 'Grammi', 'middle': '', 'family': 'Gummi-Glen', 'email': '*****@*****.**', 'github': None, 'underrepresented': 'no', 'underrepresented_details': 'Male', 'occupation': '', 'occupation_other': 'Cook', 'affiliation': 'Gummi-Glen', 'location': 'Forest', 'country': 'US', 'underresourced': True, 'domains': 'Chemistry', 'domains_other': 'Cooking', 'nonprofit_teaching_experience': 'None', 'previous_involvement': 'learner, helper', 'previous_training': 'None', 'previous_training_other': '', 'previous_training_explanation': 'I have no formal education', 'previous_experience': 'A few hours', 'previous_experience_other': '', 'previous_experience_explanation': 'I taught other Gummies', 'programming_language_usage_frequency': 'Never or almost never', 'teaching_frequency_expectation': 'Several times a year', 'teaching_frequency_expectation_other': '', 'max_travelling_frequency': 'Not at all', 'max_travelling_frequency_other': '', 'reason': 'I need to pass on the Gummiberry juice recipe one day,' ' and to do that I must know how to do it efficiently.', 'user_notes': '', 'training_completion_agreement': True, 'workshop_teaching_agreement': True, 'data_privacy_agreement': True, 'code_of_conduct_agreement': True, }, ] @patch.object(TrainingRequests, 'request', query_params=QueryDict(), create=True) def test_serialization(self, mock_request): # we're mocking a request here because it's not possible to create # a fake request context for the view serializer_class = self.view().get_serializer_class() response = serializer_class(self.view().get_queryset(), many=True) self.assertEqual(len(response.data), 2) self.assertEqual(response.data[0], self.expecting[0]) self.assertEqual(response.data[1], self.expecting[1]) def test_CSV_renderer(self): """Test columns order and labels in the resulting CSV file.""" url = reverse(self.url) # get CSV-formatted output self.client.login(username='******', password='******') response = self.client.get(url, {'format': 'csv'}) content = response.content.decode('utf-8') self.assertEqual(response.status_code, status.HTTP_200_OK) firstline = content.splitlines()[0] expected_firstline = ( 'Created at,Last updated at,State,Matched Trainee,' 'Matched Trainee ID,Badges,Training Tasks,Registration Code,' 'Personal,Middle,Family,Email,GitHub username,Underrepresented,' 'Underrepresented (reason),Occupation,Occupation (other),' 'Affiliation,Location,Country,Underresourced institution,' 'Expertise areas,Expertise areas (other),' 'Non-profit teaching experience,Previous Involvement,' 'Previous Training in Teaching,Previous Training (other),' 'Previous Training (explanation),Previous Experience in Teaching,' 'Previous Experience (other),Previous Experience (explanation),' 'Programming Language Usage,Teaching Frequency Expectation,' 'Teaching Frequency Expectation (other),Max Travelling Frequency,' 'Max Travelling Frequency (other),Reason for undertaking training,' 'User notes,Training completion agreement (yes/no),' 'Workshop teaching agreement (yes/no),' 'Data privacy agreement (yes/no),' 'Code of Conduct agreement (yes/no)' ) self.assertEqual(firstline, expected_firstline) @patch.object(TrainingRequests, 'request', query_params=QueryDict(), create=True) def test_M2M_columns(self, mock_request): """Some columns are M2M fields, but should be displayed as a string, not array /list/.""" # the same mocking as in test_serialization serializer_class = self.view().get_serializer_class() response = serializer_class(self.view().get_queryset(), many=True) self.assertEqual(len(response.data), 2) self.assertEqual(response.data[0]['domains'], 'Chemistry, Medicine') self.assertEqual(response.data[1]['previous_involvement'], 'learner, helper') def test_selected_ids(self): """Test if filtering by IDs works properly.""" url = reverse(self.url) self.client.login(username='******', password='******') response = self.client.get(url, {'ids': '{}'.format(self.tr2.pk)}) self.assertEqual(response.status_code, status.HTTP_200_OK) json = response.json() self.assertEqual(len(json), 1) self.assertEqual(json[0], self.expecting[1])
def setUp(self): # admin self.admin = Person.objects.create_superuser( username="******", personal="Super", family="User", email="*****@*****.**", password="******", ) consent_to_all_required_consents(self.admin) # some roles don't exist self.learner = Role.objects.create(name="learner", verbose_name="Learner") Role.objects.create(name="helper", verbose_name="Helper") # some tags don't exist either self.ttt = Tag.objects.create(name="TTT", details="Training") # first training request (pending) self.tr1 = TrainingRequest( state="p", person=None, review_process="preapproved", group_name="GummiBears", personal="Zummi", middle="", family="Gummi-Glen", email="*****@*****.**", github=None, occupation="", occupation_other="Magician", affiliation="Gummi-Glen", location="Forest", country="US", underresourced=True, domains_other="Magic", underrepresented="yes", underrepresented_details="LGBTQ", nonprofit_teaching_experience="None", previous_training="none", previous_training_other="", previous_training_explanation="I have no formal education", previous_experience="hours", previous_experience_other="", previous_experience_explanation="I taught other Gummies", programming_language_usage_frequency="not-much", teaching_frequency_expectation="monthly", teaching_frequency_expectation_other="", max_travelling_frequency="not-at-all", max_travelling_frequency_other="", reason="I hope to pass on the Gummi Wisdom one day, and to do that" " I must know how to do it efficiently.", user_notes="", training_completion_agreement=True, workshop_teaching_agreement=True, data_privacy_agreement=True, code_of_conduct_agreement=True, ) self.tr1.save() self.tr1.domains.set( KnowledgeDomain.objects.filter(name__in=["Chemistry", "Medicine"]) ) # no previous involvement self.tr1.previous_involvement.clear() # second training request (accepted) self.tr2 = TrainingRequest( state="a", person=self.admin, review_process="preapproved", group_name="GummiBears", personal="Grammi", middle="", family="Gummi-Glen", email="*****@*****.**", secondary_email="*****@*****.**", github=None, occupation="", occupation_other="Cook", affiliation="Gummi-Glen", location="Forest", country="US", underresourced=True, domains_other="Cooking", underrepresented="no", underrepresented_details="Male", nonprofit_teaching_experience="None", previous_training="none", previous_training_other="", previous_training_explanation="I have no formal education", previous_experience="hours", previous_experience_other="", previous_experience_explanation="I taught other Gummies", programming_language_usage_frequency="not-much", teaching_frequency_expectation="monthly", teaching_frequency_expectation_other="", max_travelling_frequency="not-at-all", max_travelling_frequency_other="", reason="I need to pass on the Gummiberry juice recipe one day, and" " to do that I must know how to do it efficiently.", user_notes="", training_completion_agreement=True, workshop_teaching_agreement=True, data_privacy_agreement=True, code_of_conduct_agreement=True, ) self.tr2.save() self.tr2.domains.set(KnowledgeDomain.objects.filter(name__in=["Chemistry"])) self.tr2.previous_involvement.set( Role.objects.filter(name__in=["learner", "helper"]) ) # add TTT event self.admin was matched to self.ttt_event = Event( slug="2018-07-12-TTT-event", host=Organization.objects.first(), ) self.ttt_event.save() self.ttt_event.tags.set(Tag.objects.filter(name="TTT")) self.admin.task_set.create(role=self.learner, event=self.ttt_event) # add some badges self.admin.award_set.create( badge=Badge.objects.get(name="swc-instructor"), awarded=datetime.date(2018, 7, 12), ) self.admin.award_set.create( badge=Badge.objects.get(name="dc-instructor"), awarded=datetime.date(2018, 7, 12), ) current_tz = timezone.get_current_timezone() # prepare expecting dataset self.expecting = [ { # due to "strange feature" in DRF, the DateTimeField serialized # representation gets rid of '+00:00' and changes it to 'Z' # if the representation is in UTC "created_at": self.tr1.created_at.astimezone(current_tz) .isoformat() .replace("+00:00", "Z"), "last_updated_at": self.tr1.last_updated_at.astimezone(current_tz) .isoformat() .replace("+00:00", "Z"), "state": "Pending", "person": None, "person_id": None, "awards": "", "training_tasks": "", "review_process": "preapproved", "group_name": "GummiBears", "personal": "Zummi", "middle": "", "family": "Gummi-Glen", "email": "*****@*****.**", "secondary_email": "", "github": None, "underrepresented": "yes", "underrepresented_details": "LGBTQ", "occupation": "", "occupation_other": "Magician", "affiliation": "Gummi-Glen", "location": "Forest", "country": "US", "underresourced": True, "domains": "Chemistry, Medicine", "domains_other": "Magic", "nonprofit_teaching_experience": "None", "previous_involvement": "", "previous_training": "None", "previous_training_other": "", "previous_training_explanation": "I have no formal education", "previous_experience": "A few hours", "previous_experience_other": "", "previous_experience_explanation": "I taught other Gummies", "programming_language_usage_frequency": "Never or almost never", "teaching_frequency_expectation": "Several times a year", "teaching_frequency_expectation_other": "", "max_travelling_frequency": "Not at all", "max_travelling_frequency_other": "", "reason": "I hope to pass on the Gummi Wisdom one day, and to do " "that I must know how to do it efficiently.", "user_notes": "", "training_completion_agreement": True, "workshop_teaching_agreement": True, "data_privacy_agreement": True, "code_of_conduct_agreement": True, }, { # due to "strange feature" in DRF, the DateTimeField serialized # representation gets rid of '+00:00' and changes it to 'Z' # if the representation is in UTC "created_at": self.tr2.created_at.astimezone(current_tz) .isoformat() .replace("+00:00", "Z"), "last_updated_at": self.tr2.last_updated_at.astimezone(current_tz) .isoformat() .replace("+00:00", "Z"), "state": "Accepted", "person": "Super User", "person_id": self.admin.pk, "awards": "swc-instructor 2018-07-12, " "dc-instructor 2018-07-12", "training_tasks": "2018-07-12-TTT-event", "review_process": "preapproved", "group_name": "GummiBears", "personal": "Grammi", "middle": "", "family": "Gummi-Glen", "email": "*****@*****.**", "secondary_email": "*****@*****.**", "github": None, "underrepresented": "no", "underrepresented_details": "Male", "occupation": "", "occupation_other": "Cook", "affiliation": "Gummi-Glen", "location": "Forest", "country": "US", "underresourced": True, "domains": "Chemistry", "domains_other": "Cooking", "nonprofit_teaching_experience": "None", "previous_involvement": "learner, helper", "previous_training": "None", "previous_training_other": "", "previous_training_explanation": "I have no formal education", "previous_experience": "A few hours", "previous_experience_other": "", "previous_experience_explanation": "I taught other Gummies", "programming_language_usage_frequency": "Never or almost never", "teaching_frequency_expectation": "Several times a year", "teaching_frequency_expectation_other": "", "max_travelling_frequency": "Not at all", "max_travelling_frequency_other": "", "reason": "I need to pass on the Gummiberry juice recipe one day," " and to do that I must know how to do it efficiently.", "user_notes": "", "training_completion_agreement": True, "workshop_teaching_agreement": True, "data_privacy_agreement": True, "code_of_conduct_agreement": True, }, ]
class TestListingTrainingRequests(APITestCase): view = TrainingRequests url = "api:training-requests" maxDiff = None def setUp(self): # admin self.admin = Person.objects.create_superuser( username="******", personal="Super", family="User", email="*****@*****.**", password="******", ) consent_to_all_required_consents(self.admin) # some roles don't exist self.learner = Role.objects.create(name="learner", verbose_name="Learner") Role.objects.create(name="helper", verbose_name="Helper") # some tags don't exist either self.ttt = Tag.objects.create(name="TTT", details="Training") # first training request (pending) self.tr1 = TrainingRequest( state="p", person=None, review_process="preapproved", group_name="GummiBears", personal="Zummi", middle="", family="Gummi-Glen", email="*****@*****.**", github=None, occupation="", occupation_other="Magician", affiliation="Gummi-Glen", location="Forest", country="US", underresourced=True, domains_other="Magic", underrepresented="yes", underrepresented_details="LGBTQ", nonprofit_teaching_experience="None", previous_training="none", previous_training_other="", previous_training_explanation="I have no formal education", previous_experience="hours", previous_experience_other="", previous_experience_explanation="I taught other Gummies", programming_language_usage_frequency="not-much", teaching_frequency_expectation="monthly", teaching_frequency_expectation_other="", max_travelling_frequency="not-at-all", max_travelling_frequency_other="", reason="I hope to pass on the Gummi Wisdom one day, and to do that" " I must know how to do it efficiently.", user_notes="", training_completion_agreement=True, workshop_teaching_agreement=True, data_privacy_agreement=True, code_of_conduct_agreement=True, ) self.tr1.save() self.tr1.domains.set( KnowledgeDomain.objects.filter(name__in=["Chemistry", "Medicine"]) ) # no previous involvement self.tr1.previous_involvement.clear() # second training request (accepted) self.tr2 = TrainingRequest( state="a", person=self.admin, review_process="preapproved", group_name="GummiBears", personal="Grammi", middle="", family="Gummi-Glen", email="*****@*****.**", secondary_email="*****@*****.**", github=None, occupation="", occupation_other="Cook", affiliation="Gummi-Glen", location="Forest", country="US", underresourced=True, domains_other="Cooking", underrepresented="no", underrepresented_details="Male", nonprofit_teaching_experience="None", previous_training="none", previous_training_other="", previous_training_explanation="I have no formal education", previous_experience="hours", previous_experience_other="", previous_experience_explanation="I taught other Gummies", programming_language_usage_frequency="not-much", teaching_frequency_expectation="monthly", teaching_frequency_expectation_other="", max_travelling_frequency="not-at-all", max_travelling_frequency_other="", reason="I need to pass on the Gummiberry juice recipe one day, and" " to do that I must know how to do it efficiently.", user_notes="", training_completion_agreement=True, workshop_teaching_agreement=True, data_privacy_agreement=True, code_of_conduct_agreement=True, ) self.tr2.save() self.tr2.domains.set(KnowledgeDomain.objects.filter(name__in=["Chemistry"])) self.tr2.previous_involvement.set( Role.objects.filter(name__in=["learner", "helper"]) ) # add TTT event self.admin was matched to self.ttt_event = Event( slug="2018-07-12-TTT-event", host=Organization.objects.first(), ) self.ttt_event.save() self.ttt_event.tags.set(Tag.objects.filter(name="TTT")) self.admin.task_set.create(role=self.learner, event=self.ttt_event) # add some badges self.admin.award_set.create( badge=Badge.objects.get(name="swc-instructor"), awarded=datetime.date(2018, 7, 12), ) self.admin.award_set.create( badge=Badge.objects.get(name="dc-instructor"), awarded=datetime.date(2018, 7, 12), ) current_tz = timezone.get_current_timezone() # prepare expecting dataset self.expecting = [ { # due to "strange feature" in DRF, the DateTimeField serialized # representation gets rid of '+00:00' and changes it to 'Z' # if the representation is in UTC "created_at": self.tr1.created_at.astimezone(current_tz) .isoformat() .replace("+00:00", "Z"), "last_updated_at": self.tr1.last_updated_at.astimezone(current_tz) .isoformat() .replace("+00:00", "Z"), "state": "Pending", "person": None, "person_id": None, "awards": "", "training_tasks": "", "review_process": "preapproved", "group_name": "GummiBears", "personal": "Zummi", "middle": "", "family": "Gummi-Glen", "email": "*****@*****.**", "secondary_email": "", "github": None, "underrepresented": "yes", "underrepresented_details": "LGBTQ", "occupation": "", "occupation_other": "Magician", "affiliation": "Gummi-Glen", "location": "Forest", "country": "US", "underresourced": True, "domains": "Chemistry, Medicine", "domains_other": "Magic", "nonprofit_teaching_experience": "None", "previous_involvement": "", "previous_training": "None", "previous_training_other": "", "previous_training_explanation": "I have no formal education", "previous_experience": "A few hours", "previous_experience_other": "", "previous_experience_explanation": "I taught other Gummies", "programming_language_usage_frequency": "Never or almost never", "teaching_frequency_expectation": "Several times a year", "teaching_frequency_expectation_other": "", "max_travelling_frequency": "Not at all", "max_travelling_frequency_other": "", "reason": "I hope to pass on the Gummi Wisdom one day, and to do " "that I must know how to do it efficiently.", "user_notes": "", "training_completion_agreement": True, "workshop_teaching_agreement": True, "data_privacy_agreement": True, "code_of_conduct_agreement": True, }, { # due to "strange feature" in DRF, the DateTimeField serialized # representation gets rid of '+00:00' and changes it to 'Z' # if the representation is in UTC "created_at": self.tr2.created_at.astimezone(current_tz) .isoformat() .replace("+00:00", "Z"), "last_updated_at": self.tr2.last_updated_at.astimezone(current_tz) .isoformat() .replace("+00:00", "Z"), "state": "Accepted", "person": "Super User", "person_id": self.admin.pk, "awards": "swc-instructor 2018-07-12, " "dc-instructor 2018-07-12", "training_tasks": "2018-07-12-TTT-event", "review_process": "preapproved", "group_name": "GummiBears", "personal": "Grammi", "middle": "", "family": "Gummi-Glen", "email": "*****@*****.**", "secondary_email": "*****@*****.**", "github": None, "underrepresented": "no", "underrepresented_details": "Male", "occupation": "", "occupation_other": "Cook", "affiliation": "Gummi-Glen", "location": "Forest", "country": "US", "underresourced": True, "domains": "Chemistry", "domains_other": "Cooking", "nonprofit_teaching_experience": "None", "previous_involvement": "learner, helper", "previous_training": "None", "previous_training_other": "", "previous_training_explanation": "I have no formal education", "previous_experience": "A few hours", "previous_experience_other": "", "previous_experience_explanation": "I taught other Gummies", "programming_language_usage_frequency": "Never or almost never", "teaching_frequency_expectation": "Several times a year", "teaching_frequency_expectation_other": "", "max_travelling_frequency": "Not at all", "max_travelling_frequency_other": "", "reason": "I need to pass on the Gummiberry juice recipe one day," " and to do that I must know how to do it efficiently.", "user_notes": "", "training_completion_agreement": True, "workshop_teaching_agreement": True, "data_privacy_agreement": True, "code_of_conduct_agreement": True, }, ] @patch.object(TrainingRequests, "request", query_params=QueryDict(), create=True) def test_serialization(self, mock_request): # we're mocking a request here because it's not possible to create # a fake request context for the view serializer_class = self.view().get_serializer_class() response = serializer_class(self.view().get_queryset(), many=True) self.assertEqual(len(response.data), 2) self.assertEqual(response.data[0], self.expecting[0]) self.assertEqual(response.data[1], self.expecting[1]) def test_CSV_renderer(self): """Test columns order and labels in the resulting CSV file.""" url = reverse(self.url) # get CSV-formatted output self.client.login(username="******", password="******") response = self.client.get(url, {"format": "csv"}) content = response.content.decode("utf-8") self.assertEqual(response.status_code, status.HTTP_200_OK) firstline = content.splitlines()[0] expected_firstline = ( "Created at,Last updated at,State,Matched Trainee," "Matched Trainee ID,Badges,Training Tasks," "Application Type,Registration Code," "Personal,Middle,Family,Email,Secondary email,GitHub username," "Underrepresented," "Underrepresented (reason),Occupation,Occupation (other)," "Affiliation,Location,Country,Underresourced institution," "Expertise areas,Expertise areas (other)," "Non-profit teaching experience,Previous Involvement," "Previous Training in Teaching,Previous Training (other)," "Previous Training (explanation),Previous Experience in Teaching," "Previous Experience (other),Previous Experience (explanation)," "Programming Language Usage,Teaching Frequency Expectation," "Teaching Frequency Expectation (other),Max Travelling Frequency," "Max Travelling Frequency (other),Reason for undertaking training," "User notes,Training completion agreement (yes/no)," "Workshop teaching agreement (yes/no)," "Data privacy agreement (yes/no)," "Code of Conduct agreement (yes/no)" ) self.assertEqual(firstline, expected_firstline) @patch.object(TrainingRequests, "request", query_params=QueryDict(), create=True) def test_M2M_columns(self, mock_request): """Some columns are M2M fields, but should be displayed as a string, not array /list/.""" # the same mocking as in test_serialization serializer_class = self.view().get_serializer_class() response = serializer_class(self.view().get_queryset(), many=True) self.assertEqual(len(response.data), 2) self.assertEqual(response.data[0]["domains"], "Chemistry, Medicine") self.assertEqual(response.data[1]["previous_involvement"], "learner, helper") def test_selected_ids(self): """Test if filtering by IDs works properly.""" url = reverse(self.url) self.client.login(username="******", password="******") response = self.client.get(url, {"ids": "{}".format(self.tr2.pk)}) self.assertEqual(response.status_code, status.HTTP_200_OK) json = response.json() self.assertEqual(len(json), 1) self.assertEqual(json[0], self.expecting[1])