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.')
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)
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))
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)
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)