4 module('tooltip plugin')
6 test('should be defined on jquery object', function () {
7 var div = $('<div></div>')
8 ok(div.tooltip, 'popover method is defined')
13 // Run all tests in noConflict mode -- it's the only way to ensure that the plugin works in noConflict mode
14 $.fn.bootstrapTooltip = $.fn.tooltip.noConflict()
16 teardown: function () {
17 $.fn.tooltip = $.fn.bootstrapTooltip
18 delete $.fn.bootstrapTooltip
22 test('should provide no conflict', function () {
23 ok(!$.fn.tooltip, 'tooltip was set back to undefined (org value)')
26 test('should return element', function () {
27 var div = $('<div></div>')
28 ok(div.bootstrapTooltip() == div, 'document.body returned')
31 test('should expose default settings', function () {
32 ok(!!$.fn.bootstrapTooltip.Constructor.DEFAULTS, 'defaults is defined')
35 test('should empty title attribute', function () {
36 var tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"></a>').bootstrapTooltip()
37 ok(tooltip.attr('title') === '', 'title attribute was emptied')
40 test('should add data attribute for referencing original title', function () {
41 var tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"></a>').bootstrapTooltip()
42 equal(tooltip.attr('data-original-title'), 'Another tooltip', 'original title preserved in data attribute')
45 test('should add set set aria describedby to the element called on show', function () {
46 var tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"></a>').bootstrapTooltip()
47 .appendTo('#qunit-fixture')
48 .bootstrapTooltip('show')
49 ok(tooltip.attr('aria-describedby'), 'has the right attributes')
50 var id = $('.tooltip').attr('id')
52 ok($('#' + id).length == 1, 'has a unique id')
53 ok($('.tooltip').attr('aria-describedby') === tooltip.attr('id'), 'they match!')
54 ok(tooltip.attr('aria-describedby') !== undefined, 'has the right attributes')
57 test('should remove the aria-describedby attributes on hide', function () {
58 var tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"></a>').bootstrapTooltip()
59 .appendTo('#qunit-fixture')
60 .bootstrapTooltip('show')
61 ok(tooltip.attr('aria-describedby'), 'has the right attributes')
62 tooltip.bootstrapTooltip('hide')
63 ok(!tooltip.attr('aria-describedby'), 'removed the attributes on hide')
66 test('should assign a unique id tooltip element', function () {
67 $('<a href="#" rel="tooltip" title="Another tooltip"></a>')
68 .appendTo('#qunit-fixture')
69 .bootstrapTooltip('show')
70 var id = $('.tooltip').attr('id')
72 ok($('#' + id).length == 1 && id.indexOf('tooltip') === 0, 'generated prefixed and unique tooltip id')
75 test('should place tooltips relative to placement option', function () {
76 $.support.transition = false
77 var tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"></a>')
78 .appendTo('#qunit-fixture')
79 .bootstrapTooltip({ placement: 'bottom' })
80 .bootstrapTooltip('show')
82 ok($('.tooltip').is('.fade.bottom.in'), 'has correct classes applied')
83 tooltip.bootstrapTooltip('hide')
86 test('should allow html entities', function () {
87 $.support.transition = false
88 var tooltip = $('<a href="#" rel="tooltip" title="<b>@fat</b>"></a>')
89 .appendTo('#qunit-fixture')
90 .bootstrapTooltip({ html: true })
91 .bootstrapTooltip('show')
93 ok($('.tooltip b').length, 'b tag was inserted')
94 tooltip.bootstrapTooltip('hide')
95 ok(!$('.tooltip').length, 'tooltip removed')
98 test('should respect custom classes', function () {
99 var tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"></a>')
100 .appendTo('#qunit-fixture')
101 .bootstrapTooltip({ template: '<div class="tooltip some-class"><div class="tooltip-arrow"/><div class="tooltip-inner"/></div>' })
102 .bootstrapTooltip('show')
104 ok($('.tooltip').hasClass('some-class'), 'custom class is present')
105 tooltip.bootstrapTooltip('hide')
106 ok(!$('.tooltip').length, 'tooltip removed')
109 test('should fire show event', function () {
111 $('<div title="tooltip title"></div>')
112 .on('show.bs.tooltip', function () {
113 ok(true, 'show was called')
116 .bootstrapTooltip('show')
119 test('should fire shown event', function () {
121 var tooltip = $('<div title="tooltip title"></div>').appendTo('#qunit-fixture')
123 .on('shown.bs.tooltip', function () {
124 ok(true, 'shown was called')
128 .bootstrapTooltip('show')
131 test('should not fire shown event when default prevented', function () {
133 $('<div title="tooltip title"></div>')
134 .on('show.bs.tooltip', function (e) {
136 ok(true, 'show was called')
139 .on('shown.bs.tooltip', function () {
140 ok(false, 'shown was called')
142 .bootstrapTooltip('show')
145 test('should fire hide event', function () {
147 var tooltip = $('<div title="tooltip title"></div>').appendTo('#qunit-fixture')
149 .on('shown.bs.tooltip', function () {
150 $(this).bootstrapTooltip('hide')
152 .on('hide.bs.tooltip', function () {
153 ok(true, 'hide was called')
157 .bootstrapTooltip('show')
160 test('should fire hidden event', function () {
162 var tooltip = $('<div title="tooltip title"></div>').appendTo('#qunit-fixture')
164 .on('shown.bs.tooltip', function () {
165 $(this).bootstrapTooltip('hide')
167 .on('hidden.bs.tooltip', function () {
168 ok(true, 'hidden was called')
172 .bootstrapTooltip('show')
175 test('should not fire hidden event when default prevented', function () {
177 var tooltip = $('<div title="tooltip title"></div>').appendTo('#qunit-fixture')
179 .on('shown.bs.tooltip', function () {
180 $(this).bootstrapTooltip('hide')
182 .on('hide.bs.tooltip', function (e) {
184 ok(true, 'hide was called')
188 .on('hidden.bs.tooltip', function () {
189 ok(false, 'hidden was called')
191 .bootstrapTooltip('show')
194 test('should not show tooltip if leave event occurs before delay expires', function () {
195 var tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"></a>')
196 .appendTo('#qunit-fixture')
197 .bootstrapTooltip({ delay: 200 })
201 tooltip.trigger('mouseenter')
203 setTimeout(function () {
204 ok(!$('.tooltip').is('.fade.in'), 'tooltip is not faded in')
205 tooltip.trigger('mouseout')
206 setTimeout(function () {
207 ok(!$('.tooltip').is('.fade.in'), 'tooltip is not faded in')
213 test('should not show tooltip if leave event occurs before delay expires, even if hide delay is 0', function () {
214 var tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"></a>')
215 .appendTo('#qunit-fixture')
216 .bootstrapTooltip({ delay: { show: 200, hide: 0 }})
220 tooltip.trigger('mouseenter')
222 setTimeout(function () {
223 ok(!$('.tooltip').is('.fade.in'), 'tooltip is not faded in')
224 tooltip.trigger('mouseout')
225 setTimeout(function () {
226 ok(!$('.tooltip').is('.fade.in'), 'tooltip is not faded in')
232 test('should wait 200 ms before hiding the tooltip', 3, function () {
233 var tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"></a>')
234 .appendTo('#qunit-fixture')
235 .bootstrapTooltip({ delay: { show: 0, hide: 200 }})
239 tooltip.trigger('mouseenter')
241 setTimeout(function () {
242 ok($('.tooltip').is('.fade.in'), 'tooltip is faded in')
243 tooltip.trigger('mouseout')
244 setTimeout(function () {
245 ok($('.tooltip').is('.fade.in'), '100ms:tooltip is still faded in')
246 setTimeout(function () {
247 ok(!$('.tooltip').is('.in'), 'tooltip removed')
254 test('should not hide tooltip if leave event occurs, then tooltip is show immediately again', function () {
255 var tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"></a>')
256 .appendTo('#qunit-fixture')
257 .bootstrapTooltip({ delay: { show: 0, hide: 200 }})
261 tooltip.trigger('mouseenter')
263 setTimeout(function () {
264 ok($('.tooltip').is('.fade.in'), 'tooltip is faded in')
265 tooltip.trigger('mouseout')
266 setTimeout(function () {
267 ok($('.tooltip').is('.fade.in'), '100ms:tooltip is still faded in')
268 tooltip.trigger('mouseenter')
269 setTimeout(function () {
270 ok($('.tooltip').is('.in'), 'tooltip removed')
277 test('should not show tooltip if leave event occurs before delay expires', function () {
278 var tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"></a>')
279 .appendTo('#qunit-fixture')
280 .bootstrapTooltip({ delay: 100 })
282 tooltip.trigger('mouseenter')
283 setTimeout(function () {
284 ok(!$('.tooltip').is('.fade.in'), 'tooltip is not faded in')
285 tooltip.trigger('mouseout')
286 setTimeout(function () {
287 ok(!$('.tooltip').is('.fade.in'), 'tooltip is not faded in')
293 test('should show tooltip if leave event hasn\'t occured before delay expires', function () {
294 var tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"></a>')
295 .appendTo('#qunit-fixture')
296 .bootstrapTooltip({ delay: 150 })
298 tooltip.trigger('mouseenter')
299 setTimeout(function () {
300 ok(!$('.tooltip').is('.fade.in'), 'tooltip is not faded in')
302 setTimeout(function () {
303 ok($('.tooltip').is('.fade.in'), 'tooltip has faded in')
308 test('should destroy tooltip', function () {
309 var tooltip = $('<div/>').bootstrapTooltip().on('click.foo', function () {})
310 ok(tooltip.data('bs.tooltip'), 'tooltip has data')
311 ok($._data(tooltip[0], 'events').mouseover && $._data(tooltip[0], 'events').mouseout, 'tooltip has hover event')
312 ok($._data(tooltip[0], 'events').click[0].namespace == 'foo', 'tooltip has extra click.foo event')
313 tooltip.bootstrapTooltip('show')
314 tooltip.bootstrapTooltip('destroy')
315 ok(!tooltip.hasClass('in'), 'tooltip is hidden')
316 ok(!$._data(tooltip[0], 'bs.tooltip'), 'tooltip does not have data')
317 ok($._data(tooltip[0], 'events').click[0].namespace == 'foo', 'tooltip still has click.foo')
318 ok(!$._data(tooltip[0], 'events').mouseover && !$._data(tooltip[0], 'events').mouseout, 'tooltip does not have any events')
321 test('should show tooltip with delegate selector on click', function () {
322 var div = $('<div><a href="#" rel="tooltip" title="Another tooltip"></a></div>')
323 div.appendTo('#qunit-fixture').bootstrapTooltip({
324 selector: 'a[rel="tooltip"]', trigger: 'click'
326 div.find('a').trigger('click')
327 ok($('.tooltip').is('.fade.in'), 'tooltip is faded in')
330 test('should show tooltip when toggle is called', function () {
331 $('<a href="#" rel="tooltip" title="tooltip on toggle"></a>')
332 .appendTo('#qunit-fixture')
333 .bootstrapTooltip({ trigger: 'manual' })
334 .bootstrapTooltip('toggle')
335 ok($('.tooltip').is('.fade.in'), 'tooltip should be toggled in')
338 test('should hide shown tooltip when toggle is called on tooltip', function () {
339 var tooltip = $('<a href="#" rel="tooltip" title="tooltip on toggle">@ResentedHook</a>')
340 .appendTo('#qunit-fixture')
341 .bootstrapTooltip({ trigger: 'manual' })
342 .bootstrapTooltip('toggle')
343 $('.tooltip', '#qunit-fixture').bootstrapTooltip('toggle')
344 ok($('.tooltip').not('.fade.in'), 'tooltip should be toggled out')
345 tooltip.bootstrapTooltip('hide')
346 $('#qunit-fixture').empty()
349 test('should place tooltips inside the body', function () {
350 var tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"></a>')
351 .appendTo('#qunit-fixture')
352 .bootstrapTooltip({ container: 'body' })
353 .bootstrapTooltip('show')
354 ok($('body > .tooltip').length, 'inside the body')
355 ok(!$('#qunit-fixture > .tooltip').length, 'not found in parent')
356 tooltip.bootstrapTooltip('hide')
359 test('should place tooltip inside window', function () {
360 var container = $('<div />').appendTo('body')
361 .css({ position: 'absolute', width: 200, height: 200, bottom: 0, left: 0 })
362 $('<a href="#" title="Very very very very very very very very long tooltip">Hover me</a>')
363 .css({ position: 'absolute', top: 0, left: 0 })
365 .bootstrapTooltip({ placement: 'top', animate: false })
366 .bootstrapTooltip('show')
370 setTimeout(function () {
371 ok($('.tooltip').offset().left >= 0)
378 test('should place tooltip on top of element', function () {
379 var container = $('<div />').appendTo('body')
380 .css({ position: 'absolute', bottom: 0, left: 0, textAlign: 'right', width: 300, height: 300 })
381 var p = $('<p style="margin-top:200px" />').appendTo(container)
382 var tooltiped = $('<a href="#" title="very very very very very very very long tooltip">Hover me</a>')
383 .css({ marginTop: 200 })
385 .bootstrapTooltip({ placement: 'top', animate: false })
386 .bootstrapTooltip('show')
390 setTimeout(function () {
391 var tooltip = container.find('.tooltip')
394 ok(Math.round(tooltip.offset().top + tooltip.outerHeight()) <= Math.round(tooltiped.offset().top))
399 test('should add position class before positioning so that position-specific styles are taken into account', function () {
400 $('head').append('<style id="test"> .tooltip.right { white-space: nowrap; } .tooltip.right .tooltip-inner { max-width: none; } </style>')
402 var container = $('<div />').appendTo('body')
403 var target = $('<a href="#" rel="tooltip" title="very very very very very very very very long tooltip in one line"></a>')
405 .bootstrapTooltip({ placement: 'right', viewport: null })
406 .bootstrapTooltip('show')
407 var tooltip = container.find('.tooltip')
409 // this is some dumb hack shit because sub pixels in firefox
410 var top = Math.round(target.offset().top + (target[0].offsetHeight / 2) - (tooltip[0].offsetHeight / 2))
411 var top2 = Math.round(tooltip.offset().top)
412 var topDiff = top - top2
413 ok(topDiff <= 1 && topDiff >= -1)
414 target.bootstrapTooltip('hide')
415 $('head #test').remove()
418 test('tooltip title test #1', function () {
419 var tooltip = $('<a href="#" rel="tooltip" title="Simple tooltip" style="display: inline-block; position: absolute; top: 0; left: 0;"></a>')
420 .appendTo('#qunit-fixture')
421 .bootstrapTooltip({})
422 .bootstrapTooltip('show')
423 equal($('.tooltip').children('.tooltip-inner').text(), 'Simple tooltip', 'title from title attribute is set')
424 tooltip.bootstrapTooltip('hide')
425 ok(!$('.tooltip').length, 'tooltip removed')
428 test('tooltip title test #2', function () {
429 var tooltip = $('<a href="#" rel="tooltip" title="Simple tooltip" style="display: inline-block; position: absolute; top: 0; left: 0;"></a>')
430 .appendTo('#qunit-fixture')
432 title: 'This is a tooltip with some content'
434 .bootstrapTooltip('show')
435 equal($('.tooltip').children('.tooltip-inner').text(), 'Simple tooltip', 'title is set from title attribute while prefered over title option')
436 tooltip.bootstrapTooltip('hide')
437 ok(!$('.tooltip').length, 'tooltip removed')
440 test('tooltip title test #3', function () {
441 var tooltip = $('<a href="#" rel="tooltip" style="display: inline-block; position: absolute; top: 0; left: 0;"></a>')
442 .appendTo('#qunit-fixture')
444 title: 'This is a tooltip with some content'
446 .bootstrapTooltip('show')
447 equal($('.tooltip').children('.tooltip-inner').text(), 'This is a tooltip with some content', 'title from title option is set')
448 tooltip.bootstrapTooltip('hide')
449 ok(!$('.tooltip').length, 'tooltip removed')
452 test('tooltips should be placed dynamically, with the dynamic placement option', function () {
453 $.support.transition = false
454 var ttContainer = $('<div id="dynamic-tt-test"/>').css({
457 position: 'absolute',
464 var topTooltip = $('<div style="display: inline-block; position: absolute; left: 0; top: 0;" rel="tooltip" title="Top tooltip">Top Dynamic Tooltip</div>')
465 .appendTo('#dynamic-tt-test')
466 .bootstrapTooltip({ placement: 'auto' })
467 .bootstrapTooltip('show')
469 ok($('.tooltip').is('.bottom'), 'top positioned tooltip is dynamically positioned bottom')
471 topTooltip.bootstrapTooltip('hide')
473 var rightTooltip = $('<div style="display: inline-block; position: absolute; right: 0;" rel="tooltip" title="Right tooltip">Right Dynamic Tooltip</div>')
474 .appendTo('#dynamic-tt-test')
475 .bootstrapTooltip({ placement: 'right auto' })
476 .bootstrapTooltip('show')
478 ok($('.tooltip').is('.left'), 'right positioned tooltip is dynamically positioned left')
479 rightTooltip.bootstrapTooltip('hide')
481 var leftTooltip = $('<div style="display: inline-block; position: absolute; left: 0;" rel="tooltip" title="Left tooltip">Left Dynamic Tooltip</div>')
482 .appendTo('#dynamic-tt-test')
483 .bootstrapTooltip({ placement: 'auto left' })
484 .bootstrapTooltip('show')
486 ok($('.tooltip').is('.right'), 'left positioned tooltip is dynamically positioned right')
487 leftTooltip.bootstrapTooltip('hide')
492 test('should adjust the tip\'s top when up against the top of the viewport', function () {
493 $('head').append('<style id="test"> .tooltip .tooltip-inner { width: 200px; height: 200px; max-width: none; } </style>')
495 var container = $('<div />').appendTo('body')
496 var target = $('<a href="#" rel="tooltip" title="tip" style="position: fixed; top: 0px; left: 0px;"></a>')
498 .bootstrapTooltip({ placement: 'right', viewport: { selector: 'body', padding: 12 }})
499 .bootstrapTooltip('show')
500 var tooltip = container.find('.tooltip')
502 ok(Math.round(tooltip.offset().top) === 12)
503 target.bootstrapTooltip('hide')
504 $('head #test').remove()
507 test('should adjust the tip\'s top when up against the bottom of the viewport', function () {
508 $('head').append('<style id="test"> .tooltip .tooltip-inner { width: 200px; height: 200px; max-width: none; } </style>')
510 var container = $('<div />').appendTo('body')
511 var target = $('<a href="#" rel="tooltip" title="tip" style="position: fixed; bottom: 0px; left: 0px;"></a>')
513 .bootstrapTooltip({ placement: 'right', viewport: { selector: 'body', padding: 12 }})
514 .bootstrapTooltip('show')
515 var tooltip = container.find('.tooltip')
517 ok(Math.round(tooltip.offset().top) === Math.round($(window).height() - 12 - tooltip[0].offsetHeight))
518 target.bootstrapTooltip('hide')
519 $('head #test').remove()
522 test('should adjust the tip\'s left when up against the left of the viewport', function () {
523 $('head').append('<style id="test"> .tooltip .tooltip-inner { width: 200px; height: 200px; max-width: none; } </style>')
525 var container = $('<div />').appendTo('body')
526 var target = $('<a href="#" rel="tooltip" title="tip" style="position: fixed; top: 0px; left: 0px;"></a>')
528 .bootstrapTooltip({ placement: 'bottom', viewport: { selector: 'body', padding: 12 }})
529 .bootstrapTooltip('show')
530 var tooltip = container.find('.tooltip')
532 ok(Math.round(tooltip.offset().left) === 12)
533 target.bootstrapTooltip('hide')
534 $('head #test').remove()
537 test('should adjust the tip\'s left when up against the right of the viewport', function () {
538 $('head').append('<style id="test"> .tooltip .tooltip-inner { width: 200px; height: 200px; max-width: none; } </style>')
540 var container = $('<div />').appendTo('body')
541 var target = $('<a href="#" rel="tooltip" title="tip" style="position: fixed; top: 0px; right: 0px;"></a>')
543 .bootstrapTooltip({ placement: 'bottom', viewport: { selector: 'body', padding: 12 }})
544 .bootstrapTooltip('show')
545 var tooltip = container.find('.tooltip')
547 ok(Math.round(tooltip.offset().left) === Math.round($(window).width() - 12 - tooltip[0].offsetWidth))
548 target.bootstrapTooltip('hide')
549 $('head #test').remove()
552 test('should adjust the tip when up against the right of an arbitrary viewport', function () {
553 $('head').append('<style id="test"> .tooltip, .tooltip .tooltip-inner { width: 200px; height: 200px; max-width: none; } </style>')
554 $('head').append('<style id="viewport-style"> .container-viewport { position: absolute; top: 50px; left: 60px; width: 300px; height: 300px; } </style>')
556 var container = $('<div />', { 'class': 'container-viewport' }).appendTo('body')
557 var target = $('<a href="#" rel="tooltip" title="tip" style="position: fixed; top: 50px; left: 350px;"></a>')
559 .bootstrapTooltip({ placement: 'bottom', viewport: '.container-viewport' })
560 .bootstrapTooltip('show')
561 var tooltip = container.find('.tooltip')
563 ok(Math.round(tooltip.offset().left) === Math.round(60 + container.width() - tooltip[0].offsetWidth))
564 target.bootstrapTooltip('hide')
565 $('head #test').remove()
566 $('head #viewport-style').remove()
569 test('should not error when trying to show an auto-placed tooltip that has been removed from the dom', function () {
570 var tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"></a>').appendTo('#qunit-fixture')
573 .one('show.bs.tooltip', function () {
576 .bootstrapTooltip({ placement: 'auto' })
580 tooltip.bootstrapTooltip('show')
586 ok(passed, '.tooltip(\'show\') should not throw an error in this case')
592 // tooltip may have already been removed