зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1742774 - [devtools] Add remove all breakpoints button in breakpoints header r=nchevobbe
In this patch - Added remove all breakpoints button in the Breakpoints list header bar - Start clearing `asyncStore.pendingBreakpoints` when we remove all the breakpoints - Add jest tests Differential Revision: https://phabricator.services.mozilla.com/D150350
This commit is contained in:
Родитель
881532a243
Коммит
4644b088bf
|
@ -8,6 +8,7 @@
|
|||
*/
|
||||
|
||||
import { PROMISE } from "../utils/middleware/promise";
|
||||
import { asyncStore } from "../../utils/prefs";
|
||||
import {
|
||||
getBreakpointsList,
|
||||
getXHRBreakpoints,
|
||||
|
@ -131,6 +132,7 @@ export function removeAllBreakpoints(cx) {
|
|||
breakpointList.map(bp => dispatch(removeBreakpoint(cx, bp)))
|
||||
);
|
||||
dispatch({ type: "CLEAR_BREAKPOINTS" });
|
||||
asyncStore.pendingBreakpoints = {};
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -13,10 +13,27 @@ import {
|
|||
import { mockCommandClient } from "../../tests/helpers/mockCommandClient";
|
||||
import { mockPendingBreakpoint } from "../../tests/helpers/breakpoints.js";
|
||||
import { makePendingLocationId } from "../../../utils/breakpoint";
|
||||
import { asyncStore } from "../../../utils/prefs";
|
||||
const {
|
||||
registerStoreObserver,
|
||||
} = require("devtools/client/shared/redux/subscriber");
|
||||
|
||||
jest.mock("../../../utils/prefs", () => ({
|
||||
prefs: {
|
||||
expressions: [],
|
||||
},
|
||||
asyncStore: {
|
||||
pendingBreakpoints: {},
|
||||
},
|
||||
features: {
|
||||
inlinePreview: true,
|
||||
},
|
||||
}));
|
||||
|
||||
function mockClient(positionsResponse = {}) {
|
||||
return {
|
||||
...mockCommandClient,
|
||||
setSkipPausing: jest.fn(),
|
||||
getSourceActorBreakpointPositions: async () => positionsResponse,
|
||||
getSourceActorBreakableLines: async () => [],
|
||||
};
|
||||
|
@ -307,10 +324,29 @@ describe("breakpoints", () => {
|
|||
const id = makePendingLocationId(mockedPendingBreakpoint.location);
|
||||
const pendingBreakpoints = { [id]: mockedPendingBreakpoint };
|
||||
|
||||
const { dispatch, getState, cx } = createStore(
|
||||
mockClient({ "5": [1], "6": [2] }),
|
||||
{ pendingBreakpoints }
|
||||
);
|
||||
asyncStore.pendingBreakpoints = pendingBreakpoints;
|
||||
|
||||
const store = createStore(mockClient({ "5": [1], "6": [2] }), {
|
||||
pendingBreakpoints,
|
||||
});
|
||||
|
||||
const { dispatch, getState, cx } = store;
|
||||
|
||||
// This mocks the updatePrefs observer which listens & updates the asyncStore
|
||||
// when the reducer state changes. See https://searchfox.org/mozilla-central/
|
||||
// rev/287583a4a605eee8cd2d41381ffaea7a93d7b987/devtools/client/debugger/
|
||||
// src/utils/bootstrap.js#114-142
|
||||
function mockUpdatePrefs(state, oldState) {
|
||||
if (
|
||||
selectors.getPendingBreakpoints(oldState) &&
|
||||
selectors.getPendingBreakpoints(oldState) !==
|
||||
selectors.getPendingBreakpoints(state)
|
||||
) {
|
||||
asyncStore.pendingBreakpoints = selectors.getPendingBreakpoints(state);
|
||||
}
|
||||
}
|
||||
|
||||
registerStoreObserver(store, mockUpdatePrefs);
|
||||
|
||||
const loc1 = {
|
||||
sourceId: "a",
|
||||
|
@ -332,16 +368,24 @@ describe("breakpoints", () => {
|
|||
const bSource = await dispatch(actions.newGeneratedSource(makeSource("b")));
|
||||
await dispatch(actions.loadSourceText({ cx, source: bSource }));
|
||||
|
||||
expect(selectors.getBreakpointsList(getState())).toHaveLength(0);
|
||||
expect(selectors.getPendingBreakpointList(getState())).toHaveLength(1);
|
||||
expect(Object.keys(asyncStore.pendingBreakpoints)).toHaveLength(1);
|
||||
|
||||
await dispatch(actions.addBreakpoint(cx, loc1));
|
||||
await dispatch(actions.addBreakpoint(cx, loc2));
|
||||
|
||||
// The breakpoint list contains all the live breakpoints while the pending-breakpoint
|
||||
// list stores contains all the breakpoints persisted across toolbox reopenings.
|
||||
expect(selectors.getBreakpointsList(getState())).toHaveLength(2);
|
||||
expect(selectors.getPendingBreakpointList(getState())).toHaveLength(3);
|
||||
expect(Object.keys(asyncStore.pendingBreakpoints)).toHaveLength(3);
|
||||
|
||||
await dispatch(actions.removeAllBreakpoints(cx));
|
||||
|
||||
const bps = selectors.getBreakpointsList(getState());
|
||||
const pendingBps = selectors.getPendingBreakpointList(getState());
|
||||
|
||||
expect(bps).toHaveLength(0);
|
||||
expect(pendingBps).toHaveLength(0);
|
||||
expect(selectors.getBreakpointsList(getState())).toHaveLength(0);
|
||||
expect(selectors.getPendingBreakpointList(getState())).toHaveLength(0);
|
||||
expect(Object.keys(asyncStore.pendingBreakpoints)).toHaveLength(0);
|
||||
});
|
||||
|
||||
it("should toggle a breakpoint at a location", async () => {
|
||||
|
|
|
@ -92,6 +92,7 @@ class SecondaryPanes extends Component {
|
|||
toggleEventLogging: PropTypes.func.isRequired,
|
||||
toggleMapScopes: PropTypes.func.isRequired,
|
||||
workers: PropTypes.array.isRequired,
|
||||
removeAllBreakpoints: PropTypes.func.isRequired,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -159,6 +160,20 @@ class SecondaryPanes extends Component {
|
|||
return buttons;
|
||||
}
|
||||
|
||||
breakpointsHeaderButtons() {
|
||||
return [
|
||||
debugBtn(
|
||||
evt => {
|
||||
evt.stopPropagation();
|
||||
this.props.removeAllBreakpoints(this.props.cx);
|
||||
},
|
||||
"removeAll",
|
||||
"removeAll",
|
||||
L10N.getStr("breakpointMenuItem.deleteAll")
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
getScopeItem() {
|
||||
return {
|
||||
header: L10N.getStr("scopes.header"),
|
||||
|
@ -304,6 +319,7 @@ class SecondaryPanes extends Component {
|
|||
return {
|
||||
header: L10N.getStr("breakpoints.header"),
|
||||
className: "breakpoints-pane",
|
||||
buttons: this.breakpointsHeaderButtons(),
|
||||
component: (
|
||||
<Breakpoints
|
||||
shouldPauseOnExceptions={shouldPauseOnExceptions}
|
||||
|
@ -501,4 +517,5 @@ export default connect(mapStateToProps, {
|
|||
toggleMapScopes: actions.toggleMapScopes,
|
||||
breakOnNext: actions.breakOnNext,
|
||||
toggleEventLogging: actions.toggleEventLogging,
|
||||
removeAllBreakpoints: actions.removeAllBreakpoints,
|
||||
})(SecondaryPanes);
|
||||
|
|
|
@ -146,6 +146,10 @@ html[dir="rtl"] .img.more-tabs {
|
|||
mask-image: url(chrome://devtools/content/debugger/images/prettyPrint.svg);
|
||||
}
|
||||
|
||||
.img.removeAll {
|
||||
mask-image: url(chrome://devtools/skin/images/clear.svg)
|
||||
}
|
||||
|
||||
.img.refresh {
|
||||
mask-image: url(chrome://devtools/content/debugger/images/reload.svg);
|
||||
}
|
||||
|
|
|
@ -9,6 +9,9 @@ const { Provider } = require("react-redux");
|
|||
|
||||
import ToolboxProvider from "devtools/client/framework/store-provider";
|
||||
import flags from "devtools/shared/flags";
|
||||
const {
|
||||
registerStoreObserver,
|
||||
} = require("devtools/client/shared/redux/subscriber");
|
||||
|
||||
const { AppConstants } = require("resource://gre/modules/AppConstants.jsm");
|
||||
|
||||
|
@ -102,15 +105,6 @@ export function unmountRoot() {
|
|||
ReactDOM.unmountComponentAtNode(getMountElement());
|
||||
}
|
||||
|
||||
function registerStoreObserver(store, subscriber) {
|
||||
let oldState = store.getState();
|
||||
store.subscribe(() => {
|
||||
const state = store.getState();
|
||||
subscriber(state, oldState);
|
||||
oldState = state;
|
||||
});
|
||||
}
|
||||
|
||||
function updatePrefs(state, oldState) {
|
||||
const hasChanged = selector =>
|
||||
selector(oldState) && selector(oldState) !== selector(state);
|
||||
|
|
|
@ -40,6 +40,7 @@ add_task(async function() {
|
|||
"resource://devtools/client/shared/vendor/react-dom-factories.js",
|
||||
"resource://devtools/client/shared/vendor/react-redux.js",
|
||||
"resource://devtools/client/shared/vendor/redux.js",
|
||||
"resource://devtools/client/shared/redux/subscriber.js",
|
||||
"resource://devtools/client/shared/worker-utils.js",
|
||||
"resource://devtools/client/debugger/src/workers/parser/index.js",
|
||||
"resource://devtools/client/shared/source-map/index.js",
|
||||
|
|
Загрузка…
Ссылка в новой задаче