Пример #1
0
    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))
Пример #2
0
Файл: views.py Проект: npch/amy
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)
Пример #3
0
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)
Пример #4
0
Файл: views.py Проект: npch/amy
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)
Пример #5
0
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)
Пример #6
0
    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))
Пример #7
0
Файл: views.py Проект: npch/amy
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'))
Пример #8
0
Файл: views.py Проект: npch/amy
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)
Пример #9
0
    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,
            },
        ]
Пример #10
0
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])
Пример #11
0
 def testCheckConditions(self):
     e = Event(slug="test-event1", host=Organization.objects.first())
     with self.assertRaises(NotImplementedError):
         GenericAction.check(e)
Пример #12
0
    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)
Пример #13
0
    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,
            },
        ]
Пример #14
0
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])
Пример #15
0
    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,
            },
        ]
Пример #16
0
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])