Files
ionic-framework/test/unit/angular/directive/tabs.unit.js
Adam Bradley 39951ca99a refactor(): navigation improvements, Angular 1.3
#### Refactor:

* **Navigation:** Refactored navigation for improved performance,
reduce DOM manipulations, increase transition FPS, cached views,
smoother transitions, platform specific transitions with added
configurable controls for transition animation and direction.
* **Cached Views:** Previously as a user navigated an app, each leaving
view’s element and scope would be destroyed. If the same view was
accessed again then the app would have to recreate the element. Views
can now be cached to improve performance. When a view is navigated away
from, its element is left in the DOM, and its scope is disconnected
from the cycle. When navigating to a view which is already cached, its
scope is reconnected, and the existing element which was left in the
DOM becomes the active view. This also allows for scroll position of
previous views to be maintained (without skippy jumps). Config
variables can be used to disable view caching (set to 0), or change the
maximum number of views to cache.
* **Angular v1.3:** Upgraded Ionic’s to work with Angular v1.3. In
general Ionic just works with the upgrade, but the required change was
that animations in v1.3 uses promise, whereas in v1.2 animations used
callbacks.

#### Features:

* **Platform Specific Transitions:** Transitions between views now
default to the transition style appropriate for each platform. For
example, iOS will move forward by transitioning the entering view from
right to center, and the leaving view from center to left. However,
Android will transition with the entering view going from bottom to
center, covering the previous view, which remains stationary. Platform
transitions are automatically applied by default, but config variables
and custom CSS allows these defaults to be easily overridden.
* **Override Transition Type and Direction:** As a user navigates the
app, Ionic automatically applies the appropriate transition type for
the platform, and the direction the user is navigating. However, both
can be overridden in numerous ways: config variable, view attribute,
stateProvider property, or attribute on the button/link that initiated
the transition.
* **enable-menu-with-back-views:** The `enable-menu-with-back-views`
attribute determines if the side menu is enabled when the back button
is showing. When set to `false`, any buttons/links with the
`menuToggle` directive will be hidden, and the user cannot swipe to
open the menu. When going back to the root page of the side menu (the
page without a back button visible), then any menuToggle buttons will
show again, and menus will be enabled again.
* **menuClose:** Closes a side menu which is currently opened.
Additionally, the menuClose directive will now cause transitions to not
animate between views while the menu is being closed.
* **ionNavBackButton:** The back button icon and text will
automatically update to platform config defaults, such as adjusting to
the platform back icon. To take advantage of this, the
`ionNavBackButton` directive now should be empty, such as
`<ion-nav-back-button></ion-nav-back-button>`. The back button can
still be fully customized like it could before, but without any inner
content it knows to style using platform configs.
* **navBar button primary/secondary sides:** Primary and secondary
sides are now the recommended values for the `side` attribute, such as
`<ion-nav-buttons side="primary">`. Primary buttons generally map to
the left side of the header, and secondary buttons are generally on the
right side. However, their exact locations are platform specific. For
example, in iOS the primary buttons are on the far left of the header,
and secondary buttons are on the far right, with the header title
centered between them. For Android however, both groups of buttons are
on the far right of the header, with the header title aligned left.
Recommendation is to always use `primary` and `secondary` so buttons
correctly map to the side familiar to users of a platform. However, in
cases where buttons should always be on an exact side, both `left` and
`right` sides are still available.
* **navDirection:** An attribute directive that sets the direction
which the nav view transition should animate.
* **navTransition:** An attribute directive that sets the transition
type which the nav view transition should use when it animates. Using
`none` will disable an animation.

#### Breaking Changes:

