1
0
mirror of https://github.com/twbs/bootstrap.git synced 2025-08-16 02:24:19 +02:00

Merge branch 'master' into fat-9461

This commit is contained in:
Mark Otto
2014-03-24 19:30:17 -07:00
73 changed files with 816 additions and 434 deletions

View File

@@ -1,77 +1,78 @@
<!DOCTYPE HTML>
<!DOCTYPE html>
<html>
<head>
<title>Bootstrap Plugin Test Suite</title>
<head>
<meta charset="utf-8">
<title>Bootstrap Plugin Test Suite</title>
<!-- jQuery -->
<script src="vendor/jquery.js"></script>
<!-- jQuery -->
<script src="vendor/jquery.js"></script>
<!-- QUnit -->
<link rel="stylesheet" href="vendor/qunit.css" media="screen">
<script src="vendor/qunit.js"></script>
<script>
// See https://github.com/axemclion/grunt-saucelabs#test-result-details-with-qunit
var log = []
QUnit.done = function (test_results) {
var tests = log.map(function (details) {
return {
name: details.name,
result: details.result,
expected: details.expected,
actual: details.actual,
source: details.source
<!-- QUnit -->
<link rel="stylesheet" href="vendor/qunit.css" media="screen">
<script src="vendor/qunit.js"></script>
<script>
// See https://github.com/axemclion/grunt-saucelabs#test-result-details-with-qunit
var log = []
QUnit.done = function (test_results) {
var tests = log.map(function (details) {
return {
name: details.name,
result: details.result,
expected: details.expected,
actual: details.actual,
source: details.source
}
})
test_results.tests = tests
// Delaying results a bit because in real-world scenario you won't get them immediately
setTimeout(function () {
window.global_test_results = test_results
}, 2000)
}
QUnit.testStart(function (testDetails) {
QUnit.log = function (details) {
if (!details.result) {
details.name = testDetails.name
log.push(details)
}
}
})
test_results.tests = tests
</script>
// Delaying results a bit because in real-world scenario you won't get them immediately
setTimeout(function () {
window.global_test_results = test_results
}, 2000)
}
<!-- Plugin sources -->
<script>$.support.transition = false</script>
<script src="../../js/alert.js"></script>
<script src="../../js/button.js"></script>
<script src="../../js/carousel.js"></script>
<script src="../../js/collapse.js"></script>
<script src="../../js/dropdown.js"></script>
<script src="../../js/modal.js"></script>
<script src="../../js/scrollspy.js"></script>
<script src="../../js/tab.js"></script>
<script src="../../js/tooltip.js"></script>
<script src="../../js/popover.js"></script>
<script src="../../js/affix.js"></script>
QUnit.testStart(function (testDetails) {
QUnit.log = function (details) {
if (!details.result) {
details.name = testDetails.name
log.push(details)
}
}
})
</script>
<!-- Unit tests -->
<script src="unit/alert.js"></script>
<script src="unit/button.js"></script>
<script src="unit/carousel.js"></script>
<script src="unit/collapse.js"></script>
<script src="unit/dropdown.js"></script>
<script src="unit/modal.js"></script>
<script src="unit/scrollspy.js"></script>
<script src="unit/tab.js"></script>
<script src="unit/tooltip.js"></script>
<script src="unit/popover.js"></script>
<script src="unit/affix.js"></script>
<!-- Plugin sources -->
<script>$.support.transition = false</script>
<script src="../../js/alert.js"></script>
<script src="../../js/button.js"></script>
<script src="../../js/carousel.js"></script>
<script src="../../js/collapse.js"></script>
<script src="../../js/dropdown.js"></script>
<script src="../../js/modal.js"></script>
<script src="../../js/scrollspy.js"></script>
<script src="../../js/tab.js"></script>
<script src="../../js/tooltip.js"></script>
<script src="../../js/popover.js"></script>
<script src="../../js/affix.js"></script>
<!-- Unit tests -->
<script src="unit/alert.js"></script>
<script src="unit/button.js"></script>
<script src="unit/carousel.js"></script>
<script src="unit/collapse.js"></script>
<script src="unit/dropdown.js"></script>
<script src="unit/modal.js"></script>
<script src="unit/scrollspy.js"></script>
<script src="unit/tab.js"></script>
<script src="unit/tooltip.js"></script>
<script src="unit/popover.js"></script>
<script src="unit/affix.js"></script>
</head>
<body>
<div>
<div id="qunit"></div>
<div id="qunit-fixture"></div>
</div>
</body>
</head>
<body>
<div>
<div id="qunit"></div>
<div id="qunit-fixture"></div>
</div>
</body>
</html>

View File

@@ -337,12 +337,12 @@ $(function () {
})
test('should add position class before positioning so that position-specific styles are taken into account', function () {
$('head').append('<style> .tooltip.right { white-space: nowrap; } .tooltip.right .tooltip-inner { max-width: none; } </style>')
$('head').append('<style id="test"> .tooltip.right { white-space: nowrap; } .tooltip.right .tooltip-inner { max-width: none; } </style>')
var container = $('<div />').appendTo('body'),
target = $('<a href="#" rel="tooltip" title="very very very very very very very very long tooltip in one line"></a>')
.appendTo(container)
.tooltip({placement: 'right'})
.tooltip({placement: 'right', viewport: null})
.tooltip('show'),
tooltip = container.find('.tooltip')
@@ -352,6 +352,7 @@ $(function () {
var topDiff = top - top2
ok(topDiff <= 1 && topDiff >= -1)
target.tooltip('hide')
$('head #test').remove()
})
test('tooltip title test #1', function () {
@@ -428,4 +429,80 @@ $(function () {
ttContainer.remove()
})
test('should adjust the tip\'s top when up against the top of the viewport', function () {
$('head').append('<style id="test"> .tooltip .tooltip-inner { width: 200px; height: 200px; max-width: none; } </style>')
var container = $('<div />').appendTo('body'),
target = $('<a href="#" rel="tooltip" title="tip" style="position: fixed; top: 0px; left: 0px;"></a>')
.appendTo(container)
.tooltip({placement: 'right', viewport: {selector: 'body', padding: 12}})
.tooltip('show'),
tooltip = container.find('.tooltip')
ok( Math.round(tooltip.offset().top) === 12 )
target.tooltip('hide')
$('head #test').remove()
})
test('should adjust the tip\'s top when up against the bottom of the viewport', function () {
$('head').append('<style id="test"> .tooltip .tooltip-inner { width: 200px; height: 200px; max-width: none; } </style>')
var container = $('<div />').appendTo('body'),
target = $('<a href="#" rel="tooltip" title="tip" style="position: fixed; bottom: 0px; left: 0px;"></a>')
.appendTo(container)
.tooltip({placement: 'right', viewport: {selector: 'body', padding: 12}})
.tooltip('show'),
tooltip = container.find('.tooltip')
ok( Math.round(tooltip.offset().top) === Math.round($(window).height() - 12 - tooltip[0].offsetHeight) )
target.tooltip('hide')
$('head #test').remove()
})
test('should adjust the tip\'s left when up against the left of the viewport', function () {
$('head').append('<style id="test"> .tooltip .tooltip-inner { width: 200px; height: 200px; max-width: none; } </style>')
var container = $('<div />').appendTo('body'),
target = $('<a href="#" rel="tooltip" title="tip" style="position: fixed; top: 0px; left: 0px;"></a>')
.appendTo(container)
.tooltip({placement: 'bottom', viewport: {selector: 'body', padding: 12}})
.tooltip('show'),
tooltip = container.find('.tooltip')
ok( Math.round(tooltip.offset().left) === 12 )
target.tooltip('hide')
$('head #test').remove()
})
test('should adjust the tip\'s left when up against the right of the viewport', function () {
$('head').append('<style id="test"> .tooltip .tooltip-inner { width: 200px; height: 200px; max-width: none; } </style>')
var container = $('<div />').appendTo('body'),
target = $('<a href="#" rel="tooltip" title="tip" style="position: fixed; top: 0px; right: 0px;"></a>')
.appendTo(container)
.tooltip({placement: 'bottom', viewport: {selector: 'body', padding: 12}})
.tooltip('show'),
tooltip = container.find('.tooltip')
ok( Math.round(tooltip.offset().left) === Math.round($(window).width() - 12 - tooltip[0].offsetWidth) )
target.tooltip('hide')
$('head #test').remove()
})
test('should adjust the tip when up against the right of an arbitrary viewport', function () {
$('head').append('<style id="test"> .tooltip, .tooltip .tooltip-inner { width: 200px; height: 200px; max-width: none; } </style>')
$('head').append('<style id="viewport-style"> .container-viewport { position: absolute; top: 50px; left: 60px; width: 300px; height: 300px; } </style>')
var container = $('<div />', {class: 'container-viewport'}).appendTo('body'),
target = $('<a href="#" rel="tooltip" title="tip" style="position: fixed; top: 50px; left: 350px;"></a>')
.appendTo(container)
.tooltip({placement: 'bottom', viewport: '.container-viewport'})
.tooltip('show'),
tooltip = container.find('.tooltip')
ok( Math.round(tooltip.offset().left) === Math.round(60 + container.width() - tooltip[0].offsetWidth) )
target.tooltip('hide')
$('head #test').remove()
$('head #viewport-style').remove()
})
})

View File

@@ -1,12 +1,12 @@
/*!
* QUnit 1.13.0
* QUnit 1.14.0
* http://qunitjs.com/
*
* Copyright 2013 jQuery Foundation and other contributors
* Released under the MIT license
* http://jquery.org/license
*
* Date: 2014-01-04T17:09Z
* Date: 2014-01-31T16:40Z
*/
/** Font Family and Sizes */
@@ -32,32 +32,29 @@
#qunit-header {
padding: 0.5em 0 0.5em 1em;
color: #8699a4;
background-color: #0d3349;
color: #8699A4;
background-color: #0D3349;
font-size: 1.5em;
line-height: 1em;
font-weight: normal;
font-weight: 400;
border-radius: 5px 5px 0 0;
-moz-border-radius: 5px 5px 0 0;
-webkit-border-top-right-radius: 5px;
-webkit-border-top-left-radius: 5px;
}
#qunit-header a {
text-decoration: none;
color: #c2ccd1;
color: #C2CCD1;
}
#qunit-header a:hover,
#qunit-header a:focus {
color: #fff;
color: #FFF;
}
#qunit-testrunner-toolbar label {
display: inline-block;
padding: 0 .5em 0 .1em;
padding: 0 0.5em 0 0.1em;
}
#qunit-banner {
@@ -67,14 +64,14 @@
#qunit-testrunner-toolbar {
padding: 0.5em 0 0.5em 2em;
color: #5E740B;
background-color: #eee;
background-color: #EEE;
overflow: hidden;
}
#qunit-userAgent {
padding: 0.5em 0 0.5em 2.5em;
background-color: #2b81af;
color: #fff;
background-color: #2B81AF;
color: #FFF;
text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
}
@@ -90,7 +87,7 @@
#qunit-tests li {
padding: 0.4em 0.5em 0.4em 2.5em;
border-bottom: 1px solid #fff;
border-bottom: 1px solid #FFF;
list-style-position: inside;
}
@@ -104,7 +101,7 @@
#qunit-tests li a {
padding: 0.5em;
color: #c2ccd1;
color: #C2CCD1;
text-decoration: none;
}
#qunit-tests li a:hover,
@@ -121,11 +118,9 @@
margin-top: 0.5em;
padding: 0.5em;
background-color: #fff;
background-color: #FFF;
border-radius: 5px;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
}
.qunit-collapsed {
@@ -134,13 +129,13 @@
#qunit-tests table {
border-collapse: collapse;
margin-top: .2em;
margin-top: 0.2em;
}
#qunit-tests th {
text-align: right;
vertical-align: top;
padding: 0 .5em 0 0;
padding: 0 0.5em 0 0;
}
#qunit-tests td {
@@ -154,26 +149,26 @@
}
#qunit-tests del {
background-color: #e0f2be;
color: #374e0c;
background-color: #E0F2BE;
color: #374E0C;
text-decoration: none;
}
#qunit-tests ins {
background-color: #ffcaca;
background-color: #FFCACA;
color: #500;
text-decoration: none;
}
/*** Test Counts */
#qunit-tests b.counts { color: black; }
#qunit-tests b.counts { color: #000; }
#qunit-tests b.passed { color: #5E740B; }
#qunit-tests b.failed { color: #710909; }
#qunit-tests li li {
padding: 5px;
background-color: #fff;
background-color: #FFF;
border-bottom: none;
list-style-position: inside;
}
@@ -181,8 +176,8 @@
/*** Passing Styles */
#qunit-tests li li.pass {
color: #3c510c;
background-color: #fff;
color: #3C510C;
background-color: #FFF;
border-left: 10px solid #C6E746;
}
@@ -190,7 +185,7 @@
#qunit-tests .pass .test-name { color: #366097; }
#qunit-tests .pass .test-actual,
#qunit-tests .pass .test-expected { color: #999999; }
#qunit-tests .pass .test-expected { color: #999; }
#qunit-banner.qunit-pass { background-color: #C6E746; }
@@ -198,24 +193,21 @@
#qunit-tests li li.fail {
color: #710909;
background-color: #fff;
background-color: #FFF;
border-left: 10px solid #EE5757;
white-space: pre;
}
#qunit-tests > li:last-child {
border-radius: 0 0 5px 5px;
-moz-border-radius: 0 0 5px 5px;
-webkit-border-bottom-right-radius: 5px;
-webkit-border-bottom-left-radius: 5px;
}
#qunit-tests .fail { color: #000000; background-color: #EE5757; }
#qunit-tests .fail { color: #000; background-color: #EE5757; }
#qunit-tests .fail .test-name,
#qunit-tests .fail .module-name { color: #000000; }
#qunit-tests .fail .module-name { color: #000; }
#qunit-tests .fail .test-actual { color: #EE5757; }
#qunit-tests .fail .test-expected { color: green; }
#qunit-tests .fail .test-expected { color: #008000; }
#qunit-banner.qunit-fail { background-color: #EE5757; }
@@ -225,13 +217,13 @@
#qunit-testresult {
padding: 0.5em 0.5em 0.5em 2.5em;
color: #2b81af;
color: #2B81AF;
background-color: #D2E0E6;
border-bottom: 1px solid white;
border-bottom: 1px solid #FFF;
}
#qunit-testresult .module-name {
font-weight: bold;
font-weight: 700;
}
/** Fixture */

