diff --git a/devtools/client/locales/en-US/webconsole.properties b/devtools/client/locales/en-US/webconsole.properties index 36133ff652a6..c8753a5193b0 100644 --- a/devtools/client/locales/en-US/webconsole.properties +++ b/devtools/client/locales/en-US/webconsole.properties @@ -417,6 +417,17 @@ webconsole.editor.toolbar.executeButton.label=Run # Parameters: %S is the keyboard shortcut. webconsole.editor.toolbar.executeButton.tooltip=Run expression (%S). This won’t clear the input. +# LOCALIZATION NOTE (webconsole.editor.toolbar.executeButton.tooltip) +# Label used for the tooltip on the history previous expression, in the editor toolbar, +# which is displayed when the editor mode is enabled (devtools.webconsole.input.editor=true). +webconsole.editor.toolbar.history.prevExpressionButton.tooltip=Previous Expression + + +# LOCALIZATION NOTE (webconsole.editor.toolbar.executeButton.tooltip) +# Label used for the tooltip on the history next expression, in the editor toolbar, +# which is displayed when the editor mode is enabled (devtools.webconsole.input.editor=true). +webconsole.editor.toolbar.history.nextExpressionButton.tooltip=Next Expression + # LOCALIZATION NOTE (webconsole.editor.toolbar.closeButton.tooltip) # Label used for the tooltip on the close button, in the editor toolbar, which is # displayed when the editor mode is enabled (devtools.webconsole.input.editor=true). diff --git a/devtools/client/webconsole/components/App.css b/devtools/client/webconsole/components/App.css index 419c2cee9469..c6ea698fd819 100644 --- a/devtools/client/webconsole/components/App.css +++ b/devtools/client/webconsole/components/App.css @@ -220,14 +220,34 @@ body { grid-row: 2 / 3; display: grid; /* We're going to have the run button, the history nav and the close button */ - grid-template-columns: auto 1fr auto; + grid-template-columns: auto 1fr auto auto auto; height: unset; } +.jsterm-editor .webconsole-editor-toolbar .webconsole-editor-toolbar-history-prevExpressionButton { + grid-column: -3 / -4; +} + +.jsterm-editor .webconsole-editor-toolbar .webconsole-editor-toolbar-history-nextExpressionButton { + grid-column: -2 / -3; +} + .jsterm-editor .webconsole-editor-toolbar .webconsole-editor-toolbar-closeButton { grid-column: -1 / -2; } +.jsterm-editor .webconsole-editor-toolbar .webconsole-editor-toolbar-history-prevExpressionButton::before { + background-image: url("chrome://devtools/skin/images/arrowhead-up.svg"); + background-size: 16px; + fill: var(--comment-node-color); +} + +.jsterm-editor .webconsole-editor-toolbar .webconsole-editor-toolbar-history-nextExpressionButton::before { + background-image: url("chrome://devtools/skin/images/arrowhead-down.svg"); + background-size: 16px; + fill: var(--comment-node-color); +} + .jsterm-editor .webconsole-editor-toolbar .webconsole-editor-toolbar-closeButton::before { background-image: url(chrome://devtools/skin/images/webconsole/editor.svg); } diff --git a/devtools/client/webconsole/components/Input/EditorToolbar.js b/devtools/client/webconsole/components/Input/EditorToolbar.js index bf38916ca8ac..dfda43770931 100644 --- a/devtools/client/webconsole/components/Input/EditorToolbar.js +++ b/devtools/client/webconsole/components/Input/EditorToolbar.js @@ -14,6 +14,12 @@ const { l10n } = require("devtools/client/webconsole/utils/messages"); const Services = require("Services"); const isMacOS = Services.appinfo.OS === "Darwin"; +// Constants used for defining the direction of JSTerm input history navigation. +const { + HISTORY_BACK, + HISTORY_FORWARD, +} = require("devtools/client/webconsole/constants"); + class EditorToolbar extends Component { static get propTypes() { return { @@ -46,6 +52,26 @@ class EditorToolbar extends Component { }, l10n.getStr("webconsole.editor.toolbar.executeButton.label") ), + dom.button({ + className: + "devtools-button webconsole-editor-toolbar-history-prevExpressionButton", + title: l10n.getStr( + "webconsole.editor.toolbar.history.prevExpressionButton.tooltip" + ), + onClick: () => { + webConsoleUI.jsterm.historyPeruse(HISTORY_BACK); + }, + }), + dom.button({ + className: + "devtools-button webconsole-editor-toolbar-history-nextExpressionButton", + title: l10n.getStr( + "webconsole.editor.toolbar.history.nextExpressionButton.tooltip" + ), + onClick: () => { + webConsoleUI.jsterm.historyPeruse(HISTORY_FORWARD); + }, + }), dom.button({ className: "devtools-button webconsole-editor-toolbar-closeButton checked", diff --git a/devtools/client/webconsole/test/mochitest/browser_jsterm_editor_toolbar.js b/devtools/client/webconsole/test/mochitest/browser_jsterm_editor_toolbar.js index 099a29784ef9..ddc666217abb 100644 --- a/devtools/client/webconsole/test/mochitest/browser_jsterm_editor_toolbar.js +++ b/devtools/client/webconsole/test/mochitest/browser_jsterm_editor_toolbar.js @@ -45,22 +45,69 @@ async function performTests() { (Services.appinfo.OS === "Darwin" ? "Cmd" : "Ctrl") + " + Enter"; is( runButton.getAttribute("title"), - `Run expression (${keyShortcut}). This won’t clear the input.` + `Run expression (${keyShortcut}). This won’t clear the input.`, + "The Run Button has the correct title" ); info("Test that clicking on the Run button works as expected"); - // Setting the input value. - const input = "`${1 + 1} = 2`"; - setInputValue(hud, input); - runButton.click(); - await waitFor(() => findMessage(hud, input)); - await waitFor(() => findMessage(hud, "2 = 2", ".message.result")); - ok(true, "The expression and its result are displayed in the output"); - ok( - isInputFocused(hud), - "input is still focused after clicking the Run button" + const jsTestStatememts = Object.entries({ + // input: output, + "`${1 + 1} = 2`": "2 = 2", + '`${"area" + 51} = aliens?`': "area51 = aliens?", + }); + + for (const [input, output] of jsTestStatememts) { + // Setting the input value. + setInputValue(hud, input); + runButton.click(); + await waitFor(() => findMessage(hud, input)); + await waitFor(() => findMessage(hud, output, ".message.result")); + ok(true, "The expression and its result are displayed in the output"); + ok( + isInputFocused(hud), + "input is still focused after clicking the Run button" + ); + } + // Clear JS Term beform testing history buttons + setInputValue(hud, ""); + + info("Test that clicking the previous expression button works as expected"); + const prevHistoryButton = toolbar.querySelector( + ".webconsole-editor-toolbar-history-prevExpressionButton" ); + is( + prevHistoryButton.getAttribute("title"), + "Previous Expression", + "The Previous Expression Button has the correct title" + ); + for (const [input] of jsTestStatememts.slice().reverse()) { + prevHistoryButton.click(); + is( + getInputValue(hud), + input, + `The JS Terminal Editor has the correct previous expresion ${input}` + ); + } + + info("Test that clicking the next expression button works as expected"); + const nextHistoryButton = toolbar.querySelector( + ".webconsole-editor-toolbar-history-nextExpressionButton" + ); + is( + nextHistoryButton.getAttribute("title"), + "Next Expression", + "The Next Expression Button has the correct title" + ); + nextHistoryButton.click(); + const [nextHistoryJsStatement] = jsTestStatememts.slice(-1).pop(); + is( + getInputValue(hud), + nextHistoryJsStatement, + `The JS Terminal Editor has the correct next expresion ${nextHistoryJsStatement}` + ); + nextHistoryButton.click(); + is(getInputValue(hud), ""); info("Test that clicking the close button works as expected"); const closeButton = toolbar.querySelector(