@darkobits/formation
Version:
687 lines (554 loc) • 20.1 kB
JavaScript
;
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);
});
});
});