Пример #1
0
 def test_quest_submission_manager_get_queryset_default(self):
     """QuestSubmissionManager.get_queryset should return all visible not archived quest submissions"""
     submissions = self.make_test_submissions_stack()
     SiteConfig.get().set_active_semester(submissions[0].semester.id)
     qs = QuestSubmission.objects.get_queryset().order_by('id').values_list(
         'id', flat=True)
     self.assertListEqual(list(qs), [submissions[0].id, submissions[1].id])
Пример #2
0
    def test_quest_manager_get_available(self):
        """ DESCRIPTION FROM METHOD:
        Quests that should appear in the user's Available quests tab.   Should exclude:
        1. Quests whose available date & time has not past, or quest that have expired
        2. Quests that are not visible to students or archived
        3. Quests who's prerequisites have not been met
        4. Quests that are not currently submitted for approval or already in progress <<<< COVERED HERE
        5. Quests who's maximum repeats have been completed
        6. Quests who's repeat time has not passed since last completion <<<< COVERED HERE
        7. Check for blocking quests (available and in-progress), if present, remove all others <<<< COVERED HERE
        """
        active_semester = self.make_test_quests_and_submissions_stack()
        SiteConfig.get().set_active_semester(active_semester.id)
        qs = Quest.objects.get_available(self.student)
        self.assertListEqual(list(qs.values_list('name', flat=True)),
                             ['Quest-blocking'])

        # Start the blocking quest.
        blocking_quest = Quest.objects.get(name='Quest-blocking')
        blocking_sub = baker.make(QuestSubmission,
                                  quest=blocking_quest,
                                  user=self.student,
                                  semester=active_semester)

        # Should have no available quests while the blocking quest is in progress
        qs = Quest.objects.get_available(self.student)
        self.assertListEqual(list(qs.values_list('name', flat=True)), [])

        # complete the blocking quest to make others available
        blocking_sub.mark_completed()
        qs = Quest.objects.get_available(self.student)
        self.assertListEqual(list(qs.values_list('name', flat=True)),
                             ['Quest-not-started', 'Welcome to ByteDeck!'])
Пример #3
0
 def test_quest_submission_manager_get_queryset_for_all_quests(self):
     submissions = self.make_test_submissions_stack()
     SiteConfig.get().set_active_semester(submissions[0].semester.id)
     qs = QuestSubmission.objects.get_queryset(
         exclude_archived_quests=False,
         exclude_quests_not_visible_to_students=False)
     self.assertEqual(qs.count(), 7)
Пример #4
0
 def test_quest_qs_not_completed(self):
     """Should return all the quests that do NOT have a completed submission (during active semester)"""
     active_semester = self.make_test_quests_and_submissions_stack()
     SiteConfig.get().set_active_semester(active_semester.id)
     qs = Quest.objects.order_by('id').not_completed(self.student)
     self.assertListEqual(list(qs.values_list('name', flat=True)), [
         'Quest-inprogress-sem2', 'Quest-completed-sem2',
         'Quest-not-started', 'Quest-blocking', 'Quest-inprogress'
     ])
Пример #5
0
    def setUp(self):
        self.teacher = Recipe(User, is_staff=True).make()  # need a teacher or student creation will fail.
        self.user = baker.make(User)
        # Profiles are created automatically with each user, so we only need to access profiles via users
        self.profile = self.user.profile

        self.active_sem = SiteConfig.get().active_semester

        # Why is this required?  Why can't I just baker.make(Semester)?  For some reason when I
        # use baker.make(Semester) it tried to duplicate the pk, using pk=1 again?!
        self.inactive_sem = baker.make(Semester, pk=(SiteConfig.get().active_semester.pk + 1))
Пример #6
0
 def test_quest_qs_not_in_progress(self):
     """Should return all the quests that do NOT have an inprogress submission (during active semester)"""
     active_semester = self.make_test_quests_and_submissions_stack()
     SiteConfig.get().set_active_semester(active_semester.id)
     qs = Quest.objects.order_by('id').not_in_progress(self.student)
     # compare sets so order doesn't matter
     self.assertSetEqual(
         set(qs.values_list('name', flat=True)),
         set([
             'Quest-inprogress-sem2', 'Quest-completed-sem2',
             'Quest-not-started', 'Quest-blocking', 'Quest-completed',
             'Quest-1hr-cooldown'
         ] + self.initial_quest_name_list))
Пример #7
0
    def send_by_mail(self):
        subject = "Test email from " + SiteConfig.get().site_name
        from_email = (SiteConfig.get().site_name + " <" + settings.EMAIL_HOST_USER + ">")
        to_emails = [from_email]
        email_message = "from %s: %s via %s" % ("Dear Bloggins", "sup", from_email)

        html_email_message = "<h1> if this is showing you received an HTML message</h1>"

        send_mail(subject,
                  email_message,
                  from_email,
                  to_emails,
                  html_message=html_email_message,
                  fail_silently=False)
Пример #8
0
    def test_student_marks_button(self):
        """
        Student should be able to see marks button when `display_marks_calculation` is True.
        Otherwise, they should not be able to see it.
        """

        # Login a student
        success = self.client.login(username=self.test_student1.username,
                                    password=self.test_password)
        self.assertTrue(success)

        # View profile page
        s_pk = self.test_student1.profile.pk

        # `display_marks_calculation` is disabled by default. Student should not be able to view it
        response = self.client.get(
            reverse('profiles:profile_detail', args=[s_pk]))
        self.assertNotContains(response, 'View your Mark Calculations')

        config = SiteConfig.get()
        config.display_marks_calculation = True
        config.save()

        # Student should be able to view marks calculation
        response = self.client.get(
            reverse('profiles:profile_detail', args=[s_pk]))
        self.assertContains(response, 'View your Mark Calculations')
Пример #9
0
 def get_icon_url(self):
     if self.icon and hasattr(self.icon, 'url'):
         return self.icon.url
     elif self.campaign and self.campaign.icon and hasattr(self.campaign.icon, 'url'):
         return self.campaign.icon.url
     else:
         return SiteConfig.get().get_default_icon_url()
Пример #10
0
def mark_calculations(request, user_id=None):
    template_name = 'courses/mark_calculations.html'

    if not SiteConfig.get().display_marks_calculation:
        raise Http404

    # Only allow staff to see other student's mark page
    if user_id is not None and request.user.is_staff:
        user = get_object_or_404(User, pk=user_id)
    else:
        user = request.user

    course_student = CourseStudent.objects.current_course(user)
    courses = CourseStudent.objects.current_courses(user)
    num_courses = courses.count()
    if courses:
        xp_per_course = user.profile.xp_cached / num_courses
    else:
        xp_per_course = None

    context = {
        'user': user,
        'obj': course_student,
        'courses': courses,
        'xp_per_course': xp_per_course,
        'num_courses': num_courses,
    }
    return render(request, template_name, context)
Пример #11
0
 def test_submission_get_previous(self):
     """ If this is a repeatable quest and has been completed already, return that previous submission """
     repeat_quest = baker.make(Quest,
                               name="repeatable-quest",
                               max_repeats=-1)
     first_sub = baker.make(QuestSubmission,
                            user=self.student,
                            quest=repeat_quest,
                            semester=self.semester)
     self.assertIsNone(first_sub.get_previous())
     # need to complete so can make another
     first_sub.mark_completed()
     SiteConfig.get().set_active_semester(first_sub.semester.id)
     second_sub = QuestSubmission.objects.create_submission(
         user=self.student, quest=repeat_quest)
     self.assertEqual(first_sub, second_sub.get_previous())
Пример #12
0
 def setUp(self):
     """TenantTestCase generates a tenant for tests.
     Each tenant should have a single SiteConfig object 
     that is created upon first access via the get() method.
     """
     self.config = SiteConfig.get()
     self.client = TenantClient(self.tenant)
Пример #13
0
def submission(request, submission_id=None, quest_id=None):
    # sub = QuestSubmission.objects.get(id = submission_id)
    sub = get_object_or_404(QuestSubmission, pk=submission_id)
    if sub.user != request.user and not request.user.is_staff:
        return redirect('quests:quests')

    if request.user.is_staff:
        # Staff form has additional fields such as award granting.
        main_comment_form = SubmissionFormStaff(request.POST or None)
    else:
        initial = {'comment_text': sub.draft_text}
        main_comment_form = SubmissionForm(request.POST or None,
                                           initial=initial)

    # main_comment_form = CommentForm(request.POST or None, wysiwyg=True, label="")
    # reply_comment_form = CommentForm(request.POST or None, label="")
    # comments = Comment.objects.all_with_target_object(sub)

    context = {
        "heading": sub.quest_name(),
        "submission": sub,
        "q": sub.
        quest,  # allows for common data to be displayed on sidebar more easily...
        # "comments": comments,
        "submission_form": main_comment_form,
        # "reply_comment_form": reply_comment_form,
        "quick_reply_text": SiteConfig.get().submission_quick_text,
    }
    return render(request, 'quest_manager/submission.html', context)
Пример #14
0
 def test_quest_submission_manager_all_for_user_quest(self):
     """
     QuestSubmissionManager.all_for_user_quest should return all visible not archived quest submissions
     for active semester, given user and quest
     """
     submissions = self.make_test_submissions_stack()
     active_semester = submissions[0].semester
     quest = submissions[0].quest
     first = baker.make(QuestSubmission,
                        user=self.student,
                        quest=quest,
                        semester=active_semester)
     SiteConfig.get().set_active_semester(active_semester)
     qs = QuestSubmission.objects.all_for_user_quest(
         self.student, quest, True).values_list('id', flat=True)
     self.assertListEqual(list(qs), [first.id])
