')($scope));
});
$scope.$apply();
}
it('should immediately remove the element if condition is falsy', function() {
makeIf('false', 'undefined', 'null', 'NaN', '\'\'', '0');
expect(element.children().length).toBe(0);
});
it('should leave the element if condition is true', function() {
makeIf('true');
expect(element.children().length).toBe(1);
});
it('should leave the element if the condition is a non-empty string', function() {
makeIf('\'f\'', '\'0\'', '\'false\'', '\'no\'', '\'n\'', '\'[]\'');
expect(element.children().length).toBe(6);
});
it('should leave the element if the condition is an object', function() {
makeIf('[]', '{}');
expect(element.children().length).toBe(2);
});
it('should not add the element twice if the condition goes from true to true', function() {
$scope.hello = 'true1';
makeIf('hello');
expect(element.children().length).toBe(1);
$scope.$apply('hello = "true2"');
expect(element.children().length).toBe(1);
});
it('should not recreate the element if the condition goes from true to true', function() {
$scope.hello = 'true1';
makeIf('hello');
element.children().data('flag', true);
$scope.$apply('hello = "true2"');
expect(element.children().data('flag')).toBe(true);
});
it('should create then remove the element if condition changes', function() {
$scope.hello = true;
makeIf('hello');
expect(element.children().length).toBe(1);
$scope.$apply('hello = false');
expect(element.children().length).toBe(0);
});
it('should create a new scope every time the expression evaluates to true', function() {
$scope.$apply('value = true');
element.append($compile(
'
'
)($scope));
$scope.$apply();
expect(element.children('div').length).toBe(1);
});
it('should destroy the child scope every time the expression evaluates to false', function() {
$scope.value = true;
element.append($compile(
''
)($scope));
$scope.$apply();
var childScope = element.children().scope();
var destroyed = false;
childScope.$on('$destroy', function() {
destroyed = true;
});
$scope.value = false;
$scope.$apply();
expect(destroyed).toBe(true);
});
it('should play nice with other elements beside it', function() {
$scope.values = [1, 2, 3, 4];
element.append($compile(
'' +
'' +
''
)($scope));
$scope.$apply();
expect(element.children().length).toBe(9);
$scope.$apply('values.splice(0,1)');
expect(element.children().length).toBe(6);
$scope.$apply('values.push(1)');
expect(element.children().length).toBe(9);
});
it('should play nice with ngInclude on the same element', inject(function($templateCache) {
$templateCache.put('test.html', [200, '{{value}}', {}]);
$scope.value = 'first';
element.append($compile(
''
)($scope));
$scope.$apply();
expect(element.text()).toBe('first');
$scope.value = 'later';
$scope.$apply();
expect(element.text()).toBe('');
}));
it('should work with multiple elements', function() {
$scope.show = true;
$scope.things = [1, 2, 3];
element.append($compile(
'
before;
' +
'
start;
' +
'
{{thing}};
' +
'
end;
' +
'
after;
'
)($scope));
$scope.$apply();
expect(element.text()).toBe('before;start;1;2;3;end;after;');
$scope.things.push(4);
$scope.$apply();
expect(element.text()).toBe('before;start;1;2;3;4;end;after;');
$scope.show = false;
$scope.$apply();
expect(element.text()).toBe('before;after;');
});
it('should restore the element to its compiled state', function() {
$scope.value = true;
makeIf('value');
expect(element.children().length).toBe(1);
jqLite(element.children()[0]).removeClass('my-class');
expect(element.children()[0].className).not.toContain('my-class');
$scope.$apply('value = false');
expect(element.children().length).toBe(0);
$scope.$apply('value = true');
expect(element.children().length).toBe(1);
expect(element.children()[0].className).toContain('my-class');
});
it('should work when combined with an ASYNC template that loads after the first digest', inject(function($httpBackend, $compile, $rootScope) {
$compileProvider.directive('test', function() {
return {
templateUrl: 'test.html'
};
});
$httpBackend.whenGET('test.html').respond('hello');
element.append('');
$compile(element)($rootScope);
$rootScope.show = true;
$rootScope.$apply();
expect(element.text()).toBe('');
$httpBackend.flush();
expect(element.text()).toBe('hello');
$rootScope.show = false;
$rootScope.$apply();
// Note: there are still comments in element!
expect(element.children().length).toBe(0);
expect(element.text()).toBe('');
}));
it('should not trigger a digest when the element is removed', inject(function($$rAF, $rootScope, $timeout) {
var spy = spyOn($rootScope, '$digest').and.callThrough();
$scope.hello = true;
makeIf('hello');
expect(element.children().length).toBe(1);
$scope.$apply('hello = false');
spy.calls.reset();
expect(element.children().length).toBe(0);
// The animation completion is async even without actual animations
$$rAF.flush();
expect(spy).not.toHaveBeenCalled();
// A digest may have been triggered asynchronously, so check the queue
$timeout.verifyNoPendingTasks();
}));
});
describe('and transcludes', function() {
it('should allow access to directive controller from children when used in a replace template', function() {
var controller;
module(function($compileProvider) {
var directive = $compileProvider.directive;
directive('template', valueFn({
template: '