Wed, 31 Dec 2014 06:55:50 +0100
Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2
michael@0 | 1 | // -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*- |
michael@0 | 2 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 5 | |
michael@0 | 6 | "use strict"; |
michael@0 | 7 | |
michael@0 | 8 | var gEdit = null; |
michael@0 | 9 | |
michael@0 | 10 | /*============================================================================= |
michael@0 | 11 | Search engine mocking utilities |
michael@0 | 12 | =============================================================================*/ |
michael@0 | 13 | |
michael@0 | 14 | var gEngine = null; |
michael@0 | 15 | |
michael@0 | 16 | const kSearchEngineName = "Foo"; |
michael@0 | 17 | const kSearchEngineURI = chromeRoot + "res/testEngine.xml"; |
michael@0 | 18 | |
michael@0 | 19 | /* |
michael@0 | 20 | * addMockSearchDefault - adds a mock search engine to the top of the engine list. |
michael@0 | 21 | */ |
michael@0 | 22 | function addMockSearchDefault(aTimeoutMs) { |
michael@0 | 23 | let deferred = Promise.defer(); |
michael@0 | 24 | let timeoutMs = aTimeoutMs || kDefaultWait; |
michael@0 | 25 | let timerID = 0; |
michael@0 | 26 | |
michael@0 | 27 | function engineAddObserver(aSubject, aTopic, aData) { |
michael@0 | 28 | if (aData != "engine-added") |
michael@0 | 29 | return; |
michael@0 | 30 | |
michael@0 | 31 | gEngine = Services.search.getEngineByName(kSearchEngineName); |
michael@0 | 32 | Services.obs.removeObserver(engineAddObserver, "browser-search-engine-modified"); |
michael@0 | 33 | clearTimeout(timerID); |
michael@0 | 34 | gEngine.hidden = false; |
michael@0 | 35 | ok(gEngine, "mock engine was added"); |
michael@0 | 36 | deferred.resolve(); |
michael@0 | 37 | } |
michael@0 | 38 | |
michael@0 | 39 | if (gEngine) { |
michael@0 | 40 | deferred.resolve(); |
michael@0 | 41 | return deferred.promise; |
michael@0 | 42 | } |
michael@0 | 43 | |
michael@0 | 44 | timerID = setTimeout(function ids_canceller() { |
michael@0 | 45 | Services.obs.removeObserver(engineAddObserver, "browser-search-engine-modified"); |
michael@0 | 46 | deferred.reject(new Error("search add timeout")); |
michael@0 | 47 | }, timeoutMs); |
michael@0 | 48 | |
michael@0 | 49 | Services.obs.addObserver(engineAddObserver, "browser-search-engine-modified", false); |
michael@0 | 50 | Services.search.addEngine(kSearchEngineURI, Ci.nsISearchEngine.DATA_XML, |
michael@0 | 51 | "data:image/x-icon,%00", false); |
michael@0 | 52 | return deferred.promise; |
michael@0 | 53 | } |
michael@0 | 54 | |
michael@0 | 55 | /* |
michael@0 | 56 | * removeMockSearchDefault - removes mock "Foo" search engine. |
michael@0 | 57 | */ |
michael@0 | 58 | |
michael@0 | 59 | function removeMockSearchDefault(aTimeoutMs) { |
michael@0 | 60 | let deferred = Promise.defer(); |
michael@0 | 61 | let timeoutMs = aTimeoutMs || kDefaultWait; |
michael@0 | 62 | let timerID = 0; |
michael@0 | 63 | |
michael@0 | 64 | function engineRemoveObserver(aSubject, aTopic, aData) { |
michael@0 | 65 | if (aData != "engine-removed") |
michael@0 | 66 | return; |
michael@0 | 67 | |
michael@0 | 68 | clearTimeout(timerID); |
michael@0 | 69 | gEngine = null; |
michael@0 | 70 | Services.obs.removeObserver(engineRemoveObserver, "browser-search-engine-modified"); |
michael@0 | 71 | deferred.resolve(); |
michael@0 | 72 | } |
michael@0 | 73 | |
michael@0 | 74 | if (!gEngine) { |
michael@0 | 75 | deferred.resolve(); |
michael@0 | 76 | return deferred.promise; |
michael@0 | 77 | } |
michael@0 | 78 | |
michael@0 | 79 | timerID = setTimeout(function ids_canceller() { |
michael@0 | 80 | Services.obs.removeObserver(engineRemoveObserver, "browser-search-engine-modified"); |
michael@0 | 81 | deferred.reject(new Error("search remove timeout")); |
michael@0 | 82 | }, timeoutMs); |
michael@0 | 83 | |
michael@0 | 84 | Services.obs.addObserver(engineRemoveObserver, "browser-search-engine-modified", false); |
michael@0 | 85 | Services.search.removeEngine(gEngine); |
michael@0 | 86 | return deferred.promise; |
michael@0 | 87 | } |
michael@0 | 88 | |
michael@0 | 89 | /*============================================================================= |
michael@0 | 90 | Test cases |
michael@0 | 91 | =============================================================================*/ |
michael@0 | 92 | |
michael@0 | 93 | function test() { |
michael@0 | 94 | waitForExplicitFinish(); |
michael@0 | 95 | runTests(); |
michael@0 | 96 | } |
michael@0 | 97 | |
michael@0 | 98 | function setUp() { |
michael@0 | 99 | if (!gEdit) |
michael@0 | 100 | gEdit = document.getElementById("urlbar-edit"); |
michael@0 | 101 | |
michael@0 | 102 | yield addTab("about:blank"); |
michael@0 | 103 | yield showNavBar(); |
michael@0 | 104 | } |
michael@0 | 105 | |
michael@0 | 106 | function tearDown() { |
michael@0 | 107 | Browser.closeTab(Browser.selectedTab, { forceClose: true }); |
michael@0 | 108 | } |
michael@0 | 109 | |
michael@0 | 110 | gTests.push({ |
michael@0 | 111 | desc: "search engines update", |
michael@0 | 112 | setUp: setUp, |
michael@0 | 113 | tearDown: tearDown, |
michael@0 | 114 | run: function testSearchEngine() { |
michael@0 | 115 | // If the XBL hasn't initialized yet, open the popup so that it will. |
michael@0 | 116 | if (gEdit.popup._searches == undefined) { |
michael@0 | 117 | gEdit.openPopup(); |
michael@0 | 118 | gEdit.closePopup(); |
michael@0 | 119 | } |
michael@0 | 120 | yield waitForCondition(() => gEdit.popup._searches.itemCount); |
michael@0 | 121 | |
michael@0 | 122 | let numSearches = gEdit.popup._searches.itemCount; |
michael@0 | 123 | function getEngineItem() { |
michael@0 | 124 | return gEdit.popup._searches.querySelector("richgriditem[value="+kSearchEngineName+"]"); |
michael@0 | 125 | } |
michael@0 | 126 | |
michael@0 | 127 | yield addMockSearchDefault(); |
michael@0 | 128 | is(gEdit.popup._searches.itemCount, numSearches + 1, "added search engine count"); |
michael@0 | 129 | ok(getEngineItem(), "added search engine item"); |
michael@0 | 130 | |
michael@0 | 131 | yield removeMockSearchDefault(); |
michael@0 | 132 | is(gEdit.popup._searches.itemCount, numSearches, "normal search engine count"); |
michael@0 | 133 | ok(!getEngineItem(), "added search engine item"); |
michael@0 | 134 | } |
michael@0 | 135 | }); |
michael@0 | 136 | |
michael@0 | 137 | gTests.push({ |
michael@0 | 138 | desc: "display autocomplete while typing, handle enter", |
michael@0 | 139 | setUp: setUp, |
michael@0 | 140 | tearDown: tearDown, |
michael@0 | 141 | run: function testUrlbarTyping() { |
michael@0 | 142 | sendElementTap(window, gEdit); |
michael@0 | 143 | ok(gEdit.isEditing, "focus urlbar: in editing mode"); |
michael@0 | 144 | ok(!gEdit.popup.popupOpen, "focus urlbar: popup not open yet"); |
michael@0 | 145 | |
michael@0 | 146 | EventUtils.sendString("about:blank", window); |
michael@0 | 147 | let opened = yield waitForCondition(() => gEdit.popup.popupOpen); |
michael@0 | 148 | ok(opened, "type in urlbar: popup opens"); |
michael@0 | 149 | |
michael@0 | 150 | EventUtils.synthesizeKey("VK_RETURN", {}, window); |
michael@0 | 151 | let closed = yield waitForCondition(() => !gEdit.popup.popupOpen); |
michael@0 | 152 | ok(closed, "hit enter in urlbar: popup closes, page loads"); |
michael@0 | 153 | ok(!gEdit.isEditing, "hit enter in urlbar: not in editing mode"); |
michael@0 | 154 | } |
michael@0 | 155 | }); |
michael@0 | 156 | |
michael@0 | 157 | gTests.push({ |
michael@0 | 158 | desc: "Control-Enter in urlbar", |
michael@0 | 159 | setUp: setUp, |
michael@0 | 160 | tearDown: tearDown, |
michael@0 | 161 | run: function () { |
michael@0 | 162 | sendElementTap(window, gEdit); |
michael@0 | 163 | ok(gEdit.isEditing, "focus urlbar: in editing mode"); |
michael@0 | 164 | |
michael@0 | 165 | EventUtils.sendString("example", window); |
michael@0 | 166 | EventUtils.synthesizeKey("VK_RETURN", { accelKey: true }, window); |
michael@0 | 167 | is(gEdit.value, "www.example.com", "Control-enter adds www. and .com"); |
michael@0 | 168 | ok(!gEdit.isEditing, "hit enter in urlbar: not in editing mode"); |
michael@0 | 169 | } |
michael@0 | 170 | }); |
michael@0 | 171 | |
michael@0 | 172 | gTests.push({ |
michael@0 | 173 | desc: "Shift-Enter in urlbar", |
michael@0 | 174 | setUp: setUp, |
michael@0 | 175 | tearDown: tearDown, |
michael@0 | 176 | run: function () { |
michael@0 | 177 | sendElementTap(window, gEdit); |
michael@0 | 178 | ok(gEdit.isEditing, "focus urlbar: in editing mode"); |
michael@0 | 179 | |
michael@0 | 180 | EventUtils.sendString("example", window); |
michael@0 | 181 | EventUtils.synthesizeKey("VK_RETURN", { shiftKey: true }, window); |
michael@0 | 182 | is(gEdit.value, "www.example.net", "Shift-enter adds www. and .net"); |
michael@0 | 183 | ok(!gEdit.isEditing, "hit enter in urlbar: not in editing mode"); |
michael@0 | 184 | } |
michael@0 | 185 | }); |
michael@0 | 186 | |
michael@0 | 187 | gTests.push({ |
michael@0 | 188 | desc: "Control-Shift-Enter in urlbar", |
michael@0 | 189 | setUp: setUp, |
michael@0 | 190 | tearDown: tearDown, |
michael@0 | 191 | run: function () { |
michael@0 | 192 | sendElementTap(window, gEdit); |
michael@0 | 193 | ok(gEdit.isEditing, "focus urlbar: in editing mode"); |
michael@0 | 194 | |
michael@0 | 195 | EventUtils.sendString("example", window); |
michael@0 | 196 | EventUtils.synthesizeKey("VK_RETURN", { accelKey: true, shiftKey: true }, window); |
michael@0 | 197 | is(gEdit.value, "www.example.org", "Shift-enter adds www. and .org"); |
michael@0 | 198 | ok(!gEdit.isEditing, "hit enter in urlbar: not in editing mode"); |
michael@0 | 199 | } |
michael@0 | 200 | }); |
michael@0 | 201 | |
michael@0 | 202 | gTests.push({ |
michael@0 | 203 | desc: "display and select a search with keyboard", |
michael@0 | 204 | setUp: setUp, |
michael@0 | 205 | tearDown: tearDown, |
michael@0 | 206 | run: function testSearchKeyboard() { |
michael@0 | 207 | yield addMockSearchDefault(); |
michael@0 | 208 | |
michael@0 | 209 | yield waitForCondition(() => !Browser.selectedTab.isLoading()); |
michael@0 | 210 | |
michael@0 | 211 | sendElementTap(window, gEdit); |
michael@0 | 212 | ok(gEdit.isEditing, "focus urlbar: in editing mode"); |
michael@0 | 213 | ok(!gEdit.popup.popupOpen, "focus urlbar: popup not open yet"); |
michael@0 | 214 | |
michael@0 | 215 | let search = "mozilla"; |
michael@0 | 216 | EventUtils.sendString(search, window); |
michael@0 | 217 | yield waitForCondition(() => gEdit.popup.popupOpen); |
michael@0 | 218 | |
michael@0 | 219 | // XXX We should probably change the keyboard selection behavior entirely, |
michael@0 | 220 | // given that it makes little to no sense, but that's a job for a later patch. |
michael@0 | 221 | |
michael@0 | 222 | EventUtils.synthesizeKey("VK_DOWN", {}, window); |
michael@0 | 223 | is(gEdit.popup.selectedIndex, -1, "key select search: no result selected"); |
michael@0 | 224 | is(gEdit.popup._searches.selectedIndex, 0, "key select search: first search selected"); |
michael@0 | 225 | |
michael@0 | 226 | let engines = Services.search.getVisibleEngines(); |
michael@0 | 227 | for (let i = 0, max = engines.length - 1; i < max; i++) { |
michael@0 | 228 | is(gEdit.popup._searches.selectedIndex, i, "key select search: next index"); |
michael@0 | 229 | EventUtils.synthesizeKey("VK_DOWN", {}, window); |
michael@0 | 230 | } |
michael@0 | 231 | |
michael@0 | 232 | let existingValue = gEdit.value; |
michael@0 | 233 | EventUtils.synthesizeKey("VK_RETURN", {}, window); |
michael@0 | 234 | |
michael@0 | 235 | yield waitForCondition(() => gEdit.value != existingValue); |
michael@0 | 236 | |
michael@0 | 237 | let closed = yield waitForCondition(() => !gEdit.popup.popupOpen); |
michael@0 | 238 | ok(closed, "hit enter in urlbar: popup closes, page loads"); |
michael@0 | 239 | ok(!gEdit.isEditing, "hit enter in urlbar: not in editing mode"); |
michael@0 | 240 | |
michael@0 | 241 | let searchSubmission = gEngine.getSubmission(search, null); |
michael@0 | 242 | let trimmedSubmission = gEdit.trimValue(searchSubmission.uri.spec); |
michael@0 | 243 | is(gEdit.value, trimmedSubmission, "hit enter in urlbar: search conducted"); |
michael@0 | 244 | |
michael@0 | 245 | yield removeMockSearchDefault(); |
michael@0 | 246 | } |
michael@0 | 247 | }); |
michael@0 | 248 | |
michael@0 | 249 | gTests.push({ |
michael@0 | 250 | desc: "display and select a search with touch", |
michael@0 | 251 | setUp: setUp, |
michael@0 | 252 | tearDown: tearDown, |
michael@0 | 253 | run: function testUrlbarSearchesTouch() { |
michael@0 | 254 | yield addMockSearchDefault(); |
michael@0 | 255 | |
michael@0 | 256 | yield waitForCondition(() => !Browser.selectedTab.isLoading()); |
michael@0 | 257 | |
michael@0 | 258 | sendElementTap(window, gEdit); |
michael@0 | 259 | ok(gEdit.isEditing, "focus urlbar: in editing mode"); |
michael@0 | 260 | ok(!gEdit.popup.popupOpen, "focus urlbar: popup not open yet"); |
michael@0 | 261 | |
michael@0 | 262 | let search = "mozilla"; |
michael@0 | 263 | EventUtils.sendString(search, window); |
michael@0 | 264 | yield waitForCondition(() => gEdit.popup.popupOpen); |
michael@0 | 265 | |
michael@0 | 266 | sendElementTap(window, gEdit.popup._searches.lastChild); |
michael@0 | 267 | |
michael@0 | 268 | let closed = yield waitForCondition(() => !gEdit.popup.popupOpen); |
michael@0 | 269 | ok(closed, "tap search option: popup closes, page loads"); |
michael@0 | 270 | ok(!gEdit.isEditing, "tap search option: not in editing mode"); |
michael@0 | 271 | |
michael@0 | 272 | let searchSubmission = gEngine.getSubmission(search, null); |
michael@0 | 273 | let trimmedSubmission = gEdit.trimValue(searchSubmission.uri.spec); |
michael@0 | 274 | is(gEdit.value, trimmedSubmission, "tap search option: search conducted"); |
michael@0 | 275 | |
michael@0 | 276 | yield removeMockSearchDefault(); |
michael@0 | 277 | } |
michael@0 | 278 | }); |
michael@0 | 279 | |
michael@0 | 280 | gTests.push({ |
michael@0 | 281 | desc: "bug 897131 - url bar update after content tap + edge swipe", |
michael@0 | 282 | tearDown: tearDown, |
michael@0 | 283 | run: function testUrlbarTyping() { |
michael@0 | 284 | let tab = yield addTab("about:mozilla"); |
michael@0 | 285 | yield showNavBar(); |
michael@0 | 286 | |
michael@0 | 287 | sendElementTap(window, gEdit); |
michael@0 | 288 | ok(gEdit.isEditing, "focus urlbar: in editing mode"); |
michael@0 | 289 | ok(!gEdit.popup.popupOpen, "focus urlbar: popup not open yet"); |
michael@0 | 290 | |
michael@0 | 291 | EventUtils.sendString("about:blank", window); |
michael@0 | 292 | let opened = yield waitForCondition(() => gEdit.popup.popupOpen); |
michael@0 | 293 | ok(opened, "type in urlbar: popup opens"); |
michael@0 | 294 | |
michael@0 | 295 | sendElementTap(window, tab.browser); |
michael@0 | 296 | |
michael@0 | 297 | let closed = yield waitForCondition(() => !gEdit.popup.popupOpen); |
michael@0 | 298 | ok(closed, "autocomplete closed after tap on content"); |
michael@0 | 299 | ok(!ContextUI.navbarVisible, "navbar closed"); |
michael@0 | 300 | |
michael@0 | 301 | let event = document.createEvent("Events"); |
michael@0 | 302 | event.initEvent("MozEdgeUICompleted", true, false); |
michael@0 | 303 | window.dispatchEvent(event); |
michael@0 | 304 | |
michael@0 | 305 | ok(ContextUI.navbarVisible, "navbar visible"); |
michael@0 | 306 | is(gEdit.value, "about:mozilla", "url bar text refreshed"); |
michael@0 | 307 | } |
michael@0 | 308 | }); |
michael@0 | 309 | |
michael@0 | 310 | gTests.push({ |
michael@0 | 311 | desc: "Bug 916383 - Invisible autocomplete items selectable by keyboard when 'your results' not shown", |
michael@0 | 312 | tearDown: tearDown, |
michael@0 | 313 | run: function testBug916383() { |
michael@0 | 314 | yield addTab("about:start"); |
michael@0 | 315 | yield showNavBar(); |
michael@0 | 316 | |
michael@0 | 317 | sendElementTap(window, gEdit); |
michael@0 | 318 | |
michael@0 | 319 | let bookmarkItem = Browser.selectedBrowser.contentWindow.BookmarksStartView._grid.querySelector("richgriditem"); |
michael@0 | 320 | // Get the first bookmark item label to make sure it will show up in 'your results' |
michael@0 | 321 | let label = bookmarkItem.getAttribute("label"); |
michael@0 | 322 | |
michael@0 | 323 | EventUtils.sendString(label, window); |
michael@0 | 324 | |
michael@0 | 325 | let opened = yield waitForCondition(() => gEdit.popup.popupOpen); |
michael@0 | 326 | yield waitForCondition(() => gEdit.popup._results.itemCount > 0); |
michael@0 | 327 | |
michael@0 | 328 | ok(!gEdit.popup.hasAttribute("nomatch"), "'Popup doesnt have nomatch attribute when there are results"); |
michael@0 | 329 | ok(gEdit.popup._resultsContainer.getBoundingClientRect().width, "'Your results' are visible"); |
michael@0 | 330 | ok(gEdit.popup._results.itemCount > 0, "'Your results' are populated"); |
michael@0 | 331 | |
michael@0 | 332 | // Append a string to make sure it doesn't match anything in 'your results' |
michael@0 | 333 | EventUtils.sendString("zzzzzzzzzzzzzzzzzz", window); |
michael@0 | 334 | |
michael@0 | 335 | yield waitForCondition(() => gEdit.popup.hasAttribute("nomatch")); |
michael@0 | 336 | |
michael@0 | 337 | is(gEdit.popup._resultsContainer.getBoundingClientRect().width, 0, "'Your results' are hidden"); |
michael@0 | 338 | ok(gEdit.popup._results.itemCount === 0, "'Your results' are empty"); |
michael@0 | 339 | |
michael@0 | 340 | EventUtils.synthesizeKey("VK_DOWN", {}, window); |
michael@0 | 341 | is(gEdit.popup._searches.selectedIndex, 0, "key select search: first search selected"); |
michael@0 | 342 | |
michael@0 | 343 | EventUtils.synthesizeKey("VK_TAB", {}, window); |
michael@0 | 344 | is(gEdit.popup._searches.selectedIndex, 1, "tab key: second search selected"); |
michael@0 | 345 | |
michael@0 | 346 | EventUtils.synthesizeKey("VK_TAB", { shiftKey: true }, window); |
michael@0 | 347 | is(gEdit.popup._searches.selectedIndex, 0, "shift-tab: first search selected"); |
michael@0 | 348 | } |
michael@0 | 349 | }); |
michael@0 | 350 | |
michael@0 | 351 | gTests.push({ |
michael@0 | 352 | desc: "Bug 891667 - Use up arrow too", |
michael@0 | 353 | tearDown: tearDown, |
michael@0 | 354 | run: function testBug891667() { |
michael@0 | 355 | yield addTab("about:start"); |
michael@0 | 356 | yield showNavBar(); |
michael@0 | 357 | |
michael@0 | 358 | sendElementTap(window, gEdit); |
michael@0 | 359 | |
michael@0 | 360 | let bookmarkItem = Browser.selectedBrowser.contentWindow.BookmarksStartView._grid.querySelector("richgriditem"); |
michael@0 | 361 | // Get the first bookmark item label to make sure it will show up in 'your results' |
michael@0 | 362 | let label = bookmarkItem.getAttribute("label"); |
michael@0 | 363 | |
michael@0 | 364 | EventUtils.sendString(label, window); |
michael@0 | 365 | |
michael@0 | 366 | yield waitForCondition(() => gEdit.popup.popupOpen); |
michael@0 | 367 | yield waitForCondition(() => gEdit.popup._results.itemCount > 0); |
michael@0 | 368 | |
michael@0 | 369 | ok(gEdit.popup._results.itemCount > 0, "'Your results' populated"); |
michael@0 | 370 | |
michael@0 | 371 | EventUtils.synthesizeKey("VK_UP", {}, window); |
michael@0 | 372 | is(gEdit.popup._results.selectedIndex, 0, "Pressing arrow up selects first item."); |
michael@0 | 373 | |
michael@0 | 374 | EventUtils.synthesizeKey("VK_BACK_SPACE", {}, window); |
michael@0 | 375 | yield waitForEvent(document.getElementById("urlbar-edit"), "input"); |
michael@0 | 376 | is(gEdit.popup._results.selectedIndex, -1, "backspace: autocomplete de-selected"); |
michael@0 | 377 | } |
michael@0 | 378 | }); |
michael@0 | 379 |