Skip to content

Commit 91e335c

Browse files
committed
added keyboard shortcuts to toolbar
1 parent ee4624c commit 91e335c

File tree

10 files changed

+139
-32
lines changed

10 files changed

+139
-32
lines changed

packages/selenium-ide/src/neo/components/ActionButtons/DisableBreakpoints/index.jsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,15 @@
1818
import React from "react";
1919
import ActionButton from "../ActionButton";
2020
import classNames from "classnames";
21+
import { parse } from "modifier-keys";
2122

2223
export default class DisableBreakpointsButton extends React.Component {
2324
render() {
2425
return (
25-
<ActionButton data-tip="<p>Disable breakpoints</p>" {...this.props} className={classNames("si-disable-breakpoints", this.props.className)} />// eslint-disable-line react/prop-types
26+
<ActionButton
27+
data-tip={`<p>Disable breakpoints <span style="color: #929292;padding-left: 5px;">${parse("y", { primaryKey: true })}</span></p>`}
28+
{...this.props}
29+
className={classNames("si-disable-breakpoints", this.props.className)} />// eslint-disable-line react/prop-types
2630
);
2731
}
2832
}

packages/selenium-ide/src/neo/components/ActionButtons/Pause/index.jsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,15 @@
1818
import React from "react";
1919
import ActionButton from "../ActionButton";
2020
import classNames from "classnames";
21+
import { parse } from "modifier-keys";
2122

2223
export default class PauseCurrentButton extends React.Component {
2324
render() {
2425
return (
25-
<ActionButton data-tip="<p>Pause test execution</p>" {...this.props} className={classNames("si-pause", this.props.className)} />// eslint-disable-line react/prop-types
26+
<ActionButton
27+
data-tip={`<p>Pause test execution <span style="color: #929292;padding-left: 5px;">${parse("p", { primaryKey: true })}</span></p>`}
28+
{...this.props}
29+
className={classNames("si-pause", this.props.className)} />// eslint-disable-line react/prop-types
2630
);
2731
}
2832
}

packages/selenium-ide/src/neo/components/ActionButtons/PlayAll/index.jsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,15 @@
1818
import React from "react";
1919
import ActionButton from "../ActionButton";
2020
import classNames from "classnames";
21+
import { parse } from "modifier-keys";
2122

2223
export default class PlayAllButton extends React.Component {
2324
render() {
2425
return (
25-
<ActionButton data-tip="<p>Run all tests in suite</p>" {...this.props} className={classNames("si-play-all", this.props.className)} />// eslint-disable-line react/prop-types
26+
<ActionButton
27+
data-tip={`<p>Run all tests in suite <span style="color: #929292;padding-left: 5px;">${parse("r", { primaryKey: true, secondaryKey: true })}</span></p>`}
28+
{...this.props}
29+
className={classNames("si-play-all", this.props.className)} />// eslint-disable-line react/prop-types
2630
);
2731
}
2832
}

packages/selenium-ide/src/neo/components/ActionButtons/PlayCurrent/index.jsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,15 @@
1818
import React from "react";
1919
import ActionButton from "../ActionButton";
2020
import classNames from "classnames";
21+
import { parse } from "modifier-keys";
2122

2223
export default class PlayCurrentButton extends React.Component {
2324
render() {
2425
return (
25-
<ActionButton data-tip="<p>Run current test</p>" {...this.props} className={classNames("si-play", this.props.className)} />// eslint-disable-line react/prop-types
26+
<ActionButton
27+
data-tip={`<p>Run current test <span style="color: #929292;padding-left: 5px;">${parse("r", { primaryKey: true })}</span></p>`}
28+
{...this.props}
29+
className={classNames("si-play", this.props.className)} />// eslint-disable-line react/prop-types
2630
);
2731
}
2832
}

packages/selenium-ide/src/neo/components/ActionButtons/Record/index.jsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import React from "react";
1919
import PropTypes from "prop-types";
2020
import styled from "styled-components";
21+
import { parse } from "modifier-keys";
2122
import "./style.css";
2223

