class TestRestPassedInPreviousPeriod(TransactionTestCase):
    def setUp(self):
        self.testhelper = TestHelper()
        self.testhelper.add(nodes='uni',
                            subjects=['sub'],
                            periods=['old:begins(-14):ends(6)', # 14 months ago
                                     'cur:begins(-2)'], # 2 months ago
                            assignments=['a1:admin(adm):pub(0)']) # 0 days after period begins
        self.client = RestClient()
        self.url = '/devilry_subjectadmin/rest/passedinpreviousperiod/{0}'.format(self.testhelper.sub_cur_a1.id)

    def _getas(self, username, **data):
        self.client.login(username=username, password='******')
        return self.client.rest_get(self.url, **data)

    def _test_get_simple_as(self, username):
        self.testhelper.add_to_path('uni;sub.cur.a1.g1:candidate(student1)')
        content, response = self._getas(username)
        self.assertEquals(response.status_code, 200)
        self.assertEquals(len(content), 1)
        item = content[0]
        self.assertEquals(item['group']['id'], self.testhelper.sub_cur_a1_g1.id)
        self.assertEquals(item['oldgroup'], None)
        self.assertEquals(item['whyignored'], 'not_in_previous')

    def test_get_simple_as_assignmentadmin(self):
        self._test_get_simple_as('adm')

    def test_get_simple_as_superuser(self):
        self.testhelper.create_superuser('super')
        self._test_get_simple_as('super')

    def test_get_as_nobody(self):
        self.testhelper.create_user('nobody')
        content, response = self._getas('nobody')
        self.assertEquals(response.status_code, 403)


    def test_with_oldfeedback(self):
        # Add a group for the student on the old period
        self.testhelper.add_to_path('uni;sub.old.a1.g1:candidate(student1):examiner(examiner1).d1:ends(1)')
        self.testhelper.create_feedbacks(
            (self.testhelper.sub_old_a1_g1, {'grade': 'approved', 'points': 1, 'is_passing_grade': True})
        )

        # Add the student to the current period
        self.testhelper.add_to_path('uni;sub.cur.a1.g1:candidate(student1)')

        content, response = self._getas('adm')
        self.assertEquals(response.status_code, 200)
        self.assertEquals(len(content), 1)
        item = content[0]
        self.assertEquals(item['group']['id'], self.testhelper.sub_cur_a1_g1.id)
        self.assertEquals(item['whyignored'], None)
        self.assertNotEquals(item['oldgroup'], None)
        oldgroup = item['oldgroup']
        self.assertEqual(oldgroup['id'], self.testhelper.sub_old_a1_g1.id)
        self.assertEqual(oldgroup['assignment']['id'], self.testhelper.sub_old_a1.id)
        self.assertEqual(oldgroup['period']['id'], self.testhelper.sub_old.id)
        self.assertEqual(oldgroup['feedback_shortformat'], 'true')



    def _putas(self, username, data):
        self.client.login(username=username, password='******')
        return self.client.rest_put(self.url, data)

    def _test_putas(self, username):
        self.testhelper.add_to_path('uni;sub.cur.a1.g1:candidate(student1).d1')
        self.testhelper.add_to_path('uni;sub.cur.a1.g2:candidate(student2).d1')
        self.testhelper.add_to_path('uni;sub.cur.a1.g3:candidate(student3).d1')

        self.testhelper.add_to_path('uni;sub.old.a1.g3:candidate(student3):examiner(examiner1).d1')
        oldg3_delivery = self.testhelper.add_delivery(self.testhelper.sub_old_a1_g3)
        self.testhelper.add_feedback(oldg3_delivery,
                                     verdict=dict(grade='C', points=40,
                                                  is_passing_grade=True))

        g1 = self.testhelper.sub_cur_a1_g1
        g2 = self.testhelper.sub_cur_a1_g2
        g3 = self.testhelper.sub_cur_a1_g3
        content, response = self._putas(username,
                                        [{'id': g1.id,
                                          'newfeedback_shortformat': 'true'},
                                         {'id': g3.id,
                                          'newfeedback_shortformat': 'true'}])
        self.assertEquals(response.status_code, 200)

        g1 = self.testhelper.reload_from_db(g1)
        self.assertEquals(g1.feedback.grade, 'approved')
        self.assertEquals(g1.feedback.delivery.delivery_type, deliverytypes.ALIAS)

        g2 = self.testhelper.reload_from_db(g2)
        self.assertEquals(g2.feedback, None)

        g3 = self.testhelper.reload_from_db(g3)
        self.assertEquals(g3.feedback.grade, 'approved')
        self.assertEquals(g3.feedback.delivery.delivery_type, deliverytypes.ALIAS)
        self.assertEquals(g3.feedback.delivery.alias_delivery, oldg3_delivery)

    def test_put_as_assignmentadmin(self):
        self._test_putas('adm')

    def test_put_as_superuser(self):
        self.testhelper.create_superuser('super')
        self._test_putas('super')

    def test_put_as_nobody(self):
        self.testhelper.create_user('nobody')
        content, response = self._putas('nobody', [])
        self.assertEquals(response.status_code, 403)


    def test_put_shortformat_validationerror(self):
        self.testhelper.add_to_path('uni;sub.cur.a1.g1:candidate(student1).d1')
        g1 = self.testhelper.sub_cur_a1_g1
        content, response = self._putas('adm',
            [{'id': g1.id,
              'newfeedback_shortformat': 'invalidstuff'}])
        self.assertEquals(response.status_code, 400)
        self.assertEquals(content['errors'][0], u'Must be one of: true, false.')
