Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Normal Nigerian number should be 10 digits long excluding country code #488

Closed
Sirneij opened this issue Jan 17, 2022 · 10 comments
Closed

Comments

@Sirneij
Copy link

Sirneij commented Jan 17, 2022

I am currently faced with the issue of validating Nigerian numbers. Normally, a typical Nigerian number is +234 XXX XXX XXXX or 0XX XXX XXX XX and when I test the formatted number against this regex r'^(0|\+234)[0-9]{10}', I always get this assertion error

AssertionError: Lists differ: [ErrorDetail(string=*Enter a valid phone number.', code='invalid')] != ['... phone number cannot be the same as your phone number.']

My settings.py has PHONENUMBER_DEFAULT_REGION = 'NG', and I tested my regex against the return value of phonenumbers.format_number( phonenumbers.parse(str(value), settings.PHONENUMBER_DEFAULT_REGION), phonenumbers.PhoneNumberFormat.E164 )

@francoisfreitag
Copy link
Collaborator

Hi,
It’s hard to see where the issue is without more details about what you are trying to achieve. Can you give a small code that allows reproducing the issue?
Also, can you access the entire error message?

It may be that the phone number your are using is not actually correct, despite being correctly formatted. Perhaps try to construct it directly with the phonenumbers library:

>>> phonenumbers.is_valid_number(
...     phonenumbers.parse("+2341234567", "NG")
... )
True

However:

>>> phonenumbers.is_valid_number(
...     phonenumbers.parse("+2340000000", "NG")
... )
False

@Sirneij Sirneij closed this as completed Jan 19, 2022
@Sirneij
Copy link
Author

Sirneij commented Jan 19, 2022

Thank you @francoisfreitag . I already fixed the issue.

@Sirneij Sirneij reopened this Jan 19, 2022
@Sirneij Sirneij closed this as completed Jan 19, 2022
@Sirneij Sirneij reopened this Jan 19, 2022
@Sirneij
Copy link
Author

Sirneij commented Jan 19, 2022

I am forced to reopen this issue.

Let me be more elaborate.

I have a serializer that tries to validate input phone number. From the input, I get the value inputted and format it using:

formatted_number = phonenumbers.format_number(
            phonenumbers.parse(str(value), 'NG'), phonenumbers.PhoneNumberFormat.E164
        )

Then, as part of the validation, I created a regex and searches the formatted number for a conformity with my regex. If it doesn't, I want a ValidationError to be raised:

nigeria_phone_number_pattern = r'^(0|\+234)[0-9]{10}'
        if not bool(re.search(nigeria_phone_number_pattern, formatted_number)):
            raise serializers.ValidationError(detail='Enter a valid phone number. Shorter length.')

When I test this serializer, with an input number that doesn't match the regex, I get the following error:

self.assertEqual(
E   AssertionError: Lists differ: [ErrorDetail(string='Enter a valid phone number.', code='invalid')] != ['Enter a valid phone number. Shorter length.']
E   
E   First differing element 0:
E   ErrorDetail(string='Enter a valid phone number.', code='invalid')
E   'Enter a valid phone number. Shorter length.'
E   
E   - [ErrorDetail(string='Enter a valid phone number.', code='invalid')]
E   + ['Enter a valid phone number. Shorter length.'] : Invalid request parameters.

Why this?

@francoisfreitag
Copy link
Collaborator

The input value is converted from a string to a PhoneNumber python object by the serializer field, then verified for validity:

phone_number = to_python(data)
if phone_number and not phone_number.is_valid():
raise ValidationError(self.error_messages["invalid"])

That verification occurs before your custom validation kicks in, which is why you are seeing the library error message and not yours.
https://www.django-rest-framework.org/api-guide/fields/#custom-fields documents to_internal_value as follows:

The .to_internal_value() method is called to restore a primitive datatype into its internal python representation. This method should raise a serializers.ValidationError if the data is invalid.

@Sirneij
Copy link
Author

Sirneij commented Jan 20, 2022

Thanks for that. How can I ensure my test passes with my custom error raised?

@francoisfreitag
Copy link
Collaborator

Maybe supply a valid phone number that does not match your regular expression?

@Sirneij
Copy link
Author

Sirneij commented Jan 20, 2022

I have done that. However, test coverage is lower than the threshold (100%) because of that line. It's saying that custom validation error hasn't been covered.

@francoisfreitag
Copy link
Collaborator

If the coverage says your line is not executed, there’s likely something wrong in your test. Re-read it carefully or use a debugger to step through the execution and understand why your line is not executed.

@Sirneij
Copy link
Author

Sirneij commented Jan 20, 2022

I have fixed it. I'll provide the detail soon

@Sirneij
Copy link
Author

Sirneij commented Jan 20, 2022

What I did was: in my test, I put a number that returns True with phonenumbers.is_valid_number() but False with my regex. This ensures that my tests passed and my custom validation error was executed in that regard.

@Sirneij Sirneij closed this as completed Jan 20, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants