Bug 940538 - Convert network monitor to use Promise.jsm. r=benvie, r=vp

This commit is contained in:
Jordan Santell 2013-12-02 11:34:47 -05:00
Родитель 513888aae8
Коммит f9aac2edf0
14 изменённых файлов: 318 добавлений и 215 удалений

Просмотреть файл

@ -55,17 +55,30 @@ const EVENTS = {
REQUEST_POST_PARAMS_DISPLAYED: "NetMonitor:RequestPostParamsAvailable",
// When the response body is displayed in the UI.
RESPONSE_BODY_DISPLAYED: "NetMonitor:ResponseBodyAvailable"
}
RESPONSE_BODY_DISPLAYED: "NetMonitor:ResponseBodyAvailable",
// When `onTabSelect` is fired and subsequently rendered
TAB_UPDATED: "NetMonitor:TabUpdated",
// Fired when Sidebar is finished being populated
SIDEBAR_POPULATED: "NetMonitor:SidebarPopulated",
// Fired when NetworkDetailsView is finished being populated
NETWORKDETAILSVIEW_POPULATED: "NetMonitor:NetworkDetailsViewPopulated",
// Fired when NetworkDetailsView is finished being populated
CUSTOMREQUESTVIEW_POPULATED: "NetMonitor:CustomRequestViewPopulated"
};
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
let promise = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js").Promise;
Cu.import("resource://gre/modules/Task.jsm");
Cu.import("resource:///modules/devtools/shared/event-emitter.js");
Cu.import("resource:///modules/devtools/SideMenuWidget.jsm");
Cu.import("resource:///modules/devtools/VariablesView.jsm");
Cu.import("resource:///modules/devtools/VariablesViewController.jsm");
Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
const { Promise: promise } = Cu.import("resource://gre/modules/Promise.jsm", {});
const require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
const Editor = require("devtools/sourceeditor/editor");

Просмотреть файл