Esempio n. 2
0
class TestRestDeadlinesBulkCreate(TestCase):
    def setUp(self):
        self.testhelper = TestHelper()
        self.testhelper.add(nodes='uni',
                            subjects=['sub'],
                            periods=['p1:begins(-2)']) # 2 months ago 
        self.testhelper.sub_p1.start_time = datetime(2000, 1, 1, 22, 30, 49)
        self.testhelper.sub_p1.save()
        self.testhelper.add_to_path('uni;sub.p1.a1:admin(adm):pub(0)') # 0 days after period begins + 2 sec
        self.client = RestClient()

        for groupnum in xrange(3):
            # deadline 5 days after assignment starts
            self.testhelper.add_to_path('uni;sub.p1.a1.g{0}:candidate(cand1):examiner(exam1).d1:ends(5)'.format(groupnum))


    def _geturl(self):
        return '/devilry_subjectadmin/rest/deadlinesbulk/{0}/'.format(self.testhelper.sub_p1_a1.id)

    def _postas(self, username, data):
        self.client.login(username=username, password='******')
        return self.client.rest_post(self._geturl(), data)

    def _itergroups(self):
        for groupnum in xrange(3):
            group_id = getattr(self.testhelper, 'sub_p1_a1_g{0}'.format(groupnum)).id
            group = AssignmentGroup.objects.get(id=group_id)
            yield group

    def test_post_no_matching_groups(self):
        for group in self._itergroups():
            deadlines = group.deadlines.all().order_by('-deadline')
            self.assertEquals(group.feedback, None)
        new_deadline = datetime(2004, 12, 24, 20, 30)
        content, response = self._postas('adm', {'deadline': format_datetime(new_deadline),
                                                 'text': 'Created',
                                                 'createmode': 'failed'})
        self.assertEquals(response.status_code, 400)
        self.assertEquals(content['field_errors']['createmode'], ['The given option did not match any groups.'])

    def test_post_createmode_failed(self):
        self.testhelper.add_delivery('sub.p1.a1.g1', {'bad.py': ['print ', 'bah']})
        self.testhelper.add_feedback('sub.p1.a1.g1', verdict={'grade': 'F', 'points': 30, 'is_passing_grade': False})
        g1 = AssignmentGroup.objects.get(id=self.testhelper.sub_p1_a1_g1.id)
        self.assertFalse(g1.is_open)


        new_deadline = datetime(2004, 12, 24, 20, 30)
        self.assertEquals(Deadline.objects.filter(deadline=new_deadline).count(), 0)
        content, response = self._postas('adm', {'deadline': format_datetime(new_deadline),
                                                 'text': 'Created',
                                                 'createmode': 'failed'})

        # Check response
        self.assertEquals(response.status_code, 201)
        self.assertEquals(decode_bulkdeadline_id(content['bulkdeadline_id'])[0],
                          new_deadline)
        self.assertEquals(len(content['groups']), 1)
        self.assertEquals(content['text'], 'Created')
        self.assertEquals(content['deadline'], format_datetime(new_deadline))

        # Check actual data
        self.assertEquals(Deadline.objects.filter(deadline=new_deadline).count(), 1)
        g1 = AssignmentGroup.objects.get(id=self.testhelper.sub_p1_a1_g1.id)
        deadlines = g1.deadlines.all().order_by('-deadline')
        self.assertEquals(len(deadlines), 2)
        self.assertEquals(deadlines[0].deadline, new_deadline)
        self.assertEquals(deadlines[0].text, 'Created')
        self.assertTrue(g1.is_open) # Group was automatically opened in devilry.apps.core.models.Deadline.save()

    def test_post_createmode_failed_or_no_feedback(self):
        # Fail g0
        self.testhelper.add_delivery('sub.p1.a1.g0', {'bad.py': ['print ', 'bah']})
        self.testhelper.add_feedback('sub.p1.a1.g0', verdict={'grade': 'F', 'points': 30, 'is_passing_grade': False})
        # Pass g1
        self.testhelper.add_delivery('sub.p1.a1.g1', {'good.py': ['print ', 'bah']})
        self.testhelper.add_feedback('sub.p1.a1.g1', verdict={'grade': 'A', 'points': 100, 'is_passing_grade': True})
        # g2 has no feedback
        self.assertEquals(self.testhelper.sub_p1_a1_g2.feedback, None)

        new_deadline = datetime(2004, 12, 24, 20, 30)
        self.assertEquals(Deadline.objects.filter(deadline=new_deadline).count(), 0)
        content, response = self._postas('adm', {'deadline': format_datetime(new_deadline),
                                                 'text': 'Created',
                                                 'createmode': 'failed-or-no-feedback'})

        # Check response
        self.assertEquals(response.status_code, 201)
        self.assertEquals(len(content['groups']), 2)

        # Check actual data
        self.assertEquals(Deadline.objects.filter(deadline=new_deadline).count(), 2)
        g0 = self.testhelper.sub_p1_a1_g0
        g2 = self.testhelper.sub_p1_a1_g2
        for group in (g0, g2):
            deadlines = group.deadlines.all().order_by('-deadline')
            self.assertEquals(len(deadlines), 2)
            self.assertEquals(deadlines[0].deadline, new_deadline)
            self.assertEquals(deadlines[0].text, 'Created')
        g1 = self.testhelper.sub_p1_a1_g1
        self.assertEquals(g1.deadlines.count(), 1) # We did not a deadline to g1 because they have passing grade

    def test_post_createmode_no_deadlines(self):
        self.assertEquals(self.testhelper.sub_p1_a1_g1.deadlines.count(), 1)
        self.testhelper.add_to_path('uni;sub.p1.a1.extragroup')
        self.assertEquals(self.testhelper.sub_p1_a1_extragroup.deadlines.count(), 0)

        new_deadline = datetime(2004, 12, 24, 20, 30)
        self.assertEquals(Deadline.objects.filter(deadline=new_deadline).count(), 0)
        content, response = self._postas('adm', {'deadline': format_datetime(new_deadline),
                                                 'text': 'Created',
                                                 'createmode': 'no-deadlines'})

        # Check response
        self.assertEquals(response.status_code, 201)
        self.assertEquals(decode_bulkdeadline_id(content['bulkdeadline_id'])[0],
                          new_deadline)
        self.assertEquals(len(content['groups']), 1)
        self.assertEquals(content['text'], 'Created')
        self.assertEquals(content['deadline'], format_datetime(new_deadline))

        # Check actual data
        self.assertEquals(Deadline.objects.filter(deadline=new_deadline).count(), 1)
        extragroup = AssignmentGroup.objects.get(id=self.testhelper.sub_p1_a1_extragroup.id)
        deadlines = extragroup.deadlines.all()
        self.assertEquals(len(deadlines), 1)
        self.assertEquals(deadlines[0].deadline, new_deadline)
        self.assertEquals(deadlines[0].text, 'Created')
        self.assertTrue(extragroup.is_open) # Group was automatically opened in devilry.apps.core.models.Deadline.save()

    def test_post_createmode_specific_groups(self):
        self.assertEquals(self.testhelper.sub_p1_a1_g1.deadlines.count(), 1)
        self.assertEquals(self.testhelper.sub_p1_a1_g2.deadlines.count(), 1)

        new_deadline = datetime(2004, 12, 24, 20, 30)
        self.assertEquals(Deadline.objects.filter(deadline=new_deadline).count(), 0)
        content, response = self._postas('adm', {'deadline': format_datetime(new_deadline),
                                                 'text': 'Created',
                                                 'group_ids': [self.testhelper.sub_p1_a1_g1.id,
                                                               self.testhelper.sub_p1_a1_g2.id],
                                                 'createmode': 'specific-groups'})

        # Check response
        self.assertEquals(response.status_code, 201)
        self.assertEquals(decode_bulkdeadline_id(content['bulkdeadline_id'])[0],
                          new_deadline)
        self.assertEquals(len(content['groups']), 2)
        self.assertEquals(content['text'], 'Created')
        self.assertEquals(content['deadline'], format_datetime(new_deadline))

        # Check actual data
        self.assertEquals(Deadline.objects.filter(deadline=new_deadline).count(), 2)
        g1 = self.testhelper.reload_from_db(self.testhelper.sub_p1_a1_g1)
        deadlines = g1.deadlines.all()
        self.assertEquals(len(deadlines), 2)
        self.assertEquals(deadlines[0].deadline, new_deadline)
        self.assertEquals(deadlines[0].text, 'Created')

    def test_post_createmode_specific_groups_nogroups(self):
        new_deadline = datetime(2004, 12, 24, 20, 30)
        self.assertEquals(Deadline.objects.filter(deadline=new_deadline).count(), 0)
        content, response = self._postas('adm', {'deadline': format_datetime(new_deadline),
                                                 'text': 'Created',
                                                 'createmode': 'specific-groups'})
        self.assertEquals(response.status_code, 400)
        self.assertEquals(content['field_errors']['group_ids'][0],
                          '``group_ids`` is required when ``createmode=="specific-groups"``.')

    def test_post_nobody(self):
        self.testhelper.create_user('nobody')
        content, response = self._postas('nobody', {})
        self.assertEquals(response.status_code, 403)
