Bug 1523868 - Add a doorhanger options menu in console toolbar - Part 1.

Differential Revision: https://phabricator.services.mozilla.com/D47979

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Armando Ferreira 2019-10-15 15:31:32 +00:00
parent 5459de4426
commit 05826d08b2
29 changed files with 444 additions and 311 deletions

View File

@ -36,6 +36,9 @@ add_task(async function() {
"resource://devtools/client/webconsole/utils/l10n.js",
"resource://devtools/client/netmonitor/src/utils/request-utils.js",
"resource://devtools/client/webconsole/types.js",
"resource://devtools/client/shared/components/menu/MenuButton.js",
"resource://devtools/client/shared/components/menu/MenuItem.js",
"resource://devtools/client/shared/components/menu/MenuList.js",
"resource://devtools/client/shared/vendor/react.js",
"resource://devtools/client/shared/vendor/react-dom.js",
"resource://devtools/client/shared/vendor/react-prop-types.js",

View File

@ -66,22 +66,6 @@
</label>
</fieldset>
<fieldset id="webconsole-options" class="options-groupbox">
<legend>&options.webconsole.label;</legend>
<label title="&options.timestampMessages.tooltip;">
<input type="checkbox"
id="webconsole-timestamp-messages"
data-pref="devtools.webconsole.timestampMessages"/>
<span>&options.timestampMessages.label;</span>
</label>
<label title="&options.warningGroups.tooltip;">
<input type="checkbox"
id="webconsole-warning-groups"
data-pref="devtools.webconsole.groupWarningMessages"/>
<span>&options.warningGroups.label;</span>
</label>
</fieldset>
<fieldset id="debugger-options" class="options-groupbox" hidden="true">
<legend>&options.debugger.label;</legend>
</fieldset>

View File

@ -115,20 +115,6 @@
- tools. -->
<!ENTITY options.selectDevToolsTheme.label2 "Themes">
<!-- LOCALIZATION NOTE (options.webconsole.label): This is the label for the
- heading of the group of Web Console preferences in the options panel. -->
<!ENTITY options.webconsole.label "Web Console">
<!-- LOCALIZATION NOTE (options.timestampMessages.label): This is the
- label for the checkbox that toggles timestamps in the Web Console -->
<!ENTITY options.timestampMessages.label "Enable timestamps">
<!ENTITY options.timestampMessages.tooltip "If you enable this option commands and output in the Web Console will display a timestamp">
<!-- LOCALIZATION NOTE (options.warningGroups.label): This is the
- label for the checkbox that toggles the warningGroups feature in the Web Console -->
<!ENTITY options.warningGroups.label "Group similar messages">
<!ENTITY options.warningGroups.tooltip "When enabled, similar messages are placed into groups">
<!-- LOCALIZATION NOTE (options.debugger.label): This is the label for the
- heading of the group of Debugger preferences in the options panel. -->
<!ENTITY options.debugger.label "Debugger">

View File

@ -308,10 +308,32 @@ webconsole.filteredMessagesByText.label=#1 hidden;#1 hidden
# example: 345 items hidden by text filter.
webconsole.filteredMessagesByText.tooltip=#1 item hidden by text filter;#1 items hidden by text filter
# LOCALIZATION NOTE (webconsole.enablePersistentLogs.label)
webconsole.enablePersistentLogs.label=Persist Logs
# LOCALIZATION NOTE (webconsole.enablePersistentLogs.tooltip)
webconsole.enablePersistentLogs.tooltip=If you enable this option the output will not be cleared each time you navigate to a new page
# LOCALIZATION NOTE (webconsole.console.settings.menu.menuButton.tooltip)
# Tooltip for the filter bar preferences menu. This menu will display multiple perefences for the
# filter bar, such as enabling the compact toolbar mode, enable the timestamps, persist logs, etc
webconsole.console.settings.menu.button.tooltip=Console Settings
# LOCALIZATION NOTE (webconsole.console.settings.menu.item.compactToolbar.label)
# Label for the `Compact Toolbar` preference option. This will turn the message filters buttons
# into a Menu Button, making the filter bar more compact.
webconsole.console.settings.menu.item.compactToolbar.label=Compact Toolbar
# LOCALIZATION NOTE (webconsole.console.settings.menu.item.timestamps.label)
# Label for enabling the timestamps in the Web Console.
webconsole.console.settings.menu.item.timestamps.label=Show Timestamps
# LOCALIZATION NOTE (webconsole.console.settings.menu.item.timestamps.tooltip)
webconsole.console.settings.menu.item.timestamps.tooltip=If you enable this option commands and output in the Web Console will display a timestamp
# LOCALIZATION NOTE (webconsole.console.settings.menu.item.warningGroups.label)
# Label for grouping the similar messages in the Web Console
webconsole.console.settings.menu.item.warningGroups.label=Group Similar Messages
# LOCALIZATION NOTE (webconsole.console.settings.menu.item.warningGroups.tooltip)
webconsole.console.settings.menu.item.warningGroups.tooltip=When enabled, similar messages are placed into groups
# LOCALIZATION NOTE (webconsole.console.settings.menu.item.enablePersistentLogs.label)
webconsole.console.settings.menu.item.enablePersistentLogs.label=Persist Logs
# LOCALIZATION NOTE (webconsole.console.settings.menu.item.enablePersistentLogs.tooltip)
webconsole.console.settings.menu.item.enablePersistentLogs.tooltip=If you enable this option the output will not be cleared each time you navigate to a new page
# LOCALIZATION NOTE (browserconsole.contentMessagesCheckbox.label)
# Label used in the browser console filter bar. This label is used for a checkbox that

View File

@ -4,6 +4,7 @@
"use strict";
const { getAllPrefs } = require("devtools/client/webconsole/selectors/prefs");
const { getAllUi } = require("devtools/client/webconsole/selectors/ui");
const { getMessage } = require("devtools/client/webconsole/selectors/messages");
@ -54,17 +55,29 @@ function contentMessagesToggle() {
};
}
function timestampsToggle(visible) {
return {
type: TIMESTAMPS_TOGGLE,
visible,
function timestampsToggle() {
return ({ dispatch, getState, prefsService }) => {
dispatch({
type: TIMESTAMPS_TOGGLE,
});
const uiState = getAllUi(getState());
prefsService.setBoolPref(
PREFS.UI.MESSAGE_TIMESTAMP,
uiState.timestampsVisible
);
};
}
function warningGroupsToggle(value) {
return {
type: WARNING_GROUPS_TOGGLE,
value,
function warningGroupsToggle() {
return ({ dispatch, getState, prefsService }) => {
dispatch({
type: WARNING_GROUPS_TOGGLE,
});
const prefsState = getAllPrefs(getState());
prefsService.setBoolPref(
PREFS.FEATURES.GROUP_WARNINGS,
prefsState.groupWarnings
);
};
}

View File

@ -101,6 +101,20 @@ body {
min-height: 19px;
}
/* webconsole.css | chrome://devtools/skin/webconsole.css */
.webconsole-filteringbar-wrapper .devtools-toolbar {
padding-inline-end: 0;
}
.devtools-button.webconsole-console-settings-menu-button {
height: 100%;
margin: 0;
}
.webconsole-console-settings-menu-button::before {
background-image: url("chrome://devtools/skin/images/settings.svg");
}
.webconsole-app .jsterm-input-container {
min-height: 28px;
padding-block-start: 2px;
@ -170,7 +184,7 @@ body {
}
.sidebar-close-button::before {
background-image: url(chrome://devtools/skin/images/close.svg);
background-image: url("chrome://devtools/skin/images/close.svg");
}
.sidebar-contents .object-inspector {
@ -249,7 +263,7 @@ body {
}
.jsterm-editor .webconsole-editor-toolbar .webconsole-editor-toolbar-executeButton {
background-image: url(chrome://devtools/skin/images/webconsole/run.svg);
background-image: url("chrome://devtools/skin/images/webconsole/run.svg");
-moz-context-properties: fill;
fill: currentColor;
padding-inline-start: 22px;
@ -282,22 +296,22 @@ body {
}
.jsterm-editor .webconsole-editor-toolbar .webconsole-editor-toolbar-history-prevExpressionButton::before {
background-image: url(chrome://devtools/skin/images/arrowhead-up.svg);
background-image: url("chrome://devtools/skin/images/arrowhead-up.svg");
background-size: 16px;
}
.jsterm-editor .webconsole-editor-toolbar .webconsole-editor-toolbar-history-nextExpressionButton::before {
background-image: url(chrome://devtools/skin/images/arrowhead-down.svg);
background-image: url("chrome://devtools/skin/images/arrowhead-down.svg");
background-size: 16px;
}
.jsterm-editor .webconsole-editor-toolbar .webconsole-editor-toolbar-reverseSearchButton::before {
background-image: url(chrome://devtools/skin/images/webconsole/reverse-search.svg);
background-image: url("chrome://devtools/skin/images/webconsole/reverse-search.svg");
background-size: 14px;
}
.jsterm-editor .webconsole-editor-toolbar .webconsole-editor-toolbar-closeButton::before {
background-image: url(chrome://devtools/skin/images/close.svg);
background-image: url("chrome://devtools/skin/images/close.svg");
}
.jsterm-editor .webconsole-input-openEditorButton {

View File

@ -250,6 +250,7 @@ class App extends Component {
filterBarDisplayMode,
hidePersistLogsCheckbox,
hideShowContentMessagesCheckbox,
webConsoleUI,
} = this.props;
return FilterBar({
@ -258,6 +259,7 @@ class App extends Component {
hideShowContentMessagesCheckbox,
closeSplitConsole,
displayMode: filterBarDisplayMode,
webConsoleUI,
});
}

View File

@ -0,0 +1,144 @@
/* 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/. */
"use strict";
// React & Redux
const { Component } = require("devtools/client/shared/vendor/react");
const { createFactory } = require("devtools/client/shared/vendor/react");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const actions = require("devtools/client/webconsole/actions/index");
const { l10n } = require("devtools/client/webconsole/utils/messages");
// Additional Components
const MenuButton = createFactory(
require("devtools/client/shared/components/menu/MenuButton")
);
const MenuItem = createFactory(
require("devtools/client/shared/components/menu/MenuItem")
);
const MenuList = createFactory(
require("devtools/client/shared/components/menu/MenuList")
);
class ConsoleSettings extends Component {
static get propTypes() {
return {
compactToolbar: PropTypes.bool.isRequired,
dispatch: PropTypes.func.isRequired,
groupWarnings: PropTypes.bool.isRequired,
hideCompactToolbarCheckbox: PropTypes.bool.isRequired,
hidePersistLogsCheckbox: PropTypes.bool.isRequired,
hideShowContentMessagesCheckbox: PropTypes.bool.isRequired,
persistLogs: PropTypes.bool.isRequired,
showContentMessages: PropTypes.bool.isRequired,
timestampsVisible: PropTypes.bool.isRequired,
webConsoleUI: PropTypes.object.isRequired,
};
}
renderMenuItems() {
const {
dispatch,
groupWarnings,
hidePersistLogsCheckbox,
hideShowContentMessagesCheckbox,
persistLogs,
showContentMessages,
timestampsVisible,
} = this.props;
const items = [];
// Persist Logs
if (!hidePersistLogsCheckbox) {
items.push(
MenuItem({
key: "webconsole-console-settings-menu-item-persistent-logs",
checked: persistLogs,
className:
"menu-item webconsole-console-settings-menu-item-persistentLogs",
label: l10n.getStr(
"webconsole.console.settings.menu.item.enablePersistentLogs.label"
),
tooltip: l10n.getStr(
"webconsole.console.settings.menu.item.enablePersistentLogs.tooltip"
),
onClick: () => dispatch(actions.persistToggle()),
})
);
}
// Show Content Messages
if (!hideShowContentMessagesCheckbox) {
items.push(
MenuItem({
key: "webconsole-console-settings-menu-item-content-messages",
checked: showContentMessages,
className:
"menu-item webconsole-console-settings-menu-item-contentMessages",
label: l10n.getStr("browserconsole.contentMessagesCheckbox.label"),
tooltip: l10n.getStr(
"browserconsole.contentMessagesCheckbox.tooltip"
),
onClick: () => dispatch(actions.contentMessagesToggle()),
})
);
}
// Timestamps
items.push(
MenuItem({
key: "webconsole-console-settings-menu-item-timestamps",
checked: timestampsVisible,
className: "menu-item webconsole-console-settings-menu-item-timestamps",
label: l10n.getStr(
"webconsole.console.settings.menu.item.timestamps.label"
),
tooltip: l10n.getStr(
"webconsole.console.settings.menu.item.timestamps.tooltip"
),
onClick: () => dispatch(actions.timestampsToggle()),
})
);
// Warning Groups
items.push(
MenuItem({
key: "webconsole-console-settings-menu-item-warning-groups",
checked: groupWarnings,
className:
"menu-item webconsole-console-settings-menu-item-warning-groups",
label: l10n.getStr(
"webconsole.console.settings.menu.item.warningGroups.label"
),
tooltip: l10n.getStr(
"webconsole.console.settings.menu.item.warningGroups.tooltip"
),
onClick: () => dispatch(actions.warningGroupsToggle()),
})
);
return MenuList({ id: "webconsole-console-settings-menu-list" }, items);
}
render() {
const { webConsoleUI } = this.props;
const doc = webConsoleUI.document;
const toolbox = webConsoleUI.wrapper.toolbox;
return MenuButton(
{
menuId: "webconsole-console-settings-menu-button",
doc: toolbox ? toolbox.doc : doc,
className: "devtools-button webconsole-console-settings-menu-button",
title: l10n.getStr("webconsole.console.settings.menu.button.tooltip"),
},
this.renderMenuItems()
);
}
}
module.exports = ConsoleSettings;

View File

@ -3,29 +3,42 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
// React & Redux
const {
Component,
createFactory,
} = require("devtools/client/shared/vendor/react");
const dom = require("devtools/client/shared/vendor/react-dom-factories");
const { connect } = require("devtools/client/shared/vendor/react-redux");
const dom = require("devtools/client/shared/vendor/react-dom-factories");
// Actions
const actions = require("devtools/client/webconsole/actions/index");
// Selectors
const {
getAllFilters,
} = require("devtools/client/webconsole/selectors/filters");
const {
getFilteredMessagesCount,
} = require("devtools/client/webconsole/selectors/messages");
const { getAllPrefs } = require("devtools/client/webconsole/selectors/prefs");
const { getAllUi } = require("devtools/client/webconsole/selectors/ui");
const actions = require("devtools/client/webconsole/actions/index");
// Utilities
const { l10n } = require("devtools/client/webconsole/utils/messages");
const { PluralForm } = require("devtools/shared/plural-form");
// Constants
const {
FILTERS,
FILTERBAR_DISPLAY_MODES,
} = require("devtools/client/webconsole/constants");
// Additional Components
const FilterButton = require("devtools/client/webconsole/components/FilterBar/FilterButton");
const FilterCheckbox = require("devtools/client/webconsole/components/FilterBar/FilterCheckbox");
const ConsoleSettings = createFactory(
require("devtools/client/webconsole/components/FilterBar/ConsoleSettings")
);
const SearchBox = createFactory(
require("devtools/client/shared/components/SearchBox")
);
@ -43,17 +56,20 @@ const disabledCssFilterButtonTitle = l10n.getStr(
class FilterBar extends Component {
static get propTypes() {
return {
dispatch: PropTypes.func.isRequired,
filter: PropTypes.object.isRequired,
persistLogs: PropTypes.bool.isRequired,
hidePersistLogsCheckbox: PropTypes.bool.isRequired,
showContentMessages: PropTypes.bool.isRequired,
hideShowContentMessagesCheckbox: PropTypes.bool.isRequired,
filteredMessagesCount: PropTypes.object.isRequired,
closeButtonVisible: PropTypes.bool,
closeSplitConsole: PropTypes.func,
dispatch: PropTypes.func.isRequired,
displayMode: PropTypes.oneOf([...Object.values(FILTERBAR_DISPLAY_MODES)])
.isRequired,
filter: PropTypes.object.isRequired,
filteredMessagesCount: PropTypes.object.isRequired,
groupWarnings: PropTypes.bool.isRequired,
hidePersistLogsCheckbox: PropTypes.bool.isRequired,
hideShowContentMessagesCheckbox: PropTypes.bool.isRequired,
persistLogs: PropTypes.bool.isRequired,
showContentMessages: PropTypes.bool.isRequired,
timestampsVisible: PropTypes.bool.isRequired,
webConsoleUI: PropTypes.object.isRequired,
};
}
@ -66,13 +82,7 @@ class FilterBar extends Component {
constructor(props) {
super(props);
this.onClickMessagesClear = this.onClickMessagesClear.bind(this);
this.onSearchBoxChange = this.onSearchBoxChange.bind(this);
this.onChangePersistToggle = this.onChangePersistToggle.bind(this);
this.onChangeShowContent = this.onChangeShowContent.bind(this);
this.renderFiltersConfigBar = this.renderFiltersConfigBar.bind(this);
this.maybeUpdateLayout = this.maybeUpdateLayout.bind(this);
this.resizeObserver = new ResizeObserver(this.maybeUpdateLayout);
}
@ -96,23 +106,25 @@ class FilterBar extends Component {
shouldComponentUpdate(nextProps, nextState) {
const {
filter,
persistLogs,
showContentMessages,
filteredMessagesCount,
closeButtonVisible,
displayMode,
filter,
filteredMessagesCount,
groupWarnings,
persistLogs,
showContentMessages,
timestampsVisible,
} = this.props;
if (nextProps.filter !== filter) {
return true;
}
if (nextProps.persistLogs !== persistLogs) {
return true;
}
if (nextProps.showContentMessages !== showContentMessages) {
if (
nextProps.closeButtonVisible !== closeButtonVisible ||
nextProps.displayMode !== displayMode ||
nextProps.filter !== filter ||
nextProps.groupWarnings !== groupWarnings ||
nextProps.persistLogs !== persistLogs ||
nextProps.showContentMessages !== showContentMessages ||
nextProps.timestampsVisible !== timestampsVisible
) {
return true;
}
@ -123,14 +135,6 @@ class FilterBar extends Component {
return true;
}
if (nextProps.closeButtonVisible != closeButtonVisible) {
return true;
}
if (nextProps.displayMode != displayMode) {
return true;
}
return false;
}
@ -188,20 +192,18 @@ class FilterBar extends Component {
}
}
onClickMessagesClear() {
this.props.dispatch(actions.messagesClear());
renderSeparator() {
return dom.div({
className: "devtools-separator",
});
}
onSearchBoxChange(text) {
this.props.dispatch(actions.filterTextSet(text));
}
onChangePersistToggle() {
this.props.dispatch(actions.persistToggle());
}
onChangeShowContent() {
this.props.dispatch(actions.contentMessagesToggle());
renderClearButton() {
return dom.button({
className: "devtools-button devtools-clear-icon",
title: l10n.getStr("webconsole.clearButton.tooltip"),
onClick: () => this.props.dispatch(actions.messagesClear()),
});
}
renderFiltersConfigBar() {
@ -290,19 +292,8 @@ class FilterBar extends Component {
);
}
render() {
const {
persistLogs,
hidePersistLogsCheckbox,
hideShowContentMessagesCheckbox,
closeSplitConsole,
displayMode,
showContentMessages,
filteredMessagesCount,
} = this.props;
const isNarrow = displayMode === FILTERBAR_DISPLAY_MODES.NARROW;
const isWide = displayMode === FILTERBAR_DISPLAY_MODES.WIDE;
renderSearchBox() {
const { dispatch, filteredMessagesCount } = this.props;
let searchBoxSummary;
let searchBoxSummaryTooltip;
@ -322,6 +313,72 @@ class FilterBar extends Component {
).replace("#1", filteredMessagesCount.text);
}
return SearchBox({
type: "filter",
placeholder: l10n.getStr("webconsole.filterInput.placeholder"),
keyShortcut: l10n.getStr("webconsole.find.key"),
onChange: text => dispatch(actions.filterTextSet(text)),
summary: searchBoxSummary,
summaryTooltip: searchBoxSummaryTooltip,
});
}
renderSettingsButton() {
const {
dispatch,
groupWarnings,
hidePersistLogsCheckbox,
hideShowContentMessagesCheckbox,
persistLogs,
showContentMessages,
timestampsVisible,
webConsoleUI,
} = this.props;
return ConsoleSettings({
dispatch,
groupWarnings,
hidePersistLogsCheckbox,
hideShowContentMessagesCheckbox,
persistLogs,
showContentMessages,
timestampsVisible,
webConsoleUI,
});
}
renderCloseButton() {
const { closeSplitConsole } = this.props;
return dom.div(
{
className: "devtools-toolbar split-console-close-button-wrapper",
key: "wrapper",
},
dom.button({
id: "split-console-close-button",
key: "split-console-close-button",
className: "devtools-button",
title: l10n.getStr("webconsole.closeSplitConsoleButton.tooltip"),
onClick: () => {
closeSplitConsole();
},
})
);
}
render() {
const { closeButtonVisible, displayMode } = this.props;
const isNarrow = displayMode === FILTERBAR_DISPLAY_MODES.NARROW;
const isWide = displayMode === FILTERBAR_DISPLAY_MODES.WIDE;
const separator = this.renderSeparator();
const clearButton = this.renderClearButton();
const searchBox = this.renderSearchBox();
const filtersConfigBar = this.renderFiltersConfigBar();
const settingsButton = this.renderSettingsButton();
const children = [
dom.div(
{
@ -329,73 +386,22 @@ class FilterBar extends Component {
"devtools-toolbar devtools-input-toolbar webconsole-filterbar-primary",
key: "primary-bar",
},
dom.button({
className: "devtools-button devtools-clear-icon",
title: l10n.getStr("webconsole.clearButton.tooltip"),
onClick: this.onClickMessagesClear,
}),
dom.div({
className: "devtools-separator",
}),
SearchBox({
type: "filter",
placeholder: l10n.getStr("webconsole.filterInput.placeholder"),
keyShortcut: l10n.getStr("webconsole.find.key"),
onChange: this.onSearchBoxChange,
summary: searchBoxSummary,
summaryTooltip: searchBoxSummaryTooltip,
}),
isWide &&
dom.div({
className: "devtools-separator",
}),
isWide && this.renderFiltersConfigBar(),
!(hidePersistLogsCheckbox && hideShowContentMessagesCheckbox)
? dom.div({
className: "devtools-separator",
})
: null,
!hidePersistLogsCheckbox &&
FilterCheckbox({
label: l10n.getStr("webconsole.enablePersistentLogs.label"),
title: l10n.getStr("webconsole.enablePersistentLogs.tooltip"),
onChange: this.onChangePersistToggle,
checked: persistLogs,
}),
!hideShowContentMessagesCheckbox &&
FilterCheckbox({
label: l10n.getStr("browserconsole.contentMessagesCheckbox.label"),
title: l10n.getStr(
"browserconsole.contentMessagesCheckbox.tooltip"
),
onChange: this.onChangeShowContent,
checked: showContentMessages,
})
clearButton,
separator,
searchBox,
isWide && separator,
isWide && filtersConfigBar,
separator,
settingsButton
),
];
if (this.props.closeButtonVisible) {
children.push(
dom.div(
{
className: "devtools-toolbar split-console-close-button-wrapper",
key: "wrapper",
},
dom.button({
id: "split-console-close-button",
key: "split-console-close-button",
className: "devtools-button",
title: l10n.getStr("webconsole.closeSplitConsoleButton.tooltip"),
onClick: () => {
closeSplitConsole();
},
})
)
);
if (closeButtonVisible) {
children.push(this.renderCloseButton());
}
if (isNarrow) {
children.push(this.renderFiltersConfigBar());
children.push(filtersConfigBar);
}
return dom.div(
@ -413,12 +419,15 @@ class FilterBar extends Component {
function mapStateToProps(state) {
const uiState = getAllUi(state);
const prefsState = getAllPrefs(state);
return {
closeButtonVisible: uiState.closeButtonVisible,
filter: getAllFilters(state),
filteredMessagesCount: getFilteredMessagesCount(state),
groupWarnings: prefsState.groupWarnings,
persistLogs: uiState.persistLogs,
showContentMessages: uiState.showContentMessages,
filteredMessagesCount: getFilteredMessagesCount(state),
closeButtonVisible: uiState.closeButtonVisible,
timestampsVisible: uiState.timestampsVisible,
};
}

View File

@ -4,6 +4,7 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
DevToolsModules(
'ConsoleSettings.js',
'FilterBar.js',
'FilterButton.js',
'FilterCheckbox.js',

View File

@ -25,11 +25,13 @@ function prefs(state = PrefState(), action) {
if (action.type === WARNING_GROUPS_TOGGLE) {
return {
...state,
groupWarnings: action.value,
groupWarnings: !state.groupWarnings,
};
}
return state;
}
exports.PrefState = PrefState;
exports.prefs = prefs;
module.exports = {
PrefState,
prefs,
};

View File

@ -53,7 +53,7 @@ function ui(state = UiState(), action) {
case SHOW_CONTENT_MESSAGES_TOGGLE:
return { ...state, showContentMessages: !state.showContentMessages };
case TIMESTAMPS_TOGGLE:
return { ...state, timestampsVisible: action.visible };
return { ...state, timestampsVisible: !state.timestampsVisible };
case SELECT_NETWORK_MESSAGE_TAB:
return { ...state, networkMessageActiveTabId: action.id };
case SIDEBAR_CLOSE:

View File

@ -3,8 +3,15 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
function getAllPrefs(state) {
return state.prefs;
}
function getLogLimit(state) {
return state.prefs.logLimit;
}
exports.getLogLimit = getLogLimit;
module.exports = {
getAllPrefs,
getLogLimit,
};

View File

@ -30,10 +30,10 @@ add_task(async function() {
ok(true, "Expected messages are displayed in the browser console");
info("Uncheck the Show content messages checkbox");
const checkbox = hud.ui.outputNode.querySelector(
".webconsole-filterbar-primary .filter-checkbox"
await toggleConsoleSetting(
hud,
".webconsole-console-settings-menu-item-contentMessages"
);
checkbox.click();
await waitFor(() => !findMessage(hud, "hello from content"));
info("Check the expected messages are still visiable in the browser console");

View File

@ -122,10 +122,10 @@ async function checkContentConsoleApiMessages(nonPrimitiveVariablesDisplayed) {
const onContentMessagesHidden = waitFor(
() => !findMessage(hud, contentArgs.log)
);
const checkbox = hud.ui.outputNode.querySelector(
".webconsole-filterbar-primary .filter-checkbox"
await toggleConsoleSetting(
hud,
".webconsole-console-settings-menu-item-contentMessages"
);
checkbox.click();
await onContentMessagesHidden;
for (const expectedMessage of expectedMessages) {
@ -136,7 +136,10 @@ async function checkContentConsoleApiMessages(nonPrimitiveVariablesDisplayed) {
const onContentMessagesDisplayed = waitFor(() =>
expectedMessages.every(expectedMessage => findMessage(hud, expectedMessage))
);
checkbox.click();
await toggleConsoleSetting(
hud,
".webconsole-console-settings-menu-item-contentMessages"
);
await onContentMessagesDisplayed;
for (const expectedMessage of expectedMessages) {

View File

@ -29,8 +29,12 @@ add_task(async function() {
is(getInputValue(hud), "", "inputnode is empty - matched");
ok(!isInputFocused(hud), "input isn't focused anymore");
ok(
hasFocus(hud.ui.outputNode.querySelector(".filter-checkbox input")),
`The "Persist Logs" checkbox is now focused`
hasFocus(
hud.ui.outputNode.querySelector(
".webconsole-console-settings-menu-button"
)
),
`The "Console Settings" menu button is now focused`
);
info("Check that hitting Tab when input is not empty insert a tab");

View File

@ -51,7 +51,10 @@ add_task(async function() {
await testMessagesCopy(hud, true);
// Disable timestamp and wait until timestamp are not displayed anymore.
await pushPref(PREF_MESSAGE_TIMESTAMP, false);
await toggleConsoleSetting(
hud,
".webconsole-console-settings-menu-item-timestamps"
);
await waitFor(
() => hud.ui.outputNode.querySelector(".message .timestamp") === null
);

View File

@ -26,7 +26,7 @@ add_task(async function() {
ok(true, "The filter bar has the narrow layout");
info("Check that the filter bar layout changes when opening the sidebar");
resizeWindow(800, win);
resizeWindow(750, win);
await waitForFilterBarLayout(hud, ".wide");
const onMessage = waitForMessage(hud, "world");
ContentTask.spawn(gBrowser.selectedBrowser, null, () => {

View File

@ -42,9 +42,10 @@ add_task(async function() {
const hud = await openNewTabAndConsole(TEST_URI);
hud.ui.outputNode
.querySelector(".webconsole-filterbar-primary .filter-checkbox")
.click();
await toggleConsoleSetting(
hud,
".webconsole-console-settings-menu-item-persistentLogs"
);
const INITIAL_LOGS_NUMBER = 5;
await ContentTask.spawn(

View File

@ -22,19 +22,20 @@ add_task(async function() {
const hud = await openNewTabAndConsole(TEST_URI);
// Get log persistence toggle button
const logPersistToggle = await waitFor(() =>
hud.ui.window.document.querySelector(".filter-checkbox")
// Toggle persistent logs - "true"
await toggleConsoleSetting(
hud,
".webconsole-console-settings-menu-item-persistentLogs"
);
// Click on the toggle - "true"
logPersistToggle.click();
await waitUntil(
() => hud.ui.wrapper.getStore().getState().ui.persistLogs === true
);
// Click a second time - "false"
logPersistToggle.click();
// Toggle persistent logs - "false"
await toggleConsoleSetting(
hud,
".webconsole-console-settings-menu-item-persistentLogs"
);
await waitUntil(
() => hud.ui.wrapper.getStore().getState().ui.persistLogs === false
);

View File

@ -29,25 +29,19 @@ add_task(async function() {
"Messages should have no timestamp by default (element check)"
);
info("Open the settings panel");
const observer = new PrefObserver("");
const toolbox = hud.toolbox;
const { panelDoc, panelWin } = await toolbox.selectTool("options");
info("Change Timestamp preference");
const prefChanged = observer.once(PREF_MESSAGE_TIMESTAMP, () => {});
const checkbox = panelDoc.getElementById("webconsole-timestamp-messages");
// We use executeSoon here to ensure that the element is in view and clickable.
checkbox.scrollIntoView();
executeSoon(() => EventUtils.synthesizeMouseAtCenter(checkbox, {}, panelWin));
await toggleConsoleSetting(
hud,
".webconsole-console-settings-menu-item-timestamps"
);
await prefChanged;
observer.destroy();
// Switch back to the console as it won't update when it is in background
info("Go back to console");
await toolbox.selectTool("webconsole");
ok(
message.node.querySelector(".timestamp"),
"Messages should have timestamp"

View File

@ -109,7 +109,8 @@ add_task(async function testContentBlockingMessage() {
]);
info("Re-disable the warningGroup feature pref");
await toggleWarningGroupPreference(hud, false);
await toggleWarningGroupPreference(hud);
console.log("toggle successful");
warningGroupMessage1 = await waitFor(() =>
findMessage(hud, CONTENT_BLOCKING_GROUP_LABEL)
);
@ -139,7 +140,7 @@ add_task(async function testContentBlockingMessage() {
await waitFor(() => findMessage(hud, "Navigated to"));
info("Disable the warningGroup feature pref again");
await toggleWarningGroupPreference(hud, false);
await toggleWarningGroupPreference(hud);
info("Add one warning message and one simple message");
await waitFor(() => findMessage(hud, `${BLOCKED_URL}?4`));
@ -163,7 +164,7 @@ add_task(async function testContentBlockingMessage() {
info(
"Enable the warningGroup feature pref to check that the group is still expanded"
);
await toggleWarningGroupPreference(hud, false);
await toggleWarningGroupPreference(hud);
await waitFor(() => findMessage(hud, CONTENT_BLOCKING_GROUP_LABEL));
checkConsoleOutputForWarningGroup(hud, [
@ -206,7 +207,7 @@ add_task(async function testContentBlockingMessage() {
info(
"Disable the warningGroup pref and check all warning messages are visible"
);
await toggleWarningGroupPreference(hud, false);
await toggleWarningGroupPreference(hud);
await waitFor(() => findMessage(hud, `${BLOCKED_URL}?6`));
checkConsoleOutputForWarningGroup(hud, [
@ -260,39 +261,18 @@ function waitForBadgeNumber(message, expectedNumber) {
);
}
/**
*
* @param {WebConsole} hud
* @param {Boolean} fromUI: By default, we change the pref by going to the settings panel
* and clicking the checkbox. If fromUI is set to false, we'll
* change the pref through Services.prefs to speed-up things.
*/
async function toggleWarningGroupPreference(hud, fromUI = true) {
if (!fromUI) {
await pushPref(
WARNING_GROUP_PREF,
!Services.prefs.getBoolPref(WARNING_GROUP_PREF)
);
return;
}
async function toggleWarningGroupPreference(hud) {
info("Open the settings panel");
const observer = new PrefObserver("");
const toolbox = hud.toolbox;
const { panelDoc, panelWin } = await toolbox.selectTool("options");
info("Change warning preference");
const prefChanged = observer.once(WARNING_GROUP_PREF, () => {});
const checkbox = panelDoc.getElementById("webconsole-warning-groups");
// We use executeSoon here to ensure that the element is in view and clickable.
checkbox.scrollIntoView();
executeSoon(() => EventUtils.synthesizeMouseAtCenter(checkbox, {}, panelWin));
await toggleConsoleSetting(
hud,
".webconsole-console-settings-menu-item-warning-groups"
);
await prefChanged;
observer.destroy();
// Switch back to the console as it won't update when it is in background
info("Go back to console");
await toolbox.selectTool("webconsole");
}

View File

@ -388,6 +388,14 @@ function loadDocument(url, browser = gBrowser.selectedBrowser) {
return BrowserTestUtils.browserLoaded(browser);
}
async function toggleConsoleSetting(hud, node) {
const toolbox = hud.toolbox;
const doc = toolbox ? toolbox.doc : hud.chromeWindow.document;
const menuItem = doc.querySelector(node);
menuItem.click();
}
/**
* Returns a promise that resolves when the node passed as an argument mutate
* according to the passed configuration.

View File

@ -15,19 +15,16 @@ const FilterButton = require("devtools/client/webconsole/components/FilterBar/Fi
const FilterBar = createFactory(
require("devtools/client/webconsole/components/FilterBar/FilterBar")
);
const { getAllUi } = require("devtools/client/webconsole/selectors/ui");
const {
FILTERBAR_DISPLAY_MODES,
} = require("devtools/client/webconsole/constants");
const {
MESSAGES_CLEAR,
FILTERS,
PREFS,
} = require("devtools/client/webconsole/constants");
const {
setupStore,
prefsService,
clearPrefs,
} = require("devtools/client/webconsole/test/node/helpers");
const serviceContainer = require("devtools/client/webconsole/test/node/fixtures/serviceContainer");
@ -37,6 +34,10 @@ function getFilterBar(overrides = {}) {
serviceContainer,
hidePersistLogsCheckbox: false,
attachRefToWebConsoleUI: () => {},
webConsoleUI: {
document,
wrapper: {},
},
...overrides,
});
}
@ -86,8 +87,10 @@ describe("FilterBar component:", () => {
"devtools-searchinput-clear"
);
// "Persist logs" checkbox
expect(wrapper.find(".filter-checkbox input").length).toBe(1);
// Settings menu icon
expect(
wrapper.find(".webconsole-console-settings-menu-button").length
).toBe(1);
});
it("displays the number of hidden messages when a search hide messages", () => {
@ -221,31 +224,4 @@ describe("FilterBar component:", () => {
input.simulate("change", { target: { value: "a" } });
expect(store.getState().filters.text).toBe("a");
});
it("toggles persist logs when checkbox is clicked", () => {
const store = setupStore();
expect(getAllUi(store.getState()).persistLogs).toBe(false);
expect(prefsService.getBoolPref(PREFS.UI.PERSIST), false);
const wrapper = mount(Provider({ store }, getFilterBar()));
wrapper.find(".filter-checkbox input").simulate("change");
expect(getAllUi(store.getState()).persistLogs).toBe(true);
expect(prefsService.getBoolPref(PREFS.UI.PERSIST), true);
});
it(`doesn't render "Persist logs" input when "hidePersistLogsCheckbox" is true`, () => {
const store = setupStore();
const wrapper = render(
Provider(
{ store },
getFilterBar({
hidePersistLogsCheckbox: true,
})
)
);
expect(wrapper.find(".filter-checkbox input").length).toBe(0);
});
});

View File

@ -0,0 +1,8 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
module.exports = {
getTopWindow: () => ({}),
};

View File

@ -8,9 +8,7 @@
const mcRoot = `${__dirname}/../../../../../`;
const getModule = mcPath => `module.exports = require("${mcRoot}${mcPath}");`;
const {
Services: { pref },
} = require("devtools-modules");
const { pref } = require("devtools-services");
pref("devtools.debugger.remote-timeout", 10000);
pref("devtools.hud.loglimit", 10000);
pref("devtools.webconsole.filter.error", true);
@ -88,6 +86,8 @@ global.ChromeUtils = {
defineModuleGetter: () => {},
};
global.define = function() {};
// Point to vendored-in files and mocks when needed.
const requireHacker = require("require-hacker");
requireHacker.global_hook("default", (path, module) => {
@ -112,9 +112,7 @@ requireHacker.global_hook("default", (path, module) => {
),
"devtools/shared/plural-form": () =>
getModule("devtools/client/webconsole/test/node/fixtures/PluralForm"),
Services: () => `module.exports = require("devtools-modules/src/Services")`,
"Services.default": () =>
`module.exports = require("devtools-modules/src/Services")`,
Services: () => `module.exports = require("devtools-services")`,
"devtools/shared/client/object-client": () => `() => {}`,
"devtools/shared/client/long-string-client": () => `() => {}`,
"devtools/client/shared/components/SmartTrace": () => "{}",
@ -128,7 +126,8 @@ requireHacker.global_hook("default", (path, module) => {
`module.exports = require("devtools-modules/src/utils/event-emitter")`,
"devtools/client/shared/unicode-url": () =>
`module.exports = require("devtools-modules/src/unicode-url")`,
"devtools/shared/DevToolsUtils": () => "{}",
"devtools/shared/DevToolsUtils": () =>
getModule("devtools/client/webconsole/test/node/fixtures/DevToolsUtils"),
"devtools/server/actors/reflow": () => "{}",
"devtools/shared/layout/utils": () => "{getCurrentZoom = () => {}}",
};

View File

@ -18,7 +18,7 @@
"test-ci": "mocha \"./{,!(node_modules)/**}/*.test.js\" -r mock-local-storage -r jsdom-global/register -r ./mocha-test-setup.js --reporter json"
},
"dependencies": {
"devtools-modules": "0.0.37",
"devtools-services": "^0.0.3",
"enzyme": "^3.3.0",
"enzyme-adapter-react-16": "^1.1.1",
"expect": "^1.16.0",

View File

@ -161,10 +161,6 @@ class WebConsoleUI {
this.jsterm = null;
}
if (this.wrapper) {
this.wrapper.destroy();
}
const toolbox = this.hud.toolbox;
if (toolbox) {
toolbox.off("webconsole-selected", this._onPanelSelected);

View File

@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const Services = require("Services");
const {
createElement,
createFactory,
@ -13,7 +12,6 @@ const { Provider } = require("devtools/client/shared/vendor/react-redux");
const actions = require("devtools/client/webconsole/actions/index");
const { configureStore } = require("devtools/client/webconsole/store");
const { PREFS } = require("devtools/client/webconsole/constants");
const {
isPacketPrivate,
@ -117,23 +115,6 @@ class WebConsoleWrapper {
const autocomplete = prefs.autocomplete;
const editorFeatureEnabled = prefs.editor;
this.prefsObservers = new Map();
this.prefsObservers.set(PREFS.UI.MESSAGE_TIMESTAMP, () => {
const enabled = Services.prefs.getBoolPref(PREFS.UI.MESSAGE_TIMESTAMP);
store.dispatch(actions.timestampsToggle(enabled));
});
this.prefsObservers.set(PREFS.FEATURES.GROUP_WARNINGS, () => {
const enabled = Services.prefs.getBoolPref(
PREFS.FEATURES.GROUP_WARNINGS
);
store.dispatch(actions.warningGroupsToggle(enabled));
});
for (const [pref, observer] of this.prefsObservers) {
Services.prefs.addObserver(pref, observer);
}
const app = App({
serviceContainer,
webConsoleUI,
@ -455,14 +436,6 @@ class WebConsoleWrapper {
closeSplitConsole() {
this.toolbox.closeSplitConsole();
}
destroy() {
if (this.prefsObservers) {
for (const [pref, observer] of this.prefsObservers) {
Services.prefs.removeObserver(pref, observer);
}
}
}
}
// Exports from this module