--- a/devtools/client/themes/webconsole.css
+++ b/devtools/client/themes/webconsole.css
@@ -1203,27 +1203,29 @@ body #output-container {
/* Set to prevent the sidebar from extending past the right edge of the page */
width: unset;
}
.sidebar-wrapper {
display: grid;
grid-template-rows: auto 1fr;
width: 100%;
+ overflow: hidden;
}
.webconsole-sidebar-toolbar {
grid-row: 1 / 2;
min-height: var(--primary-toolbar-height);
display: flex;
justify-content: end;
}
.sidebar-contents {
grid-row: 2 / 3;
+ overflow: scroll;
}
.webconsole-sidebar-toolbar .sidebar-close-button {
padding: 4px 0;
margin: 0;
margin-inline-end: -3px;
}
--- a/devtools/client/webconsole/new-console-output/actions/ui.js
+++ b/devtools/client/webconsole/new-console-output/actions/ui.js
@@ -10,17 +10,18 @@ const { getAllUi } = require("devtools/c
const Services = require("Services");
const {
FILTER_BAR_TOGGLE,
INITIALIZE,
PERSIST_TOGGLE,
PREFS,
SELECT_NETWORK_MESSAGE_TAB,
- SIDEBAR_TOGGLE,
+ SIDEBAR_CLOSE,
+ SHOW_OBJECT_IN_SIDEBAR,
TIMESTAMPS_TOGGLE,
} = require("devtools/client/webconsole/new-console-output/constants");
function filterBarToggle(show) {
return (dispatch, getState) => {
dispatch({
type: FILTER_BAR_TOGGLE,
});
@@ -54,22 +55,30 @@ function selectNetworkMessageTab(id) {
}
function initialize() {
return {
type: INITIALIZE
};
}
-function sidebarToggle(show) {
+function sidebarClose(show) {
return {
- type: SIDEBAR_TOGGLE,
+ type: SIDEBAR_CLOSE,
+ };
+}
+
+function showObjectInSidebar(grip) {
+ return {
+ type: SHOW_OBJECT_IN_SIDEBAR,
+ grip
};
}
module.exports = {
filterBarToggle,
initialize,
persistToggle,
selectNetworkMessageTab,
- sidebarToggle,
+ sidebarClose,
+ showObjectInSidebar,
timestampsToggle,
};
--- a/devtools/client/webconsole/new-console-output/components/ConsoleOutput.js
+++ b/devtools/client/webconsole/new-console-output/components/ConsoleOutput.js
@@ -40,16 +40,17 @@ class ConsoleOutput extends Component {
dispatch: PropTypes.func.isRequired,
timestampsVisible: PropTypes.bool,
messagesTableData: PropTypes.object.isRequired,
messagesRepeat: PropTypes.object.isRequired,
networkMessagesUpdate: PropTypes.object.isRequired,
visibleMessages: PropTypes.array.isRequired,
networkMessageActiveTabId: PropTypes.string.isRequired,
onFirstMeaningfulPaint: PropTypes.func.isRequired,
+ sidebarToggle: PropTypes.bool,
};
}
constructor(props) {
super(props);
this.onContextMenu = this.onContextMenu.bind(this);
}
@@ -124,16 +125,17 @@ class ConsoleOutput extends Component {
messagesUi,
messagesTableData,
messagesRepeat,
networkMessagesUpdate,
networkMessageActiveTabId,
serviceContainer,
timestampsVisible,
initialized,
+ sidebarToggle
} = this.props;
if (!initialized) {
const numberMessagesFitViewport = getInitialMessageCountForViewport(window);
if (numberMessagesFitViewport < visibleMessages.length) {
visibleMessages = visibleMessages.slice(
visibleMessages.length - numberMessagesFitViewport);
}
@@ -146,16 +148,17 @@ class ConsoleOutput extends Component {
serviceContainer,
open: messagesUi.includes(messageId),
tableData: messagesTableData.get(messageId),
timestampsVisible,
repeat: messagesRepeat[messageId],
networkMessageUpdate: networkMessagesUpdate[messageId],
networkMessageActiveTabId,
getMessage: () => messages.get(messageId),
+ sidebarToggle,
}));
return (
dom.div({
className: "webconsole-output",
onContextMenu: this.onContextMenu,
ref: node => {
this.outputNode = node;
@@ -183,16 +186,17 @@ function mapStateToProps(state, props) {
messages: getAllMessagesById(state),
visibleMessages: getVisibleMessages(state),
messagesUi: getAllMessagesUiById(state),
messagesTableData: getAllMessagesTableDataById(state),
messagesRepeat: getAllRepeatById(state),
networkMessagesUpdate: getAllNetworkMessagesUpdateById(state),
timestampsVisible: state.ui.timestampsVisible,
networkMessageActiveTabId: state.ui.networkMessageActiveTabId,
+ sidebarToggle: state.prefs.sidebarToggle,
};
}
module.exports = connect(mapStateToProps)(props =>
VisibilityHandler(
null,
createElement(ConsoleOutput, props)
)
--- a/devtools/client/webconsole/new-console-output/components/FilterBar.js
+++ b/devtools/client/webconsole/new-console-output/components/FilterBar.js
@@ -27,25 +27,23 @@ class FilterBar extends Component {
dispatch: PropTypes.func.isRequired,
filter: PropTypes.object.isRequired,
serviceContainer: PropTypes.shape({
attachRefToHud: PropTypes.func.isRequired,
}).isRequired,
filterBarVisible: PropTypes.bool.isRequired,
persistLogs: PropTypes.bool.isRequired,
filteredMessagesCount: PropTypes.object.isRequired,
- sidebarToggle: PropTypes.bool,
};
}
constructor(props) {
super(props);
this.onClickMessagesClear = this.onClickMessagesClear.bind(this);
this.onClickFilterBarToggle = this.onClickFilterBarToggle.bind(this);
- this.onClickSidebarToggle = this.onClickSidebarToggle.bind(this);
this.onClickRemoveAllFilters = this.onClickRemoveAllFilters.bind(this);
this.onClickRemoveTextFilter = this.onClickRemoveTextFilter.bind(this);
this.onSearchInput = this.onSearchInput.bind(this);
this.onChangePersistToggle = this.onChangePersistToggle.bind(this);
this.renderFiltersConfigBar = this.renderFiltersConfigBar.bind(this);
this.renderFilteredMessagesBar = this.renderFilteredMessagesBar.bind(this);
}
@@ -82,20 +80,16 @@ class FilterBar extends Component {
onClickMessagesClear() {
this.props.dispatch(actions.messagesClear());
}
onClickFilterBarToggle() {
this.props.dispatch(actions.filterBarToggle());
}
- onClickSidebarToggle() {
- this.props.dispatch(actions.sidebarToggle());
- }
-
onClickRemoveAllFilters() {
this.props.dispatch(actions.defaultFiltersReset());
}
onClickRemoveTextFilter() {
this.props.dispatch(actions.filterTextSet(""));
}
@@ -221,17 +215,16 @@ class FilterBar extends Component {
}
render() {
const {
filter,
filterBarVisible,
persistLogs,
filteredMessagesCount,
- sidebarToggle,
} = this.props;
let children = [
dom.div({
className: "devtools-toolbar webconsole-filterbar-primary",
key: "primary-bar",
},
dom.button({
@@ -256,23 +249,16 @@ class FilterBar extends Component {
onInput: this.onSearchInput
}),
FilterCheckbox({
label: l10n.getStr("webconsole.enablePersistentLogs.label"),
title: l10n.getStr("webconsole.enablePersistentLogs.tooltip"),
onChange: this.onChangePersistToggle,
checked: persistLogs,
}),
- sidebarToggle ?
- dom.button({
- className: "devtools-button webconsole-sidebar-button",
- title: l10n.getStr("webconsole.toggleFilterButton.tooltip"),
- onClick: this.onClickSidebarToggle
- }, "Toggle Sidebar")
- : null,
)
];
if (filteredMessagesCount.global > 0) {
children.push(this.renderFilteredMessagesBar());
}
if (filterBarVisible) {
@@ -293,13 +279,12 @@ class FilterBar extends Component {
function mapStateToProps(state) {
let uiState = getAllUi(state);
return {
filter: getAllFilters(state),
filterBarVisible: uiState.filterBarVisible,
persistLogs: uiState.persistLogs,
filteredMessagesCount: getFilteredMessagesCount(state),
- sidebarToggle: state.prefs.sidebarToggle,
};
}
module.exports = connect(mapStateToProps)(FilterBar);
--- a/devtools/client/webconsole/new-console-output/components/GripMessageBody.js
+++ b/devtools/client/webconsole/new-console-output/components/GripMessageBody.js
@@ -9,60 +9,66 @@
// If this is being run from Mocha, then the browser loader hasn't set up
// define. We need to do that before loading Rep.
if (typeof define === "undefined") {
require("amd-loader");
}
// React
const { createFactory } = require("devtools/client/shared/vendor/react");
+const dom = require("devtools/client/shared/vendor/react-dom-factories");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const ObjectClient = require("devtools/shared/client/object-client");
const {
MESSAGE_TYPE,
JSTERM_COMMANDS,
} = require("../constants");
+const actions = require("devtools/client/webconsole/new-console-output/actions/index");
const reps = require("devtools/client/shared/components/reps/reps");
const { REPS, MODE } = reps;
const ObjectInspector = createFactory(reps.ObjectInspector);
const { Grip } = REPS;
GripMessageBody.displayName = "GripMessageBody";
GripMessageBody.propTypes = {
+ dispatch: PropTypes.func.isRequired,
grip: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
PropTypes.object,
]).isRequired,
serviceContainer: PropTypes.shape({
createElement: PropTypes.func.isRequired,
hudProxy: PropTypes.object.isRequired,
onViewSourceInDebugger: PropTypes.func.isRequired,
}),
userProvidedStyle: PropTypes.string,
useQuotes: PropTypes.bool,
escapeWhitespace: PropTypes.bool,
type: PropTypes.string,
helperType: PropTypes.string,
+ sidebarToggle: PropTypes.bool,
};
GripMessageBody.defaultProps = {
mode: MODE.LONG,
};
function GripMessageBody(props) {
const {
grip,
userProvidedStyle,
serviceContainer,
useQuotes,
escapeWhitespace,
mode = MODE.LONG,
+ dispatch,
+ sidebarToggle,
} = props;
let styleObject;
if (userProvidedStyle && userProvidedStyle !== "") {
styleObject = cleanupStyle(userProvidedStyle, serviceContainer.createElement);
}
let onDOMNodeMouseOver;
@@ -77,16 +83,23 @@ function GripMessageBody(props) {
? (object, e) => {
// Stop the event propagation so we don't trigger ObjectInspector expand/collapse.
e.stopPropagation();
serviceContainer.openNodeInInspector(object);
}
: null;
}
+ function onClickCapture(e) {
+ if (grip.actor && (e.ctrlKey || e.metaKey)) {
+ dispatch(actions.showObjectInSidebar(grip));
+ e.stopPropagation();
+ }
+ }
+
const objectInspectorProps = {
// Auto-expand the ObjectInspector when the message is a console.dir one.
autoExpandDepth: shouldAutoExpandObjectInspector(props) ? 1 : 0,
mode,
// TODO: we disable focus since it's not currently working well in ObjectInspector.
// Let's remove the property below when problem are fixed in OI.
disabledFocus: true,
roots: [{
@@ -117,17 +130,19 @@ function GripMessageBody(props) {
Object.assign(objectInspectorProps, {
onDOMNodeMouseOver,
onDOMNodeMouseOut,
onInspectIconClick,
defaultRep: Grip,
});
}
- return ObjectInspector(objectInspectorProps);
+ return sidebarToggle
+ ? dom.span({onClickCapture}, ObjectInspector(objectInspectorProps))
+ : ObjectInspector(objectInspectorProps);
}
// Regular expression that matches the allowed CSS property names.
const allowedStylesRegex = new RegExp(
"^(?:-moz-)?(?:background|border|box|clear|color|cursor|display|float|font|line|" +
"margin|padding|text|transition|outline|white-space|word|writing|" +
"(?:min-|max-)?width|(?:min-|max-)?height)"
);
--- a/devtools/client/webconsole/new-console-output/components/MessageContainer.js
+++ b/devtools/client/webconsole/new-console-output/components/MessageContainer.js
@@ -30,16 +30,17 @@ class MessageContainer extends Component
messageId: PropTypes.string.isRequired,
open: PropTypes.bool.isRequired,
serviceContainer: PropTypes.object.isRequired,
tableData: PropTypes.object,
timestampsVisible: PropTypes.bool.isRequired,
repeat: PropTypes.number,
networkMessageUpdate: PropTypes.object,
getMessage: PropTypes.func.isRequired,
+ sidebarToggle: PropTypes.bool,
};
}
static get defaultProps() {
return {
open: false,
};
}
--- a/devtools/client/webconsole/new-console-output/components/SideBar.js
+++ b/devtools/client/webconsole/new-console-output/components/SideBar.js
@@ -9,48 +9,50 @@ const PropTypes = require("devtools/clie
const { connect } = require("devtools/client/shared/vendor/react-redux");
const actions = require("devtools/client/webconsole/new-console-output/actions/index");
const SplitBox = createFactory(require("devtools/client/shared/components/splitter/SplitBox"));
class SideBar extends Component {
static get propTypes() {
return {
dispatch: PropTypes.func.isRequired,
- sidebarVisible: PropTypes.bool
+ sidebarVisible: PropTypes.bool,
+ grip: PropTypes.object,
};
}
constructor(props) {
super(props);
- this.onClickSidebarToggle = this.onClickSidebarToggle.bind(this);
+ this.onClickSidebarClose = this.onClickSidebarClose.bind(this);
}
- onClickSidebarToggle() {
- this.props.dispatch(actions.sidebarToggle());
+ onClickSidebarClose() {
+ this.props.dispatch(actions.sidebarClose());
}
render() {
let {
sidebarVisible,
+ grip,
} = this.props;
let endPanel = dom.aside({
className: "sidebar-wrapper"
},
dom.header({
className: "devtools-toolbar webconsole-sidebar-toolbar"
},
dom.button({
className: "devtools-button sidebar-close-button",
- onClick: this.onClickSidebarToggle
+ onClick: this.onClickSidebarClose
})
),
dom.aside({
className: "sidebar-contents"
- }, "Sidebar WIP")
+ }, JSON.stringify(grip, null, 2))
);
return (
sidebarVisible ?
SplitBox({
className: "sidebar",
endPanel,
endPanelControl: true,
@@ -61,12 +63,13 @@ class SideBar extends Component {
: null
);
}
}
function mapStateToProps(state, props) {
return {
sidebarVisible: state.ui.sidebarVisible,
+ grip: state.ui.gripInSidebar,
};
}
module.exports = connect(mapStateToProps)(SideBar);
--- a/devtools/client/webconsole/new-console-output/components/message-types/ConsoleApiCall.js
+++ b/devtools/client/webconsole/new-console-output/components/message-types/ConsoleApiCall.js
@@ -19,31 +19,33 @@ const Message = createFactory(require("d
ConsoleApiCall.displayName = "ConsoleApiCall";
ConsoleApiCall.propTypes = {
dispatch: PropTypes.func.isRequired,
message: PropTypes.object.isRequired,
open: PropTypes.bool,
serviceContainer: PropTypes.object.isRequired,
timestampsVisible: PropTypes.bool.isRequired,
+ sidebarToggle: PropTypes.bool,
};
ConsoleApiCall.defaultProps = {
open: false,
};
function ConsoleApiCall(props) {
const {
dispatch,
message,
open,
tableData,
serviceContainer,
timestampsVisible,
repeat,
+ sidebarToggle,
} = props;
const {
id: messageId,
indent,
source,
type,
level,
stacktrace,
@@ -57,16 +59,17 @@ function ConsoleApiCall(props) {
let messageBody;
const messageBodyConfig = {
dispatch,
messageId,
parameters,
userProvidedStyles,
serviceContainer,
type,
+ sidebarToggle,
};
if (type === "trace") {
messageBody = dom.span({className: "cm-variable"}, "console.trace()");
} else if (type === "assert") {
let reps = formatReps(messageBodyConfig);
messageBody = dom.span({ className: "cm-variable" }, "Assertion failed: ", reps);
} else if (type === "table") {
@@ -125,32 +128,34 @@ function formatReps(options = {}) {
dispatch,
loadedObjectProperties,
loadedObjectEntries,
messageId,
parameters,
serviceContainer,
userProvidedStyles,
type,
+ sidebarToggle,
} = options;
return (
parameters
// Get all the grips.
.map((grip, key) => GripMessageBody({
dispatch,
messageId,
grip,
key,
userProvidedStyle: userProvidedStyles ? userProvidedStyles[key] : null,
serviceContainer,
useQuotes: false,
loadedObjectProperties,
loadedObjectEntries,
type,
+ sidebarToggle,
}))
// Interleave spaces.
.reduce((arr, v, i) => {
// We need to interleave a space if we are not on the last element AND
// if we are not between 2 messages with user provided style.
const needSpace = i + 1 < parameters.length &&
(!userProvidedStyles || !userProvidedStyles[i] || !userProvidedStyles[i + 1]);
--- a/devtools/client/webconsole/new-console-output/components/message-types/EvaluationResult.js
+++ b/devtools/client/webconsole/new-console-output/components/message-types/EvaluationResult.js
@@ -14,24 +14,26 @@ const GripMessageBody = require("devtool
EvaluationResult.displayName = "EvaluationResult";
EvaluationResult.propTypes = {
dispatch: PropTypes.func.isRequired,
message: PropTypes.object.isRequired,
timestampsVisible: PropTypes.bool.isRequired,
serviceContainer: PropTypes.object,
+ sidebarToggle: PropTypes.bool,
};
function EvaluationResult(props) {
const {
dispatch,
message,
serviceContainer,
timestampsVisible,
+ sidebarToggle,
} = props;
const {
source,
type,
helperType,
level,
id: messageId,
@@ -58,16 +60,17 @@ function EvaluationResult(props) {
dispatch,
messageId,
grip: parameters[0],
serviceContainer,
useQuotes: true,
escapeWhitespace: false,
type,
helperType,
+ sidebarToggle,
});
}
const topLevelClasses = ["cm-s-mozilla"];
return Message({
source,
type,
--- a/devtools/client/webconsole/new-console-output/constants.js
+++ b/devtools/client/webconsole/new-console-output/constants.js
@@ -19,17 +19,18 @@ const actionTypes = {
MESSAGE_TABLE_RECEIVE: "MESSAGE_TABLE_RECEIVE",
MESSAGES_ADD: "MESSAGES_ADD",
MESSAGES_CLEAR: "MESSAGES_CLEAR",
NETWORK_MESSAGE_UPDATE: "NETWORK_MESSAGE_UPDATE",
NETWORK_UPDATE_REQUEST: "NETWORK_UPDATE_REQUEST",
PERSIST_TOGGLE: "PERSIST_TOGGLE",
REMOVED_ACTORS_CLEAR: "REMOVED_ACTORS_CLEAR",
SELECT_NETWORK_MESSAGE_TAB: "SELECT_NETWORK_MESSAGE_TAB",
- SIDEBAR_TOGGLE: "SIDEBAR_TOGGLE",
+ SIDEBAR_CLOSE: "SIDEBAR_CLOSE",
+ SHOW_OBJECT_IN_SIDEBAR: "SHOW_OBJECT_IN_SIDEBAR",
TIMESTAMPS_TOGGLE: "TIMESTAMPS_TOGGLE",
};
const prefs = {
PREFS: {
FILTER: {
ERROR: "devtools.webconsole.filter.error",
WARN: "devtools.webconsole.filter.warn",
--- a/devtools/client/webconsole/new-console-output/reducers/ui.js
+++ b/devtools/client/webconsole/new-console-output/reducers/ui.js
@@ -5,50 +5,60 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const {
FILTER_BAR_TOGGLE,
INITIALIZE,
PERSIST_TOGGLE,
SELECT_NETWORK_MESSAGE_TAB,
- SIDEBAR_TOGGLE,
+ SIDEBAR_CLOSE,
+ SHOW_OBJECT_IN_SIDEBAR,
TIMESTAMPS_TOGGLE,
MESSAGES_CLEAR,
} = require("devtools/client/webconsole/new-console-output/constants");
const {
PANELS,
} = require("devtools/client/netmonitor/src/constants");
const UiState = (overrides) => Object.freeze(Object.assign({
filterBarVisible: false,
initialized: false,
networkMessageActiveTabId: PANELS.HEADERS,
persistLogs: false,
sidebarVisible: false,
timestampsVisible: true,
+ gripInSidebar: null
}, overrides));
function ui(state = UiState(), action) {
switch (action.type) {
case FILTER_BAR_TOGGLE:
return Object.assign({}, state, {filterBarVisible: !state.filterBarVisible});
case PERSIST_TOGGLE:
return Object.assign({}, state, {persistLogs: !state.persistLogs});
case TIMESTAMPS_TOGGLE:
return Object.assign({}, state, {timestampsVisible: action.visible});
case SELECT_NETWORK_MESSAGE_TAB:
return Object.assign({}, state, {networkMessageActiveTabId: action.id});
- case SIDEBAR_TOGGLE:
- return Object.assign({}, state, {sidebarVisible: !state.sidebarVisible});
+ case SIDEBAR_CLOSE:
+ return Object.assign({}, state, {
+ sidebarVisible: !state.sidebarVisible,
+ gripInSidebar: null
+ });
case INITIALIZE:
return Object.assign({}, state, {initialized: true});
case MESSAGES_CLEAR:
- return Object.assign({}, state, {sidebarVisible: false});
+ return Object.assign({}, state, {sidebarVisible: false, gripInSidebar: null});
+ case SHOW_OBJECT_IN_SIDEBAR:
+ if (action.grip === state.gripInSidebar) {
+ return state;
+ }
+ return Object.assign({}, state, {sidebarVisible: true, gripInSidebar: action.grip});
}
return state;
}
module.exports = {
UiState,
ui,
--- a/devtools/client/webconsole/new-console-output/test/mochitest/browser.ini
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/browser.ini
@@ -397,16 +397,17 @@ skip-if = true # Bug 1403454
# old console skip-if = e10s # Bug 1042253 - webconsole tests disabled with e10s
[browser_webconsole_scroll.js]
[browser_webconsole_select_all.js]
skip-if = true # Bug 1404359
[browser_webconsole_show_subresource_security_errors.js]
skip-if = true # Bug 1408948
# old console skip-if = e10s && (os == 'win' || os == 'mac') # Bug 1243987
[browser_webconsole_shows_reqs_in_netmonitor.js]
+[browser_webconsole_sidebar.js]
[browser_webconsole_sourcemap_css.js]
[browser_webconsole_sourcemap_error.js]
[browser_webconsole_sourcemap_invalid.js]
[browser_webconsole_sourcemap_nosource.js]
[browser_webconsole_split.js]
skip-if = true # Bug 1408949
[browser_webconsole_split_escape_key.js]
skip-if = true # Bug 1405647
--- a/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_close_sidebar.js
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_close_sidebar.js
@@ -47,14 +47,22 @@ add_task(async function () {
}
synthesizeKeyShortcut(clearShortcut);
await waitFor(() => findMessages(hud, "").length == 0);
sidebar = hud.ui.document.querySelector(".sidebar");
ok(!sidebar, "Sidebar hidden after console.clear()");
});
async function showSidebar(hud) {
- let toggleButton = hud.ui.document.querySelector(".webconsole-sidebar-button");
+ let onMessage = waitForMessage(hud, "Object");
+ ContentTask.spawn(gBrowser.selectedBrowser, {}, function () {
+ content.wrappedJSObject.console.log({a: 1});
+ });
+ await onMessage;
+
+ let objectNode = hud.ui.outputNode.querySelector(".object-inspector");
let wrapper = hud.ui.document.querySelector(".webconsole-output-wrapper");
let onSidebarShown = waitForNodeMutation(wrapper, { childList: true });
- toggleButton.click();
+
+ EventUtils.synthesizeMouseAtCenter(objectNode,
+ {[Services.appinfo.OS == "Darwin" ? "metaKey" : "ctrlKey"]: true}, hud.ui.window);
await onSidebarShown;
}
copy from devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_close_sidebar.js
copy to devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_sidebar.js
--- a/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_close_sidebar.js
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_sidebar.js
@@ -2,59 +2,94 @@
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that the sidebar is hidden when the console is cleared.
"use strict";
-const TEST_URI = "data:text/html;charset=utf8,";
+const TEST_URI =
+ "data:text/html;charset=utf8," +
+ "<script>console.log({a:1},100,{b:1},'foo',false,null,undefined);</script>";
add_task(async function () {
// Should be removed when sidebar work is complete
await SpecialPowers.pushPrefEnv({"set": [
["devtools.webconsole.sidebarToggle", true]
]});
let hud = await openNewTabAndConsole(TEST_URI);
- await showSidebar(hud);
+
+ let message = findMessage(hud, "foo");
+ let [objectA, objectB] = message.querySelectorAll(".object-inspector");
+ let number = findMessage(hud, "100", ".objectBox");
+ let string = findMessage(hud, "foo", ".objectBox");
+ let bool = findMessage(hud, "false", ".objectBox");
+ let nullMessage = findMessage(hud, "null", ".objectBox");
+ let undefinedMsg = findMessage(hud, "undefined", ".objectBox");
+
+ info("Showing sidebar for {a:1}");
+ await showSidebar(hud, objectA, true);
- info("Click the clear console button");
- let clearButton = hud.ui.document.querySelector(".devtools-button");
- clearButton.click();
- await waitFor(() => findMessages(hud, "").length == 0);
- let sidebar = hud.ui.document.querySelector(".sidebar");
- ok(!sidebar, "Sidebar hidden after clear console button clicked");
+ let sidebarText = hud.ui.document.querySelector(".sidebar-contents").textContent;
+ ok(sidebarText.includes('"a":'), "Sidebar is shown for {a:1}");
- await showSidebar(hud);
+ info("Showing sidebar for {a:1} again");
+ await showSidebar(hud, objectA, false);
+ ok(hud.ui.document.querySelector(".sidebar"),
+ "Sidebar is still shown after clicking on same object");
+ is(hud.ui.document.querySelector(".sidebar-contents").textContent, sidebarText,
+ "Sidebar is not updated after clicking on same object");
+
+ info("Showing sidebar for {b:1}");
+ await showSidebar(hud, objectB, false);
+ isnot(hud.ui.document.querySelector(".sidebar-contents").textContent, sidebarText,
+ "Sidebar is updated for {b:1}");
+ sidebarText = hud.ui.document.querySelector(".sidebar-contents").textContent;
+ ok(sidebarText.includes('"b":'), "Sidebar contents shown for {b:1}");
- info("Send a console.clear()");
- let onMessagesCleared = waitForMessage(hud, "Console was cleared");
- ContentTask.spawn(gBrowser.selectedBrowser, {}, function () {
- content.wrappedJSObject.console.clear();
- });
- await onMessagesCleared;
- sidebar = hud.ui.document.querySelector(".sidebar");
- ok(!sidebar, "Sidebar hidden after console.clear()");
+ info("Ctrl-clicking on number");
+ await showSidebar(hud, number, false);
+ ok(hud.ui.document.querySelector(".sidebar"),
+ "Sidebar is still shown after clicking on number");
+ is(hud.ui.document.querySelector(".sidebar-contents").textContent, sidebarText,
+ "Sidebar is not updated after clicking on number");
- await showSidebar(hud);
+ info("Ctrl-clicking on string");
+ await showSidebar(hud, string, false);
+ ok(hud.ui.document.querySelector(".sidebar"),
+ "Sidebar is still shown after clicking on string");
+ is(hud.ui.document.querySelector(".sidebar-contents").textContent, sidebarText,
+ "Sidebar is not updated after clicking on string");
- info("Send ctrl-l to clear console");
- let clearShortcut;
- if (Services.appinfo.OS === "Darwin") {
- clearShortcut = WCUL10n.getStr("webconsole.clear.keyOSX");
- } else {
- clearShortcut = WCUL10n.getStr("webconsole.clear.key");
- }
- synthesizeKeyShortcut(clearShortcut);
- await waitFor(() => findMessages(hud, "").length == 0);
- sidebar = hud.ui.document.querySelector(".sidebar");
- ok(!sidebar, "Sidebar hidden after console.clear()");
+ info("Ctrl-clicking on bool");
+ await showSidebar(hud, bool, false);
+ ok(hud.ui.document.querySelector(".sidebar"),
+ "Sidebar is still shown after clicking on bool");
+ is(hud.ui.document.querySelector(".sidebar-contents").textContent, sidebarText,
+ "Sidebar is not updated after clicking on bool");
+
+ info("Ctrl-clicking on null message");
+ await showSidebar(hud, nullMessage, false);
+ ok(hud.ui.document.querySelector(".sidebar"),
+ "Sidebar is still shown after clicking on null message");
+ is(hud.ui.document.querySelector(".sidebar-contents").textContent, sidebarText,
+ "Sidebar is not updated after clicking on null message");
+
+ info("Ctrl-clicking on undefined message");
+ await showSidebar(hud, undefinedMsg, false);
+ ok(hud.ui.document.querySelector(".sidebar"),
+ "Sidebar is still shown after clicking on undefined message");
+ is(hud.ui.document.querySelector(".sidebar-contents").textContent, sidebarText,
+ "Sidebar is not updated after clicking on undefined message");
});
-async function showSidebar(hud) {
- let toggleButton = hud.ui.document.querySelector(".webconsole-sidebar-button");
+async function showSidebar(hud, node, expectMutation) {
let wrapper = hud.ui.document.querySelector(".webconsole-output-wrapper");
let onSidebarShown = waitForNodeMutation(wrapper, { childList: true });
- toggleButton.click();
- await onSidebarShown;
+
+ EventUtils.synthesizeMouseAtCenter(node,
+ {[Services.appinfo.OS == "Darwin" ? "metaKey" : "ctrlKey"]: true}, hud.ui.window);
+ if (expectMutation) {
+ await onSidebarShown;
+ }
}
--- a/devtools/client/webconsole/new-console-output/test/store/ui.test.js
+++ b/devtools/client/webconsole/new-console-output/test/store/ui.test.js
@@ -2,36 +2,73 @@
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const expect = require("expect");
const actions = require("devtools/client/webconsole/new-console-output/actions/index");
const { setupStore } = require("devtools/client/webconsole/new-console-output/test/helpers");
+const { stubPreparedMessages } = require("devtools/client/webconsole/new-console-output/test/fixtures/stubs/index");
describe("Testing UI", () => {
let store;
beforeEach(() => {
store = setupStore();
});
describe("Toggle sidebar", () => {
it("sidebar is toggled on and off", () => {
- store.dispatch(actions.sidebarToggle());
+ store.dispatch(actions.sidebarClose());
expect(store.getState().ui.sidebarVisible).toEqual(true);
- store.dispatch(actions.sidebarToggle());
+ store.dispatch(actions.sidebarClose());
expect(store.getState().ui.sidebarVisible).toEqual(false);
});
});
describe("Hide sidebar on clear", () => {
it("sidebar is hidden on clear", () => {
- store.dispatch(actions.sidebarToggle());
+ store.dispatch(actions.sidebarClose());
expect(store.getState().ui.sidebarVisible).toEqual(true);
store.dispatch(actions.messagesClear());
expect(store.getState().ui.sidebarVisible).toEqual(false);
store.dispatch(actions.messagesClear());
expect(store.getState().ui.sidebarVisible).toEqual(false);
});
});
+
+ describe("Show object in sidebar", () => {
+ it("sidebar is shown with correct object", () => {
+ const message = stubPreparedMessages.get("inspect({a: 1})");
+ store.dispatch(actions.showObjectInSidebar(message.parameters[0]));
+
+ expect(store.getState().ui.sidebarVisible).toEqual(true);
+ expect(store.getState().ui.gripInSidebar).toEqual(message.parameters[0]);
+ });
+
+ it("sidebar is not updated for the same object", () => {
+ const message = stubPreparedMessages.get("inspect({a: 1})");
+ store.dispatch(actions.showObjectInSidebar(message.parameters[0]));
+
+ expect(store.getState().ui.sidebarVisible).toEqual(true);
+ expect(store.getState().ui.gripInSidebar).toEqual(message.parameters[0]);
+ let state = store.getState().ui;
+
+ store.dispatch(actions.showObjectInSidebar(message.parameters[0]));
+ expect(store.getState().ui).toEqual(state);
+ });
+
+ it("sidebar shown and updated for new object", () => {
+ const message = stubPreparedMessages.get("inspect({a: 1})");
+ store.dispatch(actions.showObjectInSidebar(message.parameters[0]));
+
+ expect(store.getState().ui.sidebarVisible).toEqual(true);
+ expect(store.getState().ui.gripInSidebar).toEqual(message.parameters[0]);
+
+ const newMessage = stubPreparedMessages.get("new Date(0)");
+ store.dispatch(actions.showObjectInSidebar(newMessage.parameters[0]));
+
+ expect(store.getState().ui.sidebarVisible).toEqual(true);
+ expect(store.getState().ui.gripInSidebar).toEqual(newMessage.parameters[0]);
+ });
+ });
});