Esempio n. 3
0
class TestRestDeadlinesBulkUpdateReadOrDelete(TestCase):
    def setUp(self):
        self.testhelper = TestHelper()
        self.testhelper.add(nodes='uni',
                            subjects=['sub'],
                            periods=['p1:begins(-2)']) # 2 months ago 
        self.testhelper.sub_p1.start_time = datetime(2000, 1, 1, 22, 30, 49)
        self.testhelper.sub_p1.save()
        self.testhelper.add_to_path('uni;sub.p1.a1:admin(adm):pub(0)') # 0 days after period begins + 2 sec
        self.client = RestClient()

        for groupnum in xrange(3):
            # deadline 5 days after assignment starts
            self.testhelper.add_to_path('uni;sub.p1.a1.g{0}:candidate(cand1):examiner(exam1).d1:ends(5)'.format(groupnum))


    def _geturl(self, deadline=None):
        deadline = deadline or self.testhelper.sub_p1_a1_g1_d1
        bulkdeadline_id = encode_bulkdeadline_id(deadline)
        return '/devilry_subjectadmin/rest/deadlinesbulk/{0}/{1}'.format(self.testhelper.sub_p1_a1.id,
                                                                         bulkdeadline_id)

    def test_encode_unique_bulkdeadline_id(self):
        d = Deadline(deadline=datetime(2000, 12, 24, 22, 30, 49))
        self.assertEquals(encode_bulkdeadline_id(d),
                          '2000-12-24T22_30_49--')
        d.text = 'Hello world'
        self.assertEquals(encode_bulkdeadline_id(d),
                          '2000-12-24T22_30_49--{0}'.format(sha1hash('Hello world')))
        # Ensure unicode works
        d.text = u'\u00e5ello world'
        self.assertEquals(encode_bulkdeadline_id(d),
                          '2000-12-24T22_30_49--{0}'.format(sha1hash(u'\u00e5ello world')))


    def test_decode_unique_bulkdeadline_id(self):
        self.assertEquals(decode_bulkdeadline_id('2000-12-24T22_30_49--'),
                          (datetime(2000, 12, 24, 22, 30, 49), ''))
        self.assertEquals(decode_bulkdeadline_id('2000-12-24T22_30_49--{0}'.format(sha1hash('Hello world'))),
                          (datetime(2000, 12, 24, 22, 30, 49), sha1hash('Hello world')))


    def _putas(self, username, data):
        self.client.login(username=username, password='******')
        return self.client.rest_put(self._geturl(), data)

    def test_put(self):
        self.assertEquals(self.testhelper.sub_p1_a1.publishing_time, datetime(2000, 1, 1, 22, 30, 51))
        self.assertEquals(self.testhelper.sub_p1_a1_g1_d1.deadline,
                          datetime(2000, 1, 1, 22, 30) + timedelta(days=5))

        new_deadline = datetime(2004, 12, 24, 20, 30)
        content, response = self._putas('adm', {'deadline': format_datetime(new_deadline),
                                                'text': 'Hello'})
        self.assertEquals(response.status_code, 200)
        self.assertEquals(decode_bulkdeadline_id(content['bulkdeadline_id'])[0],
                          new_deadline)
        self.assertEquals(len(content['groups']), 3)
        self.assertEquals(content['text'], 'Hello')
        self.assertEquals(content['deadline'], format_datetime(new_deadline))
        for groupnum in xrange(3):
            deadline_id = getattr(self.testhelper, 'sub_p1_a1_g{0}_d1'.format(groupnum)).id
            deadline = Deadline.objects.get(id=deadline_id)
            self.assertEquals(deadline.deadline, new_deadline)
            self.assertEquals(deadline.text, 'Hello')

    def test_put_nonetext(self):
        self.assertEquals(self.testhelper.sub_p1_a1.publishing_time, datetime(2000, 1, 1, 22, 30, 51))
        self.assertEquals(self.testhelper.sub_p1_a1_g1_d1.deadline,
                          datetime(2000, 1, 1, 22, 30) + timedelta(days=5))

        new_deadline = datetime(2004, 12, 24, 20, 30)
        content, response = self._putas('adm', {'deadline': format_datetime(new_deadline),
                                                'text': None})
        self.assertEquals(response.status_code, 200)
        for groupnum in xrange(3):
            deadline_id = getattr(self.testhelper, 'sub_p1_a1_g{0}_d1'.format(groupnum)).id
            deadline = Deadline.objects.get(id=deadline_id)
            self.assertEquals(deadline.deadline, new_deadline)
            self.assertEquals(deadline.text, '')

    def test_put_before_publishingtime(self):
        new_deadline = datetime(1990, 1, 1, 20, 30, 40)
        content, response = self._putas('adm', {'deadline': format_datetime(new_deadline),
                                                'text': None})
        self.assertEquals(response.status_code, 400)
        self.assertEquals(content['errors'], ['Deadline cannot be before publishing time.'])

    def test_put_nobody(self):
        self.testhelper.create_user('nobody')
        content, response = self._putas('nobody', {})
        self.assertEquals(response.status_code, 403)

    def test_put_with_bulkdeadline_id(self):
        new_deadline = datetime(2004, 12, 24, 20, 30)
        content, response = self._putas('adm', {'deadline': format_datetime(new_deadline),
                                                'bulkdeadline_id': 'ignored'})
        self.assertEquals(response.status_code, 200)

    def test_put_group_ids(self):
        new_deadline = datetime(2004, 12, 24, 20, 30)
        g1 = self.testhelper.sub_p1_a1_g1
        g2 = self.testhelper.sub_p1_a1_g2
        self.assertEquals(g1.deadlines.count(), 1)

        content, response = self._putas('adm', {'deadline': format_datetime(new_deadline),
                                                'text': 'Updated',
                                                'group_ids': [g1.id, g2.id]})
        self.assertEquals(response.status_code, 200)
        self.assertEquals(len(content['groups']), 2)
        group_ids = set([g['id'] for g in content['groups']])
        self.assertEquals(group_ids, set([g1.id, g2.id]))

        for group in g1, g2:
            group = self.testhelper.reload_from_db(group)
            self.assertEquals(group.deadlines.count(), 1)
            deadline = group.deadlines.all()[0]
            self.assertEquals(deadline.deadline, new_deadline)
            self.assertEquals(deadline.text, 'Updated')



    def _getas(self, username, **data):
        self.client.login(username=username, password='******')
        return self.client.rest_get(self._geturl(), **data)

    def test_get(self):
        content, response = self._getas('adm')
        self.assertEquals(response.status_code, 200)
        self.assertEquals(decode_bulkdeadline_id(content['bulkdeadline_id'])[0],
                          self.testhelper.sub_p1_a1_g1_d1.deadline)
        self.assertEquals(content['deadline'],
                          format_datetime(self.testhelper.sub_p1_a1_g1_d1.deadline))
        self.assertEquals(content['text'], None)
        self.assertEquals(len(content['groups']), 3)

    def test_get_nobody(self):
        self.testhelper.create_user('nobody')
        content, response = self._getas('nobody')
        self.assertEquals(response.status_code, 403)

    def _deleteas(self, username, deadline=None):
        self.client.login(username=username, password='******')
        return self.client.rest_delete(self._geturl(deadline))

    def test_delete_sanity(self):
        # Test that the deadline method actually does what it is supposed to do (only deletes what it should delete)
        new_deadline = datetime(2004, 12, 24, 20, 30)
        created_deadline = None
        for groupnum in xrange(2):
            group = getattr(self.testhelper, 'sub_p1_a1_g{0}'.format(groupnum))
            self.assertEquals(1, group.deadlines.count())
            created_deadline = group.deadlines.create(deadline=new_deadline) # NOTE: Does not matter which deadline object we user, since we only need the datetime and text to generate bulkdeadline_id
            self.assertEquals(2, group.deadlines.count())
        self.testhelper.sub_p1_a1_g2.deadlines.create(deadline=datetime(2006, 12, 24, 20, 30))

        self.testhelper.create_superuser('superuser')
        content, response = self._deleteas('superuser', deadline=created_deadline)
        self.assertEquals(response.status_code, 200)
        self.assertEquals(len(content['deleted_deadline_ids']), 2)
        self.assertEquals(1, self.testhelper.sub_p1_a1_g0.deadlines.count())
        self.assertEquals(1, self.testhelper.sub_p1_a1_g1.deadlines.count())
        self.assertEquals(2, self.testhelper.sub_p1_a1_g2.deadlines.count())

    def test_delete_with_content_as_superuser(self):
        self.testhelper.create_superuser('superuser')
        self.testhelper.add_delivery('sub.p1.a1.g1', {'bad.py': ['print ', 'bah']})
        self.testhelper.add_feedback('sub.p1.a1.g1', verdict={'grade': 'F', 'points': 30, 'is_passing_grade': False})
        content, response = self._deleteas('superuser')
        self.assertEquals(response.status_code, 200)

    def test_delete_with_content_as_assignmentadm(self):
        self.testhelper.add_delivery('sub.p1.a1.g1', {'bad.py': ['print ', 'bah']})
        self.testhelper.add_feedback('sub.p1.a1.g1', verdict={'grade': 'F', 'points': 30, 'is_passing_grade': False})
        content, response = self._deleteas('adm')
        self.assertEquals(response.status_code, 403)

    def test_delete_without_content_as_assignmentadm(self):
        content, response = self._deleteas('adm')
        self.assertEquals(response.status_code, 200)

    def test_delete_as_nobody(self):
        self.testhelper.create_user('nobody')
        content, response = self._deleteas('nobody')
        self.assertEquals(response.status_code, 403)
