I'm upgrading from ng 1.3.15 to 1.5.8, and running into an issue with animations not completing, and thus tests failing.
I've boiled the issue down to the following:
(function() {
var app = angular.module('wtf', ['ngAnimate']);
app.controller('SlideHolderController', function($rootScope, $scope, $compile, $animate) {
var vm = this;
vm.slides = [];
vm.addSlide = function(slide) {
slide._index = vm.slides.length;
vm.slides.push(slide);
slide.close = function() {
vm.removeSlide(slide);
};
console.log('Added slide: ' + slide.title);
};
vm.removeSlide = function(slide) {
$animate.leave(slide.element).then(function() {
vm.animationComplete();
});
};
vm.animationComplete = function() {
console.log('Animation complete for ' + slide.title);
};
$rootScope.$on('AddSlide', function(evt, slide) {
vm.addSlide(slide);
slide.element = $scope.element.children().eq(slide._index);
});
});
app.controller('TestAnimationController', function($rootScope) {
var vm = this;
var slide_count = 0;
vm.addNewSlide = function() {
var slide = {title: 'Slide-#' + (slide_count + 1)};
$rootScope.$broadcast('AddSlide', slide);
};
});
app.directive('slideHolder', function() {
return {
replace: false,
restrict: 'E',
template: '<div><span ng-click="slide.close();" ng-repeat="slide in vm.slides"></span></div>',
controller: 'SlideHolderController',
controllerAs: 'vm',
scope: true,
link: function(scope, elem, attrs, vm) {
scope.element = elem;
},
};
});
app.directive('testAnimation', function() {
return {
replace: false,
restrict: 'E',
template: '<div class="test"><button ng-click="vm.addNewSlide()">Add New Slide</button></div>',
controller: 'TestAnimationController',
controllerAs: 'vm',
scope: true,
};
});
})();
and the test:
(function() {
'use strict';
describe('Directive: testAnimation', function() {
var compile;
var element;
var root;
var scope;
var slideController;
beforeEach(module('wtf'));
beforeEach(module('templates'));
beforeEach(inject(function($rootScope, $compile) {
compile = $compile;
scope = $rootScope.$new();
}));
beforeEach(function() {
root = angular.element('<div></div>');
compile(root)(scope);
scope.$digest();
var html = compileDirective('<slide-holder class="slide-holder"></slide-holder>', root);
slideController = html.controller('slideHolder');
expect(slideController).toBeDefined();
expect(slideController.slides.length).toBe(0);
spyOn(slideController, 'addSlide').and.callThrough();
spyOn(slideController, 'removeSlide').and.callThrough();
spyOn(slideController, 'animationComplete').and.callThrough();
});
var compileDirective = function(directive, elemToAppendTo) {
var html = angular.element(directive);
var elem = compile(html)(scope.$new());
if (elemToAppendTo) {
elemToAppendTo.append(html);
}
var elem_scope = elem.isolateScope() || elem.scope();
elem_scope.$digest();
return elem;
};
it('verifies removing a slide', inject(function($timeout) {
var el = compileDirective('<test-animation></test-animation>', root);
var slide_holder = root.find('.slide-holder').eq(0);
var test_div = root.find('.test').eq(0);
// test animation directive and the slide-holder are now siblings under root
expect(slide_holder.parent().html()).toBe(el.parent().html());
expect(slide_holder.find('span').length).toBe(0);
expect(slideController.slides.length).toBe(0);
var button = test_div.find('button').eq(0);
expect(button.length).toBe(1);
button.click();
scope.$digest();
expect(slideController.addSlide).toHaveBeenCalled();
expect(slide_holder.find('span').length).toBe(1);
expect(slideController.slides.length).toBe(1);
var slide_span = slide_holder.children().eq(0).find('span');
slide_span.click();
scope.$digest();
expect(slideController.removeSlide).toHaveBeenCalled();
// $timeout.flush(); // fails with No deferred tasks to be flushed
expect(slideController.animationComplete).toHaveBeenCalled(); // failure here
}));
});
})();
The problem is the final expectation fails, apparently because there is no root or body element for the animate element to live in. This is a marked change from 1.3.15 (the prior version I was using) and I can't find any documentation on how to address it. This is a blocker for my production app, which relies heavily on a structure very similar to that above, where a slide-holder exists independently of any controllers or directives that might add slides.
Can anyone shed light on what I need to do?
Aucun commentaire:
Enregistrer un commentaire