diff --git a/package.json b/package.json index 2221fce5..b1258797 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "jasmine-node": "^1.14.5", "jsdom": "^3.1.2", "react": "^0.14.0-beta3", + "react-addons-test-utils": "^0.14.0-beta3", "react-dom": "^0.14.0-beta3", "webpack": "^1.7.3", "webpack-dev-server": "^1.7.0" diff --git a/specs/Element-spec.js b/specs/Element-spec.js new file mode 100644 index 00000000..3bdd548c --- /dev/null +++ b/specs/Element-spec.js @@ -0,0 +1,478 @@ +import React from 'react'; +import TestUtils from 'react-addons-test-utils'; + +import Formsy from './..'; +import TestInput, { customizeInput } from './utils/TestInput'; +import immediate from './utils/immediate'; + +describe('Element', function () { + + it('should return passed and setValue() value when using getValue()', function () { + + const form = TestUtils.renderIntoDocument( + + + + ); + + const input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT'); + expect(input.value).toBe('foo'); + TestUtils.Simulate.change(input, {target: {value: 'foobar'}}); + expect(input.value).toBe('foobar'); + + }); + + it('should set back to pristine value when running reset', function () { + + let reset = null; + const Input = customizeInput({ + componentDidMount() { + reset = this.resetValue; + } + }); + const form = TestUtils.renderIntoDocument( + + + + ); + + const input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT'); + TestUtils.Simulate.change(input, {target: {value: 'foobar'}}); + reset(); + expect(input.value).toBe('foo'); + + }); + + it('should return error message passed when calling getErrorMessage()', function () { + + let getErrorMessage = null; + const Input = customizeInput({ + componentDidMount() { + getErrorMessage = this.getErrorMessage; + } + }); + TestUtils.renderIntoDocument( + + + + ); + + expect(getErrorMessage()).toBe('Has to be email'); + + }); + + it('should return true or false when calling isValid() depending on valid state', function () { + + let isValid = null; + const Input = customizeInput({ + componentDidMount() { + isValid = this.isValid; + } + }); + const form = TestUtils.renderIntoDocument( + + + + ); + + expect(isValid()).toBe(false); + const input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT'); + TestUtils.Simulate.change(input, {target: {value: 'foo@foo.com'}}); + expect(isValid()).toBe(true); + + }); + + it('should return true or false when calling isRequired() depending on passed required attribute', function () { + + const isRequireds = []; + const Input = customizeInput({ + componentDidMount() { + isRequireds.push(this.isRequired); + } + }); + TestUtils.renderIntoDocument( + + + + + + ); + + expect(isRequireds[0]()).toBe(false); + expect(isRequireds[1]()).toBe(true); + expect(isRequireds[2]()).toBe(true); + + }); + + it('should return true or false when calling showRequired() depending on input being empty and required is passed, or not', function () { + + const showRequireds = []; + const Input = customizeInput({ + componentDidMount() { + showRequireds.push(this.showRequired); + } + }); + TestUtils.renderIntoDocument( + + + + + + ); + + expect(showRequireds[0]()).toBe(false); + expect(showRequireds[1]()).toBe(true); + expect(showRequireds[2]()).toBe(false); + + }); + + it('should return true or false when calling isPristine() depending on input has been "touched" or not', function () { + + let isPristine = null; + const Input = customizeInput({ + componentDidMount() { + isPristine = this.isPristine; + } + }); + const form = TestUtils.renderIntoDocument( + + + + ); + + expect(isPristine()).toBe(true); + const input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT'); + TestUtils.Simulate.change(input, {target: {value: 'foo'}}); + expect(isPristine()).toBe(false); + + }); + +it('should allow an undefined value to be updated to a value', function (done) { + + const TestForm = React.createClass({ + getInitialState() { + return {value: undefined}; + }, + changeValue() { + this.setState({ + value: 'foo' + }); + }, + render() { + return ( + + + + ); + } + }); + const form = TestUtils.renderIntoDocument(); + + form.changeValue(); + const input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT'); + immediate(() => { + expect(input.value).toBe('foo'); + done(); + }); + + }); + + it('should be able to test a values validity', function () { + + const TestForm = React.createClass({ + render() { + return ( + + + + ); + } + }); + const form = TestUtils.renderIntoDocument(); + + const input = TestUtils.findRenderedComponentWithType(form, TestInput); + expect(input.isValidValue('foo@bar.com')).toBe(true); + expect(input.isValidValue('foo@bar')).toBe(false); + + }); + + it('should be able to use an object as validations property', function () { + + const TestForm = React.createClass({ + render() { + return ( + + + + ); + } + }); + const form = TestUtils.renderIntoDocument(); + + const input = TestUtils.findRenderedComponentWithType(form, TestInput); + expect(input.isValidValue('foo@bar.com')).toBe(true); + expect(input.isValidValue('foo@bar')).toBe(false); + + }); + + it('should be able to pass complex values to a validation rule', function () { + + const TestForm = React.createClass({ + render() { + return ( + + + + ); + } + }); + const form = TestUtils.renderIntoDocument(); + + const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput); + expect(inputComponent.isValid()).toBe(true); + const input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT'); + TestUtils.Simulate.change(input, {target: {value: 'bar'}}); + expect(inputComponent.isValid()).toBe(false); + + }); + + it('should be able to run a function to validate', function () { + + const TestForm = React.createClass({ + customValidationA(values, value) { + return value === 'foo'; + }, + customValidationB(values, value) { + return value === 'foo' && values.A === 'foo'; + }, + render() { + return ( + + + + + ); + } + }); + const form = TestUtils.renderIntoDocument(); + + const inputComponent = TestUtils.scryRenderedComponentsWithType(form, TestInput); + expect(inputComponent[0].isValid()).toBe(true); + expect(inputComponent[1].isValid()).toBe(true); + const input = TestUtils.scryRenderedDOMComponentsWithTag(form, 'INPUT'); + TestUtils.Simulate.change(input[0], {target: {value: 'bar'}}); + expect(inputComponent[0].isValid()).toBe(false); + expect(inputComponent[1].isValid()).toBe(false); + + }); + + it('should override all error messages with error messages passed by form', function () { + + const TestForm = React.createClass({ + render() { + return ( + + + + ); + } + }); + const form = TestUtils.renderIntoDocument(); + + const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput); + expect(inputComponent.getErrorMessage()).toBe('bar'); + + }); + + it('should override validation rules with required rules', function () { + + const TestForm = React.createClass({ + render() { + return ( + + + + ); + } + }); + const form = TestUtils.renderIntoDocument(); + + const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput); + expect(inputComponent.getErrorMessage()).toBe('bar3'); + + }); + + it('should fall back to default error message when non exist in validationErrors map', function () { + + const TestForm = React.createClass({ + render() { + return ( + + + + ); + } + }); + const form = TestUtils.renderIntoDocument(); + + const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput); + expect(inputComponent.getErrorMessage()).toBe('bar'); + + }); + + it('should not be valid if it is required and required rule is true', function () { + + const TestForm = React.createClass({ + render() { + return ( + + + + ); + } + }); + const form = TestUtils.renderIntoDocument(); + + const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput); + expect(inputComponent.isValid()).toBe(false); + + }); + + it('should handle objects and arrays as values', function () { + + const TestForm = React.createClass({ + getInitialState() { + return { + foo: {foo: 'bar'}, + bar: ['foo'] + }; + }, + render() { + return ( + + + + + ); + } + }); + const form = TestUtils.renderIntoDocument(); + + form.setState({ + foo: {foo: 'foo'}, + bar: ['bar'] + }); + + const inputs = TestUtils.scryRenderedComponentsWithType(form, TestInput); + expect(inputs[0].getValue()).toEqual({foo: 'foo'}); + expect(inputs[1].getValue()).toEqual(['bar']); + + }); + + it('should handle isFormDisabled with dynamic inputs', function () { + + const TestForm = React.createClass({ + getInitialState() { + return { + bool: true + }; + }, + flip() { + this.setState({ + bool: !this.state.bool + }); + }, + render() { + return ( + + {this.state.bool ? + : + + } + + ); + } + }); + const form = TestUtils.renderIntoDocument(); + + const input = TestUtils.findRenderedComponentWithType(form, TestInput); + expect(input.isFormDisabled()).toBe(true); + form.flip(); + expect(input.isFormDisabled()).toBe(false); + + }); + + it('should allow for dot notation in name which maps to a deep object', function () { + + const TestForm = React.createClass({ + onSubmit(model) { + expect(model).toEqual({foo: {bar: 'foo', test: 'test'}}); + }, + render() { + return ( + + + + + ); + } + }); + const form = TestUtils.renderIntoDocument(); + + const formEl = TestUtils.findRenderedDOMComponentWithTag(form, 'form'); + TestUtils.Simulate.submit(formEl); + + }); + + it('should allow for application/x-www-form-urlencoded syntax and convert to object', function () { + + const TestForm = React.createClass({ + onSubmit(model) { + expect(model).toEqual({foo: ['foo', 'bar']}); + }, + render() { + return ( + + + + + ); + } + }); + const form = TestUtils.renderIntoDocument(); + + const formEl = TestUtils.findRenderedDOMComponentWithTag(form, 'form'); + TestUtils.Simulate.submit(formEl); + + }); + +}); diff --git a/specs/Element-spec.jsx b/specs/Element-spec.jsx deleted file mode 100644 index d09746d0..00000000 --- a/specs/Element-spec.jsx +++ /dev/null @@ -1,622 +0,0 @@ -var React = require('react/addons'); -var TestUtils = React.addons.TestUtils; -var Formsy = require('./../src/main.js'); - -describe('Element', function() { - - it('should return passed and setValue() value when using getValue()', function () { - - var TestInput = React.createClass({ - mixins: [Formsy.Mixin], - updateValue: function (event) { - this.setValue(event.target.value); - }, - render: function () { - return - } - }); - var form = TestUtils.renderIntoDocument( - - - - ); - - var input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT'); - expect(input.value).toBe('foo'); - TestUtils.Simulate.change(input, {target: {value: 'foobar'}}); - expect(input.value).toBe('foobar'); - - }); - - it('should set back to pristine value when running reset', function () { - - var reset = null; - var TestInput = React.createClass({ - mixins: [Formsy.Mixin], - componentDidMount: function () { - reset = this.resetValue; - }, - updateValue: function (event) { - this.setValue(event.target.value); - }, - render: function () { - return - } - }); - var form = TestUtils.renderIntoDocument( - - - - ); - - var input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT'); - TestUtils.Simulate.change(input, {target: {value: 'foobar'}}); - reset(); - expect(input.value).toBe('foo'); - - }); - - it('should return error message passed when calling getErrorMessage()', function () { - - var getErrorMessage = null; - var TestInput = React.createClass({ - mixins: [Formsy.Mixin], - componentDidMount: function () { - getErrorMessage = this.getErrorMessage; - }, - updateValue: function (event) { - this.setValue(event.target.value); - }, - render: function () { - return - } - }); - var form = TestUtils.renderIntoDocument( - - - - ); - - expect(getErrorMessage()).toBe('Has to be email'); - - }); - - it('should return true or false when calling isValid() depending on valid state', function () { - - var isValid = null; - var TestInput = React.createClass({ - mixins: [Formsy.Mixin], - componentDidMount: function () { - isValid = this.isValid; - }, - updateValue: function (event) { - this.setValue(event.target.value); - }, - render: function () { - return - } - }); - var form = TestUtils.renderIntoDocument( - - - - ); - - expect(isValid()).toBe(false); - var input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT'); - TestUtils.Simulate.change(input, {target: {value: 'foo@foo.com'}}); - expect(isValid()).toBe(true); - - }); - - it('should return true or false when calling isRequired() depending on passed required attribute', function () { - - var isRequireds = []; - var TestInput = React.createClass({ - mixins: [Formsy.Mixin], - componentDidMount: function () { - isRequireds.push(this.isRequired); - }, - updateValue: function (event) { - this.setValue(event.target.value); - }, - render: function () { - return - } - }); - var form = TestUtils.renderIntoDocument( - - - - - - ); - - expect(isRequireds[0]()).toBe(false); - expect(isRequireds[1]()).toBe(true); - expect(isRequireds[2]()).toBe(true); - - }); - - it('should return true or false when calling showRequired() depending on input being empty and required is passed, or not', function () { - - var showRequireds = []; - var TestInput = React.createClass({ - mixins: [Formsy.Mixin], - componentDidMount: function () { - showRequireds.push(this.showRequired); - }, - updateValue: function (event) { - this.setValue(event.target.value); - }, - render: function () { - return - } - }); - var form = TestUtils.renderIntoDocument( - - - - - - ); - - expect(showRequireds[0]()).toBe(false); - expect(showRequireds[1]()).toBe(true); - expect(showRequireds[2]()).toBe(false); - - }); - - it('should return true or false when calling isPristine() depending on input has been "touched" or not', function () { - - var isPristine = null; - var TestInput = React.createClass({ - mixins: [Formsy.Mixin], - componentDidMount: function () { - isPristine = this.isPristine; - }, - updateValue: function (event) { - this.setValue(event.target.value); - }, - render: function () { - return - } - }); - var form = TestUtils.renderIntoDocument( - - - - ); - - expect(isPristine()).toBe(true); - var input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT'); - TestUtils.Simulate.change(input, {target: {value: 'foo'}}); - expect(isPristine()).toBe(false); - - }); - -it('should allow an undefined value to be updated to a value', function (done) { - var TestInput = React.createClass({ - mixins: [Formsy.Mixin], - changeValue: function (event) { - this.setValue(event.target.value); - }, - render: function () { - return - } - }); - var TestForm = React.createClass({ - getInitialState: function () { - return {value: undefined}; - }, - changeValue: function () { - this.setState({ - value: 'foo' - }); - }, - render: function () { - return ( - - - - ); - } - }); - var form = TestUtils.renderIntoDocument( - - ); - - form.changeValue(); - var input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT'); - setTimeout(function () { - expect(input.value).toBe('foo'); - done(); - }, 0); - }); - - it('should be able to test a values validity', function () { - - var isInvalid = false; - var TestInput = React.createClass({ - mixins: [Formsy.Mixin], - render: function () { - return - } - }); - var TestForm = React.createClass({ - render: function () { - return ( - - - - ); - } - }); - var form = TestUtils.renderIntoDocument( - - ); - - var input = TestUtils.findRenderedComponentWithType(form, TestInput); - expect(input.isValidValue('foo@bar.com')).toBe(true); - expect(input.isValidValue('foo@bar')).toBe(false); - - }); - - it('should be able to use an object as validations property', function () { - - var TestInput = React.createClass({ - mixins: [Formsy.Mixin], - render: function () { - return - } - }); - var TestForm = React.createClass({ - render: function () { - return ( - - - - ); - } - }); - var form = TestUtils.renderIntoDocument( - - ); - - var input = TestUtils.findRenderedComponentWithType(form, TestInput); - expect(input.isValidValue('foo@bar.com')).toBe(true); - expect(input.isValidValue('foo@bar')).toBe(false); - }); - - it('should be able to pass complex values to a validation rule', function () { - - var TestInput = React.createClass({ - mixins: [Formsy.Mixin], - changeValue: function (event) { - this.setValue(event.target.value); - }, - render: function () { - return - } - }); - var TestForm = React.createClass({ - render: function () { - return ( - - - - ); - } - }); - var form = TestUtils.renderIntoDocument( - - ); - - var inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput); - expect(inputComponent.isValid()).toBe(true); - var input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT'); - TestUtils.Simulate.change(input, {target: {value: 'bar'}}); - expect(inputComponent.isValid()).toBe(false); - }); - - it('should be able to run a function to validate', function () { - - var TestInput = React.createClass({ - mixins: [Formsy.Mixin], - changeValue: function (event) { - this.setValue(event.target.value); - }, - render: function () { - return - } - }); - var TestForm = React.createClass({ - customValidationA: function (values, value) { - return value === 'foo'; - }, - customValidationB: function (values, value) { - return value === 'foo' && values.A === 'foo'; - }, - render: function () { - return ( - - - - - ); - } - }); - var form = TestUtils.renderIntoDocument( - - ); - - var inputComponent = TestUtils.scryRenderedComponentsWithType(form, TestInput); - expect(inputComponent[0].isValid()).toBe(true); - expect(inputComponent[1].isValid()).toBe(true); - var input = TestUtils.scryRenderedDOMComponentsWithTag(form, 'INPUT'); - TestUtils.Simulate.change(input[0], {target: {value: 'bar'}}); - expect(inputComponent[0].isValid()).toBe(false); - expect(inputComponent[1].isValid()).toBe(false); - }); - - it('should override all error messages with error messages passed by form', function () { - var TestInput = React.createClass({ - mixins: [Formsy.Mixin], - render: function () { - return - } - }); - var TestForm = React.createClass({ - render: function () { - return ( - - - - ); - } - }); - var form = TestUtils.renderIntoDocument( - - ); - - var inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput); - expect(inputComponent.getErrorMessage()).toBe('bar'); - }); - - it('should override validation rules with required rules', function () { - var TestInput = React.createClass({ - mixins: [Formsy.Mixin], - render: function () { - return - } - }); - var TestForm = React.createClass({ - render: function () { - return ( - - - - ); - } - }); - var form = TestUtils.renderIntoDocument( - - ); - - var inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput); - expect(inputComponent.getErrorMessage()).toBe('bar3'); - }); - - it('should fall back to default error message when non exist in validationErrors map', function () { - var TestInput = React.createClass({ - mixins: [Formsy.Mixin], - render: function () { - return - } - }); - var TestForm = React.createClass({ - render: function () { - return ( - - - - ); - } - }); - var form = TestUtils.renderIntoDocument( - - ); - - var inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput); - expect(inputComponent.getErrorMessage()).toBe('bar'); - }); - - it('should not be valid if it is required and required rule is true', function () { - var TestInput = React.createClass({ - mixins: [Formsy.Mixin], - render: function () { - return - } - }); - var TestForm = React.createClass({ - render: function () { - return ( - - - - ); - } - }); - var form = TestUtils.renderIntoDocument( - - ); - - var inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput); - expect(inputComponent.isValid()).toBe(false); - }); - - it('should handle objects and arrays as values', function () { - - var TestInput = React.createClass({ - mixins: [Formsy.Mixin], - render: function () { - return
{JSON.stringify(this.getValue())}
- } - }); - var TestForm = React.createClass({ - getInitialState: function () { - return { - foo: {foo: 'bar'}, - bar: ['foo'] - }; - }, - render: function () { - return ( - - - - - ); - } - }); - var form = TestUtils.renderIntoDocument(); - - form.setState({ - foo: {foo: 'foo'}, - bar: ['bar'] - }); - - var inputs = TestUtils.scryRenderedComponentsWithType(form, TestInput); - expect(inputs[0].getValue()).toEqual({foo: 'foo'}); - expect(inputs[1].getValue()).toEqual(['bar']); - - }); - - it('should handle isFormDisabled with dynamic inputs', function () { - - var TestInput = React.createClass({ - mixins: [Formsy.Mixin], - render: function () { - return - } - }); - - var TestForm = React.createClass({ - getInitialState: function () { - return { - bool: true - }; - }, - flip: function () { - this.setState({ - bool: !this.state.bool - }); - }, - render: function () { - return ( - - {this.state.bool ? - : - - } - - ); - } - }); - - var form = TestUtils.renderIntoDocument(); - var input = TestUtils.findRenderedComponentWithType(form, TestInput); - expect(input.isFormDisabled()).toBe(true); - form.flip(); - expect(input.isFormDisabled()).toBe(false); - - }); - - it('should allow for dot notation in name which maps to a deep object', function () { - - var TestInput = React.createClass({ - mixins: [Formsy.Mixin], - render: function () { - return - } - }); - - var TestForm = React.createClass({ - onSubmit: function (model) { - expect(model).toEqual({foo: {bar: 'foo', test: 'test'}}); - }, - render: function () { - return ( - - - - - ); - } - }); - - var form = TestUtils.renderIntoDocument(); - var formEl = TestUtils.findRenderedDOMComponentWithTag(form, 'form'); - TestUtils.Simulate.submit(formEl); - - }); - - it('should allow for application/x-www-form-urlencoded syntax and convert to object', function () { - - var TestInput = React.createClass({ - mixins: [Formsy.Mixin], - render: function () { - return - } - }); - - var TestForm = React.createClass({ - onSubmit: function (model) { - expect(model).toEqual({foo: ['foo', 'bar']}); - }, - render: function () { - return ( - - - - - ); - } - }); - - var form = TestUtils.renderIntoDocument(); - var formEl = TestUtils.findRenderedDOMComponentWithTag(form, 'form'); - TestUtils.Simulate.submit(formEl); - - }); - -}); diff --git a/specs/Formsy-spec.js b/specs/Formsy-spec.js new file mode 100755 index 00000000..211eae23 --- /dev/null +++ b/specs/Formsy-spec.js @@ -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(); + expect(React.findDOMNode(form).tagName).toEqual('FORM'); + }); + + it('should set a class name if passed', function () { + const form = TestUtils.renderIntoDocument( ); + 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 ( + (model = formModel)}> +

Test

+ { null } + { undefined } + +
+ ); + } + }); + + const form = TestUtils.renderIntoDocument(); + 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 ( + (model = formModel)}> + {inputs} + ); + } + }); + const form = TestUtils.renderIntoDocument(); + + // Wait before adding the input + setTimeout(() => { + inputs.push(); + + 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 ( + (model = formModel)}> + {inputs} + ); + } + }); + const form = TestUtils.renderIntoDocument(); + + // Wait before adding the input + immediate(() => { + inputs.push(); + + 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 = ; + + return ( + (model = formModel)}> + {input} + ); + } + }); + let form = TestUtils.renderIntoDocument(); + + // Wait before changing the input + immediate(() => { + form = TestUtils.renderIntoDocument(); + + 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) => ); + return ( + onSubmit(arg1)} + onValid={() => (isValid = true)} + onInvalid={() => (isValid = false)}> + { builtInputs } + + ); + } + }); + + 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(); + 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(); + 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(); + 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(); + 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(); + 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 ; + } + }); + TestUtils.renderIntoDocument(); + 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 ( + + + + ); + } + }); + const form = TestUtils.renderIntoDocument(); + 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 ( + + {inputs} + ); + } + }); + TestUtils.renderIntoDocument(); + + // Wait before adding the input + inputs.push(); + + 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 ( + + + ); + } + }); + const form = TestUtils.renderIntoDocument(); + + 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 ( + + + ); + } + }); + const form = TestUtils.renderIntoDocument(); + + // 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 ( + (isCalled = true)}> + + ); + } + }); + const form = TestUtils.renderIntoDocument(); + + 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 ( + (isCalled = true)}> + + ); + } + }); + const form = TestUtils.renderIntoDocument( + + ); + + 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 ( + onSubmit(x)}> + + + + ); + } + }); + + beforeEach(() => { + onSubmit = jasmine.createSpy('onSubmit'); + }); + + it("should call onSubmit correctly", function () { + const form = TestUtils.renderIntoDocument(); + TestUtils.Simulate.submit(React.findDOMNode(form)); + expect(onSubmit).toHaveBeenCalledWith({foo: false}); + }); + + it("should allow dynamic changes to false", function () { + const form = TestUtils.renderIntoDocument(); + 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(); + 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(); + 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(); + 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) => ); + return ( + + { builtInputs } + { this.props.children } + + ); + } + }); + + beforeEach(() => { + onChange = jasmine.createSpy('onChange'); + }); + + it('initially returns false', function () { + const form = TestUtils.renderIntoDocument(); + expect(form.refs.formsy.isChanged()).toEqual(false); + expect(onChange).not.toHaveBeenCalled(); + }); + + it('returns true when changed', function () { + const form = TestUtils.renderIntoDocument(); + 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(); + 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); + }); + }); + +}); diff --git a/specs/Formsy-spec.jsx b/specs/Formsy-spec.jsx deleted file mode 100755 index d9d67fa3..00000000 --- a/specs/Formsy-spec.jsx +++ /dev/null @@ -1,693 +0,0 @@ -var React = require('react/addons'); -var TestUtils = React.addons.TestUtils; -var Formsy = require('./../src/main.js'); - -describe('Formsy', function () { - - describe('Setting up a form', function () { - - it('should render a form into the document', function () { - var form = TestUtils.renderIntoDocument( ); - expect(React.findDOMNode(form).tagName).toEqual('FORM'); - }); - - it('should set a class name if passed', function () { - var form = TestUtils.renderIntoDocument( ); - expect(React.findDOMNode(form).className).toEqual('foo'); - }); - - it('should allow for null/undefined children', function (done) { - var TestInput = React.createClass({ - mixins: [Formsy.Mixin], - changeValue: function (event) { - this.setValue(event.target.value); - }, - render: function () { - return - } - }); - - var model = null; - var TestForm = React.createClass({ - onSubmit: function (formModel) { - model = formModel; - }, - render: function () { - return ( - -

