/* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ "use strict"; /** * Test search match functionality. * Search panel is visible and clicking matches shows them in the request details. */ const { PluralForm } = require("resource://devtools/shared/plural-form.js"); add_task(async function () { const { tab, monitor } = await initNetMonitor(HTTPS_CUSTOM_GET_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)); const SEARCH_STRING = "test"; // Execute two XHRs and wait until they are finished. const URLS = [ HTTPS_SEARCH_SJS + "?value=test1", HTTPS_SEARCH_SJS + "?value=test2", ]; const wait = waitForNetworkEvents(monitor, 2); await SpecialPowers.spawn(tab.linkedBrowser, [URLS], makeRequests); await wait; // Open the Search panel await store.dispatch(Actions.openSearch()); // Fill Filter input with text and check displayed messages. // The filter should be focused automatically. typeInNetmonitor(SEARCH_STRING, monitor); EventUtils.synthesizeKey("KEY_Enter"); // Wait until there are two resources rendered in the results await waitForDOMIfNeeded( document, ".search-panel-content .treeRow.resourceRow", 2 ); const searchMatchContents = document.querySelectorAll( ".search-panel-content .treeRow .treeIcon" ); for (let i = searchMatchContents.length - 1; i >= 0; i--) { clickElement(searchMatchContents[i], monitor); } // Wait until there are two resources rendered in the results await waitForDOMIfNeeded( document, ".search-panel-content .treeRow.resultRow", 12 ); // Check the matches const matches = document.querySelectorAll( ".search-panel-content .treeRow.resultRow" ); await checkSearchResult( monitor, matches[0], "#headers-panel", ".url-preview .properties-view", ".treeRow", [SEARCH_STRING] ); await checkSearchResult( monitor, matches[1], "#headers-panel", "#responseHeaders .properties-view", ".treeRow.selected", [SEARCH_STRING] ); await checkSearchResult( monitor, matches[2], "#headers-panel", "#requestHeaders .properties-view", ".treeRow.selected", [SEARCH_STRING] ); await checkSearchResult( monitor, matches[3], "#cookies-panel", "#responseCookies .properties-view", ".treeRow.selected", [SEARCH_STRING] ); await checkSearchResult( monitor, matches[4], "#response-panel", ".cm-content", ".cm-line", [SEARCH_STRING] ); await checkSearchResult( monitor, matches[5], "#headers-panel", ".url-preview .properties-view", ".treeRow", [SEARCH_STRING] ); await checkSearchResult( monitor, matches[6], "#headers-panel", "#responseHeaders .properties-view", ".treeRow.selected", [SEARCH_STRING] ); await checkSearchResult( monitor, matches[7], "#headers-panel", "#requestHeaders .properties-view", ".treeRow.selected", [SEARCH_STRING] ); await checkSearchResult( monitor, matches[8], "#headers-panel", "#requestHeaders .properties-view", ".treeRow.selected", [SEARCH_STRING] ); await checkSearchResult( monitor, matches[9], "#cookies-panel", "#responseCookies .properties-view", ".treeRow.selected", [SEARCH_STRING] ); await checkSearchResult( monitor, matches[10], "#cookies-panel", "#requestCookies .properties-view", ".treeRow.selected", [SEARCH_STRING] ); await checkSearchResult( monitor, matches[11], "#response-panel", ".cm-content", ".cm-line", [SEARCH_STRING] ); await teardown(monitor); }); /** * Test the context menu feature inside the search match functionality. * Search panel is visible and right-clicking matches shows the appropriate context-menu's. */ add_task(async function () { const { tab, monitor } = await initNetMonitor(HTTPS_CUSTOM_GET_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)); const SEARCH_STRING = "matchingResult"; const matchingUrls = [ HTTPS_SEARCH_SJS + "?value=matchingResult1", HTTPS_SEARCH_SJS + "?value=matchingResult2", ]; const nonMatchingUrls = [HTTPS_SEARCH_SJS + "?value=somethingDifferent"]; const wait = waitForNetworkEvents( monitor, matchingUrls.length + nonMatchingUrls.length ); await SpecialPowers.spawn(tab.linkedBrowser, [matchingUrls], makeRequests); await SpecialPowers.spawn(tab.linkedBrowser, [nonMatchingUrls], makeRequests); await wait; // Open the Search panel await store.dispatch(Actions.openSearch()); // Fill Filter input with text and check displayed messages. // The filter should be focused automatically. typeInNetmonitor(SEARCH_STRING, monitor); EventUtils.synthesizeKey("KEY_Enter"); // Wait for all the updates to complete await waitForAllNetworkUpdateEvents(); // Wait until there are two resources rendered in the results await waitForDOMIfNeeded( document, ".search-panel-content .treeRow.resourceRow", 2 ); const resourceMatches = document.querySelectorAll( ".search-panel-content .treeRow .treeIcon" ); // open content matches for first resource: const firstResourceMatch = resourceMatches[0]; clickElement(firstResourceMatch, monitor); // Wait until the expanded resource is rendered in the results await waitForDOMIfNeeded( document, ".search-panel-content .treeRow.resultRow", 1 ); // Check the content matches const contentMatches = document.querySelectorAll( ".search-panel-content .treeRow.resultRow" ); // test context menu entries for contained content: const firstContentMatch = contentMatches[0]; ok( document.querySelector(".treeRow.selected.opened"), "The previous line, which is the selected line, is expanded to show the result row" ); await checkContentMenuCopy(firstContentMatch, matchingUrls[0], monitor); // test the context menu entries for resources const secondResourceMatch = resourceMatches[1]; await checkResourceMenuCopyUrl(secondResourceMatch, matchingUrls[1], monitor); // checkResourceMenuResend will trigger a new request, which will be added to the search results await checkResourceMenuResend(secondResourceMatch, monitor); // Assert that the previously expanded search result is kept expanded when a new request is added ok( document.querySelector(".treeRow.selected.opened"), "The previous line is still expanded after having added a new request is the result list" ); await checkResourceMenuBlockUnblock( secondResourceMatch, matchingUrls[1], monitor ); await checkSaveAllAsHARWithContextMenu( secondResourceMatch, matchingUrls, monitor ); // reload tab const waitForEvents = waitForNetworkEvents(monitor, 1); tab.linkedBrowser.reload(); await waitForEvents; // test that the context menu entries are not available anymore: await checkResourceMenuNotAvailbale(secondResourceMatch, monitor); await teardown(monitor); }); add_task(async function searchWithRequestOnUnload() { const { tab, monitor } = await initNetMonitor(HTTPS_CUSTOM_GET_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 SpecialPowers.spawn( tab.linkedBrowser, [HTTPS_SEARCH_SJS + "?value=test1"], function (url) { content.addEventListener("unload", () => { content.wrappedJSObject.get(url); }); } ); const SEARCH_STRING = "html_custom-get-page.html"; // reload tab, expect the html page and the unload request const waitForEvents = waitForNetworkEvents(monitor, 2); tab.linkedBrowser.reload(); await waitForEvents; // Open the Search panel await store.dispatch(Actions.openSearch()); // Fill Filter input with text and check displayed messages. // The filter should be focused automatically. typeInNetmonitor(SEARCH_STRING, monitor); EventUtils.synthesizeKey("KEY_Enter"); // Wait until there are two resources rendered in the results await waitForDOMIfNeeded( document, ".search-panel-content .treeRow.resourceRow", 1 ); // Wait until there are two resources rendered in the results await waitForDOMIfNeeded(document, ".search-panel .status-bar-label"); const statusBar = document.querySelector(".search-panel .status-bar-label"); const matchingLines = PluralForm.get( 1, L10N.getStr("netmonitor.search.status.labels.matchingLines") ).replace("#1", 1); const matchingFiles = PluralForm.get( 1, L10N.getStr("netmonitor.search.status.labels.fileCount") ).replace("#1", 1); is( statusBar.textContent, L10N.getFormatStr( "netmonitor.search.status.labels.done", matchingLines, matchingFiles ), "Search completed" ); await teardown(monitor); }); // Asserts that the content is scrolled to show the correct matched content // on the line when a match is selected from the network search list. add_task(async function testContentIsScrolledWhenMatchIsSelected() { const httpServer = createTestHTTPServer(); httpServer.registerPathHandler(`/`, function (request, response) { response.setStatusLine(request.httpVersion, 200, "OK"); response.write(`