Refactored tests and made React 0.14 friendly
This commit is contained in:
commit
2846f0fadd
|
|
@ -1,3 +1,4 @@
|
|||
.DS_Store
|
||||
build
|
||||
node_modules
|
||||
lib
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
language: node_js
|
||||
node_js:
|
||||
- 'iojs'
|
||||
- '0.12'
|
||||
- '0.11'
|
||||
- '0.10'
|
||||
|
|
|
|||
67
API.md
67
API.md
|
|
@ -35,6 +35,8 @@
|
|||
- [isFormSubmitted()](#isformsubmitted)
|
||||
- [validate](#validate)
|
||||
- [formNoValidate](#formnovalidate)
|
||||
- [Formsy.HOC](#formsyhoc)
|
||||
- [Formsy.Decorator](#formsydecorator)
|
||||
- [Formsy.addValidationRule](#formsyaddvalidationrule)
|
||||
- [Validators](#validators)
|
||||
|
||||
|
|
@ -539,6 +541,41 @@ var MyInput = React.createClass({
|
|||
});
|
||||
```
|
||||
|
||||
### <a name="formsyhoc">Formsy.HOC</a>
|
||||
The same methods as the mixin are exposed to the HOC version of the element component, though through the `props`, not on the instance.
|
||||
```js
|
||||
import {HOC} from 'formsy-react';
|
||||
|
||||
class MyInput extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<input value={this.props.getValue()} onChange={(e) => this.props.setValue(e.target.value)}/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
export default HOC(MyInput);
|
||||
```
|
||||
|
||||
### <a name="formsydecorator">Formsy.Decorator</a>
|
||||
The same methods as the mixin are exposed to the decorator version of the element component, though through the `props`, not on the instance.
|
||||
```js
|
||||
import {Decorator as FormsyElement} from 'formsy-react';
|
||||
|
||||
@FormsyElement()
|
||||
class MyInput extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<input value={this.props.getValue()} onChange={(e) => this.props.setValue(e.target.value)}/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
export default MyInput
|
||||
```
|
||||
|
||||
### <a name="formsyaddvalidationrule">Formsy.addValidationRule(name, ruleFunc)</a>
|
||||
An example:
|
||||
```javascript
|
||||
|
|
@ -622,18 +659,36 @@ Returns true if the value is the boolean true
|
|||
```
|
||||
Returns true if the value is the boolean false
|
||||
|
||||
**isNumeric**
|
||||
```html
|
||||
<MyInputComponent name="foo" validations="isNumeric"/>
|
||||
```
|
||||
Returns true if string only contains numbers
|
||||
|
||||
**isAlpha**
|
||||
```html
|
||||
<MyInputComponent name="foo" validations="isAlpha"/>
|
||||
```
|
||||
Returns true if string is only letters
|
||||
|
||||
**isNumeric**
|
||||
```html
|
||||
<MyInputComponent name="foo" validations="isNumeric"/>
|
||||
```
|
||||
Returns true if string only contains numbers. Examples: 42; -3.14
|
||||
|
||||
**isAlphanumeric**
|
||||
```html
|
||||
<MyInputComponent name="foo" validations="isAlphanumeric"/>
|
||||
```
|
||||
Returns true if string only contains letters or numbers
|
||||
|
||||
**isInt**
|
||||
```html
|
||||
<MyInputComponent name="foo" validations="isInt"/>
|
||||
```
|
||||
Returns true if string represents integer value. Examples: 42; -12; 0
|
||||
|
||||
**isFloat**
|
||||
```html
|
||||
<MyInputComponent name="foo" validations="isFloat"/>
|
||||
```
|
||||
Returns true if string represents float value. Examples: 42; -3.14; 1e3
|
||||
|
||||
**isWords**
|
||||
```html
|
||||
<MyInputComponent name="foo" validations="isWords"/>
|
||||
|
|
|
|||
|
|
@ -23,10 +23,13 @@ The main concept is that forms, inputs and validation is done very differently a
|
|||
|
||||
3. Use handlers for different states of your form. Ex. "onSubmit", "onError", "onValid" etc.
|
||||
|
||||
4. Server validation errors automatically binds to the correct form input component
|
||||
4. Pass external errors to the form to invalidate elements
|
||||
|
||||
5. You can dynamically add form elements to your form and they will register/unregister to the form
|
||||
|
||||
## Default elements
|
||||
You can look at examples in this repo or use the [formsy-react-components](https://github.com/twisty/formsy-react-components) project to use bootstrap with formsy-react.
|
||||
|
||||
## Install
|
||||
|
||||
1. Download from this REPO and use globally (Formsy) or with requirejs
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "formsy-react",
|
||||
"version": "0.14.1",
|
||||
"version": "0.16.0",
|
||||
"description": "A form input builder and validator for React JS",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
|
|
|||
|
|
@ -1,37 +1,55 @@
|
|||
var React = require('react');
|
||||
var ReactDOM = require('react-dom');
|
||||
var Formsy = require('./../src/main.js');
|
||||
|
||||
var Input = React.createClass({
|
||||
|
||||
mixins: [Formsy.Mixin],
|
||||
|
||||
onChange: function (event) {
|
||||
this.props.setValue(event.currentTarget.value);
|
||||
},
|
||||
render: function () {
|
||||
return (
|
||||
<div>
|
||||
{this.showError()}
|
||||
{this.getErrorMessage()}
|
||||
<input disabled={this.isFormDisabled()} />
|
||||
{this.props.showRequired() ? 'required' : ''}
|
||||
<input disabled={this.props.isFormDisabled()} value={this.props.getValue()} onChange={this.onChange}/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var FormApp = React.createClass({
|
||||
componentDidMount: function () {
|
||||
this.refs.form.updateInputsWithError({
|
||||
'foo.bar': 'hmmm'
|
||||
Input = Formsy.HOC(Input);
|
||||
|
||||
var SomeComp = React.createClass({
|
||||
getInitialState: function () {
|
||||
return {
|
||||
isRequired: false
|
||||
};
|
||||
},
|
||||
toggleRequired: function () {
|
||||
this.setState({
|
||||
isRequired: !this.state.isRequired
|
||||
});
|
||||
},
|
||||
render: function () {
|
||||
return (
|
||||
<div>
|
||||
<Input name="foo[0]" value={''} validations="isEmail" validationError="No email" required={this.state.isRequired}/>
|
||||
<button onClick={this.toggleRequired}>Test</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
});
|
||||
|
||||
var FormApp = React.createClass({
|
||||
onSubmit: function (model) {
|
||||
console.log('model', model);
|
||||
},
|
||||
render: function () {
|
||||
return (
|
||||
<Formsy.Form ref="form" onInvalid={this.onInvalid}>
|
||||
<Input name="foo.bar" />
|
||||
<Formsy.Form ref="form" onSubmit={this.onSubmit}>
|
||||
<SomeComp/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
React.render(<FormApp />, document.getElementById('app'));
|
||||
ReactDOM.render(<FormApp />, document.getElementById('app'));
|
||||
|
|
|
|||
|
|
@ -30,3 +30,7 @@ If it is not helped try update your node.js and npm.
|
|||
2. [**Custom Validation**](custom-validation)
|
||||
|
||||
One field with added validation rule (`Formsy.addValidationRule`) and one field with dynamically added validation and error messages.
|
||||
|
||||
3. [**Reset Values**](reset-values)
|
||||
|
||||
Reset text input, checkbox and select to their pristine values.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,43 @@
|
|||
import React from 'react';
|
||||
import Formsy from 'formsy-react';
|
||||
|
||||
const MyInput = React.createClass({
|
||||
|
||||
// Add the Formsy Mixin
|
||||
mixins: [Formsy.Mixin],
|
||||
|
||||
// setValue() will set the value of the component, which in
|
||||
// turn will validate it and the rest of the form
|
||||
changeValue(event) {
|
||||
this.setValue(event.currentTarget[this.props.type === 'checkbox' ? 'checked' : 'value']);
|
||||
},
|
||||
render() {
|
||||
|
||||
// Set a specific className based on the validation
|
||||
// state of this component. showRequired() is true
|
||||
// when the value is empty and the required prop is
|
||||
// passed to the input. showError() is true when the
|
||||
// value typed is invalid
|
||||
const className = this.props.className + ' ' + (this.showRequired() ? 'required' : this.showError() ? 'error' : null);
|
||||
|
||||
// An error message is returned ONLY if the component is invalid
|
||||
// or the server has returned an error message
|
||||
const errorMessage = this.getErrorMessage();
|
||||
|
||||
return (
|
||||
<div className='form-group'>
|
||||
<label htmlFor={this.props.name}>{this.props.title}</label>
|
||||
<input
|
||||
type={this.props.type || 'text'}
|
||||
name={this.props.name}
|
||||
onChange={this.changeValue}
|
||||
value={this.getValue()}
|
||||
checked={this.props.type === 'checkbox' && this.getValue() ? 'checked' : null}
|
||||
/>
|
||||
<span className='validation-error'>{errorMessage}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default MyInput;
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
import React from 'react';
|
||||
import Formsy from 'formsy-react';
|
||||
|
||||
const MySelect = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
|
||||
changeValue(event) {
|
||||
this.setValue(event.currentTarget.value);
|
||||
},
|
||||
|
||||
render() {
|
||||
const className = this.props.className + ' ' + (this.showRequired() ? 'required' : this.showError() ? 'error' : null);
|
||||
const errorMessage = this.getErrorMessage();
|
||||
|
||||
const options = this.props.options.map((option, i) => (
|
||||
<option key={option.title+option.value} value={option.value}>
|
||||
{option.title}
|
||||
</option>
|
||||
));
|
||||
|
||||
return (
|
||||
<div className='form-group'>
|
||||
<label htmlFor={this.props.name}>{this.props.title}</label>
|
||||
<select name={this.props.name} onChange={this.changeValue} value={this.getValue()}>
|
||||
{options}
|
||||
</select>
|
||||
<span className='validation-error'>{errorMessage}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
export default MySelect;
|
||||
|
|
@ -1,9 +1,12 @@
|
|||
var React = require('react');
|
||||
var Formsy = require('formsy-react');
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import Formsy from 'formsy-react';
|
||||
|
||||
var currentYear = new Date().getFullYear();
|
||||
import MyInput from './../components/Input';
|
||||
|
||||
var validators = {
|
||||
const currentYear = new Date().getFullYear();
|
||||
|
||||
const validators = {
|
||||
time: {
|
||||
regexp: /^(([0-1]?[0-9])|([2][0-3])):([0-5]?[0-9])(:([0-5]?[0-9]))?$/,
|
||||
message: 'Not valid time'
|
||||
|
|
@ -18,79 +21,56 @@ var validators = {
|
|||
}
|
||||
};
|
||||
|
||||
Formsy.addValidationRule('isYearOfBirth', function (values, value) {
|
||||
Formsy.addValidationRule('isYearOfBirth', (values, value) => {
|
||||
value = parseInt(value);
|
||||
if (typeof value !== 'number' || value !== value) {
|
||||
if (typeof value !== 'number') {
|
||||
return false;
|
||||
}
|
||||
return value < currentYear && value > currentYear - 130;
|
||||
});
|
||||
|
||||
var App = React.createClass({
|
||||
submit: function (data) {
|
||||
const App = React.createClass({
|
||||
submit(data) {
|
||||
alert(JSON.stringify(data, null, 4));
|
||||
},
|
||||
render: function () {
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form onSubmit={this.submit} className="custom-validation">
|
||||
<MyOwnInput name="year" title="Year of Birth" type="number" validations="isYearOfBirth" validationError="Please type your year of birth" />
|
||||
<DynamicInput name="dynamic" title="..." type="text" />
|
||||
<MyInput name="year" title="Year of Birth" type="number" validations="isYearOfBirth" validationError="Please type your year of birth" />
|
||||
<DynamicInput name="dynamic" title="..." />
|
||||
<button type="submit">Submit</button>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var MyOwnInput = React.createClass({
|
||||
const DynamicInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
changeValue: function (event) {
|
||||
getInitialState() {
|
||||
return { validationType: 'time' };
|
||||
},
|
||||
changeValue(event) {
|
||||
this.setValue(event.currentTarget.value);
|
||||
},
|
||||
render: function () {
|
||||
var className = this.props.className + ' ' + (this.showError() ? 'error' : null);
|
||||
var errorMessage = this.getErrorMessage();
|
||||
|
||||
return (
|
||||
<div className='form-group'>
|
||||
<label htmlFor={this.props.name}>{this.props.title}</label>
|
||||
<input type={this.props.type || 'text'} name={this.props.name} onChange={this.changeValue} value={this.getValue()}/>
|
||||
<span className='validation-error'>{errorMessage}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var DynamicInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
getInitialState: function() {
|
||||
return {
|
||||
validationType: 'time'
|
||||
};
|
||||
},
|
||||
changeValue: function (event) {
|
||||
this.setValue(event.currentTarget.value);
|
||||
},
|
||||
changeValidation: function(validationType) {
|
||||
this.setState({
|
||||
validationType: validationType
|
||||
});
|
||||
changeValidation(validationType) {
|
||||
this.setState({ validationType: validationType });
|
||||
this.setValue(this.getValue());
|
||||
},
|
||||
validate: function () {
|
||||
var value = this.getValue();
|
||||
return value === '' ? true : validators[this.state.validationType].regexp.test(value);
|
||||
validate() {
|
||||
const value = this.getValue();
|
||||
return value !== '' ? validators[this.state.validationType].regexp.test(value) : true;
|
||||
},
|
||||
getCustomErrorMessage: function() {
|
||||
getCustomErrorMessage() {
|
||||
return this.showError() ? validators[this.state.validationType].message : '';
|
||||
},
|
||||
render: function () {
|
||||
var className = this.props.className + ' ' + (this.showError() ? 'error' : null);
|
||||
var errorMessage = this.getCustomErrorMessage();
|
||||
render() {
|
||||
const className = this.props.className + ' ' + (this.showError() ? 'error' : null);
|
||||
const errorMessage = this.getCustomErrorMessage();
|
||||
|
||||
return (
|
||||
<div className='form-group'>
|
||||
<label htmlFor={this.props.name}>{this.props.title}</label>
|
||||
<input type={this.props.type || 'text'} name={this.props.name} onChange={this.changeValue} value={this.getValue()}/>
|
||||
<input type='text' name={this.props.name} onChange={this.changeValue} value={this.getValue()}/>
|
||||
<span className='validation-error'>{errorMessage}</span>
|
||||
<Validations validationType={this.state.validationType} changeValidation={this.changeValidation}/>
|
||||
</div>
|
||||
|
|
@ -98,26 +78,27 @@ var DynamicInput = React.createClass({
|
|||
}
|
||||
});
|
||||
|
||||
var Validations = React.createClass({
|
||||
changeValidation: function(e) {
|
||||
const Validations = React.createClass({
|
||||
changeValidation(e) {
|
||||
this.props.changeValidation(e.target.value);
|
||||
},
|
||||
render: function() {
|
||||
render() {
|
||||
const { validationType } = this.props;
|
||||
return (
|
||||
<fieldset onChange={this.changeValidation}>
|
||||
<legend>Validation Type</legend>
|
||||
<div>
|
||||
<input name='validationType' type='radio' value='time' checked={this.props.validationType === 'time'}/>Time
|
||||
<input name='validationType' type='radio' value='time' defaultChecked={validationType === 'time'}/>Time
|
||||
</div>
|
||||
<div>
|
||||
<input name='validationType' type='radio' value='decimal' checked={this.props.validationType === 'decimal'}/>Decimal
|
||||
<input name='validationType' type='radio' value='decimal' defaultChecked={validationType === 'decimal'}/>Decimal
|
||||
</div>
|
||||
<div>
|
||||
<input name='validationType' type='radio' value='binary' checked={this.props.validationType === 'binary'}/>Binary
|
||||
<input name='validationType' type='radio' value='binary' defaultChecked={validationType === 'binary'}/>Binary
|
||||
</div>
|
||||
</fieldset>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
React.render(<App/>, document.getElementById('example'));
|
||||
ReactDOM.render(<App/>, document.getElementById('example'));
|
||||
|
|
|
|||
|
|
@ -38,7 +38,8 @@ form {
|
|||
.form-group input[type='text'],
|
||||
.form-group input[type='email'],
|
||||
.form-group input[type='number'],
|
||||
.form-group input[type='password'] {
|
||||
.form-group input[type='password'],
|
||||
.form-group select {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 34px;
|
||||
|
|
@ -63,3 +64,10 @@ button {
|
|||
padding: 10px 15px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.buttons button {
|
||||
margin-left: 10px;
|
||||
}
|
||||
.buttons button:first-child {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
<ul>
|
||||
<li><a href="login/index.html">Login Page</a></li>
|
||||
<li><a href="custom-validation/index.html">Custom Validation</a></li>
|
||||
<li><a href="reset-values/index.html">Reset Values</a></li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,65 +1,31 @@
|
|||
var React = require('react');
|
||||
var Formsy = require('formsy-react');
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { Form } from 'formsy-react';
|
||||
|
||||
var App = React.createClass({
|
||||
getInitialState: function() {
|
||||
import MyInput from './../components/Input';
|
||||
|
||||
const App = React.createClass({
|
||||
getInitialState() {
|
||||
return { canSubmit: false };
|
||||
},
|
||||
submit: function (data) {
|
||||
submit(data) {
|
||||
alert(JSON.stringify(data, null, 4));
|
||||
},
|
||||
enableButton: function () {
|
||||
this.setState({
|
||||
canSubmit: true
|
||||
});
|
||||
enableButton() {
|
||||
this.setState({ canSubmit: true });
|
||||
},
|
||||
disableButton: function () {
|
||||
this.setState({
|
||||
canSubmit: false
|
||||
});
|
||||
disableButton() {
|
||||
this.setState({ canSubmit: false });
|
||||
},
|
||||
render: function () {
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form onSubmit={this.submit} onValid={this.enableButton} onInvalid={this.disableButton} className="login">
|
||||
<MyOwnInput name="email" title="Email" validations="isEmail" validationError="This is not a valid email" required />
|
||||
<MyOwnInput name="password" title="Password" type="password" required />
|
||||
<Form onSubmit={this.submit} onValid={this.enableButton} onInvalid={this.disableButton} className="login">
|
||||
<MyInput name="email" title="Email" validations="isEmail" validationError="This is not a valid email" required />
|
||||
<MyInput name="password" title="Password" type="password" required />
|
||||
<button type="submit" disabled={!this.state.canSubmit}>Submit</button>
|
||||
</Formsy.Form>
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var MyOwnInput = React.createClass({
|
||||
|
||||
// Add the Formsy Mixin
|
||||
mixins: [Formsy.Mixin],
|
||||
|
||||
// setValue() will set the value of the component, which in
|
||||
// turn will validate it and the rest of the form
|
||||
changeValue: function (event) {
|
||||
this.setValue(event.currentTarget.value);
|
||||
},
|
||||
render: function () {
|
||||
|
||||
// Set a specific className based on the validation
|
||||
// state of this component. showRequired() is true
|
||||
// when the value is empty and the required prop is
|
||||
// passed to the input. showError() is true when the
|
||||
// value typed is invalid
|
||||
var className = this.props.className + ' ' + (this.showRequired() ? 'required' : this.showError() ? 'error' : null);
|
||||
|
||||
// An error message is returned ONLY if the component is invalid
|
||||
// or the server has returned an error message
|
||||
var errorMessage = this.getErrorMessage();
|
||||
|
||||
return (
|
||||
<div className='form-group'>
|
||||
<label htmlFor={this.props.name}>{this.props.title}</label>
|
||||
<input type={this.props.type || 'text'} name={this.props.name} onChange={this.changeValue} value={this.getValue()}/>
|
||||
<span className='validation-error'>{errorMessage}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
React.render(<App/>, document.getElementById('example'));
|
||||
ReactDOM.render(<App/>, document.getElementById('example'));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
.form {
|
||||
width: 400px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { Form } from 'formsy-react';
|
||||
|
||||
import MyInput from './../components/Input';
|
||||
import MySelect from './../components/Select';
|
||||
|
||||
const user = {
|
||||
name: 'Sam',
|
||||
free: true,
|
||||
hair: 'brown'
|
||||
};
|
||||
|
||||
const App = React.createClass({
|
||||
submit(data) {
|
||||
alert(JSON.stringify(data, null, 4));
|
||||
},
|
||||
resetForm() {
|
||||
this.refs.form.reset();
|
||||
},
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form ref="form" onSubmit={this.submit} className="form">
|
||||
<MyInput name="name" title="Name" value={user.name} />
|
||||
<MyInput name="free" title="Free to hire" type="checkbox" value={user.free} />
|
||||
<MySelect name="hair" title="Hair" value={user.hair}
|
||||
options={[
|
||||
{ value: "black", title: "Black" },
|
||||
{ value: "brown", title: "Brown" },
|
||||
{ value: "blonde", title: "Blonde" },
|
||||
{ value: "red", title: "Red" }
|
||||
]}
|
||||
/>
|
||||
|
||||
<div className="buttons">
|
||||
<button type="reset" onClick={this.resetForm}>Reset</button>
|
||||
<button type="submit">Submit</button>
|
||||
</div>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
ReactDOM.render(<App/>, document.getElementById('example'));
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Reset Values</title>
|
||||
<link href="../global.css" rel="stylesheet"/>
|
||||
<link href="app.css" rel="stylesheet"/>
|
||||
</head>
|
||||
<body>
|
||||
<h1 class="breadcrumbs"><a href="../index.html">Formsy React Examples</a> / Reset Values</h1>
|
||||
<div id="example"/>
|
||||
<script src="/__build__/shared.js"></script>
|
||||
<script src="/__build__/reset-values.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -11,7 +11,7 @@ module.exports = {
|
|||
devtool: 'inline-source-map',
|
||||
|
||||
entry: fs.readdirSync(__dirname).reduce(function (entries, dir) {
|
||||
var isDraft = dir.charAt(0) === '_';
|
||||
var isDraft = dir.charAt(0) === '_' || dir.indexOf('components') >= 0;
|
||||
|
||||
if (!isDraft && isDirectory(path.join(__dirname, dir))) {
|
||||
entries[dir] = path.join(__dirname, dir, 'app.js');
|
||||
|
|
|
|||
22
package.json
22
package.json
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "formsy-react",
|
||||
"version": "0.14.1",
|
||||
"version": "0.16.0",
|
||||
"description": "A form input builder and validator for React JS",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
|
@ -15,8 +15,9 @@
|
|||
"scripts": {
|
||||
"start": "webpack-dev-server --content-base build",
|
||||
"deploy": "NODE_ENV=production webpack -p --config webpack.production.config.js",
|
||||
"test": "node testrunner",
|
||||
"examples": "webpack-dev-server --config examples/webpack.config.js --content-base examples"
|
||||
"test": "babel-node testrunner",
|
||||
"examples": "webpack-dev-server --config examples/webpack.config.js --content-base examples",
|
||||
"prepublish": "babel ./src/ -d ./lib/"
|
||||
},
|
||||
"author": "Christian Alfoni",
|
||||
"license": "MIT",
|
||||
|
|
@ -27,17 +28,24 @@
|
|||
"validation",
|
||||
"react-component"
|
||||
],
|
||||
"dependencies": {
|
||||
"form-data-to-object": "^0.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel": "^5.6.4",
|
||||
"babel-core": "^5.1.11",
|
||||
"babel-loader": "^5.0.0",
|
||||
"jasmine-node": "^1.14.5",
|
||||
"jsdom": "^3.1.2",
|
||||
"react": "^0.13.1",
|
||||
"jsdom": "^6.5.1",
|
||||
"lolex": "^1.3.2",
|
||||
"nodeunit": "^0.9.1",
|
||||
"react": "^0.14.0-rc1",
|
||||
"react-addons-test-utils": "^0.14.0-rc1",
|
||||
"react-dom": "^0.14.0-rc1",
|
||||
"sinon": "^1.17.1",
|
||||
"webpack": "^1.7.3",
|
||||
"webpack-dev-server": "^1.7.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "0.13.x"
|
||||
"react": "^0.14.0-rc1"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -1,593 +0,0 @@
|
|||
var React = require('react/addons');
|
||||
var TestUtils = React.addons.TestUtils;
|
||||
var Formsy = require('./../src/main.js');
|
||||
|
||||
describe('Element', function() {
|
||||
|
||||
it('should return passed and setValue() value when using getValue()', function () {
|
||||
|
||||
var TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
updateValue: function (event) {
|
||||
this.setValue(event.target.value);
|
||||
},
|
||||
render: function () {
|
||||
return <input value={this.getValue()} onChange={this.updateValue}/>
|
||||
}
|
||||
});
|
||||
var form = TestUtils.renderIntoDocument(
|
||||
<Formsy.Form>
|
||||
<TestInput name="foo" value="foo"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
|
||||
var input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||
expect(input.getDOMNode().value).toBe('foo');
|
||||
TestUtils.Simulate.change(input, {target: {value: 'foobar'}});
|
||||
expect(input.getDOMNode().value).toBe('foobar');
|
||||
|
||||
});
|
||||
|
||||
it('should set back to pristine value when running reset', function () {
|
||||
|
||||
var reset = null;
|
||||
var TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
componentDidMount: function () {
|
||||
reset = this.resetValue;
|
||||
},
|
||||
updateValue: function (event) {
|
||||
this.setValue(event.target.value);
|
||||
},
|
||||
render: function () {
|
||||
return <input value={this.getValue()} onChange={this.updateValue}/>
|
||||
}
|
||||
});
|
||||
var form = TestUtils.renderIntoDocument(
|
||||
<Formsy.Form>
|
||||
<TestInput name="foo" value="foo"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
|
||||
var input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||
TestUtils.Simulate.change(input, {target: {value: 'foobar'}});
|
||||
reset();
|
||||
expect(input.getDOMNode().value).toBe('foo');
|
||||
|
||||
});
|
||||
|
||||
it('should return error message passed when calling getErrorMessage()', function () {
|
||||
|
||||
var getErrorMessage = null;
|
||||
var TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
componentDidMount: function () {
|
||||
getErrorMessage = this.getErrorMessage;
|
||||
},
|
||||
updateValue: function (event) {
|
||||
this.setValue(event.target.value);
|
||||
},
|
||||
render: function () {
|
||||
return <input value={this.getValue()} onChange={this.updateValue}/>
|
||||
}
|
||||
});
|
||||
var form = TestUtils.renderIntoDocument(
|
||||
<Formsy.Form>
|
||||
<TestInput name="foo" value="foo" validations="isEmail" validationError="Has to be email"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
|
||||
expect(getErrorMessage()).toBe('Has to be email');
|
||||
|
||||
});
|
||||
|
||||
it('should return true or false when calling isValid() depending on valid state', function () {
|
||||
|
||||
var isValid = null;
|
||||
var TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
componentDidMount: function () {
|
||||
isValid = this.isValid;
|
||||
},
|
||||
updateValue: function (event) {
|
||||
this.setValue(event.target.value);
|
||||
},
|
||||
render: function () {
|
||||
return <input value={this.getValue()} onChange={this.updateValue}/>
|
||||
}
|
||||
});
|
||||
var form = TestUtils.renderIntoDocument(
|
||||
<Formsy.Form url="/users">
|
||||
<TestInput name="foo" value="foo" validations="isEmail"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
|
||||
expect(isValid()).toBe(false);
|
||||
var input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||
TestUtils.Simulate.change(input, {target: {value: 'foo@foo.com'}});
|
||||
expect(isValid()).toBe(true);
|
||||
|
||||
});
|
||||
|
||||
it('should return true or false when calling isRequired() depending on passed required attribute', function () {
|
||||
|
||||
var isRequireds = [];
|
||||
var TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
componentDidMount: function () {
|
||||
isRequireds.push(this.isRequired);
|
||||
},
|
||||
updateValue: function (event) {
|
||||
this.setValue(event.target.value);
|
||||
},
|
||||
render: function () {
|
||||
return <input value={this.getValue()} onChange={this.updateValue}/>
|
||||
}
|
||||
});
|
||||
var form = TestUtils.renderIntoDocument(
|
||||
<Formsy.Form url="/users">
|
||||
<TestInput name="foo" value=""/>
|
||||
<TestInput name="foo" value="" required/>
|
||||
<TestInput name="foo" value="foo" required="isLength:3"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
|
||||
expect(isRequireds[0]()).toBe(false);
|
||||
expect(isRequireds[1]()).toBe(true);
|
||||
expect(isRequireds[2]()).toBe(true);
|
||||
|
||||
});
|
||||
|
||||
it('should return true or false when calling showRequired() depending on input being empty and required is passed, or not', function () {
|
||||
|
||||
var showRequireds = [];
|
||||
var TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
componentDidMount: function () {
|
||||
showRequireds.push(this.showRequired);
|
||||
},
|
||||
updateValue: function (event) {
|
||||
this.setValue(event.target.value);
|
||||
},
|
||||
render: function () {
|
||||
return <input value={this.getValue()} onChange={this.updateValue}/>
|
||||
}
|
||||
});
|
||||
var form = TestUtils.renderIntoDocument(
|
||||
<Formsy.Form url="/users">
|
||||
<TestInput name="A" value="foo"/>
|
||||
<TestInput name="B" value="" required/>
|
||||
<TestInput name="C" value=""/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
|
||||
expect(showRequireds[0]()).toBe(false);
|
||||
expect(showRequireds[1]()).toBe(true);
|
||||
expect(showRequireds[2]()).toBe(false);
|
||||
|
||||
});
|
||||
|
||||
it('should return true or false when calling isPristine() depending on input has been "touched" or not', function () {
|
||||
|
||||
var isPristine = null;
|
||||
var TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
componentDidMount: function () {
|
||||
isPristine = this.isPristine;
|
||||
},
|
||||
updateValue: function (event) {
|
||||
this.setValue(event.target.value);
|
||||
},
|
||||
render: function () {
|
||||
return <input value={this.getValue()} onChange={this.updateValue}/>
|
||||
}
|
||||
});
|
||||
var form = TestUtils.renderIntoDocument(
|
||||
<Formsy.Form url="/users">
|
||||
<TestInput name="A" value="foo"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
|
||||
expect(isPristine()).toBe(true);
|
||||
var input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||
TestUtils.Simulate.change(input, {target: {value: 'foo'}});
|
||||
expect(isPristine()).toBe(false);
|
||||
|
||||
});
|
||||
|
||||
it('should allow an undefined value to be updated to a value', function (done) {
|
||||
var TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
changeValue: function (event) {
|
||||
this.setValue(event.target.value);
|
||||
},
|
||||
render: function () {
|
||||
return <input value={this.getValue()} onChange={this.changeValue}/>
|
||||
}
|
||||
});
|
||||
var TestForm = React.createClass({
|
||||
getInitialState: function () {
|
||||
return {value: undefined};
|
||||
},
|
||||
changeValue: function () {
|
||||
this.setState({
|
||||
value: 'foo'
|
||||
});
|
||||
},
|
||||
render: function () {
|
||||
return (
|
||||
<Formsy.Form url="/users">
|
||||
<TestInput name="A" value={this.state.value}/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
var form = TestUtils.renderIntoDocument(
|
||||
<TestForm/>
|
||||
);
|
||||
|
||||
form.changeValue();
|
||||
var input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||
setTimeout(function () {
|
||||
expect(input.getDOMNode().value).toBe('foo');
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
it('should be able to test a values validity', function () {
|
||||
|
||||
var isInvalid = false;
|
||||
var TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
render: function () {
|
||||
return <input/>
|
||||
}
|
||||
});
|
||||
var TestForm = React.createClass({
|
||||
render: function () {
|
||||
return (
|
||||
<Formsy.Form>
|
||||
<TestInput name="A" validations="isEmail"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
var form = TestUtils.renderIntoDocument(
|
||||
<TestForm/>
|
||||
);
|
||||
|
||||
var input = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
expect(input.isValidValue('foo@bar.com')).toBe(true);
|
||||
expect(input.isValidValue('foo@bar')).toBe(false);
|
||||
|
||||
});
|
||||
|
||||
it('should be able to use an object as validations property', function () {
|
||||
|
||||
var TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
render: function () {
|
||||
return <input/>
|
||||
}
|
||||
});
|
||||
var TestForm = React.createClass({
|
||||
render: function () {
|
||||
return (
|
||||
<Formsy.Form>
|
||||
<TestInput name="A" validations={{
|
||||
isEmail: true
|
||||
}}/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
var form = TestUtils.renderIntoDocument(
|
||||
<TestForm/>
|
||||
);
|
||||
|
||||
var input = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
expect(input.isValidValue('foo@bar.com')).toBe(true);
|
||||
expect(input.isValidValue('foo@bar')).toBe(false);
|
||||
});
|
||||
|
||||
it('should be able to pass complex values to a validation rule', function () {
|
||||
|
||||
var TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
changeValue: function (event) {
|
||||
this.setValue(event.target.value);
|
||||
},
|
||||
render: function () {
|
||||
return <input value={this.getValue()} onChange={this.changeValue}/>
|
||||
}
|
||||
});
|
||||
var TestForm = React.createClass({
|
||||
render: function () {
|
||||
return (
|
||||
<Formsy.Form>
|
||||
<TestInput name="A" validations={{
|
||||
matchRegexp: /foo/
|
||||
}} value="foo"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
var form = TestUtils.renderIntoDocument(
|
||||
<TestForm/>
|
||||
);
|
||||
|
||||
var inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
expect(inputComponent.isValid()).toBe(true);
|
||||
var input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||
TestUtils.Simulate.change(input, {target: {value: 'bar'}});
|
||||
expect(inputComponent.isValid()).toBe(false);
|
||||
});
|
||||
|
||||
it('should be able to run a function to validate', function () {
|
||||
|
||||
var TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
changeValue: function (event) {
|
||||
this.setValue(event.target.value);
|
||||
},
|
||||
render: function () {
|
||||
return <input value={this.getValue()} onChange={this.changeValue}/>
|
||||
}
|
||||
});
|
||||
var TestForm = React.createClass({
|
||||
customValidationA: function (values, value) {
|
||||
return value === 'foo';
|
||||
},
|
||||
customValidationB: function (values, value) {
|
||||
return value === 'foo' && values.A === 'foo';
|
||||
},
|
||||
render: function () {
|
||||
return (
|
||||
<Formsy.Form>
|
||||
<TestInput name="A" validations={{
|
||||
custom: this.customValidationA
|
||||
}} value="foo"/>
|
||||
<TestInput name="B" validations={{
|
||||
custom: this.customValidationB
|
||||
}} value="foo"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
var form = TestUtils.renderIntoDocument(
|
||||
<TestForm/>
|
||||
);
|
||||
|
||||
var inputComponent = TestUtils.scryRenderedComponentsWithType(form, TestInput);
|
||||
expect(inputComponent[0].isValid()).toBe(true);
|
||||
expect(inputComponent[1].isValid()).toBe(true);
|
||||
var input = TestUtils.scryRenderedDOMComponentsWithTag(form, 'INPUT');
|
||||
TestUtils.Simulate.change(input[0], {target: {value: 'bar'}});
|
||||
expect(inputComponent[0].isValid()).toBe(false);
|
||||
expect(inputComponent[1].isValid()).toBe(false);
|
||||
});
|
||||
|
||||
it('should override all error messages with error messages passed by form', function () {
|
||||
var TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
render: function () {
|
||||
return <input/>
|
||||
}
|
||||
});
|
||||
var TestForm = React.createClass({
|
||||
render: function () {
|
||||
return (
|
||||
<Formsy.Form validationErrors={{A: 'bar'}}>
|
||||
<TestInput name="A" validations={{
|
||||
isEmail: true
|
||||
}} validationError="bar2" validationErrors={{isEmail: 'bar3'}} value="foo"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
var form = TestUtils.renderIntoDocument(
|
||||
<TestForm/>
|
||||
);
|
||||
|
||||
var inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
expect(inputComponent.getErrorMessage()).toBe('bar');
|
||||
});
|
||||
|
||||
it('should override validation rules with required rules', function () {
|
||||
var TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
render: function () {
|
||||
return <input/>
|
||||
}
|
||||
});
|
||||
var TestForm = React.createClass({
|
||||
render: function () {
|
||||
return (
|
||||
<Formsy.Form>
|
||||
<TestInput name="A"
|
||||
validations={{
|
||||
isEmail: true
|
||||
}}
|
||||
validationError="bar"
|
||||
validationErrors={{isEmail: 'bar2', isLength: 'bar3'}}
|
||||
value="f"
|
||||
required={{
|
||||
isLength: 1
|
||||
}}
|
||||
/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
var form = TestUtils.renderIntoDocument(
|
||||
<TestForm/>
|
||||
);
|
||||
|
||||
var inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
expect(inputComponent.getErrorMessage()).toBe('bar3');
|
||||
});
|
||||
|
||||
it('should fall back to default error message when non exist in validationErrors map', function () {
|
||||
var TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
render: function () {
|
||||
return <input/>
|
||||
}
|
||||
});
|
||||
var TestForm = React.createClass({
|
||||
render: function () {
|
||||
return (
|
||||
<Formsy.Form>
|
||||
<TestInput name="A"
|
||||
validations={{
|
||||
isEmail: true
|
||||
}}
|
||||
validationError="bar"
|
||||
validationErrors={{foo: 'bar'}}
|
||||
value="foo"
|
||||
/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
var form = TestUtils.renderIntoDocument(
|
||||
<TestForm/>
|
||||
);
|
||||
|
||||
var inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
expect(inputComponent.getErrorMessage()).toBe('bar');
|
||||
});
|
||||
|
||||
it('should not be valid if it is required and required rule is true', function () {
|
||||
var TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
render: function () {
|
||||
return <input/>
|
||||
}
|
||||
});
|
||||
var TestForm = React.createClass({
|
||||
render: function () {
|
||||
return (
|
||||
<Formsy.Form>
|
||||
<TestInput name="A"
|
||||
required
|
||||
/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
var form = TestUtils.renderIntoDocument(
|
||||
<TestForm/>
|
||||
);
|
||||
|
||||
var inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
expect(inputComponent.isValid()).toBe(false);
|
||||
});
|
||||
|
||||
it('should handle objects and arrays as values', function () {
|
||||
|
||||
var TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
render: function () {
|
||||
return <div>{JSON.stringify(this.getValue())}</div>
|
||||
}
|
||||
});
|
||||
var TestForm = React.createClass({
|
||||
getInitialState: function () {
|
||||
return {
|
||||
foo: {foo: 'bar'},
|
||||
bar: ['foo']
|
||||
};
|
||||
},
|
||||
render: function () {
|
||||
return (
|
||||
<Formsy.Form>
|
||||
<TestInput name="foo" value={this.state.foo}/>
|
||||
<TestInput name="bar" value={this.state.bar}/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
var form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
|
||||
form.setState({
|
||||
foo: {foo: 'foo'},
|
||||
bar: ['bar']
|
||||
});
|
||||
|
||||
var inputs = TestUtils.scryRenderedComponentsWithType(form, TestInput);
|
||||
expect(inputs[0].getValue()).toEqual({foo: 'foo'});
|
||||
expect(inputs[1].getValue()).toEqual(['bar']);
|
||||
|
||||
});
|
||||
|
||||
it('should handle isFormDisabled with dynamic inputs', function () {
|
||||
|
||||
var TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
render: function () {
|
||||
return <input disabled={this.isFormDisabled()} />
|
||||
}
|
||||
});
|
||||
|
||||
var TestForm = React.createClass({
|
||||
getInitialState: function () {
|
||||
return {
|
||||
bool: true
|
||||
};
|
||||
},
|
||||
flip: function () {
|
||||
this.setState({
|
||||
bool: !this.state.bool
|
||||
});
|
||||
},
|
||||
render: function () {
|
||||
return (
|
||||
<Formsy.Form disabled={this.state.bool}>
|
||||
{this.state.bool ?
|
||||
<TestInput name="foo" /> :
|
||||
<TestInput name="bar" />
|
||||
}
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
var input = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
expect(input.isFormDisabled()).toBe(true);
|
||||
form.flip();
|
||||
expect(input.isFormDisabled()).toBe(false);
|
||||
|
||||
});
|
||||
|
||||
it('should allow for dot notation in name which maps to a deep object', function () {
|
||||
|
||||
var TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
render: function () {
|
||||
return <input/>
|
||||
}
|
||||
});
|
||||
|
||||
var TestForm = React.createClass({
|
||||
onSubmit: function (model) {
|
||||
expect(model).toEqual({foo: {bar: 'foo', test: 'test'}});
|
||||
},
|
||||
render: function () {
|
||||
return (
|
||||
<Formsy.Form>
|
||||
<TestInput name="foo.bar" value="foo"/>
|
||||
<TestInput name="foo.test" value="test"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
var formEl = TestUtils.findRenderedDOMComponentWithTag(form, 'form');
|
||||
TestUtils.Simulate.submit(formEl);
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
|
@ -1,692 +0,0 @@
|
|||
var React = require('react/addons');
|
||||
var TestUtils = React.addons.TestUtils;
|
||||
var Formsy = require('./../src/main.js');
|
||||
|
||||
describe('Formsy', function () {
|
||||
|
||||
describe('Setting up a form', function () {
|
||||
|
||||
it('should render a form into the document', function () {
|
||||
var form = TestUtils.renderIntoDocument( <Formsy.Form></Formsy.Form>);
|
||||
expect(form.getDOMNode().tagName).toEqual('FORM');
|
||||
});
|
||||
|
||||
it('should set a class name if passed', function () {
|
||||
var form = TestUtils.renderIntoDocument( <Formsy.Form className="foo"></Formsy.Form>);
|
||||
expect(form.getDOMNode().className).toEqual('foo');
|
||||
});
|
||||
|
||||
it('should allow for null/undefined children', function (done) {
|
||||
var TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
changeValue: function (event) {
|
||||
this.setValue(event.target.value);
|
||||
},
|
||||
render: function () {
|
||||
return <input value={this.getValue()} onChange={this.changeValue}/>
|
||||
}
|
||||
});
|
||||
|
||||
var model = null;
|
||||
var TestForm = React.createClass({
|
||||
onSubmit: function (formModel) {
|
||||
model = formModel;
|
||||
},
|
||||
render: function () {
|
||||
return (
|
||||
<Formsy.Form onSubmit={ this.onSubmit }>
|
||||
<h1>Test</h1>
|
||||
{ null }
|
||||
{ undefined }
|
||||
<TestInput name='name' value={ 'foo' } />
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
setTimeout(function () {
|
||||
TestUtils.Simulate.submit(form.getDOMNode());
|
||||
expect(model).toEqual({name: 'foo'});
|
||||
done();
|
||||
}, 10);
|
||||
});
|
||||
|
||||
it('should allow for inputs being added dynamically', function (done) {
|
||||
|
||||
var inputs = [];
|
||||
var forceUpdate = null;
|
||||
var model = null;
|
||||
var TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
render: function () {
|
||||
return <div/>
|
||||
}
|
||||
});
|
||||
var TestForm = React.createClass({
|
||||
componentWillMount: function () {
|
||||
forceUpdate = this.forceUpdate.bind(this);
|
||||
},
|
||||
onSubmit: function (formModel) {
|
||||
model = formModel;
|
||||
},
|
||||
render: function () {
|
||||
return (
|
||||
<Formsy.Form onSubmit={this.onSubmit}>
|
||||
{inputs}
|
||||
</Formsy.Form>);
|
||||
}
|
||||
});
|
||||
var form = TestUtils.renderIntoDocument(
|
||||
<TestForm/>
|
||||
);
|
||||
|
||||
// Wait before adding the input
|
||||
setTimeout(function () {
|
||||
|
||||
inputs.push(<TestInput key={inputs.length} name="test" value=""/>);
|
||||
|
||||
forceUpdate(function () {
|
||||
// Wait for next event loop, as that does the form
|
||||
setTimeout(function () {
|
||||
TestUtils.Simulate.submit(form.getDOMNode());
|
||||
expect(model.test).toBeDefined();
|
||||
done();
|
||||
}, 0);
|
||||
|
||||
});
|
||||
|
||||
}, 10);
|
||||
|
||||
});
|
||||
|
||||
it('should allow dynamically added inputs to update the form-model', function (done) {
|
||||
|
||||
var inputs = [];
|
||||
var forceUpdate = null;
|
||||
var model = null;
|
||||
var TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
changeValue: function (event) {
|
||||
this.setValue(event.target.value);
|
||||
},
|
||||
render: function () {
|
||||
return <input value={this.getValue()} onChange={this.changeValue}/>
|
||||
}
|
||||
});
|
||||
var TestForm = React.createClass({
|
||||
componentWillMount: function () {
|
||||
forceUpdate = this.forceUpdate.bind(this);
|
||||
},
|
||||
onSubmit: function (formModel) {
|
||||
model = formModel;
|
||||
},
|
||||
render: function () {
|
||||
return (
|
||||
<Formsy.Form onSubmit={this.onSubmit}>
|
||||
{inputs}
|
||||
</Formsy.Form>);
|
||||
}
|
||||
});
|
||||
var form = TestUtils.renderIntoDocument(
|
||||
<TestForm/>
|
||||
);
|
||||
|
||||
// Wait before adding the input
|
||||
setTimeout(function () {
|
||||
|
||||
inputs.push(<TestInput key={inputs.length} name="test"/>);
|
||||
|
||||
forceUpdate(function () {
|
||||
|
||||
// Wait for next event loop, as that does the form
|
||||
setTimeout(function () {
|
||||
TestUtils.Simulate.change(TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT'), {target: {value: 'foo'}});
|
||||
TestUtils.Simulate.submit(form.getDOMNode());
|
||||
expect(model.test).toBe('foo');
|
||||
done();
|
||||
}, 0);
|
||||
|
||||
});
|
||||
|
||||
}, 0);
|
||||
|
||||
});
|
||||
|
||||
it('should allow a dynamically updated input to update the form-model', function (done) {
|
||||
|
||||
var forceUpdate = null;
|
||||
var model = null;
|
||||
var TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
changeValue: function (event) {
|
||||
this.setValue(event.target.value);
|
||||
},
|
||||
render: function () {
|
||||
return <input value={this.getValue()} onChange={this.changeValue}/>
|
||||
}
|
||||
});
|
||||
|
||||
var input;
|
||||
var TestForm = React.createClass({
|
||||
componentWillMount: function () {
|
||||
forceUpdate = this.forceUpdate.bind(this);
|
||||
},
|
||||
onSubmit: function (formModel) {
|
||||
model = formModel;
|
||||
},
|
||||
render: function () {
|
||||
input = <TestInput name='test' value={ this.props.value } />;
|
||||
|
||||
return (
|
||||
<Formsy.Form onSubmit={this.onSubmit}>
|
||||
{input}
|
||||
</Formsy.Form>);
|
||||
}
|
||||
});
|
||||
var form = TestUtils.renderIntoDocument(<TestForm value='foo'/>);
|
||||
|
||||
// Wait before changing the input
|
||||
setTimeout(function () {
|
||||
form.setProps({value: 'bar'});
|
||||
|
||||
forceUpdate(function () {
|
||||
// Wait for next event loop, as that does the form
|
||||
setTimeout(function () {
|
||||
TestUtils.Simulate.submit(form.getDOMNode());
|
||||
expect(model.test).toBe('bar');
|
||||
done();
|
||||
}, 0);
|
||||
|
||||
});
|
||||
|
||||
}, 10);
|
||||
|
||||
});
|
||||
|
||||
describe('validations', function() {
|
||||
var CheckValid, onSubmit, OtherCheckValid;
|
||||
var isValid;
|
||||
|
||||
var TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
changeValue: function (event) {
|
||||
this.setValue(event.target.value);
|
||||
},
|
||||
render: function () {
|
||||
return <input value={ this.getValue() } onChange={ this.changeValue } />
|
||||
}
|
||||
});
|
||||
|
||||
var TestForm = React.createClass({
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
inputs: [],
|
||||
};
|
||||
},
|
||||
render: function () {
|
||||
var builtInputs = [];
|
||||
var inputs = this.props.inputs;
|
||||
for (var i=0; i < inputs.length; i++) {
|
||||
var input = inputs[i];
|
||||
builtInputs.push(<TestInput { ...input } key={ input.name } />);
|
||||
}
|
||||
var _this = this;
|
||||
return <Formsy.Form
|
||||
onSubmit = { function(arg1) { onSubmit(arg1); } }
|
||||
onValid = { function() { isValid = true; } }
|
||||
onInvalid = { function() { isValid = false; } } >
|
||||
{ builtInputs }
|
||||
</Formsy.Form>;
|
||||
}
|
||||
});
|
||||
|
||||
beforeEach(function() {
|
||||
isValid = true;
|
||||
CheckValid = jasmine.createSpy('CheckValid');
|
||||
Formsy.addValidationRule('CheckValid', CheckValid);
|
||||
OtherCheckValid = jasmine.createSpy('CheckValid');
|
||||
Formsy.addValidationRule('OtherCheckValid', OtherCheckValid);
|
||||
onSubmit = jasmine.createSpy('onSubmit');
|
||||
});
|
||||
|
||||
it('should run when the input changes', function() {
|
||||
var form = TestUtils.renderIntoDocument(<TestForm inputs={ [{name: 'one', validations: 'CheckValid', value: 'foo'}] }/>);
|
||||
var input = TestUtils.findRenderedDOMComponentWithTag(form, 'input');
|
||||
TestUtils.Simulate.change(input.getDOMNode(), {target: {value: 'bar'}});
|
||||
expect(CheckValid).toHaveBeenCalledWith({one: 'bar'}, 'bar', true);
|
||||
expect(OtherCheckValid).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should allow the validation to be changed', function() {
|
||||
var form = TestUtils.renderIntoDocument(<TestForm inputs={ [{name: 'one', validations: 'CheckValid', value: 'foo'}] }/>);
|
||||
form.setProps({inputs: [{name: 'one', validations: 'OtherCheckValid', value: 'foo'}] });
|
||||
var input = TestUtils.findRenderedDOMComponentWithTag(form, 'input');
|
||||
TestUtils.Simulate.change(input.getDOMNode(), {target: {value: 'bar'}});
|
||||
expect(OtherCheckValid).toHaveBeenCalledWith({one: 'bar'}, 'bar', true);
|
||||
});
|
||||
|
||||
it('should invalidate a form if dynamically inserted input is invalid', function(done) {
|
||||
var form = TestUtils.renderIntoDocument(<TestForm inputs={ [{name: 'one', validations: 'isEmail', value: 'foo@bar.com'}] }/>);
|
||||
expect(isValid).toEqual(true);
|
||||
form.setProps({inputs: [
|
||||
{name: 'one', validations: 'isEmail', value: 'foo@bar.com'},
|
||||
{name: 'two', validations: 'isEmail', value: 'foo@bar'},
|
||||
]}, function() {
|
||||
setTimeout(function() {
|
||||
expect(isValid).toEqual(false);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
|
||||
it('should validate a form when removing an invalid input', function(done) {
|
||||
var form = TestUtils.renderIntoDocument(<TestForm inputs={ [
|
||||
{name: 'one', validations: 'isEmail', value: 'foo@bar.com'},
|
||||
{name: 'two', validations: 'isEmail', value: 'foo@bar'},
|
||||
] } />);
|
||||
expect(isValid).toEqual(false);
|
||||
form.setProps({inputs: [{name: 'one', validations: 'isEmail', value: 'foo@bar.com'}]}, function() {
|
||||
setTimeout(function() {
|
||||
expect(isValid).toEqual(true);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
|
||||
it('runs multiple validations', function() {
|
||||
var form = TestUtils.renderIntoDocument(<TestForm inputs={ [{name: 'one', validations: 'CheckValid,OtherCheckValid', value: 'foo'}] }/>);
|
||||
var input = TestUtils.findRenderedDOMComponentWithTag(form, 'input');
|
||||
TestUtils.Simulate.change(input.getDOMNode(), {target: {value: 'bar'}});
|
||||
expect(CheckValid).toHaveBeenCalledWith({one: 'bar'}, 'bar', true);
|
||||
expect(OtherCheckValid).toHaveBeenCalledWith({one: 'bar'}, 'bar', true);
|
||||
});
|
||||
});
|
||||
|
||||
it('should not trigger onChange when form is mounted', function () {
|
||||
var hasChanged = jasmine.createSpy('onChange');
|
||||
var TestForm = React.createClass({
|
||||
onChange: function () {
|
||||
hasChanged();
|
||||
},
|
||||
render: function () {
|
||||
return <Formsy.Form onChange={this.onChange}></Formsy.Form>;
|
||||
}
|
||||
});
|
||||
var form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
expect(hasChanged).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should trigger onChange when form element is changed', function () {
|
||||
var hasChanged = jasmine.createSpy('onChange');
|
||||
var MyInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
onChange: function (event) {
|
||||
this.setValue(event.target.value);
|
||||
},
|
||||
render: function () {
|
||||
return <input value={this.getValue()} onChange={this.onChange}/>
|
||||
}
|
||||
});
|
||||
var TestForm = React.createClass({
|
||||
onChange: function () {
|
||||
hasChanged();
|
||||
},
|
||||
render: function () {
|
||||
return (
|
||||
<Formsy.Form onChange={this.onChange}>
|
||||
<MyInput name="foo"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
var form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
TestUtils.Simulate.change(TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT'), {target: {value: 'bar'}});
|
||||
expect(hasChanged).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should trigger onChange when new input is added to form', function (done) {
|
||||
var hasChanged = jasmine.createSpy('onChange');
|
||||
var inputs = [];
|
||||
var forceUpdate = null;
|
||||
var TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
changeValue: function (event) {
|
||||
this.setValue(event.target.value);
|
||||
},
|
||||
render: function () {
|
||||
return <input value={this.getValue()} onChange={this.changeValue}/>
|
||||
}
|
||||
});
|
||||
var TestForm = React.createClass({
|
||||
componentWillMount: function () {
|
||||
forceUpdate = this.forceUpdate.bind(this);
|
||||
},
|
||||
onChange: function () {
|
||||
hasChanged();
|
||||
},
|
||||
render: function () {
|
||||
return (
|
||||
<Formsy.Form onChange={this.onChange}>
|
||||
{inputs}
|
||||
</Formsy.Form>);
|
||||
}
|
||||
});
|
||||
var form = TestUtils.renderIntoDocument(
|
||||
<TestForm/>
|
||||
);
|
||||
|
||||
// Wait before adding the input
|
||||
inputs.push(<TestInput key={inputs.length} name='test'/>);
|
||||
|
||||
forceUpdate(function () {
|
||||
|
||||
// Wait for next event loop, as that does the form
|
||||
setTimeout(function () {
|
||||
expect(hasChanged).toHaveBeenCalled();
|
||||
done();
|
||||
}, 0);
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('Update a form', function () {
|
||||
|
||||
it('should allow elements to check if the form is disabled', function (done) {
|
||||
|
||||
var TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
render: function () {
|
||||
return <input/>
|
||||
}
|
||||
});
|
||||
var TestForm = React.createClass({
|
||||
getInitialState: function () {
|
||||
return {disabled: true};
|
||||
},
|
||||
enableForm: function () {
|
||||
this.setState({
|
||||
disabled: false
|
||||
});
|
||||
},
|
||||
render: function () {
|
||||
return (
|
||||
<Formsy.Form onChange={this.onChange} disabled={this.state.disabled}>
|
||||
<TestInput name="foo"/>
|
||||
</Formsy.Form>);
|
||||
}
|
||||
});
|
||||
var form = TestUtils.renderIntoDocument(
|
||||
<TestForm/>
|
||||
);
|
||||
|
||||
var input = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
expect(input.isFormDisabled()).toBe(true);
|
||||
form.enableForm();
|
||||
setTimeout(function () {
|
||||
expect(input.isFormDisabled()).toBe(false);
|
||||
done();
|
||||
}, 0);
|
||||
|
||||
});
|
||||
|
||||
it('should be possible to pass error state of elements by changing an errors attribute', function (done) {
|
||||
|
||||
var TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
render: function () {
|
||||
return <input/>;
|
||||
}
|
||||
});
|
||||
var TestForm = React.createClass({
|
||||
getInitialState: function () {
|
||||
return {
|
||||
validationErrors: {
|
||||
foo: 'bar'
|
||||
}
|
||||
};
|
||||
},
|
||||
onChange: function (values) {
|
||||
if (values.foo) {
|
||||
this.setState({
|
||||
validationErrors: {}
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
validationErrors: {foo: 'bar'}
|
||||
});
|
||||
}
|
||||
},
|
||||
render: function () {
|
||||
return (
|
||||
<Formsy.Form onChange={this.onChange} validationErrors={this.state.validationErrors}>
|
||||
<TestInput name="foo"/>
|
||||
</Formsy.Form>);
|
||||
}
|
||||
});
|
||||
var form = TestUtils.renderIntoDocument(
|
||||
<TestForm/>
|
||||
);
|
||||
|
||||
// Wait for update
|
||||
setTimeout(function () {
|
||||
var input = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
expect(input.getErrorMessage()).toBe('bar');
|
||||
input.setValue('gotValue');
|
||||
|
||||
// Wait for update
|
||||
setTimeout(function () {
|
||||
expect(input.getErrorMessage()).toBe(null);
|
||||
done();
|
||||
}, 0);
|
||||
}, 0);
|
||||
|
||||
});
|
||||
|
||||
|
||||
it('should trigger an onValidSubmit when submitting a valid form', function () {
|
||||
|
||||
var isCalled = false;
|
||||
var TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
render: function () {
|
||||
return <input/>;
|
||||
}
|
||||
});
|
||||
var TestForm = React.createClass({
|
||||
onValidSubmit: function () {
|
||||
isCalled = true;
|
||||
},
|
||||
render: function () {
|
||||
return (
|
||||
<Formsy.Form onValidSubmit={this.onValidSubmit}>
|
||||
<TestInput name="foo" validations="isEmail" value="foo@bar.com"/>
|
||||
</Formsy.Form>);
|
||||
}
|
||||
});
|
||||
var form = TestUtils.renderIntoDocument(
|
||||
<TestForm/>
|
||||
);
|
||||
|
||||
var TestForm = TestUtils.findRenderedComponentWithType(form, TestForm);
|
||||
TestUtils.Simulate.submit(TestForm.getDOMNode());
|
||||
expect(isCalled).toBe(true);
|
||||
|
||||
});
|
||||
|
||||
it('should trigger an onInvalidSubmit when submitting an invalid form', function () {
|
||||
|
||||
var isCalled = false;
|
||||
var TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
render: function () {
|
||||
return <input/>;
|
||||
}
|
||||
});
|
||||
var TestForm = React.createClass({
|
||||
onInvalidSubmit: function () {
|
||||
isCalled = true;
|
||||
},
|
||||
render: function () {
|
||||
return (
|
||||
<Formsy.Form onInvalidSubmit={this.onInvalidSubmit}>
|
||||
<TestInput name="foo" validations="isEmail" value="foo@bar"/>
|
||||
</Formsy.Form>);
|
||||
}
|
||||
});
|
||||
var form = TestUtils.renderIntoDocument(
|
||||
<TestForm/>
|
||||
);
|
||||
|
||||
var TestForm = TestUtils.findRenderedComponentWithType(form, TestForm);
|
||||
TestUtils.Simulate.submit(TestForm.getDOMNode());
|
||||
expect(isCalled).toBe(true);
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe("value === false", function() {
|
||||
var onSubmit;
|
||||
var TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
type: "text",
|
||||
};
|
||||
},
|
||||
changeValue: function() {
|
||||
this.setValue(e.target[this.props.type === "checkbox" ? "checked" : "value"]);
|
||||
},
|
||||
render: function () {
|
||||
return <input type={ this.props.type } value={ this.getValue() } onChange={ this.changeValue }/>
|
||||
}
|
||||
});
|
||||
|
||||
var TestForm = React.createClass({
|
||||
render: function () {
|
||||
return (
|
||||
<Formsy.Form onSubmit={ function(arg1) { onSubmit(arg1); } }>
|
||||
<TestInput name="foo" value={ this.props.value } type="checkbox" />
|
||||
<button type="submit">Save</button>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
beforeEach(function() {
|
||||
onSubmit = jasmine.createSpy("onSubmit");
|
||||
});
|
||||
|
||||
it("should call onSubmit correctly", function() {
|
||||
var form = TestUtils.renderIntoDocument(<TestForm value={ false }/>);
|
||||
TestUtils.Simulate.submit(form.getDOMNode());
|
||||
expect(onSubmit).toHaveBeenCalledWith({foo: false});
|
||||
});
|
||||
|
||||
it("should allow dynamic changes to false", function() {
|
||||
var form = TestUtils.renderIntoDocument(<TestForm value={ true }/>);
|
||||
form.setProps({value: false});
|
||||
TestUtils.Simulate.submit(form.getDOMNode());
|
||||
expect(onSubmit).toHaveBeenCalledWith({foo: false});
|
||||
});
|
||||
|
||||
it("should say the form is submitted", function() {
|
||||
var form = TestUtils.renderIntoDocument(<TestForm value={ true }/>);
|
||||
var input = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
expect(input.isFormSubmitted()).toBe(false);
|
||||
TestUtils.Simulate.submit(form.getDOMNode());
|
||||
expect(input.isFormSubmitted()).toBe(true);
|
||||
});
|
||||
|
||||
it("should be able to reset the form to its pristine state", function() {
|
||||
var form = TestUtils.renderIntoDocument(<TestForm value={ true }/>);
|
||||
var input = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
var formsyForm = TestUtils.findRenderedComponentWithType(form, Formsy.Form);
|
||||
expect(input.getValue()).toBe(true);
|
||||
form.setProps({value: false});
|
||||
expect(input.getValue()).toBe(false);
|
||||
formsyForm.reset();
|
||||
expect(input.getValue()).toBe(true);
|
||||
});
|
||||
|
||||
it("should be able to reset the form using custom data", function() {
|
||||
var form = TestUtils.renderIntoDocument(<TestForm value={ true }/>);
|
||||
var input = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
var formsyForm = TestUtils.findRenderedComponentWithType(form, Formsy.Form);
|
||||
expect(input.getValue()).toBe(true);
|
||||
form.setProps({value: false});
|
||||
expect(input.getValue()).toBe(false);
|
||||
formsyForm.reset({
|
||||
foo: 'bar'
|
||||
});
|
||||
expect(input.getValue()).toBe('bar');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('.isChanged()', function() {
|
||||
var onChange;
|
||||
var TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
changeValue: function (event) {
|
||||
this.setValue(event.target.value);
|
||||
},
|
||||
render: function () {
|
||||
return <input value={ this.getValue() } onChange={ this.changeValue } />
|
||||
}
|
||||
});
|
||||
|
||||
var TestForm = React.createClass({
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
inputs: [],
|
||||
};
|
||||
},
|
||||
render: function () {
|
||||
var builtInputs = [];
|
||||
var inputs = this.props.inputs;
|
||||
for (var i=0; i < inputs.length; i++) {
|
||||
var input = inputs[i];
|
||||
builtInputs.push(<TestInput { ...input } key={ input.name } />);
|
||||
}
|
||||
return <Formsy.Form ref='formsy' onChange={ onChange }>
|
||||
{ builtInputs }
|
||||
{ this.props.children }
|
||||
</Formsy.Form>;
|
||||
}
|
||||
});
|
||||
|
||||
beforeEach(function() {
|
||||
onChange = jasmine.createSpy("onChange");
|
||||
});
|
||||
|
||||
it('initially returns false', function() {
|
||||
var form = TestUtils.renderIntoDocument(<TestForm inputs={ [{name: 'one', value: 'foo'}] }/>);
|
||||
expect(form.refs.formsy.isChanged()).toEqual(false);
|
||||
expect(onChange).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('returns true when changed', function() {
|
||||
var form = TestUtils.renderIntoDocument(<TestForm inputs={ [{name: 'one', value: 'foo'}] }/>);
|
||||
var input = TestUtils.findRenderedDOMComponentWithTag(form, 'input');
|
||||
TestUtils.Simulate.change(input.getDOMNode(), {target: {value: 'bar'}});
|
||||
expect(form.refs.formsy.isChanged()).toEqual(true);
|
||||
expect(onChange).toHaveBeenCalledWith({one: 'bar'}, true);
|
||||
});
|
||||
|
||||
it('returns false if changes are undone', function() {
|
||||
var form = TestUtils.renderIntoDocument(<TestForm inputs={ [{name: 'one', value: 'foo'}] }/>);
|
||||
var input = TestUtils.findRenderedDOMComponentWithTag(form, 'input');
|
||||
TestUtils.Simulate.change(input.getDOMNode(), {target: {value: 'bar'}});
|
||||
expect(onChange).toHaveBeenCalledWith({one: 'bar'}, true);
|
||||
TestUtils.Simulate.change(input.getDOMNode(), {target: {value: 'foo'}});
|
||||
expect(form.refs.formsy.isChanged()).toEqual(false);
|
||||
expect(onChange).toHaveBeenCalledWith({one: 'foo'}, false);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
var React = require('react/addons');
|
||||
var TestUtils = React.addons.TestUtils;
|
||||
var Formsy = require('./../src/main.js');
|
||||
|
||||
describe('Rules: equals', function() {
|
||||
var TestInput, isValid, form, input;
|
||||
|
||||
function pass(value) {
|
||||
return pass.length ? function () {
|
||||
TestUtils.Simulate.change(input, {target: {value: value}});
|
||||
expect(isValid).toBe(true);
|
||||
} : function () { expect(isValid).toBe(true); };
|
||||
}
|
||||
|
||||
function fail(value) {
|
||||
return fail.length ? function () {
|
||||
TestUtils.Simulate.change(input, {target: {value: value}});
|
||||
expect(isValid).toBe(false);
|
||||
} : function () { expect(isValid).toBe(false); };
|
||||
}
|
||||
|
||||
beforeEach(function() {
|
||||
TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
updateValue: function (event) {
|
||||
this.setValue(event.target.value);
|
||||
},
|
||||
render: function () {
|
||||
isValid = this.isValid();
|
||||
return <input value={this.getValue()} onChange={this.updateValue}/>
|
||||
}
|
||||
});
|
||||
|
||||
form = TestUtils.renderIntoDocument(
|
||||
<Formsy.Form>
|
||||
<TestInput name="foo" validations="equals:myValue"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
|
||||
input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
TestInput = isValid = form = null;
|
||||
});
|
||||
|
||||
it('should pass with a default value', pass());
|
||||
|
||||
it('should fail when the value is not equal', fail('foo'));
|
||||
|
||||
it('should pass when the value is equal', pass('myValue'));
|
||||
|
||||
it('should pass with an empty string', pass(''));
|
||||
|
||||
it('should pass with an undefined', pass(undefined));
|
||||
|
||||
it('should pass with a null', pass(null));
|
||||
|
||||
it('should fail with a number', fail(42));
|
||||
|
||||
});
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
var React = require('react/addons');
|
||||
var TestUtils = React.addons.TestUtils;
|
||||
var Formsy = require('./../src/main.js');
|
||||
|
||||
describe('Rules: isAlpha', function() {
|
||||
var TestInput, isValid, form, input;
|
||||
|
||||
function pass(value) {
|
||||
return pass.length ? function () {
|
||||
TestUtils.Simulate.change(input, {target: {value: value}});
|
||||
expect(isValid).toBe(true);
|
||||
} : function () { expect(isValid).toBe(true); };
|
||||
}
|
||||
|
||||
function fail(value) {
|
||||
return fail.length ? function () {
|
||||
TestUtils.Simulate.change(input, {target: {value: value}});
|
||||
expect(isValid).toBe(false);
|
||||
} : function () { expect(isValid).toBe(false); };
|
||||
}
|
||||
|
||||
beforeEach(function() {
|
||||
TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
updateValue: function (event) {
|
||||
this.setValue(event.target.value);
|
||||
},
|
||||
render: function () {
|
||||
isValid = this.isValid();
|
||||
return <input value={this.getValue()} onChange={this.updateValue}/>
|
||||
}
|
||||
});
|
||||
|
||||
form = TestUtils.renderIntoDocument(
|
||||
<Formsy.Form>
|
||||
<TestInput name="foo" validations="isAlpha"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
|
||||
input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
TestInput = isValid = form = null;
|
||||
});
|
||||
|
||||
it('should pass with a default value', pass());
|
||||
|
||||
it('should pass with a string is only latin letters', pass('myValue'));
|
||||
|
||||
it('should fail with a string with numbers', fail('myValue 42'));
|
||||
|
||||
it('should pass with an undefined', pass(undefined));
|
||||
|
||||
it('should pass with a null', pass(null));
|
||||
|
||||
it('should pass with an empty string', pass(''));
|
||||
|
||||
it('should fail with a number', fail(42));
|
||||
|
||||
});
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
var React = require('react/addons');
|
||||
var TestUtils = React.addons.TestUtils;
|
||||
var Formsy = require('./../src/main.js');
|
||||
|
||||
describe('Rules: isEmail', function() {
|
||||
var TestInput, isValid, form, input;
|
||||
|
||||
function pass(value) {
|
||||
return pass.length ? function () {
|
||||
TestUtils.Simulate.change(input, {target: {value: value}});
|
||||
expect(isValid).toBe(true);
|
||||
} : function () { expect(isValid).toBe(true); };
|
||||
}
|
||||
|
||||
function fail(value) {
|
||||
return fail.length ? function () {
|
||||
TestUtils.Simulate.change(input, {target: {value: value}});
|
||||
expect(isValid).toBe(false);
|
||||
} : function () { expect(isValid).toBe(false); };
|
||||
}
|
||||
|
||||
beforeEach(function() {
|
||||
TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
updateValue: function (event) {
|
||||
this.setValue(event.target.value);
|
||||
},
|
||||
render: function () {
|
||||
isValid = this.isValid();
|
||||
return <input value={this.getValue()} onChange={this.updateValue}/>
|
||||
}
|
||||
});
|
||||
|
||||
form = TestUtils.renderIntoDocument(
|
||||
<Formsy.Form>
|
||||
<TestInput name="foo" value="foo" validations="isEmail"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
|
||||
input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
TestInput = isValid = form = null;
|
||||
});
|
||||
|
||||
it('should pass with a default value', pass());
|
||||
|
||||
it('should fail with "foo"', fail('foo'));
|
||||
|
||||
it('should pass with "foo@foo.com"', pass('foo@foo.com'));
|
||||
|
||||
it('should pass with an undefined', pass(undefined));
|
||||
|
||||
it('should pass with a null', pass(null));
|
||||
|
||||
it('should pass with an empty string', pass(''));
|
||||
|
||||
it('should fail with a number', fail(42));
|
||||
|
||||
});
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
var React = require('react/addons');
|
||||
var TestUtils = React.addons.TestUtils;
|
||||
var Formsy = require('./../src/main.js');
|
||||
|
||||
describe('Rules: isEmptyString', function() {
|
||||
var TestInput, isValid, form, input;
|
||||
|
||||
function pass(value) {
|
||||
return pass.length ? function () {
|
||||
TestUtils.Simulate.change(input, {target: {value: value}});
|
||||
expect(isValid).toBe(true);
|
||||
} : function () { expect(isValid).toBe(true); };
|
||||
}
|
||||
|
||||
function fail(value) {
|
||||
return fail.length ? function () {
|
||||
TestUtils.Simulate.change(input, {target: {value: value}});
|
||||
expect(isValid).toBe(false);
|
||||
} : function () { expect(isValid).toBe(false); };
|
||||
}
|
||||
|
||||
beforeEach(function() {
|
||||
TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
updateValue: function (event) {
|
||||
this.setValue(event.target.value);
|
||||
},
|
||||
render: function () {
|
||||
isValid = this.isValid();
|
||||
return <input value={this.getValue()} onChange={this.updateValue}/>
|
||||
}
|
||||
});
|
||||
|
||||
form = TestUtils.renderIntoDocument(
|
||||
<Formsy.Form>
|
||||
<TestInput name="foo" validations="isEmptyString"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
|
||||
input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
TestInput = isValid = form = null;
|
||||
});
|
||||
|
||||
it('should fail with a default value', fail());
|
||||
|
||||
it('should fail with non-empty string', fail('asd'));
|
||||
|
||||
it('should pass with an empty string', pass(''));
|
||||
|
||||
it('should fail with a undefined', fail(undefined));
|
||||
|
||||
it('should fail with a null', fail(null));
|
||||
|
||||
it('should fail with a number', fail(123));
|
||||
|
||||
it('should fail with a zero', fail(0));
|
||||
|
||||
});
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
var React = require('react/addons');
|
||||
var TestUtils = React.addons.TestUtils;
|
||||
var Formsy = require('./../src/main.js');
|
||||
|
||||
describe('Rules: isExisty', function() {
|
||||
var TestInput, isValid, form, input;
|
||||
|
||||
function pass(value) {
|
||||
return pass.length ? function () {
|
||||
TestUtils.Simulate.change(input, {target: {value: value}});
|
||||
expect(isValid).toBe(true);
|
||||
} : function () { expect(isValid).toBe(true); };
|
||||
}
|
||||
|
||||
function fail(value) {
|
||||
return fail.length ? function () {
|
||||
TestUtils.Simulate.change(input, {target: {value: value}});
|
||||
expect(isValid).toBe(false);
|
||||
} : function () { expect(isValid).toBe(false); };
|
||||
}
|
||||
|
||||
beforeEach(function() {
|
||||
TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
updateValue: function (event) {
|
||||
this.setValue(event.target.value);
|
||||
},
|
||||
render: function () {
|
||||
isValid = this.isValid();
|
||||
return <input value={this.getValue()} onChange={this.updateValue}/>
|
||||
}
|
||||
});
|
||||
|
||||
form = TestUtils.renderIntoDocument(
|
||||
<Formsy.Form>
|
||||
<TestInput name="foo" validations="isExisty"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
|
||||
input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
TestInput = isValid = form = null;
|
||||
});
|
||||
|
||||
it('should fail with a default value', fail());
|
||||
|
||||
it('should pass with a string', pass('myValue'));
|
||||
|
||||
it('should pass with an empty string', pass(''));
|
||||
|
||||
it('should fail with an undefined', fail(undefined));
|
||||
|
||||
it('should fail with a null', fail(null));
|
||||
|
||||
it('should pass with a number', pass(42));
|
||||
|
||||
it('should pass with a zero', pass(0));
|
||||
|
||||
});
|
||||
|
|
@ -1,95 +0,0 @@
|
|||
var React = require('react/addons');
|
||||
var TestUtils = React.addons.TestUtils;
|
||||
var Formsy = require('./../src/main.js');
|
||||
|
||||
describe('Rules: isLength', function() {
|
||||
var TestInput, isValid, form, input;
|
||||
|
||||
function pass(value) {
|
||||
return pass.length ? function () {
|
||||
TestUtils.Simulate.change(input, {target: {value: value}});
|
||||
expect(isValid).toBe(true);
|
||||
} : function () { expect(isValid).toBe(true); };
|
||||
}
|
||||
|
||||
function fail(value) {
|
||||
return fail.length ? function () {
|
||||
TestUtils.Simulate.change(input, {target: {value: value}});
|
||||
expect(isValid).toBe(false);
|
||||
} : function () { expect(isValid).toBe(false); };
|
||||
}
|
||||
|
||||
beforeEach(function() {
|
||||
TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
updateValue: function (event) {
|
||||
this.setValue(event.target.value);
|
||||
},
|
||||
render: function () {
|
||||
isValid = this.isValid();
|
||||
return <input value={this.getValue()} onChange={this.updateValue}/>
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
TestInput = isValid = form = null;
|
||||
});
|
||||
|
||||
describe('isLength:3', function() {
|
||||
|
||||
beforeEach(function() {
|
||||
form = TestUtils.renderIntoDocument(
|
||||
<Formsy.Form>
|
||||
<TestInput name="foo" validations="isLength:3"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
|
||||
input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||
});
|
||||
|
||||
it('should pass with a default value', pass());
|
||||
|
||||
it('should fail with a string too small', fail('hi'));
|
||||
|
||||
it('should fail with a string too long', fail('foo bar'));
|
||||
|
||||
it('should pass with the right length', pass('sup'));
|
||||
|
||||
it('should pass with an undefined', pass(undefined));
|
||||
|
||||
it('should pass with a null', pass(null));
|
||||
|
||||
it('should pass with an empty string', pass(''));
|
||||
|
||||
it('should fail with a number', fail(123));
|
||||
|
||||
});
|
||||
|
||||
describe('isLength:0', function() {
|
||||
|
||||
beforeEach(function() {
|
||||
form = TestUtils.renderIntoDocument(
|
||||
<Formsy.Form>
|
||||
<TestInput name="foo" validations="isLength:0"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
|
||||
input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||
});
|
||||
|
||||
it('should pass with a default value', pass());
|
||||
|
||||
it('should fail with a string too long', fail('foo bar'));
|
||||
|
||||
it('should pass with an undefined', pass(undefined));
|
||||
|
||||
it('should pass with a null', pass(null));
|
||||
|
||||
it('should pass with an empty string', pass(''));
|
||||
|
||||
it('should fail with a number', fail(123));
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
var React = require('react/addons');
|
||||
var TestUtils = React.addons.TestUtils;
|
||||
var Formsy = require('./../src/main.js');
|
||||
|
||||
describe('Rules: isNumeric', function() {
|
||||
var TestInput, isValid, form, input;
|
||||
|
||||
function pass(value) {
|
||||
return pass.length ? function () {
|
||||
TestUtils.Simulate.change(input, {target: {value: value}});
|
||||
expect(isValid).toBe(true);
|
||||
} : function () { expect(isValid).toBe(true); };
|
||||
}
|
||||
|
||||
function fail(value) {
|
||||
return fail.length ? function () {
|
||||
TestUtils.Simulate.change(input, {target: {value: value}});
|
||||
expect(isValid).toBe(false);
|
||||
} : function () { expect(isValid).toBe(false); };
|
||||
}
|
||||
|
||||
beforeEach(function() {
|
||||
TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
updateValue: function (event) {
|
||||
this.setValue(event.target.value);
|
||||
},
|
||||
render: function () {
|
||||
isValid = this.isValid();
|
||||
return <input value={this.getValue()} onChange={this.updateValue}/>
|
||||
}
|
||||
});
|
||||
|
||||
form = TestUtils.renderIntoDocument(
|
||||
<Formsy.Form>
|
||||
<TestInput name="foo" validations="isNumeric"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
|
||||
input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
TestInput = isValid = form = null;
|
||||
});
|
||||
|
||||
it('should pass with a default value', pass());
|
||||
|
||||
it('should pass with an empty string', pass(''));
|
||||
|
||||
it('should fail with an unempty string', fail('myValue'));
|
||||
|
||||
it('should pass with a number as string', pass('+42'));
|
||||
|
||||
it('should fail with a number as string with not digits', fail('42 as an answer'));
|
||||
|
||||
it('should pass with an int', pass(42));
|
||||
|
||||
it('should pass with a float', pass(Math.PI));
|
||||
|
||||
it('should pass with an undefined', pass(undefined));
|
||||
|
||||
it('should pass with a null', pass(null));
|
||||
|
||||
it('should pass with a zero', pass(0));
|
||||
|
||||
});
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
var React = require('react/addons');
|
||||
var TestUtils = React.addons.TestUtils;
|
||||
var Formsy = require('./../src/main.js');
|
||||
|
||||
describe('Rules: isUrl', function() {
|
||||
var TestInput, isValid, form, input;
|
||||
|
||||
function pass(value) {
|
||||
return pass.length ? function () {
|
||||
TestUtils.Simulate.change(input, {target: {value: value}});
|
||||
expect(isValid).toBe(true);
|
||||
} : function () { expect(isValid).toBe(true); };
|
||||
}
|
||||
|
||||
function fail(value) {
|
||||
return fail.length ? function () {
|
||||
TestUtils.Simulate.change(input, {target: {value: value}});
|
||||
expect(isValid).toBe(false);
|
||||
} : function () { expect(isValid).toBe(false); };
|
||||
}
|
||||
|
||||
beforeEach(function() {
|
||||
TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
updateValue: function (event) {
|
||||
this.setValue(event.target.value);
|
||||
},
|
||||
render: function () {
|
||||
isValid = this.isValid();
|
||||
return <input value={this.getValue()} onChange={this.updateValue}/>
|
||||
}
|
||||
});
|
||||
|
||||
form = TestUtils.renderIntoDocument(
|
||||
<Formsy.Form>
|
||||
<TestInput name="foo" value="foo" validations="isUrl"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
|
||||
input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
TestInput = isValid = form = null;
|
||||
});
|
||||
|
||||
it('should pass with a default value', pass());
|
||||
|
||||
it('should fail with "foo"', fail('foo'));
|
||||
|
||||
it('should pass with "https://www.google.com/"', pass('https://www.google.com/'));
|
||||
|
||||
it('should pass with an undefined', pass(undefined));
|
||||
|
||||
it('should pass with a null', pass(null));
|
||||
|
||||
it('should fail with a number', fail(42));
|
||||
|
||||
it('should pass with an empty string', pass(''));
|
||||
|
||||
});
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
var React = require('react/addons');
|
||||
var TestUtils = React.addons.TestUtils;
|
||||
var Formsy = require('./../src/main.js');
|
||||
|
||||
describe('Rules: isWords', function() {
|
||||
var TestInput, isValid, form, input;
|
||||
|
||||
function pass(value) {
|
||||
return pass.length ? function () {
|
||||
TestUtils.Simulate.change(input, {target: {value: value}});
|
||||
expect(isValid).toBe(true);
|
||||
} : function () { expect(isValid).toBe(true); };
|
||||
}
|
||||
|
||||
function fail(value) {
|
||||
return fail.length ? function () {
|
||||
TestUtils.Simulate.change(input, {target: {value: value}});
|
||||
expect(isValid).toBe(false);
|
||||
} : function () { expect(isValid).toBe(false); };
|
||||
}
|
||||
|
||||
beforeEach(function() {
|
||||
TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
updateValue: function (event) {
|
||||
this.setValue(event.target.value);
|
||||
},
|
||||
render: function () {
|
||||
isValid = this.isValid();
|
||||
return <input value={this.getValue()} onChange={this.updateValue}/>
|
||||
}
|
||||
});
|
||||
|
||||
form = TestUtils.renderIntoDocument(
|
||||
<Formsy.Form>
|
||||
<TestInput name="foo" validations="isWords"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
|
||||
input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
TestInput = isValid = form = null;
|
||||
});
|
||||
|
||||
it('should pass with a default value', pass());
|
||||
|
||||
it('should pass with a 1 word', pass('sup'));
|
||||
|
||||
it('should pass with 2 words', pass('sup dude'));
|
||||
|
||||
it('should fail with a string with numbers', fail('myValue 42'));
|
||||
|
||||
it('should pass with an undefined', pass(undefined));
|
||||
|
||||
it('should pass with a null', pass(null));
|
||||
|
||||
it('should fail with a number', fail(42));
|
||||
|
||||
});
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
var React = require('react/addons');
|
||||
var TestUtils = React.addons.TestUtils;
|
||||
var Formsy = require('./../src/main.js');
|
||||
|
||||
describe('Rules: maxLength', function() {
|
||||
var TestInput, isValid, form, input;
|
||||
|
||||
function pass(value) {
|
||||
return pass.length ? function () {
|
||||
TestUtils.Simulate.change(input, {target: {value: value}});
|
||||
expect(isValid).toBe(true);
|
||||
} : function () { expect(isValid).toBe(true); };
|
||||
}
|
||||
|
||||
function fail(value) {
|
||||
return fail.length ? function () {
|
||||
TestUtils.Simulate.change(input, {target: {value: value}});
|
||||
expect(isValid).toBe(false);
|
||||
} : function () { expect(isValid).toBe(false); };
|
||||
}
|
||||
|
||||
beforeEach(function() {
|
||||
TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
updateValue: function (event) {
|
||||
this.setValue(event.target.value);
|
||||
},
|
||||
render: function () {
|
||||
isValid = this.isValid();
|
||||
return <input value={this.getValue()} onChange={this.updateValue}/>
|
||||
}
|
||||
});
|
||||
|
||||
form = TestUtils.renderIntoDocument(
|
||||
<Formsy.Form>
|
||||
<TestInput name="foo" validations="maxLength:3"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
|
||||
input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
TestInput = isValid = form = null;
|
||||
});
|
||||
|
||||
it('should pass with a default value', pass());
|
||||
|
||||
it('should pass when a string\'s length is smaller', pass('hi'));
|
||||
|
||||
it('should pass when a string\'s length is equal', pass('bar'));
|
||||
|
||||
it('should fail when a string\'s length is bigger', fail('myValue'));
|
||||
|
||||
it('should pass with an empty string', pass(''));
|
||||
|
||||
it('should pass with an undefined', pass(undefined));
|
||||
|
||||
it('should pass with a null', pass(null));
|
||||
|
||||
it('should fail with a number', fail(123));
|
||||
|
||||
});
|
||||
|
|
@ -1,95 +0,0 @@
|
|||
var React = require('react/addons');
|
||||
var TestUtils = React.addons.TestUtils;
|
||||
var Formsy = require('./../src/main.js');
|
||||
|
||||
describe('Rules: minLength', function() {
|
||||
var TestInput, isValid, form, input;
|
||||
|
||||
function pass(value) {
|
||||
return pass.length ? function () {
|
||||
TestUtils.Simulate.change(input, {target: {value: value}});
|
||||
expect(isValid).toBe(true);
|
||||
} : function () { expect(isValid).toBe(true); };
|
||||
}
|
||||
|
||||
function fail(value) {
|
||||
return fail.length ? function () {
|
||||
TestUtils.Simulate.change(input, {target: {value: value}});
|
||||
expect(isValid).toBe(false);
|
||||
} : function () { expect(isValid).toBe(false); };
|
||||
}
|
||||
|
||||
beforeEach(function() {
|
||||
TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
updateValue: function (event) {
|
||||
this.setValue(event.target.value);
|
||||
},
|
||||
render: function () {
|
||||
isValid = this.isValid();
|
||||
return <input value={this.getValue()} onChange={this.updateValue}/>
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
TestInput = isValid = form = null;
|
||||
});
|
||||
|
||||
describe('minLength:3', function() {
|
||||
|
||||
beforeEach(function() {
|
||||
form = TestUtils.renderIntoDocument(
|
||||
<Formsy.Form>
|
||||
<TestInput name="foo" validations="minLength:3"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
|
||||
input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||
});
|
||||
|
||||
it('should pass with a default value', pass());
|
||||
|
||||
it('should fail when a string\'s length is smaller', fail('hi'));
|
||||
|
||||
it('should pass when a string\'s length is equal', pass('bar'));
|
||||
|
||||
it('should pass when a string\'s length is bigger', pass('myValue'));
|
||||
|
||||
it('should pass with an empty string', pass(''));
|
||||
|
||||
it('should pass with an undefined', pass(undefined));
|
||||
|
||||
it('should pass with a null', pass(null));
|
||||
|
||||
it('should fail with a number', fail(123));
|
||||
|
||||
});
|
||||
|
||||
describe('minLength:0', function() {
|
||||
|
||||
beforeEach(function() {
|
||||
form = TestUtils.renderIntoDocument(
|
||||
<Formsy.Form>
|
||||
<TestInput name="foo" validations="minLength:0"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
|
||||
input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||
});
|
||||
|
||||
it('should pass with a default value', pass());
|
||||
|
||||
it('should pass when a string\'s length is bigger', pass('myValue'));
|
||||
|
||||
it('should pass with empty string', pass(''));
|
||||
|
||||
it('should pass with undefined', pass(undefined));
|
||||
|
||||
it('should pass with null', pass(null));
|
||||
|
||||
it('should fail with a number', fail(123));
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
var utils = require('./../src/utils.js');
|
||||
|
||||
describe('Utils', function() {
|
||||
|
||||
it('should check equality of objects and arrays', function () {
|
||||
var objA = { foo: 'bar' };
|
||||
var objB = { foo: 'bar' };
|
||||
var objC = [{ foo: ['bar'] }];
|
||||
var objD = [{ foo: ['bar'] }];
|
||||
var objE, objF;
|
||||
var objG = null;
|
||||
var objH = null;
|
||||
|
||||
expect(utils.isSame(objA, objB)).toBe(true);
|
||||
expect(utils.isSame(objC, objD)).toBe(true);
|
||||
expect(utils.isSame(objA, objD)).toBe(false);
|
||||
|
||||
expect(utils.isSame(objE, objF)).toBe(true);
|
||||
expect(utils.isSame(objA, objF)).toBe(false);
|
||||
expect(utils.isSame(objE, objA)).toBe(false);
|
||||
|
||||
expect(utils.isSame(objG, objH)).toBe(true);
|
||||
expect(utils.isSame(objA, objH)).toBe(false);
|
||||
expect(utils.isSame(objG, objA)).toBe(false);
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
|
@ -1,281 +0,0 @@
|
|||
var React = require('react/addons');
|
||||
var TestUtils = React.addons.TestUtils;
|
||||
var Formsy = require('./../src/main.js');
|
||||
|
||||
describe('Validation', function() {
|
||||
|
||||
it('should reset only changed form element when external error is passed', function (done) {
|
||||
|
||||
var onSubmit = function (model, reset, invalidate) {
|
||||
invalidate({
|
||||
foo: 'bar',
|
||||
bar: 'foo'
|
||||
});
|
||||
}
|
||||
var TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
updateValue: function (event) {
|
||||
this.setValue(event.target.value);
|
||||
},
|
||||
render: function () {
|
||||
return <input value={this.getValue()} onChange={this.updateValue}/>
|
||||
}
|
||||
});
|
||||
var form = TestUtils.renderIntoDocument(
|
||||
<Formsy.Form onSubmit={onSubmit}>
|
||||
<TestInput name="foo"/>
|
||||
<TestInput name="bar"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
|
||||
var input = TestUtils.scryRenderedDOMComponentsWithTag(form, 'INPUT')[0];
|
||||
var inputComponents = TestUtils.scryRenderedComponentsWithType(form, TestInput);
|
||||
|
||||
form.submit();
|
||||
expect(inputComponents[0].isValid()).toBe(false);
|
||||
expect(inputComponents[1].isValid()).toBe(false);
|
||||
TestUtils.Simulate.change(input, {target: {value: 'bar'}});
|
||||
setTimeout(function () {
|
||||
expect(inputComponents[0].isValid()).toBe(true);
|
||||
expect(inputComponents[1].isValid()).toBe(false);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
it('should let normal validation take over when component with external error is changed', function (done) {
|
||||
|
||||
var onSubmit = function (model, reset, invalidate) {
|
||||
invalidate({
|
||||
foo: 'bar'
|
||||
});
|
||||
}
|
||||
var TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
updateValue: function (event) {
|
||||
this.setValue(event.target.value);
|
||||
},
|
||||
render: function () {
|
||||
return <input value={this.getValue()} onChange={this.updateValue}/>
|
||||
}
|
||||
});
|
||||
var form = TestUtils.renderIntoDocument(
|
||||
<Formsy.Form onSubmit={onSubmit}>
|
||||
<TestInput name="foo" validations="isEmail"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
|
||||
var input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||
var inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
|
||||
form.submit();
|
||||
expect(inputComponent.isValid()).toBe(false);
|
||||
TestUtils.Simulate.change(input, {target: {value: 'bar'}});
|
||||
setTimeout(function () {
|
||||
expect(inputComponent.getValue()).toBe('bar');
|
||||
expect(inputComponent.isValid()).toBe(false);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
it('should trigger an onValid handler, if passed, when form is valid', function () {
|
||||
|
||||
var onValid = jasmine.createSpy('valid');
|
||||
var TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
updateValue: function (event) {
|
||||
this.setValue(event.target.value);
|
||||
},
|
||||
render: function () {
|
||||
return <input value={this.getValue()} onChange={this.updateValue}/>
|
||||
}
|
||||
});
|
||||
var form = TestUtils.renderIntoDocument(
|
||||
<Formsy.Form onValid={onValid}>
|
||||
<TestInput name="foo" required/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
|
||||
var input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||
TestUtils.Simulate.change(input, {target: {value: 'foo'}});
|
||||
expect(onValid).toHaveBeenCalled();
|
||||
|
||||
});
|
||||
|
||||
it('should trigger an onInvalid handler, if passed, when form is invalid', function () {
|
||||
|
||||
var onInvalid = jasmine.createSpy('invalid');
|
||||
var TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
updateValue: function (event) {
|
||||
this.setValue(event.target.value);
|
||||
},
|
||||
render: function () {
|
||||
return <input value={this.getValue()} onChange={this.updateValue}/>
|
||||
}
|
||||
});
|
||||
var form = TestUtils.renderIntoDocument(
|
||||
<Formsy.Form onValid={onInvalid}>
|
||||
<TestInput name="foo" value="foo"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
|
||||
var input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||
TestUtils.Simulate.change(input, {target: {value: ''}});
|
||||
expect(onInvalid).toHaveBeenCalled();
|
||||
|
||||
});
|
||||
|
||||
it('should use provided validate function', function () {
|
||||
|
||||
var isValid = jasmine.createSpy('valid');
|
||||
var TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
updateValue: function (event) {
|
||||
this.setValue(event.target.value);
|
||||
},
|
||||
render: function () {
|
||||
if (this.isValid()) {
|
||||
isValid();
|
||||
}
|
||||
return <input value={this.getValue()} onChange={this.updateValue}/>
|
||||
},
|
||||
validate: function () {
|
||||
return this.getValue() === "checkValidity";
|
||||
}
|
||||
});
|
||||
var form = TestUtils.renderIntoDocument(
|
||||
<Formsy.Form>
|
||||
<TestInput name="foo" value="checkInvalidity"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
|
||||
var input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||
TestUtils.Simulate.change(input, {target: {value: 'checkValidity'}});
|
||||
expect(isValid).toHaveBeenCalled();
|
||||
|
||||
});
|
||||
|
||||
it('should provide invalidate callback on onValiSubmit', function () {
|
||||
|
||||
var TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
render: function () {
|
||||
return <input/>
|
||||
}
|
||||
});
|
||||
var TestForm = React.createClass({
|
||||
invalidate: function (model, reset, invalidate) {
|
||||
invalidate({
|
||||
foo: 'bar'
|
||||
});
|
||||
},
|
||||
render: function () {
|
||||
return (
|
||||
<Formsy.Form onValidSubmit={this.invalidate}>
|
||||
<TestInput name="foo" value="foo"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
var form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
|
||||
var formEl = TestUtils.findRenderedDOMComponentWithTag(form, 'form');
|
||||
var input = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
TestUtils.Simulate.submit(formEl);
|
||||
expect(input.isValid()).toBe(false);
|
||||
|
||||
});
|
||||
|
||||
it('should provide invalidate callback on onInvalidSubmit', function () {
|
||||
|
||||
var TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
render: function () {
|
||||
return <input/>
|
||||
}
|
||||
});
|
||||
var TestForm = React.createClass({
|
||||
invalidate: function (model, reset, invalidate) {
|
||||
invalidate({
|
||||
foo: 'bar'
|
||||
});
|
||||
},
|
||||
render: function () {
|
||||
return (
|
||||
<Formsy.Form onInvalidSubmit={this.invalidate}>
|
||||
<TestInput name="foo" value="foo" validations="isEmail"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
var form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
|
||||
var formEl = TestUtils.findRenderedDOMComponentWithTag(form, 'form');
|
||||
var input = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
TestUtils.Simulate.submit(formEl);
|
||||
expect(input.getErrorMessage()).toBe('bar');
|
||||
|
||||
});
|
||||
|
||||
|
||||
it('should not invalidate inputs on external errors with preventExternalInvalidation prop', function () {
|
||||
|
||||
var TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
render: function () {
|
||||
return <input/>
|
||||
}
|
||||
});
|
||||
var TestForm = React.createClass({
|
||||
invalidate: function (model, reset, invalidate) {
|
||||
invalidate({
|
||||
foo: 'bar'
|
||||
});
|
||||
},
|
||||
render: function () {
|
||||
return (
|
||||
<Formsy.Form onSubmit={this.invalidate} preventExternalInvalidation>
|
||||
<TestInput name="foo" value="foo"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
var form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
var formEl = TestUtils.findRenderedDOMComponentWithTag(form, 'form');
|
||||
var input = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
TestUtils.Simulate.submit(formEl);
|
||||
expect(input.isValid()).toBe(true);
|
||||
|
||||
});
|
||||
|
||||
it('should invalidate inputs on external errors without preventExternalInvalidation prop', function () {
|
||||
|
||||
var TestInput = React.createClass({
|
||||
mixins: [Formsy.Mixin],
|
||||
render: function () {
|
||||
return <input/>
|
||||
}
|
||||
});
|
||||
var TestForm = React.createClass({
|
||||
invalidate: function (model, reset, invalidate) {
|
||||
invalidate({
|
||||
foo: 'bar'
|
||||
});
|
||||
},
|
||||
render: function () {
|
||||
return (
|
||||
<Formsy.Form onSubmit={this.invalidate}>
|
||||
<TestInput name="foo" value="foo"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
var form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
var formEl = TestUtils.findRenderedDOMComponentWithTag(form, 'form');
|
||||
var input = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
TestUtils.Simulate.submit(formEl);
|
||||
expect(input.isValid()).toBe(false);
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
var React = global.React || require('react');
|
||||
var Mixin = require('./Mixin.js');
|
||||
module.exports = function () {
|
||||
return function (Component) {
|
||||
return React.createClass({
|
||||
mixins: [Mixin],
|
||||
render: function () {
|
||||
return React.createElement(Component, {
|
||||
setValidations: this.setValidations,
|
||||
setValue: this.setValue,
|
||||
resetValue: this.resetValue,
|
||||
getValue: this.getValue,
|
||||
hasValue: this.hasValue,
|
||||
getErrorMessage: this.getErrorMessage,
|
||||
getErrorMessages: this.getErrorMessages,
|
||||
isFormDisabled: this.isFormDisabled,
|
||||
isValid: this.isValid,
|
||||
isPristine: this.isPristine,
|
||||
isFormSubmitted: this.isFormSubmitted,
|
||||
isRequired: this.isRequired,
|
||||
showRequired: this.showRequired,
|
||||
showError: this.showError,
|
||||
isValidValue: this.isValidValue,
|
||||
...this.props
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
var React = global.React || require('react');
|
||||
var Mixin = require('./Mixin.js');
|
||||
module.exports = function (Component) {
|
||||
return React.createClass({
|
||||
mixins: [Mixin],
|
||||
render: function () {
|
||||
return React.createElement(Component, {
|
||||
setValidations: this.setValidations,
|
||||
setValue: this.setValue,
|
||||
resetValue: this.resetValue,
|
||||
getValue: this.getValue,
|
||||
hasValue: this.hasValue,
|
||||
getErrorMessage: this.getErrorMessage,
|
||||
getErrorMessages: this.getErrorMessages,
|
||||
isFormDisabled: this.isFormDisabled,
|
||||
isValid: this.isValid,
|
||||
isPristine: this.isPristine,
|
||||
isFormSubmitted: this.isFormSubmitted,
|
||||
isRequired: this.isRequired,
|
||||
showRequired: this.showRequired,
|
||||
showError: this.showError,
|
||||
isValidValue: this.isValidValue
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
40
src/Mixin.js
40
src/Mixin.js
|
|
@ -1,4 +1,5 @@
|
|||
var utils = require('./utils.js');
|
||||
var React = global.React || require('react');
|
||||
|
||||
var convertValidationsToObject = function (validations) {
|
||||
|
||||
|
|
@ -37,11 +38,14 @@ module.exports = {
|
|||
_isValid: true,
|
||||
_isPristine: true,
|
||||
_pristineValue: this.props.value,
|
||||
_validationError: '',
|
||||
_validationError: [],
|
||||
_externalError: null,
|
||||
_formSubmitted: false
|
||||
};
|
||||
},
|
||||
contextTypes: {
|
||||
formsy: React.PropTypes.object // What about required?
|
||||
},
|
||||
getDefaultProps: function () {
|
||||
return {
|
||||
validationError: '',
|
||||
|
|
@ -52,13 +56,17 @@ module.exports = {
|
|||
componentWillMount: function () {
|
||||
var configure = function () {
|
||||
this.setValidations(this.props.validations, this.props.required);
|
||||
this.props._attachToForm(this);
|
||||
|
||||
// Pass a function instead?
|
||||
this.context.formsy.attachToForm(this);
|
||||
//this.props._attachToForm(this);
|
||||
}.bind(this);
|
||||
|
||||
if (!this.props.name) {
|
||||
throw new Error('Form Input requires a name property when used');
|
||||
}
|
||||
|
||||
/*
|
||||
if (!this.props._attachToForm) {
|
||||
return setTimeout(function () {
|
||||
if (!this.isMounted()) return;
|
||||
|
|
@ -68,12 +76,14 @@ module.exports = {
|
|||
configure();
|
||||
}.bind(this), 0);
|
||||
}
|
||||
*/
|
||||
configure();
|
||||
},
|
||||
|
||||
// We have to make the validate method is kept when new props are added
|
||||
componentWillReceiveProps: function (nextProps) {
|
||||
this.setValidations(nextProps.validations, nextProps.required);
|
||||
|
||||
},
|
||||
|
||||
componentDidUpdate: function (prevProps) {
|
||||
|
|
@ -83,11 +93,17 @@ module.exports = {
|
|||
if (!utils.isSame(this.props.value, prevProps.value)) {
|
||||
this.setValue(this.props.value);
|
||||
}
|
||||
|
||||
// If validations or required is changed, run a new validation
|
||||
if (!utils.isSame(this.props.validations, prevProps.validations) || !utils.isSame(this.props.required, prevProps.required)) {
|
||||
this.context.formsy.validate(this);
|
||||
}
|
||||
},
|
||||
|
||||
// Detach it when component unmounts
|
||||
componentWillUnmount: function () {
|
||||
this.props._detachFromForm(this);
|
||||
this.context.formsy.detachFromForm(this);
|
||||
//this.props._detachFromForm(this);
|
||||
},
|
||||
|
||||
setValidations: function (validations, required) {
|
||||
|
|
@ -104,7 +120,8 @@ module.exports = {
|
|||
_value: value,
|
||||
_isPristine: false
|
||||
}, function () {
|
||||
this.props._validate(this);
|
||||
this.context.formsy.validate(this);
|
||||
//this.props._validate(this);
|
||||
}.bind(this));
|
||||
},
|
||||
resetValue: function () {
|
||||
|
|
@ -112,7 +129,8 @@ module.exports = {
|
|||
_value: this.state._pristineValue,
|
||||
_isPristine: true
|
||||
}, function () {
|
||||
this.props._validate(this);
|
||||
this.context.formsy.validate(this);
|
||||
//this.props._validate(this);
|
||||
});
|
||||
},
|
||||
getValue: function () {
|
||||
|
|
@ -122,10 +140,15 @@ module.exports = {
|
|||
return this.state._value !== '';
|
||||
},
|
||||
getErrorMessage: function () {
|
||||
return !this.isValid() || this.showRequired() ? (this.state._externalError || this.state._validationError) : null;
|
||||
var messages = this.getErrorMessages();
|
||||
return messages.length ? messages[0] : null;
|
||||
},
|
||||
getErrorMessages: function () {
|
||||
return !this.isValid() || this.showRequired() ? (this.state._externalError || this.state._validationError || []) : [];
|
||||
},
|
||||
isFormDisabled: function () {
|
||||
return this.props._isFormDisabled();
|
||||
return this.context.formsy.isFormDisabled();
|
||||
//return this.props._isFormDisabled();
|
||||
},
|
||||
isValid: function () {
|
||||
return this.state._isValid;
|
||||
|
|
@ -146,6 +169,7 @@ module.exports = {
|
|||
return !this.showRequired() && !this.isValid();
|
||||
},
|
||||
isValidValue: function (value) {
|
||||
return this.props._isValidValue.call(null, this, value);
|
||||
return this.context.formsy.isValidValue.call(null, this, value);
|
||||
//return this.props._isValidValue.call(null, this, value);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
83
src/main.js
83
src/main.js
|
|
@ -1,11 +1,16 @@
|
|||
var React = global.React || require('react');
|
||||
var Formsy = {};
|
||||
var validationRules = require('./validationRules.js');
|
||||
var formDataToObject = require('form-data-to-object');
|
||||
var utils = require('./utils.js');
|
||||
var Mixin = require('./Mixin.js');
|
||||
var HOC = require('./HOC.js');
|
||||
var Decorator = require('./Decorator.js');
|
||||
var options = {};
|
||||
|
||||
Formsy.Mixin = Mixin;
|
||||
Formsy.HOC = HOC;
|
||||
Formsy.Decorator = Decorator;
|
||||
|
||||
Formsy.defaults = function (passedOptions) {
|
||||
options = passedOptions;
|
||||
|
|
@ -40,6 +45,23 @@ Formsy.Form = React.createClass({
|
|||
};
|
||||
},
|
||||
|
||||
childContextTypes: {
|
||||
formsy: React.PropTypes.object
|
||||
},
|
||||
getChildContext: function () {
|
||||
return {
|
||||
formsy: {
|
||||
attachToForm: this.attachToForm,
|
||||
detachFromForm: this.detachFromForm,
|
||||
validate: this.validate,
|
||||
isFormDisabled: this.isFormDisabled,
|
||||
isValidValue: function (component, value) {
|
||||
return this.runValidation(component, value).isValid;
|
||||
}.bind(this)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Add a map to store the inputs of the form, a model to store
|
||||
// the values of the form and register child inputs
|
||||
componentWillMount: function () {
|
||||
|
|
@ -98,7 +120,7 @@ Formsy.Form = React.createClass({
|
|||
if (this.props.mapping) {
|
||||
return this.props.mapping(this.model)
|
||||
} else {
|
||||
return Object.keys(this.model).reduce(function (mappedModel, key) {
|
||||
return formDataToObject(Object.keys(this.model).reduce(function (mappedModel, key) {
|
||||
|
||||
var keyArray = key.split('.');
|
||||
var base = mappedModel;
|
||||
|
|
@ -109,7 +131,7 @@ Formsy.Form = React.createClass({
|
|||
|
||||
return mappedModel;
|
||||
|
||||
}.bind(this), {});
|
||||
}.bind(this), {}));
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -139,7 +161,7 @@ Formsy.Form = React.createClass({
|
|||
var component = this.inputs[name];
|
||||
var args = [{
|
||||
_isValid: !(name in errors),
|
||||
_validationError: errors[name]
|
||||
_validationError: typeof errors[name] === 'string' ? [errors[name]] : errors[name]
|
||||
}];
|
||||
component.setState.apply(component, args);
|
||||
}.bind(this));
|
||||
|
|
@ -171,45 +193,12 @@ Formsy.Form = React.createClass({
|
|||
}
|
||||
var args = [{
|
||||
_isValid: this.props.preventExternalInvalidation || false,
|
||||
_externalError: errors[name]
|
||||
_externalError: typeof errors[name] === 'string' ? [errors[name]] : errors[name]
|
||||
}];
|
||||
component.setState.apply(component, args);
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
// Traverse the children and children of children to find
|
||||
// all inputs by checking the name prop. Maybe do a better
|
||||
// check here
|
||||
traverseChildrenAndRegisterInputs: function (children) {
|
||||
|
||||
if (typeof children !== 'object' || children === null) {
|
||||
return children;
|
||||
}
|
||||
return React.Children.map(children, function (child) {
|
||||
|
||||
if (typeof child !== 'object' || child === null) {
|
||||
return child;
|
||||
}
|
||||
|
||||
if (child.props && child.props.name) {
|
||||
|
||||
return React.cloneElement(child, {
|
||||
_attachToForm: this.attachToForm,
|
||||
_detachFromForm: this.detachFromForm,
|
||||
_validate: this.validate,
|
||||
_isFormDisabled: this.isFormDisabled,
|
||||
_isValidValue: function (component, value) {
|
||||
return this.runValidation(component, value).isValid;
|
||||
}.bind(this)
|
||||
}, child.props && child.props.children);
|
||||
} else {
|
||||
return React.cloneElement(child, {}, this.traverseChildrenAndRegisterInputs(child.props && child.props.children));
|
||||
}
|
||||
|
||||
}, this);
|
||||
|
||||
},
|
||||
|
||||
isFormDisabled: function () {
|
||||
return this.props.disabled;
|
||||
},
|
||||
|
|
@ -288,23 +277,29 @@ Formsy.Form = React.createClass({
|
|||
error: (function () {
|
||||
|
||||
if (isValid && !isRequired) {
|
||||
return '';
|
||||
return [];
|
||||
}
|
||||
|
||||
if (validationResults.errors.length) {
|
||||
return validationResults.errors[0];
|
||||
return validationResults.errors;
|
||||
}
|
||||
|
||||
if (this.props.validationErrors && this.props.validationErrors[component.props.name]) {
|
||||
return this.props.validationErrors[component.props.name];
|
||||
return typeof this.props.validationErrors[component.props.name] === 'string' ? [this.props.validationErrors[component.props.name]] : this.props.validationErrors[component.props.name];
|
||||
}
|
||||
|
||||
if (isRequired) {
|
||||
return validationErrors[requiredResults.success[0]] || null;
|
||||
var error = validationErrors[requiredResults.success[0]];
|
||||
return error ? [error] : null;
|
||||
}
|
||||
|
||||
if (!isValid) {
|
||||
return validationErrors[validationResults.failed[0]] || validationError;
|
||||
if (validationResults.failed.length) {
|
||||
return validationResults.failed.map(function(failed) {
|
||||
return validationErrors[failed] ? validationErrors[failed] : validationError;
|
||||
}).filter(function(x, pos, arr) {
|
||||
// Remove duplicates
|
||||
return arr.indexOf(x) === pos;
|
||||
});
|
||||
}
|
||||
|
||||
}.call(this))
|
||||
|
|
@ -438,7 +433,7 @@ Formsy.Form = React.createClass({
|
|||
|
||||
return (
|
||||
<form {...this.props} onSubmit={this.submit}>
|
||||
{this.traverseChildrenAndRegisterInputs(this.props.children)}
|
||||
{this.props.children}
|
||||
</form>
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -38,16 +38,25 @@ var validations = {
|
|||
if (typeof value === 'number') {
|
||||
return true;
|
||||
}
|
||||
return validations.matchRegexp(values, value, /^[-+]?(\d*[.])?\d+$/);
|
||||
return validations.matchRegexp(values, value, /^[-+]?(?:\d*[.])?\d+$/);
|
||||
},
|
||||
isAlpha: function (values, value) {
|
||||
return validations.matchRegexp(values, value, /^[a-zA-Z]+$/);
|
||||
return validations.matchRegexp(values, value, /^[A-Z]+$/i);
|
||||
},
|
||||
isAlphanumeric: function (values, value) {
|
||||
return validations.matchRegexp(values, value, /^[0-9A-Z]+$/i);
|
||||
},
|
||||
isInt: function (values, value) {
|
||||
return validations.matchRegexp(values, value, /^(?:[-+]?(?:0|[1-9]\d*))$/);
|
||||
},
|
||||
isFloat: function (values, value) {
|
||||
return validations.matchRegexp(values, value, /^(?:[-+]?(?:\d+))?(?:\.\d*)?(?:[eE][\+\-]?(?:\d+))?$/);
|
||||
},
|
||||
isWords: function (values, value) {
|
||||
return validations.matchRegexp(values, value, /^[a-zA-Z\s]+$/);
|
||||
return validations.matchRegexp(values, value, /^[A-Z\s]+$/i);
|
||||
},
|
||||
isSpecialWords: function (values, value) {
|
||||
return validations.matchRegexp(values, value, /^[a-zA-Z\s\u00C0-\u017F]+$/);
|
||||
return validations.matchRegexp(values, value, /^[A-Z\s\u00C0-\u017F]+$/i);
|
||||
},
|
||||
isLength: function (values, value, length) {
|
||||
return !isExisty(value) || isEmpty(value) || value.length === length;
|
||||
|
|
|
|||
|
|
@ -1,25 +1,22 @@
|
|||
require('babel/register');
|
||||
|
||||
var path = require('path');
|
||||
var jsdom = require('jsdom').jsdom;
|
||||
var jasmine = require('jasmine-node');
|
||||
import path from 'path';
|
||||
import testrunner from 'nodeunit/lib/reporters/default.js';
|
||||
import {jsdom} from 'jsdom';
|
||||
|
||||
global.document = jsdom();
|
||||
global.window = document.defaultView;
|
||||
global.navigator = global.window.navigator;
|
||||
|
||||
var jasmineOptions = {
|
||||
specFolders: [path.resolve(__dirname, 'specs')],
|
||||
//onComplete: onComplete,
|
||||
isVerbose: true,
|
||||
showColors: true,
|
||||
teamcity: false,
|
||||
useRequireJs: false,
|
||||
regExpSpec: /spec\.jsx$/,
|
||||
junitreport: true,
|
||||
includeStackTrace: true,
|
||||
//coffee: options.coffee,
|
||||
//growl: options.growl
|
||||
};
|
||||
|
||||
jasmine.executeSpecsInFolder(jasmineOptions);
|
||||
testrunner.run(['tests'], {
|
||||
"error_prefix": "\u001B[31m",
|
||||
"error_suffix": "\u001B[39m",
|
||||
"ok_prefix": "\u001B[32m",
|
||||
"ok_suffix": "\u001B[39m",
|
||||
"bold_prefix": "\u001B[1m",
|
||||
"bold_suffix": "\u001B[22m",
|
||||
"assertion_prefix": "\u001B[35m",
|
||||
"assertion_suffix": "\u001B[39m"
|
||||
}, function(err) {
|
||||
if (err) {
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,519 @@
|
|||
import React from 'react';
|
||||
import TestUtils from 'react-addons-test-utils';
|
||||
|
||||
import Formsy from './..';
|
||||
import TestInput, { InputFactory } from './utils/TestInput';
|
||||
import immediate from './utils/immediate';
|
||||
|
||||
export default {
|
||||
|
||||
'should return passed and setValue() value when using getValue()': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(
|
||||
<Formsy.Form>
|
||||
<TestInput name="foo" value="foo"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
|
||||
const input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||
test.equal(input.value, 'foo');
|
||||
TestUtils.Simulate.change(input, {target: {value: 'foobar'}});
|
||||
test.equal(input.value, 'foobar');
|
||||
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should set back to pristine value when running reset': function (test) {
|
||||
|
||||
let reset = null;
|
||||
const Input = InputFactory({
|
||||
componentDidMount() {
|
||||
reset = this.resetValue;
|
||||
}
|
||||
});
|
||||
const form = TestUtils.renderIntoDocument(
|
||||
<Formsy.Form>
|
||||
<Input name="foo" value="foo"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
|
||||
const input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||
TestUtils.Simulate.change(input, {target: {value: 'foobar'}});
|
||||
reset();
|
||||
test.equal(input.value, 'foo');
|
||||
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should return error message passed when calling getErrorMessage()': function (test) {
|
||||
|
||||
let getErrorMessage = null;
|
||||
const Input = InputFactory({
|
||||
componentDidMount() {
|
||||
getErrorMessage = this.getErrorMessage;
|
||||
}
|
||||
});
|
||||
TestUtils.renderIntoDocument(
|
||||
<Formsy.Form>
|
||||
<Input name="foo" value="foo" validations="isEmail" validationError="Has to be email"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
|
||||
test.equal(getErrorMessage(), 'Has to be email');
|
||||
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should return true or false when calling isValid() depending on valid state': function (test) {
|
||||
|
||||
let isValid = null;
|
||||
const Input = InputFactory({
|
||||
componentDidMount() {
|
||||
isValid = this.isValid;
|
||||
}
|
||||
});
|
||||
const form = TestUtils.renderIntoDocument(
|
||||
<Formsy.Form url="/users">
|
||||
<Input name="foo" value="foo" validations="isEmail"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
|
||||
test.equal(isValid(), false);
|
||||
const input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||
TestUtils.Simulate.change(input, {target: {value: 'foo@foo.com'}});
|
||||
test.equal(isValid(), true);
|
||||
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should return true or false when calling isRequired() depending on passed required attribute': function (test) {
|
||||
|
||||
const isRequireds = [];
|
||||
const Input = InputFactory({
|
||||
componentDidMount() {
|
||||
isRequireds.push(this.isRequired);
|
||||
}
|
||||
});
|
||||
TestUtils.renderIntoDocument(
|
||||
<Formsy.Form url="/users">
|
||||
<Input name="foo" value=""/>
|
||||
<Input name="foo" value="" required/>
|
||||
<Input name="foo" value="foo" required="isLength:3"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
|
||||
test.equal(isRequireds[0](), false);
|
||||
test.equal(isRequireds[1](), true);
|
||||
test.equal(isRequireds[2](), true);
|
||||
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should return true or false when calling showRequired() depending on input being empty and required is passed, or not': function (test) {
|
||||
|
||||
const showRequireds = [];
|
||||
const Input = InputFactory({
|
||||
componentDidMount() {
|
||||
showRequireds.push(this.showRequired);
|
||||
}
|
||||
});
|
||||
TestUtils.renderIntoDocument(
|
||||
<Formsy.Form url="/users">
|
||||
<Input name="A" value="foo"/>
|
||||
<Input name="B" value="" required/>
|
||||
<Input name="C" value=""/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
|
||||
test.equal(showRequireds[0](), false);
|
||||
test.equal(showRequireds[1](), true);
|
||||
test.equal(showRequireds[2](), false);
|
||||
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should return true or false when calling isPristine() depending on input has been "touched" or not': function (test) {
|
||||
|
||||
let isPristine = null;
|
||||
const Input = InputFactory({
|
||||
componentDidMount() {
|
||||
isPristine = this.isPristine;
|
||||
}
|
||||
});
|
||||
const form = TestUtils.renderIntoDocument(
|
||||
<Formsy.Form url="/users">
|
||||
<Input name="A" value="foo"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
|
||||
test.equal(isPristine(), true);
|
||||
const input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||
TestUtils.Simulate.change(input, {target: {value: 'foo'}});
|
||||
test.equal(isPristine(), false);
|
||||
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should allow an undefined value to be updated to a value': function (test) {
|
||||
|
||||
const TestForm = React.createClass({
|
||||
getInitialState() {
|
||||
return {value: undefined};
|
||||
},
|
||||
changeValue() {
|
||||
this.setState({
|
||||
value: 'foo'
|
||||
});
|
||||
},
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form url="/users">
|
||||
<TestInput name="A" value={this.state.value}/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
|
||||
form.changeValue();
|
||||
const input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||
immediate(() => {
|
||||
test.equal(input.value, 'foo');
|
||||
test.done();
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
'should be able to test a values validity': function (test) {
|
||||
|
||||
const TestForm = React.createClass({
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form>
|
||||
<TestInput name="A" validations="isEmail"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
|
||||
const input = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(input.isValidValue('foo@bar.com'), true);
|
||||
test.equal(input.isValidValue('foo@bar'), false);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should be able to use an object as validations property': function (test) {
|
||||
|
||||
const TestForm = React.createClass({
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form>
|
||||
<TestInput name="A" validations={{
|
||||
isEmail: true
|
||||
}}/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
|
||||
const input = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(input.isValidValue('foo@bar.com'), true);
|
||||
test.equal(input.isValidValue('foo@bar'), false);
|
||||
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should be able to pass complex values to a validation rule': function (test) {
|
||||
|
||||
const TestForm = React.createClass({
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form>
|
||||
<TestInput name="A" validations={{
|
||||
matchRegexp: /foo/
|
||||
}} value="foo"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
const input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||
TestUtils.Simulate.change(input, {target: {value: 'bar'}});
|
||||
test.equal(inputComponent.isValid(), false);
|
||||
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should be able to run a function to validate': function (test) {
|
||||
|
||||
const TestForm = React.createClass({
|
||||
customValidationA(values, value) {
|
||||
return value === 'foo';
|
||||
},
|
||||
customValidationB(values, value) {
|
||||
return value === 'foo' && values.A === 'foo';
|
||||
},
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form>
|
||||
<TestInput name="A" validations={{
|
||||
custom: this.customValidationA
|
||||
}} value="foo"/>
|
||||
<TestInput name="B" validations={{
|
||||
custom: this.customValidationB
|
||||
}} value="foo"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
|
||||
const inputComponent = TestUtils.scryRenderedComponentsWithType(form, TestInput);
|
||||
test.equal(inputComponent[0].isValid(), true);
|
||||
test.equal(inputComponent[1].isValid(), true);
|
||||
const input = TestUtils.scryRenderedDOMComponentsWithTag(form, 'INPUT');
|
||||
TestUtils.Simulate.change(input[0], {target: {value: 'bar'}});
|
||||
test.equal(inputComponent[0].isValid(), false);
|
||||
test.equal(inputComponent[1].isValid(), false);
|
||||
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should override all error messages with error messages passed by form': function (test) {
|
||||
|
||||
const TestForm = React.createClass({
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form validationErrors={{A: 'bar'}}>
|
||||
<TestInput name="A" validations={{
|
||||
isEmail: true
|
||||
}} validationError="bar2" validationErrors={{isEmail: 'bar3'}} value="foo"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.getErrorMessage(), 'bar');
|
||||
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should override validation rules with required rules': function (test) {
|
||||
|
||||
const TestForm = React.createClass({
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form>
|
||||
<TestInput name="A"
|
||||
validations={{
|
||||
isEmail: true
|
||||
}}
|
||||
validationError="bar"
|
||||
validationErrors={{isEmail: 'bar2', isLength: 'bar3'}}
|
||||
value="f"
|
||||
required={{
|
||||
isLength: 1
|
||||
}}
|
||||
/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.getErrorMessage(), 'bar3');
|
||||
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should fall back to default error message when non exist in validationErrors map': function (test) {
|
||||
|
||||
const TestForm = React.createClass({
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form>
|
||||
<TestInput name="A"
|
||||
validations={{
|
||||
isEmail: true
|
||||
}}
|
||||
validationError="bar"
|
||||
validationErrors={{foo: 'bar'}}
|
||||
value="foo"
|
||||
/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.getErrorMessage(), 'bar');
|
||||
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should not be valid if it is required and required rule is true': function (test) {
|
||||
|
||||
const TestForm = React.createClass({
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form>
|
||||
<TestInput name="A"
|
||||
required
|
||||
/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), false);
|
||||
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should handle objects and arrays as values': function (test) {
|
||||
|
||||
const TestForm = React.createClass({
|
||||
getInitialState() {
|
||||
return {
|
||||
foo: {foo: 'bar'},
|
||||
bar: ['foo']
|
||||
};
|
||||
},
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form>
|
||||
<TestInput name="foo" value={this.state.foo}/>
|
||||
<TestInput name="bar" value={this.state.bar}/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
|
||||
form.setState({
|
||||
foo: {foo: 'foo'},
|
||||
bar: ['bar']
|
||||
});
|
||||
|
||||
const inputs = TestUtils.scryRenderedComponentsWithType(form, TestInput);
|
||||
test.deepEqual(inputs[0].getValue(), {foo: 'foo'});
|
||||
test.deepEqual(inputs[1].getValue(), ['bar']);
|
||||
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should handle isFormDisabled with dynamic inputs': function (test) {
|
||||
|
||||
const TestForm = React.createClass({
|
||||
getInitialState() {
|
||||
return {
|
||||
bool: true
|
||||
};
|
||||
},
|
||||
flip() {
|
||||
this.setState({
|
||||
bool: !this.state.bool
|
||||
});
|
||||
},
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form disabled={this.state.bool}>
|
||||
{this.state.bool ?
|
||||
<TestInput name="foo" /> :
|
||||
<TestInput name="bar" />
|
||||
}
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
|
||||
const input = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(input.isFormDisabled(), true);
|
||||
form.flip();
|
||||
test.equal(input.isFormDisabled(), false);
|
||||
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should allow for dot notation in name which maps to a deep object': function (test) {
|
||||
|
||||
const TestForm = React.createClass({
|
||||
onSubmit(model) {
|
||||
test.deepEqual(model, {foo: {bar: 'foo', test: 'test'}});
|
||||
},
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form onSubmit={this.onSubmit}>
|
||||
<TestInput name="foo.bar" value="foo"/>
|
||||
<TestInput name="foo.test" value="test"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
|
||||
test.expect(1);
|
||||
|
||||
const formEl = TestUtils.findRenderedDOMComponentWithTag(form, 'form');
|
||||
TestUtils.Simulate.submit(formEl);
|
||||
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should allow for application/x-www-form-urlencoded syntax and convert to object': function (test) {
|
||||
|
||||
const TestForm = React.createClass({
|
||||
onSubmit(model) {
|
||||
test.deepEqual(model, {foo: ['foo', 'bar']});
|
||||
},
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form onSubmit={this.onSubmit}>
|
||||
<TestInput name="foo[0]" value="foo"/>
|
||||
<TestInput name="foo[1]" value="bar"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
|
||||
test.expect(1);
|
||||
|
||||
const formEl = TestUtils.findRenderedDOMComponentWithTag(form, 'form');
|
||||
TestUtils.Simulate.submit(formEl);
|
||||
|
||||
test.done();
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -0,0 +1,706 @@
|
|||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import TestUtils from 'react-addons-test-utils';
|
||||
|
||||
import Formsy from './..';
|
||||
import TestInput from './utils/TestInput';
|
||||
import immediate from './utils/immediate';
|
||||
import sinon from 'sinon';
|
||||
|
||||
export default {
|
||||
|
||||
'Setting up a form': {
|
||||
|
||||
'should render a form into the document': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<Formsy.Form></Formsy.Form>);
|
||||
test.equal(ReactDOM.findDOMNode(form).tagName, 'FORM');
|
||||
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should set a class name if passed': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument( <Formsy.Form className="foo"></Formsy.Form>);
|
||||
test.equal(ReactDOM.findDOMNode(form).className, 'foo');
|
||||
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should allow for null/undefined children': function (test) {
|
||||
|
||||
let model = null;
|
||||
const TestForm = React.createClass({
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form onSubmit={(formModel) => (model = formModel)}>
|
||||
<h1>Test</h1>
|
||||
{ null }
|
||||
{ undefined }
|
||||
<TestInput name="name" value={ 'foo' } />
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
immediate(() => {
|
||||
TestUtils.Simulate.submit(ReactDOM.findDOMNode(form));
|
||||
test.deepEqual(model, {name: 'foo'});
|
||||
test.done();
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
'should allow for inputs being added dynamically': function (test) {
|
||||
|
||||
const inputs = [];
|
||||
let forceUpdate = null;
|
||||
let model = null;
|
||||
const TestForm = React.createClass({
|
||||
componentWillMount() {
|
||||
forceUpdate = this.forceUpdate.bind(this);
|
||||
},
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form onSubmit={(formModel) => (model = formModel)}>
|
||||
{inputs}
|
||||
</Formsy.Form>);
|
||||
}
|
||||
});
|
||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
|
||||
// Wait before adding the input
|
||||
setTimeout(() => {
|
||||
inputs.push(<TestInput name="test" value="" key={inputs.length}/>);
|
||||
|
||||
forceUpdate(() => {
|
||||
// Wait for next event loop, as that does the form
|
||||
immediate(() => {
|
||||
TestUtils.Simulate.submit(ReactDOM.findDOMNode(form));
|
||||
test.ok('test' in model);
|
||||
test.done();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
}, 10);
|
||||
|
||||
},
|
||||
|
||||
'should allow dynamically added inputs to update the form-model': function (test) {
|
||||
|
||||
const inputs = [];
|
||||
let forceUpdate = null;
|
||||
let model = null;
|
||||
const TestForm = React.createClass({
|
||||
componentWillMount() {
|
||||
forceUpdate = this.forceUpdate.bind(this);
|
||||
},
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form onSubmit={(formModel) => (model = formModel)}>
|
||||
{inputs}
|
||||
</Formsy.Form>);
|
||||
}
|
||||
});
|
||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
|
||||
// Wait before adding the input
|
||||
immediate(() => {
|
||||
inputs.push(<TestInput name="test" key={inputs.length}/>);
|
||||
|
||||
forceUpdate(() => {
|
||||
|
||||
// Wait for next event loop, as that does the form
|
||||
immediate(() => {
|
||||
TestUtils.Simulate.change(TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT'), {target: {value: 'foo'}});
|
||||
TestUtils.Simulate.submit(ReactDOM.findDOMNode(form));
|
||||
test.equal(model.test, 'foo');
|
||||
test.done();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
'should allow a dynamically updated input to update the form-model': function (test) {
|
||||
|
||||
let forceUpdate = null;
|
||||
let model = null;
|
||||
|
||||
const TestForm = React.createClass({
|
||||
componentWillMount() {
|
||||
forceUpdate = this.forceUpdate.bind(this);
|
||||
},
|
||||
render() {
|
||||
const input = <TestInput name="test" value={this.props.value} />;
|
||||
|
||||
return (
|
||||
<Formsy.Form onSubmit={(formModel) => (model = formModel)}>
|
||||
{input}
|
||||
</Formsy.Form>);
|
||||
}
|
||||
});
|
||||
let form = TestUtils.renderIntoDocument(<TestForm value="foo"/>);
|
||||
|
||||
// Wait before changing the input
|
||||
immediate(() => {
|
||||
form = TestUtils.renderIntoDocument(<TestForm value="bar"/>);
|
||||
|
||||
forceUpdate(() => {
|
||||
// Wait for next event loop, as that does the form
|
||||
immediate(() => {
|
||||
TestUtils.Simulate.submit(ReactDOM.findDOMNode(form));
|
||||
test.equal(model.test, 'bar');
|
||||
test.done();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
'validations': {
|
||||
|
||||
'should run when the input changes': function (test) {
|
||||
|
||||
const runRule = sinon.spy();
|
||||
const notRunRule = sinon.spy();
|
||||
|
||||
Formsy.addValidationRule('runRule', runRule);
|
||||
Formsy.addValidationRule('notRunRule', notRunRule);
|
||||
|
||||
const form = TestUtils.renderIntoDocument(
|
||||
<Formsy.Form>
|
||||
<TestInput name="one" validations="runRule" value="foo"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
|
||||
const input = TestUtils.findRenderedDOMComponentWithTag(form, 'input');
|
||||
TestUtils.Simulate.change(ReactDOM.findDOMNode(input), {target: {value: 'bar'}});
|
||||
test.equal(runRule.calledWith({one: 'bar'}, 'bar', true), true);
|
||||
test.equal(notRunRule.called, false);
|
||||
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should allow the validation to be changed': function (test) {
|
||||
|
||||
const ruleA = sinon.spy();
|
||||
const ruleB = sinon.spy();
|
||||
Formsy.addValidationRule('ruleA', ruleA);
|
||||
Formsy.addValidationRule('ruleB', ruleB);
|
||||
|
||||
class TestForm extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {rule: 'ruleA'};
|
||||
}
|
||||
changeRule() {
|
||||
this.setState({
|
||||
rule: 'ruleB'
|
||||
});
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form>
|
||||
<TestInput name="one" validations={this.state.rule} value="foo"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
form.changeRule();
|
||||
const input = TestUtils.findRenderedDOMComponentWithTag(form, 'input');
|
||||
TestUtils.Simulate.change(ReactDOM.findDOMNode(input), {target: {value: 'bar'}});
|
||||
test.equal(ruleB.calledWith({one: 'bar'}, 'bar', true), true);
|
||||
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should invalidate a form if dynamically inserted input is invalid': function (test) {
|
||||
|
||||
const isInValidSpy = sinon.spy();
|
||||
|
||||
class TestForm extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {showSecondInput: false};
|
||||
}
|
||||
addInput() {
|
||||
this.setState({
|
||||
showSecondInput: true
|
||||
});
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form ref="formsy" onInvalid={isInValidSpy}>
|
||||
<TestInput name="one" validations="isEmail" value="foo@bar.com"/>
|
||||
{
|
||||
this.state.showSecondInput ?
|
||||
<TestInput name="two" validations="isEmail" value="foo@bar"/>
|
||||
:
|
||||
null
|
||||
}
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
|
||||
test.equal(form.refs.formsy.state.isValid, true);
|
||||
form.addInput();
|
||||
|
||||
immediate(() => {
|
||||
test.equal(isInValidSpy.called, true);
|
||||
test.done();
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
'should validate a form when removing an invalid input': function (test) {
|
||||
|
||||
const isValidSpy = sinon.spy();
|
||||
|
||||
class TestForm extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {showSecondInput: true};
|
||||
}
|
||||
removeInput() {
|
||||
this.setState({
|
||||
showSecondInput: false
|
||||
});
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form ref="formsy" onValid={isValidSpy}>
|
||||
<TestInput name="one" validations="isEmail" value="foo@bar.com"/>
|
||||
{
|
||||
this.state.showSecondInput ?
|
||||
<TestInput name="two" validations="isEmail" value="foo@bar"/>
|
||||
:
|
||||
null
|
||||
}
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
|
||||
test.equal(form.refs.formsy.state.isValid, false);
|
||||
form.removeInput();
|
||||
|
||||
immediate(() => {
|
||||
test.equal(isValidSpy.called, true);
|
||||
test.done();
|
||||
});
|
||||
|
||||
|
||||
},
|
||||
|
||||
'runs multiple validations': function (test) {
|
||||
|
||||
const ruleA = sinon.spy();
|
||||
const ruleB = sinon.spy();
|
||||
Formsy.addValidationRule('ruleA', ruleA);
|
||||
Formsy.addValidationRule('ruleB', ruleB);
|
||||
|
||||
const form = TestUtils.renderIntoDocument(
|
||||
<Formsy.Form>
|
||||
<TestInput name="one" validations="ruleA,ruleB" value="foo" />
|
||||
</Formsy.Form>
|
||||
);
|
||||
|
||||
const input = TestUtils.findRenderedDOMComponentWithTag(form, 'input');
|
||||
TestUtils.Simulate.change(ReactDOM.findDOMNode(input), {target: {value: 'bar'}});
|
||||
test.equal(ruleA.calledWith({one: 'bar'}, 'bar', true), true);
|
||||
test.equal(ruleB.calledWith({one: 'bar'}, 'bar', true), true);
|
||||
test.done();
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
'should not trigger onChange when form is mounted': function (test) {
|
||||
|
||||
|
||||
const hasChanged = sinon.spy();
|
||||
const TestForm = React.createClass({
|
||||
render() {
|
||||
return <Formsy.Form onChange={hasChanged}></Formsy.Form>;
|
||||
}
|
||||
});
|
||||
TestUtils.renderIntoDocument(<TestForm/>);
|
||||
test.equal(hasChanged.called, false);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should trigger onChange when form element is changed': function (test) {
|
||||
|
||||
const hasChanged = sinon.spy();
|
||||
const form = TestUtils.renderIntoDocument(
|
||||
<Formsy.Form onChange={hasChanged}>
|
||||
<TestInput name="foo"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
TestUtils.Simulate.change(TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT'), {target: {value: 'bar'}});
|
||||
test.equal(hasChanged.called, true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should trigger onChange when new input is added to form': function (test) {
|
||||
|
||||
const hasChanged = sinon.spy();
|
||||
const TestForm = React.createClass({
|
||||
getInitialState() {
|
||||
return {
|
||||
showInput: false
|
||||
};
|
||||
},
|
||||
addInput() {
|
||||
this.setState({
|
||||
showInput: true
|
||||
})
|
||||
},
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form onChange={hasChanged}>
|
||||
{
|
||||
this.state.showInput ?
|
||||
<TestInput name="test"/>
|
||||
:
|
||||
null
|
||||
}
|
||||
</Formsy.Form>);
|
||||
}
|
||||
});
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
form.addInput();
|
||||
immediate(() => {
|
||||
test.equal(hasChanged.called, true);
|
||||
test.done();
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
'Update a form': {
|
||||
|
||||
'should allow elements to check if the form is disabled': function (test) {
|
||||
|
||||
const TestForm = React.createClass({
|
||||
getInitialState() { return { disabled: true }; },
|
||||
enableForm() { this.setState({ disabled: false }); },
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form disabled={this.state.disabled}>
|
||||
<TestInput name="foo"/>
|
||||
</Formsy.Form>);
|
||||
}
|
||||
});
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
const input = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(input.isFormDisabled(), true);
|
||||
|
||||
form.enableForm();
|
||||
immediate(() => {
|
||||
test.equal(input.isFormDisabled(), false);
|
||||
test.done();
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
'should be possible to pass error state of elements by changing an errors attribute': function (test) {
|
||||
|
||||
const TestForm = React.createClass({
|
||||
getInitialState() { return { validationErrors: { foo: 'bar' } }; },
|
||||
onChange(values) {
|
||||
this.setState(values.foo ? { validationErrors: {} } : { validationErrors: {foo: 'bar'} });
|
||||
},
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form onChange={this.onChange} validationErrors={this.state.validationErrors}>
|
||||
<TestInput name="foo"/>
|
||||
</Formsy.Form>);
|
||||
}
|
||||
});
|
||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
|
||||
// Wait for update
|
||||
immediate(() => {
|
||||
const input = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(input.getErrorMessage(), 'bar');
|
||||
input.setValue('gotValue');
|
||||
|
||||
// Wait for update
|
||||
immediate(() => {
|
||||
test.equal(input.getErrorMessage(), null);
|
||||
test.done();
|
||||
});
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
'should trigger an onValidSubmit when submitting a valid form': function (test) {
|
||||
|
||||
let isCalled = sinon.spy();
|
||||
const TestForm = React.createClass({
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form onValidSubmit={isCalled}>
|
||||
<TestInput name="foo" validations="isEmail" value="foo@bar.com"/>
|
||||
</Formsy.Form>);
|
||||
}
|
||||
});
|
||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
const FoundForm = TestUtils.findRenderedComponentWithType(form, TestForm);
|
||||
TestUtils.Simulate.submit(ReactDOM.findDOMNode(FoundForm));
|
||||
test.equal(isCalled.called,true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should trigger an onInvalidSubmit when submitting an invalid form': function (test) {
|
||||
|
||||
let isCalled = sinon.spy();
|
||||
const TestForm = React.createClass({
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form onInvalidSubmit={isCalled}>
|
||||
<TestInput name="foo" validations="isEmail" value="foo@bar"/>
|
||||
</Formsy.Form>);
|
||||
}
|
||||
});
|
||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
|
||||
const FoundForm = TestUtils.findRenderedComponentWithType(form, TestForm);
|
||||
TestUtils.Simulate.submit(ReactDOM.findDOMNode(FoundForm));
|
||||
test.equal(isCalled.called, true);
|
||||
|
||||
test.done();
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
'value === false': {
|
||||
|
||||
'should call onSubmit correctly': function (test) {
|
||||
|
||||
const onSubmit = sinon.spy();
|
||||
const TestForm = React.createClass({
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form onSubmit={onSubmit}>
|
||||
<TestInput name="foo" value={false} type="checkbox" />
|
||||
<button type="submit">Save</button>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
TestUtils.Simulate.submit(ReactDOM.findDOMNode(form));
|
||||
test.equal(onSubmit.calledWith({foo: false}), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should allow dynamic changes to false': function (test) {
|
||||
|
||||
const onSubmit = sinon.spy();
|
||||
const TestForm = React.createClass({
|
||||
getInitialState() {
|
||||
return {
|
||||
value: true
|
||||
};
|
||||
},
|
||||
changeValue() {
|
||||
this.setState({
|
||||
value: false
|
||||
});
|
||||
},
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form onSubmit={onSubmit}>
|
||||
<TestInput name="foo" value={this.state.value} type="checkbox" />
|
||||
<button type="submit">Save</button>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
form.changeValue();
|
||||
TestUtils.Simulate.submit(ReactDOM.findDOMNode(form));
|
||||
test.equal(onSubmit.calledWith({foo: false}), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should say the form is submitted': function (test) {
|
||||
|
||||
const TestForm = React.createClass({
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form>
|
||||
<TestInput name="foo" value={true} type="checkbox" />
|
||||
<button type="submit">Save</button>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
const input = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(input.isFormSubmitted(), false);
|
||||
TestUtils.Simulate.submit(ReactDOM.findDOMNode(form));
|
||||
test.equal(input.isFormSubmitted(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should be able to reset the form to its pristine state': function (test) {
|
||||
|
||||
const TestForm = React.createClass({
|
||||
getInitialState() {
|
||||
return {
|
||||
value: true
|
||||
};
|
||||
},
|
||||
changeValue() {
|
||||
this.setState({
|
||||
value: false
|
||||
});
|
||||
},
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form>
|
||||
<TestInput name="foo" value={this.state.value} type="checkbox" />
|
||||
<button type="submit">Save</button>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
const input = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
const formsyForm = TestUtils.findRenderedComponentWithType(form, Formsy.Form);
|
||||
test.equal(input.getValue(), true);
|
||||
form.changeValue();
|
||||
test.equal(input.getValue(), false);
|
||||
formsyForm.reset();
|
||||
test.equal(input.getValue(), true);
|
||||
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should be able to reset the form using custom data': function (test) {
|
||||
|
||||
const TestForm = React.createClass({
|
||||
getInitialState() {
|
||||
return {
|
||||
value: true
|
||||
};
|
||||
},
|
||||
changeValue() {
|
||||
this.setState({
|
||||
value: false
|
||||
});
|
||||
},
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form>
|
||||
<TestInput name="foo" value={this.state.value} type="checkbox" />
|
||||
<button type="submit">Save</button>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
const input = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
const formsyForm = TestUtils.findRenderedComponentWithType(form, Formsy.Form);
|
||||
|
||||
test.equal(input.getValue(), true);
|
||||
form.changeValue();
|
||||
test.equal(input.getValue(), false);
|
||||
formsyForm.reset({
|
||||
foo: 'bar'
|
||||
});
|
||||
test.equal(input.getValue(), 'bar');
|
||||
test.done();
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
'.isChanged()': {
|
||||
|
||||
'initially returns false': function (test) {
|
||||
|
||||
const hasOnChanged = sinon.spy();
|
||||
const form = TestUtils.renderIntoDocument(
|
||||
<Formsy.Form onChange={hasOnChanged}>
|
||||
<TestInput name="one" value="foo" />
|
||||
</Formsy.Form>
|
||||
);
|
||||
test.equal(form.isChanged(), false);
|
||||
test.equal(hasOnChanged.called, false);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'returns true when changed': function (test) {
|
||||
|
||||
const hasOnChanged = sinon.spy();
|
||||
const form = TestUtils.renderIntoDocument(
|
||||
<Formsy.Form onChange={hasOnChanged}>
|
||||
<TestInput name="one" value="foo" />
|
||||
</Formsy.Form>
|
||||
);
|
||||
const input = TestUtils.findRenderedDOMComponentWithTag(form, 'input');
|
||||
TestUtils.Simulate.change(ReactDOM.findDOMNode(input), {target: {value: 'bar'}});
|
||||
test.equal(form.isChanged(), true);
|
||||
test.equal(hasOnChanged.calledWith({one: 'bar'}), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'returns false if changes are undone': function (test) {
|
||||
|
||||
const hasOnChanged = sinon.spy();
|
||||
const form = TestUtils.renderIntoDocument(
|
||||
<Formsy.Form onChange={hasOnChanged}>
|
||||
<TestInput name="one" value="foo" />
|
||||
</Formsy.Form>
|
||||
);
|
||||
const input = TestUtils.findRenderedDOMComponentWithTag(form, 'input');
|
||||
TestUtils.Simulate.change(ReactDOM.findDOMNode(input), {target: {value: 'bar'}});
|
||||
test.equal(hasOnChanged.calledWith({one: 'bar'}, true), true);
|
||||
|
||||
TestUtils.Simulate.change(ReactDOM.findDOMNode(input), {target: {value: 'foo'}});
|
||||
test.equal(form.isChanged(), false);
|
||||
test.equal(hasOnChanged.calledWith({one: 'foo'}, false), true);
|
||||
test.done();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
import React from 'react';
|
||||
import TestUtils from 'react-addons-test-utils';
|
||||
import immediate from './utils/immediate';
|
||||
|
||||
import Formsy from './..';
|
||||
import { InputFactory } from './utils/TestInput';
|
||||
|
||||
const TestInput = InputFactory({
|
||||
render() {
|
||||
return <input value={this.getValue()} readOnly/>;
|
||||
}
|
||||
});
|
||||
|
||||
const TestForm = React.createClass({
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form>
|
||||
<TestInput name="foo" validations="equals:foo" value={this.props.inputValue}/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default {
|
||||
|
||||
'should pass when the value is equal': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue="foo"/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should fail when the value is not equal': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue="fo"/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), false);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with an empty string': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={''}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with an undefined': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={undefined}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with a null': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={null}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should fail with a number': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={42}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), false);
|
||||
test.done();
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
import React from 'react';
|
||||
import TestUtils from 'react-addons-test-utils';
|
||||
|
||||
import Formsy from './..';
|
||||
import { InputFactory } from './utils/TestInput';
|
||||
|
||||
const TestInput = InputFactory({
|
||||
render() {
|
||||
return <input value={this.getValue()} readOnly/>;
|
||||
}
|
||||
});
|
||||
|
||||
const TestForm = React.createClass({
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form>
|
||||
<TestInput name="foo" validations="isAlpha" value={this.props.inputValue}/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default {
|
||||
|
||||
'should pass with a default value': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with a string is only latin letters': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue="myValue"/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should fail with a string with numbers': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue="myValue42"/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), false);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with an undefined': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={undefined}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with a null': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={null}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with an empty string': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={''}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should fail with a number': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={42}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), false);
|
||||
test.done();
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
import React from 'react';
|
||||
import TestUtils from 'react-addons-test-utils';
|
||||
|
||||
import Formsy from './..';
|
||||
import { InputFactory } from './utils/TestInput';
|
||||
|
||||
const TestInput = InputFactory({
|
||||
render() {
|
||||
return <input value={this.getValue()} readOnly/>;
|
||||
}
|
||||
});
|
||||
|
||||
const TestForm = React.createClass({
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form>
|
||||
<TestInput name="foo" validations="isAlphanumeric" value={this.props.inputValue}/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default {
|
||||
|
||||
'should pass with a default value': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with a string is only latin letters': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue="myValue"/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should fail with a string with numbers': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue="myValue42"/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with an undefined': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={undefined}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with a null': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={null}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with an empty string': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={''}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with a number': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={42}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should fail with a non alpha and number symbols': function (test) {
|
||||
|
||||
const value = '!@#$%^&*()';
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={value}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), false);
|
||||
test.done();
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
import React from 'react';
|
||||
import TestUtils from 'react-addons-test-utils';
|
||||
|
||||
import Formsy from './..';
|
||||
import { InputFactory } from './utils/TestInput';
|
||||
|
||||
const TestInput = InputFactory({
|
||||
render() {
|
||||
return <input value={this.getValue()} readOnly/>;
|
||||
}
|
||||
});
|
||||
|
||||
const TestForm = React.createClass({
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form>
|
||||
<TestInput name="foo" validations="isEmail" value={this.props.inputValue}/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default {
|
||||
|
||||
'should pass with a default value': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should fail with "foo"': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue="foo"/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), false);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with "foo@foo.com"': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue="foo@foo.com"/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with an undefined': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={undefined}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with a null': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={null}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with an empty string': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={''}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should fail with a number': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={42}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), false);
|
||||
test.done();
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
import React from 'react';
|
||||
import TestUtils from 'react-addons-test-utils';
|
||||
|
||||
import Formsy from './..';
|
||||
import { InputFactory } from './utils/TestInput';
|
||||
|
||||
const TestInput = InputFactory({
|
||||
render() {
|
||||
return <input value={this.getValue()} readOnly/>;
|
||||
}
|
||||
});
|
||||
|
||||
const TestForm = React.createClass({
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form>
|
||||
<TestInput name="foo" validations="isEmptyString" value={this.props.inputValue}/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default {
|
||||
|
||||
'should pass with a default value': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), false);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should fail with non-empty string': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue="abc"/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), false);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with an empty string': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue=""/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should fail with undefined': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={undefined}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), false);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should fail with null': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={null}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), false);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should fail with a number': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={42}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), false);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should fail with a zero': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={0}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), false);
|
||||
test.done();
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
import React from 'react';
|
||||
import TestUtils from 'react-addons-test-utils';
|
||||
|
||||
import Formsy from './..';
|
||||
import { InputFactory } from './utils/TestInput';
|
||||
|
||||
const TestInput = InputFactory({
|
||||
render() {
|
||||
return <input value={this.getValue()} readOnly/>;
|
||||
}
|
||||
});
|
||||
|
||||
const TestForm = React.createClass({
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form>
|
||||
<TestInput name="foo" validations="isExisty" value={this.props.inputValue}/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default {
|
||||
|
||||
'should pass with a default value': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), false);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with a string': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue="abc"/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with an empty string': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue=""/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should fail with undefined': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={undefined}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), false);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should fail with null': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={null}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), false);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with a number': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={42}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with a zero': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={0}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
import React from 'react';
|
||||
import TestUtils from 'react-addons-test-utils';
|
||||
|
||||
import Formsy from './..';
|
||||
import { InputFactory } from './utils/TestInput';
|
||||
|
||||
const TestInput = InputFactory({
|
||||
render() {
|
||||
return <input value={this.getValue()} readOnly/>;
|
||||
}
|
||||
});
|
||||
|
||||
const TestForm = React.createClass({
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form>
|
||||
<TestInput name="foo" validations="isFloat" value={this.props.inputValue}/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default {
|
||||
|
||||
'should pass with a default value': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with an empty string': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue=""/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should fail with a string': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue="abc"/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), false);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with a number as string': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue="+42"/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should fail string with digits': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue="42 is an answer"/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), false);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with an int': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={42}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with a float': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={Math.PI}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with a float in science notation': function (test) {
|
||||
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue="-1e3"/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with undefined': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={undefined}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with null': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={null}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with a zero': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={0}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
import React from 'react';
|
||||
import TestUtils from 'react-addons-test-utils';
|
||||
|
||||
import Formsy from './..';
|
||||
import { InputFactory } from './utils/TestInput';
|
||||
|
||||
const TestInput = InputFactory({
|
||||
render() {
|
||||
return <input value={this.getValue()} readOnly/>;
|
||||
}
|
||||
});
|
||||
|
||||
const TestForm = React.createClass({
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form>
|
||||
<TestInput name="foo" validations="isInt" value={this.props.inputValue}/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default {
|
||||
|
||||
'should pass with a default value': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with an empty string': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue=""/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should fail with a string': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue="abc"/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), false);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with a number as string': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue="+42"/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should fail string with digits': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue="42 is an answer"/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), false);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with an int': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={42}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should fail with a float': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={Math.PI}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), false);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should fail with a float in science notation': function (test) {
|
||||
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue="-1e3"/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), false);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with undefined': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={undefined}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with null': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={null}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with a zero': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={0}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -0,0 +1,177 @@
|
|||
import React from 'react';
|
||||
import TestUtils from 'react-addons-test-utils';
|
||||
|
||||
import Formsy from './..';
|
||||
import { InputFactory } from './utils/TestInput';
|
||||
|
||||
const TestInput = InputFactory({
|
||||
render() {
|
||||
return <input value={this.getValue()} readOnly/>;
|
||||
}
|
||||
});
|
||||
|
||||
const TestForm = React.createClass({
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form>
|
||||
<TestInput name="foo" validations={this.props.rule} value={this.props.inputValue}/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default {
|
||||
|
||||
'isLength:3': {
|
||||
|
||||
'should pass with a default value': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm rule="isLength:3"/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should fail with a string too small': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm rule="isLength:3" inputValue="hi"/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), false);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should fail with a string too long': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm rule="isLength:3" inputValue="hi ho happ"/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), false);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with matching length': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm rule="isLength:3" inputValue="foo"/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with undefined': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm rule="isLength:3" inputValue={undefined}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with null': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm rule="isLength:3" inputValue={null}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with empty string': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm rule="isLength:3" inputValue=""/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should fail with a number': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm rule="isLength:3" inputValue={123}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), false);
|
||||
test.done();
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
'isLength:0': {
|
||||
|
||||
'should pass with a default value': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm rule="isLength:0"/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should fail with a string too small': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm rule="isLength:0" inputValue="hi"/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), false);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should fail with a string too long': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm rule="isLength:0" inputValue="hi ho happ"/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), false);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with matching length': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm rule="isLength:0" inputValue=""/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with undefined': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm rule="isLength:0" inputValue={undefined}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with null': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm rule="isLength:0" inputValue={null}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with empty string': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm rule="isLength:0" inputValue=""/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should fail with a number': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm rule="isLength:0" inputValue={123}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), false);
|
||||
test.done();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
import React from 'react';
|
||||
import TestUtils from 'react-addons-test-utils';
|
||||
|
||||
import Formsy from './..';
|
||||
import { InputFactory } from './utils/TestInput';
|
||||
|
||||
const TestInput = InputFactory({
|
||||
render() {
|
||||
return <input value={this.getValue()} readOnly/>;
|
||||
}
|
||||
});
|
||||
|
||||
const TestForm = React.createClass({
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form>
|
||||
<TestInput name="foo" validations="isNumeric" value={this.props.inputValue}/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default {
|
||||
|
||||
'should pass with a default value': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with an empty string': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue=""/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should fail with an unempty string': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue="foo"/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), false);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with a number as string': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue="+42"/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should fail with a number as string with not digits': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue="42 is an answer"/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), false);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with an int': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={42}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with a float': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={Math.PI}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should fail with a float in science notation': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue="-1e3"/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), false);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with an undefined': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={undefined}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with a null': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={null}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with a zero': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={0}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
import React from 'react';
|
||||
import TestUtils from 'react-addons-test-utils';
|
||||
|
||||
import Formsy from './..';
|
||||
import { InputFactory } from './utils/TestInput';
|
||||
|
||||
const TestInput = InputFactory({
|
||||
render() {
|
||||
return <input value={this.getValue()} readOnly/>;
|
||||
}
|
||||
});
|
||||
|
||||
const TestForm = React.createClass({
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form>
|
||||
<TestInput name="foo" validations="isUrl" value={this.props.inputValue}/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default {
|
||||
|
||||
'should pass with default value': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should fail with "foo"': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue="foo"/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), false);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with "https://www.google.com/"': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue="https://www.google.com/"/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with an undefined': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={undefined}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with a null': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={null}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should fail with a number': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={42}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), false);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with an empty string': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue=""/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
import React from 'react';
|
||||
import TestUtils from 'react-addons-test-utils';
|
||||
|
||||
import Formsy from './..';
|
||||
import { InputFactory } from './utils/TestInput';
|
||||
|
||||
const TestInput = InputFactory({
|
||||
render() {
|
||||
return <input value={this.getValue()} readOnly/>;
|
||||
}
|
||||
});
|
||||
|
||||
const TestForm = React.createClass({
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form>
|
||||
<TestInput name="foo" validations="isWords" value={this.props.inputValue}/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default {
|
||||
|
||||
'should pass with a default value': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with a 1 word': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue="sup"/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with 2 words': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue="sup dude"/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should fail with a string with numbers': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue="sup 42"/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), false);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with an undefined': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={undefined}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with a null': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={null}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should fail with a number': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={42}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), false);
|
||||
test.done();
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
import React from 'react';
|
||||
import TestUtils from 'react-addons-test-utils';
|
||||
|
||||
import Formsy from './..';
|
||||
import { InputFactory } from './utils/TestInput';
|
||||
|
||||
const TestInput = InputFactory({
|
||||
render() {
|
||||
return <input value={this.getValue()} readOnly/>;
|
||||
}
|
||||
});
|
||||
|
||||
const TestForm = React.createClass({
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form>
|
||||
<TestInput name="foo" validations="maxLength:3" value={this.props.inputValue}/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default {
|
||||
|
||||
'should pass with a default value': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass when a string\'s length is smaller': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue="hi"/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass when a string\'s length is equal': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue="bar"/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should fail when a string\'s length is bigger': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue="foobar"/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), false);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with empty string': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue=""/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with an undefined': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={undefined}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with a null': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={null}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should fail with a number': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm inputValue={42}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), false);
|
||||
test.done();
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -0,0 +1,141 @@
|
|||
import React from 'react';
|
||||
import TestUtils from 'react-addons-test-utils';
|
||||
|
||||
import Formsy from './..';
|
||||
import { InputFactory } from './utils/TestInput';
|
||||
|
||||
const TestInput = InputFactory({
|
||||
render() {
|
||||
return <input value={this.getValue()} readOnly/>;
|
||||
}
|
||||
});
|
||||
|
||||
const TestForm = React.createClass({
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form>
|
||||
<TestInput name="foo" validations={this.props.rule} value={this.props.inputValue}/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default {
|
||||
|
||||
'minLength:3': {
|
||||
|
||||
'should pass with a default value': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm rule="minLength:3"/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass when a string\'s length is bigger': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm rule="minLength:3" inputValue="myValue"/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with empty string': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm rule="minLength:3" inputValue=""/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with an undefined': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm rule="minLength:3" inputValue={undefined}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with a null': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm rule="minLength:3" inputValue={null}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should fail with a number': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm rule="minLength:3" inputValue={42}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), false);
|
||||
test.done();
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
'minLength:0': {
|
||||
|
||||
'should pass with a default value': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm rule="minLength:0"/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass when a string\'s length is bigger': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm rule="minLength:0" inputValue="myValue"/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with empty string': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm rule="minLength:0" inputValue=""/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with an undefined': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm rule="minLength:0" inputValue={undefined}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should pass with a null': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm rule="minLength:0" inputValue={null}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should fail with a number': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm rule="minLength:0" inputValue={42}/>);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
test.equal(inputComponent.isValid(), false);
|
||||
test.done();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
import utils from './../src/utils.js';
|
||||
|
||||
export default {
|
||||
|
||||
'should check equality of objects and arrays': function (test) {
|
||||
|
||||
const objA = { foo: 'bar' };
|
||||
const objB = { foo: 'bar' };
|
||||
const objC = [{ foo: ['bar'] }];
|
||||
const objD = [{ foo: ['bar'] }];
|
||||
const objE = undefined;
|
||||
const objF = undefined;
|
||||
const objG = null;
|
||||
const objH = null;
|
||||
|
||||
test.equal(utils.isSame(objA, objB), true);
|
||||
test.equal(utils.isSame(objC, objD), true);
|
||||
test.equal(utils.isSame(objA, objD), false);
|
||||
|
||||
test.equal(utils.isSame(objE, objF), true);
|
||||
test.equal(utils.isSame(objA, objF), false);
|
||||
test.equal(utils.isSame(objE, objA), false);
|
||||
|
||||
test.equal(utils.isSame(objG, objH), true);
|
||||
test.equal(utils.isSame(objA, objH), false);
|
||||
test.equal(utils.isSame(objG, objA), false);
|
||||
|
||||
test.done();
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -0,0 +1,201 @@
|
|||
import React from 'react';
|
||||
import TestUtils from 'react-addons-test-utils';
|
||||
|
||||
import Formsy from './..';
|
||||
import TestInput, {InputFactory} from './utils/TestInput';
|
||||
import immediate from './utils/immediate';
|
||||
import sinon from 'sinon';
|
||||
|
||||
export default {
|
||||
|
||||
'should reset only changed form element when external error is passed': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(
|
||||
<Formsy.Form onSubmit={(model, reset, invalidate) => invalidate({ foo: 'bar', bar: 'foo' })}>
|
||||
<TestInput name="foo"/>
|
||||
<TestInput name="bar"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
|
||||
const input = TestUtils.scryRenderedDOMComponentsWithTag(form, 'INPUT')[0];
|
||||
const inputComponents = TestUtils.scryRenderedComponentsWithType(form, TestInput);
|
||||
|
||||
form.submit();
|
||||
test.equal(inputComponents[0].isValid(), false);
|
||||
test.equal(inputComponents[1].isValid(), false);
|
||||
|
||||
TestUtils.Simulate.change(input, {target: {value: 'bar'}});
|
||||
immediate(() => {
|
||||
test.equal(inputComponents[0].isValid(), true);
|
||||
test.equal(inputComponents[1].isValid(), false);
|
||||
test.done();
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
'should let normal validation take over when component with external error is changed': function (test) {
|
||||
|
||||
const form = TestUtils.renderIntoDocument(
|
||||
<Formsy.Form onSubmit={(model, reset, invalidate) => invalidate({ foo: 'bar' })}>
|
||||
<TestInput name="foo" validations="isEmail"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
|
||||
const input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
|
||||
form.submit();
|
||||
test.equal(inputComponent.isValid(), false);
|
||||
|
||||
TestUtils.Simulate.change(input, {target: {value: 'bar'}});
|
||||
immediate(() => {
|
||||
test.equal(inputComponent.getValue(), 'bar');
|
||||
test.equal(inputComponent.isValid(), false);
|
||||
test.done();
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
'should trigger an onValid handler, if passed, when form is valid': function (test) {
|
||||
|
||||
const onValid = sinon.spy();
|
||||
const onInvalid = sinon.spy();
|
||||
|
||||
TestUtils.renderIntoDocument(
|
||||
<Formsy.Form onValid={onValid} onInvalid={onInvalid}>
|
||||
<TestInput name="foo" value="bar" required/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
|
||||
test.equal(onValid.called, true);
|
||||
test.equal(onInvalid.called, false);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should trigger an onInvalid handler, if passed, when form is invalid': function (test) {
|
||||
|
||||
const onValid = sinon.spy();
|
||||
const onInvalid = sinon.spy();
|
||||
|
||||
TestUtils.renderIntoDocument(
|
||||
<Formsy.Form onValid={onValid} onInvalid={onInvalid}>
|
||||
<TestInput name="foo" required />
|
||||
</Formsy.Form>
|
||||
);
|
||||
|
||||
test.equal(onValid.called, false);
|
||||
test.equal(onInvalid.called, true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should be able to use provided validate function': function (test) {
|
||||
|
||||
let isValid = false;
|
||||
const CustomInput = InputFactory({
|
||||
componentDidMount() {
|
||||
isValid = this.isValid();
|
||||
}
|
||||
});
|
||||
const form = TestUtils.renderIntoDocument(
|
||||
<Formsy.Form>
|
||||
<CustomInput name="foo" value="foo" required/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
|
||||
const input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||
test.equal(isValid, true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should provide invalidate callback on onValiSubmit': function (test) {
|
||||
|
||||
const TestForm = React.createClass({
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form onValidSubmit={(model, reset, invalidate) => invalidate({ foo: 'bar' })}>
|
||||
<TestInput name="foo" value="foo"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
|
||||
const formEl = TestUtils.findRenderedDOMComponentWithTag(form, 'form');
|
||||
const input = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
TestUtils.Simulate.submit(formEl);
|
||||
test.equal(input.isValid(), false);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should provide invalidate callback on onInvalidSubmit': function (test) {
|
||||
|
||||
const TestForm = React.createClass({
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form onInvalidSubmit={(model, reset, invalidate) => invalidate({ foo: 'bar' })}>
|
||||
<TestInput name="foo" value="foo" validations="isEmail"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
const formEl = TestUtils.findRenderedDOMComponentWithTag(form, 'form');
|
||||
const input = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
TestUtils.Simulate.submit(formEl);
|
||||
test.equal(input.getErrorMessage(), 'bar');
|
||||
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should not invalidate inputs on external errors with preventExternalInvalidation prop': function (test) {
|
||||
|
||||
const TestForm = React.createClass({
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form
|
||||
preventExternalInvalidation
|
||||
onSubmit={(model, reset, invalidate) => invalidate({ foo: 'bar' })}>
|
||||
<TestInput name="foo" value="foo"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
const formEl = TestUtils.findRenderedDOMComponentWithTag(form, 'form');
|
||||
const input = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
TestUtils.Simulate.submit(formEl);
|
||||
test.equal(input.isValid(), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should invalidate inputs on external errors without preventExternalInvalidation prop': function (test) {
|
||||
|
||||
const TestForm = React.createClass({
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form onSubmit={(model, reset, invalidate) => invalidate({ foo: 'bar' })}>
|
||||
<TestInput name="foo" value="foo"/>
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||
const formEl = TestUtils.findRenderedDOMComponentWithTag(form, 'form');
|
||||
const input = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||
TestUtils.Simulate.submit(formEl);
|
||||
test.equal(input.isValid(), false);
|
||||
test.done();
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
import React from 'react';
|
||||
import Formsy from './../..';
|
||||
import assign from 'react/lib/Object.assign';
|
||||
|
||||
const defaultProps = {
|
||||
mixins: [Formsy.Mixin],
|
||||
getDefaultProps() {
|
||||
return { type: 'text' };
|
||||
},
|
||||
updateValue(event) {
|
||||
this.setValue(event.target[this.props.type === 'checkbox' ? 'checked' : 'value']);
|
||||
},
|
||||
render() {
|
||||
return <input type={this.props.type} value={this.getValue()} onChange={this.updateValue}/>;
|
||||
}
|
||||
};
|
||||
|
||||
export function InputFactory(props) {
|
||||
return React.createClass(assign(defaultProps, props));
|
||||
}
|
||||
|
||||
export default React.createClass(defaultProps);
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
export default function (fn) {
|
||||
setTimeout(fn, 0);
|
||||
}
|
||||
Loading…
Reference in New Issue