Files
angular.js/test/ng/directive/ngSwitchSpec.js
Matias Niemelä bf0f5502b1 feat($animate): use promises instead of callbacks for animations
The $animate service (both the service inside of ng and ngAnimate) now
makes use of promises instead of callback functions.

BREAKING CHANGE

Both the API for the cancallation method and the done callback for
$animate animations is different. Instead of using a callback function
for each of the $animate animation methods, a promise is used instead.

```js
//before
$animate.enter(element, container, null, callbackFn);

//after
$animate.enter(element, container).then(callbackFn);
```

The animation can now be cancelled via `$animate.cancel(promise)`.

```js
//before
var cancelFn = $animate.enter(element, container);
cancelFn(); //cancels the animation

//after
var promise = $animate.enter(element, container);
$animate.cancel(promise); //cancels the animation
```
2014-08-26 11:44:25 -04:00

456 lines
14 KiB
JavaScript

'use strict';
describe('ngSwitch', function() {
var element;
afterEach(function(){
dealoc(element);
});
it('should switch on value change', inject(function($rootScope, $compile) {
element = $compile(
'<div ng-switch="select">' +
'<div ng-switch-when="1">first:{{name}}</div>' +
'<div ng-switch-when="2">second:{{name}}</div>' +
'<div ng-switch-when="true">true:{{name}}</div>' +
'</div>')($rootScope);
expect(element.html()).toEqual(
'<!-- ngSwitchWhen: 1 --><!-- ngSwitchWhen: 2 --><!-- ngSwitchWhen: true -->');
$rootScope.select = 1;
$rootScope.$apply();
expect(element.text()).toEqual('first:');
$rootScope.name="shyam";
$rootScope.$apply();
expect(element.text()).toEqual('first:shyam');
$rootScope.select = 2;
$rootScope.$apply();
expect(element.text()).toEqual('second:shyam');
$rootScope.name = 'misko';
$rootScope.$apply();
expect(element.text()).toEqual('second:misko');
$rootScope.select = true;
$rootScope.$apply();
expect(element.text()).toEqual('true:misko');
}));
it('should show all switch-whens that match the current value', inject(function($rootScope, $compile) {
element = $compile(
'<ul ng-switch="select">' +
'<li ng-switch-when="1">first:{{name}}</li>' +
'<li ng-switch-when="1">, first too:{{name}}</li>' +
'<li ng-switch-when="2">second:{{name}}</li>' +
'<li ng-switch-when="true">true:{{name}}</li>' +
'</ul>')($rootScope);
expect(element.html()).toEqual('<!-- ngSwitchWhen: 1 -->' +
'<!-- ngSwitchWhen: 1 -->' +
'<!-- ngSwitchWhen: 2 -->' +
'<!-- ngSwitchWhen: true -->');
$rootScope.select = 1;
$rootScope.$apply();
expect(element.text()).toEqual('first:, first too:');
$rootScope.name="shyam";
$rootScope.$apply();
expect(element.text()).toEqual('first:shyam, first too:shyam');
$rootScope.select = 2;
$rootScope.$apply();
expect(element.text()).toEqual('second:shyam');
$rootScope.name = 'misko';
$rootScope.$apply();
expect(element.text()).toEqual('second:misko');
$rootScope.select = true;
$rootScope.$apply();
expect(element.text()).toEqual('true:misko');
}));
it('should show all elements between start and end markers that match the current value',
inject(function($rootScope, $compile) {
element = $compile(
'<ul ng-switch="select">' +
'<li ng-switch-when-start="1">A</li>' +
'<li>B</li>' +
'<li ng-switch-when-end>C</li>' +
'<li ng-switch-when-start="2">D</li>' +
'<li>E</li>' +
'<li ng-switch-when-end>F</li>' +
'</ul>')($rootScope);
$rootScope.$apply('select = "1"');
expect(element.find('li').length).toBe(3);
expect(element.find('li').eq(0).text()).toBe('A');
expect(element.find('li').eq(1).text()).toBe('B');
expect(element.find('li').eq(2).text()).toBe('C');
$rootScope.$apply('select = "2"');
expect(element.find('li').length).toBe(3);
expect(element.find('li').eq(0).text()).toBe('D');
expect(element.find('li').eq(1).text()).toBe('E');
expect(element.find('li').eq(2).text()).toBe('F');
}));
it('should switch on switch-when-default', inject(function($rootScope, $compile) {
element = $compile(
'<ng:switch on="select">' +
'<div ng:switch-when="1">one</div>' +
'<div ng:switch-default>other</div>' +
'</ng:switch>')($rootScope);
$rootScope.$apply();
expect(element.text()).toEqual('other');
$rootScope.select = 1;
$rootScope.$apply();
expect(element.text()).toEqual('one');
}));
it('should show all default elements between start and end markers when no match',
inject(function($rootScope, $compile) {
element = $compile(
'<ul ng-switch="select">' +
'<li ng-switch-when-start="1">A</li>' +
'<li>B</li>' +
'<li ng-switch-when-end>C</li>' +
'<li ng-switch-default-start>D</li>' +
'<li>E</li>' +
'<li ng-switch-default-end>F</li>' +
'</ul>')($rootScope);
$rootScope.$apply('select = "1"');
expect(element.find('li').length).toBe(3);
expect(element.find('li').eq(0).text()).toBe('A');
expect(element.find('li').eq(1).text()).toBe('B');
expect(element.find('li').eq(2).text()).toBe('C');
$rootScope.$apply('select = "2"');
expect(element.find('li').length).toBe(3);
expect(element.find('li').eq(0).text()).toBe('D');
expect(element.find('li').eq(1).text()).toBe('E');
expect(element.find('li').eq(2).text()).toBe('F');
}));
it('should show all switch-when-default', inject(function($rootScope, $compile) {
element = $compile(
'<ul ng-switch="select">' +
'<li ng-switch-when="1">one</li>' +
'<li ng-switch-default>other</li>' +
'<li ng-switch-default>, other too</li>' +
'</ul>')($rootScope);
$rootScope.$apply();
expect(element.text()).toEqual('other, other too');
$rootScope.select = 1;
$rootScope.$apply();
expect(element.text()).toEqual('one');
}));
it('should always display the elements that do not match a switch',
inject(function($rootScope, $compile) {
element = $compile(
'<ul ng-switch="select">' +
'<li>always </li>' +
'<li ng-switch-when="1">one </li>' +
'<li ng-switch-when="2">two </li>' +
'<li ng-switch-default>other, </li>' +
'<li ng-switch-default>other too </li>' +
'</ul>')($rootScope);
$rootScope.$apply();
expect(element.text()).toEqual('always other, other too ');
$rootScope.select = 1;
$rootScope.$apply();
expect(element.text()).toEqual('always one ');
}));
it('should display the elements that do not have ngSwitchWhen nor ' +
'ngSwitchDefault at the position specified in the template, when the ' +
'first and last elements in the ngSwitch body do not have a ngSwitch* ' +
'directive', inject(function($rootScope, $compile) {
element = $compile(
'<ul ng-switch="select">' +
'<li>1</li>' +
'<li ng-switch-when="1">2</li>' +
'<li>3</li>' +
'<li ng-switch-when="2">4</li>' +
'<li ng-switch-default>5</li>' +
'<li>6</li>' +
'<li ng-switch-default>7</li>' +
'<li>8</li>' +
'</ul>')($rootScope);
$rootScope.$apply();
expect(element.text()).toEqual('135678');
$rootScope.select = 1;
$rootScope.$apply();
expect(element.text()).toEqual('12368');
}));
it('should display the elements that do not have ngSwitchWhen nor ' +
'ngSwitchDefault at the position specified in the template when the ' +
'first and last elements in the ngSwitch have a ngSwitch* directive',
inject(function($rootScope, $compile) {
element = $compile(
'<ul ng-switch="select">' +
'<li ng-switch-when="1">2</li>' +
'<li>3</li>' +
'<li ng-switch-when="2">4</li>' +
'<li ng-switch-default>5</li>' +
'<li>6</li>' +
'<li ng-switch-default>7</li>' +
'</ul>')($rootScope);
$rootScope.$apply();
expect(element.text()).toEqual('3567');
$rootScope.select = 1;
$rootScope.$apply();
expect(element.text()).toEqual('236');
}));
it('should call change on switch', inject(function($rootScope, $compile) {
element = $compile(
'<ng:switch on="url" change="name=\'works\'">' +
'<div ng-switch-when="a">{{name}}</div>' +
'</ng:switch>')($rootScope);
$rootScope.url = 'a';
$rootScope.$apply();
expect($rootScope.name).toEqual('works');
expect(element.text()).toEqual('works');
}));
it('should properly create and destroy child scopes', inject(function($rootScope, $compile) {
element = $compile(
'<ng:switch on="url">' +
'<div ng-switch-when="a">{{name}}</div>' +
'</ng:switch>')($rootScope);
$rootScope.$apply();
var getChildScope = function() { return element.find('div').scope(); };
expect(getChildScope()).toBeUndefined();
$rootScope.url = 'a';
$rootScope.$apply();
var child1 = getChildScope();
expect(child1).toBeDefined();
spyOn(child1, '$destroy');
$rootScope.url = 'x';
$rootScope.$apply();
expect(getChildScope()).toBeUndefined();
expect(child1.$destroy).toHaveBeenCalled();
$rootScope.url = 'a';
$rootScope.$apply();
var child2 = getChildScope();
expect(child2).toBeDefined();
expect(child2).not.toBe(child1);
}));
it("should interoperate with other transclusion directives like ngRepeat", inject(function($rootScope, $compile) {
element = $compile(
'<div ng-switch="value">' +
'<div ng-switch-when="foo" ng-repeat="foo in foos">{{value}}:{{foo}}|</div>' +
'<div ng-switch-default ng-repeat="bar in bars">{{value}}:{{bar}}|</div>' +
'</div>'
)($rootScope);
$rootScope.$apply('value="foo";foos=["one", "two"]');
expect(element.text()).toEqual('foo:one|foo:two|');
$rootScope.$apply('value="foo";foos=["one"]');
expect(element.text()).toEqual('foo:one|');
$rootScope.$apply('value="foo";foos=["one","two","three"]');
expect(element.text()).toEqual('foo:one|foo:two|foo:three|');
$rootScope.$apply('value="bar";bars=["up", "down"]');
expect(element.text()).toEqual('bar:up|bar:down|');
$rootScope.$apply('value="bar";bars=["up", "down", "forwards", "backwards"]');
expect(element.text()).toEqual('bar:up|bar:down|bar:forwards|bar:backwards|');
}));
it('should not leak jq data when compiled but not attached to parent when parent is destroyed',
inject(function($rootScope, $compile) {
element = $compile(
'<div ng-repeat="i in []">' +
'<ng-switch on="url">' +
'<div ng-switch-when="a">{{name}}</div>' +
'</ng-switch>' +
'</div>')($rootScope);
$rootScope.$apply();
// element now contains only empty repeater. this element is dealocated by local afterEach.
// afterwards a global afterEach will check for leaks in jq data cache object
}));
it('should properly support case labels with different numbers of transclude fns', inject(function($rootScope, $compile) {
element = $compile(
'<div ng-switch="mode">' +
'<p ng-switch-when="a">Block1</p>' +
'<p ng-switch-when="a">Block2</p>' +
'<a href ng-switch-when="b">a</a>' +
'</div>'
)($rootScope);
$rootScope.$apply('mode = "a"');
expect(element.children().length).toBe(2);
$rootScope.$apply('mode = "b"');
expect(element.children().length).toBe(1);
$rootScope.$apply('mode = "a"');
expect(element.children().length).toBe(2);
$rootScope.$apply('mode = "b"');
expect(element.children().length).toBe(1);
}));
});
describe('ngSwitch animations', function() {
var body, element, $rootElement;
function html(content) {
$rootElement.html(content);
element = $rootElement.children().eq(0);
return element;
}
beforeEach(module('ngAnimateMock'));
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);
});
it('should fire off the enter animation',
inject(function($compile, $rootScope, $animate) {
var item;
var $scope = $rootScope.$new();
element = $compile(html(
'<div ng-switch on="val">' +
'<div ng-switch-when="one">one</div>' +
'<div ng-switch-when="two">two</div>' +
'<div ng-switch-when="three">three</div>' +
'</div>'
))($scope);
$rootScope.$digest(); // re-enable the animations;
$scope.val = 'one';
$scope.$digest();
item = $animate.queue.shift();
expect(item.event).toBe('enter');
expect(item.element.text()).toBe('one');
})
);
it('should fire off the leave animation',
inject(function($compile, $rootScope, $animate) {
var item;
var $scope = $rootScope.$new();
element = $compile(html(
'<div ng-switch on="val">' +
'<div ng-switch-when="one">one</div>' +
'<div ng-switch-when="two">two</div>' +
'<div ng-switch-when="three">three</div>' +
'</div>'
))($scope);
$rootScope.$digest(); // re-enable the animations;
$scope.val = 'two';
$scope.$digest();
item = $animate.queue.shift();
expect(item.event).toBe('enter');
expect(item.element.text()).toBe('two');
$scope.val = 'three';
$scope.$digest();
item = $animate.queue.shift();
expect(item.event).toBe('leave');
expect(item.element.text()).toBe('two');
item = $animate.queue.shift();
expect(item.event).toBe('enter');
expect(item.element.text()).toBe('three');
})
);
it('should destroy the previous leave animation if a new one takes place', function() {
module(function($provide) {
$provide.decorator('$animate', function($delegate, $$q) {
var emptyPromise = $$q.defer().promise;
$delegate.leave = function() {
return emptyPromise;
};
return $delegate;
});
});
inject(function ($compile, $rootScope, $animate, $templateCache) {
var item;
var $scope = $rootScope.$new();
element = $compile(html(
'<div ng-switch="inc">' +
'<div ng-switch-when="one">one</div>' +
'<div ng-switch-when="two">two</div>' +
'</div>'
))($scope);
$scope.$apply('inc = "one"');
var destroyed, inner = element.children(0);
inner.on('$destroy', function() {
destroyed = true;
});
$scope.$apply('inc = "two"');
$scope.$apply('inc = "one"');
$scope.$apply('inc = "two"');
expect(destroyed).toBe(true);
});
});
it('should work with svg elements when the svg container is transcluded', function() {
module(function($compileProvider) {
$compileProvider.directive('svgContainer', function() {
return {
template: '<svg ng-transclude></svg>',
replace: true,
transclude: true
};
});
});
inject(function($compile, $rootScope) {
element = $compile('<svg-container ng-switch="inc"><circle ng-switch-when="one"></circle>' +
'</svg-container>')($rootScope);
$rootScope.inc = 'one';
$rootScope.$apply();
var circle = element.find('circle');
expect(circle[0].toString()).toMatch(/SVG/);
});
});
});