Skip to content

Commit

Permalink
feat: autobisect gui (#619)
Browse files Browse the repository at this point in the history
* feat: autobisect gui
  • Loading branch information
ckerr authored Mar 27, 2021
1 parent 34017cd commit 362798d
Show file tree
Hide file tree
Showing 8 changed files with 148 additions and 16 deletions.
1 change: 1 addition & 0 deletions src/renderer/components/commands-bisect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ export class BisectHandler extends React.Component<BisectHandlerProps> {
<Button
icon="git-branch"
text="Bisect"
disabled={appState.isAutoBisecting}
onClick={appState.toggleBisectDialog}
/>
);
Expand Down
9 changes: 7 additions & 2 deletions src/renderer/components/commands-version-chooser.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,20 @@ export interface VersionChooserProps {
* download is managed in the state.
*/
export const VersionChooser = observer((props: VersionChooserProps) => {
const { currentElectronVersion, Bisector, setVersion } = props.appState;
const {
Bisector,
currentElectronVersion,
isAutoBisecting,
setVersion,
} = props.appState;

return (
<ButtonGroup>
<VersionSelect
appState={props.appState}
onVersionSelect={({ version }) => setVersion(version)}
currentVersion={currentElectronVersion}
disabled={!!Bisector}
disabled={!!Bisector || isAutoBisecting}
/>
</ButtonGroup>
);
Expand Down
47 changes: 36 additions & 11 deletions src/renderer/components/dialog-bisect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export class BisectDialog extends React.Component<
super(props);

this.onSubmit = this.onSubmit.bind(this);
this.onAuto = this.onAuto.bind(this);
this.onClose = this.onClose.bind(this);
this.onBeginSelect = this.onBeginSelect.bind(this);
this.onEndSelect = this.onEndSelect.bind(this);
Expand All @@ -55,25 +56,35 @@ export class BisectDialog extends React.Component<
this.setState({ endIndex: this.state.allVersions.indexOf(version) });
}

getBisectRange(): RunnableVersion[] {
const { endIndex, startIndex, allVersions } = this.state;
return endIndex !== undefined && startIndex !== undefined
? allVersions.slice(endIndex, startIndex + 1).reverse()
: [];
}

/**
* Handles the submission of the dialog
*
* @returns {Promise<void>}
*/
public async onSubmit(): Promise<void> {
const { endIndex, startIndex, allVersions } = this.state;
const { appState } = this.props;

if (endIndex === undefined || startIndex === undefined) {
return;
const range = this.getBisectRange();
if (range.length > 1) {
const { appState } = this.props;
appState.Bisector = new Bisector(range);
const initialBisectPivot = appState.Bisector.getCurrentVersion().version;
appState.setVersion(initialBisectPivot);
this.onClose();
}
}

const bisectRange = allVersions.slice(endIndex, startIndex + 1).reverse();

appState.Bisector = new Bisector(bisectRange);
const initialBisectPivot = appState.Bisector.getCurrentVersion().version;
appState.setVersion(initialBisectPivot);
this.onClose();
public async onAuto(): Promise<void> {
const range = this.getBisectRange();
if (range.length > 1) {
window.ElectronFiddle.app.runner.autobisect(range);
this.onClose();
}
}

/**
Expand All @@ -97,6 +108,13 @@ export class BisectDialog extends React.Component<
return this.state.startIndex > this.state.endIndex;
}

/**
* Can we autobisect?
*/
get canAuto(): boolean {
return this.canSubmit;
}

/**
* Renders the buttons
*/
Expand All @@ -109,6 +127,13 @@ export class BisectDialog extends React.Component<
onClick={this.onSubmit}
text="Begin"
/>,
<Button
icon="lab-test"
key="auto"
disabled={!this.canAuto}
onClick={this.onAuto}
text="Auto"
/>,
<Button icon="cross" key="cancel" onClick={this.onClose} text="Cancel" />,
];
}
Expand Down
16 changes: 15 additions & 1 deletion src/renderer/runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,21 @@ export class Runner {
* @returns {Promise<RunResult>}
* @memberof Runner
*/
public async autobisect(
public autobisect(versions: Array<RunnableVersion>): Promise<RunResult> {
const { appState } = this;
appState.isAutoBisecting = true;
const done = () => (appState.isAutoBisecting = false);
return this.autobisectImpl(versions).finally(done);
}

/**
* Bisect the current fiddle across the specified versions.
*
* @param {Array<RunnableVersion>} versions - versions to bisect
* @returns {Promise<RunResult>}
* @memberof Runner
*/
public async autobisectImpl(
versions: Array<RunnableVersion>,
): Promise<RunResult> {
const { appState } = this;
Expand Down
1 change: 1 addition & 0 deletions src/renderer/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ export class AppState {

@observable public activeGistAction: GistActionState = GistActionState.none;
@observable public isRunning = false;
@observable public isAutoBisecting = false;
@observable public isInstallingModules = false;
@observable public isUnsaved: boolean;
@observable public isUpdatingElectronVersions = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,6 @@ exports[`VersionSelect component renders 1`] = `
"version": "2.0.2",
}
}
disabled={false}
onVersionSelect={[Function]}
/>
</Blueprint3.ButtonGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,13 @@ exports[`BisectDialog component renders 1`] = `
onClick={[Function]}
text="Begin"
/>
<Blueprint3.Button
disabled={false}
icon="lab-test"
key="auto"
onClick={[Function]}
text="Auto"
/>
<Blueprint3.Button
icon="cross"
key="cancel"
Expand Down Expand Up @@ -439,6 +446,13 @@ exports[`BisectDialog component renders 2`] = `
onClick={[Function]}
text="Begin"
/>
<Blueprint3.Button
disabled={true}
icon="lab-test"
key="auto"
onClick={[Function]}
text="Auto"
/>
<Blueprint3.Button
icon="cross"
key="cancel"
Expand Down Expand Up @@ -664,6 +678,13 @@ exports[`BisectDialog component renders 3`] = `
onClick={[Function]}
text="Begin"
/>
<Blueprint3.Button
disabled={true}
icon="lab-test"
key="auto"
onClick={[Function]}
text="Auto"
/>
<Blueprint3.Button
icon="cross"
key="cancel"
Expand Down Expand Up @@ -896,6 +917,13 @@ exports[`BisectDialog component renders 4`] = `
onClick={[Function]}
text="Begin"
/>
<Blueprint3.Button
disabled={true}
icon="lab-test"
key="auto"
onClick={[Function]}
text="Auto"
/>
<Blueprint3.Button
icon="cross"
key="cancel"
Expand Down Expand Up @@ -1129,6 +1157,13 @@ exports[`BisectDialog component renders 5`] = `
onClick={[Function]}
text="Begin"
/>
<Blueprint3.Button
disabled={true}
icon="lab-test"
key="auto"
onClick={[Function]}
text="Auto"
/>
<Blueprint3.Button
icon="cross"
key="cancel"
Expand Down
54 changes: 53 additions & 1 deletion tests/renderer/components/dialog-bisect-spec.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { shallow } from 'enzyme';
import * as React from 'react';
import { VersionSource, VersionState } from '../../../src/interfaces';
import {
RunResult,
VersionSource,
VersionState,
} from '../../../src/interfaces';
import { Bisector } from '../../../src/renderer/bisect';
import { BisectDialog } from '../../../src/renderer/components/dialog-bisect';
import { ElectronReleaseChannel } from '../../../src/renderer/versions';
Expand Down Expand Up @@ -137,6 +141,54 @@ describe('BisectDialog component', () => {
});
});

describe('onAuto()', () => {
it('initiates autobisect', async () => {
// setup: dialog state
const wrapper = shallow(<BisectDialog appState={store} />);
wrapper.setState({
allVersions: generateVersionRange(5),
endIndex: 0,
startIndex: 4,
});

// setup: the spy
const spy = jest
.spyOn(window.ElectronFiddle.app.runner, 'autobisect')
.mockResolvedValueOnce(RunResult.SUCCESS);

// click the 'auto' button
const instance1: BisectDialog = wrapper.instance() as any;
await instance1.onAuto();

// check the results
expect(spy).toHaveBeenCalled();

// cleanup
spy.mockRestore();
});

it('does nothing if endIndex or startIndex are falsy', async () => {
const wrapper = shallow(<BisectDialog appState={store} />);

wrapper.setState({
startIndex: undefined,
endIndex: 0,
});
const instance1: BisectDialog = wrapper.instance() as any;
await instance1.onAuto();
expect(Bisector).not.toHaveBeenCalled();

wrapper.setState({
startIndex: 4,
endIndex: undefined,
});

const instance2: BisectDialog = wrapper.instance() as any;
await instance2.onAuto();
expect(Bisector).not.toHaveBeenCalled();
});
});

describe('items disabled', () => {
let instance: BisectDialog;

Expand Down

0 comments on commit 362798d

Please sign in to comment.