From 5da915851cbca5ee0a4e402b706619134554ada8 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Wed, 27 May 2020 12:33:01 -0500 Subject: [PATCH] strongly type MessageId This way we can add tests to ensure proper mapping in .json --- src/components/notification.en.json | 16 +++++--------- src/components/notification.test.ts | 21 ++++++++++++++++++ src/reducers/notification.ts | 33 +++++++++++++++-------------- 3 files changed, 43 insertions(+), 27 deletions(-) create mode 100644 src/components/notification.test.ts diff --git a/src/components/notification.en.json b/src/components/notification.en.json index 6762ec8b..38f03978 100644 --- a/src/components/notification.en.json +++ b/src/components/notification.en.json @@ -1,15 +1,9 @@ { - "bootloader": { - "connection": { - "didConnect": { - "cannotWriteWithoutResponse": "This web browser does not support Web Bluetooth Write Characteristic Without Response. Flashing firmware will take a long time." - }, - "didFailToConnect": { - "gattServiceNotFound": "Connected to hub but failed to get LEGO bootloader service. Try removing the \"LEGO Bootloader\" device in your OS Bluetooth settings, then try again.", - "noWebBluetooth": "This web browser does not support Web Bluetooth or it is not enabled.", - "unknown": "Unexpected error while trying to connect. Check console log and report the error." - } - } + "ble": { + "cannotWriteWithoutResponse": "This web browser does not support Web Bluetooth Write Characteristic Without Response. Flashing firmware will take a long time.", + "gattServiceNotFound": "Connected to hub but failed to get LEGO bootloader service. Try removing the \"LEGO Bootloader\" device in your OS Bluetooth settings, then try again.", + "noWebBluetooth": "This web browser does not support Web Bluetooth or it is not enabled.", + "connectFailed": "Unexpected error while trying to connect. Check console log and report the error." }, "serviceWorker": { "success": "Content is cached for offline use.", diff --git a/src/components/notification.test.ts b/src/components/notification.test.ts new file mode 100644 index 00000000..12b7c6aa --- /dev/null +++ b/src/components/notification.test.ts @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT +// Copyright (c) 2020 The Pybricks Authors + +import { MessageId } from '../reducers/notification'; +import en from './notification.en.json'; + +function lookup(obj: object, id: string): string | undefined { + const value = id + .split('.') + .reduce((pv, cv) => pv && (pv as Record)[cv], obj); + if (typeof value === 'string') { + return value; + } + return undefined; +} + +describe('Ensure .json file has matches for MessageIds', () => { + test.each(Object.values(MessageId))('%s', (id) => { + expect(lookup(en, id)).toBeDefined(); + }); +}); diff --git a/src/reducers/notification.ts b/src/reducers/notification.ts index 565907ba..496c6761 100644 --- a/src/reducers/notification.ts +++ b/src/reducers/notification.ts @@ -12,6 +12,15 @@ import { NotificationActionType } from '../actions/notification'; import { ServiceWorkerActionType } from '../actions/service-worker'; import { createCountFunc } from '../utils/iter'; +export enum MessageId { + BleCannotWriteWithoutResponse = 'ble.cannotWriteWithoutResponse', + BleConnectFailed = 'ble.connectFailed', + BleGattServiceNotFound = 'ble.gattServiceNotFound', + BleNoWebBluetooth = 'ble.noWebBluetooth', + ServiceWorkerSuccess = 'serviceWorker.success', + ServiceWorkerUpdate = 'serviceWorker.update', +} + /** * Severity level of notification. */ @@ -34,7 +43,7 @@ export interface Notification { readonly id: number; readonly level: Level; readonly message?: string; - readonly messageId?: string; + readonly messageId?: MessageId; readonly helpUrl?: string; } @@ -45,7 +54,7 @@ const nextId = createCountFunc(); function append( state: NotificationList, level: Level, - messageId: string, + messageId: MessageId, helpUrl?: string, ): NotificationList { return [...state, { id: nextId(), level, messageId, helpUrl }]; @@ -58,7 +67,7 @@ const list: Reducer = (state = [], action) => { return append( state, Level.Warning, - 'bootloader.connection.didConnect.cannotWriteWithoutResponse', + MessageId.BleCannotWriteWithoutResponse, 'https://github.com/WebBluetoothCG/web-bluetooth/blob/master/implementation-status.md', ); } @@ -66,24 +75,16 @@ const list: Reducer = (state = [], action) => { case BootloaderConnectionActionType.DidFailToConnect: switch (action.reason) { case BootloaderConnectionFailureReason.GattServiceNotFound: - return append( - state, - Level.Error, - 'bootloader.connection.didFailToConnect.gattServiceNotFound', - ); + return append(state, Level.Error, MessageId.BleGattServiceNotFound); case BootloaderConnectionFailureReason.NoWebBluetooth: return append( state, Level.Error, - 'bootloader.connection.didFailToConnect.noWebBluetooth', + MessageId.BleNoWebBluetooth, 'https://github.com/WebBluetoothCG/web-bluetooth/blob/master/implementation-status.md', ); case BootloaderConnectionFailureReason.Unknown: - return append( - state, - Level.Error, - 'bootloader.connection.didFailToConnect.unknown', - ); + return append(state, Level.Error, MessageId.BleConnectFailed); } return state; case NotificationActionType.Add: @@ -102,11 +103,11 @@ const list: Reducer = (state = [], action) => { return append( state, Level.Info, - 'serviceWorker.update', + MessageId.ServiceWorkerUpdate, 'https://bit.ly/CRA-PWA', ); case ServiceWorkerActionType.Success: - return append(state, Level.Info, 'serviceWorker.success'); + return append(state, Level.Info, MessageId.ServiceWorkerSuccess); default: return state; }