Test

- { null } - { undefined } - -
- ); - } - }); - - var form = TestUtils.renderIntoDocument(); - setTimeout(function () { - TestUtils.Simulate.submit(React.findDOMNode(form)); - expect(model).toEqual({name: 'foo'}); - done(); - }, 10); - }); - - it('should allow for inputs being added dynamically', function (done) { - - var inputs = []; - var forceUpdate = null; - var model = null; - var TestInput = React.createClass({ - mixins: [Formsy.Mixin], - render: function () { - return
- } - }); - var TestForm = React.createClass({ - componentWillMount: function () { - forceUpdate = this.forceUpdate.bind(this); - }, - onSubmit: function (formModel) { - model = formModel; - }, - render: function () { - return ( - - {inputs} - ); - } - }); - var form = TestUtils.renderIntoDocument( - - ); - - // Wait before adding the input - setTimeout(function () { - - inputs.push(); - - forceUpdate(function () { - // Wait for next event loop, as that does the form - setTimeout(function () { - TestUtils.Simulate.submit(React.findDOMNode(form)); - expect(model.test).toBeDefined(); - done(); - }, 0); - - }); - - }, 10); - - }); - - it('should allow dynamically added inputs to update the form-model', function (done) { - - var inputs = []; - var forceUpdate = null; - var model = null; - var TestInput = React.createClass({ - mixins: [Formsy.Mixin], - changeValue: function (event) { - this.setValue(event.target.value); - }, - render: function () { - return - } - }); - var TestForm = React.createClass({ - componentWillMount: function () { - forceUpdate = this.forceUpdate.bind(this); - }, - onSubmit: function (formModel) { - model = formModel; - }, - render: function () { - return ( - - {inputs} - ); - } - }); - var form = TestUtils.renderIntoDocument( - - ); - - // Wait before adding the input - setTimeout(function () { - - inputs.push(); - - forceUpdate(function () { - - // Wait for next event loop, as that does the form - setTimeout(function () { - TestUtils.Simulate.change(TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT'), {target: {value: 'foo'}}); - TestUtils.Simulate.submit(React.findDOMNode(form)); - expect(model.test).toBe('foo'); - done(); - }, 0); - - }); - - }, 0); - - }); - - it('should allow a dynamically updated input to update the form-model', function (done) { - - var forceUpdate = null; - var model = null; - var TestInput = React.createClass({ - mixins: [Formsy.Mixin], - changeValue: function (event) { - this.setValue(event.target.value); - }, - render: function () { - return - } - }); - - var input; - var TestForm = React.createClass({ - componentWillMount: function () { - forceUpdate = this.forceUpdate.bind(this); - }, - onSubmit: function (formModel) { - model = formModel; - }, - render: function () { - input = ; - - return ( - - {input} - ); - } - }); - var form = TestUtils.renderIntoDocument(); - - // Wait before changing the input - setTimeout(function () { - - form = TestUtils.renderIntoDocument(); - - forceUpdate(function () { - // Wait for next event loop, as that does the form - setTimeout(function () { - TestUtils.Simulate.submit(React.findDOMNode(form)); - expect(model.test).toBe('bar'); - done(); - }, 0); - - }); - - }, 10); - - }); - - describe('validations', function() { - var CheckValid, onSubmit, OtherCheckValid; - var isValid; - - var TestInput = React.createClass({ - mixins: [Formsy.Mixin], - changeValue: function (event) { - this.setValue(event.target.value); - }, - render: function () { - return - } - }); - - var TestForm = React.createClass({ - getDefaultProps: function() { - return { - inputs: [], - }; - }, - render: function () { - var builtInputs = []; - var inputs = this.props.inputs; - for (var i=0; i < inputs.length; i++) { - var input = inputs[i]; - builtInputs.push(); - } - var _this = this; - return - { builtInputs } - ; - } - }); - - beforeEach(function() { - isValid = true; - CheckValid = jasmine.createSpy('CheckValid'); - Formsy.addValidationRule('CheckValid', CheckValid); - OtherCheckValid = jasmine.createSpy('CheckValid'); - Formsy.addValidationRule('OtherCheckValid', OtherCheckValid); - onSubmit = jasmine.createSpy('onSubmit'); - }); - - it('should run when the input changes', function() { - var form = TestUtils.renderIntoDocument(); - var 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() { - var form = TestUtils.renderIntoDocument(); - form.setProps({inputs: [{name: 'one', validations: 'OtherCheckValid', value: 'foo'}] }); - var 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) { - var form = TestUtils.renderIntoDocument(); - expect(isValid).toEqual(true); - form.setProps({inputs: [ - {name: 'one', validations: 'isEmail', value: 'foo@bar.com'}, - {name: 'two', validations: 'isEmail', value: 'foo@bar'}, - ]}, function() { - setTimeout(function() { - expect(isValid).toEqual(false); - done(); - }, 0); - }); - }); - - it('should validate a form when removing an invalid input', function(done) { - var form = TestUtils.renderIntoDocument(); - expect(isValid).toEqual(false); - form.setProps({inputs: [{name: 'one', validations: 'isEmail', value: 'foo@bar.com'}]}, function() { - setTimeout(function() { - expect(isValid).toEqual(true); - done(); - }, 0); - }); - }); - - it('runs multiple validations', function() { - var form = TestUtils.renderIntoDocument(); - var 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 () { - var hasChanged = jasmine.createSpy('onChange'); - var TestForm = React.createClass({ - onChange: function () { - hasChanged(); - }, - render: function () { - return ; - } - }); - var form = TestUtils.renderIntoDocument(); - expect(hasChanged).not.toHaveBeenCalled(); - }); - - it('should trigger onChange when form element is changed', function () { - var hasChanged = jasmine.createSpy('onChange'); - var MyInput = React.createClass({ - mixins: [Formsy.Mixin], - onChange: function (event) { - this.setValue(event.target.value); - }, - render: function () { - return - } - }); - var TestForm = React.createClass({ - onChange: function () { - hasChanged(); - }, - render: function () { - return ( - - - - ); - } - }); - var form = TestUtils.renderIntoDocument(); - TestUtils.Simulate.change(TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT'), {target: {value: 'bar'}}); - expect(hasChanged).toHaveBeenCalled(); - }); - - it('should trigger onChange when new input is added to form', function (done) { - var hasChanged = jasmine.createSpy('onChange'); - var inputs = []; - var forceUpdate = null; - var TestInput = React.createClass({ - mixins: [Formsy.Mixin], - changeValue: function (event) { - this.setValue(event.target.value); - }, - render: function () { - return - } - }); - var TestForm = React.createClass({ - componentWillMount: function () { - forceUpdate = this.forceUpdate.bind(this); - }, - onChange: function () { - hasChanged(); - }, - render: function () { - return ( - - {inputs} - ); - } - }); - var form = TestUtils.renderIntoDocument( - - ); - - // Wait before adding the input - inputs.push(); - - forceUpdate(function () { - - // Wait for next event loop, as that does the form - setTimeout(function () { - expect(hasChanged).toHaveBeenCalled(); - done(); - }, 0); - - }); - - }); - - }); - - describe('Update a form', function () { - - it('should allow elements to check if the form is disabled', function (done) { - - var TestInput = React.createClass({ - mixins: [Formsy.Mixin], - render: function () { - return - } - }); - var TestForm = React.createClass({ - getInitialState: function () { - return {disabled: true}; - }, - enableForm: function () { - this.setState({ - disabled: false - }); - }, - render: function () { - return ( - - - ); - } - }); - var form = TestUtils.renderIntoDocument( - - ); - - var input = TestUtils.findRenderedComponentWithType(form, TestInput); - expect(input.isFormDisabled()).toBe(true); - form.enableForm(); - setTimeout(function () { - expect(input.isFormDisabled()).toBe(false); - done(); - }, 0); - - }); - - it('should be possible to pass error state of elements by changing an errors attribute', function (done) { - - var TestInput = React.createClass({ - mixins: [Formsy.Mixin], - render: function () { - return ; - } - }); - var TestForm = React.createClass({ - getInitialState: function () { - return { - validationErrors: { - foo: 'bar' - } - }; - }, - onChange: function (values) { - if (values.foo) { - this.setState({ - validationErrors: {} - }); - } else { - this.setState({ - validationErrors: {foo: 'bar'} - }); - } - }, - render: function () { - return ( - - - ); - } - }); - var form = TestUtils.renderIntoDocument( - - ); - - // Wait for update - setTimeout(function () { - var input = TestUtils.findRenderedComponentWithType(form, TestInput); - expect(input.getErrorMessage()).toBe('bar'); - input.setValue('gotValue'); - - // Wait for update - setTimeout(function () { - expect(input.getErrorMessage()).toBe(null); - done(); - }, 0); - }, 0); - - }); - - - it('should trigger an onValidSubmit when submitting a valid form', function () { - - var isCalled = false; - var TestInput = React.createClass({ - mixins: [Formsy.Mixin], - render: function () { - return ; - } - }); - var TestForm = React.createClass({ - onValidSubmit: function () { - isCalled = true; - }, - render: function () { - return ( - - - ); - } - }); - var form = TestUtils.renderIntoDocument( - - ); - - var TestForm = TestUtils.findRenderedComponentWithType(form, TestForm); - TestUtils.Simulate.submit(React.findDOMNode(TestForm)); - expect(isCalled).toBe(true); - - }); - - it('should trigger an onInvalidSubmit when submitting an invalid form', function () { - - var isCalled = false; - var TestInput = React.createClass({ - mixins: [Formsy.Mixin], - render: function () { - return ; - } - }); - var TestForm = React.createClass({ - onInvalidSubmit: function () { - isCalled = true; - }, - render: function () { - return ( - - - ); - } - }); - var form = TestUtils.renderIntoDocument( - - ); - - var TestForm = TestUtils.findRenderedComponentWithType(form, TestForm); - TestUtils.Simulate.submit(React.findDOMNode(TestForm)); - expect(isCalled).toBe(true); - - }); - - }); - - describe("value === false", function() { - var onSubmit; - var TestInput = React.createClass({ - mixins: [Formsy.Mixin], - getDefaultProps: function() { - return { - type: "text", - }; - }, - changeValue: function() { - this.setValue(e.target[this.props.type === "checkbox" ? "checked" : "value"]); - }, - render: function () { - return - } - }); - - var TestForm = React.createClass({ - render: function () { - return ( - - - - - ); - } - }); - - beforeEach(function() { - onSubmit = jasmine.createSpy("onSubmit"); - }); - - it("should call onSubmit correctly", function() { - var form = TestUtils.renderIntoDocument(); - TestUtils.Simulate.submit(React.findDOMNode(form)); - expect(onSubmit).toHaveBeenCalledWith({foo: false}); - }); - - it("should allow dynamic changes to false", function() { - var form = TestUtils.renderIntoDocument(); - form.setProps({value: false}); - TestUtils.Simulate.submit(React.findDOMNode(form)); - expect(onSubmit).toHaveBeenCalledWith({foo: false}); - }); - - it("should say the form is submitted", function() { - var form = TestUtils.renderIntoDocument(); - var 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() { - var form = TestUtils.renderIntoDocument(); - var input = TestUtils.findRenderedComponentWithType(form, TestInput); - var formsyForm = TestUtils.findRenderedComponentWithType(form, Formsy.Form); - expect(input.getValue()).toBe(true); - form.setProps({value: false}); - expect(input.getValue()).toBe(false); - formsyForm.reset(); - expect(input.getValue()).toBe(true); - }); - - it("should be able to reset the form using custom data", function() { - var form = TestUtils.renderIntoDocument(); - var input = TestUtils.findRenderedComponentWithType(form, TestInput); - var formsyForm = TestUtils.findRenderedComponentWithType(form, Formsy.Form); - expect(input.getValue()).toBe(true); - form.setProps({value: false}); - expect(input.getValue()).toBe(false); - formsyForm.reset({ - foo: 'bar' - }); - expect(input.getValue()).toBe('bar'); - }); - - }); - - describe('.isChanged()', function() { - var onChange; - var TestInput = React.createClass({ - mixins: [Formsy.Mixin], - changeValue: function (event) { - this.setValue(event.target.value); - }, - render: function () { - return - } - }); - - var TestForm = React.createClass({ - getDefaultProps: function() { - return { - inputs: [], - }; - }, - render: function () { - var builtInputs = []; - var inputs = this.props.inputs; - for (var i=0; i < inputs.length; i++) { - var input = inputs[i]; - builtInputs.push(); - } - return - { builtInputs } - { this.props.children } - ; - } - }); - - beforeEach(function() { - onChange = jasmine.createSpy("onChange"); - }); - - it('initially returns false', function() { - var form = TestUtils.renderIntoDocument(); - expect(form.refs.formsy.isChanged()).toEqual(false); - expect(onChange).not.toHaveBeenCalled(); - }); - - it('returns true when changed', function() { - var form = TestUtils.renderIntoDocument(); - var 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() { - var form = TestUtils.renderIntoDocument(); - var 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); - }); - }); - -}); diff --git a/specs/Rules-equals-spec.js b/specs/Rules-equals-spec.js new file mode 100644 index 00000000..10557749 --- /dev/null +++ b/specs/Rules-equals-spec.js @@ -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 ; + } + }); + + form = TestUtils.renderIntoDocument( + + + + ); + + 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)); + +}); diff --git a/specs/Rules-equals-spec.jsx b/specs/Rules-equals-spec.jsx deleted file mode 100644 index a689b169..00000000 --- a/specs/Rules-equals-spec.jsx +++ /dev/null @@ -1,62 +0,0 @@ -var React = require('react/addons'); -var TestUtils = React.addons.TestUtils; -var Formsy = require('./../src/main.js'); - -describe('Rules: equals', function() { - var TestInput, isValid, form, input; - - function pass(value) { - return pass.length ? function () { - TestUtils.Simulate.change(input, {target: {value: value}}); - expect(isValid).toBe(true); - } : function () { expect(isValid).toBe(true); }; - } - - function fail(value) { - return fail.length ? function () { - TestUtils.Simulate.change(input, {target: {value: value}}); - expect(isValid).toBe(false); - } : function () { expect(isValid).toBe(false); }; - } - - beforeEach(function() { - TestInput = React.createClass({ - mixins: [Formsy.Mixin], - updateValue: function (event) { - this.setValue(event.target.value); - }, - render: function () { - isValid = this.isValid(); - return - } - }); - - form = TestUtils.renderIntoDocument( - - - - ); - - input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT'); - - }); - - afterEach(function() { - TestInput = isValid = form = null; - }); - - it('should pass with a default value', pass()); - - it('should fail when the value is not equal', fail('foo')); - - it('should pass when the value is equal', pass('myValue')); - - it('should pass with an empty string', pass('')); - - it('should pass with an undefined', pass(undefined)); - - it('should pass with a null', pass(null)); - - it('should fail with a number', fail(42)); - -}); diff --git a/specs/Rules-isAlpha-spec.js b/specs/Rules-isAlpha-spec.js new file mode 100644 index 00000000..5d795d76 --- /dev/null +++ b/specs/Rules-isAlpha-spec.js @@ -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 ; + } + }); + + form = TestUtils.renderIntoDocument( + + + + ); + + 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('myValue 42')); + + it('should pass with an undefined', pass(undefined)); + + it('should pass with a null', pass(null)); + + it('should pass with an empty string', pass('')); + + it('should fail with a number', fail(42)); + +}); diff --git a/specs/Rules-isAlpha-spec.jsx b/specs/Rules-isAlpha-spec.jsx deleted file mode 100644 index 60b7a5eb..00000000 --- a/specs/Rules-isAlpha-spec.jsx +++ /dev/null @@ -1,62 +0,0 @@ -var React = require('react/addons'); -var TestUtils = React.addons.TestUtils; -var Formsy = require('./../src/main.js'); - -describe('Rules: isAlpha', function() { - var TestInput, isValid, form, input; - - function pass(value) { - return pass.length ? function () { - TestUtils.Simulate.change(input, {target: {value: value}}); - expect(isValid).toBe(true); - } : function () { expect(isValid).toBe(true); }; - } - - function fail(value) { - return fail.length ? function () { - TestUtils.Simulate.change(input, {target: {value: value}}); - expect(isValid).toBe(false); - } : function () { expect(isValid).toBe(false); }; - } - - beforeEach(function() { - TestInput = React.createClass({ - mixins: [Formsy.Mixin], - updateValue: function (event) { - this.setValue(event.target.value); - }, - render: function () { - isValid = this.isValid(); - return - } - }); - - form = TestUtils.renderIntoDocument( - - - - ); - - input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT'); - - }); - - afterEach(function() { - TestInput = isValid = form = null; - }); - - it('should pass with a default value', pass()); - - it('should pass with a string is only latin letters', pass('myValue')); - - it('should fail with a string with numbers', fail('myValue 42')); - - it('should pass with an undefined', pass(undefined)); - - it('should pass with a null', pass(null)); - - it('should pass with an empty string', pass('')); - - it('should fail with a number', fail(42)); - -}); diff --git a/specs/Rules-isEmail-spec.js b/specs/Rules-isEmail-spec.js new file mode 100644 index 00000000..55b75888 --- /dev/null +++ b/specs/Rules-isEmail-spec.js @@ -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 ; + } + }); + + form = TestUtils.renderIntoDocument( + + + + ); + + 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)); + +}); diff --git a/specs/Rules-isEmail-spec.jsx b/specs/Rules-isEmail-spec.jsx deleted file mode 100644 index 29e5943f..00000000 --- a/specs/Rules-isEmail-spec.jsx +++ /dev/null @@ -1,62 +0,0 @@ -var React = require('react/addons'); -var TestUtils = React.addons.TestUtils; -var Formsy = require('./../src/main.js'); - -describe('Rules: isEmail', function() { - var TestInput, isValid, form, input; - - function pass(value) { - return pass.length ? function () { - TestUtils.Simulate.change(input, {target: {value: value}}); - expect(isValid).toBe(true); - } : function () { expect(isValid).toBe(true); }; - } - - function fail(value) { - return fail.length ? function () { - TestUtils.Simulate.change(input, {target: {value: value}}); - expect(isValid).toBe(false); - } : function () { expect(isValid).toBe(false); }; - } - - beforeEach(function() { - TestInput = React.createClass({ - mixins: [Formsy.Mixin], - updateValue: function (event) { - this.setValue(event.target.value); - }, - render: function () { - isValid = this.isValid(); - return - } - }); - - form = TestUtils.renderIntoDocument( - - - - ); - - input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT'); - - }); - - afterEach(function() { - TestInput = isValid = form = null; - }); - - it('should pass with a default value', pass()); - - it('should fail with "foo"', fail('foo')); - - it('should pass with "foo@foo.com"', pass('foo@foo.com')); - - it('should pass with an undefined', pass(undefined)); - - it('should pass with a null', pass(null)); - - it('should pass with an empty string', pass('')); - - it('should fail with a number', fail(42)); - -}); diff --git a/specs/Rules-isEmptyString-spec.js b/specs/Rules-isEmptyString-spec.js new file mode 100644 index 00000000..e68265a0 --- /dev/null +++ b/specs/Rules-isEmptyString-spec.js @@ -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 ; + } + }); + + form = TestUtils.renderIntoDocument( + + + + ); + + 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)); + +}); diff --git a/specs/Rules-isEmptyString-spec.jsx b/specs/Rules-isEmptyString-spec.jsx deleted file mode 100644 index 7fdad833..00000000 --- a/specs/Rules-isEmptyString-spec.jsx +++ /dev/null @@ -1,62 +0,0 @@ -var React = require('react/addons'); -var TestUtils = React.addons.TestUtils; -var Formsy = require('./../src/main.js'); - -describe('Rules: isEmptyString', function() { - var TestInput, isValid, form, input; - - function pass(value) { - return pass.length ? function () { - TestUtils.Simulate.change(input, {target: {value: value}}); - expect(isValid).toBe(true); - } : function () { expect(isValid).toBe(true); }; - } - - function fail(value) { - return fail.length ? function () { - TestUtils.Simulate.change(input, {target: {value: value}}); - expect(isValid).toBe(false); - } : function () { expect(isValid).toBe(false); }; - } - - beforeEach(function() { - TestInput = React.createClass({ - mixins: [Formsy.Mixin], - updateValue: function (event) { - this.setValue(event.target.value); - }, - render: function () { - isValid = this.isValid(); - return - } - }); - - form = TestUtils.renderIntoDocument( - - - - ); - - input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT'); - - }); - - afterEach(function() { - TestInput = isValid = form = null; - }); - - it('should fail with a default value', fail()); - - it('should fail with non-empty string', fail('asd')); - - it('should pass with an empty string', pass('')); - - it('should fail with a undefined', fail(undefined)); - - it('should fail with a null', fail(null)); - - it('should fail with a number', fail(123)); - - it('should fail with a zero', fail(0)); - -}); diff --git a/specs/Rules-isExisty-spec.js b/specs/Rules-isExisty-spec.js new file mode 100644 index 00000000..25821fbe --- /dev/null +++ b/specs/Rules-isExisty-spec.js @@ -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 ; + } + }); + + form = TestUtils.renderIntoDocument( + + + + ); + + 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)); + +}); diff --git a/specs/Rules-isExisty-spec.jsx b/specs/Rules-isExisty-spec.jsx deleted file mode 100644 index e946b819..00000000 --- a/specs/Rules-isExisty-spec.jsx +++ /dev/null @@ -1,62 +0,0 @@ -var React = require('react/addons'); -var TestUtils = React.addons.TestUtils; -var Formsy = require('./../src/main.js'); - -describe('Rules: isExisty', function() { - var TestInput, isValid, form, input; - - function pass(value) { - return pass.length ? function () { - TestUtils.Simulate.change(input, {target: {value: value}}); - expect(isValid).toBe(true); - } : function () { expect(isValid).toBe(true); }; - } - - function fail(value) { - return fail.length ? function () { - TestUtils.Simulate.change(input, {target: {value: value}}); - expect(isValid).toBe(false); - } : function () { expect(isValid).toBe(false); }; - } - - beforeEach(function() { - TestInput = React.createClass({ - mixins: [Formsy.Mixin], - updateValue: function (event) { - this.setValue(event.target.value); - }, - render: function () { - isValid = this.isValid(); - return - } - }); - - form = TestUtils.renderIntoDocument( - - - - ); - - input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT'); - - }); - - afterEach(function() { - TestInput = isValid = form = null; - }); - - it('should fail with a default value', fail()); - - it('should pass with a string', pass('myValue')); - - it('should pass with an empty string', pass('')); - - it('should fail with an undefined', fail(undefined)); - - it('should fail with a null', fail(null)); - - it('should pass with a number', pass(42)); - - it('should pass with a zero', pass(0)); - -}); diff --git a/specs/Rules-isLength-spec.jsx b/specs/Rules-isLength-spec.js similarity index 57% rename from specs/Rules-isLength-spec.jsx rename to specs/Rules-isLength-spec.js index 1e52cc3d..5f7e21c2 100644 --- a/specs/Rules-isLength-spec.jsx +++ b/specs/Rules-isLength-spec.js @@ -1,47 +1,45 @@ -var React = require('react/addons'); -var TestUtils = React.addons.TestUtils; -var Formsy = require('./../src/main.js'); +import React from 'react'; +import TestUtils from 'react-addons-test-utils'; -describe('Rules: isLength', function() { - var TestInput, isValid, form, input; +import Formsy from './..'; +import { customizeInput } from './utils/TestInput'; + +describe('Rules: isLength', function () { + let Input, isValid, form, input; function pass(value) { - return pass.length ? function () { - TestUtils.Simulate.change(input, {target: {value: value}}); + return pass.length ? () => { + TestUtils.Simulate.change(input, {target: {value}}); expect(isValid).toBe(true); - } : function () { expect(isValid).toBe(true); }; + } : () => expect(isValid).toBe(true); } function fail(value) { - return fail.length ? function () { - TestUtils.Simulate.change(input, {target: {value: value}}); + return fail.length ? () => { + TestUtils.Simulate.change(input, {target: {value}}); expect(isValid).toBe(false); - } : function () { expect(isValid).toBe(false); }; + } : () => expect(isValid).toBe(false); } - beforeEach(function() { - TestInput = React.createClass({ - mixins: [Formsy.Mixin], - updateValue: function (event) { - this.setValue(event.target.value); - }, - render: function () { + beforeEach(() => { + Input = customizeInput({ + render() { isValid = this.isValid(); - return + return ; } }); }); - afterEach(function() { - TestInput = isValid = form = null; + afterEach(() => { + Input = isValid = form = null; }); - describe('isLength:3', function() { + describe('isLength:3', () => { - beforeEach(function() { + beforeEach(() => { form = TestUtils.renderIntoDocument( - + ); @@ -66,12 +64,12 @@ describe('Rules: isLength', function() { }); - describe('isLength:0', function() { + describe('isLength:0', () => { - beforeEach(function() { + beforeEach(() => { form = TestUtils.renderIntoDocument( - + ); diff --git a/specs/Rules-isNumeric-spec.jsx b/specs/Rules-isNumeric-spec.js similarity index 53% rename from specs/Rules-isNumeric-spec.jsx rename to specs/Rules-isNumeric-spec.js index 94e21fd0..f7b19387 100644 --- a/specs/Rules-isNumeric-spec.jsx +++ b/specs/Rules-isNumeric-spec.js @@ -1,39 +1,37 @@ -var React = require('react/addons'); -var TestUtils = React.addons.TestUtils; -var Formsy = require('./../src/main.js'); +import React from 'react'; +import TestUtils from 'react-addons-test-utils'; -describe('Rules: isNumeric', function() { - var TestInput, isValid, form, input; +import Formsy from './..'; +import { customizeInput } from './utils/TestInput'; + +describe('Rules: isNumeric', function () { + let Input, isValid, form, input; function pass(value) { - return pass.length ? function () { - TestUtils.Simulate.change(input, {target: {value: value}}); + return pass.length ? () => { + TestUtils.Simulate.change(input, {target: {value}}); expect(isValid).toBe(true); - } : function () { expect(isValid).toBe(true); }; + } : () => expect(isValid).toBe(true); } function fail(value) { - return fail.length ? function () { - TestUtils.Simulate.change(input, {target: {value: value}}); + return fail.length ? () => { + TestUtils.Simulate.change(input, {target: {value}}); expect(isValid).toBe(false); - } : function () { expect(isValid).toBe(false); }; + } : () => expect(isValid).toBe(false); } - beforeEach(function() { - TestInput = React.createClass({ - mixins: [Formsy.Mixin], - updateValue: function (event) { - this.setValue(event.target.value); - }, - render: function () { + beforeEach(() => { + Input = customizeInput({ + render() { isValid = this.isValid(); - return + return ; } }); form = TestUtils.renderIntoDocument( - + ); @@ -41,8 +39,8 @@ describe('Rules: isNumeric', function() { }); - afterEach(function() { - TestInput = isValid = form = null; + afterEach(() => { + Input = isValid = form = null; }); it('should pass with a default value', pass()); diff --git a/specs/Rules-isUrl-spec.js b/specs/Rules-isUrl-spec.js new file mode 100644 index 00000000..97555122 --- /dev/null +++ b/specs/Rules-isUrl-spec.js @@ -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 ; + } + }); + + form = TestUtils.renderIntoDocument( + + + + ); + + 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('')); + +}); diff --git a/specs/Rules-isUrl-spec.jsx b/specs/Rules-isUrl-spec.jsx deleted file mode 100644 index cabf8ac2..00000000 --- a/specs/Rules-isUrl-spec.jsx +++ /dev/null @@ -1,62 +0,0 @@ -var React = require('react/addons'); -var TestUtils = React.addons.TestUtils; -var Formsy = require('./../src/main.js'); - -describe('Rules: isUrl', function() { - var TestInput, isValid, form, input; - - function pass(value) { - return pass.length ? function () { - TestUtils.Simulate.change(input, {target: {value: value}}); - expect(isValid).toBe(true); - } : function () { expect(isValid).toBe(true); }; - } - - function fail(value) { - return fail.length ? function () { - TestUtils.Simulate.change(input, {target: {value: value}}); - expect(isValid).toBe(false); - } : function () { expect(isValid).toBe(false); }; - } - - beforeEach(function() { - TestInput = React.createClass({ - mixins: [Formsy.Mixin], - updateValue: function (event) { - this.setValue(event.target.value); - }, - render: function () { - isValid = this.isValid(); - return - } - }); - - form = TestUtils.renderIntoDocument( - - - - ); - - input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT'); - - }); - - afterEach(function() { - TestInput = isValid = form = null; - }); - - it('should pass with a default value', pass()); - - it('should fail with "foo"', fail('foo')); - - it('should pass with "https://www.google.com/"', pass('https://www.google.com/')); - - it('should pass with an undefined', pass(undefined)); - - it('should pass with a null', pass(null)); - - it('should fail with a number', fail(42)); - - it('should pass with an empty string', pass('')); - -}); diff --git a/specs/Rules-isWords-spec.js b/specs/Rules-isWords-spec.js new file mode 100644 index 00000000..fffd0803 --- /dev/null +++ b/specs/Rules-isWords-spec.js @@ -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 ; + } + }); + + form = TestUtils.renderIntoDocument( + + + + ); + + 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)); + +}); diff --git a/specs/Rules-isWords-spec.jsx b/specs/Rules-isWords-spec.jsx deleted file mode 100644 index f7752f4c..00000000 --- a/specs/Rules-isWords-spec.jsx +++ /dev/null @@ -1,62 +0,0 @@ -var React = require('react/addons'); -var TestUtils = React.addons.TestUtils; -var Formsy = require('./../src/main.js'); - -describe('Rules: isWords', function() { - var TestInput, isValid, form, input; - - function pass(value) { - return pass.length ? function () { - TestUtils.Simulate.change(input, {target: {value: value}}); - expect(isValid).toBe(true); - } : function () { expect(isValid).toBe(true); }; - } - - function fail(value) { - return fail.length ? function () { - TestUtils.Simulate.change(input, {target: {value: value}}); - expect(isValid).toBe(false); - } : function () { expect(isValid).toBe(false); }; - } - - beforeEach(function() { - TestInput = React.createClass({ - mixins: [Formsy.Mixin], - updateValue: function (event) { - this.setValue(event.target.value); - }, - render: function () { - isValid = this.isValid(); - return - } - }); - - form = TestUtils.renderIntoDocument( - - - - ); - - input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT'); - - }); - - afterEach(function() { - TestInput = isValid = form = null; - }); - - it('should pass with a default value', pass()); - - it('should pass with a 1 word', pass('sup')); - - it('should pass with 2 words', pass('sup dude')); - - it('should fail with a string with numbers', fail('myValue 42')); - - it('should pass with an undefined', pass(undefined)); - - it('should pass with a null', pass(null)); - - it('should fail with a number', fail(42)); - -}); diff --git a/specs/Rules-maxLength-spec.jsx b/specs/Rules-maxLength-spec.js similarity index 50% rename from specs/Rules-maxLength-spec.jsx rename to specs/Rules-maxLength-spec.js index 5c001031..727c8207 100644 --- a/specs/Rules-maxLength-spec.jsx +++ b/specs/Rules-maxLength-spec.js @@ -1,39 +1,37 @@ -var React = require('react/addons'); -var TestUtils = React.addons.TestUtils; -var Formsy = require('./../src/main.js'); +import React from 'react'; +import TestUtils from 'react-addons-test-utils'; -describe('Rules: maxLength', function() { - var TestInput, isValid, form, input; +import Formsy from './..'; +import { customizeInput } from './utils/TestInput'; + +describe('Rules: maxLength', function () { + let Input, isValid, form, input; function pass(value) { - return pass.length ? function () { - TestUtils.Simulate.change(input, {target: {value: value}}); + return pass.length ? () => { + TestUtils.Simulate.change(input, {target: {value}}); expect(isValid).toBe(true); - } : function () { expect(isValid).toBe(true); }; + } : () => expect(isValid).toBe(true); } function fail(value) { - return fail.length ? function () { - TestUtils.Simulate.change(input, {target: {value: value}}); + return fail.length ? () => { + TestUtils.Simulate.change(input, {target: {value}}); expect(isValid).toBe(false); - } : function () { expect(isValid).toBe(false); }; + } : () => expect(isValid).toBe(false); } - beforeEach(function() { - TestInput = React.createClass({ - mixins: [Formsy.Mixin], - updateValue: function (event) { - this.setValue(event.target.value); - }, - render: function () { + beforeEach(() => { + Input = customizeInput({ + render() { isValid = this.isValid(); - return + return ; } }); form = TestUtils.renderIntoDocument( - + ); @@ -41,8 +39,8 @@ describe('Rules: maxLength', function() { }); - afterEach(function() { - TestInput = isValid = form = null; + afterEach(() => { + Input = isValid = form = null; }); it('should pass with a default value', pass()); diff --git a/specs/Rules-minLength-spec.jsx b/specs/Rules-minLength-spec.js similarity index 57% rename from specs/Rules-minLength-spec.jsx rename to specs/Rules-minLength-spec.js index 57b77125..be9a4918 100644 --- a/specs/Rules-minLength-spec.jsx +++ b/specs/Rules-minLength-spec.js @@ -1,47 +1,45 @@ -var React = require('react/addons'); -var TestUtils = React.addons.TestUtils; -var Formsy = require('./../src/main.js'); +import React from 'react'; +import TestUtils from 'react-addons-test-utils'; -describe('Rules: minLength', function() { - var TestInput, isValid, form, input; +import Formsy from './..'; +import { customizeInput } from './utils/TestInput'; + +describe('Rules: minLength', function () { + let Input, isValid, form, input; function pass(value) { - return pass.length ? function () { - TestUtils.Simulate.change(input, {target: {value: value}}); + return pass.length ? () => { + TestUtils.Simulate.change(input, {target: {value}}); expect(isValid).toBe(true); - } : function () { expect(isValid).toBe(true); }; + } : () => expect(isValid).toBe(true); } function fail(value) { - return fail.length ? function () { - TestUtils.Simulate.change(input, {target: {value: value}}); + return fail.length ? () => { + TestUtils.Simulate.change(input, {target: {value}}); expect(isValid).toBe(false); - } : function () { expect(isValid).toBe(false); }; + } : () => expect(isValid).toBe(false); } - beforeEach(function() { - TestInput = React.createClass({ - mixins: [Formsy.Mixin], - updateValue: function (event) { - this.setValue(event.target.value); - }, - render: function () { + beforeEach(() => { + Input = customizeInput({ + render() { isValid = this.isValid(); - return + return ; } }); }); - afterEach(function() { - TestInput = isValid = form = null; + afterEach(() => { + Input = isValid = form = null; }); - describe('minLength:3', function() { + describe('minLength:3', function () { - beforeEach(function() { + beforeEach(() => { form = TestUtils.renderIntoDocument( - + ); @@ -66,12 +64,12 @@ describe('Rules: minLength', function() { }); - describe('minLength:0', function() { + describe('minLength:0', () => { - beforeEach(function() { + beforeEach(() => { form = TestUtils.renderIntoDocument( - + ); diff --git a/specs/Utils-spec.jsx b/specs/Utils-spec.js similarity index 55% rename from specs/Utils-spec.jsx rename to specs/Utils-spec.js index c32fa8cc..a113c1ed 100644 --- a/specs/Utils-spec.jsx +++ b/specs/Utils-spec.js @@ -1,15 +1,16 @@ -var utils = require('./../src/utils.js'); +import utils from './../src/utils.js'; -describe('Utils', function() { +describe('Utils', function () { - it('should check equality of objects and arrays', function () { - var objA = { foo: 'bar' }; - var objB = { foo: 'bar' }; - var objC = [{ foo: ['bar'] }]; - var objD = [{ foo: ['bar'] }]; - var objE, objF; - var objG = null; - var objH = null; + 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); diff --git a/specs/Validation-spec.js b/specs/Validation-spec.js new file mode 100644 index 00000000..a0d4fccb --- /dev/null +++ b/specs/Validation-spec.js @@ -0,0 +1,202 @@ +import React from 'react'; +import TestUtils from 'react-addons-test-utils'; + +import Formsy from './..'; +import TestInput, { customizeInput } from './utils/TestInput'; +import immediate from './utils/immediate'; + +describe('Validation', function () { + + it('should reset only changed form element when external error is passed', function (done) { + + const form = TestUtils.renderIntoDocument( + invalidate({ foo: 'bar', bar: 'foo' })}> + + + + ); + + const input = TestUtils.scryRenderedDOMComponentsWithTag(form, 'INPUT')[0]; + const inputComponents = TestUtils.scryRenderedComponentsWithType(form, TestInput); + + form.submit(); + expect(inputComponents[0].isValid()).toBe(false); + expect(inputComponents[1].isValid()).toBe(false); + + TestUtils.Simulate.change(input, {target: {value: 'bar'}}); + immediate(() => { + expect(inputComponents[0].isValid()).toBe(true); + expect(inputComponents[1].isValid()).toBe(false); + done(); + }); + + }); + + it('should let normal validation take over when component with external error is changed', function (done) { + + const form = TestUtils.renderIntoDocument( + invalidate({ foo: 'bar' })}> + + + ); + + const input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT'); + const inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput); + + form.submit(); + expect(inputComponent.isValid()).toBe(false); + + TestUtils.Simulate.change(input, {target: {value: 'bar'}}); + immediate(() => { + expect(inputComponent.getValue()).toBe('bar'); + expect(inputComponent.isValid()).toBe(false); + done(); + }); + + }); + + it('should trigger an onValid handler, if passed, when form is valid', function () { + + const onValid = jasmine.createSpy('valid'); + const onInvalid = jasmine.createSpy('invalid'); + + TestUtils.renderIntoDocument( + + + + ); + + expect(onValid).toHaveBeenCalled(); + expect(onInvalid).not.toHaveBeenCalled(); + + }); + + it('should trigger an onInvalid handler, if passed, when form is invalid', function () { + + const onValid = jasmine.createSpy('valid'); + const onInvalid = jasmine.createSpy('invalid'); + + TestUtils.renderIntoDocument( + + + + ); + + expect(onValid).not.toHaveBeenCalled(); + expect(onInvalid).toHaveBeenCalled(); + + }); + + it('should use provided validate function', function () { + + const isValid = jasmine.createSpy('valid'); + + const Input = customizeInput({ + render() { + if (this.isValid()) { + isValid(); + } + return ; + }, + validate() { + return this.getValue() === 'checkValidity'; + } + }); + + const form = TestUtils.renderIntoDocument( + + + + ); + + const input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT'); + TestUtils.Simulate.change(input, {target: {value: 'checkValidity'}}); + expect(isValid).toHaveBeenCalled(); + + }); + + it('should provide invalidate callback on onValiSubmit', function () { + + const TestForm = React.createClass({ + render() { + return ( + invalidate({ foo: 'bar' })}> + + + ); + } + }); + + const form = TestUtils.renderIntoDocument(); + + const formEl = TestUtils.findRenderedDOMComponentWithTag(form, 'form'); + const input = TestUtils.findRenderedComponentWithType(form, TestInput); + TestUtils.Simulate.submit(formEl); + expect(input.isValid()).toBe(false); + + }); + + it('should provide invalidate callback on onInvalidSubmit', function () { + + const TestForm = React.createClass({ + render() { + return ( + invalidate({ foo: 'bar' })}> + + + ); + } + }); + + const form = TestUtils.renderIntoDocument(); + const formEl = TestUtils.findRenderedDOMComponentWithTag(form, 'form'); + const input = TestUtils.findRenderedComponentWithType(form, TestInput); + TestUtils.Simulate.submit(formEl); + expect(input.getErrorMessage()).toBe('bar'); + + }); + + + it('should not invalidate inputs on external errors with preventExternalInvalidation prop', function () { + + const TestForm = React.createClass({ + render() { + return ( + invalidate({ foo: 'bar' })}> + + + ); + } + }); + + const form = TestUtils.renderIntoDocument(); + const formEl = TestUtils.findRenderedDOMComponentWithTag(form, 'form'); + const input = TestUtils.findRenderedComponentWithType(form, TestInput); + TestUtils.Simulate.submit(formEl); + expect(input.isValid()).toBe(true); + + }); + + it('should invalidate inputs on external errors without preventExternalInvalidation prop', function () { + + const TestForm = React.createClass({ + render() { + return ( + invalidate({ foo: 'bar' })}> + + + ); + } + }); + + const form = TestUtils.renderIntoDocument(); + const formEl = TestUtils.findRenderedDOMComponentWithTag(form, 'form'); + const input = TestUtils.findRenderedComponentWithType(form, TestInput); + TestUtils.Simulate.submit(formEl); + expect(input.isValid()).toBe(false); + + }); + +}); diff --git a/specs/Validation-spec.jsx b/specs/Validation-spec.jsx deleted file mode 100644 index fd6fabe2..00000000 --- a/specs/Validation-spec.jsx +++ /dev/null @@ -1,281 +0,0 @@ -var React = require('react/addons'); -var TestUtils = React.addons.TestUtils; -var Formsy = require('./../src/main.js'); - -describe('Validation', function() { - - it('should reset only changed form element when external error is passed', function (done) { - - var onSubmit = function (model, reset, invalidate) { - invalidate({ - foo: 'bar', - bar: 'foo' - }); - } - var TestInput = React.createClass({ - mixins: [Formsy.Mixin], - updateValue: function (event) { - this.setValue(event.target.value); - }, - render: function () { - return - } - }); - var form = TestUtils.renderIntoDocument( - - - - - ); - - var input = TestUtils.scryRenderedDOMComponentsWithTag(form, 'INPUT')[0]; - var inputComponents = TestUtils.scryRenderedComponentsWithType(form, TestInput); - - form.submit(); - expect(inputComponents[0].isValid()).toBe(false); - expect(inputComponents[1].isValid()).toBe(false); - TestUtils.Simulate.change(input, {target: {value: 'bar'}}); - setTimeout(function () { - expect(inputComponents[0].isValid()).toBe(true); - expect(inputComponents[1].isValid()).toBe(false); - done(); - }, 0); - }); - - it('should let normal validation take over when component with external error is changed', function (done) { - - var onSubmit = function (model, reset, invalidate) { - invalidate({ - foo: 'bar' - }); - } - var TestInput = React.createClass({ - mixins: [Formsy.Mixin], - updateValue: function (event) { - this.setValue(event.target.value); - }, - render: function () { - return - } - }); - var form = TestUtils.renderIntoDocument( - - - - ); - - var input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT'); - var inputComponent = TestUtils.findRenderedComponentWithType(form, TestInput); - - form.submit(); - expect(inputComponent.isValid()).toBe(false); - TestUtils.Simulate.change(input, {target: {value: 'bar'}}); - setTimeout(function () { - expect(inputComponent.getValue()).toBe('bar'); - expect(inputComponent.isValid()).toBe(false); - done(); - }, 0); - }); - - it('should trigger an onValid handler, if passed, when form is valid', function () { - - var onValid = jasmine.createSpy('valid'); - var TestInput = React.createClass({ - mixins: [Formsy.Mixin], - updateValue: function (event) { - this.setValue(event.target.value); - }, - render: function () { - return - } - }); - var form = TestUtils.renderIntoDocument( - - - - ); - - var input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT'); - TestUtils.Simulate.change(input, {target: {value: 'foo'}}); - expect(onValid).toHaveBeenCalled(); - - }); - - it('should trigger an onInvalid handler, if passed, when form is invalid', function () { - - var onInvalid = jasmine.createSpy('invalid'); - var TestInput = React.createClass({ - mixins: [Formsy.Mixin], - updateValue: function (event) { - this.setValue(event.target.value); - }, - render: function () { - return - } - }); - var form = TestUtils.renderIntoDocument( - - - - ); - - var input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT'); - TestUtils.Simulate.change(input, {target: {value: ''}}); - expect(onInvalid).toHaveBeenCalled(); - - }); - - it('should use provided validate function', function () { - - var isValid = jasmine.createSpy('valid'); - var TestInput = React.createClass({ - mixins: [Formsy.Mixin], - updateValue: function (event) { - this.setValue(event.target.value); - }, - render: function () { - if (this.isValid()) { - isValid(); - } - return - }, - validate: function () { - return this.getValue() === "checkValidity"; - } - }); - var form = TestUtils.renderIntoDocument( - - - - ); - - var input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT'); - TestUtils.Simulate.change(input, {target: {value: 'checkValidity'}}); - expect(isValid).toHaveBeenCalled(); - - }); - - it('should provide invalidate callback on onValiSubmit', function () { - - var TestInput = React.createClass({ - mixins: [Formsy.Mixin], - render: function () { - return - } - }); - var TestForm = React.createClass({ - invalidate: function (model, reset, invalidate) { - invalidate({ - foo: 'bar' - }); - }, - render: function () { - return ( - - - - ); - } - }); - var form = TestUtils.renderIntoDocument(); - - var formEl = TestUtils.findRenderedDOMComponentWithTag(form, 'form'); - var input = TestUtils.findRenderedComponentWithType(form, TestInput); - TestUtils.Simulate.submit(formEl); - expect(input.isValid()).toBe(false); - - }); - - it('should provide invalidate callback on onInvalidSubmit', function () { - - var TestInput = React.createClass({ - mixins: [Formsy.Mixin], - render: function () { - return - } - }); - var TestForm = React.createClass({ - invalidate: function (model, reset, invalidate) { - invalidate({ - foo: 'bar' - }); - }, - render: function () { - return ( - - - - ); - } - }); - var form = TestUtils.renderIntoDocument(); - - var formEl = TestUtils.findRenderedDOMComponentWithTag(form, 'form'); - var input = TestUtils.findRenderedComponentWithType(form, TestInput); - TestUtils.Simulate.submit(formEl); - expect(input.getErrorMessage()).toBe('bar'); - - }); - - - it('should not invalidate inputs on external errors with preventExternalInvalidation prop', function () { - - var TestInput = React.createClass({ - mixins: [Formsy.Mixin], - render: function () { - return - } - }); - var TestForm = React.createClass({ - invalidate: function (model, reset, invalidate) { - invalidate({ - foo: 'bar' - }); - }, - render: function () { - return ( - - - - ); - } - }); - var form = TestUtils.renderIntoDocument(); - var formEl = TestUtils.findRenderedDOMComponentWithTag(form, 'form'); - var input = TestUtils.findRenderedComponentWithType(form, TestInput); - TestUtils.Simulate.submit(formEl); - expect(input.isValid()).toBe(true); - - }); - - it('should invalidate inputs on external errors without preventExternalInvalidation prop', function () { - - var TestInput = React.createClass({ - mixins: [Formsy.Mixin], - render: function () { - return - } - }); - var TestForm = React.createClass({ - invalidate: function (model, reset, invalidate) { - invalidate({ - foo: 'bar' - }); - }, - render: function () { - return ( - - - - ); - } - }); - var form = TestUtils.renderIntoDocument(); - var formEl = TestUtils.findRenderedDOMComponentWithTag(form, 'form'); - var input = TestUtils.findRenderedComponentWithType(form, TestInput); - TestUtils.Simulate.submit(formEl); - expect(input.isValid()).toBe(false); - - }); - -}); diff --git a/specs/utils/TestInput.js b/specs/utils/TestInput.js new file mode 100644 index 00000000..8a917ae0 --- /dev/null +++ b/specs/utils/TestInput.js @@ -0,0 +1,22 @@ +import React from 'react'; +import Formsy from './../..'; +import assign from 'react/lib/Object.assign'; + +const defaultProps = { + mixins: [Formsy.Mixin], + getDefaultProps() { + return { type: 'text' }; + }, + updateValue(event) { + this.setValue(event.target[this.props.type === 'checkbox' ? 'checked' : 'value']); + }, + render() { + return ; + } +}; + +export function customizeInput(props) { + return React.createClass(assign(defaultProps, props)); +} + +export default React.createClass(defaultProps); diff --git a/specs/utils/immediate.js b/specs/utils/immediate.js new file mode 100644 index 00000000..ed311ae3 --- /dev/null +++ b/specs/utils/immediate.js @@ -0,0 +1,3 @@ +export default function (fn) { + setTimeout(fn, 0); +} diff --git a/testrunner.js b/testrunner.js index 48f42519..9801b914 100644 --- a/testrunner.js +++ b/testrunner.js @@ -10,16 +10,13 @@ global.navigator = global.window.navigator; var jasmineOptions = { specFolders: [path.resolve(__dirname, 'specs')], - //onComplete: onComplete, isVerbose: true, showColors: true, teamcity: false, useRequireJs: false, - regExpSpec: /spec\.jsx$/, + regExpSpec: /spec\.js$/, junitreport: true, - includeStackTrace: true, - //coffee: options.coffee, - //growl: options.growl + includeStackTrace: true }; jasmine.executeSpecsInFolder(jasmineOptions);