browser_prompt_close_groups.js (7025B)
1 /* Any copyright is dedicated to the Public Domain. 2 http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 const { PromptTestUtils } = ChromeUtils.importESModule( 7 "resource://testing-common/PromptTestUtils.sys.mjs" 8 ); 9 10 const { TabStateFlusher } = ChromeUtils.importESModule( 11 "resource:///modules/sessionstore/TabStateFlusher.sys.mjs" 12 ); 13 14 const TEST_ROOT = getRootDirectory(gTestPath).replace( 15 "chrome://mochitests/content", 16 "https://example.com" 17 ); 18 19 async function addTab(url) { 20 let tab = await BrowserTestUtils.openNewForegroundTab({ 21 gBrowser, 22 url, 23 animate: false, 24 }); 25 return tab; 26 } 27 28 async function addBeforeUnloadTab() { 29 let tab = await addTab(TEST_ROOT + "file_beforeunload_stop.html"); 30 await BrowserTestUtils.synthesizeMouseAtCenter( 31 "body", 32 {}, 33 tab.linkedBrowser.browsingContext 34 ); 35 Assert.ok( 36 tab.linkedBrowser.hasBeforeUnload, 37 "Added tab has a beforeUnload prompt" 38 ); 39 return tab; 40 } 41 42 add_setup(async function () { 43 await SpecialPowers.pushPrefEnv({ 44 set: [["test.wait300msAfterTabSwitch", true]], 45 }); 46 }); 47 48 /** 49 * When closing a group with a tab prompt and accepting the prompt, 50 * the group should close. 51 */ 52 add_task(async function test_closeGroupAndAcceptPrompt() { 53 await SimpleTest.requestCompleteLog(); 54 let tab1 = await addTab("about:mozilla"); 55 let tab2 = await addBeforeUnloadTab(); 56 let group = gBrowser.addTabGroup([tab1, tab2]); 57 58 let promptHandled = PromptTestUtils.handleNextPrompt( 59 window, 60 { 61 modalType: Services.prompt.MODAL_TYPE_CONTENT, 62 }, 63 { 64 buttonNumClick: 0, // 0 = leave page (accept), 1= stay on page (cancel) 65 } 66 ); 67 68 let groupRemoved = BrowserTestUtils.waitForEvent(group, "TabGroupRemoved"); 69 70 gBrowser.removeTabGroup(group); 71 await Promise.allSettled([promptHandled, groupRemoved]); 72 73 Assert.ok(!gBrowser.getAllTabGroups().length, "Tab group was removed"); 74 }); 75 76 /** 77 * When closing a group with a tab prompt and rejecting the prompt, 78 * all tabs in the group should remain open. 79 */ 80 add_task(async function test_closeGroupAndRejectPrompt() { 81 let tab1 = await addTab("about:mozilla"); 82 let tab2 = await addBeforeUnloadTab(); 83 let groupCreated = BrowserTestUtils.waitForEvent(window, "TabGroupCreate"); 84 let group = gBrowser.addTabGroup([tab1, tab2]); 85 await groupCreated; 86 let promptHandled = PromptTestUtils.handleNextPrompt( 87 tab2.linkedBrowser, 88 { 89 modalType: Services.prompt.MODAL_TYPE_CONTENT, 90 }, 91 { 92 buttonNumClick: 1, // 0 = leave page (accept), 1= stay on page (cancel) 93 } 94 ); 95 96 gBrowser.removeTabGroup(group); 97 await promptHandled; 98 99 Assert.equal(gBrowser.getAllTabGroups().length, 1, "Tab group is still open"); 100 Assert.equal(group.tabs.length, 2, "Both tabs in group remain open"); 101 let groupRemoved = BrowserTestUtils.waitForEvent(group, "TabGroupRemoved"); 102 gBrowser.removeTabGroup(group, { skipPermitUnload: true }); 103 await groupRemoved; 104 }); 105 106 /** 107 * When closing a group with multiple tab prompts and rejecting ANY of them, 108 * all tabs in the group should remain open. 109 */ 110 add_task(async function test_closeGroupAndRejectAnyPrompt() { 111 // maybe disable this test and try running a11y tests 112 let tab1 = await addBeforeUnloadTab(); 113 let tab2 = await addBeforeUnloadTab(); 114 let group = gBrowser.addTabGroup([tab1, tab2]); 115 116 let firstPromptHandled = PromptTestUtils.handleNextPrompt( 117 tab1.linkedBrowser, 118 { 119 modalType: Services.prompt.MODAL_TYPE_CONTENT, 120 }, 121 { 122 buttonNumClick: 0, // 0 = leave page (accept), 1= stay on page (cancel) 123 } 124 ); 125 126 let secondPromptHandled = PromptTestUtils.handleNextPrompt( 127 tab2.linkedBrowser, 128 { 129 modalType: Services.prompt.MODAL_TYPE_CONTENT, 130 }, 131 { 132 buttonNumClick: 1, // 0 = leave page (accept), 1= stay on page (cancel) 133 } 134 ); 135 136 let groupRemoved = gBrowser.removeTabGroup(group); 137 await Promise.race([firstPromptHandled, secondPromptHandled]); 138 await groupRemoved; 139 140 Assert.equal(gBrowser.getAllTabGroups().length, 1, "Tab group is still open"); 141 Assert.equal(group.tabs.length, 2, "Both tabs in group remain open"); 142 groupRemoved = BrowserTestUtils.waitForEvent(group, "TabGroupRemoved"); 143 gBrowser.removeTabGroup(group, { skipPermitUnload: true }); 144 await groupRemoved; 145 }); 146 147 /** 148 * When a bunch of tabs are closed, e.g. when using "close tabs to the right", 149 * any whole tabgroups with beforeunload handlers should be kept open if 150 * cancelled by the user. 151 */ 152 add_task(async function test_closeMultipleTabsAndRejectFromGroup() { 153 let group1Tab1 = await addTab("about:mozilla"); 154 let group1Tab2 = await addBeforeUnloadTab(); 155 let group2Tab1 = await addBeforeUnloadTab(); 156 let group2Tab2 = await addTab("about:mozilla"); 157 let group1 = gBrowser.addTabGroup([group1Tab1, group1Tab2], { 158 id: "leave-open", 159 label: "leave open", 160 }); 161 gBrowser.addTabGroup([group2Tab1, group2Tab2], { 162 id: "close", 163 label: "close", 164 }); 165 166 let firstPromptHandled = PromptTestUtils.handleNextPrompt( 167 group1Tab2.linkedBrowser, 168 { 169 modalType: Services.prompt.MODAL_TYPE_CONTENT, 170 }, 171 { 172 buttonNumClick: 1, // 0 = leave page (accept), 1= stay on page (cancel) 173 } 174 ); 175 176 let secondPromptHandled = PromptTestUtils.handleNextPrompt( 177 group2Tab1.linkedBrowser, 178 { 179 modalType: Services.prompt.MODAL_TYPE_CONTENT, 180 }, 181 { 182 buttonNumClick: 0, // 0 = leave page (accept), 1= stay on page (cancel) 183 } 184 ); 185 186 gBrowser.removeTabsToTheEndFrom(gBrowser.tabs[0]); 187 await Promise.allSettled([firstPromptHandled, secondPromptHandled]); 188 189 // initial tab and 1 tab group should remain open 190 await BrowserTestUtils.waitForCondition( 191 () => gBrowser.tabs.length == 3, 192 "3 tabs remain open" 193 ); 194 Assert.equal( 195 gBrowser.getAllTabGroups()[0].id, 196 group1.id, 197 "Group 1 is still open" 198 ); 199 200 await gBrowser.removeTabGroup(group1, { skipPermitUnload: true }); 201 }); 202 203 /** 204 * When a tab group is saved & closed, it should not end up saved if the user 205 * cancels the group close. 206 */ 207 add_task(async function test_cancelClosingASavingGroup() { 208 let tab1 = await addBeforeUnloadTab(); 209 let tab2 = await addTab("about:mozilla"); 210 await TabStateFlusher.flush(tab1.linkedBrowser); 211 let group = gBrowser.addTabGroup([tab1, tab2]); 212 group.save(); 213 Assert.equal( 214 SessionStore.getCurrentState().savedGroups.length, 215 1, 216 "Group is saved" 217 ); 218 219 let promptHandled = PromptTestUtils.handleNextPrompt( 220 tab1.linkedBrowser, 221 { 222 modalType: Services.prompt.MODAL_TYPE_CONTENT, 223 }, 224 { 225 buttonNumClick: 1, // 0 = leave page (accept), 1= stay on page (cancel) 226 } 227 ); 228 let groupRemoved = gBrowser.removeTabGroup(group); 229 await Promise.allSettled([promptHandled, groupRemoved]); 230 Assert.equal(gBrowser.getAllTabGroups().length, 1, "Group is still open"); 231 Assert.ok( 232 !SessionStore.getCurrentState().savedGroups.length, 233 "Group is no longer saved after close was canceled" 234 ); 235 await gBrowser.removeTabGroup(group, { skipPermitUnload: true }); 236 });