UNPKG

angular-material-npfixed

Version:

The Angular Material project is an implementation of Material Design in Angular.js. This project provides a set of reusable, well-tested, and accessible Material Design UI components. Angular Material is supported internally at Google by the Angular.js, M

349 lines (278 loc) 11.6 kB
describe('md-input-container animations', function() { var $rootScope, $compile, $animateCss, $material, $$mdInput, el, pageScope, invalidAnimation, messagesAnimation, messageAnimation, cssTransitionsDisabled = false, lastAnimateCall; // Load our modules beforeEach(module('ngAnimate', 'ngMessages', 'material.components.input', 'material.components.checkbox')); // Run pre-test setup beforeEach(decorateAnimateCss); beforeEach(injectGlobals); beforeEach(setupVariables); // Run after-test teardown afterEach(teardown); it('set the proper styles when showing messages on an input', function() { compile( '<form name="testForm">' + ' <md-input-container>' + ' <input name="foo" ng-model="foo" required ng-pattern="/^1234$/" />' + ' <div class="errors" ng-messages="testForm.foo.$error">' + ' <div ng-message="required">required</div>' + ' <div ng-message="pattern">pattern</div>' + ' </div>' + ' </md-input-container>' + '</form>' ); var container = el.find('md-input-container'), input = el.find('input'), doneSpy = jasmine.createSpy('done'); // Mimic the real validations/animations that fire /* * 1. Set to an invalid pattern but don't blur (so it's not invalid yet) * * Expect nothing to happen ($animateCss called with no options) */ setFoo('asdf'); messageAnimation.enter(getError(), doneSpy); flush(); expectError(getError(), 'pattern'); expect(doneSpy).toHaveBeenCalled(); expect(container).not.toHaveClass('md-input-invalid'); expect(lastAnimateCall).toEqual({element: getError(), options: {}}); /* * 2. Blur the input, which adds the md-input-invalid class * * Expect to animate in the pattern message */ doneSpy.calls.reset(); input.triggerHandler('blur'); invalidAnimation.addClass(container, 'md-input-invalid', doneSpy); flush(); expectError(getError(), 'pattern'); expect(doneSpy).toHaveBeenCalled(); expect(container).toHaveClass('md-input-invalid'); expect(lastAnimateCall.element).toEqual(getError()); expect(lastAnimateCall.options.event).toEqual('enter'); expect(lastAnimateCall.options.to).toEqual({"opacity": 1, "margin-top": "0"}); /* * 3. Clear the field * * Expect to animate away pattern message and animate in the required message */ // Grab the pattern error before we change foo and it disappears var patternError = getError(); doneSpy.calls.reset(); messageAnimation.leave(patternError, doneSpy); flush(); expect(doneSpy).toHaveBeenCalled(); expect(lastAnimateCall.element).toEqual(patternError); expect(lastAnimateCall.options.event).toEqual('leave'); expect(parseInt(lastAnimateCall.options.to["margin-top"])).toBeLessThan(0); setFoo(''); expectError(getError(), 'required'); doneSpy.calls.reset(); messageAnimation.enter(getError(), doneSpy); flush(); expect(doneSpy).toHaveBeenCalled(); expect(container).toHaveClass('md-input-invalid'); expect(lastAnimateCall.element).toEqual(getError()); expect(lastAnimateCall.options.event).toEqual('enter'); expect(lastAnimateCall.options.to).toEqual({"opacity": 1, "margin-top": "0"}); }); describe('method tests', function() { describe('#showInputMessages', function() { it('logs a warning with no messages element', inject(function($log) { // Note that the element does NOT have a parent md-input-messages-animation class var element = angular.element('<div><div class="md-input-message-animation"></div></div>'); var done = jasmine.createSpy('done'); var warnSpy = spyOn($log, 'warn'); $$mdInput.messages.show(element, done); expect(done).toHaveBeenCalled(); expect(warnSpy).toHaveBeenCalled(); })); it('logs a warning with no messages children', inject(function($log) { // Note that the element does NOT have any child md-input-message-animation divs var element = angular.element('<div class="md-input-messages-animation"></div>'); var done = jasmine.createSpy('done'); var warnSpy = spyOn($log, 'warn'); $$mdInput.messages.show(element, done); expect(done).toHaveBeenCalled(); expect(warnSpy).toHaveBeenCalled(); })); }); describe('#hideInputMessages', function() { it('logs a warning with no messages element', inject(function($log) { // Note that the element does NOT have a parent md-input-messages-animation class var element = angular.element('<div><div class="md-input-message-animation"></div></div>'); var done = jasmine.createSpy('done'); var warnSpy = spyOn($log, 'warn'); $$mdInput.messages.hide(element, done); expect(done).toHaveBeenCalled(); expect(warnSpy).toHaveBeenCalled(); })); it('logs a warning with no messages children', inject(function($log) { // Note that the element does NOT have any child md-input-message-animation divs var element = angular.element('<div class="md-input-messages-animation"></div>'); var done = jasmine.createSpy('done'); var warnSpy = spyOn($log, 'warn'); $$mdInput.messages.hide(element, done); expect(done).toHaveBeenCalled(); expect(warnSpy).toHaveBeenCalled(); })); }); describe('#getMessagesElement', function() { it('finds the messages element itself', function() { var template = '<div class="md-input-messages-animation"></div>'; var dom = angular.element(template); var messages = $$mdInput.messages.getElement(dom); expect(dom).toEqual(messages); }); it('finds a child element', function(){ var template = '<div><div class="md-input-messages-animation"></div></div>'; var dom = angular.element(template); var realMessages = angular.element(dom[0].querySelector('.md-input-messages-animation')); var messages = $$mdInput.messages.getElement(dom); expect(realMessages).toEqual(messages); }); it('finds the parent of a message animation element', function() { var template = '<div class="md-input-messages-animation">' + ' <div class="md-input-message-animation"></div>' + '</div>'; var dom = angular.element(template); var message = angular.element(dom[0].querySelector('.md-input-message-animation')); var messages = $$mdInput.messages.getElement(message); expect(dom).toEqual(messages); }); }); }); it('set the proper styles when showing messages on an md-checkbox', function() { compile( '<form name="testForm">' + ' <md-input-container>' + ' <md-checkbox name="cb" ng-model="foo" required>Test</md-checkbox>' + ' <div class="errors" ng-messages="testForm.cb.$error">' + ' <div ng-message="required">required</div>' + ' </div>' + ' </md-input-container>' + '</form>' ); var container = el.find('md-input-container'), checkbox = el.find('md-checkbox'), doneSpy = jasmine.createSpy('done'); // Mimic the real validations/animations that fire /* * 1. Uncheck the checkbox but don't blur (so it's not invalid yet) * * Expect nothing to happen ($animateCss called with no options) */ setFoo(true); checkbox.triggerHandler('click'); messageAnimation.enter(getError(), doneSpy); flush(); expectError(getError(), 'required'); expect(doneSpy).toHaveBeenCalled(); expect(container).not.toHaveClass('md-input-invalid'); expect(lastAnimateCall).toEqual({element: getError(), options: {}}); /* * 2. Blur the checkbox, which adds the md-input-invalid class * * Expect to animate in the required message */ doneSpy.calls.reset(); checkbox.triggerHandler('blur'); invalidAnimation.addClass(container, 'md-input-invalid', doneSpy); flush(); expectError(getError(), 'required'); expect(doneSpy).toHaveBeenCalled(); expect(container).toHaveClass('md-input-invalid'); expect(lastAnimateCall.element).toEqual(getError()); expect(lastAnimateCall.options.event).toEqual('enter'); expect(lastAnimateCall.options.to).toEqual({"opacity": 1, "margin-top": "0"}); /* * 3. Clear the field * * Expect to animate away required message */ doneSpy.calls.reset(); messageAnimation.leave(getError(), doneSpy); flush(); expect(doneSpy).toHaveBeenCalled(); expect(lastAnimateCall.element).toEqual(getError()); expect(lastAnimateCall.options.event).toEqual('leave'); expect(parseInt(lastAnimateCall.options.to["margin-top"])).toBeLessThan(0); }); /* * Test Helper Functions */ function compile(template) { el = $compile(template)(pageScope); angular.element(document.body).append(el); pageScope.$apply(); return el; } function setFoo(value) { pageScope.foo = value; pageScope.$digest(); } function getError() { return angular.element(el[0].querySelector('.errors div')); } function expectError(element, message) { expect(element.text().trim()).toBe(message); } function flush() { // Note: we use flushInterimElement() because it actually calls everything 3 times which seems // to be enough to actually flush the animations $material.flushInterimElement(); } /* * before/afterEach Helper Functions */ // Decorate the $animateCss service so we can spy on it and disable any CSS transitions function decorateAnimateCss() { module(function($provide) { $provide.decorator('$animateCss', function($delegate) { return jasmine.createSpy('$animateCss').and.callFake(function(element, options) { // Store the last call to $animateCss // // NOTE: We handle this manually because the actual code modifies the options // and can make the tests fail if it executes before the expect() fires lastAnimateCall = { element: element, options: angular.copy(options) }; // Make sure any transitions happen immediately; NOTE: this is REQUIRED for the above // tests to pass without using window.setTimeout to wait for the animations if (cssTransitionsDisabled) { element.css('transition', '0s none'); } return $delegate(element, options); }); }); }); } // Setup/grab our variables function injectGlobals() { inject(function($injector) { $rootScope = $injector.get('$rootScope'); $compile = $injector.get('$compile'); $animateCss = $injector.get('$animateCss'); $material = $injector.get('$material'); $$mdInput = $injector.get('$$mdInput'); // Grab our input animations (we MUST use the injector to setup dependencies) invalidAnimation = $injector.get('mdInputInvalidAnimation'); messagesAnimation = $injector.get('mdInputMessagesAnimation'); messageAnimation = $injector.get('mdInputMessageAnimation'); }); } // Setup some custom variables for these tests function setupVariables() { pageScope = $rootScope.$new(); cssTransitionsDisabled = true; } // Teardown our tests by resetting variables and removing our element function teardown() { cssTransitionsDisabled = false; el && el.remove && el.remove(); } });