|
1 /* Any copyright is dedicated to the Public Domain. |
|
2 * http://creativecommons.org/publicdomain/zero/1.0/ |
|
3 */ |
|
4 |
|
5 // Tests that searching for add-ons works correctly |
|
6 |
|
7 const PREF_GETADDONS_GETSEARCHRESULTS = "extensions.getAddons.search.url"; |
|
8 const SEARCH_URL = TESTROOT + "browser_searching.xml"; |
|
9 const NO_MATCH_URL = TESTROOT + "browser_searching_empty.xml"; |
|
10 |
|
11 const QUERY = "SEARCH"; |
|
12 const NO_MATCH_QUERY = "NOMATCHQUERY"; |
|
13 const REMOTE_TO_INSTALL = "remote1"; |
|
14 const REMOTE_INSTALL_URL = TESTROOT + "addons/browser_searching.xpi"; |
|
15 |
|
16 var gManagerWindow; |
|
17 var gCategoryUtilities; |
|
18 var gProvider; |
|
19 var gServer; |
|
20 var gAddonInstalled = false; |
|
21 |
|
22 function test() { |
|
23 requestLongerTimeout(2); |
|
24 // Turn on searching for this test |
|
25 Services.prefs.setIntPref(PREF_SEARCH_MAXRESULTS, 15); |
|
26 Services.prefs.setBoolPref(PREF_STRICT_COMPAT, true); |
|
27 |
|
28 waitForExplicitFinish(); |
|
29 |
|
30 gProvider = new MockProvider(); |
|
31 |
|
32 gProvider.createAddons([{ |
|
33 id: "addon1@tests.mozilla.org", |
|
34 name: "PASS - f", |
|
35 description: "Test description - SEARCH", |
|
36 size: 3, |
|
37 version: "1.0", |
|
38 updateDate: new Date(2010, 4, 2, 0, 0, 1) |
|
39 }, { |
|
40 id: "fail-addon1@tests.mozilla.org", |
|
41 name: "FAIL", |
|
42 description: "Does not match query" |
|
43 }, { |
|
44 id: "addon2@tests.mozilla.org", |
|
45 name: "PASS - c", |
|
46 description: "Test description - reSEARCHing SEARCH SEARCH", |
|
47 size: 6, |
|
48 version: "2.0", |
|
49 updateDate: new Date(2010, 4, 2, 0, 0, 0) |
|
50 }]); |
|
51 |
|
52 var installs = gProvider.createInstalls([{ |
|
53 name: "PASS - a - SEARCHing", |
|
54 sourceURI: "http://example.com/install1.xpi" |
|
55 }, { |
|
56 name: "PASS - g - reSEARCHing SEARCH", |
|
57 sourceURI: "http://example.com/install2.xpi" |
|
58 }, { |
|
59 // Does not match query |
|
60 name: "FAIL", |
|
61 sourceURI: "http://example.com/fail-install1.xpi" |
|
62 }]); |
|
63 |
|
64 for (let install of installs ) |
|
65 install.install(); |
|
66 |
|
67 open_manager("addons://list/extension", function(aWindow) { |
|
68 gManagerWindow = aWindow; |
|
69 gCategoryUtilities = new CategoryUtilities(gManagerWindow); |
|
70 run_next_test(); |
|
71 }); |
|
72 } |
|
73 |
|
74 function end_test() { |
|
75 close_manager(gManagerWindow, function() { |
|
76 var installedAddon = get_addon_item(REMOTE_TO_INSTALL).mAddon; |
|
77 installedAddon.uninstall(); |
|
78 |
|
79 AddonManager.getAllInstalls(function(aInstallsList) { |
|
80 for (var install of aInstallsList) { |
|
81 var sourceURI = install.sourceURI.spec; |
|
82 if (sourceURI == REMOTE_INSTALL_URL || |
|
83 sourceURI.match(/^http:\/\/example\.com\/(.+)\.xpi$/) != null) |
|
84 install.cancel(); |
|
85 } |
|
86 |
|
87 finish(); |
|
88 }); |
|
89 }); |
|
90 } |
|
91 |
|
92 function getAnonymousElementByAttribute(aElement, aName, aValue) { |
|
93 return gManagerWindow.document.getAnonymousElementByAttribute(aElement, |
|
94 aName, |
|
95 aValue); |
|
96 } |
|
97 |
|
98 /* |
|
99 * Checks whether or not the Add-ons Manager is currently searching |
|
100 * |
|
101 * @param aExpectedSearching |
|
102 * The expected isSearching state |
|
103 */ |
|
104 function check_is_searching(aExpectedSearching) { |
|
105 var loading = gManagerWindow.document.getElementById("search-loading"); |
|
106 is(!is_hidden(loading), aExpectedSearching, |
|
107 "Search throbber should be showing iff currently searching"); |
|
108 } |
|
109 |
|
110 /* |
|
111 * Completes a search |
|
112 * |
|
113 * @param aQuery |
|
114 * The query to search for |
|
115 * @param aFinishImmediately |
|
116 * Boolean representing whether or not the search is expected to |
|
117 * finish immediately |
|
118 * @param aCallback |
|
119 * The callback to call when the search is done |
|
120 * @param aCategoryType |
|
121 * The expected selected category after the search is done. |
|
122 * Optional and defaults to "search" |
|
123 */ |
|
124 function search(aQuery, aFinishImmediately, aCallback, aCategoryType) { |
|
125 // Point search to the correct xml test file |
|
126 var url = (aQuery == NO_MATCH_QUERY) ? NO_MATCH_URL : SEARCH_URL; |
|
127 Services.prefs.setCharPref(PREF_GETADDONS_GETSEARCHRESULTS, url); |
|
128 |
|
129 aCategoryType = aCategoryType ? aCategoryType : "search"; |
|
130 |
|
131 var searchBox = gManagerWindow.document.getElementById("header-search"); |
|
132 searchBox.value = aQuery; |
|
133 |
|
134 EventUtils.synthesizeMouseAtCenter(searchBox, { }, gManagerWindow); |
|
135 EventUtils.synthesizeKey("VK_RETURN", { }, gManagerWindow); |
|
136 |
|
137 var finishImmediately = true; |
|
138 wait_for_view_load(gManagerWindow, function() { |
|
139 is(gCategoryUtilities.selectedCategory, aCategoryType, "Expected category view should be selected"); |
|
140 is(gCategoryUtilities.isTypeVisible("search"), aCategoryType == "search", |
|
141 "Search category should only be visible if it is the current view"); |
|
142 check_is_searching(false); |
|
143 is(finishImmediately, aFinishImmediately, "Search should finish immediately only if expected"); |
|
144 |
|
145 aCallback(); |
|
146 }); |
|
147 |
|
148 finishImmediately = false |
|
149 if (!aFinishImmediately) |
|
150 check_is_searching(true); |
|
151 } |
|
152 |
|
153 /* |
|
154 * Return results of a search |
|
155 * |
|
156 * @return Array of objects, each containing the name and item of a specific |
|
157 * result |
|
158 */ |
|
159 function get_actual_results() { |
|
160 var list = gManagerWindow.document.getElementById("search-list"); |
|
161 var rows = list.getElementsByTagName("richlistitem"); |
|
162 |
|
163 var results = []; |
|
164 for (var item of rows) { |
|
165 |
|
166 // Only consider items that are currently showing |
|
167 var style = gManagerWindow.document.defaultView.getComputedStyle(item, ""); |
|
168 if (style.display == "none" || style.visibility != "visible") |
|
169 continue; |
|
170 |
|
171 if (item.mInstall || item.isPending("install")) { |
|
172 var sourceURI = item.mInstall.sourceURI.spec; |
|
173 if (sourceURI == REMOTE_INSTALL_URL) { |
|
174 results.push({name: REMOTE_TO_INSTALL, item: item}); |
|
175 continue; |
|
176 } |
|
177 |
|
178 var result = sourceURI.match(/^http:\/\/example\.com\/(.+)\.xpi$/); |
|
179 if (result != null) { |
|
180 is(item.mInstall.name.indexOf("PASS"), 0, "Install name should start with PASS"); |
|
181 results.push({name: result[1], item: item}); |
|
182 continue; |
|
183 } |
|
184 } |
|
185 else if (item.mAddon) { |
|
186 var result = item.mAddon.id.match(/^(.+)@tests\.mozilla\.org$/); |
|
187 if (result != null) { |
|
188 is(item.mAddon.name.indexOf("PASS"), 0, "Addon name should start with PASS"); |
|
189 results.push({name: result[1], item: item}); |
|
190 continue; |
|
191 } |
|
192 } |
|
193 else { |
|
194 ok(false, "Found an item in the list that was neither installing or installed"); |
|
195 } |
|
196 } |
|
197 |
|
198 return results; |
|
199 } |
|
200 |
|
201 /* |
|
202 * Returns expected results when searching for QUERY with default ordering |
|
203 * |
|
204 * @param aSortBy |
|
205 * How the results are sorted (e.g. "name") |
|
206 * @param aLocalExpected |
|
207 * Boolean representing if local results are expected |
|
208 * @return A pair: [array of results with an expected order, |
|
209 * array of results with unknown order] |
|
210 */ |
|
211 function get_expected_results(aSortBy, aLocalExpected) { |
|
212 var expectedOrder = null, unknownOrder = null; |
|
213 switch (aSortBy) { |
|
214 case "relevancescore": |
|
215 expectedOrder = [ "addon2" , "remote1", "install2", "addon1", |
|
216 "install1", "remote2", "remote3" , "remote4" ]; |
|
217 unknownOrder = []; |
|
218 break; |
|
219 case "name": |
|
220 // Defaults to ascending order |
|
221 expectedOrder = [ "install1", "remote1", "addon2" , "remote2", |
|
222 "remote3" , "addon1" , "install2", "remote4" ]; |
|
223 unknownOrder = []; |
|
224 break; |
|
225 case "dateUpdated": |
|
226 expectedOrder = [ "addon1", "addon2" ]; |
|
227 // Updated date not available for installs and remote add-ons |
|
228 unknownOrder = [ "install1", "install2", "remote1", |
|
229 "remote2" , "remote3" , "remote4" ]; |
|
230 break; |
|
231 default: |
|
232 ok(false, "Should recognize sortBy when checking the order of items"); |
|
233 } |
|
234 |
|
235 // Only keep expected results |
|
236 function filterResults(aId) { |
|
237 // Include REMOTE_TO_INSTALL as a local add-on if it has been installed |
|
238 if (gAddonInstalled && aId == REMOTE_TO_INSTALL) |
|
239 return aLocalExpected; |
|
240 |
|
241 if (aId.indexOf("addon") == 0 || aId.indexOf("install") == 0) |
|
242 return aLocalExpected; |
|
243 if (aId.indexOf("remote") == 0) |
|
244 return !aLocalExpected; |
|
245 |
|
246 return false; |
|
247 } |
|
248 |
|
249 |
|
250 return [expectedOrder.filter(filterResults), |
|
251 unknownOrder.filter(filterResults)] |
|
252 } |
|
253 |
|
254 /* |
|
255 * Check that the actual and expected results are the same |
|
256 * |
|
257 * @param aQuery |
|
258 * The search query used |
|
259 * @param aSortBy |
|
260 * How the results are sorted (e.g. "name") |
|
261 * @param aReverseOrder |
|
262 * Boolean representing if the results are in reverse default order |
|
263 * @param aShowLocal |
|
264 * Boolean representing if local results are being shown |
|
265 */ |
|
266 function check_results(aQuery, aSortBy, aReverseOrder, aShowLocal) { |
|
267 |
|
268 var xpinstall_enabled = true; |
|
269 try { |
|
270 xpinstall_enabled = Services.prefs.getBoolPref(PREF_XPI_ENABLED); |
|
271 } |
|
272 catch (e) {}; |
|
273 |
|
274 // When XPI Instalation is disabled, those buttons are hidden and unused |
|
275 if (xpinstall_enabled) { |
|
276 var localFilterSelected = gManagerWindow.document.getElementById("search-filter-local").selected; |
|
277 var remoteFilterSelected = gManagerWindow.document.getElementById("search-filter-remote").selected; |
|
278 is(localFilterSelected, aShowLocal, "Local filter should be selected if showing local items"); |
|
279 is(remoteFilterSelected, !aShowLocal, "Remote filter should be selected if showing remote items"); |
|
280 } |
|
281 |
|
282 // Get expected order assuming default order |
|
283 var expectedOrder = [], unknownOrder = []; |
|
284 if (aQuery == QUERY) |
|
285 [expectedOrder, unknownOrder] = get_expected_results(aSortBy, aShowLocal); |
|
286 |
|
287 // Get actual order of results |
|
288 var actualResults = get_actual_results(); |
|
289 var actualOrder = [result.name for each(result in actualResults)]; |
|
290 |
|
291 // Reverse array of actual results if supposed to be in reverse order. |
|
292 // Reverse actualOrder instead of expectedOrder so can always check |
|
293 // expectedOrder before unknownOrder |
|
294 if (aReverseOrder) |
|
295 actualOrder.reverse(); |
|
296 |
|
297 // Check actual vs. expected list of results |
|
298 var totalExpectedResults = expectedOrder.length + unknownOrder.length; |
|
299 is(actualOrder.length, totalExpectedResults, "Should get correct number of results"); |
|
300 |
|
301 // Check the "first" and "last" attributes are set correctly |
|
302 for (let i = 0; i < actualResults.length; i++) { |
|
303 if (i == 0) { |
|
304 is(actualResults[0].item.hasAttribute("first"), true, |
|
305 "First item should have 'first' attribute set"); |
|
306 is(actualResults[0].item.hasAttribute("last"), false, |
|
307 "First item should not have 'last' attribute set"); |
|
308 } else if (i == (actualResults.length - 1)) { |
|
309 is(actualResults[actualResults.length - 1].item.hasAttribute("first"), false, |
|
310 "Last item should not have 'first' attribute set"); |
|
311 is(actualResults[actualResults.length - 1].item.hasAttribute("last"), true, |
|
312 "Last item should have 'last' attribute set"); |
|
313 } else { |
|
314 is(actualResults[i].item.hasAttribute("first"), false, |
|
315 "Item " + i + " should not have 'first' attribute set"); |
|
316 is(actualResults[i].item.hasAttribute("last"), false, |
|
317 "Item " + i + " should not have 'last' attribute set"); |
|
318 } |
|
319 } |
|
320 |
|
321 var i = 0; |
|
322 for (; i < expectedOrder.length; i++) |
|
323 is(actualOrder[i], expectedOrder[i], "Should have seen expected item"); |
|
324 |
|
325 // Items with data that is unknown can appear in any order among themselves, |
|
326 // so just check that these items exist |
|
327 for (; i < actualOrder.length; i++) { |
|
328 var unknownOrderIndex = unknownOrder.indexOf(actualOrder[i]); |
|
329 ok(unknownOrderIndex >= 0, "Should expect to see item with data that is unknown"); |
|
330 unknownOrder[unknownOrderIndex] = null; |
|
331 } |
|
332 |
|
333 // Check status of empty notice |
|
334 var emptyNotice = gManagerWindow.document.getElementById("search-list-empty"); |
|
335 is(emptyNotice.hidden, totalExpectedResults > 0, |
|
336 "Empty notice should be hidden only if expecting shown items"); |
|
337 } |
|
338 |
|
339 /* |
|
340 * Check results of a search with different filterings |
|
341 * |
|
342 * @param aQuery |
|
343 * The search query used |
|
344 * @param aSortBy |
|
345 * How the results are sorted (e.g. "name") |
|
346 * @param aReverseOrder |
|
347 * Boolean representing if the results are in reverse default order |
|
348 * @param aLocalOnly |
|
349 * Boolean representing if the results are local only, can be undefined |
|
350 */ |
|
351 function check_filtered_results(aQuery, aSortBy, aReverseOrder, aLocalOnly) { |
|
352 var localFilter = gManagerWindow.document.getElementById("search-filter-local"); |
|
353 var remoteFilter = gManagerWindow.document.getElementById("search-filter-remote"); |
|
354 |
|
355 var list = gManagerWindow.document.getElementById("search-list"); |
|
356 list.ensureElementIsVisible(localFilter); |
|
357 |
|
358 // Check with showing local add-ons |
|
359 EventUtils.synthesizeMouseAtCenter(localFilter, { }, gManagerWindow); |
|
360 check_results(aQuery, aSortBy, aReverseOrder, true); |
|
361 |
|
362 // Check with showing remote add-ons |
|
363 aLocalOnly = aLocalOnly || false; |
|
364 EventUtils.synthesizeMouseAtCenter(remoteFilter, { }, gManagerWindow); |
|
365 check_results(aQuery, aSortBy, aReverseOrder, aLocalOnly); |
|
366 } |
|
367 |
|
368 /* |
|
369 * Get item for a specific add-on by name |
|
370 * |
|
371 * @param aName |
|
372 * The name of the add-on to search for |
|
373 * @return Row of add-on if found, null otherwise |
|
374 */ |
|
375 function get_addon_item(aName) { |
|
376 var id = aName + "@tests.mozilla.org"; |
|
377 var list = gManagerWindow.document.getElementById("search-list"); |
|
378 var rows = list.getElementsByTagName("richlistitem"); |
|
379 for (var row of rows) { |
|
380 if (row.mAddon && row.mAddon.id == id) |
|
381 return row; |
|
382 } |
|
383 |
|
384 return null; |
|
385 } |
|
386 |
|
387 /* |
|
388 * Get item for a specific install by name |
|
389 * |
|
390 * @param aName |
|
391 * The name of the install to search for |
|
392 * @return Row of install if found, null otherwise |
|
393 */ |
|
394 function get_install_item(aName) { |
|
395 var sourceURI = "http://example.com/" + aName + ".xpi"; |
|
396 var list = gManagerWindow.document.getElementById("search-list"); |
|
397 var rows = list.getElementsByTagName("richlistitem"); |
|
398 for (var row of rows) { |
|
399 if (row.mInstall && row.mInstall.sourceURI.spec == sourceURI) |
|
400 return row; |
|
401 } |
|
402 |
|
403 return null; |
|
404 } |
|
405 |
|
406 /* |
|
407 * Gets the install button for a specific item |
|
408 * |
|
409 * @param aItem |
|
410 * The item to get the install button for |
|
411 * @return The install button for aItem |
|
412 */ |
|
413 function get_install_button(aItem) { |
|
414 isnot(aItem, null, "Item should not be null when checking state of install button"); |
|
415 var installStatus = getAnonymousElementByAttribute(aItem, "anonid", "install-status"); |
|
416 return getAnonymousElementByAttribute(installStatus, "anonid", "install-remote-btn"); |
|
417 } |
|
418 |
|
419 |
|
420 // Tests that searching for the empty string does nothing when not in the search view |
|
421 add_test(function() { |
|
422 is(gCategoryUtilities.isTypeVisible("search"), false, "Search category should initially be hidden"); |
|
423 |
|
424 var selectedCategory = gCategoryUtilities.selectedCategory; |
|
425 isnot(selectedCategory, "search", "Selected type should not initially be the search view"); |
|
426 search("", true, run_next_test, selectedCategory); |
|
427 }); |
|
428 |
|
429 // Tests that the results from a query are sorted by relevancescore in descending order. |
|
430 // Also test that double clicking non-install items goes to the detail view, and that |
|
431 // only remote items have install buttons showing |
|
432 add_test(function() { |
|
433 search(QUERY, false, function() { |
|
434 check_filtered_results(QUERY, "relevancescore", false); |
|
435 |
|
436 var list = gManagerWindow.document.getElementById("search-list"); |
|
437 var results = get_actual_results(); |
|
438 for (var result of results) { |
|
439 var installBtn = get_install_button(result.item); |
|
440 is(installBtn.hidden, result.name.indexOf("remote") != 0, |
|
441 "Install button should only be showing for remote items"); |
|
442 } |
|
443 |
|
444 var currentIndex = -1; |
|
445 function run_next_double_click_test() { |
|
446 currentIndex++; |
|
447 if (currentIndex >= results.length) { |
|
448 run_next_test(); |
|
449 return; |
|
450 } |
|
451 |
|
452 var result = results[currentIndex]; |
|
453 if (result.name.indexOf("install") == 0) { |
|
454 run_next_double_click_test(); |
|
455 return; |
|
456 } |
|
457 |
|
458 var item = result.item; |
|
459 list.ensureElementIsVisible(item); |
|
460 EventUtils.synthesizeMouseAtCenter(item, { clickCount: 1 }, gManagerWindow); |
|
461 EventUtils.synthesizeMouseAtCenter(item, { clickCount: 2 }, gManagerWindow); |
|
462 wait_for_view_load(gManagerWindow, function() { |
|
463 var name = gManagerWindow.document.getElementById("detail-name").textContent; |
|
464 is(name, item.mAddon.name, "Name in detail view should be correct"); |
|
465 var version = gManagerWindow.document.getElementById("detail-version").value; |
|
466 is(version, item.mAddon.version, "Version in detail view should be correct"); |
|
467 |
|
468 EventUtils.synthesizeMouseAtCenter(gManagerWindow.document.getElementById("category-search"), |
|
469 { }, gManagerWindow); |
|
470 wait_for_view_load(gManagerWindow, run_next_double_click_test); |
|
471 }); |
|
472 } |
|
473 |
|
474 run_next_double_click_test(); |
|
475 }); |
|
476 }); |
|
477 |
|
478 // Tests that the sorters and filters correctly manipulate the results |
|
479 add_test(function() { |
|
480 var sorters = gManagerWindow.document.getElementById("search-sorters"); |
|
481 var originalHandler = sorters.handler; |
|
482 |
|
483 var sorterNames = ["name", "dateUpdated"]; |
|
484 var buttonIds = ["name-btn", "date-btn"]; |
|
485 var currentIndex = 0; |
|
486 var currentReversed = false; |
|
487 |
|
488 function run_sort_test() { |
|
489 if (currentIndex >= sorterNames.length) { |
|
490 sorters.handler = originalHandler; |
|
491 run_next_test(); |
|
492 return; |
|
493 } |
|
494 |
|
495 // Simulate clicking on a specific sorter |
|
496 var buttonId = buttonIds[currentIndex]; |
|
497 var sorter = getAnonymousElementByAttribute(sorters, "anonid", buttonId); |
|
498 is_element_visible(sorter); |
|
499 EventUtils.synthesizeMouseAtCenter(sorter, { }, gManagerWindow); |
|
500 } |
|
501 |
|
502 sorters.handler = { |
|
503 onSortChanged: function(aSortBy, aAscending) { |
|
504 if (originalHandler && "onSortChanged" in originalHandler) |
|
505 originalHandler.onSortChanged(aSortBy, aAscending); |
|
506 |
|
507 check_filtered_results(QUERY, sorterNames[currentIndex], currentReversed); |
|
508 |
|
509 if (currentReversed) |
|
510 currentIndex++; |
|
511 currentReversed = !currentReversed; |
|
512 |
|
513 run_sort_test(); |
|
514 } |
|
515 }; |
|
516 |
|
517 check_filtered_results(QUERY, "relevancescore", false); |
|
518 run_sort_test(); |
|
519 }); |
|
520 |
|
521 // Tests that searching for the empty string does nothing when in search view |
|
522 add_test(function() { |
|
523 search("", true, function() { |
|
524 check_filtered_results(QUERY, "dateUpdated", true); |
|
525 run_next_test(); |
|
526 }); |
|
527 }); |
|
528 |
|
529 // Tests that clicking a different category hides the search query |
|
530 add_test(function() { |
|
531 gCategoryUtilities.openType("extension", function() { |
|
532 is(gCategoryUtilities.isTypeVisible("search"), false, "Search category should be hidden"); |
|
533 is(gCategoryUtilities.selectedCategory, "extension", "View should have changed to extension"); |
|
534 run_next_test(); |
|
535 }); |
|
536 }); |
|
537 |
|
538 // Tests that re-searching for query doesn't actually complete a new search, |
|
539 // and the last sort is still used |
|
540 add_test(function() { |
|
541 search(QUERY, true, function() { |
|
542 check_filtered_results(QUERY, "dateUpdated", true); |
|
543 run_next_test(); |
|
544 }); |
|
545 }); |
|
546 |
|
547 // Tests that getting zero results works correctly |
|
548 add_test(function() { |
|
549 search(NO_MATCH_QUERY, false, function() { |
|
550 check_filtered_results(NO_MATCH_QUERY, "relevancescore", false); |
|
551 run_next_test(); |
|
552 }); |
|
553 }); |
|
554 |
|
555 // Tests that installing a remote add-on works |
|
556 add_test(function() { |
|
557 var installBtn = null; |
|
558 |
|
559 var listener = { |
|
560 onInstallEnded: function(aInstall, aAddon) { |
|
561 // Don't immediately consider the installed add-on as local because |
|
562 // if the user was filtering out local add-ons, the installed add-on |
|
563 // would vanish. Only consider add-on as local on new searches. |
|
564 |
|
565 aInstall.removeListener(this); |
|
566 |
|
567 is(installBtn.hidden, true, "Install button should be hidden after install ended"); |
|
568 check_filtered_results(QUERY, "relevancescore", false); |
|
569 run_next_test(); |
|
570 } |
|
571 } |
|
572 |
|
573 search(QUERY, false, function() { |
|
574 var list = gManagerWindow.document.getElementById("search-list"); |
|
575 var remoteItem = get_addon_item(REMOTE_TO_INSTALL); |
|
576 list.ensureElementIsVisible(remoteItem); |
|
577 |
|
578 installBtn = get_install_button(remoteItem); |
|
579 is(installBtn.hidden, false, "Install button should be showing before install"); |
|
580 remoteItem.mAddon.install.addListener(listener); |
|
581 EventUtils.synthesizeMouseAtCenter(installBtn, { }, gManagerWindow); |
|
582 }); |
|
583 }); |
|
584 |
|
585 // Tests that re-searching for query results in correct results |
|
586 add_test(function() { |
|
587 // Select a different category |
|
588 gCategoryUtilities.openType("extension", function() { |
|
589 is(gCategoryUtilities.isTypeVisible("search"), false, "Search category should be hidden"); |
|
590 is(gCategoryUtilities.selectedCategory, "extension", "View should have changed to extension"); |
|
591 |
|
592 var installBtn = get_install_button(get_addon_item(REMOTE_TO_INSTALL)); |
|
593 is(installBtn.hidden, true, "Install button should be hidden for installed item"); |
|
594 |
|
595 search(QUERY, true, function() { |
|
596 check_filtered_results(QUERY, "relevancescore", false); |
|
597 run_next_test(); |
|
598 }); |
|
599 }); |
|
600 }); |
|
601 |
|
602 // Tests that incompatible add-ons are shown with a warning if compatibility checking is disabled |
|
603 add_test(function() { |
|
604 AddonManager.checkCompatibility = false; |
|
605 search("incompatible", false, function() { |
|
606 var item = get_addon_item("remote5"); |
|
607 is_element_visible(item, "Incompatible addon should be visible"); |
|
608 is(item.getAttribute("notification"), "warning", "Compatibility warning should be shown"); |
|
609 |
|
610 item = get_addon_item("remote6"); |
|
611 is(item, null, "Addon incompatible with the product should not be visible"); |
|
612 |
|
613 AddonManager.checkCompatibility = true; |
|
614 run_next_test(); |
|
615 }); |
|
616 }); |
|
617 |
|
618 // Tests that compatible-by-default addons are shown if strict compatibility checking is disabled |
|
619 add_test(function() { |
|
620 restart_manager(gManagerWindow, null, function(aWindow) { |
|
621 gManagerWindow = aWindow; |
|
622 gCategoryUtilities = new CategoryUtilities(gManagerWindow); |
|
623 |
|
624 Services.prefs.setBoolPref(PREF_STRICT_COMPAT, false); |
|
625 search("incompatible", false, function() { |
|
626 var item = get_addon_item("remote5"); |
|
627 is_element_visible(item, "Incompatible addon should be visible"); |
|
628 isnot(item.getAttribute("notification"), "warning", "Compatibility warning should not be shown"); |
|
629 |
|
630 var item = get_addon_item("remote6"); |
|
631 is(item, null, "Addon incompatible with the product should not be visible"); |
|
632 |
|
633 Services.prefs.setBoolPref(PREF_STRICT_COMPAT, true); |
|
634 run_next_test(); |
|
635 }); |
|
636 }); |
|
637 }); |
|
638 |
|
639 |
|
640 // Tests that restarting the manager doesn't change search results |
|
641 add_test(function() { |
|
642 restart_manager(gManagerWindow, null, function(aWindow) { |
|
643 gManagerWindow = aWindow; |
|
644 gCategoryUtilities = new CategoryUtilities(gManagerWindow); |
|
645 |
|
646 // We never restore to the search pane |
|
647 is(gCategoryUtilities.selectedCategory, "discover", "View should have changed to discover"); |
|
648 |
|
649 // Installed add-on is considered local on new search |
|
650 gAddonInstalled = true; |
|
651 |
|
652 search(QUERY, false, function() { |
|
653 check_filtered_results(QUERY, "relevancescore", false); |
|
654 |
|
655 var installBtn = get_install_button(get_addon_item(REMOTE_TO_INSTALL)); |
|
656 is(installBtn.hidden, true, "Install button should be hidden for installed item"); |
|
657 |
|
658 run_next_test(); |
|
659 }); |
|
660 }); |
|
661 }); |
|
662 |
|
663 function bug_815120_test_search(aLocalOnly) { |
|
664 restart_manager(gManagerWindow, "addons://list/extension", function(aWindow) { |
|
665 gManagerWindow = aWindow; |
|
666 gCategoryUtilities = new CategoryUtilities(gManagerWindow); |
|
667 |
|
668 // Installed add-on is considered local on new search |
|
669 gAddonInstalled = true; |
|
670 |
|
671 // The search buttons should be hidden in the LocalOnly setup |
|
672 var localFilterButton = aWindow.document.getElementById("search-filter-local"); |
|
673 is(aLocalOnly, is_hidden(localFilterButton), "Local filter button visibility does not match, aLocalOnly = " + aLocalOnly); |
|
674 |
|
675 var remoteFilterButton = aWindow.document.getElementById("search-filter-remote"); |
|
676 is(aLocalOnly, is_hidden(remoteFilterButton), "Remote filter button visibility does not match, aLocalOnly = " + aLocalOnly); |
|
677 |
|
678 search(QUERY, false, function() { |
|
679 check_filtered_results(QUERY, "relevancescore", false, aLocalOnly); |
|
680 run_next_test(); |
|
681 }); |
|
682 }); |
|
683 } |
|
684 |
|
685 // Tests for Bug 815120 |
|
686 add_test(function() { |
|
687 Services.prefs.setBoolPref(PREF_XPI_ENABLED, false); |
|
688 bug_815120_test_search(true); |
|
689 }); |
|
690 |
|
691 add_test(function() { |
|
692 Services.prefs.setBoolPref(PREF_XPI_ENABLED, true); |
|
693 bug_815120_test_search(false); |
|
694 }); |
|
695 |