Bug 1362036 - Implement tests; r=nchevobbe
MozReview-Commit-ID: KvvWrHUC8m6
--- a/devtools/client/webconsole/new-console-output/new-console-output-wrapper.js
+++ b/devtools/client/webconsole/new-console-output/new-console-output-wrapper.js
@@ -225,16 +225,25 @@ NewConsoleOutputWrapper.prototype = {
if (res.networkInfo.updates.length === NUMBER_OF_NETWORK_UPDATE) {
batchedMessageAdd(actions.networkMessageUpdate(message));
this.jsterm.hud.emit("network-message-updated", res);
}
},
dispatchRequestUpdate: function (id, data) {
batchedMessageAdd(actions.networkUpdateRequest(id, data));
+
+ // Fire an event indicating that all data fetched from
+ // the backend has been received. This is based on
+ // 'FirefoxDataProvider.isQueuePayloadReady', see more
+ // comments in that method.
+ // (netmonitor/src/connector/firefox-data-provider).
+ // This event might be utilized in tests to find the right
+ // time when to finish.
+ this.jsterm.hud.emit("network-request-payload-ready", {id, data});
},
// Should be used for test purpose only.
getStore: function () {
return store;
}
};
--- a/devtools/client/webconsole/new-console-output/test/components/network-event-message.test.js
+++ b/devtools/client/webconsole/new-console-output/test/components/network-event-message.test.js
@@ -104,9 +104,21 @@ describe("NetworkEventMessage component:
expect(wrapper.find(".message-body .xhr").length).toBe(1);
expect(wrapper.find(".message-body .xhr").text()).toBe("XHR");
expect(wrapper.find(".message-body .url").length).toBe(1);
expect(wrapper.find(".message-body .url").text()).toBe(EXPECTED_URL);
expect(wrapper.find(".message-body .status").length).toBe(1);
expect(wrapper.find(".message-body .status").text()).toMatch(EXPECTED_STATUS);
});
});
+
+ describe("is expandable", () => {
+ it("renders as expected", () => {
+ const message = stubPreparedMessages.get("XHR POST request");
+ const wrapper = render(NetworkEventMessage({
+ message,
+ serviceContainer,
+ }));
+
+ expect(wrapper.find(".message .theme-twisty")).toExist();
+ });
+ });
});
--- a/devtools/client/webconsole/new-console-output/test/mochitest/browser.ini
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/browser.ini
@@ -43,17 +43,18 @@ skip-if = (os == 'linux' && bits == 32 &
[browser_webconsole_filters_persist.js]
[browser_webconsole_init.js]
[browser_webconsole_input_focus.js]
[browser_webconsole_keyboard_accessibility.js]
[browser_webconsole_location_debugger_link.js]
[browser_webconsole_location_scratchpad_link.js]
[browser_webconsole_location_styleeditor_link.js]
[browser_webconsole_logErrorInPage.js]
-[browser_webconsole_network_messages_click.js]
+[browser_webconsole_network_messages_openinnet.js]
+[browser_webconsole_network_messages_expand.js]
[browser_webconsole_nodes_highlight.js]
[browser_webconsole_nodes_select.js]
[browser_webconsole_object_inspector_entries.js]
[browser_webconsole_object_inspector.js]
[browser_webconsole_observer_notifications.js]
[browser_webconsole_scroll.js]
[browser_webconsole_shows_reqs_in_netmonitor.js]
[browser_webconsole_sourcemap_error.js]
new file mode 100644
--- /dev/null
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_network_messages_expand.js
@@ -0,0 +1,67 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const TEST_URI = "data:text/html;charset=utf8,Test that clicking on a network message " +
+ "in the console toggles the HTTP inspection.";
+
+const TEST_FILE = "test-network-request.html";
+const TEST_PATH = "http://example.com/browser/devtools/client/webconsole/new-console-output/test/mochitest/";
+
+const NET_PREF = "devtools.webconsole.filter.net";
+const XHR_PREF = "devtools.webconsole.filter.netxhr";
+
+Services.prefs.setBoolPref(NET_PREF, true);
+Services.prefs.setBoolPref(XHR_PREF, true);
+registerCleanupFunction(() => {
+ Services.prefs.clearUserPref(NET_PREF);
+ Services.prefs.clearUserPref(XHR_PREF);
+});
+
+add_task(async function task() {
+ const hud = await openNewTabAndConsole(TEST_URI);
+
+ const currentTab = gBrowser.selectedTab;
+ let target = TargetFactory.forTab(currentTab);
+ let toolbox = gDevTools.getToolbox(target);
+
+ const documentUrl = TEST_PATH + TEST_FILE;
+ await loadDocument(documentUrl);
+ info("Document loaded.");
+
+ await testNetworkMessage(hud, documentUrl);
+ await waitForNetworkUpdates(toolbox);
+});
+
+async function testNetworkMessage(hud, url) {
+ let messageNode = await waitFor(() => findMessage(hud, url));
+ let urlNode = messageNode.querySelector(".url");
+ info("Network message found.");
+
+ EventUtils.sendMouseEvent({ type: "click" }, urlNode);
+
+ let headersTab = messageNode.querySelector("#headers-tab");
+ let cookiesTab = messageNode.querySelector("#cookies-tab");
+ let paramsTab = messageNode.querySelector("#params-tab");
+ let responseTab = messageNode.querySelector("#response-tab");
+ let timingsTab = messageNode.querySelector("#timings-tab");
+
+ ok(headersTab, "Headers tab is available");
+ ok(cookiesTab, "Cookies tab is available");
+ ok(paramsTab, "Params tab is available");
+ ok(responseTab, "Response tab is available");
+ ok(timingsTab, "Timings tab is available");
+}
+
+async function waitForNetworkUpdates(toolbox) {
+ let panel = toolbox.getCurrentPanel();
+ let hud = panel.hud;
+ let ui = hud.ui;
+
+ return new Promise(resolve => {
+ ui.jsterm.hud.on("network-request-payload-ready", () => {
+ resolve();
+ });
+ });
+}
rename from devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_network_messages_click.js
rename to devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_network_messages_openinnet.js
--- a/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_network_messages_click.js
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_network_messages_openinnet.js
@@ -1,22 +1,23 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
-const TEST_URI = "data:text/html;charset=utf8,Test that clicking on a network message " +
- "in the console opens the netmonitor panel.";
+const TEST_URI = "data:text/html;charset=utf8,Test that 'Open in Network Panel' " +
+ "context menu item opens the selected request in netmonitor panel.";
const TEST_FILE = "test-network-request.html";
const JSON_TEST_URL = "test-network-request.html";
const TEST_PATH = "http://example.com/browser/devtools/client/webconsole/new-console-output/test/mochitest/";
const NET_PREF = "devtools.webconsole.filter.net";
const XHR_PREF = "devtools.webconsole.filter.netxhr";
+
Services.prefs.setBoolPref(NET_PREF, true);
Services.prefs.setBoolPref(XHR_PREF, true);
registerCleanupFunction(() => {
Services.prefs.clearUserPref(NET_PREF);
Services.prefs.clearUserPref(XHR_PREF);
});
add_task(async function task() {
@@ -42,27 +43,26 @@ add_task(async function task() {
});
const jsonUrl = TEST_PATH + JSON_TEST_URL;
await testNetmonitorLink(toolbox, hud, jsonUrl);
});
async function testNetmonitorLink(toolbox, hud, url) {
let messageNode = await waitFor(() => findMessage(hud, url));
- let urlNode = messageNode.querySelector(".url");
info("Network message found.");
- let onNetmonitorSelected = new Promise((resolve) => {
- toolbox.once("netmonitor-selected", (event, panel) => {
- resolve(panel);
- });
+ let onNetmonitorSelected = toolbox.once("netmonitor-selected", (event, panel) => {
+ return panel;
});
- info("Simulate click on the network message url.");
- EventUtils.sendMouseEvent({ type: "click" }, urlNode);
+ let menuPopup = await openContextMenu(hud, messageNode);
+ let openInNetMenuItem = menuPopup.querySelector("#console-menu-open-in-network-panel");
+ ok(openInNetMenuItem, "open in network panel item is enabled");
+ openInNetMenuItem.click();
const {panelWin} = await onNetmonitorSelected;
ok(true, "The netmonitor panel is selected when clicking on the network message");
let { store, windowRequire } = panelWin;
let actions = windowRequire("devtools/client/netmonitor/src/actions/index");
let { getSelectedRequest } =
windowRequire("devtools/client/netmonitor/src/selectors/index");
--- a/devtools/client/webconsole/new-console-output/test/mochitest/head.js
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/head.js
@@ -48,17 +48,17 @@ registerCleanupFunction(function* () {
var openNewTabAndConsole = Task.async(function* (url) {
let toolbox = yield openNewTabAndToolbox(url, "webconsole");
let hud = toolbox.getCurrentPanel().hud;
hud.jsterm._lazyVariablesView = false;
return hud;
});
/**
- * Wait for messages in the web console output, resolving once they are receieved.
+ * Wait for messages in the web console output, resolving once they are received.
*
* @param object options
* - hud: the webconsole
* - messages: Array[Object]. An array of messages to match.
Current supported options:
* - text: Exact text match in .message-body
*/
function waitForMessages({ hud, messages }) {
@@ -95,17 +95,17 @@ function waitForMessages({ hud, messages
/**
* Wait for a predicate to return a result.
*
* @param function condition
* Invoked once in a while until it returns a truthy value. This should be an
* idempotent function, since we have to run it a second time after it returns
* true in order to return the value.
* @param string message [optional]
- * A message to output if the condition failes.
+ * A message to output if the condition fails.
* @param number interval [optional]
* How often the predicate is invoked, in milliseconds.
* @return object
* A promise that is resolved with the result of the condition.
*/
async function waitFor(condition, message = "waitFor", interval = 10, maxTries = 500) {
await BrowserTestUtils.waitForCondition(condition, message, interval, maxTries);
return condition();
@@ -139,30 +139,31 @@ function findMessage(hud, text, selector
function findMessages(hud, text, selector = ".message") {
const messages = hud.ui.outputNode.querySelectorAll(selector);
const elements = Array.prototype.filter.call(
messages,
(el) => el.textContent.includes(text)
);
return elements;
}
+
/**
* Simulate a context menu event on the provided element, and wait for the console context
* menu to open. Returns a promise that resolves the menu popup element.
*
* @param object hud
* The web console.
* @param element element
* The dom element on which the context menu event should be synthesized.
* @return promise
*/
-function* openContextMenu(hud, element) {
+async function openContextMenu(hud, element) {
let onConsoleMenuOpened = hud.ui.newConsoleOutput.once("menu-open");
synthesizeContextMenuEvent(element);
- yield onConsoleMenuOpened;
+ await onConsoleMenuOpened;
return hud.ui.newConsoleOutput.toolbox.doc.getElementById("webconsole-menu");
}
/**
* Hide the webconsole context menu popup. Returns a promise that will resolve when the
* context menu popup is hidden or immediately if the popup can't be found.
*
* @param object hud
--- a/devtools/client/webconsole/new-console-output/test/require-helper.js
+++ b/devtools/client/webconsole/new-console-output/test/require-helper.js
@@ -31,11 +31,13 @@ requireHacker.global_hook("default", pat
return `module.exports = require("devtools/client/webconsole/new-console-output/test/fixtures/LocalizationHelper")`;
case "devtools/shared/plural-form":
return `module.exports = require("devtools/client/webconsole/new-console-output/test/fixtures/PluralForm")`;
case "Services":
case "Services.default":
return `module.exports = require("devtools/client/webconsole/new-console-output/test/fixtures/Services")`;
case "devtools/shared/client/main":
return `module.exports = require("devtools/client/webconsole/new-console-output/test/fixtures/ObjectClient")`;
+ case "devtools/client/netmonitor/src/components/tabbox-panel":
+ return "{}";
}
return undefined;
});
new file mode 100644
--- /dev/null
+++ b/devtools/client/webconsole/new-console-output/test/store/network-messages.test.js
@@ -0,0 +1,85 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+const {
+ getAllNetworkMessagesUpdateById,
+} = require("devtools/client/webconsole/new-console-output/selectors/messages");
+const {
+ setupActions,
+ setupStore,
+ clonePacket
+} = require("devtools/client/webconsole/new-console-output/test/helpers");
+const { stubPackets } = require("devtools/client/webconsole/new-console-output/test/fixtures/stubs/index");
+
+const expect = require("expect");
+
+describe("Network message reducer:", () => {
+ let actions;
+ let getState;
+ let dispatch;
+
+ before(() => {
+ actions = setupActions();
+ });
+
+ beforeEach(() => {
+ const store = setupStore([]);
+
+ getState = store.getState;
+ dispatch = store.dispatch;
+
+ let packet = clonePacket(stubPackets.get("GET request"));
+ let updatePacket = clonePacket(stubPackets.get("GET request update"));
+
+ packet.actor = "message1";
+ updatePacket.networkInfo.actor = "message1";
+ dispatch(actions.messageAdd(packet));
+ dispatch(actions.networkMessageUpdate(updatePacket.networkInfo));
+ });
+
+ describe("networkMessagesUpdateById", () => {
+ it("adds fetched HTTP request headers", () => {
+ let headers = {
+ headers: []
+ };
+
+ dispatch(actions.networkUpdateRequest("message1", {
+ requestHeaders: headers
+ }));
+
+ let networkUpdates = getAllNetworkMessagesUpdateById(getState());
+ expect(networkUpdates.message1.requestHeaders).toBe(headers);
+ });
+
+ it("adds fetched HTTP security info", () => {
+ let securityInfo = {
+ state: "insecure"
+ };
+
+ dispatch(actions.networkUpdateRequest("message1", {
+ securityInfo: securityInfo
+ }));
+
+ let networkUpdates = getAllNetworkMessagesUpdateById(getState());
+ expect(networkUpdates.message1.securityInfo).toBe(securityInfo);
+ expect(networkUpdates.message1.securityState).toBe("insecure");
+ });
+
+ it("adds fetched HTTP post data", () => {
+ let requestPostData = {
+ postData: {
+ text: ""
+ }
+ };
+
+ dispatch(actions.networkUpdateRequest("message1", {
+ requestPostData: requestPostData
+ }));
+
+ let networkUpdates = getAllNetworkMessagesUpdateById(getState());
+ expect(networkUpdates.message1.requestPostData).toBe(requestPostData);
+ expect(networkUpdates.message1.requestHeadersFromUploadStream).toExist();
+ });
+ });
+});
--- a/devtools/client/webconsole/webpack.config.js
+++ b/devtools/client/webconsole/webpack.config.js
@@ -77,16 +77,17 @@ webpackConfig.resolve = {
"devtools/client/shared/components/frame": path.join(__dirname, "../../client/shared/components/frame"),
"devtools/client/shared/key-shortcuts": "devtools-modules/src/key-shortcuts",
"devtools/client/shared/zoom-keys": "devtools-modules/src/zoom-keys",
"devtools/shared/defer": path.join(__dirname, "../../shared/defer"),
"devtools/shared/old-event-emitter": "devtools-modules/src/utils/event-emitter",
"devtools/shared/client/main": path.join(__dirname, "new-console-output/test/fixtures/ObjectClient"),
"devtools/shared/platform/clipboard": path.join(__dirname, "../../shared/platform/content/clipboard"),
+ "devtools/shared/platform/stack": path.join(__dirname, "../../shared/platform/content/stack"),
}
};
const mappings = [
[
/utils\/menu/, "devtools-launchpad/src/components/shared/menu"
],
[