def validate(form): """Extracts value from common fields from applicant info and address_fields_partial for validation. parameters: - form: The form which includes the payment methods returns: dict: An instance of ValidationErrorBuilder with a ValidationError dict and a heading summary message. """ payment_method = form.get('payment_method', '') payment_ref = form.get('payment_ref', '') no_payment_notes = form.get('no_payment_notes', '') validation_error_builder = ValidationErrorBuilder() FieldValidator(payment_method, 'payment_method', 'Payment method', validation_error_builder, inline_message='Choose one option') \ .is_required() if payment_method == "govuk": FieldValidator(payment_ref, 'payment_ref', 'Payment reference', validation_error_builder) \ .is_required() if payment_method == "none": FieldValidator(no_payment_notes, 'no_payment_notes', 'Explanation', validation_error_builder) \ .is_required() return validation_error_builder.get()
def test_error_is_added_given_nonempty_dict(self): validation_error_builder = ValidationErrorBuilder() field_validator_1 = FieldValidator('dummy value', TEST_FIELD_NAME, TEST_DISPLAY_NAME, validation_error_builder) field_validator_2 = FieldValidator('dummy value', TEST_FIELD_NAME_2, TEST_DISPLAY_NAME, validation_error_builder) default_message = '{} {}'.format(TEST_DISPLAY_NAME, TEST_MESSAGE) validation_error_builder.add_error(field_validator_1, default_message) validation_error_builder.add_error(field_validator_2, default_message) validation_errors = validation_error_builder.get().errors self.assertEqual(len(validation_errors), 2) self.assertTrue(TEST_FIELD_NAME in validation_errors) self.assertEqual(validation_errors[TEST_FIELD_NAME].summary_message, default_message) self.assertEqual(validation_errors[TEST_FIELD_NAME].inline_message, default_message) self.assertTrue(TEST_FIELD_NAME_2 in validation_errors) self.assertEqual(validation_errors[TEST_FIELD_NAME_2].summary_message, default_message) self.assertEqual(validation_errors[TEST_FIELD_NAME_2].inline_message, default_message)
def test_error_is_added_with_inline_message(self): validation_error_builder = ValidationErrorBuilder() field_validator_1 = FieldValidator('dummy value', TEST_FIELD_NAME, None, validation_error_builder, inline_message=TEST_INLINE) field_validator_2 = FieldValidator('dummy value', TEST_FIELD_NAME_2, None, validation_error_builder, inline_message=TEST_INLINE) validation_error_builder.add_error(field_validator_1, TEST_MESSAGE) validation_error_builder.add_error(field_validator_2, TEST_MESSAGE) validation_errors = validation_error_builder.get().errors self.assertEqual(len(validation_errors), 2) self.assertTrue(TEST_FIELD_NAME in validation_errors) self.assertEqual(validation_errors[TEST_FIELD_NAME].summary_message, TEST_MESSAGE) self.assertEqual(validation_errors[TEST_FIELD_NAME].inline_message, TEST_INLINE) self.assertTrue(TEST_FIELD_NAME_2 in validation_errors) self.assertEqual(validation_errors[TEST_FIELD_NAME_2].summary_message, TEST_MESSAGE) self.assertEqual(validation_errors[TEST_FIELD_NAME_2].inline_message, TEST_INLINE)
def validate(location_info, has_address): validation_error_builder = ValidationErrorBuilder() if has_address == 'ProvideAddress': FieldValidator(location_info, 'search_term', 'Charge Address', validation_error_builder, summary_message='Choose an address', inline_message='Search for a different postcode if the address you need is not listed.') \ .is_required() elif has_address == 'No': FieldValidator(location_info, 'charge-geographic-description', 'Charge Geographic Description', validation_error_builder, summary_message='Describe the search area', inline_message='Explain where you want to search without an address. ' 'For example, use a nearby landmark as a reference point. ') \ .is_required() FieldValidator(location_info, 'charge-geographic-description', 'Charge Geographic Description', validation_error_builder, summary_message='Answer is too long', inline_message='Reduce your answer to 1000 characters or less') \ .is_length_less_than_or_equal_to(1000) else: FieldValidator(has_address, 'address-from-group', 'Choose one option', validation_error_builder, summary_message='Choose one option') \ .is_required() validation_errors = validation_error_builder.get() return validation_errors
def validate(shapefile, existing_geometries, already_uploaded): """Specifies which validation methods should be called for each input field. parameters: - shapefile: The contents of the file the user has uploaded - existing_geometries: A collection of features already drawn/uploaded by the user - already_uploaded: True if user has clicked upload button multiple times and session has been updated returns: dict: An instance of ValidationErrorBuilder with a ValidationError dict and a heading summary message. """ validation_error_builder = ValidationErrorBuilder() FieldValidator(shapefile, 'shapefile-input', 'shapefile-input', validation_error_builder, summary_message="Upload a file", inline_message="Upload a file") \ .is_required() FieldValidator(shapefile, 'shapefile-input', 'shapefile-input', validation_error_builder, summary_message="File is bigger than 1MB", inline_message="Upload a smaller file") \ .is_uploaded_filesize_less_than_bytes(1000000) if already_uploaded: all_extents = existing_geometries['features'] \ if existing_geometries and 'features' in existing_geometries \ else [] else: shapefile_contents = [] try: with fiona.drivers(): with fiona.BytesCollection(shapefile.read()) as shpfile: for shape in shpfile: shapefile_contents.append(shape) shapefile.seek(0) except Exception: pass FieldValidator(shapefile_contents, 'shapefile-input', 'shapefile-input', validation_error_builder, summary_message="File not uploaded", inline_message="Upload a different file") \ .is_required() if existing_geometries and 'features' in existing_geometries: all_extents = shapefile_contents + existing_geometries[ 'features'] else: all_extents = shapefile_contents FieldValidator(all_extents, 'shapefile-input', 'shapefile-input', validation_error_builder, inline_message="Too many extents", summary_message="Number of extents must be 500 (or fewer)") \ .is_length_less_than_or_equal_to(500) return validation_error_builder.get()
def validate(authority, authorities): validation_error_builder = ValidationErrorBuilder() FieldValidator(authority, 'authority-search-field', 'Originating Authority', validation_error_builder, summary_message='Authority name is required', inline_message='Authority name is required') \ .is_required() FieldValidator(authority, 'authority-search-field', 'Originating Authority', validation_error_builder, summary_message='No match found', inline_message='Try a different search') \ .is_item_in_list(authorities) return validation_error_builder.get()
def edit_lon_land_interest_post(): if g.session.add_lon_charge_state is None: current_app.logger.error( "Charge state not found in session - Returning error") raise ApplicationError(500) # Different validation and error messages are required for other instead of the existing options. land_interest = request.form.get("servient-land-interest-description") if land_interest == "Other": land_interest = request.form.get("servient-land-interest-detail") validation_error_builder = ValidationErrorBuilder() FieldValidator(land_interest, 'servient-land-interest-detail', 'Land Interest', validation_error_builder, summary_message="There are errors on the page. Describe the interest in land", inline_message="Explain how the person applying for the light obstruction notice " "owns or uses the land") \ .is_required() checked = "Other" else: validation_error_builder = ValidationErrorBuilder() FieldValidator(land_interest, 'servient-land-interest-description', 'Land Interest', validation_error_builder, summary_message="Choose one", inline_message="Choose one") \ .is_required() checked = request.form.get("servient-land-interest-description") if validation_error_builder.errors: current_app.logger.warning("Validation errors occurred") return render_template( 'lon_land_interest.html', submit_url=url_for("modify_lon.edit_lon_land_interest_post"), validation_errors=validation_error_builder.errors, validation_summary_heading=validation_error_builder. summary_heading_text, checked=checked, request_body=land_interest), 400 if g.session.add_lon_charge_state.servient_land_interest_description != land_interest: g.session.add_lon_charge_state.servient_land_interest_description = land_interest g.session.edited_fields[ 'servient-land-interest-description'] = 'Interest' g.session.commit() charge_display_id = calc_display_id( g.session.add_lon_charge_state.local_land_charge) current_app.logger.info( "Session charge updated - Redirecting back to modify_land_charge with local_land_charge='{}'" .format(charge_display_id)) return redirect( url_for("modify_lon.modify_lon_details_get", charge_id=charge_display_id))
def validate(day, month, year): """Specifies which validation methods should be called for each input field. parameters: - day: The day the charge was added. This is an optional field on the form. - month: The month the charge was added. This is an optional field on the form. - year: The year the charge was added. This is an optional field on the form. returns: dict: An instance of ValidationErrorBuilder with a ValidationError dict and a heading summary message. """ validation_error_builder = ValidationErrorBuilder() if day or month or year: FieldsetValidator([day, month, year], 'date', 'Date', validation_error_builder) \ .is_valid_date() FieldValidator(year, "date", 'Date', validation_error_builder, summary_message="Date is invalid", inline_message="Year must be in the format YYYY")\ .is_year_format() FieldsetValidator([day, month, year], 'date', 'Date', validation_error_builder, summary_message="Date is invalid", inline_message="Date cannot be a future date") \ .is_past_date() return validation_error_builder.get()
def validate(form): """Extracts postcode and land description for validation. parameters: - form: The form which includes Yes/No radio buttons, postcode, and land description returns: dict: An instance of ValidationErrorBuilder with a ValidationError dict and a heading summary message. """ have_address = form.get('have_address', '') charge_geographic_description = form.get( 'charge_geographic_description', '') validation_error_builder = ValidationErrorBuilder() if have_address == 'No': FieldValidator(charge_geographic_description, 'charge_geographic_description', None, validation_error_builder, summary_message='Location is required', inline_message='Location is required') \ .is_required() return validation_error_builder.get()
def validate(confirmation, action): """Specifies which validation methods should be called for each input FieldValidator. parameters: - confirmation: Whether the user acknowledges they are permitted to add the charge. returns: dict: An instance of ValidationErrorBuilder with a ValidationError dict and a heading summary message. """ validation_error_builder = ValidationErrorBuilder() if action == 'update': summary_message_text = 'Confirm that you have the authority to update this charge' elif action == 'cancel': summary_message_text = 'Confirm that you have the authority to cancel this charge' FieldValidator(confirmation, 'location-confirmation', None, validation_error_builder, summary_message=summary_message_text, inline_message='If the charge is in your authority, tick and continue. ' 'If the charge is in another authority, get permission from that authority.') \ .is_required() return validation_error_builder.get()
def post_land_interest(): if g.session.add_lon_charge_state is None: current_app.logger.info("Redirecting to: %s", url_for("add_lon.new")) return redirect(url_for("add_lon.new")) current_app.logger.info("Running validation") # Different validation and error messages are required for other instead of the existing options. land_interest = request.form.get("servient-land-interest-description") if land_interest == "Other": land_interest = request.form.get("servient-land-interest-detail") validation_error_builder = ValidationErrorBuilder() FieldValidator(land_interest, 'servient-land-interest-detail', 'Land Interest', validation_error_builder, summary_message="There are errors on the page. Describe the interest in land", inline_message="Explain how the person applying for the light obstruction notice " "owns or uses the land") \ .is_required() checked = "Other" else: validation_error_builder = ValidationErrorBuilder() FieldValidator(land_interest, 'servient-land-interest-description', 'Land Interest', validation_error_builder, summary_message="Choose one", inline_message="Choose one") \ .is_required() checked = request.form.get("servient-land-interest-description") if validation_error_builder.errors: current_app.logger.warning("Validation errors occurred") return render_template( 'lon_land_interest.html', submit_url=url_for("add_lon.post_land_interest"), validation_errors=validation_error_builder.errors, validation_summary_heading=validation_error_builder. summary_heading_text, checked=checked, request_body=land_interest), 400 current_app.logger.info("Updating session object") ReviewRouter.update_edited_field('servient_land_interest_description', land_interest) g.session.add_lon_charge_state.servient_land_interest_description = land_interest g.session.commit() return redirect( ReviewRouter.get_redirect_url("add_lon.get_upload_lon_documents"))
def test_is_phone_number_doesnt_add_error_when_phone_valid(self): validation_error_builder = ValidationErrorBuilder() FieldValidator(VALID_PHONE, 'phoneNumber', 'Phone number', validation_error_builder) \ .is_phone_number() validation_errors = validation_error_builder.get().errors self.assertTrue('phoneNumber' not in validation_errors)
def test_is_positive_or_zero_does_add_error_when_invalid(self): validation_error_builder = ValidationErrorBuilder() FieldValidator("-12345", 'testfield', 'Test Field', validation_error_builder) \ .is_positive_number_or_zero() validation_errors = validation_error_builder.get().errors self.assertTrue('testfield' in validation_errors)
def test_is_int_does_add_error_when_invalid(self): validation_error_builder = ValidationErrorBuilder() FieldValidator("123.5", 'testfield', 'Test Field', validation_error_builder) \ .is_int() validation_errors = validation_error_builder.get().errors self.assertTrue('testfield' in validation_errors)
def validate(source_info): validation_error_builder = ValidationErrorBuilder() FieldValidator(source_info, 'source-information', None, validation_error_builder, summary_message="Enter a source", inline_message="Enter a source") \ .is_required() FieldValidator(source_info, 'source-information', None, validation_error_builder, summary_message='Answer too long', inline_message='Reduce your answer to 500 characters or less') \ .is_length_less_than_or_equal_to(500) validation_errors = validation_error_builder.get() return validation_errors
def test_is_less_than_length_same_value(self): validation_error_builder = ValidationErrorBuilder() FieldValidator(TEN_CHARS, 'username', 'Username', validation_error_builder) \ .is_length_less_than_or_equal_to(10) validation_errors = validation_error_builder.get().errors self.assertTrue('username' not in validation_errors)
def test_is_item_not_in_list_does_add_error_when_invalid(self): validation_error_builder = ValidationErrorBuilder() FieldValidator("def", 'testfield', 'Test Field', validation_error_builder) \ .is_item_not_in_list(["def"]) validation_errors = validation_error_builder.get().errors self.assertTrue('testfield' in validation_errors)
def test_is_length_equal_to_false(self): validation_error_builder = ValidationErrorBuilder() FieldValidator(TEN_CHARS, 'username', 'Username', validation_error_builder) \ .is_length_equal_to(9) validation_errors = validation_error_builder.get().errors self.assertTrue('username' in validation_errors)
def test_is_phone_number_adds_error_when_phone_invalid_non_numeric(self): validation_error_builder = ValidationErrorBuilder() FieldValidator(INVALID_PHONE_NON_NUMERIC, 'phoneNumber', 'Phone number', validation_error_builder) \ .is_phone_number() validation_errors = validation_error_builder.get().errors self.assertEqual(validation_errors['phoneNumber'].summary_message, 'Phone number is not a valid phone number')
def validate(form, files): form_b_name = "Form B" court_order_name = "Court Order" validation_error_builder = ValidationErrorBuilder() """ Form Fields """ # Selected Certificates cancel_options = form.getlist('cancel-options') """ Files """ form_b = files.get('form-b-cancel-lon-file-input') court_order = files.get('court-order-cancel-lon-file-input') FieldValidator(cancel_options, 'cancel-options', None, validation_error_builder, summary_message='Choose one option', inline_message='Choose one option') \ .is_required() if form_b_name in cancel_options: FieldValidator(form_b, 'form-b-cancel-lon-file-input', 'Form B', validation_error_builder, inline_message="Upload a document for Form B", summary_message="Upload a document for Form B") \ .is_required() FieldValidator(form_b, 'form-b-cancel-lon-file-input', "Form B", validation_error_builder, inline_message='Upload a different file type. Accepted file formats are: pdf', summary_message="File not recognised") \ .is_pdf() if court_order_name in cancel_options: FieldValidator(court_order, 'court-order-cancel-lon-file-input', "Court Order", validation_error_builder, inline_message="Upload a document for Court Order", summary_message="Upload a document for Court Order") \ .is_required() FieldValidator(court_order, 'court-order-cancel-lon-file-input', "Court Order", validation_error_builder, inline_message='Upload a different file type. Accepted file formats are: pdf', summary_message="File not recognised") \ .is_pdf() return validation_error_builder.get()
def validate(information, reference): validation_error_builder = ValidationErrorBuilder() FieldValidator(information, 'additional-info-error', 'Additional Information', validation_error_builder, summary_message="Answer is too long", inline_message="Reduce your answer to 500 characters or less") \ .is_length_less_than_or_equal_to(500) FieldValidator(information, 'additional-info-error', 'Additional Information', validation_error_builder, summary_message="Add a department name and address, or a link to charge documents", inline_message='Add a source') \ .is_required() FieldValidator(reference, 'reference', 'Reference', validation_error_builder, summary_message="Reference is too long", inline_message="Reduce your answer to 255 characters or less") \ .is_length_less_than_or_equal_to(255) return validation_error_builder.get()
def test_is_item_count_equal_to(self): list_set = [1, 2] validation_error_builder = ValidationErrorBuilder() FieldValidator(list_set, 'a', 'b', validation_error_builder) \ .is_item_count_equal_to(2) validation_errors = validation_error_builder.get().errors self.assertEqual(len(validation_errors), 0)
def validate(extent, part_extent_detail): part_extent_option = "Part of the extent" validation_error_builder = ValidationErrorBuilder() FieldValidator(extent, 'extent', None, validation_error_builder, summary_message='Choose one option', inline_message='Check Plan A. This will show you which part of the structure will block ' 'light') \ .is_required() if extent == part_extent_option: FieldValidator(part_extent_detail, 'part_extent_detail', None, validation_error_builder, summary_message='Enter a description', inline_message='Check Plan A. This will give you a written description of the servient ' 'land') \ .is_required() return validation_error_builder.get()
def test_is_email_adds_error_when_email_invalid(self): validation_error_builder = ValidationErrorBuilder() email = 'invalid email' FieldValidator(email, 'email', email, validation_error_builder) \ .is_email() validation_errors = validation_error_builder.get().errors self.assertEqual(validation_errors['email'].summary_message, 'invalid email is not a valid email address')
def test_is_required_doesnt_add_error_when_input_provided(self): validation_error_builder = ValidationErrorBuilder() username = '******' FieldValidator(username, 'username', 'Username', validation_error_builder) \ .is_required() validation_errors = validation_error_builder.get().errors self.assertTrue('username' not in validation_errors)
def validate(land_compensation_paid, amount_of_compensation, vary_action): """Specifies which validation methods should be called for each input field. parameters: - land_compensation_paid: Part of the compensation (paid in advance) - amount_of_compensation: The total amount of compensation payable to the landowner from which the land was acquired. returns: dict: An instance of ValidationErrorBuilder with a ValidationError dict and a heading summary message. """ validation_error_builder = ValidationErrorBuilder() FieldValidator(land_compensation_paid, 'land-compensation-paid', 'Advance payment amount', validation_error_builder, summary_message='Enter the advance payment', inline_message='This is part of the compensation (paid in advance)') \ .is_required() if not vary_action: FieldValidator(amount_of_compensation, 'amount-of-compensation', 'Total compensation amount', validation_error_builder, summary_message='Enter the total compensation', inline_message='This is the total compensation') \ .is_required() FieldValidator(amount_of_compensation, 'amount-of-compensation', 'Total compensation amount', validation_error_builder, summary_message='Compensation must be a positive number', inline_message='Compensation must be a positive number')\ .is_positive_number() FieldValidator(land_compensation_paid, 'land-compensation-paid', 'Advance payment amount', validation_error_builder, summary_message='Advance payment cannot be more than total compensation', inline_message='Advance payment cannot be more than total compensation')\ .is_less_than_or_equal_to(amount_of_compensation) FieldValidator(amount_of_compensation, 'amount-of-compensation', 'Total compensation amount', validation_error_builder, summary_message='Compensation payment can only have 2 numbers after the decimal place', inline_message='Compensation payment can only have 2 numbers after the decimal place')\ .is_number_with_zero_or_x_decimal_places(2) FieldValidator(land_compensation_paid, 'land-compensation-paid', 'Advance payment amount', validation_error_builder, summary_message='Advance payment must be a positive number', inline_message='Advance payment must be a positive number')\ .is_positive_number() FieldValidator(land_compensation_paid, 'land-compensation-paid', 'Advance payment amount', validation_error_builder, summary_message='Advance payment can only have 2 numbers after the decimal place', inline_message='Advance payment can only have 2 numbers after the decimal place')\ .is_number_with_zero_or_x_decimal_places(2) return validation_error_builder.get()
def validate(search_reference): validation_error_builder = ValidationErrorBuilder() FieldValidator(search_reference, 'search-reference', None, validation_error_builder, summary_message="Authority reference or HM Land Registry reference is required") \ .is_required() validation_errors = validation_error_builder.get() return validation_errors
def test_is_item_count_equal_to_set_error(self): list_set = [1, 2] validation_error_builder = ValidationErrorBuilder() FieldValidator(list_set, 'a', 'b', validation_error_builder) \ .is_item_count_equal_to(1) validation_errors = validation_error_builder.get().errors self.assertEqual(len(validation_errors), 1) self.assertEqual('Only 1 b can be supplied', validation_errors['a'].summary_message)
def test_is_required_adds_error_when_input_empty(self): validation_error_builder = ValidationErrorBuilder() username = '' FieldValidator(username, 'username', 'Username', validation_error_builder) \ .is_required() validation_errors = validation_error_builder.get().errors self.assertEqual(validation_errors['username'].summary_message, 'Username is required')
def test_add_error_with_inline_message(self): validation_error_builder = ValidationErrorBuilder() email = 'test' inline_message = 'This is an inline message' FieldValidator(email, 'email', None, validation_error_builder, inline_message=inline_message) \ .is_email() validation_errors = validation_error_builder.get().errors self.assertEqual(validation_errors['email'].inline_message, inline_message)