diff options
author | Filipp Lepalaan <f@230.to> | 2014-02-19 18:02:09 +0200 |
---|---|---|
committer | Filipp Lepalaan <f@230.to> | 2014-02-19 18:02:09 +0200 |
commit | 75ad7e4bd7d69243e7e5281c2642f00478fb072d (patch) | |
tree | eaaaf360902d369f42d94778aac8803db7973ce0 /apps/it/static/js/ui/tests/unit/tabs | |
parent | cfc7c3f52544af8a71d3fa3988a06fee200d2c24 (diff) | |
download | pudding-75ad7e4bd7d69243e7e5281c2642f00478fb072d.tar.gz pudding-75ad7e4bd7d69243e7e5281c2642f00478fb072d.tar.bz2 pudding-75ad7e4bd7d69243e7e5281c2642f00478fb072d.zip |
Added tags, jquery UI
Diffstat (limited to 'apps/it/static/js/ui/tests/unit/tabs')
-rw-r--r-- | apps/it/static/js/ui/tests/unit/tabs/all.html | 30 | ||||
-rw-r--r-- | apps/it/static/js/ui/tests/unit/tabs/data/test.html | 1 | ||||
-rw-r--r-- | apps/it/static/js/ui/tests/unit/tabs/tabs.html | 155 | ||||
-rw-r--r-- | apps/it/static/js/ui/tests/unit/tabs/tabs_common.js | 18 | ||||
-rw-r--r-- | apps/it/static/js/ui/tests/unit/tabs/tabs_core.js | 615 | ||||
-rw-r--r-- | apps/it/static/js/ui/tests/unit/tabs/tabs_events.js | 318 | ||||
-rw-r--r-- | apps/it/static/js/ui/tests/unit/tabs/tabs_methods.js | 270 | ||||
-rw-r--r-- | apps/it/static/js/ui/tests/unit/tabs/tabs_options.js | 345 | ||||
-rw-r--r-- | apps/it/static/js/ui/tests/unit/tabs/tabs_test_helpers.js | 67 |
9 files changed, 1819 insertions, 0 deletions
diff --git a/apps/it/static/js/ui/tests/unit/tabs/all.html b/apps/it/static/js/ui/tests/unit/tabs/all.html new file mode 100644 index 0000000..355a05d --- /dev/null +++ b/apps/it/static/js/ui/tests/unit/tabs/all.html @@ -0,0 +1,30 @@ +<!doctype html> +<html lang="en"> +<head> + <meta charset="utf-8"> + <title>jQuery UI Tabs Test Suite</title> + + <script src="../../../jquery-1.10.2.js"></script> + + <link rel="stylesheet" href="../../../external/qunit.css"> + <link rel="stylesheet" href="../qunit-composite.css"> + <script src="../../../external/qunit.js"></script> + <script src="../qunit-composite.js"></script> + <script src="../subsuite.js"></script> + + <script> + testAllVersions( "tabs" ); + </script> +</head> +<body> + +<h1 id="qunit-header">jQuery UI Tabs Test Suite</h1> +<h2 id="qunit-banner"></h2> +<div id="qunit-testrunner-toolbar"></div> +<h2 id="qunit-userAgent"></h2> +<ol id="qunit-tests"></ol> +<div id="qunit-fixture"> + +</div> +</body> +</html> diff --git a/apps/it/static/js/ui/tests/unit/tabs/data/test.html b/apps/it/static/js/ui/tests/unit/tabs/data/test.html new file mode 100644 index 0000000..cd59e64 --- /dev/null +++ b/apps/it/static/js/ui/tests/unit/tabs/data/test.html @@ -0,0 +1 @@ +<p>…content loaded via Ajax.</p>
\ No newline at end of file diff --git a/apps/it/static/js/ui/tests/unit/tabs/tabs.html b/apps/it/static/js/ui/tests/unit/tabs/tabs.html new file mode 100644 index 0000000..7c79823 --- /dev/null +++ b/apps/it/static/js/ui/tests/unit/tabs/tabs.html @@ -0,0 +1,155 @@ +<!doctype html> +<html lang="en"> +<head> + <meta charset="utf-8"> + <title>jQuery UI Tabs Test Suite</title> + + <script src="../../jquery.js"></script> + <link rel="stylesheet" href="../../../external/qunit.css"> + <script src="../../../external/qunit.js"></script> + <script src="../../jquery.simulate.js"></script> + <script src="../testsuite.js"></script> + <script> + TestHelpers.loadResources({ + css: [ "ui.core", "ui.tabs" ], + js: [ + "ui/jquery.ui.core.js", + "ui/jquery.ui.widget.js", + "ui/jquery.ui.tabs.js" + ] + }); + </script> + + <script src="tabs_test_helpers.js"></script> + <script src="tabs_common.js"></script> + <script src="tabs_core.js"></script> + <script src="tabs_events.js"></script> + <script src="tabs_methods.js"></script> + <script src="tabs_options.js"></script> + + <script src="../swarminject.js"></script> + <style> + #tabs8, #tabs8 * { + margin: 0; + padding: 0; + font-size: 12px; + line-height: 15px; + } + </style> +</head> +<body> + +<h1 id="qunit-header">jQuery UI Tabs Test Suite</h1> +<h2 id="qunit-banner"></h2> +<div id="qunit-testrunner-toolbar"></div> +<h2 id="qunit-userAgent"></h2> +<ol id="qunit-tests"></ol> +<div id="qunit-fixture"> + +<div id="tabs1"> + <ul> + <li><a href="#fragment-1"><span>1</span></a></li> + <li><a href="#fragment-2"><span>2</span></a></li> + <li><a href="#fragment-3"><span>3</span></a></li> + </ul> + <div id="fragment-1"></div> + <div id="fragment-2"></div> + <div id="fragment-3"></div> +</div> + +<div id="tabs2"> + <ul> + <li><a href="#colon:test"><span>1</span></a></li> + <li><a href="#inline-style"><span>2</span></a></li> + <li><a href="data/test.html#test"><span>3</span></a></li> + <li aria-controls="custom-id"><a href="data/test.html"><span>4</span></a></li> + <li><a href="data/test.html" title="∫ßáö Սե"><span>5</span></a></li> + </ul> + <div id="colon:test"></div> + <div style="height: 300px;" id="inline-style"></div> + <div id="custom-id"></div> +</div> + +<div id="tabs3"> + <div> + <ul id="tabs3-list"> + <li><a href="#tabs3-1">1</a></li> + </ul> + </div> +</div> + +<div id="tabs4"> + <ul id="tabs4-list"> + <li><a href="#tabs4-1">1</a></li> + </ul> + <ol> + <li><a href="#tabs4-1">1</a></li> + </ol> +</div> + +<div id="tabs4a"> + <ol id="tabs4a-list"> + <li><a href="#tabs4a-1">1</a></li> + </ol> + <ul> + <li><a href="#tabs4a-1">1</a></li> + </ul> +</div> + +<div id="tabs5"> + <div> + <ul id="tabs5-list"></ul> + </div> +</div> + +<div id="tabs6"> + <ul id="tabs6-list"> + <li><a href="#tabs6-1">1</a> + <ul> + <li><a href="#item6-3">3</a></li> + <li><a href="#item6-4">4</a></li> + </ul> + </li> + <li><a href="#tabs6-2">2</a></li> + </ul> + <div id="tabs6-1"></div> + <div id="tabs6-2"></div> +</div> + +<div id="tabs7"> + <ul id="tabs7-list"> + <li><a href="#tabs7-1">1</a></li> + <li><a href="#tabs7-2">2</a></li> + </ul> + <div id="tabs7-2"></div> + <div id="tabs7-1"></div> +</div> + +<div id="tabs8Wrapper"> + <div id="tabs8"> + <ul id="tabs8-list"> + <li><a href="#tabs8-1">1</a></li> + <li><a href="#tabs8-2">2</a></li> + </ul> + <div id="tabs8-1"> + <p>Lorem ipsum</p> + <p>Lorem ipsum</p> + <p>Lorem ipsum</p> + </div> + <div id="tabs8-2"> + <p>Lorem ipsum</p> + </div> + </div> +</div> + +<div id="tabs9"> + <ul> + <li>not a tab</li> + <li><a href="#tabs9-1">tab</a></li> + </ul> + <div id="tabs9-1"></div> +</div> + +</div> +</body> +</html> diff --git a/apps/it/static/js/ui/tests/unit/tabs/tabs_common.js b/apps/it/static/js/ui/tests/unit/tabs/tabs_common.js new file mode 100644 index 0000000..a589515 --- /dev/null +++ b/apps/it/static/js/ui/tests/unit/tabs/tabs_common.js @@ -0,0 +1,18 @@ +TestHelpers.commonWidgetTests( "tabs", { + defaults: { + active: null, + collapsible: false, + disabled: false, + event: "click", + heightStyle: "content", + hide: null, + show: null, + + // callbacks + activate: null, + beforeActivate: null, + beforeLoad: null, + create: null, + load: null + } +}); diff --git a/apps/it/static/js/ui/tests/unit/tabs/tabs_core.js b/apps/it/static/js/ui/tests/unit/tabs/tabs_core.js new file mode 100644 index 0000000..5f70206 --- /dev/null +++ b/apps/it/static/js/ui/tests/unit/tabs/tabs_core.js @@ -0,0 +1,615 @@ +(function( $ ) { + +var state = TestHelpers.tabs.state; + +module( "tabs: core" ); + +test( "markup structure", function() { + expect( 3 ); + var element = $( "#tabs1" ).tabs(); + ok( element.hasClass( "ui-tabs" ), "main element is .ui-tabs" ); + ok( element.find( "ul" ).hasClass( "ui-tabs-nav" ), "list item is .ui-tabs-nav" ); + equal( element.find( ".ui-tabs-panel" ).length, 3, + ".ui-tabs-panel elements exist, correct number" ); +}); + +$.each({ + "deep ul": "#tabs3", + "multiple lists, ul first": "#tabs4", + "multiple lists, ol first": "#tabs5", + "empty list": "#tabs6" +}, function( type, selector ) { + test( "markup structure: " + type, function() { + expect( 2 ); + var element = $( selector ).tabs(); + ok( element.hasClass( "ui-tabs" ), "main element is .ui-tabs" ); + ok( $( selector + "-list" ).hasClass( "ui-tabs-nav" ), + "list item is .ui-tabs-nav" ); + }); +}); + +// #5893 - Sublist in the tab list are considered as tab +test( "nested list", function() { + expect( 1 ); + + var element = $( "#tabs6" ).tabs(); + equal( element.data( "ui-tabs" ).anchors.length, 2, "should contain 2 tab" ); +}); + +test( "disconnected from DOM", function() { + expect( 2 ); + + var element = $( "#tabs1" ).remove().tabs(); + equal( element.find( ".ui-tabs-nav" ).length, 1, "should initialize nav" ); + equal( element.find( ".ui-tabs-panel" ).length, 3, "should initialize panels" ); +}); + +test( "non-tab list items", function() { + expect( 2 ); + + var element = $( "#tabs9" ).tabs(); + equal( element.tabs( "option", "active" ), 0, "defaults to first tab" ); + equal( element.find( ".ui-tabs-nav li.ui-state-active" ).index(), 1, + "first actual tab is active" ); +}); + +test( "aria-controls", function() { + expect( 7 ); + var element = $( "#tabs1" ).tabs(), + tabs = element.find( ".ui-tabs-nav li" ); + tabs.each(function() { + var tab = $( this ), + anchor = tab.find( ".ui-tabs-anchor" ); + equal( anchor.prop( "hash" ).substring( 1 ), tab.attr( "aria-controls" ) ); + }); + + element = $( "#tabs2" ).tabs(); + tabs = element.find( ".ui-tabs-nav li" ); + equal( tabs.eq( 0 ).attr( "aria-controls" ), "colon:test" ); + equal( tabs.eq( 1 ).attr( "aria-controls" ), "inline-style" ); + ok( /^ui-tabs-\d+$/.test( tabs.eq( 2 ).attr( "aria-controls" ) ), "generated id" ); + equal( tabs.eq( 3 ).attr( "aria-controls" ), "custom-id" ); +}); + +test( "accessibility", function() { + expect( 49 ); + var element = $( "#tabs1" ).tabs({ + active: 1, + disabled: [ 2 ] + }), + tabs = element.find( ".ui-tabs-nav li" ), + anchors = tabs.find( ".ui-tabs-anchor" ), + panels = element.find( ".ui-tabs-panel" ); + + equal( element.find( ".ui-tabs-nav" ).attr( "role" ), "tablist", "tablist role" ); + tabs.each(function( index ) { + var tab = tabs.eq( index ), + anchor = anchors.eq( index ), + anchorId = anchor.attr( "id" ), + panel = panels.eq( index ); + equal( tab.attr( "role" ), "tab", "tab " + index + " role" ); + equal( tab.attr( "aria-labelledby" ), anchorId, "tab " + index + " aria-labelledby" ); + equal( anchor.attr( "role" ), "presentation", "anchor " + index + " role" ); + equal( anchor.attr( "tabindex" ), -1, "anchor " + index + " tabindex" ); + equal( panel.attr( "role" ), "tabpanel", "panel " + index + " role" ); + equal( panel.attr( "aria-labelledby" ), anchorId, "panel " + index + " aria-labelledby" ); + }); + + equal( tabs.eq( 1 ).attr( "aria-selected" ), "true", "active tab has aria-selected=true" ); + equal( tabs.eq( 1 ).attr( "tabindex" ), 0, "active tab has tabindex=0" ); + equal( tabs.eq( 1 ).attr( "aria-disabled" ), null, "enabled tab does not have aria-disabled" ); + equal( panels.eq( 1 ).attr( "aria-expanded" ), "true", "active panel has aria-expanded=true" ); + equal( panels.eq( 1 ).attr( "aria-hidden" ), "false", "active panel has aria-hidden=false" ); + equal( tabs.eq( 0 ).attr( "aria-selected" ), "false", "inactive tab has aria-selected=false" ); + equal( tabs.eq( 0 ).attr( "tabindex" ), -1, "inactive tab has tabindex=-1" ); + equal( tabs.eq( 0 ).attr( "aria-disabled" ), null, "enabled tab does not have aria-disabled" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "false", "inactive panel has aria-expanded=false" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "true", "inactive panel has aria-hidden=true" ); + equal( tabs.eq( 2 ).attr( "aria-selected" ), "false", "inactive tab has aria-selected=false" ); + equal( tabs.eq( 2 ).attr( "tabindex" ), -1, "inactive tab has tabindex=-1" ); + equal( tabs.eq( 2 ).attr( "aria-disabled" ), "true", "disabled tab has aria-disabled=true" ); + equal( panels.eq( 2 ).attr( "aria-expanded" ), "false", "inactive panel has aria-expanded=false" ); + equal( panels.eq( 2 ).attr( "aria-hidden" ), "true", "inactive panel has aria-hidden=true" ); + + element.tabs( "option", "active", 0 ); + equal( tabs.eq( 0 ).attr( "aria-selected" ), "true", "active tab has aria-selected=true" ); + equal( tabs.eq( 0 ).attr( "tabindex" ), 0, "active tab has tabindex=0" ); + equal( tabs.eq( 0 ).attr( "aria-disabled" ), null, "enabled tab does not have aria-disabled" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "true", "active panel has aria-expanded=true" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "false", "active panel has aria-hidden=false" ); + equal( tabs.eq( 1 ).attr( "aria-selected" ), "false", "inactive tab has aria-selected=false" ); + equal( tabs.eq( 1 ).attr( "tabindex" ), -1, "inactive tab has tabindex=-1" ); + equal( tabs.eq( 1 ).attr( "aria-disabled" ), null, "enabled tab does not have aria-disabled" ); + equal( panels.eq( 1 ).attr( "aria-expanded" ), "false", "inactive panel has aria-expanded=false" ); + equal( panels.eq( 1 ).attr( "aria-hidden" ), "true", "inactive panel has aria-hidden=true" ); + equal( tabs.eq( 2 ).attr( "aria-selected" ), "false", "inactive tab has aria-selected=false" ); + equal( tabs.eq( 2 ).attr( "tabindex" ), -1, "inactive tab has tabindex=-1" ); + equal( tabs.eq( 2 ).attr( "aria-disabled" ), "true", "disabled tab has aria-disabled=true" ); + equal( panels.eq( 2 ).attr( "aria-expanded" ), "false", "inactive panel has aria-expanded=false" ); + equal( panels.eq( 2 ).attr( "aria-hidden" ), "true", "inactive panel has aria-hidden=true" ); +}); + +asyncTest( "accessibility - ajax", function() { + expect( 4 ); + var element = $( "#tabs2" ).tabs(), + panel = $( "#custom-id" ); + + equal( panel.attr( "aria-live" ), "polite", "remote panel has aria-live" ); + equal( panel.attr( "aria-busy" ), null, "does not have aria-busy on init" ); + element.tabs( "option", "active", 3 ); + equal( panel.attr( "aria-busy" ), "true", "panel has aria-busy during load" ); + element.one( "tabsload", function() { + setTimeout(function() { + equal( panel.attr( "aria-busy" ), null, "panel does not have aria-busy after load" ); + start(); + }, 1 ); + }); +}); + +asyncTest( "keyboard support - LEFT, RIGHT, UP, DOWN, HOME, END, SPACE, ENTER", function() { + expect( 92 ); + var element = $( "#tabs1" ).tabs({ + collapsible: true + }), + tabs = element.find( ".ui-tabs-nav li" ), + panels = element.find( ".ui-tabs-panel" ), + keyCode = $.ui.keyCode; + + element.data( "ui-tabs" ).delay = 50; + + equal( tabs.filter( ".ui-state-focus" ).length, 0, "no tabs focused on init" ); + tabs.eq( 0 ).simulate( "focus" ); + + // down, right, down (wrap), up (wrap) + function step1() { + ok( tabs.eq( 0 ).is( ".ui-state-focus" ), "first tab has focus" ); + equal( tabs.eq( 0 ).attr( "aria-selected" ), "true", "first tab has aria-selected=true" ); + ok( panels.eq( 0 ).is( ":visible" ), "first panel is visible" ); + + tabs.eq( 0 ).simulate( "keydown", { keyCode: keyCode.DOWN } ); + ok( tabs.eq( 1 ).is( ".ui-state-focus" ), "DOWN moves focus to next tab" ); + ok( !tabs.eq( 0 ).is( ".ui-state-focus" ), "first tab is no longer focused" ); + equal( tabs.eq( 1 ).attr( "aria-selected" ), "true", "second tab has aria-selected=true" ); + equal( tabs.eq( 0 ).attr( "aria-selected" ), "false", "first tab has aria-selected=false" ); + ok( panels.eq( 1 ).is( ":hidden" ), "second panel is still hidden" ); + equal( panels.eq( 1 ).attr( "aria-expanded" ), "false", "second panel has aria-expanded=false" ); + equal( panels.eq( 1 ).attr( "aria-hidden" ), "true", "second panel has aria-hidden=true" ); + ok( panels.eq( 0 ).is( ":visible" ), "first panel is still visible" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "true", "first panel has aria-expanded=true" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "false", "first panel has aria-hidden=false" ); + + tabs.eq( 1 ).simulate( "keydown", { keyCode: keyCode.RIGHT } ); + ok( tabs.eq( 2 ).is( ".ui-state-focus" ), "RIGHT moves focus to next tab" ); + equal( tabs.eq( 2 ).attr( "aria-selected" ), "true", "third tab has aria-selected=true" ); + equal( tabs.eq( 1 ).attr( "aria-selected" ), "false", "second tab has aria-selected=false" ); + ok( panels.eq( 2 ).is( ":hidden" ), "third panel is still hidden" ); + equal( panels.eq( 2 ).attr( "aria-expanded" ), "false", "third panel has aria-expanded=false" ); + equal( panels.eq( 2 ).attr( "aria-hidden" ), "true", "third panel has aria-hidden=true" ); + ok( panels.eq( 0 ).is( ":visible" ), "first panel is still visible" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "true", "first panel has aria-expanded=true" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "false", "first panel has aria-hidden=false" ); + + tabs.eq( 2 ).simulate( "keydown", { keyCode: keyCode.DOWN } ); + ok( tabs.eq( 0 ).is( ".ui-state-focus" ), "DOWN wraps focus to first tab" ); + equal( tabs.eq( 0 ).attr( "aria-selected" ), "true", "first tab has aria-selected=true" ); + equal( tabs.eq( 2 ).attr( "aria-selected" ), "false", "third tab has aria-selected=false" ); + ok( panels.eq( 0 ).is( ":visible" ), "first panel is still visible" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "true", "first panel has aria-expanded=true" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "false", "first panel has aria-hidden=false" ); + + tabs.eq( 0 ).simulate( "keydown", { keyCode: keyCode.UP } ); + ok( tabs.eq( 2 ).is( ".ui-state-focus" ), "UP wraps focus to last tab" ); + equal( tabs.eq( 2 ).attr( "aria-selected" ), "true", "third tab has aria-selected=true" ); + equal( tabs.eq( 0 ).attr( "aria-selected" ), "false", "first tab has aria-selected=false" ); + ok( panels.eq( 2 ).is( ":hidden" ), "third panel is still hidden" ); + equal( panels.eq( 2 ).attr( "aria-expanded" ), "false", "third panel has aria-expanded=false" ); + equal( panels.eq( 2 ).attr( "aria-hidden" ), "true", "third panel has aria-hidden=true" ); + ok( panels.eq( 0 ).is( ":visible" ), "first panel is still visible" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "true", "first panel has aria-expanded=true" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "false", "first panel has aria-hidden=false" ); + + setTimeout( step2, 100 ); + } + + // left, home, space + function step2() { + equal( tabs.eq( 2 ).attr( "aria-selected" ), "true", "third tab has aria-selected=true" ); + equal( tabs.eq( 0 ).attr( "aria-selected" ), "false", "first tab has aria-selected=false" ); + ok( panels.eq( 2 ).is( ":visible" ), "third panel is visible" ); + equal( panels.eq( 2 ).attr( "aria-expanded" ), "true", "third panel has aria-expanded=true" ); + equal( panels.eq( 2 ).attr( "aria-hidden" ), "false", "third panel has aria-hidden=false" ); + ok( panels.eq( 0 ).is( ":hidden" ), "first panel is hidden" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "false", "first panel has aria-expanded=false" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "true", "first panel has aria-hidden=true" ); + + tabs.eq( 2 ).simulate( "keydown", { keyCode: keyCode.LEFT } ); + ok( tabs.eq( 1 ).is( ".ui-state-focus" ), "LEFT moves focus to previous tab" ); + equal( tabs.eq( 1 ).attr( "aria-selected" ), "true", "second tab has aria-selected=true" ); + equal( tabs.eq( 2 ).attr( "aria-selected" ), "false", "third tab has aria-selected=false" ); + ok( panels.eq( 1 ).is( ":hidden" ), "second panel is still hidden" ); + equal( panels.eq( 1 ).attr( "aria-expanded" ), "false", "second panel has aria-expanded=false" ); + equal( panels.eq( 1 ).attr( "aria-hidden" ), "true", "second panel has aria-hidden=true" ); + ok( panels.eq( 2 ).is( ":visible" ), "third panel is still visible" ); + equal( panels.eq( 2 ).attr( "aria-expanded" ), "true", "third panel has aria-expanded=true" ); + equal( panels.eq( 2 ).attr( "aria-hidden" ), "false", "third panel has aria-hidden=false" ); + + tabs.eq( 1 ).simulate( "keydown", { keyCode: keyCode.HOME } ); + ok( tabs.eq( 0 ).is( ".ui-state-focus" ), "HOME moves focus to first tab" ); + equal( tabs.eq( 0 ).attr( "aria-selected" ), "true", "first tab has aria-selected=true" ); + equal( tabs.eq( 1 ).attr( "aria-selected" ), "false", "second tab has aria-selected=false" ); + ok( panels.eq( 0 ).is( ":hidden" ), "first panel is still hidden" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "false", "first panel has aria-expanded=false" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "true", "first panel has aria-hidden=true" ); + ok( panels.eq( 2 ).is( ":visible" ), "third panel is still visible" ); + equal( panels.eq( 2 ).attr( "aria-expanded" ), "true", "third panel has aria-expanded=true" ); + equal( panels.eq( 2 ).attr( "aria-hidden" ), "false", "third panel has aria-hidden=false" ); + + // SPACE activates, cancels delay + tabs.eq( 0 ).simulate( "keydown", { keyCode: keyCode.SPACE } ); + setTimeout( step3, 1 ); + } + + // end, enter + function step3() { + equal( tabs.eq( 0 ).attr( "aria-selected" ), "true", "first tab has aria-selected=true" ); + equal( tabs.eq( 2 ).attr( "aria-selected" ), "false", "third tab has aria-selected=false" ); + ok( panels.eq( 0 ).is( ":visible" ), "first panel is visible" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "true", "first panel has aria-expanded=true" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "false", "first panel has aria-hidden=false" ); + ok( panels.eq( 2 ).is( ":hidden" ), "third panel is hidden" ); + equal( panels.eq( 2 ).attr( "aria-expanded" ), "false", "third panel has aria-expanded=false" ); + equal( panels.eq( 2 ).attr( "aria-hidden" ), "true", "third panel has aria-hidden=true" ); + + tabs.eq( 0 ).simulate( "keydown", { keyCode: keyCode.END } ); + ok( tabs.eq( 2 ).is( ".ui-state-focus" ), "END moves focus to last tab" ); + equal( tabs.eq( 2 ).attr( "aria-selected" ), "true", "third tab has aria-selected=true" ); + equal( tabs.eq( 0 ).attr( "aria-selected" ), "false", "first tab has aria-selected=false" ); + ok( panels.eq( 2 ).is( ":hidden" ), "third panel is still hidden" ); + equal( panels.eq( 2 ).attr( "aria-expanded" ), "false", "third panel has aria-expanded=false" ); + equal( panels.eq( 2 ).attr( "aria-hidden" ), "true", "third panel has aria-hidden=true" ); + ok( panels.eq( 0 ).is( ":visible" ), "first panel is still visible" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "true", "first panel has aria-expanded=true" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "false", "first panel has aria-hidden=false" ); + + // ENTER activates, cancels delay + tabs.eq( 0 ).simulate( "keydown", { keyCode: keyCode.ENTER } ); + setTimeout( step4, 1 ); + } + + // enter (collapse) + function step4() { + equal( tabs.eq( 2 ).attr( "aria-selected" ), "true", "third tab has aria-selected=true" ); + ok( panels.eq( 2 ).is( ":visible" ), "third panel is visible" ); + equal( panels.eq( 2 ).attr( "aria-expanded" ), "true", "third panel has aria-expanded=true" ); + equal( panels.eq( 2 ).attr( "aria-hidden" ), "false", "third panel has aria-hidden=false" ); + ok( panels.eq( 0 ).is( ":hidden" ), "first panel is hidden" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "false", "first panel has aria-expanded=false" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "true", "first panel has aria-hidden=true" ); + + // ENTER collapses if active + tabs.eq( 2 ).simulate( "keydown", { keyCode: keyCode.ENTER } ); + equal( tabs.eq( 2 ).attr( "aria-selected" ), "false", "third tab has aria-selected=false" ); + ok( panels.eq( 2 ).is( ":hidden" ), "third panel is hidden" ); + equal( panels.eq( 2 ).attr( "aria-expanded" ), "false", "third panel has aria-expanded=false" ); + equal( panels.eq( 2 ).attr( "aria-hidden" ), "true", "third panel has aria-hidden=true" ); + + setTimeout( start, 1 ); + } + + setTimeout( step1, 1 ); +}); + +asyncTest( "keyboard support - CTRL navigation", function() { + expect( 115 ); + var element = $( "#tabs1" ).tabs(), + tabs = element.find( ".ui-tabs-nav li" ), + panels = element.find( ".ui-tabs-panel" ), + keyCode = $.ui.keyCode; + + element.data( "ui-tabs" ).delay = 50; + + equal( tabs.filter( ".ui-state-focus" ).length, 0, "no tabs focused on init" ); + tabs.eq( 0 ).simulate( "focus" ); + + // down + function step1() { + ok( tabs.eq( 0 ).is( ".ui-state-focus" ), "first tab has focus" ); + equal( tabs.eq( 0 ).attr( "aria-selected" ), "true", "first tab has aria-selected=true" ); + ok( panels.eq( 0 ).is( ":visible" ), "first panel is visible" ); + + tabs.eq( 0 ).simulate( "keydown", { keyCode: keyCode.DOWN, ctrlKey: true } ); + ok( tabs.eq( 1 ).is( ".ui-state-focus" ), "DOWN moves focus to next tab" ); + ok( !tabs.eq( 0 ).is( ".ui-state-focus" ), "first tab is no longer focused" ); + equal( tabs.eq( 1 ).attr( "aria-selected" ), "false", "second tab has aria-selected=false" ); + equal( tabs.eq( 0 ).attr( "aria-selected" ), "true", "first tab has aria-selected=true" ); + ok( panels.eq( 1 ).is( ":hidden" ), "second panel is still hidden" ); + equal( panels.eq( 1 ).attr( "aria-expanded" ), "false", "second panel has aria-expanded=false" ); + equal( panels.eq( 1 ).attr( "aria-hidden" ), "true", "second panel has aria-hidden=true" ); + ok( panels.eq( 0 ).is( ":visible" ), "first panel is still visible" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "true", "first panel has aria-expanded=true" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "false", "first panel has aria-hidden=false" ); + + setTimeout( step2, 100 ); + } + + // right + function step2() { + equal( tabs.eq( 0 ).attr( "aria-selected" ), "true", "first tab has aria-selected=true" ); + ok( panels.eq( 0 ).is( ":visible" ), "first panel is visible" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "true", "first panel has aria-expanded=true" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "false", "first panel has aria-hidden=false" ); + ok( panels.eq( 1 ).is( ":hidden" ), "second panel is hidden" ); + equal( panels.eq( 1 ).attr( "aria-expanded" ), "false", "second panel has aria-expanded=false" ); + equal( panels.eq( 1 ).attr( "aria-hidden" ), "true", "second panel has aria-hidden=true" ); + + tabs.eq( 1 ).simulate( "keydown", { keyCode: keyCode.RIGHT, ctrlKey: true } ); + ok( tabs.eq( 2 ).is( ".ui-state-focus" ), "RIGHT moves focus to next tab" ); + equal( tabs.eq( 2 ).attr( "aria-selected" ), "false", "third tab has aria-selected=false" ); + equal( tabs.eq( 0 ).attr( "aria-selected" ), "true", "first tab has aria-selected=true" ); + ok( panels.eq( 2 ).is( ":hidden" ), "third panel is still hidden" ); + equal( panels.eq( 2 ).attr( "aria-expanded" ), "false", "third panel has aria-expanded=false" ); + equal( panels.eq( 2 ).attr( "aria-hidden" ), "true", "third panel has aria-hidden=true" ); + ok( panels.eq( 0 ).is( ":visible" ), "first panel is still visible" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "true", "first panel has aria-expanded=true" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "false", "first panel has aria-hidden=false" ); + + setTimeout( step3, 100 ); + } + + // down (wrap) + function step3() { + equal( tabs.eq( 0 ).attr( "aria-selected" ), "true", "first tab has aria-selected=true" ); + ok( panels.eq( 0 ).is( ":visible" ), "first panel is visible" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "true", "first panel has aria-expanded=true" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "false", "first panel has aria-hidden=false" ); + ok( panels.eq( 2 ).is( ":hidden" ), "third panel is hidden" ); + equal( panels.eq( 2 ).attr( "aria-expanded" ), "false", "third panel has aria-expanded=false" ); + equal( panels.eq( 2 ).attr( "aria-hidden" ), "true", "third panel has aria-hidden=true" ); + + tabs.eq( 2 ).simulate( "keydown", { keyCode: keyCode.DOWN, ctrlKey: true } ); + ok( tabs.eq( 0 ).is( ".ui-state-focus" ), "DOWN wraps focus to first tab" ); + equal( tabs.eq( 0 ).attr( "aria-selected" ), "true", "first tab has aria-selected=true" ); + ok( panels.eq( 0 ).is( ":visible" ), "first panel is still visible" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "true", "first panel has aria-expanded=true" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "false", "first panel has aria-hidden=false" ); + + setTimeout( step4, 100 ); + } + + // up (wrap) + function step4() { + equal( tabs.eq( 0 ).attr( "aria-selected" ), "true", "first tab has aria-selected=true" ); + ok( panels.eq( 0 ).is( ":visible" ), "first panel is visible" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "true", "first panel has aria-expanded=true" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "false", "first panel has aria-hidden=false" ); + + tabs.eq( 0 ).simulate( "keydown", { keyCode: keyCode.UP, ctrlKey: true } ); + ok( tabs.eq( 2 ).is( ".ui-state-focus" ), "UP wraps focus to last tab" ); + equal( tabs.eq( 2 ).attr( "aria-selected" ), "false", "third tab has aria-selected=false" ); + equal( tabs.eq( 0 ).attr( "aria-selected" ), "true", "first tab has aria-selected=true" ); + ok( panels.eq( 2 ).is( ":hidden" ), "third panel is still hidden" ); + equal( panels.eq( 2 ).attr( "aria-expanded" ), "false", "third panel has aria-expanded=false" ); + equal( panels.eq( 2 ).attr( "aria-hidden" ), "true", "third panel has aria-hidden=true" ); + ok( panels.eq( 0 ).is( ":visible" ), "first panel is still visible" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "true", "first panel has aria-expanded=true" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "false", "first panel has aria-hidden=false" ); + + setTimeout( step5, 100 ); + } + + // left + function step5() { + equal( tabs.eq( 0 ).attr( "aria-selected" ), "true", "first tab has aria-selected=true" ); + ok( panels.eq( 0 ).is( ":visible" ), "first panel is visible" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "true", "first panel has aria-expanded=true" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "false", "first panel has aria-hidden=false" ); + ok( panels.eq( 2 ).is( ":hidden" ), "third panel is hidden" ); + equal( panels.eq( 2 ).attr( "aria-expanded" ), "false", "third panel has aria-expanded=false" ); + equal( panels.eq( 2 ).attr( "aria-hidden" ), "true", "third panel has aria-hidden=true" ); + + tabs.eq( 2 ).simulate( "keydown", { keyCode: keyCode.LEFT, ctrlKey: true } ); + ok( tabs.eq( 1 ).is( ".ui-state-focus" ), "LEFT moves focus to previous tab" ); + equal( tabs.eq( 1 ).attr( "aria-selected" ), "false", "second tab has aria-selected=false" ); + equal( tabs.eq( 0 ).attr( "aria-selected" ), "true", "first tab has aria-selected=true" ); + ok( panels.eq( 1 ).is( ":hidden" ), "second panel is still hidden" ); + equal( panels.eq( 1 ).attr( "aria-expanded" ), "false", "second panel has aria-expanded=false" ); + equal( panels.eq( 1 ).attr( "aria-hidden" ), "true", "second panel has aria-hidden=true" ); + ok( panels.eq( 0 ).is( ":visible" ), "first panel is still visible" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "true", "first panel has aria-expanded=true" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "false", "first panel has aria-hidden=false" ); + + setTimeout( step6, 100 ); + } + + // home + function step6() { + equal( tabs.eq( 0 ).attr( "aria-selected" ), "true", "first tab has aria-selected=true" ); + ok( panels.eq( 0 ).is( ":visible" ), "first panel is visible" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "true", "first panel has aria-expanded=true" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "false", "first panel has aria-hidden=false" ); + ok( panels.eq( 1 ).is( ":hidden" ), "second panel is hidden" ); + equal( panels.eq( 1 ).attr( "aria-expanded" ), "false", "second panel has aria-expanded=false" ); + equal( panels.eq( 1 ).attr( "aria-hidden" ), "true", "second panel has aria-hidden=true" ); + + tabs.eq( 1 ).simulate( "keydown", { keyCode: keyCode.HOME, ctrlKey: true } ); + ok( tabs.eq( 0 ).is( ".ui-state-focus" ), "HOME moves focus to first tab" ); + equal( tabs.eq( 0 ).attr( "aria-selected" ), "true", "first tab has aria-selected=true" ); + equal( tabs.eq( 1 ).attr( "aria-selected" ), "false", "second tab has aria-selected=false" ); + ok( panels.eq( 1 ).is( ":hidden" ), "second panel is still hidden" ); + equal( panels.eq( 1 ).attr( "aria-expanded" ), "false", "second panel has aria-expanded=false" ); + equal( panels.eq( 1 ).attr( "aria-hidden" ), "true", "second panel has aria-hidden=true" ); + ok( panels.eq( 0 ).is( ":visible" ), "first panel is still visible" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "true", "first panel has aria-expanded=true" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "false", "first panel has aria-hidden=false" ); + + setTimeout( step7, 100 ); + } + + // end + function step7() { + equal( tabs.eq( 0 ).attr( "aria-selected" ), "true", "first tab has aria-selected=true" ); + ok( panels.eq( 0 ).is( ":visible" ), "first panel is visible" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "true", "first panel has aria-expanded=true" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "false", "first panel has aria-hidden=false" ); + + tabs.eq( 0 ).simulate( "keydown", { keyCode: keyCode.END, ctrlKey: true } ); + ok( tabs.eq( 2 ).is( ".ui-state-focus" ), "END moves focus to last tab" ); + equal( tabs.eq( 2 ).attr( "aria-selected" ), "false", "third tab has aria-selected=false" ); + equal( tabs.eq( 0 ).attr( "aria-selected" ), "true", "first tab has aria-selected=true" ); + ok( panels.eq( 2 ).is( ":hidden" ), "third panel is still hidden" ); + equal( panels.eq( 2 ).attr( "aria-expanded" ), "false", "third panel has aria-expanded=false" ); + equal( panels.eq( 2 ).attr( "aria-hidden" ), "true", "third panel has aria-hidden=true" ); + ok( panels.eq( 0 ).is( ":visible" ), "first panel is still visible" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "true", "first panel has aria-expanded=true" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "false", "first panel has aria-hidden=false" ); + + setTimeout( step8, 100 ); + } + + // space + function step8() { + equal( tabs.eq( 0 ).attr( "aria-selected" ), "true", "first tab has aria-selected=true" ); + ok( panels.eq( 0 ).is( ":visible" ), "first panel is visible" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "true", "first panel has aria-expanded=true" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "false", "first panel has aria-hidden=false" ); + ok( panels.eq( 2 ).is( ":hidden" ), "third panel is hidden" ); + equal( panels.eq( 2 ).attr( "aria-expanded" ), "false", "third panel has aria-expanded=false" ); + equal( panels.eq( 2 ).attr( "aria-hidden" ), "true", "third panel has aria-hidden=true" ); + + tabs.eq( 2 ).simulate( "keydown", { keyCode: keyCode.SPACE } ); + equal( tabs.eq( 2 ).attr( "aria-selected" ), "true", "third tab has aria-selected=true" ); + equal( tabs.eq( 0 ).attr( "aria-selected" ), "false", "first tab has aria-selected=false" ); + ok( panels.eq( 2 ).is( ":visible" ), "third panel is visible" ); + equal( panels.eq( 2 ).attr( "aria-expanded" ), "true", "third panel has aria-expanded=true" ); + equal( panels.eq( 2 ).attr( "aria-hidden" ), "false", "third panel has aria-hidden=false" ); + ok( panels.eq( 0 ).is( ":hidden" ), "first panel is hidden" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "false", "first panel has aria-expanded=false" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "true", "first panel has aria-hidden=true" ); + + setTimeout( start, 1 ); + } + + setTimeout( step1, 1 ); +}); + +asyncTest( "keyboard support - CTRL+UP, ALT+PAGE_DOWN, ALT+PAGE_UP", function() { + expect( 50 ); + var element = $( "#tabs1" ).tabs(), + tabs = element.find( ".ui-tabs-nav li" ), + panels = element.find( ".ui-tabs-panel" ), + keyCode = $.ui.keyCode; + + equal( tabs.filter( ".ui-state-focus" ).length, 0, "no tabs focused on init" ); + panels.attr( "tabindex", -1 ); + panels.eq( 0 ).simulate( "focus" ); + + function step1() { + strictEqual( document.activeElement, panels[ 0 ], "first panel is activeElement" ); + + panels.eq( 0 ).simulate( "keydown", { keyCode: keyCode.PAGE_DOWN, altKey: true } ); + strictEqual( document.activeElement, tabs[ 1 ], "second tab is activeElement" ); + ok( tabs.eq( 1 ).is( ".ui-state-focus" ), "ALT+PAGE_DOWN moves focus to next tab" ); + equal( tabs.eq( 1 ).attr( "aria-selected" ), "true", "second tab has aria-selected=true" ); + ok( panels.eq( 1 ).is( ":visible" ), "second panel is visible" ); + equal( panels.eq( 1 ).attr( "aria-expanded" ), "true", "second panel has aria-expanded=true" ); + equal( panels.eq( 1 ).attr( "aria-hidden" ), "false", "second panel has aria-hidden=false" ); + ok( panels.eq( 0 ).is( ":hidden" ), "first panel is hidden" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "false", "first panel has aria-expanded=false" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "true", "first panel has aria-hidden=true" ); + + tabs.eq( 1 ).simulate( "keydown", { keyCode: keyCode.PAGE_DOWN, altKey: true } ); + strictEqual( document.activeElement, tabs[ 2 ], "third tab is activeElement" ); + ok( tabs.eq( 2 ).is( ".ui-state-focus" ), "ALT+PAGE_DOWN moves focus to next tab" ); + equal( tabs.eq( 2 ).attr( "aria-selected" ), "true", "third tab has aria-selected=true" ); + ok( panels.eq( 2 ).is( ":visible" ), "third panel is visible" ); + equal( panels.eq( 2 ).attr( "aria-expanded" ), "true", "third panel has aria-expanded=true" ); + equal( panels.eq( 2 ).attr( "aria-hidden" ), "false", "third panel has aria-hidden=false" ); + ok( panels.eq( 1 ).is( ":hidden" ), "second panel is hidden" ); + equal( panels.eq( 1 ).attr( "aria-expanded" ), "false", "second panel has aria-expanded=false" ); + equal( panels.eq( 1 ).attr( "aria-hidden" ), "true", "second panel has aria-hidden=true" ); + + tabs.eq( 2 ).simulate( "keydown", { keyCode: keyCode.PAGE_DOWN, altKey: true } ); + strictEqual( document.activeElement, tabs[ 0 ], "first tab is activeElement" ); + ok( tabs.eq( 0 ).is( ".ui-state-focus" ), "ALT+PAGE_DOWN wraps focus to first tab" ); + equal( tabs.eq( 0 ).attr( "aria-selected" ), "true", "first tab has aria-selected=true" ); + ok( panels.eq( 0 ).is( ":visible" ), "first panel is visible" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "true", "first panel has aria-expanded=true" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "false", "first panel has aria-hidden=false" ); + ok( panels.eq( 2 ).is( ":hidden" ), "third panel is hidden" ); + equal( panels.eq( 2 ).attr( "aria-expanded" ), "false", "third panel has aria-expanded=false" ); + equal( panels.eq( 2 ).attr( "aria-hidden" ), "true", "third panel has aria-hidden=true" ); + + panels.eq( 0 ).simulate( "focus" ); + setTimeout( step2, 1 ); + } + + function step2() { + strictEqual( document.activeElement, panels[ 0 ], "first panel is activeElement" ); + + panels.eq( 0 ).simulate( "keydown", { keyCode: keyCode.PAGE_UP, altKey: true } ); + strictEqual( document.activeElement, tabs[ 2 ], "third tab is activeElement" ); + ok( tabs.eq( 2 ).is( ".ui-state-focus" ), "ALT+PAGE_UP wraps focus to last tab" ); + equal( tabs.eq( 2 ).attr( "aria-selected" ), "true", "third tab has aria-selected=true" ); + ok( panels.eq( 2 ).is( ":visible" ), "third panel is visible" ); + equal( panels.eq( 2 ).attr( "aria-expanded" ), "true", "third panel has aria-expanded=true" ); + equal( panels.eq( 2 ).attr( "aria-hidden" ), "false", "third panel has aria-hidden=false" ); + ok( panels.eq( 0 ).is( ":hidden" ), "first panel is hidden" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "false", "first panel has aria-expanded=false" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "true", "first panel has aria-hidden=true" ); + + tabs.eq( 2 ).simulate( "keydown", { keyCode: keyCode.PAGE_UP, altKey: true } ); + strictEqual( document.activeElement, tabs[ 1 ], "second tab is activeElement" ); + ok( tabs.eq( 1 ).is( ".ui-state-focus" ), "ALT+PAGE_UP moves focus to previous tab" ); + equal( tabs.eq( 1 ).attr( "aria-selected" ), "true", "second tab has aria-selected=true" ); + ok( panels.eq( 1 ).is( ":visible" ), "second panel is visible" ); + equal( panels.eq( 1 ).attr( "aria-expanded" ), "true", "second panel has aria-expanded=true" ); + equal( panels.eq( 1 ).attr( "aria-hidden" ), "false", "second panel has aria-hidden=false" ); + ok( panels.eq( 2 ).is( ":hidden" ), "third panel is hidden" ); + equal( panels.eq( 2 ).attr( "aria-expanded" ), "false", "third panel has aria-expanded=false" ); + equal( panels.eq( 2 ).attr( "aria-hidden" ), "true", "third panel has aria-hidden=true" ); + + panels.eq( 1 ).simulate( "focus" ); + setTimeout( step3, 1 ); + } + + function step3() { + strictEqual( document.activeElement, panels[ 1 ], "second panel is activeElement" ); + + panels.eq( 1 ).simulate( "keydown", { keyCode: keyCode.UP, ctrlKey: true } ); + strictEqual( document.activeElement, tabs[ 1 ], "second tab is activeElement" ); + + setTimeout( start, 1 ); + } + + setTimeout( step1, 1 ); +}); + +test( "#3627 - Ajax tab with url containing a fragment identifier fails to load", function() { + expect( 1 ); + + $( "#tabs2" ).tabs({ + active: 2, + beforeLoad: function( event, ui ) { + event.preventDefault(); + ok( /test.html$/.test( ui.ajaxSettings.url ), "should ignore fragment identifier" ); + } + }); +}); + +test( "#4033 - IE expands hash to full url and misinterprets tab as ajax", function() { + expect( 2 ); + + var element = $("<div><ul><li><a href='#tab'>Tab</a></li></ul><div id='tab'></div></div>"); + element.appendTo("#qunit-fixture"); + element.tabs({ + beforeLoad: function() { + event.preventDefault(); + ok( false, "should not be an ajax tab" ); + } + }); + + equal( element.find(".ui-tabs-nav li").attr("aria-controls"), "tab", "aria-contorls attribute is correct" ); + state( element, 1 ); +}); + +}( jQuery ) ); diff --git a/apps/it/static/js/ui/tests/unit/tabs/tabs_events.js b/apps/it/static/js/ui/tests/unit/tabs/tabs_events.js new file mode 100644 index 0000000..f9b1755 --- /dev/null +++ b/apps/it/static/js/ui/tests/unit/tabs/tabs_events.js @@ -0,0 +1,318 @@ +(function( $ ) { + +var state = TestHelpers.tabs.state; + +module( "tabs: events" ); + +test( "create", function() { + expect( 10 ); + + var element = $( "#tabs1" ), + tabs = element.find( "ul li" ), + panels = element.children( "div" ); + + element.tabs({ + create: function( event, ui ) { + equal( ui.tab.length, 1, "tab length" ); + strictEqual( ui.tab[ 0 ], tabs[ 0 ], "tab" ); + equal( ui.panel.length, 1, "panel length" ); + strictEqual( ui.panel[ 0 ], panels[ 0 ], "panel" ); + } + }); + element.tabs( "destroy" ); + + element.tabs({ + active: 2, + create: function( event, ui ) { + equal( ui.tab.length, 1, "tab length" ); + strictEqual( ui.tab[ 0 ], tabs[ 2 ], "tab" ); + equal( ui.panel.length, 1, "panel length" ); + strictEqual( ui.panel[ 0 ], panels[ 2 ], "panel" ); + } + }); + element.tabs( "destroy" ); + + element.tabs({ + active: false, + collapsible: true, + create: function( event, ui ) { + equal( ui.tab.length, 0, "tab length" ); + equal( ui.panel.length, 0, "panel length" ); + } + }); + element.tabs( "destroy" ); +}); + +test( "beforeActivate", function() { + expect( 38 ); + + var element = $( "#tabs1" ).tabs({ + active: false, + collapsible: true + }), + tabs = element.find( ".ui-tabs-nav li" ), + anchors = tabs.find( ".ui-tabs-anchor" ), + panels = element.find( ".ui-tabs-panel" ); + + // from collapsed + element.one( "tabsbeforeactivate", function( event, ui ) { + ok( !( "originalEvent" in event ), "originalEvent" ); + equal( ui.oldTab.length, 0, "oldTab length" ); + equal( ui.oldPanel.length, 0, "oldPanel length" ); + equal( ui.newTab.length, 1, "newTab length" ); + strictEqual( ui.newTab[ 0 ], tabs[ 0 ], "newTab" ); + equal( ui.newPanel.length, 1, "newPanel length" ); + strictEqual( ui.newPanel[ 0 ], panels[ 0 ], "newPanel" ); + state( element, 0, 0, 0 ); + }); + element.tabs( "option", "active", 0 ); + state( element, 1, 0, 0 ); + + // switching tabs + element.one( "tabsbeforeactivate", function( event, ui ) { + equal( event.originalEvent.type, "click", "originalEvent" ); + equal( ui.oldTab.length, 1, "oldTab length" ); + strictEqual( ui.oldTab[ 0 ], tabs[ 0 ], "oldTab" ); + equal( ui.oldPanel.length, 1, "oldPanel length" ); + strictEqual( ui.oldPanel[ 0 ], panels[ 0 ], "oldPanel" ); + equal( ui.newTab.length, 1, "newTab length" ); + strictEqual( ui.newTab[ 0 ], tabs[ 1 ], "newTab" ); + equal( ui.newPanel.length, 1, "newPanel length" ); + strictEqual( ui.newPanel[ 0 ], panels[ 1 ], "newPanel" ); + state( element, 1, 0, 0 ); + }); + anchors.eq( 1 ).click(); + state( element, 0, 1, 0 ); + + // collapsing + element.one( "tabsbeforeactivate", function( event, ui ) { + ok( !( "originalEvent" in event ), "originalEvent" ); + equal( ui.oldTab.length, 1, "oldTab length" ); + strictEqual( ui.oldTab[ 0 ], tabs[ 1 ], "oldTab" ); + equal( ui.oldPanel.length, 1, "oldPanel length" ); + strictEqual( ui.oldPanel[ 0 ], panels[ 1 ], "oldPanel" ); + equal( ui.newTab.length, 0, "newTab length" ); + equal( ui.newPanel.length, 0, "newPanel length" ); + state( element, 0, 1, 0 ); + }); + element.tabs( "option", "active", false ); + state( element, 0, 0, 0 ); + + // prevent activation + element.one( "tabsbeforeactivate", function( event, ui ) { + ok( !( "originalEvent" in event ), "originalEvent" ); + equal( ui.oldTab.length, 0, "oldTab length" ); + equal( ui.oldPanel.length, 0, "oldTab" ); + equal( ui.newTab.length, 1, "newTab length" ); + strictEqual( ui.newTab[ 0 ], tabs[ 1 ], "newTab" ); + equal( ui.newPanel.length, 1, "newPanel length" ); + strictEqual( ui.newPanel[ 0 ], panels[ 1 ], "newPanel" ); + event.preventDefault(); + state( element, 0, 0, 0 ); + }); + element.tabs( "option", "active", 1 ); + state( element, 0, 0, 0 ); +}); + +test( "activate", function() { + expect( 30 ); + + var element = $( "#tabs1" ).tabs({ + active: false, + collapsible: true + }), + tabs = element.find( ".ui-tabs-nav li" ), + anchors = element.find( ".ui-tabs-anchor" ), + panels = element.find( ".ui-tabs-panel" ); + + // from collapsed + element.one( "tabsactivate", function( event, ui ) { + ok( !( "originalEvent" in event ), "originalEvent" ); + equal( ui.oldTab.length, 0, "oldTab length" ); + equal( ui.oldPanel.length, 0, "oldPanel length" ); + equal( ui.newTab.length, 1, "newTab length" ); + strictEqual( ui.newTab[ 0 ], tabs[ 0 ], "newTab" ); + equal( ui.newPanel.length, 1, "newPanel length" ); + strictEqual( ui.newPanel[ 0 ], panels[ 0 ], "newPanel" ); + state( element, 1, 0, 0 ); + }); + element.tabs( "option", "active", 0 ); + state( element, 1, 0, 0 ); + + // switching tabs + element.one( "tabsactivate", function( event, ui ) { + equal( event.originalEvent.type, "click", "originalEvent" ); + equal( ui.oldTab.length, 1, "oldTab length" ); + strictEqual( ui.oldTab[ 0 ], tabs[ 0 ], "oldTab" ); + equal( ui.oldPanel.length, 1, "oldPanel length" ); + strictEqual( ui.oldPanel[ 0 ], panels[ 0 ], "oldPanel" ); + equal( ui.newTab.length, 1, "newTab length" ); + strictEqual( ui.newTab[ 0 ], tabs[ 1 ], "newTab" ); + equal( ui.newPanel.length, 1, "newPanel length" ); + strictEqual( ui.newPanel[ 0 ], panels[ 1 ], "newPanel" ); + state( element, 0, 1, 0 ); + }); + anchors.eq( 1 ).click(); + state( element, 0, 1, 0 ); + + // collapsing + element.one( "tabsactivate", function( event, ui ) { + ok( !( "originalEvent" in event ), "originalEvent" ); + equal( ui.oldTab.length, 1, "oldTab length" ); + strictEqual( ui.oldTab[ 0 ], tabs[ 1 ], "oldTab" ); + equal( ui.oldPanel.length, 1, "oldPanel length" ); + strictEqual( ui.oldPanel[ 0 ], panels[ 1 ], "oldPanel" ); + equal( ui.newTab.length, 0, "newTab length" ); + equal( ui.newPanel.length, 0, "newPanel length" ); + state( element, 0, 0, 0 ); + }); + element.tabs( "option", "active", false ); + state( element, 0, 0, 0 ); + + // prevent activation + element.one( "tabsbeforeactivate", function( event ) { + ok( true, "tabsbeforeactivate" ); + event.preventDefault(); + }); + element.one( "tabsactivate", function() { + ok( false, "tabsactivate" ); + }); + element.tabs( "option", "active", 1 ); +}); + +test( "beforeLoad", function() { + expect( 32 ); + + var tab, panelId, panel, + element = $( "#tabs2" ); + + // init + element.one( "tabsbeforeload", function( event, ui ) { + tab = element.find( ".ui-tabs-nav li" ).eq( 2 ); + panelId = tab.attr( "aria-controls" ); + panel = $( "#" + panelId ); + + ok( !( "originalEvent" in event ), "originalEvent" ); + ok( "abort" in ui.jqXHR, "jqXHR" ); + ok( ui.ajaxSettings.url, "data/test.html", "ajaxSettings.url" ); + equal( ui.tab.length, 1, "tab length" ); + strictEqual( ui.tab[ 0 ], tab[ 0 ], "tab" ); + equal( ui.panel.length, 1, "panel length" ); + strictEqual( ui.panel[ 0 ], panel[ 0 ], "panel" ); + equal( ui.panel.html(), "", "panel html" ); + event.preventDefault(); + state( element, 0, 0, 1, 0, 0 ); + }); + element.tabs({ active: 2 }); + state( element, 0, 0, 1, 0, 0 ); + equal( panel.html(), "", "panel html after" ); + element.tabs( "destroy" ); + + // .option() + element.one( "tabsbeforeload", function( event, ui ) { + tab = element.find( ".ui-tabs-nav li" ).eq( 2 ); + panelId = tab.attr( "aria-controls" ); + panel = $( "#" + panelId ); + + ok( !( "originalEvent" in event ), "originalEvent" ); + ok( "abort" in ui.jqXHR, "jqXHR" ); + ok( ui.ajaxSettings.url, "data/test.html", "ajaxSettings.url" ); + equal( ui.tab.length, 1, "tab length" ); + strictEqual( ui.tab[ 0 ], tab[ 0 ], "tab" ); + equal( ui.panel.length, 1, "panel length" ); + strictEqual( ui.panel[ 0 ], panel[ 0 ], "panel" ); + equal( ui.panel.html(), "", "panel html" ); + event.preventDefault(); + state( element, 1, 0, 0, 0, 0 ); + }); + element.tabs(); + element.tabs( "option", "active", 2 ); + state( element, 0, 0, 1, 0, 0 ); + equal( panel.html(), "", "panel html after" ); + + // click, change panel content + element.one( "tabsbeforeload", function( event, ui ) { + tab = element.find( ".ui-tabs-nav li" ).eq( 3 ); + panelId = tab.attr( "aria-controls" ); + panel = $( "#" + panelId ); + + equal( event.originalEvent.type, "click", "originalEvent" ); + ok( "abort" in ui.jqXHR, "jqXHR" ); + ok( ui.ajaxSettings.url, "data/test.html", "ajaxSettings.url" ); + equal( ui.tab.length, 1, "tab length" ); + strictEqual( ui.tab[ 0 ], tab[ 0 ], "tab" ); + equal( ui.panel.length, 1, "panel length" ); + strictEqual( ui.panel[ 0 ], panel[ 0 ], "panel" ); + ui.panel.html( "<p>testing</p>" ); + event.preventDefault(); + state( element, 0, 0, 1, 0, 0 ); + }); + element.find( ".ui-tabs-nav .ui-tabs-anchor" ).eq( 3 ).click(); + state( element, 0, 0, 0, 1, 0 ); + // .toLowerCase() is needed to convert <P> to <p> in old IEs + equal( panel.html().toLowerCase(), "<p>testing</p>", "panel html after" ); +}); + +asyncTest( "load", function() { + expect( 21 ); + + var tab, panelId, panel, + element = $( "#tabs2" ); + + // init + element.one( "tabsload", function( event, ui ) { + tab = element.find( ".ui-tabs-nav li" ).eq( 2 ); + panelId = tab.attr( "aria-controls" ); + panel = $( "#" + panelId ); + + ok( !( "originalEvent" in event ), "originalEvent" ); + equal( ui.tab.length, 1, "tab length" ); + strictEqual( ui.tab[ 0 ], tab[ 0 ], "tab" ); + equal( ui.panel.length, 1, "panel length" ); + strictEqual( ui.panel[ 0 ], panel[ 0 ], "panel" ); + equal( ui.panel.find( "p" ).length, 1, "panel html" ); + state( element, 0, 0, 1, 0, 0 ); + tabsload1(); + }); + element.tabs({ active: 2 }); + + function tabsload1() { + // .option() + element.one( "tabsload", function( event, ui ) { + tab = element.find( ".ui-tabs-nav li" ).eq( 3 ); + panelId = tab.attr( "aria-controls" ); + panel = $( "#" + panelId ); + + ok( !( "originalEvent" in event ), "originalEvent" ); + equal( ui.tab.length, 1, "tab length" ); + strictEqual( ui.tab[ 0 ], tab[ 0 ], "tab" ); + equal( ui.panel.length, 1, "panel length" ); + strictEqual( ui.panel[ 0 ], panel[ 0 ], "panel" ); + equal( ui.panel.find( "p" ).length, 1, "panel html" ); + state( element, 0, 0, 0, 1, 0 ); + tabsload2(); + }); + element.tabs( "option", "active", 3 ); + } + + function tabsload2() { + // click, change panel content + element.one( "tabsload", function( event, ui ) { + tab = element.find( ".ui-tabs-nav li" ).eq( 4 ); + panelId = tab.attr( "aria-controls" ); + panel = $( "#" + panelId ); + + equal( event.originalEvent.type, "click", "originalEvent" ); + equal( ui.tab.length, 1, "tab length" ); + strictEqual( ui.tab[ 0 ], tab[ 0 ], "tab" ); + equal( ui.panel.length, 1, "panel length" ); + strictEqual( ui.panel[ 0 ], panel[ 0 ], "panel" ); + equal( ui.panel.find( "p" ).length, 1, "panel html" ); + state( element, 0, 0, 0, 0, 1 ); + start(); + }); + element.find( ".ui-tabs-nav .ui-tabs-anchor" ).eq( 4 ).click(); + } +}); + +}( jQuery ) ); diff --git a/apps/it/static/js/ui/tests/unit/tabs/tabs_methods.js b/apps/it/static/js/ui/tests/unit/tabs/tabs_methods.js new file mode 100644 index 0000000..a3d663f --- /dev/null +++ b/apps/it/static/js/ui/tests/unit/tabs/tabs_methods.js @@ -0,0 +1,270 @@ +(function( $ ) { + +var disabled = TestHelpers.tabs.disabled, + state = TestHelpers.tabs.state; + +module( "tabs: methods" ); + +test( "destroy", function() { + expect( 2 ); + domEqual( "#tabs1", function() { + $( "#tabs1" ).tabs().tabs( "destroy" ); + }); + domEqual( "#tabs2", function() { + $( "#tabs2" ).tabs().tabs( "destroy" ); + }); +}); + +test( "enable", function() { + expect( 8 ); + + var element = $( "#tabs1" ).tabs({ disabled: true }); + disabled( element, true ); + element.tabs( "enable" ); + disabled( element, false ); + element.tabs( "destroy" ); + + element.tabs({ disabled: [ 0, 1 ] }); + disabled( element, [ 0, 1 ] ); + element.tabs( "enable" ); + disabled( element, false ); +}); + +test( "enable( index )", function() { + expect( 10 ); + + var element = $( "#tabs1" ).tabs({ disabled: true }); + disabled( element, true ); + // fully disabled -> partially disabled + element.tabs( "enable", 1 ); + disabled( element, [ 0, 2 ] ); + // partially disabled -> partially disabled + element.tabs( "enable", 2 ); + disabled( element, [ 0 ] ); + // already enabled tab, no change + element.tabs( "enable", 2 ); + disabled( element, [ 0 ] ); + // partially disabled -> fully enabled + element.tabs( "enable", 0 ); + disabled( element, false ); +}); + +test( "disable", function() { + expect( 8 ); + + var element = $( "#tabs1" ).tabs({ disabled: false }); + disabled( element, false ); + element.tabs( "disable" ); + disabled( element, true ); + element.tabs( "destroy" ); + + element.tabs({ disabled: [ 0, 1 ] }); + disabled( element, [ 0, 1 ] ); + element.tabs( "disable" ); + disabled( element, true ); +}); + +test( "disable( index )", function() { + expect( 10 ); + + var element = $( "#tabs1" ).tabs({ disabled: false }); + disabled( element, false ); + // fully enabled -> partially disabled + element.tabs( "disable", 1 ); + disabled( element, [ 1 ] ); + // partially disabled -> partially disabled + element.tabs( "disable", 2 ); + disabled( element, [ 1, 2 ] ); + // already disabled tab, no change + element.tabs( "disable", 2 ); + disabled( element, [ 1, 2 ] ); + // partially disabled -> fully disabled + element.tabs( "disable", 0 ); + disabled( element, true ); +}); + +test( "refresh", function() { + expect( 27 ); + + var element = $( "#tabs1" ).tabs(); + state( element, 1, 0, 0 ); + disabled( element, false ); + + // disable tab via markup + element.find( ".ui-tabs-nav li" ).eq( 1 ).addClass( "ui-state-disabled" ); + element.tabs( "refresh" ); + state( element, 1, 0, 0 ); + disabled( element, [ 1 ] ); + + // add remote tab + element.find( ".ui-tabs-nav" ).append( "<li id='newTab'><a href='data/test.html'>new</a></li>" ); + element.tabs( "refresh" ); + state( element, 1, 0, 0, 0 ); + disabled( element, [ 1 ] ); + equal( element.find( "#" + $( "#newTab" ).attr( "aria-controls" ) ).length, 1, + "panel added for remote tab" ); + + // remove all tabs + element.find( ".ui-tabs-nav li, .ui-tabs-panel" ).remove(); + element.tabs( "refresh" ); + state( element ); + equal( element.tabs( "option", "active" ), false, "no active tab" ); + + // add tabs + element.find( ".ui-tabs-nav" ) + .append( "<li class='ui-state-disabled'><a href='#newTab2'>new 2</a></li>" ) + .append( "<li><a href='#newTab3'>new 3</a></li>" ) + .append( "<li><a href='#newTab4'>new 4</a></li>" ) + .append( "<li><a href='#newTab5'>new 5</a></li>" ); + element + .append( "<div id='newTab2'>new 2</div>" ) + .append( "<div id='newTab3'>new 3</div>" ) + .append( "<div id='newTab4'>new 4</div>" ) + .append( "<div id='newTab5'>new 5</div>" ); + element.tabs( "refresh" ); + state( element, 0, 0, 0, 0 ); + disabled( element, [ 0 ] ); + + // activate third tab + element.tabs( "option", "active", 2 ); + state( element, 0, 0, 1, 0 ); + disabled( element, [ 0 ] ); + + // remove fourth tab, third tab should stay active + element.find( ".ui-tabs-nav li" ).eq( 3 ).remove(); + element.find( ".ui-tabs-panel" ).eq( 3 ).remove(); + element.tabs( "refresh" ); + state( element, 0, 0, 1 ); + disabled( element, [ 0 ] ); + + // remove third (active) tab, second tab should become active + element.find( ".ui-tabs-nav li" ).eq( 2 ).remove(); + element.find( ".ui-tabs-panel" ).eq( 2 ).remove(); + element.tabs( "refresh" ); + state( element, 0, 1 ); + disabled( element, [ 0 ] ); + + // remove first tab, previously active tab (now first) should stay active + element.find( ".ui-tabs-nav li" ).eq( 0 ).remove(); + element.find( ".ui-tabs-panel" ).eq( 0 ).remove(); + element.tabs( "refresh" ); + state( element, 1 ); + disabled( element, false ); +}); + +test( "refresh - looping", function() { + expect( 6 ); + + var element = $( "#tabs1" ).tabs({ + disabled: [ 0 ], + active: 1 + }); + state( element, 0, 1, 0 ); + disabled( element, [ 0 ] ); + + // remove active, jump to previous + // previous is disabled, just back one more + // reached first tab, move to end + // activate last tab + element.find( ".ui-tabs-nav li" ).eq( 2 ).remove(); + element.tabs( "refresh" ); + state( element, 0, 1 ); + disabled( element, [ 0 ] ); +}); + +asyncTest( "load", function() { + expect( 30 ); + + var element = $( "#tabs2" ).tabs(); + + // load content of inactive tab + // useful for preloading content with custom caching + element.one( "tabsbeforeload", function( event, ui ) { + var tab = element.find( ".ui-tabs-nav li" ).eq( 3 ), + panelId = tab.attr( "aria-controls" ), + panel = $( "#" + panelId ); + + ok( !( "originalEvent" in event ), "originalEvent" ); + equal( ui.tab.length, 1, "tab length" ); + strictEqual( ui.tab[ 0 ], tab[ 0 ], "tab" ); + equal( ui.panel.length, 1, "panel length" ); + strictEqual( ui.panel[ 0 ], panel[ 0 ], "panel" ); + state( element, 1, 0, 0, 0, 0 ); + }); + element.one( "tabsload", function( event, ui ) { + // TODO: remove wrapping in 2.0 + var uiTab = $( ui.tab ), + uiPanel = $( ui.panel ), + tab = element.find( ".ui-tabs-nav li" ).eq( 3 ), + panelId = tab.attr( "aria-controls" ), + panel = $( "#" + panelId ); + + ok( !( "originalEvent" in event ), "originalEvent" ); + equal( uiTab.length, 1, "tab length" ); + strictEqual( uiTab[ 0 ], tab[ 0 ], "tab" ); + equal( uiPanel.length, 1, "panel length" ); + strictEqual( uiPanel[ 0 ], panel[ 0 ], "panel" ); + equal( uiPanel.find( "p" ).length, 1, "panel html" ); + state( element, 1, 0, 0, 0, 0 ); + setTimeout( tabsload1, 100 ); + }); + element.tabs( "load", 3 ); + state( element, 1, 0, 0, 0, 0 ); + + function tabsload1() { + // no need to test details of event (tested in events tests) + element.one( "tabsbeforeload", function() { + ok( true, "tabsbeforeload invoked" ); + }); + element.one( "tabsload", function() { + ok( true, "tabsload invoked" ); + setTimeout( tabsload2, 100 ); + }); + element.tabs( "option", "active", 3 ); + state( element, 0, 0, 0, 1, 0 ); + } + + function tabsload2() { + // reload content of active tab + element.one( "tabsbeforeload", function( event, ui ) { + var tab = element.find( ".ui-tabs-nav li" ).eq( 3 ), + panelId = tab.attr( "aria-controls" ), + panel = $( "#" + panelId ); + + ok( !( "originalEvent" in event ), "originalEvent" ); + equal( ui.tab.length, 1, "tab length" ); + strictEqual( ui.tab[ 0 ], tab[ 0 ], "tab" ); + equal( ui.panel.length, 1, "panel length" ); + strictEqual( ui.panel[ 0 ], panel[ 0 ], "panel" ); + state( element, 0, 0, 0, 1, 0 ); + }); + element.one( "tabsload", function( event, ui ) { + // TODO: remove wrapping in 2.0 + var uiTab = $( ui.tab ), + uiPanel = $( ui.panel ), + tab = element.find( ".ui-tabs-nav li" ).eq( 3 ), + panelId = tab.attr( "aria-controls" ), + panel = $( "#" + panelId ); + + ok( !( "originalEvent" in event ), "originalEvent" ); + equal( uiTab.length, 1, "tab length" ); + strictEqual( uiTab[ 0 ], tab[ 0 ], "tab" ); + equal( uiPanel.length, 1, "panel length" ); + strictEqual( uiPanel[ 0 ], panel[ 0 ], "panel" ); + state( element, 0, 0, 0, 1, 0 ); + start(); + }); + element.tabs( "load", 3 ); + state( element, 0, 0, 0, 1, 0 ); + } +}); + +test( "widget", function() { + expect( 2 ); + var element = $( "#tabs1" ).tabs(), + widgetElement = element.tabs( "widget" ); + equal( widgetElement.length, 1, "one element" ); + strictEqual( widgetElement[ 0 ], element[ 0 ], "same element" ); +}); + +}( jQuery ) ); diff --git a/apps/it/static/js/ui/tests/unit/tabs/tabs_options.js b/apps/it/static/js/ui/tests/unit/tabs/tabs_options.js new file mode 100644 index 0000000..c78c42b --- /dev/null +++ b/apps/it/static/js/ui/tests/unit/tabs/tabs_options.js @@ -0,0 +1,345 @@ +(function( $ ) { + +var disabled = TestHelpers.tabs.disabled, + equalHeight = TestHelpers.tabs.equalHeight, + state = TestHelpers.tabs.state; + +module( "tabs: options" ); + +test( "{ active: default }", function() { + expect( 6 ); + + var element = $( "#tabs1" ).tabs(); + equal( element.tabs( "option", "active" ), 0, "should be 0 by default" ); + state( element, 1, 0, 0 ); + element.tabs( "destroy" ); + + location.hash = "#fragment-3"; + element = $( "#tabs1" ).tabs(); + equal( element.tabs( "option", "active" ), 2, "should be 2 based on URL" ); + state( element, 0, 0, 1 ); + element.tabs( "destroy" ); + + location.hash = "#custom-id"; + element = $( "#tabs2" ).tabs(); + equal( element.tabs( "option", "active" ), 3, "should be 3 based on URL" ); + state( element, 0, 0, 0, 1, 0 ); + element.tabs( "destroy" ); + location.hash = "#"; +}); + +test( "{ active: false }", function() { + expect( 7 ); + + var element = $( "#tabs1" ).tabs({ + active: false, + collapsible: true + }); + state( element, 0, 0, 0 ); + equal( element.find( ".ui-tabs-nav .ui-state-active" ).length, 0, "no tabs selected" ); + strictEqual( element.tabs( "option", "active" ), false ); + + element.tabs( "option", "collapsible", false ); + state( element, 1, 0, 0 ); + equal( element.tabs( "option", "active" ), 0 ); + + element.tabs( "destroy" ); + element.tabs({ + active: false + }); + state( element, 1, 0, 0 ); + strictEqual( element.tabs( "option", "active" ), 0 ); +}); + +test( "{ active: Number }", function() { + expect( 8 ); + + var element = $( "#tabs1" ).tabs({ + active: 2 + }); + equal( element.tabs( "option", "active" ), 2 ); + state( element, 0, 0, 1 ); + + element.tabs( "option", "active", 0 ); + equal( element.tabs( "option", "active" ), 0 ); + state( element, 1, 0, 0 ); + + element.find( ".ui-tabs-nav .ui-tabs-anchor" ).eq( 1 ).click(); + equal( element.tabs( "option", "active" ), 1 ); + state( element, 0, 1, 0 ); + + element.tabs( "option", "active", 10 ); + equal( element.tabs( "option", "active" ), 1 ); + state( element, 0, 1, 0 ); +}); + +test( "{ active: -Number }", function() { + expect( 8 ); + + var element = $( "#tabs1" ).tabs({ + active: -1 + }); + equal( element.tabs( "option", "active" ), 2 ); + state( element, 0, 0, 1 ); + + element.tabs( "option", "active", -2 ); + equal( element.tabs( "option", "active" ), 1 ); + state( element, 0, 1, 0 ); + + element.tabs( "option", "active", -10 ); + equal( element.tabs( "option", "active" ), 1 ); + state( element, 0, 1, 0 ); + + element.tabs( "option", "active", -3 ); + equal( element.tabs( "option", "active" ), 0 ); + state( element, 1, 0, 0 ); +}); + +test( "active - mismatched tab/panel order", function() { + expect( 3 ); + + location.hash = "#tabs7-2"; + var element = $( "#tabs7" ).tabs(); + equal( element.tabs( "option", "active" ), 1, "should be 1 based on URL" ); + state( element, 0, 1 ); + element.tabs( "option", "active", 0 ); + state( element, 1, 0 ); + location.hash = "#"; +}); + +test( "{ collapsible: false }", function() { + expect( 4 ); + + var element = $( "#tabs1" ).tabs({ + active: 1 + }); + element.tabs( "option", "active", false ); + equal( element.tabs( "option", "active" ), 1 ); + state( element, 0, 1, 0 ); + + element.find( ".ui-state-active .ui-tabs-anchor" ).eq( 1 ).click(); + equal( element.tabs( "option", "active" ), 1 ); + state( element, 0, 1, 0 ); +}); + +test( "{ collapsible: true }", function() { + expect( 6 ); + + var element = $( "#tabs1" ).tabs({ + active: 1, + collapsible: true + }); + + element.tabs( "option", "active", false ); + equal( element.tabs( "option", "active" ), false ); + state( element, 0, 0, 0 ); + + element.tabs( "option", "active", 1 ); + equal( element.tabs( "option", "active" ), 1 ); + state( element, 0, 1, 0 ); + + element.find( ".ui-state-active .ui-tabs-anchor" ).click(); + equal( element.tabs( "option", "active" ), false ); + state( element, 0, 0, 0 ); +}); + +test( "disabled", function() { + expect( 10 ); + + // fully enabled by default + var element = $( "#tabs1" ).tabs(); + disabled( element, false ); + + // disable single tab + element.tabs( "option", "disabled", [ 1 ] ); + disabled( element, [ 1 ] ); + + // disabled active tab + element.tabs( "option", "disabled", [ 0, 1 ] ); + disabled( element, [ 0, 1 ] ); + + // disable all tabs + element.tabs( "option", "disabled", [ 0, 1, 2 ] ); + disabled( element, true ); + + // enable all tabs + element.tabs( "option", "disabled", [] ); + disabled( element, false ); +}); + +test( "{ event: null }", function() { + expect( 5 ); + + var element = $( "#tabs1" ).tabs({ + event: null + }); + state( element, 1, 0, 0 ); + + element.tabs( "option", "active", 1 ); + equal( element.tabs( "option", "active" ), 1 ); + state( element, 0, 1, 0 ); + + // ensure default click handler isn't bound + element.find( ".ui-tabs-nav .ui-tabs-anchor" ).eq( 2 ).click(); + equal( element.tabs( "option", "active" ), 1 ); + state( element, 0, 1, 0 ); +}); + +test( "{ event: custom }", function() { + expect( 11 ); + + var element = $( "#tabs1" ).tabs({ + event: "custom1 custom2" + }); + state( element, 1, 0, 0 ); + + element.find( ".ui-tabs-nav .ui-tabs-anchor" ).eq( 1 ).trigger( "custom1" ); + equal( element.tabs( "option", "active" ), 1 ); + state( element, 0, 1, 0 ); + + // ensure default click handler isn't bound + element.find( ".ui-tabs-nav .ui-tabs-anchor" ).eq( 2 ).trigger( "click" ); + equal( element.tabs( "option", "active" ), 1 ); + state( element, 0, 1, 0 ); + + element.find( ".ui-tabs-nav .ui-tabs-anchor" ).eq( 2 ).trigger( "custom2" ); + equal( element.tabs( "option", "active" ), 2 ); + state( element, 0, 0, 1 ); + + element.tabs( "option", "event", "custom3" ); + + // ensure old event handlers are unbound + element.find( ".ui-tabs-nav .ui-tabs-anchor" ).eq( 1 ).trigger( "custom1" ); + equal( element.tabs( "option", "active" ), 2 ); + state( element, 0, 0, 1 ); + + element.find( ".ui-tabs-nav .ui-tabs-anchor" ).eq( 1 ).trigger( "custom3" ); + equal( element.tabs( "option", "active" ), 1 ); + state( element, 0, 1, 0 ); +}); + +test( "{ heightStyle: 'auto' }", function() { + expect( 2 ); + var element = $( "#tabs8" ).tabs({ heightStyle: "auto" }); + equalHeight( element, 45 ); +}); + +test( "{ heightStyle: 'content' }", function() { + expect( 2 ); + var element = $( "#tabs8" ).tabs({ heightStyle: "content" }), + sizes = element.find( ".ui-tabs-panel" ).map(function() { + return $( this ).height(); + }).get(); + equal( sizes[ 0 ], 45 ); + equal( sizes[ 1 ], 15 ); +}); + +test( "{ heightStyle: 'fill' }", function() { + expect( 4 ); + $( "#tabs8Wrapper" ).height( 500 ); + var element = $( "#tabs8" ).tabs({ heightStyle: "fill" }); + equalHeight( element, 485 ); + element.tabs( "destroy" ); + + element = $( "#tabs8" ).css({ + "border": "1px solid black", + "padding": "1px 0" + }); + element.tabs({ heightStyle: "fill" }); + equalHeight( element, 481 ); +}); + +test( "{ heightStyle: 'fill' } with sibling", function() { + expect( 2 ); + $( "#tabs8Wrapper" ).height( 500 ); + $( "<p>Lorem Ipsum</p>" ) + .css({ + height: 50, + marginTop: 20, + marginBottom: 30 + }) + .prependTo( "#tabs8Wrapper" ); + var element = $( "#tabs8" ).tabs({ heightStyle: "fill" }); + equalHeight( element, 385 ); +}); + +test( "{ heightStyle: 'fill' } with multiple siblings", function() { + expect( 2 ); + $( "#tabs8Wrapper" ).height( 500 ); + $( "<p>Lorem Ipsum</p>" ) + .css({ + height: 50, + marginTop: 20, + marginBottom: 30 + }) + .prependTo( "#tabs8Wrapper" ); + $( "<p>Lorem Ipsum</p>" ) + .css({ + height: 50, + marginTop: 20, + marginBottom: 30, + position: "absolute" + }) + .prependTo( "#tabs8Wrapper" ); + $( "<p>Lorem Ipsum</p>" ) + .css({ + height: 25, + marginTop: 10, + marginBottom: 15 + }) + .prependTo( "#tabs8Wrapper" ); + var element = $( "#tabs8" ).tabs({ heightStyle: "fill" }); + equalHeight( element, 335 ); +}); + +test( "hide and show: false", function() { + expect( 3 ); + var element = $( "#tabs1" ).tabs({ + show: false, + hide: false + }), + widget = element.data( "ui-tabs" ), + panels = element.find( ".ui-tabs-panel" ); + widget._show = function() { + ok( false, "_show() called" ); + }; + widget._hide = function() { + ok( false, "_hide() called" ); + }; + + ok( panels.eq( 0 ).is( ":visible" ), "first panel visible" ); + element.tabs( "option", "active", 1 ); + ok( panels.eq( 0 ).is( ":hidden" ), "first panel hidden" ); + ok( panels.eq( 1 ).is( ":visible" ), "second panel visible" ); +}); + +asyncTest( "hide and show - animation", function() { + expect( 5 ); + var element = $( "#tabs1" ).tabs({ + show: "drop", + hide: 2000 + }), + widget = element.data( "ui-tabs" ), + panels = element.find( ".ui-tabs-panel" ); + widget._show = function( element, options, callback ) { + strictEqual( element[ 0 ], panels[ 1 ], "correct element in _show()" ); + equal( options, "drop", "correct options in _show()" ); + setTimeout(function() { + callback(); + }, 1 ); + }; + widget._hide = function( element, options, callback ) { + strictEqual( element[ 0 ], panels[ 0 ], "correct element in _hide()" ); + equal( options, 2000, "correct options in _hide()" ); + setTimeout(function() { + callback(); + start(); + }, 1 ); + }; + + ok( panels.eq( 0 ).is( ":visible" ), "first panel visible" ); + element.tabs( "option", "active", 1 ); +}); + + +}( jQuery ) ); diff --git a/apps/it/static/js/ui/tests/unit/tabs/tabs_test_helpers.js b/apps/it/static/js/ui/tests/unit/tabs/tabs_test_helpers.js new file mode 100644 index 0000000..0c93091 --- /dev/null +++ b/apps/it/static/js/ui/tests/unit/tabs/tabs_test_helpers.js @@ -0,0 +1,67 @@ +TestHelpers.tabs = { + disabled: function( tabs, state ) { + var expected, actual, + internalState = tabs.tabs( "option", "disabled" ); + + if ( internalState === false ) { + internalState = []; + } + if ( internalState === true ) { + internalState = $.map( new Array( tabs.find( ".ui-tabs-nav li" ).length ), function( _, index ) { + return index; + }); + } + + expected = $.map( new Array( tabs.find ( ".ui-tabs-nav li" ).length ), function( _, index ) { + if ( typeof state === "boolean" ) { + return state ? 1 : 0; + } else { + return $.inArray( index, state ) !== -1 ? 1 : 0; + } + }); + + actual = tabs.find( ".ui-tabs-nav li" ).map(function( index ) { + var tab = $( this ), + tabIsDisabled = tab.hasClass( "ui-state-disabled" ); + + if ( tabIsDisabled && $.inArray( index, internalState ) !== -1 ) { + return 1; + } + if ( !tabIsDisabled && $.inArray( index, internalState ) === -1 ) { + return 0; + } + // mixed state - invalid + return -1; + }).get(); + + deepEqual( tabs.tabs( "option", "disabled" ), state ); + deepEqual( actual, expected ); + }, + + equalHeight: function( tabs, height ) { + tabs.find( ".ui-tabs-panel" ).each(function() { + equal( $( this ).outerHeight(), height ); + }); + }, + + state: function( tabs ) { + var expected = $.makeArray( arguments ).slice( 1 ), + actual = tabs.find( ".ui-tabs-nav li" ).map(function() { + var tab = $( this ), + panel = $( $.ui.tabs.prototype._sanitizeSelector( + "#" + tab.attr( "aria-controls" ) ) ), + tabIsActive = tab.hasClass( "ui-state-active" ), + panelIsActive = panel.css( "display" ) !== "none"; + + if ( tabIsActive && panelIsActive ) { + return 1; + } + if ( !tabIsActive && !panelIsActive ) { + return 0; + } + return -1; // mixed state - invalid + }).get(); + deepEqual( actual, expected ); + } +}; + |