Files
UXP-Fixed/devtools/client/webconsole/net/test/mochitest/head.js
T
2018-02-02 04:16:08 -05:00

210 lines
5.8 KiB
JavaScript

/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
/* eslint no-unused-vars: [2, {"vars": "local", "args": "none"}] */
/* import-globals-from ../../../test/head.js */
"use strict";
// Load Web Console head.js, it implements helper console test API
Services.scriptloader.loadSubScript(
"chrome://mochitests/content/browser/devtools/client/webconsole/test/head.js", this);
const FRAME_SCRIPT_UTILS_URL =
"chrome://devtools/content/shared/frame-script-utils.js";
const NET_INFO_PREF = "devtools.webconsole.filter.networkinfo";
const NET_XHR_PREF = "devtools.webconsole.filter.netxhr";
// Enable XHR logging for the test
Services.prefs.setBoolPref(NET_INFO_PREF, true);
Services.prefs.setBoolPref(NET_XHR_PREF, true);
registerCleanupFunction(() => {
Services.prefs.clearUserPref(NET_INFO_PREF, true);
Services.prefs.clearUserPref(NET_XHR_PREF, true);
});
// Use the old webconsole since the new one doesn't yet support
// XHR spy. See Bug 1304794.
Services.prefs.setBoolPref("devtools.webconsole.new-frontend-enabled", false);
registerCleanupFunction(function* () {
Services.prefs.clearUserPref("devtools.webconsole.new-frontend-enabled");
});
/**
* Add a new test tab in the browser and load the given url.
* @param {String} url The url to be loaded in the new tab
* @return a promise that resolves to the tab object when the url is loaded
*/
function addTestTab(url) {
info("Adding a new JSON tab with URL: '" + url + "'");
return Task.spawn(function* () {
let tab = yield addTab(url);
// Load devtools/shared/frame-script-utils.js
loadCommonFrameScript(tab);
// Open the Console panel
let hud = yield openConsole();
return {
tab: tab,
browser: tab.linkedBrowser,
hud: hud
};
});
}
/**
*
* @param hud
* @param options
*/
function executeAndInspectXhr(hud, options) {
hud.jsterm.clearOutput();
options.queryString = options.queryString || "";
// Execute XHR in the content scope.
performRequestsInContent({
method: options.method,
url: options.url + options.queryString,
body: options.body,
nocache: options.nocache,
requestHeaders: options.requestHeaders
});
return Task.spawn(function* () {
// Wait till the appropriate Net log appears in the Console panel.
let rules = yield waitForMessages({
webconsole: hud,
messages: [{
text: options.url,
category: CATEGORY_NETWORK,
severity: SEVERITY_INFO,
isXhr: true,
}]
});
// The log is here, get its parent element (className: 'message').
let msg = [...rules[0].matched][0];
let body = msg.querySelector(".message-body");
// Open XHR HTTP details body and wait till the UI fetches
// all necessary data from the backend. All RPD requests
// needs to be finished before we can continue testing.
yield synthesizeMouseClickSoon(hud, body);
yield waitForBackend(msg);
let netInfoBody = body.querySelector(".netInfoBody");
ok(netInfoBody, "Net info body must exist");
return netInfoBody;
});
}
/**
* Wait till XHR data are fetched from the backend (i.e. there are
* no pending RDP requests.
*/
function waitForBackend(element) {
if (!element.hasAttribute("loading")) {
return;
}
return once(element, "netlog-no-pending-requests", true);
}
/**
* Select specific tab in XHR info body.
*
* @param netInfoBody The main XHR info body
* @param tabId Tab ID (possible values: 'headers', 'cookies', 'params',
* 'post', 'response');
*
* @returns Tab body element.
*/
function selectNetInfoTab(hud, netInfoBody, tabId) {
let tab = netInfoBody.querySelector(".tabs-menu-item." + tabId);
ok(tab, "Tab must exist " + tabId);
// Click to select specified tab and wait till its
// UI is populated with data from the backend.
// There must be no pending RDP requests before we can
// continue testing the UI.
return Task.spawn(function* () {
yield synthesizeMouseClickSoon(hud, tab);
let msg = getAncestorByClass(netInfoBody, "message");
yield waitForBackend(msg);
let tabBody = netInfoBody.querySelector("." + tabId + "TabBox");
ok(tabBody, "Tab body must exist");
return tabBody;
});
}
/**
* Return parent node with specified class.
*
* @param node A child element
* @param className Specified class name.
*
* @returns A parent element.
*/
function getAncestorByClass(node, className) {
for (let parent = node; parent; parent = parent.parentNode) {
if (parent.classList && parent.classList.contains(className)) {
return parent;
}
}
return null;
}
/**
* Synthesize asynchronous click event (with clean stack trace).
*/
function synthesizeMouseClickSoon(hud, element) {
return new Promise((resolve) => {
executeSoon(() => {
EventUtils.synthesizeMouse(element, 2, 2, {}, hud.iframeWindow);
resolve();
});
});
}
/**
* Execute XHR in the content scope.
*/
function performRequestsInContent(requests) {
info("Performing requests in the context of the content.");
return executeInContent("devtools:test:xhr", requests);
}
function executeInContent(name, data = {}, objects = {},
expectResponse = true) {
let mm = gBrowser.selectedBrowser.messageManager;
mm.sendAsyncMessage(name, data, objects);
if (expectResponse) {
return waitForContentMessage(name);
}
return Promise.resolve();
}
function waitForContentMessage(name) {
info("Expecting message " + name + " from content");
let mm = gBrowser.selectedBrowser.messageManager;
return new Promise((resolve) => {
mm.addMessageListener(name, function onMessage(msg) {
mm.removeMessageListener(name, onMessage);
resolve(msg.data);
});
});
}
function loadCommonFrameScript(tab) {
let browser = tab ? tab.linkedBrowser : gBrowser.selectedBrowser;
browser.messageManager.loadFrameScript(FRAME_SCRIPT_UTILS_URL, false);
}