mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
refactor(collection-repeat): performance
This commit is contained in:
@@ -1,173 +1,239 @@
|
||||
describe('collectionRepeat directive', function() {
|
||||
describe('collectionRepeat', function() {
|
||||
|
||||
var dataSource, repeatManager;
|
||||
var el;
|
||||
beforeEach(module('ionic', function($provide) {
|
||||
$provide.value(
|
||||
'$collectionDataSource',
|
||||
jasmine.createSpy('$dataSource').andCallFake(function(opts) {
|
||||
dataSource = {
|
||||
options: opts,
|
||||
setData: jasmine.createSpy('setData')
|
||||
};
|
||||
return dataSource;
|
||||
})
|
||||
);
|
||||
$provide.value(
|
||||
'$collectionRepeatManager',
|
||||
jasmine.createSpy('$repeatManager').andCallFake(function(opts) {
|
||||
repeatManager = {
|
||||
options: opts,
|
||||
resize: jasmine.createSpy('resize')
|
||||
};
|
||||
return repeatManager;
|
||||
})
|
||||
);
|
||||
$provide.decorator('$$rAF', function($delegate) {
|
||||
return function mockRaf(callback) { callback(); };
|
||||
});
|
||||
spyOn(ionic, 'animationFrameThrottle').andCallFake(function(cb) {
|
||||
return function fakeThrottled() {
|
||||
cb.apply(this, arguments);
|
||||
};
|
||||
});
|
||||
}));
|
||||
|
||||
function setup(attrs, scrollViewOpts) {
|
||||
var el;
|
||||
var scrollView;
|
||||
function setup(listData, attrs, scrollViewData) {
|
||||
var content = angular.element('<content>')
|
||||
scrollView = angular.extend({
|
||||
__content: content[0],
|
||||
__clientHeight: 100,
|
||||
__clientWidth: 50,
|
||||
|
||||
__scrollTop: 0,
|
||||
__scrollLeft: 0,
|
||||
__maxScrollTop: 100,
|
||||
__maxScrollLeft: 50,
|
||||
|
||||
options: {
|
||||
scrollingY: true
|
||||
},
|
||||
__callback: function(){},
|
||||
}, scrollViewData || {});
|
||||
var scrollCtrl = {
|
||||
scrollView: scrollView,
|
||||
$element: content
|
||||
};
|
||||
|
||||
var list = [];
|
||||
if (angular.isNumber(listData)) {
|
||||
for (var i = 0; i < listData; i++) list.push(i);
|
||||
} else if (angular.isArray(listData)) {
|
||||
list = listData;
|
||||
}
|
||||
|
||||
var element;
|
||||
inject(function($compile, $rootScope) {
|
||||
var content = $compile('<ion-content>')($rootScope.$new());
|
||||
$rootScope.$apply();
|
||||
angular.extend(
|
||||
content.controller('$ionicScroll').scrollView.options,
|
||||
scrollViewOpts || {}
|
||||
attrs = attrs || '';
|
||||
if (!/item-height/.test(attrs)) attrs += ' item-height="25px"';
|
||||
if (!/item-render-buffer/.test(attrs)) attrs += ' item-render-buffer="0"';
|
||||
element = angular.element(
|
||||
'<div collection-repeat="item in list" '+(attrs)+'>{{item}}</div>'
|
||||
);
|
||||
el = angular.element('<div ' + (attrs||'') + '></div>');
|
||||
content.append(el);
|
||||
$compile(el)(content.scope());
|
||||
content.append(element);
|
||||
content.data('$$ionicScrollController', scrollCtrl);
|
||||
$rootScope.list = list;
|
||||
$compile(element)($rootScope);
|
||||
$rootScope.$apply();
|
||||
content.triggerHandler('scroll.init');
|
||||
$rootScope.$apply();
|
||||
});
|
||||
return el;
|
||||
return element;
|
||||
}
|
||||
|
||||
describe('errors', function() {
|
||||
it('should error if scrollView is x and y', function() {
|
||||
expect(function() {
|
||||
setup('collection-repeat', {scrollingX:true, scrollingY:true});
|
||||
}).toThrow(COLLECTION_REPEAT_SCROLLVIEW_XY_ERROR);
|
||||
});
|
||||
it('should error if scrollView is x and no width', function() {
|
||||
expect(function() {
|
||||
setup('collection-repeat collection-item-height', {
|
||||
scrollingX:true,
|
||||
scrollingY:false
|
||||
});
|
||||
}).toThrow(COLLECTION_REPEAT_ATTR_WIDTH_ERROR);
|
||||
});
|
||||
it('should error if scrollView is y and no height', function() {
|
||||
expect(function() {
|
||||
setup('collection-repeat collection-item-width', {
|
||||
scrollingX:false,
|
||||
scrollingY:true
|
||||
});
|
||||
}).toThrow(COLLECTION_REPEAT_ATTR_HEIGHT_ERROR);
|
||||
});
|
||||
it('should error if no repeat expression', function() {
|
||||
expect(function() {
|
||||
setup('collection-repeat="bad" collection-item-height="1"');
|
||||
}).toThrow(COLLECTION_REPEAT_ATTR_REPEAT_ERROR.replace('%', 'bad'));
|
||||
});
|
||||
});
|
||||
function scrollTo(n) {
|
||||
if (scrollView.options.scrollingY) {
|
||||
scrollView.__scrollTop = n;
|
||||
scrollView.__maxScrollTop = scrollView.options.getContentHeight() - scrollView.__clientHeight;
|
||||
} else {
|
||||
scrollView.__scrollLeft = n;
|
||||
scrollView.__maxScrollLeft = scrollView.options.getContentWidth() - scrollView.__clientWidth;
|
||||
}
|
||||
scrollView.__callback();
|
||||
}
|
||||
|
||||
describe('widthGetter & heightGetter', function() {
|
||||
it('should work with given amounts parsed to int', function() {
|
||||
var el = setup('collection-repeat="a in b" collection-item-height="\'5\'" collection-item-width="\'10\'"');
|
||||
expect(dataSource.options.heightGetter()).toBe(5);
|
||||
expect(dataSource.options.widthGetter()).toBe(10);
|
||||
});
|
||||
it('should default width of y-scroller to 100%', function() {
|
||||
var el = setup('collection-repeat="a in b" collection-item-height="5"');
|
||||
el.controller('$ionicScroll').scrollView.__clientWidth = 200;
|
||||
expect(dataSource.options.widthGetter()).toBe(200);
|
||||
});
|
||||
it('should default height of x-scroller to 100%', function() {
|
||||
var el = setup('collection-repeat="a in b" collection-item-width="5"', {
|
||||
scrollingX: true,
|
||||
scrollingY: false
|
||||
function items() {
|
||||
return [].slice.call(scrollView.__content.querySelectorAll('[collection-repeat]'))
|
||||
.map(function(node) {
|
||||
return angular.element(node).data('$$collectionRepeatItem')
|
||||
})
|
||||
// make sure we didn't get anything that doesn't actually have the data
|
||||
.filter(function(item) {
|
||||
return !!item;
|
||||
});
|
||||
el.controller('$ionicScroll').scrollView.__clientHeight = 199;
|
||||
expect(dataSource.options.heightGetter()).toBe(199);
|
||||
});
|
||||
it('should work with user-inputted percentage height', function() {
|
||||
var el = setup('collection-repeat="a in b" collection-item-height="\'23%\'"');
|
||||
el.controller('$ionicScroll').scrollView.__clientHeight = 300;
|
||||
expect(dataSource.options.heightGetter()).toEqual(0.23 * 300);
|
||||
});
|
||||
it('should work with user-inputted percentage width', function() {
|
||||
var el = setup('collection-repeat="a in b" collection-item-width="\'23%\'"', {
|
||||
scrollingX: true,
|
||||
scrollingY: false
|
||||
}
|
||||
function activeItems() {
|
||||
return items()
|
||||
.filter(function(item) {
|
||||
return item.isShown;
|
||||
})
|
||||
.sort(function(a, b) {
|
||||
return a.primaryPos + a.secondaryPos > b.primaryPos + b.secondaryPos ? 1 : -1;
|
||||
});
|
||||
el.controller('$ionicScroll').scrollView.__clientWidth = 300;
|
||||
expect(dataSource.options.widthGetter()).toEqual(0.23 * 300);
|
||||
}
|
||||
function activeItemContents() {
|
||||
return activeItems().map(function(item) {
|
||||
return item.node.innerHTML.trim();
|
||||
});
|
||||
});
|
||||
}
|
||||
function activeItemIds() {
|
||||
return activeItems().map(function(item) {
|
||||
return item.id;
|
||||
});
|
||||
}
|
||||
|
||||
it('should error if list is not an array and is truthy', function() {
|
||||
var el = setup('collection-repeat="item in items" collection-item-height="50"');
|
||||
it('should error with direction="xy" parent', function() {
|
||||
expect(function() {
|
||||
el.scope().$apply('items = "string"');
|
||||
}).toThrow();
|
||||
expect(function() {
|
||||
el.scope().$apply('items = 123');
|
||||
}).toThrow();
|
||||
expect(function() {
|
||||
el.scope().$apply('items = {}');
|
||||
setup(10, '', {
|
||||
options: { scrollingX: true, scrollingY: true }
|
||||
});
|
||||
}).toThrow();
|
||||
});
|
||||
|
||||
it('should rerender on list change', function() {
|
||||
var el = setup('collection-repeat="item in items" collection-item-height="50"');
|
||||
var scrollView = el.controller('$ionicScroll').scrollView;
|
||||
spyOn(scrollView, 'resize');
|
||||
dataSource.setData.reset();
|
||||
repeatManager.resize.reset();
|
||||
|
||||
el.scope().$apply('items = [ 1,2,3 ]');
|
||||
expect(dataSource.setData).toHaveBeenCalledWith(el.scope().items, [], []);
|
||||
expect(repeatManager.resize.callCount).toBe(1);
|
||||
expect(scrollView.resize.callCount).toBe(1);
|
||||
el.scope().$apply('items = null');
|
||||
expect(dataSource.setData).toHaveBeenCalledWith(null, [], []);
|
||||
expect(repeatManager.resize.callCount).toBe(2);
|
||||
expect(scrollView.resize.callCount).toBe(2);
|
||||
});
|
||||
|
||||
it('should rerender on window resize', function() {
|
||||
var el = setup('collection-repeat="item in items" collection-item-height="50"');
|
||||
var scrollView = el.controller('$ionicScroll').scrollView;
|
||||
spyOn(scrollView, 'resize');
|
||||
dataSource.setData.reset();
|
||||
repeatManager.resize.reset();
|
||||
|
||||
el.scope().items = [1,2,3];
|
||||
|
||||
ionic.trigger('resize', { target: window });
|
||||
expect(dataSource.setData).toHaveBeenCalledWith(el.scope().items, [], []);
|
||||
expect(repeatManager.resize.callCount).toBe(1);
|
||||
expect(scrollView.resize.callCount).toBe(1);
|
||||
});
|
||||
|
||||
it('should rerender on scrollCtrl resize', inject(function($timeout) {
|
||||
var el = setup('collection-repeat="item in items" collection-item-height="50"');
|
||||
var scrollCtrl = el.controller('$ionicScroll');
|
||||
repeatManager.resize.reset();
|
||||
|
||||
scrollCtrl.resize();
|
||||
$timeout.flush();
|
||||
expect(repeatManager.resize.callCount).toBe(1);
|
||||
it('should error without proper collection-repeat expression', inject(function($compile, $rootScope) {
|
||||
expect(function() {
|
||||
$compile('<ion-content>' +
|
||||
'<div collection-repeat="bad"></div>' +
|
||||
'</ion-content>')($rootScope);
|
||||
}).toThrow();
|
||||
}));
|
||||
|
||||
it('$destroy', function() {
|
||||
var el = setup('collection-repeat="item in items" collection-item-height="50"');
|
||||
dataSource.destroy = jasmine.createSpy('dataSourceDestroy');
|
||||
repeatManager.destroy = jasmine.createSpy('repeatManagerDestroy');
|
||||
spyOn(ionic, 'off');
|
||||
|
||||
el.scope().$destroy();
|
||||
expect(dataSource.destroy).toHaveBeenCalled();
|
||||
expect(repeatManager.destroy).toHaveBeenCalled();
|
||||
expect(ionic.off).toHaveBeenCalledWith('resize', jasmine.any(Function), window);
|
||||
it('should destroy', inject(function($compile, $rootScope) {
|
||||
var scope = $rootScope.$new();
|
||||
var content = $compile('<ion-content>' +
|
||||
'<div collection-repeat="item in items"></div>' +
|
||||
'</ion-content>')(scope);
|
||||
$rootScope.$apply();
|
||||
content.triggerHandler('scroll.init');
|
||||
scope.$destroy();
|
||||
}));
|
||||
|
||||
describe('horizontal static list', function() {
|
||||
beforeEach(function() {
|
||||
setup(10, 'item-height="100%" item-width="30"', {
|
||||
options: {
|
||||
scrollingX: true,
|
||||
scrollingY: false
|
||||
},
|
||||
__clientWidth: 80,
|
||||
__clientHeight: 25
|
||||
});
|
||||
});
|
||||
it('should show initial screen of items', function() {
|
||||
expect(activeItems().length).toBe(3);
|
||||
expect(activeItemContents()).toEqual(['0','1','2'])
|
||||
});
|
||||
it('should switch out as you scroll', function() {
|
||||
expect(activeItems().length).toBe(3);
|
||||
expect(activeItemContents()).toEqual(['0','1','2'])
|
||||
expect(activeItemIds()).toEqual(['item_0','item_1','item_2']);
|
||||
|
||||
// Item 0 gets sent down to the bottom after scrolling past it
|
||||
scrollTo(31);
|
||||
expect(activeItems().length).toBe(3);
|
||||
expect(activeItemContents()).toEqual(['1','2','3'])
|
||||
expect(activeItemIds()).toEqual(['item_1','item_2','item_0']);
|
||||
|
||||
// Item 1 gets sent down
|
||||
scrollTo(61);
|
||||
expect(activeItems().length).toBe(3);
|
||||
expect(activeItemContents()).toEqual(['2','3','4'])
|
||||
expect(activeItemIds()).toEqual(['item_2','item_0','item_1']);
|
||||
});
|
||||
it('should start with the same items when resizing', inject(function($window) {
|
||||
scrollTo(31);
|
||||
scrollTo(61);
|
||||
|
||||
expect(activeItems().length).toBe(3);
|
||||
expect(activeItemContents()).toEqual(['2','3','4'])
|
||||
expect(activeItemIds()).toEqual(['item_2','item_0','item_1']);
|
||||
|
||||
scrollView.__clientWidth = 50;
|
||||
scrollView.__clientHeight = 40;
|
||||
angular.element($window).triggerHandler('resize');
|
||||
|
||||
expect(activeItems().length).toBe(2);
|
||||
expect(activeItemContents()).toEqual(['2','3'])
|
||||
expect(activeItemIds()).toEqual(['item_2','item_0']);
|
||||
}));
|
||||
});
|
||||
|
||||
describe('vertical static list', function() {
|
||||
beforeEach(function() {
|
||||
setup(10);
|
||||
});
|
||||
|
||||
it('should show initial screen of items', function() {
|
||||
expect(activeItems().length).toBe(5);
|
||||
expect(activeItemContents()).toEqual(['0','1','2','3','4'])
|
||||
});
|
||||
|
||||
it('should switch out as you scroll', function() {
|
||||
expect(activeItems().length).toBe(5);
|
||||
expect(activeItemContents()).toEqual(['0','1','2','3','4'])
|
||||
expect(activeItemIds()).toEqual(['item_0','item_1','item_2','item_3','item_4']);
|
||||
|
||||
// Item 0 gets sent down to the bottom after scrolling past it
|
||||
scrollTo(26);
|
||||
expect(activeItems().length).toBe(5);
|
||||
expect(activeItemContents()).toEqual(['1','2','3','4','5'])
|
||||
expect(activeItemIds()).toEqual(['item_1','item_2','item_3','item_4','item_0']);
|
||||
|
||||
// Item 1 gets sent down
|
||||
scrollTo(51);
|
||||
expect(activeItems().length).toBe(5);
|
||||
expect(activeItemContents()).toEqual(['2','3','4','5','6'])
|
||||
expect(activeItemIds()).toEqual(['item_2','item_3','item_4','item_0','item_1']);
|
||||
|
||||
// scroll to bottom incrementally
|
||||
// items are traded our until it's the first case again
|
||||
scrollTo(76);
|
||||
scrollTo(101);
|
||||
scrollTo(126);
|
||||
expect(activeItems().length).toBe(5);
|
||||
expect(activeItemContents()).toEqual(['5','6','7','8','9'])
|
||||
expect(activeItemIds()).toEqual(['item_0','item_1','item_2','item_3','item_4']);
|
||||
});
|
||||
|
||||
it('should start with the same items when resizing', inject(function($window) {
|
||||
setup(10);
|
||||
scrollTo(26);
|
||||
scrollTo(51);
|
||||
|
||||
expect(activeItems().length).toBe(5);
|
||||
expect(activeItemContents()).toEqual(['2','3','4','5','6'])
|
||||
expect(activeItemIds()).toEqual(['item_2','item_3','item_4','item_0','item_1']);
|
||||
|
||||
scrollView.__clientWidth = 200;
|
||||
scrollView.__clientHeight = 40;
|
||||
angular.element($window).triggerHandler('resize');
|
||||
|
||||
expect(activeItems().length).toBe(2);
|
||||
expect(activeItemContents()).toEqual(['2','3'])
|
||||
expect(activeItemIds()).toEqual(['item_2','item_3']);
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -1,262 +0,0 @@
|
||||
describe('$collectionDataSource service', function() {
|
||||
|
||||
beforeEach(module('ionic'));
|
||||
|
||||
function setup(options, template, dataSourceOptions) {
|
||||
var dataSource;
|
||||
inject(function($rootScope, $compile, $collectionDataSource) {
|
||||
options = angular.extend({
|
||||
scope: $rootScope.$new(),
|
||||
transcludeParent: angular.element('<div>'),
|
||||
keyExpr: 'key',
|
||||
listExpr: 'list',
|
||||
heightGetter: function() {
|
||||
return 1;
|
||||
},
|
||||
widthGetter: function() {
|
||||
return 1;
|
||||
}
|
||||
}, options || {});
|
||||
options.transcludeFn = options.transcludeFn || function(scope, cb) {
|
||||
cb( $compile(template || '<div>')(scope) );
|
||||
};
|
||||
dataSource = new $collectionDataSource(options);
|
||||
dataSource.dataStartIndex = 0;
|
||||
dataSource.beforeSiblings = [];
|
||||
dataSource.afterSiblings = [];
|
||||
if (dataSourceOptions && dataSourceOptions.afterSiblings) {
|
||||
dataSource.afterSiblings = dataSourceOptions.afterSiblings;
|
||||
}
|
||||
});
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
it('should have properties', inject(function($collectionDataSource) {
|
||||
var source = setup({
|
||||
scope: 1,
|
||||
transcludeFn: 2,
|
||||
transcludeParent: 3,
|
||||
keyExpr: 4,
|
||||
listExpr: 5,
|
||||
heightGetter: 7,
|
||||
widthGetter: 8
|
||||
});
|
||||
expect(source.scope).toBe(1);
|
||||
expect(source.transcludeFn).toBe(2);
|
||||
expect(source.transcludeParent).toBe(3);
|
||||
expect(source.keyExpr).toBe(4);
|
||||
expect(source.listExpr).toBe(5);
|
||||
expect(source.heightGetter).toBe(7);
|
||||
expect(source.widthGetter).toBe(8);
|
||||
}));
|
||||
|
||||
it('.calculateDataDimensions()', function() {
|
||||
function widthGetter(scope, locals) {
|
||||
return locals.$index + locals.item + 'w';
|
||||
}
|
||||
function heightGetter(scope, locals) {
|
||||
return locals.$index + locals.item + 'h';
|
||||
}
|
||||
var source = setup({
|
||||
keyExpr: 'item',
|
||||
widthGetter: widthGetter,
|
||||
heightGetter: heightGetter
|
||||
});
|
||||
source.data = ['a', 'b', 'c'];
|
||||
expect(source.dimensions).toEqual([]);
|
||||
source.calculateDataDimensions();
|
||||
expect(source.dimensions[0]).toEqual({
|
||||
width: '0aw',
|
||||
height: '0ah'
|
||||
});
|
||||
expect(source.dimensions[1]).toEqual({
|
||||
width: '1bw',
|
||||
height: '1bh'
|
||||
});
|
||||
expect(source.dimensions[2]).toEqual({
|
||||
width: '2cw',
|
||||
height: '2ch'
|
||||
});
|
||||
});
|
||||
|
||||
describe('.createItem()', function() {
|
||||
it('should return item with new scope and transclude', function() {
|
||||
var source = setup();
|
||||
|
||||
var item = source.createItem();
|
||||
|
||||
expect(item.scope.$parent).toBe(source.scope);
|
||||
|
||||
expect(item.element).toBeTruthy();
|
||||
expect(item.element.scope()).toBe(item.scope);
|
||||
|
||||
expect(item.element.parent()[0]).toBe(source.transcludeParent[0]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('.getItem()', function() {
|
||||
it('should return attachedItems[index] if available', function() {
|
||||
var source = setup();
|
||||
var item = {};
|
||||
source.attachedItems['123'] = item;
|
||||
expect(source.getItem('123')).toBe(item);
|
||||
});
|
||||
|
||||
it('should return backupItemsArray item if available, and reconnect the item', function() {
|
||||
var source = setup();
|
||||
var item = {
|
||||
scope: {},
|
||||
};
|
||||
spyOn(ionic.Utils, 'reconnectScope');
|
||||
source.backupItemsArray = [item];
|
||||
expect(source.getItem('123')).toBe(item);
|
||||
expect(ionic.Utils.reconnectScope).toHaveBeenCalledWith(item.scope);
|
||||
});
|
||||
|
||||
it('should last resort create an item', function() {
|
||||
var source = setup();
|
||||
var item = {};
|
||||
spyOn(source, 'createItem').andReturn(item);
|
||||
expect(source.getItem('123')).toBe(item);
|
||||
});
|
||||
});
|
||||
|
||||
describe('.attachItemAtIndex()', function() {
|
||||
it('should return a value with index values set and put in attachedItems', inject(function($rootScope) {
|
||||
var source = setup({
|
||||
keyExpr: 'value'
|
||||
}, null, {afterSiblings:[{
|
||||
width: 50,
|
||||
height: 50,
|
||||
element: angular.element('<div class="tail"></div>'),
|
||||
scope: null,
|
||||
isOutside: true
|
||||
}]});
|
||||
source.data = ['a', 'b', 'c'];
|
||||
source.dimensions = ['a','b','c'];
|
||||
spyOn(source, 'getItem').andCallFake(function() {
|
||||
return { scope: $rootScope.$new() };
|
||||
});
|
||||
|
||||
var item1 = source.attachItemAtIndex(0);
|
||||
expect(item1.scope.value).toEqual('a');
|
||||
expect(item1.scope.$index).toBe(0);
|
||||
expect(item1.scope.$first).toBe(true);
|
||||
expect(item1.scope.$last).toBe(false);
|
||||
expect(item1.scope.$middle).toBe(false);
|
||||
expect(item1.scope.$odd).toBe(false);
|
||||
|
||||
var item2 = source.attachItemAtIndex(1);
|
||||
expect(item2.scope.value).toEqual('b');
|
||||
expect(item2.scope.$index).toBe(1);
|
||||
expect(item2.scope.$first).toBe(false);
|
||||
expect(item2.scope.$last).toBe(false);
|
||||
expect(item2.scope.$middle).toBe(true);
|
||||
expect(item2.scope.$odd).toBe(true);
|
||||
|
||||
var item3 = source.attachItemAtIndex(2);
|
||||
expect(item3.scope.value).toEqual('c');
|
||||
expect(item3.scope.$index).toBe(2);
|
||||
expect(item3.scope.$first).toBe(false);
|
||||
expect(item3.scope.$last).toBe(true);
|
||||
expect(item3.scope.$middle).toBe(false);
|
||||
expect(item3.scope.$odd).toBe(false);
|
||||
|
||||
expect(source.attachedItems).toEqual({
|
||||
0: item1,
|
||||
1: item2,
|
||||
2: item3
|
||||
});
|
||||
|
||||
var item4 = source.attachItemAtIndex(3);
|
||||
|
||||
expect(item4.width).toEqual(50);
|
||||
expect(item4.isOutside).toEqual(true);
|
||||
}));
|
||||
});
|
||||
|
||||
describe('.detachItem()', function() {
|
||||
it('should detach item and add to backup array if there is room', function() {
|
||||
var source = setup();
|
||||
var item = {
|
||||
element: angular.element('<div>'),
|
||||
scope: {},
|
||||
index: 1
|
||||
};
|
||||
source.backupItemsArray = [];
|
||||
source.attachedItems[1] = item;
|
||||
spyOn(ionic.Utils, 'disconnectScope');
|
||||
source.detachItem(item);
|
||||
expect(source.attachedItems).toEqual({});
|
||||
expect(source.backupItemsArray).toEqual([item]);
|
||||
expect(ionic.Utils.disconnectScope).toHaveBeenCalledWith(item.scope);
|
||||
});
|
||||
it('should remove element from parent and disconnectScope if backupItemsArray is full', function() {
|
||||
var source = setup();
|
||||
spyOn(source, 'destroyItem');
|
||||
source.BACKUP_ITEMS_LENGTH = 0;
|
||||
|
||||
var item = { index: 0 };
|
||||
source.attachedItems[item.index] = item;
|
||||
source.detachItem(item);
|
||||
expect(source.destroyItem).toHaveBeenCalledWith(item);
|
||||
expect(source.attachedItems).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
describe('.destroyItem()', function() {
|
||||
it('should remove element and destroy scope', function() {
|
||||
var source = setup();
|
||||
var element = angular.element('<div>');
|
||||
var parent = angular.element('<div>').append(element);
|
||||
var item = {
|
||||
element: element,
|
||||
scope: {}
|
||||
};
|
||||
var destroySpy = item.scope.$destroy = jasmine.createSpy('$destroy');
|
||||
|
||||
expect(element[0].parentNode).toBe(parent[0]);
|
||||
source.destroyItem(item);
|
||||
expect(element[0].parentNode).toBeFalsy();
|
||||
expect(destroySpy).toHaveBeenCalled();
|
||||
expect(item.scope).toBe(null);
|
||||
expect(item.element).toBe(null);
|
||||
});
|
||||
});
|
||||
|
||||
describe('.getLength()', function() {
|
||||
it('should return 0 by default', function() {
|
||||
var source = setup();
|
||||
source.dimensions = null;
|
||||
expect(source.getLength()).toBe(0);
|
||||
});
|
||||
|
||||
it('should return dimensions length', function() {
|
||||
var source = setup();
|
||||
source.dimensions = [1,2,3];
|
||||
expect(source.getLength()).toBe(3);
|
||||
source.dimensions = [];
|
||||
expect(source.getLength()).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('.setData()', function() {
|
||||
it('should set data and calculateDataDimensions()', function() {
|
||||
var source = setup();
|
||||
spyOn(source, 'calculateDataDimensions');
|
||||
|
||||
expect(source.data).toEqual([]);
|
||||
source.setData([1,2,3]);
|
||||
expect(source.data).toEqual([1,2,3]);
|
||||
expect(source.calculateDataDimensions).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should default falsy to empty array', function() {
|
||||
var source = setup();
|
||||
source.data = 'none';
|
||||
source.setData(null);
|
||||
expect(source.data).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
@@ -1,501 +0,0 @@
|
||||
describe('collectionRepeatManager service', function() {
|
||||
beforeEach(module('ionic'));
|
||||
|
||||
var afThrottle;
|
||||
beforeEach(function() {
|
||||
afThrottle = ionic.animationFrameThrottle;
|
||||
ionic.animationFrameThrottle = function(cb) {
|
||||
return function() {
|
||||
cb.apply(this, arguments);
|
||||
};
|
||||
};
|
||||
});
|
||||
afterEach(function() {
|
||||
ionic.animationFrameThrottle = afThrottle;
|
||||
});
|
||||
|
||||
function setup(options, dataSourceOptions, scrollViewOptions) {
|
||||
var manager;
|
||||
inject(function($collectionDataSource, $rootScope, $compile, $collectionRepeatManager) {
|
||||
var dataSource = new $collectionDataSource(angular.extend({
|
||||
scope: $rootScope.$new(),
|
||||
transcludeParent: angular.element('<div>'),
|
||||
transcludeFn: function(scope, cb) {
|
||||
cb($compile('<div></div>')(scope));
|
||||
},
|
||||
keyExpr: 'key',
|
||||
listExpr: 'list',
|
||||
heightGetter: function() {
|
||||
return 1;
|
||||
},
|
||||
widthGetter: function() {
|
||||
return 1;
|
||||
}
|
||||
}, dataSourceOptions || {}));
|
||||
|
||||
var el = angular.element('<div scroll-container>')
|
||||
.append(angular.element('<div scroll-content>'));
|
||||
options = angular.extend({
|
||||
dataSource: dataSource,
|
||||
element: el,
|
||||
scrollView: new ionic.views.Scroll(angular.extend({
|
||||
el: el[0]
|
||||
}, scrollViewOptions || {})),
|
||||
}, options || {});
|
||||
manager = new $collectionRepeatManager(options);
|
||||
});
|
||||
return manager;
|
||||
}
|
||||
|
||||
it('should have properties', function() {
|
||||
var manager = setup();
|
||||
expect(manager.dataSource).toBeTruthy();
|
||||
expect(manager.scrollView).toBeTruthy();
|
||||
expect(manager.element[0]).toBe(manager.scrollView.__container);
|
||||
});
|
||||
|
||||
it('should be isVertical if scrollingY', function() {
|
||||
var manager = setup();
|
||||
expect(manager.scrollView.options.scrollingY).toBe(true);
|
||||
expect(manager.isVertical).toBe(true);
|
||||
});
|
||||
|
||||
it('should be !isVertical if scrollingX', function() {
|
||||
var manager = setup({}, {}, {
|
||||
scrollingX: true,
|
||||
scrollingY: false
|
||||
});
|
||||
expect(manager.scrollView.options.scrollingX).toBe(true);
|
||||
expect(manager.scrollView.options.scrollingY).toBe(false);
|
||||
expect(manager.isVertical).toBe(false);
|
||||
});
|
||||
|
||||
describe('isVertical', function() {
|
||||
|
||||
it('should set getContentHeight', function() {
|
||||
var manager = setup();
|
||||
manager.viewportSize = 55;
|
||||
expect(manager.scrollView.options.getContentHeight()).toBe(55);
|
||||
});
|
||||
|
||||
it('.scrollValue()', function() {
|
||||
var manager = setup();
|
||||
manager.scrollView.__scrollTop = 33;
|
||||
expect(manager.scrollValue()).toBe(33);
|
||||
});
|
||||
|
||||
it('.scrollMaxValue()', function() {
|
||||
var manager = setup();
|
||||
manager.scrollView.__maxScrollTop = 123;
|
||||
expect(manager.scrollMaxValue()).toBe(123);
|
||||
});
|
||||
|
||||
it('.scrollSize()', function() {
|
||||
var manager = setup();
|
||||
manager.scrollView.__clientHeight = 12;
|
||||
expect(manager.scrollSize()).toBe(12);
|
||||
});
|
||||
|
||||
it('.secondaryScrollSize()', function() {
|
||||
var manager = setup();
|
||||
manager.scrollView.__clientWidth = 999;
|
||||
expect(manager.secondaryScrollSize()).toBe(999);
|
||||
});
|
||||
|
||||
it('.transformString()', function() {
|
||||
var manager = setup();
|
||||
expect(manager.transformString(3,6)).toBe('translate3d(6px,3px,0)');
|
||||
});
|
||||
|
||||
it('.primaryDimension()', function() {
|
||||
var manager = setup();
|
||||
expect(manager.primaryDimension({height: 100})).toBe(100);
|
||||
});
|
||||
|
||||
it('.secondaryDimension()', function() {
|
||||
var manager = setup();
|
||||
expect(manager.secondaryDimension({width: 99})).toBe(99);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('!isVertical', function() {
|
||||
|
||||
it('should set getContentWidth', function() {
|
||||
var manager = setup({}, {}, { scrollingX: true, scrollingY: false });
|
||||
manager.viewportSize = 55;
|
||||
expect(manager.scrollView.options.getContentWidth()).toBe(55);
|
||||
});
|
||||
|
||||
it('.scrollValue()', function() {
|
||||
var manager = setup({}, {}, { scrollingX: true, scrollingY: false });
|
||||
manager.scrollView.__scrollLeft = 33;
|
||||
expect(manager.scrollValue()).toBe(33);
|
||||
});
|
||||
|
||||
it('.scrollMaxValue()', function() {
|
||||
var manager = setup({}, {}, { scrollingX: true, scrollingY: false });
|
||||
manager.scrollView.__maxScrollLeft = 123;
|
||||
expect(manager.scrollMaxValue()).toBe(123);
|
||||
});
|
||||
|
||||
it('.scrollSize()', function() {
|
||||
var manager = setup({}, {}, { scrollingX: true, scrollingY: false });
|
||||
manager.scrollView.__clientWidth = 12;
|
||||
expect(manager.scrollSize()).toBe(12);
|
||||
});
|
||||
|
||||
it('.secondaryScrollSize()', function() {
|
||||
var manager = setup({}, {}, { scrollingX: true, scrollingY: false });
|
||||
manager.scrollView.__clientHeight = 999;
|
||||
expect(manager.secondaryScrollSize()).toBe(999);
|
||||
});
|
||||
|
||||
it('.transformString()', function() {
|
||||
var manager = setup({}, {}, { scrollingX: true, scrollingY: false });
|
||||
expect(manager.transformString(3,6)).toBe('translate3d(3px,6px,0)');
|
||||
});
|
||||
|
||||
it('.primaryDimension()', function() {
|
||||
var manager = setup({}, {}, { scrollingX: true, scrollingY: false });
|
||||
expect(manager.primaryDimension({width: 100})).toBe(100);
|
||||
});
|
||||
|
||||
it('.secondaryDimension()', function() {
|
||||
var manager = setup({}, {}, { scrollingX: true, scrollingY: false });
|
||||
expect(manager.secondaryDimension({height: 99})).toBe(99);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('.calculateDimensions()', function() {
|
||||
it('should work with 1 item per space', function() {
|
||||
var manager = setup();
|
||||
manager.dataSource.dimensions = [
|
||||
{ width: 100, height: 20 },
|
||||
{ width: 100, height: 30 },
|
||||
{ width: 100, height: 40 },
|
||||
{ width: 100, height: 50 }
|
||||
];
|
||||
manager.secondaryScrollSize = function() {
|
||||
return 100;
|
||||
};
|
||||
var result = manager.calculateDimensions().dimensions;
|
||||
expect(result[0].primarySize).toBe(20);
|
||||
expect(result[0].secondarySize).toBe(100);
|
||||
expect(result[0].primaryPos).toBe(0);
|
||||
expect(result[0].secondaryPos).toBe(0);
|
||||
|
||||
expect(result[1].primarySize).toBe(30);
|
||||
expect(result[1].secondarySize).toBe(100);
|
||||
expect(result[1].primaryPos).toBe(20);
|
||||
expect(result[1].secondaryPos).toBe(0);
|
||||
|
||||
expect(result[2].primarySize).toBe(40);
|
||||
expect(result[2].secondarySize).toBe(100);
|
||||
expect(result[2].primaryPos).toBe(50);
|
||||
expect(result[2].secondaryPos).toBe(0);
|
||||
|
||||
expect(result[3].primarySize).toBe(50);
|
||||
expect(result[3].secondarySize).toBe(100);
|
||||
expect(result[3].primaryPos).toBe(90);
|
||||
expect(result[3].secondaryPos).toBe(0);
|
||||
});
|
||||
it('should work with a grid', function() {
|
||||
var manager = setup();
|
||||
manager.dataSource.dimensions = [
|
||||
{ width: 30, height: 30 },
|
||||
{ width: 35, height: 30 },
|
||||
{ width: 40, height: 30 },
|
||||
{ width: 30, height: 30 },
|
||||
{ width: 20, height: 30 },
|
||||
{ width: 35, height: 30 },
|
||||
];
|
||||
manager.secondaryScrollSize = function() {
|
||||
return 90;
|
||||
};
|
||||
var result = manager.calculateDimensions().dimensions;
|
||||
expect(result[0].primarySize).toBe(30);
|
||||
expect(result[0].secondarySize).toBe(30);
|
||||
expect(result[0].primaryPos).toBe(0);
|
||||
expect(result[0].secondaryPos).toBe(0);
|
||||
|
||||
expect(result[1].primarySize).toBe(30);
|
||||
expect(result[1].secondarySize).toBe(35);
|
||||
expect(result[1].primaryPos).toBe(0);
|
||||
expect(result[1].secondaryPos).toBe(30);
|
||||
|
||||
expect(result[2].primarySize).toBe(30);
|
||||
expect(result[2].secondarySize).toBe(40);
|
||||
expect(result[2].primaryPos).toBe(30);
|
||||
expect(result[2].secondaryPos).toBe(0);
|
||||
|
||||
expect(result[3].primarySize).toBe(30);
|
||||
expect(result[3].secondarySize).toBe(30);
|
||||
expect(result[3].primaryPos).toBe(30);
|
||||
expect(result[3].secondaryPos).toBe(40);
|
||||
|
||||
expect(result[4].primarySize).toBe(30);
|
||||
expect(result[4].secondarySize).toBe(20);
|
||||
expect(result[4].primaryPos).toBe(30);
|
||||
expect(result[4].secondaryPos).toBe(70);
|
||||
|
||||
expect(result[5].primarySize).toBe(30);
|
||||
expect(result[5].secondarySize).toBe(35);
|
||||
expect(result[5].primaryPos).toBe(60);
|
||||
expect(result[5].secondaryPos).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('.resize()', function() {
|
||||
it('should work without data', function() {
|
||||
var manager = setup();
|
||||
spyOn(manager, 'render');
|
||||
spyOn(manager, 'calculateDimensions').andReturn({
|
||||
dimensions: [],
|
||||
beforeSize: 0,
|
||||
totalSize: 0
|
||||
});
|
||||
spyOn(manager, 'setCurrentIndex');
|
||||
manager.resize();
|
||||
expect(manager.dimensions).toEqual([]);
|
||||
expect(manager.viewportSize).toBe(0);
|
||||
expect(manager.setCurrentIndex).toHaveBeenCalledWith(0);
|
||||
expect(manager.render).toHaveBeenCalledWith(true);
|
||||
});
|
||||
it('should work with data', function() {
|
||||
var manager = setup();
|
||||
spyOn(manager, 'calculateDimensions').andReturn({
|
||||
dimensions: [{
|
||||
primaryPos: 100, primarySize: 30
|
||||
}],
|
||||
beforeSize: 0,
|
||||
totalSize: 130
|
||||
});
|
||||
manager.resize();
|
||||
expect(manager.dataSource.transcludeParent[0].style.height).toBe('130px');
|
||||
expect(manager.viewportSize).toBe(130);
|
||||
});
|
||||
});
|
||||
|
||||
describe('.setCurrentIndex()', function() {
|
||||
it('without prev or next', function() {
|
||||
var manager = setup();
|
||||
spyOn(manager.dataSource, 'getLength').andReturn(0);
|
||||
manager.setCurrentIndex(0);
|
||||
expect(manager.currentIndex).toBe(0);
|
||||
expect(manager.hasPrevIndex).toBe(false);
|
||||
expect(manager.previousPos).toBeFalsy();
|
||||
expect(manager.hasNextIndex).toBe(false);
|
||||
expect(manager.nextPos).toBeFalsy();
|
||||
});
|
||||
|
||||
it('with next', function() {
|
||||
var manager = setup();
|
||||
spyOn(manager.dataSource, 'getLength').andReturn(2);
|
||||
manager.dimensions = [{ primaryPos: 0 ,primarySize: 25}, { primaryPos: 25, primarySize: 35 }];
|
||||
manager.setCurrentIndex(0);
|
||||
expect(manager.currentIndex).toBe(0);
|
||||
expect(manager.hasPrevIndex).toBe(false);
|
||||
expect(manager.previousPos).toBeFalsy();
|
||||
expect(manager.hasNextIndex).toBe(true);
|
||||
expect(manager.nextPos).toBe(25);
|
||||
});
|
||||
|
||||
it('with prev', function() {
|
||||
var manager = setup();
|
||||
spyOn(manager.dataSource, 'getLength').andReturn(2);
|
||||
manager.dimensions = [{ primaryPos: 0 , primarySize: 25 }, { primaryPos: 25, primarySize: 25 }];
|
||||
manager.setCurrentIndex(1);
|
||||
expect(manager.currentIndex).toBe(1);
|
||||
expect(manager.hasPrevIndex).toBe(true);
|
||||
expect(manager.previousPos).toBe(0);
|
||||
expect(manager.hasNextIndex).toBe(false);
|
||||
expect(manager.nextPos).toBeFalsy();
|
||||
});
|
||||
|
||||
it('with next and prev', function() {
|
||||
var manager = setup();
|
||||
spyOn(manager.dataSource, 'getLength').andReturn(3);
|
||||
manager.dimensions = [{ primarySize: 25, primaryPos: 0 }, { primarySize: 25, primaryPos: 25 }, { primarySize: 25, primaryPos: 50 }];
|
||||
manager.setCurrentIndex(1);
|
||||
expect(manager.currentIndex).toBe(1);
|
||||
expect(manager.hasPrevIndex).toBe(true);
|
||||
expect(manager.previousPos).toBe(0);
|
||||
expect(manager.hasNextIndex).toBe(true);
|
||||
expect(manager.nextPos).toBe(50);
|
||||
});
|
||||
});
|
||||
|
||||
describe('.renderScroll()', function() {
|
||||
it('should pass the values to __$callback', function() {
|
||||
var manager = setup();
|
||||
spyOn(manager.scrollView, '__$callback');
|
||||
manager.renderScroll(1, 2, 3, 4);
|
||||
expect(manager.scrollView.__$callback).toHaveBeenCalledWith(1, 2, 3, 4);
|
||||
});
|
||||
});
|
||||
|
||||
describe('.renderIfNeeded()', function() {
|
||||
it('should render if >= nextPos', function() {
|
||||
var manager = setup();
|
||||
spyOn(manager, 'render');
|
||||
manager.hasNextIndex = true;
|
||||
manager.nextPos = 30;
|
||||
manager.renderIfNeeded(20);
|
||||
expect(manager.render).not.toHaveBeenCalled();
|
||||
manager.renderIfNeeded(30);
|
||||
expect(manager.render).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should render if < previousPos', function() {
|
||||
var manager = setup();
|
||||
spyOn(manager, 'render');
|
||||
manager.hasPrevIndex = true;
|
||||
manager.previousPos = 50;
|
||||
manager.renderIfNeeded(60);
|
||||
expect(manager.render).not.toHaveBeenCalled();
|
||||
manager.renderIfNeeded(50);
|
||||
expect(manager.render).not.toHaveBeenCalled();
|
||||
manager.renderIfNeeded(49);
|
||||
expect(manager.render).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('.getIndexForScrollValue()', function() {
|
||||
it('should scroll until it finds right position', function() {
|
||||
var manager = setup();
|
||||
manager.dimensions = [
|
||||
{ primaryPos: 0 },
|
||||
{ primaryPos: 100 },
|
||||
{ primaryPos: 200 },
|
||||
{ primaryPos: 300 },
|
||||
{ primaryPos: 400 },
|
||||
{ primaryPos: 500 }
|
||||
];
|
||||
expect(manager.getIndexForScrollValue(3, 50)).toBe(1);
|
||||
expect(manager.getIndexForScrollValue(1, 450)).toBe(4);
|
||||
//bounds
|
||||
expect(manager.getIndexForScrollValue(0, 1000)).toBe(5);
|
||||
expect(manager.getIndexForScrollValue(2, -100)).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('.render()', function() {
|
||||
|
||||
it('currentIndex >= length should remove all and return', function() {
|
||||
var manager = setup();
|
||||
manager.renderedItems = {'a':1, 'b':1};
|
||||
spyOn(manager, 'removeItem');
|
||||
spyOn(manager.dataSource, 'getLength').andReturn(0);
|
||||
manager.currentIndex = 1;
|
||||
manager.render();
|
||||
expect(manager.removeItem).toHaveBeenCalledWith('a');
|
||||
expect(manager.removeItem).toHaveBeenCalledWith('b');
|
||||
});
|
||||
it('shouldRedrawAll should remove all', function() {
|
||||
var manager = setup();
|
||||
manager.renderedItems = {'a':1, 'b':1};
|
||||
manager.currentIndex = 0;
|
||||
spyOn(manager, 'removeItem');
|
||||
manager.render(true);
|
||||
expect(manager.removeItem).toHaveBeenCalledWith('a');
|
||||
expect(manager.removeItem).toHaveBeenCalledWith('b');
|
||||
});
|
||||
|
||||
function mockRendering(options) {
|
||||
var manager = setup({}, {
|
||||
keyExpr: 'item',
|
||||
listExpr: 'items',
|
||||
heightGetter: function() {
|
||||
return options.itemHeight;
|
||||
},
|
||||
widthGetter: function() {
|
||||
return options.itemWidth;
|
||||
}
|
||||
});
|
||||
spyOn(manager, 'scrollSize').andReturn(options.scrollHeight);
|
||||
spyOn(manager, 'secondaryScrollSize').andReturn(options.scrollWidth);
|
||||
spyOn(manager, 'renderItem').andCallFake(function(i) {
|
||||
manager.renderedItems[i] = true;
|
||||
});
|
||||
spyOn(manager, 'removeItem').andCallFake(function(i) {
|
||||
delete manager.renderedItems[i];
|
||||
});
|
||||
var data = [];
|
||||
for (var i = 0; i < 100; i++) {
|
||||
data.push(i);
|
||||
}
|
||||
manager.dataSource.setData(data);
|
||||
return manager;
|
||||
}
|
||||
|
||||
// it('should render the first items that fit on screen', function() {
|
||||
// var manager = mockRendering({
|
||||
// itemWidth: 3,
|
||||
// itemHeight: 20,
|
||||
// scrollWidth: 10,
|
||||
// scrollHeight: 100
|
||||
// });
|
||||
// manager.resize(); //triggers render
|
||||
|
||||
// //it should render (items that fit * items per row) with extra row at end
|
||||
// expect(Object.keys(manager.renderedItems).length).toBe(24);
|
||||
// for (var i = 0; i < 20; i++) {
|
||||
// expect(manager.renderedItems[i]).toBe(true);
|
||||
// }
|
||||
// expect(manager.renderedItems[20]).toBeUndefined();
|
||||
// });
|
||||
|
||||
// it('should render items in the middle of the screen', function() {
|
||||
// var manager = mockRendering({
|
||||
// itemWidth: 3,
|
||||
// itemHeight: 20,
|
||||
// scrollWidth: 10,
|
||||
// scrollHeight: 100
|
||||
// });
|
||||
// spyOn(manager, 'scrollValue').andReturn(111);
|
||||
// manager.resize();
|
||||
// var startIndex = 17;
|
||||
// var bufferStartIndex = 14; //one row of buffer before the start
|
||||
// var bufferEndIndex = 37; //start + 17 + 6
|
||||
|
||||
// expect(Object.keys(manager.renderedItems).length).toBe(24);
|
||||
// for (var i = bufferStartIndex; i <= bufferEndIndex; i++) {
|
||||
// expect(manager.renderedItems[i]).toBe(true);
|
||||
// }
|
||||
// expect(manager.renderedItems[bufferStartIndex - 1]).toBeUndefined();
|
||||
// expect(manager.renderedItems[bufferEndIndex + 1]).toBeUndefined();
|
||||
// });
|
||||
});
|
||||
|
||||
describe('.renderItem()', function() {
|
||||
it('should attachItemAtIndex and set the element transform', function() {
|
||||
var manager = setup();
|
||||
var item = {
|
||||
element: angular.element('<div>')
|
||||
};
|
||||
spyOn(item.element, 'css');
|
||||
spyOn(manager.dataSource, 'attachItemAtIndex').andReturn(item);
|
||||
manager.renderItem(0, 33, 44);
|
||||
expect(manager.dataSource.attachItemAtIndex).toHaveBeenCalledWith(0);
|
||||
expect(item.element.css).toHaveBeenCalledWith(
|
||||
ionic.CSS.TRANSFORM,
|
||||
manager.transformString(33, 44)
|
||||
);
|
||||
expect(manager.renderedItems[0]).toBe(item);
|
||||
});
|
||||
});
|
||||
|
||||
describe('.removeItem()', function() {
|
||||
it('should detachItem', function() {
|
||||
var manager = setup();
|
||||
var item = {};
|
||||
manager.renderedItems[0] = item;
|
||||
spyOn(manager, 'removeItem').andCallThrough();
|
||||
spyOn(manager.dataSource, 'detachItem');
|
||||
manager.removeItem(0);
|
||||
expect(manager.renderedItems).toEqual({});
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user