Compare commits
No commits in common. "master" and "react-0.14" have entirely different histories.
master
...
react-0.14
|
|
@ -1,2 +1,4 @@
|
||||||
|
.DS_Store
|
||||||
|
build
|
||||||
node_modules
|
node_modules
|
||||||
lib
|
lib
|
||||||
|
|
|
||||||
11
.npmignore
11
.npmignore
|
|
@ -1,8 +1,3 @@
|
||||||
.babelrc
|
build/
|
||||||
.editorconfig
|
bower.json
|
||||||
.travis.yml
|
Gulpfile.js
|
||||||
testrunner.js
|
|
||||||
webpack.production.config.js
|
|
||||||
examples/
|
|
||||||
release/
|
|
||||||
tests/
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
language: node_js
|
language: node_js
|
||||||
sudo: false
|
|
||||||
node_js:
|
node_js:
|
||||||
- '4.1'
|
- '0.12'
|
||||||
|
- '0.10'
|
||||||
|
|
|
||||||
227
API.md
227
API.md
|
|
@ -1,5 +1,6 @@
|
||||||
# API
|
# API
|
||||||
|
|
||||||
|
- [Formsy.defaults - DEPRECATED](#formsydefaults)
|
||||||
- [Formsy.Form](#formsyform)
|
- [Formsy.Form](#formsyform)
|
||||||
- [className](#classname)
|
- [className](#classname)
|
||||||
- [mapping](#mapping)
|
- [mapping](#mapping)
|
||||||
|
|
@ -11,21 +12,19 @@
|
||||||
- [onInvalidSubmit()](#oninvalidsubmit)
|
- [onInvalidSubmit()](#oninvalidsubmit)
|
||||||
- [onChange()](#onchange)
|
- [onChange()](#onchange)
|
||||||
- [reset()](#resetform)
|
- [reset()](#resetform)
|
||||||
- [getModel()](#getmodel)
|
|
||||||
- [updateInputsWithError()](#updateinputswitherrorerrors)
|
|
||||||
- [preventExternalInvalidation](#preventexternalinvalidation)
|
- [preventExternalInvalidation](#preventexternalinvalidation)
|
||||||
- [Formsy.Mixin](#formsymixin)
|
- [Formsy.Mixin](#formsymixin)
|
||||||
- [name](#name)
|
- [name](#name)
|
||||||
- [value](#value)
|
- [value](#value)
|
||||||
- [validations](#validations)
|
- [validations](#validations)
|
||||||
- [validationError](#validationerror)
|
- [validationError](#validationerror)
|
||||||
- [validationErrors](#validationerrors-1)
|
- [validationErrors](#validationerrors)
|
||||||
- [required](#required)
|
- [required](#required)
|
||||||
- [getValue()](#getvalue)
|
- [getValue()](#getvalue)
|
||||||
- [setValue()](#setvalue)
|
- [setValue()](#setvalue)
|
||||||
|
- [hasValue() - DEPRECATED](#hasvalue)
|
||||||
- [resetValue()](#resetvalue)
|
- [resetValue()](#resetvalue)
|
||||||
- [getErrorMessage()](#geterrormessage)
|
- [getErrorMessage()](#geterrormessage)
|
||||||
- [getErrorMessages()](#geterrormessages)
|
|
||||||
- [isValid()](#isvalid)
|
- [isValid()](#isvalid)
|
||||||
- [isValidValue()](#isvalidvalue)
|
- [isValidValue()](#isvalidvalue)
|
||||||
- [isRequired()](#isrequired)
|
- [isRequired()](#isrequired)
|
||||||
|
|
@ -37,21 +36,22 @@
|
||||||
- [validate](#validate)
|
- [validate](#validate)
|
||||||
- [formNoValidate](#formnovalidate)
|
- [formNoValidate](#formnovalidate)
|
||||||
- [Formsy.HOC](#formsyhoc)
|
- [Formsy.HOC](#formsyhoc)
|
||||||
- [innerRef](#innerRef)
|
|
||||||
- [Formsy.Decorator](#formsydecorator)
|
- [Formsy.Decorator](#formsydecorator)
|
||||||
- [Formsy.addValidationRule](#formsyaddvalidationrule)
|
- [Formsy.addValidationRule](#formsyaddvalidationrule)
|
||||||
- [Validators](#validators)
|
- [Validators](#validators)
|
||||||
|
|
||||||
|
### <a name="formsydefaults">Formsy.defaults(options) - DEPRECATED</a>
|
||||||
|
|
||||||
### <a name="formsyform">Formsy.Form</a>
|
### <a name="formsyform">Formsy.Form</a>
|
||||||
|
|
||||||
#### <a name="classname">className</a>
|
#### <a name="classname">className</a>
|
||||||
```jsx
|
```html
|
||||||
<Formsy.Form className="my-class"></Formsy.Form>
|
<Formsy.Form className="my-class"></Formsy.Form>
|
||||||
```
|
```
|
||||||
Sets a class name on the form itself.
|
Sets a class name on the form itself.
|
||||||
|
|
||||||
#### <a name="mapping">mapping</a>
|
#### <a name="mapping">mapping</a>
|
||||||
```jsx
|
```javascript
|
||||||
var MyForm = React.createClass({
|
var MyForm = React.createClass({
|
||||||
mapInputs: function (inputs) {
|
mapInputs: function (inputs) {
|
||||||
return {
|
return {
|
||||||
|
|
@ -77,7 +77,7 @@ Use mapping to change the data structure of your input elements. This structure
|
||||||
#### <a name="validationerrors">validationErrors</a>
|
#### <a name="validationerrors">validationErrors</a>
|
||||||
You can manually pass down errors to your form. In combination with `onChange` you are able to validate using an external validator.
|
You can manually pass down errors to your form. In combination with `onChange` you are able to validate using an external validator.
|
||||||
|
|
||||||
```jsx
|
```js
|
||||||
var Form = React.createClass({
|
var Form = React.createClass({
|
||||||
getInitialState: function () {
|
getInitialState: function () {
|
||||||
return {
|
return {
|
||||||
|
|
@ -108,45 +108,45 @@ var Form = React.createClass({
|
||||||
```
|
```
|
||||||
|
|
||||||
#### <a name="onsubmit">onSubmit(data, resetForm, invalidateForm)</a>
|
#### <a name="onsubmit">onSubmit(data, resetForm, invalidateForm)</a>
|
||||||
```jsx
|
```html
|
||||||
<Formsy.Form onSubmit={this.showFormLoader}></Formsy.Form>
|
<Formsy.Form onSubmit={this.showFormLoader}></Formsy.Form>
|
||||||
```
|
```
|
||||||
Takes a function to run when the submit button has been clicked.
|
Takes a function to run when the submit button has been clicked.
|
||||||
|
|
||||||
The first argument is the data of the form. The second argument will reset the form. The third argument will invalidate the form by taking an object that maps to inputs. This is useful for server side validation. E.g. `{email: "This email is taken"}`. Resetting or invalidating the form will cause **setState** to run on the form element component.
|
The first argument is the data of the form. The second argument will reset the form. The third argument will invalidate the form by taking an object that maps to inputs. E.g. `{email: "This email is taken"}`. Resetting or invalidating the form will cause **setState** to run on the form element component.
|
||||||
|
|
||||||
#### <a name="onvalid">onValid()</a>
|
#### <a name="onvalid">onValid()</a>
|
||||||
```jsx
|
```html
|
||||||
<Formsy.Form onValid={this.enableSubmitButton}></Formsy.Form>
|
<Formsy.Form onValid={this.enableSubmitButton}></Formsy.Form>
|
||||||
```
|
```
|
||||||
Whenever the form becomes valid the "onValid" handler is called. Use it to change state of buttons or whatever your heart desires.
|
Whenever the form becomes valid the "onValid" handler is called. Use it to change state of buttons or whatever your heart desires.
|
||||||
|
|
||||||
#### <a name="oninvalid">onInvalid()</a>
|
#### <a name="oninvalid">onInvalid()</a>
|
||||||
```jsx
|
```html
|
||||||
<Formsy.Form onInvalid={this.disableSubmitButton}></Formsy.Form>
|
<Formsy.Form onInvalid={this.disableSubmitButton}></Formsy.Form>
|
||||||
```
|
```
|
||||||
Whenever the form becomes invalid the "onInvalid" handler is called. Use it to for example revert "onValid" state.
|
Whenever the form becomes invalid the "onInvalid" handler is called. Use it to for example revert "onValid" state.
|
||||||
|
|
||||||
#### <a name="onvalidsubmit">onValidSubmit(model, resetForm, invalidateForm)</a>
|
#### <a name="onvalidsubmit">onValidSubmit(model, resetForm, invalidateForm)</a>
|
||||||
```jsx
|
```html
|
||||||
<Formsy.Form onValidSubmit={this.sendToServer}></Formsy.Form>
|
<Formsy.Form onValidSubmit={this.sendToServer}></Formsy.Form>
|
||||||
```
|
```
|
||||||
Triggers when form is submitted with a valid state. The arguments are the same as on `onSubmit`.
|
Triggers when form is submitted with a valid state. The arguments are the same as on `onSubmit`.
|
||||||
|
|
||||||
#### <a name="oninvalidsubmit">onInvalidSubmit(model, resetForm, invalidateForm)</a>
|
#### <a name="oninvalidsubmit">onInvalidSubmit(model, resetForm, invalidateForm)</a>
|
||||||
```jsx
|
```html
|
||||||
<Formsy.Form onInvalidSubmit={this.notifyFormError}></Formsy.Form>
|
<Formsy.Form onInvalidSubmit={this.notifyFormError}></Formsy.Form>
|
||||||
```
|
```
|
||||||
Triggers when form is submitted with an invalid state. The arguments are the same as on `onSubmit`.
|
Triggers when form is submitted with an invalid state. The arguments are the same as on `onSubmit`.
|
||||||
|
|
||||||
#### <a name="onchange">onChange(currentValues, isChanged)</a>
|
#### <a name="onchange">onChange(currentValues, isChanged)</a>
|
||||||
```jsx
|
```html
|
||||||
<Formsy.Form onChange={this.saveCurrentValuesToLocalStorage}></Formsy.Form>
|
<Formsy.Form onChange={this.saveCurrentValuesToLocalStorage}></Formsy.Form>
|
||||||
```
|
```
|
||||||
"onChange" triggers when setValue is called on your form elements. It is also triggered when dynamic form elements have been added to the form. The "currentValues" is an object where the key is the name of the input and the value is the current value. The second argument states if the forms initial values actually has changed.
|
"onChange" triggers when setValue is called on your form elements. It is also triggered when dynamic form elements have been added to the form. The "currentValues" is an object where the key is the name of the input and the value is the current value. The second argument states if the forms initial values actually has changed.
|
||||||
|
|
||||||
#### <a name="resetform">reset(values)</a>
|
#### <a name="resetform">reset(values)</a>
|
||||||
```jsx
|
```html
|
||||||
var MyForm = React.createClass({
|
var MyForm = React.createClass({
|
||||||
resetForm: function () {
|
resetForm: function () {
|
||||||
this.refs.form.reset();
|
this.refs.form.reset();
|
||||||
|
|
@ -162,45 +162,8 @@ var MyForm = React.createClass({
|
||||||
```
|
```
|
||||||
Manually reset the form to its pristine state. You can also pass an object that inserts new values into the inputs. Keys are name of input and value is of course the value.
|
Manually reset the form to its pristine state. You can also pass an object that inserts new values into the inputs. Keys are name of input and value is of course the value.
|
||||||
|
|
||||||
#### <a name="getmodel">getModel()</a>
|
|
||||||
```jsx
|
|
||||||
var MyForm = React.createClass({
|
|
||||||
getMyData: function () {
|
|
||||||
alert(this.refs.form.getModel());
|
|
||||||
},
|
|
||||||
render: function () {
|
|
||||||
return (
|
|
||||||
<Formsy.Form ref="form">
|
|
||||||
...
|
|
||||||
</Formsy.Form>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
```
|
|
||||||
Manually get values from all registered components. Keys are name of input and value is of course the value.
|
|
||||||
|
|
||||||
#### <a name="updateInputsWithError">updateInputsWithError(errors)</a>
|
|
||||||
```jsx
|
|
||||||
var MyForm = React.createClass({
|
|
||||||
someFunction: function () {
|
|
||||||
this.refs.form.updateInputsWithError({
|
|
||||||
email: 'This email is taken',
|
|
||||||
'field[10]': 'Some error!'
|
|
||||||
});
|
|
||||||
},
|
|
||||||
render: function () {
|
|
||||||
return (
|
|
||||||
<Formsy.Form ref="form">
|
|
||||||
...
|
|
||||||
</Formsy.Form>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
```
|
|
||||||
Manually invalidate the form by taking an object that maps to inputs. This is useful for server side validation. You can also use a third parameter to the [`onSubmit`](#onsubmitdata-resetform-invalidateform), [`onValidSubmit`](#onvalidsubmitmodel-resetform-invalidateform) or [`onInvalidSubmit`](#oninvalidsubmitmodel-resetform-invalidateform).
|
|
||||||
|
|
||||||
#### <a name="preventExternalInvalidation">preventExternalInvalidation</a>
|
#### <a name="preventExternalInvalidation">preventExternalInvalidation</a>
|
||||||
```jsx
|
```html
|
||||||
var MyForm = React.createClass({
|
var MyForm = React.createClass({
|
||||||
onSubmit: function (model, reset, invalidate) {
|
onSubmit: function (model, reset, invalidate) {
|
||||||
invalidate({
|
invalidate({
|
||||||
|
|
@ -221,20 +184,20 @@ With the `preventExternalInvalidation` the input will not be invalidated though
|
||||||
### <a name="formsymixin">Formsy.Mixin</a>
|
### <a name="formsymixin">Formsy.Mixin</a>
|
||||||
|
|
||||||
#### <a name="name">name</a>
|
#### <a name="name">name</a>
|
||||||
```jsx
|
```html
|
||||||
<MyInputComponent name="email"/>
|
<MyInputComponent name="email"/>
|
||||||
<MyInputComponent name="address.street"/>
|
<MyInputComponent name="address.street"/>
|
||||||
```
|
```
|
||||||
The name is required to register the form input component in the form. You can also use dot notation. This will result in the "form model" being a nested object. `{email: 'value', address: {street: 'value'}}`.
|
The name is required to register the form input component in the form. You can also use dot notation. This will result in the "form model" being a nested object. `{email: 'value', address: {street: 'value'}}`.
|
||||||
|
|
||||||
#### <a name="value">value</a>
|
#### <a name="value">value</a>
|
||||||
```jsx
|
```html
|
||||||
<MyInputComponent name="email" value="My initial value"/>
|
<MyInputComponent name="email" value="My initial value"/>
|
||||||
```
|
```
|
||||||
You should always use the [**getValue()**](#getvalue) method inside your formsy form element. To pass an initial value, use the value attribute. This value will become the "pristine" value and any reset of the form will bring back this value.
|
You should always use the [**getValue()**](#getvalue) method inside your formsy form element. To pass an initial value, use the value attribute. This value will become the "pristine" value and any reset of the form will bring back this value.
|
||||||
|
|
||||||
#### <a name="validations">validations</a>
|
#### <a name="validations">validations</a>
|
||||||
```jsx
|
```html
|
||||||
<MyInputComponent name="email" validations="isEmail"/>
|
<MyInputComponent name="email" validations="isEmail"/>
|
||||||
<MyInputComponent name="number" validations="isNumeric,isLength:5"/>
|
<MyInputComponent name="number" validations="isNumeric,isLength:5"/>
|
||||||
<MyInputComponent name="number" validations={{
|
<MyInputComponent name="number" validations={{
|
||||||
|
|
@ -249,22 +212,22 @@ You should always use the [**getValue()**](#getvalue) method inside your formsy
|
||||||
}
|
}
|
||||||
}}/>
|
}}/>
|
||||||
```
|
```
|
||||||
A comma separated list with validation rules. Take a look at [**Validators**](#validators) to see default rules. Use ":" to separate argument passed to the validator. The argument will go through a **JSON.parse** converting them into correct JavaScript types. Meaning:
|
An comma separated list with validation rules. Take a look at [**Validators**](#validators) to see default rules. Use ":" to separate argument passed to the validator. The argument will go through a **JSON.parse** converting them into correct JavaScript types. Meaning:
|
||||||
|
|
||||||
```jsx
|
```html
|
||||||
<MyInputComponent name="fruit" validations="isIn:['apple', 'orange']"/>
|
<MyInputComponent name="fruit" validations="isIn:['apple', 'orange']"/>
|
||||||
<MyInputComponent name="car" validations="mapsTo:{'bmw': true, 'vw': true}"/>
|
<MyInputComponent name="car" validations="mapsTo:{'bmw': true, 'vw': true}"/>
|
||||||
```
|
```
|
||||||
Works just fine.
|
Works just fine.
|
||||||
|
|
||||||
#### <a name="validationerror">validationError</a>
|
#### <a name="validationerror">validationError</a>
|
||||||
```jsx
|
```html
|
||||||
<MyInputComponent name="email" validations="isEmail" validationError="This is not an email"/>
|
<MyInputComponent name="email" validations="isEmail" validationError="This is not an email"/>
|
||||||
```
|
```
|
||||||
The message that will show when the form input component is invalid. It will be used as a default error.
|
The message that will show when the form input component is invalid. It will be used as a default error.
|
||||||
|
|
||||||
#### <a name="validationerrors">validationErrors</a>
|
#### <a name="validationerrors">validationErrors</a>
|
||||||
```jsx
|
```html
|
||||||
<MyInputComponent
|
<MyInputComponent
|
||||||
name="email"
|
name="email"
|
||||||
validations={{
|
validations={{
|
||||||
|
|
@ -280,19 +243,19 @@ The message that will show when the form input component is invalid. It will be
|
||||||
The message that will show when the form input component is invalid. You can combine this with `validationError`. Keys not found in `validationErrors` defaults to the general error message.
|
The message that will show when the form input component is invalid. You can combine this with `validationError`. Keys not found in `validationErrors` defaults to the general error message.
|
||||||
|
|
||||||
#### <a name="required">required</a>
|
#### <a name="required">required</a>
|
||||||
```jsx
|
```html
|
||||||
<MyInputComponent name="email" validations="isEmail" validationError="This is not an email" required/>
|
<MyInputComponent name="email" validations="isEmail" validationError="This is not an email" required/>
|
||||||
```
|
```
|
||||||
|
|
||||||
A property that tells the form that the form input component value is required. By default it uses `isDefaultRequiredValue`, but you can define your own definition of what defined a required state.
|
A property that tells the form that the form input component value is required. By default it uses `isDefaultRequiredValue`, but you can define your own definition of what defined a required state.
|
||||||
|
|
||||||
```jsx
|
```html
|
||||||
<MyInputComponent name="email" required="isFalse"/>
|
<MyInputComponent name="email" required="isFalse"/>
|
||||||
```
|
```
|
||||||
Would be typical for a checkbox type of form element that must be checked, e.g. agreeing to Terms of Service.
|
Would be typical for a checkbox type of form element.
|
||||||
|
|
||||||
#### <a name="getvalue">getValue()</a>
|
#### <a name="getvalue">getValue()</a>
|
||||||
```jsx
|
```javascript
|
||||||
var MyInput = React.createClass({
|
var MyInput = React.createClass({
|
||||||
mixins: [Formsy.Mixin],
|
mixins: [Formsy.Mixin],
|
||||||
render: function () {
|
render: function () {
|
||||||
|
|
@ -305,7 +268,7 @@ var MyInput = React.createClass({
|
||||||
Gets the current value of the form input component.
|
Gets the current value of the form input component.
|
||||||
|
|
||||||
#### <a name="setvalue">setValue(value)</a>
|
#### <a name="setvalue">setValue(value)</a>
|
||||||
```jsx
|
```javascript
|
||||||
var MyInput = React.createClass({
|
var MyInput = React.createClass({
|
||||||
mixins: [Formsy.Mixin],
|
mixins: [Formsy.Mixin],
|
||||||
changeValue: function (event) {
|
changeValue: function (event) {
|
||||||
|
|
@ -320,8 +283,27 @@ var MyInput = React.createClass({
|
||||||
```
|
```
|
||||||
Sets the value of your form input component. Notice that it does not have to be a text input. Anything can set a value on the component. Think calendars, checkboxes, autocomplete stuff etc. Running this method will trigger a **setState()** on the component and do a render.
|
Sets the value of your form input component. Notice that it does not have to be a text input. Anything can set a value on the component. Think calendars, checkboxes, autocomplete stuff etc. Running this method will trigger a **setState()** on the component and do a render.
|
||||||
|
|
||||||
|
#### <a name="hasvalue">hasValue() - DEPRECATED</a>
|
||||||
|
```javascript
|
||||||
|
var MyInput = React.createClass({
|
||||||
|
mixins: [Formsy.Mixin],
|
||||||
|
changeValue: function (event) {
|
||||||
|
this.setValue(event.currentTarget.value);
|
||||||
|
},
|
||||||
|
render: function () {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<input type="text" onChange={this.changeValue} value={this.getValue()}/>
|
||||||
|
{this.hasValue() ? 'There is a value here' : 'No value entered yet'}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
The hasValue() method helps you identify if there actually is a value or not. The only invalid value in Formsy is an empty string, "". All other values are valid as they could be something you want to send to the server. F.ex. the number zero (0), or false.
|
||||||
|
|
||||||
#### <a name="resetvalue">resetValue()</a>
|
#### <a name="resetvalue">resetValue()</a>
|
||||||
```jsx
|
```javascript
|
||||||
var MyInput = React.createClass({
|
var MyInput = React.createClass({
|
||||||
mixins: [Formsy.Mixin],
|
mixins: [Formsy.Mixin],
|
||||||
changeValue: function (event) {
|
changeValue: function (event) {
|
||||||
|
|
@ -340,7 +322,7 @@ var MyInput = React.createClass({
|
||||||
Resets to empty value. This will run a **setState()** on the component and do a render.
|
Resets to empty value. This will run a **setState()** on the component and do a render.
|
||||||
|
|
||||||
#### <a name="geterrormessage">getErrorMessage()</a>
|
#### <a name="geterrormessage">getErrorMessage()</a>
|
||||||
```jsx
|
```javascript
|
||||||
var MyInput = React.createClass({
|
var MyInput = React.createClass({
|
||||||
mixins: [Formsy.Mixin],
|
mixins: [Formsy.Mixin],
|
||||||
changeValue: function (event) {
|
changeValue: function (event) {
|
||||||
|
|
@ -358,11 +340,8 @@ var MyInput = React.createClass({
|
||||||
```
|
```
|
||||||
Will return the validation message set if the form input component is invalid. If form input component is valid it returns **null**.
|
Will return the validation message set if the form input component is invalid. If form input component is valid it returns **null**.
|
||||||
|
|
||||||
#### <a name="geterrormessages">getErrorMessages()</a>
|
|
||||||
Will return the validation messages set if the form input component is invalid. If form input component is valid it returns empty array.
|
|
||||||
|
|
||||||
#### <a name="isvalid">isValid()</a>
|
#### <a name="isvalid">isValid()</a>
|
||||||
```jsx
|
```javascript
|
||||||
var MyInput = React.createClass({
|
var MyInput = React.createClass({
|
||||||
mixins: [Formsy.Mixin],
|
mixins: [Formsy.Mixin],
|
||||||
changeValue: function (event) {
|
changeValue: function (event) {
|
||||||
|
|
@ -385,7 +364,7 @@ Returns the valid state of the form input component.
|
||||||
#### <a name="isvalidvalue">isValidValue()</a>
|
#### <a name="isvalidvalue">isValidValue()</a>
|
||||||
You can pre-verify a value against the passed validators to the form element.
|
You can pre-verify a value against the passed validators to the form element.
|
||||||
|
|
||||||
```jsx
|
```javascript
|
||||||
var MyInput = React.createClass({
|
var MyInput = React.createClass({
|
||||||
mixins: [Formsy.Mixin],
|
mixins: [Formsy.Mixin],
|
||||||
changeValue: function (event) {
|
changeValue: function (event) {
|
||||||
|
|
@ -410,7 +389,7 @@ var MyForm = React.createClass({
|
||||||
```
|
```
|
||||||
|
|
||||||
#### <a name="isrequired">isRequired()</a>
|
#### <a name="isrequired">isRequired()</a>
|
||||||
```jsx
|
```javascript
|
||||||
var MyInput = React.createClass({
|
var MyInput = React.createClass({
|
||||||
mixins: [Formsy.Mixin],
|
mixins: [Formsy.Mixin],
|
||||||
changeValue: function (event) {
|
changeValue: function (event) {
|
||||||
|
|
@ -430,7 +409,7 @@ var MyInput = React.createClass({
|
||||||
Returns true if the required property has been passed.
|
Returns true if the required property has been passed.
|
||||||
|
|
||||||
#### <a name="showrequired">showRequired()</a>
|
#### <a name="showrequired">showRequired()</a>
|
||||||
```jsx
|
```javascript
|
||||||
var MyInput = React.createClass({
|
var MyInput = React.createClass({
|
||||||
mixins: [Formsy.Mixin],
|
mixins: [Formsy.Mixin],
|
||||||
changeValue: function (event) {
|
changeValue: function (event) {
|
||||||
|
|
@ -450,7 +429,7 @@ var MyInput = React.createClass({
|
||||||
Lets you check if the form input component should indicate if it is a required field. This happens when the form input component value is empty and the required prop has been passed.
|
Lets you check if the form input component should indicate if it is a required field. This happens when the form input component value is empty and the required prop has been passed.
|
||||||
|
|
||||||
#### <a name="showerror">showError()</a>
|
#### <a name="showerror">showError()</a>
|
||||||
```jsx
|
```javascript
|
||||||
var MyInput = React.createClass({
|
var MyInput = React.createClass({
|
||||||
mixins: [Formsy.Mixin],
|
mixins: [Formsy.Mixin],
|
||||||
changeValue: function (event) {
|
changeValue: function (event) {
|
||||||
|
|
@ -470,7 +449,7 @@ var MyInput = React.createClass({
|
||||||
Lets you check if the form input component should indicate if there is an error. This happens if there is a form input component value and it is invalid or if a server error is received.
|
Lets you check if the form input component should indicate if there is an error. This happens if there is a form input component value and it is invalid or if a server error is received.
|
||||||
|
|
||||||
#### <a name="ispristine">isPristine()</a>
|
#### <a name="ispristine">isPristine()</a>
|
||||||
```jsx
|
```javascript
|
||||||
var MyInput = React.createClass({
|
var MyInput = React.createClass({
|
||||||
mixins: [Formsy.Mixin],
|
mixins: [Formsy.Mixin],
|
||||||
changeValue: function (event) {
|
changeValue: function (event) {
|
||||||
|
|
@ -491,7 +470,7 @@ By default all formsy input elements are pristine, which means they are not "tou
|
||||||
**note!** When the form is reset, using the resetForm callback function on for example [**onSubmit**](#onsubmitdata-resetform-invalidateform) the inputs are reset to their pristine state.
|
**note!** When the form is reset, using the resetForm callback function on for example [**onSubmit**](#onsubmitdata-resetform-invalidateform) the inputs are reset to their pristine state.
|
||||||
|
|
||||||
#### <a name="isformdisabled">isFormDisabled()</a>
|
#### <a name="isformdisabled">isFormDisabled()</a>
|
||||||
```jsx
|
```javascript
|
||||||
var MyInput = React.createClass({
|
var MyInput = React.createClass({
|
||||||
mixins: [Formsy.Mixin],
|
mixins: [Formsy.Mixin],
|
||||||
render: function () {
|
render: function () {
|
||||||
|
|
@ -508,7 +487,7 @@ React.render(<Formy.Form disabled={true}/>);
|
||||||
You can now disable the form itself with a prop and use **isFormDisabled()** inside form elements to verify this prop.
|
You can now disable the form itself with a prop and use **isFormDisabled()** inside form elements to verify this prop.
|
||||||
|
|
||||||
#### <a name="isformsubmitted">isFormSubmitted()</a>
|
#### <a name="isformsubmitted">isFormSubmitted()</a>
|
||||||
```jsx
|
```javascript
|
||||||
var MyInput = React.createClass({
|
var MyInput = React.createClass({
|
||||||
mixins: [Formsy.Mixin],
|
mixins: [Formsy.Mixin],
|
||||||
render: function () {
|
render: function () {
|
||||||
|
|
@ -525,7 +504,7 @@ var MyInput = React.createClass({
|
||||||
You can check if the form has been submitted.
|
You can check if the form has been submitted.
|
||||||
|
|
||||||
#### <a name="validate">validate</a>
|
#### <a name="validate">validate</a>
|
||||||
```jsx
|
```javascript
|
||||||
var MyInput = React.createClass({
|
var MyInput = React.createClass({
|
||||||
mixins: [Formsy.Mixin],
|
mixins: [Formsy.Mixin],
|
||||||
changeValue: function (event) {
|
changeValue: function (event) {
|
||||||
|
|
@ -549,7 +528,7 @@ You can create custom validation inside a form element. The validate method defi
|
||||||
|
|
||||||
#### <a name="formnovalidate">formNoValidate</a>
|
#### <a name="formnovalidate">formNoValidate</a>
|
||||||
To avoid native validation behavior on inputs, use the React `formNoValidate` property.
|
To avoid native validation behavior on inputs, use the React `formNoValidate` property.
|
||||||
```jsx
|
```javascript
|
||||||
var MyInput = React.createClass({
|
var MyInput = React.createClass({
|
||||||
mixins: [Formsy.Mixin],
|
mixins: [Formsy.Mixin],
|
||||||
render: function () {
|
render: function () {
|
||||||
|
|
@ -564,10 +543,10 @@ var MyInput = React.createClass({
|
||||||
|
|
||||||
### <a name="formsyhoc">Formsy.HOC</a>
|
### <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.
|
The same methods as the mixin are exposed to the HOC version of the element component, though through the `props`, not on the instance.
|
||||||
```jsx
|
```js
|
||||||
import {HOC} from 'formsy-react';
|
import {HOC} from 'formsy-react';
|
||||||
|
|
||||||
class MyInputHoc extends React.Component {
|
class MyInput extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -576,31 +555,12 @@ class MyInputHoc extends React.Component {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
export default HOC(MyInputHoc);
|
export default HOC(MyInput);
|
||||||
```
|
|
||||||
|
|
||||||
#### <a name="innerRef">innerRef</a>
|
|
||||||
|
|
||||||
Use an `innerRef` prop to get a reference to your DOM node.
|
|
||||||
|
|
||||||
```jsx
|
|
||||||
var MyForm = React.createClass({
|
|
||||||
componentDidMount() {
|
|
||||||
this.searchInput.focus()
|
|
||||||
},
|
|
||||||
render: function () {
|
|
||||||
return (
|
|
||||||
<Formsy.Form>
|
|
||||||
<MyInputHoc name="search" innerRef={(c) => { this.searchInput = c; }} />
|
|
||||||
</Formsy.Form>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### <a name="formsydecorator">Formsy.Decorator</a>
|
### <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.
|
The same methods as the mixin are exposed to the decorator version of the element component, though through the `props`, not on the instance.
|
||||||
```jsx
|
```js
|
||||||
import {Decorator as FormsyElement} from 'formsy-react';
|
import {Decorator as FormsyElement} from 'formsy-react';
|
||||||
|
|
||||||
@FormsyElement()
|
@FormsyElement()
|
||||||
|
|
@ -618,25 +578,25 @@ export default MyInput
|
||||||
|
|
||||||
### <a name="formsyaddvalidationrule">Formsy.addValidationRule(name, ruleFunc)</a>
|
### <a name="formsyaddvalidationrule">Formsy.addValidationRule(name, ruleFunc)</a>
|
||||||
An example:
|
An example:
|
||||||
```jsx
|
```javascript
|
||||||
Formsy.addValidationRule('isFruit', function (values, value) {
|
Formsy.addValidationRule('isFruit', function (values, value) {
|
||||||
return ['apple', 'orange', 'pear'].indexOf(value) >= 0;
|
return ['apple', 'orange', 'pear'].indexOf(value) >= 0;
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
```jsx
|
```html
|
||||||
<MyInputComponent name="fruit" validations="isFruit"/>
|
<MyInputComponent name="fruit" validations="'isFruit"/>
|
||||||
```
|
```
|
||||||
Another example:
|
Another example:
|
||||||
```jsx
|
```javascript
|
||||||
Formsy.addValidationRule('isIn', function (values, value, array) {
|
Formsy.addValidationRule('isIn', function (values, value, array) {
|
||||||
return array.indexOf(value) >= 0;
|
return array.indexOf(value) >= 0;
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
```jsx
|
```html
|
||||||
<MyInputComponent name="fruit" validations="isIn:['apple', 'orange', 'pear']"/>
|
<MyInputComponent name="fruit" validations="isIn:['apple', 'orange', 'pear']"/>
|
||||||
```
|
```
|
||||||
Cross input validation:
|
Cross input validation:
|
||||||
```jsx
|
```javascript
|
||||||
Formsy.addValidationRule('isMoreThan', function (values, value, otherField) {
|
Formsy.addValidationRule('isMoreThan', function (values, value, otherField) {
|
||||||
// The this context points to an object containing the values
|
// The this context points to an object containing the values
|
||||||
// {childAge: "", parentAge: "5"}
|
// {childAge: "", parentAge: "5"}
|
||||||
|
|
@ -644,133 +604,130 @@ Formsy.addValidationRule('isMoreThan', function (values, value, otherField) {
|
||||||
return Number(value) > Number(values[otherField]);
|
return Number(value) > Number(values[otherField]);
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
```jsx
|
```html
|
||||||
<MyInputComponent name="childAge"/>
|
<MyInputComponent name="childAge"/>
|
||||||
<MyInputComponent name="parentAge" validations="isMoreThan:childAge"/>
|
<MyInputComponent name="parentAge" validations="isMoreThan:childAge"/>
|
||||||
```
|
```
|
||||||
## <a name="validators">Validators</a>
|
## <a name="validators">Validators</a>
|
||||||
**matchRegexp**
|
**matchRegexp**
|
||||||
```jsx
|
```html
|
||||||
<MyInputComponent name="foo" validations={{
|
<MyInputComponent name="foo" validations={{
|
||||||
matchRegexp: /foo/
|
matchRegexp: /foo/
|
||||||
}}/>
|
}}/>
|
||||||
```
|
```
|
||||||
Returns true if the value is thruthful
|
Returns true if the value is thruthful
|
||||||
|
|
||||||
_For more complicated regular expressions (emoji, international characters) you can use [xregexp](https://github.com/slevithan/xregexp). See [this comment](https://github.com/christianalfoni/formsy-react/issues/407#issuecomment-266306783) for an example._
|
|
||||||
|
|
||||||
**isEmail**
|
**isEmail**
|
||||||
```jsx
|
```html
|
||||||
<MyInputComponent name="foo" validations="isEmail"/>
|
<MyInputComponent name="foo" validations="isEmail"/>
|
||||||
```
|
```
|
||||||
Return true if it is an email
|
Return true if it is an email
|
||||||
|
|
||||||
**isUrl**
|
**isUrl**
|
||||||
```jsx
|
```html
|
||||||
<MyInputComponent name="foo" validations="isUrl"/>
|
<MyInputComponent name="foo" validations="isUrl"/>
|
||||||
```
|
```
|
||||||
Return true if it is an url
|
Return true if it is an url
|
||||||
|
|
||||||
**isExisty**
|
**isExisty**
|
||||||
```jsx
|
```html
|
||||||
<MyInputComponent name="foo" validations="isExisty"/>
|
<MyInputComponent name="foo" validations="isExisty"/>
|
||||||
```
|
```
|
||||||
Returns true if the value is not undefined or null
|
Returns true if the value is not undefined or null
|
||||||
|
|
||||||
**isUndefined**
|
**isUndefined**
|
||||||
```jsx
|
```html
|
||||||
<MyInputComponent name="foo" validations="isUndefined"/>
|
<MyInputComponent name="foo" validations="isUndefined"/>
|
||||||
```
|
```
|
||||||
Returns true if the value is the undefined
|
Returns true if the value is the undefined
|
||||||
|
|
||||||
**isEmptyString**
|
**isEmptyString**
|
||||||
```jsx
|
```html
|
||||||
<MyInputComponent name="foo" validations="isEmptyString"/>
|
<MyInputComponent name="foo" validations="isEmptyString"/>
|
||||||
```
|
```
|
||||||
Returns true if the value is an empty string
|
Returns true if the value is an empty string
|
||||||
|
|
||||||
**isTrue**
|
**isTrue**
|
||||||
```jsx
|
```html
|
||||||
<MyInputComponent name="foo" validations="isTrue"/>
|
<MyInputComponent name="foo" validations="isTrue"/>
|
||||||
```
|
```
|
||||||
Returns true if the value is the boolean true
|
Returns true if the value is the boolean true
|
||||||
|
|
||||||
**isFalse**
|
**isFalse**
|
||||||
```jsx
|
```html
|
||||||
<MyInputComponent name="foo" validations="isFalse"/>
|
<MyInputComponent name="foo" validations="isFalse"/>
|
||||||
```
|
```
|
||||||
Returns true if the value is the boolean false
|
Returns true if the value is the boolean false
|
||||||
|
|
||||||
**isAlpha**
|
**isAlpha**
|
||||||
```jsx
|
```html
|
||||||
<MyInputComponent name="foo" validations="isAlpha"/>
|
<MyInputComponent name="foo" validations="isAlpha"/>
|
||||||
```
|
```
|
||||||
Returns true if string is only letters
|
Returns true if string is only letters
|
||||||
|
|
||||||
**isNumeric**
|
**isNumeric**
|
||||||
```jsx
|
```html
|
||||||
<MyInputComponent name="foo" validations="isNumeric"/>
|
<MyInputComponent name="foo" validations="isNumeric"/>
|
||||||
```
|
```
|
||||||
Returns true if string only contains numbers. Examples: 42; -3.14
|
Returns true if string only contains numbers. Examples: 42; -3.14
|
||||||
|
|
||||||
**isAlphanumeric**
|
**isAlphanumeric**
|
||||||
```jsx
|
```html
|
||||||
<MyInputComponent name="foo" validations="isAlphanumeric"/>
|
<MyInputComponent name="foo" validations="isAlphanumeric"/>
|
||||||
```
|
```
|
||||||
Returns true if string only contains letters or numbers
|
Returns true if string only contains letters or numbers
|
||||||
|
|
||||||
**isInt**
|
**isInt**
|
||||||
```jsx
|
```html
|
||||||
<MyInputComponent name="foo" validations="isInt"/>
|
<MyInputComponent name="foo" validations="isInt"/>
|
||||||
```
|
```
|
||||||
Returns true if string represents integer value. Examples: 42; -12; 0
|
Returns true if string represents integer value. Examples: 42; -12; 0
|
||||||
|
|
||||||
**isFloat**
|
**isFloat**
|
||||||
```jsx
|
```html
|
||||||
<MyInputComponent name="foo" validations="isFloat"/>
|
<MyInputComponent name="foo" validations="isFloat"/>
|
||||||
```
|
```
|
||||||
Returns true if string represents float value. Examples: 42; -3.14; 1e3
|
Returns true if string represents float value. Examples: 42; -3.14; 1e3
|
||||||
|
|
||||||
**isWords**
|
**isWords**
|
||||||
```jsx
|
```html
|
||||||
<MyInputComponent name="foo" validations="isWords"/>
|
<MyInputComponent name="foo" validations="isWords"/>
|
||||||
```
|
```
|
||||||
Returns true if string is only letters, including spaces and tabs
|
Returns true if string is only letters, including spaces and tabs
|
||||||
|
|
||||||
**isSpecialWords**
|
**isSpecialWords**
|
||||||
```jsx
|
```html
|
||||||
<MyInputComponent name="foo" validations="isSpecialWords"/>
|
<MyInputComponent name="foo" validations="isSpecialWords"/>
|
||||||
```
|
```
|
||||||
Returns true if string is only letters, including special letters (a-z,ú,ø,æ,å)
|
Returns true if string is only letters, including special letters (a-z,ú,ø,æ,å)
|
||||||
|
|
||||||
**equals:value**
|
**equals:value**
|
||||||
```jsx
|
```html
|
||||||
<MyInputComponent name="foo" validations="equals:4"/>
|
<MyInputComponent name="foo" validations="equals:4"/>
|
||||||
```
|
```
|
||||||
Return true if the value from input component matches value passed (==).
|
Return true if the value from input component matches value passed (==).
|
||||||
|
|
||||||
**equalsField:fieldName**
|
**equalsField:fieldName**
|
||||||
```jsx
|
```html
|
||||||
<MyInputComponent name="password"/>
|
<MyInputComponent name="password"/>
|
||||||
<MyInputComponent name="repeated_password" validations="equalsField:password"/>
|
<MyInputComponent name="repeated_password" validations="equalsField:password"/>
|
||||||
```
|
```
|
||||||
Return true if the value from input component matches value passed (==).
|
Return true if the value from input component matches value passed (==).
|
||||||
|
|
||||||
**isLength:length**
|
**isLength:length**
|
||||||
```jsx
|
```html
|
||||||
<MyInputComponent name="foo" validations="isLength:8"/>
|
<MyInputComponent name="foo" validations="isLength:8"/>
|
||||||
```
|
```
|
||||||
Returns true if the value length is the equal.
|
Returns true if the value length is the equal.
|
||||||
|
|
||||||
**minLength:length**
|
**minLength:length**
|
||||||
```jsx
|
```html
|
||||||
<MyInputComponent name="number" validations="minLength:1"/>
|
<MyInputComponent name="number" validations="minLength:1"/>
|
||||||
```
|
```
|
||||||
Return true if the value is more or equal to argument.
|
Return true if the value is more or equal to argument
|
||||||
**Also returns true for an empty value.** If you want to get false, then you should use [`required`](#required) additionally.
|
|
||||||
|
|
||||||
**maxLength:length**
|
**maxLength:length**
|
||||||
```jsx
|
```html
|
||||||
<MyInputComponent name="number" validations="maxLength:5"/>
|
<MyInputComponent name="number" validations="maxLength:5"/>
|
||||||
```
|
```
|
||||||
Return true if the value is less or equal to argument
|
Return true if the value is less or equal to argument
|
||||||
|
|
|
||||||
2
LICENSE
2
LICENSE
|
|
@ -1,6 +1,6 @@
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2014-2016 PatientSky A/S
|
Copyright (c) 2014 Christian Alfoni
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
||||||
77
README.md
77
README.md
|
|
@ -6,6 +6,10 @@ A form input builder and validator for React JS
|
||||||
| [How to use](#how-to-use) | [API](/API.md) | [Examples](/examples) |
|
| [How to use](#how-to-use) | [API](/API.md) | [Examples](/examples) |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
|
|
||||||
|
### Currently, the development is in 'react-0.14' branch. For more information see [#158](https://github.com/christianalfoni/formsy-react/issues/158)
|
||||||
|
|
||||||
|
### From version 0.12.0 Formsy only supports React 0.13.1 and up
|
||||||
|
|
||||||
## <a name="background">Background</a>
|
## <a name="background">Background</a>
|
||||||
I wrote an article on forms and validation with React JS, [Nailing that validation with React JS](http://christianalfoni.github.io/javascript/2014/10/22/nailing-that-validation-with-reactjs.html), the result of that was this extension.
|
I wrote an article on forms and validation with React JS, [Nailing that validation with React JS](http://christianalfoni.github.io/javascript/2014/10/22/nailing-that-validation-with-reactjs.html), the result of that was this extension.
|
||||||
|
|
||||||
|
|
@ -24,7 +28,7 @@ The main concept is that forms, inputs and validation is done very differently a
|
||||||
5. You can dynamically add form elements to your form and they will register/unregister to the form
|
5. You can dynamically add form elements to your form and they will register/unregister to the form
|
||||||
|
|
||||||
## Default elements
|
## 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, or use [formsy-material-ui](https://github.com/mbrookes/formsy-material-ui) to use [Material-UI](http://material-ui.com/) with formsy-react.
|
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
|
## Install
|
||||||
|
|
||||||
|
|
@ -40,35 +44,30 @@ You can look at examples in this repo or use the [formsy-react-components](https
|
||||||
|
|
||||||
## How to use
|
## How to use
|
||||||
|
|
||||||
See [`examples` folder](/examples) for examples. [Codepen demo](http://codepen.io/semigradsky/pen/dYYpwv?editors=001).
|
See [`examples` folder](/examples) for examples.
|
||||||
|
|
||||||
Complete API reference is available [here](/API.md).
|
Complete API reference is available [here](/API.md).
|
||||||
|
|
||||||
#### Formsy gives you a form straight out of the box
|
#### Formsy gives you a form straight out of the box
|
||||||
|
|
||||||
```jsx
|
```javascript
|
||||||
import Formsy from 'formsy-react';
|
/** @jsx React.DOM */
|
||||||
|
var Formsy = require('formsy-react');
|
||||||
const MyAppForm = React.createClass({
|
var MyAppForm = React.createClass({
|
||||||
getInitialState() {
|
enableButton: function () {
|
||||||
return {
|
|
||||||
canSubmit: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
enableButton() {
|
|
||||||
this.setState({
|
this.setState({
|
||||||
canSubmit: true
|
canSubmit: true
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
disableButton() {
|
disableButton: function () {
|
||||||
this.setState({
|
this.setState({
|
||||||
canSubmit: false
|
canSubmit: false
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
submit(model) {
|
submit: function (model) {
|
||||||
someDep.saveEmail(model.email);
|
someDep.saveEmail(model.email);
|
||||||
},
|
},
|
||||||
render() {
|
render: function () {
|
||||||
return (
|
return (
|
||||||
<Formsy.Form onValidSubmit={this.submit} onValid={this.enableButton} onInvalid={this.disableButton}>
|
<Formsy.Form onValidSubmit={this.submit} onValid={this.enableButton} onInvalid={this.disableButton}>
|
||||||
<MyOwnInput name="email" validations="isEmail" validationError="This is not a valid email" required/>
|
<MyOwnInput name="email" validations="isEmail" validationError="This is not a valid email" required/>
|
||||||
|
|
@ -82,31 +81,31 @@ Complete API reference is available [here](/API.md).
|
||||||
This code results in a form with a submit button that will run the `submit` method when the submit button is clicked with a valid email. The submit button is disabled as long as the input is empty ([required](/API.md#required)) or the value is not an email ([isEmail](/API.md#validators)). On validation error it will show the message: "This is not a valid email".
|
This code results in a form with a submit button that will run the `submit` method when the submit button is clicked with a valid email. The submit button is disabled as long as the input is empty ([required](/API.md#required)) or the value is not an email ([isEmail](/API.md#validators)). On validation error it will show the message: "This is not a valid email".
|
||||||
|
|
||||||
#### Building a form element (required)
|
#### Building a form element (required)
|
||||||
```jsx
|
```javascript
|
||||||
import Formsy from 'formsy-react';
|
/** @jsx React.DOM */
|
||||||
|
var Formsy = require('formsy-react');
|
||||||
const MyOwnInput = React.createClass({
|
var MyOwnInput = React.createClass({
|
||||||
|
|
||||||
// Add the Formsy Mixin
|
// Add the Formsy Mixin
|
||||||
mixins: [Formsy.Mixin],
|
mixins: [Formsy.Mixin],
|
||||||
|
|
||||||
// setValue() will set the value of the component, which in
|
// setValue() will set the value of the component, which in
|
||||||
// turn will validate it and the rest of the form
|
// turn will validate it and the rest of the form
|
||||||
changeValue(event) {
|
changeValue: function (event) {
|
||||||
this.setValue(event.currentTarget.value);
|
this.setValue(event.currentTarget.value);
|
||||||
},
|
},
|
||||||
|
render: function () {
|
||||||
|
|
||||||
render() {
|
|
||||||
// Set a specific className based on the validation
|
// Set a specific className based on the validation
|
||||||
// state of this component. showRequired() is true
|
// state of this component. showRequired() is true
|
||||||
// when the value is empty and the required prop is
|
// when the value is empty and the required prop is
|
||||||
// passed to the input. showError() is true when the
|
// passed to the input. showError() is true when the
|
||||||
// value typed is invalid
|
// value typed is invalid
|
||||||
const className = this.showRequired() ? 'required' : this.showError() ? 'error' : null;
|
var className = this.showRequired() ? 'required' : this.showError() ? 'error' : null;
|
||||||
|
|
||||||
// An error message is returned ONLY if the component is invalid
|
// An error message is returned ONLY if the component is invalid
|
||||||
// or the server has returned an error message
|
// or the server has returned an error message
|
||||||
const errorMessage = this.getErrorMessage();
|
var errorMessage = this.getErrorMessage();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={className}>
|
<div className={className}>
|
||||||
|
|
@ -120,19 +119,39 @@ This code results in a form with a submit button that will run the `submit` meth
|
||||||
The form element component is what gives the form validation functionality to whatever you want to put inside this wrapper. You do not have to use traditional inputs, it can be anything you want and the value of the form element can also be anything you want. As you can see it is very flexible, you just have a small API to help you identify the state of the component and set its value.
|
The form element component is what gives the form validation functionality to whatever you want to put inside this wrapper. You do not have to use traditional inputs, it can be anything you want and the value of the form element can also be anything you want. As you can see it is very flexible, you just have a small API to help you identify the state of the component and set its value.
|
||||||
|
|
||||||
## Related projects
|
## Related projects
|
||||||
- [formsy-material-ui](https://github.com/mbrookes/formsy-material-ui) - A formsy-react compatibility wrapper for [Material-UI](http://material-ui.com/) form components.
|
- [formsy-react-components](https://github.com/twisty/formsy-react-components) - A set of React JS components for use in a formsy-react form
|
||||||
- [formsy-react-components](https://github.com/twisty/formsy-react-components) - A set of React JS components for use in a formsy-react form.
|
|
||||||
- ...
|
- ...
|
||||||
- Send PR for adding your project to this list!
|
- Send PR for adding your project to this list!
|
||||||
|
|
||||||
## Contribute
|
## Contribute
|
||||||
- Fork repo
|
- Fork repo
|
||||||
- `npm install`
|
- `npm install`
|
||||||
- `npm run examples` runs the development server on `localhost:8080`
|
- `npm start` runs the development server on `localhost:8080`
|
||||||
- `npm test` runs the tests
|
- `npm test` runs the tests
|
||||||
|
|
||||||
## License
|
License
|
||||||
|
-------
|
||||||
|
|
||||||
[The MIT License (MIT)](/LICENSE)
|
formsy-react is licensed under the [MIT license](LICENSE).
|
||||||
|
|
||||||
Copyright (c) 2014-2016 PatientSky A/S
|
> The MIT License (MIT)
|
||||||
|
>
|
||||||
|
> Copyright (c) 2015 Gloppens EDB Lag
|
||||||
|
>
|
||||||
|
> Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
> of this software and associated documentation files (the "Software"), to deal
|
||||||
|
> in the Software without restriction, including without limitation the rights
|
||||||
|
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
> copies of the Software, and to permit persons to whom the Software is
|
||||||
|
> furnished to do so, subject to the following conditions:
|
||||||
|
>
|
||||||
|
> The above copyright notice and this permission notice shall be included in
|
||||||
|
> all copies or substantial portions of the Software.
|
||||||
|
>
|
||||||
|
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
> THE SOFTWARE.
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "formsy-react",
|
"name": "formsy-react",
|
||||||
"version": "0.18.0",
|
"version": "0.14.1",
|
||||||
"description": "A form input builder and validator for React JS",
|
"description": "A form input builder and validator for React JS",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
"Gulpfile.js"
|
"Gulpfile.js"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"react": "^0.14.7 || ^15.0.0"
|
"react": "^0.13.1"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"react",
|
"react",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Formsy Test</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
<script src="build.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
var React = require('react');
|
||||||
|
var ReactDOM = require('react-dom');
|
||||||
|
var Formsy = require('./../src/main.js');
|
||||||
|
|
||||||
|
var Input = React.createClass({
|
||||||
|
onChange: function (event) {
|
||||||
|
this.props.setValue(event.currentTarget.value);
|
||||||
|
},
|
||||||
|
render: function () {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{this.props.showRequired() ? 'required' : ''}
|
||||||
|
<input disabled={this.props.isFormDisabled()} value={this.props.getValue()} onChange={this.onChange}/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
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" onSubmit={this.onSubmit}>
|
||||||
|
<SomeComp/>
|
||||||
|
</Formsy.Form>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ReactDOM.render(<FormApp />, document.getElementById('app'));
|
||||||
|
|
@ -34,7 +34,3 @@ If it is not helped try update your node.js and npm.
|
||||||
3. [**Reset Values**](reset-values)
|
3. [**Reset Values**](reset-values)
|
||||||
|
|
||||||
Reset text input, checkbox and select to their pristine values.
|
Reset text input, checkbox and select to their pristine values.
|
||||||
|
|
||||||
4. [**Dynamic Form Fields**](dynamic-form-fields)
|
|
||||||
|
|
||||||
Dynamically adding and removing fields to form.
|
|
||||||
|
|
|
||||||
|
|
@ -18,15 +18,14 @@ const MyInput = React.createClass({
|
||||||
// when the value is empty and the required prop is
|
// when the value is empty and the required prop is
|
||||||
// passed to the input. showError() is true when the
|
// passed to the input. showError() is true when the
|
||||||
// value typed is invalid
|
// value typed is invalid
|
||||||
const className = 'form-group' + (this.props.className || ' ') +
|
const className = this.props.className + ' ' + (this.showRequired() ? 'required' : this.showError() ? 'error' : null);
|
||||||
(this.showRequired() ? 'required' : this.showError() ? 'error' : '');
|
|
||||||
|
|
||||||
// An error message is returned ONLY if the component is invalid
|
// An error message is returned ONLY if the component is invalid
|
||||||
// or the server has returned an error message
|
// or the server has returned an error message
|
||||||
const errorMessage = this.getErrorMessage();
|
const errorMessage = this.getErrorMessage();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={className}>
|
<div className='form-group'>
|
||||||
<label htmlFor={this.props.name}>{this.props.title}</label>
|
<label htmlFor={this.props.name}>{this.props.title}</label>
|
||||||
<input
|
<input
|
||||||
type={this.props.type || 'text'}
|
type={this.props.type || 'text'}
|
||||||
|
|
|
||||||
|
|
@ -1,66 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import Formsy from 'formsy-react';
|
|
||||||
|
|
||||||
function contains(container, item, cmp) {
|
|
||||||
for (const it of container) {
|
|
||||||
if (cmp(it, item)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const MyRadioGroup = React.createClass({
|
|
||||||
mixins: [Formsy.Mixin],
|
|
||||||
getInitialState() {
|
|
||||||
return { value: [], cmp: (a, b) => a === b };
|
|
||||||
},
|
|
||||||
componentDidMount() {
|
|
||||||
const value = this.props.value || [];
|
|
||||||
this.setValue(value);
|
|
||||||
this.setState({ value: value, cmp: this.props.cmp || this.state.cmp });
|
|
||||||
},
|
|
||||||
|
|
||||||
changeValue(value, event) {
|
|
||||||
const checked = event.currentTarget.checked;
|
|
||||||
|
|
||||||
let newValue = [];
|
|
||||||
if (checked) {
|
|
||||||
newValue = this.state.value.concat(value);
|
|
||||||
} else {
|
|
||||||
newValue = this.state.value.filter(it => !this.state.cmp(it, value));
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setValue(newValue);
|
|
||||||
this.setState({ value: newValue });
|
|
||||||
},
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const className = 'form-group' + (this.props.className || ' ') +
|
|
||||||
(this.showRequired() ? 'required' : this.showError() ? 'error' : '');
|
|
||||||
const errorMessage = this.getErrorMessage();
|
|
||||||
|
|
||||||
const { name, title, items } = this.props;
|
|
||||||
return (
|
|
||||||
<div className={className}>
|
|
||||||
<label htmlFor={name}>{title}</label>
|
|
||||||
{items.map((item, i) => (
|
|
||||||
<div key={i}>
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
name={name}
|
|
||||||
onChange={this.changeValue.bind(this, item)}
|
|
||||||
checked={contains(this.state.value, item, this.state.cmp)}
|
|
||||||
/>
|
|
||||||
<span>{JSON.stringify(item)}</span>
|
|
||||||
</div>
|
|
||||||
))
|
|
||||||
}
|
|
||||||
<span className='validation-error'>{errorMessage}</span>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
export default MyRadioGroup;
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import Formsy from 'formsy-react';
|
|
||||||
|
|
||||||
const MyRadioGroup = React.createClass({
|
|
||||||
mixins: [Formsy.Mixin],
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
const value = this.props.value;
|
|
||||||
this.setValue(value);
|
|
||||||
this.setState({ value });
|
|
||||||
},
|
|
||||||
|
|
||||||
changeValue(value) {
|
|
||||||
this.setValue(value);
|
|
||||||
this.setState({ value });
|
|
||||||
},
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const className = 'form-group' + (this.props.className || ' ') +
|
|
||||||
(this.showRequired() ? 'required' : this.showError() ? 'error' : '');
|
|
||||||
const errorMessage = this.getErrorMessage();
|
|
||||||
|
|
||||||
const { name, title, items } = this.props;
|
|
||||||
return (
|
|
||||||
<div className={className}>
|
|
||||||
<label htmlFor={name}>{title}</label>
|
|
||||||
{items.map((item, i) => (
|
|
||||||
<div key={i}>
|
|
||||||
<input
|
|
||||||
type="radio"
|
|
||||||
name={name}
|
|
||||||
onChange={this.changeValue.bind(this, item)}
|
|
||||||
checked={this.state.value === item}
|
|
||||||
/>
|
|
||||||
<span>{item.toString()}</span>
|
|
||||||
</div>
|
|
||||||
))
|
|
||||||
}
|
|
||||||
<span className='validation-error'>{errorMessage}</span>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
export default MyRadioGroup;
|
|
||||||
|
|
@ -9,8 +9,7 @@ const MySelect = React.createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const className = 'form-group' + (this.props.className || ' ') +
|
const className = this.props.className + ' ' + (this.showRequired() ? 'required' : this.showError() ? 'error' : null);
|
||||||
(this.showRequired() ? 'required' : this.showError() ? 'error' : '');
|
|
||||||
const errorMessage = this.getErrorMessage();
|
const errorMessage = this.getErrorMessage();
|
||||||
|
|
||||||
const options = this.props.options.map((option, i) => (
|
const options = this.props.options.map((option, i) => (
|
||||||
|
|
@ -20,7 +19,7 @@ const MySelect = React.createClass({
|
||||||
));
|
));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={className}>
|
<div className='form-group'>
|
||||||
<label htmlFor={this.props.name}>{this.props.title}</label>
|
<label htmlFor={this.props.name}>{this.props.title}</label>
|
||||||
<select name={this.props.name} onChange={this.changeValue} value={this.getValue()}>
|
<select name={this.props.name} onChange={this.changeValue} value={this.getValue()}>
|
||||||
{options}
|
{options}
|
||||||
|
|
|
||||||
|
|
@ -58,20 +58,19 @@ const DynamicInput = React.createClass({
|
||||||
},
|
},
|
||||||
validate() {
|
validate() {
|
||||||
const value = this.getValue();
|
const value = this.getValue();
|
||||||
console.log(value, this.state.validationType);
|
return value !== '' ? validators[this.state.validationType].regexp.test(value) : true;
|
||||||
return value ? validators[this.state.validationType].regexp.test(value) : true;
|
|
||||||
},
|
},
|
||||||
getCustomErrorMessage() {
|
getCustomErrorMessage() {
|
||||||
return this.showError() ? validators[this.state.validationType].message : '';
|
return this.showError() ? validators[this.state.validationType].message : '';
|
||||||
},
|
},
|
||||||
render() {
|
render() {
|
||||||
const className = 'form-group' + (this.props.className || ' ') + (this.showRequired() ? 'required' : this.showError() ? 'error' : null);
|
const className = this.props.className + ' ' + (this.showError() ? 'error' : null);
|
||||||
const errorMessage = this.getCustomErrorMessage();
|
const errorMessage = this.getCustomErrorMessage();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={className}>
|
<div className='form-group'>
|
||||||
<label htmlFor={this.props.name}>{this.props.title}</label>
|
<label htmlFor={this.props.name}>{this.props.title}</label>
|
||||||
<input 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>
|
<span className='validation-error'>{errorMessage}</span>
|
||||||
<Validations validationType={this.state.validationType} changeValidation={this.changeValidation}/>
|
<Validations validationType={this.state.validationType} changeValidation={this.changeValidation}/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
.many-fields-conf {
|
|
||||||
width: 400px;
|
|
||||||
margin: 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.many-fields {
|
|
||||||
width: 600px;
|
|
||||||
margin: 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.field {
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.many-fields .form-group {
|
|
||||||
width: calc(100% - 20px);
|
|
||||||
float: left;
|
|
||||||
}
|
|
||||||
.many-fields .remove-field {
|
|
||||||
margin-top: 30px;
|
|
||||||
margin-left: 8px;
|
|
||||||
display: inline-block;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
@ -1,113 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import ReactDOM from 'react-dom';
|
|
||||||
import { Form } from 'formsy-react';
|
|
||||||
|
|
||||||
import MyInput from './../components/Input';
|
|
||||||
import MySelect from './../components/Select';
|
|
||||||
import MyRadioGroup from './../components/RadioGroup';
|
|
||||||
import MyMultiCheckboxSet from './../components/MultiCheckboxSet';
|
|
||||||
|
|
||||||
const Fields = props => {
|
|
||||||
function onRemove(pos) {
|
|
||||||
return event => {
|
|
||||||
event.preventDefault();
|
|
||||||
props.onRemove(pos);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
const foo = 'required';
|
|
||||||
return (
|
|
||||||
<div className="fields">
|
|
||||||
{props.data.map((field, i) => (
|
|
||||||
<div className="field" key={field.id}>
|
|
||||||
{
|
|
||||||
field.type === 'input' ?
|
|
||||||
(
|
|
||||||
<MyInput
|
|
||||||
value=""
|
|
||||||
name={`fields[${i}]`}
|
|
||||||
title={field.validations ? JSON.stringify(field.validations) : 'No validations'}
|
|
||||||
required={field.required}
|
|
||||||
validations={field.validations}
|
|
||||||
/>
|
|
||||||
) :
|
|
||||||
(
|
|
||||||
<MySelect
|
|
||||||
name={`fields[${i}]`}
|
|
||||||
title={field.validations ? JSON.stringify(field.validations) : 'No validations'}
|
|
||||||
required={field.required}
|
|
||||||
validations={field.validations}
|
|
||||||
options={[
|
|
||||||
{title: '123', value: '123'},
|
|
||||||
{title: 'some long text', value: 'some long text'},
|
|
||||||
{title: '`empty string`', value: ''},
|
|
||||||
{title: 'alpha42', value: 'alpha42'},
|
|
||||||
{title: 'test@mail.com', value: 'test@mail.com'}
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
<a href="#" className="remove-field" onClick={onRemove(i)}>X</a>
|
|
||||||
</div>
|
|
||||||
))
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const App = React.createClass({
|
|
||||||
getInitialState() {
|
|
||||||
return { fields: [], canSubmit: false };
|
|
||||||
},
|
|
||||||
submit(data) {
|
|
||||||
alert(JSON.stringify(data, null, 4));
|
|
||||||
},
|
|
||||||
addField(fieldData) {
|
|
||||||
fieldData.validations = fieldData.validations.length ?
|
|
||||||
fieldData.validations.reduce((a, b) => Object.assign({}, a, b)) :
|
|
||||||
null;
|
|
||||||
fieldData.id = Date.now();
|
|
||||||
this.setState({ fields: this.state.fields.concat(fieldData) });
|
|
||||||
},
|
|
||||||
removeField(pos) {
|
|
||||||
const fields = this.state.fields;
|
|
||||||
this.setState({ fields: fields.slice(0, pos).concat(fields.slice(pos+1)) })
|
|
||||||
},
|
|
||||||
enableButton() {
|
|
||||||
this.setState({ canSubmit: true });
|
|
||||||
},
|
|
||||||
disableButton() {
|
|
||||||
this.setState({ canSubmit: false });
|
|
||||||
},
|
|
||||||
render() {
|
|
||||||
const { fields, canSubmit } = this.state;
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<Form onSubmit={this.addField} className="many-fields-conf">
|
|
||||||
<MyMultiCheckboxSet name="validations" title="Validations"
|
|
||||||
cmp={(a, b) => JSON.stringify(a) === JSON.stringify(b)}
|
|
||||||
items={[
|
|
||||||
{isEmail: true},
|
|
||||||
{isEmptyString: true},
|
|
||||||
{isNumeric: true},
|
|
||||||
{isAlphanumeric: true},
|
|
||||||
{equals: 5},
|
|
||||||
{minLength: 3},
|
|
||||||
{maxLength: 7}
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
<MyRadioGroup name="required" value={false} title="Required"
|
|
||||||
items={[true, false]} />
|
|
||||||
<MyRadioGroup name="type" value="input" title="Type"
|
|
||||||
items={['input', 'select']} />
|
|
||||||
<button type="submit">Add</button>
|
|
||||||
</Form>
|
|
||||||
<Form onSubmit={this.submit} onValid={this.enableButton} onInvalid={this.disableButton} className="many-fields">
|
|
||||||
<Fields data={fields} onRemove={this.removeField} />
|
|
||||||
<button type="submit" disabled={!canSubmit}>Submit</button>
|
|
||||||
</Form>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
ReactDOM.render(<App/>, document.getElementById('example'));
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
<!doctype html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Dynamic Form Fields</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> / Dynamic Form Fields</h1>
|
|
||||||
<div id="example"/>
|
|
||||||
<script src="/__build__/shared.js"></script>
|
|
||||||
<script src="/__build__/dynamic-form-fields.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
@ -49,28 +49,11 @@ form {
|
||||||
color: #555;
|
color: #555;
|
||||||
background-color: #FFF;
|
background-color: #FFF;
|
||||||
background-image: none;
|
background-image: none;
|
||||||
border: 2px solid #CCC;
|
border: 1px solid #CCC;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-group.error input[type='text'],
|
|
||||||
.form-group.error input[type='email'],
|
|
||||||
.form-group.error input[type='number'],
|
|
||||||
.form-group.error input[type='password'],
|
|
||||||
.form-group.error select {
|
|
||||||
border-color: red;
|
|
||||||
color: red;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-group.required input[type='text'],
|
|
||||||
.form-group.required input[type='email'],
|
|
||||||
.form-group.required input[type='number'],
|
|
||||||
.form-group.required input[type='password'],
|
|
||||||
.form-group.required select {
|
|
||||||
border-color: #FF9696;
|
|
||||||
}
|
|
||||||
|
|
||||||
.validation-error {
|
.validation-error {
|
||||||
color: red;
|
color: red;
|
||||||
margin: 5px 0;
|
margin: 5px 0;
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@
|
||||||
<li><a href="login/index.html">Login Page</a></li>
|
<li><a href="login/index.html">Login Page</a></li>
|
||||||
<li><a href="custom-validation/index.html">Custom Validation</a></li>
|
<li><a href="custom-validation/index.html">Custom Validation</a></li>
|
||||||
<li><a href="reset-values/index.html">Reset Values</a></li>
|
<li><a href="reset-values/index.html">Reset Values</a></li>
|
||||||
<li><a href="dynamic-form-fields/index.html">Dynamic Form Fields</a></li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,8 @@ const App = React.createClass({
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Form onSubmit={this.submit} onValid={this.enableButton} onInvalid={this.disableButton} className="login">
|
<Form onSubmit={this.submit} onValid={this.enableButton} onInvalid={this.disableButton} className="login">
|
||||||
<MyInput value="" name="email" title="Email" validations="isEmail" validationError="This is not a valid email" required />
|
<MyInput name="email" title="Email" validations="isEmail" validationError="This is not a valid email" required />
|
||||||
<MyInput value="" name="password" title="Password" type="password" required />
|
<MyInput name="password" title="Password" type="password" required />
|
||||||
<button type="submit" disabled={!this.state.canSubmit}>Submit</button>
|
<button type="submit" disabled={!this.state.canSubmit}>Submit</button>
|
||||||
</Form>
|
</Form>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
37
package.json
37
package.json
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "formsy-react",
|
"name": "formsy-react",
|
||||||
"version": "0.19.5",
|
"version": "0.15.1",
|
||||||
"description": "A form input builder and validator for React JS",
|
"description": "A form input builder and validator for React JS",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
@ -8,8 +8,9 @@
|
||||||
},
|
},
|
||||||
"main": "lib/main.js",
|
"main": "lib/main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "NODE_ENV=production webpack -p --config webpack.production.config.js",
|
"start": "webpack-dev-server --content-base build",
|
||||||
"test": "babel-node testrunner",
|
"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",
|
"examples": "webpack-dev-server --config examples/webpack.config.js --content-base examples",
|
||||||
"prepublish": "babel ./src/ -d ./lib/"
|
"prepublish": "babel ./src/ -d ./lib/"
|
||||||
},
|
},
|
||||||
|
|
@ -23,27 +24,21 @@
|
||||||
"react-component"
|
"react-component"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"form-data-to-object": "^0.2.0"
|
"form-data-to-object": "^0.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"babel-cli": "^6.6.5",
|
"babel": "^5.6.4",
|
||||||
"babel-loader": "^6.2.4",
|
"babel-core": "^5.1.11",
|
||||||
"babel-preset-es2015": "^6.6.0",
|
"babel-loader": "^5.0.0",
|
||||||
"babel-preset-react": "^6.5.0",
|
"jasmine-node": "^1.14.5",
|
||||||
"babel-preset-stage-2": "^6.5.0",
|
"jsdom": "^3.1.2",
|
||||||
"create-react-class": "^15.6.0",
|
"react": "^0.14.0-beta3",
|
||||||
"jsdom": "^6.5.1",
|
"react-addons-test-utils": "^0.14.0-beta3",
|
||||||
"nodeunit": "^0.9.1",
|
"react-dom": "^0.14.0-beta3",
|
||||||
"prop-types": "^15.5.10",
|
"webpack": "^1.7.3",
|
||||||
"react": "^15.0.0",
|
"webpack-dev-server": "^1.7.0"
|
||||||
"react-addons-pure-render-mixin": "^15.0.0",
|
|
||||||
"react-addons-test-utils": "^15.0.0",
|
|
||||||
"react-dom": "^15.0.0",
|
|
||||||
"sinon": "^1.17.3",
|
|
||||||
"webpack": "^1.12.14",
|
|
||||||
"webpack-dev-server": "^1.14.1"
|
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": "^0.14.0 || ^15.0.0"
|
"react": "^0.14.0-beta3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -1,15 +1,13 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import TestUtils from 'react-addons-test-utils';
|
import TestUtils from 'react-addons-test-utils';
|
||||||
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
|
||||||
import sinon from 'sinon';
|
|
||||||
|
|
||||||
import Formsy from './..';
|
import Formsy from './..';
|
||||||
import TestInput, { InputFactory } from './utils/TestInput';
|
import TestInput, { customizeInput } from './utils/TestInput';
|
||||||
import immediate from './utils/immediate';
|
import immediate from './utils/immediate';
|
||||||
|
|
||||||
export default {
|
describe('Element', function () {
|
||||||
|
|
||||||
'should return passed and setValue() value when using getValue()': function (test) {
|
it('should return passed and setValue() value when using getValue()', function () {
|
||||||
|
|
||||||
const form = TestUtils.renderIntoDocument(
|
const form = TestUtils.renderIntoDocument(
|
||||||
<Formsy.Form>
|
<Formsy.Form>
|
||||||
|
|
@ -18,18 +16,16 @@ export default {
|
||||||
);
|
);
|
||||||
|
|
||||||
const input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
const input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||||
test.equal(input.value, 'foo');
|
expect(input.value).toBe('foo');
|
||||||
TestUtils.Simulate.change(input, {target: {value: 'foobar'}});
|
TestUtils.Simulate.change(input, {target: {value: 'foobar'}});
|
||||||
test.equal(input.value, 'foobar');
|
expect(input.value).toBe('foobar');
|
||||||
|
|
||||||
test.done();
|
});
|
||||||
|
|
||||||
},
|
it('should set back to pristine value when running reset', function () {
|
||||||
|
|
||||||
'should set back to pristine value when running reset': function (test) {
|
|
||||||
|
|
||||||
let reset = null;
|
let reset = null;
|
||||||
const Input = InputFactory({
|
const Input = customizeInput({
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
reset = this.resetValue;
|
reset = this.resetValue;
|
||||||
}
|
}
|
||||||
|
|
@ -43,16 +39,14 @@ export default {
|
||||||
const input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
const input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||||
TestUtils.Simulate.change(input, {target: {value: 'foobar'}});
|
TestUtils.Simulate.change(input, {target: {value: 'foobar'}});
|
||||||
reset();
|
reset();
|
||||||
test.equal(input.value, 'foo');
|
expect(input.value).toBe('foo');
|
||||||
|
|
||||||
test.done();
|
});
|
||||||
|
|
||||||
},
|
it('should return error message passed when calling getErrorMessage()', function () {
|
||||||
|
|
||||||
'should return error message passed when calling getErrorMessage()': function (test) {
|
|
||||||
|
|
||||||
let getErrorMessage = null;
|
let getErrorMessage = null;
|
||||||
const Input = InputFactory({
|
const Input = customizeInput({
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
getErrorMessage = this.getErrorMessage;
|
getErrorMessage = this.getErrorMessage;
|
||||||
}
|
}
|
||||||
|
|
@ -63,16 +57,14 @@ export default {
|
||||||
</Formsy.Form>
|
</Formsy.Form>
|
||||||
);
|
);
|
||||||
|
|
||||||
test.equal(getErrorMessage(), 'Has to be email');
|
expect(getErrorMessage()).toBe('Has to be email');
|
||||||
|
|
||||||
test.done();
|
});
|
||||||
|
|
||||||
},
|
it('should return true or false when calling isValid() depending on valid state', function () {
|
||||||
|
|
||||||
'should return true or false when calling isValid() depending on valid state': function (test) {
|
|
||||||
|
|
||||||
let isValid = null;
|
let isValid = null;
|
||||||
const Input = InputFactory({
|
const Input = customizeInput({
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
isValid = this.isValid;
|
isValid = this.isValid;
|
||||||
}
|
}
|
||||||
|
|
@ -83,19 +75,17 @@ export default {
|
||||||
</Formsy.Form>
|
</Formsy.Form>
|
||||||
);
|
);
|
||||||
|
|
||||||
test.equal(isValid(), false);
|
expect(isValid()).toBe(false);
|
||||||
const input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
const input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||||
TestUtils.Simulate.change(input, {target: {value: 'foo@foo.com'}});
|
TestUtils.Simulate.change(input, {target: {value: 'foo@foo.com'}});
|
||||||
test.equal(isValid(), true);
|
expect(isValid()).toBe(true);
|
||||||
|
|
||||||
test.done();
|
});
|
||||||
|
|
||||||
},
|
it('should return true or false when calling isRequired() depending on passed required attribute', function () {
|
||||||
|
|
||||||
'should return true or false when calling isRequired() depending on passed required attribute': function (test) {
|
|
||||||
|
|
||||||
const isRequireds = [];
|
const isRequireds = [];
|
||||||
const Input = InputFactory({
|
const Input = customizeInput({
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
isRequireds.push(this.isRequired);
|
isRequireds.push(this.isRequired);
|
||||||
}
|
}
|
||||||
|
|
@ -108,18 +98,16 @@ export default {
|
||||||
</Formsy.Form>
|
</Formsy.Form>
|
||||||
);
|
);
|
||||||
|
|
||||||
test.equal(isRequireds[0](), false);
|
expect(isRequireds[0]()).toBe(false);
|
||||||
test.equal(isRequireds[1](), true);
|
expect(isRequireds[1]()).toBe(true);
|
||||||
test.equal(isRequireds[2](), true);
|
expect(isRequireds[2]()).toBe(true);
|
||||||
|
|
||||||
test.done();
|
});
|
||||||
|
|
||||||
},
|
it('should return true or false when calling showRequired() depending on input being empty and required is passed, or not', function () {
|
||||||
|
|
||||||
'should return true or false when calling showRequired() depending on input being empty and required is passed, or not': function (test) {
|
|
||||||
|
|
||||||
const showRequireds = [];
|
const showRequireds = [];
|
||||||
const Input = InputFactory({
|
const Input = customizeInput({
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
showRequireds.push(this.showRequired);
|
showRequireds.push(this.showRequired);
|
||||||
}
|
}
|
||||||
|
|
@ -132,18 +120,16 @@ export default {
|
||||||
</Formsy.Form>
|
</Formsy.Form>
|
||||||
);
|
);
|
||||||
|
|
||||||
test.equal(showRequireds[0](), false);
|
expect(showRequireds[0]()).toBe(false);
|
||||||
test.equal(showRequireds[1](), true);
|
expect(showRequireds[1]()).toBe(true);
|
||||||
test.equal(showRequireds[2](), false);
|
expect(showRequireds[2]()).toBe(false);
|
||||||
|
|
||||||
test.done();
|
});
|
||||||
|
|
||||||
},
|
it('should return true or false when calling isPristine() depending on input has been "touched" or not', function () {
|
||||||
|
|
||||||
'should return true or false when calling isPristine() depending on input has been "touched" or not': function (test) {
|
|
||||||
|
|
||||||
let isPristine = null;
|
let isPristine = null;
|
||||||
const Input = InputFactory({
|
const Input = customizeInput({
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
isPristine = this.isPristine;
|
isPristine = this.isPristine;
|
||||||
}
|
}
|
||||||
|
|
@ -154,16 +140,14 @@ export default {
|
||||||
</Formsy.Form>
|
</Formsy.Form>
|
||||||
);
|
);
|
||||||
|
|
||||||
test.equal(isPristine(), true);
|
expect(isPristine()).toBe(true);
|
||||||
const input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
const input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||||
TestUtils.Simulate.change(input, {target: {value: 'foo'}});
|
TestUtils.Simulate.change(input, {target: {value: 'foo'}});
|
||||||
test.equal(isPristine(), false);
|
expect(isPristine()).toBe(false);
|
||||||
|
|
||||||
test.done();
|
});
|
||||||
|
|
||||||
},
|
it('should allow an undefined value to be updated to a value', function (done) {
|
||||||
|
|
||||||
'should allow an undefined value to be updated to a value': function (test) {
|
|
||||||
|
|
||||||
const TestForm = React.createClass({
|
const TestForm = React.createClass({
|
||||||
getInitialState() {
|
getInitialState() {
|
||||||
|
|
@ -187,13 +171,13 @@ export default {
|
||||||
form.changeValue();
|
form.changeValue();
|
||||||
const input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
const input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||||
immediate(() => {
|
immediate(() => {
|
||||||
test.equal(input.value, 'foo');
|
expect(input.value).toBe('foo');
|
||||||
test.done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
},
|
});
|
||||||
|
|
||||||
'should be able to test a values validity': function (test) {
|
it('should be able to test a values validity', function () {
|
||||||
|
|
||||||
const TestForm = React.createClass({
|
const TestForm = React.createClass({
|
||||||
render() {
|
render() {
|
||||||
|
|
@ -207,13 +191,12 @@ export default {
|
||||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||||
|
|
||||||
const input = TestUtils.findRenderedComponentWithType(form, TestInput);
|
const input = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||||
test.equal(input.isValidValue('foo@bar.com'), true);
|
expect(input.isValidValue('foo@bar.com')).toBe(true);
|
||||||
test.equal(input.isValidValue('foo@bar'), false);
|
expect(input.isValidValue('foo@bar')).toBe(false);
|
||||||
test.done();
|
|
||||||
|
|
||||||
},
|
});
|
||||||
|
|
||||||
'should be able to use an object as validations property': function (test) {
|
it('should be able to use an object as validations property', function () {
|
||||||
|
|
||||||
const TestForm = React.createClass({
|
const TestForm = React.createClass({
|
||||||
render() {
|
render() {
|
||||||
|
|
@ -229,14 +212,12 @@ export default {
|
||||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||||
|
|
||||||
const input = TestUtils.findRenderedComponentWithType(form, TestInput);
|
const input = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||||
test.equal(input.isValidValue('foo@bar.com'), true);
|
expect(input.isValidValue('foo@bar.com')).toBe(true);
|
||||||
test.equal(input.isValidValue('foo@bar'), false);
|
expect(input.isValidValue('foo@bar')).toBe(false);
|
||||||
|
|
||||||
test.done();
|
});
|
||||||
|
|
||||||
},
|
it('should be able to pass complex values to a validation rule', function () {
|
||||||
|
|
||||||
'should be able to pass complex values to a validation rule': function (test) {
|
|
||||||
|
|
||||||
const TestForm = React.createClass({
|
const TestForm = React.createClass({
|
||||||
render() {
|
render() {
|
||||||
|
|
@ -252,16 +233,14 @@ export default {
|
||||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||||
|
|
||||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||||
test.equal(inputComponent.isValid(), true);
|
expect(inputComponent.isValid()).toBe(true);
|
||||||
const input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
const input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||||
TestUtils.Simulate.change(input, {target: {value: 'bar'}});
|
TestUtils.Simulate.change(input, {target: {value: 'bar'}});
|
||||||
test.equal(inputComponent.isValid(), false);
|
expect(inputComponent.isValid()).toBe(false);
|
||||||
|
|
||||||
test.done();
|
});
|
||||||
|
|
||||||
},
|
it('should be able to run a function to validate', function () {
|
||||||
|
|
||||||
'should be able to run a function to validate': function (test) {
|
|
||||||
|
|
||||||
const TestForm = React.createClass({
|
const TestForm = React.createClass({
|
||||||
customValidationA(values, value) {
|
customValidationA(values, value) {
|
||||||
|
|
@ -286,41 +265,16 @@ export default {
|
||||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||||
|
|
||||||
const inputComponent = TestUtils.scryRenderedComponentsWithType(form, TestInput);
|
const inputComponent = TestUtils.scryRenderedComponentsWithType(form, TestInput);
|
||||||
test.equal(inputComponent[0].isValid(), true);
|
expect(inputComponent[0].isValid()).toBe(true);
|
||||||
test.equal(inputComponent[1].isValid(), true);
|
expect(inputComponent[1].isValid()).toBe(true);
|
||||||
const input = TestUtils.scryRenderedDOMComponentsWithTag(form, 'INPUT');
|
const input = TestUtils.scryRenderedDOMComponentsWithTag(form, 'INPUT');
|
||||||
TestUtils.Simulate.change(input[0], {target: {value: 'bar'}});
|
TestUtils.Simulate.change(input[0], {target: {value: 'bar'}});
|
||||||
test.equal(inputComponent[0].isValid(), false);
|
expect(inputComponent[0].isValid()).toBe(false);
|
||||||
test.equal(inputComponent[1].isValid(), false);
|
expect(inputComponent[1].isValid()).toBe(false);
|
||||||
|
|
||||||
test.done();
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
'should not override error messages with error messages passed by form if passed eror messages is an empty object': function (test) {
|
|
||||||
|
|
||||||
const TestForm = React.createClass({
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<Formsy.Form validationErrors={{}}>
|
|
||||||
<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);
|
it('should override all error messages with error messages passed by form', function () {
|
||||||
test.equal(inputComponent.getErrorMessage(), 'bar3');
|
|
||||||
|
|
||||||
test.done();
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
'should override all error messages with error messages passed by form': function (test) {
|
|
||||||
|
|
||||||
const TestForm = React.createClass({
|
const TestForm = React.createClass({
|
||||||
render() {
|
render() {
|
||||||
|
|
@ -336,13 +290,11 @@ export default {
|
||||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||||
|
|
||||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||||
test.equal(inputComponent.getErrorMessage(), 'bar');
|
expect(inputComponent.getErrorMessage()).toBe('bar');
|
||||||
|
|
||||||
test.done();
|
});
|
||||||
|
|
||||||
},
|
it('should override validation rules with required rules', function () {
|
||||||
|
|
||||||
'should override validation rules with required rules': function (test) {
|
|
||||||
|
|
||||||
const TestForm = React.createClass({
|
const TestForm = React.createClass({
|
||||||
render() {
|
render() {
|
||||||
|
|
@ -366,13 +318,11 @@ export default {
|
||||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||||
|
|
||||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||||
test.equal(inputComponent.getErrorMessage(), 'bar3');
|
expect(inputComponent.getErrorMessage()).toBe('bar3');
|
||||||
|
|
||||||
test.done();
|
});
|
||||||
|
|
||||||
},
|
it('should fall back to default error message when non exist in validationErrors map', function () {
|
||||||
|
|
||||||
'should fall back to default error message when non exist in validationErrors map': function (test) {
|
|
||||||
|
|
||||||
const TestForm = React.createClass({
|
const TestForm = React.createClass({
|
||||||
render() {
|
render() {
|
||||||
|
|
@ -393,13 +343,11 @@ export default {
|
||||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||||
|
|
||||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||||
test.equal(inputComponent.getErrorMessage(), 'bar');
|
expect(inputComponent.getErrorMessage()).toBe('bar');
|
||||||
|
|
||||||
test.done();
|
});
|
||||||
|
|
||||||
},
|
it('should not be valid if it is required and required rule is true', function () {
|
||||||
|
|
||||||
'should not be valid if it is required and required rule is true': function (test) {
|
|
||||||
|
|
||||||
const TestForm = React.createClass({
|
const TestForm = React.createClass({
|
||||||
render() {
|
render() {
|
||||||
|
|
@ -415,13 +363,11 @@ export default {
|
||||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||||
|
|
||||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||||
test.equal(inputComponent.isValid(), false);
|
expect(inputComponent.isValid()).toBe(false);
|
||||||
|
|
||||||
test.done();
|
});
|
||||||
|
|
||||||
},
|
it('should handle objects and arrays as values', function () {
|
||||||
|
|
||||||
'should handle objects and arrays as values': function (test) {
|
|
||||||
|
|
||||||
const TestForm = React.createClass({
|
const TestForm = React.createClass({
|
||||||
getInitialState() {
|
getInitialState() {
|
||||||
|
|
@ -447,14 +393,12 @@ export default {
|
||||||
});
|
});
|
||||||
|
|
||||||
const inputs = TestUtils.scryRenderedComponentsWithType(form, TestInput);
|
const inputs = TestUtils.scryRenderedComponentsWithType(form, TestInput);
|
||||||
test.deepEqual(inputs[0].getValue(), {foo: 'foo'});
|
expect(inputs[0].getValue()).toEqual({foo: 'foo'});
|
||||||
test.deepEqual(inputs[1].getValue(), ['bar']);
|
expect(inputs[1].getValue()).toEqual(['bar']);
|
||||||
|
|
||||||
test.done();
|
});
|
||||||
|
|
||||||
},
|
it('should handle isFormDisabled with dynamic inputs', function () {
|
||||||
|
|
||||||
'should handle isFormDisabled with dynamic inputs': function (test) {
|
|
||||||
|
|
||||||
const TestForm = React.createClass({
|
const TestForm = React.createClass({
|
||||||
getInitialState() {
|
getInitialState() {
|
||||||
|
|
@ -481,19 +425,17 @@ export default {
|
||||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||||
|
|
||||||
const input = TestUtils.findRenderedComponentWithType(form, TestInput);
|
const input = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||||
test.equal(input.isFormDisabled(), true);
|
expect(input.isFormDisabled()).toBe(true);
|
||||||
form.flip();
|
form.flip();
|
||||||
test.equal(input.isFormDisabled(), false);
|
expect(input.isFormDisabled()).toBe(false);
|
||||||
|
|
||||||
test.done();
|
});
|
||||||
|
|
||||||
},
|
it('should allow for dot notation in name which maps to a deep object', function () {
|
||||||
|
|
||||||
'should allow for dot notation in name which maps to a deep object': function (test) {
|
|
||||||
|
|
||||||
const TestForm = React.createClass({
|
const TestForm = React.createClass({
|
||||||
onSubmit(model) {
|
onSubmit(model) {
|
||||||
test.deepEqual(model, {foo: {bar: 'foo', test: 'test'}});
|
expect(model).toEqual({foo: {bar: 'foo', test: 'test'}});
|
||||||
},
|
},
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
|
|
@ -506,20 +448,16 @@ export default {
|
||||||
});
|
});
|
||||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||||
|
|
||||||
test.expect(1);
|
|
||||||
|
|
||||||
const formEl = TestUtils.findRenderedDOMComponentWithTag(form, 'form');
|
const formEl = TestUtils.findRenderedDOMComponentWithTag(form, 'form');
|
||||||
TestUtils.Simulate.submit(formEl);
|
TestUtils.Simulate.submit(formEl);
|
||||||
|
|
||||||
test.done();
|
});
|
||||||
|
|
||||||
},
|
it('should allow for application/x-www-form-urlencoded syntax and convert to object', function () {
|
||||||
|
|
||||||
'should allow for application/x-www-form-urlencoded syntax and convert to object': function (test) {
|
|
||||||
|
|
||||||
const TestForm = React.createClass({
|
const TestForm = React.createClass({
|
||||||
onSubmit(model) {
|
onSubmit(model) {
|
||||||
test.deepEqual(model, {foo: ['foo', 'bar']});
|
expect(model).toEqual({foo: ['foo', 'bar']});
|
||||||
},
|
},
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
|
|
@ -532,37 +470,9 @@ export default {
|
||||||
});
|
});
|
||||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||||
|
|
||||||
test.expect(1);
|
|
||||||
|
|
||||||
const formEl = TestUtils.findRenderedDOMComponentWithTag(form, 'form');
|
const formEl = TestUtils.findRenderedDOMComponentWithTag(form, 'form');
|
||||||
TestUtils.Simulate.submit(formEl);
|
TestUtils.Simulate.submit(formEl);
|
||||||
|
|
||||||
test.done();
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
'input should rendered once with PureRenderMixin': function (test) {
|
|
||||||
|
|
||||||
var renderSpy = sinon.spy();
|
|
||||||
|
|
||||||
const Input = InputFactory({
|
|
||||||
mixins: [Formsy.Mixin, PureRenderMixin],
|
|
||||||
render() {
|
|
||||||
renderSpy();
|
|
||||||
return <input type={this.props.type} value={this.getValue()} onChange={this.updateValue}/>;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const form = TestUtils.renderIntoDocument(
|
});
|
||||||
<Formsy.Form>
|
|
||||||
<Input name="foo" value="foo"/>
|
|
||||||
</Formsy.Form>
|
|
||||||
);
|
|
||||||
|
|
||||||
test.equal(renderSpy.calledOnce, true);
|
|
||||||
|
|
||||||
test.done();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
@ -0,0 +1,519 @@
|
||||||
|
import React from 'react';
|
||||||
|
import TestUtils from 'react-addons-test-utils';
|
||||||
|
|
||||||
|
import Formsy from './..';
|
||||||
|
import TestInput from './utils/TestInput';
|
||||||
|
import immediate from './utils/immediate';
|
||||||
|
|
||||||
|
describe('Formsy', function () {
|
||||||
|
|
||||||
|
describe('Setting up a form', function () {
|
||||||
|
|
||||||
|
it('should render a form into the document', function () {
|
||||||
|
const form = TestUtils.renderIntoDocument(<Formsy.Form></Formsy.Form>);
|
||||||
|
expect(React.findDOMNode(form).tagName).toEqual('FORM');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set a class name if passed', function () {
|
||||||
|
const form = TestUtils.renderIntoDocument( <Formsy.Form className="foo"></Formsy.Form>);
|
||||||
|
expect(React.findDOMNode(form).className).toEqual('foo');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should allow for null/undefined children', function (done) {
|
||||||
|
|
||||||
|
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(React.findDOMNode(form));
|
||||||
|
expect(model).toEqual({name: 'foo'});
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should allow for inputs being added dynamically', function (done) {
|
||||||
|
|
||||||
|
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(React.findDOMNode(form));
|
||||||
|
expect(model.test).toBeDefined();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
}, 10);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should allow dynamically added inputs to update the form-model', function (done) {
|
||||||
|
|
||||||
|
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(React.findDOMNode(form));
|
||||||
|
expect(model.test).toBe('foo');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should allow a dynamically updated input to update the form-model', function (done) {
|
||||||
|
|
||||||
|
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(React.findDOMNode(form));
|
||||||
|
expect(model.test).toBe('bar');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('validations', function () {
|
||||||
|
let CheckValid, onSubmit, OtherCheckValid;
|
||||||
|
let isValid;
|
||||||
|
|
||||||
|
const TestForm = React.createClass({
|
||||||
|
getDefaultProps() {
|
||||||
|
return { inputs: [] };
|
||||||
|
},
|
||||||
|
render() {
|
||||||
|
const builtInputs = this.props.inputs.map((input) => <TestInput { ...input } key={ input.name } />);
|
||||||
|
return (
|
||||||
|
<Formsy.Form
|
||||||
|
onSubmit={(arg1) => onSubmit(arg1)}
|
||||||
|
onValid={() => (isValid = true)}
|
||||||
|
onInvalid={() => (isValid = false)}>
|
||||||
|
{ builtInputs }
|
||||||
|
</Formsy.Form>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
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 () {
|
||||||
|
const inputs = [{name: 'one', validations: 'CheckValid', value: 'foo'}];
|
||||||
|
const form = TestUtils.renderIntoDocument(<TestForm inputs={inputs}/>);
|
||||||
|
const input = TestUtils.findRenderedDOMComponentWithTag(form, 'input');
|
||||||
|
TestUtils.Simulate.change(React.findDOMNode(input), {target: {value: 'bar'}});
|
||||||
|
expect(CheckValid).toHaveBeenCalledWith({one: 'bar'}, 'bar', true);
|
||||||
|
expect(OtherCheckValid).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should allow the validation to be changed', function () {
|
||||||
|
const inputs = [{name: 'one', validations: 'CheckValid', value: 'foo'}];
|
||||||
|
const form = TestUtils.renderIntoDocument(<TestForm inputs={inputs}/>);
|
||||||
|
form.setProps({inputs: [{name: 'one', validations: 'OtherCheckValid', value: 'foo'}] });
|
||||||
|
const input = TestUtils.findRenderedDOMComponentWithTag(form, 'input');
|
||||||
|
TestUtils.Simulate.change(React.findDOMNode(input), {target: {value: 'bar'}});
|
||||||
|
expect(OtherCheckValid).toHaveBeenCalledWith({one: 'bar'}, 'bar', true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should invalidate a form if dynamically inserted input is invalid', function (done) {
|
||||||
|
const inputs = [{name: 'one', validations: 'isEmail', value: 'foo@bar.com'}];
|
||||||
|
const form = TestUtils.renderIntoDocument(<TestForm inputs={inputs}/>);
|
||||||
|
expect(isValid).toEqual(true);
|
||||||
|
form.setProps({inputs: [
|
||||||
|
{name: 'one', validations: 'isEmail', value: 'foo@bar.com'},
|
||||||
|
{name: 'two', validations: 'isEmail', value: 'foo@bar'}
|
||||||
|
]}, () => {
|
||||||
|
immediate(() => {
|
||||||
|
expect(isValid).toEqual(false);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should validate a form when removing an invalid input', function (done) {
|
||||||
|
const 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'}]}, () => {
|
||||||
|
immediate(() => {
|
||||||
|
expect(isValid).toEqual(true);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('runs multiple validations', function () {
|
||||||
|
const inputs = [{name: 'one', validations: 'CheckValid,OtherCheckValid', value: 'foo'}];
|
||||||
|
const form = TestUtils.renderIntoDocument(<TestForm inputs={inputs}/>);
|
||||||
|
const input = TestUtils.findRenderedDOMComponentWithTag(form, 'input');
|
||||||
|
TestUtils.Simulate.change(React.findDOMNode(input), {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 () {
|
||||||
|
const hasChanged = jasmine.createSpy('onChange');
|
||||||
|
const TestForm = React.createClass({
|
||||||
|
render() {
|
||||||
|
return <Formsy.Form onChange={hasChanged}></Formsy.Form>;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
TestUtils.renderIntoDocument(<TestForm/>);
|
||||||
|
expect(hasChanged).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should trigger onChange when form element is changed', function () {
|
||||||
|
const hasChanged = jasmine.createSpy('onChange');
|
||||||
|
const TestForm = React.createClass({
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Formsy.Form onChange={hasChanged}>
|
||||||
|
<TestInput name="foo"/>
|
||||||
|
</Formsy.Form>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const 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) {
|
||||||
|
const hasChanged = jasmine.createSpy('onChange');
|
||||||
|
const inputs = [];
|
||||||
|
let forceUpdate = null;
|
||||||
|
const TestForm = React.createClass({
|
||||||
|
componentWillMount() {
|
||||||
|
forceUpdate = this.forceUpdate.bind(this);
|
||||||
|
},
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Formsy.Form onChange={hasChanged}>
|
||||||
|
{inputs}
|
||||||
|
</Formsy.Form>);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
TestUtils.renderIntoDocument(<TestForm/>);
|
||||||
|
|
||||||
|
// Wait before adding the input
|
||||||
|
inputs.push(<TestInput name="test" key={inputs.length}/>);
|
||||||
|
|
||||||
|
forceUpdate(() => {
|
||||||
|
|
||||||
|
// Wait for next event loop, as that does the form
|
||||||
|
immediate(() => {
|
||||||
|
expect(hasChanged).toHaveBeenCalled();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Update a form', function () {
|
||||||
|
|
||||||
|
it('should allow elements to check if the form is disabled', function (done) {
|
||||||
|
|
||||||
|
const TestForm = React.createClass({
|
||||||
|
getInitialState() { return { disabled: true }; },
|
||||||
|
enableForm() { this.setState({ disabled: false }); },
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Formsy.Form onChange={this.onChange} disabled={this.state.disabled}>
|
||||||
|
<TestInput name="foo"/>
|
||||||
|
</Formsy.Form>);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
||||||
|
|
||||||
|
const input = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||||
|
expect(input.isFormDisabled()).toBe(true);
|
||||||
|
|
||||||
|
form.enableForm();
|
||||||
|
immediate(() => {
|
||||||
|
expect(input.isFormDisabled()).toBe(false);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be possible to pass error state of elements by changing an errors attribute', function (done) {
|
||||||
|
|
||||||
|
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);
|
||||||
|
expect(input.getErrorMessage()).toBe('bar');
|
||||||
|
input.setValue('gotValue');
|
||||||
|
|
||||||
|
// Wait for update
|
||||||
|
immediate(() => {
|
||||||
|
expect(input.getErrorMessage()).toBe(null);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('should trigger an onValidSubmit when submitting a valid form', function () {
|
||||||
|
|
||||||
|
let isCalled = false;
|
||||||
|
const TestForm = React.createClass({
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Formsy.Form onValidSubmit={() => (isCalled = true)}>
|
||||||
|
<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(React.findDOMNode(FoundForm));
|
||||||
|
expect(isCalled).toBe(true);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should trigger an onInvalidSubmit when submitting an invalid form', function () {
|
||||||
|
|
||||||
|
let isCalled = false;
|
||||||
|
const TestForm = React.createClass({
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Formsy.Form onInvalidSubmit={() => (isCalled = true)}>
|
||||||
|
<TestInput name="foo" validations="isEmail" value="foo@bar"/>
|
||||||
|
</Formsy.Form>);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const form = TestUtils.renderIntoDocument(
|
||||||
|
<TestForm/>
|
||||||
|
);
|
||||||
|
|
||||||
|
const FoundForm = TestUtils.findRenderedComponentWithType(form, TestForm);
|
||||||
|
TestUtils.Simulate.submit(React.findDOMNode(FoundForm));
|
||||||
|
expect(isCalled).toBe(true);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("value === false", function () {
|
||||||
|
let onSubmit;
|
||||||
|
const TestForm = React.createClass({
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Formsy.Form onSubmit={(x) => onSubmit(x)}>
|
||||||
|
<TestInput name="foo" value={ this.props.value } type="checkbox" />
|
||||||
|
<button type="submit">Save</button>
|
||||||
|
</Formsy.Form>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
onSubmit = jasmine.createSpy('onSubmit');
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should call onSubmit correctly", function () {
|
||||||
|
const form = TestUtils.renderIntoDocument(<TestForm value={ false }/>);
|
||||||
|
TestUtils.Simulate.submit(React.findDOMNode(form));
|
||||||
|
expect(onSubmit).toHaveBeenCalledWith({foo: false});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should allow dynamic changes to false", function () {
|
||||||
|
const form = TestUtils.renderIntoDocument(<TestForm value={ true }/>);
|
||||||
|
form.setProps({value: false});
|
||||||
|
TestUtils.Simulate.submit(React.findDOMNode(form));
|
||||||
|
expect(onSubmit).toHaveBeenCalledWith({foo: false});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should say the form is submitted", function () {
|
||||||
|
const form = TestUtils.renderIntoDocument(<TestForm value={ true }/>);
|
||||||
|
const input = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||||
|
expect(input.isFormSubmitted()).toBe(false);
|
||||||
|
TestUtils.Simulate.submit(React.findDOMNode(form));
|
||||||
|
expect(input.isFormSubmitted()).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should be able to reset the form to its pristine state", function () {
|
||||||
|
const form = TestUtils.renderIntoDocument(<TestForm value={ true }/>);
|
||||||
|
const input = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||||
|
const 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 () {
|
||||||
|
const form = TestUtils.renderIntoDocument(<TestForm value={ true }/>);
|
||||||
|
const input = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||||
|
const 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 () {
|
||||||
|
let onChange;
|
||||||
|
|
||||||
|
const TestForm = React.createClass({
|
||||||
|
getDefaultProps() {
|
||||||
|
return { inputs: [] };
|
||||||
|
},
|
||||||
|
render() {
|
||||||
|
const builtInputs = this.props.inputs.map((input) => <TestInput {...input} key={input.name}/>);
|
||||||
|
return (
|
||||||
|
<Formsy.Form ref="formsy" onChange={ onChange }>
|
||||||
|
{ builtInputs }
|
||||||
|
{ this.props.children }
|
||||||
|
</Formsy.Form>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
onChange = jasmine.createSpy('onChange');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('initially returns false', function () {
|
||||||
|
const 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 () {
|
||||||
|
const form = TestUtils.renderIntoDocument(<TestForm inputs={ [{name: 'one', value: 'foo'}] }/>);
|
||||||
|
const input = TestUtils.findRenderedDOMComponentWithTag(form, 'input');
|
||||||
|
TestUtils.Simulate.change(React.findDOMNode(input), {target: {value: 'bar'}});
|
||||||
|
expect(form.refs.formsy.isChanged()).toEqual(true);
|
||||||
|
expect(onChange).toHaveBeenCalledWith({one: 'bar'}, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns false if changes are undone', function () {
|
||||||
|
const form = TestUtils.renderIntoDocument(<TestForm inputs={ [{name: 'one', value: 'foo'}] }/>);
|
||||||
|
const input = TestUtils.findRenderedDOMComponentWithTag(form, 'input');
|
||||||
|
TestUtils.Simulate.change(React.findDOMNode(input), {target: {value: 'bar'}});
|
||||||
|
expect(onChange).toHaveBeenCalledWith({one: 'bar'}, true);
|
||||||
|
TestUtils.Simulate.change(React.findDOMNode(input), {target: {value: 'foo'}});
|
||||||
|
expect(form.refs.formsy.isChanged()).toEqual(false);
|
||||||
|
expect(onChange).toHaveBeenCalledWith({one: 'foo'}, false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
import React from 'react';
|
||||||
|
import TestUtils from 'react-addons-test-utils';
|
||||||
|
|
||||||
|
import Formsy from './..';
|
||||||
|
import { customizeInput } from './utils/TestInput';
|
||||||
|
|
||||||
|
describe('Rules: equals', function () {
|
||||||
|
let Input, isValid, form, input;
|
||||||
|
|
||||||
|
function pass(value) {
|
||||||
|
return pass.length ? () => {
|
||||||
|
TestUtils.Simulate.change(input, {target: {value}});
|
||||||
|
expect(isValid).toBe(true);
|
||||||
|
} : () => expect(isValid).toBe(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function fail(value) {
|
||||||
|
return fail.length ? () => {
|
||||||
|
TestUtils.Simulate.change(input, {target: {value}});
|
||||||
|
expect(isValid).toBe(false);
|
||||||
|
} : () => expect(isValid).toBe(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
Input = customizeInput({
|
||||||
|
render() {
|
||||||
|
isValid = this.isValid();
|
||||||
|
return <input value={this.getValue()} onChange={this.updateValue}/>;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
form = TestUtils.renderIntoDocument(
|
||||||
|
<Formsy.Form>
|
||||||
|
<Input name="foo" validations="equals:myValue"/>
|
||||||
|
</Formsy.Form>
|
||||||
|
);
|
||||||
|
|
||||||
|
input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
Input = 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));
|
||||||
|
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
import React from 'react';
|
||||||
|
import TestUtils from 'react-addons-test-utils';
|
||||||
|
|
||||||
|
import Formsy from './..';
|
||||||
|
import { customizeInput } from './utils/TestInput';
|
||||||
|
|
||||||
|
describe('Rules: isAlpha', function () {
|
||||||
|
let Input, isValid, form, input;
|
||||||
|
|
||||||
|
function pass(value) {
|
||||||
|
return pass.length ? () => {
|
||||||
|
TestUtils.Simulate.change(input, {target: {value}});
|
||||||
|
expect(isValid).toBe(true);
|
||||||
|
} : () => expect(isValid).toBe(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function fail(value) {
|
||||||
|
return fail.length ? () => {
|
||||||
|
TestUtils.Simulate.change(input, {target: {value}});
|
||||||
|
expect(isValid).toBe(false);
|
||||||
|
} : () => expect(isValid).toBe(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
Input = customizeInput({
|
||||||
|
render() {
|
||||||
|
isValid = this.isValid();
|
||||||
|
return <input value={this.getValue()} onChange={this.updateValue}/>;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
form = TestUtils.renderIntoDocument(
|
||||||
|
<Formsy.Form>
|
||||||
|
<Input name="foo" validations="isAlpha"/>
|
||||||
|
</Formsy.Form>
|
||||||
|
);
|
||||||
|
|
||||||
|
input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
Input = 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('myValue42'));
|
||||||
|
|
||||||
|
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));
|
||||||
|
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
import React from 'react';
|
||||||
|
import TestUtils from 'react-addons-test-utils';
|
||||||
|
|
||||||
|
import Formsy from './..';
|
||||||
|
import { customizeInput } from './utils/TestInput';
|
||||||
|
|
||||||
|
describe('Rules: isAlphanumeric', function () {
|
||||||
|
let Input, isValid, form, input;
|
||||||
|
|
||||||
|
function pass(value) {
|
||||||
|
return pass.length ? () => {
|
||||||
|
TestUtils.Simulate.change(input, {target: {value}});
|
||||||
|
expect(isValid).toBe(true);
|
||||||
|
} : () => expect(isValid).toBe(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function fail(value) {
|
||||||
|
return fail.length ? () => {
|
||||||
|
TestUtils.Simulate.change(input, {target: {value}});
|
||||||
|
expect(isValid).toBe(false);
|
||||||
|
} : () => expect(isValid).toBe(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
Input = customizeInput({
|
||||||
|
render() {
|
||||||
|
isValid = this.isValid();
|
||||||
|
return <input value={this.getValue()} onChange={this.updateValue}/>;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
form = TestUtils.renderIntoDocument(
|
||||||
|
<Formsy.Form>
|
||||||
|
<Input name="foo" validations="isAlphanumeric"/>
|
||||||
|
</Formsy.Form>
|
||||||
|
);
|
||||||
|
|
||||||
|
input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
Input = 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 pass with a string with numbers', pass('myValue42'));
|
||||||
|
|
||||||
|
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 pass with a number', pass(42));
|
||||||
|
|
||||||
|
it('should fail with a non alpha and number symbols', fail('!@#$%^&*()'));
|
||||||
|
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
import React from 'react';
|
||||||
|
import TestUtils from 'react-addons-test-utils';
|
||||||
|
|
||||||
|
import Formsy from './..';
|
||||||
|
import { customizeInput } from './utils/TestInput';
|
||||||
|
|
||||||
|
describe('Rules: isEmail', function () {
|
||||||
|
let Input, isValid, form, input;
|
||||||
|
|
||||||
|
function pass(value) {
|
||||||
|
return pass.length ? () => {
|
||||||
|
TestUtils.Simulate.change(input, {target: {value}});
|
||||||
|
expect(isValid).toBe(true);
|
||||||
|
} : () => expect(isValid).toBe(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function fail(value) {
|
||||||
|
return fail.length ? () => {
|
||||||
|
TestUtils.Simulate.change(input, {target: {value}});
|
||||||
|
expect(isValid).toBe(false);
|
||||||
|
} : () => expect(isValid).toBe(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
Input = customizeInput({
|
||||||
|
render() {
|
||||||
|
isValid = this.isValid();
|
||||||
|
return <input value={this.getValue()} onChange={this.updateValue}/>;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
form = TestUtils.renderIntoDocument(
|
||||||
|
<Formsy.Form>
|
||||||
|
<Input name="foo" value="foo" validations="isEmail"/>
|
||||||
|
</Formsy.Form>
|
||||||
|
);
|
||||||
|
|
||||||
|
input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
Input = 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));
|
||||||
|
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
import React from 'react';
|
||||||
|
import TestUtils from 'react-addons-test-utils';
|
||||||
|
|
||||||
|
import Formsy from './..';
|
||||||
|
import { customizeInput } from './utils/TestInput';
|
||||||
|
|
||||||
|
describe('Rules: isEmptyString', function () {
|
||||||
|
let Input, isValid, form, input;
|
||||||
|
|
||||||
|
function pass(value) {
|
||||||
|
return pass.length ? () => {
|
||||||
|
TestUtils.Simulate.change(input, {target: {value}});
|
||||||
|
expect(isValid).toBe(true);
|
||||||
|
} : () => expect(isValid).toBe(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function fail(value) {
|
||||||
|
return fail.length ? () => {
|
||||||
|
TestUtils.Simulate.change(input, {target: {value}});
|
||||||
|
expect(isValid).toBe(false);
|
||||||
|
} : () => expect(isValid).toBe(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
Input = customizeInput({
|
||||||
|
render() {
|
||||||
|
isValid = this.isValid();
|
||||||
|
return <input value={this.getValue()} onChange={this.updateValue}/>;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
form = TestUtils.renderIntoDocument(
|
||||||
|
<Formsy.Form>
|
||||||
|
<Input name="foo" validations="isEmptyString"/>
|
||||||
|
</Formsy.Form>
|
||||||
|
);
|
||||||
|
|
||||||
|
input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
Input = 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));
|
||||||
|
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
import React from 'react';
|
||||||
|
import TestUtils from 'react-addons-test-utils';
|
||||||
|
|
||||||
|
import Formsy from './..';
|
||||||
|
import { customizeInput } from './utils/TestInput';
|
||||||
|
|
||||||
|
describe('Rules: isExisty', function () {
|
||||||
|
let Input, isValid, form, input;
|
||||||
|
|
||||||
|
function pass(value) {
|
||||||
|
return pass.length ? () => {
|
||||||
|
TestUtils.Simulate.change(input, {target: {value}});
|
||||||
|
expect(isValid).toBe(true);
|
||||||
|
} : () => expect(isValid).toBe(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function fail(value) {
|
||||||
|
return fail.length ? () => {
|
||||||
|
TestUtils.Simulate.change(input, {target: {value}});
|
||||||
|
expect(isValid).toBe(false);
|
||||||
|
} : () => expect(isValid).toBe(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
Input = customizeInput({
|
||||||
|
render() {
|
||||||
|
isValid = this.isValid();
|
||||||
|
return <input value={this.getValue()} onChange={this.updateValue}/>;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
form = TestUtils.renderIntoDocument(
|
||||||
|
<Formsy.Form>
|
||||||
|
<Input name="foo" validations="isExisty"/>
|
||||||
|
</Formsy.Form>
|
||||||
|
);
|
||||||
|
|
||||||
|
input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
Input = 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));
|
||||||
|
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
import React from 'react';
|
||||||
|
import TestUtils from 'react-addons-test-utils';
|
||||||
|
|
||||||
|
import Formsy from './..';
|
||||||
|
import { customizeInput } from './utils/TestInput';
|
||||||
|
|
||||||
|
describe('Rules: isFloat', function () {
|
||||||
|
let Input, isValid, form, input;
|
||||||
|
|
||||||
|
function pass(value) {
|
||||||
|
return pass.length ? () => {
|
||||||
|
TestUtils.Simulate.change(input, {target: {value}});
|
||||||
|
expect(isValid).toBe(true);
|
||||||
|
} : () => expect(isValid).toBe(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function fail(value) {
|
||||||
|
return fail.length ? () => {
|
||||||
|
TestUtils.Simulate.change(input, {target: {value}});
|
||||||
|
expect(isValid).toBe(false);
|
||||||
|
} : () => expect(isValid).toBe(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
Input = customizeInput({
|
||||||
|
render() {
|
||||||
|
isValid = this.isValid();
|
||||||
|
return <input value={this.getValue()} onChange={this.updateValue}/>;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
form = TestUtils.renderIntoDocument(
|
||||||
|
<Formsy.Form>
|
||||||
|
<Input name="foo" validations="isFloat"/>
|
||||||
|
</Formsy.Form>
|
||||||
|
);
|
||||||
|
|
||||||
|
input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
Input = 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 a float in science notation', pass('-1e3'));
|
||||||
|
|
||||||
|
it('should pass with an undefined', pass(undefined));
|
||||||
|
|
||||||
|
it('should pass with a null', pass(null));
|
||||||
|
|
||||||
|
it('should pass with a zero', pass(0));
|
||||||
|
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
import React from 'react';
|
||||||
|
import TestUtils from 'react-addons-test-utils';
|
||||||
|
|
||||||
|
import Formsy from './..';
|
||||||
|
import { customizeInput } from './utils/TestInput';
|
||||||
|
|
||||||
|
describe('Rules: isInt', function () {
|
||||||
|
let Input, isValid, form, input;
|
||||||
|
|
||||||
|
function pass(value) {
|
||||||
|
return pass.length ? () => {
|
||||||
|
TestUtils.Simulate.change(input, {target: {value}});
|
||||||
|
expect(isValid).toBe(true);
|
||||||
|
} : () => expect(isValid).toBe(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function fail(value) {
|
||||||
|
return fail.length ? () => {
|
||||||
|
TestUtils.Simulate.change(input, {target: {value}});
|
||||||
|
expect(isValid).toBe(false);
|
||||||
|
} : () => expect(isValid).toBe(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
Input = customizeInput({
|
||||||
|
render() {
|
||||||
|
isValid = this.isValid();
|
||||||
|
return <input value={this.getValue()} onChange={this.updateValue}/>;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
form = TestUtils.renderIntoDocument(
|
||||||
|
<Formsy.Form>
|
||||||
|
<Input name="foo" validations="isInt"/>
|
||||||
|
</Formsy.Form>
|
||||||
|
);
|
||||||
|
|
||||||
|
input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
Input = 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 fail with a float', fail(Math.PI));
|
||||||
|
|
||||||
|
it('should fail with a float in science notation', fail('-1e3'));
|
||||||
|
|
||||||
|
it('should pass with an undefined', pass(undefined));
|
||||||
|
|
||||||
|
it('should pass with a null', pass(null));
|
||||||
|
|
||||||
|
it('should pass with a zero', pass(0));
|
||||||
|
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,93 @@
|
||||||
|
import React from 'react';
|
||||||
|
import TestUtils from 'react-addons-test-utils';
|
||||||
|
|
||||||
|
import Formsy from './..';
|
||||||
|
import { customizeInput } from './utils/TestInput';
|
||||||
|
|
||||||
|
describe('Rules: isLength', function () {
|
||||||
|
let Input, isValid, form, input;
|
||||||
|
|
||||||
|
function pass(value) {
|
||||||
|
return pass.length ? () => {
|
||||||
|
TestUtils.Simulate.change(input, {target: {value}});
|
||||||
|
expect(isValid).toBe(true);
|
||||||
|
} : () => expect(isValid).toBe(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function fail(value) {
|
||||||
|
return fail.length ? () => {
|
||||||
|
TestUtils.Simulate.change(input, {target: {value}});
|
||||||
|
expect(isValid).toBe(false);
|
||||||
|
} : () => expect(isValid).toBe(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
Input = customizeInput({
|
||||||
|
render() {
|
||||||
|
isValid = this.isValid();
|
||||||
|
return <input value={this.getValue()} onChange={this.updateValue}/>;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
Input = isValid = form = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('isLength:3', () => {
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
form = TestUtils.renderIntoDocument(
|
||||||
|
<Formsy.Form>
|
||||||
|
<Input 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', () => {
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
form = TestUtils.renderIntoDocument(
|
||||||
|
<Formsy.Form>
|
||||||
|
<Input 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));
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
import React from 'react';
|
||||||
|
import TestUtils from 'react-addons-test-utils';
|
||||||
|
|
||||||
|
import Formsy from './..';
|
||||||
|
import { customizeInput } from './utils/TestInput';
|
||||||
|
|
||||||
|
describe('Rules: isNumeric', function () {
|
||||||
|
let Input, isValid, form, input;
|
||||||
|
|
||||||
|
function pass(value) {
|
||||||
|
return pass.length ? () => {
|
||||||
|
TestUtils.Simulate.change(input, {target: {value}});
|
||||||
|
expect(isValid).toBe(true);
|
||||||
|
} : () => expect(isValid).toBe(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function fail(value) {
|
||||||
|
return fail.length ? () => {
|
||||||
|
TestUtils.Simulate.change(input, {target: {value}});
|
||||||
|
expect(isValid).toBe(false);
|
||||||
|
} : () => expect(isValid).toBe(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
Input = customizeInput({
|
||||||
|
render() {
|
||||||
|
isValid = this.isValid();
|
||||||
|
return <input value={this.getValue()} onChange={this.updateValue}/>;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
form = TestUtils.renderIntoDocument(
|
||||||
|
<Formsy.Form>
|
||||||
|
<Input name="foo" validations="isNumeric"/>
|
||||||
|
</Formsy.Form>
|
||||||
|
);
|
||||||
|
|
||||||
|
input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
Input = 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 fail with a float in science notation', fail('-1e3'));
|
||||||
|
|
||||||
|
it('should pass with an undefined', pass(undefined));
|
||||||
|
|
||||||
|
it('should pass with a null', pass(null));
|
||||||
|
|
||||||
|
it('should pass with a zero', pass(0));
|
||||||
|
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
import React from 'react';
|
||||||
|
import TestUtils from 'react-addons-test-utils';
|
||||||
|
|
||||||
|
import Formsy from './..';
|
||||||
|
import { customizeInput } from './utils/TestInput';
|
||||||
|
|
||||||
|
describe('Rules: isUrl', function () {
|
||||||
|
let Input, isValid, form, input;
|
||||||
|
|
||||||
|
function pass(value) {
|
||||||
|
return pass.length ? () => {
|
||||||
|
TestUtils.Simulate.change(input, {target: {value}});
|
||||||
|
expect(isValid).toBe(true);
|
||||||
|
} : () => expect(isValid).toBe(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function fail(value) {
|
||||||
|
return fail.length ? () => {
|
||||||
|
TestUtils.Simulate.change(input, {target: {value}});
|
||||||
|
expect(isValid).toBe(false);
|
||||||
|
} : () => expect(isValid).toBe(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
Input = customizeInput({
|
||||||
|
render() {
|
||||||
|
isValid = this.isValid();
|
||||||
|
return <input value={this.getValue()} onChange={this.updateValue}/>;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
form = TestUtils.renderIntoDocument(
|
||||||
|
<Formsy.Form>
|
||||||
|
<Input name="foo" value="foo" validations="isUrl"/>
|
||||||
|
</Formsy.Form>
|
||||||
|
);
|
||||||
|
|
||||||
|
input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
Input = 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(''));
|
||||||
|
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
import React from 'react';
|
||||||
|
import TestUtils from 'react-addons-test-utils';
|
||||||
|
|
||||||
|
import Formsy from './..';
|
||||||
|
import { customizeInput } from './utils/TestInput';
|
||||||
|
|
||||||
|
describe('Rules: isWords', function () {
|
||||||
|
let Input, isValid, form, input;
|
||||||
|
|
||||||
|
function pass(value) {
|
||||||
|
return pass.length ? () => {
|
||||||
|
TestUtils.Simulate.change(input, {target: {value}});
|
||||||
|
expect(isValid).toBe(true);
|
||||||
|
} : () => expect(isValid).toBe(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function fail(value) {
|
||||||
|
return fail.length ? () => {
|
||||||
|
TestUtils.Simulate.change(input, {target: {value}});
|
||||||
|
expect(isValid).toBe(false);
|
||||||
|
} : () => expect(isValid).toBe(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
Input = customizeInput({
|
||||||
|
render() {
|
||||||
|
isValid = this.isValid();
|
||||||
|
return <input value={this.getValue()} onChange={this.updateValue}/>;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
form = TestUtils.renderIntoDocument(
|
||||||
|
<Formsy.Form>
|
||||||
|
<Input name="foo" validations="isWords"/>
|
||||||
|
</Formsy.Form>
|
||||||
|
);
|
||||||
|
|
||||||
|
input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
Input = 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));
|
||||||
|
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
import React from 'react';
|
||||||
|
import TestUtils from 'react-addons-test-utils';
|
||||||
|
|
||||||
|
import Formsy from './..';
|
||||||
|
import { customizeInput } from './utils/TestInput';
|
||||||
|
|
||||||
|
describe('Rules: maxLength', function () {
|
||||||
|
let Input, isValid, form, input;
|
||||||
|
|
||||||
|
function pass(value) {
|
||||||
|
return pass.length ? () => {
|
||||||
|
TestUtils.Simulate.change(input, {target: {value}});
|
||||||
|
expect(isValid).toBe(true);
|
||||||
|
} : () => expect(isValid).toBe(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function fail(value) {
|
||||||
|
return fail.length ? () => {
|
||||||
|
TestUtils.Simulate.change(input, {target: {value}});
|
||||||
|
expect(isValid).toBe(false);
|
||||||
|
} : () => expect(isValid).toBe(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
Input = customizeInput({
|
||||||
|
render() {
|
||||||
|
isValid = this.isValid();
|
||||||
|
return <input value={this.getValue()} onChange={this.updateValue}/>;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
form = TestUtils.renderIntoDocument(
|
||||||
|
<Formsy.Form>
|
||||||
|
<Input name="foo" validations="maxLength:3"/>
|
||||||
|
</Formsy.Form>
|
||||||
|
);
|
||||||
|
|
||||||
|
input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
Input = 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));
|
||||||
|
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,93 @@
|
||||||
|
import React from 'react';
|
||||||
|
import TestUtils from 'react-addons-test-utils';
|
||||||
|
|
||||||
|
import Formsy from './..';
|
||||||
|
import { customizeInput } from './utils/TestInput';
|
||||||
|
|
||||||
|
describe('Rules: minLength', function () {
|
||||||
|
let Input, isValid, form, input;
|
||||||
|
|
||||||
|
function pass(value) {
|
||||||
|
return pass.length ? () => {
|
||||||
|
TestUtils.Simulate.change(input, {target: {value}});
|
||||||
|
expect(isValid).toBe(true);
|
||||||
|
} : () => expect(isValid).toBe(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function fail(value) {
|
||||||
|
return fail.length ? () => {
|
||||||
|
TestUtils.Simulate.change(input, {target: {value}});
|
||||||
|
expect(isValid).toBe(false);
|
||||||
|
} : () => expect(isValid).toBe(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
Input = customizeInput({
|
||||||
|
render() {
|
||||||
|
isValid = this.isValid();
|
||||||
|
return <input value={this.getValue()} onChange={this.updateValue}/>;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
Input = isValid = form = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('minLength:3', function () {
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
form = TestUtils.renderIntoDocument(
|
||||||
|
<Formsy.Form>
|
||||||
|
<Input 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', () => {
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
form = TestUtils.renderIntoDocument(
|
||||||
|
<Formsy.Form>
|
||||||
|
<Input 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));
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
import utils from './../src/utils.js';
|
||||||
|
|
||||||
|
describe('Utils', function () {
|
||||||
|
|
||||||
|
it('should check equality of objects and arrays', () => {
|
||||||
|
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;
|
||||||
|
|
||||||
|
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);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
@ -2,13 +2,12 @@ import React from 'react';
|
||||||
import TestUtils from 'react-addons-test-utils';
|
import TestUtils from 'react-addons-test-utils';
|
||||||
|
|
||||||
import Formsy from './..';
|
import Formsy from './..';
|
||||||
import TestInput, {InputFactory} from './utils/TestInput';
|
import TestInput, { customizeInput } from './utils/TestInput';
|
||||||
import immediate from './utils/immediate';
|
import immediate from './utils/immediate';
|
||||||
import sinon from 'sinon';
|
|
||||||
|
|
||||||
export default {
|
describe('Validation', function () {
|
||||||
|
|
||||||
'should reset only changed form element when external error is passed': function (test) {
|
it('should reset only changed form element when external error is passed', function (done) {
|
||||||
|
|
||||||
const form = TestUtils.renderIntoDocument(
|
const form = TestUtils.renderIntoDocument(
|
||||||
<Formsy.Form onSubmit={(model, reset, invalidate) => invalidate({ foo: 'bar', bar: 'foo' })}>
|
<Formsy.Form onSubmit={(model, reset, invalidate) => invalidate({ foo: 'bar', bar: 'foo' })}>
|
||||||
|
|
@ -21,19 +20,19 @@ export default {
|
||||||
const inputComponents = TestUtils.scryRenderedComponentsWithType(form, TestInput);
|
const inputComponents = TestUtils.scryRenderedComponentsWithType(form, TestInput);
|
||||||
|
|
||||||
form.submit();
|
form.submit();
|
||||||
test.equal(inputComponents[0].isValid(), false);
|
expect(inputComponents[0].isValid()).toBe(false);
|
||||||
test.equal(inputComponents[1].isValid(), false);
|
expect(inputComponents[1].isValid()).toBe(false);
|
||||||
|
|
||||||
TestUtils.Simulate.change(input, {target: {value: 'bar'}});
|
TestUtils.Simulate.change(input, {target: {value: 'bar'}});
|
||||||
immediate(() => {
|
immediate(() => {
|
||||||
test.equal(inputComponents[0].isValid(), true);
|
expect(inputComponents[0].isValid()).toBe(true);
|
||||||
test.equal(inputComponents[1].isValid(), false);
|
expect(inputComponents[1].isValid()).toBe(false);
|
||||||
test.done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
},
|
});
|
||||||
|
|
||||||
'should let normal validation take over when component with external error is changed': function (test) {
|
it('should let normal validation take over when component with external error is changed', function (done) {
|
||||||
|
|
||||||
const form = TestUtils.renderIntoDocument(
|
const form = TestUtils.renderIntoDocument(
|
||||||
<Formsy.Form onSubmit={(model, reset, invalidate) => invalidate({ foo: 'bar' })}>
|
<Formsy.Form onSubmit={(model, reset, invalidate) => invalidate({ foo: 'bar' })}>
|
||||||
|
|
@ -45,21 +44,21 @@ export default {
|
||||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||||
|
|
||||||
form.submit();
|
form.submit();
|
||||||
test.equal(inputComponent.isValid(), false);
|
expect(inputComponent.isValid()).toBe(false);
|
||||||
|
|
||||||
TestUtils.Simulate.change(input, {target: {value: 'bar'}});
|
TestUtils.Simulate.change(input, {target: {value: 'bar'}});
|
||||||
immediate(() => {
|
immediate(() => {
|
||||||
test.equal(inputComponent.getValue(), 'bar');
|
expect(inputComponent.getValue()).toBe('bar');
|
||||||
test.equal(inputComponent.isValid(), false);
|
expect(inputComponent.isValid()).toBe(false);
|
||||||
test.done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
},
|
});
|
||||||
|
|
||||||
'should trigger an onValid handler, if passed, when form is valid': function (test) {
|
it('should trigger an onValid handler, if passed, when form is valid', function () {
|
||||||
|
|
||||||
const onValid = sinon.spy();
|
const onValid = jasmine.createSpy('valid');
|
||||||
const onInvalid = sinon.spy();
|
const onInvalid = jasmine.createSpy('invalid');
|
||||||
|
|
||||||
TestUtils.renderIntoDocument(
|
TestUtils.renderIntoDocument(
|
||||||
<Formsy.Form onValid={onValid} onInvalid={onInvalid}>
|
<Formsy.Form onValid={onValid} onInvalid={onInvalid}>
|
||||||
|
|
@ -67,16 +66,15 @@ export default {
|
||||||
</Formsy.Form>
|
</Formsy.Form>
|
||||||
);
|
);
|
||||||
|
|
||||||
test.equal(onValid.called, true);
|
expect(onValid).toHaveBeenCalled();
|
||||||
test.equal(onInvalid.called, false);
|
expect(onInvalid).not.toHaveBeenCalled();
|
||||||
test.done();
|
|
||||||
|
|
||||||
},
|
});
|
||||||
|
|
||||||
'should trigger an onInvalid handler, if passed, when form is invalid': function (test) {
|
it('should trigger an onInvalid handler, if passed, when form is invalid', function () {
|
||||||
|
|
||||||
const onValid = sinon.spy();
|
const onValid = jasmine.createSpy('valid');
|
||||||
const onInvalid = sinon.spy();
|
const onInvalid = jasmine.createSpy('invalid');
|
||||||
|
|
||||||
TestUtils.renderIntoDocument(
|
TestUtils.renderIntoDocument(
|
||||||
<Formsy.Form onValid={onValid} onInvalid={onInvalid}>
|
<Formsy.Form onValid={onValid} onInvalid={onInvalid}>
|
||||||
|
|
@ -84,33 +82,40 @@ export default {
|
||||||
</Formsy.Form>
|
</Formsy.Form>
|
||||||
);
|
);
|
||||||
|
|
||||||
test.equal(onValid.called, false);
|
expect(onValid).not.toHaveBeenCalled();
|
||||||
test.equal(onInvalid.called, true);
|
expect(onInvalid).toHaveBeenCalled();
|
||||||
test.done();
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should use provided validate function', function () {
|
||||||
|
|
||||||
|
const isValid = jasmine.createSpy('valid');
|
||||||
|
|
||||||
|
const Input = customizeInput({
|
||||||
|
render() {
|
||||||
|
if (this.isValid()) {
|
||||||
|
isValid();
|
||||||
|
}
|
||||||
|
return <input value={this.getValue()} onChange={this.updateValue}/>;
|
||||||
},
|
},
|
||||||
|
validate() {
|
||||||
'should be able to use provided validate function': function (test) {
|
return this.getValue() === 'checkValidity';
|
||||||
|
|
||||||
let isValid = false;
|
|
||||||
const CustomInput = InputFactory({
|
|
||||||
componentDidMount() {
|
|
||||||
isValid = this.isValid();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const form = TestUtils.renderIntoDocument(
|
const form = TestUtils.renderIntoDocument(
|
||||||
<Formsy.Form>
|
<Formsy.Form>
|
||||||
<CustomInput name="foo" value="foo" required/>
|
<Input name="foo" value="checkInvalidity"/>
|
||||||
</Formsy.Form>
|
</Formsy.Form>
|
||||||
);
|
);
|
||||||
|
|
||||||
const input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
const input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||||
test.equal(isValid, true);
|
TestUtils.Simulate.change(input, {target: {value: 'checkValidity'}});
|
||||||
test.done();
|
expect(isValid).toHaveBeenCalled();
|
||||||
|
|
||||||
},
|
});
|
||||||
|
|
||||||
'should provide invalidate callback on onValiSubmit': function (test) {
|
it('should provide invalidate callback on onValiSubmit', function () {
|
||||||
|
|
||||||
const TestForm = React.createClass({
|
const TestForm = React.createClass({
|
||||||
render() {
|
render() {
|
||||||
|
|
@ -127,12 +132,11 @@ export default {
|
||||||
const formEl = TestUtils.findRenderedDOMComponentWithTag(form, 'form');
|
const formEl = TestUtils.findRenderedDOMComponentWithTag(form, 'form');
|
||||||
const input = TestUtils.findRenderedComponentWithType(form, TestInput);
|
const input = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||||
TestUtils.Simulate.submit(formEl);
|
TestUtils.Simulate.submit(formEl);
|
||||||
test.equal(input.isValid(), false);
|
expect(input.isValid()).toBe(false);
|
||||||
test.done();
|
|
||||||
|
|
||||||
},
|
});
|
||||||
|
|
||||||
'should provide invalidate callback on onInvalidSubmit': function (test) {
|
it('should provide invalidate callback on onInvalidSubmit', function () {
|
||||||
|
|
||||||
const TestForm = React.createClass({
|
const TestForm = React.createClass({
|
||||||
render() {
|
render() {
|
||||||
|
|
@ -148,13 +152,12 @@ export default {
|
||||||
const formEl = TestUtils.findRenderedDOMComponentWithTag(form, 'form');
|
const formEl = TestUtils.findRenderedDOMComponentWithTag(form, 'form');
|
||||||
const input = TestUtils.findRenderedComponentWithType(form, TestInput);
|
const input = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||||
TestUtils.Simulate.submit(formEl);
|
TestUtils.Simulate.submit(formEl);
|
||||||
test.equal(input.getErrorMessage(), 'bar');
|
expect(input.getErrorMessage()).toBe('bar');
|
||||||
|
|
||||||
test.done();
|
});
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
'should not invalidate inputs on external errors with preventExternalInvalidation prop': function (test) {
|
it('should not invalidate inputs on external errors with preventExternalInvalidation prop', function () {
|
||||||
|
|
||||||
const TestForm = React.createClass({
|
const TestForm = React.createClass({
|
||||||
render() {
|
render() {
|
||||||
|
|
@ -172,12 +175,11 @@ export default {
|
||||||
const formEl = TestUtils.findRenderedDOMComponentWithTag(form, 'form');
|
const formEl = TestUtils.findRenderedDOMComponentWithTag(form, 'form');
|
||||||
const input = TestUtils.findRenderedComponentWithType(form, TestInput);
|
const input = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||||
TestUtils.Simulate.submit(formEl);
|
TestUtils.Simulate.submit(formEl);
|
||||||
test.equal(input.isValid(), true);
|
expect(input.isValid()).toBe(true);
|
||||||
test.done();
|
|
||||||
|
|
||||||
},
|
});
|
||||||
|
|
||||||
'should invalidate inputs on external errors without preventExternalInvalidation prop': function (test) {
|
it('should invalidate inputs on external errors without preventExternalInvalidation prop', function () {
|
||||||
|
|
||||||
const TestForm = React.createClass({
|
const TestForm = React.createClass({
|
||||||
render() {
|
render() {
|
||||||
|
|
@ -193,9 +195,8 @@ export default {
|
||||||
const formEl = TestUtils.findRenderedDOMComponentWithTag(form, 'form');
|
const formEl = TestUtils.findRenderedDOMComponentWithTag(form, 'form');
|
||||||
const input = TestUtils.findRenderedComponentWithType(form, TestInput);
|
const input = TestUtils.findRenderedComponentWithType(form, TestInput);
|
||||||
TestUtils.Simulate.submit(formEl);
|
TestUtils.Simulate.submit(formEl);
|
||||||
test.equal(input.isValid(), false);
|
expect(input.isValid()).toBe(false);
|
||||||
test.done();
|
|
||||||
|
|
||||||
}
|
});
|
||||||
|
|
||||||
};
|
});
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Formsy from './../..';
|
import Formsy from './../..';
|
||||||
|
import assign from 'react/lib/Object.assign';
|
||||||
|
|
||||||
const defaultProps = {
|
const defaultProps = {
|
||||||
mixins: [Formsy.Mixin],
|
mixins: [Formsy.Mixin],
|
||||||
|
|
@ -14,8 +15,8 @@ const defaultProps = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export function InputFactory(props) {
|
export function customizeInput(props) {
|
||||||
return React.createClass(Object.assign(defaultProps, props));
|
return React.createClass(assign(defaultProps, props));
|
||||||
}
|
}
|
||||||
|
|
||||||
export default React.createClass(defaultProps);
|
export default React.createClass(defaultProps);
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
var React = global.React || require('react');
|
var React = global.React || require('react');
|
||||||
var createReactClass = require('create-react-class');
|
|
||||||
var Mixin = require('./Mixin.js');
|
var Mixin = require('./Mixin.js');
|
||||||
module.exports = function () {
|
module.exports = function () {
|
||||||
return function (Component) {
|
return function (Component) {
|
||||||
return createReactClass({
|
return React.createClass({
|
||||||
mixins: [Mixin],
|
mixins: [Mixin],
|
||||||
render: function () {
|
render: function () {
|
||||||
return React.createElement(Component, {
|
return React.createElement(Component, {
|
||||||
|
|
|
||||||
26
src/HOC.js
26
src/HOC.js
|
|
@ -1,14 +1,10 @@
|
||||||
var React = global.React || require('react');
|
var React = global.React || require('react');
|
||||||
var createReactClass = require('create-react-class');
|
|
||||||
var Mixin = require('./Mixin.js');
|
var Mixin = require('./Mixin.js');
|
||||||
module.exports = function (Component) {
|
module.exports = function (Component) {
|
||||||
return createReactClass({
|
return React.createClass({
|
||||||
displayName: 'Formsy(' + getDisplayName(Component) + ')',
|
|
||||||
mixins: [Mixin],
|
mixins: [Mixin],
|
||||||
|
|
||||||
render: function () {
|
render: function () {
|
||||||
const { innerRef } = this.props;
|
return React.createElement(Component, {
|
||||||
const propsForElement = {
|
|
||||||
setValidations: this.setValidations,
|
setValidations: this.setValidations,
|
||||||
setValue: this.setValue,
|
setValue: this.setValue,
|
||||||
resetValue: this.resetValue,
|
resetValue: this.resetValue,
|
||||||
|
|
@ -23,22 +19,8 @@ module.exports = function (Component) {
|
||||||
isRequired: this.isRequired,
|
isRequired: this.isRequired,
|
||||||
showRequired: this.showRequired,
|
showRequired: this.showRequired,
|
||||||
showError: this.showError,
|
showError: this.showError,
|
||||||
isValidValue: this.isValidValue,
|
isValidValue: this.isValidValue
|
||||||
...this.props
|
});
|
||||||
};
|
|
||||||
|
|
||||||
if (innerRef) {
|
|
||||||
propsForElement.ref = innerRef;
|
|
||||||
}
|
|
||||||
return React.createElement(Component, propsForElement);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
function getDisplayName(Component) {
|
|
||||||
return (
|
|
||||||
Component.displayName ||
|
|
||||||
Component.name ||
|
|
||||||
(typeof Component === 'string' ? Component : 'Component')
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
var PropTypes = require('prop-types');
|
|
||||||
var utils = require('./utils.js');
|
var utils = require('./utils.js');
|
||||||
var React = global.React || require('react');
|
var React = global.React || require('react');
|
||||||
|
|
||||||
|
|
@ -45,7 +44,7 @@ module.exports = {
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
contextTypes: {
|
contextTypes: {
|
||||||
formsy: PropTypes.object // What about required?
|
formsy: React.PropTypes.object // What about required?
|
||||||
},
|
},
|
||||||
getDefaultProps: function () {
|
getDefaultProps: function () {
|
||||||
return {
|
return {
|
||||||
|
|
|
||||||
188
src/main.js
188
src/main.js
|
|
@ -1,6 +1,4 @@
|
||||||
var PropTypes = require('prop-types');
|
|
||||||
var React = global.React || require('react');
|
var React = global.React || require('react');
|
||||||
var createReactClass = require('create-react-class');
|
|
||||||
var Formsy = {};
|
var Formsy = {};
|
||||||
var validationRules = require('./validationRules.js');
|
var validationRules = require('./validationRules.js');
|
||||||
var formDataToObject = require('form-data-to-object');
|
var formDataToObject = require('form-data-to-object');
|
||||||
|
|
@ -9,7 +7,6 @@ var Mixin = require('./Mixin.js');
|
||||||
var HOC = require('./HOC.js');
|
var HOC = require('./HOC.js');
|
||||||
var Decorator = require('./Decorator.js');
|
var Decorator = require('./Decorator.js');
|
||||||
var options = {};
|
var options = {};
|
||||||
var emptyArray = [];
|
|
||||||
|
|
||||||
Formsy.Mixin = Mixin;
|
Formsy.Mixin = Mixin;
|
||||||
Formsy.HOC = HOC;
|
Formsy.HOC = HOC;
|
||||||
|
|
@ -23,8 +20,7 @@ Formsy.addValidationRule = function (name, func) {
|
||||||
validationRules[name] = func;
|
validationRules[name] = func;
|
||||||
};
|
};
|
||||||
|
|
||||||
Formsy.Form = createReactClass({
|
Formsy.Form = React.createClass({
|
||||||
displayName: 'Formsy',
|
|
||||||
getInitialState: function () {
|
getInitialState: function () {
|
||||||
return {
|
return {
|
||||||
isValid: true,
|
isValid: true,
|
||||||
|
|
@ -39,6 +35,7 @@ Formsy.Form = createReactClass({
|
||||||
onSubmit: function () {},
|
onSubmit: function () {},
|
||||||
onValidSubmit: function () {},
|
onValidSubmit: function () {},
|
||||||
onInvalidSubmit: function () {},
|
onInvalidSubmit: function () {},
|
||||||
|
onSubmitted: function () {},
|
||||||
onValid: function () {},
|
onValid: function () {},
|
||||||
onInvalid: function () {},
|
onInvalid: function () {},
|
||||||
onChange: function () {},
|
onChange: function () {},
|
||||||
|
|
@ -48,7 +45,7 @@ Formsy.Form = createReactClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
childContextTypes: {
|
childContextTypes: {
|
||||||
formsy: PropTypes.object
|
formsy: React.PropTypes.object
|
||||||
},
|
},
|
||||||
getChildContext: function () {
|
getChildContext: function () {
|
||||||
return {
|
return {
|
||||||
|
|
@ -57,9 +54,9 @@ Formsy.Form = createReactClass({
|
||||||
detachFromForm: this.detachFromForm,
|
detachFromForm: this.detachFromForm,
|
||||||
validate: this.validate,
|
validate: this.validate,
|
||||||
isFormDisabled: this.isFormDisabled,
|
isFormDisabled: this.isFormDisabled,
|
||||||
isValidValue: (component, value) => {
|
isValidValue: function (component, value) {
|
||||||
return this.runValidation(component, value).isValid;
|
return this.runValidation(component, value).isValid;
|
||||||
}
|
}.bind(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -67,7 +64,8 @@ Formsy.Form = createReactClass({
|
||||||
// Add a map to store the inputs of the form, a model to store
|
// Add a map to store the inputs of the form, a model to store
|
||||||
// the values of the form and register child inputs
|
// the values of the form and register child inputs
|
||||||
componentWillMount: function () {
|
componentWillMount: function () {
|
||||||
this.inputs = [];
|
this.inputs = {};
|
||||||
|
this.model = {};
|
||||||
},
|
},
|
||||||
|
|
||||||
componentDidMount: function () {
|
componentDidMount: function () {
|
||||||
|
|
@ -75,19 +73,21 @@ Formsy.Form = createReactClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
componentWillUpdate: function () {
|
componentWillUpdate: function () {
|
||||||
// Keep a reference to input names before form updates,
|
|
||||||
|
// Keep a reference to input keys before form updates,
|
||||||
// to check if inputs has changed after render
|
// to check if inputs has changed after render
|
||||||
this.prevInputNames = this.inputs.map(component => component.props.name);
|
this.prevInputKeys = Object.keys(this.inputs);
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
componentDidUpdate: function () {
|
componentDidUpdate: function () {
|
||||||
|
|
||||||
if (this.props.validationErrors && typeof this.props.validationErrors === 'object' && Object.keys(this.props.validationErrors).length > 0) {
|
if (this.props.validationErrors) {
|
||||||
this.setInputValidationErrors(this.props.validationErrors);
|
this.setInputValidationErrors(this.props.validationErrors);
|
||||||
}
|
}
|
||||||
|
|
||||||
var newInputNames = this.inputs.map(component => component.props.name);
|
var newInputKeys = Object.keys(this.inputs);
|
||||||
if (utils.arraysDiffer(this.prevInputNames, newInputNames)) {
|
if (utils.arraysDiffer(this.prevInputKeys, newInputKeys)) {
|
||||||
this.validateForm();
|
this.validateForm();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -108,59 +108,62 @@ Formsy.Form = createReactClass({
|
||||||
// If any inputs have not been touched yet this will make them dirty
|
// If any inputs have not been touched yet this will make them dirty
|
||||||
// so validation becomes visible (if based on isPristine)
|
// so validation becomes visible (if based on isPristine)
|
||||||
this.setFormPristine(false);
|
this.setFormPristine(false);
|
||||||
var model = this.getModel();
|
this.updateModel();
|
||||||
|
var model = this.mapModel();
|
||||||
this.props.onSubmit(model, this.resetModel, this.updateInputsWithError);
|
this.props.onSubmit(model, this.resetModel, this.updateInputsWithError);
|
||||||
this.state.isValid ? this.props.onValidSubmit(model, this.resetModel, this.updateInputsWithError) : this.props.onInvalidSubmit(model, this.resetModel, this.updateInputsWithError);
|
this.state.isValid ? this.props.onValidSubmit(model, this.resetModel, this.updateInputsWithError) : this.props.onInvalidSubmit(model, this.resetModel, this.updateInputsWithError);
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
mapModel: function (model) {
|
mapModel: function () {
|
||||||
|
|
||||||
if (this.props.mapping) {
|
if (this.props.mapping) {
|
||||||
return this.props.mapping(model)
|
return this.props.mapping(this.model)
|
||||||
} else {
|
} else {
|
||||||
return formDataToObject.toObj(Object.keys(model).reduce((mappedModel, key) => {
|
return formDataToObject(Object.keys(this.model).reduce(function (mappedModel, key) {
|
||||||
|
|
||||||
var keyArray = key.split('.');
|
var keyArray = key.split('.');
|
||||||
var base = mappedModel;
|
var base = mappedModel;
|
||||||
while (keyArray.length) {
|
while (keyArray.length) {
|
||||||
var currentKey = keyArray.shift();
|
var currentKey = keyArray.shift();
|
||||||
base = (base[currentKey] = keyArray.length ? base[currentKey] || {} : model[key]);
|
base = (base[currentKey] = keyArray.length ? base[currentKey] || {} : this.model[key]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return mappedModel;
|
return mappedModel;
|
||||||
|
|
||||||
}, {}));
|
}.bind(this), {}));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
getModel: function () {
|
// Goes through all registered components and
|
||||||
var currentValues = this.getCurrentValues();
|
// updates the model values
|
||||||
return this.mapModel(currentValues);
|
updateModel: function () {
|
||||||
|
Object.keys(this.inputs).forEach(function (name) {
|
||||||
|
var component = this.inputs[name];
|
||||||
|
this.model[name] = component.state._value;
|
||||||
|
}.bind(this));
|
||||||
},
|
},
|
||||||
|
|
||||||
// Reset each key in the model to the original / initial / specified value
|
// Reset each key in the model to the original / initial / specified value
|
||||||
resetModel: function (data) {
|
resetModel: function (data) {
|
||||||
this.inputs.forEach(component => {
|
Object.keys(this.inputs).forEach(function (name) {
|
||||||
var name = component.props.name;
|
if (data && data[name]) {
|
||||||
if (data && data.hasOwnProperty(name)) {
|
this.inputs[name].setValue(data[name]);
|
||||||
component.setValue(data[name]);
|
|
||||||
} else {
|
} else {
|
||||||
component.resetValue();
|
this.inputs[name].resetValue();
|
||||||
}
|
}
|
||||||
});
|
}.bind(this));
|
||||||
this.validateForm();
|
this.validateForm();
|
||||||
},
|
},
|
||||||
|
|
||||||
setInputValidationErrors: function (errors) {
|
setInputValidationErrors: function (errors) {
|
||||||
this.inputs.forEach(component => {
|
Object.keys(this.inputs).forEach(function (name, index) {
|
||||||
var name = component.props.name;
|
var component = this.inputs[name];
|
||||||
var args = [{
|
var args = [{
|
||||||
_isValid: !(name in errors),
|
_isValid: !(name in errors),
|
||||||
_validationError: typeof errors[name] === 'string' ? [errors[name]] : errors[name]
|
_validationError: typeof errors[name] === 'string' ? [errors[name]] : errors[name]
|
||||||
}];
|
}];
|
||||||
component.setState.apply(component, args);
|
component.setState.apply(component, args);
|
||||||
});
|
}.bind(this));
|
||||||
},
|
},
|
||||||
|
|
||||||
// Checks if the values have changed from their initial value
|
// Checks if the values have changed from their initial value
|
||||||
|
|
@ -169,8 +172,9 @@ Formsy.Form = createReactClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
getPristineValues: function() {
|
getPristineValues: function() {
|
||||||
return this.inputs.reduce((data, component) => {
|
var inputs = this.inputs;
|
||||||
var name = component.props.name;
|
return Object.keys(inputs).reduce(function (data, name) {
|
||||||
|
var component = inputs[name];
|
||||||
data[name] = component.props.value;
|
data[name] = component.props.value;
|
||||||
return data;
|
return data;
|
||||||
}, {});
|
}, {});
|
||||||
|
|
@ -180,18 +184,51 @@ Formsy.Form = createReactClass({
|
||||||
// stored in the inputs map. Change their state to invalid
|
// stored in the inputs map. Change their state to invalid
|
||||||
// and set the serverError message
|
// and set the serverError message
|
||||||
updateInputsWithError: function (errors) {
|
updateInputsWithError: function (errors) {
|
||||||
Object.keys(errors).forEach((name, index) => {
|
Object.keys(errors).forEach(function (name, index) {
|
||||||
var component = utils.find(this.inputs, component => component.props.name === name);
|
var component = this.inputs[name];
|
||||||
|
|
||||||
if (!component) {
|
if (!component) {
|
||||||
throw new Error('You are trying to update an input that does not exist. ' +
|
throw new Error('You are trying to update an input that does not exist. Verify errors object with input names. ' + JSON.stringify(errors));
|
||||||
'Verify errors object with input names. ' + JSON.stringify(errors));
|
|
||||||
}
|
}
|
||||||
var args = [{
|
var args = [{
|
||||||
_isValid: this.props.preventExternalInvalidation || false,
|
_isValid: this.props.preventExternalInvalidation || false,
|
||||||
_externalError: typeof errors[name] === 'string' ? [errors[name]] : errors[name]
|
_externalError: typeof errors[name] === 'string' ? [errors[name]] : errors[name]
|
||||||
}];
|
}];
|
||||||
component.setState.apply(component, args);
|
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 () {
|
isFormDisabled: function () {
|
||||||
|
|
@ -199,26 +236,30 @@ Formsy.Form = createReactClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
getCurrentValues: function () {
|
getCurrentValues: function () {
|
||||||
return this.inputs.reduce((data, component) => {
|
return Object.keys(this.inputs).reduce(function (data, name) {
|
||||||
var name = component.props.name;
|
var component = this.inputs[name];
|
||||||
data[name] = component.state._value;
|
data[name] = component.state._value;
|
||||||
return data;
|
return data;
|
||||||
}, {});
|
}.bind(this), {});
|
||||||
},
|
},
|
||||||
|
|
||||||
setFormPristine: function (isPristine) {
|
setFormPristine: function (isPristine) {
|
||||||
|
var inputs = this.inputs;
|
||||||
|
var inputKeys = Object.keys(inputs);
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
_formSubmitted: !isPristine
|
_formSubmitted: !isPristine
|
||||||
});
|
})
|
||||||
|
|
||||||
// Iterate through each component and set it as pristine
|
// Iterate through each component and set it as pristine
|
||||||
// or "dirty".
|
// or "dirty".
|
||||||
this.inputs.forEach((component, index) => {
|
inputKeys.forEach(function (name, index) {
|
||||||
|
var component = inputs[name];
|
||||||
component.setState({
|
component.setState({
|
||||||
_formSubmitted: !isPristine,
|
_formSubmitted: !isPristine,
|
||||||
_isPristine: isPristine
|
_isPristine: isPristine
|
||||||
});
|
});
|
||||||
});
|
}.bind(this));
|
||||||
},
|
},
|
||||||
|
|
||||||
// Use the binded values and the actual input value to
|
// Use the binded values and the actual input value to
|
||||||
|
|
@ -268,7 +309,7 @@ Formsy.Form = createReactClass({
|
||||||
error: (function () {
|
error: (function () {
|
||||||
|
|
||||||
if (isValid && !isRequired) {
|
if (isValid && !isRequired) {
|
||||||
return emptyArray;
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (validationResults.errors.length) {
|
if (validationResults.errors.length) {
|
||||||
|
|
@ -352,13 +393,16 @@ Formsy.Form = createReactClass({
|
||||||
// Validate the form by going through all child input components
|
// Validate the form by going through all child input components
|
||||||
// and check their state
|
// and check their state
|
||||||
validateForm: function () {
|
validateForm: function () {
|
||||||
|
var allIsValid;
|
||||||
|
var inputs = this.inputs;
|
||||||
|
var inputKeys = Object.keys(inputs);
|
||||||
|
|
||||||
// We need a callback as we are validating all inputs again. This will
|
// We need a callback as we are validating all inputs again. This will
|
||||||
// run when the last component has set its state
|
// run when the last component has set its state
|
||||||
var onValidationComplete = function () {
|
var onValidationComplete = function () {
|
||||||
var allIsValid = this.inputs.every(component => {
|
allIsValid = inputKeys.every(function (name) {
|
||||||
return component.state._isValid;
|
return inputs[name].state._isValid;
|
||||||
});
|
}.bind(this));
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
isValid: allIsValid
|
isValid: allIsValid
|
||||||
|
|
@ -379,7 +423,8 @@ Formsy.Form = createReactClass({
|
||||||
|
|
||||||
// Run validation again in case affected by other inputs. The
|
// Run validation again in case affected by other inputs. The
|
||||||
// last component validated will run the onValidationComplete callback
|
// last component validated will run the onValidationComplete callback
|
||||||
this.inputs.forEach((component, index) => {
|
inputKeys.forEach(function (name, index) {
|
||||||
|
var component = inputs[name];
|
||||||
var validation = this.runValidation(component);
|
var validation = this.runValidation(component);
|
||||||
if (validation.isValid && component.state._externalError) {
|
if (validation.isValid && component.state._externalError) {
|
||||||
validation.isValid = false;
|
validation.isValid = false;
|
||||||
|
|
@ -389,12 +434,12 @@ Formsy.Form = createReactClass({
|
||||||
_isRequired: validation.isRequired,
|
_isRequired: validation.isRequired,
|
||||||
_validationError: validation.error,
|
_validationError: validation.error,
|
||||||
_externalError: !validation.isValid && component.state._externalError ? component.state._externalError : null
|
_externalError: !validation.isValid && component.state._externalError ? component.state._externalError : null
|
||||||
}, index === this.inputs.length - 1 ? onValidationComplete : null);
|
}, index === inputKeys.length - 1 ? onValidationComplete : null);
|
||||||
});
|
}.bind(this));
|
||||||
|
|
||||||
// If there are no inputs, set state where form is ready to trigger
|
// If there are no inputs, set state where form is ready to trigger
|
||||||
// change event. New inputs might be added later
|
// change event. New inputs might be added later
|
||||||
if (!this.inputs.length) {
|
if (!inputKeys.length && this.isMounted()) {
|
||||||
this.setState({
|
this.setState({
|
||||||
canChange: true
|
canChange: true
|
||||||
});
|
});
|
||||||
|
|
@ -404,46 +449,23 @@ Formsy.Form = createReactClass({
|
||||||
// Method put on each input component to register
|
// Method put on each input component to register
|
||||||
// itself to the form
|
// itself to the form
|
||||||
attachToForm: function (component) {
|
attachToForm: function (component) {
|
||||||
|
this.inputs[component.props.name] = component;
|
||||||
if (this.inputs.indexOf(component) === -1) {
|
this.model[component.props.name] = component.state._value;
|
||||||
this.inputs.push(component);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.validate(component);
|
this.validate(component);
|
||||||
},
|
},
|
||||||
|
|
||||||
// Method put on each input component to unregister
|
// Method put on each input component to unregister
|
||||||
// itself from the form
|
// itself from the form
|
||||||
detachFromForm: function (component) {
|
detachFromForm: function (component) {
|
||||||
var componentPos = this.inputs.indexOf(component);
|
delete this.inputs[component.props.name];
|
||||||
|
delete this.model[component.props.name];
|
||||||
if (componentPos !== -1) {
|
|
||||||
this.inputs = this.inputs.slice(0, componentPos)
|
|
||||||
.concat(this.inputs.slice(componentPos + 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
this.validateForm();
|
|
||||||
},
|
},
|
||||||
render: function () {
|
render: function () {
|
||||||
var {
|
|
||||||
mapping,
|
|
||||||
validationErrors,
|
|
||||||
onSubmit,
|
|
||||||
onValid,
|
|
||||||
onValidSubmit,
|
|
||||||
onInvalid,
|
|
||||||
onInvalidSubmit,
|
|
||||||
onChange,
|
|
||||||
reset,
|
|
||||||
preventExternalInvalidation,
|
|
||||||
onSuccess,
|
|
||||||
onError,
|
|
||||||
...nonFormsyProps
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form {...nonFormsyProps} onSubmit={this.submit}>
|
<form {...this.props} onSubmit={this.submit}>
|
||||||
{this.props.children}
|
{this.props.children}
|
||||||
|
{/*this.traverseChildrenAndRegisterInputs(this.props.children)*/}
|
||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
14
src/utils.js
14
src/utils.js
|
|
@ -30,24 +30,12 @@ module.exports = {
|
||||||
isSame: function (a, b) {
|
isSame: function (a, b) {
|
||||||
if (typeof a !== typeof b) {
|
if (typeof a !== typeof b) {
|
||||||
return false;
|
return false;
|
||||||
} else if (Array.isArray(a) && Array.isArray(b)) {
|
} else if (Array.isArray(a)) {
|
||||||
return !this.arraysDiffer(a, b);
|
return !this.arraysDiffer(a, b);
|
||||||
} else if (typeof a === 'function') {
|
|
||||||
return a.toString() === b.toString();
|
|
||||||
} else if (typeof a === 'object' && a !== null && b !== null) {
|
} else if (typeof a === 'object' && a !== null && b !== null) {
|
||||||
return !this.objectsDiffer(a, b);
|
return !this.objectsDiffer(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
return a === b;
|
return a === b;
|
||||||
},
|
|
||||||
|
|
||||||
find: function (collection, fn) {
|
|
||||||
for (var i = 0, l = collection.length; i < l; i++) {
|
|
||||||
var item = collection[i];
|
|
||||||
if (fn(item)) {
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,22 @@
|
||||||
import path from 'path';
|
require('babel/register');
|
||||||
import testrunner from 'nodeunit/lib/reporters/default.js';
|
|
||||||
import {jsdom} from 'jsdom';
|
var path = require('path');
|
||||||
|
var jsdom = require('jsdom').jsdom;
|
||||||
|
var jasmine = require('jasmine-node');
|
||||||
|
|
||||||
global.document = jsdom();
|
global.document = jsdom();
|
||||||
global.window = document.defaultView;
|
global.window = document.defaultView;
|
||||||
global.navigator = global.window.navigator;
|
global.navigator = global.window.navigator;
|
||||||
|
|
||||||
testrunner.run(['tests'], {
|
var jasmineOptions = {
|
||||||
"error_prefix": "\u001B[31m",
|
specFolders: [path.resolve(__dirname, 'specs')],
|
||||||
"error_suffix": "\u001B[39m",
|
isVerbose: true,
|
||||||
"ok_prefix": "\u001B[32m",
|
showColors: true,
|
||||||
"ok_suffix": "\u001B[39m",
|
teamcity: false,
|
||||||
"bold_prefix": "\u001B[1m",
|
useRequireJs: false,
|
||||||
"bold_suffix": "\u001B[22m",
|
regExpSpec: /spec\.js$/,
|
||||||
"assertion_prefix": "\u001B[35m",
|
junitreport: true,
|
||||||
"assertion_suffix": "\u001B[39m"
|
includeStackTrace: true
|
||||||
}, function(err) {
|
};
|
||||||
if (err) {
|
|
||||||
process.exit(1);
|
jasmine.executeSpecsInFolder(jasmineOptions);
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
|
||||||
|
|
@ -1,748 +0,0 @@
|
||||||
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 TestInputHoc from './utils/TestInputHoc';
|
|
||||||
import immediate from './utils/immediate';
|
|
||||||
import sinon from 'sinon';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
|
|
||||||
'Setting up a form': {
|
|
||||||
'should expose the users DOM node through an innerRef prop': function (test) {
|
|
||||||
const TestForm = React.createClass({
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<Formsy.Form>
|
|
||||||
<TestInputHoc name="name" innerRef={(c) => { this.name = c; }} />
|
|
||||||
</Formsy.Form>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const form = TestUtils.renderIntoDocument(<TestForm/>);
|
|
||||||
const input = form.name;
|
|
||||||
test.equal(input.methodOnWrappedInstance('foo'), 'foo');
|
|
||||||
|
|
||||||
test.done();
|
|
||||||
},
|
|
||||||
|
|
||||||
'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 once 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.calledOnce, true);
|
|
||||||
test.done();
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
'should trigger onChange once 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.calledOnce, 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();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
'should be able to reset the form to empty values': function (test) {
|
|
||||||
|
|
||||||
const TestForm = React.createClass({
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<Formsy.Form>
|
|
||||||
<TestInput name="foo" value="42" 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);
|
|
||||||
|
|
||||||
formsyForm.reset({
|
|
||||||
foo: ''
|
|
||||||
});
|
|
||||||
test.equal(input.getValue(), '');
|
|
||||||
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();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
@ -1,80 +0,0 @@
|
||||||
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();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
@ -1,88 +0,0 @@
|
||||||
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();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
@ -1,98 +0,0 @@
|
||||||
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();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
@ -1,88 +0,0 @@
|
||||||
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();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
@ -1,88 +0,0 @@
|
||||||
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();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
@ -1,88 +0,0 @@
|
||||||
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();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
@ -1,125 +0,0 @@
|
||||||
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();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
@ -1,125 +0,0 @@
|
||||||
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();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
@ -1,177 +0,0 @@
|
||||||
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();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
@ -1,124 +0,0 @@
|
||||||
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();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
@ -1,88 +0,0 @@
|
||||||
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();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
@ -1,88 +0,0 @@
|
||||||
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();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
@ -1,97 +0,0 @@
|
||||||
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();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
@ -1,150 +0,0 @@
|
||||||
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 fail when a string\'s length is smaller': function (test) {
|
|
||||||
|
|
||||||
const form = TestUtils.renderIntoDocument(<TestForm rule="minLength:3" inputValue="my"/>);
|
|
||||||
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 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();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
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(objC, objH), false);
|
|
||||||
test.equal(utils.isSame(objG, objA), false);
|
|
||||||
|
|
||||||
test.equal(utils.isSame(() => {}, () => {}), true);
|
|
||||||
test.equal(utils.isSame(objA, () => {}), false);
|
|
||||||
test.equal(utils.isSame(() => {}, objA), false);
|
|
||||||
|
|
||||||
test.done();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { HOC as formsyHoc } from './../..';
|
|
||||||
|
|
||||||
const defaultProps = {
|
|
||||||
methodOnWrappedInstance(param) {
|
|
||||||
return param;
|
|
||||||
},
|
|
||||||
render() {
|
|
||||||
return (<input />);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export default formsyHoc(React.createClass(defaultProps));
|
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
var path = require('path');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
|
||||||
|
devtool: 'inline-source-map',
|
||||||
|
|
||||||
|
entry: path.resolve(__dirname, 'build', 'test.js'),
|
||||||
|
|
||||||
|
output: {
|
||||||
|
path: path.resolve(__dirname, 'build'),
|
||||||
|
filename: 'build.js'
|
||||||
|
},
|
||||||
|
|
||||||
|
module: {
|
||||||
|
loaders: [
|
||||||
|
{ test: /\.js$/, exclude: /node_modules/, loader: 'babel' },
|
||||||
|
{ test: /\.json$/, loader: 'json' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
Loading…
Reference in New Issue