2 * mobile navigation unit tests
5 // TODO move siteDirectory over to the nav path helper
6 var changePageFn = $.mobile.changePage,
7 originalTitle = document.title,
8 originalLinkBinding = $.mobile.linkBindingEnabled,
9 siteDirectory = location.pathname.replace( /[^/]+$/, "" ),
10 home = $.mobile.path.parseUrl(location.pathname).directory,
11 navigateTestRoot = function(){
12 $.testHelper.openPage( "#" + location.pathname + location.search );
15 module('jquery.mobile.navigation.js', {
17 $.mobile.changePage = changePageFn;
18 document.title = originalTitle;
20 var pageReset = function( hash ) {
25 $(document).one( "pagechange", function() {
29 location.hash = "#" + hash;
32 // force the page reset for hash based tests
33 if ( location.hash && !$.support.pushState ) {
37 // force the page reset for all pushstate tests
38 if ( $.support.pushState ) {
42 $.mobile.urlHistory.stack = [];
43 $.mobile.urlHistory.activeIndex = 0;
44 $.Event.prototype.which = undefined;
45 $.mobile.linkBindingEnabled = originalLinkBinding;
49 asyncTest( "window.history.back() from external to internal page", function(){
51 $.testHelper.pageSequence([
55 $.testHelper.openPage("#active-state-page1");
59 ok( $.mobile.activePage[0] === $( "#active-state-page1" )[ 0 ], "successful navigation to internal page." );
61 //location.hash = siteDirectory + "external.html";
62 $.mobile.changePage("external.html");
66 ok( $.mobile.activePage[0] !== $( "#active-state-page1" )[ 0 ], "successful navigation to external page." );
68 window.history.back();
72 ok( $.mobile.activePage[0] === $( "#active-state-page1" )[ 0 ], "successful navigation back to internal page." );
79 asyncTest( "external page is removed from the DOM after pagehide", function(){
80 $.testHelper.pageSequence([
84 $.mobile.changePage( "external.html" );
87 // page is pulled and displayed in the dom
89 same( $( "#external-test" ).length, 1 );
90 window.history.back();
93 // external-test is *NOT* cached in the dom after transitioning away
95 same( $( "#external-test" ).length, 0 );
101 asyncTest( "preventDefault on pageremove event can prevent external page from being removed from the DOM", function(){
102 var preventRemoval = true,
103 removeCallback = function( e ) {
104 if ( preventRemoval ) {
109 $( document ).bind( "pageremove", removeCallback );
111 $.testHelper.pageSequence([
115 $.mobile.changePage( "external.html" );
118 // page is pulled and displayed in the dom
120 same( $( "#external-test" ).length, 1 );
121 window.history.back();
124 // external-test *IS* cached in the dom after transitioning away
126 same( $( "#external-test" ).length, 1 );
128 // Switch back to the page again!
129 $.mobile.changePage( "external.html" );
132 // page is still present and displayed in the dom
134 same( $( "#external-test" ).length, 1 );
136 // Now turn off our removal prevention.
137 preventRemoval = false;
139 window.history.back();
142 // external-test is *NOT* cached in the dom after transitioning away
144 same( $( "#external-test" ).length, 0 );
145 $( document ).unbind( "pageremove", removeCallback );
151 asyncTest( "external page is cached in the DOM after pagehide", function(){
152 $.testHelper.pageSequence([
156 $.mobile.changePage( "cached-external.html" );
159 // page is pulled and displayed in the dom
161 same( $( "#external-test-cached" ).length, 1 );
162 window.history.back();
165 // external test page is cached in the dom after transitioning away
167 same( $( "#external-test-cached" ).length, 1 );
173 asyncTest( "external page is cached in the DOM after pagehide when option is set globally", function(){
174 $.testHelper.pageSequence([
178 $.mobile.page.prototype.options.domCache = true;
179 $.mobile.changePage( "external.html" );
182 // page is pulled and displayed in the dom
184 same( $( "#external-test" ).length, 1 );
185 window.history.back();
188 // external test page is cached in the dom after transitioning away
190 same( $( "#external-test" ).length, 1 );
191 $.mobile.page.prototype.options.domCache = false;
192 $( "#external-test" ).remove();
197 asyncTest( "page last scroll distance is remembered while navigating to and from pages", function(){
198 $.testHelper.pageSequence([
200 $( "body" ).height( $( window ).height() + 500 );
201 $.mobile.changePage( "external.html" );
205 // wait for the initial scroll to 0
206 setTimeout( function() {
207 window.scrollTo( 0, 300 );
208 same( $(window).scrollTop(), 300, "scrollTop is 300 after setting it" );
211 // wait for the scrollstop to fire and for the scroll to be
212 // recorded 100 ms afterward (see changes made to handle hash
213 // scrolling in some browsers)
214 setTimeout( navigateTestRoot, 500 );
222 // Give the silentScroll function some time to kick in.
223 setTimeout(function() {
224 same( $(window).scrollTop(), 300, "scrollTop is 300 after returning to the page" );
225 $( "body" ).height( "" );
232 asyncTest( "forms with data attribute ajax set to false will not call changePage", function(){
234 var newChangePage = function(){
238 $.testHelper.sequence([
239 // avoid initial page load triggering changePage early
241 $.mobile.changePage = newChangePage;
243 $('#non-ajax-form').one('submit', function(event){
244 ok(true, 'submit callbacks are fired');
245 event.preventDefault();
250 ok(!called, "change page should not be called");
255 asyncTest( "forms with data attribute ajax not set or set to anything but false will call changePage", function(){
257 newChangePage = function(){
261 $.testHelper.sequence([
262 // avoid initial page load triggering changePage early
264 $.mobile.changePage = newChangePage;
265 $('#ajax-form, #rand-ajax-form').submit();
269 ok(called >= 2, "change page should be called at least twice");
275 asyncTest( "anchors with no href attribute will do nothing when clicked", function(){
278 $(window).bind("hashchange.temp", function(){
282 $( "<a>test</a>" ).appendTo( $.mobile.firstPage ).click();
284 setTimeout(function(){
285 same(fired, false, "hash shouldn't change after click");
286 $(window).unbind("hashchange.temp");
291 test( "urlHistory is working properly", function(){
294 same( $.type( $.mobile.urlHistory.stack ), "array", "urlHistory.stack is an array" );
297 $.mobile.urlHistory.stack[0] = { url: "foo", transition: "bar" };
298 $.mobile.urlHistory.stack[1] = { url: "baz", transition: "shizam" };
299 $.mobile.urlHistory.stack[2] = { url: "shizoo", transition: "shizaah" };
302 same( $.mobile.urlHistory.activeIndex , 0, "urlHistory.activeIndex is 0" );
305 same( $.type( $.mobile.urlHistory.getActive() ) , "object", "active item is an object" );
306 same( $.mobile.urlHistory.getActive().url , "foo", "active item has url foo" );
307 same( $.mobile.urlHistory.getActive().transition , "bar", "active item has transition bar" );
310 same( $.mobile.urlHistory.getPrev(), undefined, "urlHistory.getPrev() is undefined when active index is 0" );
311 $.mobile.urlHistory.activeIndex = 1;
312 same( $.mobile.urlHistory.getPrev().url, "foo", "urlHistory.getPrev() has url foo when active index is 1" );
313 $.mobile.urlHistory.activeIndex = 0;
314 same( $.mobile.urlHistory.getNext().url, "baz", "urlHistory.getNext() has url baz when active index is 0" );
317 $.mobile.urlHistory.activeIndex = 2;
318 $.mobile.urlHistory.addNew("test");
319 same( $.mobile.urlHistory.stack.length, 4, "urlHistory.addNew() adds an item after the active index" );
320 same( $.mobile.urlHistory.activeIndex, 3, "urlHistory.addNew() moves the activeIndex to the newly added item" );
323 $.mobile.urlHistory.activeIndex = 0;
324 $.mobile.urlHistory.clearForward();
325 same( $.mobile.urlHistory.stack.length, 1, "urlHistory.clearForward() clears the url stack after the active index" );
329 function testListening( prop ){
330 var stillListening = false;
331 $(document).bind("pagebeforehide", function(){
332 stillListening = true;
334 location.hash = "foozball";
335 setTimeout(function(){
336 ok( prop == stillListening, prop + " = false disables default hashchange event handler");
343 asyncTest( "ability to disable our hash change event listening internally", function(){
344 testListening( ! $.mobile.urlHistory.ignoreNextHashChange );
347 asyncTest( "ability to disable our hash change event listening globally", function(){
348 testListening( $.mobile.hashListeningEnabled );
351 var testDataUrlHash = function( linkSelector, matches ) {
352 $.testHelper.pageSequence([
353 function(){ window.location.hash = ""; },
354 function(){ $(linkSelector).click(); },
356 $.testHelper.assertUrlLocation(
358 report: "url or hash should match"
369 test( "when loading a page where data-url is not defined on a sub element hash defaults to the url", function(){
370 testDataUrlHash( "#non-data-url a", {hashOrPush: siteDirectory + "data-url-tests/non-data-url.html"} );
373 test( "data url works for nested paths", function(){
374 var url = "foo/bar.html";
375 testDataUrlHash( "#nested-data-url a", {hash: url, push: home + url} );
378 test( "data url works for single quoted paths and roles", function(){
379 var url = "foo/bar/single.html";
380 testDataUrlHash( "#single-quotes-data-url a", {hash: url, push: home + url} );
383 test( "data url works when role and url are reversed on the page element", function(){
384 var url = "foo/bar/reverse.html";
385 testDataUrlHash( "#reverse-attr-data-url a", {hash: url, push: home + url} );
388 asyncTest( "last entry choosen amongst multiple identical url history stack entries on hash change", function(){
389 // make sure the stack is clear after initial page load an any other delayed page loads
390 // TODO better browser state management
391 $.mobile.urlHistory.stack = [];
392 $.mobile.urlHistory.activeIndex = 0;
394 $.testHelper.pageSequence([
395 function(){ $.testHelper.openPage("#dup-history-first"); },
396 function(){ $("#dup-history-first a").click(); },
397 function(){ $("#dup-history-second a:first").click(); },
398 function(){ $("#dup-history-first a").click(); },
399 function(){ $("#dup-history-second a:last").click(); },
400 function(){ $("#dup-history-dialog a:contains('Close')").click(); },
403 // fourth page (third index) in the stack to account for first page being hash manipulation,
404 // the third page is dup-history-second which has two entries in history
405 // the test is to make sure the index isn't 1 in this case, or the first entry for dup-history-second
406 same($.mobile.urlHistory.activeIndex, 3, "should be the fourth page in the stack");
411 asyncTest( "going back from a page entered from a dialog skips the dialog and goes to the previous page", function(){
412 $.testHelper.pageSequence([
414 function(){ $.testHelper.openPage("#skip-dialog-first"); },
416 // transition to the dialog
417 function(){ $("#skip-dialog-first a").click(); },
419 // transition to the second page
420 function(){ $("#skip-dialog a").click(); },
422 // transition past the dialog via data-rel=back link on the second page
423 function(){ $("#skip-dialog-second a").click(); },
425 // make sure we're at the first page and not the dialog
427 $.testHelper.assertUrlLocation({
428 hash: "skip-dialog-first",
429 push: home + "#skip-dialog-first",
430 report: "should be the first page in the sequence"
437 asyncTest( "going forward from a page entered from a dialog skips the dialog and goes to the next page", function(){
438 $.testHelper.pageSequence([
440 function(){ $.testHelper.openPage("#skip-dialog-first"); },
442 // transition to the dialog
443 function(){ $("#skip-dialog-first a").click(); },
445 // transition to the second page
446 function(){ $("#skip-dialog a").click(); },
448 // transition to back past the dialog
449 function(){ window.history.back(); },
451 // transition to the second page past the dialog through history
452 function(){ window.history.forward(); },
454 // make sure we're on the second page and not the dialog
456 $.testHelper.assertUrlLocation({
457 hash: "skip-dialog-second",
458 push: home + "#skip-dialog-second",
459 report: "should be the second page after the dialog"
466 asyncTest( "going back from a dialog triggered from a dialog should result in the first dialog ", function(){
467 $.testHelper.pageSequence([
469 function(){ $.testHelper.openPage("#nested-dialog-page"); },
471 // transition to the dialog
472 function(){ $("#nested-dialog-page a").click(); },
474 // transition to the second dialog
475 function(){ $("#nested-dialog-first a").click(); },
477 // transition to back to the first dialog
478 function(){ window.history.back(); },
480 // make sure we're on first dialog
482 same($(".ui-page-active")[0], $("#nested-dialog-first")[0], "should be the first dialog");
487 asyncTest( "loading a relative file path after an embeded page works", function(){
488 $.testHelper.pageSequence([
489 // transition second page
490 function(){ $.testHelper.openPage("#relative-after-embeded-page-first"); },
492 // transition second page
493 function(){ $("#relative-after-embeded-page-first a").click(); },
495 // transition to the relative ajax loaded page
496 function(){ $("#relative-after-embeded-page-second a").click(); },
498 // make sure the page was loaded properly via ajax
500 // data attribute intentionally left without namespace
501 same($(".ui-page-active").data("other"), "for testing", "should be relative ajax loaded page");
506 asyncTest( "Page title updates properly when clicking back to previous page", function(){
507 $.testHelper.pageSequence([
509 $.testHelper.openPage("#relative-after-embeded-page-first");
513 window.history.back();
517 same(document.title, "jQuery Mobile Navigation Test Suite");
523 asyncTest( "Page title updates properly when clicking a link back to first page", function(){
524 var title = document.title;
526 $.testHelper.pageSequence([
528 $.testHelper.openPage("#ajax-title-page");
532 $("#titletest1").click();
536 same(document.title, "Title Tag");
537 $.mobile.activePage.find("#title-check-link").click();
541 same(document.title, title);
547 asyncTest( "Page title updates properly from title tag when loading an external page", function(){
548 $.testHelper.pageSequence([
550 $.testHelper.openPage("#ajax-title-page");
554 $("#titletest1").click();
558 same(document.title, "Title Tag");
564 asyncTest( "Page title updates properly from data-title attr when loading an external page", function(){
565 $.testHelper.pageSequence([
567 $.testHelper.openPage("#ajax-title-page");
571 $("#titletest2").click();
575 same(document.title, "Title Attr");
581 asyncTest( "Page title updates properly from heading text in header when loading an external page", function(){
582 $.testHelper.pageSequence([
584 $.testHelper.openPage("#ajax-title-page");
588 $("#titletest3").click();
592 same(document.title, "Title Heading");
598 asyncTest( "Page links to the current active page result in the same active page", function(){
599 $.testHelper.pageSequence([
601 $.testHelper.openPage("#self-link");
605 $("a[href='#self-link']").click();
609 same($.mobile.activePage[0], $("#self-link")[0], "self-link page is still the active page" );
615 asyncTest( "links on subdirectory pages with query params append the params and load the page", function(){
616 $.testHelper.pageSequence([
618 $.testHelper.openPage("#data-url-tests/non-data-url.html");
622 $("#query-param-anchor").click();
626 $.testHelper.assertUrlLocation({
627 hashOrPush: home + "data-url-tests/non-data-url.html?foo=bar",
628 report: "the hash or url has query params"
631 ok($(".ui-page-active").jqmData("url").indexOf("?foo=bar") > -1, "the query params are in the data url");
637 asyncTest( "identical query param link doesn't add additional set of query params", function(){
638 $.testHelper.pageSequence([
640 $.testHelper.openPage("#data-url-tests/non-data-url.html");
644 $("#query-param-anchor").click();
648 $.testHelper.assertUrlLocation({
649 hashOrPush: home + "data-url-tests/non-data-url.html?foo=bar",
650 report: "the hash or url has query params"
653 $("#query-param-anchor").click();
657 $.testHelper.assertUrlLocation({
658 hashOrPush: home + "data-url-tests/non-data-url.html?foo=bar",
659 report: "the hash or url still has query params"
667 // Special handling inside navigation because query params must be applied to the hash
668 // or absolute reference and dialogs apply extra information int the hash that must be removed
669 asyncTest( "query param link from a dialog to itself should be a not add another dialog", function(){
672 $.testHelper.pageSequence([
673 // open our test page
675 $.testHelper.openPage("#dialog-param-link");
678 // navigate to the subdirectory page with the query link
680 $("#dialog-param-link a").click();
683 // navigate to the query param self reference link
685 $("#dialog-param-link-page a").click();
688 // attempt to navigate to the same link
690 // store the current hash for comparison (with one dialog hash key)
691 firstDialogLoc = location.hash || location.href;
692 $("#dialog-param-link-page a").click();
696 same(location.hash || location.href, firstDialogLoc, "additional dialog hash key not added");
702 asyncTest( "query data passed as string to changePage is appended to URL", function(){
703 $.testHelper.pageSequence([
704 // open our test page
706 $.mobile.changePage( "form-tests/changepage-data.html", {
712 $.testHelper.assertUrlLocation({
713 hashOrPush: home + "form-tests/changepage-data.html?foo=1&bar=2",
714 report: "the hash or url still has query params"
722 asyncTest( "query data passed as object to changePage is appended to URL", function(){
723 $.testHelper.pageSequence([
724 // open our test page
726 $.mobile.changePage( "form-tests/changepage-data.html", {
735 $.testHelper.assertUrlLocation({
736 hashOrPush: home + "form-tests/changepage-data.html?foo=3&bar=4",
737 report: "the hash or url still has query params"
745 asyncTest( "refresh of a dialog url should not duplicate page", function(){
746 $.testHelper.pageSequence([
747 // open our test page
749 same($(".foo-class").length, 1, "should only have one instance of foo-class in the document");
750 location.hash = "#foo&ui-state=dialog";
754 $.testHelper.assertUrlLocation({
755 hash: "foo&ui-state=dialog",
756 push: home + "#foo&ui-state=dialog",
757 report: "hash should match what was loaded"
760 same( $(".foo-class").length, 1, "should only have one instance of foo-class in the document" );
766 asyncTest( "internal form with no action submits to document URL", function(){
767 $.testHelper.pageSequence([
768 // open our test page
770 $.testHelper.openPage("#internal-no-action-form-page");
774 $("#internal-no-action-form-page form").eq(0).submit();
778 $.testHelper.assertUrlLocation({
779 hashOrPush: home + "?foo=1&bar=2",
780 report: "hash should match what was loaded"
788 asyncTest( "external page containing form with no action submits to page URL", function(){
789 $.testHelper.pageSequence([
790 // open our test page
792 $.testHelper.openPage("#internal-no-action-form-page");
796 $("#internal-no-action-form-page a").eq(0).click();
800 $("#external-form-no-action-page form").eq(0).submit();
804 $.testHelper.assertUrlLocation({
805 hashOrPush: home + "form-tests/form-no-action.html?foo=1&bar=2",
806 report: "hash should match page url and not document url"
814 asyncTest( "handling of active button state when navigating", 1, function(){
816 $.testHelper.pageSequence([
817 // open our test page
819 $.testHelper.openPage("#active-state-page1");
823 $("#active-state-page1 a").eq(0).click();
827 $("#active-state-page2 a").eq(0).click();
831 ok(!$("#active-state-page1 a").hasClass( $.mobile.activeBtnClass ), "No button should not have class " + $.mobile.activeBtnClass );
837 // issue 2444 https://github.com/jquery/jquery-mobile/issues/2444
838 // results from preventing spurious hash changes
839 asyncTest( "dialog should return to its parent page when open and closed multiple times", function() {
840 $.testHelper.pageSequence([
841 // open our test page
843 $.testHelper.openPage("#default-trans-dialog");
847 $.mobile.activePage.find( "a" ).click();
851 window.history.back();
855 same( $.mobile.activePage[0], $( "#default-trans-dialog" )[0] );
856 $.mobile.activePage.find( "a" ).click();
860 window.history.back();
864 same( $.mobile.activePage[0], $( "#default-trans-dialog" )[0] );
870 asyncTest( "clicks with middle mouse button are ignored", function() {
871 $.testHelper.pageSequence([
873 $.testHelper.openPage( "#odd-clicks-page" );
877 $( "#right-or-middle-click" ).click();
880 // make sure the page is opening first without the mocked button click value
881 // only necessary to prevent issues with test specific fixtures
883 same($.mobile.activePage[0], $("#odd-clicks-page-dest")[0]);
884 $.testHelper.openPage( "#odd-clicks-page" );
886 // mock the which value to simulate a middle click
887 $.Event.prototype.which = 2;
891 $( "#right-or-middle-click" ).click();
894 function( timeout ) {
895 ok( timeout, "page event handler timed out due to ignored click" );
896 ok($.mobile.activePage[0] !== $("#odd-clicks-page-dest")[0], "pages are not the same");
902 asyncTest( "disabling link binding disables navigation via links and highlighting", function() {
903 $.mobile.linkBindingEnabled = false;
905 $.testHelper.pageSequence([
907 $.testHelper.openPage("#bar");
911 $.mobile.activePage.find( "a" ).click();
914 function( timeout ) {
915 ok( !$.mobile.activePage.find( "a" ).hasClass( $.mobile.activeBtnClass ), "vlick handler doesn't add the activebtn class" );
916 ok( timeout, "no page change was fired" );
922 asyncTest( "handling of button active state when navigating by clicking back button", 1, function(){
923 $.testHelper.pageSequence([
924 // open our test page
926 $.testHelper.openPage("#active-state-page1");
930 $("#active-state-page1 a").eq(0).click();
934 $("#active-state-page2 a").eq(1).click();
938 $("#active-state-page1 a").eq(0).click();
942 ok(!$("#active-state-page2 a").hasClass( $.mobile.activeBtnClass ), "No button should not have class " + $.mobile.activeBtnClass );
948 asyncTest( "can navigate to dynamically injected page with dynamically injected link", function(){
949 $.testHelper.pageSequence([
950 // open our test page
952 $.testHelper.openPage("#inject-links-page");
956 var $ilpage = $( "#inject-links-page" ),
957 $link = $( "<a href='#injected-test-page'>injected-test-page link</a>" );
959 // Make sure we actually navigated to the expected page.
960 ok( $.mobile.activePage[ 0 ] == $ilpage[ 0 ], "navigated successfully to #inject-links-page" );
962 // Now dynamically insert a page.
963 $ilpage.parent().append( "<div data-role='page' id='injected-test-page'>testing...</div>" );
965 // Now inject a link to this page dynamically and attempt to navigate
966 // to the page we just inserted.
967 $link.appendTo( $ilpage ).click();
971 // Make sure we actually navigated to the expected page.
972 ok( $.mobile.activePage[ 0 ] == $( "#injected-test-page" )[ 0 ], "navigated successfully to #injected-test-page" );
979 asyncTest( "application url with dialogHashKey loads application's first page", function(){
980 $.testHelper.pageSequence([
981 // open our test page
983 // Navigate to any page except the first page of the application.
984 $.testHelper.openPage("#foo");
988 ok( $.mobile.activePage[ 0 ] === $( "#foo" )[ 0 ], "navigated successfully to #foo" );
990 // Now navigate to an hash that contains just a dialogHashKey.
991 $.mobile.changePage("#" + $.mobile.dialogHashKey);
995 // Make sure we actually navigated to the first page.
996 ok( $.mobile.activePage[ 0 ] === $.mobile.firstPage[ 0 ], "navigated successfully to first-page" );
998 // Now make sure opening the page didn't result in page duplication.
999 ok( $.mobile.firstPage.hasClass( "first-page" ), "first page has expected class" );
1000 same( $( ".first-page" ).length, 1, "first page was not duplicated" );
1007 asyncTest( "navigate to non-existent internal page throws pagechangefailed", function(){
1008 var pagechangefailed = false,
1009 pageChangeFailedCB = function( e ) {
1010 pagechangefailed = true;
1013 $( document ).bind( "pagechangefailed", pageChangeFailedCB );
1015 $.testHelper.pageSequence([
1016 // open our test page
1018 // Make sure there's only one copy of the first-page in the DOM to begin with.
1019 ok( $.mobile.firstPage.hasClass( "first-page" ), "first page has expected class" );
1020 same( $( ".first-page" ).length, 1, "first page was not duplicated" );
1022 // Navigate to any page except the first page of the application.
1023 $.testHelper.openPage("#foo");
1027 var $foo = $( "#foo" );
1028 ok( $.mobile.activePage[ 0 ] === $foo[ 0 ], "navigated successfully to #foo" );
1029 same( pagechangefailed, false, "no page change failures" );
1031 // Now navigate to a non-existent page.
1032 $foo.find( "#bad-internal-page-link" ).click();
1036 // Make sure a pagechangefailed event was triggered.
1037 same( pagechangefailed, true, "pagechangefailed dispatched" );
1039 // Make sure we didn't navigate away from #foo.
1040 ok( $.mobile.activePage[ 0 ] === $( "#foo" )[ 0 ], "did not navigate away from #foo" );
1042 // Now make sure opening the page didn't result in page duplication.
1043 same( $( ".first-page" ).length, 1, "first page was not duplicated" );
1045 $( document ).unbind( "pagechangefailed", pageChangeFailedCB );
1052 asyncTest( "prefetched links with data rel dialog result in a dialog", function() {
1053 $.testHelper.pageSequence([
1054 // open our test page
1056 // Navigate to any page except the first page of the application.
1057 $.testHelper.openPage("#prefetched-dialog-page");
1061 $("#prefetched-dialog-link").click();
1065 ok( $.mobile.activePage.is(".ui-dialog"), "prefetched page is rendered as a dialog" );
1071 asyncTest( "first page gets reloaded if pruned from the DOM", function(){
1072 var hideCallbackTriggered = false;
1074 function hideCallback( e, data )
1076 var page = e.target;
1077 ok( ( page === $.mobile.firstPage[ 0 ] ), "hide called with prevPage set to firstPage");
1078 if ( page === $.mobile.firstPage[ 0 ] ) {
1081 hideCallbackTriggered = true;
1084 $(document).bind('pagehide', hideCallback);
1086 $.testHelper.pageSequence([
1088 // Make sure the first page is actually in the DOM.
1089 ok( $.mobile.firstPage.parent().length !== 0, "first page is currently in the DOM" );
1091 // Make sure the first page is the active page.
1092 ok( $.mobile.activePage[ 0 ] === $.mobile.firstPage[ 0 ], "first page is the active page" );
1094 // Now make sure the first page has an id that we can use to reload it.
1095 ok( $.mobile.firstPage[ 0 ].id, "first page has an id" );
1097 // Make sure there is only one first page in the DOM.
1098 same( $( ".first-page" ).length, 1, "only one instance of the first page in the DOM" );
1100 // Navigate to any page except the first page of the application.
1101 $.testHelper.openPage("#foo");
1105 // Make sure the active page is #foo.
1106 ok( $.mobile.activePage[ 0 ] === $( "#foo" )[ 0 ], "navigated successfully to #foo" );
1108 // Make sure our hide callback was triggered.
1109 ok( hideCallbackTriggered, "hide callback was triggered" );
1111 // Make sure the first page was actually pruned from the document.
1112 ok( $.mobile.firstPage.parent().length === 0, "first page was pruned from the DOM" );
1113 same( $( ".first-page" ).length, 0, "no instance of the first page in the DOM" );
1115 // Remove our hideCallback.
1116 $(document).unbind('pagehide', hideCallback);
1118 // Navigate back to the first page!
1119 $.testHelper.openPage( "#" + $.mobile.firstPage[0].id );
1123 var firstPage = $( ".first-page" );
1125 // We should only have one first page in the document at any time!
1126 same( firstPage.length, 1, "single instance of first page recreated in the DOM" );
1128 // Make sure the first page in the DOM is actually a different DOM element than the original
1129 // one we started with.
1130 ok( $.mobile.firstPage[ 0 ] !== firstPage[ 0 ], "first page is a new DOM element");
1132 // Make sure we actually navigated to the new first page.
1133 ok( $.mobile.activePage[ 0 ] === firstPage[ 0 ], "navigated successfully to new first-page");
1135 // Reset the $.mobile.firstPage for subsequent tests.
1136 // XXX: Should we just get rid of the new one and restore the old?
1137 $.mobile.firstPage = $.mobile.activePage;