Beispiel #1
0
    def fill_form(self, form, fill_complete):
        form[question_id(self.course.general_contribution,
                         self.top_course_questionnaire,
                         self.top_text_question)] = "some text"
        form[question_id(self.course.general_contribution,
                         self.top_course_questionnaire,
                         self.top_grade_question)] = 3
        form[question_id(self.course.general_contribution,
                         self.top_course_questionnaire,
                         self.top_likert_question)] = 1

        form[question_id(self.course.general_contribution,
                         self.bottom_course_questionnaire,
                         self.bottom_text_question)] = "some bottom text"
        form[question_id(self.course.general_contribution,
                         self.bottom_course_questionnaire,
                         self.bottom_grade_question)] = 4
        form[question_id(self.course.general_contribution,
                         self.bottom_course_questionnaire,
                         self.bottom_likert_question)] = 2

        form[question_id(self.contribution1, self.contributor_questionnaire,
                         self.contributor_text_question)] = "some other text"
        form[question_id(self.contribution1, self.contributor_questionnaire,
                         self.contributor_likert_question)] = 4

        form[question_id(self.contribution2, self.contributor_questionnaire,
                         self.contributor_text_question)] = "some more text"

        if fill_complete:
            form[question_id(self.contribution2,
                             self.contributor_questionnaire,
                             self.contributor_likert_question)] = 2
Beispiel #2
0
    def test_incomplete_form(self):
        """
            Submits a student vote, verifies that an error message is
            displayed if not all rating questions have been answered and that all
            given answers stay selected/filled.
        """
        page = self.app.get(self.url, user=self.voting_user1.username, status=200)
        form = page.forms["student-vote-form"]
        self.fill_form(form, fill_complete=False)
        response = form.submit()

        self.assertEqual(response.status_code, 200)
        self.assertIn("vote for all rating questions", response)

        form = page.forms["student-vote-form"]

        self.assertEqual(form[question_id(self.evaluation.general_contribution, self.top_general_questionnaire, self.top_text_question)].value, "some text")
        self.assertEqual(form[question_id(self.evaluation.general_contribution, self.top_general_questionnaire, self.top_likert_question)].value, "1")
        self.assertEqual(form[question_id(self.evaluation.general_contribution, self.top_general_questionnaire, self.top_grade_question)].value, "3")

        self.assertEqual(form[question_id(self.evaluation.general_contribution, self.bottom_general_questionnaire, self.bottom_text_question)].value, "some bottom text")
        self.assertEqual(form[question_id(self.evaluation.general_contribution, self.bottom_general_questionnaire, self.bottom_likert_question)].value, "2")
        self.assertEqual(form[question_id(self.evaluation.general_contribution, self.bottom_general_questionnaire, self.bottom_grade_question)].value, "4")

        self.assertEqual(form[question_id(self.contribution1, self.contributor_questionnaire, self.contributor_text_question)].value, "some other text")
        self.assertEqual(form[question_id(self.contribution1, self.contributor_questionnaire, self.contributor_likert_question)].value, "4")

        self.assertEqual(form[question_id(self.contribution2, self.contributor_questionnaire, self.contributor_text_question)].value, "some more text")
Beispiel #3
0
    def test_incomplete_form(self):
        """
            Submits a student vote, verifies that an error message is
            displayed if not all rating questions have been answered and that all
            given answers stay selected/filled.
        """
        page = self.app.get(self.url, user=self.voting_user1.username, status=200)
        form = page.forms["student-vote-form"]
        self.fill_form(form, fill_complete=False)
        response = form.submit()

        self.assertEqual(response.status_code, 200)
        self.assertIn("vote for all rating questions", response)

        form = page.forms["student-vote-form"]

        self.assertEqual(form[question_id(self.course.general_contribution, self.top_general_questionnaire, self.top_text_question)].value, "some text")
        self.assertEqual(form[question_id(self.course.general_contribution, self.top_general_questionnaire, self.top_likert_question)].value, "1")
        self.assertEqual(form[question_id(self.course.general_contribution, self.top_general_questionnaire, self.top_grade_question)].value, "3")

        self.assertEqual(form[question_id(self.course.general_contribution, self.bottom_general_questionnaire, self.bottom_text_question)].value, "some bottom text")
        self.assertEqual(form[question_id(self.course.general_contribution, self.bottom_general_questionnaire, self.bottom_likert_question)].value, "2")
        self.assertEqual(form[question_id(self.course.general_contribution, self.bottom_general_questionnaire, self.bottom_grade_question)].value, "4")

        self.assertEqual(form[question_id(self.contribution1, self.contributor_questionnaire, self.contributor_text_question)].value, "some other text")
        self.assertEqual(form[question_id(self.contribution1, self.contributor_questionnaire, self.contributor_likert_question)].value, "4")

        self.assertEqual(form[question_id(self.contribution2, self.contributor_questionnaire, self.contributor_text_question)].value, "some more text")
