1 /* Any copyright is dedicated to the Public Domain.
2 * http://creativecommons.org/publicdomain/zero/1.0/ */
7 * Tests if resending a request works.
10 add_task(async
function () {
12 Services
.prefs
.getBoolPref(
13 "devtools.netmonitor.features.newEditAndResend",
17 await
testResendRequest();
19 await
testOldEditAndResendPanel();
23 // This tests resending a request without editing using
24 // the resend context menu item. This particularly covering
25 // the new resend functionality.
26 async
function testResendRequest() {
27 const { tab
, monitor
} = await
initNetMonitor(POST_DATA_URL
, {
30 info("Starting test... ");
32 const { document
, store
, windowRequire
} = monitor
.panelWin
;
34 // Action should be processed synchronously in tests.
35 const Actions
= windowRequire("devtools/client/netmonitor/src/actions/index");
36 store
.dispatch(Actions
.batchEnable(false));
38 await
performRequests(monitor
, tab
, 2);
41 document
.querySelectorAll(".request-list-item").length
,
43 "There are currently two requests"
46 const firstResend
= await
resendRequestAndWaitForNewRequest(
48 document
.querySelectorAll(".request-list-item")[0]
51 Assert
.notStrictEqual(
52 firstResend
.originalResource
.resourceId
,
53 firstResend
.newResource
.resourceId
,
54 "The resent request is different resource from the first request"
58 firstResend
.originalResource
.url
,
59 firstResend
.newResource
.url
,
60 "The resent request has the same url and query parameters and the first request"
63 // The priority header only appears when the urgency and incremental values
64 // are not both default values (u=3 and i=false). In this case the original
65 // request has no priority header and the resent request does, hence we subtract one.
67 firstResend
.originalResource
.requestHeaders
.headers
.length
,
68 firstResend
.newResource
.requestHeaders
.headers
.length
- 1,
69 "The no of headers are the same"
72 // Because a resent request has a different purpose and principal it will
73 // also have a different CoS flag (meaning a different priority header).
74 // So we can't compare the original and resent request's priority and skip it.
75 firstResend
.originalResource
.requestHeaders
.headers
.forEach(
76 ({ name
, value
}) => {
77 if (name
=== "Priority") {
80 const foundHeader
= firstResend
.newResource
.requestHeaders
.headers
.find(
81 header
=> header
.name
== name
86 `The '${name}' header for the request and the resent request match`
91 info("Check that the custom headers and form data are resent correctly");
92 const secondResend
= await
resendRequestAndWaitForNewRequest(
94 document
.querySelectorAll(".request-list-item")[1]
97 Assert
.notStrictEqual(
98 secondResend
.originalResource
.resourceId
,
99 secondResend
.newResource
.resourceId
,
100 "The resent request is different resource from the second request"
104 secondResend
.originalResource
.requestHeaders
.headers
.find(
105 header
=> header
.name
== "custom-header-xxx"
108 const customHeaderInResentRequest
=
109 secondResend
.newResource
.requestHeaders
.headers
.find(
110 header
=> header
.name
== "custom-header-xxx"
115 customHeaderInResentRequest
.value
,
116 "The custom header in the resent request is the same as the second request"
120 customHeaderInResentRequest
.value
,
122 "The custom header in the resent request is correct"
126 secondResend
.originalResource
.requestPostData
.postData
.text
,
127 secondResend
.newResource
.requestPostData
.postData
.text
,
128 "The form data in the resent is the same as the second request"
132 async
function resendRequestAndWaitForNewRequest(monitor
, originalRequestItem
) {
133 const { document
, store
, windowRequire
, connector
} = monitor
.panelWin
;
134 const { getSelectedRequest
, getDisplayedRequests
} = windowRequire(
135 "devtools/client/netmonitor/src/selectors/index"
138 info("Select the request to resend");
139 const expectedNoOfRequestsAfterResend
=
140 getDisplayedRequests(store
.getState()).length
+ 1;
142 const waitForHeaders
= waitUntil(() =>
143 document
.querySelector(".headers-overview")
145 EventUtils
.sendMouseEvent({ type
: "mousedown" }, originalRequestItem
);
146 await waitForHeaders
;
148 const originalResourceId
= getSelectedRequest(store
.getState()).id
;
150 const waitForNewRequest
= waitUntil(
152 getDisplayedRequests(store
.getState()).length
==
153 expectedNoOfRequestsAfterResend
&&
154 getSelectedRequest(store
.getState()).id
!== originalResourceId
157 info("Open the context menu and select the resend for the request");
158 EventUtils
.sendMouseEvent({ type
: "contextmenu" }, originalRequestItem
);
159 await
selectContextMenuItem(monitor
, "request-list-context-resend-only");
160 await waitForNewRequest
;
162 const newResourceId
= getSelectedRequest(store
.getState()).id
;
164 // Make sure we fetch the request headers and post data for the
165 // new request so we can assert them.
166 await connector
.requestData(newResourceId
, "requestHeaders");
167 await connector
.requestData(newResourceId
, "requestPostData");
170 originalResource
: getRequestById(store
.getState(), originalResourceId
),
171 newResource
: getRequestById(store
.getState(), newResourceId
),
175 // This is a basic test for the old edit and resend panel
176 // This should be removed soon in Bug 1745416 when we remove
177 // the old panel functionality.
178 async
function testOldEditAndResendPanel() {
179 const ADD_QUERY
= "t1=t2";
180 const ADD_HEADER
= "Test-header: true";
181 const ADD_UA_HEADER
= "User-Agent: Custom-Agent";
182 const ADD_POSTDATA
= "&t3=t4";
184 const { tab
, monitor
} = await
initNetMonitor(POST_DATA_URL
, {
187 info("Starting test... ");
189 const { document
, store
, windowRequire
} = monitor
.panelWin
;
190 const Actions
= windowRequire("devtools/client/netmonitor/src/actions/index");
191 const { getSelectedRequest
, getSortedRequests
} = windowRequire(
192 "devtools/client/netmonitor/src/selectors/index"
195 store
.dispatch(Actions
.batchEnable(false));
198 await
performRequests(monitor
, tab
, 2);
200 const origItemId
= getSortedRequests(store
.getState())[0].id
;
202 store
.dispatch(Actions
.selectRequest(origItemId
));
203 await
waitForRequestData(
205 ["requestHeaders", "requestPostData"],
209 let origItem
= getSortedRequests(store
.getState())[0];
211 // add a new custom request cloned from selected request
213 store
.dispatch(Actions
.cloneSelectedRequest());
214 await
testCustomForm(origItem
);
216 let customItem
= getSelectedRequest(store
.getState());
217 testCustomItem(customItem
, origItem
);
219 // edit the custom request
220 await
editCustomForm();
222 // FIXME: reread the customItem, it's been replaced by a new object (immutable!)
223 customItem
= getSelectedRequest(store
.getState());
224 testCustomItemChanged(customItem
, origItem
);
226 // send the new request
227 const wait
= waitForNetworkEvents(monitor
, 1);
228 store
.dispatch(Actions
.sendCustomRequest());
232 // Testing sent request will require updated requestHeaders and requestPostData,
233 // we must wait for both properties get updated before starting test.
234 await
waitUntil(() => {
235 sentItem
= getSelectedRequest(store
.getState());
236 origItem
= getSortedRequests(store
.getState())[0];
239 sentItem
.requestHeaders
&&
240 sentItem
.requestPostData
&&
242 origItem
.requestHeaders
&&
243 origItem
.requestPostData
247 await
testSentRequest(sentItem
, origItem
);
249 // Ensure the UI shows the new request, selected, and that the detail panel was closed.
251 getSortedRequests(store
.getState()).length
,
253 "There are 3 requests shown"
257 .querySelector(".request-list-item.selected")
258 .getAttribute("data-id"),
260 "The sent request is selected"
263 document
.querySelector(".network-details-bar"),
265 "The detail panel is hidden"
268 await
teardown(monitor
);
270 function testCustomItem(item
, orig
) {
274 "item is showing the same method as original request"
276 is(item
.url
, orig
.url
, "item is showing the same URL as original request");
279 function testCustomItemChanged(item
, orig
) {
280 const { url
} = item
;
281 const expectedUrl
= orig
.url
+ "&" + ADD_QUERY
;
283 is(url
, expectedUrl
, "menu item is updated to reflect url entered in form");
287 * Test that the New Request form was populated correctly
289 async
function testCustomForm(data
) {
290 await
waitUntil(() => document
.querySelector(".custom-request-panel"));
292 document
.getElementById("custom-method-value").value
,
294 "new request form showing correct method"
298 document
.getElementById("custom-url-value").value
,
300 "new request form showing correct url"
303 const query
= document
.getElementById("custom-query-value");
306 "foo=bar\nbaz=42\ntype=urlencoded",
307 "new request form showing correct query string"
310 const headers
= document
311 .getElementById("custom-headers-value")
313 for (const { name
, value
} of data
.requestHeaders
.headers
) {
315 headers
.includes(name
+ ": " + value
),
316 "form contains header from request"
320 const postData
= document
.getElementById("custom-postdata-value");
323 data
.requestPostData
.postData
.text
,
324 "new request form showing correct post data"
329 * Add some params and headers to the request form
331 async
function editCustomForm() {
332 monitor
.panelWin
.focus();
334 const query
= document
.getElementById("custom-query-value");
335 const queryFocus
= once(query
, "focus", false);
336 // Bug 1195825: Due to some unexplained dark-matter with promise,
337 // focus only works if delayed by one tick.
338 query
.setSelectionRange(query
.value
.length
, query
.value
.length
);
339 executeSoon(() => query
.focus());
342 // add params to url query string field
343 typeInNetmonitor(["VK_RETURN"], monitor
);
344 typeInNetmonitor(ADD_QUERY
, monitor
);
346 const headers
= document
.getElementById("custom-headers-value");
347 const headersFocus
= once(headers
, "focus", false);
348 headers
.setSelectionRange(headers
.value
.length
, headers
.value
.length
);
353 typeInNetmonitor(["VK_RETURN"], monitor
);
354 typeInNetmonitor(ADD_HEADER
, monitor
);
356 // add a User-Agent header, to check if default headers can be modified
357 // (there will be two of them, first gets overwritten by the second)
358 typeInNetmonitor(["VK_RETURN"], monitor
);
359 typeInNetmonitor(ADD_UA_HEADER
, monitor
);
361 const postData
= document
.getElementById("custom-postdata-value");
362 const postFocus
= once(postData
, "focus", false);
363 postData
.setSelectionRange(postData
.value
.length
, postData
.value
.length
);
367 // add to POST data once textarea has updated
368 await
waitUntil(() => postData
.textContent
!== "");
369 typeInNetmonitor(ADD_POSTDATA
, monitor
);
373 * Make sure newly created event matches expected request
375 async
function testSentRequest(data
, origData
) {
376 is(data
.method
, origData
.method
, "correct method in sent request");
377 is(data
.url
, origData
.url
+ "&" + ADD_QUERY
, "correct url in sent request");
379 const { headers
} = data
.requestHeaders
;
380 const hasHeader
= headers
.some(h
=> `${h.name}: ${h.value}` == ADD_HEADER
);
381 ok(hasHeader
, "new header added to sent request");
383 const hasUAHeader
= headers
.some(
384 h
=> `${h.name}: ${h.value}` == ADD_UA_HEADER
386 ok(hasUAHeader
, "User-Agent header added to sent request");
389 data
.requestPostData
.postData
.text
,
390 origData
.requestPostData
.postData
.text
+ ADD_POSTDATA
,
391 "post data added to sent request"