class TestCreateNewPeriod(SubjectAdminSeleniumTestCase):
    def setUp(self):
        self.testhelper = TestHelper()
        self.testhelper.add(nodes='uni',
                            subjects=['sub:admin(subadmin)'])

    def _loginTo(self, username, id):
        self.loginTo(username, '/subject/{id}/@@create-new-period'.format(id=id))

    def _waitForFields(self):
        self.short_name_field = self.waitForAndFindElementByCssSelector('input[name=short_name]')
        self.long_name_field = self.waitForAndFindElementByCssSelector('input[name=long_name]')
        self.start_time_datefield = self.waitForAndFindElementByCssSelector('.start_time_field .devilry_extjsextras_datefield input')
        self.start_time_timefield = self.waitForAndFindElementByCssSelector('.start_time_field .devilry_extjsextras_timefield input')
        self.end_time_datefield = self.waitForAndFindElementByCssSelector('.end_time_field .devilry_extjsextras_datefield input')
        self.end_time_timefield = self.waitForAndFindElementByCssSelector('.end_time_field .devilry_extjsextras_timefield input')
        self.savebutton = self.waitForAndFindElementByCssSelector('.devilry_primarybutton button')

    def _set_values(self,
                    short_name,
                    long_name,
                    start_date, start_time,
                    end_date, end_time):
        self.long_name_field.clear()
        self.start_time_datefield.clear()
        self.start_time_timefield.clear()
        self.end_time_datefield.clear()
        self.end_time_timefield.clear()

        self.long_name_field.send_keys(long_name)
        self.start_time_datefield.send_keys(start_date)
        self.start_time_timefield.send_keys(start_time)
        self.end_time_datefield.send_keys(end_date)
        self.end_time_timefield.send_keys(end_time)

        self.short_name_field.clear()
        self.short_name_field.send_keys(short_name)

    def _waitForSaved(self):
        self.waitForCssSelector('.devilry_subjectadmin_periodoverview')

    def test_edit(self):
        self.assertEquals(self.testhelper.sub.periods.count(), 0)
        self._loginTo('subadmin', self.testhelper.sub.id)
        self._waitForFields()
        self.assertFalse(self.savebutton.is_enabled())
        self._set_values(short_name='p1',
                         long_name='Period One',
                         start_date='2000-12-24', start_time='12:00',
                         end_date='2001-11-22', end_time='16:00')
        self.waitForEnabled(self.savebutton)
        self.savebutton.click()
        self._waitForSaved()
        sub = self.testhelper.reload_from_db(self.testhelper.sub)

        self.assertEquals(sub.periods.count(), 1)
        p1 = sub.periods.all()[0]
        self.assertEquals(p1.long_name, 'Period One')
        self.assertEquals(p1.short_name, 'p1')
        self.assertEquals(p1.start_time, datetime(2000, 12, 24, 12, 0))
        self.assertEquals(p1.end_time, datetime(2001, 11, 22, 16, 0))
