browser_html_tooltip-02.js (6790B)
1 /* Any copyright is dedicated to the Public Domain. 2 http://creativecommons.org/publicdomain/zero/1.0/ */ 3 /* import-globals-from helper_html_tooltip.js */ 4 "use strict"; 5 6 /** 7 * Test the HTMLTooltip is closed when clicking outside of its container. 8 */ 9 10 const HTML_NS = "http://www.w3.org/1999/xhtml"; 11 const TEST_URI = CHROME_URL_ROOT + "doc_html_tooltip-02.xhtml"; 12 const PROMISE_TIMEOUT = 3000; 13 14 const { 15 HTMLTooltip, 16 } = require("resource://devtools/client/shared/widgets/tooltip/HTMLTooltip.js"); 17 loadHelperScript("helper_html_tooltip.js"); 18 19 let useXulWrapper; 20 21 add_task(async function () { 22 await addTab("about:blank"); 23 const { doc } = await createHost("bottom", TEST_URI); 24 25 info("Run tests for a Tooltip without using a XUL panel"); 26 useXulWrapper = false; 27 await runTests(doc); 28 29 info("Run tests for a Tooltip with a XUL panel"); 30 useXulWrapper = true; 31 await runTests(doc); 32 }); 33 34 async function runTests(doc) { 35 await testClickInTooltipContent(doc); 36 await testClickInTooltipIcon(doc); 37 await testConsumeOutsideClicksFalse(doc); 38 await testConsumeOutsideClicksTrue(doc); 39 await testConsumeWithRightClick(doc); 40 await testClickInOuterIframe(doc); 41 await testClickInInnerIframe(doc); 42 } 43 44 async function testClickInTooltipContent(doc) { 45 info("Test a tooltip is not closed when clicking inside itself"); 46 47 const tooltip = new HTMLTooltip(doc, { useXulWrapper }); 48 tooltip.panel.appendChild(getTooltipContent(doc)); 49 tooltip.setContentSize({ width: 100, height: 50 }); 50 await showTooltip(tooltip, doc.getElementById("box1")); 51 52 const onTooltipContainerClick = once(tooltip.container, "click"); 53 EventUtils.synthesizeMouseAtCenter(tooltip.container, {}, doc.defaultView); 54 await onTooltipContainerClick; 55 is(tooltip.isVisible(), true, "Tooltip is still visible"); 56 57 tooltip.destroy(); 58 } 59 60 async function testClickInTooltipIcon(doc) { 61 info("Test a tooltip is not closed when clicking it's icon"); 62 63 const tooltip = new HTMLTooltip(doc, { useXulWrapper, noAutoHide: true }); 64 tooltip.panel.appendChild(getTooltipContent(doc)); 65 tooltip.setContentSize({ width: 100, height: 50 }); 66 67 const box1 = doc.getElementById("box1"); 68 await showTooltip(tooltip, box1); 69 70 const onHidden = once(tooltip, "hidden"); 71 box1.click(); 72 73 // Hiding the tooltip is async so we need to wait for "hidden" to be emitted 74 // timing out after 3 seconds. If hidden is emitted we need to fail, 75 // otherwise the test passes. 76 const shown = await Promise.race([ 77 onHidden, 78 wait(PROMISE_TIMEOUT).then(() => true), 79 ]); 80 81 ok(shown, "Tooltip is still visible"); 82 83 tooltip.destroy(); 84 } 85 86 async function testConsumeOutsideClicksFalse(doc) { 87 info("Test closing a tooltip via click with consumeOutsideClicks: false"); 88 const box4 = doc.getElementById("box4"); 89 90 const tooltip = new HTMLTooltip(doc, { 91 consumeOutsideClicks: false, 92 useXulWrapper, 93 }); 94 tooltip.panel.appendChild(getTooltipContent(doc)); 95 tooltip.setContentSize({ width: 100, height: 50 }); 96 await showTooltip(tooltip, doc.getElementById("box1")); 97 98 const onBox4Clicked = once(box4, "click"); 99 const onHidden = once(tooltip, "hidden"); 100 box4.click(); 101 await onHidden; 102 await onBox4Clicked; 103 104 is(tooltip.isVisible(), false, "Tooltip is hidden"); 105 106 tooltip.destroy(); 107 } 108 109 async function testConsumeOutsideClicksTrue(doc) { 110 info("Test closing a tooltip via click with consumeOutsideClicks: true"); 111 const box4 = doc.getElementById("box4"); 112 113 // Count clicks on box4 114 let box4clicks = 0; 115 box4.addEventListener("click", () => box4clicks++); 116 117 const tooltip = new HTMLTooltip(doc, { 118 consumeOutsideClicks: true, 119 useXulWrapper, 120 }); 121 tooltip.panel.appendChild(getTooltipContent(doc)); 122 tooltip.setContentSize({ width: 100, height: 50 }); 123 await showTooltip(tooltip, doc.getElementById("box1")); 124 125 const onHidden = once(tooltip, "hidden"); 126 box4.click(); 127 await onHidden; 128 129 is(box4clicks, 0, "box4 catched no click event"); 130 is(tooltip.isVisible(), false, "Tooltip is hidden"); 131 132 tooltip.destroy(); 133 } 134 135 async function testConsumeWithRightClick(doc) { 136 info( 137 "Test closing a tooltip with a right-click, with consumeOutsideClicks: true" 138 ); 139 const box4 = doc.getElementById("box4"); 140 141 const tooltip = new HTMLTooltip(doc, { 142 consumeOutsideClicks: true, 143 useXulWrapper, 144 }); 145 tooltip.panel.appendChild(getTooltipContent(doc)); 146 tooltip.setContentSize({ width: 100, height: 50 }); 147 await showTooltip(tooltip, doc.getElementById("box1")); 148 149 // Only left-click events should be consumed, so we expect to catch a click when using 150 // {button: 2}, which simulates a right-click. 151 info( 152 "Right click on box4, expect tooltip to be hidden, event should not be consumed" 153 ); 154 const onBox4Clicked = once(box4, "click"); 155 const onHidden = once(tooltip, "hidden"); 156 EventUtils.synthesizeMouseAtCenter(box4, { button: 2 }, doc.defaultView); 157 await onHidden; 158 await onBox4Clicked; 159 160 is(tooltip.isVisible(), false, "Tooltip is hidden"); 161 162 tooltip.destroy(); 163 } 164 165 async function testClickInOuterIframe(doc) { 166 info("Test clicking an iframe outside of the tooltip closes the tooltip"); 167 const frame = doc.getElementById("frame"); 168 169 const tooltip = new HTMLTooltip(doc, { useXulWrapper }); 170 tooltip.panel.appendChild(getTooltipContent(doc)); 171 tooltip.setContentSize({ width: 100, height: 50 }); 172 await showTooltip(tooltip, doc.getElementById("box1")); 173 174 const onHidden = once(tooltip, "hidden"); 175 frame.click(); 176 await onHidden; 177 178 is(tooltip.isVisible(), false, "Tooltip is hidden"); 179 tooltip.destroy(); 180 } 181 182 async function testClickInInnerIframe(doc) { 183 info( 184 "Test clicking an iframe inside the tooltip content does not close the tooltip" 185 ); 186 187 const tooltip = new HTMLTooltip(doc, { 188 consumeOutsideClicks: false, 189 useXulWrapper, 190 }); 191 192 const iframe = doc.createElementNS(HTML_NS, "iframe"); 193 iframe.style.width = "100px"; 194 iframe.style.height = "50px"; 195 196 tooltip.panel.appendChild(iframe); 197 198 tooltip.setContentSize({ width: 100, height: 50 }); 199 await showTooltip(tooltip, doc.getElementById("box1")); 200 201 iframe.srcdoc = "<div id=test style='height:50px'></div>"; 202 await new Promise(r => { 203 const frameLoad = () => { 204 r(); 205 }; 206 DOMHelpers.onceDOMReady(iframe.contentWindow, frameLoad); 207 }); 208 209 await waitUntil(() => iframe.contentWindow.document.getElementById("test")); 210 211 const target = iframe.contentWindow.document.getElementById("test"); 212 const onTooltipClick = once(target, "click"); 213 target.click(); 214 await onTooltipClick; 215 216 is(tooltip.isVisible(), true, "Tooltip is still visible"); 217 218 tooltip.destroy(); 219 } 220 221 function getTooltipContent(doc) { 222 const div = doc.createElementNS(HTML_NS, "div"); 223 div.style.height = "50px"; 224 div.style.boxSizing = "border-box"; 225 div.textContent = "tooltip"; 226 return div; 227 }