diff --git a/__tests__/mask/credit-card.mask.test.js b/__tests__/mask/credit-card.mask.test.js index 0760d828..46f9ebfe 100644 --- a/__tests__/mask/credit-card.mask.test.js +++ b/__tests__/mask/credit-card.mask.test.js @@ -1,5 +1,12 @@ import { CreditCardMask } from '../../lib/masks' +const testCards = { + visa: '4263982640269299', + mastercard: '5425233430109903', + amex: '374245455400126', + maestro: '6759649826438453' +} + test('getType results credit-card', () => { var expected = 'credit-card' var received = CreditCardMask.getType() @@ -7,73 +14,53 @@ test('getType results credit-card', () => { expect(received).toBe(expected) }) -test('1234123412341234 results 1234 1234 1234 1234', () => { +test('basic formatting', () => { var mask = new CreditCardMask() - var expected = '1234 1234 1234 1234' - var received = mask.getValue('1234123412341234') + var expected = '4263 9826 4026 9299' + var received = mask.getValue(testCards.visa) expect(received).toBe(expected) }) -test('1234123412341234 obfuscated true results 1234 **** **** 1234', () => { +test('obfuscated formatting', () => { var mask = new CreditCardMask() - var expected = '1234 **** **** 1234' - var received = mask.getValue('1234123412341234', { + var expected = '4263 **** **** 9299' + var received = mask.getValue(testCards.visa, { obfuscated: true }) expect(received).toBe(expected) }) -test('1234123412341234 obfuscated false results 1234 1234 1234 1234', () => { +test('correct raw value of basic formatting', () => { var mask = new CreditCardMask() - var expected = '1234 1234 1234 1234' - var received = mask.getValue('1234123412341234', { - obfuscated: false - }) + var received = mask.getValue(testCards.visa) - expect(received).toBe(expected) -}) - -test('1234123412341234 obfuscated false results 1234 1234 1234 1234 and raw value [1234, 1234, 1234, 1234]', () => { - var mask = new CreditCardMask() - var options = { - obfuscated: false - } - - var expected = '1234 1234 1234 1234' - var received = mask.getValue('1234123412341234', options) - - var expectedRawValue = ['1234', '1234', '1234', '1234'] - var receivedRawValue = mask.getRawValue(received, options) - - expect(received).toBe(expected) + var expectedRawValue = ['4263', '9826', '4026', '9299'] + var receivedRawValue = mask.getRawValue(received) expectedRawValue.forEach((val, index) => { expect(val).toBe(receivedRawValue[index]) }) }) -test('1234123412341234 obfuscated true results 1234 **** **** 1234 and raw value [1234, ****, ****, 1234]', () => { +test('correct raw value of obfuscated formatting', () => { var mask = new CreditCardMask() var options = { obfuscated: true } - var expected = '1234 **** **** 1234' - var received = mask.getValue('1234123412341234', options) + var received = mask.getValue(testCards.visa, options) - var expectedRawValue = ['1234', '****', '****', '1234'] + var expectedRawValue = ['4263', '****', '****', '9299'] var receivedRawValue = mask.getRawValue(received, options) - expect(received).toBe(expected) - expectedRawValue.forEach((val, index) => { expect(val).toBe(receivedRawValue[index]) }) }) -test('getMask returns 9999 9999 9999 9999', () => { +test('returns correct default regular mask', () => { var mask = new CreditCardMask() var expected = '9999 9999 9999 9999' var received = mask.getMask() @@ -81,26 +68,42 @@ test('getMask returns 9999 9999 9999 9999', () => { expect(received).toBe(expected) }) -test('getMask obfuscated returns 9999 **** **** 9999', () => { +test('returns correct default obfuscated mask', () => { var mask = new CreditCardMask() var expected = '9999 **** **** 9999' - var received = mask.getMask('', { obfuscated: true }) + var received = mask.getMask(null, { obfuscated: true }) + + expect(received).toBe(expected) +}) + +test('basic formatting of amex card', () => { + var mask = new CreditCardMask() + var expected = '3742 454554 00126' + var received = mask.getValue(testCards.amex) expect(received).toBe(expected) }) -test('get masked value with amex issuer must return 1234 123456 12345', () => { +test('obfuscated formatting of amex card', () => { var mask = new CreditCardMask() - var expected = '1234 123456 12345' - var received = mask.getValue('123412345612345', { issuer: 'amex' }) + var expected = '3742 ****** 00126' + var received = mask.getValue(testCards.amex, { obfuscated: true }) expect(received).toBe(expected) }) -test('getMask with diners issuer must return 1234 123456 1234', () => { +test('basic formatting of mastercard card', () => { var mask = new CreditCardMask() - var expected = '1234 123456 1234' - var received = mask.getValue('12341234561234', { issuer: 'diners' }) + var expected = '5425 2334 3010 9903' + var received = mask.getValue(testCards.mastercard) expect(received).toBe(expected) -}) \ No newline at end of file +}) + +test('basic formatting of maestro card', () => { + var mask = new CreditCardMask() + var expected = '6759 6498 2643 8453' + var received = mask.getValue(testCards.maestro) + + expect(received).toBe(expected) +}) diff --git a/dist/lib/masks/credit-card.mask.js b/dist/lib/masks/credit-card.mask.js index d38ca78d..575deb89 100644 --- a/dist/lib/masks/credit-card.mask.js +++ b/dist/lib/masks/credit-card.mask.js @@ -1 +1 @@ -Object.defineProperty(exports,"__esModule",{value:true});var _createClass=function(){function defineProperties(target,props){for(var i=0;i1&&arguments[1]!==undefined?arguments[1]:{};var type=this.getCardType(value);var length=Math.max.apply(Math,_toConsumableArray(type.lengths));var gaps=type.gaps.map(function(g,i){return g+i;});var firstGap=gaps[0];var lastGap=gaps[gaps.length-1];return Array.from(new Array(length+gaps.length)).map(function(_,i){if(gaps.includes(i))return' ';if(settings.obfuscated&&i>firstGap&&i null + '*': val => '*' } export default class CreditCardMask extends BaseMask { @@ -31,17 +14,16 @@ export default class CreditCardMask extends BaseMask { } getValue(value, settings) { - let selectedMask = this.getMask(value, settings) return CustomMask.shared.getValue(value, { - mask: selectedMask, + mask: this.getMask(value, settings), translation: MASK_TRANSLATION }) } - validate(value, settings) { + validate(value) { if (!!value) { - let selectedMask = this.getMask(value, settings) - return value.length === selectedMask.length + const type = this.getCardType(value) + return type.lengths.includes(value.length) } return true @@ -57,16 +39,21 @@ export default class CreditCardMask extends BaseMask { }) } - getMask(value, settings) { - let mergedSettings = super.mergeSettings(CREDIT_CARD_SETTINGS, settings) - const selectedMask = this._selectMask(mergedSettings.issuer, mergedSettings.obfuscated) - - return selectedMask + getMask(value, settings = {}) { + const type = this.getCardType(value) + const length = Math.max(...type.lengths) + const gaps = type.gaps.map((g, i) => g + i) + + const firstGap = gaps[0] + const lastGap = gaps[gaps.length - 1] + return Array.from(new Array(length + gaps.length)).map((_, i) => { + if (gaps.includes(i)) return ' ' + if (settings.obfuscated && i > firstGap && i < lastGap) return '*' + return 9 + }).join('') } - _selectMask(issuer, obfuscated) { - const maskType = obfuscated ? 'obfuscated' : 'regular' - - return CREDIT_CARD_MASKS[issuer][maskType] + getCardType(value) { + return cardTypes(value)[0] || defaultType } } diff --git a/package.json b/package.json index 1060d91f..ae6c2d02 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-masked-text", - "version": "1.12.3", + "version": "1.13.1", "description": "Text and TextInput with mask for React Native applications", "licenses": [ { @@ -36,21 +36,21 @@ }, "homepage": "https://github.com/benhurott/react-native-masked-text#readme", "dependencies": { - "moment": "2.19.3", + "credit-card-type": "^8.2.0", + "moment": "2.29.2", "tinymask": "^1.0.2" }, "devDependencies": { - "@types/react-native": "*", "@types/react": "*", + "@types/react-native": "*", "babel-cli": "^6.26.0", - "rimraf": "^2.6.2", - "react": "16.3.1", - "react-native": "0.55.4", "babel-jest": "23.4.2", "babel-preset-react-native": "4.0.0", "jest": "23.5.0", + "react": "16.3.1", + "react-native": "0.55.4", "react-test-renderer": "16.3.1", - "react-native-masked-text": "1.9.0" + "rimraf": "^2.6.2" }, "jest": { "preset": "react-native" diff --git a/yarn.lock b/yarn.lock index bb455c5e..b1d0fdc0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1998,6 +1998,11 @@ create-react-class@^15.6.3: loose-envify "^1.3.1" object-assign "^4.1.1" +credit-card-type@^8.2.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/credit-card-type/-/credit-card-type-8.2.0.tgz#507a43b257f0f3b8bd4d4b339a419741fc7e6236" + integrity sha512-+1kZKW717eDTbZ1/EjkEi4+UrD2SygU2Iujn/VlrMHXloGW/y5GqPlQ/KgT4gaoDmWyufBfm/CAzNkpeccfMtA== + cross-spawn@^5.0.1, cross-spawn@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" @@ -4298,10 +4303,10 @@ mkdirp@^0.5.0, mkdirp@^0.5.1: dependencies: minimist "0.0.8" -moment@2.19.3: - version "2.19.3" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.19.3.tgz#bdb99d270d6d7fda78cc0fbace855e27fe7da69f" - integrity sha1-vbmdJw1tf9p4zA+6zoVeJ/59pp8= +moment@2.29.2: + version "2.29.2" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.2.tgz#00910c60b20843bcba52d37d58c628b47b1f20e4" + integrity sha512-UgzG4rvxYpN15jgCmVJwac49h9ly9NurikMWGPdVxm8GZD6XjkKPxDTjQQ43gtGgnV3X0cAyWDdP2Wexoquifg== morgan@^1.9.0: version "1.9.1" @@ -5000,14 +5005,6 @@ react-is@^16.3.1, react-is@^16.8.1: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.6.tgz#5bbc1e2d29141c9fbdfed456343fe2bc430a6a16" integrity sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA== -react-native-masked-text@1.9.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/react-native-masked-text/-/react-native-masked-text-1.9.0.tgz#562be7aa544eebb42c9633134a918bc78eda33da" - integrity sha512-LEWxk1Uf4kFcTX2DtE5S8N1Hd6wg6IyHFQBYfhRnw/hLOTfJSXd69PsxlnjxECuS80rBCmFCcixdfC1vtbhmug== - dependencies: - moment "2.19.3" - tinymask "^1.0.2" - react-native@0.55.4: version "0.55.4" resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.55.4.tgz#eecffada3750a928e2ddd07cf11d857ae9751c30"