* **Animation CSS:** The CSS for view transitions have changed. This is
a breaking change only if Ionic apps had customized Ionic’s animation
CSS.
* **$ionicPlatformDefaults:** Platform config variables are no longer
in the $ionicPlatformDefaults constant, but within `$ionicConfig`.
* **$ionicViewService:** In the navigation refactoring,
$ionicViewService was split up into two factories, `$ionicViewSwitcher`
and `$ionicHistory`. The `$ionicHistory` is largely what
`$ionicViewService`, but between the two factories there is a better
separation of concerns for improved testing.
* **navClear:** The navClear directive was created to do what the new
side menu `enable-menu-with-back-views` attribute accomplishes.
Additionally, the new `navTransition` and `navDirection` directives are
more useful and granular than the navClear directive.
* **scrollView.rememberScrollPosition:** This method has been removed
since it is no longer needed with cached views.

#### Deprecated:

* **ionView.title:** The `ionView` directive used the `title`
attribute, but this can cause the tooltip to show up on desktop
browsers. The `title` attribute will still work for backwards
compatibility, but we now recommend using `view-title`, such as
`<ion-view view-title=”My Title”>`.
* **ionNavView animation attribute removed:** The animation attribute
is no longer used for nav views. Instead use `$ionicConfig`.
* **ionNavBar animation attribute removed:** The animation attribute is
no longer used for nav bars. Instead use `$ionicConfig`.
2014-11-11 14:43:10 -06:00

640 lines
20 KiB
JavaScript

