From 6fd5733c1fa23fee64b9edb8a519a5a1746fab84 Mon Sep 17 00:00:00 2001 From: Tim Nguyen Date: Thu, 7 Jan 2016 23:18:56 +0100 Subject: [PATCH 01/10] Bug 1235953 - Refactor responsive mode tests to use add_task to not use CPOWs and make sure they all wait for the off event. r=ochameau --HG-- extra : transplant_source : %E2%A7%C4%C5Z%1B%9B%ED%F6%AC%A7%AD%22%BE%60/%84%2C%1B%96 --- devtools/.eslintrc.mochitests | 5 + .../client/responsivedesign/test/.eslintrc | 6 +- .../test/browser_responsive_cmd.js | 52 +- .../test/browser_responsive_devicewidth.js | 102 ++-- .../test/browser_responsivecomputedview.js | 3 +- .../test/browser_responsiveruleview.js | 20 +- .../test/browser_responsiveui.js | 510 ++++++++---------- .../test/browser_responsiveui_touch.js | 21 +- .../browser_responsiveuiaddcustompreset.js | 254 ++++----- devtools/client/responsivedesign/test/head.js | 103 ++-- testing/mochitest/browser.eslintrc | 1 + 11 files changed, 503 insertions(+), 574 deletions(-) diff --git a/devtools/.eslintrc.mochitests b/devtools/.eslintrc.mochitests index 1b681da94dc4..bec9930503f4 100644 --- a/devtools/.eslintrc.mochitests +++ b/devtools/.eslintrc.mochitests @@ -5,6 +5,11 @@ ], // All globals made available in the test environment. "globals": { + "DevToolsUtils": true, "gDevTools": true, + "once": true, + "synthesizeKeyFromKeyTag": true, + "TargetFactory": true, + "waitForTick": true, } } diff --git a/devtools/client/responsivedesign/test/.eslintrc b/devtools/client/responsivedesign/test/.eslintrc index 044c3e4f49e8..35f62c76be80 100644 --- a/devtools/client/responsivedesign/test/.eslintrc +++ b/devtools/client/responsivedesign/test/.eslintrc @@ -1,4 +1,8 @@ { // Extend from the shared list of defined globals for mochitests. - "extends": "../../../.eslintrc.mochitests" + "extends": "../../../.eslintrc.mochitests", + "globals": { + "ResponsiveUI": true, + "helpers": true + } } diff --git a/devtools/client/responsivedesign/test/browser_responsive_cmd.js b/devtools/client/responsivedesign/test/browser_responsive_cmd.js index 738cd8fe4b8c..0a5c4ba4b09f 100644 --- a/devtools/client/responsivedesign/test/browser_responsive_cmd.js +++ b/devtools/client/responsivedesign/test/browser_responsive_cmd.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /////////////////// // // Whitelisting this test. @@ -14,15 +16,15 @@ function test() { .hasAttribute("responsivemode"); } - helpers.addTabWithToolbar("data:text/html;charset=utf-8,hi", function(options) { + helpers.addTabWithToolbar("data:text/html;charset=utf-8,hi", (options) => { return helpers.audit(options, [ { setup: "resize toggle", check: { - input: 'resize toggle', - hints: '', - markup: 'VVVVVVVVVVVVV', - status: 'VALID' + input: "resize toggle", + hints: "", + markup: "VVVVVVVVVVVVV", + status: "VALID" }, exec: { output: "" @@ -34,10 +36,10 @@ function test() { { setup: "resize toggle", check: { - input: 'resize toggle', - hints: '', - markup: 'VVVVVVVVVVVVV', - status: 'VALID' + input: "resize toggle", + hints: "", + markup: "VVVVVVVVVVVVV", + status: "VALID" }, exec: { output: "" @@ -49,10 +51,10 @@ function test() { { setup: "resize on", check: { - input: 'resize on', - hints: '', - markup: 'VVVVVVVVV', - status: 'VALID' + input: "resize on", + hints: "", + markup: "VVVVVVVVV", + status: "VALID" }, exec: { output: "" @@ -64,10 +66,10 @@ function test() { { setup: "resize off", check: { - input: 'resize off', - hints: '', - markup: 'VVVVVVVVVV', - status: 'VALID' + input: "resize off", + hints: "", + markup: "VVVVVVVVVV", + status: "VALID" }, exec: { output: "" @@ -79,10 +81,10 @@ function test() { { setup: "resize to 400 400", check: { - input: 'resize to 400 400', - hints: '', - markup: 'VVVVVVVVVVVVVVVVV', - status: 'VALID', + input: "resize to 400 400", + hints: "", + markup: "VVVVVVVVVVVVVVVVV", + status: "VALID", args: { width: { value: 400 }, height: { value: 400 }, @@ -98,10 +100,10 @@ function test() { { setup: "resize off", check: { - input: 'resize off', - hints: '', - markup: 'VVVVVVVVVV', - status: 'VALID' + input: "resize off", + hints: "", + markup: "VVVVVVVVVV", + status: "VALID" }, exec: { output: "" diff --git a/devtools/client/responsivedesign/test/browser_responsive_devicewidth.js b/devtools/client/responsivedesign/test/browser_responsive_devicewidth.js index e09301697e17..67b3e3bc815b 100644 --- a/devtools/client/responsivedesign/test/browser_responsive_devicewidth.js +++ b/devtools/client/responsivedesign/test/browser_responsive_devicewidth.js @@ -1,62 +1,68 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ -function test() { - let instance; - let mgr = ResponsiveUI.ResponsiveUIManager; +"use strict"; - waitForExplicitFinish(); +add_task(function*() { + let tab = yield addTab("about:logo"); + let {rdm} = yield openRDM(tab); + ok(rdm, "An instance of the RDM should be attached to the tab."); + rdm.setSize(110, 500); - gBrowser.selectedTab = gBrowser.addTab("about:logo"); - gBrowser.selectedBrowser.addEventListener("load", function onload() { - gBrowser.selectedBrowser.removeEventListener("load", onload, true); - startTest(); - }, true); + info("Checking initial width/height properties."); + yield doInitialChecks(); - function startTest() { - mgr.once("on", function() {executeSoon(onUIOpen)}); - document.getElementById("Tools:ResponsiveUI").doCommand(); - } - - function onUIOpen() { - instance = mgr.getResponsiveUIForTab(gBrowser.selectedTab); - instance.stack.setAttribute("notransition", "true"); - ok(instance, "instance of the module is attached to the tab."); - - instance.setSize(110, 500); - ok(content.innerWidth, 110, "initial width is valid"); - - let mql = content.matchMedia("(max-device-width:100px)") - - ok(!mql.matches, "media query doesn't match."); - - mql.addListener(onMediaChange); - instance.setSize(90, 500); - } - - function onMediaChange(mql) { - mql.removeListener(onMediaChange); - ok(mql.matches, "media query matches."); - ok(window.screen.width != content.screen.width, "screen.width is not the size of the screen."); - is(content.screen.width, 90, "screen.width is the width of the page."); - is(content.screen.height, 500, "screen.height is the height of the page."); + info("Changing the RDM size"); + rdm.setSize(90, 500); + info("Checking for screen props"); + yield checkScreenProps(); + info("Setting docShell.deviceSizeIsPageSize to false"); + yield ContentTask.spawn(gBrowser.selectedBrowser, {}, function*() { let docShell = content.QueryInterface(Ci.nsIInterfaceRequestor) .getInterface(Ci.nsIWebNavigation) .QueryInterface(Ci.nsIDocShell); - - mql.addListener(onMediaChange2); docShell.deviceSizeIsPageSize = false; - } + }); - function onMediaChange2(mql) { - mql.removeListener(onMediaChange); - ok(!mql.matches, "media query has been re-evaluated."); - ok(window.screen.width == content.screen.width, "screen.width is not the size of the screen."); - instance.stack.removeAttribute("notransition"); - document.getElementById("Tools:ResponsiveUI").doCommand(); - gBrowser.removeCurrentTab(); - finish(); - } + info("Checking for screen props once again."); + yield checkScreenProps2(); + + yield closeRDM(rdm); +}); + +function* doInitialChecks() { + let {innerWidth, matchesMedia} = yield grabContentInfo(); + is(innerWidth, 110, "initial width should be 110px"); + ok(!matchesMedia, "media query shouldn't match."); +} + +function* checkScreenProps() { + let {matchesMedia, screen} = yield grabContentInfo(); + ok(matchesMedia, "media query should match"); + isnot(window.screen.width, screen.width, + "screen.width should not be the size of the screen."); + is(screen.width, 90, "screen.width should be the page width"); + is(screen.height, 500, "screen.height should be the page height"); +} + +function* checkScreenProps2() { + let {matchesMedia, screen} = yield grabContentInfo(); + ok(!matchesMedia, "media query should be re-evaluated."); + is(window.screen.width, screen.width, + "screen.width should be the size of the screen."); +} + +function grabContentInfo() { + return ContentTask.spawn(gBrowser.selectedBrowser, {}, function*() { + return { + screen: { + width: content.screen.width, + height: content.screen.height + }, + innerWidth: content.innerWidth, + matchesMedia: content.matchMedia("(max-device-width:100px)").matches + }; + }); } diff --git a/devtools/client/responsivedesign/test/browser_responsivecomputedview.js b/devtools/client/responsivedesign/test/browser_responsivecomputedview.js index 4d5a4e4c9183..70fb04821498 100644 --- a/devtools/client/responsivedesign/test/browser_responsivecomputedview.js +++ b/devtools/client/responsivedesign/test/browser_responsivecomputedview.js @@ -35,7 +35,8 @@ add_task(function*() { info("Try growing the viewport and checking the applied styles"); yield testGrow(view, inspector, rdm); - gBrowser.removeCurrentTab(); + yield closeRDM(rdm); + yield closeToolbox(); }); function* testShrink(computedView, inspector, rdm) { diff --git a/devtools/client/responsivedesign/test/browser_responsiveruleview.js b/devtools/client/responsivedesign/test/browser_responsiveruleview.js index 85b831917429..d6640710ee8f 100644 --- a/devtools/client/responsivedesign/test/browser_responsiveruleview.js +++ b/devtools/client/responsivedesign/test/browser_responsiveruleview.js @@ -25,7 +25,7 @@ add_task(function*() { yield addTab(TEST_URI); info("Open the responsive design mode and set its size to 500x500 to start"); - let {rdm, manager} = yield openRDM(); + let {rdm} = yield openRDM(); rdm.setSize(500, 500); info("Open the inspector, rule-view and select the test node"); @@ -41,11 +41,12 @@ add_task(function*() { info("Check that ESC still opens the split console"); yield testEscapeOpensSplitConsole(inspector); + yield closeToolbox(); + info("Test the state of the RDM menu item"); - yield testMenuItem(manager); + yield testMenuItem(rdm); Services.prefs.clearUserPref("devtools.toolbox.splitconsoleEnabled"); - gBrowser.removeCurrentTab(); }); function* testShrink(ruleView, rdm) { @@ -79,19 +80,14 @@ function* testEscapeOpensSplitConsole(inspector) { ok(inspector._toolbox._splitConsole, "Console is split after pressing ESC."); } -function* testMenuItem(manager) { +function* testMenuItem(rdm) { is(document.getElementById("Tools:ResponsiveUI").getAttribute("checked"), - "true", - "The menu item is checked"); + "true", "The menu item is checked"); - info("Toggle off the RDM"); - let onManagerOff = manager.once("off"); - manager.toggle(window, gBrowser.selectedTab); - yield onManagerOff; + yield closeRDM(rdm); is(document.getElementById("Tools:ResponsiveUI").getAttribute("checked"), - "false", - "The menu item is unchecked"); + "false", "The menu item is unchecked"); } function numberOfRules(ruleView) { diff --git a/devtools/client/responsivedesign/test/browser_responsiveui.js b/devtools/client/responsivedesign/test/browser_responsiveui.js index 68e203420f58..2394df39dd70 100644 --- a/devtools/client/responsivedesign/test/browser_responsiveui.js +++ b/devtools/client/responsivedesign/test/browser_responsiveui.js @@ -1,309 +1,255 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ -thisTestLeaksUncaughtRejectionsAndShouldBeFixed("Protocol error (unknownError): Error: Got an invalid root window in DocumentWalker"); +"use strict"; -function test() { - waitForExplicitFinish(); +add_task(function*() { SimpleTest.requestCompleteLog(); - Task.spawn(function*() { + let tab = yield addTab("data:text/html,mop"); - function extractSizeFromString(str) { - let numbers = str.match(/(\d+)[^\d]*(\d+)/); - if (numbers) { - return [numbers[1], numbers[2]]; - } else { - return [null, null]; - } - } + let {rdm, manager} = yield openRDM(tab, "menu"); + let container = gBrowser.getBrowserContainer(); + is(container.getAttribute("responsivemode"), "true", + "Should be in responsive mode."); + is(document.getElementById("Tools:ResponsiveUI").getAttribute("checked"), + "true", "Menu item should be checked"); - function processStringAsKey(str) { - for (let i = 0, l = str.length; i < l; i++) { - EventUtils.synthesizeKey(str.charAt(i), {}); - } - } + ok(rdm, "An instance of the RDM should be attached to the tab."); - yield addTab("data:text/html,mop"); + let originalWidth = (yield getSizing()).width; - let mgr = ResponsiveUI.ResponsiveUIManager; + let documentLoaded = waitForDocLoadComplete(); + gBrowser.loadURI("data:text/html;charset=utf-8,mop" + + "
<%2Fdiv>"); + yield documentLoaded; - synthesizeKeyFromKeyTag(document.getElementById("key_responsiveUI")); + let newWidth = (yield getSizing()).width; + is(originalWidth, newWidth, "Floating scrollbars shouldn't change the width"); - yield once(mgr, "on"); + yield rdm._test_notifyOnResize(); + yield waitForTick(); - // Is it open? - let container = gBrowser.getBrowserContainer(); - is(container.getAttribute("responsivemode"), "true", "In responsive mode."); + yield testPresets(rdm, manager); - // Menus are correctly updated? - is(document.getElementById("Tools:ResponsiveUI").getAttribute("checked"), "true", "menus checked"); + info("Testing mouse resizing"); + yield testManualMouseResize(rdm, manager); - let instance = mgr.getResponsiveUIForTab(gBrowser.selectedTab); - ok(instance, "instance of the module is attached to the tab."); + info("Testing mouse resizing with shift key"); + yield testManualMouseResize(rdm, manager, "shift"); - let originalWidth = content.innerWidth; + info("Testing mouse resizing with ctrl key"); + yield testManualMouseResize(rdm, manager, "ctrl"); - let documentLoaded = waitForDocLoadComplete(); - content.location = "data:text/html;charset=utf-8,mop
<%2Fdiv>"; - yield documentLoaded; + info("Testing resizing with user custom keyboard input"); + yield testResizeUsingCustomInput(rdm, manager); - let newWidth = content.innerWidth; - is(originalWidth, newWidth, "Floating scrollbars are presents"); + info("Testing invalid keyboard input"); + yield testInvalidUserInput(rdm); - yield instance._test_notifyOnResize(); + info("Testing rotation"); + yield testRotate(rdm, manager); - yield nextTick(); + let {width: widthBeforeClose, height: heightBeforeClose} = yield getSizing(); - instance.transitionsEnabled = false; + info("Restarting responsive mode"); + yield closeRDM(rdm); + ({rdm} = yield openRDM(tab, "keyboard")); - // Starting from length - 4 because last 3 items are not presets : separator, addbutton and removebutton - for (let c = instance.menulist.firstChild.childNodes.length - 4; c >= 0; c--) { - let item = instance.menulist.firstChild.childNodes[c]; - let [width, height] = extractSizeFromString(item.getAttribute("label")); - let onContentResize = once(mgr, "contentResize"); - instance.menulist.selectedIndex = c; - yield onContentResize; - is(content.innerWidth, width, "preset " + c + ": dimension valid (width)"); - is(content.innerHeight, height, "preset " + c + ": dimension valid (height)"); - } + let currentSize = yield getSizing(); + is(currentSize.width, widthBeforeClose, "width should be restored"); + is(currentSize.height, heightBeforeClose, "height should be restored"); - // test custom + container = gBrowser.getBrowserContainer(); + is(container.getAttribute("responsivemode"), "true", "In responsive mode."); + is(document.getElementById("Tools:ResponsiveUI").getAttribute("checked"), + "true", "menu item should be checked"); - instance.setSize(100, 100); + let isWinXP = navigator.userAgent.indexOf("Windows NT 5.1") != -1; + if (!isWinXP) { + yield testScreenshot(rdm); + } - yield once(mgr, "contentResize"); + yield closeRDM(rdm); + is(document.getElementById("Tools:ResponsiveUI").getAttribute("checked"), + "false", "menu item should be unchecked"); +}); - let initialWidth = content.innerWidth; - let initialHeight = content.innerHeight; +function* testPresets(rdm, manager) { + // Starting from length - 4 because last 3 items are not presets : + // the separator, the add button and the remove button + for (let c = rdm.menulist.firstChild.childNodes.length - 4; c >= 0; c--) { + let item = rdm.menulist.firstChild.childNodes[c]; + let [width, height] = extractSizeFromString(item.getAttribute("label")); + let onContentResize = once(manager, "contentResize"); + rdm.menulist.selectedIndex = c; + yield onContentResize; - is(initialWidth, 100, "Width reset to 100"); - is(initialHeight, 100, "Height reset to 100"); - - let x = 2, y = 2; - EventUtils.synthesizeMouse(instance.resizer, x, y, {type: "mousedown"}, window); - x += 20; y += 10; - EventUtils.synthesizeMouse(instance.resizer, x, y, {type: "mousemove"}, window); - EventUtils.synthesizeMouse(instance.resizer, x, y, {type: "mouseup"}, window); - - yield once(mgr, "contentResize"); - - let expectedWidth = initialWidth + 20; - let expectedHeight = initialHeight + 10; - info("initial width: " + initialWidth); - info("initial height: " + initialHeight); - is(content.innerWidth, expectedWidth, "Size correctly updated (width)."); - is(content.innerHeight, expectedHeight, "Size correctly updated (height)."); - - is(instance.menulist.selectedIndex, -1, "Custom menuitem cannot be selected"); - let label = instance.menulist.firstChild.firstChild.getAttribute("label"); - let value = instance.menulist.value; - isnot(label, value, "Label from the menulist item is different than the value of the menulist") - let [width, height] = extractSizeFromString(label); - is(width, expectedWidth, "Label updated (width)."); - is(height, expectedHeight, "Label updated (height)."); - [width, height] = extractSizeFromString(value); - is(width, expectedWidth, "Value updated (width)."); - is(height, expectedHeight, "Value updated (height)."); - - // With "shift" key pressed - - instance.setSize(100, 100); - - yield once(mgr, "contentResize"); - - initialWidth = content.innerWidth; - initialHeight = content.innerHeight; - - x = 2; y = 2; - EventUtils.synthesizeMouse(instance.resizer, x, y, {type: "mousedown"}, window); - x += 23; y += 13; - EventUtils.synthesizeMouse(instance.resizer, x, y, {type: "mousemove", shiftKey: true}, window); - EventUtils.synthesizeMouse(instance.resizer, x, y, {type: "mouseup"}, window); - - yield once(mgr, "contentResize"); - - expectedWidth = initialWidth + 20; - expectedHeight = initialHeight + 10; - is(content.innerWidth, expectedWidth, "with shift: Size correctly updated (width)."); - is(content.innerHeight, expectedHeight, "with shift: Size correctly updated (height)."); - is(instance.menulist.selectedIndex, -1, "with shift: Custom menuitem cannot be selected"); - label = instance.menulist.firstChild.firstChild.getAttribute("label"); - value = instance.menulist.value; - isnot(label, value, "Label from the menulist item is different than the value of the menulist"); - [width, height] = extractSizeFromString(label); - is(width, expectedWidth, "Label updated (width)."); - is(height, expectedHeight, "Label updated (height)."); - [width, height] = extractSizeFromString(value); - is(width, expectedWidth, "Value updated (width)."); - is(height, expectedHeight, "Value updated (height)."); - - - // With "ctrl" key pressed - - instance.setSize(100, 100); - - yield once(mgr, "contentResize"); - - initialWidth = content.innerWidth; - initialHeight = content.innerHeight; - - x = 2; y = 2; - EventUtils.synthesizeMouse(instance.resizer, x, y, {type: "mousedown"}, window); - x += 60; y += 30; - EventUtils.synthesizeMouse(instance.resizer, x, y, {type: "mousemove", ctrlKey: true}, window); - EventUtils.synthesizeMouse(instance.resizer, x, y, {type: "mouseup"}, window); - - yield once(mgr, "contentResize"); - - expectedWidth = initialWidth + 10; - expectedHeight = initialHeight + 5; - is(content.innerWidth, expectedWidth, "with ctrl: Size correctly updated (width)."); - is(content.innerHeight, expectedHeight, "with ctrl: Size correctly updated (height)."); - is(instance.menulist.selectedIndex, -1, "with ctrl: Custom menuitem cannot be selected"); - label = instance.menulist.firstChild.firstChild.getAttribute("label"); - value = instance.menulist.value; - isnot(label, value, "Label from the menulist item is different than the value of the menulist"); - [width, height] = extractSizeFromString(label); - is(width, expectedWidth, "Label updated (width)."); - is(height, expectedHeight, "Label updated (height)."); - [width, height] = extractSizeFromString(value); - is(width, expectedWidth, "Value updated (width)."); - is(height, expectedHeight, "Value updated (height)."); - - - // Test custom input - - initialWidth = content.innerWidth; - initialHeight = content.innerHeight; - expectedWidth = initialWidth - 20; - expectedHeight = initialHeight - 10; - let index = instance.menulist.selectedIndex; - - let userInput = expectedWidth + " x " + expectedHeight; - - instance.menulist.inputField.value = ""; - instance.menulist.focus(); - processStringAsKey(userInput); - - // While typing, the size should not change - is(content.innerWidth, initialWidth, "Size hasn't changed (width)."); - is(content.innerHeight, initialHeight, "Size hasn't changed (height)."); - - // Only the `change` event must change the size - EventUtils.synthesizeKey("VK_RETURN", {}); - - yield once(mgr, "contentResize"); - - is(content.innerWidth, expectedWidth, "Size correctly updated (width)."); - is(content.innerHeight, expectedHeight, "Size correctly updated (height)."); - is(instance.menulist.selectedIndex, -1, "Custom menuitem cannot be selected"); - label = instance.menulist.firstChild.firstChild.getAttribute("label"); - value = instance.menulist.value; - isnot(label, value, "Label from the menulist item is different than the value of the menulist"); - [width, height] = extractSizeFromString(label); - is(width, expectedWidth, "Label updated (width)."); - is(height, expectedHeight, "Label updated (height)."); - [width, height] = extractSizeFromString(value); - is(width, expectedWidth, "Value updated (width)."); - is(height, expectedHeight, "Value updated (height)."); - - - // Invalid input - - - initialWidth = content.innerWidth; - initialHeight = content.innerHeight; - index = instance.menulist.selectedIndex; - let expectedValue = initialWidth + "\u00D7" + initialHeight; - let expectedLabel = instance.menulist.firstChild.firstChild.getAttribute("label"); - - userInput = "I'm wrong"; - - instance.menulist.inputField.value = ""; - instance.menulist.focus(); - processStringAsKey(userInput); - EventUtils.synthesizeKey("VK_RETURN", {}); - - is(content.innerWidth, initialWidth, "Size hasn't changed (width)."); - is(content.innerHeight, initialHeight, "Size hasn't changed (height)."); - is(instance.menulist.selectedIndex, index, "Selected item hasn't changed."); - is(instance.menulist.value, expectedValue, "Value has been reset") - label = instance.menulist.firstChild.firstChild.getAttribute("label"); - is(label, expectedLabel, "Custom menuitem's label hasn't changed"); - - - // Rotate - - initialWidth = content.innerWidth; - initialHeight = content.innerHeight; - - info("rotate"); - instance.rotate(); - - yield once(mgr, "contentResize"); - - is(content.innerWidth, initialHeight, "The width is now the height."); - is(content.innerHeight, initialWidth, "The height is now the width."); - [width, height] = extractSizeFromString(instance.menulist.firstChild.firstChild.getAttribute("label")); - is(width, initialHeight, "Label updated (width)."); - is(height, initialWidth, "Label updated (height)."); - - let widthBeforeClose = content.innerWidth; - let heightBeforeClose = content.innerHeight; - - // Restart - - mgr.toggle(window, gBrowser.selectedTab); - - yield once(mgr, "off"); - - mgr.toggle(window, gBrowser.selectedTab); - - yield once(mgr, "on"); - - container = gBrowser.getBrowserContainer(); - is(container.getAttribute("responsivemode"), "true", "In responsive mode."); - - // Menus are correctly updated? - - is(document.getElementById("Tools:ResponsiveUI").getAttribute("checked"), "true", "menus checked"); - - is(content.innerWidth, widthBeforeClose, "width restored."); - is(content.innerHeight, heightBeforeClose, "height restored."); - - // Screenshot - - - let isWinXP = navigator.userAgent.indexOf("Windows NT 5.1") != -1; - if (!isWinXP) { - info("screenshot"); - instance.screenshot("responsiveui"); - let FileUtils = (Cu.import("resource://gre/modules/FileUtils.jsm", {})).FileUtils; - - while(true) { - // while(true) until we find the file. - // no need for a timeout, the test will get killed anyway. - let file = FileUtils.getFile("DfltDwnld", [ "responsiveui.png" ]); - if (file.exists()) { - ok(true, "Screenshot file exists"); - file.remove(false); - break; - } - info("checking if file exists in 200ms"); - yield wait(200); - } - } - - mgr.toggle(window, gBrowser.selectedTab); - - yield once(mgr, "off"); - - // Menus are correctly updated? - is(document.getElementById("Tools:ResponsiveUI").getAttribute("checked"), "false", "menu unchecked"); - - delete instance; - gBrowser.removeCurrentTab(); - finish(); - - }); + let {width: contentWidth, height: contentHeight} = yield getSizing(); + is(contentWidth, width, "preset" + c + ": the width should be changed"); + is(contentHeight, height, "preset" + c + ": the height should be changed"); + } +} + +function* testManualMouseResize(rdm, manager, pressedKey) { + rdm.setSize(100, 100); + yield once(manager, "contentResize"); + + let {width: initialWidth, height: initialHeight} = yield getSizing(); + is(initialWidth, 100, "Width should be reset to 100"); + is(initialHeight, 100, "Height should be reset to 100"); + + let x = 2, y = 2; + EventUtils.synthesizeMouse(rdm.resizer, x, y, {type: "mousedown"}, window); + + let mouseMoveParams = {type: "mousemove"}; + if (pressedKey == "shift") { + x += 23; y += 10; + mouseMoveParams.shiftKey = true; + } else if (pressedKey == "ctrl") { + x += 120; y += 60; + mouseMoveParams.ctrlKey = true; + } else { + x += 20; y += 10; + } + + EventUtils.synthesizeMouse(rdm.resizer, x, y, mouseMoveParams, window); + EventUtils.synthesizeMouse(rdm.resizer, x, y, {type: "mouseup"}, window); + + yield once(manager, "contentResize"); + + let expectedWidth = initialWidth + 20; + let expectedHeight = initialHeight + 10; + info("initial width: " + initialWidth); + info("initial height: " + initialHeight); + + yield verifyResize(rdm, expectedWidth, expectedHeight); +} + +function* testResizeUsingCustomInput(rdm, manager) { + let {width: initialWidth, height: initialHeight} = yield getSizing(); + let expectedWidth = initialWidth - 20, expectedHeight = initialHeight - 10; + + let userInput = expectedWidth + " x " + expectedHeight; + rdm.menulist.inputField.value = ""; + rdm.menulist.focus(); + processStringAsKey(userInput); + + // While typing, the size should not change + let currentSize = yield getSizing(); + is(currentSize.width, initialWidth, "Typing shouldn't change the width"); + is(currentSize.height, initialHeight, "Typing shouldn't change the height"); + + // Only the `change` event must change the size + EventUtils.synthesizeKey("VK_RETURN", {}); + + yield once(manager, "contentResize"); + + yield verifyResize(rdm, expectedWidth, expectedHeight); +} + +function* testInvalidUserInput(rdm) { + let {width: initialWidth, height: initialHeight} = yield getSizing(); + let index = rdm.menulist.selectedIndex; + let expectedValue = initialWidth + "\u00D7" + initialHeight; + let expectedLabel = rdm.menulist.firstChild.firstChild.getAttribute("label"); + + let userInput = "I'm wrong"; + + rdm.menulist.inputField.value = ""; + rdm.menulist.focus(); + processStringAsKey(userInput); + EventUtils.synthesizeKey("VK_RETURN", {}); + + let currentSize = yield getSizing(); + is(currentSize.width, initialWidth, "Width should not change"); + is(currentSize.height, initialHeight, "Height should not change"); + is(rdm.menulist.selectedIndex, index, "Selected item should not change."); + is(rdm.menulist.value, expectedValue, "Value should be reset"); + + let label = rdm.menulist.firstChild.firstChild.getAttribute("label"); + is(label, expectedLabel, "Custom menuitem's label should not change"); +} + +function* testRotate(rdm, manager) { + rdm.setSize(100, 200); + yield once(manager, "contentResize"); + + let {width: initialWidth, height: initialHeight} = yield getSizing(); + rdm.rotate(); + + yield once(manager, "contentResize"); + + let newSize = yield getSizing(); + is(newSize.width, initialHeight, "The width should now be the height."); + is(newSize.height, initialWidth, "The height should now be the width."); + + let label = rdm.menulist.firstChild.firstChild.getAttribute("label"); + let [width, height] = extractSizeFromString(label); + is(width, initialHeight, "Width in label should be updated"); + is(height, initialWidth, "Height in label should be updated"); +} + +function* verifyResize(rdm, expectedWidth, expectedHeight) { + let currentSize = yield getSizing(); + is(currentSize.width, expectedWidth, "Width should now change"); + is(currentSize.height, expectedHeight, "Height should now change"); + + is(rdm.menulist.selectedIndex, -1, "Custom menuitem cannot be selected"); + + let label = rdm.menulist.firstChild.firstChild.getAttribute("label"); + let value = rdm.menulist.value; + isnot(label, value, + "The menulist item label should be different than the menulist value"); + + let [width, height] = extractSizeFromString(label); + is(width, expectedWidth, "Width in label should be updated"); + is(height, expectedHeight, "Height in label should be updated"); + + [width, height] = extractSizeFromString(value); + is(width, expectedWidth, "Value should be updated with new width"); + is(height, expectedHeight, "Value should be updated with new height"); +} + +function* testScreenshot(rdm) { + info("Testing screenshot"); + rdm.screenshot("responsiveui"); + let {FileUtils} = Cu.import("resource://gre/modules/FileUtils.jsm", {}); + + while (true) { + // while(true) until we find the file. + // no need for a timeout, the test will get killed anyway. + let file = FileUtils.getFile("DfltDwnld", [ "responsiveui.png" ]); + if (file.exists()) { + ok(true, "Screenshot file exists"); + file.remove(false); + break; + } + info("checking if file exists in 200ms"); + yield wait(200); + } +} + +function* getSizing() { + let browser = gBrowser.selectedBrowser; + let sizing = yield ContentTask.spawn(browser, {}, function*() { + return { + width: content.innerWidth, + height: content.innerHeight + }; + }); + return sizing; +} + +function extractSizeFromString(str) { + let numbers = str.match(/(\d+)[^\d]*(\d+)/); + if (numbers) { + return [numbers[1], numbers[2]]; + } + return [null, null]; +} + +function processStringAsKey(str) { + for (let i = 0, l = str.length; i < l; i++) { + EventUtils.synthesizeKey(str.charAt(i), {}); + } } diff --git a/devtools/client/responsivedesign/test/browser_responsiveui_touch.js b/devtools/client/responsivedesign/test/browser_responsiveui_touch.js index d859700c8a9c..8315efb98363 100644 --- a/devtools/client/responsivedesign/test/browser_responsiveui_touch.js +++ b/devtools/client/responsivedesign/test/browser_responsiveui_touch.js @@ -7,19 +7,14 @@ const TEST_URI = "http://mochi.test:8888/browser/devtools/client/" + "responsivedesign/test/touch.html"; add_task(function*() { - yield addTab(TEST_URI); - let mgr = ResponsiveUI.ResponsiveUIManager; - let mgrOn = once(mgr, "on"); - mgr.toggle(window, gBrowser.selectedTab); - yield mgrOn; + let tab = yield addTab(TEST_URI); + let {rdm} = yield openRDM(tab); yield testWithNoTouch(); - yield mgr.getResponsiveUIForTab(gBrowser.selectedTab).enableTouch(); + yield rdm.enableTouch(); yield testWithTouch(); - yield mgr.getResponsiveUIForTab(gBrowser.selectedTab).disableTouch(); + yield rdm.disableTouch(); yield testWithNoTouch(); - let mgrOff = once(mgr, "off"); - mgr.toggle(window, gBrowser.selectedTab); - yield mgrOff; + yield closeRDM(rdm); }); function* testWithNoTouch() { @@ -30,7 +25,7 @@ function* testWithNoTouch() { x += 20; y += 10; yield BrowserTestUtils.synthesizeMouse("div", x, y, { type: "mousemove", isSynthesized: false }, gBrowser.selectedBrowser); - is(div.style.transform, "none", "touch didn't work"); + is(div.style.transform, "none", "touch shouldn't work"); yield BrowserTestUtils.synthesizeMouse("div", x, y, { type: "mouseup", isSynthesized: false }, gBrowser.selectedBrowser); } @@ -43,8 +38,8 @@ function* testWithTouch() { x += 20; y += 10; yield BrowserTestUtils.synthesizeMouse("div", x, y, { type: "mousemove", isSynthesized: false }, gBrowser.selectedBrowser); - is(div.style.transform, "translate(20px, 10px)", "touch worked"); + is(div.style.transform, "translate(20px, 10px)", "touch should work"); yield BrowserTestUtils.synthesizeMouse("div", x, y, { type: "mouseup", isSynthesized: false }, gBrowser.selectedBrowser); - is(div.style.transform, "none", "end event worked"); + is(div.style.transform, "none", "end event should work"); } diff --git a/devtools/client/responsivedesign/test/browser_responsiveuiaddcustompreset.js b/devtools/client/responsivedesign/test/browser_responsiveuiaddcustompreset.js index 34ba9f616927..01d402cc6eba 100644 --- a/devtools/client/responsivedesign/test/browser_responsiveuiaddcustompreset.js +++ b/devtools/client/responsivedesign/test/browser_responsiveuiaddcustompreset.js @@ -1,145 +1,129 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ -function test() { - waitForExplicitFinish(); - SimpleTest.requestCompleteLog(); +"use strict"; - let instance, deletedPresetA, deletedPresetB, oldPrompt; +add_task(function*() { + let tab = yield addTab("data:text/html;charset=utf8,Test RDM custom presets"); - function getPresetIndex(presetLabel) { - function testOnePreset(c) { - if (c == 0) { - return -1; - } - instance.menulist.selectedIndex = c; + let {rdm} = yield openRDM(tab); - let item = instance.menulist.firstChild.childNodes[c]; - if (item.getAttribute("label") === presetLabel) { - return c; - } else { - return testOnePreset(c - 1); - } + let oldPrompt = Services.prompt; + Services.prompt = { + value: "", + returnBool: true, + prompt: function(parent, dialogTitle, text, value, checkMsg, checkState) { + value.value = this.value; + return this.returnBool; } - return testOnePreset(instance.menulist.firstChild.childNodes.length - 4); - } + }; - Task.spawn(function*() { - - yield addTab("data:text/html;charset=utf8,test custom presets in responsive mode"); - - let mgr = ResponsiveUI.ResponsiveUIManager; - - synthesizeKeyFromKeyTag(document.getElementById("key_responsiveUI")); - - yield once(mgr, "on"); - - oldPrompt = Services.prompt; - Services.prompt = { - value: "", - returnBool: true, - prompt: function(aParent, aDialogTitle, aText, aValue, aCheckMsg, aCheckState) { - aValue.value = this.value; - return this.returnBool; - } - }; - - registerCleanupFunction(() => Services.prompt = oldPrompt); - - // Is it open? - let container = gBrowser.getBrowserContainer(); - is(container.getAttribute("responsivemode"), "true", "In responsive mode."); - - instance = mgr.getResponsiveUIForTab(gBrowser.selectedTab); - ok(instance, "instance of the module is attached to the tab."); - - instance.transitionsEnabled = false; - - yield instance._test_notifyOnResize(); - - // Tries to add a custom preset and cancel the prompt - let idx = instance.menulist.selectedIndex; - let presetCount = instance.presets.length; - - Services.prompt.value = ""; - Services.prompt.returnBool = false; - instance.addbutton.doCommand(); - - is(idx, instance.menulist.selectedIndex, "selected item didn't change after add preset and cancel"); - is(presetCount, instance.presets.length, "number of presets didn't change after add preset and cancel"); - - // Adds the custom preset with "Testing preset" - Services.prompt.value = "Testing preset"; - Services.prompt.returnBool = true; - - let customHeight = 123, customWidth = 456; - instance.startResizing({}); - instance.setSize(customWidth, customHeight); - instance.stopResizing({}); - - instance.addbutton.doCommand(); - - // Force document reflow to avoid intermittent failures. - info("document height " + document.height); - - instance.close(); - - info("waiting for responsive mode to turn off"); - yield once(mgr, "off"); - - // We're still in the loop of initializing the responsive mode. - // Let's wait next loop to stop it. - yield nextTick(); - - synthesizeKeyFromKeyTag(document.getElementById("key_responsiveUI")); - - yield once(mgr, "on"); - - is(container.getAttribute("responsivemode"), "true", "In responsive mode."); - - instance = mgr.getResponsiveUIForTab(gBrowser.selectedTab); - - let customPresetIndex = getPresetIndex("456" + "\u00D7" + "123 (Testing preset)"); - info(customPresetIndex); - ok(customPresetIndex >= 0, "is the previously added preset (idx = " + customPresetIndex + ") in the list of items"); - - let resizePromise = instance._test_notifyOnResize(); - instance.menulist.selectedIndex = customPresetIndex; - yield resizePromise; - - is(content.innerWidth, 456, "add preset, and selected in the list, dimension valid (width)"); - is(content.innerHeight, 123, "add preset, and selected in the list, dimension valid (height)"); - - instance.removebutton.doCommand(); - - instance.menulist.selectedIndex = 2; - deletedPresetA = instance.menulist.selectedItem.getAttribute("label"); - instance.removebutton.doCommand(); - - instance.menulist.selectedIndex = 2; - deletedPresetB = instance.menulist.selectedItem.getAttribute("label"); - instance.removebutton.doCommand(); - - yield nextTick(); - instance.close(); - yield once(mgr, "off"); - - synthesizeKeyFromKeyTag(document.getElementById("key_responsiveUI")); - - info("waiting for responsive mode to turn on"); - yield once(mgr, "on"); - - instance = mgr.getResponsiveUIForTab(gBrowser.selectedTab); - - customPresetIndex = getPresetIndex(deletedPresetA); - is(customPresetIndex, -1, "deleted preset " + deletedPresetA + " is not in the list anymore"); - - customPresetIndex = getPresetIndex(deletedPresetB); - is(customPresetIndex, -1, "deleted preset " + deletedPresetB + " is not in the list anymore"); - - yield nextTick(); - - gBrowser.removeCurrentTab(); - finish(); + registerCleanupFunction(() => { + Services.prompt = oldPrompt; }); + + // Is it open? + let container = gBrowser.getBrowserContainer(); + is(container.getAttribute("responsivemode"), "true", + "Should be in responsive mode."); + + ok(rdm, "RDM instance should be attached to the tab."); + + yield rdm._test_notifyOnResize(); + + // Tries to add a custom preset and cancel the prompt + let idx = rdm.menulist.selectedIndex; + let presetCount = rdm.presets.length; + + Services.prompt.value = ""; + Services.prompt.returnBool = false; + rdm.addbutton.doCommand(); + + is(idx, rdm.menulist.selectedIndex, + "selected item shouldn't change after add preset and cancel"); + is(presetCount, rdm.presets.length, + "number of presets shouldn't change after add preset and cancel"); + + // Adds the custom preset with "Testing preset" + Services.prompt.value = "Testing preset"; + Services.prompt.returnBool = true; + + let customHeight = 123, customWidth = 456; + rdm.startResizing({}); + rdm.setSize(customWidth, customHeight); + rdm.stopResizing({}); + + rdm.addbutton.doCommand(); + + // Force document reflow to avoid intermittent failures. + info("document height " + document.height); + + yield closeRDM(rdm); + + // We're still in the loop of initializing the responsive mode. + // Let's wait next loop to stop it. + yield waitForTick(); + + ({rdm} = yield openRDM(tab)); + is(container.getAttribute("responsivemode"), "true", + "Should be in responsive mode."); + + let presetLabel = "456" + "\u00D7" + "123 (Testing preset)"; + let customPresetIndex = getPresetIndex(rdm, presetLabel); + info(customPresetIndex); + ok(customPresetIndex >= 0, "(idx = " + customPresetIndex + ") should be the" + + " previously added preset in the list of items"); + + let resizePromise = rdm._test_notifyOnResize(); + rdm.menulist.selectedIndex = customPresetIndex; + yield resizePromise; + + let browser = gBrowser.selectedBrowser; + let props = yield ContentTask.spawn(browser, {}, function*() { + let {innerWidth, innerHeight} = content; + return {innerWidth, innerHeight}; + }); + + is(props.innerWidth, 456, "Selecting preset should change the width"); + is(props.innerHeight, 123, "Selecting preset should change the height"); + + rdm.removebutton.doCommand(); + + rdm.menulist.selectedIndex = 2; + let deletedPresetA = rdm.menulist.selectedItem.getAttribute("label"); + rdm.removebutton.doCommand(); + + rdm.menulist.selectedIndex = 2; + let deletedPresetB = rdm.menulist.selectedItem.getAttribute("label"); + rdm.removebutton.doCommand(); + + yield closeRDM(rdm); + yield waitForTick(); + ({rdm} = yield openRDM(tab)); + + customPresetIndex = getPresetIndex(rdm, deletedPresetA); + is(customPresetIndex, -1, + "Deleted preset " + deletedPresetA + " should not be in the list anymore"); + + customPresetIndex = getPresetIndex(rdm, deletedPresetB); + is(customPresetIndex, -1, + "Deleted preset " + deletedPresetB + " should not be in the list anymore"); + + yield closeRDM(rdm); +}); + +function getPresetIndex(rdm, presetLabel) { + function testOnePreset(c) { + if (c == 0) { + return -1; + } + rdm.menulist.selectedIndex = c; + + let item = rdm.menulist.firstChild.childNodes[c]; + if (item.getAttribute("label") === presetLabel) { + return c; + } + return testOnePreset(c - 1); + } + return testOnePreset(rdm.menulist.firstChild.childNodes.length - 4); } diff --git a/devtools/client/responsivedesign/test/head.js b/devtools/client/responsivedesign/test/head.js index a8c21fbbd2a3..1fe076e120af 100644 --- a/devtools/client/responsivedesign/test/head.js +++ b/devtools/client/responsivedesign/test/head.js @@ -3,12 +3,14 @@ "use strict"; +let testDir = gTestPath.substr(0, gTestPath.lastIndexOf("/")); // shared-head.js handles imports, constants, and utility functions -Services.scriptloader.loadSubScript("chrome://mochitests/content/browser/devtools/client/framework/test/shared-head.js", this); +let sharedHeadURI = testDir + "../../../framework/test/shared-head.js"; +Services.scriptloader.loadSubScript(sharedHeadURI, this); // Import the GCLI test helper -var testDir = gTestPath.substr(0, gTestPath.lastIndexOf("/")); -Services.scriptloader.loadSubScript(testDir + "../../../commandline/test/helpers.js", this); +let gcliHelpersURI = testDir + "../../../commandline/test/helpers.js"; +Services.scriptloader.loadSubScript(gcliHelpersURI, this); DevToolsUtils.testing = true; registerCleanupFunction(() => { @@ -21,22 +23,41 @@ registerCleanupFunction(() => { /** * Open the Responsive Design Mode * @param {Tab} The browser tab to open it into (defaults to the selected tab). - * @return {Promise} Resolves to the instance of the responsive design mode. + * @param {method} The method to use to open the RDM (values: menu, keyboard) + * @return {rdm, manager} Returns the RUI instance and the manager */ -function openRDM(tab = gBrowser.selectedTab) { - return new Promise(resolve => { - let manager = ResponsiveUI.ResponsiveUIManager; +var openRDM = Task.async(function*(tab = gBrowser.selectedTab, + method = "menu") { + let manager = ResponsiveUI.ResponsiveUIManager; + let mgrOn = once(manager, "on"); + if (method == "menu") { document.getElementById("Tools:ResponsiveUI").doCommand(); - executeSoon(() => { - let rdm = manager.getResponsiveUIForTab(tab); - rdm.stack.setAttribute("notransition", "true"); - registerCleanupFunction(function() { - rdm.stack.removeAttribute("notransition"); - }); - resolve({rdm, manager}); - }); + } else { + synthesizeKeyFromKeyTag(document.getElementById("key_responsiveUI")); + } + yield mgrOn; + + let rdm = manager.getResponsiveUIForTab(tab); + rdm.transitionsEnabled = false; + registerCleanupFunction(() => { + rdm.transitionsEnabled = true; }); -} + return {rdm, manager}; +}); + +/** + * Close a responsive mode instance + * @param {rdm} ResponsiveUI instance for the tab + */ +var closeRDM = Task.async(function*(rdm) { + let mgr = ResponsiveUI.ResponsiveUIManager; + if (!rdm) { + rdm = mgr.getResponsiveUIForTab(gBrowser.selectedTab); + } + let mgrOff = mgr.once("off"); + rdm.close(); + yield mgrOff; +}); /** * Open the toolbox, with the inspector tool visible. @@ -77,6 +98,11 @@ var openInspector = Task.async(function*() { }; }); +var closeToolbox = Task.async(function*() { + let target = TargetFactory.forTab(gBrowser.selectedTab); + yield gDevTools.closeToolbox(target); +}); + /** * Wait for the toolbox frame to receive focus after it loads * @param {Toolbox} toolbox @@ -164,67 +190,30 @@ var addTab = Task.async(function* (url) { return tab; }); -/** - * Wait for eventName on target. - * @param {Object} target An observable object that either supports on/off or - * addEventListener/removeEventListener - * @param {String} eventName - * @param {Boolean} useCapture Optional, for addEventListener/removeEventListener - * @return A promise that resolves when the event has been handled - */ -function once(target, eventName, useCapture=false) { - info("Waiting for event: '" + eventName + "' on " + target + "."); - - let deferred = promise.defer(); - - for (let [add, remove] of [ - ["addEventListener", "removeEventListener"], - ["addListener", "removeListener"], - ["on", "off"] - ]) { - if ((add in target) && (remove in target)) { - target[add](eventName, function onEvent(...aArgs) { - info("Got event: '" + eventName + "' on " + target + "."); - target[remove](eventName, onEvent, useCapture); - deferred.resolve.apply(deferred, aArgs); - }, useCapture); - break; - } - } - - return deferred.promise; -} - function wait(ms) { let def = promise.defer(); setTimeout(def.resolve, ms); return def.promise; } -function nextTick() { - let def = promise.defer(); - executeSoon(() => def.resolve()) - return def.promise; -} - /** * Waits for the next load to complete in the current browser. * * @return promise */ -function waitForDocLoadComplete(aBrowser=gBrowser) { +function waitForDocLoadComplete(aBrowser = gBrowser) { let deferred = promise.defer(); let progressListener = { - onStateChange: function (webProgress, req, flags, status) { + onStateChange: function(webProgress, req, flags, status) { let docStop = Ci.nsIWebProgressListener.STATE_IS_NETWORK | Ci.nsIWebProgressListener.STATE_STOP; - info("Saw state " + flags.toString(16) + " and status " + status.toString(16)); + info(`Saw state ${flags.toString(16)} and status ${status.toString(16)}`); // When a load needs to be retargetted to a new process it is cancelled // with NS_BINDING_ABORTED so ignore that case if ((flags & docStop) == docStop && status != Cr.NS_BINDING_ABORTED) { aBrowser.removeProgressListener(progressListener); - info("Browser loaded " + aBrowser.contentWindow.location); + info("Browser loaded"); deferred.resolve(); } }, diff --git a/testing/mochitest/browser.eslintrc b/testing/mochitest/browser.eslintrc index ee4efb7c55a8..4a8009bc49ee 100644 --- a/testing/mochitest/browser.eslintrc +++ b/testing/mochitest/browser.eslintrc @@ -31,6 +31,7 @@ "requestLongerTimeout": false, "SimpleTest": false, "SpecialPowers": false, + "thisTestLeaksUncaughtRejectionsAndShouldBeFixed": false, "todo": false, "todo_is": false, "todo_isnot": false, From ff3269f2d2906e25a5bdbc4b2d218134ac8a437e Mon Sep 17 00:00:00 2001 From: AJ Kerrigan Date: Thu, 7 Jan 2016 03:26:31 -0500 Subject: [PATCH 02/10] Bug 1132556 - Replace runInContent() with ContentTask.spawn(). r=smacleod --- browser/components/sessionstore/test/browser_447951.js | 6 +++--- browser/components/sessionstore/test/browser_500328.js | 10 +++++----- browser/components/sessionstore/test/content.js | 6 ------ browser/components/sessionstore/test/head.js | 10 ---------- 4 files changed, 8 insertions(+), 24 deletions(-) diff --git a/browser/components/sessionstore/test/browser_447951.js b/browser/components/sessionstore/test/browser_447951.js index 9ede1218c53b..a7b6a5ee8448 100644 --- a/browser/components/sessionstore/test/browser_447951.js +++ b/browser/components/sessionstore/test/browser_447951.js @@ -32,9 +32,9 @@ function test() { is(tabState.entries[0].url, baseURL + 0, "... but not more"); // visit yet another anchor (appending it to session history) - runInContent(tab.linkedBrowser, function(win) { - win.document.querySelector("a").click(); - }, null).then(flushAndCheck); + ContentTask.spawn(tab.linkedBrowser, null, function() { + content.window.document.querySelector("a").click(); + }).then(flushAndCheck); function flushAndCheck() { TabStateFlusher.flush(tab.linkedBrowser).then(check); diff --git a/browser/components/sessionstore/test/browser_500328.js b/browser/components/sessionstore/test/browser_500328.js index 646e4b80045e..e5cbd6b8fe15 100644 --- a/browser/components/sessionstore/test/browser_500328.js +++ b/browser/components/sessionstore/test/browser_500328.js @@ -42,9 +42,9 @@ function checkState(tab) { // deserialized in the content scope. And in this case, since RegExps are // not currently Xrayable (see bug 1014991), trying to pull |obj3| (a RegExp) // off of an Xrayed Object won't work. So we need to waive. - runInContent(tab.linkedBrowser, function(win, state) { + ContentTask.spawn(tab.linkedBrowser, aEvent.state, function(state) { return Cu.waiveXrays(state).obj3.toString(); - }, aEvent.state).then(function(stateStr) { + }).then(function(stateStr) { is(stateStr, '/^a$/', "second popstate object."); // Make sure that the new-elem node is present in the document. If it's @@ -92,13 +92,13 @@ function test() { // testURL (state object: null) <-- oldest // testURL (state object: {obj1:1}) // testURL?page2 (state object: {obj3:/^a$/}) <-- newest - function contentTest(win) { - let history = win.history; + function contentTest() { + let history = content.window.history; history.pushState({obj1:1}, "title-obj1"); history.pushState({obj2:2}, "title-obj2", "?page2"); history.replaceState({obj3:/^a$/}, "title-obj3"); } - runInContent(browser, contentTest, null).then(function() { + ContentTask.spawn(browser, null, contentTest).then(function() { return TabStateFlusher.flush(tab.linkedBrowser); }).then(() => { let state = ss.getTabState(tab); diff --git a/browser/components/sessionstore/test/content.js b/browser/components/sessionstore/test/content.js index d1a48f7a6497..e815a6783f8b 100644 --- a/browser/components/sessionstore/test/content.js +++ b/browser/components/sessionstore/test/content.js @@ -216,12 +216,6 @@ addMessageListener("ss-test:click", function ({data}) { sendAsyncMessage("ss-test:click"); }); -addMessageListener("ss-test:run", function({data, objects}) { - let f = eval('(' + data.code + ')'); - let result = f(content, objects.arg); - sendAsyncMessage("ss-test:runFinished", result); -}); - addEventListener("load", function(event) { let subframe = event.target != content.document; sendAsyncMessage("ss-test:loadEvent", {subframe: subframe, url: event.target.documentURI}); diff --git a/browser/components/sessionstore/test/head.js b/browser/components/sessionstore/test/head.js index 541032492c8b..9a2cc301ea07 100644 --- a/browser/components/sessionstore/test/head.js +++ b/browser/components/sessionstore/test/head.js @@ -449,16 +449,6 @@ function promiseNewWindowLoaded(aOptions) { return new Promise(resolve => whenNewWindowLoaded(aOptions, resolve)); } -function runInContent(browser, func, arg, callback = null) { - let deferred = Promise.defer(); - - let mm = browser.messageManager; - mm.sendAsyncMessage("ss-test:run", {code: func.toSource()}, {arg: arg}); - mm.addMessageListener("ss-test:runFinished", ({data}) => deferred.resolve(data)); - - return deferred.promise; -} - /** * This waits for the browser-delayed-startup-finished notification of a given * window. It indicates that the windows has loaded completely and is ready to From 64a1cfc0a0adfada31bd81d8de713dee884236d7 Mon Sep 17 00:00:00 2001 From: Anup Kumar Date: Thu, 7 Jan 2016 20:44:00 -0500 Subject: [PATCH 03/10] Bug 1234734 - Replace CommonUtils.stackTrace() with Log.stackTrace(). r=markh --HG-- rename : services/common/tests/unit/test_utils_stackTrace.js => toolkit/modules/tests/xpcshell/test_Log_stackTrace.js --- .../tests/unit/test_utils_stackTrace.js | 33 ------------------- services/common/tests/unit/xpcshell.ini | 1 - services/common/utils.js | 3 -- services/sync/modules/util.js | 1 - .../sync/tps/extensions/tps/resource/tps.jsm | 2 +- .../tests/xpcshell/test_Log_stackTrace.js | 30 +++++++++++++++++ toolkit/modules/tests/xpcshell/xpcshell.ini | 1 + 7 files changed, 32 insertions(+), 39 deletions(-) delete mode 100644 services/common/tests/unit/test_utils_stackTrace.js create mode 100644 toolkit/modules/tests/xpcshell/test_Log_stackTrace.js diff --git a/services/common/tests/unit/test_utils_stackTrace.js b/services/common/tests/unit/test_utils_stackTrace.js deleted file mode 100644 index 6c71d07535d2..000000000000 --- a/services/common/tests/unit/test_utils_stackTrace.js +++ /dev/null @@ -1,33 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -_("Define some functions in well defined line positions for the test"); -function foo(v) { return bar(v + 1); } // line 2 -function bar(v) { return baz(v + 1); } // line 3 -function baz(v) { throw new Error(v + 1); } // line 4 - -_("Make sure lazy constructor calling/assignment works"); -Cu.import("resource://services-common/utils.js"); - -function run_test() { - _("Make sure functions, arguments, files are pretty printed in the trace"); - let trace = ""; - try { - foo(0); - } - catch(ex) { - trace = CommonUtils.stackTrace(ex); - } - _("Got trace:", trace); - do_check_neq(trace, ""); - - let bazPos = trace.indexOf("baz@test_utils_stackTrace.js:7"); - let barPos = trace.indexOf("bar@test_utils_stackTrace.js:6"); - let fooPos = trace.indexOf("foo@test_utils_stackTrace.js:5"); - _("String positions:", bazPos, barPos, fooPos); - - _("Make sure the desired messages show up"); - do_check_true(bazPos >= 0); - do_check_true(barPos > bazPos); - do_check_true(fooPos > barPos); -} diff --git a/services/common/tests/unit/xpcshell.ini b/services/common/tests/unit/xpcshell.ini index c817e7dd6637..2cdbe79be36c 100644 --- a/services/common/tests/unit/xpcshell.ini +++ b/services/common/tests/unit/xpcshell.ini @@ -23,7 +23,6 @@ support-files = [test_utils_makeURI.js] [test_utils_namedTimer.js] [test_utils_sets.js] -[test_utils_stackTrace.js] [test_utils_utf8.js] [test_utils_uuid.js] diff --git a/services/common/utils.js b/services/common/utils.js index 68418c5f8c4e..f0f57d14afb6 100644 --- a/services/common/utils.js +++ b/services/common/utils.js @@ -69,9 +69,6 @@ this.CommonUtils = { return true; }, - // Import these from Log.jsm for backward compatibility - stackTrace: Log.stackTrace, - /** * Encode byte string as base64URL (RFC 4648). * diff --git a/services/sync/modules/util.js b/services/sync/modules/util.js index 5c16e45efa8b..f2604bab62fc 100644 --- a/services/sync/modules/util.js +++ b/services/sync/modules/util.js @@ -35,7 +35,6 @@ this.Utils = { // In the ideal world, references to these would be removed. nextTick: CommonUtils.nextTick, namedTimer: CommonUtils.namedTimer, - stackTrace: CommonUtils.stackTrace, makeURI: CommonUtils.makeURI, encodeUTF8: CommonUtils.encodeUTF8, decodeUTF8: CommonUtils.decodeUTF8, diff --git a/services/sync/tps/extensions/tps/resource/tps.jsm b/services/sync/tps/extensions/tps/resource/tps.jsm index 4644c51ccbe1..02b304b675b4 100644 --- a/services/sync/tps/extensions/tps/resource/tps.jsm +++ b/services/sync/tps/extensions/tps/resource/tps.jsm @@ -142,7 +142,7 @@ var TPS = { errInfo = Log.exceptionStr(exc); // includes details and stack-trace. } else { // always write a stack even if no error passed. - errInfo = Utils.stackTrace(new Error()); + errInfo = Log.stackTrace(new Error()); } Logger.logError(`[phase ${this._currentPhase}] ${msg} - ${errInfo}`); this.quit(); diff --git a/toolkit/modules/tests/xpcshell/test_Log_stackTrace.js b/toolkit/modules/tests/xpcshell/test_Log_stackTrace.js new file mode 100644 index 000000000000..f6aac6decd23 --- /dev/null +++ b/toolkit/modules/tests/xpcshell/test_Log_stackTrace.js @@ -0,0 +1,30 @@ +print("Define some functions in well defined line positions for the test"); +function foo(v) { return bar(v + 1); } // line 2 +function bar(v) { return baz(v + 1); } // line 3 +function baz(v) { throw new Error(v + 1); } // line 4 + +print("Make sure lazy constructor calling/assignment works"); +Components.utils.import("resource://gre/modules/Log.jsm"); + +function run_test() { + print("Make sure functions, arguments, files are pretty printed in the trace"); + let trace = ""; + try { + foo(0); + } + catch(ex) { + trace = Log.stackTrace(ex); + } + print(`Got trace: ${trace}`); + do_check_neq(trace, ""); + + let bazPos = trace.indexOf("baz@test_Log_stackTrace.js:4"); + let barPos = trace.indexOf("bar@test_Log_stackTrace.js:3"); + let fooPos = trace.indexOf("foo@test_Log_stackTrace.js:2"); + print(`String positions: ${bazPos} ${barPos} ${fooPos}`); + + print("Make sure the desired messages show up"); + do_check_true(bazPos >= 0); + do_check_true(barPos > bazPos); + do_check_true(fooPos > barPos); +} diff --git a/toolkit/modules/tests/xpcshell/xpcshell.ini b/toolkit/modules/tests/xpcshell/xpcshell.ini index f4bf5d872ce3..66832dbbbeb5 100644 --- a/toolkit/modules/tests/xpcshell/xpcshell.ini +++ b/toolkit/modules/tests/xpcshell/xpcshell.ini @@ -61,3 +61,4 @@ skip-if = toolkit == 'android' [test_web_channel_broker.js] [test_ZipUtils.js] skip-if = toolkit == 'android' +[test_Log_stackTrace.js] From 7ce1de0dec23a45d77b8c742c497ce0a2e363aca Mon Sep 17 00:00:00 2001 From: Luca Greco Date: Fri, 8 Jan 2016 05:38:00 -0500 Subject: [PATCH 04/10] Bug 1237357 - Fix missing Cr used by AddonLocalizationConverter in simpleServices. r=kmag --- .../extensions/test/xpcshell/test_locale_converter.js | 10 ++++++++-- toolkit/components/utils/simpleServices.js | 1 + 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/toolkit/components/extensions/test/xpcshell/test_locale_converter.js b/toolkit/components/extensions/test/xpcshell/test_locale_converter.js index 71643551cac0..8715fa150254 100644 --- a/toolkit/components/extensions/test/xpcshell/test_locale_converter.js +++ b/toolkit/components/extensions/test/xpcshell/test_locale_converter.js @@ -107,13 +107,19 @@ add_task(function* testInvalidUUID() { let uri = NetUtil.newURI("moz-extension://eb4f3be8-41c9-4970-aa6d-b84d1ecc02b2/file.css"); let stream = StringStream("Foo __MSG_xxx__ bar __MSG_yyy__ baz"); + // Assert.throws raise a TypeError exception when the expected param + // is an arrow function. (See Bug 1237961 for rationale) + let expectInvalidContextException = function(e) { + return e.result === Cr.NS_ERROR_INVALID_ARG && /Invalid context/.test(e); + }; + Assert.throws(() => { convService.convert(stream, FROM_TYPE, TO_TYPE, uri); - }); + }, expectInvalidContextException); Assert.throws(() => { let listener = { QueryInterface: XPCOMUtils.generateQI([Ci.nsIStreamListener]) }; convService.asyncConvertData(FROM_TYPE, TO_TYPE, listener, uri); - }); + }, expectInvalidContextException); }); diff --git a/toolkit/components/utils/simpleServices.js b/toolkit/components/utils/simpleServices.js index 9343cd70fc30..4ad42d7050a9 100644 --- a/toolkit/components/utils/simpleServices.js +++ b/toolkit/components/utils/simpleServices.js @@ -15,6 +15,7 @@ const Cc = Components.classes; const Cu = Components.utils; const Ci = Components.interfaces; +const Cr = Components.results; Cu.import("resource://gre/modules/XPCOMUtils.jsm"); From 88f250d269582ea5848507772d877494684fecf5 Mon Sep 17 00:00:00 2001 From: Razvan Balosin Date: Fri, 11 Dec 2015 10:02:00 -0500 Subject: [PATCH 05/10] Bug 1228829 - Make infobar more visible on dark backgrounds. r=pbro, r=ntim --- devtools/server/actors/highlighters.css | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/devtools/server/actors/highlighters.css b/devtools/server/actors/highlighters.css index 1c82c28e3637..30bed95de0cd 100644 --- a/devtools/server/actors/highlighters.css +++ b/devtools/server/actors/highlighters.css @@ -97,6 +97,8 @@ color: hsl(216,33%,97%); text-shadow: none; + + border: 1px solid rgba(255,255,255,0.2); } :-moz-native-anonymous .box-model-nodeinfobar-container[hide-arrow] > .box-model-nodeinfobar { @@ -106,26 +108,35 @@ /* Arrows */ :-moz-native-anonymous .box-model-nodeinfobar-container > .box-model-nodeinfobar:before { + left: calc(50% - 8px); + border: 8px solid rgba(255,255,255,0.2); +} + +:-moz-native-anonymous .box-model-nodeinfobar-container > .box-model-nodeinfobar:after { + left: calc(50% - 7px); + border: 7px solid hsl(214,13%,24%); +} + +:-moz-native-anonymous .box-model-nodeinfobar-container > .box-model-nodeinfobar:before, +:-moz-native-anonymous .box-model-nodeinfobar-container > .box-model-nodeinfobar:after { content: ""; display: none; - position: absolute; - left: calc(50% - 8px); - height: 0; width: 0; - border: 8px solid hsl(214,13%,24%); border-left-color: transparent; border-right-color: transparent; } -:-moz-native-anonymous .box-model-nodeinfobar-container[position="top"]:not([hide-arrow]) > .box-model-nodeinfobar:before { +:-moz-native-anonymous .box-model-nodeinfobar-container[position="top"]:not([hide-arrow]) > .box-model-nodeinfobar:before, +:-moz-native-anonymous .box-model-nodeinfobar-container[position="top"]:not([hide-arrow]) > .box-model-nodeinfobar:after { border-bottom: 0; top: 100%; display: block; } -:-moz-native-anonymous .box-model-nodeinfobar-container[position="bottom"]:not([hide-arrow]) > .box-model-nodeinfobar:before { +:-moz-native-anonymous .box-model-nodeinfobar-container[position="bottom"]:not([hide-arrow]) > .box-model-nodeinfobar:before, +:-moz-native-anonymous .box-model-nodeinfobar-container[position="bottom"]:not([hide-arrow]) > .box-model-nodeinfobar:after { border-top: 0; bottom: 100%; display: block; From f48cabf9a7a32580029b77eb191a6c87ccdcb7b6 Mon Sep 17 00:00:00 2001 From: Lin Clark Date: Mon, 4 Jan 2016 08:34:00 -0500 Subject: [PATCH 06/10] Bug 1235375 - Change FrameActor to protocol.js. r=ejpbruel --- devtools/server/actors/frame.js | 101 +++++++++++++++++++++++++++++++ devtools/server/actors/moz.build | 1 + devtools/server/actors/script.js | 87 +------------------------- 3 files changed, 103 insertions(+), 86 deletions(-) create mode 100644 devtools/server/actors/frame.js diff --git a/devtools/server/actors/frame.js b/devtools/server/actors/frame.js new file mode 100644 index 000000000000..544f310b2b83 --- /dev/null +++ b/devtools/server/actors/frame.js @@ -0,0 +1,101 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2; js-indent-level: 2 -*- */ +/* vim: set ft=javascript ts=2 et sw=2 tw=80: */ +/* 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/. */ + +"use strict"; + +const { ActorPool } = require("devtools/server/actors/common"); +const { createValueGrip } = require("devtools/server/actors/object"); +const { ActorClass } = require("devtools/server/protocol"); + +/** + * An actor for a specified stack frame. + */ +let FrameActor = ActorClass({ + typeName: "frame", + + /** + * Creates the Frame actor. + * + * @param frame Debugger.Frame + * The debuggee frame. + * @param threadActor ThreadActor + * The parent thread actor for this frame. + */ + initialize: function(frame, threadActor) { + this.frame = frame; + this.threadActor = threadActor; + }, + + /** + * A pool that contains frame-lifetime objects, like the environment. + */ + _frameLifetimePool: null, + get frameLifetimePool() { + if (!this._frameLifetimePool) { + this._frameLifetimePool = new ActorPool(this.conn); + this.conn.addActorPool(this._frameLifetimePool); + } + return this._frameLifetimePool; + }, + + /** + * Finalization handler that is called when the actor is being evicted from + * the pool. + */ + disconnect: function() { + this.conn.removeActorPool(this._frameLifetimePool); + this._frameLifetimePool = null; + }, + + /** + * Returns a frame form for use in a protocol message. + */ + form: function() { + let threadActor = this.threadActor; + let form = { actor: this.actorID, + type: this.frame.type }; + if (this.frame.type === "call") { + form.callee = createValueGrip(this.frame.callee, threadActor._pausePool, + threadActor.objectGrip); + } + + if (this.frame.environment) { + let envActor = threadActor.createEnvironmentActor( + this.frame.environment, + this.frameLifetimePool + ); + form.environment = envActor.form(); + } + form.this = createValueGrip(this.frame.this, threadActor._pausePool, + threadActor.objectGrip); + form.arguments = this._args(); + if (this.frame.script) { + var generatedLocation = this.threadActor.sources.getFrameLocation(this.frame); + form.where = { + source: generatedLocation.generatedSourceActor.form(), + line: generatedLocation.generatedLine, + column: generatedLocation.generatedColumn + }; + } + + if (!this.frame.older) { + form.oldest = true; + } + + return form; + }, + + _args: function() { + if (!this.frame.arguments) { + return []; + } + + return this.frame.arguments.map(arg => createValueGrip(arg, + this.threadActor._pausePool, this.threadActor.objectGrip)); + } +}); + +exports.FrameActor = FrameActor; diff --git a/devtools/server/actors/moz.build b/devtools/server/actors/moz.build index 5044e1610f6a..f544b7bb0f47 100644 --- a/devtools/server/actors/moz.build +++ b/devtools/server/actors/moz.build @@ -24,6 +24,7 @@ DevToolsModules( 'director-manager.js', 'director-registry.js', 'eventlooplag.js', + 'frame.js', 'framerate.js', 'gcli.js', 'heap-snapshot-file.js', diff --git a/devtools/server/actors/script.js b/devtools/server/actors/script.js index fd3fcd3f68b9..9fa242e1b72d 100644 --- a/devtools/server/actors/script.js +++ b/devtools/server/actors/script.js @@ -9,6 +9,7 @@ const Services = require("Services"); const { Cc, Ci, Cu, components, ChromeWorker } = require("chrome"); const { ActorPool, OriginalLocation, GeneratedLocation } = require("devtools/server/actors/common"); +const { FrameActor } = require("devtools/server/actors/frame"); const { ObjectActor, createValueGrip, longStringGrip } = require("devtools/server/actors/object"); const { DebuggerServer } = require("devtools/server/main"); const DevToolsUtils = require("devtools/shared/DevToolsUtils"); @@ -2972,92 +2973,6 @@ update(PauseScopedObjectActor.prototype.requestTypes, { "threadGrip": PauseScopedObjectActor.prototype.onThreadGrip, }); -/** - * Creates an actor for the specified stack frame. - * - * @param aFrame Debugger.Frame - * The debuggee frame. - * @param aThreadActor ThreadActor - * The parent thread actor for this frame. - */ -function FrameActor(aFrame, aThreadActor) -{ - this.frame = aFrame; - this.threadActor = aThreadActor; -} - -FrameActor.prototype = { - actorPrefix: "frame", - - /** - * A pool that contains frame-lifetime objects, like the environment. - */ - _frameLifetimePool: null, - get frameLifetimePool() { - if (!this._frameLifetimePool) { - this._frameLifetimePool = new ActorPool(this.conn); - this.conn.addActorPool(this._frameLifetimePool); - } - return this._frameLifetimePool; - }, - - /** - * Finalization handler that is called when the actor is being evicted from - * the pool. - */ - disconnect: function () { - this.conn.removeActorPool(this._frameLifetimePool); - this._frameLifetimePool = null; - }, - - /** - * Returns a frame form for use in a protocol message. - */ - form: function () { - let threadActor = this.threadActor; - let form = { actor: this.actorID, - type: this.frame.type }; - if (this.frame.type === "call") { - form.callee = createValueGrip(this.frame.callee, threadActor._pausePool, - threadActor.objectGrip); - } - - if (this.frame.environment) { - let envActor = threadActor.createEnvironmentActor( - this.frame.environment, - this.frameLifetimePool - ); - form.environment = envActor.form(); - } - form.this = createValueGrip(this.frame.this, threadActor._pausePool, - threadActor.objectGrip); - form.arguments = this._args(); - if (this.frame.script) { - var generatedLocation = this.threadActor.sources.getFrameLocation(this.frame); - form.where = { - source: generatedLocation.generatedSourceActor.form(), - line: generatedLocation.generatedLine, - column: generatedLocation.generatedColumn - }; - } - - if (!this.frame.older) { - form.oldest = true; - } - - return form; - }, - - _args: function () { - if (!this.frame.arguments) { - return []; - } - - return this.frame.arguments.map(arg => createValueGrip(arg, - this.threadActor._pausePool, this.threadActor.objectGrip)); - }, -}; - /** * Creates a BreakpointActor. BreakpointActors exist for the lifetime of their * containing thread and are responsible for deleting breakpoints, handling From 3aa86fa346a022e56e08ac530d731f85a00d8cd0 Mon Sep 17 00:00:00 2001 From: Jan Odvarko Date: Wed, 6 Jan 2016 08:47:56 +0100 Subject: [PATCH 07/10] Bug 1232615 - Properly parse server logs without a label. r=jryans --- devtools/client/webconsole/test/browser.ini | 1 + .../test/browser_console_server_logging.js | 33 ++++++++++++++++++- .../test-console-server-logging-array.sjs | 32 ++++++++++++++++++ .../test/test-console-server-logging.sjs | 2 +- devtools/shared/webconsole/server-logger.js | 10 +++++- 5 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 devtools/client/webconsole/test/test-console-server-logging-array.sjs diff --git a/devtools/client/webconsole/test/browser.ini b/devtools/client/webconsole/test/browser.ini index 12c42c6283bb..88c9125322bf 100644 --- a/devtools/client/webconsole/test/browser.ini +++ b/devtools/client/webconsole/test/browser.ini @@ -74,6 +74,7 @@ support-files = test-console-extras.html test-console-replaced-api.html test-console-server-logging.sjs + test-console-server-logging-array.sjs test-console.html test-console-workers.html test-console-table.html diff --git a/devtools/client/webconsole/test/browser_console_server_logging.js b/devtools/client/webconsole/test/browser_console_server_logging.js index 8be38928c737..60d02f4acff2 100644 --- a/devtools/client/webconsole/test/browser_console_server_logging.js +++ b/devtools/client/webconsole/test/browser_console_server_logging.js @@ -37,10 +37,41 @@ add_task(function* () { yield updateServerLoggingListener(hud); }); +add_task(function* () { + const TEST_URI = "http://example.com/browser/devtools/client/webconsole/test/test-console-server-logging-array.sjs"; + + yield loadTab(TEST_URI); + + let hud = yield openConsole(); + + // Set logging filter and wait till it's set on the backend + hud.setFilterState("serverlog", true); + yield updateServerLoggingListener(hud); + + BrowserReloadSkipCache(); + + // Note that the test is also checking out the (printf like) + // formatters and encoding of UTF8 characters (see the one at the end). + let text = "Object { best: \"Firefox\", reckless: \"Chrome\", new_ie: \"Safari\", new_new_ie: \"Edge\" }"; + + yield waitForMessages({ + webconsole: hud, + messages: [{ + text: text, + category: CATEGORY_SERVER, + severity: SEVERITY_LOG, + }], + }) + + // Clean up filter + hud.setFilterState("serverlog", false); + yield updateServerLoggingListener(hud); +}); + function updateServerLoggingListener(hud) { let deferred = promise.defer(); hud.ui._updateServerLoggingListener(response => { deferred.resolve(response); }); return deferred.promise; -} \ No newline at end of file +} diff --git a/devtools/client/webconsole/test/test-console-server-logging-array.sjs b/devtools/client/webconsole/test/test-console-server-logging-array.sjs new file mode 100644 index 000000000000..bba39426420f --- /dev/null +++ b/devtools/client/webconsole/test/test-console-server-logging-array.sjs @@ -0,0 +1,32 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +function handleRequest(request, response) +{ + var page = "" + + "" + + "

