394 lines
12 KiB
JavaScript
394 lines
12 KiB
JavaScript
/* Any copyright is dedicated to the Public Domain.
|
|
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
|
|
"use strict";
|
|
|
|
/**
|
|
* Tests if resending a request works.
|
|
*/
|
|
|
|
add_task(async function () {
|
|
if (
|
|
Services.prefs.getBoolPref(
|
|
"devtools.netmonitor.features.newEditAndResend",
|
|
true
|
|
)
|
|
) {
|
|
await testResendRequest();
|
|
} else {
|
|
await testOldEditAndResendPanel();
|
|
}
|
|
});
|
|
|
|
// This tests resending a request without editing using
|
|
// the resend context menu item. This particularly covering
|
|
// the new resend functionality.
|
|
async function testResendRequest() {
|
|
const { tab, monitor } = await initNetMonitor(POST_DATA_URL, {
|
|
requestCount: 1,
|
|
});
|
|
info("Starting test... ");
|
|
|
|
const { document, store, windowRequire } = monitor.panelWin;
|
|
|
|
// Action should be processed synchronously in tests.
|
|
const Actions = windowRequire("devtools/client/netmonitor/src/actions/index");
|
|
store.dispatch(Actions.batchEnable(false));
|
|
|
|
await performRequests(monitor, tab, 2);
|
|
|
|
is(
|
|
document.querySelectorAll(".request-list-item").length,
|
|
2,
|
|
"There are currently two requests"
|
|
);
|
|
|
|
const firstResend = await resendRequestAndWaitForNewRequest(
|
|
monitor,
|
|
document.querySelectorAll(".request-list-item")[0]
|
|
);
|
|
|
|
Assert.notStrictEqual(
|
|
firstResend.originalResource.resourceId,
|
|
firstResend.newResource.resourceId,
|
|
"The resent request is different resource from the first request"
|
|
);
|
|
|
|
is(
|
|
firstResend.originalResource.url,
|
|
firstResend.newResource.url,
|
|
"The resent request has the same url and query parameters and the first request"
|
|
);
|
|
|
|
// The priority header only appears when the urgency and incremental values
|
|
// are not both default values (u=3 and i=false). In this case the original
|
|
// request has no priority header and the resent request does, hence we subtract one.
|
|
is(
|
|
firstResend.originalResource.requestHeaders.headers.length,
|
|
firstResend.newResource.requestHeaders.headers.length - 1,
|
|
"The no of headers are the same"
|
|
);
|
|
|
|
// Because a resent request has a different purpose and principal it will
|
|
// also have a different CoS flag (meaning a different priority header).
|
|
// So we can't compare the original and resent request's priority and skip it.
|
|
firstResend.originalResource.requestHeaders.headers.forEach(
|
|
({ name, value }) => {
|
|
if (name === "Priority") {
|
|
return;
|
|
}
|
|
const foundHeader = firstResend.newResource.requestHeaders.headers.find(
|
|
header => header.name == name
|
|
);
|
|
is(
|
|
value,
|
|
foundHeader.value,
|
|
`The '${name}' header for the request and the resent request match`
|
|
);
|
|
}
|
|
);
|
|
|
|
info("Check that the custom headers and form data are resent correctly");
|
|
const secondResend = await resendRequestAndWaitForNewRequest(
|
|
monitor,
|
|
document.querySelectorAll(".request-list-item")[1]
|
|
);
|
|
|
|
Assert.notStrictEqual(
|
|
secondResend.originalResource.resourceId,
|
|
secondResend.newResource.resourceId,
|
|
"The resent request is different resource from the second request"
|
|
);
|
|
|
|
const customHeader =
|
|
secondResend.originalResource.requestHeaders.headers.find(
|
|
header => header.name == "custom-header-xxx"
|
|
);
|
|
|
|
const customHeaderInResentRequest =
|
|
secondResend.newResource.requestHeaders.headers.find(
|
|
header => header.name == "custom-header-xxx"
|
|
);
|
|
|
|
is(
|
|
customHeader.value,
|
|
customHeaderInResentRequest.value,
|
|
"The custom header in the resent request is the same as the second request"
|
|
);
|
|
|
|
is(
|
|
customHeaderInResentRequest.value,
|
|
"custom-value-xxx",
|
|
"The custom header in the resent request is correct"
|
|
);
|
|
|
|
is(
|
|
secondResend.originalResource.requestPostData.postData.text,
|
|
secondResend.newResource.requestPostData.postData.text,
|
|
"The form data in the resent is the same as the second request"
|
|
);
|
|
}
|
|
|
|
async function resendRequestAndWaitForNewRequest(monitor, originalRequestItem) {
|
|
const { document, store, windowRequire, connector } = monitor.panelWin;
|
|
const { getSelectedRequest, getDisplayedRequests } = windowRequire(
|
|
"devtools/client/netmonitor/src/selectors/index"
|
|
);
|
|
|
|
info("Select the request to resend");
|
|
const expectedNoOfRequestsAfterResend =
|
|
getDisplayedRequests(store.getState()).length + 1;
|
|
|
|
const waitForHeaders = waitUntil(() =>
|
|
document.querySelector(".headers-overview")
|
|
);
|
|
EventUtils.sendMouseEvent({ type: "mousedown" }, originalRequestItem);
|
|
await waitForHeaders;
|
|
|
|
const originalResourceId = getSelectedRequest(store.getState()).id;
|
|
|
|
const waitForNewRequest = waitUntil(
|
|
() =>
|
|
getDisplayedRequests(store.getState()).length ==
|
|
expectedNoOfRequestsAfterResend &&
|
|
getSelectedRequest(store.getState()).id !== originalResourceId
|
|
);
|
|
|
|
info("Open the context menu and select the resend for the request");
|
|
EventUtils.sendMouseEvent({ type: "contextmenu" }, originalRequestItem);
|
|
await selectContextMenuItem(monitor, "request-list-context-resend-only");
|
|
await waitForNewRequest;
|
|
|
|
const newResourceId = getSelectedRequest(store.getState()).id;
|
|
|
|
// Make sure we fetch the request headers and post data for the
|
|
// new request so we can assert them.
|
|
await connector.requestData(newResourceId, "requestHeaders");
|
|
await connector.requestData(newResourceId, "requestPostData");
|
|
|
|
return {
|
|
originalResource: getRequestById(store.getState(), originalResourceId),
|
|
newResource: getRequestById(store.getState(), newResourceId),
|
|
};
|
|
}
|
|
|
|
// This is a basic test for the old edit and resend panel
|
|
// This should be removed soon in Bug 1745416 when we remove
|
|
// the old panel functionality.
|
|
async function testOldEditAndResendPanel() {
|
|
const ADD_QUERY = "t1=t2";
|
|
const ADD_HEADER = "Test-header: true";
|
|
const ADD_UA_HEADER = "User-Agent: Custom-Agent";
|
|
const ADD_POSTDATA = "&t3=t4";
|
|
|
|
const { tab, monitor } = await initNetMonitor(POST_DATA_URL, {
|
|
requestCount: 1,
|
|
});
|
|
info("Starting test... ");
|
|
|
|
const { document, store, windowRequire } = monitor.panelWin;
|
|
const Actions = windowRequire("devtools/client/netmonitor/src/actions/index");
|
|
const { getSelectedRequest, getSortedRequests } = windowRequire(
|
|
"devtools/client/netmonitor/src/selectors/index"
|
|
);
|
|
|
|
store.dispatch(Actions.batchEnable(false));
|
|
|
|
// Execute requests.
|
|
await performRequests(monitor, tab, 2);
|
|
|
|
const origItemId = getSortedRequests(store.getState())[0].id;
|
|
|
|
store.dispatch(Actions.selectRequest(origItemId));
|
|
await waitForRequestData(
|
|
store,
|
|
["requestHeaders", "requestPostData"],
|
|
origItemId
|
|
);
|
|
|
|
let origItem = getSortedRequests(store.getState())[0];
|
|
|
|
// add a new custom request cloned from selected request
|
|
|
|
store.dispatch(Actions.cloneSelectedRequest());
|
|
await testCustomForm(origItem);
|
|
|
|
let customItem = getSelectedRequest(store.getState());
|
|
testCustomItem(customItem, origItem);
|
|
|
|
// edit the custom request
|
|
await editCustomForm();
|
|
|
|
// FIXME: reread the customItem, it's been replaced by a new object (immutable!)
|
|
customItem = getSelectedRequest(store.getState());
|
|
testCustomItemChanged(customItem, origItem);
|
|
|
|
// send the new request
|
|
const wait = waitForNetworkEvents(monitor, 1);
|
|
store.dispatch(Actions.sendCustomRequest());
|
|
await wait;
|
|
|
|
let sentItem;
|
|
// Testing sent request will require updated requestHeaders and requestPostData,
|
|
// we must wait for both properties get updated before starting test.
|
|
await waitUntil(() => {
|
|
sentItem = getSelectedRequest(store.getState());
|
|
origItem = getSortedRequests(store.getState())[0];
|
|
return (
|
|
sentItem &&
|
|
sentItem.requestHeaders &&
|
|
sentItem.requestPostData &&
|
|
origItem &&
|
|
origItem.requestHeaders &&
|
|
origItem.requestPostData
|
|
);
|
|
});
|
|
|
|
await testSentRequest(sentItem, origItem);
|
|
|
|
// Ensure the UI shows the new request, selected, and that the detail panel was closed.
|
|
is(
|
|
getSortedRequests(store.getState()).length,
|
|
3,
|
|
"There are 3 requests shown"
|
|
);
|
|
is(
|
|
document
|
|
.querySelector(".request-list-item.selected")
|
|
.getAttribute("data-id"),
|
|
sentItem.id,
|
|
"The sent request is selected"
|
|
);
|
|
is(
|
|
document.querySelector(".network-details-bar"),
|
|
null,
|
|
"The detail panel is hidden"
|
|
);
|
|
|
|
await teardown(monitor);
|
|
|
|
function testCustomItem(item, orig) {
|
|
is(
|
|
item.method,
|
|
orig.method,
|
|
"item is showing the same method as original request"
|
|
);
|
|
is(item.url, orig.url, "item is showing the same URL as original request");
|
|
}
|
|
|
|
function testCustomItemChanged(item, orig) {
|
|
const { url } = item;
|
|
const expectedUrl = orig.url + "&" + ADD_QUERY;
|
|
|
|
is(url, expectedUrl, "menu item is updated to reflect url entered in form");
|
|
}
|
|
|
|
/*
|
|
* Test that the New Request form was populated correctly
|
|
*/
|
|
async function testCustomForm(data) {
|
|
await waitUntil(() => document.querySelector(".custom-request-panel"));
|
|
is(
|
|
document.getElementById("custom-method-value").value,
|
|
data.method,
|
|
"new request form showing correct method"
|
|
);
|
|
|
|
is(
|
|
document.getElementById("custom-url-value").value,
|
|
data.url,
|
|
"new request form showing correct url"
|
|
);
|
|
|
|
const query = document.getElementById("custom-query-value");
|
|
is(
|
|
query.value,
|
|
"foo=bar\nbaz=42\ntype=urlencoded",
|
|
"new request form showing correct query string"
|
|
);
|
|
|
|
const headers = document
|
|
.getElementById("custom-headers-value")
|
|
.value.split("\n");
|
|
for (const { name, value } of data.requestHeaders.headers) {
|
|
ok(
|
|
headers.includes(name + ": " + value),
|
|
"form contains header from request"
|
|
);
|
|
}
|
|
|
|
const postData = document.getElementById("custom-postdata-value");
|
|
is(
|
|
postData.value,
|
|
data.requestPostData.postData.text,
|
|
"new request form showing correct post data"
|
|
);
|
|
}
|
|
|
|
/*
|
|
* Add some params and headers to the request form
|
|
*/
|
|
async function editCustomForm() {
|
|
monitor.panelWin.focus();
|
|
|
|
const query = document.getElementById("custom-query-value");
|
|
const queryFocus = once(query, "focus", false);
|
|
// Bug 1195825: Due to some unexplained dark-matter with promise,
|
|
// focus only works if delayed by one tick.
|
|
query.setSelectionRange(query.value.length, query.value.length);
|
|
executeSoon(() => query.focus());
|
|
await queryFocus;
|
|
|
|
// add params to url query string field
|
|
typeInNetmonitor(["VK_RETURN"], monitor);
|
|
typeInNetmonitor(ADD_QUERY, monitor);
|
|
|
|
const headers = document.getElementById("custom-headers-value");
|
|
const headersFocus = once(headers, "focus", false);
|
|
headers.setSelectionRange(headers.value.length, headers.value.length);
|
|
headers.focus();
|
|
await headersFocus;
|
|
|
|
// add a header
|
|
typeInNetmonitor(["VK_RETURN"], monitor);
|
|
typeInNetmonitor(ADD_HEADER, monitor);
|
|
|
|
// add a User-Agent header, to check if default headers can be modified
|
|
// (there will be two of them, first gets overwritten by the second)
|
|
typeInNetmonitor(["VK_RETURN"], monitor);
|
|
typeInNetmonitor(ADD_UA_HEADER, monitor);
|
|
|
|
const postData = document.getElementById("custom-postdata-value");
|
|
const postFocus = once(postData, "focus", false);
|
|
postData.setSelectionRange(postData.value.length, postData.value.length);
|
|
postData.focus();
|
|
await postFocus;
|
|
|
|
// add to POST data once textarea has updated
|
|
await waitUntil(() => postData.textContent !== "");
|
|
typeInNetmonitor(ADD_POSTDATA, monitor);
|
|
}
|
|
|
|
/*
|
|
* Make sure newly created event matches expected request
|
|
*/
|
|
async function testSentRequest(data, origData) {
|
|
is(data.method, origData.method, "correct method in sent request");
|
|
is(data.url, origData.url + "&" + ADD_QUERY, "correct url in sent request");
|
|
|
|
const { headers } = data.requestHeaders;
|
|
const hasHeader = headers.some(h => `${h.name}: ${h.value}` == ADD_HEADER);
|
|
ok(hasHeader, "new header added to sent request");
|
|
|
|
const hasUAHeader = headers.some(
|
|
h => `${h.name}: ${h.value}` == ADD_UA_HEADER
|
|
);
|
|
ok(hasUAHeader, "User-Agent header added to sent request");
|
|
|
|
is(
|
|
data.requestPostData.postData.text,
|
|
origData.requestPostData.postData.text + ADD_POSTDATA,
|
|
"post data added to sent request"
|
|
);
|
|
}
|
|
}
|