View File

@@ -1,12 +1,12 @@
/*!
* QUnit 1.13.0
* QUnit 1.14.0
* http://qunitjs.com/
*
* Copyright 2013 jQuery Foundation and other contributors
* Released under the MIT license
* http://jquery.org/license
*
* Date: 2014-01-04T17:09Z
* Date: 2014-01-31T16:40Z
*/
(function( window ) {
@@ -22,6 +22,7 @@ var QUnit,
// Keep a local reference to Date (GH-283)
Date = window.Date,
setTimeout = window.setTimeout,
clearTimeout = window.clearTimeout,
defined = {
document: typeof window.document !== "undefined",
setTimeout: typeof window.setTimeout !== "undefined",
@@ -238,6 +239,9 @@ config = {
// by default, modify document.title when suite is done
altertitle: true,
// by default, scroll to top of the page when suite is done
scrolltop: true,
// when enabled, all tests must call expect()
requireExpects: false,
@@ -271,20 +275,24 @@ config = {
// Initialize more QUnit.config and QUnit.urlParams
(function() {
var i,
var i, current,
location = window.location || { search: "", protocol: "file:" },
params = location.search.slice( 1 ).split( "&" ),
length = params.length,
urlParams = {},
current;
urlParams = {};
if ( params[ 0 ] ) {
for ( i = 0; i < length; i++ ) {
current = params[ i ].split( "=" );
current[ 0 ] = decodeURIComponent( current[ 0 ] );
// allow just a key to turn on a flag, e.g., test.html?noglobals
current[ 1 ] = current[ 1 ] ? decodeURIComponent( current[ 1 ] ) : true;
urlParams[ current[ 0 ] ] = current[ 1 ];
if ( urlParams[ current[ 0 ] ] ) {
urlParams[ current[ 0 ] ] = [].concat( urlParams[ current[ 0 ] ], current[ 1 ] );
} else {
urlParams[ current[ 0 ] ] = current[ 1 ];
}
}
}
@@ -296,7 +304,16 @@ config = {
// Exact match of the module name
config.module = urlParams.module;
config.testNumber = parseInt( urlParams.testNumber, 10 ) || null;
config.testNumber = [];
if ( urlParams.testNumber ) {
// Ensure that urlParams.testNumber is an array
urlParams.testNumber = [].concat( urlParams.testNumber );
for ( i = 0; i < urlParams.testNumber.length; i++ ) {
current = urlParams.testNumber[ i ];
config.testNumber.push( parseInt( current, 10 ) );
}
}
// Figure out if we're running the tests from a server or not
QUnit.isLocal = location.protocol === "file:";
@@ -558,8 +575,8 @@ QUnit.load = function() {
runLoggingCallbacks( "begin", QUnit, {} );
// Initialize the config, saving the execution queue
var banner, filter, i, label, len, main, ol, toolbar, userAgent, val,
urlConfigCheckboxesContainer, urlConfigCheckboxes, moduleFilter,
var banner, filter, i, j, label, len, main, ol, toolbar, val, selection,
urlConfigContainer, moduleFilter, userAgent,
numModules = 0,
moduleNames = [],
moduleFilterHtml = "",
@@ -578,17 +595,55 @@ QUnit.load = function() {
if ( typeof val === "string" ) {
val = {
id: val,
label: val,
tooltip: "[no tooltip available]"
label: val
};
}
config[ val.id ] = QUnit.urlParams[ val.id ];
urlConfigHtml += "<input id='qunit-urlconfig-" + escapeText( val.id ) +
"' name='" + escapeText( val.id ) +
"' type='checkbox'" + ( config[ val.id ] ? " checked='checked'" : "" ) +
" title='" + escapeText( val.tooltip ) +
"'><label for='qunit-urlconfig-" + escapeText( val.id ) +
"' title='" + escapeText( val.tooltip ) + "'>" + val.label + "</label>";
if ( !val.value || typeof val.value === "string" ) {
urlConfigHtml += "<input id='qunit-urlconfig-" + escapeText( val.id ) +
"' name='" + escapeText( val.id ) +
"' type='checkbox'" +
( val.value ? " value='" + escapeText( val.value ) + "'" : "" ) +
( config[ val.id ] ? " checked='checked'" : "" ) +
" title='" + escapeText( val.tooltip ) +
"'><label for='qunit-urlconfig-" + escapeText( val.id ) +
"' title='" + escapeText( val.tooltip ) + "'>" + val.label + "</label>";
} else {
urlConfigHtml += "<label for='qunit-urlconfig-" + escapeText( val.id ) +
"' title='" + escapeText( val.tooltip ) +
"'>" + val.label +
": </label><select id='qunit-urlconfig-" + escapeText( val.id ) +
"' name='" + escapeText( val.id ) +
"' title='" + escapeText( val.tooltip ) +
"'><option></option>";
selection = false;
if ( QUnit.is( "array", val.value ) ) {
for ( j = 0; j < val.value.length; j++ ) {
urlConfigHtml += "<option value='" + escapeText( val.value[j] ) + "'" +
( config[ val.id ] === val.value[j] ?
(selection = true) && " selected='selected'" :
"" ) +
">" + escapeText( val.value[j] ) + "</option>";
}
} else {
for ( j in val.value ) {
if ( hasOwn.call( val.value, j ) ) {
urlConfigHtml += "<option value='" + escapeText( j ) + "'" +
( config[ val.id ] === j ?
(selection = true) && " selected='selected'" :
"" ) +
">" + escapeText( val.value[j] ) + "</option>";
}
}
}
if ( config[ val.id ] && !selection ) {
urlConfigHtml += "<option value='" + escapeText( config[ val.id ] ) +
"' selected='selected' disabled='disabled'>" +
escapeText( config[ val.id ] ) +
"</option>";
}
urlConfigHtml += "</select>";
}
}
for ( i in config.modules ) {
if ( config.modules.hasOwnProperty( i ) ) {
@@ -665,20 +720,27 @@ QUnit.load = function() {
label.innerHTML = "Hide passed tests";
toolbar.appendChild( label );
urlConfigCheckboxesContainer = document.createElement("span");
urlConfigCheckboxesContainer.innerHTML = urlConfigHtml;
urlConfigCheckboxes = urlConfigCheckboxesContainer.getElementsByTagName("input");
urlConfigContainer = document.createElement("span");
urlConfigContainer.innerHTML = urlConfigHtml;
// For oldIE support:
// * Add handlers to the individual elements instead of the container
// * Use "click" instead of "change"
// * Use "click" instead of "change" for checkboxes
// * Fallback from event.target to event.srcElement
addEvents( urlConfigCheckboxes, "click", function( event ) {
addEvents( urlConfigContainer.getElementsByTagName("input"), "click", function( event ) {
var params = {},
target = event.target || event.srcElement;
params[ target.name ] = target.checked ? true : undefined;
params[ target.name ] = target.checked ?
target.defaultValue || true :
undefined;
window.location = QUnit.url( params );
});
toolbar.appendChild( urlConfigCheckboxesContainer );
addEvents( urlConfigContainer.getElementsByTagName("select"), "change", function( event ) {
var params = {},
target = event.target || event.srcElement;
params[ target.name ] = target.options[ target.selectedIndex ].value || undefined;
window.location = QUnit.url( params );
});
toolbar.appendChild( urlConfigContainer );
if (numModules > 1) {
moduleFilter = document.createElement( "span" );
@@ -807,7 +869,7 @@ function done() {
}
// scroll back to top to show results
if ( window.scrollTo ) {
if ( config.scrolltop && window.scrollTo ) {
window.scrollTo(0, 0);
}
@@ -824,7 +886,7 @@ function validTest( test ) {
var include,
filter = config.filter && config.filter.toLowerCase(),
module = config.module && config.module.toLowerCase(),
fullName = (test.module + ": " + test.testName).toLowerCase();
fullName = ( test.module + ": " + test.testName ).toLowerCase();
// Internally-generated tests are always valid
if ( test.callback && test.callback.validTest === validTest ) {
@@ -832,8 +894,10 @@ function validTest( test ) {
return true;
}
if ( config.testNumber ) {
return test.testNumber === config.testNumber;
if ( config.testNumber.length > 0 ) {
if ( inArray( test.testNumber, config.testNumber ) < 0 ) {
return false;
}
}
if ( module && ( !test.module || test.module.toLowerCase() !== module ) ) {
@@ -1375,7 +1439,7 @@ Test.prototype = {
total: this.assertions.length,
runtime: this.runtime,
// DEPRECATED: this property will be removed in 2.0.0, use runtime instead
duration: this.runtime,
duration: this.runtime
});
QUnit.reset();
@@ -1543,7 +1607,7 @@ assert = QUnit.assert = {
ok = false;
// 'expected' is optional
if ( typeof expected === "string" ) {
if ( !message && typeof expected === "string" ) {
message = expected;
expected = null;
}
@@ -1557,16 +1621,30 @@ assert = QUnit.assert = {
config.current.ignoreGlobalErrors = false;
if ( actual ) {
// we don't want to validate thrown error
if ( !expected ) {
ok = true;
expectedOutput = null;
// expected is an Error object
} else if ( expected instanceof Error ) {
ok = actual instanceof Error &&
actual.name === expected.name &&
actual.message === expected.message;
// expected is a regexp
} else if ( QUnit.objectType( expected ) === "regexp" ) {
ok = expected.test( errorString( actual ) );
// expected is a string
} else if ( QUnit.objectType( expected ) === "string" ) {
ok = expected === errorString( actual );
// expected is a constructor
} else if ( actual instanceof expected ) {
ok = true;
// expected is a validation function which returns true is validation passed
} else if ( expected.call( {}, actual ) === true ) {
expectedOutput = null;