@shaaditech/react-cc-validator
Version:
Credit/Debit card number validation library with input formatting
234 lines (177 loc) • 6.82 kB
JavaScript
import React from 'react';
import Enzyme, { mount } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import cardValidator from 'card-validator';
import { cardNumberCases, mountValidatorInput, CARD_IS_VALID, CARD_IS_INVALID } from './helpers';
import CardNumberValidator, { addCard, removeCard } from '../src/CardNumberValidator';
Enzyme.configure({ adapter: new Adapter() });
describe('<CardNumberValidator />', () => {
let node = null;
let inputNode = null;
afterEach(() => {
if (node) {
node.unmount();
}
});
it('should render the passed component', () => {
const InputComponent = jest.fn();
InputComponent.mockReturnValue(<div className="test-input" />);
node = mount(<CardNumberValidator>{InputComponent}</CardNumberValidator>);
expect(node.props().children).toBe(InputComponent);
expect(InputComponent).toHaveBeenCalled();
expect(node.find('.test-input').length).toBe(1);
});
it('should pass the correct props to the passed component in its initial state', () => {
const InputComponent = jest.fn();
InputComponent.mockReturnValue(<div />);
node = mount(<CardNumberValidator>{InputComponent}</CardNumberValidator>);
const propsPassed = InputComponent.mock.calls[0][0];
expect(propsPassed.isValid).toBe(false);
expect(propsPassed.cardType).toBe('');
expect(propsPassed.value).toBe('');
expect(propsPassed.onChange).toBeInstanceOf(Function);
expect(propsPassed.getInputProps().value).toBe(propsPassed.value);
expect(propsPassed.getInputProps().onChange).toBe(propsPassed.onChange);
});
describe('placeholder', () => {
beforeEach(() => {
node = mountValidatorInput();
inputNode = node.find('input');
});
it('should format the card number correctly', () => {
cardNumberCases.forEach(
({ cardNum, formattedCardNum }) => {
inputNode.instance().value = cardNum;
inputNode.simulate('change');
expect(node.find('.card-number').text()).toBe(formattedCardNum);
}
);
});
it('should validate the card number correctly', () => {
cardNumberCases.forEach(
({ cardNum, isValid }) => {
inputNode.instance().value = cardNum;
inputNode.simulate('change');
expect(node.find('.card-isvalid').text()).toBe(
isValid ? CARD_IS_VALID : CARD_IS_INVALID
);
}
);
});
it('should detect the correct card type', () => {
cardNumberCases.forEach(
({ cardNum, cardType }) => {
inputNode.instance().value = cardNum;
inputNode.simulate('change');
expect(node.find('.card-type').text()).toBe(cardType);
}
);
});
it('should handle non-digit cases', () => {
inputNode.instance().value = 'aksfhjsfhjsdf';
inputNode.simulate('change');
expect(node.find('.card-number').text()).toBe('');
expect(node.find('.card-type').text()).toBe('');
expect(node.find('.card-isvalid').text()).toBe(CARD_IS_INVALID);
inputNode.instance().value = ';jdjshnjs@$#%^%dg]\\]l;l;';
inputNode.simulate('change');
expect(node.find('.card-number').text()).toBe('');
expect(node.find('.card-type').text()).toBe('');
expect(node.find('.card-isvalid').text()).toBe(CARD_IS_INVALID);
});
it('should handle empty cases', () => {
inputNode.instance().value = '';
inputNode.simulate('change');
expect(node.find('.card-number').text()).toBe('');
expect(node.find('.card-type').text()).toBe('');
expect(node.find('.card-isvalid').text()).toBe(CARD_IS_INVALID);
inputNode.instance().value = null;
inputNode.simulate('change');
expect(node.find('.card-number').text()).toBe('');
expect(node.find('.card-type').text()).toBe('');
expect(node.find('.card-isvalid').text()).toBe(CARD_IS_INVALID);
});
});
describe('with validCardTypes prop passed', () => {
const validCardTypes = [
'master-card',
'visa',
];
const cardNumbers = {
withValidTypes: [
'4111111111111111',
'5414101008948858',
'5479585630696996',
],
withInvalidTypes: [
'6220420252000044153',
'3557994704466882',
'30569309025904',
'6759632829754159',
'6761932556762300',
],
invalid: [
'4122423423423',
'35424253234252352354',
'11111111111111111',
'4111111111111114',
],
};
beforeEach(() => {
node = mountValidatorInput({ validCardTypes });
inputNode = node.find('input');
});
it('should show valid card numbers with valid types as valid', () => {
cardNumbers.withValidTypes.forEach(cardNum => {
inputNode.instance().value = cardNum;
inputNode.simulate('change');
expect(node.find('.card-isvalid').text()).toBe(CARD_IS_VALID);
});
});
it('should show valid card numbers with types not from the validCardType array as invalid', () => {
cardNumbers.withInvalidTypes.forEach(cardNum => {
inputNode.instance().value = cardNum;
inputNode.simulate('change');
expect(node.find('.card-isvalid').text()).toBe(CARD_IS_INVALID);
});
});
it('should show invalid card numbers with types as invalid', () => {
cardNumbers.invalid.forEach(cardNum => {
inputNode.instance().value = cardNum;
inputNode.simulate('change');
expect(node.find('.card-isvalid').text()).toBe(CARD_IS_INVALID);
});
});
});
describe('with formatting disabled', () => {
beforeEach(() => {
node = mountValidatorInput({ format: false });
inputNode = node.find('input');
});
it('should not format the card number', () => {
cardNumberCases.forEach(
({ cardNum }) => {
inputNode.instance().value = cardNum;
inputNode.simulate('change');
expect(node.find('.card-number').text()).toBe(cardNum);
}
);
});
it('should handle display all characters as it is', () => {
inputNode.instance().value = 'aksfhjsfhjsdf';
inputNode.simulate('change');
expect(node.find('.card-number').text()).toBe('aksfhjsfhjsdf');
inputNode.instance().value = ';jdjshnjs@$#%^%dg]\\]l;l;';
inputNode.simulate('change');
expect(node.find('.card-number').text()).toBe(';jdjshnjs@$#%^%dg]\\]l;l;');
});
it('should handle empty cases', () => {
inputNode.instance().value = '';
inputNode.simulate('change');
expect(node.find('.card-number').text()).toBe('');
inputNode.instance().value = null;
inputNode.simulate('change');
expect(node.find('.card-number').text()).toBe('');
});
});
});