Bug 975528 - Add search component tests for Bing searches. r=MattN,gavin
authorDrew Willcoxon <adw@mozilla.com>
Wed, 12 Mar 2014 16:56:00 -0700
changeset 173333 f2839d31d72d7e261973dc3ef0f2474bf8e65ede
parent 173332 dbf07d71ffc11a2a1affe50caf9e08b233b3638b
child 173334 1af5827670f84d91e359e4beeca40432c2eeebf1
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersMattN, gavin
bugs975528
milestone30.0a1
Bug 975528 - Add search component tests for Bing searches. r=MattN,gavin
browser/components/search/test/browser.ini
browser/components/search/test/browser_bing.js
browser/components/search/test/browser_bing_behavior.js
browser/components/search/test/browser_google.js
browser/components/search/test/browser_google_behavior.js
browser/components/search/test/head.js
--- a/browser/components/search/test/browser.ini
+++ b/browser/components/search/test/browser.ini
@@ -8,13 +8,15 @@ support-files =
   testEngine.src
   testEngine.xml
   testEngine_mozsearch.xml
 
 [browser_405664.js]
 [browser_426329.js]
 [browser_483086.js]
 [browser_addEngine.js]
+[browser_bing.js]
+[browser_bing_behavior.js]
 [browser_contextmenu.js]
 [browser_google.js]
 [browser_google_behavior.js]
 [browser_healthreport.js]
 [browser_private_search_perwindowpb.js]
