describe('tooltip directive', function() { var $rootScope, $compile, $document, $timeout; beforeEach(module('ui.bootstrap.tooltip')); beforeEach(module('template/tooltip/tooltip-popup.html')); beforeEach(module('template/tooltip/tooltip-template-popup.html')); beforeEach(module('template/tooltip/tooltip-html-popup.html')); beforeEach(inject(function(_$rootScope_, _$compile_, _$document_, _$timeout_) { $rootScope = _$rootScope_; $compile = _$compile_; $document = _$document_; $timeout = _$timeout_; })); beforeEach(function() { jasmine.addMatchers({ toHaveOpenTooltips: function(util, customEqualityTesters) { return { compare: function(actual, noOfOpened) { var ttipElements = actual.find('div.tooltip'); noOfOpened = noOfOpened || 1; var result = { pass: util.equals(ttipElements.length, noOfOpened, customEqualityTesters) }; if (result.message) { result.message = 'Expected "' + angular.mock.dump(ttipElements) + '" not to have "' + ttipElements.length + '" opened tooltips.'; } else { result.message = 'Expected "' + angular.mock.dump(ttipElements) + '" to have "' + ttipElements.length + '" opened tooltips.'; } return result; } }; } }); }); function compileTooltip(ttipMarkup) { var fragment = $compile('
' + ttipMarkup + '
')($rootScope); $rootScope.$digest(); return fragment; } function closeTooltip(hostEl, triggerEvt, shouldNotFlush) { trigger(hostEl, triggerEvt || 'mouseleave'); hostEl.scope().$$childTail.$digest(); if (!shouldNotFlush) { $timeout.flush(); } } function trigger(element, evt) { evt = new Event(evt); element[0].dispatchEvent(evt); element.scope().$$childTail.$digest(); } describe('basic scenarios with default options', function() { it('shows default tooltip on mouse enter and closes on mouse leave', function() { var fragment = compileTooltip('Trigger here'); trigger(fragment.find('span'), 'mouseenter'); expect(fragment).toHaveOpenTooltips(); closeTooltip(fragment.find('span')); expect(fragment).not.toHaveOpenTooltips(); }); it('should not show a tooltip when its content is empty', function() { var fragment = compileTooltip(''); trigger(fragment.find('span'), 'mouseenter'); expect(fragment).not.toHaveOpenTooltips(); }); it('should not show a tooltip when its content becomes empty', function() { $rootScope.content = 'some text'; var fragment = compileTooltip(''); trigger(fragment.find('span'), 'mouseenter'); expect(fragment).toHaveOpenTooltips(); $rootScope.content = ''; $rootScope.$digest(); $timeout.flush(); expect(fragment).not.toHaveOpenTooltips(); }); it('should update tooltip when its content becomes empty', function() { $rootScope.content = 'some text'; var fragment = compileTooltip(''); $rootScope.content = ''; $rootScope.$digest(); trigger(fragment.find('span'), 'mouseenter'); expect(fragment).not.toHaveOpenTooltips(); }); }); describe('option by option', function() { var tooltipTypes = { 'tooltip': 'uib-tooltip="tooltip text"', 'tooltip-html': 'uib-tooltip-html="tooltipSafeHtml"', 'tooltip-template': 'uib-tooltip-template="\'tooltipTextUrl\'"' }; beforeEach(inject(function($sce, $templateCache) { $rootScope.tooltipText = 'tooltip text'; $rootScope.tooltipSafeHtml = $sce.trustAsHtml('tooltip text'); $templateCache.put('tooltipTextUrl', [200, 'tooltip text', {}]); })); angular.forEach(tooltipTypes, function(html, key) { describe(key, function() { describe('placement', function() { it('can specify an alternative, valid placement', function() { var fragment = compileTooltip('Trigger here'); trigger(fragment.find('span'), 'mouseenter'); var ttipElement = fragment.find('div.tooltip'); expect(fragment).toHaveOpenTooltips(); expect(ttipElement).toHaveClass('left'); closeTooltip(fragment.find('span')); expect(fragment).not.toHaveOpenTooltips(); }); }); describe('class', function() { it('can specify a custom class', function() { var fragment = compileTooltip('Trigger here'); trigger(fragment.find('span'), 'mouseenter'); var ttipElement = fragment.find('div.tooltip'); expect(fragment).toHaveOpenTooltips(); expect(ttipElement).toHaveClass('custom'); closeTooltip(fragment.find('span')); expect(fragment).not.toHaveOpenTooltips(); }); }); }); }); }); it('should show even after close trigger is called multiple times - issue #1847', function() { var fragment = compileTooltip('Trigger here'); trigger(fragment.find('span'), 'mouseenter'); expect(fragment).toHaveOpenTooltips(); closeTooltip(fragment.find('span'), null, true); // Close trigger is called again before timer completes // The close trigger can be called any number of times (even after close has already been called) // since users can trigger the hide triggers manually. closeTooltip(fragment.find('span'), null, true); expect(fragment).toHaveOpenTooltips(); trigger(fragment.find('span'), 'mouseenter'); expect(fragment).toHaveOpenTooltips(); $timeout.flush(); expect(fragment).toHaveOpenTooltips(); }); it('should hide even after show trigger is called multiple times', function() { var fragment = compileTooltip('Trigger here'); trigger(fragment.find('span'), 'mouseenter'); trigger(fragment.find('span'), 'mouseenter'); closeTooltip(fragment.find('span')); expect(fragment).not.toHaveOpenTooltips(); }); it('should not show tooltips element is disabled (button) - issue #3167', function() { var fragment = compileTooltip(''); trigger(fragment.find('button'), 'mouseenter'); expect(fragment).toHaveOpenTooltips(); trigger(fragment.find('button'), 'click'); $timeout.flush(); // One needs to flush deferred functions before checking there is no tooltip. expect(fragment).not.toHaveOpenTooltips(); }); }); /* Deprecation tests below */ describe('tooltip deprecation', function() { beforeEach(module('ui.bootstrap.tooltip')); beforeEach(module('template/tooltip/tooltip-popup.html')); beforeEach(module('template/tooltip/tooltip-template-popup.html')); beforeEach(module('template/tooltip/tooltip-html-popup.html')); describe('tooltip', function() { it('should suppress warning', function() { module(function($provide) { $provide.value('$tooltipSuppressWarning', true); }); inject(function($compile, $log, $rootScope) { spyOn($log, 'warn'); var element = '
Trigger here
'; element = $compile(element)($rootScope); $rootScope.$digest(); expect($log.warn.calls.count()).toBe(0); }); }); it('should give warning by default', inject(function($compile, $log, $rootScope) { spyOn($log, 'warn'); var element = '
Trigger here
'; element = $compile(element)($rootScope); $rootScope.$digest(); expect($log.warn.calls.count()).toBe(1); expect($log.warn.calls.argsFor(0)).toEqual(['$tooltip is now deprecated. Use $uibTooltip instead.']); })); }); describe('tooltip html', function() { var elm, elmBody, elmScope, tooltipScope; function trigger(element, evt) { evt = new Event(evt); element[0].dispatchEvent(evt); element.scope().$$childTail.$digest(); } it('should suppress warning', function() { module(function($provide) { $provide.value('$tooltipSuppressWarning', true); }); inject(function($compile, $log, $rootScope, $sce) { spyOn($log, 'warn'); $rootScope.html = 'I say: Hello!'; $rootScope.safeHtml = $sce.trustAsHtml($rootScope.html); elmBody = angular.element('
Selector Text
'); $compile(elmBody)($rootScope); $rootScope.$digest(); elm = elmBody.find('span'); elmScope = elm.scope(); tooltipScope = elmScope.$$childTail; trigger(elm, 'mouseenter'); tooltipScope.$digest(); expect($log.warn.calls.count()).toBe(0); }); }); it('should give warning by default', inject(function($compile, $log, $rootScope, $sce) { spyOn($log, 'warn'); $rootScope.html = 'I say: Hello!'; $rootScope.safeHtml = $sce.trustAsHtml($rootScope.html); elmBody = angular.element('
Selector Text
'); $compile(elmBody)($rootScope); $rootScope.$digest(); elm = elmBody.find('span'); elmScope = elm.scope(); tooltipScope = elmScope.$$childTail; trigger(elm, 'mouseenter'); tooltipScope.$digest(); expect($log.warn.calls.count()).toBe(2); expect($log.warn.calls.argsFor(0)).toEqual(['$tooltip is now deprecated. Use $uibTooltip instead.']); expect($log.warn.calls.argsFor(1)).toEqual(['tooltip-html-popup is now deprecated. Use uib-tooltip-html-popup instead.']); })); }); });