summaryrefslogtreecommitdiffstats
path: root/devtools/client/debugger/src/components/SecondaryPanes/tests
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /devtools/client/debugger/src/components/SecondaryPanes/tests
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'devtools/client/debugger/src/components/SecondaryPanes/tests')
-rw-r--r--devtools/client/debugger/src/components/SecondaryPanes/tests/CommandBar.spec.js78
-rw-r--r--devtools/client/debugger/src/components/SecondaryPanes/tests/EventListeners.spec.js136
-rw-r--r--devtools/client/debugger/src/components/SecondaryPanes/tests/Expressions.spec.js77
-rw-r--r--devtools/client/debugger/src/components/SecondaryPanes/tests/XHRBreakpoints.spec.js341
-rw-r--r--devtools/client/debugger/src/components/SecondaryPanes/tests/__snapshots__/EventListeners.spec.js.snap408
-rw-r--r--devtools/client/debugger/src/components/SecondaryPanes/tests/__snapshots__/Expressions.spec.js.snap203
-rw-r--r--devtools/client/debugger/src/components/SecondaryPanes/tests/__snapshots__/XHRBreakpoints.spec.js.snap619
7 files changed, 1862 insertions, 0 deletions
diff --git a/devtools/client/debugger/src/components/SecondaryPanes/tests/CommandBar.spec.js b/devtools/client/debugger/src/components/SecondaryPanes/tests/CommandBar.spec.js
new file mode 100644
index 0000000000..b82997eb9a
--- /dev/null
+++ b/devtools/client/debugger/src/components/SecondaryPanes/tests/CommandBar.spec.js
@@ -0,0 +1,78 @@
+/* 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/>. */
+
+import React from "devtools/client/shared/vendor/react";
+import { shallow } from "enzyme";
+import CommandBar from "../CommandBar";
+
+describe("CommandBar", () => {
+ it("f8 key command calls props.breakOnNext when not in paused state", () => {
+ const props = {
+ breakOnNext: jest.fn(),
+ resume: jest.fn(),
+ isPaused: false,
+ };
+ const mockEvent = {
+ preventDefault: jest.fn(),
+ stopPropagation: jest.fn(),
+ };
+
+ // The "on" spy will see all the keyboard listeners being registered by
+ // the shortcuts.on function
+ const context = { shortcuts: { on: jest.fn() } };
+
+ shallow(React.createElement(CommandBar.WrappedComponent, props), {
+ context,
+ });
+
+ // get the keyboard event listeners recorded from the "on" spy.
+ // this will be an array where each item is itself a two item array
+ // containing the key code and the corresponding handler for that key code
+ const keyEventHandlers = context.shortcuts.on.mock.calls;
+
+ // simulate pressing the F8 key by calling the F8 handlers
+ keyEventHandlers
+ .filter(i => i[0] === "F8")
+ .forEach(([_, handler]) => {
+ handler(mockEvent);
+ });
+
+ expect(props.breakOnNext).toHaveBeenCalled();
+ expect(props.resume).not.toHaveBeenCalled();
+ });
+
+ it("f8 key command calls props.resume when in paused state", () => {
+ const props = {
+ breakOnNext: jest.fn(),
+ resume: jest.fn(),
+ isPaused: true,
+ };
+ const mockEvent = {
+ preventDefault: jest.fn(),
+ stopPropagation: jest.fn(),
+ };
+
+ // The "on" spy will see all the keyboard listeners being registered by
+ // the shortcuts.on function
+ const context = { shortcuts: { on: jest.fn() } };
+
+ shallow(React.createElement(CommandBar.WrappedComponent, props), {
+ context,
+ });
+
+ // get the keyboard event listeners recorded from the "on" spy.
+ // this will be an array where each item is itself a two item array
+ // containing the key code and the corresponding handler for that key code
+ const keyEventHandlers = context.shortcuts.on.mock.calls;
+
+ // simulate pressing the F8 key by calling the F8 handlers
+ keyEventHandlers
+ .filter(i => i[0] === "F8")
+ .forEach(([_, handler]) => {
+ handler(mockEvent);
+ });
+ expect(props.resume).toHaveBeenCalled();
+ expect(props.breakOnNext).not.toHaveBeenCalled();
+ });
+});
diff --git a/devtools/client/debugger/src/components/SecondaryPanes/tests/EventListeners.spec.js b/devtools/client/debugger/src/components/SecondaryPanes/tests/EventListeners.spec.js
new file mode 100644
index 0000000000..58d7776e5a
--- /dev/null
+++ b/devtools/client/debugger/src/components/SecondaryPanes/tests/EventListeners.spec.js
@@ -0,0 +1,136 @@
+/* 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/>. */
+
+import React from "devtools/client/shared/vendor/react";
+import { shallow } from "enzyme";
+import EventListeners from "../EventListeners";
+
+function getCategories() {
+ return [
+ {
+ name: "Category 1",
+ events: [
+ { name: "Subcategory 1", id: "category1.subcategory1" },
+ { name: "Subcategory 2", id: "category1.subcategory2" },
+ ],
+ },
+ {
+ name: "Category 2",
+ events: [
+ { name: "Subcategory 3", id: "category2.subcategory1" },
+ { name: "Subcategory 4", id: "category2.subcategory2" },
+ ],
+ },
+ ];
+}
+
+function generateDefaults(overrides = {}) {
+ const defaults = {
+ activeEventListeners: [],
+ expandedCategories: [],
+ categories: [],
+ };
+
+ return { ...defaults, ...overrides };
+}
+
+function render(overrides = {}) {
+ const props = generateDefaults(overrides);
+ const component = shallow(
+ React.createElement(EventListeners.WrappedComponent, props)
+ );
+ return { component, props };
+}
+
+describe("EventListeners", () => {
+ it("should render", async () => {
+ const { component } = render();
+ expect(component).toMatchSnapshot();
+ });
+
+ it("should render categories appropriately", async () => {
+ const props = {
+ ...generateDefaults(),
+ categories: getCategories(),
+ };
+ const { component } = render(props);
+ expect(component).toMatchSnapshot();
+ });
+
+ it("should render expanded categories appropriately", async () => {
+ const props = {
+ ...generateDefaults(),
+ categories: getCategories(),
+ expandedCategories: ["Category 2"],
+ };
+ const { component } = render(props);
+ expect(component).toMatchSnapshot();
+ });
+
+ it("should render checked subcategories appropriately", async () => {
+ const props = {
+ ...generateDefaults(),
+ categories: getCategories(),
+ activeEventListeners: ["category1.subcategory2"],
+ expandedCategories: ["Category 1"],
+ };
+ const { component } = render(props);
+ expect(component).toMatchSnapshot();
+ });
+
+ it("should filter the event listeners based on the event name", async () => {
+ const props = {
+ ...generateDefaults(),
+ categories: getCategories(),
+ };
+ const { component } = render(props);
+ component.find(".event-search-input").simulate("focus");
+
+ const searchInput = component.find(".event-search-input");
+ // Simulate a search query of "Subcategory 3" to display just one event which
+ // will be the Subcategory 3 event
+ searchInput.simulate("change", {
+ currentTarget: { value: "Subcategory 3" },
+ });
+
+ const displayedEvents = component.find(".event-listener-event");
+ expect(displayedEvents).toHaveLength(1);
+ });
+
+ it("should filter the event listeners based on the category name", async () => {
+ const props = {
+ ...generateDefaults(),
+ categories: getCategories(),
+ };
+ const { component } = render(props);
+ component.find(".event-search-input").simulate("focus");
+
+ const searchInput = component.find(".event-search-input");
+ // Simulate a search query of "Category 1" to display two events which will be
+ // the Subcategory 1 event and the Subcategory 2 event
+ searchInput.simulate("change", { currentTarget: { value: "Category 1" } });
+
+ const displayedEvents = component.find(".event-listener-event");
+ expect(displayedEvents).toHaveLength(2);
+ });
+
+ it("should be case insensitive when filtering events and categories", async () => {
+ const props = {
+ ...generateDefaults(),
+ categories: getCategories(),
+ };
+ const { component } = render(props);
+ component.find(".event-search-input").simulate("focus");
+
+ const searchInput = component.find(".event-search-input");
+ // Simulate a search query of "Subcategory 3" to display just one event which
+ // will be the Subcategory 3 event
+ searchInput.simulate("change", {
+ currentTarget: { value: "sUbCaTeGoRy 3" },
+ });
+
+ const displayedEvents = component.find(".event-listener-event");
+ expect(displayedEvents).toHaveLength(1);
+ });
+});
diff --git a/devtools/client/debugger/src/components/SecondaryPanes/tests/Expressions.spec.js b/devtools/client/debugger/src/components/SecondaryPanes/tests/Expressions.spec.js
new file mode 100644
index 0000000000..685c636f05
--- /dev/null
+++ b/devtools/client/debugger/src/components/SecondaryPanes/tests/Expressions.spec.js
@@ -0,0 +1,77 @@
+/* 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/>. */
+
+import React from "devtools/client/shared/vendor/react";
+import { shallow } from "enzyme";
+import Expressions from "../Expressions";
+
+function generateDefaults(overrides) {
+ return {
+ evaluateExpressions: async () => {},
+ expressions: [
+ {
+ input: "expression1",
+ value: {
+ result: {
+ value: "foo",
+ class: "",
+ },
+ },
+ },
+ {
+ input: "expression2",
+ value: {
+ result: {
+ value: "bar",
+ class: "",
+ },
+ },
+ },
+ ],
+ ...overrides,
+ };
+}
+
+function render(overrides = {}) {
+ const props = generateDefaults(overrides);
+ const component = shallow(
+ React.createElement(Expressions.WrappedComponent, props)
+ );
+ return { component, props };
+}
+
+describe("Expressions", () => {
+ it("should render", async () => {
+ const { component } = render();
+ expect(component).toMatchSnapshot();
+ });
+
+ it("should always have unique keys", async () => {
+ const overrides = {
+ expressions: [
+ {
+ input: "expression1",
+ value: {
+ result: {
+ value: undefined,
+ class: "",
+ },
+ },
+ },
+ {
+ input: "expression2",
+ value: {
+ result: {
+ value: undefined,
+ class: "",
+ },
+ },
+ },
+ ],
+ };
+
+ const { component } = render(overrides);
+ expect(component).toMatchSnapshot();
+ });
+});
diff --git a/devtools/client/debugger/src/components/SecondaryPanes/tests/XHRBreakpoints.spec.js b/devtools/client/debugger/src/components/SecondaryPanes/tests/XHRBreakpoints.spec.js
new file mode 100644
index 0000000000..532c95e4ad
--- /dev/null
+++ b/devtools/client/debugger/src/components/SecondaryPanes/tests/XHRBreakpoints.spec.js
@@ -0,0 +1,341 @@
+/* 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/>. */
+
+import React from "devtools/client/shared/vendor/react";
+import { mount } from "enzyme";
+import XHRBreakpoints from "../XHRBreakpoints";
+
+const xhrMethods = [
+ "ANY",
+ "GET",
+ "POST",
+ "PUT",
+ "HEAD",
+ "DELETE",
+ "PATCH",
+ "OPTIONS",
+];
+
+// default state includes xhrBreakpoints[0] which is the checkbox that
+// enables breaking on any url during an XMLHTTPRequest
+function generateDefaultState(propsOverride) {
+ return {
+ xhrBreakpoints: [
+ {
+ path: "",
+ method: "ANY",
+ disabled: false,
+ loading: false,
+ text: 'URL contains ""',
+ },
+ ],
+ enableXHRBreakpoint: () => {},
+ disableXHRBreakpoint: () => {},
+ updateXHRBreakpoint: () => {},
+ removeXHRBreakpoint: () => {},
+ setXHRBreakpoint: () => {},
+ togglePauseOnAny: () => {},
+ showInput: false,
+ shouldPauseOnAny: false,
+ onXHRAdded: () => {},
+ ...propsOverride,
+ };
+}
+
+function renderXHRBreakpointsComponent(propsOverride) {
+ const props = generateDefaultState(propsOverride);
+ const xhrBreakpointsComponent = mount(
+ React.createElement(XHRBreakpoints.WrappedComponent, props)
+ );
+ return xhrBreakpointsComponent;
+}
+
+describe("XHR Breakpoints", function () {
+ it("should render with 0 expressions passed from props", function () {
+ const xhrBreakpointsComponent = renderXHRBreakpointsComponent();
+ expect(xhrBreakpointsComponent).toMatchSnapshot();
+ });
+
+ it("should render with 8 expressions passed from props", function () {
+ const allXHRBreakpointMethods = {
+ xhrBreakpoints: [
+ {
+ path: "",
+ method: "ANY",
+ disabled: false,
+ loading: false,
+ text: 'URL contains ""',
+ },
+ {
+ path: "this is any",
+ method: "ANY",
+ disabled: false,
+ loading: false,
+ text: 'URL contains "this is any"',
+ },
+ {
+ path: "this is get",
+ method: "GET",
+ disabled: false,
+ loading: false,
+ text: 'URL contains "this is get"',
+ },
+ {
+ path: "this is post",
+ method: "POST",
+ disabled: false,
+ loading: false,
+ text: 'URL contains "this is post"',
+ },
+ {
+ path: "this is put",
+ method: "PUT",
+ disabled: false,
+ loading: false,
+ text: 'URL contains "this is put"',
+ },
+ {
+ path: "this is head",
+ method: "HEAD",
+ disabled: false,
+ loading: false,
+ text: 'URL contains "this is head"',
+ },
+ {
+ path: "this is delete",
+ method: "DELETE",
+ disabled: false,
+ loading: false,
+ text: 'URL contains "this is delete"',
+ },
+ {
+ path: "this is patch",
+ method: "PATCH",
+ disabled: false,
+ loading: false,
+ text: 'URL contains "this is patch"',
+ },
+ {
+ path: "this is options",
+ method: "OPTIONS",
+ disabled: false,
+ loading: false,
+ text: 'URL contains "this is options"',
+ },
+ ],
+ };
+
+ const xhrBreakpointsComponent = renderXHRBreakpointsComponent(
+ allXHRBreakpointMethods
+ );
+ expect(xhrBreakpointsComponent).toMatchSnapshot();
+ });
+
+ it("should display xhr-input-method on click", function () {
+ const xhrBreakpointsComponent = renderXHRBreakpointsComponent();
+ xhrBreakpointsComponent.find(".xhr-input-url").simulate("focus");
+
+ const xhrInputContainer = xhrBreakpointsComponent.find(
+ ".xhr-input-container"
+ );
+ expect(xhrInputContainer.hasClass("focused")).toBeTruthy();
+ });
+
+ it("should have focused and editing default to false", function () {
+ const xhrBreakpointsComponent = renderXHRBreakpointsComponent();
+ expect(xhrBreakpointsComponent.state("focused")).toBe(false);
+ expect(xhrBreakpointsComponent.state("editing")).toBe(false);
+ });
+
+ it("should have state {..focused: true, editing: true} on focus", function () {
+ const xhrBreakpointsComponent = renderXHRBreakpointsComponent();
+ xhrBreakpointsComponent.find(".xhr-input-url").simulate("focus");
+ expect(xhrBreakpointsComponent.state("focused")).toBe(true);
+ expect(xhrBreakpointsComponent.state("editing")).toBe(true);
+ });
+
+ // shifting focus from .xhr-input to any other element apart from
+ // .xhr-input-method should unrender .xhr-input-method
+ it("shifting focus should unrender XHR methods", function () {
+ const propsOverride = {
+ onXHRAdded: jest.fn,
+ togglePauseOnAny: jest.fn,
+ };
+ const xhrBreakpointsComponent =
+ renderXHRBreakpointsComponent(propsOverride);
+ xhrBreakpointsComponent.find(".xhr-input-url").simulate("focus");
+ let xhrInputContainer = xhrBreakpointsComponent.find(
+ ".xhr-input-container"
+ );
+ expect(xhrInputContainer.hasClass("focused")).toBeTruthy();
+
+ xhrBreakpointsComponent.find(".breakpoints-options").simulate("mousedown");
+ expect(xhrBreakpointsComponent.state("focused")).toBe(true);
+ expect(xhrBreakpointsComponent.state("editing")).toBe(true);
+ expect(xhrBreakpointsComponent.state("clickedOnFormElement")).toBe(false);
+
+ xhrBreakpointsComponent.find(".xhr-input-url").simulate("blur");
+ expect(xhrBreakpointsComponent.state("focused")).toBe(false);
+ expect(xhrBreakpointsComponent.state("editing")).toBe(false);
+ expect(xhrBreakpointsComponent.state("clickedOnFormElement")).toBe(false);
+
+ xhrBreakpointsComponent.find(".breakpoints-options").simulate("click");
+
+ xhrInputContainer = xhrBreakpointsComponent.find(".xhr-input-container");
+ expect(xhrInputContainer.hasClass("focused")).not.toBeTruthy();
+ });
+
+ // shifting focus from .xhr-input to .xhr-input-method
+ // should not unrender .xhr-input-method
+ it("shifting focus to XHR methods should not unrender", function () {
+ const xhrBreakpointsComponent = renderXHRBreakpointsComponent();
+ xhrBreakpointsComponent.find(".xhr-input-url").simulate("focus");
+
+ xhrBreakpointsComponent.find(".xhr-input-method").simulate("mousedown");
+ expect(xhrBreakpointsComponent.state("focused")).toBe(true);
+ expect(xhrBreakpointsComponent.state("editing")).toBe(false);
+ expect(xhrBreakpointsComponent.state("clickedOnFormElement")).toBe(true);
+
+ xhrBreakpointsComponent.find(".xhr-input-url").simulate("blur");
+ expect(xhrBreakpointsComponent.state("focused")).toBe(true);
+ expect(xhrBreakpointsComponent.state("editing")).toBe(false);
+ expect(xhrBreakpointsComponent.state("clickedOnFormElement")).toBe(false);
+
+ xhrBreakpointsComponent.find(".xhr-input-method").simulate("click");
+ const xhrInputContainer = xhrBreakpointsComponent.find(
+ ".xhr-input-container"
+ );
+ expect(xhrInputContainer.hasClass("focused")).toBeTruthy();
+ });
+
+ it("should have all 8 methods available as options", function () {
+ const xhrBreakpointsComponent = renderXHRBreakpointsComponent();
+ xhrBreakpointsComponent.find(".xhr-input-url").simulate("focus");
+
+ const xhrInputMethod = xhrBreakpointsComponent.find(".xhr-input-method");
+ expect(xhrInputMethod.children()).toHaveLength(8);
+
+ const actualXHRMethods = [];
+ const expectedXHRMethods = xhrMethods;
+
+ // fill the actualXHRMethods array with actual methods displayed in DOM
+ for (let i = 0; i < xhrInputMethod.children().length; i++) {
+ actualXHRMethods.push(xhrInputMethod.childAt(i).key());
+ }
+
+ // check each expected XHR Method to see if they match the actual methods
+ expectedXHRMethods.forEach((expectedMethod, i) => {
+ function compareMethods(actualMethod) {
+ return expectedMethod === actualMethod;
+ }
+ expect(actualXHRMethods.find(compareMethods)).toBeTruthy();
+ });
+ });
+
+ it("should return focus to input box after selecting a method", function () {
+ const xhrBreakpointsComponent = renderXHRBreakpointsComponent();
+
+ // focus starts off at .xhr-input
+ xhrBreakpointsComponent.find(".xhr-input-url").simulate("focus");
+
+ // click on method options and select GET
+ const methodEvent = { target: { value: "GET" } };
+ xhrBreakpointsComponent.find(".xhr-input-method").simulate("mousedown");
+ expect(xhrBreakpointsComponent.state("inputMethod")).toBe("ANY");
+ expect(xhrBreakpointsComponent.state("editing")).toBe(false);
+ xhrBreakpointsComponent
+ .find(".xhr-input-method")
+ .simulate("change", methodEvent);
+
+ // if state.editing changes from false to true, infer that
+ // this._input.focus() is called, which shifts focus back to input box
+ expect(xhrBreakpointsComponent.state("inputMethod")).toBe("GET");
+ expect(xhrBreakpointsComponent.state("editing")).toBe(true);
+ });
+
+ it("should submit the URL and method when adding a breakpoint", function () {
+ const setXHRBreakpointCallback = jest.fn();
+ const propsOverride = {
+ setXHRBreakpoint: setXHRBreakpointCallback,
+ onXHRAdded: jest.fn(),
+ };
+ const mockEvent = {
+ preventDefault: jest.fn(),
+ stopPropagation: jest.fn(),
+ };
+ const availableXHRMethods = xhrMethods;
+ expect(!!availableXHRMethods.length).toBeTruthy();
+
+ // check each of the available methods to see whether
+ // adding them as a method to a new breakpoint works as expected
+ availableXHRMethods.forEach(function (method) {
+ const xhrBreakpointsComponent =
+ renderXHRBreakpointsComponent(propsOverride);
+ xhrBreakpointsComponent.find(".xhr-input-url").simulate("focus");
+ const urlValue = `${method.toLowerCase()}URLValue`;
+
+ // simulate DOM event adding urlValue to .xhr-input
+ const xhrInput = xhrBreakpointsComponent.find(".xhr-input-url");
+ xhrInput.simulate("change", { target: { value: urlValue } });
+
+ // simulate DOM event adding the input method to .xhr-input-method
+ const xhrInputMethod = xhrBreakpointsComponent.find(".xhr-input-method");
+ xhrInputMethod.simulate("change", { target: { value: method } });
+
+ xhrBreakpointsComponent.find("form").simulate("submit", mockEvent);
+ expect(setXHRBreakpointCallback).toHaveBeenCalledWith(urlValue, method);
+ });
+ });
+
+ it("should submit the URL and method when editing a breakpoint", function () {
+ const setXHRBreakpointCallback = jest.fn();
+ const mockEvent = {
+ preventDefault: jest.fn(),
+ stopPropagation: jest.fn(),
+ };
+ const propsOverride = {
+ updateXHRBreakpoint: setXHRBreakpointCallback,
+ onXHRAdded: jest.fn(),
+ xhrBreakpoints: [
+ {
+ path: "",
+ method: "ANY",
+ disabled: false,
+ loading: false,
+ text: 'URL contains ""',
+ },
+ {
+ path: "this is GET",
+ method: "GET",
+ disabled: false,
+ loading: false,
+ text: 'URL contains "this is get"',
+ },
+ ],
+ };
+ const xhrBreakpointsComponent =
+ renderXHRBreakpointsComponent(propsOverride);
+
+ // load xhrBreakpoints pane with one existing xhrBreakpoint
+ const existingXHRbreakpoint =
+ xhrBreakpointsComponent.find(".xhr-container");
+ expect(existingXHRbreakpoint).toHaveLength(1);
+
+ // double click on existing breakpoint
+ existingXHRbreakpoint.simulate("doubleclick");
+ const xhrInput = xhrBreakpointsComponent.find(".xhr-input-url");
+ xhrInput.simulate("focus");
+
+ // change inputs and submit form
+ const xhrInputMethod = xhrBreakpointsComponent.find(".xhr-input-method");
+ xhrInput.simulate("change", { target: { value: "POSTURLValue" } });
+ xhrInputMethod.simulate("change", { target: { value: "POST" } });
+ xhrBreakpointsComponent.find("form").simulate("submit", mockEvent);
+ expect(setXHRBreakpointCallback).toHaveBeenCalledWith(
+ 1,
+ "POSTURLValue",
+ "POST"
+ );
+ });
+});
diff --git a/devtools/client/debugger/src/components/SecondaryPanes/tests/__snapshots__/EventListeners.spec.js.snap b/devtools/client/debugger/src/components/SecondaryPanes/tests/__snapshots__/EventListeners.spec.js.snap
new file mode 100644
index 0000000000..cc2ddf09f6
--- /dev/null
+++ b/devtools/client/debugger/src/components/SecondaryPanes/tests/__snapshots__/EventListeners.spec.js.snap
@@ -0,0 +1,408 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`EventListeners should render 1`] = `
+<div
+ className="event-listeners"
+>
+ <div
+ className="event-search-container"
+ >
+ <form
+ className="event-search-form"
+ onSubmit={[Function]}
+ >
+ <input
+ className="event-search-input"
+ onBlur={[Function]}
+ onChange={[Function]}
+ onFocus={[Function]}
+ onKeyDown={[Function]}
+ placeholder="Filter by event type"
+ value=""
+ />
+ </form>
+ </div>
+ <div
+ className="event-listeners-content"
+ >
+ <ul
+ className="event-listeners-list"
+ />
+ </div>
+</div>
+`;
+
+exports[`EventListeners should render categories appropriately 1`] = `
+<div
+ className="event-listeners"
+>
+ <div
+ className="event-search-container"
+ >
+ <form
+ className="event-search-form"
+ onSubmit={[Function]}
+ >
+ <input
+ className="event-search-input"
+ onBlur={[Function]}
+ onChange={[Function]}
+ onFocus={[Function]}
+ onKeyDown={[Function]}
+ placeholder="Filter by event type"
+ value=""
+ />
+ </form>
+ </div>
+ <div
+ className="event-listeners-content"
+ >
+ <ul
+ className="event-listeners-list"
+ >
+ <li
+ className="event-listener-group"
+ key="0"
+ >
+ <div
+ className="event-listener-header"
+ >
+ <button
+ className="event-listener-expand"
+ onClick={[Function]}
+ >
+ <AccessibleImage
+ className="arrow"
+ />
+ </button>
+ <label
+ className="event-listener-label"
+ >
+ <input
+ checked={false}
+ onChange={[Function]}
+ type="checkbox"
+ value="Category 1"
+ />
+ <span
+ className="event-listener-category"
+ >
+ Category 1
+ </span>
+ </label>
+ </div>
+ </li>
+ <li
+ className="event-listener-group"
+ key="1"
+ >
+ <div
+ className="event-listener-header"
+ >
+ <button
+ className="event-listener-expand"
+ onClick={[Function]}
+ >
+ <AccessibleImage
+ className="arrow"
+ />
+ </button>
+ <label
+ className="event-listener-label"
+ >
+ <input
+ checked={false}
+ onChange={[Function]}
+ type="checkbox"
+ value="Category 2"
+ />
+ <span
+ className="event-listener-category"
+ >
+ Category 2
+ </span>
+ </label>
+ </div>
+ </li>
+ </ul>
+ </div>
+</div>
+`;
+
+exports[`EventListeners should render checked subcategories appropriately 1`] = `
+<div
+ className="event-listeners"
+>
+ <div
+ className="event-search-container"
+ >
+ <form
+ className="event-search-form"
+ onSubmit={[Function]}
+ >
+ <input
+ className="event-search-input"
+ onBlur={[Function]}
+ onChange={[Function]}
+ onFocus={[Function]}
+ onKeyDown={[Function]}
+ placeholder="Filter by event type"
+ value=""
+ />
+ </form>
+ </div>
+ <div
+ className="event-listeners-content"
+ >
+ <ul
+ className="event-listeners-list"
+ >
+ <li
+ className="event-listener-group"
+ key="0"
+ >
+ <div
+ className="event-listener-header"
+ >
+ <button
+ className="event-listener-expand"
+ onClick={[Function]}
+ >
+ <AccessibleImage
+ className="arrow expanded"
+ />
+ </button>
+ <label
+ className="event-listener-label"
+ >
+ <input
+ checked={false}
+ onChange={[Function]}
+ type="checkbox"
+ value="Category 1"
+ />
+ <span
+ className="event-listener-category"
+ >
+ Category 1
+ </span>
+ </label>
+ </div>
+ <ul>
+ <li
+ className="event-listener-event"
+ key="category1.subcategory1"
+ >
+ <label
+ className="event-listener-label"
+ >
+ <input
+ checked={false}
+ onChange={[Function]}
+ type="checkbox"
+ value="category1.subcategory1"
+ />
+ <span
+ className="event-listener-name"
+ >
+ Subcategory 1
+ </span>
+ </label>
+ </li>
+ <li
+ className="event-listener-event"
+ key="category1.subcategory2"
+ >
+ <label
+ className="event-listener-label"
+ >
+ <input
+ checked={true}
+ onChange={[Function]}
+ type="checkbox"
+ value="category1.subcategory2"
+ />
+ <span
+ className="event-listener-name"
+ >
+ Subcategory 2
+ </span>
+ </label>
+ </li>
+ </ul>
+ </li>
+ <li
+ className="event-listener-group"
+ key="1"
+ >
+ <div
+ className="event-listener-header"
+ >
+ <button
+ className="event-listener-expand"
+ onClick={[Function]}
+ >
+ <AccessibleImage
+ className="arrow"
+ />
+ </button>
+ <label
+ className="event-listener-label"
+ >
+ <input
+ checked={false}
+ onChange={[Function]}
+ type="checkbox"
+ value="Category 2"
+ />
+ <span
+ className="event-listener-category"
+ >
+ Category 2
+ </span>
+ </label>
+ </div>
+ </li>
+ </ul>
+ </div>
+</div>
+`;
+
+exports[`EventListeners should render expanded categories appropriately 1`] = `
+<div
+ className="event-listeners"
+>
+ <div
+ className="event-search-container"
+ >
+ <form
+ className="event-search-form"
+ onSubmit={[Function]}
+ >
+ <input
+ className="event-search-input"
+ onBlur={[Function]}
+ onChange={[Function]}
+ onFocus={[Function]}
+ onKeyDown={[Function]}
+ placeholder="Filter by event type"
+ value=""
+ />
+ </form>
+ </div>
+ <div
+ className="event-listeners-content"
+ >
+ <ul
+ className="event-listeners-list"
+ >
+ <li
+ className="event-listener-group"
+ key="0"
+ >
+ <div
+ className="event-listener-header"
+ >
+ <button
+ className="event-listener-expand"
+ onClick={[Function]}
+ >
+ <AccessibleImage
+ className="arrow"
+ />
+ </button>
+ <label
+ className="event-listener-label"
+ >
+ <input
+ checked={false}
+ onChange={[Function]}
+ type="checkbox"
+ value="Category 1"
+ />
+ <span
+ className="event-listener-category"
+ >
+ Category 1
+ </span>
+ </label>
+ </div>
+ </li>
+ <li
+ className="event-listener-group"
+ key="1"
+ >
+ <div
+ className="event-listener-header"
+ >
+ <button
+ className="event-listener-expand"
+ onClick={[Function]}
+ >
+ <AccessibleImage
+ className="arrow expanded"
+ />
+ </button>
+ <label
+ className="event-listener-label"
+ >
+ <input
+ checked={false}
+ onChange={[Function]}
+ type="checkbox"
+ value="Category 2"
+ />
+ <span
+ className="event-listener-category"
+ >
+ Category 2
+ </span>
+ </label>
+ </div>
+ <ul>
+ <li
+ className="event-listener-event"
+ key="category2.subcategory1"
+ >
+ <label
+ className="event-listener-label"
+ >
+ <input
+ checked={false}
+ onChange={[Function]}
+ type="checkbox"
+ value="category2.subcategory1"
+ />
+ <span
+ className="event-listener-name"
+ >
+ Subcategory 3
+ </span>
+ </label>
+ </li>
+ <li
+ className="event-listener-event"
+ key="category2.subcategory2"
+ >
+ <label
+ className="event-listener-label"
+ >
+ <input
+ checked={false}
+ onChange={[Function]}
+ type="checkbox"
+ value="category2.subcategory2"
+ />
+ <span
+ className="event-listener-name"
+ >
+ Subcategory 4
+ </span>
+ </label>
+ </li>
+ </ul>
+ </li>
+ </ul>
+ </div>
+</div>
+`;
diff --git a/devtools/client/debugger/src/components/SecondaryPanes/tests/__snapshots__/Expressions.spec.js.snap b/devtools/client/debugger/src/components/SecondaryPanes/tests/__snapshots__/Expressions.spec.js.snap
new file mode 100644
index 0000000000..6ecf6c2c2e
--- /dev/null
+++ b/devtools/client/debugger/src/components/SecondaryPanes/tests/__snapshots__/Expressions.spec.js.snap
@@ -0,0 +1,203 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Expressions should always have unique keys 1`] = `
+<div
+ className="pane"
+>
+ <ul
+ className="pane expressions-list"
+ >
+ <li
+ className="expression-container"
+ key="expression1"
+ title="expression1"
+ >
+ <div
+ className="expression-content"
+ >
+ <Component
+ autoExpandDepth={0}
+ createElement={[Function]}
+ disableWrap={true}
+ mayUseCustomFormatter={true}
+ onDOMNodeClick={[Function]}
+ onDOMNodeMouseOut={[Function]}
+ onDOMNodeMouseOver={[Function]}
+ onDoubleClick={[Function]}
+ onInspectIconClick={[Function]}
+ roots={
+ Array [
+ Object {
+ "contents": Object {
+ "front": null,
+ "value": Object {
+ "class": "",
+ "value": undefined,
+ },
+ },
+ "name": "expression1",
+ "path": "expression1",
+ },
+ ]
+ }
+ shouldRenderTooltip={true}
+ />
+ <div
+ className="expression-container__close-btn"
+ >
+ <CloseButton
+ handleClick={[Function]}
+ tooltip="Remove watch expression"
+ />
+ </div>
+ </div>
+ </li>
+ <li
+ className="expression-container"
+ key="expression2"
+ title="expression2"
+ >
+ <div
+ className="expression-content"
+ >
+ <Component
+ autoExpandDepth={0}
+ createElement={[Function]}
+ disableWrap={true}
+ mayUseCustomFormatter={true}
+ onDOMNodeClick={[Function]}
+ onDOMNodeMouseOut={[Function]}
+ onDOMNodeMouseOver={[Function]}
+ onDoubleClick={[Function]}
+ onInspectIconClick={[Function]}
+ roots={
+ Array [
+ Object {
+ "contents": Object {
+ "front": null,
+ "value": Object {
+ "class": "",
+ "value": undefined,
+ },
+ },
+ "name": "expression2",
+ "path": "expression2",
+ },
+ ]
+ }
+ shouldRenderTooltip={true}
+ />
+ <div
+ className="expression-container__close-btn"
+ >
+ <CloseButton
+ handleClick={[Function]}
+ tooltip="Remove watch expression"
+ />
+ </div>
+ </div>
+ </li>
+ </ul>
+</div>
+`;
+
+exports[`Expressions should render 1`] = `
+<div
+ className="pane"
+>
+ <ul
+ className="pane expressions-list"
+ >
+ <li
+ className="expression-container"
+ key="expression1"
+ title="expression1"
+ >
+ <div
+ className="expression-content"
+ >
+ <Component
+ autoExpandDepth={0}
+ createElement={[Function]}
+ disableWrap={true}
+ mayUseCustomFormatter={true}
+ onDOMNodeClick={[Function]}
+ onDOMNodeMouseOut={[Function]}
+ onDOMNodeMouseOver={[Function]}
+ onDoubleClick={[Function]}
+ onInspectIconClick={[Function]}
+ roots={
+ Array [
+ Object {
+ "contents": Object {
+ "front": null,
+ "value": Object {
+ "class": "",
+ "value": "foo",
+ },
+ },
+ "name": "expression1",
+ "path": "expression1",
+ },
+ ]
+ }
+ shouldRenderTooltip={true}
+ />
+ <div
+ className="expression-container__close-btn"
+ >
+ <CloseButton
+ handleClick={[Function]}
+ tooltip="Remove watch expression"
+ />
+ </div>
+ </div>
+ </li>
+ <li
+ className="expression-container"
+ key="expression2"
+ title="expression2"
+ >
+ <div
+ className="expression-content"
+ >
+ <Component
+ autoExpandDepth={0}
+ createElement={[Function]}
+ disableWrap={true}
+ mayUseCustomFormatter={true}
+ onDOMNodeClick={[Function]}
+ onDOMNodeMouseOut={[Function]}
+ onDOMNodeMouseOver={[Function]}
+ onDoubleClick={[Function]}
+ onInspectIconClick={[Function]}
+ roots={
+ Array [
+ Object {
+ "contents": Object {
+ "front": null,
+ "value": Object {
+ "class": "",
+ "value": "bar",
+ },
+ },
+ "name": "expression2",
+ "path": "expression2",
+ },
+ ]
+ }
+ shouldRenderTooltip={true}
+ />
+ <div
+ className="expression-container__close-btn"
+ >
+ <CloseButton
+ handleClick={[Function]}
+ tooltip="Remove watch expression"
+ />
+ </div>
+ </div>
+ </li>
+ </ul>
+</div>
+`;
diff --git a/devtools/client/debugger/src/components/SecondaryPanes/tests/__snapshots__/XHRBreakpoints.spec.js.snap b/devtools/client/debugger/src/components/SecondaryPanes/tests/__snapshots__/XHRBreakpoints.spec.js.snap
new file mode 100644
index 0000000000..e7c4527621
--- /dev/null
+++ b/devtools/client/debugger/src/components/SecondaryPanes/tests/__snapshots__/XHRBreakpoints.spec.js.snap
@@ -0,0 +1,619 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`XHR Breakpoints should render with 0 expressions passed from props 1`] = `
+<XHRBreakpoints
+ disableXHRBreakpoint={[Function]}
+ enableXHRBreakpoint={[Function]}
+ onXHRAdded={[Function]}
+ removeXHRBreakpoint={[Function]}
+ setXHRBreakpoint={[Function]}
+ shouldPauseOnAny={false}
+ showInput={false}
+ togglePauseOnAny={[Function]}
+ updateXHRBreakpoint={[Function]}
+ xhrBreakpoints={
+ Array [
+ Object {
+ "disabled": false,
+ "loading": false,
+ "method": "ANY",
+ "path": "",
+ "text": "URL contains \\"\\"",
+ },
+ ]
+ }
+>
+ <div
+ className="breakpoints-options empty"
+ >
+ <ExceptionOption
+ className="breakpoints-exceptions"
+ isChecked={false}
+ label="Pause on any URL"
+ onChange={[Function]}
+ >
+ <label
+ className="breakpoints-exceptions"
+ >
+ <input
+ checked={false}
+ onChange={[Function]}
+ type="checkbox"
+ />
+ <div
+ className="breakpoint-exceptions-label"
+ >
+ Pause on any URL
+ </div>
+ </label>
+ </ExceptionOption>
+ </div>
+ <form
+ className="xhr-input-container xhr-input-form"
+ key="xhr-input-container"
+ onSubmit={[Function]}
+ >
+ <input
+ className="xhr-input-url"
+ onBlur={[Function]}
+ onChange={[Function]}
+ onFocus={[Function]}
+ onKeyDown={[Function]}
+ placeholder="Break when URL contains"
+ type="text"
+ value=""
+ />
+ <select
+ className="xhr-input-method"
+ onChange={[Function]}
+ onKeyDown={[Function]}
+ onMouseDown={[Function]}
+ value="ANY"
+ >
+ <option
+ key="ANY"
+ onMouseDown={[Function]}
+ value="ANY"
+ >
+ ANY
+ </option>
+ <option
+ key="GET"
+ onMouseDown={[Function]}
+ value="GET"
+ >
+ GET
+ </option>
+ <option
+ key="POST"
+ onMouseDown={[Function]}
+ value="POST"
+ >
+ POST
+ </option>
+ <option
+ key="PUT"
+ onMouseDown={[Function]}
+ value="PUT"
+ >
+ PUT
+ </option>
+ <option
+ key="HEAD"
+ onMouseDown={[Function]}
+ value="HEAD"
+ >
+ HEAD
+ </option>
+ <option
+ key="DELETE"
+ onMouseDown={[Function]}
+ value="DELETE"
+ >
+ DELETE
+ </option>
+ <option
+ key="PATCH"
+ onMouseDown={[Function]}
+ value="PATCH"
+ >
+ PATCH
+ </option>
+ <option
+ key="OPTIONS"
+ onMouseDown={[Function]}
+ value="OPTIONS"
+ >
+ OPTIONS
+ </option>
+ </select>
+ <input
+ style={
+ Object {
+ "display": "none",
+ }
+ }
+ type="submit"
+ />
+ </form>
+</XHRBreakpoints>
+`;
+
+exports[`XHR Breakpoints should render with 8 expressions passed from props 1`] = `
+<XHRBreakpoints
+ disableXHRBreakpoint={[Function]}
+ enableXHRBreakpoint={[Function]}
+ onXHRAdded={[Function]}
+ removeXHRBreakpoint={[Function]}
+ setXHRBreakpoint={[Function]}
+ shouldPauseOnAny={false}
+ showInput={false}
+ togglePauseOnAny={[Function]}
+ updateXHRBreakpoint={[Function]}
+ xhrBreakpoints={
+ Array [
+ Object {
+ "disabled": false,
+ "loading": false,
+ "method": "ANY",
+ "path": "",
+ "text": "URL contains \\"\\"",
+ },
+ Object {
+ "disabled": false,
+ "loading": false,
+ "method": "ANY",
+ "path": "this is any",
+ "text": "URL contains \\"this is any\\"",
+ },
+ Object {
+ "disabled": false,
+ "loading": false,
+ "method": "GET",
+ "path": "this is get",
+ "text": "URL contains \\"this is get\\"",
+ },
+ Object {
+ "disabled": false,
+ "loading": false,
+ "method": "POST",
+ "path": "this is post",
+ "text": "URL contains \\"this is post\\"",
+ },
+ Object {
+ "disabled": false,
+ "loading": false,
+ "method": "PUT",
+ "path": "this is put",
+ "text": "URL contains \\"this is put\\"",
+ },
+ Object {
+ "disabled": false,
+ "loading": false,
+ "method": "HEAD",
+ "path": "this is head",
+ "text": "URL contains \\"this is head\\"",
+ },
+ Object {
+ "disabled": false,
+ "loading": false,
+ "method": "DELETE",
+ "path": "this is delete",
+ "text": "URL contains \\"this is delete\\"",
+ },
+ Object {
+ "disabled": false,
+ "loading": false,
+ "method": "PATCH",
+ "path": "this is patch",
+ "text": "URL contains \\"this is patch\\"",
+ },
+ Object {
+ "disabled": false,
+ "loading": false,
+ "method": "OPTIONS",
+ "path": "this is options",
+ "text": "URL contains \\"this is options\\"",
+ },
+ ]
+ }
+>
+ <div
+ className="breakpoints-options"
+ >
+ <ExceptionOption
+ className="breakpoints-exceptions"
+ isChecked={false}
+ label="Pause on any URL"
+ onChange={[Function]}
+ >
+ <label
+ className="breakpoints-exceptions"
+ >
+ <input
+ checked={false}
+ onChange={[Function]}
+ type="checkbox"
+ />
+ <div
+ className="breakpoint-exceptions-label"
+ >
+ Pause on any URL
+ </div>
+ </label>
+ </ExceptionOption>
+ </div>
+ <ul
+ className="pane expressions-list"
+ >
+ <li
+ className="xhr-container"
+ key="this is any-ANY"
+ onDoubleClick={[Function]}
+ title="this is any"
+ >
+ <label>
+ <input
+ checked={true}
+ className="xhr-checkbox"
+ onChange={[Function]}
+ onClick={[Function]}
+ type="checkbox"
+ />
+ <div
+ className="xhr-label-method"
+ >
+ ANY
+ </div>
+ <div
+ className="xhr-label-url"
+ >
+ this is any
+ </div>
+ <div
+ className="xhr-container__close-btn"
+ >
+ <CloseButton
+ handleClick={[Function]}
+ >
+ <button
+ className="close-btn"
+ onClick={[Function]}
+ >
+ <AccessibleImage
+ className="close"
+ >
+ <span
+ className="img close"
+ />
+ </AccessibleImage>
+ </button>
+ </CloseButton>
+ </div>
+ </label>
+ </li>
+ <li
+ className="xhr-container"
+ key="this is get-GET"
+ onDoubleClick={[Function]}
+ title="this is get"
+ >
+ <label>
+ <input
+ checked={true}
+ className="xhr-checkbox"
+ onChange={[Function]}
+ onClick={[Function]}
+ type="checkbox"
+ />
+ <div
+ className="xhr-label-method"
+ >
+ GET
+ </div>
+ <div
+ className="xhr-label-url"
+ >
+ this is get
+ </div>
+ <div
+ className="xhr-container__close-btn"
+ >
+ <CloseButton
+ handleClick={[Function]}
+ >
+ <button
+ className="close-btn"
+ onClick={[Function]}
+ >
+ <AccessibleImage
+ className="close"
+ >
+ <span
+ className="img close"
+ />
+ </AccessibleImage>
+ </button>
+ </CloseButton>
+ </div>
+ </label>
+ </li>
+ <li
+ className="xhr-container"
+ key="this is post-POST"
+ onDoubleClick={[Function]}
+ title="this is post"
+ >
+ <label>
+ <input
+ checked={true}
+ className="xhr-checkbox"
+ onChange={[Function]}
+ onClick={[Function]}
+ type="checkbox"
+ />
+ <div
+ className="xhr-label-method"
+ >
+ POST
+ </div>
+ <div
+ className="xhr-label-url"
+ >
+ this is post
+ </div>
+ <div
+ className="xhr-container__close-btn"
+ >
+ <CloseButton
+ handleClick={[Function]}
+ >
+ <button
+ className="close-btn"
+ onClick={[Function]}
+ >
+ <AccessibleImage
+ className="close"
+ >
+ <span
+ className="img close"
+ />
+ </AccessibleImage>
+ </button>
+ </CloseButton>
+ </div>
+ </label>
+ </li>
+ <li
+ className="xhr-container"
+ key="this is put-PUT"
+ onDoubleClick={[Function]}
+ title="this is put"
+ >
+ <label>
+ <input
+ checked={true}
+ className="xhr-checkbox"
+ onChange={[Function]}
+ onClick={[Function]}
+ type="checkbox"
+ />
+ <div
+ className="xhr-label-method"
+ >
+ PUT
+ </div>
+ <div
+ className="xhr-label-url"
+ >
+ this is put
+ </div>
+ <div
+ className="xhr-container__close-btn"
+ >
+ <CloseButton
+ handleClick={[Function]}
+ >
+ <button
+ className="close-btn"
+ onClick={[Function]}
+ >
+ <AccessibleImage
+ className="close"
+ >
+ <span
+ className="img close"
+ />
+ </AccessibleImage>
+ </button>
+ </CloseButton>
+ </div>
+ </label>
+ </li>
+ <li
+ className="xhr-container"
+ key="this is head-HEAD"
+ onDoubleClick={[Function]}
+ title="this is head"
+ >
+ <label>
+ <input
+ checked={true}
+ className="xhr-checkbox"
+ onChange={[Function]}
+ onClick={[Function]}
+ type="checkbox"
+ />
+ <div
+ className="xhr-label-method"
+ >
+ HEAD
+ </div>
+ <div
+ className="xhr-label-url"
+ >
+ this is head
+ </div>
+ <div
+ className="xhr-container__close-btn"
+ >
+ <CloseButton
+ handleClick={[Function]}
+ >
+ <button
+ className="close-btn"
+ onClick={[Function]}
+ >
+ <AccessibleImage
+ className="close"
+ >
+ <span
+ className="img close"
+ />
+ </AccessibleImage>
+ </button>
+ </CloseButton>
+ </div>
+ </label>
+ </li>
+ <li
+ className="xhr-container"
+ key="this is delete-DELETE"
+ onDoubleClick={[Function]}
+ title="this is delete"
+ >
+ <label>
+ <input
+ checked={true}
+ className="xhr-checkbox"
+ onChange={[Function]}
+ onClick={[Function]}
+ type="checkbox"
+ />
+ <div
+ className="xhr-label-method"
+ >
+ DELETE
+ </div>
+ <div
+ className="xhr-label-url"
+ >
+ this is delete
+ </div>
+ <div
+ className="xhr-container__close-btn"
+ >
+ <CloseButton
+ handleClick={[Function]}
+ >
+ <button
+ className="close-btn"
+ onClick={[Function]}
+ >
+ <AccessibleImage
+ className="close"
+ >
+ <span
+ className="img close"
+ />
+ </AccessibleImage>
+ </button>
+ </CloseButton>
+ </div>
+ </label>
+ </li>
+ <li
+ className="xhr-container"
+ key="this is patch-PATCH"
+ onDoubleClick={[Function]}
+ title="this is patch"
+ >
+ <label>
+ <input
+ checked={true}
+ className="xhr-checkbox"
+ onChange={[Function]}
+ onClick={[Function]}
+ type="checkbox"
+ />
+ <div
+ className="xhr-label-method"
+ >
+ PATCH
+ </div>
+ <div
+ className="xhr-label-url"
+ >
+ this is patch
+ </div>
+ <div
+ className="xhr-container__close-btn"
+ >
+ <CloseButton
+ handleClick={[Function]}
+ >
+ <button
+ className="close-btn"
+ onClick={[Function]}
+ >
+ <AccessibleImage
+ className="close"
+ >
+ <span
+ className="img close"
+ />
+ </AccessibleImage>
+ </button>
+ </CloseButton>
+ </div>
+ </label>
+ </li>
+ <li
+ className="xhr-container"
+ key="this is options-OPTIONS"
+ onDoubleClick={[Function]}
+ title="this is options"
+ >
+ <label>
+ <input
+ checked={true}
+ className="xhr-checkbox"
+ onChange={[Function]}
+ onClick={[Function]}
+ type="checkbox"
+ />
+ <div
+ className="xhr-label-method"
+ >
+ OPTIONS
+ </div>
+ <div
+ className="xhr-label-url"
+ >
+ this is options
+ </div>
+ <div
+ className="xhr-container__close-btn"
+ >
+ <CloseButton
+ handleClick={[Function]}
+ >
+ <button
+ className="close-btn"
+ onClick={[Function]}
+ >
+ <AccessibleImage
+ className="close"
+ >
+ <span
+ className="img close"
+ />
+ </AccessibleImage>
+ </button>
+ </CloseButton>
+ </div>
+ </label>
+ </li>
+ </ul>
+</XHRBreakpoints>
+`;