hello world!

" + + ""; + + var data = { + "version": "4.1.0", + "columns": ["log", "backtrace", "type"], + "rows":[[ + [{ "best": "Firefox", "reckless": "Chrome", "new_ie": "Safari", "new_new_ie": "Edge"}], + "C:\\src\\www\\serverlogging\\test7.php:4:1", + "" + ]], + }; + + // Put log into headers. + var value = b64EncodeUnicode(JSON.stringify(data)); + response.setHeader("X-ChromeLogger-Data", value, false); + + response.write(page); +} + +function b64EncodeUnicode(str) { + return btoa(unescape(encodeURIComponent(str))); +} diff --git a/devtools/client/webconsole/test/test-console-server-logging.sjs b/devtools/client/webconsole/test/test-console-server-logging.sjs index 167a6e39a311..7177e71852a1 100644 --- a/devtools/client/webconsole/test/test-console-server-logging.sjs +++ b/devtools/client/webconsole/test/test-console-server-logging.sjs @@ -29,4 +29,4 @@ function handleRequest(request, response) function b64EncodeUnicode(str) { return btoa(unescape(encodeURIComponent(str))); -} \ No newline at end of file +} diff --git a/devtools/shared/webconsole/server-logger.js b/devtools/shared/webconsole/server-logger.js index 4f7a8940c6f8..b24be573b6ac 100644 --- a/devtools/shared/webconsole/server-logger.js +++ b/devtools/shared/webconsole/server-logger.js @@ -408,7 +408,15 @@ function format(msg) { msg.styles = []; // Remove and get the first log (in which the specifiers are). - let firstString = msg.logs.shift(); + // Note that the first string doesn't have to be specified. + // An example of a log on the server side: + // ChromePhp::log("server info: ", $_SERVER); + // ChromePhp::log($_SERVER); + let firstString = ""; + if (typeof msg.logs[0] == "string") { + firstString = msg.logs.shift(); + } + // All the specifiers present in the first string. let splitLogRegExp = /(.*?)(%[oOcsdif]|$)/g; let splitLogRegExpRes; From 6fcca8b4409d375b08f81245cb5d2c0efe623391 Mon Sep 17 00:00:00 2001 From: Georg Fritzsche Date: Fri, 8 Jan 2016 19:12:01 +0200 Subject: [PATCH 08/10] Bug 1238046 - Update Telemetry docs for environment.profile being available on Android. r=Dexter --- toolkit/components/telemetry/docs/environment.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/toolkit/components/telemetry/docs/environment.rst b/toolkit/components/telemetry/docs/environment.rst index 5472a56ede53..d09d42875700 100644 --- a/toolkit/components/telemetry/docs/environment.rst +++ b/toolkit/components/telemetry/docs/environment.rst @@ -59,7 +59,7 @@ Structure:: // only the fact that the value has been changed is recorded }, }, - profile: { // This section is not available on Android. + profile: { creationDate: , // integer days since UNIX epoch, e.g. 16446 resetDate: , // integer days since UNIX epoch, e.g. 16446 - optional }, From e1be1b03aca43cefe8c3b861659cd57398e0df95 Mon Sep 17 00:00:00 2001 From: Tracy Walker Date: Thu, 7 Jan 2016 13:41:52 -0600 Subject: [PATCH 09/10] Bug 1237713 - Fix and re-enable test browser_tabkeynavigation on e10s. r=jimm --- browser/base/content/test/general/browser.ini | 1 - .../test/general/browser_tabkeynavigation.js | 80 +++++++------------ 2 files changed, 29 insertions(+), 52 deletions(-) diff --git a/browser/base/content/test/general/browser.ini b/browser/base/content/test/general/browser.ini index 3723d391d203..52d25d1f5a6a 100644 --- a/browser/base/content/test/general/browser.ini +++ b/browser/base/content/test/general/browser.ini @@ -419,7 +419,6 @@ skip-if = os == "linux" || os == "mac" # No tabs in titlebar on linux # Disabled on OS X because of bug 967917 [browser_tabfocus.js] [browser_tabkeynavigation.js] -skip-if = e10s [browser_tabopen_reflows.js] [browser_tabs_close_beforeunload.js] support-files = diff --git a/browser/base/content/test/general/browser_tabkeynavigation.js b/browser/base/content/test/general/browser_tabkeynavigation.js index 64b0a3510116..13fb78dcceb9 100644 --- a/browser/base/content/test/general/browser_tabkeynavigation.js +++ b/browser/base/content/test/general/browser_tabkeynavigation.js @@ -42,23 +42,19 @@ function test() { is(gBrowser.selectedTab, tab1, "Tab1 should be activated"); - EventUtils.synthesizeKey("VK_TAB", { ctrlKey: true }, - browser1.contentWindow); + EventUtils.synthesizeKey("VK_TAB", { ctrlKey: true }); is(gBrowser.selectedTab, tab2, "Tab2 should be activated by pressing Ctrl+Tab on Tab1"); - EventUtils.synthesizeKey("VK_TAB", { ctrlKey: true }, - browser2.contentWindow); + EventUtils.synthesizeKey("VK_TAB", { ctrlKey: true }); is(gBrowser.selectedTab, tab3, "Tab3 should be activated by pressing Ctrl+Tab on Tab2"); - EventUtils.synthesizeKey("VK_TAB", { ctrlKey: true, shiftKey: true }, - browser3.contentWindow); + EventUtils.synthesizeKey("VK_TAB", { ctrlKey: true, shiftKey: true }); is(gBrowser.selectedTab, tab2, "Tab2 should be activated by pressing Ctrl+Shift+Tab on Tab3"); - EventUtils.synthesizeKey("VK_TAB", { ctrlKey: true, shiftKey: true }, - browser2.contentWindow); + EventUtils.synthesizeKey("VK_TAB", { ctrlKey: true, shiftKey: true }); is(gBrowser.selectedTab, tab1, "Tab1 should be activated by pressing Ctrl+Shift+Tab on Tab2"); @@ -67,23 +63,19 @@ function test() { is(gBrowser.selectedTab, tab1, "Tab1 should be activated"); - EventUtils.synthesizeKey("VK_PAGE_DOWN", { ctrlKey: true }, - browser1.contentWindow); + EventUtils.synthesizeKey("VK_PAGE_DOWN", { ctrlKey: true }); is(gBrowser.selectedTab, tab2, "Tab2 should be activated by pressing Ctrl+PageDown on Tab1"); - EventUtils.synthesizeKey("VK_PAGE_DOWN", { ctrlKey: true }, - browser2.contentWindow); + EventUtils.synthesizeKey("VK_PAGE_DOWN", { ctrlKey: true }); is(gBrowser.selectedTab, tab3, "Tab3 should be activated by pressing Ctrl+PageDown on Tab2"); - EventUtils.synthesizeKey("VK_PAGE_UP", { ctrlKey: true }, - browser3.contentWindow); + EventUtils.synthesizeKey("VK_PAGE_UP", { ctrlKey: true }); is(gBrowser.selectedTab, tab2, "Tab2 should be activated by pressing Ctrl+PageUp on Tab3"); - EventUtils.synthesizeKey("VK_PAGE_UP", { ctrlKey: true }, - browser2.contentWindow); + EventUtils.synthesizeKey("VK_PAGE_UP", { ctrlKey: true }); is(gBrowser.selectedTab, tab1, "Tab1 should be activated by pressing Ctrl+PageUp on Tab2"); @@ -98,23 +90,19 @@ function test() { is(gBrowser.selectedTab, tab1, "Tab1 should be activated"); - EventUtils.synthesizeKey(advanceKey, { altKey: true, metaKey: true }, - browser1.contentWindow); + EventUtils.synthesizeKey(advanceKey, { altKey: true, metaKey: true }); is(gBrowser.selectedTab, tab2, "Tab2 should be activated by pressing Ctrl+" + advanceKey + " on Tab1"); - EventUtils.synthesizeKey(advanceKey, { altKey: true, metaKey: true }, - browser2.contentWindow); + EventUtils.synthesizeKey(advanceKey, { altKey: true, metaKey: true }); is(gBrowser.selectedTab, tab3, "Tab3 should be activated by pressing Ctrl+" + advanceKey + " on Tab2"); - EventUtils.synthesizeKey(reverseKey, { altKey: true, metaKey: true }, - browser3.contentWindow); + EventUtils.synthesizeKey(reverseKey, { altKey: true, metaKey: true }); is(gBrowser.selectedTab, tab2, "Tab2 should be activated by pressing Ctrl+" + reverseKey + " on Tab3"); - EventUtils.synthesizeKey(reverseKey, { altKey: true, metaKey: true }, - browser2.contentWindow); + EventUtils.synthesizeKey(reverseKey, { altKey: true, metaKey: true }); is(gBrowser.selectedTab, tab1, "Tab1 should be activated by pressing Ctrl+" + reverseKey + " on Tab2"); } @@ -125,15 +113,13 @@ function test() { is(gBrowser.tabContainer.selectedIndex, 2, "Tab2 index should be 2"); - EventUtils.synthesizeKey("VK_PAGE_DOWN", { ctrlKey: true, shiftKey: true }, - browser2.contentWindow); + EventUtils.synthesizeKey("VK_PAGE_DOWN", { ctrlKey: true, shiftKey: true }); is(gBrowser.selectedTab, tab2, "Tab2 should be activated after Ctrl+Shift+PageDown"); is(gBrowser.tabContainer.selectedIndex, 3, "Tab2 index should be 1 after Ctrl+Shift+PageDown"); - EventUtils.synthesizeKey("VK_PAGE_UP", { ctrlKey: true, shiftKey: true }, - browser2.contentWindow); + EventUtils.synthesizeKey("VK_PAGE_UP", { ctrlKey: true, shiftKey: true }); is(gBrowser.selectedTab, tab2, "Tab2 should be activated after Ctrl+Shift+PageUp"); is(gBrowser.tabContainer.selectedIndex, 2, @@ -153,45 +139,37 @@ function test() { is(gBrowser.selectedTab, tab1, "Tab1 should be activated"); - EventUtils.synthesizeKey(advanceKey, { metaKey: true }, - browser1.contentWindow); + EventUtils.synthesizeKey(advanceKey, { metaKey: true }); is(gBrowser.selectedTab, tab2, "Tab2 should be activated by pressing Ctrl+" + advanceKey + " on Tab1"); - EventUtils.synthesizeKey(advanceKey, { metaKey: true }, - browser2.contentWindow); - todo_is(gBrowser.selectedTab, tab3, - "Tab3 should be activated by pressing Ctrl+" + advanceKey + " on Tab2"); + EventUtils.synthesizeKey(advanceKey, { metaKey: true }); + is(gBrowser.selectedTab, tab3, + "Tab3 should be activated by pressing Ctrl+" + advanceKey + " on Tab2"); - if (gBrowser.selectedTab != tab3) { - EventUtils.synthesizeKey(reverseKey, { metaKey: true }, - browser3.contentWindow); - is(gBrowser.selectedTab, tab2, - "Tab2 should be activated by pressing Ctrl+" + reverseKey + " on Tab3"); - } + EventUtils.synthesizeKey(reverseKey, { metaKey: true }); + is(gBrowser.selectedTab, tab2, + "Tab2 should be activated by pressing Ctrl+" + reverseKey + " on Tab3"); - EventUtils.synthesizeKey(reverseKey, { metaKey: true }, - browser2.contentWindow); - todo_is(gBrowser.selectedTab, tab1, - "Tab1 should be activated by pressing Ctrl+" + reverseKey + " on Tab2"); + EventUtils.synthesizeKey(reverseKey, { metaKey: true }); + is(gBrowser.selectedTab, tab1, + "Tab1 should be activated by pressing Ctrl+" + reverseKey + " on Tab2"); } else { gBrowser.selectedTab = tab2; - EventUtils.synthesizeKey("VK_F4", { type: "keydown", ctrlKey: true }, - browser2.contentWindow); + EventUtils.synthesizeKey("VK_F4", { type: "keydown", ctrlKey: true }); isnot(gBrowser.selectedTab, tab2, "Tab2 should be closed by pressing Ctrl+F4 on Tab2"); is(gBrowser.tabs.length, 3, - "The count of tabs should be 3 since tab2 should be closed"); + "The count of tabs should be 3 since tab2 should be closed"); let activeWindow = gBrowser.getBrowserForTab(gBrowser.selectedTab).contentWindow; // NOTE: keypress event shouldn't be fired since the keydown event should // be consumed by tab2. - EventUtils.synthesizeKey("VK_F4", { type: "keyup", ctrlKey: true }, - activeWindow); - is(gBrowser.tabs.length, 3, - "The count of tabs should be 3 since renaming key events shouldn't close other tabs"); + EventUtils.synthesizeKey("VK_F4", { type: "keyup", ctrlKey: true }); + is(gBrowser.tabs.length, 3, + "The count of tabs should be 3 since renaming key events shouldn't close other tabs"); } gBrowser.selectedTab = tab3; From bd528af5a4f04f1eda6d792b9e2ec140e5705718 Mon Sep 17 00:00:00 2001 From: Phil Ringnalda Date: Sat, 9 Jan 2016 20:18:12 -0800 Subject: [PATCH 10/10] Back out changeset c06ff2c95163 (bug 1237713) for enabling parts of browser_tabkeynavigation.js which fail on non-e10s OS X --- browser/base/content/test/general/browser.ini | 1 + .../test/general/browser_tabkeynavigation.js | 80 ++++++++++++------- 2 files changed, 52 insertions(+), 29 deletions(-) diff --git a/browser/base/content/test/general/browser.ini b/browser/base/content/test/general/browser.ini index 52d25d1f5a6a..3723d391d203 100644 --- a/browser/base/content/test/general/browser.ini +++ b/browser/base/content/test/general/browser.ini @@ -419,6 +419,7 @@ skip-if = os == "linux" || os == "mac" # No tabs in titlebar on linux # Disabled on OS X because of bug 967917 [browser_tabfocus.js] [browser_tabkeynavigation.js] +skip-if = e10s [browser_tabopen_reflows.js] [browser_tabs_close_beforeunload.js] support-files = diff --git a/browser/base/content/test/general/browser_tabkeynavigation.js b/browser/base/content/test/general/browser_tabkeynavigation.js index 13fb78dcceb9..64b0a3510116 100644 --- a/browser/base/content/test/general/browser_tabkeynavigation.js +++ b/browser/base/content/test/general/browser_tabkeynavigation.js @@ -42,19 +42,23 @@ function test() { is(gBrowser.selectedTab, tab1, "Tab1 should be activated"); - EventUtils.synthesizeKey("VK_TAB", { ctrlKey: true }); + EventUtils.synthesizeKey("VK_TAB", { ctrlKey: true }, + browser1.contentWindow); is(gBrowser.selectedTab, tab2, "Tab2 should be activated by pressing Ctrl+Tab on Tab1"); - EventUtils.synthesizeKey("VK_TAB", { ctrlKey: true }); + EventUtils.synthesizeKey("VK_TAB", { ctrlKey: true }, + browser2.contentWindow); is(gBrowser.selectedTab, tab3, "Tab3 should be activated by pressing Ctrl+Tab on Tab2"); - EventUtils.synthesizeKey("VK_TAB", { ctrlKey: true, shiftKey: true }); + EventUtils.synthesizeKey("VK_TAB", { ctrlKey: true, shiftKey: true }, + browser3.contentWindow); is(gBrowser.selectedTab, tab2, "Tab2 should be activated by pressing Ctrl+Shift+Tab on Tab3"); - EventUtils.synthesizeKey("VK_TAB", { ctrlKey: true, shiftKey: true }); + EventUtils.synthesizeKey("VK_TAB", { ctrlKey: true, shiftKey: true }, + browser2.contentWindow); is(gBrowser.selectedTab, tab1, "Tab1 should be activated by pressing Ctrl+Shift+Tab on Tab2"); @@ -63,19 +67,23 @@ function test() { is(gBrowser.selectedTab, tab1, "Tab1 should be activated"); - EventUtils.synthesizeKey("VK_PAGE_DOWN", { ctrlKey: true }); + EventUtils.synthesizeKey("VK_PAGE_DOWN", { ctrlKey: true }, + browser1.contentWindow); is(gBrowser.selectedTab, tab2, "Tab2 should be activated by pressing Ctrl+PageDown on Tab1"); - EventUtils.synthesizeKey("VK_PAGE_DOWN", { ctrlKey: true }); + EventUtils.synthesizeKey("VK_PAGE_DOWN", { ctrlKey: true }, + browser2.contentWindow); is(gBrowser.selectedTab, tab3, "Tab3 should be activated by pressing Ctrl+PageDown on Tab2"); - EventUtils.synthesizeKey("VK_PAGE_UP", { ctrlKey: true }); + EventUtils.synthesizeKey("VK_PAGE_UP", { ctrlKey: true }, + browser3.contentWindow); is(gBrowser.selectedTab, tab2, "Tab2 should be activated by pressing Ctrl+PageUp on Tab3"); - EventUtils.synthesizeKey("VK_PAGE_UP", { ctrlKey: true }); + EventUtils.synthesizeKey("VK_PAGE_UP", { ctrlKey: true }, + browser2.contentWindow); is(gBrowser.selectedTab, tab1, "Tab1 should be activated by pressing Ctrl+PageUp on Tab2"); @@ -90,19 +98,23 @@ function test() { is(gBrowser.selectedTab, tab1, "Tab1 should be activated"); - EventUtils.synthesizeKey(advanceKey, { altKey: true, metaKey: true }); + EventUtils.synthesizeKey(advanceKey, { altKey: true, metaKey: true }, + browser1.contentWindow); is(gBrowser.selectedTab, tab2, "Tab2 should be activated by pressing Ctrl+" + advanceKey + " on Tab1"); - EventUtils.synthesizeKey(advanceKey, { altKey: true, metaKey: true }); + EventUtils.synthesizeKey(advanceKey, { altKey: true, metaKey: true }, + browser2.contentWindow); is(gBrowser.selectedTab, tab3, "Tab3 should be activated by pressing Ctrl+" + advanceKey + " on Tab2"); - EventUtils.synthesizeKey(reverseKey, { altKey: true, metaKey: true }); + EventUtils.synthesizeKey(reverseKey, { altKey: true, metaKey: true }, + browser3.contentWindow); is(gBrowser.selectedTab, tab2, "Tab2 should be activated by pressing Ctrl+" + reverseKey + " on Tab3"); - EventUtils.synthesizeKey(reverseKey, { altKey: true, metaKey: true }); + EventUtils.synthesizeKey(reverseKey, { altKey: true, metaKey: true }, + browser2.contentWindow); is(gBrowser.selectedTab, tab1, "Tab1 should be activated by pressing Ctrl+" + reverseKey + " on Tab2"); } @@ -113,13 +125,15 @@ function test() { is(gBrowser.tabContainer.selectedIndex, 2, "Tab2 index should be 2"); - EventUtils.synthesizeKey("VK_PAGE_DOWN", { ctrlKey: true, shiftKey: true }); + EventUtils.synthesizeKey("VK_PAGE_DOWN", { ctrlKey: true, shiftKey: true }, + browser2.contentWindow); is(gBrowser.selectedTab, tab2, "Tab2 should be activated after Ctrl+Shift+PageDown"); is(gBrowser.tabContainer.selectedIndex, 3, "Tab2 index should be 1 after Ctrl+Shift+PageDown"); - EventUtils.synthesizeKey("VK_PAGE_UP", { ctrlKey: true, shiftKey: true }); + EventUtils.synthesizeKey("VK_PAGE_UP", { ctrlKey: true, shiftKey: true }, + browser2.contentWindow); is(gBrowser.selectedTab, tab2, "Tab2 should be activated after Ctrl+Shift+PageUp"); is(gBrowser.tabContainer.selectedIndex, 2, @@ -139,37 +153,45 @@ function test() { is(gBrowser.selectedTab, tab1, "Tab1 should be activated"); - EventUtils.synthesizeKey(advanceKey, { metaKey: true }); + EventUtils.synthesizeKey(advanceKey, { metaKey: true }, + browser1.contentWindow); is(gBrowser.selectedTab, tab2, "Tab2 should be activated by pressing Ctrl+" + advanceKey + " on Tab1"); - EventUtils.synthesizeKey(advanceKey, { metaKey: true }); - is(gBrowser.selectedTab, tab3, - "Tab3 should be activated by pressing Ctrl+" + advanceKey + " on Tab2"); + EventUtils.synthesizeKey(advanceKey, { metaKey: true }, + browser2.contentWindow); + todo_is(gBrowser.selectedTab, tab3, + "Tab3 should be activated by pressing Ctrl+" + advanceKey + " on Tab2"); - EventUtils.synthesizeKey(reverseKey, { metaKey: true }); - is(gBrowser.selectedTab, tab2, - "Tab2 should be activated by pressing Ctrl+" + reverseKey + " on Tab3"); + if (gBrowser.selectedTab != tab3) { + EventUtils.synthesizeKey(reverseKey, { metaKey: true }, + browser3.contentWindow); + is(gBrowser.selectedTab, tab2, + "Tab2 should be activated by pressing Ctrl+" + reverseKey + " on Tab3"); + } - EventUtils.synthesizeKey(reverseKey, { metaKey: true }); - is(gBrowser.selectedTab, tab1, - "Tab1 should be activated by pressing Ctrl+" + reverseKey + " on Tab2"); + EventUtils.synthesizeKey(reverseKey, { metaKey: true }, + browser2.contentWindow); + todo_is(gBrowser.selectedTab, tab1, + "Tab1 should be activated by pressing Ctrl+" + reverseKey + " on Tab2"); } else { gBrowser.selectedTab = tab2; - EventUtils.synthesizeKey("VK_F4", { type: "keydown", ctrlKey: true }); + EventUtils.synthesizeKey("VK_F4", { type: "keydown", ctrlKey: true }, + browser2.contentWindow); isnot(gBrowser.selectedTab, tab2, "Tab2 should be closed by pressing Ctrl+F4 on Tab2"); is(gBrowser.tabs.length, 3, - "The count of tabs should be 3 since tab2 should be closed"); + "The count of tabs should be 3 since tab2 should be closed"); let activeWindow = gBrowser.getBrowserForTab(gBrowser.selectedTab).contentWindow; // NOTE: keypress event shouldn't be fired since the keydown event should // be consumed by tab2. - EventUtils.synthesizeKey("VK_F4", { type: "keyup", ctrlKey: true }); - is(gBrowser.tabs.length, 3, - "The count of tabs should be 3 since renaming key events shouldn't close other tabs"); + EventUtils.synthesizeKey("VK_F4", { type: "keyup", ctrlKey: true }, + activeWindow); + is(gBrowser.tabs.length, 3, + "The count of tabs should be 3 since renaming key events shouldn't close other tabs"); } gBrowser.selectedTab = tab3;