2324
const RecordButton = styled.button`
@@ -91,7 +92,12 @@ export default class Record extends React.Component {
9192
};
9293
render() {
9394
return (
94-
<div className="record" data-tip={this.props.isRecording ? "<p>Stop recording</p>" : "<p>Start recording</p>"}>
95+
<div
96+
className="record"
97+
data-tip={this.props.isRecording ?
98+
`<p>Stop recording <span style="color: #929292;padding-left: 5px;">${parse("u", { primaryKey: true })}</span></p>` :
99+
`<p>Start recording <span style="color: #929292;padding-left: 5px;">${parse("u", { primaryKey: true })}</span></p>`
100+
}>
95101
<RecordButton disabled={this.props.disabled} isActive={this.props.isRecording} onClick={this.props.onClick}></RecordButton>
96102
</div>
97103
);

packages/selenium-ide/src/neo/components/ActionButtons/StepInto/index.jsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,15 @@
1818
import React from "react";
1919
import ActionButton from "../ActionButton";
2020
import classNames from "classnames";
21+
import { parse } from "modifier-keys";
2122

2223
export default class StepIntoButton extends React.Component {
2324
render() {
2425
return (
25-
<ActionButton data-tip="<p>Run current command</p>" {...this.props} className={classNames("si-step-down", this.props.className)} />// eslint-disable-line react/prop-types
26+
<ActionButton
27+
data-tip={`<p>Step over current command <span style="color: #929292;padding-left: 5px;">${parse("'", { primaryKey: true })}</span></p>`}
28+
{...this.props}
29+
className={classNames("si-step-down", this.props.className)} />// eslint-disable-line react/prop-types
2630
);
2731
}
2832
}

packages/selenium-ide/src/neo/components/ActionButtons/Stop/index.jsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,15 @@
1818
import React from "react";
1919
import ActionButton from "../ActionButton";
2020
import classNames from "classnames";
21+
import { parse } from "modifier-keys";
2122

2223
export default class StopButton extends React.Component {
2324
render() {
2425
return (
25-
<ActionButton data-tip="<p>Stop test execution</p>" {...this.props} className={classNames("si-stop", this.props.className)} />// eslint-disable-line react/prop-types
26+
<ActionButton
27+
data-tip={`<p>Stop test execution <span style="color: #929292;padding-left: 5px;">${parse(".", { primaryKey: true })}</span></p>`}
28+
{...this.props}
29+
className={classNames("si-stop", this.props.className)} />// eslint-disable-line react/prop-types
2630
);
2731
}
2832
}

packages/selenium-ide/src/neo/components/ToolBar/index.jsx

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import React from "react";
1919
import { observer } from "mobx-react";
20+
import { parse } from "modifier-keys";
2021
import PlayAll from "../../components/ActionButtons/PlayAll";
2122
import PlayCurrent from "../../components/ActionButtons/PlayCurrent";
2223
import Pause from "../../components/ActionButtons/Pause";
@@ -34,35 +35,29 @@ import "./style.css";
3435
@observer
3536
export default class ToolBar extends React.Component {
3637
render() {
37-
const isPlayingSuite = PlaybackState.isPlaying && !!PlaybackState.currentRunningSuite;
38-
const isPlayingTest = PlaybackState.isPlaying && PlaybackState.currentRunningTest && !PlaybackState.currentRunningSuite;
3938
const isTestEmpty = UiState.selectedTest.test && !UiState.selectedTest.test.commands.length;
4039
const isCommandValid = UiState.selectedCommand && UiState.selectedCommand.isValid;
4140
return (
4241
<div className="toolbar">
4342
<PlayAll
44-
isActive={!PlaybackState.paused && isPlayingSuite}
45-
disabled={!UiState.selectedTest.suite || isPlayingTest}
46-
onClick={() => (!PlaybackState.paused ? PlaybackState.startPlayingSuite() : PlaybackState.resume())}
43+
isActive={!PlaybackState.paused && PlaybackState.isPlayingSuite}
44+
disabled={!PlaybackState.canPlaySuite}
45+
onClick={PlaybackState.playSuiteOrResume}
4746
/>
4847
<PlayCurrent
49-
isActive={!PlaybackState.paused && isPlayingTest}
50-
disabled={isTestEmpty || isPlayingSuite}
51-
onClick={() => (!PlaybackState.paused ? PlaybackState.startPlaying() : PlaybackState.resume())}
48+
isActive={!PlaybackState.paused && PlaybackState.isPlayingTest}
49+
disabled={isTestEmpty || PlaybackState.isPlayingSuite}
50+
onClick={PlaybackState.playTestOrResume}
5251
/>
5352
{ PlaybackState.isPlaying ? <Stop onClick={() => {PlaybackState.abortPlaying();}} /> : null }
5453
{ PlaybackState.isPlaying ?
5554
<Pause isActive={PlaybackState.paused}
56-
data-tip={!PlaybackState.paused ? "<p>Pause test execution</p>" : "<p>Resume test execution</p>"}
57-
onClick={() => (!PlaybackState.paused ? PlaybackState.pause() : PlaybackState.resume())} /> : null }
58-
<StepInto disabled={!isCommandValid} onClick={() => {
59-
if (!PlaybackState.paused) {
60-
PlaybackState.startPlaying(UiState.selectedCommand, true);
61-
} else {
62-
PlaybackState.resume(true);
63-
}
64-
}}
65-
/>
55+
data-tip={!PlaybackState.paused ?
56+
`<p>Pause test execution <span style="color: #929292;padding-left: 5px;">${parse("p", { primaryKey: true })}</span></p>` :
57+
`<p>Resume test execution <span style="color: #929292;padding-left: 5px;">${parse("p", { primaryKey: true })}</span></p>`
58+
}
59+
onClick={PlaybackState.pauseOrResume} /> : null }
60+
<StepInto disabled={!isCommandValid} onClick={PlaybackState.stepOver} />
6661
<GaugeMenu opener={
6762
<SpeedGauge speed={UiState.gaugeSpeed} />
6863
} value={PlaybackState.delay} maxDelay={PlaybackState.maxDelay} onChange={PlaybackState.setDelay} />

packages/selenium-ide/src/neo/containers/Panel/index.jsx

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import Console from "../Console";
3838
import Modal from "../Modal";
3939
import Changelog from "../../components/Changelog";
4040
import UiState from "../../stores/view/UiState";
41+
import PlaybackState from "../../stores/view/PlaybackState";
4142
import "../../side-effects/contextMenu";
4243
import "../../styles/app.css";
4344
import "../../styles/font.css";
@@ -132,6 +133,7 @@ if (browser.windows) {
132133
handleKeyDown(e) {
133134
modifier(e);
134135
const key = e.key.toUpperCase();
136+
const bothModifiers = (e.primaryKey && e.secondaryKey);
135137
const onlyPrimary = (e.primaryKey && !e.secondaryKey);
136138
const noModifiers = (!e.primaryKey && !e.secondaryKey);
137139

@@ -141,6 +143,40 @@ if (browser.windows) {
141143
} else if (onlyPrimary && key === "O" && this.openFile) {
142144
e.preventDefault();
143145
this.openFile();
146+
} else if (onlyPrimary && key === "R") {
147+
// run test
148+
e.preventDefault();
149+
if (!PlaybackState.isPlayingSuite) {
150+
PlaybackState.playTestOrResume();
151+
}
152+
} else if (bothModifiers && e.code === "KeyR") {
153+
// run suite
154+
e.preventDefault();
155+
if (PlaybackState.canPlaySuite) {
156+
PlaybackState.playSuiteOrResume();
157+
}
158+
} else if (onlyPrimary && key === "P") {
159+
// pause
160+
e.preventDefault();
161+
PlaybackState.pauseOrResume();
162+
} else if (onlyPrimary && key === ".") {
163+
// stop
164+
e.preventDefault();
165+
PlaybackState.abortPlaying();
166+
} else if (onlyPrimary && key === "'") {
167+
// step over
168+
e.preventDefault();
169+
PlaybackState.stepOver();
170+
} else if (onlyPrimary && key === "Y") {
171+
// disable breakpoints
172+
e.preventDefault();
173+
PlaybackState.toggleDisableBreakpoints();
174+
} else if (onlyPrimary && key === "U") {
175+
// record
176+
e.preventDefault();
177+
if (!PlaybackState.isPlaying) {
178+
UiState.toggleRecord();
179+
}
144180
} else if (noModifiers && key === "ESCAPE") {
145181
UiState.toggleConsole();
146182
}

packages/selenium-ide/src/neo/stores/view/PlaybackState.js

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,18 @@ class PlaybackState {
8181
}, {});
8282
}
8383

84+
@computed get isPlayingSuite() {
85+
return this.isPlaying && !!this.currentRunningSuite;
86+
}
87+
88+
@computed get isPlayingTest() {
89+
return this.isPlaying && this.currentRunningTest && !this.currentRunningSuite;
90+
}
91+
92+
@computed get canPlaySuite() {
93+
return UiState.selectedTest.suite && !this.isPlayingTest;
94+
}
95+
8496
@action.bound toggleDisableBreakpoints() {
8597
this.breakpointsDisabled = !this.breakpointsDisabled;
8698
}
@@ -121,6 +133,38 @@ class PlaybackState {
121133
this.currentRunningSuite = undefined;
122134
}
123135

136+
@action.bound playSuiteOrResume() {
137+
if (this.paused) {
138+
return this.resume();
139+
} else if (!this.isPlaying) {
140+
this.startPlayingSuite();
141+
}
142+
}
143+
144+
@action.bound playTestOrResume() {
145+
if (this.paused) {
146+
return this.resume();
147+
} else if (!this.isPlaying) {
148+
return this.startPlaying();
149+
}
150+
}
151+
152+
@action.bound pauseOrResume() {
153+
if (this.paused) {
154+
return this.resume();
155+
} else if (this.isPlaying) {
156+
return this.pause();
157+
}
158+
}
159+
160+
@action.bound stepOver() {
161+
if (this.paused) {
162+
this.resume(true);
163+
} else if (!this.isPlaying) {
164+
this.startPlaying(UiState.selectedCommand, true);
165+
}
166+
}
167+
124168
@action.bound startPlayingSuite() {
125169
const playSuite = action(() => {
126170
const { suite } = UiState.selectedTest;
@@ -293,14 +337,16 @@ class PlaybackState {
293337
}
294338

295339
@action.bound abortPlaying() {
296-
this.aborted = true;
297-
this._testsToRun = [];
298-
if (this.paused) {
299-
this.setCommandStateAtomically(this.currentExecutingCommandNode.command.id, this.callstack.length ? this.callstack.length - 1 : undefined, PlaybackStates.Fatal, "Playback aborted");
300-
} else {
301-
this.setCommandStateAtomically(this.currentExecutingCommandNode.command.id, this.callstack.length ? this.callstack.length - 1 : undefined, PlaybackStates.Undetermined, "Aborting...");
340+
if (this.isPlaying) {
341+
this.aborted = true;
342+
this._testsToRun = [];
343+
if (this.paused) {
344+
this.setCommandStateAtomically(this.currentExecutingCommandNode.command.id, this.callstack.length ? this.callstack.length - 1 : undefined, PlaybackStates.Fatal, "Playback aborted");
345+
} else {
346+
this.setCommandStateAtomically(this.currentExecutingCommandNode.command.id, this.callstack.length ? this.callstack.length - 1 : undefined, PlaybackStates.Undetermined, "Aborting...");
347+
}
348+
this.stopPlayingGracefully();
302349
}
303-
this.stopPlayingGracefully();
304350
}
305351

306352
@action.bound forceFailure() {

0 commit comments

Comments
 (0)