diff --git a/.gitignore b/.gitignore index f06884f..c2ca283 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ node_modules .coverage/ dist/ lib/ +coverage/ diff --git a/__tests__/RenderTests.js b/__tests__/RenderTests.js index a5e4c53..aa789be 100644 --- a/__tests__/RenderTests.js +++ b/__tests__/RenderTests.js @@ -1,5 +1,5 @@ 'use strict'; -import Form from '../src/Form'; +import {ValidatedInput,Form, Radio, RadioGroup} from '../src'; // Note: THere is an issue with react-bootstrap and mocking. For now the whole node_modules directory has been unmocked. describe('React bootstrap validation compilation test', () => { @@ -7,7 +7,7 @@ describe('React bootstrap validation compilation test', () => { var TestUtils = require('react-addons-test-utils'); beforeEach(function() { - + }); it('Renders Form component correctly.', () => { @@ -19,5 +19,40 @@ describe('React bootstrap validation compilation test', () => { // Do some work with the validation outcomes } } />); + }); + it('Renders ValidatedInput component correctly.', () => { + // Render into document + let validSubmit = function(event){}; + TestUtils.renderIntoDocument( +
+ + ); + }); + it('Renders RadioGroup component correctly.', () => { + // Render into document + let validSubmit = function(event){}; + TestUtils.renderIntoDocument( +
+ v === 'cola'} + errorHelp='Pepsi? Seriously?' + labelClassName='col-xs-2' + wrapperClassName='col-xs-10'> + + + +
); }); + }); diff --git a/__tests__/ValidatedInputTests.js b/__tests__/ValidatedInputTests.js new file mode 100644 index 0000000..8d6c96d --- /dev/null +++ b/__tests__/ValidatedInputTests.js @@ -0,0 +1,150 @@ +'use strict'; +import {ValidatedInput,Form} from '../src'; + +// Note: THere is an issue with react-bootstrap and mocking. For now the whole node_modules directory has been unmocked. +describe('React bootstrap ValidatedInput test', () => { + var React = require('react'); + var TestUtils = require('react-addons-test-utils'); + beforeEach(function() { + }); + it('Validates or conditons.', () => { + // Render into document + var submittedObject = null; + var validSubmit = function(event){ + submittedObject = event; + }; + + let item = TestUtils.renderIntoDocument( +
+ + ); + + let input = TestUtils.scryRenderedDOMComponentsWithClass(item, 'testInput')[1]; + input.value=''; + TestUtils.Simulate.change(input); + TestUtils.Simulate.submit(item.refs.form); + // test for error messages next to the item + expect(submittedObject.email).toBe(''); + + input.value='someone@test.com'; + TestUtils.Simulate.change(input); + TestUtils.Simulate.submit(item.refs.form); + // test for error messages next to the item + expect(submittedObject.email).toBe('someone@test.com'); + + }); + it('Validates an empty field.', () => { + // Render into document + var submittedObject = null; + var validSubmit = function(event){ + submittedObject = event; + }; + + let item = TestUtils.renderIntoDocument( +
+ + ); + + let input = TestUtils.scryRenderedDOMComponentsWithClass(item, 'testInput')[1]; + input.value='aaaa'; + TestUtils.Simulate.change(input); + TestUtils.Simulate.submit(item.refs.form); + // test for error messages next to the item + expect(submittedObject).toBe(null); + input.value=''; + TestUtils.Simulate.change(input); + TestUtils.Simulate.submit(item.refs.form); + // test for error messages next to the item + expect(submittedObject.email).toBe(''); + }); + + it('Validates a number.', () => { + // Render into document + var submittedObject = null; + var validSubmit = function(event){ + submittedObject = event; + }; + + let item = TestUtils.renderIntoDocument( +
+ + ); + + let input = TestUtils.scryRenderedDOMComponentsWithClass(item, 'testInput')[1]; + input.value='not a number'; + TestUtils.Simulate.change(input); + TestUtils.Simulate.submit(item.refs.form); + // test for error messages next to the item + expect(submittedObject).toBe(null); + + input.value='23'; + TestUtils.Simulate.change(input); + TestUtils.Simulate.submit(item.refs.form); + // test for error messages next to the item + expect(submittedObject.number).toBe('23'); + }); + + it('Validates an email.', () => { + // Render into document + var submittedObject = null; + var validSubmit = function(event){ + submittedObject = event; + }; + + let item = TestUtils.renderIntoDocument( +
+ + ); + + let input = TestUtils.scryRenderedDOMComponentsWithClass(item, 'testInput')[1]; + input.value='notavlidaemailaddress'; + TestUtils.Simulate.change(input); + TestUtils.Simulate.submit(item.refs.form); + // test for error messages next to the item + expect(submittedObject).toBe(null); + + input.value='test@nowhere.com'; + TestUtils.Simulate.change(input); + TestUtils.Simulate.submit(item.refs.form); + console.log(submittedObject); + expect(submittedObject.email).toBe('test@nowhere.com'); + }); +}); diff --git a/package.json b/package.json index e31f51d..c19654b 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ }, "jest": { "scriptPreprocessor": "node_modules/babel-jest", + "collectCoverage": true, "unmockedModulePathPatterns": [ "node_modules", "src" diff --git a/src/Form.js b/src/Form.js index d8b82dc..ad9875b 100644 --- a/src/Form.js +++ b/src/Form.js @@ -200,7 +200,7 @@ export default class Form extends InputContainer { if (typeof this.props.validateOne === 'function') { result = this.props.validateOne(iptName, value, context, result); - } + } // if result is !== true, it is considered an error // it can be either bool or string error if (result !== true) { @@ -248,7 +248,16 @@ export default class Form extends InputContainer { } _compileValidationRules(input, ruleProp) { - let rules = ruleProp.split(',').map(rule => { + let deliminator =','; + let andCondition =true; + // set the deliminator + if(ruleProp.indexOf('|')>0){ + + deliminator='|'; + andCondition=false; + } + // Split and groups + let rules = ruleProp.split(deliminator).map(rule => { let params = rule.split(':'); let name = params.shift(); let inverse = name[0] === '!'; @@ -257,14 +266,14 @@ export default class Form extends InputContainer { name = name.substr(1); } - return { name, inverse, params }; + return { name, inverse, params,andCondition:andCondition }; }); let validator = (input.props && input.props.type) === 'file' ? FileValidator : Validator; return val => { let result = true; - + let previousResult = true; rules.forEach(rule => { if (typeof validator[rule.name] !== 'function') { throw new Error('Invalid input validation rule "' + rule.name + '"'); @@ -275,6 +284,10 @@ export default class Form extends InputContainer { if (rule.inverse) { ruleResult = !ruleResult; } + if(!rule.andCondition){ + ruleResult = ruleResult || previousResult; + } + previousResult = ruleResult; if (result === true && ruleResult !== true) { result = getInputErrorMessage(input, rule.name) || diff --git a/src/Validator.js b/src/Validator.js index 0e267e9..be2969f 100644 --- a/src/Validator.js +++ b/src/Validator.js @@ -8,6 +8,7 @@ import validator from 'validator'; */ validator.extend('required', val => !validator.isNull(val)); +validator.extend('isEmpty', val => validator.isNull(val)); /** * Returns true if the value is boolean true *