Beispiel #4
0
def let_user_vote_for_evaluation(app, user, evaluation):
    url = '/student/vote/{}'.format(evaluation.id)
    page = app.get(url, user=user, status=200)
    form = page.forms["student-vote-form"]
    for contribution in evaluation.contributions.all().prefetch_related("questionnaires", "questionnaires__questions"):
        for questionnaire in contribution.questionnaires.all():
            for question in questionnaire.questions.all():
                if question.is_text_question:
                    form[question_id(contribution, questionnaire, question)] = "Lorem ispum"
                elif question.is_rating_question:
                    form[question_id(contribution, questionnaire, question)] = 1
    form.submit()
Beispiel #5
0
def let_user_vote_for_evaluation(app, user, evaluation):
    url = '/student/vote/{}'.format(evaluation.id)
    page = app.get(url, user=user, status=200)
    form = page.forms["student-vote-form"]
    for contribution in evaluation.contributions.all().prefetch_related("questionnaires", "questionnaires__questions"):
        for questionnaire in contribution.questionnaires.all():
            for question in questionnaire.questions.all():
                if question.is_text_question:
                    form[question_id(contribution, questionnaire, question)] = "Lorem ispum"
                elif question.is_rating_question:
                    form[question_id(contribution, questionnaire, question)] = 1
    form.submit()
Beispiel #6
0
 def let_user_vote_for_course(self, user, course):
     url = '/student/vote/{}'.format(course.id)
     page = self.app.get(url, user=user, status=200)
     form = page.forms["student-vote-form"]
     for contribution in course.contributions.all().prefetch_related("questionnaires", "questionnaires__question_set"):
         for questionnaire in contribution.questionnaires.all():
             for question in questionnaire.question_set.all():
                 if question.type == "T":
                     form[question_id(contribution, questionnaire, question)] = "Lorem ispum"
                 elif question.type in ["L", "G", "P", "N"]:
                     form[question_id(contribution, questionnaire, question)] = 1
     form.submit()
Beispiel #7
0
def let_user_vote_for_course(app, user, course):
    url = '/student/vote/{}'.format(course.id)
    page = app.get(url, user=user, status=200)
    form = page.forms["student-vote-form"]
    for contribution in course.contributions.all().prefetch_related(
            "questionnaires", "questionnaires__questions"):
        for questionnaire in contribution.questionnaires.all():
            for question in questionnaire.questions.all():
                if question.type == "T":
                    form[question_id(contribution, questionnaire,
                                     question)] = "Lorem ispum"
                elif question.type in ["L", "G", "P", "N"]:
                    form[question_id(contribution, questionnaire,
                                     question)] = 1
    form.submit()
Beispiel #8
0
    def fill_form(self, form, fill_complete):
        form[question_id(self.evaluation.general_contribution, self.top_general_questionnaire, self.top_text_question)] = "some text"
        form[question_id(self.evaluation.general_contribution, self.top_general_questionnaire, self.top_grade_question)] = 3
        form[question_id(self.evaluation.general_contribution, self.top_general_questionnaire, self.top_likert_question)] = 1

        form[question_id(self.evaluation.general_contribution, self.bottom_general_questionnaire, self.bottom_text_question)] = "some bottom text"
        form[question_id(self.evaluation.general_contribution, self.bottom_general_questionnaire, self.bottom_grade_question)] = 4
        form[question_id(self.evaluation.general_contribution, self.bottom_general_questionnaire, self.bottom_likert_question)] = 2

        form[question_id(self.contribution1, self.contributor_questionnaire, self.contributor_text_question)] = "some other text"
        form[question_id(self.contribution1, self.contributor_questionnaire, self.contributor_likert_question)] = 4

        form[question_id(self.contribution2, self.contributor_questionnaire, self.contributor_text_question)] = "some more text"

        if fill_complete:
            form[question_id(self.contribution2, self.contributor_questionnaire, self.contributor_likert_question)] = 2
