UNPKG

@darkobits/formation

Version:
894 lines (717 loc) 30.6 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 _unity = require('@darkobits/unity'); var _interfaces = require('../../etc/interfaces'); var _constants = require('../../etc/constants'); var _index = require('../../index'); var _index2 = _interopRequireDefault(_index); var _FormationControl = require('../../classes/FormationControl'); var _Form = require('./Form'); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } describe('FormController', function () { var T = void 0; var logSpy = jest.fn(); beforeEach(function () { (0, _unity.module)(_index2.default, { mock: { $log: { log: logSpy } } }); T = (0, _unity.directive)('fm', { template: '<fm></fm>' }); }); // ----- Interfaces ---------------------------------------------------------- describe('[Interface] RegisterNgForm', function () { it('should implement the RegisterNgForm interface', function () { expect(_typeof(T.fm[_interfaces.RegisterNgForm])).toEqual('function'); }); it('should assign the ngForm controller to the correct key', function () { expect(T.fm[_Form.NG_FORM_CONTROLLER]).toBeTruthy(); }); it('should expose validation properties from ngForm', function () { var props = ['$dirty', '$invalid', '$pending', '$pristine', '$submitted', '$valid']; props.forEach(function (prop) { expect(Reflect.has(T.fm, prop)).toBe(true); }); }); describe('trying to register multiple ngForms', function () { it('should throw an error', function () { var ngForm = (0, _unity.compile)({ template: '<form></form>', scope: T.$scope.$new() }); expect(function () { T.fm[_interfaces.RegisterNgForm](ngForm); }).toThrow(/ngForm already registered/); }); }); }); describe('[Interface] RegisterForm', function () { it('should implement the RegisterForm interface', function () { expect(_typeof(T.fm[_interfaces.RegisterForm])).toEqual('function'); }); describe('when another child form with the same name is present', function () { beforeEach(function () { T = (0, _unity.directive)('fm', { template: '\n <fm name="parentForm">\n <fm name="childForm"></fm>\n <transclude></transclude>\n </fm>\n ' }); }); it('should throw an error', function () { var childForm = (0, _unity.compile)({ template: '<fm name="childForm"></fm>', scope: T.$scope.$new() }); var childFormCtrl = childForm.controller('fm'); expect(function () { T.fm[_interfaces.RegisterForm](childFormCtrl); }).toThrow('another child form with this name already exists'); }); }); describe('when a control with the same name is present', function () { var name = 'foo'; beforeEach(function () { T = (0, _unity.directive)('fm', { template: '\n <fm name="parentForm">\n <fm-input name="' + name + '"></fm-input>\n <transclude></transclude>\n </fm>\n ' }); }); it('should throw an error', function () { var childForm = (0, _unity.compile)({ template: '<fm name="' + name + '"></fm>', scope: T.$scope.$new() }); var childFormCtrl = childForm.controller('fm'); expect(function () { T.fm[_interfaces.RegisterForm](childFormCtrl); }).toThrow('a control with this name already exists'); }); }); describe('configuring the child form', function () { var configKey = 'config'; var childFormName = 'childForm'; beforeEach(function () { T = (0, _unity.directive)('fm', { template: '\n <fm name="parentForm" controls="' + configKey + '">\n <transclude></transclude>\n </fm>\n ', scope: _defineProperty({}, configKey, _defineProperty({}, childFormName, { foo: 'bar' })) }); }); it('should pass configuration data to the child form', function () { // Note: Add tests for this. }); }); }); describe('[Interface] RegisterControl', function () { it('should implement the RegisterControl interface', function () { expect(_typeof(T.fm[_interfaces.RegisterControl])).toEqual('function'); }); describe('with a child form of the same name already registered', function () { it('should throw an error', function () { var controlName = 'foo'; expect(function () { T = (0, _unity.directive)('fmInput', { template: '<fm-input name="' + controlName + '"></fm-input>', wrap: '\n <fm name="parentForm">\n <fm name="' + controlName + '"></fm>\n <transclude></transclude>\n </fm>\n ' }); }).toThrow('a child form with this name already exists'); }); }); }); describe('[Interface] RegisterNgModel', function () { var controlName = 'foo'; var modelValue = 'bar'; beforeEach(function () { T = (0, _unity.directive)('fm', { template: '\n <fm>\n <input type="text" name="' + controlName + '" ng-model="vm.foo">\n </fm>\n ', scope: { vm: { foo: modelValue } } }); jest.spyOn(T.fm, _interfaces.RegisterNgModel); (0, _unity.digest)(); }); it('should implement the RegisterNgModel interface', function () { expect(_typeof(T.fm[_interfaces.RegisterNgModel])).toEqual('function'); }); it('should create a mock control', function () { expect(T.fm.getControl(controlName)).toMatchObject({ name: controlName }); expect(T.fm.getControl(controlName).getModelValue()).toEqual(modelValue); }); }); describe('[Interface] Configure', function () { var formName = 'form'; var configKey = 'config'; var controlNameA = 'foo'; var controlNameB = 'bar'; var errors = [['required', 'This field is required.']]; beforeEach(function () { var _configKey2; T = (0, _unity.directive)('fm', { template: '\n <fm name="' + formName + '" controls="' + configKey + '">\n <fm-input name="' + controlNameA + '"></fm-input>\n <transclude></transclude>\n </fm>\n ', scope: _defineProperty({}, configKey, (_configKey2 = {}, _defineProperty(_configKey2, controlNameA, { errors: errors }), _defineProperty(_configKey2, controlNameB, { errors: errors }), _configKey2)) }); }); it('should implement the Configure interface', function () { expect(_typeof(T.fm[_interfaces.Configure])).toEqual('function'); }); it('should configure known entities', function () { expect(T.fm.getControl(controlNameA).getErrorMessages()).toEqual(errors); }); it('should cache configuration data and pass it to newly-registered controls', function () { var controlB = (0, _unity.compile)({ template: '<fm-input name="' + controlNameB + '""></fm-input>', insertAt: T.$element.find('transclude') }).controller('fmInput'); expect(controlB.getErrorMessages()).toEqual(errors); }); it('should throw an error if not passed an object', function () { expect(function () { T.fm[_interfaces.Configure]('foo'); }).toThrow('expected configuration to be of type Object or Undefined'); }); }); describe('[Interface] GetModelValue / SetModelValue', function () { var spies = {}; var modelValues = { foo: 'bar', childForm: { childFoo: 'bar' }, group: [{ groupedFoo1: 'bar' }, { groupedFoo2: 'bar' }] }; beforeEach(function () { T = (0, _unity.directive)('fm', { template: '\n <fm>\n <fm-input name="foo"></fm-input>\n <fm name="childForm">\n <fm-input name="childFoo"></fm-input>\n </fm>\n <fm-group name="group">\n <fm name="grouped1">\n <fm-input name="groupedFoo1"></fm-input>\n </fm>\n <fm name="grouped2">\n <fm-input name="groupedFoo2"></fm-input>\n </fm>\n </fm-group>\n </fm>\n ' }); (0, _unity.digest)(); Object.assign(spies, { foo: { getModelValue: jest.spyOn(T.fm.getControl('foo'), _interfaces.GetModelValue), setModelValue: jest.spyOn(T.fm.getControl('foo'), _interfaces.SetModelValue) }, childForm: { getModelValue: jest.spyOn(T.fm.getForm('childForm'), _interfaces.GetModelValue), setModelValue: jest.spyOn(T.fm.getForm('childForm'), _interfaces.SetModelValue), childFoo: { getModelValue: jest.spyOn(T.fm.getForm('childForm').getControl('childFoo'), _interfaces.GetModelValue), setModelValue: jest.spyOn(T.fm.getForm('childForm').getControl('childFoo'), _interfaces.SetModelValue) } }, group: { getModelValue: jest.spyOn(T.fm.getForm('group'), _interfaces.GetModelValue), setModelValue: jest.spyOn(T.fm.getForm('group'), _interfaces.SetModelValue), grouped1: { getModelValue: jest.spyOn(T.fm.getForm('group').getForm('grouped1'), _interfaces.GetModelValue), setModelValue: jest.spyOn(T.fm.getForm('group').getForm('grouped1'), _interfaces.SetModelValue), groupedFoo1: { getModelValue: jest.spyOn(T.fm.getForm('group').getForm('grouped1').getControl('groupedFoo1'), _interfaces.GetModelValue), setModelValue: jest.spyOn(T.fm.getForm('group').getForm('grouped1').getControl('groupedFoo1'), _interfaces.SetModelValue) } }, grouped2: { getModelValue: jest.spyOn(T.fm.getForm('group').getForm('grouped2'), _interfaces.GetModelValue), setModelValue: jest.spyOn(T.fm.getForm('group').getForm('grouped2'), _interfaces.SetModelValue), groupedFoo2: { getModelValue: jest.spyOn(T.fm.getForm('group').getForm('grouped2').getControl('groupedFoo2'), _interfaces.GetModelValue), setModelValue: jest.spyOn(T.fm.getForm('group').getForm('grouped2').getControl('groupedFoo2'), _interfaces.SetModelValue) } } } }); }); it('should implement the SetModelValue interface', function () { expect(_typeof(T.fm[_interfaces.SetModelValue])).toEqual('function'); }); it('should delegate to the SetModelValue interface of registry members', function () { T.fm.setModelValues(modelValues); (0, _unity.digest)(); expect(spies.foo.setModelValue.mock.calls.length).toEqual(1); expect(spies.foo.setModelValue.mock.calls[0]).toEqual([modelValues.foo]); expect(spies.childForm.setModelValue.mock.calls.length).toEqual(1); expect(spies.childForm.setModelValue.mock.calls[0]).toEqual([modelValues.childForm]); expect(spies.childForm.childFoo.setModelValue.mock.calls.length).toEqual(1); expect(spies.childForm.childFoo.setModelValue.mock.calls[0]).toEqual([modelValues.childForm.childFoo]); expect(spies.group.setModelValue.mock.calls.length).toEqual(1); expect(spies.group.setModelValue.mock.calls[0]).toEqual([modelValues.group]); expect(spies.group.grouped1.setModelValue.mock.calls.length).toEqual(1); expect(spies.group.grouped1.setModelValue.mock.calls[0]).toEqual([modelValues.group[0]]); expect(spies.group.grouped1.groupedFoo1.setModelValue.mock.calls.length).toEqual(1); expect(spies.group.grouped1.groupedFoo1.setModelValue.mock.calls[0]).toEqual([modelValues.group[0].groupedFoo1]); expect(spies.group.grouped2.setModelValue.mock.calls.length).toEqual(1); expect(spies.group.grouped2.setModelValue.mock.calls[0]).toEqual([modelValues.group[1]]); expect(spies.group.grouped2.groupedFoo2.setModelValue.mock.calls.length).toEqual(1); expect(spies.group.grouped2.groupedFoo2.setModelValue.mock.calls[0]).toEqual([modelValues.group[1].groupedFoo2]); }); it('should implement the GetModelValue interface', function () { expect(_typeof(T.fm[_interfaces.GetModelValue])).toEqual('function'); }); it('should delegate to the GetModelValue interface of registry members', function () { T.fm.setModelValues(modelValues); (0, _unity.digest)(); var result = T.fm.getModelValues(); expect(result).toEqual(modelValues); // Forms and form groups should have had GetModelValues invoked once. expect(spies.childForm.getModelValue.mock.calls.length).toEqual(1); expect(spies.group.getModelValue.mock.calls.length).toEqual(1); expect(spies.group.grouped1.getModelValue.mock.calls.length).toEqual(1); expect(spies.group.grouped2.getModelValue.mock.calls.length).toEqual(1); // Child controls will have had GetModelValue invoked 3 times. expect(spies.foo.getModelValue.mock.calls.length).toEqual(3); expect(spies.childForm.childFoo.getModelValue.mock.calls.length).toEqual(3); expect(spies.group.grouped1.groupedFoo1.getModelValue.mock.calls.length).toEqual(3); expect(spies.group.grouped2.groupedFoo2.getModelValue.mock.calls.length).toEqual(3); }); it('SetModelValue should throw an error if not passed an object', function () { expect(function () { T.fm[_interfaces.SetModelValue]('foo'); }).toThrow('expected model values to be of type Object or Undefined'); }); }); describe('[Interface] SetCustomErrorMessage', function () { var controlName = 'foo'; var errorMessage = 'bar'; var errorData = _defineProperty({}, controlName, errorMessage); beforeEach(function () { T = (0, _unity.directive)('fm', { template: '\n <fm>\n <fm-input name="' + controlName + '"></fm-input>\n </fm>\n ' }); }); it('should implement the SetCustomErrorMessage interface', function () { expect(_typeof(T.fm[_interfaces.SetCustomErrorMessage])).toEqual('function'); }); it('should assign error messages to known controls', function () { expect(T.fm.getControl(controlName)[_FormationControl.CUSTOM_ERROR_MESSAGE_KEY]).toBeFalsy(); T.fm[_interfaces.SetCustomErrorMessage](errorData); expect(T.fm.getControl(controlName)[_FormationControl.CUSTOM_ERROR_MESSAGE_KEY]).toEqual(errorMessage); }); it('should throw an error if not passed an object', function () { expect(function () { T.fm[_interfaces.SetCustomErrorMessage]('foo'); }).toThrow('expected error messages to be of type Object or Undefined'); }); }); describe('[Interface] ClearCustomErrorMessage', function () { var controlName = 'foo'; var errorMessage = 'bar'; beforeEach(function () { T = (0, _unity.directive)('fm', { template: '\n <fm>\n <fm-input name="' + controlName + '"></fm-input>\n </fm>\n ' }); T.fm.getControl(controlName)[_interfaces.SetCustomErrorMessage](errorMessage); }); it('should implement the ClearCustomErrorMessage interface', function () { expect(_typeof(T.fm[_interfaces.ClearCustomErrorMessage])).toEqual('function'); }); it('should clear custom error messages from known controls', function () { T.fm[_interfaces.ClearCustomErrorMessage](); expect(T.fm.getControl(controlName)[_FormationControl.CUSTOM_ERROR_MESSAGE_KEY]).toBeFalsy(); }); }); describe('[Interface] Reset', function () { var controlName = 'foo'; var resetSpy = void 0; beforeEach(function () { T = (0, _unity.directive)('fm', { template: '\n <fm>\n <fm-input name="' + controlName + '"></fm-input>\n </fm>\n ' }); resetSpy = jest.spyOn(T.fm.getControl(controlName), _interfaces.Reset); }); it('should implement the Reset interface', function () { expect(_typeof(T.fm[_interfaces.Reset])).toEqual('function'); }); it('should set the $pristine flag to true', function () { T.fm[_Form.NG_FORM_CONTROLLER].$setDirty(); expect(T.fm[_Form.NG_FORM_CONTROLLER].$pristine).toBeFalsy(); T.fm[_interfaces.Reset](); expect(T.fm[_Form.NG_FORM_CONTROLLER].$pristine).toBeTruthy(); }); it('should delegate model values to known controls', function () { var value = 'bar'; var modelValues = _defineProperty({}, controlName, value); T.fm[_interfaces.Reset](modelValues); (0, _unity.digest)(); expect(T.fm.getControl(controlName)[_interfaces.GetModelValue]()).toEqual(value); expect(resetSpy.mock.calls[0]).toEqual([value]); }); it('should throw an error if passed a truthy value that is not an object', function () { expect(function () { T.fm[_interfaces.Reset](); }).not.toThrow(); expect(function () { T.fm[_interfaces.Reset]('foo'); }).toThrow('expected model values to be of type Object or Undefined'); }); }); // ----- Semi-Private Methods ------------------------------------------------ describe('$debug', function () { var message = 'foo'; beforeEach(function () { T = (0, _unity.directive)('fm', { template: '<fm debug></fm>' }); }); it('should log debug messages when "$debugging" is true', function () { T.fm.$debug(message); expect(logSpy.mock.calls[0]).toEqual(expect.arrayContaining([message])); }); }); describe('$onInit', function () { describe('setting the "$debugging" flag', function () { describe('when the "debug" attribute is present', function () { beforeEach(function () { T = (0, _unity.directive)('fm', { template: '<fm debug></fm>' }); }); it('should set the "$debugging" flag to "true"', function () { expect(T.fm.$debugging).toBe(true); }); }); describe('when the "debug" attribute is absent', function () { beforeEach(function () { T = (0, _unity.directive)('fm', { template: '<fm></fm>' }); }); it('should not set the "$debugging" flag to "true"', function () { expect(T.fm.$debugging).toBeFalsy(); }); }); }); describe('assigning "$name" to parent scope', function () { describe('when provided a non-empty string', function () { var name = 'foo'; beforeEach(function () { T = (0, _unity.directive)('fm', { template: '<fm name="' + name + '"></fm>' }); }); it('should assign the form controller to its parent scope', function () { expect(T.$scope[name]).toBe(T.fm); }); }); describe('when provided a falsy value', function () { beforeEach(function () { T = (0, _unity.directive)('fm', { template: '<fm></fm>' }); }); it('should assign an auto-generated name', function () { expect(T.fm.name).toMatch(new RegExp('Form-\\d*')); }); }); }); describe('parsing "$showErrorsOn"', function () { describe('when provided a valid string', function () { var attrString = 'touched, submitted'; var expectedFlags = ['$touched', '$submitted']; beforeEach(function () { T = (0, _unity.directive)('fm', { template: '<fm show-errors-on="' + attrString + '"></fm>' }); }); it('should parse the string into an array of flags', function () { expect(T.fm.$getErrorBehavior()).toEqual(expectedFlags); }); }); describe('when provided a falsy value', function () { beforeEach(function () { T = (0, _unity.directive)('fm', { template: '<fm></fm>' }); }); it('should no-op', function () { expect(T.fm.$getErrorBehavior()).toBeFalsy(); }); }); describe('when provided an empty string', function () { beforeEach(function () { T = (0, _unity.directive)('fm', { template: '<fm show-errors-on=""></fm>' }); }); it('should no-op', function () { expect(T.fm.$getErrorBehavior()).toBeFalsy(); }); }); }); }); describe('$unregisterControl', function () { var controlName = 'foo'; beforeEach(function () { T = (0, _unity.directive)('fm', { template: '\n <fm>\n <fm-input name="' + controlName + '"></fm-input>\n </fm>\n ' }); }); it('should unregister the named control', function () { var control = T.fm.getControl(controlName); expect(T.fm.getControl(controlName)).toBeTruthy(); T.fm.$unregisterControl(control); expect(T.fm.getControl(controlName)).toBeFalsy(); }); }); describe('$submit', function () { jest.useFakeTimers(); var controlName = 'foo'; var onSubmitSpy = void 0; var disableSpy = void 0; var enableSpy = void 0; var setValid = void 0; var setPending = void 0; var setSubmitting = void 0; beforeEach(function () { onSubmitSpy = jest.fn(); T = (0, _unity.directive)('fm', { template: '\n <fm controls="controls" on-submit="onSubmit">\n <fm-input name="' + controlName + '"></fm-input>\n </fm>\n ', scope: { onSubmit: onSubmitSpy } }); (0, _unity.digest)(); // Spy on the form's enable / disable functions. disableSpy = jest.spyOn(T.fm, 'disable'); enableSpy = jest.spyOn(T.fm, 'enable'); // Set up helpers to manipulate the ngForm controller's $valid and // $pending states. setValid = function setValid(value) { T.fm[_Form.NG_FORM_CONTROLLER].$valid = Boolean(value); T.fm[_Form.NG_FORM_CONTROLLER].$invalid = !value; }; setPending = function setPending(value) { T.fm[_Form.NG_FORM_CONTROLLER].$pending = Boolean(value); }; // Set up a helper to manipulate the form's $submitting state. setSubmitting = function setSubmitting(value) { T.fm.$submitting = Boolean(value); }; }); /** * Scenario 1 * * - [X] Form is already submitting * - [ ] Form has pending async validators * - [ ] Form is valid * - [ ] Control has a custom error set * - [ ] onSubmit returned field errors */ describe('Scenario 1', function () { it('should return immediately', function () { expect.assertions(1); setSubmitting(true); return T.fm.$submit().catch(function (err) { expect(err.message).toEqual('SUBMIT_IN_PROGRESS'); }); }); }); /** * Scenario 2 * * - [ ] Form is already submitting * - [X] Form has pending async validators * - [ ] Form is valid * - [ ] Control has a custom error set * - [ ] onSubmit returned field errors */ describe('Scenario 2', function () { it('should wait until $pending is "false"', function () { expect.assertions(4); setPending(true); setValid(false); // Queue up a micro-task that will execute as soon as we call // runAllTimers(). setImmediate(function () { return setPending(false); }); var promise = T.fm.$submit().catch(function (err) { expect(err.message).toEqual('NG_FORM_INVALID'); expect(disableSpy.mock.calls.length).toBe(1); expect(onSubmitSpy.mock.calls.length).toBe(0); expect(enableSpy.mock.calls.length).toBe(1); }); jest.runAllTimers(); (0, _unity.digest)(); return promise; }); }); /** * Scenario 3 * * - [ ] Form is already submitting * - [X] Form has pending async validators * - [X] Form is valid * - [ ] Control has a custom error set * - [ ] onSubmit returned field errors */ describe('Scenario 3', function () { it('should wait until $pending is false, then call onSubmit', function () { expect.assertions(3); setPending(true); setValid(true); // Queue up a micro-task that will execute as soon as we call // runAllTimers(). setImmediate(function () { return setPending(false); }); var promise = T.fm.$submit().then(function () { expect(disableSpy.mock.calls.length).toBe(1); expect(onSubmitSpy.mock.calls.length).toBe(1); expect(enableSpy.mock.calls.length).toBe(1); }); jest.runAllTimers(); (0, _unity.digest)(); return promise; }); }); /** * Scenario 4 * * - [ ] Form is already submitting * - [ ] Form has pending async validators * - [X] Form is valid * - [ ] Control has a custom error set * - [X] onSubmit returned a promise */ describe('Scenario 4', function () { it('should call onSubmit and apply field errors', function () { expect.assertions(4); var fieldError = 'bar'; var fieldErrors = _defineProperty({}, controlName, fieldError); setPending(false); setValid(true); T.$scope.onSubmit = jest.fn(function () { return fieldErrors; }); var promise = T.fm.$submit().then(function () { expect(disableSpy.mock.calls.length).toBe(1); expect(T.$scope.onSubmit.mock.calls.length).toBe(1); expect(enableSpy.mock.calls.length).toBe(1); expect(T.fm.getControl(controlName)[_FormationControl.CUSTOM_ERROR_MESSAGE_KEY]).toBe(fieldError); }); jest.runAllTimers(); (0, _unity.digest)(); return promise; }); }); /** * Scenario 5 * * - [ ] Form is already submitting * - [ ] Form has pending async validators * - [X] Form is valid * - [ ] Control has a custom error set * - [ ] onSubmit returned field errors */ describe('Scenario 5', function () { it('should indicate that onSubmit did not catch', function () { expect.assertions(4); var error = 'foo'; setPending(false); setValid(true); T.$scope.onSubmit = jest.fn(function () { return Promise.reject(new Error(error)); }); var promise = T.fm.$submit().catch(function (err) { expect(err.message).toBe(error); expect(disableSpy.mock.calls.length).toBe(1); expect(T.$scope.onSubmit.mock.calls.length).toBe(1); expect(enableSpy.mock.calls.length).toBe(1); }); jest.runAllTimers(); (0, _unity.digest)(); return promise; }); }); /** * Scenario 6 * * - [ ] Form is already submitting * - [ ] Form has pending async validators * - [ ] Form is valid * - [X] Control has a custom error set * - [ ] onSubmit returned field errors */ describe('Scenario 6', function () { it('should clear custom errors on controls', function () { expect.assertions(6); var customErrorMessage = 'foo'; T.fm.getControl(controlName)[_interfaces.SetCustomErrorMessage](customErrorMessage); expect(T.fm.getControl(controlName)[_FormationControl.CUSTOM_ERROR_MESSAGE_KEY]).toBe(customErrorMessage); setPending(false); setValid(true); var promise = T.fm.$submit().then(function () { expect(T.fm.getControl(controlName)[_FormationControl.CUSTOM_ERROR_MESSAGE_KEY]).toBeFalsy(); expect(T.fm.getControl(controlName)[_constants.NG_MODEL_CTRL].$error[_constants.CUSTOM_ERROR_KEY]).toBeFalsy(); expect(disableSpy.mock.calls.length).toBe(1); expect(onSubmitSpy.mock.calls.length).toBe(1); expect(enableSpy.mock.calls.length).toBe(1); }); jest.runAllTimers(); (0, _unity.digest)(); return promise; }); }); }); // ----- Public Methods ------------------------------------------------------ describe('isDisabled', function () { describe('when "$disabled" is truthy', function () { beforeEach(function () { T = (0, _unity.directive)('fm', { template: '<fm></fm>' }); T.fm.disable(); }); it('should return true', function () { expect(T.fm.isDisabled()).toBe(true); }); }); describe('when "$ngDisabled" is truthy', function () { beforeEach(function () { T = (0, _unity.directive)('fm', { template: '<fm ng-disabled="true"></fm>' }); }); it('should return true', function () { expect(T.fm.isDisabled()).toBe(true); }); }); describe('when neither "$disabled" nor "$ngDisabled" are truthy', function () { beforeEach(function () { T = (0, _unity.directive)('fm', { template: '<fm></fm>' }); }); it('should return falsy', function () { expect(T.fm.isDisabled()).toBeFalsy(); }); }); }); describe('getControl', function () { var ctrlName = 'foo'; var badName = 'bar'; beforeEach(function () { T = (0, _unity.directive)('fm', { template: '\n <fm>\n <fm-input name="' + ctrlName + '"></fm-input>\n </fm>\n ' }); }); it('should return the named control, if it exists', function () { expect(T.fm.getControl(badName)).toBeFalsy(); expect(T.fm.getControl(ctrlName)).toBeTruthy(); }); }); });