UNPKG

angular-ui-router-tabs

Version:

Idiot-proof tab panes with route support using Angular.js + Bootstrap 3 + UI Router.

284 lines (206 loc) 7.03 kB
'use strict'; var forceResolveFailure = false; var loadData = function() { if (forceResolveFailure) { throw new Error(); } return []; }; beforeEach(function() { module('ui.router.tabs'); module('ui.router'); module('ui.bootstrap'); module(function($stateProvider) { $stateProvider .state('menu', { url: '/menu', resolve: { data: loadData } }) .state('menu.route1', { url: '/route1', resolve: { data: loadData } }).state('menu.route2', { url: '/route2', resolve: { data: loadData } }) .state('notabs', { url: '/notabs', resolve: { data: loadData } }); }); this.sandbox = sinon.sandbox.create(); forceResolveFailure = false; }); afterEach(function() { this.sandbox.restore(); }); describe('Directive : UI Router : Tabs', function() { var root_scope, isolate_scope, scope, directive_scope, view, element, state, sandbox, spy; var createView, get_current_state, get_current_params; var $ngView; var params = {}; beforeEach(inject(function($rootScope, $state, $templateCache) { createView = function(html, scope) { element = angular.element(view); inject(function($compile) { $ngView = $compile(html)(scope); }); scope.$digest(); directive_scope = $ngView.isolateScope(); return $ngView; }; scope = $rootScope.$new(); state = $state; root_scope = $rootScope; get_current_state = function() { return state.current.name; }; get_current_params = function() { return state.params; }; scope.tabConfiguration = [{ heading: 'Heading 1A', route: 'menu.route1' }, { heading: 'Heading 1B', route: 'menu.route1', params: { a: 5 } }, { heading: 'Heading 2', route: 'menu.route2', params: params }]; view = '<tabs data="tabConfiguration" type="pills" class="someClass"></tabs>'; sandbox = this.sandbox; })); var renderView = function() { $ngView = createView(view, scope); isolate_scope = $ngView.isolateScope(); spy = sandbox.spy(state, 'go'); }; it('should define the tabs directive with isolated scope', function() { renderView(); expect(directive_scope).toBeDefined(); }); it('should throw an error if no data attribute was specified', function() { renderView(); expect(function() { createView('<tabs></tabs>', scope); }).toThrow('UI Router Tabs: \'data\' attribute not defined, please check documentation for how to use this directive.'); }); it('should throw an error if no data attributes is not an array', function() { renderView(); expect(function() { scope.tabConfiguration = {}; createView('<tabs data="tabConfiguration"></tabs>', scope); }).toThrow('UI Router Tabs: \'data\' attribute must be an array of tab data with at least one tab defined.'); }); it('should initialise the tab configuration correctly when defined', function() { renderView(); expect(scope.tabConfiguration).toBeDefined(); expect(directive_scope.tabs).toBeDefined(); expect(scope.tabConfiguration).toEqual(directive_scope.tabs); expect(directive_scope.type).toEqual('pills'); expect(directive_scope.class).toEqual('someClass'); }); it('should route to the correct entry in tabConfiguration array', function() { view = '<tabs data="tabConfiguration"></tabs>'; renderView(); var tabIndex = 2; var route = scope.tabConfiguration[tabIndex].route; state.go(route); scope.$apply(); expect(get_current_state()).toEqual(route); expect(scope.tabConfiguration[tabIndex].active).toBeTruthy(); }); it('should change the route and update the tabs when selecting a different tab', function() { renderView(); var previous_state = get_current_state(); $ngView.find('a').eq(2).click(); scope.$apply(); expect(get_current_state()).not.toEqual(previous_state); }); it('should not change the route or active tab heading if a $stateChangeStart handler cancels the route change', function() { view = '<tabs data="tabConfiguration"></tabs>'; renderView(); var initialTabIndex = 0; var initialRoute = scope.tabConfiguration[initialTabIndex].route; state.go(initialRoute); scope.$apply(); root_scope.$on('$stateChangeStart', function(event) { event.preventDefault(); }); var targetTabIndex = 2; var targetRoute = scope.tabConfiguration[targetTabIndex].route; state.go(targetRoute); scope.$apply(); expect(get_current_state()).toEqual(initialRoute); expect(scope.tabConfiguration[initialTabIndex].active).toBeTruthy(); }); it('should not change the route or active tab heading if a $stateChangeError event triggers during the route change', function() { view = '<tabs data="tabConfiguration"></tabs>'; renderView(); var initialTabIndex = 0; var initialRoute = scope.tabConfiguration[initialTabIndex].route; state.go(initialRoute); scope.$apply(); forceResolveFailure = true; var targetTabIndex = 2; var targetRoute = scope.tabConfiguration[targetTabIndex].route; state.go(targetRoute); scope.$apply(); expect(get_current_state()).toEqual(initialRoute); expect(scope.tabConfiguration[initialTabIndex].active).toBeTruthy(); }); it('should not change the route or active tab heading if a $stateNotFound event triggers during the route change', function() { view = '<tabs data="tabConfiguration"></tabs>'; renderView(); var initialTabIndex = 0; var initialRoute = scope.tabConfiguration[initialTabIndex].route; state.go(initialRoute); scope.$apply(); forceResolveFailure = true; var targetTabIndex = 2; var targetRoute = 'some.invalid.route'; try { state.go(targetRoute); } catch (error) { /* do nothing */ } scope.$apply(); expect(get_current_state()).toEqual(initialRoute); expect(scope.tabConfiguration[initialTabIndex].active).toBeTruthy(); }); it('should not change the route when selecting the current tab', function() { renderView(); $ngView.find('a').eq(0).click(); scope.$apply(); spy.reset(); var previous_state = get_current_state(); $ngView.find('a').eq(0).click(); scope.$apply(); expect(get_current_state()).toEqual(previous_state); expect(spy.notCalled).toBeTruthy(); }); it('should not change the route when the clicked tab is disabled', function() { renderView(); $ngView.find('a').eq(2).click(); scope.$apply(); spy.reset(); var previous_state = get_current_state(); scope.tabConfiguration[0].disable = true; $ngView.find('a').eq(0).click(); scope.$apply(); expect(get_current_state()).toEqual(previous_state); expect(spy.notCalled).toBeTruthy(); }); });