'use strict'; describe('ngMessages', function() { beforeEach(inject.strictDi()); beforeEach(module('ngMessages')); function they(msg, vals, spec, focus) { forEach(vals, function(val, key) { var m = msg.replace('$prop', key); (focus ? iit : it)(m, function() { spec(val); }); }); } function tthey(msg, vals, spec) { they(msg, vals, spec, true); } function s(str) { return str.replace(/\s+/g,''); } var element; afterEach(function() { dealoc(element); }); it('should render based off of a hashmap collection', inject(function($rootScope, $compile) { element = $compile('
' + '
Message is set
' + '
')($rootScope); $rootScope.$digest(); expect(element.text()).not.toContain('Message is set'); $rootScope.$apply(function() { $rootScope.col = { val: true }; }); expect(element.text()).toContain('Message is set'); })); it('should use the data attribute when an element directive is used', inject(function($rootScope, $compile) { element = $compile('' + ' Message is set' + '')($rootScope); $rootScope.$digest(); expect(element.text()).not.toContain('Message is set'); $rootScope.$apply(function() { $rootScope.col = { val: true }; }); expect(element.text()).toContain('Message is set'); })); they('should render empty when $prop is used as a collection value', { 'null': null, 'false': false, '0': 0, '[]': [], '[{}]': [{}], '': '', '{ val2 : true }': { val2: true } }, function(prop) { inject(function($rootScope, $compile) { element = $compile('
' + '
Message is set
' + '
')($rootScope); $rootScope.$digest(); $rootScope.$apply(function() { $rootScope.col = prop; }); expect(element.text()).not.toContain('Message is set'); }); }); they('should insert and remove matching inner elements when $prop is used as a value', { 'true': true, '1': 1, '{}': {}, '[]': [], '[null]': [null] }, function(prop) { inject(function($rootScope, $compile) { element = $compile('
' + '
This message is blue
' + '
This message is red
' + '
')($rootScope); $rootScope.$apply(function() { $rootScope.col = {}; }); expect(element.children().length).toBe(0); expect(trim(element.text())).toEqual(''); $rootScope.$apply(function() { $rootScope.col = { blue: true, red: false }; }); expect(element.children().length).toBe(1); expect(trim(element.text())).toEqual('This message is blue'); $rootScope.$apply(function() { $rootScope.col = { red: prop }; }); expect(element.children().length).toBe(1); expect(trim(element.text())).toEqual('This message is red'); $rootScope.$apply(function() { $rootScope.col = null; }); expect(element.children().length).toBe(0); expect(trim(element.text())).toEqual(''); $rootScope.$apply(function() { $rootScope.col = { blue: 0, red: null }; }); expect(element.children().length).toBe(0); expect(trim(element.text())).toEqual(''); }); }); it('should display the elements in the order defined in the DOM', inject(function($rootScope, $compile) { element = $compile('
' + '
Message#one
' + '
Message#two
' + '
Message#three
' + '
')($rootScope); $rootScope.$apply(function() { $rootScope.col = { three: true, one: true, two: true }; }); angular.forEach(['one','two','three'], function(key) { expect(s(element.text())).toEqual('Message#' + key); $rootScope.$apply(function() { $rootScope.col[key] = false; }); }); expect(s(element.text())).toEqual(''); })); it('should add ng-active/ng-inactive CSS classes to the element when errors are/aren\'t displayed', inject(function($rootScope, $compile) { element = $compile('
' + '
This message is ready
' + '
')($rootScope); $rootScope.$apply(function() { $rootScope.col = {}; }); expect(element.hasClass('ng-active')).toBe(false); expect(element.hasClass('ng-inactive')).toBe(true); $rootScope.$apply(function() { $rootScope.col = { ready: true }; }); expect(element.hasClass('ng-active')).toBe(true); expect(element.hasClass('ng-inactive')).toBe(false); })); it('should render animations when the active/inactive classes are added/removed', function() { module('ngAnimate'); module('ngAnimateMock'); inject(function($rootScope, $compile, $animate) { element = $compile('
' + '
This message is ready
' + '
')($rootScope); $rootScope.$apply(function() { $rootScope.col = {}; }); var event = $animate.queue.pop(); expect(event.event).toBe('setClass'); expect(event.args[1]).toBe('ng-inactive'); expect(event.args[2]).toBe('ng-active'); $rootScope.$apply(function() { $rootScope.col = { ready: true }; }); event = $animate.queue.pop(); expect(event.event).toBe('setClass'); expect(event.args[1]).toBe('ng-active'); expect(event.args[2]).toBe('ng-inactive'); }); }); describe('when including templates', function() { they('should load a remote template using $prop', {'
': '
', '': ''}, function(html) { inject(function($compile, $rootScope, $templateCache) { $templateCache.put('abc.html', '
A
' + '
B
' + '
C
'); element = $compile(html)($rootScope); $rootScope.$apply(function() { $rootScope.data = { 'a': 1, 'b': 2, 'c': 3 }; }); expect(element.children().length).toBe(1); expect(trim(element.text())).toEqual("A"); $rootScope.$apply(function() { $rootScope.data = { 'c': 3 }; }); expect(element.children().length).toBe(1); expect(trim(element.text())).toEqual("C"); }); }); it('should cache the template after download', inject(function($rootScope, $compile, $templateCache, $httpBackend) { $httpBackend.expect('GET', 'tpl').respond(201, 'abc'); expect($templateCache.get('tpl')).toBeUndefined(); element = $compile('
')($rootScope); $rootScope.$digest(); $httpBackend.flush(); expect($templateCache.get('tpl')).toBeDefined(); })); it('should re-render the messages after download without an extra digest', inject(function($rootScope, $compile, $httpBackend) { $httpBackend.expect('GET', 'my-messages').respond(201,'
You did not enter a value
'); element = $compile('
' + '
Your value is that of failure
' + '
')($rootScope); $rootScope.data = { required: true, failed: true }; $rootScope.$digest(); expect(element.children().length).toBe(1); expect(trim(element.text())).toEqual("Your value is that of failure"); $httpBackend.flush(); expect(element.children().length).toBe(1); expect(trim(element.text())).toEqual("You did not enter a value"); })); it('should allow for overriding the remote template messages within the element', inject(function($compile, $rootScope, $templateCache) { $templateCache.put('abc.html', '
A
' + '
B
' + '
C
'); element = $compile('
' + '
AAA
' + '
CCC
' + '
')($rootScope); $rootScope.$apply(function() { $rootScope.data = { 'a': 1, 'b': 2, 'c': 3 }; }); expect(element.children().length).toBe(1); expect(trim(element.text())).toEqual("AAA"); $rootScope.$apply(function() { $rootScope.data = { 'b': 2, 'c': 3 }; }); expect(element.children().length).toBe(1); expect(trim(element.text())).toEqual("B"); $rootScope.$apply(function() { $rootScope.data = { 'c': 3 }; }); expect(element.children().length).toBe(1); expect(trim(element.text())).toEqual("CCC"); })); it('should retain the order of the remote template\'s messages when overriding within the element', inject(function($compile, $rootScope, $templateCache) { $templateCache.put('abc.html', '
C
' + '
A
' + '
B
'); element = $compile('
' + '
AAA
' + '
CCC
' + '
')($rootScope); $rootScope.$apply(function() { $rootScope.data = { 'a': 1, 'b': 2, 'c': 3 }; }); expect(element.children().length).toBe(1); expect(trim(element.text())).toEqual("CCC"); $rootScope.$apply(function() { $rootScope.data = { 'a': 1, 'b': 2 }; }); expect(element.children().length).toBe(1); expect(trim(element.text())).toEqual("AAA"); $rootScope.$apply(function() { $rootScope.data = { 'b': 3 }; }); expect(element.children().length).toBe(1); expect(trim(element.text())).toEqual("B"); })); }); describe('when multiple', function() { they('should show all truthy messages when the $prop attr is present', { 'multiple': 'multiple', 'ng-messages-multiple': 'ng-messages-multiple' }, function(prop) { inject(function($rootScope, $compile) { element = $compile('
' + '
1
' + '
2
' + '
3
' + '
')($rootScope); $rootScope.$apply(function() { $rootScope.data = { 'one': true, 'two': false, 'three': true }; }); expect(element.children().length).toBe(2); expect(s(element.text())).toContain("13"); }); }); it('should render all truthy messages from a remote template', inject(function($rootScope, $compile, $templateCache) { $templateCache.put('xyz.html', '
X
' + '
Y
' + '
Z
'); element = $compile('
')($rootScope); $rootScope.$apply(function() { $rootScope.data = { 'x': 'a', 'y': null, 'z': true }; }); expect(element.children().length).toBe(2); expect(s(element.text())).toEqual("XZ"); $rootScope.$apply(function() { $rootScope.data.y = {}; }); expect(element.children().length).toBe(3); expect(s(element.text())).toEqual("XYZ"); })); it('should render and override all truthy messages from a remote template', inject(function($rootScope, $compile, $templateCache) { $templateCache.put('xyz.html', '
X
' + '
Y
' + '
Z
'); element = $compile('
' + '
YYY
' + '
ZZZ
' + '
')($rootScope); $rootScope.$apply(function() { $rootScope.data = { 'x': 'a', 'y': null, 'z': true }; }); expect(element.children().length).toBe(2); expect(s(element.text())).toEqual("XZZZ"); $rootScope.$apply(function() { $rootScope.data.y = {}; }); expect(element.children().length).toBe(3); expect(s(element.text())).toEqual("XYYYZZZ"); })); }); });