aboutsummaryrefslogtreecommitdiff
path: root/js/tests
diff options
context:
space:
mode:
authorMark Otto <[email protected]>2014-10-26 22:31:59 -0700
committerMark Otto <[email protected]>2014-10-26 22:31:59 -0700
commitd6b0f45fb711989cb8ac32f6717d6920ef5c68e0 (patch)
tree48f08aacd9aadf5cf6fe9aaeeebfa6eb7fab26d0 /js/tests
parentd1660ad0788fa4e9b0d072323c1d70f9c6f5dbf2 (diff)
parent66bb0b4fc963fec42e7168f40b18703d3f31bfa8 (diff)
downloadbootstrap-d6b0f45fb711989cb8ac32f6717d6920ef5c68e0.tar.xz
bootstrap-d6b0f45fb711989cb8ac32f6717d6920ef5c68e0.zip
Merge branch 'master' into derp
Conflicts: Gruntfile.js dist/css/bootstrap-theme.css dist/css/bootstrap-theme.css.map dist/css/bootstrap-theme.min.css dist/css/bootstrap.css dist/css/bootstrap.css.map dist/css/bootstrap.min.css docs/_includes/components/dropdowns.html docs/_includes/components/media.html docs/_includes/components/navs.html docs/_includes/components/progress-bars.html docs/_includes/components/responsive-embed.html docs/_includes/css/buttons.html docs/_includes/css/forms.html docs/_includes/css/less.html docs/_includes/css/overview.html docs/_includes/css/responsive-utilities.html docs/_includes/customizer-variables.html docs/_includes/getting-started/browser-device-support.html docs/_includes/getting-started/grunt.html docs/_includes/getting-started/template.html docs/_includes/header.html docs/_includes/js/alerts.html docs/_includes/js/buttons.html docs/_includes/js/carousel.html docs/_includes/js/collapse.html docs/_includes/js/dropdowns.html docs/_includes/js/modal.html docs/_includes/js/popovers.html docs/_includes/js/scrollspy.html docs/_includes/js/tabs.html docs/_includes/js/tooltips.html docs/_includes/nav/components.html docs/_includes/nav/getting-started.html docs/_layouts/default.html docs/about.html docs/assets/css/docs.min.css docs/assets/css/src/docs.css docs/assets/js/customize.min.js docs/assets/js/docs.min.js docs/assets/js/raw-files.min.js docs/browser-bugs.html docs/components.html docs/components/navbar.md docs/css.html docs/dist/css/bootstrap-theme.css docs/dist/css/bootstrap-theme.css.map docs/dist/css/bootstrap-theme.min.css docs/dist/css/bootstrap.css docs/dist/css/bootstrap.css.map docs/dist/css/bootstrap.min.css docs/examples/blog/index.html docs/examples/carousel/index.html docs/examples/cover/index.html docs/examples/dashboard/index.html docs/examples/grid/index.html docs/examples/jumbotron-narrow/index.html docs/examples/jumbotron/index.html docs/examples/justified-nav/index.html docs/examples/navbar-fixed-top/index.html docs/examples/navbar-static-top/index.html docs/examples/navbar/index.html docs/examples/non-responsive/index.html docs/examples/offcanvas/index.html docs/examples/signin/index.html docs/examples/starter-template/index.html docs/examples/sticky-footer-navbar/index.html docs/examples/sticky-footer/index.html docs/examples/theme/index.html docs/examples/tooltip-viewport/index.html docs/getting-started.html docs/javascript.html docs/migration.html less/_animation.less less/_modal.less less/_navbar.less less/_variables.less less/glyphicons.less less/navs.less less/panels.less less/progress-bars.less
Diffstat (limited to 'js/tests')
-rw-r--r--js/tests/index.html5
-rw-r--r--js/tests/unit/button.js20
-rw-r--r--js/tests/unit/carousel.js101
-rw-r--r--js/tests/unit/collapse.js35
-rw-r--r--js/tests/unit/modal.js4
-rw-r--r--js/tests/unit/popover.js48
-rw-r--r--js/tests/unit/scrollspy.js69
-rw-r--r--js/tests/unit/tab.js101
-rw-r--r--js/tests/unit/tooltip.js271
-rw-r--r--js/tests/visual/dropdown.html41
10 files changed, 647 insertions, 48 deletions
diff --git a/js/tests/index.html b/js/tests/index.html
index 1c025cf76..194f531aa 100644
--- a/js/tests/index.html
+++ b/js/tests/index.html
@@ -10,6 +10,11 @@
<!-- QUnit -->
<link rel="stylesheet" href="vendor/qunit.css" media="screen">
<script src="vendor/qunit.js"></script>
+ <style>
+ #qunit-tests > li.pass {
+ display: none;/* Make it easier to see failing tests is Sauce screencasts */
+ }
+ </style>
<script>
// See https://github.com/axemclion/grunt-saucelabs#test-result-details-with-qunit
var log = []
diff --git a/js/tests/unit/button.js b/js/tests/unit/button.js
index bd431d546..73747cdd4 100644
--- a/js/tests/unit/button.js
+++ b/js/tests/unit/button.js
@@ -85,7 +85,7 @@ $(function () {
})
test('should toggle active', function () {
- var $btn = $('<button class="btn">mdo</button>')
+ var $btn = $('<button class="btn" data-toggle="button">mdo</button>')
ok(!$btn.hasClass('active'), 'btn does not have active class')
$btn.bootstrapButton('toggle')
ok($btn.hasClass('active'), 'btn has class active')
@@ -102,6 +102,24 @@ $(function () {
ok($btn.hasClass('active'), 'btn has class active')
})
+ test('should toggle aria-pressed', function () {
+ var $btn = $('<button class="btn" data-toggle="button" aria-pressed="false">redux</button>')
+ equal($btn.attr('aria-pressed'), 'false', 'btn aria-pressed state is false')
+ $btn.bootstrapButton('toggle')
+ equal($btn.attr('aria-pressed'), 'true', 'btn aria-pressed state is true')
+ })
+
+ test('should toggle aria-pressed when btn children are clicked', function () {
+ var $btn = $('<button class="btn" data-toggle="button" aria-pressed="false">redux</button>')
+ var $inner = $('<i/>')
+ $btn
+ .append($inner)
+ .appendTo('#qunit-fixture')
+ equal($btn.attr('aria-pressed'), 'false', 'btn aria-pressed state is false')
+ $inner.click()
+ equal($btn.attr('aria-pressed'), 'true', 'btn aria-pressed state is true')
+ })
+
test('should toggle active when btn children are clicked within btn-group', function () {
var $btngroup = $('<div class="btn-group" data-toggle="buttons"/>')
var $btn = $('<button class="btn">fat</button>')
diff --git a/js/tests/unit/carousel.js b/js/tests/unit/carousel.js
index 3f9e61a34..6f0b9642f 100644
--- a/js/tests/unit/carousel.js
+++ b/js/tests/unit/carousel.js
@@ -398,4 +398,105 @@ $(function () {
strictEqual($template.find('.item')[1], $template.find('.active')[0], 'second item active')
})
+
+ test('should go to previous item if left arrow key is pressed', function () {
+ var templateHTML = '<div id="myCarousel" class="carousel" data-interval="false">'
+ + '<div class="carousel-inner">'
+ + '<div id="first" class="item">'
+ + '<img alt="">'
+ + '</div>'
+ + '<div id="second" class="item active">'
+ + '<img alt="">'
+ + '</div>'
+ + '<div id="third" class="item">'
+ + '<img alt="">'
+ + '</div>'
+ + '</div>'
+ + '</div>'
+ var $template = $(templateHTML)
+
+ $template.bootstrapCarousel()
+
+ strictEqual($template.find('.item')[1], $template.find('.active')[0], 'second item active')
+
+ $template.trigger($.Event('keydown', { which: 37 }))
+
+ strictEqual($template.find('.item')[0], $template.find('.active')[0], 'first item active')
+ })
+
+ test('should go to next item if right arrow key is pressed', function () {
+ var templateHTML = '<div id="myCarousel" class="carousel" data-interval="false">'
+ + '<div class="carousel-inner">'
+ + '<div id="first" class="item active">'
+ + '<img alt="">'
+ + '</div>'
+ + '<div id="second" class="item">'
+ + '<img alt="">'
+ + '</div>'
+ + '<div id="third" class="item">'
+ + '<img alt="">'
+ + '</div>'
+ + '</div>'
+ + '</div>'
+ var $template = $(templateHTML)
+
+ $template.bootstrapCarousel()
+
+ strictEqual($template.find('.item')[0], $template.find('.active')[0], 'first item active')
+
+ $template.trigger($.Event('keydown', { which: 39 }))
+
+ strictEqual($template.find('.item')[1], $template.find('.active')[0], 'second item active')
+ })
+
+ test('should support disabling the keyboard navigation', function () {
+ var templateHTML = '<div id="myCarousel" class="carousel" data-interval="false" data-keyboard="false">'
+ + '<div class="carousel-inner">'
+ + '<div id="first" class="item active">'
+ + '<img alt="">'
+ + '</div>'
+ + '<div id="second" class="item">'
+ + '<img alt="">'
+ + '</div>'
+ + '<div id="third" class="item">'
+ + '<img alt="">'
+ + '</div>'
+ + '</div>'
+ + '</div>'
+ var $template = $(templateHTML)
+
+ $template.bootstrapCarousel()
+
+ strictEqual($template.find('.item')[0], $template.find('.active')[0], 'first item active')
+
+ $template.trigger($.Event('keydown', { which: 39 }))
+
+ strictEqual($template.find('.item')[0], $template.find('.active')[0], 'first item still active after right arrow press')
+
+ $template.trigger($.Event('keydown', { which: 37 }))
+
+ strictEqual($template.find('.item')[0], $template.find('.active')[0], 'first item still active after left arrow press')
+ })
+
+ test('should only add mouseenter and mouseleave listeners when not on mobile', function () {
+ var isMobile = 'ontouchstart' in document.documentElement
+ var templateHTML = '<div id="myCarousel" class="carousel" data-interval="false" data-pause="hover">'
+ + '<div class="carousel-inner">'
+ + '<div id="first" class="item active">'
+ + '<img alt="">'
+ + '</div>'
+ + '<div id="second" class="item">'
+ + '<img alt="">'
+ + '</div>'
+ + '<div id="third" class="item">'
+ + '<img alt="">'
+ + '</div>'
+ + '</div>'
+ + '</div>'
+ var $template = $(templateHTML).bootstrapCarousel()
+
+ $.each(['mouseover', 'mouseout'], function (i, type) {
+ strictEqual(type in $._data($template[0], 'events'), !isMobile, 'does' + (isMobile ? ' not' : '') + ' listen for ' + type + ' events')
+ })
+ })
})
diff --git a/js/tests/unit/collapse.js b/js/tests/unit/collapse.js
index 825f79360..c1d78575c 100644
--- a/js/tests/unit/collapse.js
+++ b/js/tests/unit/collapse.js
@@ -263,4 +263,39 @@ $(function () {
$target3.click()
})
+ test('should not fire show event if show is prevented because other element is still transitioning', function () {
+ stop()
+
+ var accordionHTML = '<div id="accordion">'
+ + '<div class="panel"/>'
+ + '<div class="panel"/>'
+ + '</div>'
+ var showFired = false
+ var $groups = $(accordionHTML).appendTo('#qunit-fixture').find('.panel')
+
+ var $target1 = $('<a data-toggle="collapse" href="#body1" data-parent="#accordion"/>').appendTo($groups.eq(0))
+
+ $('<div id="body1" class="collapse"/>')
+ .appendTo($groups.eq(0))
+ .on('show.bs.collapse', function () {
+ showFired = true
+ })
+
+ var $target2 = $('<a data-toggle="collapse" href="#body2" data-parent="#accordion"/>').appendTo($groups.eq(1))
+ var $body2 = $('<div id="body2" class="collapse"/>').appendTo($groups.eq(1))
+
+ $target2.click()
+
+ $body2
+ .toggleClass('in collapsing')
+ .data('bs.collapse').transitioning = 1
+
+ $target1.click()
+
+ setTimeout(function () {
+ ok(!showFired, 'show event didn\'t fire')
+ start()
+ }, 1)
+ })
+
})
diff --git a/js/tests/unit/modal.js b/js/tests/unit/modal.js
index 2262465a4..efd478b20 100644
--- a/js/tests/unit/modal.js
+++ b/js/tests/unit/modal.js
@@ -141,7 +141,7 @@ $(function () {
notEqual($('#modal-test').length, 0, 'modal insterted into dom')
$('.contents').click()
ok($('#modal-test').is(':visible'), 'modal visible')
- $('#modal-test').click()
+ $('#modal-test .modal-backdrop').click()
})
.on('hidden.bs.modal', function () {
ok(!$('#modal-test').is(':visible'), 'modal hidden')
@@ -196,7 +196,7 @@ $(function () {
$('<div id="modal-test"><div class="contents"/></div>')
.on('shown.bs.modal', function () {
triggered = 0
- $('#modal-test').click()
+ $('#modal-test .modal-backdrop').click()
})
.on('hide.bs.modal', function () {
triggered += 1
diff --git a/js/tests/unit/popover.js b/js/tests/unit/popover.js
index 5cb4cafdd..466ebace2 100644
--- a/js/tests/unit/popover.js
+++ b/js/tests/unit/popover.js
@@ -30,7 +30,7 @@ $(function () {
})
test('should render popover element', function () {
- var $popover = $('<a href="#" title="mdo" data-content="http://twitter.com/mdo">@mdo</a>')
+ var $popover = $('<a href="#" title="mdo" data-content="https://twitter.com/mdo">@mdo</a>')
.appendTo('#qunit-fixture')
.bootstrapPopover('show')
@@ -40,7 +40,7 @@ $(function () {
})
test('should store popover instance in popover data object', function () {
- var $popover = $('<a href="#" title="mdo" data-content="http://twitter.com/mdo">@mdo</a>').bootstrapPopover()
+ var $popover = $('<a href="#" title="mdo" data-content="https://twitter.com/mdo">@mdo</a>').bootstrapPopover()
ok($popover.data('bs.popover'), 'popover instance exists')
})
@@ -173,4 +173,48 @@ $(function () {
ok(!$._data($popover[0], 'events').mouseover && !$._data($popover[0], 'events').mouseout, 'popover does not have any events')
})
+ test('should render popover element using delegated selector', function () {
+ var $div = $('<div><a href="#" title="mdo" data-content="http://twitter.com/mdo">@mdo</a></div>')
+ .appendTo('#qunit-fixture')
+ .bootstrapPopover({
+ selector: 'a',
+ trigger: 'click'
+ })
+
+ $div.find('a').click()
+ notEqual($('.popover').length, 0, 'popover was inserted')
+
+ $div.find('a').click()
+ equal($('.popover').length, 0, 'popover was removed')
+ })
+
+ test('should render popover elements using different delegated selectors on the same node', function () {
+ var popoverHTML = '<div>'
+ + '<a href="#" class="first" title="mdo" data-content="http://twitter.com/mdo">@mdo</a>'
+ + '<a href="#" class="second" title="mdo" data-content="http://twitter.com/mdo">@mdo</a>'
+ + '</div>'
+
+ var $div = $(popoverHTML)
+ .appendTo('#qunit-fixture')
+ .bootstrapPopover({
+ selector: 'a.first',
+ trigger: 'click'
+ })
+ .bootstrapPopover({
+ selector: 'a.second',
+ trigger: 'click'
+ })
+
+ $div.find('a.first').click()
+ notEqual($('.popover').length, 0, 'first popover was inserted')
+
+ $div.find('a.first').click()
+ equal($('.popover').length, 0, 'first popover removed')
+
+ $div.find('a.second').click()
+ notEqual($('.popover').length, 0, 'second popover was inserted')
+
+ $div.find('a.second').click()
+ equal($('.popover').length, 0, 'second popover removed')
+ })
})
diff --git a/js/tests/unit/scrollspy.js b/js/tests/unit/scrollspy.js
index c071d0f65..0c9081491 100644
--- a/js/tests/unit/scrollspy.js
+++ b/js/tests/unit/scrollspy.js
@@ -29,22 +29,6 @@ $(function () {
strictEqual($scrollspy[0], $el[0], 'collection contains element')
})
- // Does not work properly ATM, #13500 will fix this
- test('should switch "active" class on scroll', function () {
- var topbarHTML = '<div class="topbar">'
- + '<div class="topbar-inner">'
- + '<div class="container">'
- + '<h3><a href="#">Bootstrap</a></h3>'
- + '<li><a href="#masthead">Overview</a></li>'
- + '</ul>'
- + '</div>'
- + '</div>'
- + '</div>'
- var $topbar = $(topbarHTML).bootstrapScrollspy()
-
- ok($topbar.find('.active', true))
- })
-
test('should only switch "active" class on current target', function () {
stop()
@@ -77,9 +61,9 @@ $(function () {
var $section = $(sectionHTML).appendTo('#qunit-fixture')
var $scrollspy = $section
- .show()
- .find('#scrollspy-example')
- .bootstrapScrollspy({ target: '#ss-target' })
+ .show()
+ .find('#scrollspy-example')
+ .bootstrapScrollspy({ target: '#ss-target' })
$scrollspy.on('scroll.bs.scrollspy', function () {
ok($section.hasClass('active'), '"active" class still on root node')
@@ -89,7 +73,7 @@ $(function () {
$scrollspy.scrollTop(350)
})
- test('middle navigation option correctly selected when large offset is used', function () {
+ test('should correctly select middle navigation option when large offset is used', function () {
stop()
var sectionHTML = '<div id="header" style="height: 500px;"></div>'
@@ -107,8 +91,8 @@ $(function () {
+ '</div>'
var $section = $(sectionHTML).appendTo('#qunit-fixture')
var $scrollspy = $section
- .show()
- .filter('#content')
+ .show()
+ .filter('#content')
$scrollspy.bootstrapScrollspy({ target: '#navigation', offset: $scrollspy.position().top })
@@ -158,4 +142,45 @@ $(function () {
.then(function () { return testElementIsActiveAfterScroll('#li-2', '#div-2') })
})
+ test('should clear selection if above the first section', function () {
+ stop()
+
+ var sectionHTML = '<div id="header" style="height: 500px;"></div>'
+ + '<nav id="navigation" class="navbar">'
+ + '<ul class="nav navbar-nav">'
+ + '<li class="active"><a id="one-link" href="#one">One</a></li>'
+ + '<li><a id="two-link" href="#two">Two</a></li>'
+ + '<li><a id="three-link" href="#three">Three</a></li>'
+ + '</ul>'
+ + '</nav>'
+ $(sectionHTML).appendTo('#qunit-fixture')
+
+ var scrollspyHTML = '<div id="content" style="height: 200px; overflow-y: auto;">'
+ + '<div id="spacer" style="height: 100px;"/>'
+ + '<div id="one" style="height: 100px;"/>'
+ + '<div id="two" style="height: 100px;"/>'
+ + '<div id="three" style="height: 100px;"/>'
+ + '<div id="spacer" style="height: 100px;"/>'
+ + '</div>'
+ var $scrollspy = $(scrollspyHTML).appendTo('#qunit-fixture')
+
+ $scrollspy
+ .bootstrapScrollspy({
+ target: '#navigation',
+ offset: $scrollspy.position().top
+ })
+ .one('scroll.bs.scrollspy', function () {
+ strictEqual($('.active').length, 1, '"active" class on only one element present')
+ strictEqual($('.active').has('#two-link').length, 1, '"active" class on second section')
+
+ $scrollspy
+ .one('scroll.bs.scrollspy', function () {
+ strictEqual($('.active').length, 0, 'selection cleared')
+ start()
+ })
+ .scrollTop(0)
+ })
+ .scrollTop(201)
+ })
+
})
diff --git a/js/tests/unit/tab.js b/js/tests/unit/tab.js
index 8e50614ec..9b2a18d57 100644
--- a/js/tests/unit/tab.js
+++ b/js/tests/unit/tab.js
@@ -101,4 +101,105 @@ $(function () {
.bootstrapTab('show')
})
+ test('should fire hide and hidden events', function () {
+ stop()
+
+ var tabsHTML = '<ul class="tabs">'
+ + '<li><a href="#home">Home</a></li>'
+ + '<li><a href="#profile">Profile</a></li>'
+ + '</ul>'
+
+ $(tabsHTML)
+ .find('li:first a')
+ .on('hide.bs.tab', function () {
+ ok(true, 'hide event fired')
+ })
+ .bootstrapTab('show')
+ .end()
+ .find('li:last a')
+ .bootstrapTab('show')
+
+ $(tabsHTML)
+ .find('li:first a')
+ .on('hidden.bs.tab', function () {
+ ok(true, 'hidden event fired')
+ start()
+ })
+ .bootstrapTab('show')
+ .end()
+ .find('li:last a')
+ .bootstrapTab('show')
+ })
+
+ test('should not fire hidden when hide is prevented', function () {
+ stop()
+
+ var tabsHTML = '<ul class="tabs">'
+ + '<li><a href="#home">Home</a></li>'
+ + '<li><a href="#profile">Profile</a></li>'
+ + '</ul>'
+
+ $(tabsHTML)
+ .find('li:first a')
+ .on('hide.bs.tab', function (e) {
+ e.preventDefault()
+ ok(true, 'hide event fired')
+ start()
+ })
+ .on('hidden.bs.tab', function () {
+ ok(false, 'hidden event fired')
+ })
+ .bootstrapTab('show')
+ .end()
+ .find('li:last a')
+ .bootstrapTab('show')
+ })
+
+ test('hide and hidden events contain correct relatedTarget', function () {
+ stop()
+
+ var tabsHTML = '<ul class="tabs">'
+ + '<li><a href="#home">Home</a></li>'
+ + '<li><a href="#profile">Profile</a></li>'
+ + '</ul>'
+
+ $(tabsHTML)
+ .find('li:first a')
+ .on('hide.bs.tab', function (e) {
+ equal(e.relatedTarget.hash, '#profile', 'references correct element as relatedTarget')
+ })
+ .on('hidden.bs.tab', function (e) {
+ equal(e.relatedTarget.hash, '#profile', 'references correct element as relatedTarget')
+ start()
+ })
+ .bootstrapTab('show')
+ .end()
+ .find('li:last a')
+ .bootstrapTab('show')
+ })
+
+ test('selected tab should have aria-expanded', function () {
+ var tabsHTML = '<ul class="nav nav-tabs">'
+ + '<li class="active"><a href="#home" toggle="tab" aria-expanded="true">Home</a></li>'
+ + '<li><a href="#profile" toggle="tab" aria-expanded="false">Profile</a></li>'
+ + '</ul>'
+ var $tabs = $(tabsHTML).appendTo('#qunit-fixture')
+
+ $tabs.find('li:first a').bootstrapTab('show')
+ equal($tabs.find('.active a').attr('aria-expanded'), 'true', 'shown tab has aria-expanded = true')
+ equal($tabs.find('li:not(.active) a').attr('aria-expanded'), 'false', 'hidden tab has aria-expanded = false')
+
+ $tabs.find('li:last a').click()
+ equal($tabs.find('.active a').attr('aria-expanded'), 'true', 'after click, shown tab has aria-expanded = true')
+ equal($tabs.find('li:not(.active) a').attr('aria-expanded'), 'false', 'after click, hidden tab has aria-expanded = false')
+
+ $tabs.find('li:first a').bootstrapTab('show')
+ equal($tabs.find('.active a').attr('aria-expanded'), 'true', 'shown tab has aria-expanded = true')
+ equal($tabs.find('li:not(.active) a').attr('aria-expanded'), 'false', 'hidden tab has aria-expanded = false')
+
+ $tabs.find('li:first a').click()
+ equal($tabs.find('.active a').attr('aria-expanded'), 'true', 'after second show event, shown tab still has aria-expanded = true')
+ equal($tabs.find('li:not(.active) a').attr('aria-expanded'), 'false', 'after second show event, hidden tab has aria-expanded = false')
+ })
+
})
diff --git a/js/tests/unit/tooltip.js b/js/tests/unit/tooltip.js
index c75924e9f..351dd61cb 100644
--- a/js/tests/unit/tooltip.js
+++ b/js/tests/unit/tooltip.js
@@ -235,6 +235,37 @@ $(function () {
equal($('.tooltip').length, 0, 'tooltip was removed from dom')
})
+ test('should show tooltips with different delegate selectors on the same node on click', function () {
+ var tooltipHTML = '<div>'
+ + '<a href="#" class="first" rel="tooltip" title="First delegated tooltip"/>'
+ + '<a href="#" class="second" rel="tooltip" title="Second delegated tooltip"/>'
+ + '</div>'
+
+ var $div = $(tooltipHTML)
+ .append()
+ .appendTo('#qunit-fixture')
+ .bootstrapTooltip({
+ selector: 'a.first[rel="tooltip"]',
+ trigger: 'click'
+ })
+ .bootstrapTooltip({
+ selector: 'a.second[rel="tooltip"]',
+ trigger: 'click'
+ })
+
+ $div.find('a.first').click()
+ ok($('.tooltip').is('.fade.in'), 'first tooltip is faded in')
+
+ $div.find('a.first').click()
+ equal($('.tooltip').length, 0, 'first tooltip was removed from dom')
+
+ $div.find('a.second').click()
+ ok($('.tooltip').is('.fade.in'), 'second tooltip is faded in')
+
+ $div.find('a.second').click()
+ equal($('.tooltip').length, 0, 'second tooltip was removed from dom')
+ })
+
test('should show tooltip when toggle is called', function () {
$('<a href="#" rel="tooltip" title="tooltip on toggle"/>')
.appendTo('#qunit-fixture')
@@ -382,6 +413,164 @@ $(function () {
$style.remove()
})
+ test('should position tip on top if viewport has enough space and placement is "auto top"', function () {
+ var styles = '<style>'
+ + 'body { padding-top: 100px; }'
+ + '#section { height: 300px; border: 1px solid red; padding-top: 50px }'
+ + 'div[rel="tooltip"] { width: 150px; border: 1px solid blue; }'
+ + '</style>'
+ var $styles = $(styles).appendTo('head')
+
+ var $container = $('<div id="section"/>').appendTo('#qunit-fixture')
+ var $target = $('<div rel="tooltip" title="tip"/>')
+ .appendTo($container)
+ .bootstrapTooltip({
+ placement: 'auto top',
+ viewport: '#section'
+ })
+
+ $target.bootstrapTooltip('show')
+ ok($('.tooltip').is('.top'), 'top positioned tooltip is dynamically positioned to top')
+
+ $target.bootstrapTooltip('hide')
+ equal($('.tooltip').length, 0, 'tooltip removed from dom')
+
+ $styles.remove()
+ })
+
+ test('should position tip on bottom if the tip\'s dimension exceeds the viewport area and placement is "auto top"', function () {
+ var styles = '<style>'
+ + 'body { padding-top: 100px; }'
+ + '#section { height: 300px; border: 1px solid red; }'
+ + 'div[rel="tooltip"] { width: 150px; border: 1px solid blue; }'
+ + '</style>'
+ var $styles = $(styles).appendTo('head')
+
+ var $container = $('<div id="section"/>').appendTo('#qunit-fixture')
+ var $target = $('<div rel="tooltip" title="tip"/>')
+ .appendTo($container)
+ .bootstrapTooltip({
+ placement: 'auto top',
+ viewport: '#section'
+ })
+
+ $target.bootstrapTooltip('show')
+ ok($('.tooltip').is('.bottom'), 'top positioned tooltip is dynamically positioned to bottom')
+
+ $target.bootstrapTooltip('hide')
+ equal($('.tooltip').length, 0, 'tooltip removed from dom')
+
+ $styles.remove()
+ })
+
+ test('should display the tip on top whenever scrollable viewport has enough room if the given placement is "auto top"', function () {
+ var styles = '<style>'
+ + '#scrollable-div { height: 200px; overflow: auto; }'
+ + '.tooltip-item { margin: 200px 0 400px; width: 150px; }'
+ + '</style>'
+ var $styles = $(styles).appendTo('head')
+
+ var $container = $('<div id="scrollable-div"/>').appendTo('#qunit-fixture')
+ var $target = $('<div rel="tooltip" title="tip" class="tooltip-item">Tooltip Item</div>')
+ .appendTo($container)
+ .bootstrapTooltip({
+ placement: 'top auto',
+ viewport: '#scrollable-div'
+ })
+
+ $('#scrollable-div').scrollTop(100)
+
+ $target.bootstrapTooltip('show')
+ ok($('.tooltip').is('.fade.top.in'), 'has correct classes applied')
+
+ $target.bootstrapTooltip('hide')
+ equal($('.tooltip').length, 0, 'tooltip removed from dom')
+
+ $styles.remove()
+ })
+
+ test('should display the tip on bottom whenever scrollable viewport doesn\'t have enough room if the given placement is "auto top"', function () {
+ var styles = '<style>'
+ + '#scrollable-div { height: 200px; overflow: auto; }'
+ + '.tooltip-item { padding: 200px 0 400px; width: 150px; }'
+ + '</style>'
+ var $styles = $(styles).appendTo('head')
+
+ var $container = $('<div id="scrollable-div"/>').appendTo('#qunit-fixture')
+ var $target = $('<div rel="tooltip" title="tip" class="tooltip-item">Tooltip Item</div>')
+ .appendTo($container)
+ .bootstrapTooltip({
+ placement: 'top auto',
+ viewport: '#scrollable-div'
+ })
+
+ $('#scrollable-div').scrollTop(200)
+
+ $target.bootstrapTooltip('show')
+ ok($('.tooltip').is('.fade.bottom.in'), 'has correct classes applied')
+
+ $target.bootstrapTooltip('hide')
+ equal($('.tooltip').length, 0, 'tooltip removed from dom')
+
+ $styles.remove()
+ })
+
+ test('should display the tip on bottom whenever scrollable viewport has enough room if the given placement is "auto bottom"', function () {
+ var styles = '<style>'
+ + '#scrollable-div { height: 200px; overflow: auto; }'
+ + '.spacer { height: 400px; }'
+ + '.spacer:first-child { height: 200px; }'
+ + '.tooltip-item { width: 150px; }'
+ + '</style>'
+ var $styles = $(styles).appendTo('head')
+
+ var $container = $('<div id="scrollable-div"/>').appendTo('#qunit-fixture')
+ var $target = $('<div rel="tooltip" title="tip" class="tooltip-item">Tooltip Item</div>')
+ .appendTo($container)
+ .before('<div class="spacer"/>')
+ .after('<div class="spacer"/>')
+ .bootstrapTooltip({
+ placement: 'bottom auto',
+ viewport: '#scrollable-div'
+ })
+
+ $('#scrollable-div').scrollTop(200)
+
+ $target.bootstrapTooltip('show')
+ ok($('.tooltip').is('.fade.bottom.in'), 'has correct classes applied')
+
+ $target.bootstrapTooltip('hide')
+ equal($('.tooltip').length, 0, 'tooltip removed from dom')
+
+ $styles.remove()
+ })
+
+ test('should display the tip on top whenever scrollable viewport doesn\'t have enough room if the given placement is "auto bottom"', function () {
+ var styles = '<style>'
+ + '#scrollable-div { height: 200px; overflow: auto; }'
+ + '.tooltip-item { margin-top: 400px; width: 150px; }'
+ + '</style>'
+ var $styles = $(styles).appendTo('head')
+
+ var $container = $('<div id="scrollable-div"/>').appendTo('#qunit-fixture')
+ var $target = $('<div rel="tooltip" title="tip" class="tooltip-item">Tooltip Item</div>')
+ .appendTo($container)
+ .bootstrapTooltip({
+ placement: 'bottom auto',
+ viewport: '#scrollable-div'
+ })
+
+ $('#scrollable-div').scrollTop(400)
+
+ $target.bootstrapTooltip('show')
+ ok($('.tooltip').is('.fade.top.in'), 'has correct classes applied')
+
+ $target.bootstrapTooltip('hide')
+ equal($('.tooltip').length, 0, 'tooltip removed from dom')
+
+ $styles.remove()
+ })
+
test('should adjust the tip\'s top position when up against the top of the viewport', function () {
var styles = '<style>'
+ '.tooltip .tooltip-inner { width: 200px; height: 200px; max-width: none; }'
@@ -609,7 +798,7 @@ $(function () {
}, 0)
})
- test('should show tooltip if leave event hasn\'t occured before delay expires', function () {
+ test('should show tooltip if leave event hasn\'t occurred before delay expires', function () {
stop()
var $tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"/>')
@@ -777,6 +966,47 @@ $(function () {
$circle.bootstrapTooltip('show')
})
+ test('should correctly determine auto placement based on container rather than parent', function () {
+ stop()
+
+ var styles = '<style>'
+ + '.tooltip, .tooltip *, .tooltip *:before, .tooltip *:after { box-sizing: border-box; }'
+ + '.tooltip { position: absolute; display: block; font-size: 12px; line-height: 1.4; }'
+ + '.tooltip .tooltip-inner { max-width: 200px; padding: 3px 8px; font-family: Helvetica; text-align: center; }'
+ + '#trigger-parent {'
+ + ' position: fixed;'
+ + ' top: 100px;'
+ + ' right: 17px;'
+ + '}'
+ + '</style>'
+ var $styles = $(styles).appendTo('head')
+
+ $('#qunit-fixture').append('<span id="trigger-parent"><a id="tt-trigger" title="If a_larger_text is written here, it won\'t fit using older broken version of BS">HOVER OVER ME</a></span>')
+ var $trigger = $('#tt-trigger')
+
+ $trigger
+ .on('shown.bs.tooltip', function () {
+ var $tip = $('.tooltip-inner')
+ var tipXrightEdge = $tip.offset().left + $tip.width()
+ var triggerXleftEdge = $trigger.offset().left
+ ok(tipXrightEdge < triggerXleftEdge, 'tooltip with auto left placement, when near the right edge of the viewport, gets left placement')
+ $trigger.bootstrapTooltip('hide')
+ })
+ .on('hidden.bs.tooltip', function () {
+ $styles.remove()
+ $(this).remove()
+ equal($('.tooltip').length, 0, 'tooltip removed from dom')
+ start()
+ })
+ .bootstrapTooltip({
+ container: 'body',
+ placement: 'auto left',
+ trigger: 'manual'
+ })
+
+ $trigger.bootstrapTooltip('show')
+ })
+
test('should not reload the tooltip on subsequent mouseenter events', function () {
var titleHtml = function () {
var uid = $.fn.bootstrapTooltip.Constructor.prototype.getUID('tooltip')
@@ -859,6 +1089,7 @@ $(function () {
.on('hidden.bs.tooltip', function () {
$styles.remove()
$(this).remove()
+ equal($('.tooltip').length, 0, 'tooltip removed from dom')
start()
})
.bootstrapTooltip({
@@ -869,4 +1100,42 @@ $(function () {
.bootstrapTooltip('show')
})
+ test('should correctly position tooltips on transformed elements', function () {
+ var styleProps = document.documentElement.style
+ if (!('transform' in styleProps) && !('webkitTransform' in styleProps) && !('msTransform' in styleProps)) {
+ expect(0)
+ return
+ }
+
+ stop()
+
+ var styles = '<style>'
+ + '#qunit-fixture { top: 0; left: 0; }'
+ + '.tooltip, .tooltip *, .tooltip *:before, .tooltip *:after { box-sizing: border-box; }'
+ + '.tooltip { position: absolute; }'
+ + '.tooltip .tooltip-inner { width: 24px; height: 24px; font-family: Helvetica; }'
+ + '#target { position: absolute; top: 100px; left: 50px; width: 100px; height: 200px; -webkit-transform: rotate(270deg); -ms-transform: rotate(270deg); transform: rotate(270deg); }'
+ + '</style>'
+ var $styles = $(styles).appendTo('head')
+
+ var $element = $('<div id="target" title="1"/>').appendTo('#qunit-fixture')
+
+ $element
+ .on('shown.bs.tooltip', function () {
+ var offset = $('.tooltip').offset()
+ $styles.remove()
+ ok(Math.abs(offset.left - 88) <= 1, 'tooltip has correct horizontal location')
+ ok(Math.abs(offset.top - 126) <= 1, 'tooltip has correct vertical location')
+ $element.bootstrapTooltip('hide')
+ start()
+ })
+ .bootstrapTooltip({
+ container: 'body',
+ placement: 'top',
+ trigger: 'manual'
+ })
+
+ $element.bootstrapTooltip('show')
+ })
+
})
diff --git a/js/tests/visual/dropdown.html b/js/tests/visual/dropdown.html
index 455a4f571..6c7f52b2f 100644
--- a/js/tests/visual/dropdown.html
+++ b/js/tests/visual/dropdown.html
@@ -28,21 +28,21 @@
<li class="dropdown">
<a id="drop1" href="#" role="button" class="dropdown-toggle" data-toggle="dropdown">Dropdown <b class="caret"></b></a>
<ul class="dropdown-menu" role="menu" aria-labelledby="drop1">
- <li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Action</a></li>
- <li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Another action</a></li>
- <li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Something else here</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Action</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Another action</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Something else here</a></li>
<li role="presentation" class="divider"></li>
- <li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Separated link</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Separated link</a></li>
</ul>
</li>
<li class="dropdown">
<a href="#" id="drop2" role="button" class="dropdown-toggle" data-toggle="dropdown">Dropdown 2 <b class="caret"></b></a>
<ul class="dropdown-menu" role="menu" aria-labelledby="drop2">
- <li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Action</a></li>
- <li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Another action</a></li>
- <li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Something else here</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Action</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Another action</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Something else here</a></li>
<li role="presentation" class="divider"></li>
- <li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Separated link</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Separated link</a></li>
</ul>
</li>
</ul>
@@ -50,11 +50,11 @@
<li id="fat-menu" class="dropdown">
<a href="#" id="drop3" role="button" class="dropdown-toggle" data-toggle="dropdown">Dropdown 3 <b class="caret"></b></a>
<ul class="dropdown-menu" role="menu" aria-labelledby="drop3">
- <li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Action</a></li>
- <li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Another action</a></li>
- <li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Something else here</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Action</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Another action</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Something else here</a></li>
<li role="presentation" class="divider"></li>
- <li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Separated link</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Separated link</a></li>
</ul>
</li>
</ul>
@@ -67,21 +67,21 @@
<li class="dropdown">
<a id="drop4" role="button" data-toggle="dropdown" href="#">Dropdown <b class="caret"></b></a>
<ul id="menu1" class="dropdown-menu" role="menu" aria-labelledby="drop4">
- <li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Action</a></li>
- <li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Another action</a></li>
- <li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Something else here</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Action</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Another action</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Something else here</a></li>
<li role="presentation" class="divider"></li>
- <li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Separated link</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Separated link</a></li>
</ul>
</li>
<li class="dropdown">
<a id="drop5" role="button" data-toggle="dropdown" href="#">Dropdown 2 <b class="caret"></b></a>
<ul id="menu2" class="dropdown-menu" role="menu" aria-labelledby="drop5">
- <li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Action</a></li>
- <li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Another action</a></li>
- <li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Something else here</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Action</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Another action</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Something else here</a></li>
<li role="presentation" class="divider"></li>
- <li role="presentation"><a role="menuitem" tabindex="-1" href="http://twitter.com/fat">Separated link</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://twitter.com/fat">Separated link</a></li>
</ul>
</li>
</ul>
@@ -92,6 +92,7 @@
<script src="../vendor/jquery.min.js"></script>
<script src="../../transition.js"></script>
<script src="../../dropdown.js"></script>
+<script src="../../collapse.js"></script>
</body>
</html>