]> git.ipfire.org Git - ipfire.org.git/blob - src/scss/bootstrap-4.0.0-alpha.6/js/tests/unit/tooltip.js
.gitignore: Add .vscode
[ipfire.org.git] / src / scss / bootstrap-4.0.0-alpha.6 / js / tests / unit / tooltip.js
1 $(function () {
2 'use strict'
3
4 QUnit.module('tooltip plugin')
5
6 QUnit.test('should be defined on jquery object', function (assert) {
7 assert.expect(1)
8 assert.ok($(document.body).tooltip, 'tooltip method is defined')
9 })
10
11 QUnit.module('tooltip', {
12 beforeEach: function () {
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()
15 },
16 afterEach: function () {
17 $.fn.tooltip = $.fn.bootstrapTooltip
18 delete $.fn.bootstrapTooltip
19 $('.tooltip').remove()
20 }
21 })
22
23 QUnit.test('should provide no conflict', function (assert) {
24 assert.expect(1)
25 assert.strictEqual($.fn.tooltip, undefined, 'tooltip was set back to undefined (org value)')
26 })
27
28 QUnit.test('should throw explicit error on undefined method', function (assert) {
29 assert.expect(1)
30 var $el = $('<div/>')
31 $el.bootstrapTooltip()
32 try {
33 $el.bootstrapTooltip('noMethod')
34 }
35 catch (err) {
36 assert.strictEqual(err.message, 'No method named "noMethod"')
37 }
38 })
39
40 QUnit.test('should return jquery collection containing the element', function (assert) {
41 assert.expect(2)
42 var $el = $('<div/>')
43 var $tooltip = $el.bootstrapTooltip()
44 assert.ok($tooltip instanceof $, 'returns jquery collection')
45 assert.strictEqual($tooltip[0], $el[0], 'collection contains element')
46 })
47
48 QUnit.test('should expose default settings', function (assert) {
49 assert.expect(1)
50 assert.ok($.fn.bootstrapTooltip.Constructor.Default, 'defaults is defined')
51 })
52
53 QUnit.test('should empty title attribute', function (assert) {
54 assert.expect(1)
55 var $trigger = $('<a href="#" rel="tooltip" title="Another tooltip"/>').bootstrapTooltip()
56 assert.strictEqual($trigger.attr('title'), '', 'title attribute was emptied')
57 })
58
59 QUnit.test('should add data attribute for referencing original title', function (assert) {
60 assert.expect(1)
61 var $trigger = $('<a href="#" rel="tooltip" title="Another tooltip"/>').bootstrapTooltip()
62 assert.strictEqual($trigger.attr('data-original-title'), 'Another tooltip', 'original title preserved in data attribute')
63 })
64
65 QUnit.test('should add aria-describedby to the trigger on show', function (assert) {
66 assert.expect(3)
67 var $trigger = $('<a href="#" rel="tooltip" title="Another tooltip"/>')
68 .bootstrapTooltip()
69 .appendTo('#qunit-fixture')
70 .bootstrapTooltip('show')
71
72 var id = $('.tooltip').attr('id')
73
74 assert.strictEqual($('#' + id).length, 1, 'has a unique id')
75 assert.strictEqual($('.tooltip').attr('aria-describedby'), $trigger.attr('id'), 'tooltip id and aria-describedby on trigger match')
76 assert.ok($trigger[0].hasAttribute('aria-describedby'), 'trigger has aria-describedby')
77 })
78
79 QUnit.test('should remove aria-describedby from trigger on hide', function (assert) {
80 assert.expect(2)
81 var $trigger = $('<a href="#" rel="tooltip" title="Another tooltip"/>')
82 .bootstrapTooltip()
83 .appendTo('#qunit-fixture')
84
85 $trigger.bootstrapTooltip('show')
86 assert.ok($trigger[0].hasAttribute('aria-describedby'), 'trigger has aria-describedby')
87
88 $trigger.bootstrapTooltip('hide')
89 assert.ok(!$trigger[0].hasAttribute('aria-describedby'), 'trigger does not have aria-describedby')
90 })
91
92 QUnit.test('should assign a unique id tooltip element', function (assert) {
93 assert.expect(2)
94 $('<a href="#" rel="tooltip" title="Another tooltip"/>')
95 .appendTo('#qunit-fixture')
96 .bootstrapTooltip('show')
97
98 var id = $('.tooltip').attr('id')
99
100 assert.strictEqual($('#' + id).length, 1, 'tooltip has unique id')
101 assert.strictEqual(id.indexOf('tooltip'), 0, 'tooltip id has prefix')
102 })
103
104 QUnit.test('should place tooltips relative to placement option', function (assert) {
105 assert.expect(2)
106 var $tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"/>')
107 .appendTo('#qunit-fixture')
108 .bootstrapTooltip({ placement: 'bottom' })
109
110 $tooltip.bootstrapTooltip('show')
111
112 assert
113 .ok($('.tooltip')
114 .is('.fade.bs-tether-element-attached-top.bs-tether-element-attached-center.show'), 'has correct classes applied')
115
116 $tooltip.bootstrapTooltip('hide')
117
118 assert.strictEqual($tooltip.data('bs.tooltip').tip.parentNode, null, 'tooltip removed')
119 })
120
121 QUnit.test('should allow html entities', function (assert) {
122 assert.expect(2)
123 var $tooltip = $('<a href="#" rel="tooltip" title="&lt;b&gt;@fat&lt;/b&gt;"/>')
124 .appendTo('#qunit-fixture')
125 .bootstrapTooltip({ html: true })
126
127 $tooltip.bootstrapTooltip('show')
128 assert.notEqual($('.tooltip b').length, 0, 'b tag was inserted')
129
130 $tooltip.bootstrapTooltip('hide')
131 assert.strictEqual($tooltip.data('bs.tooltip').tip.parentNode, null, 'tooltip removed')
132 })
133
134 QUnit.test('should allow DOMElement title (html: false)', function (assert) {
135 assert.expect(3)
136 var title = document.createTextNode('<3 writing tests')
137 var $tooltip = $('<a href="#" rel="tooltip"/>')
138 .appendTo('#qunit-fixture')
139 .bootstrapTooltip({ title: title })
140
141 $tooltip.bootstrapTooltip('show')
142
143 assert.notEqual($('.tooltip').length, 0, 'tooltip inserted')
144 assert.strictEqual($('.tooltip').text(), '<3 writing tests', 'title inserted')
145 assert.ok(!$.contains($('.tooltip').get(0), title), 'title node copied, not moved')
146 })
147
148 QUnit.test('should allow DOMElement title (html: true)', function (assert) {
149 assert.expect(3)
150 var title = document.createTextNode('<3 writing tests')
151 var $tooltip = $('<a href="#" rel="tooltip"/>')
152 .appendTo('#qunit-fixture')
153 .bootstrapTooltip({ html: true, title: title })
154
155 $tooltip.bootstrapTooltip('show')
156
157 assert.notEqual($('.tooltip').length, 0, 'tooltip inserted')
158 assert.strictEqual($('.tooltip').text(), '<3 writing tests', 'title inserted')
159 assert.ok($.contains($('.tooltip').get(0), title), 'title node moved, not copied')
160 })
161
162
163 QUnit.test('should respect custom classes', function (assert) {
164 assert.expect(2)
165 var $tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"/>')
166 .appendTo('#qunit-fixture')
167 .bootstrapTooltip({ template: '<div class="tooltip some-class"><div class="tooltip-arrow"/><div class="tooltip-inner"/></div>' })
168
169 $tooltip.bootstrapTooltip('show')
170 assert.ok($('.tooltip').hasClass('some-class'), 'custom class is present')
171
172 $tooltip.bootstrapTooltip('hide')
173 assert.strictEqual($tooltip.data('bs.tooltip').tip.parentNode, null, 'tooltip removed')
174 })
175
176 QUnit.test('should fire show event', function (assert) {
177 assert.expect(1)
178 var done = assert.async()
179
180 $('<div title="tooltip title"/>')
181 .on('show.bs.tooltip', function () {
182 assert.ok(true, 'show event fired')
183 done()
184 })
185 .bootstrapTooltip('show')
186 })
187
188 QUnit.test('should throw an error when show is called on hidden elements', function (assert) {
189 assert.expect(1)
190 var done = assert.async()
191
192 try {
193 $('<div title="tooltip title" style="display: none"/>').bootstrapTooltip('show')
194 }
195 catch (err) {
196 assert.strictEqual(err.message, 'Please use show on visible elements')
197 done()
198 }
199 })
200
201 QUnit.test('should fire inserted event', function (assert) {
202 assert.expect(2)
203 var done = assert.async()
204
205 $('<div title="tooltip title"/>')
206 .appendTo('#qunit-fixture')
207 .on('inserted.bs.tooltip', function () {
208 assert.notEqual($('.tooltip').length, 0, 'tooltip was inserted')
209 assert.ok(true, 'inserted event fired')
210 done()
211 })
212 .bootstrapTooltip('show')
213 })
214
215 QUnit.test('should fire shown event', function (assert) {
216 assert.expect(1)
217 var done = assert.async()
218
219 $('<div title="tooltip title"></div>')
220 .appendTo('#qunit-fixture')
221 .on('shown.bs.tooltip', function () {
222 assert.ok(true, 'shown was called')
223 done()
224 })
225 .bootstrapTooltip('show')
226 })
227
228 QUnit.test('should not fire shown event when show was prevented', function (assert) {
229 assert.expect(1)
230 var done = assert.async()
231
232 $('<div title="tooltip title"/>')
233 .on('show.bs.tooltip', function (e) {
234 e.preventDefault()
235 assert.ok(true, 'show event fired')
236 done()
237 })
238 .on('shown.bs.tooltip', function () {
239 assert.ok(false, 'shown event fired')
240 })
241 .bootstrapTooltip('show')
242 })
243
244 QUnit.test('should fire hide event', function (assert) {
245 assert.expect(1)
246 var done = assert.async()
247
248 $('<div title="tooltip title"/>')
249 .appendTo('#qunit-fixture')
250 .on('shown.bs.tooltip', function () {
251 $(this).bootstrapTooltip('hide')
252 })
253 .on('hide.bs.tooltip', function () {
254 assert.ok(true, 'hide event fired')
255 done()
256 })
257 .bootstrapTooltip('show')
258 })
259
260 QUnit.test('should fire hidden event', function (assert) {
261 assert.expect(1)
262 var done = assert.async()
263
264 $('<div title="tooltip title"/>')
265 .appendTo('#qunit-fixture')
266 .on('shown.bs.tooltip', function () {
267 $(this).bootstrapTooltip('hide')
268 })
269 .on('hidden.bs.tooltip', function () {
270 assert.ok(true, 'hidden event fired')
271 done()
272 })
273 .bootstrapTooltip('show')
274 })
275
276 QUnit.test('should not fire hidden event when hide was prevented', function (assert) {
277 assert.expect(1)
278 var done = assert.async()
279
280 $('<div title="tooltip title"/>')
281 .appendTo('#qunit-fixture')
282 .on('shown.bs.tooltip', function () {
283 $(this).bootstrapTooltip('hide')
284 })
285 .on('hide.bs.tooltip', function (e) {
286 e.preventDefault()
287 assert.ok(true, 'hide event fired')
288 done()
289 })
290 .on('hidden.bs.tooltip', function () {
291 assert.ok(false, 'hidden event fired')
292 })
293 .bootstrapTooltip('show')
294 })
295
296 QUnit.test('should destroy tooltip', function (assert) {
297 assert.expect(7)
298 var $tooltip = $('<div/>')
299 .bootstrapTooltip()
300 .on('click.foo', function () {})
301
302 assert.ok($tooltip.data('bs.tooltip'), 'tooltip has data')
303 assert.ok($._data($tooltip[0], 'events').mouseover && $._data($tooltip[0], 'events').mouseout, 'tooltip has hover events')
304 assert.strictEqual($._data($tooltip[0], 'events').click[0].namespace, 'foo', 'tooltip has extra click.foo event')
305
306 $tooltip.bootstrapTooltip('show')
307 $tooltip.bootstrapTooltip('dispose')
308
309 assert.ok(!$tooltip.hasClass('show'), 'tooltip is hidden')
310 assert.ok(!$._data($tooltip[0], 'bs.tooltip'), 'tooltip does not have data')
311 assert.strictEqual($._data($tooltip[0], 'events').click[0].namespace, 'foo', 'tooltip still has click.foo')
312 assert.ok(!$._data($tooltip[0], 'events').mouseover && !$._data($tooltip[0], 'events').mouseout, 'tooltip does not have hover events')
313 })
314
315 // QUnit.test('should show tooltip with delegate selector on click', function (assert) {
316 // assert.expect(2)
317 // var $div = $('<div><a href="#" rel="tooltip" title="Another tooltip"/></div>')
318 // .appendTo('#qunit-fixture')
319 // .bootstrapTooltip({
320 // selector: 'a[rel="tooltip"]',
321 // trigger: 'click'
322 // })
323
324 // $div.find('a').trigger('click')
325 // assert.ok($('.tooltip').is('.fade.in'), 'tooltip is faded in')
326
327 // $div.find('a').trigger('click')
328 // assert.strictEqual($div.data('bs.tooltip').tip.parentNode, null, 'tooltip removed')
329 // })
330
331 QUnit.test('should show tooltip when toggle is called', function (assert) {
332 assert.expect(1)
333 $('<a href="#" rel="tooltip" title="tooltip on toggle"/>')
334 .appendTo('#qunit-fixture')
335 .bootstrapTooltip({ trigger: 'manual' })
336 .bootstrapTooltip('toggle')
337
338 assert.ok($('.tooltip').is('.fade.show'), 'tooltip is faded active')
339 })
340
341 QUnit.test('should hide previously shown tooltip when toggle is called on tooltip', function (assert) {
342 assert.expect(1)
343 $('<a href="#" rel="tooltip" title="tooltip on toggle">@ResentedHook</a>')
344 .appendTo('#qunit-fixture')
345 .bootstrapTooltip({ trigger: 'manual' })
346 .bootstrapTooltip('show')
347
348 $('.tooltip').bootstrapTooltip('toggle')
349 assert.ok($('.tooltip').not('.fade.show'), 'tooltip was faded out')
350 })
351
352 QUnit.test('should place tooltips inside body when container is body', function (assert) {
353 assert.expect(3)
354 var $tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"/>')
355 .appendTo('#qunit-fixture')
356 .bootstrapTooltip({ container: 'body' })
357 .bootstrapTooltip('show')
358
359 assert.notEqual($('body > .tooltip').length, 0, 'tooltip is direct descendant of body')
360 assert.strictEqual($('#qunit-fixture > .tooltip').length, 0, 'tooltip is not in parent')
361
362 $tooltip.bootstrapTooltip('hide')
363 assert.strictEqual($('body > .tooltip').length, 0, 'tooltip was removed from dom')
364 })
365
366 QUnit.test('should add position class before positioning so that position-specific styles are taken into account', function (assert) {
367 assert.expect(1)
368 var styles = '<style>'
369 + '.tooltip.right { white-space: nowrap; }'
370 + '.tooltip.right .tooltip-inner { max-width: none; }'
371 + '</style>'
372 var $styles = $(styles).appendTo('head')
373
374 var $container = $('<div/>').appendTo('#qunit-fixture')
375 var $target = $('<a href="#" rel="tooltip" title="very very very very very very very very long tooltip in one line"/>')
376 .appendTo($container)
377 .bootstrapTooltip({
378 placement: 'right'
379 })
380 .bootstrapTooltip('show')
381
382 var $tooltip = $($target.data('bs.tooltip').tip)
383
384 // this is some dumb hack stuff because sub pixels in firefox
385 var top = Math.round($target.offset().top + $target[0].offsetHeight / 2 - $tooltip[0].offsetHeight / 2)
386 var top2 = Math.round($tooltip.offset().top)
387 var topDiff = top - top2
388 assert.ok(topDiff <= 1 && topDiff >= -1)
389 $target.bootstrapTooltip('hide')
390
391 $container.remove()
392 $styles.remove()
393 })
394
395 QUnit.test('should use title attribute for tooltip text', function (assert) {
396 assert.expect(2)
397 var $tooltip = $('<a href="#" rel="tooltip" title="Simple tooltip"/>')
398 .appendTo('#qunit-fixture')
399 .bootstrapTooltip()
400
401 $tooltip.bootstrapTooltip('show')
402 assert.strictEqual($('.tooltip').children('.tooltip-inner').text(), 'Simple tooltip', 'title from title attribute is set')
403
404 $tooltip.bootstrapTooltip('hide')
405 assert.strictEqual($('.tooltip').length, 0, 'tooltip removed from dom')
406 })
407
408 QUnit.test('should prefer title attribute over title option', function (assert) {
409 assert.expect(2)
410 var $tooltip = $('<a href="#" rel="tooltip" title="Simple tooltip"/>')
411 .appendTo('#qunit-fixture')
412 .bootstrapTooltip({
413 title: 'This is a tooltip with some content'
414 })
415
416 $tooltip.bootstrapTooltip('show')
417 assert.strictEqual($('.tooltip').children('.tooltip-inner').text(), 'Simple tooltip', 'title is set from title attribute while preferred over title option')
418
419 $tooltip.bootstrapTooltip('hide')
420 assert.strictEqual($('.tooltip').length, 0, 'tooltip removed from dom')
421 })
422
423 QUnit.test('should use title option', function (assert) {
424 assert.expect(2)
425 var $tooltip = $('<a href="#" rel="tooltip"/>')
426 .appendTo('#qunit-fixture')
427 .bootstrapTooltip({
428 title: 'This is a tooltip with some content'
429 })
430
431 $tooltip.bootstrapTooltip('show')
432 assert.strictEqual($('.tooltip').children('.tooltip-inner').text(), 'This is a tooltip with some content', 'title from title option is set')
433
434 $tooltip.bootstrapTooltip('hide')
435 assert.strictEqual($('.tooltip').length, 0, 'tooltip removed from dom')
436 })
437
438 QUnit.test('should not error when trying to show an top-placed tooltip that has been removed from the dom', function (assert) {
439 assert.expect(1)
440 var passed = true
441 var $tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"/>')
442 .appendTo('#qunit-fixture')
443 .one('show.bs.tooltip', function () {
444 $(this).remove()
445 })
446 .bootstrapTooltip({ placement: 'top' })
447
448 try {
449 $tooltip.bootstrapTooltip('show')
450 } catch (err) {
451 passed = false
452 console.log(err)
453 }
454
455 assert.ok(passed, '.tooltip(\'show\') should not throw an error if element no longer is in dom')
456 })
457
458 QUnit.test('should place tooltip on top of element', function (assert) {
459 assert.expect(1)
460 var done = assert.async()
461
462 var containerHTML = '<div>'
463 + '<p style="margin-top: 200px">'
464 + '<a href="#" title="very very very very very very very long tooltip">Hover me</a>'
465 + '</p>'
466 + '</div>'
467
468 var $container = $(containerHTML)
469 .css({
470 position: 'absolute',
471 bottom: 0,
472 left: 0,
473 textAlign: 'right',
474 width: 300,
475 height: 300
476 })
477 .appendTo('#qunit-fixture')
478
479 var $trigger = $container
480 .find('a')
481 .css('margin-top', 200)
482 .bootstrapTooltip({
483 placement: 'top',
484 animate: false
485 })
486 .bootstrapTooltip('show')
487
488 var $tooltip = $($trigger.data('bs.tooltip').tip)
489
490 setTimeout(function () {
491 assert.ok(Math.round($tooltip.offset().top + $tooltip.outerHeight()) <= Math.round($trigger.offset().top))
492 done()
493 }, 0)
494 })
495
496 QUnit.test('should show tooltip if leave event hasn\'t occurred before delay expires', function (assert) {
497 assert.expect(2)
498 var done = assert.async()
499
500 var $tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"/>')
501 .appendTo('#qunit-fixture')
502 .bootstrapTooltip({ delay: 150 })
503
504 setTimeout(function () {
505 assert.ok(!$('.tooltip').is('.fade.show'), '100ms: tooltip is not faded active')
506 }, 100)
507
508 setTimeout(function () {
509 assert.ok($('.tooltip').is('.fade.show'), '200ms: tooltip is faded active')
510 done()
511 }, 200)
512
513 $tooltip.trigger('mouseenter')
514 })
515
516 QUnit.test('should not show tooltip if leave event occurs before delay expires', function (assert) {
517 assert.expect(2)
518 var done = assert.async()
519
520 var $tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"/>')
521 .appendTo('#qunit-fixture')
522 .bootstrapTooltip({ delay: 150 })
523
524 setTimeout(function () {
525 assert.ok(!$('.tooltip').is('.fade.show'), '100ms: tooltip not faded active')
526 $tooltip.trigger('mouseout')
527 }, 100)
528
529 setTimeout(function () {
530 assert.ok(!$('.tooltip').is('.fade.show'), '200ms: tooltip not faded active')
531 done()
532 }, 200)
533
534 $tooltip.trigger('mouseenter')
535 })
536
537 QUnit.test('should not hide tooltip if leave event occurs and enter event occurs within the hide delay', function (assert) {
538 assert.expect(3)
539 var done = assert.async()
540
541 var $tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"/>')
542 .appendTo('#qunit-fixture')
543 .bootstrapTooltip({ delay: { show: 0, hide: 150 } })
544
545 setTimeout(function () {
546 assert.ok($('.tooltip').is('.fade.show'), '1ms: tooltip faded active')
547 $tooltip.trigger('mouseout')
548
549 setTimeout(function () {
550 assert.ok($('.tooltip').is('.fade.show'), '100ms: tooltip still faded active')
551 $tooltip.trigger('mouseenter')
552 }, 100)
553
554 setTimeout(function () {
555 assert.ok($('.tooltip').is('.fade.show'), '200ms: tooltip still faded active')
556 done()
557 }, 200)
558 }, 0)
559
560 $tooltip.trigger('mouseenter')
561 })
562
563 QUnit.test('should not show tooltip if leave event occurs before delay expires', function (assert) {
564 assert.expect(2)
565 var done = assert.async()
566
567 var $tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"/>')
568 .appendTo('#qunit-fixture')
569 .bootstrapTooltip({ delay: 150 })
570
571 setTimeout(function () {
572 assert.ok(!$('.tooltip').is('.fade.show'), '100ms: tooltip not faded active')
573 $tooltip.trigger('mouseout')
574 }, 100)
575
576 setTimeout(function () {
577 assert.ok(!$('.tooltip').is('.fade.show'), '200ms: tooltip not faded active')
578 done()
579 }, 200)
580
581 $tooltip.trigger('mouseenter')
582 })
583
584 QUnit.test('should not show tooltip if leave event occurs before delay expires, even if hide delay is 0', function (assert) {
585 assert.expect(2)
586 var done = assert.async()
587
588 var $tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"/>')
589 .appendTo('#qunit-fixture')
590 .bootstrapTooltip({ delay: { show: 150, hide: 0 } })
591
592 setTimeout(function () {
593 assert.ok(!$('.tooltip').is('.fade.show'), '100ms: tooltip not faded active')
594 $tooltip.trigger('mouseout')
595 }, 100)
596
597 setTimeout(function () {
598 assert.ok(!$('.tooltip').is('.fade.show'), '250ms: tooltip not faded active')
599 done()
600 }, 250)
601
602 $tooltip.trigger('mouseenter')
603 })
604
605 QUnit.test('should wait 200ms before hiding the tooltip', function (assert) {
606 assert.expect(3)
607 var done = assert.async()
608
609 var $tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"/>')
610 .appendTo('#qunit-fixture')
611 .bootstrapTooltip({ delay: { show: 0, hide: 150 } })
612
613 setTimeout(function () {
614 assert.ok($($tooltip.data('bs.tooltip').tip).is('.fade.show'), '1ms: tooltip faded active')
615
616 $tooltip.trigger('mouseout')
617
618 setTimeout(function () {
619 assert.ok($($tooltip.data('bs.tooltip').tip).is('.fade.show'), '100ms: tooltip still faded active')
620 }, 100)
621
622 setTimeout(function () {
623 assert.ok(!$($tooltip.data('bs.tooltip').tip).is('.show'), '200ms: tooltip removed')
624 done()
625 }, 200)
626
627 }, 0)
628
629 $tooltip.trigger('mouseenter')
630 })
631
632 QUnit.test('should correctly position tooltips on SVG elements', function (assert) {
633 if (!window.SVGElement) {
634 // Skip IE8 since it doesn't support SVG
635 assert.expect(0)
636 return
637 }
638 assert.expect(2)
639
640 var done = assert.async()
641
642 var styles = '<style>'
643 + '.tooltip, .tooltip *, .tooltip *:before, .tooltip *:after { box-sizing: border-box; }'
644 + '.tooltip { position: absolute; }'
645 + '.tooltip .tooltip-inner { width: 24px; height: 24px; font-family: Helvetica; }'
646 + '</style>'
647 var $styles = $(styles).appendTo('head')
648
649 $('#qunit-fixture').append(
650 '<div style="position: fixed; top: 0; left: 0;">'
651 + ' <svg width="200" height="200">'
652 + ' <circle cx="100" cy="100" r="10" title="m" id="theCircle" />'
653 + ' </svg>'
654 + '</div>')
655 var $circle = $('#theCircle')
656
657 $circle
658 .on('shown.bs.tooltip', function () {
659 var offset = $('.tooltip').offset()
660 $styles.remove()
661 assert.ok(Math.abs(offset.left - 88) <= 1, 'tooltip has correct horizontal location')
662 $circle.bootstrapTooltip('hide')
663 assert.strictEqual($('.tooltip').length, 0, 'tooltip removed from dom')
664 done()
665 })
666 .bootstrapTooltip({ placement: 'top', trigger: 'manual' })
667
668 $circle.bootstrapTooltip('show')
669 })
670
671 QUnit.test('should not reload the tooltip on subsequent mouseenter events', function (assert) {
672 assert.expect(1)
673 var titleHtml = function () {
674 var uid = Util.getUID('tooltip')
675 return '<p id="tt-content">' + uid + '</p><p>' + uid + '</p><p>' + uid + '</p>'
676 }
677
678 var $tooltip = $('<span id="tt-outer" rel="tooltip" data-trigger="hover" data-placement="top">some text</span>')
679 .appendTo('#qunit-fixture')
680
681 $tooltip.bootstrapTooltip({
682 html: true,
683 animation: false,
684 trigger: 'hover',
685 delay: { show: 0, hide: 500 },
686 container: $tooltip,
687 title: titleHtml
688 })
689
690 $('#tt-outer').trigger('mouseenter')
691
692 var currentUid = $('#tt-content').text()
693
694 $('#tt-content').trigger('mouseenter')
695 assert.strictEqual(currentUid, $('#tt-content').text())
696 })
697
698 QUnit.test('should not reload the tooltip if the mouse leaves and re-enters before hiding', function (assert) {
699 assert.expect(4)
700
701 var titleHtml = function () {
702 var uid = Util.getUID('tooltip')
703 return '<p id="tt-content">' + uid + '</p><p>' + uid + '</p><p>' + uid + '</p>'
704 }
705
706 var $tooltip = $('<span id="tt-outer" rel="tooltip" data-trigger="hover" data-placement="top">some text</span>')
707 .appendTo('#qunit-fixture')
708
709 $tooltip.bootstrapTooltip({
710 html: true,
711 animation: false,
712 trigger: 'hover',
713 delay: { show: 0, hide: 500 },
714 title: titleHtml
715 })
716
717 var obj = $tooltip.data('bs.tooltip')
718
719 $('#tt-outer').trigger('mouseenter')
720
721 var currentUid = $('#tt-content').text()
722
723 $('#tt-outer').trigger('mouseleave')
724 assert.strictEqual(currentUid, $('#tt-content').text())
725
726 assert.ok(obj._hoverState === 'out', 'the tooltip hoverState should be set to "out"')
727
728 $('#tt-outer').trigger('mouseenter')
729 assert.ok(obj._hoverState === 'show', 'the tooltip hoverState should be set to "show"')
730
731 assert.strictEqual(currentUid, $('#tt-content').text())
732 })
733
734 QUnit.test('should correctly position tooltips on transformed elements', function (assert) {
735 var styleProps = document.documentElement.style
736 if (!('transform' in styleProps) && !('webkitTransform' in styleProps) && !('msTransform' in styleProps)) {
737 assert.expect(0)
738 return
739 }
740 assert.expect(2)
741
742 var done = assert.async()
743
744 var styles = '<style>'
745 + '#qunit-fixture { top: 0; left: 0; }'
746 + '.tooltip, .tooltip *, .tooltip *:before, .tooltip *:after { box-sizing: border-box; }'
747 + '.tooltip { position: absolute; }'
748 + '.tooltip .tooltip-inner { width: 24px; height: 24px; font-family: Helvetica; }'
749 + '#target { position: absolute; top: 100px; left: 50px; width: 100px; height: 200px; -webkit-transform: rotate(270deg); -ms-transform: rotate(270deg); transform: rotate(270deg); }'
750 + '</style>'
751 var $styles = $(styles).appendTo('head')
752
753 var $element = $('<div id="target" title="1"/>').appendTo('#qunit-fixture')
754
755 $element
756 .on('shown.bs.tooltip', function () {
757 var offset = $('.tooltip').offset()
758 $styles.remove()
759 assert.ok(Math.abs(offset.left - 88) <= 1, 'tooltip has correct horizontal location')
760 assert.ok(Math.abs(offset.top - 126) <= 1, 'tooltip has correct vertical location')
761 $element.bootstrapTooltip('hide')
762 done()
763 })
764 .bootstrapTooltip({
765 trigger: 'manual'
766 })
767
768 $element.bootstrapTooltip('show')
769 })
770
771 QUnit.test('should do nothing when an attempt is made to hide an uninitialized tooltip', function (assert) {
772 assert.expect(1)
773
774 var $tooltip = $('<span data-toggle="tooltip" title="some tip">some text</span>')
775 .appendTo('#qunit-fixture')
776 .on('hidden.bs.tooltip shown.bs.tooltip', function () {
777 assert.ok(false, 'should not fire any tooltip events')
778 })
779 .bootstrapTooltip('hide')
780 assert.strictEqual($tooltip.data('bs.tooltip'), undefined, 'should not initialize the tooltip')
781 })
782
783 QUnit.test('should not remove tooltip if multiple triggers are set and one is still active', function (assert) {
784 assert.expect(41)
785 var $el = $('<button>Trigger</button>')
786 .appendTo('#qunit-fixture')
787 .bootstrapTooltip({ trigger: 'click hover focus', animation: false })
788 var tooltip = $el.data('bs.tooltip')
789 var $tooltip = $(tooltip.getTipElement())
790
791 function showingTooltip() { return $tooltip.hasClass('show') || tooltip._hoverState === 'show' }
792
793 var tests = [
794 ['mouseenter', 'mouseleave'],
795
796 ['focusin', 'focusout'],
797
798 ['click', 'click'],
799
800 ['mouseenter', 'focusin', 'focusout', 'mouseleave'],
801 ['mouseenter', 'focusin', 'mouseleave', 'focusout'],
802
803 ['focusin', 'mouseenter', 'mouseleave', 'focusout'],
804 ['focusin', 'mouseenter', 'focusout', 'mouseleave'],
805
806 ['click', 'focusin', 'mouseenter', 'focusout', 'mouseleave', 'click'],
807 ['mouseenter', 'click', 'focusin', 'focusout', 'mouseleave', 'click'],
808 ['mouseenter', 'focusin', 'click', 'click', 'mouseleave', 'focusout']
809 ]
810
811 assert.ok(!showingTooltip())
812
813 $.each(tests, function (idx, triggers) {
814 for (var i = 0, len = triggers.length; i < len; i++) {
815 $el.trigger(triggers[i])
816 assert.equal(i < len - 1, showingTooltip())
817 }
818 })
819 })
820
821 QUnit.test('should show on first trigger after hide', function (assert) {
822 assert.expect(3)
823 var $el = $('<a href="#" rel="tooltip" title="Test tooltip"/>')
824 .appendTo('#qunit-fixture')
825 .bootstrapTooltip({ trigger: 'click hover focus', animation: false })
826
827 var tooltip = $el.data('bs.tooltip')
828 var $tooltip = $(tooltip.getTipElement())
829
830 function showingTooltip() { return $tooltip.hasClass('show') || tooltip._hoverState === 'show' }
831
832 $el.trigger('click')
833 assert.ok(showingTooltip(), 'tooltip is faded in')
834
835 $el.bootstrapTooltip('hide')
836 assert.ok(!showingTooltip(), 'tooltip was faded out')
837
838 $el.trigger('click')
839 assert.ok(showingTooltip(), 'tooltip is faded in again')
840 })
841
842 QUnit.test('should hide tooltip when their containing modal is closed', function (assert) {
843 assert.expect(1)
844 var done = assert.async()
845 var templateHTML = '<div id="modal-test" class="modal">' +
846 '<div class="modal-dialog" role="document">' +
847 '<div class="modal-content">' +
848 '<div class="modal-body">' +
849 '<a id="tooltipTest" href="#" data-toggle="tooltip" title="Some tooltip text!">Tooltip</a>' +
850 '</div>' +
851 '</div>' +
852 '</div>' +
853 '</div>'
854
855 $(templateHTML).appendTo('#qunit-fixture')
856 $('#tooltipTest')
857 .bootstrapTooltip({ trigger: 'manuel' })
858 .on('shown.bs.tooltip', function () {
859 $('#modal-test').modal('hide')
860 })
861 .on('hide.bs.tooltip', function () {
862 assert.ok(true, 'tooltip hide')
863 done()
864 })
865
866 $('#modal-test')
867 .on('shown.bs.modal', function () {
868 $('#tooltipTest').bootstrapTooltip('show')
869 })
870 .modal('show')
871 })
872 })