mirror of
				https://github.com/mozilla/gecko-dev.git
				synced 2025-10-31 16:28:05 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			329 lines
		
	
	
	
		
			9.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			329 lines
		
	
	
	
		
			9.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /* This Source Code Form is subject to the terms of the Mozilla Public
 | |
|  * License, v. 2.0. If a copy of the MPL was not distributed with this
 | |
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | |
| 
 | |
| /**
 | |
|  * Test for bug 549340.
 | |
|  * Test for browser.js::contentAreaClick() util.
 | |
|  *
 | |
|  * The test opens a new browser window, then replaces browser.js methods invoked
 | |
|  * by contentAreaClick with a mock function that tracks which methods have been
 | |
|  * called.
 | |
|  * Each sub-test synthesizes a mouse click event on links injected in content,
 | |
|  * the event is collected by a click handler that ensures that contentAreaClick
 | |
|  * correctly prevent default events, and follows the correct code path.
 | |
|  */
 | |
| 
 | |
| const { sinon } = ChromeUtils.importESModule(
 | |
|   "resource://testing-common/Sinon.sys.mjs"
 | |
| );
 | |
| 
 | |
| var gTests = [
 | |
|   {
 | |
|     desc: "Simple left click",
 | |
|     setup() {},
 | |
|     clean() {},
 | |
|     event: {},
 | |
|     targets: ["commonlink", "mathlink", "svgxlink", "maplink"],
 | |
|     expectedInvokedMethods: [],
 | |
|     preventDefault: false,
 | |
|   },
 | |
| 
 | |
|   {
 | |
|     desc: "Ctrl/Cmd left click",
 | |
|     setup() {},
 | |
|     clean() {},
 | |
|     event: { ctrlKey: true, metaKey: true },
 | |
|     targets: ["commonlink", "mathlink", "svgxlink", "maplink"],
 | |
|     expectedInvokedMethods: ["urlSecurityCheck", "openLinkIn"],
 | |
|     preventDefault: true,
 | |
|   },
 | |
| 
 | |
|   // The next test should just be like Alt click.
 | |
|   {
 | |
|     desc: "Shift+Alt left click",
 | |
|     setup() {
 | |
|       Services.prefs.setBoolPref("browser.altClickSave", true);
 | |
|     },
 | |
|     clean() {
 | |
|       Services.prefs.clearUserPref("browser.altClickSave");
 | |
|     },
 | |
|     event: { shiftKey: true, altKey: true },
 | |
|     targets: ["commonlink", "maplink"],
 | |
|     expectedInvokedMethods: ["gatherTextUnder", "saveURL"],
 | |
|     preventDefault: true,
 | |
|   },
 | |
| 
 | |
|   {
 | |
|     desc: "Shift+Alt left click on XLinks",
 | |
|     setup() {
 | |
|       Services.prefs.setBoolPref("browser.altClickSave", true);
 | |
|     },
 | |
|     clean() {
 | |
|       Services.prefs.clearUserPref("browser.altClickSave");
 | |
|     },
 | |
|     event: { shiftKey: true, altKey: true },
 | |
|     targets: ["mathlink", "svgxlink"],
 | |
|     expectedInvokedMethods: ["saveURL"],
 | |
|     preventDefault: true,
 | |
|   },
 | |
| 
 | |
|   {
 | |
|     desc: "Shift click",
 | |
|     setup() {},
 | |
|     clean() {},
 | |
|     event: { shiftKey: true },
 | |
|     targets: ["commonlink", "mathlink", "svgxlink", "maplink"],
 | |
|     expectedInvokedMethods: ["urlSecurityCheck", "openLinkIn"],
 | |
|     preventDefault: true,
 | |
|   },
 | |
| 
 | |
|   {
 | |
|     desc: "Alt click",
 | |
|     setup() {
 | |
|       Services.prefs.setBoolPref("browser.altClickSave", true);
 | |
|     },
 | |
|     clean() {
 | |
|       Services.prefs.clearUserPref("browser.altClickSave");
 | |
|     },
 | |
|     event: { altKey: true },
 | |
|     targets: ["commonlink", "maplink"],
 | |
|     expectedInvokedMethods: ["gatherTextUnder", "saveURL"],
 | |
|     preventDefault: true,
 | |
|   },
 | |
| 
 | |
|   {
 | |
|     desc: "Alt click on XLinks",
 | |
|     setup() {
 | |
|       Services.prefs.setBoolPref("browser.altClickSave", true);
 | |
|     },
 | |
|     clean() {
 | |
|       Services.prefs.clearUserPref("browser.altClickSave");
 | |
|     },
 | |
|     event: { altKey: true },
 | |
|     targets: ["mathlink", "svgxlink"],
 | |
|     expectedInvokedMethods: ["saveURL"],
 | |
|     preventDefault: true,
 | |
|   },
 | |
| 
 | |
|   {
 | |
|     desc: "Panel click",
 | |
|     setup() {},
 | |
|     clean() {},
 | |
|     event: {},
 | |
|     targets: ["panellink"],
 | |
|     expectedInvokedMethods: ["urlSecurityCheck", "loadURI"],
 | |
|     preventDefault: true,
 | |
|   },
 | |
| 
 | |
|   {
 | |
|     desc: "Simple middle click opentab",
 | |
|     setup() {},
 | |
|     clean() {},
 | |
|     event: { button: 1 },
 | |
|     wantedEvent: "auxclick",
 | |
|     targets: ["commonlink", "mathlink", "svgxlink", "maplink"],
 | |
|     expectedInvokedMethods: ["urlSecurityCheck", "openLinkIn"],
 | |
|     preventDefault: true,
 | |
|   },
 | |
| 
 | |
|   {
 | |
|     desc: "Simple middle click openwin",
 | |
|     setup() {
 | |
|       Services.prefs.setBoolPref("browser.tabs.opentabfor.middleclick", false);
 | |
|     },
 | |
|     clean() {
 | |
|       Services.prefs.clearUserPref("browser.tabs.opentabfor.middleclick");
 | |
|     },
 | |
|     event: { button: 1 },
 | |
|     wantedEvent: "auxclick",
 | |
|     targets: ["commonlink", "mathlink", "svgxlink", "maplink"],
 | |
|     expectedInvokedMethods: ["urlSecurityCheck", "openLinkIn"],
 | |
|     preventDefault: true,
 | |
|   },
 | |
| 
 | |
|   {
 | |
|     desc: "Middle mouse paste",
 | |
|     setup() {
 | |
|       Services.prefs.setBoolPref("middlemouse.contentLoadURL", true);
 | |
|       Services.prefs.setBoolPref("general.autoScroll", false);
 | |
|     },
 | |
|     clean() {
 | |
|       Services.prefs.clearUserPref("middlemouse.contentLoadURL");
 | |
|       Services.prefs.clearUserPref("general.autoScroll");
 | |
|     },
 | |
|     event: { button: 1 },
 | |
|     wantedEvent: "auxclick",
 | |
|     targets: ["emptylink"],
 | |
|     expectedInvokedMethods: ["middleMousePaste"],
 | |
|     preventDefault: true,
 | |
|   },
 | |
| ];
 | |
| 
 | |
| // Array of method names that will be replaced in the new window.
 | |
| var gReplacedMethods = [
 | |
|   "middleMousePaste",
 | |
|   "urlSecurityCheck",
 | |
|   "loadURI",
 | |
|   "gatherTextUnder",
 | |
|   "saveURL",
 | |
|   "openLinkIn",
 | |
|   "getShortcutOrURIAndPostData",
 | |
| ];
 | |
| 
 | |
| // Returns the target object for the replaced method.
 | |
| function getStub(replacedMethod) {
 | |
|   let targetObj =
 | |
|     replacedMethod == "getShortcutOrURIAndPostData" ? UrlbarUtils : gTestWin;
 | |
|   return targetObj[replacedMethod];
 | |
| }
 | |
| 
 | |
| // Reference to the new window.
 | |
| var gTestWin = null;
 | |
| 
 | |
| // The test currently running.
 | |
| var gCurrentTest = null;
 | |
| 
 | |
| function test() {
 | |
|   waitForExplicitFinish();
 | |
| 
 | |
|   registerCleanupFunction(function () {
 | |
|     sinon.restore();
 | |
|   });
 | |
| 
 | |
|   gTestWin = openDialog(location, "", "chrome,all,dialog=no", "about:blank");
 | |
|   whenDelayedStartupFinished(gTestWin, function () {
 | |
|     info("Browser window opened");
 | |
|     waitForFocus(function () {
 | |
|       info("Browser window focused");
 | |
|       waitForFocus(
 | |
|         function () {
 | |
|           info("Setting up browser...");
 | |
|           setupTestBrowserWindow();
 | |
|           info("Running tests...");
 | |
|           executeSoon(runNextTest);
 | |
|         },
 | |
|         gTestWin.content,
 | |
|         true
 | |
|       );
 | |
|     }, gTestWin);
 | |
|   });
 | |
| }
 | |
| 
 | |
| // Click handler used to steal click events.
 | |
