зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1460971 - Update Debugger Frontend v52. r=jdescottes
MozReview-Commit-ID: J3gIzebCWre
This commit is contained in:
Родитель
922e46b318
Коммит
0da2193389
|
@ -1,9 +1,9 @@
|
||||||
This is the debugger.html project output.
|
This is the debugger.html project output.
|
||||||
See https://github.com/devtools-html/debugger.html
|
See https://github.com/devtools-html/debugger.html
|
||||||
|
|
||||||
Version 50
|
Version 52
|
||||||
|
|
||||||
Comparison: https://github.com/devtools-html/debugger.html/compare/release-49...release-50
|
Comparison: https://github.com/devtools-html/debugger.html/compare/release-51...release-52
|
||||||
|
|
||||||
Packages:
|
Packages:
|
||||||
- babel-plugin-transform-es2015-modules-commonjs @6.26.2
|
- babel-plugin-transform-es2015-modules-commonjs @6.26.2
|
||||||
|
|
|
@ -973,16 +973,17 @@ img.close::before {
|
||||||
|
|
||||||
.search-field {
|
.search-field {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
height: 27px;
|
||||||
width: calc(100% - 1px);
|
width: calc(100% - 1px);
|
||||||
background-color: var(--theme-toolbar-background);
|
background-color: var(--theme-toolbar-background);
|
||||||
border-bottom: 1px solid var(--theme-splitter-color);
|
border-bottom: 1px solid var(--theme-splitter-color);
|
||||||
padding: 5px 10px;
|
padding-right: 10px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-field.big {
|
.search-field.big {
|
||||||
|
padding: 5px 10px;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -993,23 +994,27 @@ img.close::before {
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-field i svg {
|
.search-field i svg {
|
||||||
|
width: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-field.big i svg {
|
||||||
width: 22px;
|
width: 22px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-field.big input {
|
|
||||||
line-height: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.search-field input {
|
.search-field input {
|
||||||
position: relative;
|
|
||||||
margin-left: 30px;
|
|
||||||
border: none;
|
border: none;
|
||||||
line-height: 30px;
|
line-height: 30px;
|
||||||
background-color: var(--theme-toolbar-background);
|
background-color: var(--theme-toolbar-background);
|
||||||
color: var(--theme-body-color-active);
|
color: var(--theme-body-color-active);
|
||||||
width: calc(100% - 38px);
|
width: calc(100% - 38px);
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-field.big input {
|
||||||
|
position: relative;
|
||||||
|
margin-left: 30px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
line-height: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-field input:focus {
|
.search-field input:focus {
|
||||||
|
@ -1022,22 +1027,14 @@ img.close::before {
|
||||||
|
|
||||||
.search-field i.magnifying-glass,
|
.search-field i.magnifying-glass,
|
||||||
.search-field i.sad-face {
|
.search-field i.sad-face {
|
||||||
position: absolute;
|
padding: 6px;
|
||||||
top: 50%;
|
|
||||||
padding: 2px 0;
|
|
||||||
width: 24px;
|
width: 24px;
|
||||||
margin-top: -12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.search-field i.sad-face {
|
|
||||||
padding-top: 1px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-field.big i.magnifying-glass,
|
.search-field.big i.magnifying-glass,
|
||||||
.search-field.big i.sad-face {
|
.search-field.big i.sad-face {
|
||||||
padding: 14px;
|
position: absolute;
|
||||||
width: 40px;
|
width: 40px;
|
||||||
margin-top: -20px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-field .magnifying-glass path,
|
.search-field .magnifying-glass path,
|
||||||
|
@ -1053,16 +1050,16 @@ img.close::before {
|
||||||
color: var(--theme-highlight-orange);
|
color: var(--theme-highlight-orange);
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-field.big .summary {
|
|
||||||
line-height: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.search-field .summary {
|
.search-field .summary {
|
||||||
line-height: 27px;
|
line-height: 27px;
|
||||||
padding-right: 10px;
|
padding-right: 10px;
|
||||||
color: var(--theme-body-color-inactive);
|
color: var(--theme-body-color-inactive);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.search-field.big .summary {
|
||||||
|
line-height: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
.search-field .search-nav-buttons {
|
.search-field .search-nav-buttons {
|
||||||
display: flex;
|
display: flex;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
@ -1869,7 +1866,7 @@ html .toggle-button.end.vertical svg {
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-field .close-btn {
|
.search-field .close-btn {
|
||||||
margin-top: 12px;
|
align-self: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-bottom-bar * {
|
.search-bottom-bar * {
|
||||||
|
@ -2918,6 +2915,7 @@ debug-expression-error {
|
||||||
color: var(--theme-content-color1);
|
color: var(--theme-content-color1);
|
||||||
position: relative;
|
position: relative;
|
||||||
transition: all 0.25s ease;
|
transition: all 0.25s ease;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.breakpoints-list .breakpoint-heading,
|
.breakpoints-list .breakpoint-heading,
|
||||||
|
@ -3087,7 +3085,7 @@ html[dir="rtl"] .breakpoints-list .breakpoint .breakpoint-line {
|
||||||
}
|
}
|
||||||
|
|
||||||
.CodeMirror.cm-s-mozilla-breakpoint {
|
.CodeMirror.cm-s-mozilla-breakpoint {
|
||||||
cursor: default;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.CodeMirror.cm-s-mozilla-breakpoint .CodeMirror-lines {
|
.CodeMirror.cm-s-mozilla-breakpoint .CodeMirror-lines {
|
||||||
|
|
|
@ -24745,6 +24745,10 @@ const inExpression = (parent, grandParent) => inStepExpression(parent) || t.isJS
|
||||||
|
|
||||||
const isExport = node => t.isExportNamedDeclaration(node) || t.isExportDefaultDeclaration(node);
|
const isExport = node => t.isExportNamedDeclaration(node) || t.isExportDefaultDeclaration(node);
|
||||||
|
|
||||||
|
function getStartLine(node) {
|
||||||
|
return node.loc.start.line;
|
||||||
|
}
|
||||||
|
|
||||||
function getPausePoints(sourceId) {
|
function getPausePoints(sourceId) {
|
||||||
const state = {};
|
const state = {};
|
||||||
(0, _ast.traverseAst)(sourceId, { enter: onEnter }, state);
|
(0, _ast.traverseAst)(sourceId, { enter: onEnter }, state);
|
||||||
|
@ -24781,10 +24785,12 @@ function onEnter(node, ancestors, state) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isReturn(node)) {
|
if (isReturn(node)) {
|
||||||
// We do not want to pause at the return and the call e.g. return foo()
|
// We do not want to pause at the return if the
|
||||||
if (isCall(node.argument)) {
|
// argument is a call on the same line e.g. return foo()
|
||||||
|
if (isCall(node.argument) && getStartLine(node) == getStartLine(node.argument)) {
|
||||||
return addEmptyPoint(state, startLocation);
|
return addEmptyPoint(state, startLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
return addStopPoint(state, startLocation);
|
return addStopPoint(state, startLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -112,15 +112,16 @@ function setPausePoints(sourceId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const pausePoints = await (0, _parser.getPausePoints)(source.id);
|
const pausePoints = await (0, _parser.getPausePoints)(sourceId);
|
||||||
|
|
||||||
if ((0, _devtoolsSourceMap.isGeneratedId)(source.id)) {
|
if ((0, _devtoolsSourceMap.isGeneratedId)(sourceId)) {
|
||||||
await client.setPausePoints(source.id, pausePoints);
|
await client.setPausePoints(sourceId, pausePoints);
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: "SET_PAUSE_POINTS",
|
type: "SET_PAUSE_POINTS",
|
||||||
source: source.toJS(),
|
sourceText: source.text,
|
||||||
|
sourceId,
|
||||||
pausePoints
|
pausePoints
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -18,14 +18,13 @@ exports.breakOnNext = breakOnNext;
|
||||||
* @static
|
* @static
|
||||||
*/
|
*/
|
||||||
function breakOnNext() {
|
function breakOnNext() {
|
||||||
return ({
|
return async ({
|
||||||
dispatch,
|
dispatch,
|
||||||
client
|
client
|
||||||
}) => {
|
}) => {
|
||||||
client.breakOnNext();
|
await client.breakOnNext();
|
||||||
return dispatch({
|
return dispatch({
|
||||||
type: "BREAK_ON_NEXT",
|
type: "BREAK_ON_NEXT"
|
||||||
value: true
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -142,6 +142,15 @@ Object.defineProperty(exports, "pauseOnExceptions", {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var _selectComponent = require("./selectComponent");
|
||||||
|
|
||||||
|
Object.defineProperty(exports, "selectComponent", {
|
||||||
|
enumerable: true,
|
||||||
|
get: function () {
|
||||||
|
return _selectComponent.selectComponent;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
var _selectFrame = require("./selectFrame");
|
var _selectFrame = require("./selectFrame");
|
||||||
|
|
||||||
Object.defineProperty(exports, "selectFrame", {
|
Object.defineProperty(exports, "selectFrame", {
|
||||||
|
|
|
@ -19,6 +19,7 @@ DevToolsModules(
|
||||||
'paused.js',
|
'paused.js',
|
||||||
'pauseOnExceptions.js',
|
'pauseOnExceptions.js',
|
||||||
'resumed.js',
|
'resumed.js',
|
||||||
|
'selectComponent.js',
|
||||||
'selectFrame.js',
|
'selectFrame.js',
|
||||||
'setPopupObjectProperties.js',
|
'setPopupObjectProperties.js',
|
||||||
'skipPausing.js',
|
'skipPausing.js',
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
Object.defineProperty(exports, "__esModule", {
|
||||||
|
value: true
|
||||||
|
});
|
||||||
|
exports.selectComponent = selectComponent;
|
||||||
|
|
||||||
|
/* 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/>. */
|
||||||
|
function selectComponent(componentIndex) {
|
||||||
|
return async ({
|
||||||
|
dispatch
|
||||||
|
}) => {
|
||||||
|
dispatch({
|
||||||
|
type: "SELECT_COMPONENT",
|
||||||
|
componentIndex
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
|
@ -118,7 +118,7 @@ function selectLocation(location) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const source = sourceRecord.toJS();
|
const source = sourceRecord.toJS();
|
||||||
dispatch((0, _tabs.addTab)(source, 0));
|
dispatch((0, _tabs.addTab)(source.url, 0));
|
||||||
dispatch({
|
dispatch({
|
||||||
type: "SELECT_SOURCE",
|
type: "SELECT_SOURCE",
|
||||||
source,
|
source,
|
||||||
|
|
|
@ -22,10 +22,10 @@ var _selectors = require("../../selectors/index");
|
||||||
* Redux actions for the sources state
|
* Redux actions for the sources state
|
||||||
* @module actions/sources
|
* @module actions/sources
|
||||||
*/
|
*/
|
||||||
function addTab(source, tabIndex) {
|
function addTab(url, tabIndex) {
|
||||||
return {
|
return {
|
||||||
type: "ADD_TAB",
|
type: "ADD_TAB",
|
||||||
source,
|
url,
|
||||||
tabIndex
|
tabIndex
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -436,7 +436,7 @@ class QuickOpenModal extends _react.Component {
|
||||||
return _react2.default.createElement(_Modal2.default, {
|
return _react2.default.createElement(_Modal2.default, {
|
||||||
"in": enabled,
|
"in": enabled,
|
||||||
handleClose: this.closeModal
|
handleClose: this.closeModal
|
||||||
}, _react2.default.createElement(_SearchInput2.default, {
|
}, _react2.default.createElement(_SearchInput2.default, _extends({
|
||||||
query: query,
|
query: query,
|
||||||
hasPrefix: true,
|
hasPrefix: true,
|
||||||
count: this.getResultCount(),
|
count: this.getResultCount(),
|
||||||
|
@ -447,8 +447,11 @@ class QuickOpenModal extends _react.Component {
|
||||||
onKeyDown: this.onKeyDown,
|
onKeyDown: this.onKeyDown,
|
||||||
handleClose: this.closeModal,
|
handleClose: this.closeModal,
|
||||||
expanded: expanded,
|
expanded: expanded,
|
||||||
|
showClose: false,
|
||||||
selectedItemId: expanded && items[selectedIndex] ? items[selectedIndex].id : ""
|
selectedItemId: expanded && items[selectedIndex] ? items[selectedIndex].id : ""
|
||||||
}), this.renderLoading(), newResults && _react2.default.createElement(_ResultList2.default, _extends({
|
}, this.isSourceSearch() ? {
|
||||||
|
size: "big"
|
||||||
|
} : {})), this.renderLoading(), newResults && _react2.default.createElement(_ResultList2.default, _extends({
|
||||||
key: "results",
|
key: "results",
|
||||||
items: items,
|
items: items,
|
||||||
selected: selectedIndex,
|
selected: selectedIndex,
|
||||||
|
|
|
@ -14,6 +14,10 @@ var _actions = require("../../actions/index");
|
||||||
|
|
||||||
var _actions2 = _interopRequireDefault(_actions);
|
var _actions2 = _interopRequireDefault(_actions);
|
||||||
|
|
||||||
|
var _classnames = require("devtools/client/debugger/new/dist/vendors").vendored["classnames"];
|
||||||
|
|
||||||
|
var _classnames2 = _interopRequireDefault(_classnames);
|
||||||
|
|
||||||
var _selectors = require("../../selectors/index");
|
var _selectors = require("../../selectors/index");
|
||||||
|
|
||||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||||
|
@ -22,6 +26,14 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/>. */
|
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||||
class ReactComponentStack extends _react.PureComponent {
|
class ReactComponentStack extends _react.PureComponent {
|
||||||
|
onMouseDown(e, componentIndex) {
|
||||||
|
if (e.nativeEvent.which == 3) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.props.selectComponent(componentIndex);
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
componentStack
|
componentStack
|
||||||
|
@ -29,14 +41,19 @@ class ReactComponentStack extends _react.PureComponent {
|
||||||
return _react2.default.createElement("div", {
|
return _react2.default.createElement("div", {
|
||||||
className: "pane frames"
|
className: "pane frames"
|
||||||
}, _react2.default.createElement("ul", null, componentStack.slice().reverse().map((component, index) => _react2.default.createElement("li", {
|
}, _react2.default.createElement("ul", null, componentStack.slice().reverse().map((component, index) => _react2.default.createElement("li", {
|
||||||
key: index
|
className: (0, _classnames2.default)("frame", {
|
||||||
|
selected: this.props.selectedComponentIndex === index
|
||||||
|
}),
|
||||||
|
key: index,
|
||||||
|
onMouseDown: e => this.onMouseDown(e, index)
|
||||||
}, component))));
|
}, component))));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = state => ({
|
||||||
extra: (0, _selectors.getExtra)(state)
|
extra: (0, _selectors.getExtra)(state),
|
||||||
|
selectedComponentIndex: (0, _selectors.getSelectedComponentIndex)(state)
|
||||||
});
|
});
|
||||||
|
|
||||||
exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(ReactComponentStack);
|
exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(ReactComponentStack);
|
|
@ -8,7 +8,6 @@ DIRS += [
|
||||||
'PrimaryPanes',
|
'PrimaryPanes',
|
||||||
'SecondaryPanes',
|
'SecondaryPanes',
|
||||||
'shared',
|
'shared',
|
||||||
'test',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
DevToolsModules(
|
DevToolsModules(
|
||||||
|
|
|
@ -141,7 +141,8 @@ class SearchInput extends _react.Component {
|
||||||
selectedItemId,
|
selectedItemId,
|
||||||
showErrorEmoji,
|
showErrorEmoji,
|
||||||
size,
|
size,
|
||||||
summaryMsg
|
summaryMsg,
|
||||||
|
showClose
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const inputProps = {
|
const inputProps = {
|
||||||
className: (0, _classnames2.default)({
|
className: (0, _classnames2.default)({
|
||||||
|
@ -172,7 +173,7 @@ class SearchInput extends _react.Component {
|
||||||
"aria-expanded": expanded
|
"aria-expanded": expanded
|
||||||
}, this.renderSvg(), _react2.default.createElement("input", inputProps), summaryMsg && _react2.default.createElement("div", {
|
}, this.renderSvg(), _react2.default.createElement("input", inputProps), summaryMsg && _react2.default.createElement("div", {
|
||||||
className: "summary"
|
className: "summary"
|
||||||
}, summaryMsg), this.renderNav(), _react2.default.createElement(_Close2.default, {
|
}, summaryMsg), this.renderNav(), showClose && _react2.default.createElement(_Close2.default, {
|
||||||
handleClick: handleClose,
|
handleClick: handleClose,
|
||||||
buttonClass: size
|
buttonClass: size
|
||||||
})));
|
})));
|
||||||
|
@ -184,6 +185,7 @@ SearchInput.defaultProps = {
|
||||||
expanded: false,
|
expanded: false,
|
||||||
hasPrefix: false,
|
hasPrefix: false,
|
||||||
selectedItemId: "",
|
selectedItemId: "",
|
||||||
size: ""
|
size: "",
|
||||||
|
showClose: true
|
||||||
};
|
};
|
||||||
exports.default = SearchInput;
|
exports.default = SearchInput;
|
|
@ -1,316 +0,0 @@
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var _react = require("devtools/client/shared/vendor/react");
|
|
||||||
|
|
||||||
var _react2 = _interopRequireDefault(_react);
|
|
||||||
|
|
||||||
var _enzyme = require("enzyme/index");
|
|
||||||
|
|
||||||
var _Outline = require("../../components/PrimaryPanes/Outline");
|
|
||||||
|
|
||||||
var _Outline2 = _interopRequireDefault(_Outline);
|
|
||||||
|
|
||||||
var _testHead = require("../../utils/test-head");
|
|
||||||
|
|
||||||
var _devtoolsContextmenu = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-contextmenu"];
|
|
||||||
|
|
||||||
var _clipboard = require("../../utils/clipboard");
|
|
||||||
|
|
||||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
||||||
|
|
||||||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }
|
|
||||||
|
|
||||||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
||||||
|
|
||||||
jest.mock("devtools-contextmenu", () => ({
|
|
||||||
showMenu: jest.fn()
|
|
||||||
}));
|
|
||||||
jest.mock("../../utils/clipboard", () => ({
|
|
||||||
copyToTheClipboard: jest.fn()
|
|
||||||
}));
|
|
||||||
const sourceId = "id";
|
|
||||||
const mockFunctionText = "mock function text";
|
|
||||||
|
|
||||||
function generateDefaults(overrides) {
|
|
||||||
return _objectSpread({
|
|
||||||
selectLocation: jest.genMockFunction(),
|
|
||||||
selectedSource: {
|
|
||||||
get: () => sourceId
|
|
||||||
},
|
|
||||||
getFunctionText: jest.fn().mockReturnValue(mockFunctionText),
|
|
||||||
flashLineRange: jest.fn(),
|
|
||||||
isHidden: false,
|
|
||||||
symbols: {},
|
|
||||||
selectedLocation: {
|
|
||||||
sourceId: sourceId
|
|
||||||
},
|
|
||||||
onAlphabetizeClick: jest.fn()
|
|
||||||
}, overrides);
|
|
||||||
}
|
|
||||||
|
|
||||||
function render(overrides = {}) {
|
|
||||||
const props = generateDefaults(overrides);
|
|
||||||
const component = (0, _enzyme.shallow)(_react2.default.createElement(_Outline2.default.WrappedComponent, props));
|
|
||||||
const instance = component.instance();
|
|
||||||
return {
|
|
||||||
component,
|
|
||||||
props,
|
|
||||||
instance
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
describe("Outline", () => {
|
|
||||||
afterEach(() => {
|
|
||||||
_clipboard.copyToTheClipboard.mockClear();
|
|
||||||
|
|
||||||
_devtoolsContextmenu.showMenu.mockClear();
|
|
||||||
});
|
|
||||||
it("renders a list of functions when properties change", async () => {
|
|
||||||
const symbols = {
|
|
||||||
functions: [(0, _testHead.makeSymbolDeclaration)("my_example_function1", 21), (0, _testHead.makeSymbolDeclaration)("my_example_function2", 22)]
|
|
||||||
};
|
|
||||||
const {
|
|
||||||
component
|
|
||||||
} = render({
|
|
||||||
symbols
|
|
||||||
});
|
|
||||||
expect(component).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
it("selects a line of code in the current file on click", async () => {
|
|
||||||
const startLine = 12;
|
|
||||||
const symbols = {
|
|
||||||
functions: [(0, _testHead.makeSymbolDeclaration)("my_example_function", startLine)]
|
|
||||||
};
|
|
||||||
const {
|
|
||||||
component,
|
|
||||||
props
|
|
||||||
} = render({
|
|
||||||
symbols
|
|
||||||
});
|
|
||||||
const {
|
|
||||||
selectLocation
|
|
||||||
} = props;
|
|
||||||
const listItem = component.find("li").first();
|
|
||||||
listItem.simulate("click");
|
|
||||||
expect(selectLocation).toHaveBeenCalledWith({
|
|
||||||
line: startLine,
|
|
||||||
sourceId
|
|
||||||
});
|
|
||||||
});
|
|
||||||
describe("renders outline", () => {
|
|
||||||
describe("renders loading", () => {
|
|
||||||
it("if symbols is not defined", () => {
|
|
||||||
const {
|
|
||||||
component
|
|
||||||
} = render({
|
|
||||||
symbols: null
|
|
||||||
});
|
|
||||||
expect(component).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
it("if symbols are loading", () => {
|
|
||||||
const {
|
|
||||||
component
|
|
||||||
} = render({
|
|
||||||
symbols: {
|
|
||||||
loading: true
|
|
||||||
}
|
|
||||||
});
|
|
||||||
expect(component).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it("renders ignore anonymous functions", async () => {
|
|
||||||
const symbols = {
|
|
||||||
functions: [(0, _testHead.makeSymbolDeclaration)("my_example_function1", 21), (0, _testHead.makeSymbolDeclaration)("anonymous", 25)]
|
|
||||||
};
|
|
||||||
const {
|
|
||||||
component
|
|
||||||
} = render({
|
|
||||||
symbols
|
|
||||||
});
|
|
||||||
expect(component).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
describe("renders placeholder", () => {
|
|
||||||
it("`No File Selected` if selectedSource is not defined", async () => {
|
|
||||||
const {
|
|
||||||
component
|
|
||||||
} = render({
|
|
||||||
selectedSource: null
|
|
||||||
});
|
|
||||||
expect(component).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
it("`No functions` if all func are anonymous", async () => {
|
|
||||||
const symbols = {
|
|
||||||
functions: [(0, _testHead.makeSymbolDeclaration)("anonymous", 25), (0, _testHead.makeSymbolDeclaration)("anonymous", 30)]
|
|
||||||
};
|
|
||||||
const {
|
|
||||||
component
|
|
||||||
} = render({
|
|
||||||
symbols
|
|
||||||
});
|
|
||||||
expect(component).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
it("`No functions` if symbols has no func", async () => {
|
|
||||||
const symbols = {
|
|
||||||
functions: []
|
|
||||||
};
|
|
||||||
const {
|
|
||||||
component
|
|
||||||
} = render({
|
|
||||||
symbols
|
|
||||||
});
|
|
||||||
expect(component).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it("sorts functions alphabetically by function name", async () => {
|
|
||||||
const symbols = {
|
|
||||||
functions: [(0, _testHead.makeSymbolDeclaration)("c_function", 25), (0, _testHead.makeSymbolDeclaration)("x_function", 30), (0, _testHead.makeSymbolDeclaration)("a_function", 70)]
|
|
||||||
};
|
|
||||||
const {
|
|
||||||
component
|
|
||||||
} = render({
|
|
||||||
symbols: symbols,
|
|
||||||
alphabetizeOutline: true
|
|
||||||
});
|
|
||||||
expect(component).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
it("calls onAlphabetizeClick when sort button is clicked", async () => {
|
|
||||||
const symbols = {
|
|
||||||
functions: [(0, _testHead.makeSymbolDeclaration)("example_function", 25)]
|
|
||||||
};
|
|
||||||
const {
|
|
||||||
component,
|
|
||||||
props
|
|
||||||
} = render({
|
|
||||||
symbols
|
|
||||||
});
|
|
||||||
await component.find(".outline-footer").find("button").simulate("click", {});
|
|
||||||
expect(props.onAlphabetizeClick).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
it("renders functions by function class", async () => {
|
|
||||||
const symbols = {
|
|
||||||
functions: [(0, _testHead.makeSymbolDeclaration)("x_function", 25, 26, "x_klass"), (0, _testHead.makeSymbolDeclaration)("a2_function", 30, 31, "a_klass"), (0, _testHead.makeSymbolDeclaration)("a1_function", 70, 71, "a_klass")],
|
|
||||||
classes: [(0, _testHead.makeSymbolDeclaration)("x_klass", 24, 27), (0, _testHead.makeSymbolDeclaration)("a_klass", 29, 72)]
|
|
||||||
};
|
|
||||||
const {
|
|
||||||
component
|
|
||||||
} = render({
|
|
||||||
symbols: symbols
|
|
||||||
});
|
|
||||||
expect(component).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
it("renders functions by function class, alphabetically", async () => {
|
|
||||||
const symbols = {
|
|
||||||
functions: [(0, _testHead.makeSymbolDeclaration)("x_function", 25, 26, "x_klass"), (0, _testHead.makeSymbolDeclaration)("a2_function", 30, 31, "a_klass"), (0, _testHead.makeSymbolDeclaration)("a1_function", 70, 71, "a_klass")],
|
|
||||||
classes: [(0, _testHead.makeSymbolDeclaration)("x_klass", 24, 27), (0, _testHead.makeSymbolDeclaration)("a_klass", 29, 72)]
|
|
||||||
};
|
|
||||||
const {
|
|
||||||
component
|
|
||||||
} = render({
|
|
||||||
symbols: symbols,
|
|
||||||
alphabetizeOutline: true
|
|
||||||
});
|
|
||||||
expect(component).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
it("selects class on click on class headline", async () => {
|
|
||||||
const symbols = {
|
|
||||||
functions: [(0, _testHead.makeSymbolDeclaration)("x_function", 25, 26, "x_klass")],
|
|
||||||
classes: [(0, _testHead.makeSymbolDeclaration)("x_klass", 24, 27)]
|
|
||||||
};
|
|
||||||
const {
|
|
||||||
component,
|
|
||||||
props
|
|
||||||
} = render({
|
|
||||||
symbols: symbols
|
|
||||||
});
|
|
||||||
await component.find("h2").simulate("click", {});
|
|
||||||
expect(props.selectLocation).toHaveBeenCalledWith({
|
|
||||||
line: 24,
|
|
||||||
sourceId: sourceId
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it("does not select an item if selectedSource is not defined", async () => {
|
|
||||||
const {
|
|
||||||
instance,
|
|
||||||
props
|
|
||||||
} = render({
|
|
||||||
selectedSource: null
|
|
||||||
});
|
|
||||||
await instance.selectItem({});
|
|
||||||
expect(props.selectLocation).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
describe("onContextMenu of Outline", () => {
|
|
||||||
it("is called onContextMenu for each item", async () => {
|
|
||||||
const event = {
|
|
||||||
event: "oncontextmenu"
|
|
||||||
};
|
|
||||||
const fn = (0, _testHead.makeSymbolDeclaration)("exmple_function", 2);
|
|
||||||
const symbols = {
|
|
||||||
functions: [fn]
|
|
||||||
};
|
|
||||||
const {
|
|
||||||
component,
|
|
||||||
instance
|
|
||||||
} = render({
|
|
||||||
symbols
|
|
||||||
});
|
|
||||||
instance.onContextMenu = jest.fn(() => {});
|
|
||||||
await component.find(".outline-list__element").simulate("contextmenu", event);
|
|
||||||
expect(instance.onContextMenu).toHaveBeenCalledWith(event, fn);
|
|
||||||
});
|
|
||||||
it("does not show menu with no selected source", async () => {
|
|
||||||
const mockEvent = {
|
|
||||||
preventDefault: jest.fn(),
|
|
||||||
stopPropagation: jest.fn()
|
|
||||||
};
|
|
||||||
const {
|
|
||||||
instance
|
|
||||||
} = render({
|
|
||||||
selectedSource: null
|
|
||||||
});
|
|
||||||
await instance.onContextMenu(mockEvent, {});
|
|
||||||
expect(mockEvent.preventDefault).toHaveBeenCalled();
|
|
||||||
expect(mockEvent.stopPropagation).toHaveBeenCalled();
|
|
||||||
expect(_devtoolsContextmenu.showMenu).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
it("shows menu to copy func, copies to clipboard on click", async () => {
|
|
||||||
const startLine = 12;
|
|
||||||
const endLine = 21;
|
|
||||||
const func = (0, _testHead.makeSymbolDeclaration)("my_example_function", startLine, endLine);
|
|
||||||
const symbols = {
|
|
||||||
functions: [func]
|
|
||||||
};
|
|
||||||
const mockEvent = {
|
|
||||||
preventDefault: jest.fn(),
|
|
||||||
stopPropagation: jest.fn()
|
|
||||||
};
|
|
||||||
const {
|
|
||||||
instance,
|
|
||||||
props
|
|
||||||
} = render({
|
|
||||||
symbols
|
|
||||||
});
|
|
||||||
await instance.onContextMenu(mockEvent, func);
|
|
||||||
expect(mockEvent.preventDefault).toHaveBeenCalled();
|
|
||||||
expect(mockEvent.stopPropagation).toHaveBeenCalled();
|
|
||||||
const expectedMenuOptions = [{
|
|
||||||
accesskey: "F",
|
|
||||||
click: expect.any(Function),
|
|
||||||
disabled: false,
|
|
||||||
id: "node-menu-copy-function",
|
|
||||||
label: "Copy function"
|
|
||||||
}];
|
|
||||||
expect(props.getFunctionText).toHaveBeenCalledWith(12);
|
|
||||||
expect(_devtoolsContextmenu.showMenu).toHaveBeenCalledWith(mockEvent, expectedMenuOptions);
|
|
||||||
|
|
||||||
_devtoolsContextmenu.showMenu.mock.calls[0][1][0].click();
|
|
||||||
|
|
||||||
expect(_clipboard.copyToTheClipboard).toHaveBeenCalledWith(mockFunctionText);
|
|
||||||
expect(props.flashLineRange).toHaveBeenCalledWith({
|
|
||||||
end: endLine,
|
|
||||||
sourceId: sourceId,
|
|
||||||
start: startLine
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,248 +0,0 @@
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var _react = require("devtools/client/shared/vendor/react");
|
|
||||||
|
|
||||||
var _react2 = _interopRequireDefault(_react);
|
|
||||||
|
|
||||||
var _enzyme = require("enzyme/index");
|
|
||||||
|
|
||||||
var _immutable = require("devtools/client/shared/vendor/immutable");
|
|
||||||
|
|
||||||
var _ProjectSearch = require("../ProjectSearch");
|
|
||||||
|
|
||||||
var _projectTextSearch = require("../../reducers/project-text-search");
|
|
||||||
|
|
||||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
||||||
|
|
||||||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }
|
|
||||||
|
|
||||||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
||||||
|
|
||||||
const hooks = {
|
|
||||||
on: [],
|
|
||||||
off: []
|
|
||||||
};
|
|
||||||
const shortcuts = {
|
|
||||||
dispatch(eventName) {
|
|
||||||
hooks.on.forEach(hook => {
|
|
||||||
if (hook.event === eventName) {
|
|
||||||
hook.cb();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
hooks.off.forEach(hook => {
|
|
||||||
if (hook.event === eventName) {
|
|
||||||
hook.cb();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
on: jest.fn((event, cb) => hooks.on.push({
|
|
||||||
event,
|
|
||||||
cb
|
|
||||||
})),
|
|
||||||
off: jest.fn((event, cb) => hooks.off.push({
|
|
||||||
event,
|
|
||||||
cb
|
|
||||||
}))
|
|
||||||
};
|
|
||||||
const context = {
|
|
||||||
shortcuts
|
|
||||||
};
|
|
||||||
const testResults = (0, _immutable.List)([{
|
|
||||||
filepath: "testFilePath1",
|
|
||||||
matches: [{
|
|
||||||
match: "match1",
|
|
||||||
value: "some thing match1",
|
|
||||||
column: 30
|
|
||||||
}, {
|
|
||||||
match: "match2",
|
|
||||||
value: "some thing match2",
|
|
||||||
column: 60
|
|
||||||
}, {
|
|
||||||
match: "match3",
|
|
||||||
value: "some thing match3",
|
|
||||||
column: 90
|
|
||||||
}]
|
|
||||||
}, {
|
|
||||||
filepath: "testFilePath2",
|
|
||||||
matches: [{
|
|
||||||
match: "match4",
|
|
||||||
value: "some thing match4",
|
|
||||||
column: 80
|
|
||||||
}, {
|
|
||||||
match: "match5",
|
|
||||||
value: "some thing match5",
|
|
||||||
column: 40
|
|
||||||
}]
|
|
||||||
}]);
|
|
||||||
const testMatch = {
|
|
||||||
match: "match1",
|
|
||||||
value: "some thing match1",
|
|
||||||
column: 30
|
|
||||||
};
|
|
||||||
|
|
||||||
function render(overrides = {}, mounted = false) {
|
|
||||||
const props = _objectSpread({
|
|
||||||
status: "DONE",
|
|
||||||
sources: {},
|
|
||||||
results: (0, _immutable.List)([]),
|
|
||||||
query: "foo",
|
|
||||||
activeSearch: "project",
|
|
||||||
closeProjectSearch: jest.fn(),
|
|
||||||
searchSources: jest.fn(),
|
|
||||||
clearSearch: jest.fn(),
|
|
||||||
updateSearchStatus: jest.fn(),
|
|
||||||
selectLocation: jest.fn(),
|
|
||||||
doSearchForHighlight: jest.fn()
|
|
||||||
}, overrides);
|
|
||||||
|
|
||||||
return mounted ? (0, _enzyme.mount)(_react2.default.createElement(_ProjectSearch.ProjectSearch, props), {
|
|
||||||
context
|
|
||||||
}) : (0, _enzyme.shallow)(_react2.default.createElement(_ProjectSearch.ProjectSearch, props), {
|
|
||||||
context
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
describe("ProjectSearch", () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
context.shortcuts.on.mockClear();
|
|
||||||
context.shortcuts.off.mockClear();
|
|
||||||
});
|
|
||||||
it("renders nothing when disabled", () => {
|
|
||||||
const component = render({
|
|
||||||
activeSearch: null
|
|
||||||
});
|
|
||||||
expect(component).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
it("where <Enter> has not been pressed", () => {
|
|
||||||
const component = render({
|
|
||||||
query: ""
|
|
||||||
});
|
|
||||||
expect(component).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
it("found no search results", () => {
|
|
||||||
const component = render();
|
|
||||||
expect(component).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
it("should display loading message while search is in progress", () => {
|
|
||||||
const component = render({
|
|
||||||
query: "match",
|
|
||||||
status: _projectTextSearch.statusType.fetching
|
|
||||||
});
|
|
||||||
expect(component).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
it("found search results", () => {
|
|
||||||
const component = render({
|
|
||||||
query: "match",
|
|
||||||
results: testResults
|
|
||||||
}, true);
|
|
||||||
expect(component).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
it("turns off shortcuts on unmount", () => {
|
|
||||||
const component = render({
|
|
||||||
query: ""
|
|
||||||
});
|
|
||||||
expect(component).toMatchSnapshot();
|
|
||||||
component.unmount();
|
|
||||||
expect(context.shortcuts.off).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
it("calls inputOnChange", () => {
|
|
||||||
const component = render({
|
|
||||||
results: testResults
|
|
||||||
}, true);
|
|
||||||
component.find("SearchInput input").simulate("change", {
|
|
||||||
target: {
|
|
||||||
value: "bar"
|
|
||||||
}
|
|
||||||
});
|
|
||||||
expect(component.state().inputValue).toEqual("bar");
|
|
||||||
});
|
|
||||||
it("onKeyDown Escape/Other", () => {
|
|
||||||
const searchSources = jest.fn();
|
|
||||||
const component = render({
|
|
||||||
results: testResults,
|
|
||||||
searchSources
|
|
||||||
}, true);
|
|
||||||
component.find("SearchInput input").simulate("keydown", {
|
|
||||||
key: "Escape"
|
|
||||||
});
|
|
||||||
expect(searchSources).not.toHaveBeenCalled();
|
|
||||||
searchSources.mockClear();
|
|
||||||
component.find("SearchInput input").simulate("keydown", {
|
|
||||||
key: "Other",
|
|
||||||
stopPropagation: jest.fn()
|
|
||||||
});
|
|
||||||
expect(searchSources).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
it("onKeyDown Enter", () => {
|
|
||||||
const searchSources = jest.fn();
|
|
||||||
const component = render({
|
|
||||||
results: testResults,
|
|
||||||
searchSources
|
|
||||||
}, true);
|
|
||||||
component.find("SearchInput input").simulate("keydown", {
|
|
||||||
key: "Enter",
|
|
||||||
stopPropagation: jest.fn()
|
|
||||||
});
|
|
||||||
expect(searchSources).toHaveBeenCalledWith("foo");
|
|
||||||
});
|
|
||||||
it("onEnterPress shortcut no match or setExpanded", () => {
|
|
||||||
const selectLocation = jest.fn();
|
|
||||||
const component = render({
|
|
||||||
results: testResults,
|
|
||||||
selectLocation
|
|
||||||
}, true);
|
|
||||||
component.instance().focusedItem = {};
|
|
||||||
shortcuts.dispatch("Enter");
|
|
||||||
expect(selectLocation).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
it("onEnterPress shortcut match", () => {
|
|
||||||
const selectLocation = jest.fn();
|
|
||||||
const component = render({
|
|
||||||
results: testResults,
|
|
||||||
selectLocation
|
|
||||||
}, true);
|
|
||||||
component.instance().focusedItem = {
|
|
||||||
match: testMatch
|
|
||||||
};
|
|
||||||
shortcuts.dispatch("Enter");
|
|
||||||
expect(selectLocation).toHaveBeenCalledWith(testMatch);
|
|
||||||
});
|
|
||||||
it("onEnterPress shortcut setExpanded", () => {
|
|
||||||
const selectLocation = jest.fn();
|
|
||||||
const component = render({
|
|
||||||
results: testResults,
|
|
||||||
selectLocation
|
|
||||||
}, true);
|
|
||||||
const setExpanded = jest.fn();
|
|
||||||
const testFile = {
|
|
||||||
filepath: "testFilePath1",
|
|
||||||
matches: [testMatch]
|
|
||||||
};
|
|
||||||
component.instance().focusedItem = {
|
|
||||||
setExpanded,
|
|
||||||
file: testFile,
|
|
||||||
expanded: true
|
|
||||||
};
|
|
||||||
shortcuts.dispatch("Enter");
|
|
||||||
expect(setExpanded).toHaveBeenCalledWith(testFile, false);
|
|
||||||
});
|
|
||||||
describe("showErrorEmoji", () => {
|
|
||||||
it("false if not done & results", () => {
|
|
||||||
const component = render({
|
|
||||||
status: _projectTextSearch.statusType.fetching,
|
|
||||||
results: testResults
|
|
||||||
});
|
|
||||||
expect(component).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
it("false if not done & no results", () => {
|
|
||||||
const component = render({
|
|
||||||
status: _projectTextSearch.statusType.fetching
|
|
||||||
});
|
|
||||||
expect(component).toMatchSnapshot();
|
|
||||||
}); // "false if done & has results"
|
|
||||||
// is the same test as "found search results"
|
|
||||||
// "true if done & has no results"
|
|
||||||
// is the same test as "found no search results"
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,277 +0,0 @@
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var _react = require("devtools/client/shared/vendor/react");
|
|
||||||
|
|
||||||
var _react2 = _interopRequireDefault(_react);
|
|
||||||
|
|
||||||
var _enzyme = require("enzyme/index");
|
|
||||||
|
|
||||||
var _QuickOpenModal = require("../QuickOpenModal");
|
|
||||||
|
|
||||||
var _fuzzaldrinPlus = require("devtools/client/debugger/new/dist/vendors").vendored["fuzzaldrin-plus"];
|
|
||||||
|
|
||||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
||||||
|
|
||||||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }
|
|
||||||
|
|
||||||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
||||||
|
|
||||||
jest.mock("fuzzaldrin-plus");
|
|
||||||
|
|
||||||
function generateModal(propOverrides, renderType = "shallow") {
|
|
||||||
const props = _objectSpread({
|
|
||||||
enabled: false,
|
|
||||||
query: "",
|
|
||||||
searchType: "sources",
|
|
||||||
sources: [],
|
|
||||||
tabs: [],
|
|
||||||
selectLocation: jest.fn(),
|
|
||||||
setQuickOpenQuery: jest.fn(),
|
|
||||||
highlightLineRange: jest.fn(),
|
|
||||||
clearHighlightLineRange: jest.fn(),
|
|
||||||
closeQuickOpen: jest.fn()
|
|
||||||
}, propOverrides);
|
|
||||||
|
|
||||||
return {
|
|
||||||
wrapper: renderType === "shallow" ? (0, _enzyme.shallow)(_react2.default.createElement(_QuickOpenModal.QuickOpenModal, props)) : (0, _enzyme.mount)(_react2.default.createElement(_QuickOpenModal.QuickOpenModal, props)),
|
|
||||||
props
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
describe("QuickOpenModal", () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
_fuzzaldrinPlus.filter.mockClear();
|
|
||||||
});
|
|
||||||
test("Doesn't render when disabled", () => {
|
|
||||||
const {
|
|
||||||
wrapper
|
|
||||||
} = generateModal();
|
|
||||||
expect(wrapper).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
test("Renders when enabled", () => {
|
|
||||||
const {
|
|
||||||
wrapper
|
|
||||||
} = generateModal({
|
|
||||||
enabled: true
|
|
||||||
});
|
|
||||||
expect(wrapper).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
test("Basic render with mount", () => {
|
|
||||||
const {
|
|
||||||
wrapper
|
|
||||||
} = generateModal({
|
|
||||||
enabled: true
|
|
||||||
}, "mount");
|
|
||||||
expect(wrapper).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
test("Basic render with mount & searchType = functions", () => {
|
|
||||||
const {
|
|
||||||
wrapper
|
|
||||||
} = generateModal({
|
|
||||||
enabled: true,
|
|
||||||
query: "@",
|
|
||||||
searchType: "functions",
|
|
||||||
symbols: {
|
|
||||||
functions: [],
|
|
||||||
variables: []
|
|
||||||
}
|
|
||||||
}, "mount");
|
|
||||||
expect(wrapper).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
test("Ensure anonymous functions do not render in QuickOpenModal", () => {
|
|
||||||
const {
|
|
||||||
wrapper
|
|
||||||
} = generateModal({
|
|
||||||
enabled: true,
|
|
||||||
query: "@",
|
|
||||||
searchType: "functions",
|
|
||||||
symbols: {
|
|
||||||
functions: [{
|
|
||||||
title: "anonymous"
|
|
||||||
}, {
|
|
||||||
title: "c"
|
|
||||||
}, {
|
|
||||||
title: "anonymous"
|
|
||||||
}],
|
|
||||||
variables: []
|
|
||||||
}
|
|
||||||
}, "mount");
|
|
||||||
expect(wrapper.find("ResultList")).toHaveLength(1);
|
|
||||||
expect(wrapper.find("li")).toHaveLength(1);
|
|
||||||
});
|
|
||||||
test("Basic render with mount & searchType = variables", () => {
|
|
||||||
const {
|
|
||||||
wrapper
|
|
||||||
} = generateModal({
|
|
||||||
enabled: true,
|
|
||||||
query: "#",
|
|
||||||
searchType: "variables",
|
|
||||||
symbols: {
|
|
||||||
functions: [],
|
|
||||||
variables: []
|
|
||||||
}
|
|
||||||
}, "mount");
|
|
||||||
expect(wrapper).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
test("Basic render with mount & searchType = shortcuts", () => {
|
|
||||||
const {
|
|
||||||
wrapper
|
|
||||||
} = generateModal({
|
|
||||||
enabled: true,
|
|
||||||
query: "?",
|
|
||||||
searchType: "shortcuts",
|
|
||||||
symbols: {
|
|
||||||
functions: [],
|
|
||||||
variables: []
|
|
||||||
}
|
|
||||||
}, "mount");
|
|
||||||
expect(wrapper.find("ResultList")).toHaveLength(1);
|
|
||||||
expect(wrapper.find("li")).toHaveLength(3);
|
|
||||||
});
|
|
||||||
test("updateResults on enable", () => {
|
|
||||||
const {
|
|
||||||
wrapper
|
|
||||||
} = generateModal({}, "mount");
|
|
||||||
expect(wrapper).toMatchSnapshot();
|
|
||||||
wrapper.setProps({
|
|
||||||
enabled: true
|
|
||||||
});
|
|
||||||
expect(wrapper).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
test("basic source search", () => {
|
|
||||||
const {
|
|
||||||
wrapper
|
|
||||||
} = generateModal({
|
|
||||||
enabled: true,
|
|
||||||
symbols: {
|
|
||||||
functions: [],
|
|
||||||
variables: []
|
|
||||||
}
|
|
||||||
}, "mount");
|
|
||||||
wrapper.find("input").simulate("change", {
|
|
||||||
target: {
|
|
||||||
value: "somefil"
|
|
||||||
}
|
|
||||||
});
|
|
||||||
expect(_fuzzaldrinPlus.filter).toHaveBeenCalledWith([], "somefil", {
|
|
||||||
key: "value",
|
|
||||||
maxResults: 1000
|
|
||||||
});
|
|
||||||
});
|
|
||||||
test("basic gotoSource search", () => {
|
|
||||||
const {
|
|
||||||
wrapper
|
|
||||||
} = generateModal({
|
|
||||||
enabled: true,
|
|
||||||
searchType: "gotoSource",
|
|
||||||
symbols: {
|
|
||||||
functions: [],
|
|
||||||
variables: []
|
|
||||||
}
|
|
||||||
}, "mount");
|
|
||||||
wrapper.find("input").simulate("change", {
|
|
||||||
target: {
|
|
||||||
value: "somefil:33"
|
|
||||||
}
|
|
||||||
});
|
|
||||||
expect(_fuzzaldrinPlus.filter).toHaveBeenCalledWith([], "somefil", {
|
|
||||||
key: "value",
|
|
||||||
maxResults: 1000
|
|
||||||
});
|
|
||||||
});
|
|
||||||
test("basic symbol seach", () => {
|
|
||||||
const {
|
|
||||||
wrapper
|
|
||||||
} = generateModal({
|
|
||||||
enabled: true,
|
|
||||||
searchType: "functions",
|
|
||||||
symbols: {
|
|
||||||
functions: [],
|
|
||||||
variables: []
|
|
||||||
},
|
|
||||||
// symbol searching relies on a source being selected.
|
|
||||||
// So we dummy out the source and the API.
|
|
||||||
selectedSource: {
|
|
||||||
get: jest.fn(() => true)
|
|
||||||
}
|
|
||||||
}, "mount");
|
|
||||||
wrapper.find("input").simulate("change", {
|
|
||||||
target: {
|
|
||||||
value: "@someFunc"
|
|
||||||
}
|
|
||||||
});
|
|
||||||
expect(_fuzzaldrinPlus.filter).toHaveBeenCalledWith([], "someFunc", {
|
|
||||||
key: "value",
|
|
||||||
maxResults: 1000
|
|
||||||
});
|
|
||||||
});
|
|
||||||
test("Simple goto search query = :abc & searchType = goto", () => {
|
|
||||||
const {
|
|
||||||
wrapper
|
|
||||||
} = generateModal({
|
|
||||||
enabled: true,
|
|
||||||
query: ":abc",
|
|
||||||
searchType: "goto",
|
|
||||||
symbols: {
|
|
||||||
functions: [],
|
|
||||||
variables: []
|
|
||||||
}
|
|
||||||
}, "mount");
|
|
||||||
expect(wrapper).toMatchSnapshot();
|
|
||||||
expect(wrapper.state().results).toEqual(null);
|
|
||||||
});
|
|
||||||
describe("showErrorEmoji", () => {
|
|
||||||
it("true when no count + query", () => {
|
|
||||||
const {
|
|
||||||
wrapper
|
|
||||||
} = generateModal({
|
|
||||||
enabled: true,
|
|
||||||
query: "test",
|
|
||||||
searchType: ""
|
|
||||||
}, "mount");
|
|
||||||
expect(wrapper).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
it("false when count + query", () => {
|
|
||||||
const {
|
|
||||||
wrapper
|
|
||||||
} = generateModal({
|
|
||||||
enabled: true,
|
|
||||||
query: "dasdasdas"
|
|
||||||
}, "mount");
|
|
||||||
wrapper.setState(() => ({
|
|
||||||
results: [1, 2]
|
|
||||||
}));
|
|
||||||
expect(wrapper).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
it("false when no query", () => {
|
|
||||||
const {
|
|
||||||
wrapper
|
|
||||||
} = generateModal({
|
|
||||||
enabled: true,
|
|
||||||
query: "",
|
|
||||||
searchType: ""
|
|
||||||
}, "mount");
|
|
||||||
expect(wrapper).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
it("false when goto numeric ':2222'", () => {
|
|
||||||
const {
|
|
||||||
wrapper
|
|
||||||
} = generateModal({
|
|
||||||
enabled: true,
|
|
||||||
query: ":2222",
|
|
||||||
searchType: "goto"
|
|
||||||
}, "mount");
|
|
||||||
expect(wrapper).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
it("true when goto not numeric ':22k22'", () => {
|
|
||||||
const {
|
|
||||||
wrapper
|
|
||||||
} = generateModal({
|
|
||||||
enabled: true,
|
|
||||||
query: ":22k22",
|
|
||||||
searchType: "goto"
|
|
||||||
}, "mount");
|
|
||||||
expect(wrapper).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,28 +0,0 @@
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var _react = require("devtools/client/shared/vendor/react");
|
|
||||||
|
|
||||||
var _react2 = _interopRequireDefault(_react);
|
|
||||||
|
|
||||||
var _enzyme = require("enzyme/index");
|
|
||||||
|
|
||||||
var _ShortcutsModal = require("../ShortcutsModal");
|
|
||||||
|
|
||||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
||||||
|
|
||||||
/* 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/>. */
|
|
||||||
describe("ShortcutsModal", () => {
|
|
||||||
it("renders when enabled", () => {
|
|
||||||
const enabled = true;
|
|
||||||
const wrapper = (0, _enzyme.shallow)(_react2.default.createElement(_ShortcutsModal.ShortcutsModal, {
|
|
||||||
enabled: enabled
|
|
||||||
}));
|
|
||||||
expect(wrapper).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
it("renders nothing when not enabled", () => {
|
|
||||||
const wrapper = (0, _enzyme.shallow)(_react2.default.createElement(_ShortcutsModal.ShortcutsModal, null));
|
|
||||||
expect(wrapper.text()).toBe("");
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,639 +0,0 @@
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var _react = require("devtools/client/shared/vendor/react");
|
|
||||||
|
|
||||||
var _react2 = _interopRequireDefault(_react);
|
|
||||||
|
|
||||||
var _enzyme = require("enzyme/index");
|
|
||||||
|
|
||||||
var _SourcesTree = require("../../components/PrimaryPanes/SourcesTree");
|
|
||||||
|
|
||||||
var _SourcesTree2 = _interopRequireDefault(_SourcesTree);
|
|
||||||
|
|
||||||
var _immutable = require("devtools/client/shared/vendor/immutable");
|
|
||||||
|
|
||||||
var I = _interopRequireWildcard(_immutable);
|
|
||||||
|
|
||||||
var _devtoolsContextmenu = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-contextmenu"];
|
|
||||||
|
|
||||||
var _clipboard = require("../../utils/clipboard");
|
|
||||||
|
|
||||||
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
|
|
||||||
|
|
||||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
||||||
|
|
||||||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }
|
|
||||||
|
|
||||||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
||||||
|
|
||||||
jest.mock("devtools-contextmenu", () => ({
|
|
||||||
showMenu: jest.fn()
|
|
||||||
}));
|
|
||||||
jest.mock("../../utils/clipboard", () => ({
|
|
||||||
copyToTheClipboard: jest.fn()
|
|
||||||
}));
|
|
||||||
describe("SourcesTree", () => {
|
|
||||||
afterEach(() => {
|
|
||||||
_clipboard.copyToTheClipboard.mockClear();
|
|
||||||
|
|
||||||
_devtoolsContextmenu.showMenu.mockClear();
|
|
||||||
});
|
|
||||||
it("Should show the tree with nothing expanded", async () => {
|
|
||||||
const {
|
|
||||||
component
|
|
||||||
} = render();
|
|
||||||
expect(component).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
describe("When loading initial source", () => {
|
|
||||||
it("Shows the tree with one.js, two.js and three.js expanded", async () => {
|
|
||||||
const {
|
|
||||||
component,
|
|
||||||
props
|
|
||||||
} = render();
|
|
||||||
await component.setProps(_objectSpread({}, props, {
|
|
||||||
expanded: ["one.js", "two.js", "three.js"]
|
|
||||||
}));
|
|
||||||
expect(component).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
describe("After changing expanded nodes", () => {
|
|
||||||
it("Shows the tree with four.js, five.js and six.js expanded", async () => {
|
|
||||||
const {
|
|
||||||
component,
|
|
||||||
props
|
|
||||||
} = render();
|
|
||||||
await component.setProps(_objectSpread({}, props, {
|
|
||||||
expanded: ["four.js", "five.js", "six.js"]
|
|
||||||
}));
|
|
||||||
expect(component).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
describe("on receiving new props", () => {
|
|
||||||
describe("recreates tree", () => {
|
|
||||||
it("does not recreate tree if no new source is added", async () => {
|
|
||||||
const {
|
|
||||||
component,
|
|
||||||
props,
|
|
||||||
defaultState
|
|
||||||
} = render();
|
|
||||||
const mockSource = I.Map({
|
|
||||||
"server1.conn13.child1/41": createMockSource("server1.conn13.child1/41", "http://mdn.com/three.js")
|
|
||||||
});
|
|
||||||
await component.setProps(_objectSpread({}, props, {
|
|
||||||
sources: mockSource
|
|
||||||
}));
|
|
||||||
expect(component.state("uncollapsedTree")).toEqual(defaultState.uncollapsedTree);
|
|
||||||
});
|
|
||||||
it("updates tree with a new item", async () => {
|
|
||||||
const {
|
|
||||||
component,
|
|
||||||
props
|
|
||||||
} = render();
|
|
||||||
const sources = props.sources.merge({
|
|
||||||
"server1.conn13.child1/42": createMockSource("server1.conn13.child1/42", "http://mdn.com/four.js")
|
|
||||||
});
|
|
||||||
await component.setProps(_objectSpread({}, props, {
|
|
||||||
sources: sources
|
|
||||||
}));
|
|
||||||
expect(component.state("uncollapsedTree").contents[0].contents).toHaveLength(4);
|
|
||||||
});
|
|
||||||
it("updates sources if sources are emptied", async () => {
|
|
||||||
const {
|
|
||||||
component,
|
|
||||||
props,
|
|
||||||
defaultState
|
|
||||||
} = render();
|
|
||||||
expect(defaultState.uncollapsedTree.contents).toHaveLength(1);
|
|
||||||
await component.setProps(_objectSpread({}, props, {
|
|
||||||
sources: I.Map({})
|
|
||||||
}));
|
|
||||||
expect(component.state("uncollapsedTree").contents).toHaveLength(0);
|
|
||||||
});
|
|
||||||
it("recreates tree if projectRoot is changed", async () => {
|
|
||||||
const {
|
|
||||||
component,
|
|
||||||
props,
|
|
||||||
defaultState
|
|
||||||
} = render();
|
|
||||||
const sources = I.Map({
|
|
||||||
"server1.conn13.child1/41": createMockSource("server1.conn13.child1/41", "http://mozilla.com/three.js")
|
|
||||||
});
|
|
||||||
expect(defaultState.uncollapsedTree.contents[0].contents).toHaveLength(3);
|
|
||||||
await component.setProps(_objectSpread({}, props, {
|
|
||||||
sources: sources,
|
|
||||||
projectRoot: "mozilla"
|
|
||||||
}));
|
|
||||||
expect(component.state("uncollapsedTree").contents[0].contents).toHaveLength(1);
|
|
||||||
});
|
|
||||||
it("recreates tree if debugeeUrl is changed", async () => {
|
|
||||||
const {
|
|
||||||
component,
|
|
||||||
props,
|
|
||||||
defaultState
|
|
||||||
} = render();
|
|
||||||
const mockSource = I.Map({
|
|
||||||
"server1.conn13.child1/41": createMockSource("server1.conn13.child1/41", "http://mdn.com/three.js")
|
|
||||||
});
|
|
||||||
expect(defaultState.uncollapsedTree.contents[0].contents).toHaveLength(3);
|
|
||||||
await component.setProps(_objectSpread({}, props, {
|
|
||||||
debuggeeUrl: "mozilla",
|
|
||||||
sources: mockSource
|
|
||||||
}));
|
|
||||||
expect(component.state("uncollapsedTree").contents[0].contents).toHaveLength(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
describe("updates list items", () => {
|
|
||||||
it("updates list items if shownSource changes", async () => {
|
|
||||||
const {
|
|
||||||
component,
|
|
||||||
props
|
|
||||||
} = render();
|
|
||||||
await component.setProps(_objectSpread({}, props, {
|
|
||||||
shownSource: "http://mdn.com/three.js"
|
|
||||||
}));
|
|
||||||
expect(component).toMatchSnapshot();
|
|
||||||
expect(props.selectLocation).toHaveBeenCalledWith({
|
|
||||||
sourceId: "server1.conn13.child1/41"
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
describe("updates highlighted items", () => {
|
|
||||||
it("updates highlightItems if selectedSource changes", async () => {
|
|
||||||
const {
|
|
||||||
component,
|
|
||||||
props
|
|
||||||
} = render();
|
|
||||||
const mockSource = I.Map({
|
|
||||||
"server1.conn13.child1/41": createMockSource("server1.conn13.child1/41", "http://mdn.com/three.js")
|
|
||||||
});
|
|
||||||
await component.setProps(_objectSpread({}, props, {
|
|
||||||
selectedSource: mockSource
|
|
||||||
}));
|
|
||||||
expect(component).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
describe("focusItem", () => {
|
|
||||||
it("update the focused item", async () => {
|
|
||||||
const {
|
|
||||||
component,
|
|
||||||
instance,
|
|
||||||
props
|
|
||||||
} = render();
|
|
||||||
const item = createMockItem();
|
|
||||||
await instance.focusItem(item);
|
|
||||||
await component.update();
|
|
||||||
await component.find(".sources-list").simulate("keydown", {
|
|
||||||
keyCode: 13
|
|
||||||
});
|
|
||||||
expect(props.selectLocation).toHaveBeenCalledWith({
|
|
||||||
sourceId: item.contents.get("id")
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
describe("with custom root", () => {
|
|
||||||
it("renders custom root source list", async () => {
|
|
||||||
const {
|
|
||||||
component
|
|
||||||
} = render({
|
|
||||||
projectRoot: "mdn.com"
|
|
||||||
});
|
|
||||||
expect(component).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
it("calls clearProjectDirectoryRoot on click", async () => {
|
|
||||||
const {
|
|
||||||
component,
|
|
||||||
props
|
|
||||||
} = render({
|
|
||||||
projectRoot: "mdn"
|
|
||||||
});
|
|
||||||
component.find(".sources-clear-root").simulate("click");
|
|
||||||
expect(props.clearProjectDirectoryRoot).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
it("renders empty custom root source list", async () => {
|
|
||||||
const {
|
|
||||||
component
|
|
||||||
} = render({
|
|
||||||
projectRoot: "custom",
|
|
||||||
sources: I.Map()
|
|
||||||
});
|
|
||||||
expect(component).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
describe("onContextMenu of the tree", () => {
|
|
||||||
it("shows context menu on directory to set as root", async () => {
|
|
||||||
const menuOptions = [{
|
|
||||||
accesskey: "r",
|
|
||||||
click: expect.any(Function),
|
|
||||||
disabled: false,
|
|
||||||
id: "node-set-directory-root",
|
|
||||||
label: "Set directory root"
|
|
||||||
}];
|
|
||||||
const mockEvent = {
|
|
||||||
preventDefault: jest.fn(),
|
|
||||||
stopPropagation: jest.fn()
|
|
||||||
};
|
|
||||||
const {
|
|
||||||
props,
|
|
||||||
instance
|
|
||||||
} = render({
|
|
||||||
projectRoot: "root/"
|
|
||||||
});
|
|
||||||
await instance.onContextMenu(mockEvent, createMockDirectory());
|
|
||||||
expect(_devtoolsContextmenu.showMenu).toHaveBeenCalledWith(mockEvent, menuOptions);
|
|
||||||
expect(mockEvent.preventDefault).toHaveBeenCalled();
|
|
||||||
expect(mockEvent.stopPropagation).toHaveBeenCalled();
|
|
||||||
|
|
||||||
_devtoolsContextmenu.showMenu.mock.calls[0][1][0].click();
|
|
||||||
|
|
||||||
expect(props.setProjectDirectoryRoot).toHaveBeenCalled();
|
|
||||||
expect(props.clearProjectDirectoryRoot).not.toHaveBeenCalled();
|
|
||||||
expect(_clipboard.copyToTheClipboard).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
it("shows context menu on file to copy source uri", async () => {
|
|
||||||
const menuOptions = [{
|
|
||||||
accesskey: "u",
|
|
||||||
click: expect.any(Function),
|
|
||||||
disabled: false,
|
|
||||||
id: "node-menu-copy-source",
|
|
||||||
label: "Copy source URI"
|
|
||||||
}];
|
|
||||||
const mockEvent = {
|
|
||||||
preventDefault: jest.fn(),
|
|
||||||
stopPropagation: jest.fn()
|
|
||||||
};
|
|
||||||
const {
|
|
||||||
props,
|
|
||||||
instance
|
|
||||||
} = render({
|
|
||||||
projectRoot: "root/"
|
|
||||||
});
|
|
||||||
await instance.onContextMenu(mockEvent, createMockItem());
|
|
||||||
expect(_devtoolsContextmenu.showMenu).toHaveBeenCalledWith(mockEvent, menuOptions);
|
|
||||||
expect(mockEvent.preventDefault).toHaveBeenCalled();
|
|
||||||
expect(mockEvent.stopPropagation).toHaveBeenCalled();
|
|
||||||
|
|
||||||
_devtoolsContextmenu.showMenu.mock.calls[0][1][0].click();
|
|
||||||
|
|
||||||
expect(props.setProjectDirectoryRoot).not.toHaveBeenCalled();
|
|
||||||
expect(props.clearProjectDirectoryRoot).not.toHaveBeenCalled();
|
|
||||||
expect(_clipboard.copyToTheClipboard).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
it("shows context menu on root to remove directory root", async () => {
|
|
||||||
const menuOptions = [{
|
|
||||||
click: expect.any(Function),
|
|
||||||
disabled: false,
|
|
||||||
id: "node-remove-directory-root",
|
|
||||||
label: "Remove directory root"
|
|
||||||
}];
|
|
||||||
const {
|
|
||||||
props,
|
|
||||||
instance
|
|
||||||
} = render({
|
|
||||||
projectRoot: "root/"
|
|
||||||
});
|
|
||||||
const mockEvent = {
|
|
||||||
preventDefault: jest.fn(),
|
|
||||||
stopPropagation: jest.fn()
|
|
||||||
};
|
|
||||||
await instance.onContextMenu(mockEvent, createMockDirectory("root/", "root"));
|
|
||||||
expect(_devtoolsContextmenu.showMenu).toHaveBeenCalledWith(mockEvent, menuOptions);
|
|
||||||
expect(mockEvent.preventDefault).toHaveBeenCalled();
|
|
||||||
expect(mockEvent.stopPropagation).toHaveBeenCalled();
|
|
||||||
|
|
||||||
_devtoolsContextmenu.showMenu.mock.calls[0][1][0].click();
|
|
||||||
|
|
||||||
expect(props.setProjectDirectoryRoot).not.toHaveBeenCalled();
|
|
||||||
expect(props.clearProjectDirectoryRoot).toHaveBeenCalled();
|
|
||||||
expect(_clipboard.copyToTheClipboard).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
describe("renderItem", () => {
|
|
||||||
it("should show icon for webpack item", async () => {
|
|
||||||
const {
|
|
||||||
instance
|
|
||||||
} = render();
|
|
||||||
const item = createMockDirectory("webpack://", "webpack://");
|
|
||||||
const node = renderItem(instance, item);
|
|
||||||
expect(node).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
it("should show icon for angular item", async () => {
|
|
||||||
const {
|
|
||||||
instance
|
|
||||||
} = render();
|
|
||||||
const item = createMockDirectory("ng://", "ng://");
|
|
||||||
const node = renderItem(instance, item);
|
|
||||||
expect(node).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
it("should show icon for moz-extension item", async () => {
|
|
||||||
const {
|
|
||||||
instance
|
|
||||||
} = render();
|
|
||||||
const item = createMockDirectory("moz-extension://", "moz-extension://");
|
|
||||||
const node = renderItem(instance, item);
|
|
||||||
expect(node).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
it("should show icon for folder with arrow", async () => {
|
|
||||||
const {
|
|
||||||
instance
|
|
||||||
} = render();
|
|
||||||
const node = renderItem(instance, createMockDirectory());
|
|
||||||
expect(node).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
it("should show icon for folder with expanded arrow", async () => {
|
|
||||||
const {
|
|
||||||
instance
|
|
||||||
} = render();
|
|
||||||
const node = renderItem(instance, createMockDirectory(), 1, false, true);
|
|
||||||
expect(node).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
it("should show focused item for folder with expanded arrow", async () => {
|
|
||||||
const {
|
|
||||||
instance
|
|
||||||
} = render();
|
|
||||||
const node = renderItem(instance, createMockDirectory(), 1, true, true);
|
|
||||||
expect(node).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
it("should show source item with source icon", async () => {
|
|
||||||
const {
|
|
||||||
instance
|
|
||||||
} = render();
|
|
||||||
const node = renderItem(instance, createMockItem());
|
|
||||||
expect(node).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
it("should show source item with source icon with focus", async () => {
|
|
||||||
const {
|
|
||||||
instance
|
|
||||||
} = render();
|
|
||||||
const node = renderItem(instance, createMockItem(), 1, true, false);
|
|
||||||
expect(node).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
it("should show domain item", async () => {
|
|
||||||
const {
|
|
||||||
instance
|
|
||||||
} = render();
|
|
||||||
const item = createMockItem("root", "root");
|
|
||||||
const node = renderItem(instance, item, 0);
|
|
||||||
expect(node).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
it("should show domain item as debuggee", async () => {
|
|
||||||
const {
|
|
||||||
instance
|
|
||||||
} = render();
|
|
||||||
const item = createMockItem("root", "http://mdn.com");
|
|
||||||
const node = renderItem(instance, item, 0);
|
|
||||||
expect(node).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
it("should show domain item as debuggee with focus and arrow", async () => {
|
|
||||||
const {
|
|
||||||
instance
|
|
||||||
} = render();
|
|
||||||
const item = createMockDirectory("root", "http://mdn.com");
|
|
||||||
const node = renderItem(instance, item, 0, true);
|
|
||||||
expect(node).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
it("should not show domain item when the projectRoot exists", async () => {
|
|
||||||
const {
|
|
||||||
instance
|
|
||||||
} = render({
|
|
||||||
projectRoot: "root/"
|
|
||||||
});
|
|
||||||
const node = renderItem(instance, createMockItem(), 0);
|
|
||||||
expect(node).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
it("should show menu on contextmenu of an item", async () => {
|
|
||||||
const {
|
|
||||||
instance
|
|
||||||
} = render();
|
|
||||||
const item = createMockItem();
|
|
||||||
instance.onContextMenu = jest.fn(() => {});
|
|
||||||
const event = {
|
|
||||||
event: "contextmenu"
|
|
||||||
};
|
|
||||||
const node = (0, _enzyme.shallow)(renderItem(instance, item, 1, true));
|
|
||||||
node.simulate("contextmenu", event);
|
|
||||||
expect(instance.onContextMenu).toHaveBeenCalledWith(event, item);
|
|
||||||
});
|
|
||||||
it("should focus on and select item on click", async () => {
|
|
||||||
const {
|
|
||||||
component,
|
|
||||||
instance,
|
|
||||||
props
|
|
||||||
} = render();
|
|
||||||
const item = createMockItem();
|
|
||||||
const event = {
|
|
||||||
event: "click"
|
|
||||||
};
|
|
||||||
const setExpanded = jest.fn();
|
|
||||||
const node = (0, _enzyme.shallow)(renderItem(instance, item, 1, true, false, setExpanded));
|
|
||||||
node.simulate("click", event);
|
|
||||||
await component.find(".sources-list").simulate("keydown", {
|
|
||||||
keyCode: 13
|
|
||||||
});
|
|
||||||
expect(props.selectLocation).toHaveBeenCalledWith({
|
|
||||||
sourceId: item.contents.get("id")
|
|
||||||
});
|
|
||||||
expect(setExpanded).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
it("should focus on and expand directory on click", async () => {
|
|
||||||
const {
|
|
||||||
component,
|
|
||||||
instance,
|
|
||||||
props
|
|
||||||
} = render();
|
|
||||||
const event = {
|
|
||||||
event: "click"
|
|
||||||
};
|
|
||||||
const setExpanded = jest.fn();
|
|
||||||
const mockDirectory = createMockDirectory();
|
|
||||||
const node = (0, _enzyme.shallow)(renderItem(instance, mockDirectory, 1, true, false, setExpanded));
|
|
||||||
node.simulate("click", event);
|
|
||||||
expect(component.state("focusedItem")).toEqual(mockDirectory);
|
|
||||||
expect(setExpanded).toHaveBeenCalled();
|
|
||||||
expect(props.selectLocation).not.toHaveBeenCalledWith();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
describe("selectItem", () => {
|
|
||||||
it("should select item with no children", async () => {
|
|
||||||
const {
|
|
||||||
instance,
|
|
||||||
props
|
|
||||||
} = render();
|
|
||||||
instance.selectItem(createMockItem());
|
|
||||||
expect(props.selectLocation).toHaveBeenCalledWith({
|
|
||||||
sourceId: "server1.conn13.child1/39"
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it("should not select item with children", async () => {
|
|
||||||
const {
|
|
||||||
props,
|
|
||||||
instance
|
|
||||||
} = render();
|
|
||||||
instance.selectItem(createMockDirectory());
|
|
||||||
expect(props.selectLocation).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
it("should select item on enter onKeyDown event", async () => {
|
|
||||||
const {
|
|
||||||
component,
|
|
||||||
props,
|
|
||||||
instance
|
|
||||||
} = render();
|
|
||||||
await instance.focusItem(createMockItem());
|
|
||||||
await component.update();
|
|
||||||
await component.find(".sources-list").simulate("keydown", {
|
|
||||||
keyCode: 13
|
|
||||||
});
|
|
||||||
expect(props.selectLocation).toHaveBeenCalledWith({
|
|
||||||
sourceId: "server1.conn13.child1/39"
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it("does not select if no item is focused on", async () => {
|
|
||||||
const {
|
|
||||||
component,
|
|
||||||
props
|
|
||||||
} = render();
|
|
||||||
await component.find(".sources-list").simulate("keydown", {
|
|
||||||
keyCode: 13
|
|
||||||
});
|
|
||||||
expect(props.selectLocation).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
describe("handles items", () => {
|
|
||||||
it("getChildren from directory", async () => {
|
|
||||||
const {
|
|
||||||
component
|
|
||||||
} = render();
|
|
||||||
const item = createMockDirectory("http://mdn.com/views", "views", ["a", "b"]);
|
|
||||||
const children = component.find("ManagedTree").props().getChildren(item);
|
|
||||||
expect(children).toEqual(["a", "b"]);
|
|
||||||
});
|
|
||||||
it("getChildren from non directory", async () => {
|
|
||||||
const {
|
|
||||||
component
|
|
||||||
} = render();
|
|
||||||
const children = component.find("ManagedTree").props().getChildren(createMockItem());
|
|
||||||
expect(children).toEqual([]);
|
|
||||||
});
|
|
||||||
it("onExpand", async () => {
|
|
||||||
const {
|
|
||||||
component,
|
|
||||||
props
|
|
||||||
} = render();
|
|
||||||
const expandedState = ["x", "y"];
|
|
||||||
await component.find("ManagedTree").props().onExpand({}, expandedState);
|
|
||||||
expect(props.setExpandedState).toHaveBeenCalledWith(expandedState);
|
|
||||||
});
|
|
||||||
it("onCollapse", async () => {
|
|
||||||
const {
|
|
||||||
component,
|
|
||||||
props
|
|
||||||
} = render();
|
|
||||||
const expandedState = ["y", "z"];
|
|
||||||
await component.find("ManagedTree").props().onCollapse({}, expandedState);
|
|
||||||
expect(props.setExpandedState).toHaveBeenCalledWith(expandedState);
|
|
||||||
});
|
|
||||||
it("getParent", async () => {
|
|
||||||
const {
|
|
||||||
component
|
|
||||||
} = render();
|
|
||||||
const item = component.state("sourceTree").contents[0].contents[0];
|
|
||||||
const parent = component.find("ManagedTree").props().getParent(item);
|
|
||||||
expect(parent.path).toEqual("mdn.com");
|
|
||||||
expect(parent.contents).toHaveLength(3);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
describe("getPath", () => {
|
|
||||||
it("should return path for item", async () => {
|
|
||||||
const {
|
|
||||||
instance
|
|
||||||
} = render();
|
|
||||||
const path = instance.getPath(createMockItem());
|
|
||||||
expect(path).toEqual("http://mdn.com/one.js/one.js/");
|
|
||||||
});
|
|
||||||
it("should return path for blackboxedboxed item", async () => {
|
|
||||||
const item = createMockItem("http://mdn.com/blackboxed.js", "blackboxed.js", I.Map({
|
|
||||||
id: "server1.conn13.child1/59"
|
|
||||||
}));
|
|
||||||
const source = I.Map({
|
|
||||||
"server1.conn13.child1/59": createMockSource("server1.conn13.child1/59", "http://mdn.com/blackboxed.js", true)
|
|
||||||
});
|
|
||||||
const {
|
|
||||||
instance
|
|
||||||
} = render({
|
|
||||||
sources: source
|
|
||||||
});
|
|
||||||
const path = instance.getPath(item);
|
|
||||||
expect(path).toEqual("http://mdn.com/blackboxed.js/blackboxed.js/update");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
function generateDefaults(overrides) {
|
|
||||||
const defaultSources = I.Map({
|
|
||||||
"server1.conn13.child1/39": createMockSource("server1.conn13.child1/39", "http://mdn.com/one.js"),
|
|
||||||
"server1.conn13.child1/40": createMockSource("server1.conn13.child1/40", "http://mdn.com/two.js"),
|
|
||||||
"server1.conn13.child1/41": createMockSource("server1.conn13.child1/41", "http://mdn.com/three.js")
|
|
||||||
});
|
|
||||||
return _objectSpread({
|
|
||||||
autoExpandAll: true,
|
|
||||||
selectLocation: jest.fn(),
|
|
||||||
setExpandedState: jest.fn(),
|
|
||||||
sources: defaultSources,
|
|
||||||
debuggeeUrl: "http://mdn.com",
|
|
||||||
clearProjectDirectoryRoot: jest.fn(),
|
|
||||||
setProjectDirectoryRoot: jest.fn(),
|
|
||||||
projectRoot: ""
|
|
||||||
}, overrides);
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderItem(instance, item = createMockItem(), depth = 1, focused = false, expanded = false, setExpanded = jest.fn()) {
|
|
||||||
return instance.renderItem(item, depth, focused, null, expanded, {
|
|
||||||
setExpanded: setExpanded
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function render(overrides = {}) {
|
|
||||||
const props = generateDefaults(overrides);
|
|
||||||
const component = (0, _enzyme.shallow)(_react2.default.createElement(_SourcesTree2.default.WrappedComponent, props));
|
|
||||||
const defaultState = component.state();
|
|
||||||
const instance = component.instance();
|
|
||||||
|
|
||||||
instance.shouldComponentUpdate = () => true;
|
|
||||||
|
|
||||||
return {
|
|
||||||
component,
|
|
||||||
props,
|
|
||||||
defaultState,
|
|
||||||
instance
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function createMockSource(id, url, isBlackBoxed = false) {
|
|
||||||
return I.Map({
|
|
||||||
id: id,
|
|
||||||
url: url,
|
|
||||||
isPrettyPrinted: false,
|
|
||||||
isWasm: false,
|
|
||||||
sourceMapURL: null,
|
|
||||||
isBlackBoxed: isBlackBoxed,
|
|
||||||
loadedState: "unloaded"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function createMockDirectory(path = "folder/", name = "folder", contents = []) {
|
|
||||||
return {
|
|
||||||
name,
|
|
||||||
path,
|
|
||||||
contents
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function createMockItem(path = "http://mdn.com/one.js", name = "one.js", contents = I.Map({
|
|
||||||
id: "server1.conn13.child1/39"
|
|
||||||
})) {
|
|
||||||
return {
|
|
||||||
name,
|
|
||||||
path,
|
|
||||||
contents
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,50 +0,0 @@
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var _react = require("devtools/client/shared/vendor/react");
|
|
||||||
|
|
||||||
var _react2 = _interopRequireDefault(_react);
|
|
||||||
|
|
||||||
var _enzyme = require("enzyme/index");
|
|
||||||
|
|
||||||
var _WelcomeBox = require("../WelcomeBox");
|
|
||||||
|
|
||||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
||||||
|
|
||||||
/* 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/>. */
|
|
||||||
describe("WelomeBox", () => {
|
|
||||||
const setActiveSearch = () => null;
|
|
||||||
|
|
||||||
it("renders with default values", () => {
|
|
||||||
const wrapper = (0, _enzyme.shallow)(_react2.default.createElement(_WelcomeBox.WelcomeBox, {
|
|
||||||
setActiveSearch: setActiveSearch
|
|
||||||
}));
|
|
||||||
expect(wrapper).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
it("doesn't render toggle button in horizontal mode", () => {
|
|
||||||
const horizontal = true;
|
|
||||||
const wrapper = (0, _enzyme.shallow)(_react2.default.createElement(_WelcomeBox.WelcomeBox, {
|
|
||||||
horizontal: horizontal,
|
|
||||||
setActiveSearch: setActiveSearch
|
|
||||||
}));
|
|
||||||
expect(wrapper.find("PaneToggleButton")).toHaveLength(0);
|
|
||||||
});
|
|
||||||
it("calls correct function on searchSources click", () => {
|
|
||||||
const openQuickOpen = jest.fn();
|
|
||||||
const wrapper = (0, _enzyme.shallow)(_react2.default.createElement(_WelcomeBox.WelcomeBox, {
|
|
||||||
setActiveSearch: setActiveSearch,
|
|
||||||
openQuickOpen: openQuickOpen
|
|
||||||
}));
|
|
||||||
wrapper.find(".welcomebox__searchSources").simulate("click");
|
|
||||||
expect(openQuickOpen).toBeCalled();
|
|
||||||
});
|
|
||||||
it("calls correct function on searchProject click", () => {
|
|
||||||
const setActiveSearchSpy = jest.fn();
|
|
||||||
const wrapper = (0, _enzyme.shallow)(_react2.default.createElement(_WelcomeBox.WelcomeBox, {
|
|
||||||
setActiveSearch: setActiveSearchSpy
|
|
||||||
}));
|
|
||||||
wrapper.find(".welcomebox__searchProject").simulate("click");
|
|
||||||
expect(setActiveSearchSpy).toBeCalled();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,45 +0,0 @@
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var _enzyme = require("enzyme/index");
|
|
||||||
|
|
||||||
var _WhyPaused = require("../SecondaryPanes/Frames/WhyPaused.js/index");
|
|
||||||
|
|
||||||
var _WhyPaused2 = _interopRequireDefault(_WhyPaused);
|
|
||||||
|
|
||||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
||||||
|
|
||||||
/* 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/>. */
|
|
||||||
describe("WhyPaused", () => {
|
|
||||||
it("should pause reason with message", () => {
|
|
||||||
const why = {
|
|
||||||
type: "breakpoint",
|
|
||||||
message: "bla is hit"
|
|
||||||
};
|
|
||||||
const component = (0, _enzyme.shallow)((0, _WhyPaused2.default)(why));
|
|
||||||
expect(component).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
it("should show pause reason with exception details", () => {
|
|
||||||
const why = {
|
|
||||||
type: "exception",
|
|
||||||
exception: {
|
|
||||||
class: "Error",
|
|
||||||
preview: {
|
|
||||||
name: "ReferenceError",
|
|
||||||
message: "o is not defined"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const component = (0, _enzyme.shallow)((0, _WhyPaused2.default)(why));
|
|
||||||
expect(component).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
it("should show pause reason with exception string", () => {
|
|
||||||
const why = {
|
|
||||||
type: "exception",
|
|
||||||
exception: "Not Available"
|
|
||||||
};
|
|
||||||
const component = (0, _enzyme.shallow)((0, _WhyPaused2.default)(why));
|
|
||||||
expect(component).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,18 +0,0 @@
|
||||||
# vim: set filetype=python:
|
|
||||||
# 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/.
|
|
||||||
|
|
||||||
DIRS += [
|
|
||||||
|
|
||||||
]
|
|
||||||
|
|
||||||
DevToolsModules(
|
|
||||||
'Outline.spec.js',
|
|
||||||
'ProjectSearch.spec.js',
|
|
||||||
'QuickOpenModal.spec.js',
|
|
||||||
'ShortcutsModal.spec.js',
|
|
||||||
'SourcesTree.spec.js',
|
|
||||||
'WelcomeBox.spec.js',
|
|
||||||
'WhyPaused.spec.js',
|
|
||||||
)
|
|
|
@ -70,11 +70,12 @@ function update(state = initialASTState(), action) {
|
||||||
case "SET_PAUSE_POINTS":
|
case "SET_PAUSE_POINTS":
|
||||||
{
|
{
|
||||||
const {
|
const {
|
||||||
source,
|
sourceText,
|
||||||
|
sourceId,
|
||||||
pausePoints
|
pausePoints
|
||||||
} = action;
|
} = action;
|
||||||
const emptyLines = (0, _ast.findEmptyLines)(source, pausePoints);
|
const emptyLines = (0, _ast.findEmptyLines)(sourceText, pausePoints);
|
||||||
return state.setIn(["pausePoints", source.id], pausePoints).setIn(["emptyLines", source.id], emptyLines);
|
return state.setIn(["pausePoints", sourceId], pausePoints).setIn(["emptyLines", sourceId], emptyLines);
|
||||||
}
|
}
|
||||||
|
|
||||||
case "OUT_OF_SCOPE_LOCATIONS":
|
case "OUT_OF_SCOPE_LOCATIONS":
|
||||||
|
|
|
@ -24,6 +24,7 @@ exports.getFrameScope = getFrameScope;
|
||||||
exports.getSelectedScope = getSelectedScope;
|
exports.getSelectedScope = getSelectedScope;
|
||||||
exports.getSelectedScopeMappings = getSelectedScopeMappings;
|
exports.getSelectedScopeMappings = getSelectedScopeMappings;
|
||||||
exports.getSelectedFrameId = getSelectedFrameId;
|
exports.getSelectedFrameId = getSelectedFrameId;
|
||||||
|
exports.getSelectedComponentIndex = getSelectedComponentIndex;
|
||||||
exports.getTopFrame = getTopFrame;
|
exports.getTopFrame = getTopFrame;
|
||||||
exports.getDebuggeeUrl = getDebuggeeUrl;
|
exports.getDebuggeeUrl = getDebuggeeUrl;
|
||||||
exports.getSkipPausing = getSkipPausing;
|
exports.getSkipPausing = getSkipPausing;
|
||||||
|
@ -47,6 +48,7 @@ const createPauseState = exports.createPauseState = () => ({
|
||||||
isWaitingOnBreak: false,
|
isWaitingOnBreak: false,
|
||||||
frames: undefined,
|
frames: undefined,
|
||||||
selectedFrameId: undefined,
|
selectedFrameId: undefined,
|
||||||
|
selectedComponentIndex: undefined,
|
||||||
frameScopes: {
|
frameScopes: {
|
||||||
generated: {},
|
generated: {},
|
||||||
original: {},
|
original: {},
|
||||||
|
@ -177,6 +179,11 @@ function update(state = createPauseState(), action) {
|
||||||
selectedFrameId: action.frame.id
|
selectedFrameId: action.frame.id
|
||||||
});
|
});
|
||||||
|
|
||||||
|
case "SELECT_COMPONENT":
|
||||||
|
return _objectSpread({}, state, {
|
||||||
|
selectedComponentIndex: action.componentIndex
|
||||||
|
});
|
||||||
|
|
||||||
case "SET_POPUP_OBJECT_PROPERTIES":
|
case "SET_POPUP_OBJECT_PROPERTIES":
|
||||||
if (!action.properties) {
|
if (!action.properties) {
|
||||||
return _objectSpread({}, state);
|
return _objectSpread({}, state);
|
||||||
|
@ -386,6 +393,10 @@ function getSelectedFrameId(state) {
|
||||||
return state.pause.selectedFrameId;
|
return state.pause.selectedFrameId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getSelectedComponentIndex(state) {
|
||||||
|
return state.pause.selectedComponentIndex;
|
||||||
|
}
|
||||||
|
|
||||||
function getTopFrame(state) {
|
function getTopFrame(state) {
|
||||||
const frames = getFrames(state);
|
const frames = getFrames(state);
|
||||||
return frames && frames[0];
|
return frames && frames[0];
|
||||||
|
|
|
@ -115,7 +115,7 @@ function update(state = initialSourcesState(), action) {
|
||||||
return state.merge({
|
return state.merge({
|
||||||
tabs: updateTabList({
|
tabs: updateTabList({
|
||||||
sources: state
|
sources: state
|
||||||
}, action.source.url)
|
}, action.url)
|
||||||
});
|
});
|
||||||
|
|
||||||
case "MOVE_TAB":
|
case "MOVE_TAB":
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
DIRS += [
|
DIRS += [
|
||||||
'test',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
DevToolsModules(
|
DevToolsModules(
|
||||||
|
|
|
@ -1,189 +0,0 @@
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var _getCallStackFrames = require("../getCallStackFrames");
|
|
||||||
|
|
||||||
var _immutable = require("devtools/client/shared/vendor/immutable");
|
|
||||||
|
|
||||||
var _lodash = require("devtools/client/shared/vendor/lodash");
|
|
||||||
|
|
||||||
/* 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/>. */
|
|
||||||
describe("getCallStackFrames selector", () => {
|
|
||||||
describe("library annotation", () => {
|
|
||||||
it("annotates React frames", () => {
|
|
||||||
const state = {
|
|
||||||
frames: [{
|
|
||||||
location: {
|
|
||||||
sourceId: "source1"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
location: {
|
|
||||||
sourceId: "source2"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
location: {
|
|
||||||
sourceId: "source2"
|
|
||||||
}
|
|
||||||
}],
|
|
||||||
sources: (0, _immutable.fromJS)({
|
|
||||||
source1: {
|
|
||||||
id: "source1",
|
|
||||||
url: "webpack:///src/App.js"
|
|
||||||
},
|
|
||||||
source2: {
|
|
||||||
id: "source2",
|
|
||||||
url: "webpack:///~/react-dom/lib/ReactCompositeComponent.js"
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
selectedSource: (0, _immutable.fromJS)({
|
|
||||||
id: "sourceId-originalSource"
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
const frames = _getCallStackFrames.getCallStackFrames.resultFunc(state.frames, state.sources, state.selectedSource, true);
|
|
||||||
|
|
||||||
expect(frames[0]).not.toHaveProperty("library");
|
|
||||||
expect(frames[1]).toHaveProperty("library", "React");
|
|
||||||
expect(frames[2]).toHaveProperty("library", "React");
|
|
||||||
}); // Multiple Babel async frame groups occur when you have an async function
|
|
||||||
// calling another async function (a common case).
|
|
||||||
//
|
|
||||||
// There are two possible frame groups that can occur depending on whether
|
|
||||||
// one sets a breakpoint before or after an await
|
|
||||||
|
|
||||||
it("annotates frames related to Babel async transforms", () => {
|
|
||||||
const preAwaitGroup = [{
|
|
||||||
displayName: "asyncAppFunction",
|
|
||||||
location: {
|
|
||||||
sourceId: "bundle"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
displayName: "tryCatch",
|
|
||||||
location: {
|
|
||||||
sourceId: "regenerator"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
displayName: "invoke",
|
|
||||||
location: {
|
|
||||||
sourceId: "regenerator"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
displayName: "defineIteratorMethods/</prototype[method]",
|
|
||||||
location: {
|
|
||||||
sourceId: "regenerator"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
displayName: "step",
|
|
||||||
location: {
|
|
||||||
sourceId: "bundle"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
displayName: "_asyncToGenerator/</<",
|
|
||||||
location: {
|
|
||||||
sourceId: "bundle"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
displayName: "Promise",
|
|
||||||
location: {
|
|
||||||
sourceId: "promise"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
displayName: "_asyncToGenerator/<",
|
|
||||||
location: {
|
|
||||||
sourceId: "bundle"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
displayName: "asyncAppFunction",
|
|
||||||
location: {
|
|
||||||
sourceId: "app"
|
|
||||||
}
|
|
||||||
}];
|
|
||||||
const postAwaitGroup = [{
|
|
||||||
displayName: "asyncAppFunction",
|
|
||||||
location: {
|
|
||||||
sourceId: "bundle"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
displayName: "tryCatch",
|
|
||||||
location: {
|
|
||||||
sourceId: "regenerator"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
displayName: "invoke",
|
|
||||||
location: {
|
|
||||||
sourceId: "regenerator"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
displayName: "defineIteratorMethods/</prototype[method]",
|
|
||||||
location: {
|
|
||||||
sourceId: "regenerator"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
displayName: "step",
|
|
||||||
location: {
|
|
||||||
sourceId: "bundle"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
displayName: "step/<",
|
|
||||||
location: {
|
|
||||||
sourceId: "bundle"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
displayName: "run",
|
|
||||||
location: {
|
|
||||||
sourceId: "bundle"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
displayName: "notify/<",
|
|
||||||
location: {
|
|
||||||
sourceId: "bundle"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
displayName: "flush",
|
|
||||||
location: {
|
|
||||||
sourceId: "microtask"
|
|
||||||
}
|
|
||||||
}];
|
|
||||||
const state = {
|
|
||||||
frames: [...preAwaitGroup, ...postAwaitGroup],
|
|
||||||
sources: (0, _immutable.fromJS)({
|
|
||||||
app: {
|
|
||||||
id: "app",
|
|
||||||
url: "webpack///app.js"
|
|
||||||
},
|
|
||||||
bundle: {
|
|
||||||
id: "bundle",
|
|
||||||
url: "https://foo.com/bundle.js"
|
|
||||||
},
|
|
||||||
regenerator: {
|
|
||||||
id: "regenerator",
|
|
||||||
url: "webpack:///foo/node_modules/regenerator-runtime/runtime.js"
|
|
||||||
},
|
|
||||||
microtask: {
|
|
||||||
id: "microtask",
|
|
||||||
url: "webpack:///foo/node_modules/core-js/modules/_microtask.js"
|
|
||||||
},
|
|
||||||
promise: {
|
|
||||||
id: "promise",
|
|
||||||
url: "webpack///foo/node_modules/core-js/modules/es6.promise.js"
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
selectedSource: (0, _immutable.fromJS)({
|
|
||||||
id: "sourceId-originalSource"
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
const frames = _getCallStackFrames.getCallStackFrames.resultFunc(state.frames, state.sources, state.selectedSource);
|
|
||||||
|
|
||||||
const babelFrames = (0, _lodash.pullAt)(frames, [1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15, 16, 17]);
|
|
||||||
const otherFrames = frames;
|
|
||||||
expect(babelFrames).toEqual(Array(babelFrames.length).fill(expect.objectContaining({
|
|
||||||
library: "Babel"
|
|
||||||
})));
|
|
||||||
expect(otherFrames).not.toEqual(Array(babelFrames.length).fill(expect.objectContaining({
|
|
||||||
library: "Babel"
|
|
||||||
})));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,12 +0,0 @@
|
||||||
# vim: set filetype=python:
|
|
||||||
# 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/.
|
|
||||||
|
|
||||||
DIRS += [
|
|
||||||
|
|
||||||
]
|
|
||||||
|
|
||||||
DevToolsModules(
|
|
||||||
'getCallStackFrames.spec.js',
|
|
||||||
)
|
|
|
@ -44,8 +44,8 @@ function findBestMatchExpression(symbols, tokenPos) {
|
||||||
}, null);
|
}, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
function findEmptyLines(selectedSource, pausePoints) {
|
function findEmptyLines(sourceText, pausePoints) {
|
||||||
if (!pausePoints || !selectedSource) {
|
if (!pausePoints || !sourceText) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,11 +53,11 @@ function findEmptyLines(selectedSource, pausePoints) {
|
||||||
const breakpoints = pausePointsList.filter(point => point.types.break);
|
const breakpoints = pausePointsList.filter(point => point.types.break);
|
||||||
const breakpointLines = breakpoints.map(point => point.location.line);
|
const breakpointLines = breakpoints.map(point => point.location.line);
|
||||||
|
|
||||||
if (!selectedSource.text || breakpointLines.length == 0) {
|
if (!sourceText || breakpointLines.length == 0) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const lineCount = selectedSource.text.split("\n").length;
|
const lineCount = sourceText.split("\n").length;
|
||||||
const sourceLines = (0, _lodash.range)(1, lineCount + 1);
|
const sourceLines = (0, _lodash.range)(1, lineCount + 1);
|
||||||
return (0, _lodash.xor)(sourceLines, breakpointLines);
|
return (0, _lodash.xor)(sourceLines, breakpointLines);
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,6 @@ DevToolsModules(
|
||||||
'source.js',
|
'source.js',
|
||||||
'tabs.js',
|
'tabs.js',
|
||||||
'task.js',
|
'task.js',
|
||||||
'test-head.js',
|
|
||||||
'text.js',
|
'text.js',
|
||||||
'timings.js',
|
'timings.js',
|
||||||
'ui.js',
|
'ui.js',
|
||||||
|
|
|
@ -40,6 +40,10 @@ const inExpression = (parent, grandParent) => inStepExpression(parent) || t.isJS
|
||||||
|
|
||||||
const isExport = node => t.isExportNamedDeclaration(node) || t.isExportDefaultDeclaration(node);
|
const isExport = node => t.isExportNamedDeclaration(node) || t.isExportDefaultDeclaration(node);
|
||||||
|
|
||||||
|
function getStartLine(node) {
|
||||||
|
return node.loc.start.line;
|
||||||
|
}
|
||||||
|
|
||||||
function getPausePoints(sourceId) {
|
function getPausePoints(sourceId) {
|
||||||
const state = {};
|
const state = {};
|
||||||
(0, _ast.traverseAst)(sourceId, {
|
(0, _ast.traverseAst)(sourceId, {
|
||||||
|
@ -81,8 +85,9 @@ function onEnter(node, ancestors, state) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isReturn(node)) {
|
if (isReturn(node)) {
|
||||||
// We do not want to pause at the return and the call e.g. return foo()
|
// We do not want to pause at the return if the
|
||||||
if (isCall(node.argument)) {
|
// argument is a call on the same line e.g. return foo()
|
||||||
|
if (isCall(node.argument) && getStartLine(node) == getStartLine(node.argument)) {
|
||||||
return addEmptyPoint(state, startLocation);
|
return addEmptyPoint(state, startLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -186,6 +186,7 @@ skip-if = os == "linux" # bug 1351952
|
||||||
[browser_dbg-outline.js]
|
[browser_dbg-outline.js]
|
||||||
[browser_dbg-pause-exceptions.js]
|
[browser_dbg-pause-exceptions.js]
|
||||||
skip-if = !debug && (os == "win" && os_version == "6.1") # Bug 1456441
|
skip-if = !debug && (os == "win" && os_version == "6.1") # Bug 1456441
|
||||||
|
[browser_dbg-pause-on-next.js]
|
||||||
[browser_dbg-pause-ux.js]
|
[browser_dbg-pause-ux.js]
|
||||||
skip-if = os == "win"
|
skip-if = os == "win"
|
||||||
[browser_dbg-navigation.js]
|
[browser_dbg-navigation.js]
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
// Tests that when pause on next is selected, we pause on the next execution
|
||||||
|
|
||||||
|
add_task(async function() {
|
||||||
|
const dbg = await initDebugger("doc-scripts.html");
|
||||||
|
|
||||||
|
clickElement(dbg, "pause");
|
||||||
|
await waitForState(dbg, state => dbg.selectors.getIsWaitingOnBreak(state))
|
||||||
|
invokeInTab("simple");
|
||||||
|
|
||||||
|
await waitForPaused(dbg, "simple3");
|
||||||
|
assertPaused(dbg);
|
||||||
|
});
|
|
@ -249,6 +249,15 @@ function assertNotPaused(dbg) {
|
||||||
ok(!isPaused(dbg), "client is not paused");
|
ok(!isPaused(dbg), "client is not paused");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assert that the debugger is currently paused.
|
||||||
|
* @memberof mochitest/asserts
|
||||||
|
* @static
|
||||||
|
*/
|
||||||
|
function assertPaused(dbg) {
|
||||||
|
ok(isPaused(dbg), "client is paused");
|
||||||
|
}
|
||||||
|
|
||||||
function getVisibleSelectedFrameLine(dbg) {
|
function getVisibleSelectedFrameLine(dbg) {
|
||||||
const { selectors: { getVisibleSelectedFrame }, getState } = dbg;
|
const { selectors: { getVisibleSelectedFrame }, getState } = dbg;
|
||||||
const frame = getVisibleSelectedFrame(getState());
|
const frame = getVisibleSelectedFrame(getState());
|
||||||
|
@ -1014,6 +1023,7 @@ const selectors = {
|
||||||
debugErrorLine: ".new-debug-line-error",
|
debugErrorLine: ".new-debug-line-error",
|
||||||
codeMirror: ".CodeMirror",
|
codeMirror: ".CodeMirror",
|
||||||
resume: ".resume.active",
|
resume: ".resume.active",
|
||||||
|
pause: ".pause.active",
|
||||||
sourceTabs: ".source-tabs",
|
sourceTabs: ".source-tabs",
|
||||||
stepOver: ".stepOver.active",
|
stepOver: ".stepOver.active",
|
||||||
stepOut: ".stepOut.active",
|
stepOut: ".stepOut.active",
|
||||||
|
|
Загрузка…
Ссылка в новой задаче