Esempio n. 5
0
class TestDeadlines(SubjectAdminSeleniumTestCase):
    def setUp(self):
        self.testhelper = TestHelper()
        self.testhelper.add(nodes='uni',
                            subjects=['sub'],
                            periods=['p1:begins(-2)'],
                            assignments=['a1:admin(a1admin):pub(1)'])
        self.assignment = self.testhelper.sub_p1_a1

    def _loginTo(self, username, assignmentid):
        self.loginTo(username, '/assignment/{id}/@@bulk-manage-deadlines/'.format(id=assignmentid))

    def _find_gridrows(self, grid):
        return grid.find_elements_by_css_selector('.x-grid-row')

    def _get_row_by_group(self, grid, group):
        cssselector = '.groupInfoWrapper_{id}'.format(id=group.id)
        self.waitFor(grid, lambda g: len(grid.find_elements_by_css_selector(cssselector)) == 1)
        for row in self._find_gridrows(grid):
            matches = row.find_elements_by_css_selector(cssselector)
            if len(matches) > 0:
                return row
        raise ValueError('Could not find any rows matching the following group: {0}.'.format(group))

    def _click_row_by_group(self, grid, group):
        self._get_row_by_group(grid, group).find_element_by_css_selector('.x-grid-row-checker').click()

    def _get_addbutton(self):
        return self.waitForAndFindElementByCssSelector('.add_deadline_button')

    def _open_addform(self):
        self._get_addbutton().click()
        return self.waitForAndFindElementByCssSelector('.devilry_subjectadmin_bulkmanagedeadlines_deadlineform.createdeadlineform')

    def _create_datestring_from_offset(self, dayoffset=1):
        now = datetime.now()
        datetimeObj = now + timedelta(days=1)
        datestring = datetimeObj.date().isoformat()
        return datestring

    def _create_badgroup(self):
        self.testhelper.add_to_path('uni;sub.p1.a1.badgroup:candidate(student1):examiner(examiner1).d1')
        badgroup = self.testhelper.sub_p1_a1_badgroup
        self.testhelper.add_delivery(badgroup, {'f.py': ['print ', 'meh']})
        self.testhelper.add_feedback(badgroup, verdict={'grade': 'F', 'points': 1, 'is_passing_grade': False})
        return badgroup

    def _create_goodgroup(self):
        self.testhelper.add_to_path('uni;sub.p1.a1.goodgroup:candidate(student1):examiner(examiner1).d1')
        goodgroup = self.testhelper.sub_p1_a1_goodgroup
        self.testhelper.add_delivery(goodgroup, {'a.py': ['print ', 'yess']})
        self.testhelper.add_feedback(goodgroup, verdict={'grade': 'A', 'points': 100, 'is_passing_grade': True})
        return goodgroup

    def _create_nodeadlinegroup(self):
        self.testhelper.add_to_path('uni;sub.p1.a1.nodeadlinegroup:candidate(student1):examiner(examiner1)')
        return self.testhelper.sub_p1_a1_nodeadlinegroup

    def _create_nofeedbackgroup(self):
        self.testhelper.add_to_path('uni;sub.p1.a1.nofeedbackgroup:candidate(student1):examiner(examiner1).d1')
        nofeedbackgroup = self.testhelper.sub_p1_a1_nofeedbackgroup
        self.testhelper.add_delivery(nofeedbackgroup, {'a.py': ['print ', 'yess']})
        return nofeedbackgroup

    def _get_formsavebutton(self, form):
        return form.find_element_by_css_selector('.savedeadlinebutton button')


    #
    #
    # Add deadline tests
    #
    #
    def _fill_addform(self, form, date, time, text='', createmodecls=None):
        datefield = self.waitForAndFindElementByCssSelector('.deadlinefield .devilry_extjsextras_datefield input[type=text]',
                                                            within=form)
        timefield = self.waitForAndFindElementByCssSelector('.deadlinefield .devilry_extjsextras_timefield input[type=text]',
                                                            within=form)
        textfield = self.waitForAndFindElementByCssSelector('textarea[name="text"]',
                                                            within=form)

        for field in (datefield, timefield, textfield):
            field.clear()
        datefield.send_keys(date)
        timefield.send_keys(time)
        textfield.send_keys(text)
        if createmodecls:
            checkbox = form.find_element_by_css_selector('.{0} input[type=button]'.format(createmodecls))
            checkbox.click()

    def test_add_deadline_failed(self):
        nodeadlinegroup = self._create_nodeadlinegroup()
        nofeedbackgroup = self._create_nofeedbackgroup()
        badgroup = self._create_badgroup()
        goodgroup = self._create_goodgroup()
        self.assertEquals(len(nodeadlinegroup.deadlines.all()), 0)
        self.assertEquals(len(nofeedbackgroup.deadlines.all()), 1)
        self.assertEquals(len(badgroup.deadlines.all()), 1)
        self.assertEquals(len(goodgroup.deadlines.all()), 1)

        self._loginTo('a1admin', self.assignment.id)
        addform = self._open_addform()
        self._fill_addform(addform, date=self._create_datestring_from_offset(2),
                        time='12:00', text='Hello', createmodecls='createmode_failed')

        url = self.selenium.current_url
        self._get_formsavebutton(addform).click()
        self.waitFor(self.selenium, lambda s: s.current_url != url) # Wait for the page to be reloaded with the new deadline URL

        nofeedbackgroup = self.testhelper.reload_from_db(nofeedbackgroup)
        badgroup = self.testhelper.reload_from_db(badgroup)
        goodgroup = self.testhelper.reload_from_db(goodgroup)

        # Has new deadline:
        self.assertEquals(len(badgroup.deadlines.all()), 2)

        # Unchaged:
        self.assertEquals(len(nodeadlinegroup.deadlines.all()), 0)
        self.assertEquals(len(nofeedbackgroup.deadlines.all()), 1)
        self.assertEquals(len(goodgroup.deadlines.all()), 1)

        newdeadline = badgroup.deadlines.all()[0]
        self.assertEquals(newdeadline.text, 'Hello')
        self.assertEquals(newdeadline.deadline.hour, 12)
        self.assertEquals(newdeadline.deadline.minute, 0)

    def test_add_deadline_failed_or_no_feedback(self):
        nodeadlinegroup = self._create_nodeadlinegroup()
        nofeedbackgroup = self._create_nofeedbackgroup()
        badgroup = self._create_badgroup()
        goodgroup = self._create_goodgroup()

        self._loginTo('a1admin', self.assignment.id)
        addform = self._open_addform()
        self._fill_addform(addform, date=self._create_datestring_from_offset(2),
                        time='12:00', text='Hello', createmodecls='createmode_failed_or_no_feedback')

        url = self.selenium.current_url
        self._get_formsavebutton(addform).click()
        self.waitFor(self.selenium, lambda s: s.current_url != url) # Wait for the page to be reloaded with the new deadline URL

        nofeedbackgroup = self.testhelper.reload_from_db(nofeedbackgroup)
        badgroup = self.testhelper.reload_from_db(badgroup)
        goodgroup = self.testhelper.reload_from_db(goodgroup)

        # Has new deadline:
        self.assertEquals(len(nodeadlinegroup.deadlines.all()), 1)
        self.assertEquals(len(nofeedbackgroup.deadlines.all()), 2)
        self.assertEquals(len(badgroup.deadlines.all()), 2)

        # Unchaged:
        self.assertEquals(len(goodgroup.deadlines.all()), 1)

    def test_add_deadline_no_deadlines(self):
        nodeadlinegroup = self._create_nodeadlinegroup()
        nofeedbackgroup = self._create_nofeedbackgroup()
        badgroup = self._create_badgroup()
        goodgroup = self._create_goodgroup()

        self._loginTo('a1admin', self.assignment.id)
        addform = self._open_addform()
        self._fill_addform(addform, date=self._create_datestring_from_offset(2),
                        time='12:00', text='Hello', createmodecls='createmode_no_deadlines')

        url = self.selenium.current_url
        self._get_formsavebutton(addform).click()
        self.waitFor(self.selenium, lambda s: s.current_url != url) # Wait for the page to be reloaded with the new deadline URL

        nofeedbackgroup = self.testhelper.reload_from_db(nofeedbackgroup)
        badgroup = self.testhelper.reload_from_db(badgroup)
        goodgroup = self.testhelper.reload_from_db(goodgroup)

        # Has new deadline:
        self.assertEquals(len(nodeadlinegroup.deadlines.all()), 1)

        # Unchanged:
        self.assertEquals(len(nofeedbackgroup.deadlines.all()), 1)
        self.assertEquals(len(badgroup.deadlines.all()), 1)
        self.assertEquals(len(goodgroup.deadlines.all()), 1)

    def _click_specific_groups(self, addform, groups):
        grid = self.waitForAndFindElementByCssSelector('.devilry_subjectadmin_bulkmanagedeadlines_allgroupsgrid',
                                                       within=addform)
        for group in groups:
            self._click_row_by_group(grid, group)

    def test_add_deadline_specific_groups(self):
        nodeadlinegroup = self._create_nodeadlinegroup()
        nofeedbackgroup = self._create_nofeedbackgroup()
        badgroup = self._create_badgroup()
        goodgroup = self._create_goodgroup()

        self._loginTo('a1admin', self.assignment.id)
        addform = self._open_addform()
        savebutton = self._get_formsavebutton(addform)
        self._fill_addform(addform, date=self._create_datestring_from_offset(2),
                        time='12:00', text='Hello', createmodecls='createmode_specific_groups')
        self.waitForDisabled(savebutton)
        self._click_specific_groups(addform, [goodgroup, badgroup])
        self.waitForEnabled(savebutton)

        url = self.selenium.current_url
        savebutton.click()
        self.waitFor(self.selenium, lambda s: s.current_url != url) # Wait for the page to be reloaded with the new deadline URL

        nofeedbackgroup = self.testhelper.reload_from_db(nofeedbackgroup)
        badgroup = self.testhelper.reload_from_db(badgroup)
        goodgroup = self.testhelper.reload_from_db(goodgroup)

        # Has new deadline:
        self.assertEquals(len(badgroup.deadlines.all()), 2)
        self.assertEquals(len(goodgroup.deadlines.all()), 2)

        # Unchanged:
        self.assertEquals(len(nofeedbackgroup.deadlines.all()), 1)
        self.assertEquals(len(nodeadlinegroup.deadlines.all()), 0)

    def test_add_deadline_enable_disable(self):
        goodgroup = self._create_goodgroup()
        self._loginTo('a1admin', self.assignment.id)

        addform = self._open_addform()
        savebutton = self._get_formsavebutton(addform)

        self.waitForDisabled(savebutton) # Should start as disabled

        self._fill_addform(addform, date=self._create_datestring_from_offset(2),
                           time='12:00', text='Hello')
        self.waitForEnabled(savebutton)

        self._fill_addform(addform, date='',
                           time='12:00', text='Hello')
        self.waitForDisabled(savebutton)

        self._fill_addform(addform, date=self._create_datestring_from_offset(2),
                           time='12:00', text='Hello', createmodecls='createmode_specific_groups')
        self.waitForDisabled(savebutton)

        self._click_specific_groups(addform, [goodgroup]) # Select goodgroup
        self.waitForEnabled(savebutton)

        self._click_specific_groups(addform, [goodgroup]) # Deselect goodgroup
        self.waitForDisabled(savebutton)

        self._fill_addform(addform, date=self._create_datestring_from_offset(2),
                           time='12:00', text='Hello', createmodecls='createmode_failed')
        self.waitForEnabled(savebutton)




    #
    #
    # Edit deadline tests
    #
    #
    def _fill_editform(self, form, date, time, text=''):
        self._fill_addform(form, date, time, text)

    def _get_deadlinepanels(self, expectedcount):
        cssselector = '.devilry_subjectadmin_bulkmanagedeadlines_deadline'
        self.waitFor(self.selenium, lambda s: len(s.find_elements_by_css_selector(cssselector)) == expectedcount)
        return self.selenium.find_elements_by_css_selector(cssselector)

    def _expand_deadlinepanel(self, deadlinepanel):
        button = deadlinepanel.find_element_by_css_selector('.x-panel-header .x-tool-expand-bottom')
        button.click()
        return self.waitForAndFindElementByCssSelector('.bulkmanagedeadlines_deadline_body', within=deadlinepanel)

    def _expand_deadline_by_index(self, index, expectedcount):
        return self._expand_deadlinepanel(self._get_deadlinepanels(expectedcount)[index])

    def _open_editform(self, deadlinepanelbody):
        button = self.waitForAndFindElementByCssSelector('.edit_deadline_button', within=deadlinepanelbody)
        button.click()
        return self.waitForAndFindElementByCssSelector('.devilry_subjectadmin_bulkmanagedeadlines_deadlineform.editdeadlineform',
                                                       within=deadlinepanelbody)

    def _click_onlysomegroups_checkbox(self, editform):
        checkbutton = editform.find_element_by_css_selector('.edit_specific_groups_fieldset .x-fieldset-header-checkbox input.x-form-checkbox')
        checkbutton.click()

    def _editform_clickgroups(self, editform, groups):
        grid = self.waitForAndFindElementByCssSelector('.devilry_subjectadmin_bulkmanagedeadlines_groupsindeadlineselectgrid',
                                                       within=editform)
        for group in groups:
            self._click_row_by_group(grid, group)


    def test_edit_deadline(self):
        badgroup = self._create_badgroup()
        goodgroup = self._create_goodgroup()
        self._loginTo('a1admin', self.assignment.id)
        deadlinepanelbody = self._expand_deadline_by_index(index=0, expectedcount=1)
        editform = self._open_editform(deadlinepanelbody)
        self._fill_editform(editform, date=self._create_datestring_from_offset(2),
                            time='12:00', text='Hello')

        url = self.selenium.current_url
        self._get_formsavebutton(editform).click()
        self.waitFor(self.selenium, lambda s: s.current_url != url) # Wait for the page to be reloaded with the new deadline URL

        for group in badgroup, goodgroup:
            deadline = group.deadlines.all()[0]
            self.assertEquals(deadline.text, 'Hello')
            self.assertEquals(deadline.deadline.hour, 12)
            self.assertEquals(deadline.deadline.minute, 0)

    def test_edit_deadline_afterperiod(self):
        goodgroup = self._create_goodgroup()
        self._loginTo('a1admin', self.assignment.id)

        deadlinepanelbody = self._expand_deadline_by_index(index=0, expectedcount=1)
        editform = self._open_editform(deadlinepanelbody)
        alertmessagelist = editform.find_element_by_css_selector('.devilry_extjsextras_alertmessagelist')
        self.assertEquals(alertmessagelist.find_elements_by_css_selector('.alert-error'), [])

        year = goodgroup.deadlines.all()[0].deadline.year
        self._fill_editform(editform, date='{0}-01-01'.format(year+3), time='12:00')
        self._get_formsavebutton(editform).click()

        def has_out_of_period_error(a):
            if len(alertmessagelist.find_elements_by_css_selector('.alert-error')) == 1:
                error = alertmessagelist.find_element_by_css_selector('.alert-error')
                return 'Deadline must be within' in error.text
            return False
        self.waitFor(alertmessagelist, has_out_of_period_error)

    def test_edit_deadline_beforepubtime(self):
        goodgroup = self._create_goodgroup()
        self._loginTo('a1admin', self.assignment.id)

        deadlinepanelbody = self._expand_deadline_by_index(index=0, expectedcount=1)
        editform = self._open_editform(deadlinepanelbody)
        alertmessagelist = editform.find_element_by_css_selector('.devilry_extjsextras_alertmessagelist')
        self.assertEquals(alertmessagelist.find_elements_by_css_selector('.alert-error'), [])

        self._fill_editform(editform, date='2000-01-01', time='12:00')
        self._get_formsavebutton(editform).click()

        def has_out_of_period_error(a):
            if len(alertmessagelist.find_elements_by_css_selector('.alert-error')) == 1:
                error = alertmessagelist.find_element_by_css_selector('.alert-error')
                return 'Deadline cannot be before publishing time' in error.text
            return False
        self.waitFor(alertmessagelist, has_out_of_period_error)

    def test_edit_deadline_somegroups(self):
        badgroup = self._create_badgroup()
        goodgroup = self._create_goodgroup()
        goodgroup_deadline = goodgroup.deadlines.all()[0].deadline
        self._loginTo('a1admin', self.assignment.id)

        deadlinepanelbody = self._expand_deadline_by_index(index=0, expectedcount=1)
        editform = self._open_editform(deadlinepanelbody)
        self._fill_editform(editform, date=self._create_datestring_from_offset(2),
                            time='12:00', text='Hello')
        self._click_onlysomegroups_checkbox(editform)
        self._editform_clickgroups(editform, [badgroup])

        url = self.selenium.current_url
        self._get_formsavebutton(editform).click()
        self.waitFor(self.selenium, lambda s: s.current_url != url) # Wait for the page to be reloaded with the new deadline URL

        # Goodgroup is unchanged?
        self.assertEquals(goodgroup.deadlines.all()[0].deadline, goodgroup_deadline)

        # Badgroup was updated?
        deadline = badgroup.deadlines.all()[0]
        self.assertEquals(deadline.text, 'Hello')
        self.assertEquals(deadline.deadline.hour, 12)
        self.assertEquals(deadline.deadline.minute, 0)

    def test_edit_deadline_enable_disable(self):
        badgroup = self._create_badgroup()
        goodgroup = self._create_goodgroup()
        self._loginTo('a1admin', self.assignment.id)

        deadlinepanelbody = self._expand_deadline_by_index(index=0, expectedcount=1)
        editform = self._open_editform(deadlinepanelbody)
        savebutton = self._get_formsavebutton(editform)

        self.waitForEnabled(savebutton) # Should start as enabled since we load a valid deadline

        self._fill_editform(editform, date='',
                            time='12:00', text='Hello')
        self.waitForDisabled(savebutton)

        self._fill_editform(editform, date=self._create_datestring_from_offset(2),
                            time='12:00', text='Hello')
        self.waitForEnabled(savebutton)

        self._click_onlysomegroups_checkbox(editform) # Expand only some groups panel
        self.waitForDisabled(savebutton)

        self._editform_clickgroups(editform, [badgroup]) # Select badgroup
        self.waitForEnabled(savebutton)

        self._editform_clickgroups(editform, [badgroup]) # Deselect badgroup
        self.waitForDisabled(savebutton)

        self._click_onlysomegroups_checkbox(editform) # Collapse only some groups panel
        self.waitForEnabled(savebutton)
