diff options
Diffstat (limited to 'devtools/client/webconsole/net/test/mochitest')
17 files changed, 629 insertions, 0 deletions
diff --git a/devtools/client/webconsole/net/test/mochitest/.eslintrc.js b/devtools/client/webconsole/net/test/mochitest/.eslintrc.js new file mode 100644 index 000000000..76904829d --- /dev/null +++ b/devtools/client/webconsole/net/test/mochitest/.eslintrc.js @@ -0,0 +1,6 @@ +"use strict"; + +module.exports = { + // Extend from the shared list of defined globals for mochitests. + "extends": "../../../../../.eslintrc.mochitests.js", +}; diff --git a/devtools/client/webconsole/net/test/mochitest/browser.ini b/devtools/client/webconsole/net/test/mochitest/browser.ini new file mode 100644 index 000000000..9414414c6 --- /dev/null +++ b/devtools/client/webconsole/net/test/mochitest/browser.ini @@ -0,0 +1,22 @@ +[DEFAULT] +tags = devtools +subsuite = devtools +support-files = + head.js + page_basic.html + test.json + test.json^headers^ + test-cookies.json + test-cookies.json^headers^ + test.txt + test.xml + test.xml^headers^ + !/devtools/client/webconsole/test/head.js + !/devtools/client/framework/test/shared-head.js + +[browser_net_basic.js] +[browser_net_cookies.js] +[browser_net_headers.js] +[browser_net_params.js] +[browser_net_post.js] +[browser_net_response.js] diff --git a/devtools/client/webconsole/net/test/mochitest/browser_net_basic.js b/devtools/client/webconsole/net/test/mochitest/browser_net_basic.js new file mode 100644 index 000000000..57273bec0 --- /dev/null +++ b/devtools/client/webconsole/net/test/mochitest/browser_net_basic.js @@ -0,0 +1,33 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const TEST_PAGE_URL = URL_ROOT + "page_basic.html"; +const JSON_XHR_URL = URL_ROOT + "test.json"; + +/** + * Basic test that generates XHR in the content and + * checks the related log in the Console panel can + * be expanded. + */ +add_task(function* () { + info("Test XHR Spy basic started"); + + let {hud} = yield addTestTab(TEST_PAGE_URL); + + let netInfoBody = yield executeAndInspectXhr(hud, { + method: "GET", + url: JSON_XHR_URL + }); + + ok(netInfoBody, "The network details must be available"); + + // There should be at least two tabs: Headers and Response + ok(netInfoBody.querySelector(".tabs .tabs-menu-item.headers"), + "Headers tab must be available"); + ok(netInfoBody.querySelector(".tabs .tabs-menu-item.response"), + "Response tab must be available"); +}); diff --git a/devtools/client/webconsole/net/test/mochitest/browser_net_cookies.js b/devtools/client/webconsole/net/test/mochitest/browser_net_cookies.js new file mode 100644 index 000000000..cfd85c2ed --- /dev/null +++ b/devtools/client/webconsole/net/test/mochitest/browser_net_cookies.js @@ -0,0 +1,54 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const TEST_PAGE_URL = URL_ROOT + "page_basic.html"; +const JSON_XHR_URL = URL_ROOT + "test-cookies.json"; + +/** + * This test generates XHR requests in the page, expands + * networks details in the Console panel and checks that + * Cookies are properly displayed. + */ +add_task(function* () { + info("Test XHR Spy cookies started"); + + let {hud} = yield addTestTab(TEST_PAGE_URL); + + let netInfoBody = yield executeAndInspectXhr(hud, { + method: "GET", + url: JSON_XHR_URL + }); + + // Select "Cookies" tab + let tabBody = yield selectNetInfoTab(hud, netInfoBody, "cookies"); + + let requestCookieName = tabBody.querySelector( + ".netInfoGroup.requestCookies .netInfoParamName > span[title='bar']"); + + // Verify request cookies (name and value) + ok(requestCookieName, "Request Cookie name must exist"); + is(requestCookieName.textContent, "bar", + "The cookie name must have proper value"); + + let requestCookieValue = requestCookieName.parentNode.nextSibling; + ok(requestCookieValue, "Request Cookie value must exist"); + is(requestCookieValue.textContent, "foo", + "The cookie value must have proper value"); + + let responseCookieName = tabBody.querySelector( + ".netInfoGroup.responseCookies .netInfoParamName > span[title='test']"); + + // Verify response cookies (name and value) + ok(responseCookieName, "Response Cookie name must exist"); + is(responseCookieName.textContent, "test", + "The cookie name must have proper value"); + + let responseCookieValue = responseCookieName.parentNode.nextSibling; + ok(responseCookieValue, "Response Cookie value must exist"); + is(responseCookieValue.textContent, "abc", + "The cookie value must have proper value"); +}); diff --git a/devtools/client/webconsole/net/test/mochitest/browser_net_headers.js b/devtools/client/webconsole/net/test/mochitest/browser_net_headers.js new file mode 100644 index 000000000..4a47074ee --- /dev/null +++ b/devtools/client/webconsole/net/test/mochitest/browser_net_headers.js @@ -0,0 +1,40 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const TEST_PAGE_URL = URL_ROOT + "page_basic.html"; +const JSON_XHR_URL = URL_ROOT + "test.json"; + +/** + * This test generates XHR requests in the page, expands + * networks details in the Console panel and checks that + * HTTP headers are there. + */ +add_task(function* () { + info("Test XHR Spy headers started"); + + let {hud} = yield addTestTab(TEST_PAGE_URL); + + let netInfoBody = yield executeAndInspectXhr(hud, { + method: "GET", + url: JSON_XHR_URL + }); + + // Select "Headers" tab + let tabBody = yield selectNetInfoTab(hud, netInfoBody, "headers"); + let paramName = tabBody.querySelector( + ".netInfoParamName > span[title='Content-Type']"); + + // Verify "Content-Type" header (name and value) + ok(paramName, "Header name must exist"); + is(paramName.textContent, "Content-Type", + "The header name must have proper value"); + + let paramValue = paramName.parentNode.nextSibling; + ok(paramValue, "Header value must exist"); + is(paramValue.textContent, "application/json; charset=utf-8", + "The header value must have proper value"); +}); diff --git a/devtools/client/webconsole/net/test/mochitest/browser_net_params.js b/devtools/client/webconsole/net/test/mochitest/browser_net_params.js new file mode 100644 index 000000000..d8b0e2c84 --- /dev/null +++ b/devtools/client/webconsole/net/test/mochitest/browser_net_params.js @@ -0,0 +1,69 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const TEST_PAGE_URL = URL_ROOT + "page_basic.html"; +const JSON_XHR_URL = URL_ROOT + "test.json"; + +/** + * This test generates XHR requests in the page, expands + * networks details in the Console panel and checks that + * HTTP parameters (query string) are there. + */ +add_task(function* () { + info("Test XHR Spy params started"); + + let {hud} = yield addTestTab(TEST_PAGE_URL); + + let netInfoBody = yield executeAndInspectXhr(hud, { + method: "GET", + url: JSON_XHR_URL, + queryString: "?foo=bar" + }); + + // Check headers + let tabBody = yield selectNetInfoTab(hud, netInfoBody, "params"); + + let paramName = tabBody.querySelector( + ".netInfoParamName > span[title='foo']"); + + // Verify "Content-Type" header (name and value) + ok(paramName, "Header name must exist"); + is(paramName.textContent, "foo", + "The param name must have proper value"); + + let paramValue = paramName.parentNode.nextSibling; + ok(paramValue, "param value must exist"); + is(paramValue.textContent, "bar", + "The param value must have proper value"); +}); + +/** + * Test URL parameters with the same name. + */ +add_task(function* () { + info("Test XHR Spy params started"); + + let {hud} = yield addTestTab(TEST_PAGE_URL); + + let netInfoBody = yield executeAndInspectXhr(hud, { + method: "GET", + url: JSON_XHR_URL, + queryString: "?box[]=123&box[]=456" + }); + + // Check headers + let tabBody = yield selectNetInfoTab(hud, netInfoBody, "params"); + + let params = tabBody.querySelectorAll( + ".netInfoParamName > span[title='box[]']"); + is(params.length, 2, "Two URI parameters must exist"); + + let values = tabBody.querySelectorAll( + ".netInfoParamValue > code"); + is(values[0].textContent, 123, "First value must match"); + is(values[1].textContent, 456, "Second value must match"); +}); diff --git a/devtools/client/webconsole/net/test/mochitest/browser_net_post.js b/devtools/client/webconsole/net/test/mochitest/browser_net_post.js new file mode 100644 index 000000000..f6e776ef0 --- /dev/null +++ b/devtools/client/webconsole/net/test/mochitest/browser_net_post.js @@ -0,0 +1,88 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const TEST_PAGE_URL = URL_ROOT + "page_basic.html"; +const JSON_XHR_URL = URL_ROOT + "test.json"; + +const plainPostBody = "test-data"; +const jsonData = "{\"bar\": \"baz\"}"; +const jsonRendered = "bar\"baz\""; +const xmlPostBody = "<xml><name>John</name></xml>"; + +/** + * This test generates XHR requests in the page, expands + * networks details in the Console panel and checks that + * Post data are properly rendered. + */ +add_task(function* () { + info("Test XHR Spy post plain body started"); + + let {hud} = yield addTestTab(TEST_PAGE_URL); + + let netInfoBody = yield executeAndInspectXhr(hud, { + method: "POST", + url: JSON_XHR_URL, + body: plainPostBody + }); + + // Check post body data + let tabBody = yield selectNetInfoTab(hud, netInfoBody, "post"); + let postContent = tabBody.querySelector( + ".netInfoGroup.raw.opened .netInfoGroupContent"); + is(postContent.textContent, plainPostBody, + "Post body must be properly rendered"); +}); + +add_task(function* () { + info("Test XHR Spy post JSON body started"); + + let {hud} = yield addTestTab(TEST_PAGE_URL); + + let netInfoBody = yield executeAndInspectXhr(hud, { + method: "POST", + url: JSON_XHR_URL, + body: jsonData, + requestHeaders: [{ + name: "Content-Type", + value: "application/json" + }] + }); + + // Check post body data + let tabBody = yield selectNetInfoTab(hud, netInfoBody, "post"); + let postContent = tabBody.querySelector( + ".netInfoGroup.json.opened .netInfoGroupContent"); + is(postContent.textContent, jsonRendered, + "Post body must be properly rendered"); + + let rawPostContent = tabBody.querySelector( + ".netInfoGroup.raw.opened .netInfoGroupContent"); + ok(!rawPostContent, "Raw response group must be collapsed"); +}); + +add_task(function* () { + info("Test XHR Spy post XML body started"); + + let {hud} = yield addTestTab(TEST_PAGE_URL); + + let netInfoBody = yield executeAndInspectXhr(hud, { + method: "POST", + url: JSON_XHR_URL, + body: xmlPostBody, + requestHeaders: [{ + name: "Content-Type", + value: "application/xml" + }] + }); + + // Check post body data + let tabBody = yield selectNetInfoTab(hud, netInfoBody, "post"); + let rawPostContent = tabBody.querySelector( + ".netInfoGroup.raw.opened .netInfoGroupContent"); + is(rawPostContent.textContent, xmlPostBody, + "Raw response group must not be collapsed"); +}); diff --git a/devtools/client/webconsole/net/test/mochitest/browser_net_response.js b/devtools/client/webconsole/net/test/mochitest/browser_net_response.js new file mode 100644 index 000000000..ec5543043 --- /dev/null +++ b/devtools/client/webconsole/net/test/mochitest/browser_net_response.js @@ -0,0 +1,86 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const TEST_PAGE_URL = URL_ROOT + "page_basic.html"; +const TEXT_XHR_URL = URL_ROOT + "test.txt"; +const JSON_XHR_URL = URL_ROOT + "test.json"; +const XML_XHR_URL = URL_ROOT + "test.xml"; + +const textResponseBody = "this is a response"; +const jsonResponseBody = "name\"John\""; + +// Individual tests below generate XHR request in the page, expand +// network details in the Console panel and checks various types +// of response bodies. + +/** + * Validate plain text response + */ +add_task(function* () { + info("Test XHR Spy respone plain body started"); + + let {hud} = yield addTestTab(TEST_PAGE_URL); + + let netInfoBody = yield executeAndInspectXhr(hud, { + method: "GET", + url: TEXT_XHR_URL, + }); + + // Check response body data + let tabBody = yield selectNetInfoTab(hud, netInfoBody, "response"); + let responseContent = tabBody.querySelector( + ".netInfoGroup.raw.opened .netInfoGroupContent"); + + ok(responseContent.textContent.indexOf(textResponseBody) > -1, + "Response body must be properly rendered"); +}); + +/** + * Validate XML response + */ +add_task(function* () { + info("Test XHR Spy response XML body started"); + + let {hud} = yield addTestTab(TEST_PAGE_URL); + + let netInfoBody = yield executeAndInspectXhr(hud, { + method: "GET", + url: XML_XHR_URL, + }); + + // Check response body data + let tabBody = yield selectNetInfoTab(hud, netInfoBody, "response"); + let rawResponseContent = tabBody.querySelector( + ".netInfoGroup.raw.opened .netInfoGroupContent"); + ok(rawResponseContent, "Raw response group must not be collapsed"); +}); + +/** + * Validate JSON response + */ +add_task(function* () { + info("Test XHR Spy response JSON body started"); + + let {hud} = yield addTestTab(TEST_PAGE_URL); + + let netInfoBody = yield executeAndInspectXhr(hud, { + method: "GET", + url: JSON_XHR_URL, + }); + + // Check response body data + let tabBody = yield selectNetInfoTab(hud, netInfoBody, "response"); + let responseContent = tabBody.querySelector( + ".netInfoGroup.json .netInfoGroupContent"); + + is(responseContent.textContent, jsonResponseBody, + "Response body must be properly rendered"); + + let rawResponseContent = tabBody.querySelector( + ".netInfoGroup.raw.opened .netInfoGroupContent"); + ok(!rawResponseContent, "Raw response group must be collapsed"); +}); diff --git a/devtools/client/webconsole/net/test/mochitest/head.js b/devtools/client/webconsole/net/test/mochitest/head.js new file mode 100644 index 000000000..c01206948 --- /dev/null +++ b/devtools/client/webconsole/net/test/mochitest/head.js @@ -0,0 +1,209 @@ +/* vim: set ts=2 et sw=2 tw=80: */ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint no-unused-vars: [2, {"vars": "local", "args": "none"}] */ +/* import-globals-from ../../../test/head.js */ + +"use strict"; + +// Load Web Console head.js, it implements helper console test API +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/devtools/client/webconsole/test/head.js", this); + +const FRAME_SCRIPT_UTILS_URL = + "chrome://devtools/content/shared/frame-script-utils.js"; + +const NET_INFO_PREF = "devtools.webconsole.filter.networkinfo"; +const NET_XHR_PREF = "devtools.webconsole.filter.netxhr"; + +// Enable XHR logging for the test +Services.prefs.setBoolPref(NET_INFO_PREF, true); +Services.prefs.setBoolPref(NET_XHR_PREF, true); + +registerCleanupFunction(() => { + Services.prefs.clearUserPref(NET_INFO_PREF, true); + Services.prefs.clearUserPref(NET_XHR_PREF, true); +}); + +// Use the old webconsole since the new one doesn't yet support +// XHR spy. See Bug 1304794. +Services.prefs.setBoolPref("devtools.webconsole.new-frontend-enabled", false); +registerCleanupFunction(function* () { + Services.prefs.clearUserPref("devtools.webconsole.new-frontend-enabled"); +}); + +/** + * Add a new test tab in the browser and load the given url. + * @param {String} url The url to be loaded in the new tab + * @return a promise that resolves to the tab object when the url is loaded + */ +function addTestTab(url) { + info("Adding a new JSON tab with URL: '" + url + "'"); + + return Task.spawn(function* () { + let tab = yield addTab(url); + + // Load devtools/shared/frame-script-utils.js + loadCommonFrameScript(tab); + + // Open the Console panel + let hud = yield openConsole(); + + return { + tab: tab, + browser: tab.linkedBrowser, + hud: hud + }; + }); +} + +/** + * + * @param hud + * @param options + */ +function executeAndInspectXhr(hud, options) { + hud.jsterm.clearOutput(); + + options.queryString = options.queryString || ""; + + // Execute XHR in the content scope. + performRequestsInContent({ + method: options.method, + url: options.url + options.queryString, + body: options.body, + nocache: options.nocache, + requestHeaders: options.requestHeaders + }); + + return Task.spawn(function* () { + // Wait till the appropriate Net log appears in the Console panel. + let rules = yield waitForMessages({ + webconsole: hud, + messages: [{ + text: options.url, + category: CATEGORY_NETWORK, + severity: SEVERITY_INFO, + isXhr: true, + }] + }); + + // The log is here, get its parent element (className: 'message'). + let msg = [...rules[0].matched][0]; + let body = msg.querySelector(".message-body"); + + // Open XHR HTTP details body and wait till the UI fetches + // all necessary data from the backend. All RPD requests + // needs to be finished before we can continue testing. + yield synthesizeMouseClickSoon(hud, body); + yield waitForBackend(msg); + let netInfoBody = body.querySelector(".netInfoBody"); + ok(netInfoBody, "Net info body must exist"); + return netInfoBody; + }); +} + +/** + * Wait till XHR data are fetched from the backend (i.e. there are + * no pending RDP requests. + */ +function waitForBackend(element) { + if (!element.hasAttribute("loading")) { + return; + } + return once(element, "netlog-no-pending-requests", true); +} + +/** + * Select specific tab in XHR info body. + * + * @param netInfoBody The main XHR info body + * @param tabId Tab ID (possible values: 'headers', 'cookies', 'params', + * 'post', 'response'); + * + * @returns Tab body element. + */ +function selectNetInfoTab(hud, netInfoBody, tabId) { + let tab = netInfoBody.querySelector(".tabs-menu-item." + tabId); + ok(tab, "Tab must exist " + tabId); + + // Click to select specified tab and wait till its + // UI is populated with data from the backend. + // There must be no pending RDP requests before we can + // continue testing the UI. + return Task.spawn(function* () { + yield synthesizeMouseClickSoon(hud, tab); + let msg = getAncestorByClass(netInfoBody, "message"); + yield waitForBackend(msg); + let tabBody = netInfoBody.querySelector("." + tabId + "TabBox"); + ok(tabBody, "Tab body must exist"); + return tabBody; + }); +} + +/** + * Return parent node with specified class. + * + * @param node A child element + * @param className Specified class name. + * + * @returns A parent element. + */ +function getAncestorByClass(node, className) { + for (let parent = node; parent; parent = parent.parentNode) { + if (parent.classList && parent.classList.contains(className)) { + return parent; + } + } + return null; +} + +/** + * Synthesize asynchronous click event (with clean stack trace). + */ +function synthesizeMouseClickSoon(hud, element) { + return new Promise((resolve) => { + executeSoon(() => { + EventUtils.synthesizeMouse(element, 2, 2, {}, hud.iframeWindow); + resolve(); + }); + }); +} + +/** + * Execute XHR in the content scope. + */ +function performRequestsInContent(requests) { + info("Performing requests in the context of the content."); + return executeInContent("devtools:test:xhr", requests); +} + +function executeInContent(name, data = {}, objects = {}, + expectResponse = true) { + let mm = gBrowser.selectedBrowser.messageManager; + + mm.sendAsyncMessage(name, data, objects); + if (expectResponse) { + return waitForContentMessage(name); + } + + return Promise.resolve(); +} + +function waitForContentMessage(name) { + info("Expecting message " + name + " from content"); + + let mm = gBrowser.selectedBrowser.messageManager; + + return new Promise((resolve) => { + mm.addMessageListener(name, function onMessage(msg) { + mm.removeMessageListener(name, onMessage); + resolve(msg.data); + }); + }); +} + +function loadCommonFrameScript(tab) { + let browser = tab ? tab.linkedBrowser : gBrowser.selectedBrowser; + browser.messageManager.loadFrameScript(FRAME_SCRIPT_UTILS_URL, false); +} diff --git a/devtools/client/webconsole/net/test/mochitest/page_basic.html b/devtools/client/webconsole/net/test/mochitest/page_basic.html new file mode 100644 index 000000000..da7158492 --- /dev/null +++ b/devtools/client/webconsole/net/test/mochitest/page_basic.html @@ -0,0 +1,14 @@ +<!-- Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ --> +<!doctype html> +<html> + <head> + <meta charset="utf-8"/> + <title>XHR Spy test page</title> + </head> + <body> + <script type="text/javascript"> + document.cookie = "bar=foo"; + </script> + </body> +</html> diff --git a/devtools/client/webconsole/net/test/mochitest/test-cookies.json b/devtools/client/webconsole/net/test/mochitest/test-cookies.json new file mode 100644 index 000000000..b5e739025 --- /dev/null +++ b/devtools/client/webconsole/net/test/mochitest/test-cookies.json @@ -0,0 +1 @@ +{"name":"Cookies Test"} diff --git a/devtools/client/webconsole/net/test/mochitest/test-cookies.json^headers^ b/devtools/client/webconsole/net/test/mochitest/test-cookies.json^headers^ new file mode 100644 index 000000000..94a8c0c69 --- /dev/null +++ b/devtools/client/webconsole/net/test/mochitest/test-cookies.json^headers^ @@ -0,0 +1,2 @@ +Content-Type: application/json; charset=utf-8 +Set-Cookie: test=abc diff --git a/devtools/client/webconsole/net/test/mochitest/test.json b/devtools/client/webconsole/net/test/mochitest/test.json new file mode 100644 index 000000000..6548f8e3e --- /dev/null +++ b/devtools/client/webconsole/net/test/mochitest/test.json @@ -0,0 +1 @@ +{"name":"John"} diff --git a/devtools/client/webconsole/net/test/mochitest/test.json^headers^ b/devtools/client/webconsole/net/test/mochitest/test.json^headers^ new file mode 100644 index 000000000..6010bfd18 --- /dev/null +++ b/devtools/client/webconsole/net/test/mochitest/test.json^headers^ @@ -0,0 +1 @@ +Content-Type: application/json; charset=utf-8 diff --git a/devtools/client/webconsole/net/test/mochitest/test.txt b/devtools/client/webconsole/net/test/mochitest/test.txt new file mode 100644 index 000000000..af7014e11 --- /dev/null +++ b/devtools/client/webconsole/net/test/mochitest/test.txt @@ -0,0 +1 @@ +this is a response diff --git a/devtools/client/webconsole/net/test/mochitest/test.xml b/devtools/client/webconsole/net/test/mochitest/test.xml new file mode 100644 index 000000000..3749c8e5a --- /dev/null +++ b/devtools/client/webconsole/net/test/mochitest/test.xml @@ -0,0 +1 @@ +<xml><name>John</name></xml> diff --git a/devtools/client/webconsole/net/test/mochitest/test.xml^headers^ b/devtools/client/webconsole/net/test/mochitest/test.xml^headers^ new file mode 100644 index 000000000..10ecdf5f4 --- /dev/null +++ b/devtools/client/webconsole/net/test/mochitest/test.xml^headers^ @@ -0,0 +1 @@ +Content-Type: application/xml; charset=utf-8 |