browser_tabclose.js (4003B)
1 "use strict"; 2 3 /** 4 * WHOA THERE: We should never be adding new things to EXPECTED_REFLOWS. 5 * Instead of adding reflows to the list, you should be modifying your code to 6 * avoid the reflow. 7 * 8 * See https://firefox-source-docs.mozilla.org/performance/bestpractices.html 9 * for tips on how to do that. 10 */ 11 const EXPECTED_REFLOWS = [ 12 /** 13 * Nothing here! Please don't add anything new! 14 */ 15 ]; 16 17 /* 18 * This test ensures that there are no unexpected 19 * uninterruptible reflows when closing new tabs. 20 */ 21 add_task(async function () { 22 // Force-enable tab animations 23 gReduceMotionOverride = false; 24 25 await ensureNoPreloadedBrowser(); 26 await disableFxaBadge(); 27 28 // The test starts on about:blank and opens an about:blank 29 // tab which triggers opening the toolbar since 30 // ensureNoPreloadedBrowser sets AboutNewTab.newTabURL to about:blank. 31 await SpecialPowers.pushPrefEnv({ 32 set: [["browser.toolbars.bookmarks.visibility", "never"]], 33 }); 34 35 let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser); 36 await TestUtils.waitForCondition(() => tab._fullyOpen); 37 38 let tabStripRect = 39 gBrowser.tabContainer.arrowScrollbox.getBoundingClientRect(); 40 let newTabButtonRect = 41 gBrowser.tabContainer.newTabButton.getBoundingClientRect(); 42 let inRange = (val, min, max) => min <= val && val <= max; 43 44 // Add a reflow observer and open a new tab. 45 await withPerfObserver( 46 async function () { 47 let switchDone = BrowserTestUtils.waitForEvent(window, "TabSwitchDone"); 48 gBrowser.removeTab(tab, { animate: true }); 49 await BrowserTestUtils.waitForEvent(tab, "TabAnimationEnd"); 50 await switchDone; 51 }, 52 { 53 expectedReflows: EXPECTED_REFLOWS, 54 frames: { 55 filter: rects => 56 rects.filter( 57 r => 58 !( 59 // We expect all changes to be within the tab strip. 60 ( 61 r.y1 >= tabStripRect.top && 62 r.y2 <= tabStripRect.bottom && 63 r.x1 >= tabStripRect.left && 64 r.x2 <= tabStripRect.right && 65 // The closed tab should disappear at the same time as the previous 66 // tab gets selected, causing both tab areas to change color at once: 67 // this should be a single rect of the width of 2 tabs, and can 68 // include the '+' button if it starts its animation. 69 ((r.w > gBrowser.selectedTab.clientWidth && 70 r.x2 <= newTabButtonRect.right) || 71 // The '+' icon moves with an animation. At the end of the animation 72 // the former and new positions can touch each other causing the rect 73 // to have twice the icon's width. 74 (r.h == 13 && r.w <= 2 * 13 + kMaxEmptyPixels) || 75 // We sometimes have a rect for the right most 2px of the '+' button. 76 (r.h == 2 && r.w == 2)) 77 ) 78 ) 79 ), 80 exceptions: [ 81 { 82 name: 83 "bug 1444886 - the next tab should be selected at the same time" + 84 " as the closed one disappears", 85 condition: r => 86 // In tab strip 87 r.y1 >= tabStripRect.top && 88 r.y2 <= tabStripRect.bottom && 89 r.x1 >= tabStripRect.left && 90 r.x2 <= tabStripRect.right && 91 // Width of one tab plus tab separator(s) 92 inRange(gBrowser.selectedTab.clientWidth - r.w, 0, 2), 93 }, 94 { 95 name: "bug 1446449 - spurious tab switch spinner", 96 condition: r => 97 AppConstants.DEBUG && 98 // In the content area 99 r.y1 >= 100 document 101 .getElementById("tabbrowser-tabbox") 102 .getBoundingClientRect().top, 103 }, 104 ], 105 }, 106 } 107 ); 108 is(EXPECTED_REFLOWS.length, 0, "No reflows are expected when closing a tab"); 109 });