@ -6,7 +6,7 @@
"use strict";
const { Cc, Ci, Cu, Cr } = require("chrome");
const promise = require("sdk/core/promise");
const { Promise: promise } = Cu.import("resource://gre/modules/Promise.jsm", {});
const EventEmitter = require("devtools/shared/event-emitter");
function NetMonitorPanel(iframeWindow, toolbox) {

Просмотреть файл

@ -1382,15 +1382,19 @@ SidebarView.prototype = {
*
* @param object aData
* The data source (this should be the attachment of a request item).
* @return object
* Returns a promise that resolves upon population of the subview.
*/
populate: function(aData) {
if (aData.isCustom) {
NetMonitorView.CustomRequest.populate(aData);
$("#details-pane").selectedIndex = 0;
} else {
NetMonitorView.NetworkDetails.populate(aData);
$("#details-pane").selectedIndex = 1;
}
let isCustom = aData.isCustom;
let view = isCustom ?
NetMonitorView.CustomRequest :
NetMonitorView.NetworkDetails;
return view.populate(aData).then(() => {
$("#details-pane").selectedIndex = isCustom ? 0 : 1
window.emit(EVENTS.SIDEBAR_POPULATED)
});
},
/**
@ -1414,6 +1418,8 @@ CustomRequestView.prototype = {
*
* @param object aData
* The data source (this should be the attachment of a request item).
* @return object
* Returns a promise that resolves upon population the view.
*/
populate: function(aData) {
$("#custom-url-value").value = aData.url;
@ -1421,15 +1427,22 @@ CustomRequestView.prototype = {
$("#custom-headers-value").value =
writeHeaderText(aData.requestHeaders.headers);
let view = this;
let postDataPromise = null;
if (aData.requestPostData) {
let body = aData.requestPostData.postData.text;
gNetwork.getString(body).then(aString => {
postDataPromise = gNetwork.getString(body).then(aString => {
$("#custom-postdata-value").value = aString;
});
} else {
postDataPromise = promise.resolve();
}
this.updateCustomQuery(aData.url);
return postDataPromise
.then(() => view.updateCustomQuery(aData.url))
.then(() => window.emit(EVENTS.CUSTOMREQUESTVIEW_POPULATED));
},
/**
@ -1584,6 +1597,8 @@ NetworkDetailsView.prototype = {
*
* @param object aData
* The data source (this should be the attachment of a request item).
* @return object
* Returns a promise that resolves upon population the view.
*/
populate: function(aData) {
$("#request-params-box").setAttribute("flex", "1");
@ -1601,6 +1616,9 @@ NetworkDetailsView.prototype = {
this._dataSrc = { src: aData, populated: [] };
this._onTabSelect();
window.emit(EVENTS.NETWORKDETAILSVIEW_POPULATED);
return promise.resolve();
},
/**
@ -1609,35 +1627,38 @@ NetworkDetailsView.prototype = {
_onTabSelect: function() {
let { src, populated } = this._dataSrc || {};
let tab = this.widget.selectedIndex;
let view = this;
// Make sure the data source is valid and don't populate the same tab twice.
if (!src || populated[tab]) {
return;
}
switch (tab) {
case 0: // "Headers"
this._setSummary(src);
this._setResponseHeaders(src.responseHeaders);
this._setRequestHeaders(src.requestHeaders);
break;
case 1: // "Cookies"
this._setResponseCookies(src.responseCookies);
this._setRequestCookies(src.requestCookies);
break;
case 2: // "Params"
this._setRequestGetParams(src.url);
this._setRequestPostParams(src.requestHeaders, src.requestPostData);
break;
case 3: // "Response"
this._setResponseBody(src.url, src.responseContent);
break;
case 4: // "Timings"
this._setTimingsInformation(src.eventTimings);
break;
}
populated[tab] = true;
Task.spawn(function*() {
switch (tab) {
case 0: // "Headers"
yield view._setSummary(src);
yield view._setResponseHeaders(src.responseHeaders);
yield view._setRequestHeaders(src.requestHeaders);
break;
case 1: // "Cookies"
yield view._setResponseCookies(src.responseCookies);
yield view._setRequestCookies(src.requestCookies);
break;
case 2: // "Params"
yield view._setRequestGetParams(src.url);
yield view._setRequestPostParams(src.requestHeaders, src.requestPostData);
break;
case 3: // "Response"
yield view._setResponseBody(src.url, src.responseContent);
break;
case 4: // "Timings"
yield view._setTimingsInformation(src.eventTimings);
break;
}
populated[tab] = true;
window.emit(EVENTS.TAB_UPDATED);
});
},
/**
@ -1684,11 +1705,14 @@ NetworkDetailsView.prototype = {
*
* @param object aResponse
* The message received from the server.
* @return object
* A promise that resolves when request headers are set.
*/
_setRequestHeaders: function(aResponse) {
if (aResponse && aResponse.headers.length) {
this._addHeaders(this._requestHeaders, aResponse);
return this._addHeaders(this._requestHeaders, aResponse);
}
return promise.resolve();
},
/**
@ -1696,12 +1720,15 @@ NetworkDetailsView.prototype = {
*
* @param object aResponse
* The message received from the server.
* @return object
* A promise that resolves when response headers are set.
*/
_setResponseHeaders: function(aResponse) {
if (aResponse && aResponse.headers.length) {
aResponse.headers.sort((a, b) => a.name > b.name);
this._addHeaders(this._responseHeaders, aResponse);
return this._addHeaders(this._responseHeaders, aResponse);
}
return promise.resolve();
},
/**
@ -1711,6 +1738,8 @@ NetworkDetailsView.prototype = {
* The type of headers to populate (request or response).
* @param object aResponse
* The message received from the server.
* @return object
* A promise that resolves when headers are added.
*/
_addHeaders: function(aName, aResponse) {
let kb = aResponse.headersSize / 1024;
@ -1719,10 +1748,11 @@ NetworkDetailsView.prototype = {
let headersScope = this._headers.addScope(aName + " (" + text + ")");
headersScope.expanded = true;
for (let header of aResponse.headers) {
return promise.all(aResponse.headers.map(header => {
let headerVar = headersScope.addItem(header.name, {}, true);
gNetwork.getString(header.value).then(aString => headerVar.setGrip(aString));
}
return gNetwork.getString(header.value)
.then(aString => headerVar.setGrip(aString));
}));
},
/**
@ -1730,12 +1760,15 @@ NetworkDetailsView.prototype = {
*
* @param object aResponse
* The message received from the server.
* @return object
* A promise that is resolved when the request cookies are set.
*/
_setRequestCookies: function(aResponse) {
if (aResponse && aResponse.cookies.length) {
aResponse.cookies.sort((a, b) => a.name > b.name);
this._addCookies(this._requestCookies, aResponse);
return this._addCookies(this._requestCookies, aResponse);
}
return promise.resolve();
},
/**
@ -1743,11 +1776,14 @@ NetworkDetailsView.prototype = {
*
* @param object aResponse
* The message received from the server.
* @return object
* A promise that is resolved when the response cookies are set.
*/
_setResponseCookies: function(aResponse) {
if (aResponse && aResponse.cookies.length) {
this._addCookies(this._responseCookies, aResponse);
return this._addCookies(this._responseCookies, aResponse);
}
return promise.resolve();
},
/**
@ -1757,33 +1793,37 @@ NetworkDetailsView.prototype = {
* The type of cookies to populate (request or response).
* @param object aResponse
* The message received from the server.
* @return object
* Returns a promise that resolves upon the adding of cookies.
*/
_addCookies: function(aName, aResponse) {
let cookiesScope = this._cookies.addScope(aName);
cookiesScope.expanded = true;
for (let cookie of aResponse.cookies) {
return promise.all(aResponse.cookies.map(cookie => {
let cookieVar = cookiesScope.addItem(cookie.name, {}, true);
gNetwork.getString(cookie.value).then(aString => cookieVar.setGrip(aString));
return gNetwork.getString(cookie.value).then(aString => {
cookieVar.setGrip(aString);
// By default the cookie name and value are shown. If this is the only
// information available, then nothing else is to be displayed.
let cookieProps = Object.keys(cookie);
if (cookieProps.length == 2) {
continue;
}
// By default the cookie name and value are shown. If this is the only
// information available, then nothing else is to be displayed.
let cookieProps = Object.keys(cookie);
if (cookieProps.length == 2) {
return;
}
// Display any other information other than the cookie name and value
// which may be available.
let rawObject = Object.create(null);
let otherProps = cookieProps.filter(e => e != "name" && e != "value");
for (let prop of otherProps) {
rawObject[prop] = cookie[prop];
}
cookieVar.populate(rawObject);
cookieVar.twisty = true;
cookieVar.expanded = true;
}
// Display any other information other than the cookie name and value
// which may be available.
let rawObject = Object.create(null);
let otherProps = cookieProps.filter(e => e != "name" && e != "value");
for (let prop of otherProps) {
rawObject[prop] = cookie[prop];
}
cookieVar.populate(rawObject);
cookieVar.twisty = true;
cookieVar.expanded = true;
});
}));
},
/**
@ -1806,12 +1846,14 @@ NetworkDetailsView.prototype = {
* The "requestHeaders" message received from the server.
* @param object aPostDataResponse
* The "requestPostData" message received from the server.
* @return object
* A promise that is resolved when the request post params are set.
*/
_setRequestPostParams: function(aHeadersResponse, aPostDataResponse) {
if (!aHeadersResponse || !aPostDataResponse) {
return;
return promise.resolve();
}
gNetwork.getString(aPostDataResponse.postData.text).then(aString => {
return gNetwork.getString(aPostDataResponse.postData.text).then(aString => {
// Handle query strings (poor man's forms, e.g. "?foo=bar&baz=42").
let cType = aHeadersResponse.headers.filter(({ name }) => name == "Content-Type")[0];
let cString = cType ? cType.value : "";
@ -1833,12 +1875,11 @@ NetworkDetailsView.prototype = {
paramsScope.locked = true;
$("#request-post-data-textarea-box").hidden = false;
NetMonitorView.editor("#request-post-data-textarea").then(aEditor => {
return NetMonitorView.editor("#request-post-data-textarea").then(aEditor => {
aEditor.setText(aString);
});
}
window.emit(EVENTS.REQUEST_POST_PARAMS_DISPLAYED);
});
}).then(() => window.emit(EVENTS.REQUEST_POST_PARAMS_DISPLAYED));
},
/**
@ -1870,14 +1911,16 @@ NetworkDetailsView.prototype = {
* The request's url.
* @param object aResponse
* The message received from the server.
* @return object
* A promise that is resolved when the response body is set
*/
_setResponseBody: function(aUrl, aResponse) {
if (!aResponse) {
return;
return promise.resolve();
}
let { mimeType, text, encoding } = aResponse.content;
gNetwork.getString(text).then(aString => {
return gNetwork.getString(text).then(aString => {
// Handle json, which we tentatively identify by checking the MIME type
// for "json" after any word boundary. This works for the standard
// "application/json", and also for custom types like "x-bigcorp-json".
@ -1903,22 +1946,22 @@ NetworkDetailsView.prototype = {
? L10N.getFormatStr("jsonpScopeName", callbackPadding[0].slice(0, -1))
: L10N.getStr("jsonScopeName");
this._json.controller.setSingleVariable({
return this._json.controller.setSingleVariable({
label: jsonScopeName,
rawObject: jsonObject,
});
}).expanded;
}
// Malformed JSON.
else {
$("#response-content-textarea-box").hidden = false;
NetMonitorView.editor("#response-content-textarea").then(aEditor => {
aEditor.setMode(Editor.modes.js);
aEditor.setText(aString);
});
let infoHeader = $("#response-content-info-header");
infoHeader.setAttribute("value", parsingError);
infoHeader.setAttribute("tooltiptext", parsingError);
infoHeader.hidden = false;
return NetMonitorView.editor("#response-content-textarea").then(aEditor => {
aEditor.setMode(Editor.modes.js);
aEditor.setText(aString);
});
}
}
// Handle images.
@ -1948,7 +1991,7 @@ NetworkDetailsView.prototype = {
// Handle anything else.
else {
$("#response-content-textarea-box").hidden = false;
NetMonitorView.editor("#response-content-textarea").then(aEditor => {
return NetMonitorView.editor("#response-content-textarea").then(aEditor => {
aEditor.setMode(Editor.modes.text);
aEditor.setText(aString);
@ -1964,8 +2007,7 @@ NetworkDetailsView.prototype = {
}
});
}
window.emit(EVENTS.RESPONSE_BODY_DISPLAYED);
});
}).then(() => window.emit(EVENTS.RESPONSE_BODY_DISPLAYED));
},
/**

Просмотреть файл

@ -75,31 +75,27 @@ function test() {
EventUtils.sendMouseEvent({ type: "mousedown" },
document.querySelectorAll("#details-pane tab")[3]);
testResponseTab("xml")
.then(() => {
RequestsMenu.selectedIndex = 1;
return testResponseTab("css");
})
.then(() => {
RequestsMenu.selectedIndex = 2;
return testResponseTab("js");
})
.then(() => {
RequestsMenu.selectedIndex = 3;
return testResponseTab("json");
})
.then(() => {
RequestsMenu.selectedIndex = 4;
return testResponseTab("html");
})
.then(() => {
RequestsMenu.selectedIndex = 5;
return testResponseTab("png");
})
.then(() => {
return teardown(aMonitor);
})
.then(finish);
Task.spawn(function*() {
yield waitForResponseBodyDisplayed();
yield testResponseTab("xml");
RequestsMenu.selectedIndex = 1;
yield waitForTabUpdated();
yield testResponseTab("css");
RequestsMenu.selectedIndex = 2;
yield waitForTabUpdated();
yield testResponseTab("js");
RequestsMenu.selectedIndex = 3;
yield waitForTabUpdated();
yield testResponseTab("json");
RequestsMenu.selectedIndex = 4;
yield waitForTabUpdated();
yield testResponseTab("html");
RequestsMenu.selectedIndex = 5;
yield waitForTabUpdated();
yield testResponseTab("png");
yield teardown(aMonitor);
finish();
});
function testResponseTab(aType) {
let tab = document.querySelectorAll("#details-pane tab")[3];
@ -221,6 +217,14 @@ function test() {
}
}
}
function waitForTabUpdated () {
return waitFor(aMonitor.panelWin, aMonitor.panelWin.EVENTS.TAB_UPDATED);
}
function waitForResponseBodyDisplayed () {
return waitFor(aMonitor.panelWin, aMonitor.panelWin.EVENTS.RESPONSE_BODY_DISPLAYED);
}
});
aDebuggee.performRequests();

Просмотреть файл

@ -26,7 +26,10 @@ function test() {
EventUtils.sendMouseEvent({ type: "mousedown" },
document.querySelectorAll("#details-pane tab")[3]);
NetMonitorView.editor("#response-content-textarea").then((aEditor) => {
let RESPONSE_BODY_DISPLAYED = aMonitor.panelWin.EVENTS.RESPONSE_BODY_DISPLAYED;
waitFor(aMonitor.panelWin, RESPONSE_BODY_DISPLAYED).then(() =>
NetMonitorView.editor("#response-content-textarea")
).then((aEditor) => {
is(aEditor.getText().indexOf("\u044F"), 26, // я
"The text shown in the source editor is incorrect.");
is(aEditor.getMode(), Editor.modes.text,

Просмотреть файл

@ -27,7 +27,10 @@ function test() {
EventUtils.sendMouseEvent({ type: "mousedown" },
document.querySelectorAll("#details-pane tab")[3]);
NetMonitorView.editor("#response-content-textarea").then((aEditor) => {
let RESPONSE_BODY_DISPLAYED = aMonitor.panelWin.EVENTS.RESPONSE_BODY_DISPLAYED;
waitFor(aMonitor.panelWin, RESPONSE_BODY_DISPLAYED).then(() =>
NetMonitorView.editor("#response-content-textarea")
).then((aEditor) => {
is(aEditor.getText().indexOf("\u044F"), 302, // я
"The text shown in the source editor is incorrect.");
is(aEditor.getMode(), Editor.modes.html,

Просмотреть файл

@ -31,38 +31,41 @@ function test() {
let tab = document.querySelectorAll("#details-pane tab")[3];
let tabpanel = document.querySelectorAll("#details-pane tabpanel")[3];
is(tab.getAttribute("selected"), "true",
"The response tab in the network details pane should be selected.");
let RESPONSE_BODY_DISPLAYED = aMonitor.panelWin.EVENTS.RESPONSE_BODY_DISPLAYED;
waitFor(aMonitor.panelWin, RESPONSE_BODY_DISPLAYED).then(() => {
is(tab.getAttribute("selected"), "true",
"The response tab in the network details pane should be selected.");
is(tabpanel.querySelector("#response-content-info-header")
.hasAttribute("hidden"), false,
"The response info header doesn't have the intended visibility.");
is(tabpanel.querySelector("#response-content-info-header")
.getAttribute("value"),
"SyntaxError: JSON.parse: unexpected non-whitespace character after JSON data",
"The response info header doesn't have the intended value attribute.");
is(tabpanel.querySelector("#response-content-info-header")
.getAttribute("tooltiptext"),
"SyntaxError: JSON.parse: unexpected non-whitespace character after JSON data",
"The response info header doesn't have the intended tooltiptext attribute.");
is(tabpanel.querySelector("#response-content-info-header")
.hasAttribute("hidden"), false,
"The response info header doesn't have the intended visibility.");
is(tabpanel.querySelector("#response-content-info-header")
.getAttribute("value"),
"SyntaxError: JSON.parse: unexpected non-whitespace character after JSON data",
"The response info header doesn't have the intended value attribute.");
is(tabpanel.querySelector("#response-content-info-header")
.getAttribute("tooltiptext"),
"SyntaxError: JSON.parse: unexpected non-whitespace character after JSON data",
"The response info header doesn't have the intended tooltiptext attribute.");
is(tabpanel.querySelector("#response-content-json-box")
.hasAttribute("hidden"), true,
"The response content json box doesn't have the intended visibility.");
is(tabpanel.querySelector("#response-content-textarea-box")
.hasAttribute("hidden"), false,
"The response content textarea box doesn't have the intended visibility.");
is(tabpanel.querySelector("#response-content-image-box")
.hasAttribute("hidden"), true,
"The response content image box doesn't have the intended visibility.");
is(tabpanel.querySelector("#response-content-json-box")
.hasAttribute("hidden"), true,
"The response content json box doesn't have the intended visibility.");
is(tabpanel.querySelector("#response-content-textarea-box")
.hasAttribute("hidden"), false,
"The response content textarea box doesn't have the intended visibility.");
is(tabpanel.querySelector("#response-content-image-box")
.hasAttribute("hidden"), true,
"The response content image box doesn't have the intended visibility.");
NetMonitorView.editor("#response-content-textarea").then((aEditor) => {
is(aEditor.getText(), "{ \"greeting\": \"Hello malformed JSON!\" },",
"The text shown in the source editor is incorrect.");
is(aEditor.getMode(), Editor.modes.js,
"The mode active in the source editor is incorrect.");
NetMonitorView.editor("#response-content-textarea").then((aEditor) => {
is(aEditor.getText(), "{ \"greeting\": \"Hello malformed JSON!\" },",
"The text shown in the source editor is incorrect.");
is(aEditor.getMode(), Editor.modes.js,
"The mode active in the source editor is incorrect.");
teardown(aMonitor).then(finish);
teardown(aMonitor).then(finish);
});
});
});

Просмотреть файл

@ -30,8 +30,11 @@ function test() {
EventUtils.sendMouseEvent({ type: "mousedown" },
document.querySelectorAll("#details-pane tab")[3]);
testResponseTab();
teardown(aMonitor).then(finish);
let RESPONSE_BODY_DISPLAYED = aMonitor.panelWin.EVENTS.RESPONSE_BODY_DISPLAYED;
waitFor(aMonitor.panelWin, RESPONSE_BODY_DISPLAYED)
.then(testResponseTab)
.then(() => teardown(aMonitor))
.then(finish);
function testResponseTab() {
let tab = document.querySelectorAll("#details-pane tab")[3];

Просмотреть файл

@ -30,8 +30,11 @@ function test() {
EventUtils.sendMouseEvent({ type: "mousedown" },
document.querySelectorAll("#details-pane tab")[3]);
testResponseTab();
teardown(aMonitor).then(finish);
let RESPONSE_BODY_DISPLAYED = aMonitor.panelWin.EVENTS.RESPONSE_BODY_DISPLAYED;
waitFor(aMonitor.panelWin, RESPONSE_BODY_DISPLAYED)
.then(testResponseTab)
.then(() => teardown(aMonitor))
.then(finish);
function testResponseTab() {
let tab = document.querySelectorAll("#details-pane tab")[3];

Просмотреть файл

@ -40,14 +40,14 @@ function test() {
EventUtils.sendMouseEvent({ type: "mousedown" },
document.querySelectorAll("#details-pane tab")[2]);
testParamsTab("urlencoded")
.then(() => {
RequestsMenu.selectedIndex = 1;
return testParamsTab("multipart");
})
.then(() => {
return teardown(aMonitor);
})
let TAB_UPDATED = aMonitor.panelWin.EVENTS.TAB_UPDATED;
waitFor(aMonitor.panelWin, TAB_UPDATED).then(() =>
testParamsTab("urlencoded")
).then(() => {
RequestsMenu.selectedIndex = 1;
return waitFor(aMonitor.panelWin, TAB_UPDATED);
}).then(() => testParamsTab("multipart"))
.then(() => teardown(aMonitor))
.then(finish);
function testParamsTab(aType) {

Просмотреть файл

@ -20,41 +20,43 @@ function test() {
NetMonitorView.toggleDetailsPane({ visible: true }, 2)
RequestsMenu.selectedIndex = 0;
let tab = document.querySelectorAll("#event-details-pane tab")[2];
let tabpanel = document.querySelectorAll("#event-details-pane tabpanel")[2];
let TAB_UPDATED = aMonitor.panelWin.EVENTS.TAB_UPDATED;
waitFor(aMonitor.panelWin, TAB_UPDATED).then(() => {
let tab = document.querySelectorAll("#event-details-pane tab")[2];
let tabpanel = document.querySelectorAll("#event-details-pane tabpanel")[2];
is(tab.getAttribute("selected"), "true",
"The params tab in the network details pane should be selected.");
is(tab.getAttribute("selected"), "true",
"The params tab in the network details pane should be selected.");
is(tabpanel.querySelector("#request-params-box")
.hasAttribute("hidden"), false,
"The request params box doesn't have the indended visibility.");
is(tabpanel.querySelector("#request-post-data-textarea-box")
.hasAttribute("hidden"), true,
"The request post data textarea box doesn't have the indended visibility.");
is(tabpanel.querySelector("#request-params-box")
.hasAttribute("hidden"), false,
"The request params box doesn't have the indended visibility.");
is(tabpanel.querySelector("#request-post-data-textarea-box")
.hasAttribute("hidden"), true,
"The request post data textarea box doesn't have the indended visibility.");
is(tabpanel.querySelectorAll(".variables-view-scope").length, 1,
"There should be 1 param scopes displayed in this tabpanel.");
is(tabpanel.querySelectorAll(".variables-view-empty-notice").length, 0,
"The empty notice should not be displayed in this tabpanel.");
is(tabpanel.querySelectorAll(".variables-view-scope").length, 1,
"There should be 1 param scopes displayed in this tabpanel.");
is(tabpanel.querySelectorAll(".variables-view-empty-notice").length, 0,
"The empty notice should not be displayed in this tabpanel.");
let postScope = tabpanel.querySelectorAll(".variables-view-scope")[0];
is(postScope.querySelector(".name").getAttribute("value"),
L10N.getStr("paramsFormData"),
"The post scope doesn't have the correct title.");
let postScope = tabpanel.querySelectorAll(".variables-view-scope")[0];
is(postScope.querySelector(".name").getAttribute("value"),
L10N.getStr("paramsFormData"),
"The post scope doesn't have the correct title.");
is(postScope.querySelectorAll(".variables-view-variable").length, 2,
"There should be 2 param values displayed in the post scope.");
is(postScope.querySelectorAll(".variables-view-variable .name")[0].getAttribute("value"),
"foo", "The first query param name was incorrect.");
is(postScope.querySelectorAll(".variables-view-variable .value")[0].getAttribute("value"),
"\"bar\"", "The first query param value was incorrect.");
is(postScope.querySelectorAll(".variables-view-variable .name")[1].getAttribute("value"),
"baz", "The second query param name was incorrect.");
is(postScope.querySelectorAll(".variables-view-variable .value")[1].getAttribute("value"),
"\"123\"", "The second query param value was incorrect.");
teardown(aMonitor).then(finish);
is(postScope.querySelectorAll(".variables-view-variable").length, 2,
"There should be 2 param values displayed in the post scope.");
is(postScope.querySelectorAll(".variables-view-variable .name")[0].getAttribute("value"),
"foo", "The first query param name was incorrect.");
is(postScope.querySelectorAll(".variables-view-variable .value")[0].getAttribute("value"),
"\"bar\"", "The first query param value was incorrect.");
is(postScope.querySelectorAll(".variables-view-variable .name")[1].getAttribute("value"),
"baz", "The second query param name was incorrect.");
is(postScope.querySelectorAll(".variables-view-variable .value")[1].getAttribute("value"),
"\"123\"", "The second query param value was incorrect.");
teardown(aMonitor).then(finish);
});
});
aDebuggee.performRequests();

Просмотреть файл

@ -21,6 +21,8 @@ function test() {
let { NetMonitorView } = gPanelWin;
let { RequestsMenu } = NetMonitorView;
let TAB_UPDATED = aMonitor.panelWin.EVENTS.TAB_UPDATED;
let CUSTOMREQUESTVIEW_POPULATED = aMonitor.panelWin.EVENTS.CUSTOMREQUESTVIEW_POPULATED;
RequestsMenu.lazyUpdate = false;
@ -28,24 +30,28 @@ function test() {
let origItem = RequestsMenu.getItemAtIndex(0);
RequestsMenu.selectedItem = origItem;
// add a new custom request cloned from selected request
RequestsMenu.cloneSelectedRequest();
testCustomForm(origItem.attachment);
waitFor(aMonitor.panelWin, TAB_UPDATED).then(() => {
// add a new custom request cloned from selected request
RequestsMenu.cloneSelectedRequest();
return waitFor(aMonitor.panelWin, CUSTOMREQUESTVIEW_POPULATED);
}).then(() => {
testCustomForm(origItem.attachment);
let customItem = RequestsMenu.selectedItem;
testCustomItem(customItem, origItem);
let customItem = RequestsMenu.selectedItem;
testCustomItem(customItem, origItem);
// edit the custom request
editCustomForm(() => {
testCustomItemChanged(customItem, origItem);
// edit the custom request
editCustomForm(() => {
testCustomItemChanged(customItem, origItem);
waitForNetworkEvents(aMonitor, 0, 1).then(() => {
let sentItem = RequestsMenu.selectedItem;
testSentRequest(sentItem.attachment, origItem.attachment);
finishUp(aMonitor);
waitForNetworkEvents(aMonitor, 0, 1).then(() => {
let sentItem = RequestsMenu.selectedItem;
testSentRequest(sentItem.attachment, origItem.attachment);
finishUp(aMonitor);
});
// send the new request
RequestsMenu.sendCustomRequest();
});
// send the new request
RequestsMenu.sendCustomRequest();
});
});

Просмотреть файл

@ -11,10 +11,11 @@ function test() {
let { document, L10N, Editor, NetMonitorView } = aMonitor.panelWin;
let { RequestsMenu, NetworkDetails } = NetMonitorView;
let TAB_UPDATED = aMonitor.panelWin.EVENTS.TAB_UPDATED;
RequestsMenu.lazyUpdate = false;
waitForNetworkEvents(aMonitor, 1).then(() => {
Task.spawn(function () {
yield waitForNetworkEvents(aMonitor, 1);
is(RequestsMenu.selectedItem, null,
"There shouldn't be any selected item in the requests menu.");
is(RequestsMenu.itemCount, 1,
@ -32,15 +33,14 @@ function test() {
is(NetMonitorView.detailsPaneHidden, false,
"The details pane should not be hidden after toggle button was pressed.");
yield waitFor(aMonitor.panelWin, TAB_UPDATED)
testHeadersTab();
testCookiesTab();
testParamsTab();
testResponseTab()
.then(() => {
testTimingsTab();
return teardown(aMonitor);
})
.then(finish);
yield testResponseTab();
testTimingsTab();
yield teardown(aMonitor);
finish();
});
function testHeadersTab() {
@ -172,26 +172,29 @@ function test() {
EventUtils.sendMouseEvent({ type: "mousedown" },
document.querySelectorAll("#details-pane tab")[3]);
let tab = document.querySelectorAll("#details-pane tab")[3];
let tabpanel = document.querySelectorAll("#details-pane tabpanel")[3];
return Task.spawn(function () {
yield waitFor(aMonitor.panelWin, TAB_UPDATED);
is(tab.getAttribute("selected"), "true",
"The response tab in the network details pane should be selected.");
let tab = document.querySelectorAll("#details-pane tab")[3];
let tabpanel = document.querySelectorAll("#details-pane tabpanel")[3];
is(tabpanel.querySelector("#response-content-info-header")
.hasAttribute("hidden"), true,
"The response info header should be hidden.");
is(tabpanel.querySelector("#response-content-json-box")
.hasAttribute("hidden"), true,
"The response content json box should be hidden.");
is(tabpanel.querySelector("#response-content-textarea-box")
.hasAttribute("hidden"), false,
"The response content textarea box should not be hidden.");
is(tabpanel.querySelector("#response-content-image-box")
.hasAttribute("hidden"), true,
"The response content image box should be hidden.");
is(tab.getAttribute("selected"), "true",
"The response tab in the network details pane should be selected.");
return NetMonitorView.editor("#response-content-textarea").then((aEditor) => {
is(tabpanel.querySelector("#response-content-info-header")
.hasAttribute("hidden"), true,
"The response info header should be hidden.");
is(tabpanel.querySelector("#response-content-json-box")
.hasAttribute("hidden"), true,
"The response content json box should be hidden.");
is(tabpanel.querySelector("#response-content-textarea-box")
.hasAttribute("hidden"), false,
"The response content textarea box should not be hidden.");
is(tabpanel.querySelector("#response-content-image-box")
.hasAttribute("hidden"), true,
"The response content image box should be hidden.");
let aEditor = yield NetMonitorView.editor("#response-content-textarea");
is(aEditor.getText(), "Hello world!",
"The text shown in the source editor is incorrect.");
is(aEditor.getMode(), Editor.modes.text,

Просмотреть файл

@ -5,7 +5,8 @@
const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
let { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
let { Promise: promise } = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {});
let { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
let { Promise: promise } = Cu.import("resource://gre/modules/Promise.jsm", {});
let { gDevTools } = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
let { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
let TargetFactory = devtools.TargetFactory;
@ -282,3 +283,20 @@ function verifyRequestItemTarget(aRequestItem, aMethod, aUrl, aData = {}) {
}
}
}
/**
* Helper function for waiting for an event to fire before resolving a promise.
* Example: waitFor(aMonitor.panelWin, aMonitor.panelWin.EVENTS.TAB_UPDATED);
*
* @param object subject
* The event emitter object that is being listened to.
* @param string eventName
* The name of the event to listen to.
* @return object
* Returns a promise that resolves upon firing of the event.
*/
function waitFor (subject, eventName) {
let deferred = promise.defer();
subject.once(eventName, deferred.resolve);
return deferred.promise;
}