UNPKG

@darkobits/formation

Version:
687 lines (554 loc) 20.1 kB
'use strict'; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; var _ramda = require('ramda'); var _unity = require('@darkobits/unity'); var _Form = require('../../components/Form/Form'); var _constants = require('../../etc/constants'); var _interfaces = require('../../etc/interfaces'); var _index = require('../../index'); var _index2 = _interopRequireDefault(_index); var _FormationControl = require('./FormationControl'); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } describe('FormationControl', function () { var T = void 0; var Form = void 0; var wrapper = void 0; beforeEach(function () { (0, _unity.module)(_index2.default); wrapper = (0, _unity.compile)({ template: '<fm></fm>' }); Form = wrapper.controller('fm'); jest.spyOn(Form, _interfaces.RegisterControl); }); describe('$getName', function () { describe('when assigned a "name" binding', function () { var name = 'foo'; beforeEach(function () { T = (0, _unity.directive)('fmInput', { template: '<fm-input name="' + name + '"></fm-input>', wrap: wrapper }); }); it('should report its name', function () { expect(T.fmInput.$getName()).toEqual(name); }); }); describe('when assigned a "for" binding', function () { var forStr = 'foo'; beforeEach(function () { T = (0, _unity.directive)('fmInput', { template: '<fm-input name="' + forStr + '"></fm-input>', wrap: wrapper }); }); it('should report its name', function () { expect(T.fmInput.$getName()).toEqual(forStr); }); }); }); describe('$onDestroy', function () { var unregisterSpy = void 0; beforeEach(function () { T = (0, _unity.directive)('fmInput', { template: '<fm-input></fm-input>', wrap: wrapper }); unregisterSpy = jest.spyOn(Form, '$unregisterControl'); }); it('should unregister from its form controller if it has a model', function () { T.fmInput.$onDestroy(); expect(unregisterSpy.mock.calls[0][0]).toEqual(T.fmInput); }); }); describe('#isDisabled', function () { describe('when not disabled', function () { beforeEach(function () { T = (0, _unity.directive)('fmInput', { template: '<fm-input></fm-input>', wrap: wrapper }); }); it('should return false', function () { expect(T.fmInput.isDisabled()).toBeFalsy(); }); }); describe('with a truthy ngDisabled binding', function () { beforeEach(function () { T = (0, _unity.directive)('fmInput', { template: '<fm-input ng-disabled="true"></fm-input>', wrap: wrapper }); }); it('should return false', function () { expect(T.fmInput.isDisabled()).toBeTruthy(); }); }); describe('when programatically disabled', function () { beforeEach(function () { T = (0, _unity.directive)('fmInput', { template: '<fm-input></fm-input>', wrap: wrapper }); T.fmInput.disable(); }); it('should return false', function () { expect(T.fmInput.isDisabled()).toBeTruthy(); }); }); describe('when the form is disabled', function () { beforeEach(function () { T = (0, _unity.directive)('fmInput', { template: '<fm-input></fm-input>', wrap: wrapper }); Form.disable(); }); it('should return false', function () { expect(T.fmInput.isDisabled()).toBeTruthy(); }); }); }); describe('$getControl', function () { var name = 'foo'; var getControlSpy = void 0; beforeEach(function () { T = (0, _unity.directive)('fmInput', { template: '<fm-input name="' + name + '"></fm-input>', wrap: wrapper }); getControlSpy = jest.spyOn(Form, 'getControl'); }); it('should attempt to get the correct control from the form', function () { expect(T.fmInput.$getControl()).toEqual(T.fmInput); expect(getControlSpy.mock.calls[0][0]).toEqual(name); }); }); describe('#getControlId', function () { var formName = 'foo'; var controlName = 'bar'; beforeEach(function () { wrapper = (0, _unity.compile)({ template: '<fm name="' + formName + '"></fm>' }); Form = wrapper.controller('fm'); T = (0, _unity.directive)('fmInput', { template: '<fm-input name="' + controlName + '"></fm-input>', wrap: wrapper }); }); it('should return its ID', function () { expect(T.fmInput.getControlId()).toEqual(formName + '-' + controlName + '-0'); }); }); describe('#enable / #disable', function () { beforeEach(function () { T = (0, _unity.directive)('fmInput', { template: '<fm-input></fm-input>', wrap: wrapper }); }); it('should enable / disable the control', function () { T.fmInput.disable(); expect(T.fmInput.isDisabled()).toBeTruthy(); T.fmInput.enable(); expect(T.fmInput.isDisabled()).toBeFalsy(); }); }); describe('#getErrors', function () { /** * Scenario 1 * * - [ ] Control is invalid * - [X] Show errors on $touched * - [X] Show errors on $submitted * - [ ] Control has been touched * - [ ] Form has been submitted */ describe('Scenario 1', function () { beforeEach(function () { wrapper = (0, _unity.compile)({ template: '<fm show-errors-on="touched, submitted"></fm>' }); Form = wrapper.controller('fm'); T = (0, _unity.directive)('fmInput', { template: '<fm-input></fm-input>', wrap: wrapper }); T.fmInput[_constants.NG_MODEL_CTRL].$valid = true; T.fmInput[_constants.NG_MODEL_CTRL].$touched = false; }); it('should return false', function () { expect(T.fmInput.getErrors()).toBeFalsy(); }); }); /** * Scenario 2 * * - [X] Control is invalid * - [X] Show errors on $touched * - [X] Show errors on $submitted * - [ ] Control has been touched * - [ ] Form has been submitted */ describe('Scenario 2', function () { beforeEach(function () { wrapper = (0, _unity.compile)({ template: '<fm show-errors-on="touched, submitted"></fm>' }); Form = wrapper.controller('fm'); T = (0, _unity.directive)('fmInput', { template: '<fm-input></fm-input>', wrap: wrapper }); T.fmInput[_constants.NG_MODEL_CTRL].$valid = false; }); it('should return false', function () { expect(T.fmInput.getErrors()).toBeFalsy(); }); }); /** * Scenario 3 * * - [X] Control is invalid * - [X] Show errors on $touched * - [ ] Show errors on $submitted * - [ ] Control has been touched * - [ ] Form has been submitted */ describe('Scenario 3', function () { beforeEach(function () { wrapper = (0, _unity.compile)({ template: '<fm show-errors-on="touched"></fm>' }); Form = wrapper.controller('fm'); T = (0, _unity.directive)('fmInput', { template: '<fm-input></fm-input>', wrap: wrapper }); T.fmInput[_constants.NG_MODEL_CTRL].$valid = false; }); it('should return false', function () { expect(T.fmInput.getErrors()).toBeFalsy(); }); }); /** * Scenario 4 * * - [X] Control is invalid * - [ ] Show errors on $touched * - [ ] Show errors on $submitted * - [ ] Control has been touched * - [ ] Form has been submitted */ describe('Scenario 4', function () { beforeEach(function () { wrapper = (0, _unity.compile)({ template: '<fm></fm>' }); Form = wrapper.controller('fm'); T = (0, _unity.directive)('fmInput', { template: '<fm-input></fm-input>', wrap: wrapper }); T.fmInput[_constants.NG_MODEL_CTRL].$valid = false; }); it('should return errors', function () { expect(T.fmInput.getErrors()).toBeTruthy(); }); }); /** * Scenario 5 * * - [X] Control is invalid * - [ ] Show errors on $touched * - [X] Show errors on $submitted * - [X] Control has been touched * - [ ] Form has been submitted */ describe('Scenario 5', function () { beforeEach(function () { wrapper = (0, _unity.compile)({ template: '<fm show-errors-on="submitted"></fm>' }); Form = wrapper.controller('fm'); T = (0, _unity.directive)('fmInput', { template: '<fm-input></fm-input>', wrap: wrapper }); T.fmInput[_constants.NG_MODEL_CTRL].$valid = false; T.fmInput[_constants.NG_MODEL_CTRL].$touched = true; }); it('should return false', function () { expect(T.fmInput.getErrors()).toBeFalsy(); }); }); /** * Scenario 6 * * - [X] Control is invalid * - [ ] Show errors on $touched * - [X] Show errors on $submitted * - [ ] Control has been touched * - [X] Form has been submitted */ describe('Scenario 6', function () { beforeEach(function () { wrapper = (0, _unity.compile)({ template: '<fm show-errors-on="submitted"></fm>' }); Form = wrapper.controller('fm'); T = (0, _unity.directive)('fmInput', { template: '<fm-input></fm-input>', wrap: wrapper }); T.fmInput[_constants.NG_MODEL_CTRL].$valid = false; Form[_Form.NG_FORM_CONTROLLER].$submitted = true; }); it('should return errors', function () { expect(T.fmInput.getErrors()).toBeTruthy(); }); }); }); describe('#getErrorMessages', function () { var controlName = 'foo'; var errors = [['foo', 'bar']]; beforeEach(function () { T = (0, _unity.directive)('fmInput', { template: '<fm-input name="' + controlName + '"></fm-input>', wrap: wrapper }); T.fmInput[_interfaces.Configure]({ errors: errors }); }); it('should assign error messages to the correct key', function () { expect(T.fmInput[_FormationControl.NG_MESSAGES]).toEqual(errors); }); it('should return its configured error messages', function () { expect(T.fmInput.getErrorMessages()).toEqual(errors); }); }); // ----- Interfaces ---------------------------------------------------------- describe('[Interface] Configure', function () { beforeEach(function () { T = (0, _unity.directive)('fmInput', { template: '<fm-input></fm-input>', wrap: wrapper }); }); describe('applying error messages', function () { it('should ensure each error is a tuple', function () { expect(function () { T.fmInput[_interfaces.Configure]({ errors: [null, null, 'foo'] }); }).toThrow('Expected error message to be a [key, value] entry'); }); it('should not overwrite matching error tuples', function () { var error1 = ['foo', 'bar']; var error2 = ['foo', 'bar']; T.fmInput[_interfaces.Configure]({ errors: [error1] }); T.fmInput[_interfaces.Configure]({ errors: [error2] }); expect(T.fmInput.getErrorMessages().length).toBe(1); }); }); describe('applying parsers', function () { it('should ensure each parser is a function', function () { expect(function () { T.fmInput[_interfaces.Configure]({ parsers: [null, null, 'foo'] }); }).toThrow('expected parser to be of type Function'); }); it('should push parsers onto $parsers', function () { var parser = function parser() {}; T.fmInput[_interfaces.Configure]({ parsers: [parser] }); // The actual function pushed onto $parsers will be a bound version of // the original. expect((0, _ramda.last)(T.fmInput[_constants.NG_MODEL_CTRL].$parsers).name).toMatch('bound parser'); }); }); describe('applying formatters', function () { it('should ensure each formatter is a function', function () { expect(function () { T.fmInput[_interfaces.Configure]({ formatters: [null, null, 'foo'] }); }).toThrow('expected formatter to be of type Function'); }); it('should push formatters onto $formatters', function () { function formatter() {} T.fmInput[_interfaces.Configure]({ formatters: [formatter] }); // The actual function pushed onto $formatters will be a bound version of // the original. expect((0, _ramda.last)(T.fmInput[_constants.NG_MODEL_CTRL].$formatters).name).toMatch('bound formatter'); }); }); describe('applying validators', function () { it('should ensure each validator is a function', function () { expect(function () { T.fmInput[_interfaces.Configure]({ validators: { foo: null, bar: null } }); }).toThrow('expected validator to be of type Function'); }); it('should add validators to $validators', function () { function validator() {} T.fmInput[_interfaces.Configure]({ validators: { validator: validator } }); // The actual function added to $validators will be a bound version of // the original. expect(T.fmInput[_constants.NG_MODEL_CTRL].$validators.validator.name).toMatch('bound validator'); }); }); describe('applying async validators', function () { it('should ensure each async validator is a function', function () { expect(function () { T.fmInput[_interfaces.Configure]({ asyncValidators: { foo: null, bar: null } }); }).toThrow('expected async validator to be of type Function'); }); it('should add async validators to $asyncValidators', function () { function asyncValidator() { return Promise.resolve(); } T.fmInput[_interfaces.Configure]({ asyncValidators: { asyncValidator: asyncValidator } }); // The actual function added to $asyncValidator will be a bound version of // the original. expect(T.fmInput[_constants.NG_MODEL_CTRL].$asyncValidators.asyncValidator.name).toMatch('bound asyncValidator'); }); }); describe('applying ngModelOptions', function () { it('should configure ngModelOptions', function () { var options = { updateOn: 'blur', allowInvalid: true }; T.fmInput[_interfaces.Configure]({ ngModelOptions: options }); expect(T.fmInput[_constants.NG_MODEL_CTRL].$options.$$options).toEqual(expect.objectContaining(options)); }); }); }); describe('[Interface] RegisterNgModel / Form Registration', function () { beforeEach(function () { T = (0, _unity.directive)('fmInput', { template: '<fm-input></fm-input>', wrap: wrapper }); }); it('should implement the RegisterNgModel interface', function () { expect(_typeof(T.fmInput[_interfaces.RegisterNgModel])).toEqual('function'); }); it('should register with the form', function () { expect(Form[_interfaces.RegisterControl].mock.calls[0][0]).toEqual(T.fmInput); }); it('should assign its ngModel controller to the correct key', function () { expect(T.fmInput[_constants.NG_MODEL_CTRL]).toBeTruthy(); }); }); describe('[Interface] SetModelValue / GetModelValue', function () { var modelValue = 'foo'; beforeEach(function () { T = (0, _unity.directive)('fmInput', { template: '<fm-input></fm-input>', wrap: wrapper }); }); it('should implement the SetModelValue interface', function () { expect(_typeof(T.fmInput[_interfaces.SetModelValue])).toEqual('function'); }); it('should implement the GetModelValue interface', function () { expect(_typeof(T.fmInput[_interfaces.GetModelValue])).toEqual('function'); }); it('should get/set the controls model value', function () { T.fmInput.setModelValue(modelValue); (0, _unity.digest)(); expect(T.fmInput.getModelValue()).toEqual(modelValue); }); it('should no-op when passed "undefined"', function () { T.fmInput.setModelValue(modelValue); (0, _unity.digest)(); expect(T.fmInput.getModelValue()).toEqual(modelValue); T.fmInput.setModelValue(); (0, _unity.digest)(); expect(T.fmInput.getModelValue()).toEqual(modelValue); }); }); describe('[Interface] SetCustomErrorMessage / ClearCustomErrorMessage', function () { var errorMessage = 'foo'; beforeEach(function () { T = (0, _unity.directive)('fmInput', { template: '<fm-input></fm-input>', wrap: wrapper }); }); it('should implmenet SetCustomErrorMessage', function () { expect(_typeof(T.fmInput[_interfaces.SetCustomErrorMessage])).toEqual('function'); }); it('getCustomErrorMessage should return the current custom errror', function () { T.fmInput[_interfaces.SetCustomErrorMessage](errorMessage); expect(T.fmInput.getCustomErrorMessage()).toEqual(errorMessage); }); it('should implmenet ClearCustomErrorMessage', function () { expect(_typeof(T.fmInput[_interfaces.ClearCustomErrorMessage])).toEqual('function'); T.fmInput[_interfaces.SetCustomErrorMessage](errorMessage); expect(T.fmInput.getCustomErrorMessage()).toEqual(errorMessage); T.fmInput[_interfaces.ClearCustomErrorMessage](); expect(T.fmInput.getCustomErrorMessage()).toBeFalsy(); }); it('SetCustomErrorMessage should throw an error if not passed a string', function () { expect(function () { T.fmInput[_interfaces.SetCustomErrorMessage]({}); }).toThrow('expected error message to be of type String'); }); }); describe('[Interface] Reset', function () { beforeEach(function () { T = (0, _unity.directive)('fmInput', { template: '<fm-input name="foo"></fm-input>', wrap: wrapper }); }); it('should implement the Reset interface', function () { expect(_typeof(T.fmInput[_interfaces.Reset])).toEqual('function'); }); it('should set the control to an untouched, pristine state', function () { T.fmInput[_constants.NG_MODEL_CTRL].$setDirty(); T.fmInput[_constants.NG_MODEL_CTRL].$setTouched(); T.fmInput[_interfaces.Reset](); expect(T.fmInput[_constants.NG_MODEL_CTRL].$dirty).toBeFalsy(); expect(T.fmInput[_constants.NG_MODEL_CTRL].$touched).toBeFalsy(); }); it('should validate the control', function () { var validateSpy = jest.spyOn(T.fmInput[_constants.NG_MODEL_CTRL], '$validate'); T.fmInput[_interfaces.Reset](); expect(validateSpy.mock.calls.length).toBe(1); }); it('if provided a non-undefined value, it should set the its model value', function () { var value = 'foo'; expect(T.fmInput[_interfaces.GetModelValue]()).toBeFalsy(); T.fmInput[_interfaces.Reset](value); (0, _unity.digest)(); expect(T.fmInput[_interfaces.GetModelValue]()).toBe(value); }); }); });