browser_appendSpanCount.js (6372B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 // This test makes sure that when the view updates itself and appends new rows, 6 // the new rows start out hidden when they exceed the current visible result 7 // span count. It includes a tip result so that it tests a row with > 1 result 8 // span. 9 10 "use strict"; 11 12 add_setup(async function () { 13 await SpecialPowers.pushPrefEnv({ 14 set: [["browser.urlbar.scotchBonnet.enableOverride", false]], 15 }); 16 }); 17 18 add_task(async function viewUpdateAppendHidden() { 19 // We'll use this test provider to test specific results. We assume that 20 // history and bookmarks have been cleared (by init() above). 21 let provider = new DelayingTestProvider(); 22 UrlbarProvidersManager.registerProvider(provider); 23 registerCleanupFunction(() => { 24 UrlbarProvidersManager.unregisterProvider(provider); 25 }); 26 27 // We do two searches below without closing the panel. Use "firefox cach" as 28 // the first query and "firefox cache" as the second so that (1) an 29 // intervention tip is triggered both times but also so that (2) the queries 30 // are different each time. 31 let baseQuery = "firefox cache"; 32 let queries = [baseQuery.substring(0, baseQuery.length - 1), baseQuery]; 33 let maxResults = UrlbarPrefs.get("maxRichResults"); 34 35 let queryStrings = []; 36 for (let i = 0; i < maxResults; i++) { 37 queryStrings.push(`${baseQuery} ${i}`); 38 } 39 40 // First search: Trigger the intervention tip and a view full of search 41 // suggestions. 42 provider.results = queryStrings.map( 43 suggestion => 44 new UrlbarResult({ 45 type: UrlbarUtils.RESULT_TYPE.SEARCH, 46 source: UrlbarUtils.RESULT_SOURCE.SEARCH, 47 payload: { 48 query: queries[0], 49 suggestion, 50 lowerCaseSuggestion: suggestion.toLocaleLowerCase(), 51 engine: Services.search.defaultEngine.name, 52 }, 53 }) 54 ); 55 provider.finishQueryPromise = Promise.resolve(); 56 await UrlbarTestUtils.promiseAutocompleteResultPopup({ 57 window, 58 value: queries[0], 59 }); 60 61 // Sanity check the tip result and row count. 62 let tipResult = await UrlbarTestUtils.getDetailsOfResultAt(window, 1); 63 Assert.equal( 64 tipResult.type, 65 UrlbarUtils.RESULT_TYPE.TIP, 66 "Result at index 1 is a tip" 67 ); 68 let tipResultSpan = UrlbarUtils.getSpanForResult( 69 tipResult.element.row.result 70 ); 71 Assert.greater(tipResultSpan, 1, "Sanity check: Tip has large result span"); 72 let expectedRowCount = maxResults - tipResultSpan + 1; 73 Assert.equal( 74 UrlbarTestUtils.getResultCount(window), 75 expectedRowCount, 76 "Sanity check: Initial row count takes tip result span into account" 77 ); 78 79 // Second search: Change the provider's results so that it has enough history 80 // to fill up the view. Search suggestion rows cannot be updated to history 81 // results, so the view will append the history results as new rows. 82 provider.results = queryStrings.map(title => { 83 let url = "http://example.com/" + title; 84 return new UrlbarResult({ 85 type: UrlbarUtils.RESULT_TYPE.URL, 86 source: UrlbarUtils.RESULT_SOURCE.HISTORY, 87 payload: { 88 title, 89 url, 90 }, 91 }); 92 }); 93 94 // Don't allow the search to finish until we check the updated rows. We'll 95 // accomplish that by adding a mutation observer on the rows and delaying 96 // resolving the provider's finishQueryPromise. When all new rows have been 97 // added, we expect the new row count to be: 98 // 99 // expectedRowCount // the original row count 100 // + (expectedRowCount - 2) // the newly added history row count (hidden) 101 // -------------------------- 102 // (2 * expectedRowCount) - 2 103 // 104 // The `- 2` subtracts the heuristic and tip result. 105 let newExpectedRowCount = 2 * expectedRowCount - 2; 106 let mutationPromise = new Promise(resolve => { 107 let observer = new MutationObserver(() => { 108 let childCount = UrlbarTestUtils.getResultCount(window); 109 info(`Rows mutation observer called, childCount now ${childCount}`); 110 if (newExpectedRowCount <= childCount) { 111 observer.disconnect(); 112 resolve(); 113 } 114 }); 115 observer.observe(UrlbarTestUtils.getResultsContainer(window), { 116 childList: true, 117 }); 118 }); 119 120 // Now do the second search but don't wait for it to finish. 121 let resolveQuery; 122 provider.finishQueryPromise = new Promise( 123 resolve => (resolveQuery = resolve) 124 ); 125 let queryPromise = UrlbarTestUtils.promiseAutocompleteResultPopup({ 126 window, 127 value: queries[1], 128 }); 129 130 // Wait for the history rows to be added. 131 await mutationPromise; 132 133 // Check the rows. We can't use UrlbarTestUtils.getDetailsOfResultAt() here 134 // because it waits for the query to finish. 135 Assert.equal( 136 UrlbarTestUtils.getResultCount(window), 137 newExpectedRowCount, 138 "New expected row count" 139 ); 140 // stale search rows 141 let rows = UrlbarTestUtils.getResultsContainer(window).children; 142 for (let i = 2; i < expectedRowCount; i++) { 143 let row = rows[i]; 144 Assert.equal( 145 row.result.type, 146 UrlbarUtils.RESULT_TYPE.SEARCH, 147 `Result at index ${i} is a search result` 148 ); 149 Assert.ok( 150 BrowserTestUtils.isVisible(row), 151 `Search result at index ${i} is visible` 152 ); 153 Assert.equal( 154 row.getAttribute("stale"), 155 "true", 156 `Search result at index ${i} is stale` 157 ); 158 } 159 // new hidden history rows 160 for (let i = expectedRowCount; i < newExpectedRowCount; i++) { 161 let row = rows[i]; 162 Assert.equal( 163 row.result.type, 164 UrlbarUtils.RESULT_TYPE.URL, 165 `Result at index ${i} is a URL result` 166 ); 167 Assert.ok( 168 !BrowserTestUtils.isVisible(row), 169 `URL result at index ${i} is hidden` 170 ); 171 Assert.ok( 172 !row.hasAttribute("stale"), 173 `URL result at index ${i} is not stale` 174 ); 175 } 176 177 // Finish the query, and we're done. 178 resolveQuery(); 179 await queryPromise; 180 181 await UrlbarTestUtils.promisePopupClose(window); 182 gURLBar.handleRevert(); 183 184 // We unregister the provider above in a cleanup function so we don't 185 // accidentally interfere with later tests, but do it here too in case we add 186 // more tasks to this test. It's harmless to call more than once. 187 UrlbarProvidersManager.unregisterProvider(provider); 188 });