describe('tabs', function() {
describe('$ionicTabs controller', function() {
beforeEach(module('ionic'));
var ctrl, scope;
beforeEach(inject(function($rootScope, $controller) {
scope = $rootScope.$new();
ctrl = $controller('$ionicTabs', {
$scope: scope,
$element: angular.element('<div>')
});
}));
it('.getTabIndex should return indexOf tab', function() {
expect(ctrl.selectedIndex()).toBe(-1);
var tab1 = {}, tab2 = {};
ctrl.add(tab1);
ctrl.add(tab2);
// .add does not automatically select the first anymore
expect(ctrl.selectedIndex()).toBe(-1);
ctrl.select(tab1);
expect(ctrl.selectedIndex()).toBe(0);
ctrl.select(0);
expect(ctrl.selectedIndex()).toBe(0);
ctrl.select(tab2);
expect(ctrl.selectedIndex()).toBe(1);
ctrl.deselect(tab2);
expect(ctrl.selectedIndex()).toBe(-1);
});
it('.add should add tab and NOT select if empty, & set historyId', inject(function($ionicHistory) {
var tab1 = {};
var tab2 = {};
spyOn($ionicHistory, 'registerHistory');
spyOn(ctrl, 'select');
ctrl.add(tab1);
ctrl.select(tab1);
expect($ionicHistory.registerHistory).toHaveBeenCalledWith(tab1);
expect(ctrl.tabs).toEqual([tab1]);
expect(ctrl.select).toHaveBeenCalledWith(tab1);
ctrl.select.reset();
ctrl.add(tab2);
expect($ionicHistory.registerHistory).toHaveBeenCalledWith(tab2);
expect(ctrl.tabs).toEqual([tab1, tab2]);
expect(ctrl.select).not.toHaveBeenCalled();
}));
it('.remove should remove tab and reselect', function() {
var tab1 = {}, tab2 = {}, tab3 = {};
ctrl.add(tab1);
ctrl.add(tab2);
ctrl.add(tab3);
ctrl.select(tab1);
expect(ctrl.selectedTab()).toBe(tab1);
ctrl.select(tab3);
expect(ctrl.selectedTab()).toBe(tab3);
ctrl.remove(tab3);
expect(ctrl.selectedTab()).toBe(tab2);
expect(ctrl.tabs.indexOf(tab3)).toBe(-1);
ctrl.remove(tab1);
expect(ctrl.selectedTab()).toBe(tab2);
expect(ctrl.tabs.indexOf(tab1)).toBe(-1);
ctrl.remove(tab2);
expect(ctrl.selectedTab()).toBe(null);
expect(ctrl.tabs.indexOf(tab2)).toBe(-1);
expect(ctrl.tabs.length).toBe(0);
});
it('.deselect should unselect if visible', function() {
var tab1 = {
$tabSelected: true,
onDeselect: jasmine.createSpy('deselect'),
};
ctrl.deselect(tab1);
expect(tab1.$tabSelected).toBe(false);
expect(tab1.onDeselect).toHaveBeenCalled();
expect(ctrl.selectedTab()).toBe(null);
});
it('.deselect should do nothing if not visible', function() {
var tab1 = {
$tabSelected: false,
onDeselect: jasmine.createSpy('deselect')
};
spyOn(ctrl, 'selectedTab').andCallFake(function() {
return 'foo';
});
ctrl.deselect(tab1);
expect(tab1.$tabSelected).toBe(false);
expect(tab1.onDeselect).not.toHaveBeenCalled();
expect(ctrl.selectedTab()).toBe('foo');
});
it('.select should allow number', function() {
var tab1 = {}, tab2 = {};
ctrl.add(tab1);
ctrl.add(tab2);
ctrl.select(tab2);
expect(ctrl.selectedTab()).toBe(tab2);
ctrl.select(0);
expect(ctrl.selectedTab()).toBe(tab1);
ctrl.select(1);
expect(ctrl.selectedTab()).toBe(tab2);
ctrl.select(tab1);
expect(ctrl.selectedTab()).toBe(tab1);
});
it('.select on selected tab should do nothing or go to history root', inject(function($ionicHistory) {
spyOn($ionicHistory, 'goToHistoryRoot');
var tab = { $historyId: '1' };
ctrl.add(tab);
ctrl.select(tab);
expect(ctrl.selectedTab()).toBe(tab);
//Do nothing unless emit event is passed
ctrl.select(tab);
expect($ionicHistory.goToHistoryRoot).not.toHaveBeenCalled();
ctrl.select(tab, true);
expect($ionicHistory.goToHistoryRoot).toHaveBeenCalledWith(tab.$historyId);
}));
it('.select should deselect all other tabs and set selected', function() {
var tab1 = {}, tab2 = {
onSelect: jasmine.createSpy('select')
};
ctrl.add(tab1);
ctrl.add(tab2);
spyOn(ctrl, 'deselect');
ctrl.select(tab2);
expect(ctrl.deselect).toHaveBeenCalledWith(tab1);
expect(ctrl.deselect).toHaveBeenCalledWith(tab2);
expect(tab2.$tabSelected).toBe(true);
expect(ctrl.selectedTab()).toBe(tab2);
expect(tab2.onSelect).toHaveBeenCalled();
});
it('.select with true should emit event', function() {
var tab1 = {};
var tab2 = {};
var tab3 = {
navViewName: 'viewName',
hasNavView: true,
title: 'Super Tab',
url: 'ionicframework.com',
uiSref: 'drifty'
};
var eName, eData;
spyOn(scope, '$emit').andCallFake(function(eventName, data) {
eName = eventName;
eData = data;
});
ctrl.add(tab1);
ctrl.add(tab2);
ctrl.add(tab3);
ctrl.select(tab2);
expect(scope.$emit).not.toHaveBeenCalled();
ctrl.select(tab3, true);
expect(scope.$emit).toHaveBeenCalled();
expect(eName).toBe('$ionicHistory.change');
expect(eData).toEqual({
type: 'tab',
tabIndex: 2,
historyId: tab3.$historyId,
navViewName: tab3.navViewName,
hasNavView: tab3.hasNavView,
title: tab3.title,
url: tab3.href,
uiSref: tab3.uiSref
});
});
});
describe('ionTabs directive', function() {
beforeEach(module('ionic'));
function setup(attrs, content) {
var element;
inject(function($compile, $rootScope) {
var scope = $rootScope.$new();
element = $compile('<ion-tabs ' + (attrs||'') + '>' + (content||'') + '</ion-tabs>')(scope);
scope.$apply();
});
return element;
}
it('should register with given handle and deregister on destroy', inject(function($ionicTabsDelegate) {
var deregisterSpy = jasmine.createSpy('deregister');
spyOn($ionicTabsDelegate, '_registerInstance').andCallFake(function() {
return deregisterSpy;
});
var el = setup('delegate-handle="banana"');
expect($ionicTabsDelegate._registerInstance)
.toHaveBeenCalledWith(el.controller('ionTabs'), 'banana');
expect(deregisterSpy).not.toHaveBeenCalled();
el.scope().$destroy();
expect(deregisterSpy).toHaveBeenCalled();
}));
it('should $hasTabs and $hasTabsTop', function() {
TestUtil.setPlatform('ios');
var el = setup();
var scope = el.scope();
expect(scope.$hasTabs).toBe(true);
expect(scope.$hasTabsTop).toBe(false);
el.addClass('tabs-top');
scope.$apply();
expect(scope.$hasTabs).toBe(false);
expect(scope.$hasTabsTop).toBe(true);
el.removeClass('tabs-top');
scope.$apply();
expect(scope.$hasTabs).toBe(true);
expect(scope.$hasTabsTop).toBe(false);
});
it('should transclude content with same scope', function() {
var el = setup('', '<div class="content"></div>');
expect(el[0].querySelector('.tabs .content')).toBeTruthy();
});
});
describe('ionicTab controller', function() {
beforeEach(module('ionic'));
function setup(attrs) {
var ctrl;
inject(function($controller, $rootScope) {
ctrl = $controller('$ionicTab', {
$scope: $rootScope.$new(),
$attrs: attrs || {}
});
});
return ctrl;
}
it('.hrefMatchesState', inject(function($location) {
spyOn($location, 'path').andReturn('/a/b/c');
var attr = {};
var ctrl = setup(attr);
expect(ctrl.hrefMatchesState()).toBeFalsy();
attr.href = 'a';
expect(ctrl.hrefMatchesState()).toBe(false);
attr.href = '/a';
expect(ctrl.hrefMatchesState()).toBe(true);
attr.href = '#/a';
expect(ctrl.hrefMatchesState()).toBe(true);
attr.href = '#/a/b/c';
expect(ctrl.hrefMatchesState()).toBe(true);
attr.href = '#/a/b/c/';
expect(ctrl.hrefMatchesState()).toBe(true);
attr.href = '/a/b/c/';
expect(ctrl.hrefMatchesState()).toBe(true);
attr.href = '/a/b/c/d';
expect(ctrl.hrefMatchesState()).toBe(false);
attr.href = 'something';
expect(ctrl.hrefMatchesState()).toBe(false);
}));
it('.srefMatchesState', inject(function($state) {
spyOn($state, 'includes').andReturn(111);
var attr = {};
var ctrl = setup(attr);
expect(ctrl.srefMatchesState()).toBeFalsy();
expect($state.includes).not.toHaveBeenCalled();
//We won't unit test $state.includes, only that it was called
attr.uiSref = 'abc';
expect(ctrl.srefMatchesState()).toBe(111);
expect($state.includes).toHaveBeenCalledWith('abc');
$state.includes.reset();
attr.uiSref = 'def({ param: "value" })';
ctrl.srefMatchesState();
expect($state.includes).toHaveBeenCalledWith('def');
}));
it('.navNameMatchesState', inject(function($ionicHistory) {
spyOn($ionicHistory, 'isCurrentStateNavView').andReturn(123);
var ctrl = setup();
expect(ctrl.navNameMatchesState()).toBeFalsy();
ctrl.navViewName = 'foo';
expect(ctrl.navNameMatchesState()).toBe(123);
expect($ionicHistory.isCurrentStateNavView).toHaveBeenCalledWith('foo');
}));
});
describe('ionTab directive', function() {
var tabDoesMatch;
beforeEach(module('ionic', function($controllerProvider) {
$controllerProvider.register('$ionicTab', function($scope) {
this.$scope = $scope;
this.tabMatchesState = jasmine.createSpy('tabMatchesState')
.andCallFake(function() {
return tabDoesMatch;
});
});
}));
var tabsCtrl, tabsEl, scope, tabEl;
function setup(attrs, content) {
inject(function($compile, $rootScope) {
tabsEl = angular.element(
'<ion-tabs>' +
'<ion-tab '+(attrs||'')+'>'+(content||'')+'</ion-tab>' +
'</ion-tabs>'
);
tabEl = tabsEl.find('ion-tab');
$compile(tabsEl)($rootScope.$new());
$rootScope.$apply();
tabsCtrl = tabsEl.data('$ionTabsController');
scope = tabsEl.scope();
spyOn(tabsCtrl, 'remove');
});
}
it('should not initially compile content until selected', inject(function($compile, $rootScope) {
var el = $compile('<ion-tabs>' +
'<ion-tab></ion-tab>' +
'<ion-tab><div ng-init="$root.elephant = \'banana\'"></div></ion-tab>' +
'</ion-tabs>')($rootScope);
$rootScope.$apply();
expect($rootScope.elephant).toBeUndefined();
el.controller('ionTabs').select(1);
$rootScope.$apply();
expect($rootScope.elephant).toBe('banana');
}));
it('should add itself to tabsCtrl and remove on $destroy', function() {
setup();
var tab = tabsCtrl.tabs[0];
tab.$destroy();
expect(tabsCtrl.remove).toHaveBeenCalledWith(tab);
});
it('should compile a <ion-tab-nav> with all of the relevant attrs', function() {
setup('title="{{a}}" icon-on="{{b}}" icon-off="{{c}}" badge="d" badge-style="{{e}}" class="{{f}}" ng-click="click" hidden="{{g}}"');
angular.extend(tabEl.scope(), {
a: 'title',
b: 'on',
c: 'off',
d: 6,
e: 'badger',
f: 'someClass',
g: true
});
tabEl.scope().$apply();
var navItem = angular.element(tabsEl[0].querySelector('.tab-item'));
expect(navItem.isolateScope().title).toEqual('title');
expect(navItem.isolateScope().iconOn).toEqual('on');
expect(navItem.isolateScope().iconOff).toEqual('off');
expect(navItem.isolateScope().badge).toEqual(6);
expect(navItem.isolateScope().badgeStyle).toEqual('badger');
expect(navItem[0].className).toMatch(/someClass/);
expect(navItem.attr('ng-click')).toEqual('click');
expect(navItem.isolateScope().hidden).toEqual('true');
angular.extend(tabEl.scope(), {
a: 'title2',
b: 'on2',
c: 'off2',
d: 7,
e: 'badger2',
f: 'someClass2',
g: false
});
tabEl.scope().$apply();
expect(navItem.isolateScope().title).toEqual('title2');
expect(navItem.isolateScope().iconOn).toEqual('on2');
expect(navItem.isolateScope().iconOff).toEqual('off2');
expect(navItem.isolateScope().badge).toEqual(7);
expect(navItem.isolateScope().badgeStyle).toEqual('badger2');
expect(navItem[0].className).toMatch(/someClass2/);
expect(navItem.isolateScope().hidden).toEqual('false');
expect(navItem.parent()[0]).toBe(tabsCtrl.$tabsElement[0]);
});
it('should remove <ion-tab-nav> on $destroy', function() {
setup();
var navItem = angular.element(tabsEl[0].querySelector('.tab-item'));
var navItemScope = navItem.isolateScope();
spyOn(navItemScope, '$destroy');
tabsCtrl.tabs[0].$destroy();
expect(navItemScope.$destroy).toHaveBeenCalled();
expect(navItem.parent().length).toBe(0);
});
it('should not set navViewName by default', function() {
setup();
expect(tabEl.controller('ionTab').navViewName).toBeUndefined();
});
it('should set navViewName if a child ion-nav-view', inject(function($ionicHistory, $rootScope) {
setup('', '<ion-nav-view name="banana"></ion-nav-view>');
spyOn(tabsCtrl, 'select');
var tab = tabsCtrl.tabs[0];
expect(tabEl.controller('ionTab').navViewName).toBe('banana');
}));
it('should call tabMatchesState on compile and if match select', function() {
setup();
expect(tabEl.controller('ionTab').tabMatchesState).toHaveBeenCalled();
tabDoesMatch = true;
setup();
expect(tabEl.controller('ionTab').tabMatchesState).toHaveBeenCalled();
});
it('should call selectIfMatchesState on $stateChangeSuccess', function() {
setup('', '<ion-nav-view name="banana"></ion-nav-view>');
var tabMatchesState = tabEl.controller('ionTab').tabMatchesState;
tabMatchesState.reset();
spyOn(tabsCtrl, 'select');
tabDoesMatch = false;
tabEl.scope().$broadcast('$stateChangeSuccess');
expect(tabMatchesState).toHaveBeenCalled();
expect(tabsCtrl.select).not.toHaveBeenCalled();
tabMatchesState.reset();
tabDoesMatch = true;
tabEl.scope().$broadcast('$stateChangeSuccess');
expect(tabMatchesState).toHaveBeenCalled();
expect(tabsCtrl.select).toHaveBeenCalledWith(tabEl.scope(), false);
});
it('should transclude on $tabSelected=true', function() {
setup('', '<div class="inside-content"></div>');
var tab = tabsCtrl.tabs[0];
tabsCtrl.deselect(tab);
tab.$apply();
spyOn(tab, '$broadcast');
var tabContent = tabsEl.find('.inside-content');
expect(tabContent.length).toBe(1);
expect(tabContent.attr('nav-view')).toBe('cached');
tab.$apply('$tabSelected = true');
tabContent = tabsEl.find('.inside-content');
expect(tabContent.parent()[0]).toBe(tabsCtrl.$element[0]);
var contentScope = tabContent.scope();
expect(tabContent.length).toBe(1);
spyOn(tabContent, 'remove');
spyOn(contentScope, '$destroy');
tab.$broadcast.reset();
tab.$apply('$tabSelected = false');
expect(tabContent.attr('nav-view')).toBe('cached');
});
});
describe('ionTabNav directive', function() {
beforeEach(module('ionic'));
var tabsCtrl, tabCtrl;
function setup(attrs) {
tabsCtrl = {
select: jasmine.createSpy('select'),
_selectedTab: null,
selectedTab: function() {
return this._selectedTab;
}
};
tabCtrl = {
$scope: {}
};
var element;
inject(function($compile, $rootScope) {
var scope = $rootScope.$new();
element = angular.element('<ion-tab-nav ' + (attrs||'') + '></ion-tab-nav>');
element.data('$ionTabsController', tabsCtrl);
element.data('$ionTabController', tabCtrl);
element = $compile(element)(scope);
scope.$apply();
});
return element;
}
it('should set tabs css from $ionicConfig', inject(function($rootScope, $compile, $ionicConfig){
$ionicConfig.tabs.position('top');
$ionicConfig.tabs.style('striped');
var scope = $rootScope.$new();
var element = angular.element('<ion-tabs></ion-tabs>');
element = $compile(element)(scope);
expect(element.hasClass('tabs-striped')).toBe(true);
expect(element.hasClass('tabs-top')).toBe(true);
}));
it('should remove title attribute', function() {
var el = setup('title="something"');
expect(el[0].hasAttribute('title')).toBe(false);
expect(el.isolateScope().title).toBe('something');
});
// These next two are REALLY specific unit tests,
// but also are really really vital pieces of code
it('.isTabActive should be correct', function() {
var el = setup();
expect(el.isolateScope().isTabActive()).toBe(false);
tabsCtrl._selectedTab = tabCtrl.$scope;
expect(el.isolateScope().isTabActive()).toBe(true);
tabsCtrl._selectedTab = null;
expect(el.isolateScope().isTabActive()).toBe(false);
});
it('.selectTab should be correct and preventDefault', function() {
var el = setup();
var preventSpy = jasmine.createSpy('preventDefault');
el.isolateScope().selectTab({
preventDefault: preventSpy
});
expect(preventSpy).toHaveBeenCalled();
expect(tabsCtrl.select).toHaveBeenCalledWith(tabCtrl.$scope, true);
});
it('should fallback to icon for icon-on and icon-off', function() {
var el = setup('icon=1');
expect(el.isolateScope().getIconOn()).toBe('1');
el.isolateScope().iconOn = 2;
expect(el.isolateScope().getIconOn()).toBe(2);
el.isolateScope().iconOn = null;
expect(el.isolateScope().getIconOn()).toBe('1');
expect(el.isolateScope().getIconOff()).toBe('1');
el.isolateScope().iconOff = 3;
expect(el.isolateScope().getIconOff()).toBe(3);
el.isolateScope().iconOff = null;
expect(el.isolateScope().getIconOff()).toBe('1');
});
it('should select tab on click by default', function() {
var el = setup();
el.triggerHandler('click');
expect(tabsCtrl.select).toHaveBeenCalledWith(tabCtrl.$scope, true);
});
it('should use ngClick if defined', function() {
var el = setup('ng-click="doSomething()"');
el.scope().doSomething = jasmine.createSpy('doSomething');
el.triggerHandler('click');
expect(tabsCtrl.select).not.toHaveBeenCalled();
expect(el.scope().doSomething).toHaveBeenCalled();
});
it('should have title and only title', function() {
var el = setup('title="<b>hi, {{name}}!</b>"');
expect(el.find('.tab-title').html()).toBe('<b>hi, !</b>');
expect(el.find('.icon.on').length).toBe(0);
expect(el.find('.icon.off').length).toBe(0);
el.scope().$apply('name = "joe"');
expect(el.find('.tab-title').html()).toBe('<b>hi, joe!</b>');
});
it('should change icon class with just icon', function() {
//In this case, icon-on and icon-off should be same
var el = setup('icon={{icon}}');
el.scope().icon="superIcon";
el.scope().$apply();
el.isolateScope().isTabActive = function() { return true; };
el.isolateScope().$apply();
expect(el.find('.icon.superIcon').length).toBe(1);
el.isolateScope().isTabActive = function() { return false; };
el.isolateScope().$apply();
expect(el.find('.icon.superIcon').length).toBe(1);
});
it('should change classes based on active', function() {
var el = setup('icon-on="{{true}}" icon-off="{{false}}"');
el.isolateScope().isTabActive = function() { return true; };
el.isolateScope().$apply();
expect(el.hasClass('tab-item-active')).toBe(true);
expect(el.find('.icon.true').length).toBe(1);
expect(el.find('.icon.false').length).toBe(0);
el.isolateScope().isTabActive = function() { return false; };
el.isolateScope().$apply();
expect(el.hasClass('tab-item-active')).toBe(false);
expect(el.find('.icon.true').length).toBe(0);
expect(el.find('.icon.false').length).toBe(1);
});
it('shouldnt has-badge without badge', function() {
var el = setup();
expect(el.hasClass('has-badge')).toBe(false);
expect(el.find('.badge').length).toBe(0);
});
it('should have badge', function() {
var el = setup('badge="\'badger\'" badge-style="super-style"');
expect(el.hasClass('has-badge')).toBe(true);
expect(el.find('.badge.super-style').text()).toBe('badger');
});
});
});