'use strict'; describe('uiSortable', function() { beforeEach(module(function($compileProvider) { if (typeof $compileProvider.debugInfoEnabled === 'function') { $compileProvider.debugInfoEnabled(false); } })); // Ensure the sortable angular module is loaded beforeEach(module('ui.sortable')); beforeEach(module('ui.sortable.testHelper')); var listContent; beforeEach(inject(function (sortableTestHelper) { listContent = sortableTestHelper.listContent; })); describe('Simple use', function() { it('should have a ui-sortable class', function() { inject(function($compile, $rootScope) { var element; element = $compile('')($rootScope); expect(element.hasClass('ui-sortable')).toBeTruthy(); }); }); it('should log that ngModel was not provided', function() { inject(function($compile, $rootScope, $log) { var element; element = $compile('')($rootScope); $rootScope.$apply(function() { $rootScope.items = ['One', 'Two', 'Three']; }); expect($log.info.logs.length).toEqual(1); expect($log.info.logs[0].length).toEqual(2); expect($log.info.logs[0][0]).toEqual('ui.sortable: ngModel not provided!'); }); }); it('should log an error about jQuery dependency', function() { inject(function($compile, $rootScope, $log) { var oldAngularElementFn = angular.element.fn; var mockJQliteFn = $({}, angular.element.fn, true); mockJQliteFn.jquery = null; angular.element.fn = mockJQliteFn; var element; element = $compile('')($rootScope); $rootScope.$apply(function() { $rootScope.items = ['One', 'Two', 'Three']; }); expect($log.error.logs.length).toEqual(1); expect($log.error.logs[0].length).toEqual(1); expect($log.error.logs[0][0]).toEqual('ui.sortable: jQuery should be included before AngularJS!'); angular.element.fn = oldAngularElementFn; }); }); it('should refresh sortable properly after an apply', function() { inject(function($compile, $rootScope, $timeout) { var element; var childScope = $rootScope.$new(); element = $compile('')(childScope); $rootScope.$apply(function() { childScope.items = ['One', 'Two', 'Three']; }); expect(function() { $timeout.flush(); }).not.toThrow(); expect(childScope.items).toEqual(['One', 'Two', 'Three']); expect(childScope.items).toEqual(listContent(element)); }); }); it('should refresh sortable properly after an apply [data-* anotation]', function() { inject(function($compile, $rootScope, $timeout) { var element; var childScope = $rootScope.$new(); element = $compile('')(childScope); $rootScope.$apply(function() { childScope.items = ['One', 'Two', 'Three']; childScope.opts = {}; }); expect(function() { $timeout.flush(); }).not.toThrow(); expect(childScope.items).toEqual(['One', 'Two', 'Three']); expect(childScope.items).toEqual(listContent(element)); }); }); it('should not refresh sortable if destroyed', function() { inject(function($compile, $rootScope, $timeout) { var element; var childScope = $rootScope.$new(); element = $compile('
')(childScope); $rootScope.$apply(function() { childScope.items = ['One', 'Two', 'Three']; }); element.remove(element.firstChild); expect(function() { $timeout.flush(); }).not.toThrow(); }); }); it('should not refresh sortable if destroyed [data-* anotation]', function() { inject(function($compile, $rootScope, $timeout) { var element; var childScope = $rootScope.$new(); element = $compile('
')(childScope); $rootScope.$apply(function() { childScope.items = ['One', 'Two', 'Three']; childScope.opts = {}; }); element.remove(element.firstChild); expect(function() { $timeout.flush(); }).not.toThrow(); }); }); it('should not try to apply options to a destroyed sortable', function() { inject(function($compile, $rootScope, $timeout) { var element; var childScope = $rootScope.$new(); element = $compile('
')(childScope); $rootScope.$apply(function() { childScope.items = ['One', 'Two', 'Three']; childScope.opts = { update: function() {} }; element.remove(element.firstChild); }); expect(function() { $timeout.flush(); }).not.toThrow(); }); }); it('should not try to apply options to a destroyed sortable [data-* anotation]', function() { inject(function($compile, $rootScope, $timeout) { var element; var childScope = $rootScope.$new(); element = $compile('
')(childScope); $rootScope.$apply(function() { childScope.items = ['One', 'Two', 'Three']; childScope.opts = { update: function() {} }; element.remove(element.firstChild); }); expect(function() { $timeout.flush(); }).not.toThrow(); }); }); describe('items option', function() { it('should use a default items that is restricted to ng-repeat items', function() { inject(function($compile, $rootScope, $timeout) { var element; var childScope = $rootScope.$new(); element = $compile('
')(childScope); $rootScope.$digest(); expect(element.find('ul').sortable('option', 'items')).toBe('> [ng-repeat],> [data-ng-repeat],> [x-ng-repeat]'); element.remove(element.firstChild); expect(function() { $timeout.flush(); }).not.toThrow(); }); }); it('should not change items option if given', function() { inject(function($compile, $rootScope, $timeout) { var element; var childScope = $rootScope.$new(); childScope.opts = { items: '> .class' }; element = $compile('
')(childScope); $rootScope.$digest(); expect(element.find('ul').sortable('option', 'items')).toBe('> .class'); element.remove(element.firstChild); expect(function() { $timeout.flush(); }).not.toThrow(); }); }); it('should restrict to ng-items if items is removed after initialization', function() { inject(function($compile, $rootScope, $timeout) { var element; var childScope = $rootScope.$new(); childScope.opts = { items: '> .class' }; element = $compile('
')(childScope); $rootScope.$digest(); $rootScope.$apply(function() { childScope.opts = { items: null }; }); expect(element.find('ul').sortable('option', 'items')).toBe('> [ng-repeat],> [data-ng-repeat],> [x-ng-repeat]'); element.remove(element.firstChild); expect(function() { $timeout.flush(); }).not.toThrow(); }); }); it('should properly reset the value of a deleted option', function() { inject(function($compile, $rootScope, $timeout) { var element; var childScope = $rootScope.$new(); childScope.opts = { opacity: 0.7, placeholder: 'phClass', update: function() { } }; element = $compile('
')(childScope); var $sortableElement = element.find('[data-ui-sortable]'); expect($sortableElement.sortable('option', 'opacity')).toBe(0.7); expect($sortableElement.sortable('option', 'placeholder')).toBe('phClass'); expect(typeof $sortableElement.sortable('option', 'update')).toBe('function'); $rootScope.$digest(); $rootScope.$apply(function() { delete childScope.opts.opacity; }); expect($sortableElement.sortable('option', 'opacity')).toBe(false); expect($sortableElement.sortable('option', 'placeholder')).toBe('phClass'); expect(typeof $sortableElement.sortable('option', 'update')).toBe('function'); $rootScope.$digest(); $rootScope.$apply(function() { childScope.opts = {}; }); expect($sortableElement.sortable('option', 'opacity')).toBe(false); expect($sortableElement.sortable('option', 'placeholder')).toBe(false); expect(typeof $sortableElement.sortable('option', 'update')).toBe('function'); element.remove(element.firstChild); expect(function() { $timeout.flush(); }).not.toThrow(); }); }); it('should not initialize a disabled sortable', function() { inject(function($compile, $rootScope) { var element; var childScope = $rootScope.$new(); spyOn(angular.element.fn, 'sortable'); childScope.items = ['One', 'Two', 'Three']; childScope.opts = { disabled: true }; element = $compile('')(childScope); expect(angular.element.fn.sortable).not.toHaveBeenCalled(); }); }); it('should lazily initialize a latelly enabled sortable (set disabled = false)', function() { inject(function($compile, $rootScope, $timeout) { var element; var childScope = $rootScope.$new(); spyOn(angular.element.fn, 'sortable'); childScope.items = ['One', 'Two', 'Three']; childScope.opts = { disabled: true }; element = $compile('')(childScope); expect(angular.element.fn.sortable).not.toHaveBeenCalled(); $rootScope.$apply(function() { childScope.opts.disabled = false; }); expect(function() { $timeout.flush(); }).not.toThrow(); expect(angular.element.fn.sortable).toHaveBeenCalled(); }); }); it('should lazily initialize a sortable enabled in $timeout (set disabled = false)', function() { inject(function($compile, $rootScope, $timeout) { var element; var childScope = $rootScope.$new(); spyOn(angular.element.fn, 'sortable'); childScope.items = ['One', 'Two', 'Three']; childScope.opts = { disabled: true }; element = $compile('')(childScope); expect(angular.element.fn.sortable).not.toHaveBeenCalled(); $timeout(function () { childScope.opts.disabled = false; }); $timeout(function () { expect(angular.element.fn.sortable).toHaveBeenCalled(); }); expect(function() { $timeout.flush(); }).not.toThrow(); }); }); it('should lazily initialize a latelly enabled sortable (delete disabled option)', function() { inject(function($compile, $rootScope, $timeout) { var element; var childScope = $rootScope.$new(); spyOn(angular.element.fn, 'sortable'); childScope.items = ['One', 'Two', 'Three']; childScope.opts = { disabled: true }; element = $compile('')(childScope); expect(angular.element.fn.sortable).not.toHaveBeenCalled(); $rootScope.$apply(function() { childScope.opts = {}; }); expect(function() { $timeout.flush(); }).not.toThrow(); expect(angular.element.fn.sortable).toHaveBeenCalled(); }); }); it('should lazily initialize a sortable enabled in $timeout (delete disabled option)', function() { inject(function($compile, $rootScope, $timeout) { var element; var childScope = $rootScope.$new(); spyOn(angular.element.fn, 'sortable'); childScope.items = ['One', 'Two', 'Three']; childScope.opts = { disabled: true }; element = $compile('')(childScope); expect(angular.element.fn.sortable).not.toHaveBeenCalled(); expect(function() { $timeout.flush(); }).not.toThrow(); $timeout(function () { childScope.opts = {}; }); $timeout(function () { expect(angular.element.fn.sortable).toHaveBeenCalled(); }); expect(function() { $timeout.flush(); }).not.toThrow(); }); }); }); }); });