Files
pybricks-code/src/hub/reducers.test.ts
T
David Lechner 960a3163ed add support for Pybricks Profile v1.2.0
This adds support to the BLE Pybricks Profile v1.2.0. This includes a
new method to download and run programs and a new file format for the
user program.

Code for the old download and run is kept for backwards compatibility.
However, the PnP ID characteristic is no longer optional, so the
minimum Pybricks Profile is now v1.1.0.
2022-10-14 16:21:18 -05:00

159 lines
5.1 KiB
TypeScript

// SPDX-License-Identifier: MIT
// Copyright (c) 2021-2022 The Pybricks Authors
import { AnyAction } from 'redux';
import { didReceiveStatusReport } from '../ble-pybricks-service/actions';
import { Status, statusToFlag } from '../ble-pybricks-service/protocol';
import { bleDidConnectPybricks, bleDidDisconnectPybricks } 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 AnyAction)).toMatchInlineSnapshot(`
{
"downloadProgress": null,
"hasRepl": false,
"maxBleWriteSize": 0,
"maxUserProgramSize": 0,
"preferredFileFormat": null,
"runtime": "hub.runtime.disconnected",
"useLegacyDownload": false,
}
`);
});
describe('runtime', () => {
test('', () => {
expect(
reducers(
{ runtime: HubRuntimeState.Disconnected } as State,
bleDidConnectPybricks('test-id', 'Test Name'),
).runtime,
).toBe(HubRuntimeState.Unknown);
});
test.each(Object.values(HubRuntimeState))('didDisconnect', (startingState) => {
// all states are overridden by disconnect
expect(
reducers({ runtime: startingState } as State, bleDidDisconnectPybricks())
.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('didReceiveStatusReport', () => {
// don't ever expect this to happen in practice since we can't receive
// updates while disconnected
expect(
reducers(
{ runtime: HubRuntimeState.Disconnected } as State,
didReceiveStatusReport(statusToFlag(Status.UserProgramRunning)),
).runtime,
).toBe(HubRuntimeState.Disconnected);
// status update ignored while download not finished
expect(
reducers(
{ runtime: HubRuntimeState.Loading } as State,
didReceiveStatusReport(statusToFlag(Status.UserProgramRunning)),
).runtime,
).toBe(HubRuntimeState.Loading);
// normal operation - user program started
expect(
reducers(
{ runtime: HubRuntimeState.Loaded } as State,
didReceiveStatusReport(statusToFlag(Status.UserProgramRunning)),
).runtime,
).toBe(HubRuntimeState.Running);
// really short program run finished before receiving download finished
expect(
reducers(
{ runtime: HubRuntimeState.Loaded } as State,
didReceiveStatusReport(0),
).runtime,
).toBe(HubRuntimeState.Idle);
// normal operation - user program stopped
expect(
reducers(
{ runtime: HubRuntimeState.Running } as State,
didReceiveStatusReport(0),
).runtime,
).toBe(HubRuntimeState.Idle);
});
});