From 5892bc98e6767c8521c839786f3b71e8f9727c60 Mon Sep 17 00:00:00 2001 From: Gianluca Canese Date: Tue, 28 May 2024 19:31:21 -0400 Subject: [PATCH 1/3] Add support for missing phone number types --- lib/src/validation/phone_number_type.dart | 7 +++ lib/src/validation/validator.dart | 66 ++++++++++++++++++++--- 2 files changed, 65 insertions(+), 8 deletions(-) diff --git a/lib/src/validation/phone_number_type.dart b/lib/src/validation/phone_number_type.dart index 5fbc128..c9c9ead 100644 --- a/lib/src/validation/phone_number_type.dart +++ b/lib/src/validation/phone_number_type.dart @@ -2,4 +2,11 @@ enum PhoneNumberType { mobile, fixedLine, voip, + tollFree, + premiumRate, + sharedCost, + personalNumber, + uan, + pager, + voiceMail, } diff --git a/lib/src/validation/validator.dart b/lib/src/validation/validator.dart index 0663079..3fb2357 100644 --- a/lib/src/validation/validator.dart +++ b/lib/src/validation/validator.dart @@ -32,7 +32,22 @@ abstract class Validator { patterns.addAll([ _getPatterns(patternMetadatas, PhoneNumberType.fixedLine), _getPatterns(patternMetadatas, PhoneNumberType.mobile), - _getPatterns(patternMetadatas, PhoneNumberType.voip) + if (patternMetadatas.voip.isNotEmpty) + _getPatterns(patternMetadatas, PhoneNumberType.voip), + if (patternMetadatas.tollFree.isNotEmpty) + _getPatterns(patternMetadatas, PhoneNumberType.tollFree), + if (patternMetadatas.premiumRate.isNotEmpty) + _getPatterns(patternMetadatas, PhoneNumberType.premiumRate), + if (patternMetadatas.sharedCost.isNotEmpty) + _getPatterns(patternMetadatas, PhoneNumberType.sharedCost), + if (patternMetadatas.personalNumber.isNotEmpty) + _getPatterns(patternMetadatas, PhoneNumberType.personalNumber), + if (patternMetadatas.uan.isNotEmpty) + _getPatterns(patternMetadatas, PhoneNumberType.uan), + if (patternMetadatas.pager.isNotEmpty) + _getPatterns(patternMetadatas, PhoneNumberType.pager), + if (patternMetadatas.voiceMail.isNotEmpty) + _getPatterns(patternMetadatas, PhoneNumberType.voiceMail), ]); } else { patterns.add(_getPatterns(patternMetadatas, type)); @@ -72,13 +87,20 @@ abstract class Validator { final lengths = _getLengths(lengthMetadatas, type); return Set.from(lengths); } else { - // if the type is not specified it can be either mobile, fixedLine or voip - // so we return a set containing both - final rulesFixed = - _getLengths(lengthMetadatas, PhoneNumberType.fixedLine); - final rulesMobile = _getLengths(lengthMetadatas, PhoneNumberType.mobile); - final rulesVoip = _getLengths(lengthMetadatas, PhoneNumberType.voip); - return {...rulesFixed, ...rulesMobile, ...rulesVoip}; + // if the type is not specified it can be any of them + // so we return a set containing all their possible lengths + return { + ..._getLengths(lengthMetadatas, PhoneNumberType.fixedLine), + ..._getLengths(lengthMetadatas, PhoneNumberType.mobile), + ..._getLengths(lengthMetadatas, PhoneNumberType.voip), + ..._getLengths(lengthMetadatas, PhoneNumberType.tollFree), + ..._getLengths(lengthMetadatas, PhoneNumberType.premiumRate), + ..._getLengths(lengthMetadatas, PhoneNumberType.sharedCost), + ..._getLengths(lengthMetadatas, PhoneNumberType.personalNumber), + ..._getLengths(lengthMetadatas, PhoneNumberType.uan), + ..._getLengths(lengthMetadatas, PhoneNumberType.pager), + ..._getLengths(lengthMetadatas, PhoneNumberType.voiceMail), + }; } } @@ -93,6 +115,20 @@ abstract class Validator { return lengthMetadatas.fixedLine; case PhoneNumberType.voip: return lengthMetadatas.voip; + case PhoneNumberType.tollFree: + return lengthMetadatas.tollFree; + case PhoneNumberType.premiumRate: + return lengthMetadatas.premiumRate; + case PhoneNumberType.sharedCost: + return lengthMetadatas.sharedCost; + case PhoneNumberType.personalNumber: + return lengthMetadatas.personalNumber; + case PhoneNumberType.uan: + return lengthMetadatas.uan; + case PhoneNumberType.pager: + return lengthMetadatas.pager; + case PhoneNumberType.voiceMail: + return lengthMetadatas.voiceMail; default: return lengthMetadatas.general; } @@ -109,6 +145,20 @@ abstract class Validator { return patternMetadatas.fixedLine; case PhoneNumberType.voip: return patternMetadatas.voip; + case PhoneNumberType.tollFree: + return patternMetadatas.tollFree; + case PhoneNumberType.premiumRate: + return patternMetadatas.premiumRate; + case PhoneNumberType.sharedCost: + return patternMetadatas.sharedCost; + case PhoneNumberType.personalNumber: + return patternMetadatas.personalNumber; + case PhoneNumberType.uan: + return patternMetadatas.uan; + case PhoneNumberType.pager: + return patternMetadatas.pager; + case PhoneNumberType.voiceMail: + return patternMetadatas.voiceMail; default: return patternMetadatas.general; } From 928410fac4ffab7c1935b621a037779b90e3675f Mon Sep 17 00:00:00 2001 From: Gianluca Canese Date: Wed, 29 May 2024 11:09:22 -0400 Subject: [PATCH 2/3] Update demo and tests --- demo/lib/main.dart | 174 ++++++++++++++++-------- test/internal/_validator_test.dart | 207 +++++++++++++++++++++++++++++ test/phone_number_test.dart | 10 ++ 3 files changed, 338 insertions(+), 53 deletions(-) diff --git a/demo/lib/main.dart b/demo/lib/main.dart index f5eeba4..73e918d 100644 --- a/demo/lib/main.dart +++ b/demo/lib/main.dart @@ -60,59 +60,127 @@ class _MyHomePageState extends State { }, ), const SizedBox(height: 12), - ListTile( - title: const Text('international'), - trailing: phoneNumber != null - ? Text(phoneNumber.international) - : const Text('-'), - ), - ListTile( - title: const Text('Formatted national'), - trailing: phoneNumber != null - ? Text(phoneNumber.formatNsn()) - : const Text('-'), - ), - ListTile( - title: const Text('Iso code'), - trailing: phoneNumber != null - ? Text(phoneNumber.isoCode.name) - : const Text('-'), - ), - ListTile( - title: const Text('Country Dial Code'), - trailing: phoneNumber != null - ? Text(phoneNumber.countryCode) - : const Text('-'), - ), - ListTile( - title: const Text('Is Valid'), - trailing: phoneNumber != null - ? Text(phoneNumber.isValid().toString()) - : const Text('-'), - ), - ListTile( - title: const Text('Is Valid Mobile'), - trailing: phoneNumber != null - ? Text(phoneNumber - .isValid(type: PhoneNumberType.mobile) - .toString()) - : const Text('-'), - ), - ListTile( - title: const Text('Is Valid Fixed Line'), - trailing: phoneNumber != null - ? Text(phoneNumber - .isValid(type: PhoneNumberType.fixedLine) - .toString()) - : const Text('-'), - ), - ListTile( - title: const Text('Is Valid Voip'), - trailing: phoneNumber != null - ? Text(phoneNumber - .isValid(type: PhoneNumberType.voip) - .toString()) - : const Text('-'), + Expanded( + child: CustomScrollView( + slivers: [ + SliverList( + delegate: SliverChildListDelegate( + [ + ListTile( + title: const Text('international'), + trailing: phoneNumber != null + ? Text(phoneNumber.international) + : const Text('-'), + ), + ListTile( + title: const Text('Formatted national'), + trailing: phoneNumber != null + ? Text(phoneNumber.formatNsn()) + : const Text('-'), + ), + ListTile( + title: const Text('Iso code'), + trailing: phoneNumber != null + ? Text(phoneNumber.isoCode.name) + : const Text('-'), + ), + ListTile( + title: const Text('Country Dial Code'), + trailing: phoneNumber != null + ? Text(phoneNumber.countryCode) + : const Text('-'), + ), + ListTile( + title: const Text('Is Valid'), + trailing: phoneNumber != null + ? Text(phoneNumber.isValid().toString()) + : const Text('-'), + ), + ListTile( + title: const Text('Is Valid Mobile'), + trailing: phoneNumber != null + ? Text(phoneNumber + .isValid(type: PhoneNumberType.mobile) + .toString()) + : const Text('-'), + ), + ListTile( + title: const Text('Is Valid Fixed Line'), + trailing: phoneNumber != null + ? Text(phoneNumber + .isValid(type: PhoneNumberType.fixedLine) + .toString()) + : const Text('-'), + ), + ListTile( + title: const Text('Is Valid Voip'), + trailing: phoneNumber != null + ? Text(phoneNumber + .isValid(type: PhoneNumberType.voip) + .toString()) + : const Text('-'), + ), + ListTile( + title: const Text('Is Valid Toll-Free'), + trailing: phoneNumber != null + ? Text(phoneNumber + .isValid(type: PhoneNumberType.tollFree) + .toString()) + : const Text('-'), + ), + ListTile( + title: const Text('Is Valid Premium Rate'), + trailing: phoneNumber != null + ? Text(phoneNumber + .isValid(type: PhoneNumberType.premiumRate) + .toString()) + : const Text('-'), + ), + ListTile( + title: const Text('Is Valid Shared Cost'), + trailing: phoneNumber != null + ? Text(phoneNumber + .isValid(type: PhoneNumberType.sharedCost) + .toString()) + : const Text('-'), + ), + ListTile( + title: const Text('Is Valid Personal Number'), + trailing: phoneNumber != null + ? Text(phoneNumber + .isValid(type: PhoneNumberType.personalNumber) + .toString()) + : const Text('-'), + ), + ListTile( + title: const Text('Is Valid UAN'), + trailing: phoneNumber != null + ? Text(phoneNumber + .isValid(type: PhoneNumberType.uan) + .toString()) + : const Text('-'), + ), + ListTile( + title: const Text('Is Valid Pager'), + trailing: phoneNumber != null + ? Text(phoneNumber + .isValid(type: PhoneNumberType.pager) + .toString()) + : const Text('-'), + ), + ListTile( + title: const Text('Is Valid Voice Mail'), + trailing: phoneNumber != null + ? Text(phoneNumber + .isValid(type: PhoneNumberType.voiceMail) + .toString()) + : const Text('-'), + ), + ], + ), + ), + ], + ), ), ], ), diff --git a/test/internal/_validator_test.dart b/test/internal/_validator_test.dart index 11a2889..2630f10 100644 --- a/test/internal/_validator_test.dart +++ b/test/internal/_validator_test.dart @@ -1,3 +1,4 @@ +import 'package:phone_numbers_parser/metadata.dart'; import 'package:phone_numbers_parser/phone_numbers_parser.dart'; import 'package:phone_numbers_parser/src/validation/validator.dart'; import 'package:test/test.dart'; @@ -76,6 +77,109 @@ void main() { isTrue, ); }); + + // Portugal supports all phone types + test('PT', () { + final isoCode = IsoCode.PT; + final examples = metadataExamplesByIsoCode[isoCode]!; + expect( + Validator.validateWithLength( + isoCode, + examples.mobile, + ), + isTrue, + ); + + expect( + Validator.validateWithLength( + isoCode, + examples.mobile, + PhoneNumberType.mobile, + ), + isTrue, + ); + + expect( + Validator.validateWithLength( + isoCode, + examples.fixedLine, + PhoneNumberType.fixedLine, + ), + isTrue, + ); + + expect( + Validator.validateWithLength( + isoCode, + examples.voip, + PhoneNumberType.voip, + ), + isTrue, + ); + + expect( + Validator.validateWithLength( + isoCode, + examples.tollFree, + PhoneNumberType.tollFree, + ), + isTrue, + ); + + expect( + Validator.validateWithLength( + isoCode, + examples.premiumRate, + PhoneNumberType.premiumRate, + ), + isTrue, + ); + + expect( + Validator.validateWithLength( + isoCode, + examples.sharedCost, + PhoneNumberType.sharedCost, + ), + isTrue, + ); + + expect( + Validator.validateWithLength( + isoCode, + examples.personalNumber, + PhoneNumberType.personalNumber, + ), + isTrue, + ); + + expect( + Validator.validateWithLength( + isoCode, + examples.uan, + PhoneNumberType.uan, + ), + isTrue, + ); + + expect( + Validator.validateWithLength( + isoCode, + examples.pager, + PhoneNumberType.pager, + ), + isTrue, + ); + + expect( + Validator.validateWithLength( + isoCode, + examples.voiceMail, + PhoneNumberType.voiceMail, + ), + isTrue, + ); + }); }); group('ValidateWithPattern()', () { @@ -113,6 +217,109 @@ void main() { expect( Validator.validateWithPattern(IsoCode.US, '6135550165'), isFalse); }); + + // Portugal supports all phone types + test('PT', () { + final isoCode = IsoCode.PT; + final examples = metadataExamplesByIsoCode[isoCode]!; + expect( + Validator.validateWithPattern( + isoCode, + examples.mobile, + ), + isTrue, + ); + + expect( + Validator.validateWithPattern( + isoCode, + examples.mobile, + PhoneNumberType.mobile, + ), + isTrue, + ); + + expect( + Validator.validateWithPattern( + isoCode, + examples.fixedLine, + PhoneNumberType.fixedLine, + ), + isTrue, + ); + + expect( + Validator.validateWithPattern( + isoCode, + examples.voip, + PhoneNumberType.voip, + ), + isTrue, + ); + + expect( + Validator.validateWithPattern( + isoCode, + examples.tollFree, + PhoneNumberType.tollFree, + ), + isTrue, + ); + + expect( + Validator.validateWithPattern( + isoCode, + examples.premiumRate, + PhoneNumberType.premiumRate, + ), + isTrue, + ); + + expect( + Validator.validateWithPattern( + isoCode, + examples.sharedCost, + PhoneNumberType.sharedCost, + ), + isTrue, + ); + + expect( + Validator.validateWithPattern( + isoCode, + examples.personalNumber, + PhoneNumberType.personalNumber, + ), + isTrue, + ); + + expect( + Validator.validateWithPattern( + isoCode, + examples.uan, + PhoneNumberType.uan, + ), + isTrue, + ); + + expect( + Validator.validateWithPattern( + isoCode, + examples.pager, + PhoneNumberType.pager, + ), + isTrue, + ); + + expect( + Validator.validateWithPattern( + isoCode, + examples.voiceMail, + PhoneNumberType.voiceMail, + ), + isTrue, + ); + }); }); }); } diff --git a/test/phone_number_test.dart b/test/phone_number_test.dart index f57706c..5c83429 100644 --- a/test/phone_number_test.dart +++ b/test/phone_number_test.dart @@ -225,6 +225,16 @@ void main() { expect(gbValidLength.isValid(type: PhoneNumberType.mobile), isFalse); expect(gbValidLength.isValid(type: PhoneNumberType.fixedLine), isFalse); expect(gbValidLength.isValid(type: PhoneNumberType.voip), isFalse); + expect(gbValidLength.isValid(type: PhoneNumberType.tollFree), isFalse); + expect(gbValidLength.isValid(type: PhoneNumberType.premiumRate), isFalse); + expect(gbValidLength.isValid(type: PhoneNumberType.sharedCost), isFalse); + expect( + gbValidLength.isValid(type: PhoneNumberType.personalNumber), + isFalse, + ); + expect(gbValidLength.isValid(type: PhoneNumberType.uan), isFalse); + expect(gbValidLength.isValid(type: PhoneNumberType.pager), isFalse); + expect(gbValidLength.isValid(type: PhoneNumberType.voiceMail), isFalse); expect(gbValidLength.isValid(), isFalse); final gbValidPattern = PhoneNumber.parse('7111111111', destinationCountry: IsoCode.GB); From 69286e49108d9993a19a382ef2aa330ecff0bec5 Mon Sep 17 00:00:00 2001 From: Gianluca Canese Date: Wed, 29 May 2024 11:44:59 -0400 Subject: [PATCH 3/3] Add more test cases --- test/internal/_validator_test.dart | 41 ++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/test/internal/_validator_test.dart b/test/internal/_validator_test.dart index 2630f10..c0f001a 100644 --- a/test/internal/_validator_test.dart +++ b/test/internal/_validator_test.dart @@ -180,6 +180,47 @@ void main() { isTrue, ); }); + + // Italy has different lengths for different formats + test('IT', () { + final isoCode = IsoCode.IT; + final examples = metadataExamplesByIsoCode[isoCode]!; + expect( + Validator.validateWithLength( + isoCode, + examples.sharedCost, // Can be 6 or 9 + PhoneNumberType.voip, // Can be 10 + ), + isFalse, + ); + + expect( + Validator.validateWithLength( + isoCode, + examples.voip, // Can be 10 + PhoneNumberType.sharedCost, // Can be 6 or 9 + ), + isFalse, + ); + + expect( + Validator.validateWithLength( + isoCode, + examples.voiceMail, // Can be 11 or 12 + PhoneNumberType.personalNumber, // Can be 9 or 10 + ), + isFalse, + ); + + expect( + Validator.validateWithLength( + isoCode, + examples.personalNumber, // Can be 9 or 10 + PhoneNumberType.voiceMail, // Can be 11 or 12 + ), + isFalse, + ); + }); }); group('ValidateWithPattern()', () {