Пример #15
0
    def setUp(self):
        self.client = TenantClient(self.tenant)
        self.sem = SiteConfig.get().active_semester

        self.teacher = Recipe(User, is_staff=True).make(
        )  # need a teacher or student creation will fail.
        self.student = baker.make(User)
Пример #16
0
 def setUp(self):
     self.student = baker.make(User)
     self.course = baker.make(Course)
     self.course_student = baker.make(
         CourseStudent,
         user=self.student,
         course=self.course,
         semester=SiteConfig.get().active_semester)
Пример #17
0
 def all_users_for_active_semester(self, students_only=False):
     """
     :return: queryset of all Users who are enrolled in a course during the active semester (doubles removed)
     """
     courses = self.all_for_semester(SiteConfig.get().active_semester,
                                     students_only=students_only)
     user_list = courses.values_list('user', flat=True)
     user_list = set(user_list)  # removes doubles
     return User.objects.filter(id__in=user_list)
Пример #18
0
    def test_profile_recalculate_xp_status_codes(self):
        """Need to test this view with students in an active course"""
        # why testing this here?
        self.assertEqual(self.active_sem.pk,
                         SiteConfig.get().active_semester.pk)

        self.assertEqual(
            self.client.get(
                reverse('profiles:recalculate_xp_current')).status_code, 302)
Пример #19
0
 def test_set_active(self):
     """ Only one active semester, so should also set all others to active=False  """
     current_sem = SiteConfig.get().active_semester
     self.assertTrue(current_sem.active)
     Semester.objects.set_active(self.semester1.id)
     self.semester1.refresh_from_db()
     self.assertTrue(self.semester1.active)
     # previous active semester is now not
     current_sem.refresh_from_db()
     self.assertFalse(current_sem.active)
Пример #20
0
def save_announcement_signal(sender, instance, **kwargs):
    """ After an announcement is saves, check if it's a draft and that it should auto-publish the results.
    If it should, then check if there is already a beat task scheduled and replace it, or create a new schedule
    """

    task_name = "Autopublication task for announcement #{}".format(instance.id)

    if instance.draft and instance.auto_publish:

        sending_user, _ = User.objects.get_or_create(
            pk=SiteConfig.get().deck_ai.pk,
            defaults={
                'username':
                "******",
                'password':
                "******",
            },
        )

        schedule, _ = ClockedSchedule.objects.get_or_create(
            clocked_time=instance.datetime_released)

        # PeriodicTask doesn't have an update_or_create method for some reason, so do it long way
        # https://github.com/celery/django-celery-beat/issues/106
        defaults = {
            'clocked': schedule,
            'task': 'announcements.tasks.publish_announcement',
            'queue': 'default',
            'kwargs': json.dumps({  # beat needs json serializable args, so make sure they are
                'user_id': sending_user.id,
                'announcement_id': instance.id,
                'absolute_url': instance.get_absolute_url(),
            }),
            'one_off': True,
            'enabled': True,
        }

        try:
            task = PeriodicTask.objects.get(name=task_name)
            for key, value in defaults.items():
                setattr(task, key, value)
            task.save()
        except PeriodicTask.DoesNotExist:
            new_values = {'name': task_name}
            new_values.update(defaults)
            task = PeriodicTask(**new_values)
            task.save()

    else:  # There shouldn't be a task so delete if it exists
        try:
            task = PeriodicTask.objects.get(name=task_name)
            task.delete()
        except PeriodicTask.DoesNotExist:
            pass
Пример #21
0
    def test_condition_met_as_prerequisite(self):
        """ If the user is CURRENTLY registered in this course, then condition is met """
        student = baker.make(User)
        baker.make(CourseStudent, user=student, course=self.course)
        self.assertFalse(self.course.condition_met_as_prerequisite(student, 1))

        baker.make(CourseStudent,
                   user=student,
                   course=self.course,
                   semester=SiteConfig.get().active_semester)
        self.assertTrue(self.course.condition_met_as_prerequisite(student, 1))
Пример #22
0
    def create_assertion(self,
                         user,
                         badge,
                         issued_by=None,
                         transfer=False,
                         active_semester=None):
        ordinal = self.get_assertion_ordinal(user, badge)
        if issued_by is None:
            issued_by = get_object_or_404(User, pk=SiteConfig.get().deck_ai.pk)

        if not active_semester:
            active_semester = SiteConfig.get().active_semester.id

        new_assertion = BadgeAssertion(badge=badge,
                                       user=user,
                                       ordinal=ordinal,
                                       issued_by=issued_by,
                                       game_lab_transfer=transfer,
                                       semester_id=active_semester)
        new_assertion.save()
        user.profile.xp_invalidate_cache()  # recalculate user's XP
        return new_assertion