Esempio n. 6
0
class TestPeriodEditDuration(SubjectAdminSeleniumTestCase, PeriodTestCommonMixin):
    def setUp(self):
        self.testhelper = TestHelper()
        self.testhelper.add(nodes='uni',
                            subjects=['sub'],
                            periods=['p1:admin(p1admin)'])
        self.p1 = self.testhelper.sub_p1
        self.p1.start_time = datetime(2005, 1, 1)
        self.p1.end_time = datetime(2006, 1, 1)
        self.p1.save()
        self.loginToPeriod('p1admin', self.p1.id)

        self.readOnlyPanel = self.waitForAndFindElementByCssSelector('.devilry_subjectadmin_editperiod_duration_widget .containerwithedittitle')

    def _click_edit(self):
        button = self.waitForAndFindElementByCssSelector('.devilry_subjectadmin_editperiod_duration_widget .containerwithedittitle .edit_link')
        button.click()

        panel = self.waitForAndFindElementByCssSelector('.devilry_subjectadmin_editdurationpanel')
        self.start_time_datefield = panel.find_element_by_css_selector('.start_time_field .devilry_extjsextras_datefield input')
        self.start_time_timefield = panel.find_element_by_css_selector('.start_time_field .devilry_extjsextras_timefield input')
        self.end_time_datefield = panel.find_element_by_css_selector('.end_time_field .devilry_extjsextras_datefield input')
        self.end_time_timefield = panel.find_element_by_css_selector('.end_time_field .devilry_extjsextras_timefield input')
        self.savebutton = panel.find_element_by_css_selector('.okbutton button')
        self.cancelbutton = panel.find_element_by_css_selector('.cancelbutton button')
        self.editpanel = panel

    def _set_values(self, start_date, start_time, end_date, end_time):
        self.start_time_datefield.clear()
        self.start_time_timefield.clear()
        self.end_time_datefield.clear()
        self.end_time_timefield.clear()
        self.start_time_datefield.send_keys(start_date)
        self.start_time_timefield.send_keys(start_time)
        self.end_time_datefield.send_keys(end_date)
        self.end_time_timefield.send_keys(end_time)

    def _get_durationdisplay(self):
        return self.readOnlyPanel.find_element_by_css_selector('.durationdisplay').text.strip()

    def test_render(self):
        self.waitForDisplayed(self.readOnlyPanel)
        self.assertEquals(self._get_durationdisplay(),
                          '2005-01-01 00:00 - 2006-01-01 00:00')

    def test_edit(self):
        self._click_edit()
        self._set_values(start_date='2000-12-24', start_time='12:00',
                         end_date='2001-11-22', end_time='16:00')
        self.savebutton.click()
        self.waitForDisplayed(self.readOnlyPanel)
        self.assertEquals(self._get_durationdisplay(),
                          '2000-12-24 12:00 - 2001-11-22 16:00')
        p1 = self.testhelper.reload_from_db(self.p1)
        self.assertEquals(p1.start_time, datetime(2000, 12, 24, 12, 0))
        self.assertEquals(p1.end_time, datetime(2001, 11, 22, 16, 0))

    def test_errorhandling(self):
        self._click_edit()
        self._set_values(start_date='', start_time='12:00',
                         end_date='2001-11-22', end_time='16:00')
        self.savebutton.click()
        self.waitFor(self.editpanel, lambda p: 'Start time: This field is required' in p.text)