toolkit/mozapps/extensions/test/browser/browser_searching.js

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/toolkit/mozapps/extensions/test/browser/browser_searching.js	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,695 @@
     1.4 +/* Any copyright is dedicated to the Public Domain.
     1.5 + * http://creativecommons.org/publicdomain/zero/1.0/
     1.6 + */
     1.7 +
     1.8 +// Tests that searching for add-ons works correctly
     1.9 +
    1.10 +const PREF_GETADDONS_GETSEARCHRESULTS = "extensions.getAddons.search.url";
    1.11 +const SEARCH_URL = TESTROOT + "browser_searching.xml";
    1.12 +const NO_MATCH_URL = TESTROOT + "browser_searching_empty.xml";
    1.13 +
    1.14 +const QUERY = "SEARCH";
    1.15 +const NO_MATCH_QUERY = "NOMATCHQUERY";
    1.16 +const REMOTE_TO_INSTALL = "remote1";
    1.17 +const REMOTE_INSTALL_URL = TESTROOT + "addons/browser_searching.xpi";
    1.18 +
    1.19 +var gManagerWindow;
    1.20 +var gCategoryUtilities;
    1.21 +var gProvider;
    1.22 +var gServer;
    1.23 +var gAddonInstalled = false;
    1.24 +
    1.25 +function test() {
    1.26 +  requestLongerTimeout(2);
    1.27 +  // Turn on searching for this test
    1.28 +  Services.prefs.setIntPref(PREF_SEARCH_MAXRESULTS, 15);
    1.29 +  Services.prefs.setBoolPref(PREF_STRICT_COMPAT, true);
    1.30 +
    1.31 +  waitForExplicitFinish();
    1.32 +
    1.33 +  gProvider = new MockProvider();
    1.34 +
    1.35 +  gProvider.createAddons([{
    1.36 +    id: "addon1@tests.mozilla.org",
    1.37 +    name: "PASS - f",
    1.38 +    description: "Test description - SEARCH",
    1.39 +    size: 3,
    1.40 +    version: "1.0",
    1.41 +    updateDate: new Date(2010, 4, 2, 0, 0, 1)
    1.42 +  }, {
    1.43 +    id: "fail-addon1@tests.mozilla.org",
    1.44 +    name: "FAIL",
    1.45 +    description: "Does not match query"
    1.46 +  }, {
    1.47 +    id: "addon2@tests.mozilla.org",
    1.48 +    name: "PASS - c",
    1.49 +    description: "Test description - reSEARCHing SEARCH SEARCH",
    1.50 +    size: 6,
    1.51 +    version: "2.0",
    1.52 +    updateDate: new Date(2010, 4, 2, 0, 0, 0)
    1.53 +  }]);
    1.54 +
    1.55 +  var installs = gProvider.createInstalls([{
    1.56 +    name: "PASS - a - SEARCHing",
    1.57 +    sourceURI: "http://example.com/install1.xpi"
    1.58 +  }, {
    1.59 +    name: "PASS - g - reSEARCHing SEARCH",
    1.60 +    sourceURI: "http://example.com/install2.xpi"
    1.61 +  }, {
    1.62 +    // Does not match query
    1.63 +    name: "FAIL",
    1.64 +    sourceURI: "http://example.com/fail-install1.xpi"
    1.65 +  }]);
    1.66 +
    1.67 +  for (let install of installs )
    1.68 +    install.install();
    1.69 +
    1.70 +  open_manager("addons://list/extension", function(aWindow) {
    1.71 +    gManagerWindow = aWindow;
    1.72 +    gCategoryUtilities = new CategoryUtilities(gManagerWindow);
    1.73 +    run_next_test();
    1.74 +  });
    1.75 +}
    1.76 +
    1.77 +function end_test() {
    1.78 +  close_manager(gManagerWindow, function() {
    1.79 +    var installedAddon = get_addon_item(REMOTE_TO_INSTALL).mAddon;
    1.80 +    installedAddon.uninstall();
    1.81 +
    1.82 +    AddonManager.getAllInstalls(function(aInstallsList) {
    1.83 +      for (var install of aInstallsList) {
    1.84 +        var sourceURI = install.sourceURI.spec;
    1.85 +        if (sourceURI == REMOTE_INSTALL_URL ||
    1.86 +            sourceURI.match(/^http:\/\/example\.com\/(.+)\.xpi$/) != null)
    1.87 +          install.cancel();
    1.88 +      }
    1.89 +
    1.90 +      finish();
    1.91 +    });
    1.92 +  });
    1.93 +}
    1.94 +
    1.95 +function getAnonymousElementByAttribute(aElement, aName, aValue) {
    1.96 +  return gManagerWindow.document.getAnonymousElementByAttribute(aElement,
    1.97 +                                                                aName,
    1.98 +                                                                aValue);
    1.99 +}
   1.100 +
   1.101 +/*
   1.102 + * Checks whether or not the Add-ons Manager is currently searching
   1.103 + *
   1.104 + * @param  aExpectedSearching
   1.105 + *         The expected isSearching state
   1.106 + */
   1.107 +function check_is_searching(aExpectedSearching) {
   1.108 +  var loading = gManagerWindow.document.getElementById("search-loading");
   1.109 +  is(!is_hidden(loading), aExpectedSearching,
   1.110 +     "Search throbber should be showing iff currently searching");
   1.111 +}
   1.112 +
   1.113 +/*
   1.114 + * Completes a search
   1.115 + *
   1.116 + * @param  aQuery
   1.117 + *         The query to search for
   1.118 + * @param  aFinishImmediately
   1.119 + *         Boolean representing whether or not the search is expected to
   1.120 + *         finish immediately
   1.121 + * @param  aCallback
   1.122 + *         The callback to call when the search is done
   1.123 + * @param  aCategoryType
   1.124 + *         The expected selected category after the search is done.
   1.125 + *         Optional and defaults to "search"
   1.126 + */
   1.127 +function search(aQuery, aFinishImmediately, aCallback, aCategoryType) {
   1.128 +  // Point search to the correct xml test file
   1.129 +  var url = (aQuery == NO_MATCH_QUERY) ? NO_MATCH_URL : SEARCH_URL;
   1.130 +  Services.prefs.setCharPref(PREF_GETADDONS_GETSEARCHRESULTS, url);
   1.131 +
   1.132 +  aCategoryType = aCategoryType ? aCategoryType : "search";
   1.133 +
   1.134 +  var searchBox = gManagerWindow.document.getElementById("header-search");
   1.135 +  searchBox.value = aQuery;
   1.136 +
   1.137 +  EventUtils.synthesizeMouseAtCenter(searchBox, { }, gManagerWindow);
   1.138 +  EventUtils.synthesizeKey("VK_RETURN", { }, gManagerWindow);
   1.139 +
   1.140 +  var finishImmediately = true;
   1.141 +  wait_for_view_load(gManagerWindow, function() {
   1.142 +    is(gCategoryUtilities.selectedCategory, aCategoryType, "Expected category view should be selected");
   1.143 +    is(gCategoryUtilities.isTypeVisible("search"), aCategoryType == "search",
   1.144 +       "Search category should only be visible if it is the current view");
   1.145 +    check_is_searching(false);
   1.146 +    is(finishImmediately, aFinishImmediately, "Search should finish immediately only if expected");
   1.147 +
   1.148 +    aCallback();
   1.149 +  });
   1.150 +
   1.151 +  finishImmediately = false
   1.152 +  if (!aFinishImmediately)
   1.153 +    check_is_searching(true);
   1.154 +}
   1.155 +
   1.156 +/*
   1.157 + * Return results of a search
   1.158 + *
   1.159 + * @return Array of objects, each containing the name and item of a specific
   1.160 + *         result
   1.161 + */
   1.162 +function get_actual_results() {
   1.163 +  var list = gManagerWindow.document.getElementById("search-list");
   1.164 +  var rows = list.getElementsByTagName("richlistitem");
   1.165 +
   1.166 +  var results = [];
   1.167 +  for (var item of rows) {
   1.168 +
   1.169 +    // Only consider items that are currently showing
   1.170 +    var style = gManagerWindow.document.defaultView.getComputedStyle(item, "");
   1.171 +    if (style.display == "none" || style.visibility != "visible")
   1.172 +      continue;
   1.173 +
   1.174 +    if (item.mInstall || item.isPending("install")) {
   1.175 +      var sourceURI = item.mInstall.sourceURI.spec;
   1.176 +      if (sourceURI == REMOTE_INSTALL_URL) {
   1.177 +        results.push({name: REMOTE_TO_INSTALL, item: item});
   1.178 +        continue;
   1.179 +      }
   1.180 +
   1.181 +      var result = sourceURI.match(/^http:\/\/example\.com\/(.+)\.xpi$/);
   1.182 +      if (result != null) {
   1.183 +        is(item.mInstall.name.indexOf("PASS"), 0, "Install name should start with PASS");
   1.184 +        results.push({name: result[1], item: item});
   1.185 +        continue;
   1.186 +      }
   1.187 +    }
   1.188 +    else if (item.mAddon) {
   1.189 +      var result = item.mAddon.id.match(/^(.+)@tests\.mozilla\.org$/);
   1.190 +      if (result != null) {
   1.191 +        is(item.mAddon.name.indexOf("PASS"), 0, "Addon name should start with PASS");
   1.192 +        results.push({name: result[1], item: item});
   1.193 +        continue;
   1.194 +      }
   1.195 +    }
   1.196 +    else {
   1.197 +      ok(false, "Found an item in the list that was neither installing or installed");
   1.198 +    }
   1.199 +  }
   1.200 +
   1.201 +  return results;
   1.202 +}
   1.203 +
   1.204 +/*
   1.205 + * Returns expected results when searching for QUERY with default ordering
   1.206 + *
   1.207 + * @param  aSortBy
   1.208 + *         How the results are sorted (e.g. "name")
   1.209 + * @param  aLocalExpected
   1.210 + *         Boolean representing if local results are expected
   1.211 + * @return A pair: [array of results with an expected order,
   1.212 + *                  array of results with unknown order]
   1.213 + */
   1.214 +function get_expected_results(aSortBy, aLocalExpected) {
   1.215 +  var expectedOrder = null, unknownOrder = null;
   1.216 +  switch (aSortBy) {
   1.217 +    case "relevancescore":
   1.218 +      expectedOrder = [ "addon2"  , "remote1", "install2", "addon1",
   1.219 +                        "install1", "remote2", "remote3" , "remote4" ];
   1.220 +      unknownOrder = [];
   1.221 +      break;
   1.222 +    case "name":
   1.223 +      // Defaults to ascending order
   1.224 +      expectedOrder = [ "install1", "remote1",  "addon2" , "remote2",
   1.225 +                        "remote3" , "addon1" , "install2", "remote4" ];
   1.226 +      unknownOrder = [];
   1.227 +      break;
   1.228 +    case "dateUpdated":
   1.229 +      expectedOrder = [ "addon1", "addon2" ];
   1.230 +      // Updated date not available for installs and remote add-ons
   1.231 +      unknownOrder = [ "install1", "install2", "remote1",
   1.232 +                       "remote2" , "remote3" , "remote4" ];
   1.233 +      break;
   1.234 +    default:
   1.235 +      ok(false, "Should recognize sortBy when checking the order of items");
   1.236 +  }
   1.237 +
   1.238 +  // Only keep expected results
   1.239 +  function filterResults(aId) {
   1.240 +    // Include REMOTE_TO_INSTALL as a local add-on if it has been installed
   1.241 +    if (gAddonInstalled && aId == REMOTE_TO_INSTALL)
   1.242 +      return aLocalExpected;
   1.243 +
   1.244 +    if (aId.indexOf("addon") == 0 || aId.indexOf("install") == 0)
   1.245 +      return aLocalExpected;
   1.246 +    if (aId.indexOf("remote") == 0)
   1.247 +      return !aLocalExpected;
   1.248 +
   1.249 +    return false;
   1.250 +  }
   1.251 +
   1.252 +
   1.253 +  return [expectedOrder.filter(filterResults),
   1.254 +          unknownOrder.filter(filterResults)]
   1.255 +}
   1.256 +
   1.257 +/*
   1.258 + * Check that the actual and expected results are the same
   1.259 + *
   1.260 + * @param  aQuery
   1.261 + *         The search query used
   1.262 + * @param  aSortBy
   1.263 + *         How the results are sorted (e.g. "name")
   1.264 + * @param  aReverseOrder
   1.265 + *         Boolean representing if the results are in reverse default order
   1.266 + * @param  aShowLocal
   1.267 + *         Boolean representing if local results are being shown
   1.268 + */
   1.269 +function check_results(aQuery, aSortBy, aReverseOrder, aShowLocal) {
   1.270 +
   1.271 +  var xpinstall_enabled = true;
   1.272 +  try {
   1.273 +    xpinstall_enabled = Services.prefs.getBoolPref(PREF_XPI_ENABLED);
   1.274 +  }
   1.275 +  catch (e) {};
   1.276 +
   1.277 +  // When XPI Instalation is disabled, those buttons are hidden and unused  
   1.278 +  if (xpinstall_enabled) {
   1.279 +    var localFilterSelected = gManagerWindow.document.getElementById("search-filter-local").selected;
   1.280 +    var remoteFilterSelected = gManagerWindow.document.getElementById("search-filter-remote").selected;
   1.281 +    is(localFilterSelected, aShowLocal, "Local filter should be selected if showing local items");
   1.282 +    is(remoteFilterSelected, !aShowLocal, "Remote filter should be selected if showing remote items");
   1.283 +  }
   1.284 +
   1.285 +  // Get expected order assuming default order
   1.286 +  var expectedOrder = [], unknownOrder = [];
   1.287 +  if (aQuery == QUERY)
   1.288 +    [expectedOrder, unknownOrder] = get_expected_results(aSortBy, aShowLocal);
   1.289 +
   1.290 +  // Get actual order of results
   1.291 +  var actualResults = get_actual_results();
   1.292 +  var actualOrder = [result.name for each(result in actualResults)];
   1.293 +
   1.294 +  // Reverse array of actual results if supposed to be in reverse order.
   1.295 +  // Reverse actualOrder instead of expectedOrder so can always check
   1.296 +  // expectedOrder before unknownOrder
   1.297 +  if (aReverseOrder)
   1.298 +    actualOrder.reverse();
   1.299 +
   1.300 +  // Check actual vs. expected list of results
   1.301 +  var totalExpectedResults = expectedOrder.length + unknownOrder.length;
   1.302 +  is(actualOrder.length, totalExpectedResults, "Should get correct number of results");
   1.303 +
   1.304 +  // Check the "first" and "last" attributes are set correctly
   1.305 +  for (let i = 0; i < actualResults.length; i++) {
   1.306 +    if (i == 0) {
   1.307 +      is(actualResults[0].item.hasAttribute("first"), true,
   1.308 +         "First item should have 'first' attribute set");
   1.309 +      is(actualResults[0].item.hasAttribute("last"), false,
   1.310 +         "First item should not have 'last' attribute set");
   1.311 +    } else if (i == (actualResults.length - 1)) {
   1.312 +      is(actualResults[actualResults.length - 1].item.hasAttribute("first"), false,
   1.313 +         "Last item should not have 'first' attribute set");
   1.314 +      is(actualResults[actualResults.length - 1].item.hasAttribute("last"), true,
   1.315 +         "Last item should have 'last' attribute set");
   1.316 +    } else {
   1.317 +      is(actualResults[i].item.hasAttribute("first"), false,
   1.318 +         "Item " + i + " should not have 'first' attribute set");
   1.319 +      is(actualResults[i].item.hasAttribute("last"), false,
   1.320 +         "Item " + i + " should not have 'last' attribute set");
   1.321 +    }
   1.322 +  }
   1.323 +
   1.324 +  var i = 0;
   1.325 +  for (; i < expectedOrder.length; i++)
   1.326 +    is(actualOrder[i], expectedOrder[i], "Should have seen expected item");
   1.327 +
   1.328 +  // Items with data that is unknown can appear in any order among themselves,
   1.329 +  // so just check that these items exist
   1.330 +  for (; i < actualOrder.length; i++) {
   1.331 +    var unknownOrderIndex = unknownOrder.indexOf(actualOrder[i]);
   1.332 +    ok(unknownOrderIndex >= 0, "Should expect to see item with data that is unknown");
   1.333 +    unknownOrder[unknownOrderIndex] = null;
   1.334 +  }
   1.335 +
   1.336 +  // Check status of empty notice
   1.337 +  var emptyNotice = gManagerWindow.document.getElementById("search-list-empty");
   1.338 +  is(emptyNotice.hidden, totalExpectedResults > 0,
   1.339 +     "Empty notice should be hidden only if expecting shown items");
   1.340 +}
   1.341 +
   1.342 +/*
   1.343 + * Check results of a search with different filterings
   1.344 + *
   1.345 + * @param  aQuery
   1.346 + *         The search query used
   1.347 + * @param  aSortBy
   1.348 + *         How the results are sorted (e.g. "name")
   1.349 + * @param  aReverseOrder
   1.350 + *         Boolean representing if the results are in reverse default order
   1.351 + * @param  aLocalOnly
   1.352 + *         Boolean representing if the results are local only, can be undefined
   1.353 + */
   1.354 +function check_filtered_results(aQuery, aSortBy, aReverseOrder, aLocalOnly) {
   1.355 +  var localFilter = gManagerWindow.document.getElementById("search-filter-local");
   1.356 +  var remoteFilter = gManagerWindow.document.getElementById("search-filter-remote");
   1.357 +
   1.358 +  var list = gManagerWindow.document.getElementById("search-list");
   1.359 +  list.ensureElementIsVisible(localFilter);
   1.360 +
   1.361 +  // Check with showing local add-ons
   1.362 +  EventUtils.synthesizeMouseAtCenter(localFilter, { }, gManagerWindow);
   1.363 +  check_results(aQuery, aSortBy, aReverseOrder, true);
   1.364 +
   1.365 +  // Check with showing remote add-ons
   1.366 +  aLocalOnly = aLocalOnly || false;
   1.367 +  EventUtils.synthesizeMouseAtCenter(remoteFilter, { }, gManagerWindow);
   1.368 +  check_results(aQuery, aSortBy, aReverseOrder, aLocalOnly);
   1.369 +}
   1.370 +
   1.371 +/*
   1.372 + * Get item for a specific add-on by name
   1.373 + *
   1.374 + * @param  aName
   1.375 + *         The name of the add-on to search for
   1.376 + * @return Row of add-on if found, null otherwise
   1.377 + */
   1.378 +function get_addon_item(aName) {
   1.379 +  var id = aName + "@tests.mozilla.org";
   1.380 +  var list = gManagerWindow.document.getElementById("search-list");
   1.381 +  var rows = list.getElementsByTagName("richlistitem");
   1.382 +  for (var row of rows) {
   1.383 +    if (row.mAddon && row.mAddon.id == id)
   1.384 +      return row;
   1.385 +  }
   1.386 +
   1.387 +  return null;
   1.388 +}
   1.389 +
   1.390 +/*
   1.391 + * Get item for a specific install by name
   1.392 + *
   1.393 + * @param  aName
   1.394 + *         The name of the install to search for
   1.395 + * @return Row of install if found, null otherwise
   1.396 + */
   1.397 +function get_install_item(aName) {
   1.398 +  var sourceURI = "http://example.com/" + aName + ".xpi";
   1.399 +  var list = gManagerWindow.document.getElementById("search-list");
   1.400 +  var rows = list.getElementsByTagName("richlistitem");
   1.401 +  for (var row of rows) {
   1.402 +    if (row.mInstall && row.mInstall.sourceURI.spec == sourceURI)
   1.403 +      return row;
   1.404 +  }
   1.405 +
   1.406 +  return null;
   1.407 +}
   1.408 +
   1.409 +/*
   1.410 + * Gets the install button for a specific item
   1.411 + *
   1.412 + * @param  aItem
   1.413 + *         The item to get the install button for
   1.414 + * @return The install button for aItem
   1.415 + */
   1.416 +function get_install_button(aItem) {
   1.417 +  isnot(aItem, null, "Item should not be null when checking state of install button");
   1.418 +  var installStatus = getAnonymousElementByAttribute(aItem, "anonid", "install-status");
   1.419 +  return getAnonymousElementByAttribute(installStatus, "anonid", "install-remote-btn");
   1.420 +}
   1.421 +
   1.422 +
   1.423 +// Tests that searching for the empty string does nothing when not in the search view
   1.424 +add_test(function() {
   1.425 +  is(gCategoryUtilities.isTypeVisible("search"), false, "Search category should initially be hidden");
   1.426 +
   1.427 +  var selectedCategory = gCategoryUtilities.selectedCategory;
   1.428 +  isnot(selectedCategory, "search", "Selected type should not initially be the search view");
   1.429 +  search("", true, run_next_test, selectedCategory);
   1.430 +});
   1.431 +
   1.432 +// Tests that the results from a query are sorted by relevancescore in descending order.
   1.433 +// Also test that double clicking non-install items goes to the detail view, and that
   1.434 +// only remote items have install buttons showing
   1.435 +add_test(function() {
   1.436 +  search(QUERY, false, function() {
   1.437 +    check_filtered_results(QUERY, "relevancescore", false);
   1.438 +
   1.439 +    var list = gManagerWindow.document.getElementById("search-list");
   1.440 +    var results = get_actual_results();
   1.441 +    for (var result of results) {
   1.442 +      var installBtn = get_install_button(result.item);
   1.443 +      is(installBtn.hidden, result.name.indexOf("remote") != 0,
   1.444 +         "Install button should only be showing for remote items");
   1.445 +    }
   1.446 +
   1.447 +    var currentIndex = -1;
   1.448 +    function run_next_double_click_test() {
   1.449 +      currentIndex++;
   1.450 +      if (currentIndex >= results.length) {
   1.451 +        run_next_test();
   1.452 +        return;
   1.453 +      }
   1.454 +
   1.455 +      var result = results[currentIndex];
   1.456 +      if (result.name.indexOf("install") == 0) {
   1.457 +        run_next_double_click_test();
   1.458 +        return;
   1.459 +      }
   1.460 +
   1.461 +      var item = result.item;
   1.462 +      list.ensureElementIsVisible(item);
   1.463 +      EventUtils.synthesizeMouseAtCenter(item, { clickCount: 1 }, gManagerWindow);
   1.464 +      EventUtils.synthesizeMouseAtCenter(item, { clickCount: 2 }, gManagerWindow);
   1.465 +      wait_for_view_load(gManagerWindow, function() {
   1.466 +        var name = gManagerWindow.document.getElementById("detail-name").textContent;
   1.467 +        is(name, item.mAddon.name, "Name in detail view should be correct");
   1.468 +        var version = gManagerWindow.document.getElementById("detail-version").value;
   1.469 +        is(version, item.mAddon.version, "Version in detail view should be correct");
   1.470 +
   1.471 +        EventUtils.synthesizeMouseAtCenter(gManagerWindow.document.getElementById("category-search"),
   1.472 +                                           { }, gManagerWindow);
   1.473 +        wait_for_view_load(gManagerWindow, run_next_double_click_test);
   1.474 +      });
   1.475 +    }
   1.476 +
   1.477 +    run_next_double_click_test();
   1.478 +  });
   1.479 +});
   1.480 +
   1.481 +// Tests that the sorters and filters correctly manipulate the results
   1.482 +add_test(function() {
   1.483 +  var sorters = gManagerWindow.document.getElementById("search-sorters");
   1.484 +  var originalHandler = sorters.handler;
   1.485 +
   1.486 +  var sorterNames = ["name", "dateUpdated"];
   1.487 +  var buttonIds = ["name-btn", "date-btn"];
   1.488 +  var currentIndex = 0;
   1.489 +  var currentReversed = false;
   1.490 +
   1.491 +  function run_sort_test() {
   1.492 +    if (currentIndex >= sorterNames.length) {
   1.493 +      sorters.handler = originalHandler;
   1.494 +      run_next_test();
   1.495 +      return;
   1.496 +    }
   1.497 +
   1.498 +    // Simulate clicking on a specific sorter
   1.499 +    var buttonId = buttonIds[currentIndex];
   1.500 +    var sorter = getAnonymousElementByAttribute(sorters, "anonid", buttonId);
   1.501 +    is_element_visible(sorter);
   1.502 +    EventUtils.synthesizeMouseAtCenter(sorter, { }, gManagerWindow);
   1.503 +  }
   1.504 +
   1.505 +  sorters.handler = {
   1.506 +    onSortChanged: function(aSortBy, aAscending) {
   1.507 +      if (originalHandler && "onSortChanged" in originalHandler)
   1.508 +        originalHandler.onSortChanged(aSortBy, aAscending);
   1.509 +
   1.510 +      check_filtered_results(QUERY, sorterNames[currentIndex], currentReversed);
   1.511 +
   1.512 +      if (currentReversed)
   1.513 +        currentIndex++;
   1.514 +      currentReversed = !currentReversed;
   1.515 +
   1.516 +      run_sort_test();
   1.517 +    }
   1.518 +  };
   1.519 +
   1.520 +  check_filtered_results(QUERY, "relevancescore", false);
   1.521 +  run_sort_test();
   1.522 +});
   1.523 +
   1.524 +// Tests that searching for the empty string does nothing when in search view
   1.525 +add_test(function() {
   1.526 +  search("", true, function() {
   1.527 +    check_filtered_results(QUERY, "dateUpdated", true);
   1.528 +    run_next_test();
   1.529 +  });
   1.530 +});
   1.531 +
   1.532 +// Tests that clicking a different category hides the search query
   1.533 +add_test(function() {
   1.534 +  gCategoryUtilities.openType("extension", function() {
   1.535 +    is(gCategoryUtilities.isTypeVisible("search"), false, "Search category should be hidden");
   1.536 +    is(gCategoryUtilities.selectedCategory, "extension", "View should have changed to extension");
   1.537 +    run_next_test();
   1.538 +  });
   1.539 +});
   1.540 +
   1.541 +// Tests that re-searching for query doesn't actually complete a new search,
   1.542 +// and the last sort is still used
   1.543 +add_test(function() {
   1.544 +  search(QUERY, true, function() {
   1.545 +    check_filtered_results(QUERY, "dateUpdated", true);
   1.546 +    run_next_test();
   1.547 +  });
   1.548 +});
   1.549 +
   1.550 +// Tests that getting zero results works correctly
   1.551 +add_test(function() {
   1.552 +  search(NO_MATCH_QUERY, false, function() {
   1.553 +    check_filtered_results(NO_MATCH_QUERY, "relevancescore", false);
   1.554 +    run_next_test();
   1.555 +  });
   1.556 +});
   1.557 +
   1.558 +// Tests that installing a remote add-on works
   1.559 +add_test(function() {
   1.560 +  var installBtn = null;
   1.561 +
   1.562 +  var listener = {
   1.563 +    onInstallEnded: function(aInstall, aAddon) {
   1.564 +      // Don't immediately consider the installed add-on as local because
   1.565 +      // if the user was filtering out local add-ons, the installed add-on
   1.566 +      // would vanish. Only consider add-on as local on new searches.
   1.567 +
   1.568 +      aInstall.removeListener(this);
   1.569 +
   1.570 +      is(installBtn.hidden, true, "Install button should be hidden after install ended");
   1.571 +      check_filtered_results(QUERY, "relevancescore", false);
   1.572 +      run_next_test();
   1.573 +    }
   1.574 +  }
   1.575 +
   1.576 +  search(QUERY, false, function() {
   1.577 +    var list = gManagerWindow.document.getElementById("search-list");
   1.578 +    var remoteItem = get_addon_item(REMOTE_TO_INSTALL);
   1.579 +    list.ensureElementIsVisible(remoteItem);
   1.580 +
   1.581 +    installBtn = get_install_button(remoteItem);
   1.582 +    is(installBtn.hidden, false, "Install button should be showing before install");
   1.583 +    remoteItem.mAddon.install.addListener(listener);
   1.584 +    EventUtils.synthesizeMouseAtCenter(installBtn, { }, gManagerWindow);
   1.585 +  });
   1.586 +});
   1.587 +
   1.588 +// Tests that re-searching for query results in correct results
   1.589 +add_test(function() {
   1.590 +  // Select a different category
   1.591 +  gCategoryUtilities.openType("extension", function() {
   1.592 +    is(gCategoryUtilities.isTypeVisible("search"), false, "Search category should be hidden");
   1.593 +    is(gCategoryUtilities.selectedCategory, "extension", "View should have changed to extension");
   1.594 +
   1.595 +    var installBtn = get_install_button(get_addon_item(REMOTE_TO_INSTALL));
   1.596 +    is(installBtn.hidden, true, "Install button should be hidden for installed item");
   1.597 +
   1.598 +    search(QUERY, true, function() {
   1.599 +      check_filtered_results(QUERY, "relevancescore", false);
   1.600 +      run_next_test();
   1.601 +    });
   1.602 +  });
   1.603 +});
   1.604 +
   1.605 +// Tests that incompatible add-ons are shown with a warning if compatibility checking is disabled
   1.606 +add_test(function() {
   1.607 +  AddonManager.checkCompatibility = false;
   1.608 +  search("incompatible", false, function() {
   1.609 +    var item = get_addon_item("remote5");
   1.610 +    is_element_visible(item, "Incompatible addon should be visible");
   1.611 +    is(item.getAttribute("notification"), "warning", "Compatibility warning should be shown");
   1.612 +
   1.613 +    item = get_addon_item("remote6");
   1.614 +    is(item, null, "Addon incompatible with the product should not be visible");
   1.615 +
   1.616 +    AddonManager.checkCompatibility = true;
   1.617 +    run_next_test();
   1.618 +  });
   1.619 +});
   1.620 +
   1.621 +// Tests that compatible-by-default addons are shown if strict compatibility checking is disabled
   1.622 +add_test(function() {
   1.623 +  restart_manager(gManagerWindow, null, function(aWindow) {
   1.624 +    gManagerWindow = aWindow;
   1.625 +    gCategoryUtilities = new CategoryUtilities(gManagerWindow);
   1.626 +
   1.627 +    Services.prefs.setBoolPref(PREF_STRICT_COMPAT, false);
   1.628 +    search("incompatible", false, function() {
   1.629 +      var item = get_addon_item("remote5");
   1.630 +      is_element_visible(item, "Incompatible addon should be visible");
   1.631 +      isnot(item.getAttribute("notification"), "warning", "Compatibility warning should not be shown");
   1.632 +  
   1.633 +      var item = get_addon_item("remote6");
   1.634 +      is(item, null, "Addon incompatible with the product should not be visible");
   1.635 +  
   1.636 +      Services.prefs.setBoolPref(PREF_STRICT_COMPAT, true);
   1.637 +      run_next_test();
   1.638 +    });
   1.639 +  });
   1.640 +});
   1.641 +
   1.642 +
   1.643 +// Tests that restarting the manager doesn't change search results
   1.644 +add_test(function() {
   1.645 +  restart_manager(gManagerWindow, null, function(aWindow) {
   1.646 +    gManagerWindow = aWindow;
   1.647 +    gCategoryUtilities = new CategoryUtilities(gManagerWindow);
   1.648 +
   1.649 +    // We never restore to the search pane
   1.650 +    is(gCategoryUtilities.selectedCategory, "discover", "View should have changed to discover");
   1.651 +
   1.652 +    // Installed add-on is considered local on new search
   1.653 +    gAddonInstalled = true;
   1.654 +
   1.655 +    search(QUERY, false, function() {
   1.656 +      check_filtered_results(QUERY, "relevancescore", false);
   1.657 +
   1.658 +      var installBtn = get_install_button(get_addon_item(REMOTE_TO_INSTALL));
   1.659 +      is(installBtn.hidden, true, "Install button should be hidden for installed item");
   1.660 +
   1.661 +      run_next_test();
   1.662 +    });
   1.663 +  });
   1.664 +});
   1.665 +
   1.666 +function bug_815120_test_search(aLocalOnly) {
   1.667 +  restart_manager(gManagerWindow, "addons://list/extension", function(aWindow) {
   1.668 +    gManagerWindow = aWindow;
   1.669 +    gCategoryUtilities = new CategoryUtilities(gManagerWindow);
   1.670 +
   1.671 +    // Installed add-on is considered local on new search
   1.672 +    gAddonInstalled = true;
   1.673 +
   1.674 +    // The search buttons should be hidden in the LocalOnly setup
   1.675 +    var localFilterButton = aWindow.document.getElementById("search-filter-local");
   1.676 +    is(aLocalOnly, is_hidden(localFilterButton), "Local filter button visibility does not match, aLocalOnly = " + aLocalOnly);
   1.677 +
   1.678 +    var remoteFilterButton = aWindow.document.getElementById("search-filter-remote");
   1.679 +    is(aLocalOnly, is_hidden(remoteFilterButton), "Remote filter button visibility does not match, aLocalOnly = " + aLocalOnly);
   1.680 +
   1.681 +    search(QUERY, false, function() {
   1.682 +      check_filtered_results(QUERY, "relevancescore", false, aLocalOnly);
   1.683 +      run_next_test();
   1.684 +    });
   1.685 +  });
   1.686 +}
   1.687 +
   1.688 +// Tests for Bug 815120
   1.689 +add_test(function() {
   1.690 +  Services.prefs.setBoolPref(PREF_XPI_ENABLED, false);
   1.691 +  bug_815120_test_search(true);
   1.692 +});
   1.693 +
   1.694 +add_test(function() {
   1.695 +  Services.prefs.setBoolPref(PREF_XPI_ENABLED, true);
   1.696 +  bug_815120_test_search(false);
   1.697 +});
   1.698 +

mercurial