Beispiel #9
0
    def __init__(self, *args, contribution, questionnaire, **kwargs):
        super().__init__(*args, **kwargs)
        self.questionnaire = questionnaire

        for question in self.questionnaire.questions.all():
            # generic arguments for all kinds of fields
            field_args = dict(label=question.text)

            if question.is_text_question:
                field = forms.CharField(required=False, widget=forms.Textarea(),
                                        **field_args)
            elif question.is_rating_question:
                choices = CHOICES[question.type]
                field = forms.TypedChoiceField(widget=forms.RadioSelect(attrs={'choices': choices}),
                                               choices=zip(choices.values, choices.names),
                                               coerce=int,
                                               **field_args)
            elif question.is_heading_question:
                field = HeadingField(label=question.text)

            identifier = question_id(contribution,
                                     questionnaire,
                                     question)

            self.fields[identifier] = field
Beispiel #10
0
    def __init__(self, *args, contribution, questionnaire, **kwargs):
        super().__init__(*args, **kwargs)
        self.questionnaire = questionnaire

        for question in self.questionnaire.questions.all():
            # generic arguments for all kinds of fields
            field_args = dict(label=question.text)

            if question.is_text_question:
                field = forms.CharField(required=False,
                                        widget=forms.Textarea(),
                                        **field_args)
            elif question.is_rating_question:
                choices = CHOICES[question.type]
                field = forms.TypedChoiceField(
                    widget=forms.RadioSelect(attrs={'choices': choices}),
                    choices=zip(choices.values, choices.names),
                    coerce=int,
                    **field_args)
            elif question.is_heading_question:
                field = HeadingField(label=question.text)

            identifier = question_id(contribution, questionnaire, question)

            self.fields[identifier] = field
Beispiel #11
0
    def test_xmin_of_all_answers_is_updated(self):
        page = self.app.get(self.url, user=self.voting_user1)
        form = page.forms["student-vote-form"]
        self.fill_form(form)
        form.submit()

        page = self.app.get(self.url, user=self.voting_user2)
        form = page.forms["student-vote-form"]
        self.fill_form(form)
        form[question_id(self.evaluation.general_contribution, self.top_general_questionnaire, self.top_grade_question)] = 2
        form.submit()

        self.assertEqual(
            set(Answer.__subclasses__()),
            {RatingAnswerCounter, TextAnswer},
            "This test requires an update if a new answer type is added. Also, when adding a new answer type, "
            "the new table should probably also be vacuumed and clustered -- see and update "
            "https://github.com/e-valuation/EvaP/wiki/Installation#database-vacuuming-and-clustering"
        )

        query = RatingAnswerCounter.objects.raw("SELECT id, xmin FROM evaluation_ratinganswercounter")
        rating_answer_xmins = [row.xmin for row in query]
        self.assertTrue(all(xmin == rating_answer_xmins[0] for xmin in rating_answer_xmins))

        query = TextAnswer.objects.raw("SELECT id, xmin FROM evaluation_textanswer")
        text_answer_xmins = [row.xmin for row in query]
        self.assertTrue(all(xmin == text_answer_xmins[0] for xmin in text_answer_xmins))
Beispiel #12
0
    def test_xmin_of_all_answers_is_updated(self):
        page = self.app.get(self.url, user=self.voting_user1)
        form = page.forms["student-vote-form"]
        self.fill_form(form)
        form.submit()

        page = self.app.get(self.url, user=self.voting_user2)
        form = page.forms["student-vote-form"]
        self.fill_form(form)
        form[question_id(self.evaluation.general_contribution,
                         self.top_general_questionnaire,
                         self.top_grade_question)] = 2
        form.submit()

        self.assertEqual(
            set(Answer.__subclasses__()), {RatingAnswerCounter, TextAnswer},
            "This requires an update if a new answer type is added")

        query = RatingAnswerCounter.objects.raw(
            "SELECT id, xmin FROM evaluation_ratinganswercounter")
        rating_answer_xmins = [row.xmin for row in query]
        self.assertTrue(
            all(xmin == rating_answer_xmins[0]
                for xmin in rating_answer_xmins))

        query = TextAnswer.objects.raw(
            "SELECT id, xmin FROM evaluation_textanswer")
        text_answer_xmins = [row.xmin for row in query]
        self.assertTrue(
            all(xmin == text_answer_xmins[0] for xmin in text_answer_xmins))
