Commit c5061146 authored by redatawfik's avatar redatawfik Committed by Commit Bot

Test Extract Card Number From Text

1- Move two methods "ExtractCreditCardNumber" and
   "SubstituteSimilarCharactersInRecognizedText" from mediator to
    Util file.
2- Write a unit test for the two methods.

Change-Id: Ie6e191cf06e4ae23d9993ded738dc374ec1c8790
Bug: 984545
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1782802Reviewed-by: default avatarGauthier Ambard <gambard@chromium.org>
Reviewed-by: default avatarJavier Ernesto Flores Robles <javierrobles@chromium.org>
Commit-Queue: Reda Tawfik <redatawfik@google.com>
Cr-Commit-Position: refs/heads/master@{#694756}
parent dd942877
...@@ -148,79 +148,8 @@ using base::UserMetricsAction; ...@@ -148,79 +148,8 @@ using base::UserMetricsAction;
self.expirationYear = [@([components year]) stringValue]; self.expirationYear = [@([components year]) stringValue];
} }
if (!self.cardNumber) { if (!self.cardNumber) {
self.cardNumber = [self extractCreditCardNumber:text]; self.cardNumber = ios::ExtractCreditCardNumber(text);
} }
} }
// Extracts credit card number from |string|.
- (NSString*)extractCreditCardNumber:(NSString*)string {
NSString* text = [[NSString alloc] initWithString:string];
// Strip whitespaces and symbols.
NSArray* ignoreSymbols = @[ @" ", @"/", @"-", @".", @":", @"\\" ];
for (NSString* symbol in ignoreSymbols) {
text = [text stringByReplacingOccurrencesOfString:symbol withString:@""];
}
// Matches strings which have 13-19 characters between the start(^) and the
// end($) of the line.
NSString* pattern = @"^(\\w{13,19})$";
NSError* error;
NSRegularExpression* regex = [[NSRegularExpression alloc]
initWithPattern:pattern
options:NSRegularExpressionAllowCommentsAndWhitespace
error:&error];
NSRange rangeOfText = NSMakeRange(0, [text length]);
NSTextCheckingResult* match = [regex firstMatchInString:text
options:0
range:rangeOfText];
if (!match) {
return nil;
}
NSString* stringMatchingPattern = [text substringWithRange:match.range];
NSString* creditCardNumber =
[self substituteSimilarCharactersInRecognizedText:stringMatchingPattern];
NSCharacterSet* allowedCharacterSet =
[NSCharacterSet decimalDigitCharacterSet];
NSCharacterSet* creditCardNumberSet =
[NSCharacterSet characterSetWithCharactersInString:creditCardNumber];
if ([allowedCharacterSet isSupersetOfSet:creditCardNumberSet]) {
return creditCardNumber;
}
return nil;
}
// Substitutes commonly misrecognized characters, for example: 'S' -> '5' or
// 'l' -> '1'
- (NSString*)substituteSimilarCharactersInRecognizedText:
(NSString*)recognizedText {
NSDictionary* misrecognisedAlphabets = @{
@"B" : @"8",
@"C" : @"0",
@"D" : @"0",
@"G" : @"9",
@"I" : @"1",
@"L" : @"1",
@"O" : @"0",
@"Q" : @"0",
@"S" : @"5",
@"T" : @"7",
@"U" : @"0",
@"Z" : @"7"
};
NSString* substitutedText =
[[NSString alloc] initWithString:recognizedText].uppercaseString;
for (NSString* alphabet in misrecognisedAlphabets) {
NSString* digit = misrecognisedAlphabets[alphabet];
substitutedText =
[substitutedText stringByReplacingOccurrencesOfString:alphabet
withString:digit];
}
return substitutedText;
}
@end @end
...@@ -12,6 +12,13 @@ namespace ios { ...@@ -12,6 +12,13 @@ namespace ios {
// Extracts credit card expiration month and year from |text|. // Extracts credit card expiration month and year from |text|.
NSDateComponents* ExtractExpirationDateFromText(NSString* text); NSDateComponents* ExtractExpirationDateFromText(NSString* text);
// Extracts credit card number from |string|.
NSString* ExtractCreditCardNumber(NSString* string);
// Substitutes commonly misrecognized characters, for example: 'S' -> '5' or
// 'l' -> '1'
NSString* SubstituteSimilarCharactersInRecognizedText(NSString* recognizedText);
} // namespace ios } // namespace ios
#endif // IOS_CHROME_BROWSER_UI_SETTINGS_CREDIT_CARD_SCANNER_CREDIT_CARD_SCANNER_MEDIATOR_UTIL_H_ #endif // IOS_CHROME_BROWSER_UI_SETTINGS_CREDIT_CARD_SCANNER_CREDIT_CARD_SCANNER_MEDIATOR_UTIL_H_
...@@ -25,4 +25,72 @@ NSDateComponents* ExtractExpirationDateFromText(NSString* text) { ...@@ -25,4 +25,72 @@ NSDateComponents* ExtractExpirationDateFromText(NSString* text) {
return nil; return nil;
} }
NSString* ExtractCreditCardNumber(NSString* string) {
NSString* text = [[NSString alloc] initWithString:string];
// Strip whitespaces and symbols.
NSArray* ignoreSymbols = @[ @" ", @"/", @"-", @".", @":", @"\\" ];
for (NSString* symbol in ignoreSymbols) {
text = [text stringByReplacingOccurrencesOfString:symbol withString:@""];
}
// Matches strings which have 13-19 characters between the start(^) and the
// end($) of the line.
NSString* pattern = @"^(\\w{13,19})$";
NSError* error;
NSRegularExpression* regex = [[NSRegularExpression alloc]
initWithPattern:pattern
options:NSRegularExpressionAllowCommentsAndWhitespace
error:&error];
NSRange rangeOfText = NSMakeRange(0, [text length]);
NSTextCheckingResult* match = [regex firstMatchInString:text
options:0
range:rangeOfText];
if (!match) {
return nil;
}
NSString* stringMatchingPattern = [text substringWithRange:match.range];
NSString* creditCardNumber =
SubstituteSimilarCharactersInRecognizedText(stringMatchingPattern);
NSCharacterSet* allowedCharacterSet =
[NSCharacterSet decimalDigitCharacterSet];
NSCharacterSet* creditCardNumberSet =
[NSCharacterSet characterSetWithCharactersInString:creditCardNumber];
if ([allowedCharacterSet isSupersetOfSet:creditCardNumberSet]) {
return creditCardNumber;
}
return nil;
}
NSString* SubstituteSimilarCharactersInRecognizedText(
NSString* recognizedText) {
NSDictionary* misrecognisedAlphabets = @{
@"B" : @"8",
@"C" : @"0",
@"D" : @"0",
@"G" : @"9",
@"I" : @"1",
@"L" : @"1",
@"O" : @"0",
@"Q" : @"0",
@"S" : @"5",
@"T" : @"7",
@"U" : @"0",
@"Z" : @"7"
};
NSString* substitutedText =
[[NSString alloc] initWithString:recognizedText].uppercaseString;
for (NSString* alphabet in misrecognisedAlphabets) {
NSString* digit = misrecognisedAlphabets[alphabet];
substitutedText =
[substitutedText stringByReplacingOccurrencesOfString:alphabet
withString:digit];
}
return substitutedText;
}
} // namespace ios } // namespace ios
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#import "ios/chrome/browser/ui/settings/credit_card_scanner/credit_card_scanner_mediator_util.h" #import "ios/chrome/browser/ui/settings/credit_card_scanner/credit_card_scanner_mediator_util.h"
#include "testing/gtest_mac.h"
#include "testing/platform_test.h" #include "testing/platform_test.h"
#if !defined(__has_feature) || !__has_feature(objc_arc) #if !defined(__has_feature) || !__has_feature(objc_arc)
...@@ -12,6 +13,8 @@ ...@@ -12,6 +13,8 @@
using CreditCardScannerMediatorUtilTest = PlatformTest; using CreditCardScannerMediatorUtilTest = PlatformTest;
#pragma mark - Test ExtractExpirationDateFromText
// Tests extracting month and year from valid date text. // Tests extracting month and year from valid date text.
TEST_F(CreditCardScannerMediatorUtilTest, TEST_F(CreditCardScannerMediatorUtilTest,
TestExtractExpirationDateFromValidDateText) { TestExtractExpirationDateFromValidDateText) {
...@@ -44,3 +47,84 @@ TEST_F(CreditCardScannerMediatorUtilTest, ...@@ -44,3 +47,84 @@ TEST_F(CreditCardScannerMediatorUtilTest,
EXPECT_FALSE(components); EXPECT_FALSE(components);
} }
#pragma mark - Test ExtractCreditCardNumber
// Tests extracting card number from valid card number text (16 digits).
TEST_F(CreditCardScannerMediatorUtilTest,
TestExtractCardNumberFromValidCreditCardNumber16Digits) {
NSString* cardNumber = ios::ExtractCreditCardNumber(@"4111111111111111");
EXPECT_NSEQ(cardNumber, @"4111111111111111");
}
// Tests extracting card number from valid card number text (14 digits).
TEST_F(CreditCardScannerMediatorUtilTest,
TestExtractCardNumberFromValidCreditCardNumber14Digits) {
NSString* cardNumber = ios::ExtractCreditCardNumber(@"4111111111111");
EXPECT_NSEQ(cardNumber, @"4111111111111");
}
// Tests extracting card number from valid card number text contains wrong
// characters.
TEST_F(CreditCardScannerMediatorUtilTest,
TestExtractCardNumberFromValidCreditCardNumberWithWrongCharacters) {
NSString* cardNumber = ios::ExtractCreditCardNumber(@"41/11-1111 1111.11:11");
EXPECT_NSEQ(cardNumber, @"4111111111111111");
}
// Tests extracting card number from text after converting
// illegal characters.
TEST_F(CreditCardScannerMediatorUtilTest,
TestExtractCardNumberFromValidCreditCardNumberAfterConversion) {
NSString* cardNumber = ios::ExtractCreditCardNumber(@"41b1C1g1D1i1L1z1");
EXPECT_NSEQ(cardNumber, @"4181019101111171");
}
// Tests extracting card number from invalid card number text (10 digits).
TEST_F(CreditCardScannerMediatorUtilTest,
TestExtractCardNumberFromInvalidCreditCardNumber10Digits) {
NSString* cardNumber = ios::ExtractCreditCardNumber(@"4111111111");
EXPECT_FALSE(cardNumber);
}
// Tests extracting card number from invalid card number text.
TEST_F(CreditCardScannerMediatorUtilTest,
TestExtractCardNumberFromInvalidCreditCardNumber) {
NSString* cardNumber = ios::ExtractCreditCardNumber(@"4111a11b11c11");
EXPECT_FALSE(cardNumber);
}
#pragma mark - Test SubstituteSimilarCharactersInRecognizedText
// Tests substituting convertible characters with digits.
TEST_F(CreditCardScannerMediatorUtilTest,
TestSubstitutingTrueCharactersWithDigits) {
NSString* number =
ios::SubstituteSimilarCharactersInRecognizedText(@"bCdGiLoQsTuZ");
EXPECT_NSEQ(number, @"800911005707");
}
// Tests substituting text without characters with digits.
TEST_F(CreditCardScannerMediatorUtilTest,
TestSubstitutingTextWithoutCharacters) {
NSString* number =
ios::SubstituteSimilarCharactersInRecognizedText(@"4111111111111111");
EXPECT_NSEQ(number, @"4111111111111111");
}
// Tests substituting inconvertible characters with digits.
TEST_F(CreditCardScannerMediatorUtilTest,
TestSubstitutingFalseCharactersWithDigits) {
NSString* cardNumber =
ios::SubstituteSimilarCharactersInRecognizedText(@"abcdefghi");
EXPECT_NSEQ(cardNumber, @"A800EF9H1");
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment