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(form.getDOMNode().tagName).toEqual('FORM'); }); it('should set a class name if passed', function () { var form = TestUtils.renderIntoDocument( ); expect(form.getDOMNode().className).toEqual('foo'); }); it('should allow for null/undefined children', function (done) { var TestInput = React.createClass({ mixins: [Formsy.Mixin], changeValue: function (event) { this.setValue(event.target.value); }, render: function () { return } }); 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(form.getDOMNode()); expect(model).toEqual({name: 'foo'}); done(); }, 10); }); it('should allow for inputs being added dynamically', function (done) { var inputs = []; var forceUpdate = null; var model = null; var TestInput = React.createClass({ mixins: [Formsy.Mixin], render: function () { return
} }); 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(TestInput({ name: 'test' })); forceUpdate(function () { // Wait for next event loop, as that does the form setTimeout(function () { TestUtils.Simulate.submit(form.getDOMNode()); expect(model.test).toBeDefined(); done(); }, 0); }); }, 10); }); it('should allow dynamically added inputs to update the form-model', function (done) { var inputs = []; var forceUpdate = null; var model = null; var TestInput = React.createClass({ mixins: [Formsy.Mixin], changeValue: function (event) { this.setValue(event.target.value); }, render: function () { return } }); 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(TestInput({ name: 'test' })); forceUpdate(function () { // Wait for next event loop, as that does the form setTimeout(function () { TestUtils.Simulate.change(TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT'), {target: {value: 'foo'}}); TestUtils.Simulate.submit(form.getDOMNode()); expect(model.test).toBe('foo'); done(); }, 0); }); }, 0); }); it('should allow a dynamically updated input to update the form-model', function (done) { var forceUpdate = null; var model = null; var TestInput = React.createClass({ mixins: [Formsy.Mixin], changeValue: function (event) { this.setValue(event.target.value); }, render: function () { return } }); 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.setProps({value: 'bar'}); forceUpdate(function () { // Wait for next event loop, as that does the form setTimeout(function () { TestUtils.Simulate.submit(form.getDOMNode()); expect(model.test).toBe('bar'); done(); }, 0); }); }, 10); }); describe('validations', function() { var CheckValid, onSubmit, OtherCheckValid; var isValid; var TestInput = React.createClass({ mixins: [Formsy.Mixin], changeValue: function (event) { this.setValue(event.target.value); }, render: function () { return } }); 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(input.getDOMNode(), {target: {value: 'bar'}}); expect(CheckValid).toHaveBeenCalledWith('bar'); 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(input.getDOMNode(), {target: {value: 'bar'}}); expect(OtherCheckValid).toHaveBeenCalledWith('bar'); }); 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(input.getDOMNode(), {target: {value: 'bar'}}); expect(CheckValid).toHaveBeenCalledWith('bar'); expect(OtherCheckValid).toHaveBeenCalledWith('bar'); }); }); 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(TestInput({ name: 'test' })); forceUpdate(function () { // Wait for next event loop, as that does the form setTimeout(function () { expect(hasChanged).toHaveBeenCalled(); done(); }, 0); }); }); }); describe('Update a form', function () { it('should allow elements to check if the form is disabled', function (done) { var TestInput = React.createClass({ mixins: [Formsy.Mixin], render: function () { return } }); 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(TestForm.getDOMNode()); expect(isCalled).toBe(true); }); it('should trigger an onInvalidSubmit when submitting an invalid form', function () { var isCalled = false; var TestInput = React.createClass({ mixins: [Formsy.Mixin], render: function () { return ; } }); var TestForm = React.createClass({ onInvalidSubmit: function () { isCalled = true; }, render: function () { return ( ); } }); var form = TestUtils.renderIntoDocument( ); var TestForm = TestUtils.findRenderedComponentWithType(form, TestForm); TestUtils.Simulate.submit(TestForm.getDOMNode()); expect(isCalled).toBe(true); }); }); describe("value === false", function() { var onSubmit; var TestInput = React.createClass({ mixins: [Formsy.Mixin], getDefaultProps: function() { return { type: "text", }; }, changeValue: function() { this.setValue(e.target[this.props.type === "checkbox" ? "checked" : "value"]); }, render: function () { return } }); 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(form.getDOMNode()); expect(onSubmit).toHaveBeenCalledWith({foo: false}); }); it("should allow dynamic changes to false", function() { var form = TestUtils.renderIntoDocument(); form.setProps({value: false}); TestUtils.Simulate.submit(form.getDOMNode()); expect(onSubmit).toHaveBeenCalledWith({foo: false}); }); }); });