'use strict';
describe('ngInclude', function() {
var element;
afterEach(function(){
dealoc(element);
});
function putIntoCache(url, content) {
return function($templateCache) {
$templateCache.put(url, [200, content, {}]);
};
}
it('should trust and use literal urls', inject(function(
$rootScope, $httpBackend, $compile) {
element = $compile('
')($rootScope);
$httpBackend.expect('GET', 'url').respond('template text');
$rootScope.$digest();
$httpBackend.flush();
expect(element.text()).toEqual('template text');
dealoc($rootScope);
}));
it('should trust and use trusted urls', inject(function($rootScope, $httpBackend, $compile, $sce) {
element = $compile('')($rootScope);
$httpBackend.expect('GET', 'http://foo.bar/url').respond('template text');
$rootScope.fooUrl = $sce.trustAsResourceUrl('http://foo.bar/url');
$rootScope.$digest();
$httpBackend.flush();
expect(element.text()).toEqual('template text');
dealoc($rootScope);
}));
it('should include an external file', inject(putIntoCache('myUrl', '{{name}}'),
function($rootScope, $compile) {
element = jqLite('
');
var body = jqLite(document.body);
body.append(element);
element = $compile(element)($rootScope);
$rootScope.name = 'misko';
$rootScope.url = 'myUrl';
$rootScope.$digest();
expect(body.text()).toEqual('misko');
body.html('');
}));
it('should support ng-include="src" syntax', inject(putIntoCache('myUrl', '{{name}}'),
function($rootScope, $compile) {
element = jqLite('');
jqLite(document.body).append(element);
element = $compile(element)($rootScope);
$rootScope.name = 'Alibaba';
$rootScope.url = 'myUrl';
$rootScope.$digest();
expect(element.text()).toEqual('Alibaba');
jqLite(document.body).html('');
}));
it('should NOT use untrusted expressions ', inject(putIntoCache('myUrl', '{{name}} text'),
function($rootScope, $compile, $sce) {
element = jqLite('');
jqLite(document.body).append(element);
element = $compile(element)($rootScope);
$rootScope.name = 'chirayu';
$rootScope.url = 'myUrl';
expect($rootScope.$digest).toThrow();
jqLite(document.body).html('');
}));
it('should NOT use mistyped expressions ', inject(putIntoCache('myUrl', '{{name}} text'),
function($rootScope, $compile, $sce) {
element = jqLite('');
jqLite(document.body).append(element);
element = $compile(element)($rootScope);
$rootScope.name = 'chirayu';
$rootScope.url = $sce.trustAsUrl('myUrl');
expect($rootScope.$digest).toThrow();
jqLite(document.body).html('');
}));
it('should remove previously included text if a falsy value is bound to src', inject(
putIntoCache('myUrl', '{{name}}'),
function($rootScope, $compile) {
element = jqLite('
');
element = $compile(element)($rootScope);
$rootScope.name = 'igor';
$rootScope.url = 'myUrl';
$rootScope.$digest();
expect(element.text()).toEqual('igor');
$rootScope.url = undefined;
$rootScope.$digest();
expect(element.text()).toEqual('');
}));
it('should fire $includeContentRequested event on scope after making the xhr call', inject(
function ($rootScope, $compile, $httpBackend) {
var contentRequestedSpy = jasmine.createSpy('content requested').andCallFake(function (event) {
expect(event.targetScope).toBe($rootScope);
});
$httpBackend.whenGET('url').respond('my partial');
$rootScope.$on('$includeContentRequested', contentRequestedSpy);
element = $compile('')($rootScope);
$rootScope.$digest();
expect(contentRequestedSpy).toHaveBeenCalledOnce();
$httpBackend.flush();
}));
it('should fire $includeContentLoaded event on child scope after linking the content', inject(
function($rootScope, $compile, $templateCache) {
var contentLoadedSpy = jasmine.createSpy('content loaded').andCallFake(function(event) {
expect(event.targetScope.$parent).toBe($rootScope);
expect(element.text()).toBe('partial content');
});
$templateCache.put('url', [200, 'partial content', {}]);
$rootScope.$on('$includeContentLoaded', contentLoadedSpy);
element = $compile('')($rootScope);
$rootScope.$digest();
expect(contentLoadedSpy).toHaveBeenCalledOnce();
}));
it('should evaluate onload expression when a partial is loaded', inject(
putIntoCache('myUrl', 'my partial'),
function($rootScope, $compile) {
element = jqLite('');
element = $compile(element)($rootScope);
expect($rootScope.loaded).not.toBeDefined();
$rootScope.url = 'myUrl';
$rootScope.$digest();
expect(element.text()).toEqual('my partial');
expect($rootScope.loaded).toBe(true);
}));
it('should create child scope and destroy old one', inject(
function($rootScope, $compile, $httpBackend) {
$httpBackend.whenGET('url1').respond('partial {{$parent.url}}');
$httpBackend.whenGET('url2').respond(404);
element = $compile('
')($rootScope);
expect(element.children().scope()).toBeFalsy();
$rootScope.url = 'url1';
$rootScope.$digest();
$httpBackend.flush();
expect(element.children().scope().$parent).toBe($rootScope);
expect(element.text()).toBe('partial url1');
$rootScope.url = 'url2';
$rootScope.$digest();
$httpBackend.flush();
expect($rootScope.$$childHead).toBeFalsy();
expect(element.text()).toBe('');
$rootScope.url = 'url1';
$rootScope.$digest();
expect(element.children().scope().$parent).toBe($rootScope);
$rootScope.url = null;
$rootScope.$digest();
expect($rootScope.$$childHead).toBeFalsy();
}));
it('should do xhr request and cache it',
inject(function($rootScope, $httpBackend, $compile) {
element = $compile('
')($rootScope);
$httpBackend.expect('GET', 'myUrl').respond('my partial');
$rootScope.url = 'myUrl';
$rootScope.$digest();
$httpBackend.flush();
expect(element.text()).toEqual('my partial');
$rootScope.url = null;
$rootScope.$digest();
expect(element.text()).toEqual('');
$rootScope.url = 'myUrl';
$rootScope.$digest();
expect(element.text()).toEqual('my partial');
dealoc($rootScope);
}));
it('should clear content when error during xhr request',
inject(function($httpBackend, $compile, $rootScope) {
element = $compile('content
')($rootScope);
$httpBackend.expect('GET', 'myUrl').respond(404, '');
$rootScope.url = 'myUrl';
$rootScope.$digest();
$httpBackend.flush();
expect(element.text()).toBe('');
}));
it('should be async even if served from cache', inject(
putIntoCache('myUrl', 'my partial'),
function($rootScope, $compile) {
element = $compile('
')($rootScope);
$rootScope.url = 'myUrl';
var called = 0;
// we want to assert only during first watch
$rootScope.$watch(function() {
if (!called++) expect(element.text()).toBe('');
});
$rootScope.$digest();
expect(element.text()).toBe('my partial');
}));
it('should discard pending xhr callbacks if a new template is requested before the current ' +
'finished loading', inject(function($rootScope, $compile, $httpBackend) {
element = jqLite("
");
var log = {};
$rootScope.templateUrl = 'myUrl1';
$rootScope.logger = function(msg) {
log[msg] = true;
}
$compile(element)($rootScope);
expect(log).toEqual({});
$httpBackend.expect('GET', 'myUrl1').respond('{{logger("url1")}}
');
$rootScope.$digest();
expect(log).toEqual({});
$rootScope.templateUrl = 'myUrl2';
$httpBackend.expect('GET', 'myUrl2').respond('{{logger("url2")}}
');
$httpBackend.flush(); // now that we have two requests pending, flush!
expect(log).toEqual({ url2 : true });
}));
it('should compile only the content', inject(function($compile, $rootScope, $templateCache) {
// regression
var onload = jasmine.createSpy('$includeContentLoaded');
$rootScope.$on('$includeContentLoaded', onload);
$templateCache.put('tpl.html', [200, 'partial {{tpl}}', {}]);
element = $compile('')($rootScope);
expect(onload).not.toHaveBeenCalled();
$rootScope.$apply(function() {
$rootScope.tpl = 'tpl.html';
});
expect(onload).toHaveBeenCalledOnce();
$rootScope.tpl = '';
$rootScope.$digest();
dealoc(element);
}));
it('should compile only the inner content once', function() {
var log = [];
module(function($compileProvider) {
$compileProvider.directive('compileLog', function() {
return {
compile: function() {
log.push('compile');
}
};
});
});
inject(function($compile, $rootScope, $templateCache) {
$templateCache.put('tpl.html', [200, '123
', {}]);
element = $compile('')($rootScope);
$rootScope.exp = 'tpl.html';
$rootScope.$digest();
expect(element.text()).toBe('123');
expect(log).toEqual(['compile']);
});
});
describe('autoscoll', function() {
var autoScrollSpy;
function spyOnAnchorScroll() {
return function($provide) {
autoScrollSpy = jasmine.createSpy('$anchorScroll');
$provide.value('$anchorScroll', autoScrollSpy);
};
}
function compileAndLink(tpl) {
return function($compile, $rootScope) {
element = $compile(tpl)($rootScope);
};
}
function changeTplAndValueTo(template, value) {
return function($rootScope, $browser) {
$rootScope.$apply(function() {
$rootScope.tpl = template;
$rootScope.value = value;
});
};
}
beforeEach(module(spyOnAnchorScroll()));
beforeEach(inject(
putIntoCache('template.html', 'CONTENT'),
putIntoCache('another.html', 'CONTENT')));
it('should call $anchorScroll if autoscroll attribute is present', inject(
compileAndLink('
'),
changeTplAndValueTo('template.html'), function() {
expect(autoScrollSpy).toHaveBeenCalledOnce();
}));
it('should call $anchorScroll if autoscroll evaluates to true', inject(
compileAndLink('
'),
changeTplAndValueTo('template.html', true),
changeTplAndValueTo('another.html', 'some-string'),
changeTplAndValueTo('template.html', 100), function() {
expect(autoScrollSpy).toHaveBeenCalled();
expect(autoScrollSpy.callCount).toBe(3);
}));
it('should not call $anchorScroll if autoscroll attribute is not present', inject(
compileAndLink('
'),
changeTplAndValueTo('template.html'), function() {
expect(autoScrollSpy).not.toHaveBeenCalled();
}));
it('should not call $anchorScroll if autoscroll evaluates to false', inject(
compileAndLink('
'),
changeTplAndValueTo('template.html', false),
changeTplAndValueTo('template.html', undefined),
changeTplAndValueTo('template.html', null), function() {
expect(autoScrollSpy).not.toHaveBeenCalled();
}));
});
});
describe('ngInclude animations', function() {
var body, element, $rootElement;
function html(html) {
$rootElement.html(html);
element = $rootElement.children().eq(0);
return element;
}
beforeEach(module(function() {
// we need to run animation on attached elements;
return function(_$rootElement_) {
$rootElement = _$rootElement_;
body = jqLite(document.body);
body.append($rootElement);
};
}));
afterEach(function(){
dealoc(body);
dealoc(element);
});
beforeEach(module('mock.animate'));
afterEach(function(){
dealoc(element);
});
it('should fire off the enter animation',
inject(function($compile, $rootScope, $templateCache, $animate) {
var item;
$templateCache.put('enter', [200, 'data
', {}]);
$rootScope.tpl = 'enter';
element = $compile(html(
''
))($rootScope);
$rootScope.$digest();
item = $animate.flushNext('enter').element;
expect(item.text()).toBe('data');
}));
it('should fire off the leave animation',
inject(function($compile, $rootScope, $templateCache, $animate) {
var item;
$templateCache.put('enter', [200, 'data
', {}]);
$rootScope.tpl = 'enter';
element = $compile(html(
''
))($rootScope);
$rootScope.$digest();
item = $animate.flushNext('enter').element;
expect(item.text()).toBe('data');
$rootScope.tpl = '';
$rootScope.$digest();
item = $animate.flushNext('leave').element;
expect(item.text()).toBe('data');
}));
it('should animate two separate ngInclude elements',
inject(function($compile, $rootScope, $templateCache, $animate) {
var item;
$templateCache.put('one', [200, 'one', {}]);
$templateCache.put('two', [200, 'two', {}]);
$rootScope.tpl = 'one';
element = $compile(html(
''
))($rootScope);
$rootScope.$digest();
item = $animate.flushNext('enter').element;
expect(item.text()).toBe('one');
$rootScope.tpl = 'two';
$rootScope.$digest();
var itemA = $animate.flushNext('leave').element;
var itemB = $animate.flushNext('enter').element;
expect(itemA.attr('ng-include')).toBe('tpl');
expect(itemB.attr('ng-include')).toBe('tpl');
expect(itemA).not.toEqual(itemB);
}));
});