0001-fields-custom-error-message-for-django-regex-validat.patch
tests/admin_pages/test_form.py | ||
---|---|---|
1492 | 1492 |
resp = resp.click('Edit', href='1/') |
1493 | 1493 |
resp.form['validation$type'] = 'Regular Expression' |
1494 | 1494 |
resp.form['validation$value_regex'] = r'\d+' |
1495 |
resp.form['validation$error_message'] = 'Foo Error' |
|
1495 | 1496 |
resp = resp.form.submit('submit').follow() |
1496 |
assert FormDef.get(formdef.id).fields[0].validation == {'type': 'regex', 'value': r'\d+'} |
|
1497 |
assert FormDef.get(formdef.id).fields[0].validation == {'type': 'regex', 'value': r'\d+', 'error_message': 'Foo Error'}
|
|
1497 | 1498 | |
1498 | 1499 |
resp = resp.click('Edit', href='1/') |
1499 | 1500 |
resp.form['validation$type'] = 'None' |
... | ... | |
1503 | 1504 |
resp = resp.click('Edit', href='1/') |
1504 | 1505 |
resp.form['validation$type'] = 'Django Condition' |
1505 | 1506 |
resp.form['validation$value_django'] = 'value|decimal < 20' |
1507 |
resp.form['validation$error_message'] = 'Bar Error' |
|
1506 | 1508 |
resp = resp.form.submit('submit').follow() |
1507 |
assert FormDef.get(formdef.id).fields[0].validation == {'type': 'django', 'value': 'value|decimal < 20'} |
|
1509 |
assert FormDef.get(formdef.id).fields[0].validation == {'type': 'django', 'value': 'value|decimal < 20', 'error_message': 'Bar Error'}
|
|
1508 | 1510 | |
1509 | 1511 |
resp = resp.click('Edit', href='1/') |
1510 | 1512 |
resp.form['validation$type'] = 'Django Condition' |
tests/test_widgets.py | ||
---|---|---|
720 | 720 |
widget.field = fakefield |
721 | 721 |
mock_form_submission(req, widget, {'test': '12,34'}) |
722 | 722 |
assert widget.has_error() |
723 |
assert widget.error == 'invalid value' |
|
724 | ||
725 |
widget = WcsExtraStringWidget('test', value='foo', required=False) |
|
726 |
fakefield.validation = { |
|
727 |
'type': 'regex', 'value': r'\d+(\.\d{1,2})?', |
|
728 |
'error_message': 'Foo Bar Custom Error' |
|
729 |
} |
|
730 |
widget.field = fakefield |
|
731 |
mock_form_submission(req, widget, {'test': '12,34'}) |
|
732 |
assert widget.has_error() |
|
733 |
assert widget.error == 'Foo Bar Custom Error' |
|
723 | 734 | |
724 | 735 | |
725 | 736 |
def test_wcsextrastringwidget_builtin_validation(): |
... | ... | |
736 | 747 |
widget.field = fakefield |
737 | 748 |
mock_form_submission(req, widget, {'test': 'az'}) |
738 | 749 |
assert widget.has_error() |
750 |
assert widget.error == 'Only digits are allowed' |
|
739 | 751 | |
740 | 752 |
fakefield.validation = {'type': 'zipcode-fr'} |
741 | 753 |
widget = WcsExtraStringWidget('test', value='foo', required=False) |
... | ... | |
752 | 764 |
widget.field = fakefield |
753 | 765 |
mock_form_submission(req, widget, {'test': '1234'}) |
754 | 766 |
assert widget.has_error() |
767 |
assert widget.error == 'Invalid zip code (5 digits required)' |
|
755 | 768 | |
756 | 769 | |
757 | 770 |
def test_wcsextrastringwidget_phone(): |
... | ... | |
772 | 785 |
widget.field = fakefield |
773 | 786 |
mock_form_submission(req, widget, {'test': invalid_case}) |
774 | 787 |
assert widget.has_error() |
788 |
assert widget.error == 'Invalid phone number' |
|
775 | 789 | |
776 | 790 |
# and check it gets a special HTML input type |
777 | 791 |
widget = WcsExtraStringWidget('test', value='foo', required=False) |
... | ... | |
800 | 814 |
widget.field = fakefield |
801 | 815 |
mock_form_submission(req, widget, {'test': 'az'}) |
802 | 816 |
assert widget.has_error() |
817 |
assert widget.error == 'Invalid phone number' |
|
803 | 818 | |
804 | 819 |
widget = WcsExtraStringWidget('test', value='foo', required=False) |
805 | 820 |
widget.field = fakefield |
... | ... | |
829 | 844 |
widget.field = fakefield |
830 | 845 |
mock_form_submission(req, widget, {'test': '443170130'}) |
831 | 846 |
assert widget.has_error() |
847 |
assert widget.error == 'Invalid SIREN code' |
|
832 | 848 | |
833 | 849 |
widget = WcsExtraStringWidget('test', value='foo', required=False) |
834 | 850 |
widget.field = fakefield |
... | ... | |
868 | 884 |
widget.field = fakefield |
869 | 885 |
mock_form_submission(req, widget, {'test': '44317013900037'}) |
870 | 886 |
assert widget.has_error() |
887 |
assert widget.error == 'Invalid SIRET code' |
|
871 | 888 | |
872 | 889 |
widget = WcsExtraStringWidget('test', value='foo', required=False) |
873 | 890 |
widget.field = fakefield |
... | ... | |
907 | 924 |
widget.field = fakefield |
908 | 925 |
mock_form_submission(req, widget, {'test': '42'}) |
909 | 926 |
assert widget.has_error() |
927 |
assert widget.error == 'Invalid NIR' |
|
910 | 928 | |
911 | 929 |
widget = WcsExtraStringWidget('test', value='foo', required=False) |
912 | 930 |
widget.field = fakefield |
... | ... | |
979 | 997 |
widget.field = fakefield |
980 | 998 |
mock_form_submission(req, widget, {'test': iban.replace(' ', '')}) |
981 | 999 |
assert widget.has_error() |
1000 |
assert widget.error == 'Invalid IBAN' |
|
982 | 1001 | |
983 | 1002 | |
984 | 1003 |
def test_wcsextrastringwidget_django_validation(): |
... | ... | |
1000 | 1019 |
widget.field = fakefield |
1001 | 1020 |
mock_form_submission(req, widget, {'test': 'az'}) |
1002 | 1021 |
assert widget.has_error() |
1022 |
assert widget.error == 'invalid value' |
|
1023 | ||
1024 |
widget = WcsExtraStringWidget('test', value='foo', required=False) |
|
1025 |
fakefield.validation = { |
|
1026 |
'type': 'django', 'value': 'value|decimal and value|decimal < 20', |
|
1027 |
'error_message': 'Foo Bar Custom Error' |
|
1028 |
} |
|
1029 |
widget.field = fakefield |
|
1030 |
mock_form_submission(req, widget, {'test': 'az'}) |
|
1031 |
assert widget.has_error() |
|
1032 |
assert widget.error == 'Foo Bar Custom Error' |
|
1003 | 1033 | |
1004 | 1034 | |
1005 | 1035 |
def test_widgetdict_widget(): |
wcs/qommon/form.py | ||
---|---|---|
1022 | 1022 |
('digits', { |
1023 | 1023 |
'title': N_('Digits'), |
1024 | 1024 |
'regex': r'\d+', |
1025 |
'error_message': N_('Only digits are allowed'), |
|
1025 | 1026 |
'html_inputmode': 'numeric'} |
1026 | 1027 |
), |
1027 | 1028 |
('phone', { |
1028 | 1029 |
'title': N_('Phone Number'), |
1029 | 1030 |
'regex': r'\+?[-\(\)\d\.\s/]+', |
1031 |
'error_message': N_('Invalid phone number'), |
|
1030 | 1032 |
'html_input_type': 'tel'} |
1031 | 1033 |
), |
1032 | 1034 |
('phone-fr', { |
1033 | 1035 |
'title': N_('Phone Number (France)'), |
1034 | 1036 |
'function': 'validate_phone_fr', |
1037 |
'error_message': N_('Invalid phone number'), |
|
1035 | 1038 |
'html_input_type': 'tel'} |
1036 | 1039 |
), |
1037 | 1040 |
('zipcode-fr', { |
1038 | 1041 |
'title': N_('Zip Code (France)'), |
1039 | 1042 |
'regex': r'\d{5}', |
1043 |
'error_message': N_('Invalid zip code (5 digits required)'), |
|
1040 | 1044 |
'html_inputmode': 'numeric'} |
1041 | 1045 |
), |
1042 | 1046 |
('siren-fr', { |
1043 | 1047 |
'title': N_('SIREN Code (France)'), |
1044 | 1048 |
'function': 'validate_siren', |
1049 |
'error_message': N_('Invalid SIREN code'), |
|
1045 | 1050 |
'html_inputmode': 'numeric'} |
1046 | 1051 |
), |
1047 | 1052 |
('siret-fr', { |
1048 | 1053 |
'title': N_('SIRET Code (France)'), |
1049 | 1054 |
'function': 'validate_siret', |
1055 |
'error_message': N_('Invalid SIRET code'), |
|
1050 | 1056 |
'html_inputmode': 'numeric'} |
1051 | 1057 |
), |
1052 | 1058 |
('nir-fr', { |
1053 | 1059 |
'title': N_('NIR (France)'), |
1060 |
'error_message': N_('Invalid NIR'), |
|
1054 | 1061 |
'function': 'validate_nir'} |
1055 | 1062 |
), |
1056 | 1063 |
('iban', { |
1057 | 1064 |
'title': N_('IBAN'), |
1058 |
'function': 'validate_iban'} |
|
1065 |
'function': 'validate_iban', |
|
1066 |
'error_message': N_('Invalid IBAN')} |
|
1059 | 1067 |
), |
1060 | 1068 |
('regex', {'title': N_('Regular Expression')}), |
1061 | 1069 |
('django', {'title': N_('Django Condition')}), |
... | ... | |
1075 | 1083 |
self.value = {} |
1076 | 1084 | |
1077 | 1085 |
validation_labels = collections.OrderedDict(options) |
1078 |
self.add(RegexStringWidget, 'value_regex', size=80,
|
|
1086 |
self.add(RegexStringWidget, 'value_regex', size=40,
|
|
1079 | 1087 |
value=value.get('value') if value.get('type') == 'regex' else None, |
1080 | 1088 |
attrs={'data-dynamic-display-child-of': 'validation$type', |
1081 | 1089 |
'data-dynamic-display-value': validation_labels.get('regex')}) |
1082 |
self.add(DjangoConditionWidget, 'value_django', size=80,
|
|
1090 |
self.add(DjangoConditionWidget, 'value_django', size=40,
|
|
1083 | 1091 |
value=value.get('value') if value.get('type') == 'django' else None, |
1084 | 1092 |
attrs={'data-dynamic-display-child-of': 'validation$type', |
1085 | 1093 |
'data-dynamic-display-value': validation_labels.get('django')}) |
1094 |
self.add(StringWidget, 'error_message', size=60, |
|
1095 |
value=value.get('error_message') if value.get('type') in ['regex', 'django'] else None, |
|
1096 |
placeholder=_('Custom error message.'), |
|
1097 |
attrs={'data-dynamic-display-child-of': 'validation$type', |
|
1098 |
'data-dynamic-display-value-in': '|'.join([ |
|
1099 |
validation_labels.get('regex'), |
|
1100 |
validation_labels.get('django')])}) |
|
1086 | 1101 |
self._parsed = False |
1087 | 1102 | |
1088 | 1103 |
def _parse(self, request): |
... | ... | |
1093 | 1108 |
value = self.get('value_%s' % type_) |
1094 | 1109 |
if value: |
1095 | 1110 |
values['value'] = value |
1111 |
if type_ in ['regex', 'django']: |
|
1112 |
error_message = self.get('error_message') |
|
1113 |
if error_message: |
|
1114 |
values['error_message'] = error_message |
|
1096 | 1115 |
self.value = values or None |
1097 | 1116 | |
1098 | 1117 |
def render_content(self): |
... | ... | |
1119 | 1138 |
if validation_method and 'function' in validation_method: |
1120 | 1139 |
return getattr(misc, validation_method['function']) |
1121 | 1140 | |
1141 |
@classmethod |
|
1142 |
def get_validation_error_message(cls, validation): |
|
1143 |
pattern = cls.get_validation_pattern(validation) |
|
1144 |
if validation['type'] == 'regex' and pattern: |
|
1145 |
return validation.get('error_message') |
|
1146 |
if validation['type'] == 'django' and validation.get('value'): |
|
1147 |
return validation.get('error_message') |
|
1148 |
validation_method = cls.validation_methods.get(validation['type']) |
|
1149 |
if validation_method and 'error_message' in validation_method: |
|
1150 |
return validation_method['error_message'] |
|
1151 | ||
1122 | 1152 |
@classmethod |
1123 | 1153 |
def get_validation_pattern(cls, validation): |
1124 | 1154 |
validation_method = cls.validation_methods.get(validation['type']) |
... | ... | |
1163 | 1193 |
StringWidget._parse(self, request) |
1164 | 1194 |
if self.field and self.field.validation and self.value is not None: |
1165 | 1195 |
self.validation_function = ValidationWidget.get_validation_function(self.field.validation) |
1196 |
self.validation_function_error_message = ValidationWidget.get_validation_error_message(self.field.validation) |
|
1166 | 1197 | |
1167 | 1198 |
if self.validation_function and not self.validation_function(self.value): |
1168 | 1199 |
self.error = self.validation_function_error_message or _('invalid value') |
1169 |
- |