Beispiel #13
0
def vote(request, evaluation_id):
    evaluation = get_object_or_404(Evaluation, id=evaluation_id)
    if not evaluation.can_user_vote(request.user):
        raise PermissionDenied

    form_groups, rendered_page = get_valid_form_groups_or_render_vote_page(
        request, evaluation, preview=False)
    if rendered_page is not None:
        return rendered_page

    # all forms are valid, begin vote operation
    with transaction.atomic():
        # add user to evaluation.voters
        # not using evaluation.voters.add(request.user) since that fails silently when done twice.
        evaluation.voters.through.objects.create(
            userprofile_id=request.user.pk, evaluation_id=evaluation.pk)

        for contribution, form_group in form_groups.items():
            for questionnaire_form in form_group:
                questionnaire = questionnaire_form.questionnaire
                for question in questionnaire.questions.all():
                    if question.is_heading_question:
                        continue

                    identifier = question_id(contribution, questionnaire,
                                             question)
                    value = questionnaire_form.cleaned_data.get(identifier)

                    if question.is_text_question:
                        if value:
                            question.answer_class.objects.create(
                                contribution=contribution,
                                question=question,
                                answer=value)
                    else:
                        if value != NO_ANSWER:
                            answer_counter, __ = question.answer_class.objects.get_or_create(
                                contribution=contribution,
                                question=question,
                                answer=value)
                            answer_counter.count += 1
                            answer_counter.save()

        if not evaluation.can_publish_text_results:
            # enable text result publishing if first user confirmed that publishing is okay or second user voted
            if request.POST.get('text_results_publish_confirmation_top'
                                ) == 'on' or request.POST.get(
                                    'text_results_publish_confirmation_bottom'
                                ) == 'on' or evaluation.voters.count() >= 2:
                evaluation.can_publish_text_results = True
                evaluation.save()

        evaluation.evaluation_evaluated.send(
            sender=Evaluation,
            request=request,
            semester=evaluation.course.semester)

    messages.success(request, _("Your vote was recorded."))
    return HttpResponse(SUCCESS_MAGIC_STRING)
Beispiel #14
0
def vote(request, course_id):

    course = get_object_or_404(Course, id=course_id)
    if not course.can_user_vote(request.user):
        raise PermissionDenied

    form_groups, rendered_page = get_valid_form_groups_or_render_vote_page(
        request, course, preview=False)
    if rendered_page is not None:
        return rendered_page

    # all forms are valid, begin vote operation
    with transaction.atomic():
        # add user to course.voters
        # not using course.voters.add(request.user) since it fails silently when done twice.
        # manually inserting like this gives us the 'created' return value and ensures at the database level that nobody votes twice.
        __, created = course.voters.through.objects.get_or_create(
            userprofile_id=request.user.pk, course_id=course.pk)
        if not created:  # vote already got recorded, bail out
            raise SuspiciousOperation(
                "A second vote has been received shortly after the first one.")

        for contribution, form_group in form_groups.items():
            for questionnaire_form in form_group:
                questionnaire = questionnaire_form.questionnaire
                for question in questionnaire.question_set.all():
                    identifier = question_id(contribution, questionnaire,
                                             question)
                    value = questionnaire_form.cleaned_data.get(identifier)

                    if question.is_text_question:
                        if value:
                            question.answer_class.objects.create(
                                contribution=contribution,
                                question=question,
                                answer=value)
                    elif question.is_heading_question:
                        pass  # ignore these
                    else:
                        if value != 6:
                            answer_counter, __ = question.answer_class.objects.get_or_create(
                                contribution=contribution,
                                question=question,
                                answer=value)
                            answer_counter.add_vote()
                            answer_counter.save()

        course.course_evaluated.send(sender=Course,
                                     request=request,
                                     semester=course.semester)

    messages.success(request, _("Your vote was recorded."))
    return HttpResponse(SUCCESS_MAGIC_STRING)
Beispiel #15
0
def vote(request, evaluation_id):
    evaluation = get_object_or_404(Evaluation, id=evaluation_id)
    if not evaluation.can_be_voted_for_by(request.user):
        raise PermissionDenied

    form_groups, rendered_page = get_valid_form_groups_or_render_vote_page(request, evaluation, preview=False)
    if rendered_page is not None:
        return rendered_page

    # all forms are valid, begin vote operation
    with transaction.atomic():
        # add user to evaluation.voters
        # not using evaluation.voters.add(request.user) since that fails silently when done twice.
        evaluation.voters.through.objects.create(userprofile_id=request.user.pk, evaluation_id=evaluation.pk)

        for contribution, form_group in form_groups.items():
            for questionnaire_form in form_group:
                questionnaire = questionnaire_form.questionnaire
                for question in questionnaire.questions.all():
                    if question.is_heading_question:
                        continue

                    identifier = question_id(contribution, questionnaire, question)
                    value = questionnaire_form.cleaned_data.get(identifier)

                    if question.is_text_question:
                        if value:
                            question.answer_class.objects.create(contribution=contribution, question=question, answer=value)
                    else:
                        if value != NO_ANSWER:
                            answer_counter, __ = question.answer_class.objects.get_or_create(contribution=contribution, question=question, answer=value)
                            answer_counter.count += 1
                            answer_counter.save()

        if not evaluation.can_publish_text_results:
            # enable text result publishing if first user confirmed that publishing is okay or second user voted
            if request.POST.get('text_results_publish_confirmation_top') == 'on' or request.POST.get('text_results_publish_confirmation_bottom') == 'on' or evaluation.voters.count() >= 2:
                evaluation.can_publish_text_results = True
                evaluation.save()

        evaluation.evaluation_evaluated.send(sender=Evaluation, request=request, semester=evaluation.course.semester)

    messages.success(request, _("Your vote was recorded."))
    return HttpResponse(SUCCESS_MAGIC_STRING)
