diff --git a/devtools/client/jar.mn b/devtools/client/jar.mn index 9c5279d53c15..e38cd0966b6d 100644 --- a/devtools/client/jar.mn +++ b/devtools/client/jar.mn @@ -404,7 +404,6 @@ devtools.jar: content/netmonitor/src/assets/styles/NetworkActionBar.css (netmonitor/src/assets/styles/NetworkActionBar.css) content/netmonitor/src/assets/styles/RequestBlockingPanel.css (netmonitor/src/assets/styles/RequestBlockingPanel.css) content/netmonitor/src/assets/styles/NetworkDetailsBar.css (netmonitor/src/assets/styles/NetworkDetailsBar.css) - content/netmonitor/src/assets/styles/ResponsePanel.css (netmonitor/src/assets/styles/ResponsePanel.css) content/netmonitor/src/assets/styles/CustomRequestPanel.css (netmonitor/src/assets/styles/CustomRequestPanel.css) content/netmonitor/src/assets/styles/RequestList.css (netmonitor/src/assets/styles/RequestList.css) content/netmonitor/src/assets/styles/StatisticsPanel.css (netmonitor/src/assets/styles/StatisticsPanel.css) diff --git a/devtools/client/locales/en-US/netmonitor.properties b/devtools/client/locales/en-US/netmonitor.properties index 084d4c885d7b..71599fc004cb 100644 --- a/devtools/client/locales/en-US/netmonitor.properties +++ b/devtools/client/locales/en-US/netmonitor.properties @@ -136,6 +136,15 @@ responseCookies=Response Cookies # in the network details response tab identifying the response payload. responsePayload=Response Payload +# LOCALIZATION NOTE (netmonitor.response.raw): This is the label displayed +# on the button in the network details response tab that toggles the +# view of the network response between the raw data and the formatted display. +netmonitor.response.raw=Raw + +# LOCALIZATION NOTE (netmonitor.response.html): This is the text displayed +# in the response tab of the network details pane for an HTML preview. +netmonitor.response.html=HTML + # LOCALIZATION NOTE (jsonFilterText): This is the text displayed # in the response tab of the network details pane for the JSON filtering input. jsonFilterText=Filter properties @@ -158,10 +167,6 @@ responseTruncated=Response has been truncated # the truncation limit and thus was truncated. requestTruncated=Request has been truncated -# LOCALIZATION NOTE (responsePreview): This is the text displayed -# in the response tab of the network details pane for an HTML preview. -responsePreview=Preview - # LOCALIZATION NOTE (networkMenu.raced): This is the label displayed # in the network menu specifying the transfer or a request is # raced. %S refers to the current transfer size. diff --git a/devtools/client/netmonitor/src/assets/styles/NetworkDetailsBar.css b/devtools/client/netmonitor/src/assets/styles/NetworkDetailsBar.css index d23a0e215c48..f2337163e572 100644 --- a/devtools/client/netmonitor/src/assets/styles/NetworkDetailsBar.css +++ b/devtools/client/netmonitor/src/assets/styles/NetworkDetailsBar.css @@ -28,6 +28,8 @@ display: flex; flex-direction: column; flex-grow: 1; + height: 100%; + overflow: auto; } .network-monitor .properties-view .searchbox-section { @@ -185,7 +187,7 @@ /* If there is a source editor shows up in the last row of TreeView, * it should occupy the available vertical space. */ -.network-monitor .accordion .editor-row-container, +.network-monitor .editor-row-container, .network-monitor .tree-container .treeTable tr:last-child td[colspan="2"] { display: block; height: 100%; @@ -193,7 +195,7 @@ overflow-x: auto; } -.network-monitor .accordion .responseTextContainer { +.network-monitor .responseTextContainer { overflow-x: auto; width: 100%; height: 100%; @@ -234,6 +236,8 @@ background-color: var(--red-70); } +/* Response tabpanel */ + .network-monitor .response-image-box { display: flex; flex-direction: column; @@ -281,6 +285,59 @@ min-height: 0; } +/* Request and response data */ + +.network-monitor #response-panel .panel-container { + overflow-y: hidden; +} + +.network-monitor .data-header { + background: var(--theme-toolbar-background); + border-bottom: 1px solid var(--theme-splitter-color); + color: var(--theme-toolbar-color); + font-size: inherit; + font-weight: normal; + line-height: 16px; + margin: 0; + padding: 2px 4px; + width: 100%; + align-items: center; + display: flex; + user-select: none; +} + +.network-monitor .data-label { + display: block; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + font-size: inherit; + line-height: 20px; + color: var(--theme-toolbar-color); +} + +.network-monitor .raw-data-toggle { + flex: none; + display: flex; + align-items: center; + justify-content: flex-end; + max-width: 50%; + margin-inline-start: auto; + padding-inline-start: 4px; +} + +.network-monitor .raw-data-toggle-label { + white-space: nowrap; + color: var(--theme-toolbar-color); +} + +.network-monitor .raw-data-toggle-input > input { + display: inline-block; + width: 2em; + vertical-align: bottom; + font-size: 12px; +} + /* Timings tabpanel */ .network-monitor .timings-container { diff --git a/devtools/client/netmonitor/src/assets/styles/ResponsePanel.css b/devtools/client/netmonitor/src/assets/styles/ResponsePanel.css deleted file mode 100644 index 7c7e16df80a1..000000000000 --- a/devtools/client/netmonitor/src/assets/styles/ResponsePanel.css +++ /dev/null @@ -1,37 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* Response tabpanel */ -/* Supports the single expand mode used for the accordion in the response panel */ -.network-monitor #response-panel .panel-container { - overflow-y: hidden; -} - -/* The following styles should not override/affect accordion styles defined in MessagesView */ -.network-monitor #response-panel .panel-container .accordion { - position: relative; - overflow: hidden; -} - -.network-monitor #response-panel .panel-container .accordion-item .accordion-content { - position: absolute; - top: calc(var(--theme-toolbar-height) + 1px); - bottom: 0; - left: 0; - right: 0; - overflow: hidden; -} - -.network-monitor #response-panel .panel-container .properties-view { - height: 100%; -} - -.network-monitor #response-panel .panel-container .accordion-item { - position: relative; - height: auto; -} - -.network-monitor #response-panel .panel-container .accordion-item.accordion-open { - height: 100%; -} diff --git a/devtools/client/netmonitor/src/assets/styles/messages.css b/devtools/client/netmonitor/src/assets/styles/messages.css index 35a8064fa916..d0d0666a6a3f 100644 --- a/devtools/client/netmonitor/src/assets/styles/messages.css +++ b/devtools/client/netmonitor/src/assets/styles/messages.css @@ -64,15 +64,18 @@ font-variant-numeric: tabular-nums; } -/* Styles related to the Accordion items in the MessagePayload component */ +/* Styles related to the data items in the MessagePayload component */ #messages-view .message-payload { width: 100%; + display: flex; + flex-direction: column; } #messages-view .message-rawData-payload { display: block; width: 100%; + height: 100%; overflow: auto; white-space: pre; padding: 4px 8px; diff --git a/devtools/client/netmonitor/src/assets/styles/netmonitor.css b/devtools/client/netmonitor/src/assets/styles/netmonitor.css index a0df7c89b233..b55ab796039c 100644 --- a/devtools/client/netmonitor/src/assets/styles/netmonitor.css +++ b/devtools/client/netmonitor/src/assets/styles/netmonitor.css @@ -21,7 +21,6 @@ @import "chrome://devtools/content/netmonitor/src/assets/styles/NetworkActionBar.css"; @import "chrome://devtools/content/netmonitor/src/assets/styles/RequestBlockingPanel.css"; @import "chrome://devtools/content/netmonitor/src/assets/styles/NetworkDetailsBar.css"; -@import "chrome://devtools/content/netmonitor/src/assets/styles/ResponsePanel.css"; @import "chrome://devtools/content/netmonitor/src/assets/styles/StatisticsPanel.css"; @import "chrome://devtools/content/netmonitor/src/assets/styles/CustomRequestPanel.css"; @import "chrome://devtools/content/netmonitor/src/assets/styles/StatusCode.css"; diff --git a/devtools/client/netmonitor/src/components/messages/MessagePayload.js b/devtools/client/netmonitor/src/components/messages/MessagePayload.js index 51c78060f183..f928d9947550 100644 --- a/devtools/client/netmonitor/src/components/messages/MessagePayload.js +++ b/devtools/client/netmonitor/src/components/messages/MessagePayload.js @@ -9,7 +9,7 @@ const { createFactory, } = require("devtools/client/shared/vendor/react"); const dom = require("devtools/client/shared/vendor/react-dom-factories"); -const { div } = dom; +const { div, input, label, span, h2 } = dom; const PropTypes = require("devtools/client/shared/vendor/react-prop-types"); const { @@ -49,9 +49,6 @@ const { } = require("devtools/client/netmonitor/src/selectors/index"); // Components -const Accordion = createFactory( - require("devtools/client/shared/components/Accordion") -); const RawData = createFactory( require("devtools/client/netmonitor/src/components/messages/RawData") ); @@ -61,6 +58,8 @@ loader.lazyGetter(this, "PropertiesView", function() { ); }); +const RAW_DATA = L10N.getStr("netmonitor.response.raw"); + /** * Shows the full payload of a message. * The payload is unwrapped from the LongStringActor object. @@ -82,7 +81,11 @@ class MessagePayload extends Component { isFormattedData: false, formattedData: {}, formattedDataTitle: "", + rawDataDisplayed: false, }; + + this.toggleRawData = this.toggleRawData.bind(this); + this.renderRawDataBtn = this.renderRawDataBtn.bind(this); } componentDidMount() { @@ -306,43 +309,71 @@ class MessagePayload extends Component { return payload; } + toggleRawData() { + this.setState({ + rawDataDisplayed: !this.state.rawDataDisplayed, + }); + } + + renderRawDataBtn(key, checked, onChange) { + return [ + label( + { + key: `${key}RawDataBtn`, + className: "raw-data-toggle", + htmlFor: `raw-${key}-checkbox`, + onClick: event => { + // stop the header click event + event.stopPropagation(); + }, + }, + span({ className: "raw-data-toggle-label" }, RAW_DATA), + span( + { className: "raw-data-toggle-input" }, + input({ + id: `raw-${key}-checkbox`, + checked, + className: "devtools-checkbox-toggle", + onChange, + type: "checkbox", + }) + ) + ), + ]; + } + + renderData(component, componentProps) { + return component(componentProps); + } + render() { - let { payload } = this.state; + let component; + let componentProps; + let dataLabel; + let { payload, rawDataDisplayed } = this.state; let isTruncated = false; if (this.state.payload.length >= MESSAGE_DATA_LIMIT) { payload = payload.substring(0, MESSAGE_DATA_LIMIT); isTruncated = true; } - const items = [ - { - className: "rawData", - component: RawData, - componentProps: { payload }, - header: L10N.getFormatStrWithNumbers( - "netmonitor.ws.rawData.header", - getFormattedSize(this.state.payload.length) - ), - id: "message-rawData", - opened: true, - }, - ]; - if (!isTruncated && this.state.isFormattedData) { - /** - * Push the JSON section (formatted data) at the begging of the array - * before the raw data section. Note that the JSON section will be - * auto-expanded while the raw data auto-collapsed. - */ - items.unshift({ - className: "formattedData", - component: PropertiesView, - componentProps: { - object: this.state.formattedData, - }, - header: this.state.formattedDataTitle, - id: "message-formattedData", - opened: true, - }); + if ( + !isTruncated && + this.state.isFormattedData && + !this.state.rawDataDisplayed + ) { + component = PropertiesView; + componentProps = { + object: this.state.formattedData, + }; + dataLabel = this.state.formattedDataTitle; + } else { + component = RawData; + componentProps = { payload }; + dataLabel = L10N.getFormatStrWithNumbers( + "netmonitor.ws.rawData.header", + getFormattedSize(this.state.payload.length) + ); } return div( @@ -356,9 +387,13 @@ class MessagePayload extends Component { }, MESSAGE_DATA_TRUNCATED ), - Accordion({ - items, - }) + h2({ className: "data-header", role: "heading" }, [ + span({ key: "data-label", className: "data-label" }, dataLabel), + !isTruncated && + this.state.isFormattedData && + this.renderRawDataBtn("data", rawDataDisplayed, this.toggleRawData), + ]), + this.renderData(component, componentProps) ); } } diff --git a/devtools/client/netmonitor/src/components/request-details/ResponsePanel.js b/devtools/client/netmonitor/src/components/request-details/ResponsePanel.js index e3c9a8ac676c..5e8551dfcfcb 100644 --- a/devtools/client/netmonitor/src/components/request-details/ResponsePanel.js +++ b/devtools/client/netmonitor/src/components/request-details/ResponsePanel.js @@ -39,9 +39,6 @@ const HtmlPreview = createFactory( const MessagesView = createFactory( require("devtools/client/netmonitor/src/components/messages/MessagesView") ); -const Accordion = createFactory( - require("devtools/client/shared/components/Accordion") -); const SearchBox = createFactory( require("devtools/client/shared/components/SearchBox") ); @@ -50,11 +47,12 @@ loader.lazyGetter(this, "MODE", function() { return require("devtools/client/shared/components/reps/index").MODE; }); -const { div } = dom; +const { div, input, label, span, h2 } = dom; const JSON_SCOPE_NAME = L10N.getStr("jsonScopeName"); const JSON_FILTER_TEXT = L10N.getStr("jsonFilterText"); const RESPONSE_PAYLOAD = L10N.getStr("responsePayload"); -const RESPONSE_PREVIEW = L10N.getStr("responsePreview"); +const RAW_RESPONSE_PAYLOAD = L10N.getStr("netmonitor.response.raw"); +const HTML_RESPONSE = L10N.getStr("netmonitor.response.html"); const RESPONSE_EMPTY_TEXT = L10N.getStr("responseEmptyText"); const RESPONSE_TRUNCATED = L10N.getStr("responseTruncated"); @@ -80,8 +78,13 @@ class ResponsePanel extends Component { this.state = { filterText: "", - currentOpen: undefined, + rawResponsePayloadDisplayed: false, }; + + this.toggleRawResponsePayload = this.toggleRawResponsePayload.bind(this); + this.renderRawResponsePayloadBtn = this.renderRawResponsePayloadBtn.bind( + this + ); } componentDidMount() { @@ -162,6 +165,43 @@ class ResponsePanel extends Component { return null; } + toggleRawResponsePayload() { + this.setState({ + rawResponsePayloadDisplayed: !this.state.rawResponsePayloadDisplayed, + }); + } + + renderRawResponsePayloadBtn(key, checked, onChange) { + return [ + label( + { + key: `${key}RawResponsePayloadBtn`, + className: "raw-data-toggle", + htmlFor: `raw-${key}-checkbox`, + onClick: event => { + // stop the header click event + event.stopPropagation(); + }, + }, + span({ className: "raw-data-toggle-label" }, RAW_RESPONSE_PAYLOAD), + span( + { className: "raw-data-toggle-input" }, + input({ + id: `raw-${key}-checkbox`, + checked, + className: "devtools-checkbox-toggle", + onChange, + type: "checkbox", + }) + ) + ), + ]; + } + + renderResponsePayload(component, componentProps) { + return component(componentProps); + } + render() { const { connector, @@ -170,7 +210,7 @@ class ResponsePanel extends Component { targetSearchResult, } = this.props; const { responseContent, url } = request; - const { filterText } = this.state; + const { filterText, rawResponsePayloadDisplayed } = this.state; if (showMessagesView) { return MessagesView({ connector }); @@ -199,117 +239,47 @@ class ResponsePanel extends Component { const { json, jsonpCallback, error } = this.handleJSONResponse(mimeType, text) || {}; - const items = []; - let sectionName; - - const onToggle = (open, item) => { - this.setState({ currentOpen: open ? item : null }); - }; + let component; + let componentProps; + let responsePayloadLabel = RESPONSE_PAYLOAD; + let hasFormattedDisplay = false; if (json) { if (jsonpCallback) { - sectionName = L10N.getFormatStr("jsonpScopeName", jsonpCallback); + responsePayloadLabel = L10N.getFormatStr( + "jsonpScopeName", + jsonpCallback + ); } else { - sectionName = JSON_SCOPE_NAME; + responsePayloadLabel = JSON_SCOPE_NAME; } - items.push({ - component: PropertiesView, - componentProps: { - object: json, - useQuotes: true, - filterText, - targetSearchResult, - defaultSelectFirstNode: false, - mode: MODE.LONG, - }, - header: sectionName, - id: "jsonpScopeName", - opened: true, - shouldOpen: item => { - const { currentOpen } = this.state; - if (typeof currentOpen == "undefined" && item.id === items[0].id) { - // if this the first and panel just displayed, open this item - // by default; - return true; - } else if (!currentOpen) { - if (!targetSearchResult) { - return false; - } - return true; - } - // Open the item is toggled open or there is a serch result to show - if (item.id == currentOpen.id || targetSearchResult) { - return true; - } - return false; - }, - onToggle, - }); + component = PropertiesView; + componentProps = { + object: json, + useQuotes: true, + filterText, + targetSearchResult, + defaultSelectFirstNode: false, + mode: MODE.LONG, + }; + hasFormattedDisplay = true; + } else if (Filters.html(this.props.request)) { + // Display HTML + responsePayloadLabel = HTML_RESPONSE; + component = HtmlPreview; + componentProps = { responseContent }; + hasFormattedDisplay = true; } - // Display HTML - if (Filters.html(this.props.request)) { - items.push({ - component: HtmlPreview, - componentProps: { responseContent }, - header: RESPONSE_PREVIEW, - id: "responsePreview", - opened: false, - shouldOpen: item => { - const { currentOpen } = this.state; - if (typeof currentOpen == "undefined" && item.id === items[0].id) { - // if this the first and panel just displayed, open this item - // by default; - if (targetSearchResult) { - // collapse when we do a search - return false; - } - return true; - } else if (!currentOpen) { - return false; - } - // close this if there is a search result since - // it does not apply search - if (targetSearchResult) { - return false; - } - if (item.id == currentOpen.id) { - return true; - } - return false; - }, - onToggle, - }); - } - - items.push({ - component: SourcePreview, - componentProps: { + if (!hasFormattedDisplay || this.state.rawResponsePayloadDisplayed) { + component = SourcePreview; + componentProps = { text, mode: json ? "application/json" : mimeType.replace(/;.+/, ""), targetSearchResult, - }, - header: RESPONSE_PAYLOAD, - id: "responsePayload", - opened: !!targetSearchResult, - shouldOpen: item => { - const { currentOpen } = this.state; - if (typeof currentOpen == "undefined" && item.id === items[0].id) { - return true; - } else if (!currentOpen) { - if (targetSearchResult) { - return true; - } - return false; - } - if (item.id == currentOpen.id || targetSearchResult) { - return true; - } - return false; - }, - onToggle, - }); + }; + } const classList = ["panel-container"]; if (Filters.html(this.props.request)) { @@ -330,7 +300,22 @@ class ResponsePanel extends Component { value: filterText, }) ), - Accordion({ items }) + h2({ className: "data-header", role: "heading" }, [ + span( + { + key: "data-label", + className: "data-label", + }, + responsePayloadLabel + ), + hasFormattedDisplay && + this.renderRawResponsePayloadBtn( + "response", + rawResponsePayloadDisplayed, + this.toggleRawResponsePayload + ), + ]), + this.renderResponsePayload(component, componentProps) ); } } diff --git a/devtools/client/netmonitor/test/browser_net_content-type.js b/devtools/client/netmonitor/test/browser_net_content-type.js index 914bf03e81d0..6d6d5d1704a1 100644 --- a/devtools/client/netmonitor/test/browser_net_content-type.js +++ b/devtools/client/netmonitor/test/browser_net_content-type.js @@ -174,8 +174,7 @@ add_task(async function() { true, "The response error header doesn't display" ); - const jsonView = - tabpanel.querySelector(".accordion-item .accordion-header-label") || {}; + const jsonView = tabpanel.querySelector(".data-label") || {}; is( jsonView.textContent !== L10N.getStr("jsonScopeName"), box != "json", @@ -234,9 +233,9 @@ add_task(async function() { checkVisibility("json"); is( - tabpanel.querySelectorAll(".accordion-item").length, - 2, - "There should be 2 accordion items displayed in this tabpanel." + tabpanel.querySelectorAll(".raw-data-toggle").length, + 1, + "The response payload toggle should be displayed in this tabpanel." ); is( tabpanel.querySelectorAll(".empty-notice").length, @@ -245,8 +244,7 @@ add_task(async function() { ); is( - tabpanel.querySelector(".accordion-item .accordion-header-label") - .textContent, + tabpanel.querySelector(".data-label").textContent, L10N.getStr("jsonScopeName"), "The json view section doesn't have the correct title." ); diff --git a/devtools/client/netmonitor/test/browser_net_cyrillic-02.js b/devtools/client/netmonitor/test/browser_net_cyrillic-02.js index 364133c0ffa1..314edede932b 100644 --- a/devtools/client/netmonitor/test/browser_net_cyrillic-02.js +++ b/devtools/client/netmonitor/test/browser_net_cyrillic-02.js @@ -52,13 +52,13 @@ add_task(async function() { ); await wait; - wait = waitForDOM(document, "#response-panel .accordion-item", 2); + wait = waitForDOM(document, "#response-panel .data-header"); clickOnSidebarTab(document, "response"); await wait; wait = waitForDOM(document, "#response-panel .CodeMirror-code"); const header = document.querySelector( - "#response-panel .accordion-item:last-child .accordion-header" + "#response-panel .raw-data-toggle-input .devtools-checkbox-toggle" ); clickElement(header, monitor); await wait; diff --git a/devtools/client/netmonitor/test/browser_net_json-b64.js b/devtools/client/netmonitor/test/browser_net_json-b64.js index 8bea7b487137..d974d849112b 100644 --- a/devtools/client/netmonitor/test/browser_net_json-b64.js +++ b/devtools/client/netmonitor/test/browser_net_json-b64.js @@ -22,7 +22,7 @@ add_task(async function() { // Execute requests. await performRequests(monitor, tab, 1); - let wait = waitForDOM(document, "#response-panel .accordion-item", 2); + let wait = waitForDOM(document, "#response-panel .data-header"); const waitForPropsView = waitForDOM( document, "#response-panel .properties-view", @@ -59,7 +59,7 @@ add_task(async function() { // Open the response payload section, it should hide the json section wait = waitForDOM(document, "#response-panel .CodeMirror-code"); const header = document.querySelector( - "#response-panel .accordion-item:last-child .accordion-header" + "#response-panel .raw-data-toggle-input .devtools-checkbox-toggle" ); clickElement(header, monitor); await wait; @@ -69,13 +69,18 @@ add_task(async function() { true, "The response error header doesn't have the intended visibility." ); - const jsonView = - tabpanel.querySelector(".accordion-item .accordion-header-label") || {}; + const jsonView = tabpanel.querySelector(".data-label") || {}; is( jsonView.textContent === L10N.getStr("jsonScopeName"), true, "The response json view has the intended visibility." ); + is( + tabpanel.querySelector(".raw-data-toggle-input .devtools-checkbox-toggle") + .checked, + true, + "The raw response toggle should be on." + ); is( tabpanel.querySelector(".CodeMirror-code") === null, false, @@ -86,12 +91,6 @@ add_task(async function() { true, "The response image box doesn't have the intended visibility." ); - - is( - tabpanel.querySelectorAll(".accordion-item").length, - 2, - "There should be 2 tree sections displayed in this tabpanel." - ); is( tabpanel.querySelectorAll(".empty-notice").length, 0, diff --git a/devtools/client/netmonitor/test/browser_net_json-empty.js b/devtools/client/netmonitor/test/browser_net_json-empty.js index 8f1fa3111970..9ef1828f3d16 100644 --- a/devtools/client/netmonitor/test/browser_net_json-empty.js +++ b/devtools/client/netmonitor/test/browser_net_json-empty.js @@ -25,8 +25,7 @@ add_task(async function() { const onResponsePanelReady = waitForDOM( document, - "#response-panel .accordion-item", - 2 + "#response-panel .data-header" ); store.dispatch(Actions.toggleNetworkDetails()); @@ -40,18 +39,13 @@ add_task(async function() { ); const header = document.querySelector( - "#response-panel .accordion-item:last-child .accordion-header" + "#response-panel .raw-data-toggle-input .devtools-checkbox-toggle" ); clickElement(header, monitor); await codeMirrorReady; const tabpanel = document.querySelector("#response-panel"); - is( - tabpanel.querySelectorAll(".accordion-item").length, - 2, - "There should be 2 accordion items displayed in this tabpanel." - ); is( tabpanel.querySelectorAll(".empty-notice").length, 0, @@ -74,8 +68,7 @@ add_task(async function() { "The response image box doesn't have the intended visibility." ); - const jsonView = - tabpanel.querySelector(".accordion-item .accordion-header-label") || {}; + const jsonView = tabpanel.querySelector(".data-label") || {}; is( jsonView.textContent === L10N.getStr("jsonScopeName"), true, diff --git a/devtools/client/netmonitor/test/browser_net_json-long.js b/devtools/client/netmonitor/test/browser_net_json-long.js index 7ed7cfa09337..579fb88ee402 100644 --- a/devtools/client/netmonitor/test/browser_net_json-long.js +++ b/devtools/client/netmonitor/test/browser_net_json-long.js @@ -55,7 +55,7 @@ add_task(async function() { } ); - let wait = waitForDOM(document, "#response-panel .accordion-item", 2); + let wait = waitForDOM(document, "#response-panel .data-header"); const waitForPropsView = waitForDOM( document, "#response-panel .properties-view", @@ -74,20 +74,20 @@ add_task(async function() { ); lastItem.scrollIntoView(); - testJsonAccordionInResposeTab(); + testJsonInResposeTab(); wait = waitForDOM(document, "#response-panel .CodeMirror-code"); - const payloadHeader = document.querySelector( - "#response-panel .accordion-item:last-child .accordion-header" + const rawResponseToggle = document.querySelector( + "#response-panel .raw-data-toggle-input .devtools-checkbox-toggle" ); - clickElement(payloadHeader, monitor); + clickElement(rawResponseToggle, monitor); await wait; testResponseTab(); await teardown(monitor); - function testJsonAccordionInResposeTab() { + function testJsonInResposeTab() { const tabpanel = document.querySelector("#response-panel"); is( tabpanel.querySelectorAll(".treeRow").length, @@ -132,8 +132,7 @@ add_task(async function() { true, "The response error header doesn't have the intended visibility." ); - const jsonView = - tabpanel.querySelector(".accordion-item .accordion-header-label") || {}; + const jsonView = tabpanel.querySelector(".data-label") || {}; is( jsonView.textContent === L10N.getStr("jsonScopeName"), true, @@ -154,12 +153,6 @@ add_task(async function() { true, "The response image box doesn't have the intended visibility." ); - - is( - tabpanel.querySelectorAll(".accordion-item").length, - 2, - "There should be 2 accordion items displayed in this tabpanel." - ); is( tabpanel.querySelectorAll(".empty-notice").length, 0, @@ -167,8 +160,7 @@ add_task(async function() { ); is( - tabpanel.querySelector(".accordion-item .accordion-header-label") - .textContent, + tabpanel.querySelector(".data-label").textContent, L10N.getStr("jsonScopeName"), "The json view section doesn't have the correct title." ); diff --git a/devtools/client/netmonitor/test/browser_net_json-nogrip.js b/devtools/client/netmonitor/test/browser_net_json-nogrip.js index a1f901ea5840..52a4ff5ddc72 100644 --- a/devtools/client/netmonitor/test/browser_net_json-nogrip.js +++ b/devtools/client/netmonitor/test/browser_net_json-nogrip.js @@ -23,8 +23,7 @@ add_task(async function() { const onResponsePanelReady = waitForDOM( document, - "#response-panel .accordion-item", - 2 + "#response-panel .data-header" ); const onPropsViewReady = waitForDOM( diff --git a/devtools/client/netmonitor/test/browser_net_json-null.js b/devtools/client/netmonitor/test/browser_net_json-null.js index a9b41167d846..2b1775ca9123 100644 --- a/devtools/client/netmonitor/test/browser_net_json-null.js +++ b/devtools/client/netmonitor/test/browser_net_json-null.js @@ -24,8 +24,7 @@ add_task(async function() { const onResponsePanelReady = waitForDOM( document, - "#response-panel .accordion-item", - 2 + "#response-panel .data-header" ); const onPropsViewReady = waitForDOM( @@ -39,9 +38,9 @@ add_task(async function() { const tabpanel = document.querySelector("#response-panel"); is( - tabpanel.querySelectorAll(".accordion-item").length, - 2, - "There should be 2 accordion items displayed in this tabpanel." + tabpanel.querySelectorAll(".raw-data-toggle").length, + 1, + "There should be 1 raw response toggle." ); is( tabpanel.querySelectorAll(".treeRow").length, @@ -73,10 +72,10 @@ add_task(async function() { "#response-panel .CodeMirror-code" ); - const payloadHeader = document.querySelector( - "#response-panel .accordion-item:last-child .accordion-header" + const rawResponseToggle = document.querySelector( + "#response-panel .raw-data-toggle-input .devtools-checkbox-toggle" ); - clickElement(payloadHeader, monitor); + clickElement(rawResponseToggle, monitor); await onCodeMirrorReady; @@ -95,8 +94,7 @@ add_task(async function() { true, "The response error header doesn't have the intended visibility." ); - const jsonView = - panel.querySelector(".accordion-item .accordion-header-label") || {}; + const jsonView = panel.querySelector(".data-label") || {}; is( jsonView.textContent === L10N.getStr("jsonScopeName"), true, diff --git a/devtools/client/netmonitor/test/browser_net_json_custom_mime.js b/devtools/client/netmonitor/test/browser_net_json_custom_mime.js index 0f510c6ddbe9..e78fbec90ef4 100644 --- a/devtools/client/netmonitor/test/browser_net_json_custom_mime.js +++ b/devtools/client/netmonitor/test/browser_net_json_custom_mime.js @@ -47,7 +47,7 @@ add_task(async function() { } ); - let wait = waitForDOM(document, "#response-panel .accordion-item", 2); + let wait = waitForDOM(document, "#response-panel .data-header"); const waitForPropsView = waitForDOM( document, "#response-panel .properties-view", @@ -61,10 +61,10 @@ add_task(async function() { testJsonSectionInResponseTab(); wait = waitForDOM(document, "#response-panel .CodeMirror-code"); - const payloadHeader = document.querySelector( - "#response-panel .accordion-item:last-child .accordion-header" + const rawResponseToggle = document.querySelector( + "#response-panel .raw-data-toggle-input .devtools-checkbox-toggle" ); - clickElement(payloadHeader, monitor); + clickElement(rawResponseToggle, monitor); await wait; testResponseTab(); @@ -102,13 +102,18 @@ add_task(async function() { true, "The response error header doesn't have the intended visibility." ); - const jsonView = - tabpanel.querySelector(".accordion-item .accordion-header-label") || {}; + const jsonView = tabpanel.querySelector(".data-label") || {}; is( jsonView.textContent === L10N.getStr("jsonScopeName"), true, "The response json view has the intended visibility." ); + is( + tabpanel.querySelector(".raw-data-toggle-input .devtools-checkbox-toggle") + .checked, + true, + "The raw response toggle should be on." + ); is( tabpanel.querySelector(".CodeMirror-code") === null, false, @@ -119,13 +124,6 @@ add_task(async function() { true, "The response image box doesn't have the intended visibility." ); - - is( - tabpanel.querySelectorAll(".accordion-item").length, - 2, - "There should be 2 accordion items displayed in this tabpanel." - ); - is( tabpanel.querySelectorAll(".empty-notice").length, 0, diff --git a/devtools/client/netmonitor/test/browser_net_json_text_mime.js b/devtools/client/netmonitor/test/browser_net_json_text_mime.js index 25ddc6d351cf..2bd01e8f494a 100644 --- a/devtools/client/netmonitor/test/browser_net_json_text_mime.js +++ b/devtools/client/netmonitor/test/browser_net_json_text_mime.js @@ -48,7 +48,7 @@ add_task(async function() { } ); - let wait = waitForDOM(document, "#response-panel .accordion-item", 2); + let wait = waitForDOM(document, "#response-panel .data-header"); const waitForPropsView = waitForDOM( document, "#response-panel .properties-view", @@ -62,10 +62,10 @@ add_task(async function() { testJsonSectionInResponseTab(); wait = waitForDOM(document, "#response-panel .CodeMirror-code"); - const payloadHeader = document.querySelector( - "#response-panel .accordion-item:last-child .accordion-header" + const rawResponseToggle = document.querySelector( + "#response-panel .raw-data-toggle-input .devtools-checkbox-toggle" ); - clickElement(payloadHeader, monitor); + clickElement(rawResponseToggle, monitor); await wait; testResponseTab(); @@ -103,8 +103,7 @@ add_task(async function() { true, "The response error header doesn't have the intended visibility." ); - const jsonView = - tabpanel.querySelector(".accordion-item .accordion-header-label") || {}; + const jsonView = tabpanel.querySelector(".data-label") || {}; is( jsonView.textContent === L10N.getStr("jsonScopeName"), true, @@ -115,17 +114,17 @@ add_task(async function() { false, "The response editor has the intended visibility." ); + is( + tabpanel.querySelector(".raw-data-toggle-input .devtools-checkbox-toggle") + .checked, + true, + "The raw response toggle should be on." + ); is( tabpanel.querySelector(".response-image-box") === null, true, "The response image box doesn't have the intended visibility." ); - - is( - tabpanel.querySelectorAll(".accordion-item").length, - 2, - "There should be 2 accordion items displayed in this tabpanel." - ); is( tabpanel.querySelectorAll(".empty-notice").length, 0, diff --git a/devtools/client/netmonitor/test/browser_net_jsonp.js b/devtools/client/netmonitor/test/browser_net_jsonp.js index e0b48df140b0..c823dfdffd87 100644 --- a/devtools/client/netmonitor/test/browser_net_jsonp.js +++ b/devtools/client/netmonitor/test/browser_net_jsonp.js @@ -65,7 +65,7 @@ add_task(async function() { ); info("Testing first request"); - let wait = waitForDOM(document, "#response-panel .accordion-item", 2); + let wait = waitForDOM(document, "#response-panel .data-header"); let waitForPropsView = waitForDOM( document, "#response-panel .properties-view", @@ -79,17 +79,17 @@ add_task(async function() { testJsonSectionInResponseTab(`"Hello JSONP!"`); wait = waitForDOM(document, "#response-panel .CodeMirror-code"); - let payloadHeader = document.querySelector( - "#response-panel .accordion-item:last-child .accordion-header" + let rawResponseToggle = document.querySelector( + "#response-panel .raw-data-toggle-input .devtools-checkbox-toggle" ); - clickElement(payloadHeader, monitor); + clickElement(rawResponseToggle, monitor); await wait; testResponseTab("$_0123Fun"); info("Testing second request"); - wait = waitForDOM(document, "#response-panel .accordion-item", 2); + wait = waitForDOM(document, "#response-panel .data-header"); EventUtils.sendMouseEvent( { type: "mousedown" }, document.querySelectorAll(".request-list-item")[1] @@ -102,20 +102,20 @@ add_task(async function() { "#response-panel .properties-view", 1 ); - payloadHeader = document.querySelector( - "#response-panel .accordion-item:first-child .accordion-header" + rawResponseToggle = document.querySelector( + "#response-panel .raw-data-toggle-input .devtools-checkbox-toggle" ); - clickElement(payloadHeader, monitor); + clickElement(rawResponseToggle, monitor); await waitForPropsView; testJsonSectionInResponseTab(`"Hello weird JSONP!"`); wait = waitForDOM(document, "#response-panel .CodeMirror-code"); - payloadHeader = document.querySelector( - "#response-panel .accordion-item:last-child .accordion-header" + rawResponseToggle = document.querySelector( + "#response-panel .raw-data-toggle-input .devtools-checkbox-toggle" ); - clickElement(payloadHeader, monitor); + clickElement(rawResponseToggle, monitor); await wait; testResponseTab("$_4567Sad"); @@ -154,8 +154,7 @@ add_task(async function() { "The response error header doesn't have the intended visibility." ); is( - tabpanel.querySelector(".accordion-item .accordion-header-label") - .textContent, + tabpanel.querySelector(".data-label").textContent, L10N.getFormatStr("jsonpScopeName", func), "The response json view has the intened visibility and correct title." ); @@ -169,12 +168,6 @@ add_task(async function() { true, "The response image box doesn't have the intended visibility." ); - - is( - tabpanel.querySelectorAll(".accordion-item").length, - 2, - "There should be 2 accordion items displayed in this tabpanel." - ); is( tabpanel.querySelectorAll(".empty-notice").length, 0, diff --git a/devtools/client/netmonitor/test/browser_net_large-response.js b/devtools/client/netmonitor/test/browser_net_large-response.js index d64a3f74c1c9..5dc096d2eed8 100644 --- a/devtools/client/netmonitor/test/browser_net_large-response.js +++ b/devtools/client/netmonitor/test/browser_net_large-response.js @@ -54,14 +54,14 @@ add_task(async function() { } ); - wait = waitForDOM(document, "#response-panel .accordion-item", 2); + wait = waitForDOM(document, "#response-panel .data-header"); store.dispatch(Actions.toggleNetworkDetails()); clickOnSidebarTab(document, "response"); await wait; wait = waitForDOM(document, "#response-panel .CodeMirror-code"); const payloadHeader = document.querySelector( - "#response-panel .accordion-item:last-child .accordion-header" + "#response-panel .raw-data-toggle-input .devtools-checkbox-toggle" ); clickElement(payloadHeader, monitor); await wait; diff --git a/devtools/client/netmonitor/test/browser_net_simple-request-details.js b/devtools/client/netmonitor/test/browser_net_simple-request-details.js index 954887cf0b78..86efda31053d 100644 --- a/devtools/client/netmonitor/test/browser_net_simple-request-details.js +++ b/devtools/client/netmonitor/test/browser_net_simple-request-details.js @@ -296,18 +296,19 @@ add_task(async function() { async function testResponseTab() { const tabpanel = await selectTab(PANELS.RESPONSE, 3); - await waitForDOM(document, ".accordion .source-editor-mount"); + await waitForDOM(document, "#response-panel .source-editor-mount"); - const responseAccordion = tabpanel.querySelector(".accordion"); is( - responseAccordion.querySelectorAll(".accordion-item").length, - 1, - "There should be 1 response scope displayed in this tabpanel." + tabpanel.querySelectorAll( + "#response-panel .raw-data-toggle-input .devtools-checkbox-toggle" + ).length, + 0, + "The raw data toggle should not be shown in this tabpanel." ); is( - responseAccordion.querySelectorAll(".source-editor-mount").length, + tabpanel.querySelectorAll(".source-editor-mount").length, 1, - "The response payload tab should be open initially." + "The response payload should be shown initially." ); } diff --git a/devtools/client/netmonitor/test/browser_net_ws-json-action-cable-payload.js b/devtools/client/netmonitor/test/browser_net_ws-json-action-cable-payload.js index ab4f6b0a3a93..98b37f7ebd5e 100644 --- a/devtools/client/netmonitor/test/browser_net_ws-json-action-cable-payload.js +++ b/devtools/client/netmonitor/test/browser_net_ws-json-action-cable-payload.js @@ -33,7 +33,7 @@ add_task(async function() { is(requests.length, 1, "There should be one request"); // Wait for all sent/received messages to be displayed in DevTools - const wait = waitForDOM( + let wait = waitForDOM( document, "#messages-view .message-list-table .message-list-item", 2 @@ -56,20 +56,20 @@ add_task(async function() { // Wait for next tick to do async stuff (The MessagePayload component uses the async function getMessagePayload) await waitForTick(); - const waitForData = waitForDOM(document, "#message-formattedData"); + const waitForData = waitForDOM(document, "#messages-view .properties-view"); const [requestFrame] = frames; EventUtils.sendMouseEvent({ type: "mousedown" }, requestFrame); await waitForData; is( - document.querySelector("#message-formattedData-header").innerText, + document.querySelector("#messages-view .data-label").innerText, "Action Cable", "The Action Cable payload panel should be displayed" ); ok( - document.querySelector("#message-formattedData .treeTable"), + document.querySelector("#messages-view .treeTable"), "A tree table should be used to display the formatted payload" ); @@ -82,6 +82,26 @@ add_task(async function() { "The 'x' property in the 'data' object should be displayed" ); + // Toggle raw data display + wait = waitForDOM(document, "#messages-view .message-rawData-payload"); + const rawDataToggle = document.querySelector( + "#messages-view .devtools-checkbox-toggle" + ); + clickElement(rawDataToggle, monitor); + await wait; + + is( + document.querySelector("#messages-view .data-label").innerText, + "Raw Data (20 B)", + "The raw data payload info should be displayed" + ); + + is( + document.querySelector("#messages-view .message-rawData-payload").value, + `{"data":"{\\"x\\":2}"}`, + "The raw data must be shown correctly" + ); + // Close WS connection await SpecialPowers.spawn(tab.linkedBrowser, [], async () => { await content.wrappedJSObject.closeConnection(); diff --git a/devtools/client/netmonitor/test/browser_net_ws-json-payload.js b/devtools/client/netmonitor/test/browser_net_ws-json-payload.js index 9e63275afb3c..4a9d53d1f8d9 100644 --- a/devtools/client/netmonitor/test/browser_net_ws-json-payload.js +++ b/devtools/client/netmonitor/test/browser_net_ws-json-payload.js @@ -35,7 +35,7 @@ add_task(async function() { is(requests.length, 1, "There should be one request"); // Wait for all sent/received messages to be displayed in DevTools - const wait = waitForDOM( + let wait = waitForDOM( document, "#messages-view .message-list-table .message-list-item", 2 @@ -58,20 +58,20 @@ add_task(async function() { // Wait for next tick to do async stuff (The MessagePayload component uses the async function getMessagePayload) await waitForTick(); - const waitForData = waitForDOM(document, "#message-formattedData"); + const waitForData = waitForDOM(document, "#messages-view .properties-view"); const [requestFrame] = frames; EventUtils.sendMouseEvent({ type: "mousedown" }, requestFrame); await waitForData; is( - document.querySelector("#message-formattedData-header").innerText, + document.querySelector("#messages-view .data-label").innerText, "JSON", "The JSON payload panel should be displayed" ); ok( - document.querySelector("#message-formattedData .treeTable"), + document.querySelector("#messages-view .treeTable"), "A tree table should be used to display the formatted payload" ); @@ -85,6 +85,26 @@ add_task(async function() { "The 'y' property in the `bar` object should be displayed" ); + // Toggle raw data display + wait = waitForDOM(document, "#messages-view .message-rawData-payload"); + const rawDataToggle = document.querySelector( + "#messages-view .devtools-checkbox-toggle" + ); + clickElement(rawDataToggle, monitor); + await wait; + + is( + document.querySelector("#messages-view .data-label").innerText, + "Raw Data (42 B)", + "The raw data payload info should be displayed" + ); + + is( + document.querySelector("#messages-view .message-rawData-payload").value, + `{\"foo\":{\"x\":1,\"y\":2}, \"bar\":{\"x\":1,\"y\":2}}`, + "The raw data must be shown correctly" + ); + // Close WS connection await SpecialPowers.spawn(tab.linkedBrowser, [], async () => { await content.wrappedJSObject.closeConnection(); diff --git a/devtools/client/netmonitor/test/browser_net_ws-json-stomp-payload.js b/devtools/client/netmonitor/test/browser_net_ws-json-stomp-payload.js index 381bba060cfa..efbe4e612dcc 100644 --- a/devtools/client/netmonitor/test/browser_net_ws-json-stomp-payload.js +++ b/devtools/client/netmonitor/test/browser_net_ws-json-stomp-payload.js @@ -35,7 +35,7 @@ add_task(async function() { is(requests.length, 1, "There should be one request"); // Wait for all sent/received messages to be displayed in DevTools - const wait = waitForDOM( + let wait = waitForDOM( document, "#messages-view .message-list-table .message-list-item", 2 @@ -58,20 +58,20 @@ add_task(async function() { // Wait for next tick to do async stuff (The MessagePayload component uses the async function getMessagePayload) await waitForTick(); - const waitForData = waitForDOM(document, "#message-formattedData"); + const waitForData = waitForDOM(document, "#messages-view .properties-view"); const [requestFrame] = frames; EventUtils.sendMouseEvent({ type: "mousedown" }, requestFrame); await waitForData; is( - document.querySelector("#message-formattedData-header").innerText, + document.querySelector("#messages-view .data-label").innerText, "JSON", "The JSON payload panel should be displayed" ); ok( - document.querySelector("#message-formattedData .treeTable"), + document.querySelector("#messages-view .treeTable"), "A tree table should be used to display the formatted payload" ); @@ -88,6 +88,26 @@ add_task(async function() { "The message 'body' should be displayed" ); + // Toggle raw data display + wait = waitForDOM(document, "#messages-view .message-rawData-payload"); + const rawDataToggle = document.querySelector( + "#messages-view .devtools-checkbox-toggle" + ); + clickElement(rawDataToggle, monitor); + await wait; + + is( + document.querySelector("#messages-view .data-label").innerText, + "Raw Data (79 B)", + "The raw data payload info should be displayed" + ); + + is( + document.querySelector("#messages-view .message-rawData-payload").value, + `[\"SEND\\nx-firefox-test:true\\ncontent-length:17\\n\\n[{\\\"key\\\":\\\"value\\\"}]\\u0000\"]`, + "The raw data must be shown correctly" + ); + // Close WS connection await SpecialPowers.spawn(tab.linkedBrowser, [], async () => { await content.wrappedJSObject.closeConnection(); diff --git a/devtools/client/netmonitor/test/browser_net_ws-sockjs-stomp-payload.js b/devtools/client/netmonitor/test/browser_net_ws-sockjs-stomp-payload.js index 676029a3068f..abc0a85e85f5 100644 --- a/devtools/client/netmonitor/test/browser_net_ws-sockjs-stomp-payload.js +++ b/devtools/client/netmonitor/test/browser_net_ws-sockjs-stomp-payload.js @@ -35,7 +35,7 @@ add_task(async function() { is(requests.length, 1, "There should be one requests"); // Wait for all sent/received messages to be displayed in DevTools - const wait = waitForDOM( + let wait = waitForDOM( document, "#messages-view .message-list-table .message-list-item", 2 @@ -58,20 +58,20 @@ add_task(async function() { // Wait for next tick to do async stuff (The MessagePayload component uses the async function getMessagePayload) await waitForTick(); - const waitForData = waitForDOM(document, "#message-formattedData"); + const waitForData = waitForDOM(document, "#messages-view .properties-view"); const [, responseFrame] = frames; EventUtils.sendMouseEvent({ type: "mousedown" }, responseFrame); await waitForData; is( - document.querySelector("#message-formattedData-header").innerText, + document.querySelector("#messages-view .data-label").innerText, "SockJS", "The SockJS payload panel should be displayed" ); ok( - document.querySelector("#message-formattedData .treeTable"), + document.querySelector("#messages-view .treeTable"), "A tree table should be used to display the formatted payload" ); @@ -88,6 +88,26 @@ add_task(async function() { "The message 'body' should be displayed" ); + // Toggle raw data display + wait = waitForDOM(document, "#messages-view .message-rawData-payload"); + const rawDataToggle = document.querySelector( + "#messages-view .devtools-checkbox-toggle" + ); + clickElement(rawDataToggle, monitor); + await wait; + + is( + document.querySelector("#messages-view .data-label").innerText, + "Raw Data (80 B)", + "The raw data payload info should be displayed" + ); + + is( + document.querySelector("#messages-view .message-rawData-payload").value, + `a[\"SEND\\nx-firefox-test:true\\ncontent-length:17\\n\\n[{\\\"key\\\":\\\"value\\\"}]\\u0000\"]`, + "The raw data must be shown correctly" + ); + // Close WS connection await SpecialPowers.spawn(tab.linkedBrowser, [], async () => { await content.wrappedJSObject.closeConnection(); diff --git a/devtools/client/netmonitor/test/browser_net_ws-stomp-payload.js b/devtools/client/netmonitor/test/browser_net_ws-stomp-payload.js index 7e01bf7b3e9e..7fa36188c69f 100644 --- a/devtools/client/netmonitor/test/browser_net_ws-stomp-payload.js +++ b/devtools/client/netmonitor/test/browser_net_ws-stomp-payload.js @@ -35,7 +35,7 @@ add_task(async function() { is(requests.length, 1, "There should be one request"); // Wait for all sent/received messages to be displayed in DevTools - const wait = waitForDOM( + let wait = waitForDOM( document, "#messages-view .message-list-table .message-list-item", 2 @@ -58,20 +58,20 @@ add_task(async function() { // Wait for next tick to do async stuff (The MessagePayload component uses the async function getMessagePayload) await waitForTick(); - const waitForData = waitForDOM(document, "#message-formattedData"); + const waitForData = waitForDOM(document, "#messages-view .properties-view"); const [requestFrame] = frames; EventUtils.sendMouseEvent({ type: "mousedown" }, requestFrame); await waitForData; is( - document.querySelector("#message-formattedData-header").innerText, + document.querySelector("#messages-view .data-label").innerText, "STOMP", "The STOMP payload panel should be displayed" ); ok( - document.querySelector("#message-formattedData .treeTable"), + document.querySelector("#messages-view .treeTable"), "A tree table should be used to display the formatted payload" ); @@ -88,6 +88,26 @@ add_task(async function() { "The message 'body' should be displayed" ); + // Toggle raw data display + wait = waitForDOM(document, "#messages-view .message-rawData-payload"); + const rawDataToggle = document.querySelector( + "#messages-view .devtools-checkbox-toggle" + ); + clickElement(rawDataToggle, monitor); + await wait; + + is( + document.querySelector("#messages-view .data-label").innerText, + "Raw Data (63 B)", + "The raw data payload info should be displayed" + ); + + is( + document.querySelector("#messages-view .message-rawData-payload").value, + `SEND\nx-firefox-test:true\ncontent-length:17\n\n[{"key":"value"}]\u0000\n`, + "The raw data must be shown correctly" + ); + // Close WS connection await SpecialPowers.spawn(tab.linkedBrowser, [], async () => { await content.wrappedJSObject.closeConnection(); diff --git a/devtools/client/webconsole/test/browser/browser_webconsole_network_messages_expand_before_updates.js b/devtools/client/webconsole/test/browser/browser_webconsole_network_messages_expand_before_updates.js index 3dc33fdb252a..cda433ce8a1a 100644 --- a/devtools/client/webconsole/test/browser/browser_webconsole_network_messages_expand_before_updates.js +++ b/devtools/client/webconsole/test/browser/browser_webconsole_network_messages_expand_before_updates.js @@ -223,7 +223,7 @@ async function testResponse(messageNode) { responseTab.click(); const responsePanel = messageNode.querySelector("#response-panel"); const responsePayloadHeader = await waitFor(() => - responsePanel.querySelector("#responsePayload-header") + responsePanel.querySelector(".data-header") ); // Expand the header if it wasn't yet. if (responsePayloadHeader.getAttribute("aria-expanded") === "false") {