diff --git a/src/ble/actions.ts b/src/ble/actions.ts index 0c85d711..6cf0f3e8 100644 --- a/src/ble/actions.ts +++ b/src/ble/actions.ts @@ -5,17 +5,17 @@ import { createAction } from '../actions'; /** - * Creates an action that indicates connecting has been requested. + * Creates an action that initiates a connection to a hub running Pybricks firmware. */ -export const connect = createAction(() => ({ - type: 'ble.device.action.connect', +export const bleConnectPybricks = createAction(() => ({ + type: 'ble.action.connectPybricks', })); /** - * Creates an action that indicates a device was connected. + * Response that indicates {@link bleConnectPybricks} succeeded. */ -export const didConnect = createAction((id: string, name: string) => ({ - type: 'ble.device.action.didConnect', +export const bleDidConnectPybricks = createAction((id: string, name: string) => ({ + type: 'ble.device.action.didConnectPybricks', id, name, })); @@ -67,34 +67,34 @@ export type BleDeviceDidFailToConnectReason = | BleDeviceFailToConnectUnknownReason; /** - * Creates an action that indicates a device failed to connect. + * Response that indicates {@link bleConnectPybricks} failed. */ -export const didFailToConnect = createAction( +export const bleDidFailToConnectPybricks = createAction( (reason: BleDeviceDidFailToConnectReason) => ({ - type: 'ble.device.action.didFailToConnect', + type: 'ble.action.didFailToConnectPybricks', ...reason, }), ); /** - * Creates an action that indicates disconnecting was requested. + * Creates an action to request disconnecting a hub running Pybricks firmware. */ -export const disconnect = createAction(() => ({ - type: 'ble.device.action.disconnect', +export const bleDisconnectPybricks = createAction(() => ({ + type: 'ble.action.disconnectPybricks', })); /** - * Creates an action that indicates a device was disconnected. + * Creates an action that indicates that {@link bleDisconnectPybricks} succeeded. */ -export const didDisconnect = createAction(() => ({ - type: 'ble.device.action.didDisconnect', +export const bleDidDisconnectPybricks = createAction(() => ({ + type: 'ble.action.didDisconnectPybricks', })); /** - * Creates an action that indicates a device failed to disconnect. + * Creates an action that indicates that {@link bleDisconnectPybricks} failed. */ -export const didFailToDisconnect = createAction(() => ({ - type: 'ble.device.action.didFailToDisconnect', +export const bleDidFailToDisconnectPybricks = createAction(() => ({ + type: 'ble.action.didFailToDisconnectPybricks', })); /** diff --git a/src/ble/reducers.test.ts b/src/ble/reducers.test.ts index 742c5ed3..4c043cb3 100644 --- a/src/ble/reducers.test.ts +++ b/src/ble/reducers.test.ts @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// Copyright (c) 2021 The Pybricks Authors +// Copyright (c) 2021-2022 The Pybricks Authors import { AnyAction } from 'redux'; import { @@ -12,12 +12,12 @@ import { didReceiveStatusReport } from '../ble-pybricks-service/actions'; import { Status, statusToFlag } from '../ble-pybricks-service/protocol'; import { BleDeviceDidFailToConnectReason, - connect, - didConnect, - didDisconnect, - didFailToConnect, - didFailToDisconnect, - disconnect, + bleConnectPybricks, + bleDidConnectPybricks, + bleDidDisconnectPybricks, + bleDidFailToConnectPybricks, + bleDidFailToDisconnectPybricks, + bleDisconnectPybricks, } from './actions'; import reducers, { BleConnectionState } from './reducers'; @@ -38,35 +38,39 @@ test('initial state', () => { test('connection', () => { expect( - reducers({ connection: BleConnectionState.Disconnected } as State, connect()) - .connection, + reducers( + { connection: BleConnectionState.Disconnected } as State, + bleConnectPybricks(), + ).connection, ).toBe(BleConnectionState.Connecting); expect( reducers( { connection: BleConnectionState.Connecting } as State, - didConnect('test-id', 'Test Name'), + bleDidConnectPybricks('test-id', 'Test Name'), ).connection, ).toBe(BleConnectionState.Connected); expect( reducers( { connection: BleConnectionState.Connecting } as State, - didFailToConnect({} as BleDeviceDidFailToConnectReason), + bleDidFailToConnectPybricks({} as BleDeviceDidFailToConnectReason), ).connection, ).toBe(BleConnectionState.Disconnected); expect( - reducers({ connection: BleConnectionState.Connected } as State, disconnect()) - .connection, + reducers( + { connection: BleConnectionState.Connected } as State, + bleDisconnectPybricks(), + ).connection, ).toBe(BleConnectionState.Disconnecting); expect( reducers( { connection: BleConnectionState.Disconnecting } as State, - didDisconnect(), + bleDidDisconnectPybricks(), ).connection, ).toBe(BleConnectionState.Disconnected); expect( reducers( { connection: BleConnectionState.Disconnecting } as State, - didFailToDisconnect(), + bleDidFailToDisconnectPybricks(), ).connection, ).toBe(BleConnectionState.Connected); }); @@ -76,11 +80,13 @@ test('deviceName', () => { const testName = 'Test Name'; expect( - reducers({ deviceName: '' } as State, didConnect(testId, testName)).deviceName, + reducers({ deviceName: '' } as State, bleDidConnectPybricks(testId, testName)) + .deviceName, ).toBe(testName); expect( - reducers({ deviceName: testName } as State, didDisconnect()).deviceName, + reducers({ deviceName: testName } as State, bleDidDisconnectPybricks()) + .deviceName, ).toBe(''); }); @@ -98,7 +104,8 @@ test('deviceType', () => { ).toBe('Move hub'); expect( - reducers({ deviceType: 'Move hub' } as State, didDisconnect()).deviceType, + reducers({ deviceType: 'Move hub' } as State, bleDidDisconnectPybricks()) + .deviceType, ).toBe(''); }); @@ -113,8 +120,10 @@ test('deviceFirmwareVersion', () => { ).toBe(testVersion); expect( - reducers({ deviceFirmwareVersion: testVersion } as State, didDisconnect()) - .deviceFirmwareVersion, + reducers( + { deviceFirmwareVersion: testVersion } as State, + bleDidDisconnectPybricks(), + ).deviceFirmwareVersion, ).toBe(''); }); @@ -134,14 +143,14 @@ test('deviceLowBatteryWarning', () => { ).toBeFalsy(); expect( - reducers({ deviceLowBatteryWarning: true } as State, didDisconnect()) + reducers({ deviceLowBatteryWarning: true } as State, bleDidDisconnectPybricks()) .deviceLowBatteryWarning, ).toBeFalsy(); }); test('deviceBatteryCharging', () => { expect( - reducers({ deviceBatteryCharging: true } as State, didDisconnect()) + reducers({ deviceBatteryCharging: true } as State, bleDidDisconnectPybricks()) .deviceBatteryCharging, ).toBeFalsy(); }); diff --git a/src/ble/reducers.ts b/src/ble/reducers.ts index f69d9eaf..808a42fa 100644 --- a/src/ble/reducers.ts +++ b/src/ble/reducers.ts @@ -13,12 +13,12 @@ import { getHubTypeName } from '../ble-device-info-service/protocol'; import { didReceiveStatusReport } from '../ble-pybricks-service/actions'; import { Status, statusToFlag } from '../ble-pybricks-service/protocol'; import { - connect, - didConnect, - didDisconnect, - didFailToConnect, - didFailToDisconnect, - disconnect, + bleConnectPybricks, + bleDidConnectPybricks, + bleDidDisconnectPybricks, + bleDidFailToConnectPybricks, + bleDidFailToDisconnectPybricks, + bleDisconnectPybricks, } from './actions'; /** @@ -47,19 +47,25 @@ const connection: Reducer = ( state = BleConnectionState.Disconnected, action, ) => { - if (connect.matches(action)) { + if (bleConnectPybricks.matches(action)) { return BleConnectionState.Connecting; } - if (didConnect.matches(action) || didFailToDisconnect.matches(action)) { + if ( + bleDidConnectPybricks.matches(action) || + bleDidFailToDisconnectPybricks.matches(action) + ) { return BleConnectionState.Connected; } - if (disconnect.matches(action)) { + if (bleDisconnectPybricks.matches(action)) { return BleConnectionState.Disconnecting; } - if (didFailToConnect.matches(action) || didDisconnect.matches(action)) { + if ( + bleDidFailToConnectPybricks.matches(action) || + bleDidDisconnectPybricks.matches(action) + ) { return BleConnectionState.Disconnected; } @@ -67,11 +73,11 @@ const connection: Reducer = ( }; const deviceName: Reducer = (state = '', action) => { - if (didDisconnect.matches(action)) { + if (bleDidDisconnectPybricks.matches(action)) { return ''; } - if (didConnect.matches(action)) { + if (bleDidConnectPybricks.matches(action)) { return action.name; } @@ -79,7 +85,7 @@ const deviceName: Reducer = (state = '', action) => { }; const deviceType: Reducer = (state = '', action) => { - if (didDisconnect.matches(action)) { + if (bleDidDisconnectPybricks.matches(action)) { return ''; } @@ -91,7 +97,7 @@ const deviceType: Reducer = (state = '', action) => { }; const deviceFirmwareVersion: Reducer = (state = '', action) => { - if (didDisconnect.matches(action)) { + if (bleDidDisconnectPybricks.matches(action)) { return ''; } @@ -103,7 +109,7 @@ const deviceFirmwareVersion: Reducer = (state = '', action) => { }; const deviceLowBatteryWarning: Reducer = (state = false, action) => { - if (didDisconnect.matches(action)) { + if (bleDidDisconnectPybricks.matches(action)) { return false; } @@ -117,7 +123,7 @@ const deviceLowBatteryWarning: Reducer = (state = false, action) => { }; const deviceBatteryCharging: Reducer = (state = false, action) => { - if (didDisconnect.matches(action)) { + if (bleDidDisconnectPybricks.matches(action)) { return false; } diff --git a/src/ble/sagas.test.ts b/src/ble/sagas.test.ts index 8f3eb3e2..453c11ff 100644 --- a/src/ble/sagas.test.ts +++ b/src/ble/sagas.test.ts @@ -27,11 +27,11 @@ import { } from '../ble-pybricks-service/protocol'; import { BleDeviceFailToConnectReasonType, - connect, - didConnect, - didDisconnect, - didFailToConnect, - disconnect, + bleConnectPybricks, + bleDidConnectPybricks, + bleDidDisconnectPybricks, + bleDidFailToConnectPybricks, + bleDisconnectPybricks, toggleBluetooth, } from './actions'; import { BleConnectionState } from './reducers'; @@ -191,7 +191,7 @@ enum ConnectRunPoint { * @param point The point at which to stop running. */ async function runConnectUntil(saga: AsyncSaga, point: ConnectRunPoint): Promise { - saga.put(connect()); + saga.put(bleConnectPybricks()); if (point === ConnectRunPoint.Connect) { return; @@ -226,7 +226,9 @@ async function runConnectUntil(saga: AsyncSaga, point: ConnectRunPoint): Promise return; } - await expect(saga.take()).resolves.toEqual(didConnect('test-id', 'test name')); + await expect(saga.take()).resolves.toEqual( + bleDidConnectPybricks('test-id', 'test name'), + ); } describe('connect action is dispatched', () => { @@ -240,7 +242,7 @@ describe('connect action is dispatched', () => { await runConnectUntil(saga, ConnectRunPoint.Connect); await expect(saga.take()).resolves.toEqual( - didFailToConnect({ + bleDidFailToConnectPybricks({ reason: BleDeviceFailToConnectReasonType.NoWebBluetooth, }), ); @@ -259,7 +261,7 @@ describe('connect action is dispatched', () => { await runConnectUntil(saga, ConnectRunPoint.Connect); await expect(saga.take()).resolves.toEqual( - didFailToConnect({ + bleDidFailToConnectPybricks({ reason: BleDeviceFailToConnectReasonType.NoBluetooth, }), ); @@ -273,7 +275,7 @@ describe('connect action is dispatched', () => { await runConnectUntil(saga, ConnectRunPoint.Connect); await expect(saga.take()).resolves.toEqual( - didFailToConnect({ + bleDidFailToConnectPybricks({ reason: BleDeviceFailToConnectReasonType.Canceled, }), ); @@ -288,7 +290,7 @@ describe('connect action is dispatched', () => { await runConnectUntil(saga, ConnectRunPoint.Connect); await expect(saga.take()).resolves.toEqual( - didFailToConnect({ + bleDidFailToConnectPybricks({ reason: BleDeviceFailToConnectReasonType.Unknown, err: testError, }), @@ -301,7 +303,7 @@ describe('connect action is dispatched', () => { await runConnectUntil(saga, ConnectRunPoint.Connect); await expect(saga.take()).resolves.toEqual( - didFailToConnect({ + bleDidFailToConnectPybricks({ reason: BleDeviceFailToConnectReasonType.NoGatt, }), ); @@ -314,7 +316,7 @@ describe('connect action is dispatched', () => { await runConnectUntil(saga, ConnectRunPoint.Connect); await expect(saga.take()).resolves.toEqual( - didFailToConnect({ + bleDidFailToConnectPybricks({ reason: BleDeviceFailToConnectReasonType.Unknown, err: testError, }), @@ -330,7 +332,7 @@ describe('connect action is dispatched', () => { await runConnectUntil(saga, ConnectRunPoint.Connect); await expect(saga.take()).resolves.toEqual( - didFailToConnect({ + bleDidFailToConnectPybricks({ reason: BleDeviceFailToConnectReasonType.NoDeviceInfoService, }), ); @@ -347,7 +349,7 @@ describe('connect action is dispatched', () => { await runConnectUntil(saga, ConnectRunPoint.Connect); await expect(saga.take()).resolves.toEqual( - didFailToConnect({ + bleDidFailToConnectPybricks({ reason: BleDeviceFailToConnectReasonType.Unknown, err: testError, }), @@ -363,7 +365,7 @@ describe('connect action is dispatched', () => { await runConnectUntil(saga, ConnectRunPoint.Connect); await expect(saga.take()).resolves.toEqual( - didFailToConnect({ + bleDidFailToConnectPybricks({ reason: BleDeviceFailToConnectReasonType.Unknown, err: testError, }), @@ -381,7 +383,7 @@ describe('connect action is dispatched', () => { await runConnectUntil(saga, ConnectRunPoint.DidReceiveFirmwareRevision); await expect(saga.take()).resolves.toEqual( - didFailToConnect({ + bleDidFailToConnectPybricks({ reason: BleDeviceFailToConnectReasonType.Unknown, err: testError, }), @@ -397,7 +399,7 @@ describe('connect action is dispatched', () => { await runConnectUntil(saga, ConnectRunPoint.DidReceiveFirmwareRevision); await expect(saga.take()).resolves.toEqual( - didFailToConnect({ + bleDidFailToConnectPybricks({ reason: BleDeviceFailToConnectReasonType.Unknown, err: testError, }), @@ -415,7 +417,7 @@ describe('connect action is dispatched', () => { await runConnectUntil(saga, ConnectRunPoint.DidReceiveSoftwareRevision); await expect(saga.take()).resolves.toEqual( - didConnect('test-id', 'test name'), + bleDidConnectPybricks('test-id', 'test name'), ); }); @@ -426,7 +428,7 @@ describe('connect action is dispatched', () => { await runConnectUntil(saga, ConnectRunPoint.DidReceiveSoftwareRevision); await expect(saga.take()).resolves.toEqual( - didFailToConnect({ + bleDidFailToConnectPybricks({ reason: BleDeviceFailToConnectReasonType.Unknown, err: testError, }), @@ -444,7 +446,7 @@ describe('connect action is dispatched', () => { await runConnectUntil(saga, ConnectRunPoint.DidReceivePnpId); await expect(saga.take()).resolves.toEqual( - didFailToConnect({ + bleDidFailToConnectPybricks({ reason: BleDeviceFailToConnectReasonType.NoPybricksService, }), ); @@ -461,7 +463,7 @@ describe('connect action is dispatched', () => { await runConnectUntil(saga, ConnectRunPoint.DidReceivePnpId); await expect(saga.take()).resolves.toEqual( - didFailToConnect({ + bleDidFailToConnectPybricks({ reason: BleDeviceFailToConnectReasonType.Unknown, err: testError, }), @@ -477,7 +479,7 @@ describe('connect action is dispatched', () => { await runConnectUntil(saga, ConnectRunPoint.DidReceivePnpId); await expect(saga.take()).resolves.toEqual( - didFailToConnect({ + bleDidFailToConnectPybricks({ reason: BleDeviceFailToConnectReasonType.Unknown, err: testError, }), @@ -493,7 +495,7 @@ describe('connect action is dispatched', () => { await runConnectUntil(saga, ConnectRunPoint.DidReceivePnpId); await expect(saga.take()).resolves.toEqual( - didFailToConnect({ + bleDidFailToConnectPybricks({ reason: BleDeviceFailToConnectReasonType.Unknown, err: testError, }), @@ -511,7 +513,7 @@ describe('connect action is dispatched', () => { await runConnectUntil(saga, ConnectRunPoint.DidReceivePnpId); await expect(saga.take()).resolves.toEqual( - didFailToConnect({ + bleDidFailToConnectPybricks({ // FIXME: this is wrong error reason: BleDeviceFailToConnectReasonType.NoPybricksService, }), @@ -529,7 +531,7 @@ describe('connect action is dispatched', () => { await runConnectUntil(saga, ConnectRunPoint.DidReceivePnpId); await expect(saga.take()).resolves.toEqual( - didFailToConnect({ + bleDidFailToConnectPybricks({ reason: BleDeviceFailToConnectReasonType.Unknown, err: testError, }), @@ -547,7 +549,7 @@ describe('connect action is dispatched', () => { await runConnectUntil(saga, ConnectRunPoint.DidReceivePnpId); await expect(saga.take()).resolves.toEqual( - didFailToConnect({ + bleDidFailToConnectPybricks({ reason: BleDeviceFailToConnectReasonType.Unknown, err: testError, }), @@ -563,7 +565,7 @@ describe('connect action is dispatched', () => { await runConnectUntil(saga, ConnectRunPoint.DidReceivePnpId); await expect(saga.take()).resolves.toEqual( - didFailToConnect({ + bleDidFailToConnectPybricks({ reason: BleDeviceFailToConnectReasonType.Unknown, err: testError, }), @@ -579,7 +581,7 @@ describe('connect action is dispatched', () => { await runConnectUntil(saga, ConnectRunPoint.DidReceivePnpId); await expect(saga.take()).resolves.toEqual( - didFailToConnect({ + bleDidFailToConnectPybricks({ reason: BleDeviceFailToConnectReasonType.Unknown, err: testError, }), @@ -595,9 +597,9 @@ describe('connect action is dispatched', () => { it('should handle disconnect', async () => { await runConnectUntil(saga, ConnectRunPoint.DidConnect); - saga.put(disconnect()); + saga.put(bleDisconnectPybricks()); - await expect(saga.take()).resolves.toEqual(didDisconnect()); + await expect(saga.take()).resolves.toEqual(bleDidDisconnectPybricks()); expect(mocks.gatt.disconnect).toHaveBeenCalled(); }); @@ -616,7 +618,7 @@ describe('toggleBluetooth action', () => { saga.put(toggleBluetooth()); - await expect(saga.take()).resolves.toEqual(connect()); + await expect(saga.take()).resolves.toEqual(bleConnectPybricks()); }); it('should disconnect when connected', async () => { @@ -626,6 +628,6 @@ describe('toggleBluetooth action', () => { saga.put(toggleBluetooth()); - await expect(saga.take()).resolves.toEqual(disconnect()); + await expect(saga.take()).resolves.toEqual(bleDisconnectPybricks()); }); }); diff --git a/src/ble/sagas.ts b/src/ble/sagas.ts index 44a5d09d..a5cc6d1e 100644 --- a/src/ble/sagas.ts +++ b/src/ble/sagas.ts @@ -52,11 +52,11 @@ import { RootState } from '../reducers'; import { ensureError } from '../utils'; import { BleDeviceFailToConnectReasonType as Reason, - connect, - didConnect, - didDisconnect, - didFailToConnect, - disconnect, + bleConnectPybricks as bleConnectPybricks, + bleDidConnectPybricks, + bleDidDisconnectPybricks, + bleDidFailToConnectPybricks, + bleDisconnectPybricks, toggleBluetooth, } from './actions'; import { BleConnectionState } from './reducers'; @@ -99,15 +99,15 @@ function* handleWriteUart( } } -function* handleConnect(): Generator { +function* handleBleConnectPybricks(): Generator { if (navigator.bluetooth === undefined) { - yield* put(didFailToConnect({ reason: Reason.NoWebBluetooth })); + yield* put(bleDidFailToConnectPybricks({ reason: Reason.NoWebBluetooth })); return; } const available = yield* call(() => navigator.bluetooth.getAvailability()); if (!available) { - yield* put(didFailToConnect({ reason: Reason.NoBluetooth })); + yield* put(bleDidFailToConnectPybricks({ reason: Reason.NoBluetooth })); return; } @@ -126,17 +126,20 @@ function* handleConnect(): Generator { } catch (err) { if (err instanceof DOMException && err.code === DOMException.NOT_FOUND_ERR) { // this can happen if the use cancels the dialog - yield* put(didFailToConnect({ reason: Reason.Canceled })); + yield* put(bleDidFailToConnectPybricks({ reason: Reason.Canceled })); } else { yield* put( - didFailToConnect({ reason: Reason.Unknown, err: ensureError(err) }), + bleDidFailToConnectPybricks({ + reason: Reason.Unknown, + err: ensureError(err), + }), ); } return; } if (device.gatt === undefined) { - yield* put(didFailToConnect({ reason: Reason.NoGatt })); + yield* put(bleDidFailToConnectPybricks({ reason: Reason.NoGatt })); return; } @@ -152,11 +155,16 @@ function* handleConnect(): Generator { server = yield* call([device.gatt, 'connect']); } catch (err) { disconnectChannel.close(); - yield* put(didFailToConnect({ reason: Reason.Unknown, err: ensureError(err) })); + yield* put( + bleDidFailToConnectPybricks({ + reason: Reason.Unknown, + err: ensureError(err), + }), + ); return; } - yield* takeEvery(disconnect, handleDisconnect, server); + yield* takeEvery(bleDisconnectPybricks, handleDisconnect, server); let deviceInfoService: BluetoothRemoteGATTService; try { @@ -168,10 +176,15 @@ function* handleConnect(): Generator { server.disconnect(); yield* takeMaybe(disconnectChannel); if (err instanceof DOMException && err.code === DOMException.NOT_FOUND_ERR) { - yield* put(didFailToConnect({ reason: Reason.NoDeviceInfoService })); + yield* put( + bleDidFailToConnectPybricks({ reason: Reason.NoDeviceInfoService }), + ); } else { yield* put( - didFailToConnect({ reason: Reason.Unknown, err: ensureError(err) }), + bleDidFailToConnectPybricks({ + reason: Reason.Unknown, + err: ensureError(err), + }), ); } return; @@ -186,7 +199,12 @@ function* handleConnect(): Generator { } catch (err) { server.disconnect(); yield* takeMaybe(disconnectChannel); - yield* put(didFailToConnect({ reason: Reason.Unknown, err: ensureError(err) })); + yield* put( + bleDidFailToConnectPybricks({ + reason: Reason.Unknown, + err: ensureError(err), + }), + ); return; } @@ -196,7 +214,12 @@ function* handleConnect(): Generator { } catch (err) { server.disconnect(); yield* takeMaybe(disconnectChannel); - yield* put(didFailToConnect({ reason: Reason.Unknown, err: ensureError(err) })); + yield* put( + bleDidFailToConnectPybricks({ + reason: Reason.Unknown, + err: ensureError(err), + }), + ); return; } @@ -209,7 +232,12 @@ function* handleConnect(): Generator { } catch (err) { server.disconnect(); yield* takeMaybe(disconnectChannel); - yield* put(didFailToConnect({ reason: Reason.Unknown, err: ensureError(err) })); + yield* put( + bleDidFailToConnectPybricks({ + reason: Reason.Unknown, + err: ensureError(err), + }), + ); return; } @@ -219,7 +247,12 @@ function* handleConnect(): Generator { } catch (err) { server.disconnect(); yield* takeMaybe(disconnectChannel); - yield* put(didFailToConnect({ reason: Reason.Unknown, err: ensureError(err) })); + yield* put( + bleDidFailToConnectPybricks({ + reason: Reason.Unknown, + err: ensureError(err), + }), + ); return; } @@ -240,7 +273,10 @@ function* handleConnect(): Generator { server.disconnect(); yield* takeMaybe(disconnectChannel); yield* put( - didFailToConnect({ reason: Reason.Unknown, err: ensureError(err) }), + bleDidFailToConnectPybricks({ + reason: Reason.Unknown, + err: ensureError(err), + }), ); return; } @@ -256,10 +292,15 @@ function* handleConnect(): Generator { server.disconnect(); yield* takeMaybe(disconnectChannel); if (err instanceof DOMException && err.code === DOMException.NOT_FOUND_ERR) { - yield* put(didFailToConnect({ reason: Reason.NoPybricksService })); + yield* put( + bleDidFailToConnectPybricks({ reason: Reason.NoPybricksService }), + ); } else { yield* put( - didFailToConnect({ reason: Reason.Unknown, err: ensureError(err) }), + bleDidFailToConnectPybricks({ + reason: Reason.Unknown, + err: ensureError(err), + }), ); } return; @@ -274,7 +315,12 @@ function* handleConnect(): Generator { } catch (err) { server.disconnect(); yield* takeMaybe(disconnectChannel); - yield* put(didFailToConnect({ reason: Reason.Unknown, err: ensureError(err) })); + yield* put( + bleDidFailToConnectPybricks({ + reason: Reason.Unknown, + err: ensureError(err), + }), + ); return; } @@ -313,7 +359,12 @@ function* handleConnect(): Generator { pybricksControlChannel.close(); server.disconnect(); yield* takeMaybe(disconnectChannel); - yield* put(didFailToConnect({ reason: Reason.Unknown, err: ensureError(err) })); + yield* put( + bleDidFailToConnectPybricks({ + reason: Reason.Unknown, + err: ensureError(err), + }), + ); return; } @@ -328,10 +379,15 @@ function* handleConnect(): Generator { server.disconnect(); yield* takeMaybe(disconnectChannel); if (err instanceof DOMException && err.code === DOMException.NOT_FOUND_ERR) { - yield* put(didFailToConnect({ reason: Reason.NoPybricksService })); + yield* put( + bleDidFailToConnectPybricks({ reason: Reason.NoPybricksService }), + ); } else { yield* put( - didFailToConnect({ reason: Reason.Unknown, err: ensureError(err) }), + bleDidFailToConnectPybricks({ + reason: Reason.Unknown, + err: ensureError(err), + }), ); } return; @@ -345,7 +401,12 @@ function* handleConnect(): Generator { pybricksControlChannel.close(); server.disconnect(); yield* takeMaybe(disconnectChannel); - yield* put(didFailToConnect({ reason: Reason.Unknown, err: ensureError(err) })); + yield* put( + bleDidFailToConnectPybricks({ + reason: Reason.Unknown, + err: ensureError(err), + }), + ); return; } @@ -357,7 +418,12 @@ function* handleConnect(): Generator { pybricksControlChannel.close(); server.disconnect(); yield* takeMaybe(disconnectChannel); - yield* put(didFailToConnect({ reason: Reason.Unknown, err: ensureError(err) })); + yield* put( + bleDidFailToConnectPybricks({ + reason: Reason.Unknown, + err: ensureError(err), + }), + ); return; } @@ -389,13 +455,18 @@ function* handleConnect(): Generator { pybricksControlChannel.close(); server.disconnect(); yield* takeMaybe(disconnectChannel); - yield* put(didFailToConnect({ reason: Reason.Unknown, err: ensureError(err) })); + yield* put( + bleDidFailToConnectPybricks({ + reason: Reason.Unknown, + err: ensureError(err), + }), + ); return; } tasks.push(yield* takeEvery(writeUart, handleWriteUart, uartRxChar)); - yield* put(didConnect(device.id, device.name || '')); + yield* put(bleDidConnectPybricks(device.id, device.name || '')); // wait for disconnection yield* takeMaybe(disconnectChannel); @@ -404,7 +475,7 @@ function* handleConnect(): Generator { uartTxChannel.close(); pybricksControlChannel.close(); - yield* put(didDisconnect()); + yield* put(bleDidDisconnectPybricks()); } function* handleToggleBluetooth(): Generator { @@ -414,15 +485,15 @@ function* handleToggleBluetooth(): Generator { switch (connectionState) { case BleConnectionState.Connected: - yield* put(disconnect()); + yield* put(bleDisconnectPybricks()); break; case BleConnectionState.Disconnected: - yield* put(connect()); + yield* put(bleConnectPybricks()); break; } } export default function* (): Generator { - yield* takeEvery(connect, handleConnect); + yield* takeEvery(bleConnectPybricks, handleBleConnectPybricks); yield* takeEvery(toggleBluetooth, handleToggleBluetooth); } diff --git a/src/error-log/sagas.test.ts b/src/error-log/sagas.test.ts index 52711661..468f99a9 100644 --- a/src/error-log/sagas.test.ts +++ b/src/error-log/sagas.test.ts @@ -6,7 +6,7 @@ import { didFailToWrite } from '../ble-nordic-uart-service/actions'; import { eventProtocolError } from '../ble-pybricks-service/actions'; import { BleDeviceFailToConnectReasonType, - didFailToConnect as bleDidFailToConnect, + bleDidFailToConnectPybricks, } from '../ble/actions'; import { BootloaderConnectionFailureReason, @@ -21,12 +21,14 @@ test('bleDeviceDidFailToConnect', async () => { console.error = jest.fn(); saga.put( - bleDidFailToConnect({ reason: BleDeviceFailToConnectReasonType.Canceled }), + bleDidFailToConnectPybricks({ + reason: BleDeviceFailToConnectReasonType.Canceled, + }), ); expect(console.error).toHaveBeenCalledTimes(0); saga.put( - bleDidFailToConnect({ + bleDidFailToConnectPybricks({ reason: BleDeviceFailToConnectReasonType.Unknown, err: new Error('test error'), }), diff --git a/src/error-log/sagas.ts b/src/error-log/sagas.ts index aca7848a..3c52074a 100644 --- a/src/error-log/sagas.ts +++ b/src/error-log/sagas.ts @@ -6,7 +6,7 @@ import { didFailToWrite as bleUartDidFailToWrite } from '../ble-nordic-uart-serv import { eventProtocolError as pybricksEventProtocolError } from '../ble-pybricks-service/actions'; import { BleDeviceFailToConnectReasonType, - didFailToConnect as bleDeviceDidFailToConnect, + bleDidFailToConnectPybricks, } from '../ble/actions'; import { fileStorageDidFailToStoreTextFileValue } from '../fileStorage/actions'; import { @@ -16,7 +16,7 @@ import { } from '../lwp3-bootloader/actions'; function handleBleDeviceDidFailToConnect( - action: ReturnType, + action: ReturnType, ): void { if (action.reason === BleDeviceFailToConnectReasonType.Unknown) { console.error(action.err); @@ -54,7 +54,7 @@ function handleFileStorageDidFailToStoreTextFileValue( } export default function* (): Generator { - yield* takeEvery(bleDeviceDidFailToConnect, handleBleDeviceDidFailToConnect); + yield* takeEvery(bleDidFailToConnectPybricks, handleBleDeviceDidFailToConnect); yield* takeEvery(pybricksEventProtocolError, handlePybricksEventProtocolError); yield* takeEvery(bleUartDidFailToWrite, handleBleUartDidFailToWrite); yield* takeEvery(bootloaderDidFailToConnect, handleBootloaderDidFailToConnect); diff --git a/src/hub/reducers.test.ts b/src/hub/reducers.test.ts index 21526eb8..d590b1b6 100644 --- a/src/hub/reducers.test.ts +++ b/src/hub/reducers.test.ts @@ -4,7 +4,7 @@ import { AnyAction } from 'redux'; import { didReceiveStatusReport } from '../ble-pybricks-service/actions'; import { Status, statusToFlag } from '../ble-pybricks-service/protocol'; -import { didConnect, didDisconnect } from '../ble/actions'; +import { bleDidConnectPybricks, bleDidDisconnectPybricks } from '../ble/actions'; import { didFailToFinishDownload, didFinishDownload, @@ -30,7 +30,7 @@ describe('runtime', () => { expect( reducers( { runtime: HubRuntimeState.Disconnected } as State, - didConnect('test-id', 'Test Name'), + bleDidConnectPybricks('test-id', 'Test Name'), ).runtime, ).toBe(HubRuntimeState.Unknown); }); @@ -38,7 +38,8 @@ describe('runtime', () => { test.each(Object.values(HubRuntimeState))('didDisconnect', (startingState) => { // all states are overridden by disconnect expect( - reducers({ runtime: startingState } as State, didDisconnect()).runtime, + reducers({ runtime: startingState } as State, bleDidDisconnectPybricks()) + .runtime, ).toBe(HubRuntimeState.Disconnected); }); diff --git a/src/hub/reducers.ts b/src/hub/reducers.ts index c0b4ef52..16986c61 100644 --- a/src/hub/reducers.ts +++ b/src/hub/reducers.ts @@ -6,7 +6,7 @@ import * as semver from 'semver'; import { bleDIServiceDidReceiveFirmwareRevision } from '../ble-device-info-service/actions'; import { didReceiveStatusReport } from '../ble-pybricks-service/actions'; import { Status, statusToFlag } from '../ble-pybricks-service/protocol'; -import { didConnect, didDisconnect } from '../ble/actions'; +import { bleDidConnectPybricks, bleDidDisconnectPybricks } from '../ble/actions'; import { pythonVersionToSemver } from '../utils/version'; import { didFailToFinishDownload, @@ -49,11 +49,11 @@ const runtime: Reducer = ( state = HubRuntimeState.Disconnected, action, ) => { - if (didConnect.matches(action)) { + if (bleDidConnectPybricks.matches(action)) { return HubRuntimeState.Unknown; } - if (didDisconnect.matches(action)) { + if (bleDidDisconnectPybricks.matches(action)) { return HubRuntimeState.Disconnected; } diff --git a/src/hub/sagas.ts b/src/hub/sagas.ts index f2013b10..a64fbf6a 100644 --- a/src/hub/sagas.ts +++ b/src/hub/sagas.ts @@ -18,7 +18,7 @@ import { didSendCommand, sendStopUserProgramCommand, } from '../ble-pybricks-service/actions'; -import { didConnect } from '../ble/actions'; +import { bleDidConnectPybricks } from '../ble/actions'; import { editorGetValue } from '../editor/sagas'; import { compile, didCompile, didFailToCompile } from '../mpy/actions'; import { defined } from '../utils'; @@ -190,5 +190,5 @@ export default function* (): Generator { yield* takeEvery(repl, handleRepl); yield* takeEvery(stop, handleStop); // calling stop right after connecting should get the hub into a known state - yield* takeEvery(didConnect, handleStop); + yield* takeEvery(bleDidConnectPybricks, handleStop); } diff --git a/src/notifications/sagas.test.ts b/src/notifications/sagas.test.ts index c3d08c18..edac4794 100644 --- a/src/notifications/sagas.test.ts +++ b/src/notifications/sagas.test.ts @@ -14,7 +14,7 @@ import { appDidCheckForUpdate } from '../app/actions'; import { bleDIServiceDidReceiveFirmwareRevision } from '../ble-device-info-service/actions'; import { BleDeviceFailToConnectReasonType, - didFailToConnect as bleDidFailToConnect, + bleDidFailToConnectPybricks, } from '../ble/actions'; import { editorDidFailToOpenFile } from '../editor/actions'; import { EditorError } from '../editor/error'; @@ -61,14 +61,20 @@ function createTestToasterSaga(): { toaster: IToaster; saga: AsyncSaga } { } test.each([ - bleDidFailToConnect({ reason: BleDeviceFailToConnectReasonType.NoWebBluetooth }), - bleDidFailToConnect({ reason: BleDeviceFailToConnectReasonType.NoBluetooth }), - bleDidFailToConnect({ reason: BleDeviceFailToConnectReasonType.NoGatt }), - bleDidFailToConnect({ + bleDidFailToConnectPybricks({ + reason: BleDeviceFailToConnectReasonType.NoWebBluetooth, + }), + bleDidFailToConnectPybricks({ + reason: BleDeviceFailToConnectReasonType.NoBluetooth, + }), + bleDidFailToConnectPybricks({ reason: BleDeviceFailToConnectReasonType.NoGatt }), + bleDidFailToConnectPybricks({ reason: BleDeviceFailToConnectReasonType.NoDeviceInfoService, }), - bleDidFailToConnect({ reason: BleDeviceFailToConnectReasonType.NoPybricksService }), - bleDidFailToConnect({ + bleDidFailToConnectPybricks({ + reason: BleDeviceFailToConnectReasonType.NoPybricksService, + }), + bleDidFailToConnectPybricks({ reason: BleDeviceFailToConnectReasonType.Unknown, err: { name: 'test', message: 'unknown' }, }), @@ -129,7 +135,7 @@ test.each([ }); test.each([ - bleDidFailToConnect({ reason: BleDeviceFailToConnectReasonType.Canceled }), + bleDidFailToConnectPybricks({ reason: BleDeviceFailToConnectReasonType.Canceled }), bootloaderDidFailToConnect(BootloaderConnectionFailureReason.Canceled), didFailToFinish(FailToFinishReasonType.FailedToConnect), serviceWorkerDidSucceed(), diff --git a/src/notifications/sagas.ts b/src/notifications/sagas.ts index 5b4470f1..75728fac 100644 --- a/src/notifications/sagas.ts +++ b/src/notifications/sagas.ts @@ -16,7 +16,7 @@ import { appName } from '../app/constants'; import { bleDIServiceDidReceiveFirmwareRevision } from '../ble-device-info-service/actions'; import { BleDeviceFailToConnectReasonType, - didFailToConnect as bleDeviceDidFailToConnect, + bleDidFailToConnectPybricks, } from '../ble/actions'; import { editorDidFailToOpenFile } from '../editor/actions'; import { EditorError } from '../editor/error'; @@ -171,7 +171,7 @@ function* showUnexpectedError(messageId: I18nId, error: Error): Generator { } function* showBleDeviceDidFailToConnectError( - action: ReturnType, + action: ReturnType, ): Generator { switch (action.reason) { case BleDeviceFailToConnectReasonType.NoGatt: @@ -454,7 +454,7 @@ function* showExplorerFailToDelete( } export default function* (): Generator { - yield* takeEvery(bleDeviceDidFailToConnect, showBleDeviceDidFailToConnectError); + yield* takeEvery(bleDidFailToConnectPybricks, showBleDeviceDidFailToConnectError); yield* takeEvery(bootloaderDidFailToConnect, showBootloaderDidFailToConnectError); yield* takeEvery(didFailToFinish, showFlashFirmwareError); yield* takeEvery(didCompile, dismissCompilerError);