def test_max_length(self): """Verify that the word count is enforced""" prompt = EssayPrompt.objects.create(identifier='test', prompt='This is a test!', word_limit=6, previous_version=None) essay = Essay.objects.create(application=self.application, prompt=prompt, response="""lorem ipsum! facto blargson test text""") issues = CustomValidationIssueSet() self.application.custom_validate(issues) found_issues = issues.search(section='essay', code='max-length') self.assertEqual(len(found_issues), 0) # Only one more word is needed to meet the advertised limit, but the # code is generous and makes this a "soft" limit; add several more # words to test the "hard" limit essay.response += ' anotherword!' * 6 essay.full_clean() essay.save() self.application.custom_validate(issues) found_issues = issues.search(section='essay', code='max-length') self.assertEqual(len(found_issues), 1) first_iter = iter(found_issues) self.assertNotEqual(next(first_iter).subfield, None)
def test_endowment_senior_limitation(self): """Ensure that a graduating senior cannot select endowment awards""" excellence = Award.objects.latest_version_of('excellence') self.application.semester_graduating = Semester('FA16') self.application.award_set.add(excellence) issues = CustomValidationIssueSet() self.application.custom_validate(issues) self.assertNotEqual( list( issues.search(section='basicinfo', field='semester_graduating', code='prohibited')), [])
def clean(self, *args, **kwargs): if self.submitted: issues = CustomValidationIssueSet() self.custom_validate(issues) if len(issues) > 0: # last line of defense; should never have to be raised raise ValidationError('cannot submit Application with issues!') return super(Application, self).clean(*args, **kwargs)
def post(self, request): """Don't override this method, but use the hooks instead""" if type(self) == WizardPageView: raise NotImplementedError('WizardPageView is an abstract base') else: error_response = self._initialize_for_request(request) if error_response is not None: return error_response self.form = self.parse_form() if self.form is None or self.form.is_valid(): if self.form is not None: self.save_changes() submit_type = request.POST.get('submit-type', default=None) if submit_type == 'submit': self.application.submitted = True self.issues = CustomValidationIssueSet() self.application.custom_validate(self.issues) if submit_type == 'restart': self.application.delete() self.application = Application.objects.create( due_at=settings.FREEMONEY_DUE_DATE, applicant=self.applicant) self.applicant.full_clean() self.applicant.save() add_message(self.request, INFO, 'Application was successfully restarted') return redirect(self._uri_of(self._my_pages[0][0])) else: including_me = (submit_type != 'prev') failing_sentry = self._find_failing_sentry(including_me) if failing_sentry is None: if submit_type == 'prev': redirect_to = self._my_pages[self._page_index - 1][0] elif submit_type == 'next': redirect_to = self._my_pages[self._page_index + 1][0] elif submit_type == 'submit': self.application.full_clean() self.application.save() redirect_to = 'submitted' else: redirect_to = self._my_pages[self._page_index][0] return redirect(self._uri_of(redirect_to)) else: add_message( self.request, ERROR, 'Please fix form errors below before proceeding') return redirect(self._uri_of(failing_sentry.page_name))
def test_past_finished_date(self): aid = FinancialAid.objects.create(application=self.application, aid_type='test', provider='provider', semester_finished=Semester( ('Spring', 2016)), installment_frequency='yearly', installment_amount=1.00) # finished in the past (no good) issues = CustomValidationIssueSet() self.application.custom_validate(issues) found_issues = issues.search(section='finaid', field='semester_finished', code='invalid') self.assertEqual(len(found_issues), 1) first_iter = iter(found_issues) self.assertNotEqual(next(first_iter).subfield, None) # finished in the present (good) aid.semester_finished = Semester(settings.FREEMONEY_DUE_DATE) issues = CustomValidationIssueSet() self.application.custom_validate(issues) found_issues = issues.search(section='finaid', field='semester_finished', code='invalid') self.assertEqual(len(found_issues), 1) first_iter = iter(found_issues) self.assertNotEqual(next(first_iter).subfield, None)
def test_valid_installments(self): aid = FinancialAid.objects.create( application=self.application, aid_type='test', provider='testprovider', semester_finished=None, installment_frequency='yearly', installment_amount=-1.00, ) # too small (negative) issues = CustomValidationIssueSet() self.application.custom_validate(issues) found_issues = issues.search(section='finaid', field='installment_amount', code='invalid') self.assertEqual(len(found_issues), 1) first_iter = iter(found_issues) self.assertNotEqual(next(first_iter).subfield, None) # too large aid.installment_amount = 1000000.00 aid.full_clean() aid.save() issues = CustomValidationIssueSet() self.application.custom_validate(issues) found_issues = issues.search(section='finaid', field='installment_amount', code='invalid') self.assertEqual(len(found_issues), 1) first_iter = iter(found_issues) self.assertNotEqual(next(first_iter).subfield, None) # just right aid.installment_amount = 5000.00 aid.full_clean() aid.save() issues = CustomValidationIssueSet() self.application.custom_validate(issues) self.assertEqual( len( issues.search(section='finaid', field='installment_amount', code='invalid')), 0)
def attempt_valid_and_invalid_values(self, attr, valids, invalids): consolidated = (list(zip(valids, [True] * len(valids))) + list(zip(invalids, [False] * len(invalids)))) for attempt, should_be_valid in consolidated: setattr(self.application, attr, attempt) issues = CustomValidationIssueSet() self.application.custom_validate(issues) is_actually_valid = True for issue in issues: if (issue.section == 'basicinfo' and issue.field == attr): is_actually_valid = False break self.assertEqual(should_be_valid, is_actually_valid)
def test_invalid_specifications(self): """Try various ways of incorrectly adding issues to the manager""" issues = CustomValidationIssueSet() with self.assertRaises(TypeError): # incorrect type for field issues.create(section='test', field=5, subfield=5, code='invalid') with self.assertRaises(KeyError): # nonexistent code issues.create(section='t', field='t', code='FALSE') with self.assertRaises(ValueError): # subfield without a section issues.create(subfield=5, code='invalid')
def test_too_few_awards(self): """Verify that at least one award must be selected""" issues = CustomValidationIssueSet() self.application.custom_validate(issues) self.assertNotEqual( list(issues.search(section='award', code='min-length')), []) excellence = Award.objects.latest_version_of('excellence') self.application.award_set.add(excellence) issues = CustomValidationIssueSet() self.application.custom_validate(issues) self.assertEqual(list(issues.search(section='award')), []) self.application.award_set.clear() issues = CustomValidationIssueSet() self.application.custom_validate(issues) self.assertNotEqual( list(issues.search(section='award', code='min-length')), [])
def _initialize_for_request(self, request): self.request = request try: self.applicant = self.request.user.applicantprofile if self.applicant.must_change_password: # TODO: forced password change return server_error(self.request) except ObjectDoesNotExist: # TODO: make a landing page for non-applicant users return server_error(self.request) try: self.application = self.applicant.current_application if self.application.submitted: return redirect(self._uri_of('submitted')) except ObjectDoesNotExist: # TODO: same landing page as for non-applicant users return server_error(self.request) self.issues = CustomValidationIssueSet() self.application.custom_validate(self.issues) self._my_pages = [] self._page_index = None needs_finaid = Award.objects.check_app_needs_finaid(self.application) needs_essay = Award.objects.check_app_needs_essay(self.application) for index, names in enumerate(WizardPageView.PAGES): short_name, long_name = names if ((not needs_finaid and short_name == 'finaid') or (not needs_essay and short_name == 'essay')): if type(self).page_name == short_name: return redirect(self._uri_of(self._my_pages[-1][0])) else: continue if type(self).page_name == short_name: self._page_index = index self._my_pages.append((short_name, long_name)) if self._page_index == None: raise KeyError('invalid page name: {}'.format(page_name)) failing_sentry = self._find_failing_sentry(including_me=False) if failing_sentry is not None: add_message(self.request, ERROR, 'Please complete this section first') return redirect(self._uri_of(failing_sentry.page_name))
def test_non_semester_award(self): """Verify error if a Spring award is selected in the Fall""" excellence = Award.objects.latest_version_of('excellence') self.application.award_set.add(excellence) issues = CustomValidationIssueSet() self.application.custom_validate(issues) self.assertEqual(list(issues.search(section='award')), []) ambassador = Award.objects.latest_version_of('ambassador') self.application.award_set.add(ambassador) issues = CustomValidationIssueSet() self.application.custom_validate(issues) self.assertNotEqual( list(issues.search(section='award', code='invalid')), [])
def test_aggregate(self): """Add and aggregate several issues for a single field""" issues = CustomValidationIssueSet() issues.create(section='section1', field='c', code='min-length') issues.create(section='section2', field='c', code='min-length') issues.create(section='section2', field='c', code='prohibited') issues.create(section='section2', field='c', code='invalid') issues.create(section='section3', code='prohibited') self.assertSetEqual( set(['min-length', 'prohibited', 'invalid']), set(issues.search(section='section2', field='c', aggregate=True)))
def test_search_by_code(self): """Add a bunch of tests and filter by code""" issues = CustomValidationIssueSet() issues.create(section='section1', code='prohibited') issues.create(section='section1', field='a', code='invalid') issues.create(section='section1', field='b', code='invalid') issues.create(section='section1', field='c', code='min-length') issues.create(section='section2', field='b', code='min-length') issues.create(section='section2', field='c', code='prohibited') issues.create(section='section3', code='invalid') issues.create(code='max-length') self.assertEqual(3, len(issues.search(code='invalid')))
def test_all_for_section(self): """Add a bunch of issues on several sections, and check one section""" issues = CustomValidationIssueSet() issues.create(section='section1', code='prohibited') issues.create(section='section2', field='a', code='min-length') issues.create(section='section3', field='b', subfield=5, code='invalid') issues.create(section='section1', field='c', subfield=1, code='max-length') self.assertEqual(2, len(issues.search(section='section1')))
def test_major_restrictions(self): """Ensure that only certain majors can apply to restricted awards""" joe_conway = Award.objects.latest_version_of('joe_conway') giff_albright = Award.objects.latest_version_of('giff_albright') self.application.award_set.set([giff_albright]) self.application.major = 'Electrical Engineering' self.application.full_clean() self.application.save() issues = CustomValidationIssueSet() self.application.custom_validate(issues) self.assertNotEqual( list( issues.search(section='basicinfo', field='major', code='prohibited')), []) self.application.award_set.set([giff_albright]) self.application.major = 'Architectural Engineering' self.application.full_clean() self.application.save() issues = CustomValidationIssueSet() self.application.custom_validate(issues) self.assertEqual( list( issues.search(section='basicinfo', field='major', code='prohibited')), []) self.application.award_set.set([joe_conway]) self.application.major = 'Electrical Engineering' self.application.full_clean() self.application.save() issues = CustomValidationIssueSet() self.application.custom_validate(issues) self.assertNotEqual( list( issues.search(section='basicinfo', field='major', code='prohibited')), []) self.application.award_set.set([joe_conway]) self.application.emch_minor = True self.application.full_clean() self.application.save() issues = CustomValidationIssueSet() self.application.custom_validate(issues) self.assertEqual( list( issues.search(section='basicinfo', field='major', code='prohibited')), []) self.application.award_set.set([joe_conway]) self.application.major = 'Engineering Science' self.application.emch_minor = False self.application.full_clean() self.application.save() issues = CustomValidationIssueSet() self.application.custom_validate(issues) self.assertEqual( list( issues.search(section='basicinfo', field='major', code='prohibited')), [])
def test_hierarchy(self): """Verify that it is impossible to use an invalid hierarchy spec""" issues = CustomValidationIssueSet() with self.assertRaises(ValueError): issues.create(field='noparent', code='invalid') with self.assertRaises(ValueError): issues.create(subfield=5, code='invalid') with self.assertRaises(ValueError): issues.create(section='grandparent', subfield=4, code='invalid') self.assertEqual(0, len(issues)) with self.assertRaises(ValueError): issues.search(section=CustomValidationIssueSet.GLOBAL, field=CustomValidationIssueSet.GLOBAL, subfield=5) with self.assertRaises(ValueError): issues.search(field=CustomValidationIssueSet.GLOBAL) with self.assertRaises(ValueError): issues.search(field='noparent') with self.assertRaises(ValueError): issues.search(subfield=5) with self.assertRaises(ValueError): issues.search(section='grandparent', subfield=4) with self.assertRaises(ValueError): issues.search(section='grandparent', field=CustomValidationIssueSet.GLOBAL, subfield=4)
def test_required_fields(self): aid = FinancialAid.objects.create(application=self.application, aid_type='test', provider='', semester_finished=None, installment_frequency='yearly', installment_amount=1.00) # no provider issues = CustomValidationIssueSet() self.application.custom_validate(issues) found_issues = issues.search(section='finaid', field='provider', code='required') self.assertEqual(len(found_issues), 1) first_iter = iter(found_issues) self.assertNotEqual(next(first_iter).subfield, None) # no installment frequency aid.provider = 'test' aid.installment_frequency = '' aid.full_clean() aid.save() issues = CustomValidationIssueSet() self.application.custom_validate(issues) found_issues = issues.search(section='finaid', field='installment_frequency', code='required') self.assertEqual(len(found_issues), 1) first_iter = iter(found_issues) self.assertNotEqual(next(first_iter).subfield, None) # no aid_type aid.installment_frequency = 'yearly' aid.aid_type = '' aid.full_clean() aid.save() issues = CustomValidationIssueSet() self.application.custom_validate(issues) found_issues = issues.search(section='finaid', field='aid_type', code='required') self.assertEqual(len(found_issues), 1) first_iter = iter(found_issues) self.assertNotEqual(next(first_iter).subfield, None) # all required fields (and no optional fields) present aid.aid_type = 'test' aid.full_clean() aid.save() issues = CustomValidationIssueSet() self.application.custom_validate(issues) self.assertEqual(len(issues.search(section='finaid')), 0)