mirror of
https://github.com/pybricks/pybricks-code.git
synced 2026-09-12 09:36:27 +00:00
Merge pull request #453 from pybricks/dlech
fix run button when hub disconnects during download
This commit is contained in:
@@ -53,9 +53,12 @@ it('should manage license dialog open/close', async () => {
|
||||
userEvent.click(screen.getByText('Software Licenses'));
|
||||
|
||||
expect(
|
||||
screen.getByText('Pybricks Code is built on open source software.', {
|
||||
exact: false,
|
||||
}),
|
||||
screen.getByText(
|
||||
`${process.env.REACT_APP_NAME} is built on open source software.`,
|
||||
{
|
||||
exact: false,
|
||||
},
|
||||
),
|
||||
).toBeInTheDocument();
|
||||
|
||||
const licenseDialog = document.querySelector(
|
||||
@@ -64,8 +67,11 @@ it('should manage license dialog open/close', async () => {
|
||||
userEvent.click(getByLabelText(licenseDialog, 'Close'));
|
||||
|
||||
await waitForElementToBeRemoved(() =>
|
||||
screen.queryByText('Pybricks Code is built on open source software.', {
|
||||
exact: false,
|
||||
}),
|
||||
screen.queryByText(
|
||||
`${process.env.REACT_APP_NAME} is built on open source software.`,
|
||||
{
|
||||
exact: false,
|
||||
},
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2021 The Pybricks Authors
|
||||
|
||||
import { Action } from '../actions';
|
||||
import { statusReportEvent } from '../ble-pybricks-service/actions';
|
||||
import { Status, statusToFlag } from '../ble-pybricks-service/protocol';
|
||||
import { didDisconnect } from '../ble/actions';
|
||||
import {
|
||||
didFailToFinishDownload,
|
||||
didFinishDownload,
|
||||
didProgressDownload,
|
||||
didStartDownload,
|
||||
} from './actions';
|
||||
import reducers, { HubRuntimeState } from './reducers';
|
||||
|
||||
type State = ReturnType<typeof reducers>;
|
||||
|
||||
test('initial state', () => {
|
||||
expect(reducers(undefined, {} as Action)).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"downloadProgress": null,
|
||||
"runtime": "hub.runtime.disconnected",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
describe('runtime', () => {
|
||||
test.each(Object.values(HubRuntimeState))('didDisconnect', (startingState) => {
|
||||
// all states are overridden by disconnect
|
||||
expect(
|
||||
reducers({ runtime: startingState } as State, didDisconnect()).runtime,
|
||||
).toBe(HubRuntimeState.Disconnected);
|
||||
});
|
||||
|
||||
test('didStartDownload', () => {
|
||||
// download ignored if disconnected
|
||||
expect(
|
||||
reducers(
|
||||
{ runtime: HubRuntimeState.Disconnected } as State,
|
||||
didStartDownload(),
|
||||
).runtime,
|
||||
).toBe(HubRuntimeState.Disconnected);
|
||||
expect(
|
||||
reducers({ runtime: HubRuntimeState.Idle } as State, didStartDownload())
|
||||
.runtime,
|
||||
).toBe(HubRuntimeState.Loading);
|
||||
});
|
||||
|
||||
test('didProgressDownload', () => {
|
||||
// download ignored if disconnected
|
||||
expect(
|
||||
reducers(
|
||||
{ runtime: HubRuntimeState.Disconnected } as State,
|
||||
didProgressDownload(0),
|
||||
).runtime,
|
||||
).toBe(HubRuntimeState.Disconnected);
|
||||
|
||||
// this shouldn't have any effect
|
||||
expect(
|
||||
reducers(
|
||||
{ runtime: HubRuntimeState.Loading } as State,
|
||||
didProgressDownload(0),
|
||||
).runtime,
|
||||
).toBe(HubRuntimeState.Loading);
|
||||
});
|
||||
|
||||
test('didFinishDownload', () => {
|
||||
// download ignored if disconnected
|
||||
expect(
|
||||
reducers(
|
||||
{ runtime: HubRuntimeState.Disconnected } as State,
|
||||
didFinishDownload(),
|
||||
).runtime,
|
||||
).toBe(HubRuntimeState.Disconnected);
|
||||
|
||||
// normal operation
|
||||
expect(
|
||||
reducers({ runtime: HubRuntimeState.Loading } as State, didFinishDownload())
|
||||
.runtime,
|
||||
).toBe(HubRuntimeState.Loaded);
|
||||
});
|
||||
|
||||
test('didFinishDownload', () => {
|
||||
// download ignored if disconnected
|
||||
expect(
|
||||
reducers(
|
||||
{ runtime: HubRuntimeState.Disconnected } as State,
|
||||
didFailToFinishDownload(),
|
||||
).runtime,
|
||||
).toBe(HubRuntimeState.Disconnected);
|
||||
|
||||
// normal operation for error path
|
||||
expect(
|
||||
reducers(
|
||||
{ runtime: HubRuntimeState.Loading } as State,
|
||||
didFailToFinishDownload(),
|
||||
).runtime,
|
||||
).toBe(HubRuntimeState.Idle);
|
||||
});
|
||||
|
||||
test('statusReportEvent', () => {
|
||||
// don't ever expect this to happen in practice since we can't receive
|
||||
// updates while disconnected
|
||||
expect(
|
||||
reducers(
|
||||
{ runtime: HubRuntimeState.Disconnected } as State,
|
||||
statusReportEvent(statusToFlag(Status.UserProgramRunning)),
|
||||
).runtime,
|
||||
).toBe(HubRuntimeState.Disconnected);
|
||||
|
||||
// status update ignored while download not finished
|
||||
expect(
|
||||
reducers(
|
||||
{ runtime: HubRuntimeState.Loading } as State,
|
||||
statusReportEvent(statusToFlag(Status.UserProgramRunning)),
|
||||
).runtime,
|
||||
).toBe(HubRuntimeState.Loading);
|
||||
|
||||
// normal operation - user program started
|
||||
expect(
|
||||
reducers(
|
||||
{ runtime: HubRuntimeState.Loaded } as State,
|
||||
statusReportEvent(statusToFlag(Status.UserProgramRunning)),
|
||||
).runtime,
|
||||
).toBe(HubRuntimeState.Running);
|
||||
|
||||
// really short program run finished before receiving download finished
|
||||
expect(
|
||||
reducers({ runtime: HubRuntimeState.Loaded } as State, statusReportEvent(0))
|
||||
.runtime,
|
||||
).toBe(HubRuntimeState.Idle);
|
||||
|
||||
// normal operation - user program stopped
|
||||
expect(
|
||||
reducers(
|
||||
{ runtime: HubRuntimeState.Running } as State,
|
||||
statusReportEvent(0),
|
||||
).runtime,
|
||||
).toBe(HubRuntimeState.Idle);
|
||||
});
|
||||
});
|
||||
+23
-6
@@ -46,21 +46,38 @@ const runtime: Reducer<HubRuntimeState, Action> = (
|
||||
case BleDeviceActionType.DidDisconnect:
|
||||
return HubRuntimeState.Disconnected;
|
||||
case HubActionType.DidStartDownload:
|
||||
// disconnected overrides download
|
||||
if (state === HubRuntimeState.Disconnected) {
|
||||
return state;
|
||||
}
|
||||
return HubRuntimeState.Loading;
|
||||
case HubActionType.DidFinishDownload:
|
||||
// disconnected overrides download
|
||||
if (state === HubRuntimeState.Disconnected) {
|
||||
return state;
|
||||
}
|
||||
return HubRuntimeState.Loaded;
|
||||
case HubActionType.DidFailToFinishDownload:
|
||||
// disconnected overrides download
|
||||
if (state === HubRuntimeState.Disconnected) {
|
||||
return state;
|
||||
}
|
||||
return HubRuntimeState.Idle;
|
||||
case BlePybricksServiceEventActionType.StatusReport:
|
||||
// The loading state is determined solely by the IDE, so we can't
|
||||
// let the hub status interfere with it.
|
||||
if (state !== HubRuntimeState.Loading) {
|
||||
if (action.statusFlags & statusToFlag(Status.UserProgramRunning)) {
|
||||
return HubRuntimeState.Running;
|
||||
}
|
||||
return HubRuntimeState.Idle;
|
||||
if (
|
||||
state === HubRuntimeState.Disconnected ||
|
||||
state === HubRuntimeState.Loading
|
||||
) {
|
||||
return state;
|
||||
}
|
||||
return state;
|
||||
|
||||
if (action.statusFlags & statusToFlag(Status.UserProgramRunning)) {
|
||||
return HubRuntimeState.Running;
|
||||
}
|
||||
|
||||
return HubRuntimeState.Idle;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user