Пример #23
0
    def get_queryset(self,
                     active_semester_only=False,
                     exclude_archived_quests=True,
                     exclude_quests_not_visible_to_students=True):

        qs = QuestSubmissionQuerySet(self.model, using=self._db)
        if active_semester_only:
            qs = qs.get_semester(SiteConfig.get().active_semester.pk)
        if exclude_archived_quests:
            qs = qs.exclude_archived_quests()
        if exclude_quests_not_visible_to_students:
            qs = qs.exclude_quests_not_visible_to_students()
        return qs.select_related('quest')
Пример #24
0
def config(request):
    """
    Simple context processor that puts the config into every
    RequestContext, except those coming from the public schema,
    which doesn't include the config app.
        TEMPLATE_CONTEXT_PROCESSORS = (
            # ...
            'siteconfig.context_processors.config',
        )
    """
    if connection.schema_name != get_public_schema_name():
        return {"config": SiteConfig.get()}
    return {"config": None}
Пример #25
0
    def setUp(self):
        self.client = TenantClient(self.tenant)
        self.sem = SiteConfig.get().active_semester

        self.teacher = Recipe(User, is_staff=True).make(
        )  # need a teacher or student creation will fail.
        self.student = baker.make(User)
        self.assertion = baker.make(BadgeAssertion, semester=self.sem)
        self.badge = Recipe(Badge, xp=20).make()

        self.badge_assertion_recipe = Recipe(BadgeAssertion,
                                             user=self.student,
                                             badge=self.badge,
                                             semester=self.sem)
Пример #26
0
    def setUp(self):
        self.client = TenantClient(self.tenant)
        User = get_user_model()
        self.sem = SiteConfig.get().active_semester

        # need a teacher and a student with known password so tests can log in as each, or could use force_login()?
        self.test_password = "******"

        # need a teacher before students can be created or the profile creation will fail when trying to notify
        self.test_teacher = User.objects.create_user('test_teacher', password=self.test_password, is_staff=True)
        self.test_student1 = User.objects.create_user('test_student', password=self.test_password)
        self.test_student2 = mommy.make(User)

        self.quest1 = mommy.make(Quest)
        self.quest2 = mommy.make(Quest)
Пример #27
0
    def move_incomplete_to_active_semester(self):
        """ Called when changing Active Semesters, however should be uneccessary
        as Closing a semester removes all incomplete quests.

        Not sure why you would need to change active semester without having
        closed other, perhaps to look at old quests?

        Either way, this prevents them from getting stuck in an inactive semester
        """
        # submitted but not accepted
        qs = self.all_not_approved(active_semester_only=False)
        # print("NOT APPROVED ********")
        # print(qs)
        for sub in qs:
            sub.semester_id = SiteConfig.get().active_semester.id
            sub.save()

        # started but not submitted
        qs = self.all_not_completed(active_semester_only=False)
        # print("NOT COMPLETED ********")
        # print(qs)
        for sub in qs:
            sub.semester_id = SiteConfig.get().active_semester.id
            sub.save()
Пример #28
0
 def create_submission(self, user, quest):
     # this logic should probably be removed from this location?
     # When would I want to return None that isn't already handled?
     if self.not_submitted_or_inprogress(user, quest):
         ordinal = self.num_submissions(user, quest) + 1
         new_submission = QuestSubmission(
             quest=quest,
             user=user,
             ordinal=ordinal,
             semester_id=SiteConfig.get().active_semester.pk,
         )
         new_submission.save()
         return new_submission
     else:
         return None
Пример #29
0
    def setUp(self):
        self.announcement = baker.make(Announcement)

        # need a teacher before students can be created or the profile creation will fail when trying to notify
        self.test_teacher = User.objects.create_user('test_teacher',
                                                     is_staff=True)
        self.test_student1 = User.objects.create_user('test_student')
        self.test_student2 = baker.make(User)

        self.ai_user, _ = User.objects.get_or_create(
            pk=SiteConfig.get().deck_ai.pk,
            defaults={
                'username': "******",
            },
        )
Пример #30
0
    def setUp(self):
        self.client = TenantClient(self.tenant)
        User = get_user_model()

        # need a teacher and a student with known password so tests can log in as each, or could use force_login()?
        self.test_password = "******"

        # need a teacher before students can be created or the profile creation will fail when trying to notify
        self.test_teacher = User.objects.create_user(
            'test_teacher', password=self.test_password, is_staff=True)
        self.test_student1 = User.objects.create_user(
            'test_student', password=self.test_password)
        self.test_student2 = baker.make(User)

        # create semester with pk of default semester
        # this seems backward, but no semesters should exist yet in the test, so their shouldn't be any conflicts.
        self.active_sem = SiteConfig.get().active_semester