new file mode 100644
--- /dev/null
+++ b/browser/components/search/test/browser_bing.js
@@ -0,0 +1,114 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/*
+ * Test Bing search plugin URLs
+ */
+
+"use strict";
+
+const BROWSER_SEARCH_PREF = "browser.search.";
+
+let runtime = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime);
+// Custom search parameters
+const PC_PARAM_VALUE = runtime.isOfficialBranding ? "MOZI" : null;
+
+function test() {
+  let engine = Services.search.getEngineByName("Bing");
+  ok(engine, "Bing");
+
+  let base = "http://www.bing.com/search?q=foo";
+  if (typeof(PC_PARAM_VALUE) == "string")
+    base += "&pc=" + PC_PARAM_VALUE;
+
+  let url;
+
+  // Test search URLs (including purposes).
+  url = engine.getSubmission("foo").uri.spec;
+  is(url, base, "Check search URL for 'foo'");
+  url = engine.getSubmission("foo", null, "contextmenu").uri.spec;
+  is(url, base + "&form=MOZSBR", "Check context menu search URL for 'foo'");
+  url = engine.getSubmission("foo", null, "keyword").uri.spec;
+  is(url, base + "&form=MOZLBR", "Check keyword search URL for 'foo'");
+  url = engine.getSubmission("foo", null, "searchbar").uri.spec;
+  is(url, base + "&form=MOZSBR", "Check search bar search URL for 'foo'");
+  url = engine.getSubmission("foo", null, "homepage").uri.spec;
+  is(url, base + "&form=MOZSPG", "Check homepage search URL for 'foo'");
+
+  // Check search suggestion URL.
+  url = engine.getSubmission("foo", "application/x-suggestions+json").uri.spec;
+  is(url, "http://api.bing.com/osjson.aspx?query=foo&form=OSDJAS&language=" + getLocale(), "Check search suggestion URL for 'foo'");
+
+  // Check all other engine properties.
+  const EXPECTED_ENGINE = {
+    name: "Bing",
+    alias: null,
+    description: "Bing. Search by Microsoft.",
+    searchForm: "http://www.bing.com/search",
+    type: Ci.nsISearchEngine.TYPE_MOZSEARCH,
+    hidden: false,
+    wrappedJSObject: {
+      queryCharset: "UTF-8",
+      "_iconURL": "data:image/x-icon;base64,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",
+      _urls : [
+        {
+          type: "application/x-suggestions+json",
+          method: "GET",
+          template: "http://api.bing.com/osjson.aspx",
+          params: [
+            {
+              name: "query",
+              value: "{searchTerms}",
+              purpose: undefined,
+            },
+            {
+              name: "form",
+              value: "OSDJAS",
+              purpose: undefined,
+            },
+            {
+              name: "language",
+              value: "{moz:locale}",
+              purpose: undefined,
+            },
+          ],
+        },
+        {
+          type: "text/html",
+          method: "GET",
+          template: "http://www.bing.com/search",
+          params: [
+            {
+              name: "q",
+              value: "{searchTerms}",
+              purpose: undefined,
+            },
+            {
+              name: "form",
+              value: "MOZSBR",
+              purpose: "contextmenu",
+            },
+            {
+              name: "form",
+              value: "MOZSBR",
+              purpose: "searchbar",
+            },
+            {
+              name: "form",
+              value: "MOZSPG",
+              purpose: "homepage",
+            },
+            {
+              name: "form",
+              value: "MOZLBR",
+              purpose:"keyword",
+            },
+          ],
+          mozparams: {},
+        },
+      ],
+    },
+  };
+
+  isSubObjectOf(EXPECTED_ENGINE, engine, "Bing");
+}
new file mode 100644
--- /dev/null
+++ b/browser/components/search/test/browser_bing_behavior.js
@@ -0,0 +1,147 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/*
+ * Test Bing search plugin URLs
+ */
+
+"use strict";
+
+const BROWSER_SEARCH_PREF = "browser.search.";
+
+let runtime = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime);
+// Custom search parameters
+const PC_PARAM_VALUE = runtime.isOfficialBranding ? "MOZI" : null;
+
+function test() {
+  let engine = Services.search.getEngineByName("Bing");
+  ok(engine, "Bing is installed");
+
+  let previouslySelectedEngine = Services.search.currentEngine;
+  Services.search.currentEngine = engine;
+
+  let base = "http://www.bing.com/search?q=foo";
+  if (typeof(PC_PARAM_VALUE) == "string")
+    base += "&pc=" + PC_PARAM_VALUE;
+
+  let url;
+
+  // Test search URLs (including purposes).
+  url = engine.getSubmission("foo").uri.spec;
+  is(url, base, "Check search URL for 'foo'");
+
+  waitForExplicitFinish();
+
+  var gCurrTest;
+  var gTests = [
+    {
+      name: "context menu search",
+      searchURL: base + "&form=MOZSBR",
+      run: function () {
+        // Simulate a contextmenu search
+        // FIXME: This is a bit "low-level"...
+        BrowserSearch.loadSearch("foo", false, "contextmenu");
+      }
+    },
+    {
+      name: "keyword search",
+      searchURL: base + "&form=MOZLBR",
+      run: function () {
+        gURLBar.value = "? foo";
+        gURLBar.focus();
+        EventUtils.synthesizeKey("VK_RETURN", {});
+      }
+    },
+    {
+      name: "search bar search",
+      searchURL: base + "&form=MOZSBR",
+      run: function () {
+        let sb = BrowserSearch.searchBar;
+        sb.focus();
+        sb.value = "foo";
+        registerCleanupFunction(function () {
+          sb.value = "";
+        });
+        EventUtils.synthesizeKey("VK_RETURN", {});
+      }
+    },
+    {
+      name: "home page search",
+      searchURL: base + "&form=MOZSPG",
+      run: function () {
+        // load about:home, but remove the listener first so it doesn't
+        // get in the way
+        gBrowser.removeProgressListener(listener);
+        gBrowser.loadURI("about:home");
+        info("Waiting for about:home load");
+        tab.linkedBrowser.addEventListener("load", function load(event) {
+          if (event.originalTarget != tab.linkedBrowser.contentDocument ||
+              event.target.location.href == "about:blank") {
+            info("skipping spurious load event");
+            return;
+          }
+          tab.linkedBrowser.removeEventListener("load", load, true);
+
+          // Observe page setup
+          let doc = gBrowser.contentDocument;
+          let mutationObserver = new MutationObserver(function (mutations) {
+            for (let mutation of mutations) {
+              if (mutation.attributeName == "searchEngineName") {
+                // Re-add the listener, and perform a search
+                gBrowser.addProgressListener(listener);
+                doc.getElementById("searchText").value = "foo";
+                doc.getElementById("searchSubmit").click();
+              }
+            }
+          });
+          mutationObserver.observe(doc.documentElement, { attributes: true });
+        }, true);
+      }
+    }
+  ];
+
+  function nextTest() {
+    if (gTests.length) {
+      gCurrTest = gTests.shift();
+      info("Running : " + gCurrTest.name);
+      executeSoon(gCurrTest.run);
+    } else {
+      finish();
+    }
+  }
+
+  let tab = gBrowser.selectedTab = gBrowser.addTab();
+
+  let listener = {
+    onStateChange: function onStateChange(webProgress, req, flags, status) {
+      info("onStateChange");
+      // Only care about top-level document starts
+      let docStart = Ci.nsIWebProgressListener.STATE_IS_DOCUMENT |
+                     Ci.nsIWebProgressListener.STATE_START;
+      if (!(flags & docStart) || !webProgress.isTopLevel)
+        return;
+
+      info("received document start");
+
+      ok(req instanceof Ci.nsIChannel, "req is a channel");
+      is(req.originalURI.spec, gCurrTest.searchURL, "search URL was loaded");
+      info("Actual URI: " + req.URI.spec);
+
+      req.cancel(Components.results.NS_ERROR_FAILURE);
+
+      executeSoon(nextTest);
+    }
+  }
+
+  registerCleanupFunction(function () {
+    gBrowser.removeProgressListener(listener);
+    gBrowser.removeTab(tab);
+    Services.search.currentEngine = previouslySelectedEngine;
+  });
+
+  tab.linkedBrowser.addEventListener("load", function load() {
+    tab.linkedBrowser.removeEventListener("load", load, true);
+    gBrowser.addProgressListener(listener);
+    nextTest();
+  }, true);
+}
--- a/browser/components/search/test/browser_google.js
+++ b/browser/components/search/test/browser_google.js
@@ -31,37 +31,16 @@ case "nightly":
 default:
   google_client = "firefox-a";
   break;
 }
 
 const GOOGLE_CLIENT = google_client;
 const MOZ_DISTRIBUTION_ID = runtime.distributionID;
 