| var gClickHandler = {
 | |
|   handleEvent(event) {
 | |
|     if (event.type == "click" && event.button != 0) {
 | |
|       return;
 | |
|     }
 | |
|     let linkId = event.target.id || event.target.localName;
 | |
|     let wantedEvent = gCurrentTest.wantedEvent || "click";
 | |
|     is(
 | |
|       event.type,
 | |
|       wantedEvent,
 | |
|       `${gCurrentTest.desc}:Handler received a ${wantedEvent} event on ${linkId}`
 | |
|     );
 | |
| 
 | |
|     let isPanelClick = linkId == "panellink";
 | |
|     gTestWin.contentAreaClick(event, isPanelClick);
 | |
|     let prevent = event.defaultPrevented;
 | |
|     is(
 | |
|       prevent,
 | |
|       gCurrentTest.preventDefault,
 | |
|       gCurrentTest.desc +
 | |
|         ": event.defaultPrevented is correct (" +
 | |
|         prevent +
 | |
|         ")"
 | |
|     );
 | |
| 
 | |
|     // Check that all required methods have been called.
 | |
|     for (let expectedMethod of gCurrentTest.expectedInvokedMethods) {
 | |
|       ok(
 | |
|         getStub(expectedMethod).called,
 | |
|         `${gCurrentTest.desc}:${expectedMethod} should have been invoked`
 | |
|       );
 | |
|     }
 | |
| 
 | |
|     for (let method of gReplacedMethods) {
 | |
|       if (
 | |
|         getStub(method).called &&
 | |
|         !gCurrentTest.expectedInvokedMethods.includes(method)
 | |
|       ) {
 | |
|         ok(false, `Should have not called ${method}`);
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     event.preventDefault();
 | |
|     event.stopPropagation();
 | |
| 
 | |
|     executeSoon(runNextTest);
 | |
|   },
 | |
| };
 | |
| 
 | |
| function setupTestBrowserWindow() {
 | |
|   // Steal click events and don't propagate them.
 | |
|   gTestWin.addEventListener("click", gClickHandler, true);
 | |
|   gTestWin.addEventListener("auxclick", gClickHandler, true);
 | |
| 
 | |
|   // Replace methods.
 | |
|   gReplacedMethods.forEach(function (methodName) {
 | |
|     let targetObj =
 | |
|       methodName == "getShortcutOrURIAndPostData" ? UrlbarUtils : gTestWin;
 | |
|     sinon.stub(targetObj, methodName).returnsArg(0);
 | |
|   });
 | |
| 
 | |
|   // Inject links in content.
 | |
|   let doc = gTestWin.content.document;
 | |
|   let mainDiv = doc.createElement("div");
 | |
|   mainDiv.innerHTML =
 | |
|     '<p><a id="commonlink" href="http://mochi.test/moz/">Common link</a></p>' +
 | |
|     '<p><a id="panellink" href="http://mochi.test/moz/">Panel link</a></p>' +
 | |
|     '<p><a id="emptylink">Empty link</a></p>' +
 | |
|     '<p><math id="mathlink" xmlns="http://www.w3.org/1998/Math/MathML" href="http://mochi.test/moz/"><mtext>MathML XLink</mtext></math></p>' +
 | |
|     '<p><svg id="svgxlink" xmlns="http://www.w3.org/2000/svg" width="100px" height="50px" version="1.1"><a xlink:type="simple" xlink:href="http://mochi.test/moz/"><text transform="translate(10, 25)">SVG XLink</text></a></svg></p>' +
 | |
|     '<p><map name="map" id="map"><area href="http://mochi.test/moz/" shape="rect" coords="0,0,128,128" /></map><img id="maplink" usemap="#map" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAIAAABMXPacAAAABGdBTUEAALGPC%2FxhBQAAAOtJREFUeF7t0IEAAAAAgKD9qRcphAoDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGBgwIAAAT0N51AAAAAASUVORK5CYII%3D"/></p>';
 | |
|   doc.body.appendChild(mainDiv);
 | |
| }
 | |
| 
 | |
| function runNextTest() {
 | |
|   if (!gCurrentTest) {
 | |
|     gCurrentTest = gTests.shift();
 | |
|     gCurrentTest.setup();
 | |
|   }
 | |
| 
 | |
|   if (!gCurrentTest.targets.length) {
 | |
|     info(gCurrentTest.desc + ": cleaning up...");
 | |
|     gCurrentTest.clean();
 | |
| 
 | |
|     if (gTests.length) {
 | |
|       gCurrentTest = gTests.shift();
 | |
|       gCurrentTest.setup();
 | |
|     } else {
 | |
|       finishTest();
 | |
|       return;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   // Move to next target.
 | |
|   sinon.resetHistory();
 | |
|   let target = gCurrentTest.targets.shift();
 | |
| 
 | |
|   info(gCurrentTest.desc + ": testing " + target);
 | |
| 
 | |
|   // Fire (aux)click event.
 | |
|   let targetElt = gTestWin.content.document.getElementById(target);
 | |
|   ok(targetElt, gCurrentTest.desc + ": target is valid (" + targetElt.id + ")");
 | |
|   EventUtils.synthesizeMouseAtCenter(
 | |
|     targetElt,
 | |
|     gCurrentTest.event,
 | |
|     gTestWin.content
 | |
|   );
 | |
| }
 | |
| 
 | |
| function finishTest() {
 | |
|   info("Restoring browser...");
 | |
|   gTestWin.removeEventListener("click", gClickHandler, true);
 | |
|   gTestWin.removeEventListener("auxclick", gClickHandler, true);
 | |
|   gTestWin.close();
 | |
|   finish();
 | |
| }
 | 