Beispiel #16
0
    def __init__(self, *args, contribution, questionnaire, **kwargs):
        super().__init__(*args, **kwargs)
        self.questionnaire = questionnaire

        for question in self.questionnaire.question_set.all():
            # generic arguments for all kinds of fields
            field_args = dict(label=question.text)

            if question.is_text_question:
                field = forms.CharField(required=False, widget=forms.Textarea(),
                                        **field_args)
            elif question.is_likert_question:
                field = forms.TypedChoiceField(widget=forms.RadioSelect(),
                                               choices=LIKERT_CHOICES,
                                               coerce=int,
                                               **field_args)
            elif question.is_grade_question:
                field = forms.TypedChoiceField(widget=forms.RadioSelect(),
                                               choices=GRADE_CHOICES,
                                               coerce=int,
                                               **field_args)
            elif question.is_positive_yes_no_question:
                field = forms.TypedChoiceField(widget=forms.RadioSelect(),
                                               choices=POSITIVE_YES_NO_CHOICES,
                                               coerce=int,
                                               **field_args)
            elif question.is_negative_yes_no_question:
                field = forms.TypedChoiceField(widget=forms.RadioSelect(),
                                               choices=NEGATIVE_YES_NO_CHOICES,
                                               coerce=int,
                                               **field_args)
            elif question.is_heading_question:
                field = HeadingField(label=question.text)

            identifier = question_id(contribution,
                                     questionnaire,
                                     question)

            self.fields[identifier] = field
Beispiel #17
0
def vote(request, course_id):
    # retrieve course and make sure that the user is allowed to vote
    course = get_object_or_404(Course, id=course_id)
    if not course.can_user_vote(request.user):
        raise PermissionDenied

    # prevent a user from voting on themselves.
    contributions_to_vote_on = course.contributions.exclude(
        contributor=request.user).all()
    form_groups = helper_create_voting_form_groups(request,
                                                   contributions_to_vote_on)

    if not all(
            all(form.is_valid() for form in form_group)
            for form_group in form_groups.values()):
        errors_exist = any(
            helper_has_errors(form_group)
            for form_group in form_groups.values())

        course_form_group = form_groups.pop(course.general_contribution)

        contributor_form_groups = list(
            (contribution.contributor, contribution.label, form_group,
             helper_has_errors(form_group))
            for contribution, form_group in form_groups.items())

        template_data = dict(errors_exist=errors_exist,
                             course_form_group=course_form_group,
                             contributor_form_groups=contributor_form_groups,
                             course=course,
                             participants_warning=course.num_participants <= 5,
                             preview=False)
        return render(request, "student_vote.html", template_data)

    # all forms are valid, begin vote operation
    with transaction.atomic():
        # add user to course.voters
        # not using course.voters.add(request.user) since it fails silently when done twice.
        # manually inserting like this gives us the 'created' return value and ensures at the database level that nobody votes twice.
        __, created = course.voters.through.objects.get_or_create(
            userprofile_id=request.user.pk, course_id=course.pk)
        if not created:  # vote already got recorded, bail out
            raise SuspiciousOperation(
                "A second vote has been received shortly after the first one.")

        for contribution, form_group in form_groups.items():
            for questionnaire_form in form_group:
                questionnaire = questionnaire_form.questionnaire
                for question in questionnaire.question_set.all():
                    identifier = question_id(contribution, questionnaire,
                                             question)
                    value = questionnaire_form.cleaned_data.get(identifier)

                    if question.is_text_question:
                        if value:
                            question.answer_class.objects.create(
                                contribution=contribution,
                                question=question,
                                answer=value)
                    else:
                        if value != 6:
                            answer_counter, __ = question.answer_class.objects.get_or_create(
                                contribution=contribution,
                                question=question,
                                answer=value)
                            answer_counter.add_vote()
                            answer_counter.save()

        course.course_evaluated.send(sender=Course,
                                     request=request,
                                     semester=course.semester)

    messages.success(request, _("Your vote was recorded."))
    return redirect('student:index')