-function getLocale() {
-  const localePref = "general.useragent.locale";
-  return getLocalizedPref(localePref, Services.prefs.getCharPref(localePref));
-}
-
-/**
- * Wrapper for nsIPrefBranch::getComplexValue.
- * @param aPrefName
- *        The name of the pref to get.
- * @returns aDefault if the requested pref doesn't exist.
- */
-function getLocalizedPref(aPrefName, aDefault) {
-  try {
-    return Services.prefs.getComplexValue(aPrefName, Ci.nsIPrefLocalizedString).data;
-  } catch (ex) {
-    return aDefault;
-  }
-
-  return aDefault;
-}
-
 function test() {
   let engine = Services.search.getEngineByName("Google");
   ok(engine, "Google");
 
   is(Services.search.defaultEngine, engine, "Check that Google is the default search engine");
 
   let distributionID;
   try {
@@ -97,16 +76,17 @@ function test() {
   const EXPECTED_ENGINE = {
     name: "Google",
     alias: null,
     description: "Google Search",
     searchForm: "https://www.google.com/",
     type: Ci.nsISearchEngine.TYPE_MOZSEARCH,
     hidden: false,
     wrappedJSObject: {
+      queryCharset: "UTF-8",
       "_iconURL": "data:image/x-icon;base64,AAABAAIAEBAAAAAAAAB9AQAAJgAAACAgAAAAAAAA8gIAAKMBAACJUE5HDQoaCgAAAA1JSERSAAAAEAAAABAIBgAAAB/z/2EAAAFESURBVDjLpZNJSwNBEIXnt4lE4kHxovgT9BDwJHqPy0HEEOJBiAuCRg+KUdC4QS4KrpC4gCBGE3NQ48JsnZ6eZ3UOM6gjaePhQU93v6+qq2q0pqgeJj2S8EdJT1hr0OxBtKCD5iEd8QxDYpvhvOBAuMDKURX9C9aPu4GA1GEVkzvMg10UBfYveWAWgYAP00V01fa+R9M2bA51wJvhIn3qR+ybt3D3JNQBE5sMjCIOLFpoHzOwdsLRO22qA6R6kiZiWwxUvy/PUQZIhYZ1vFM9cvcOOsYNdcBgysISdSJBnZjJMlR0Fw8vAp0xoz5gao/h+NZBy4i/10XGwrPA+hmvDyhVRG2Avu/LwcrkFADZa16L1h330w1RNgc3DiJzCpPYRm1bpveXX11clQR28xwblHpk1vq1iP/5mcoS0CoXDZiL0vsJ+dzfl+3T/VYAAAAASUVORK5CYIKJUE5HDQoaCgAAAA1JSERSAAAAIAAAACAIBgAAAHN6evQAAAK5SURBVFjDxVfrSxRRFJ9/Jta/oyWjF5XQm6D6EkHRgygIIgjUTcueVgqVWSRRkppEUQYWWB8ye1iGWilWlo/Ude489s7M6Zw7D9dlt53dmd29cFiWvXvO77x+51xpaaUsoSxBaUWZQ4ECy5xji2xKZDyCMlMEw6lCNiOSgwZKJK1SkcKeSealfP64t0mBjl4Ow39MkDUL0p2RSROOtqhZdeUEYM1pBl39XCg/fEeFtWcY7G9W4csvUxjlBkCsQ4Nt9QyWVfvT6RsAKXw3aoDGATZeYIt+W1kjw7cJG0RctWDTRebbKd8A6h5pwsDb70ba3w/eUr3wt/cmwgfw6Yft4TNMQaY7o1P2ncm4FT4ANQH/jQBJ2xv7kqIXEADDql8eS3+n8bku7oxNm+EDIM/dU92upb3T/NJGeaNbDx/AsbsLRUY5Xn92caWXY5d8RV6gWllxSg4fAEnTC90DQW13BLlgXR2D3dcUeDVkwOthA1bXspxILWcm3HdThcfvufB26LcJpkOEAz9NKI/lzqpSEC7feol5EWnpSeSlIxCALUkApmULdjUqxQVAQnl3D/X/yQda4QBEq2TYc12By091MQ17Bg3R88nHKlQbVmHvj89awNBLYrwT9zXY2aBAxTkGFdiSxP/Jp6FLDw+AS7GfsdJTJ2EqSO5khD43nGfBARy/ZxOQgZHe7GPM1jzUvChUtmnBAXQPcKGMJp3fdFGq6NByEhiAO4b/YptFfQJwNyQ/bZkVQGcf90Ja25ndIyrKBOa/f8wIpwi3X1G8UcxNu7ozUS7tiH0jBswwS3RIaF1w6LYKU/ML2+8sGnjygQswtKrVIy/Qd9qQP6LnO64q4fPAKpxyZIymHo1jWk6p1ag2BsdNwQMHcC+M5kHFJX+YlPxpVlbCx2mZ5DzPI04k4kUwHHdskU3pH76iftG8yWlkAAAAAElFTkSuQmCC",
       _urls : [
         {
           type: "application/x-suggestions+json",
           method: "GET",
           template: "https://www.google.com/complete/search?client=firefox&q={searchTerms}",
           params: "",
         },
--- a/browser/components/search/test/browser_google_behavior.js
+++ b/browser/components/search/test/browser_google_behavior.js
@@ -31,31 +31,16 @@ case "nightly":
 default:
   google_client = "firefox-a";
   break;
 }
 
 const GOOGLE_CLIENT = google_client;
 const MOZ_DISTRIBUTION_ID = runtime.distributionID;
 
-function getLocale() {
-  const localePref = "general.useragent.locale";
-  return getLocalizedPref(localePref, Services.prefs.getCharPref(localePref));
-}
-
-function getLocalizedPref(aPrefName, aDefault) {
-  try {
-    return Services.prefs.getComplexValue(aPrefName, Ci.nsIPrefLocalizedString).data;
-  } catch (ex) {
-    return aDefault;
-  }
-
-  return aDefault;
-}
-
 function test() {
   let engine = Services.search.getEngineByName("Google");
   ok(engine, "Google is installed");
 
   is(Services.search.defaultEngine, engine, "Check that Google is the default search engine");
 
   let distributionID;
   try {
--- a/browser/components/search/test/head.js
+++ b/browser/components/search/test/head.js
@@ -46,16 +46,37 @@ function isSubObjectOf(expectedObj, actu
       is(actualObj[prop].length, expectedObj[prop].length, name + "[" + prop + "]");
       isSubObjectOf(expectedObj[prop], actualObj[prop], name + "[" + prop + "]");
     } else {
       is(actualObj[prop], expectedObj[prop], name + "[" + prop + "]");
     }
   }
 }
 
+function getLocale() {
+  const localePref = "general.useragent.locale";
+  return getLocalizedPref(localePref, Services.prefs.getCharPref(localePref));
+}
+
+/**
+ * Wrapper for nsIPrefBranch::getComplexValue.
+ * @param aPrefName
+ *        The name of the pref to get.
+ * @returns aDefault if the requested pref doesn't exist.
+ */
+function getLocalizedPref(aPrefName, aDefault) {
+  try {
+    return Services.prefs.getComplexValue(aPrefName, Ci.nsIPrefLocalizedString).data;
+  } catch (ex) {
+    return aDefault;
+  }
+
+  return aDefault;
+}
+
 function waitForPopupShown(aPopupId, aCallback) {
   let popup = document.getElementById(aPopupId);
   info("waitForPopupShown: got popup: " + popup.id);
   function onPopupShown() {
     info("onPopupShown");
     removePopupShownListener();
     SimpleTest.executeSoon(aCallback);
   }