From b8f3345906e55869b792e52ecaea561e8e688fc6 Mon Sep 17 00:00:00 2001 From: Richie Date: Wed, 21 Apr 2021 15:19:32 +0800 Subject: [PATCH] feat: add setAlertMessage, enhance cancelTechnologyRequest * setAlertMessage is no-op for Android, and the same as setAlertMessageIOS for iOS. * cancelTechnology won't throw any exceptions by default. --- __tests__/NfcManager.test.js | 30 ++++++++++++++++++++++++++++- __tests__/NfcManagerAndroid.test.js | 6 ++++++ index.d.ts | 7 ++++++- src/NfcManager.js | 6 ++++++ src/NfcManagerAndroid.js | 18 ++++++++++++----- src/NfcManagerIOS.js | 22 ++++++++++++++++----- src/__mocks__/NativeNfcManager.js | 13 ++++++++++++- 7 files changed, 89 insertions(+), 13 deletions(-) diff --git a/__tests__/NfcManager.test.js b/__tests__/NfcManager.test.js index 5a1ab90..8b667e2 100644 --- a/__tests__/NfcManager.test.js +++ b/__tests__/NfcManager.test.js @@ -1,7 +1,11 @@ jest.mock('../src/NativeNfcManager'); import {Platform} from 'react-native'; -import {NfcManagerEmitter, callNative} from '../src/NativeNfcManager'; +import { + NativeNfcManager, + NfcManagerEmitter, + callNative, +} from '../src/NativeNfcManager'; describe('NfcManager (ios)', () => { Platform.setOS('ios'); @@ -92,6 +96,30 @@ describe('NfcManager (ios)', () => { expect(options.invalidateAfterFirstRead).toBe(false); }); + test('API: cancelTechnologyRequest', async () => { + // won't throw any error during cancellation by default + NativeNfcManager.setNextError('fake-error'); + await NfcManager.cancelTechnologyRequest(); + + NativeNfcManager.setNextError('fake-error-again'); + try { + // default can be overriden by throwOnError + await NfcManager.cancelTechnologyRequest({throwOnError: true}); + } catch (ex) { + expect(ex).toEqual('fake-error-again'); + } + }); + + test('API: setAlertMessage', () => { + NfcManager.setAlertMessageIOS('hello'); + expect(lastNativeCall()[0]).toEqual('setAlertMessage'); + expect(lastNativeCall()[1]).toEqual(['hello']); + + NfcManager.setAlertMessage('hello'); + expect(lastNativeCall()[0]).toEqual('setAlertMessage'); + expect(lastNativeCall()[1]).toEqual(['hello']); + }); + test('NfcErrorIOS', () => { expect(NfcErrorIOS.parse({})).toEqual(NfcErrorIOS.errCodes.unknown); expect(NfcErrorIOS.parse('nosucherror')).toEqual( diff --git a/__tests__/NfcManagerAndroid.test.js b/__tests__/NfcManagerAndroid.test.js index d82a67b..7fdcb8b 100644 --- a/__tests__/NfcManagerAndroid.test.js +++ b/__tests__/NfcManagerAndroid.test.js @@ -50,4 +50,10 @@ describe('NfcManager (android)', () => { Array.from({length: 4}).map((_, i) => i), ); }); + + test('API: setAlertMessage', async () => { + // test if the method stub exists and can be called without exception + await NfcManager.setAlertMessage(); + expect(true).toBe(true); + }); }); diff --git a/index.d.ts b/index.d.ts index 32722db..8654c93 100644 --- a/index.d.ts +++ b/index.d.ts @@ -73,6 +73,10 @@ declare module 'react-native-nfc-manager' { readerModeDelay?: number; } + export interface CancelTechReqOpts { + throwOnError?: boolean = false; + } + interface NdefHandler { writeNdefMessage: (bytes: number[]) => Promise; getNdefMessage: () => Promise; @@ -185,8 +189,9 @@ declare module 'react-native-nfc-manager' { tech: NfcTech | NfcTech[], options?: RegisterTagEventOpts, ): Promise; - cancelTechnologyRequest: () => Promise; + cancelTechnologyRequest: (options?: CancelTechReqOpts) => Promise; getTag: () => Promise; + setAlertMessage: (alertMessage: string) => Promise; /** * common tech handler getters for both iOS / Android diff --git a/src/NfcManager.js b/src/NfcManager.js index 5b0a9d2..175c62f 100644 --- a/src/NfcManager.js +++ b/src/NfcManager.js @@ -41,6 +41,10 @@ function NotImpl() { throw new Error('not implemented'); } +async function DoNothing() { + // allow derived class to not implment it +} + class NfcManagerBase { constructor() { this._subscribeNativeEvents(); @@ -84,6 +88,8 @@ class NfcManagerBase { cancelTechnologyRequest = NotImpl; + setAlertMessage = DoNothing; + async writeNdefMessage(bytes) { return callNative('writeNdefMessage', [bytes]); } diff --git a/src/NfcManagerAndroid.js b/src/NfcManagerAndroid.js index dd06222..4c2bd13 100644 --- a/src/NfcManagerAndroid.js +++ b/src/NfcManagerAndroid.js @@ -39,12 +39,20 @@ class NfcManagerAndroid extends NfcManagerBase { } }; - cancelTechnologyRequest = async () => { - await callNative('cancelTechnologyRequest'); + cancelTechnologyRequest = async (options = {}) => { + const {throwOnError = false} = options; - if (!this.cleanUpTagRegistration) { - await this.unregisterTagEvent(); - this.cleanUpTagRegistration = false; + try { + await callNative('cancelTechnologyRequest'); + + if (!this.cleanUpTagRegistration) { + await this.unregisterTagEvent(); + this.cleanUpTagRegistration = false; + } + } catch (ex) { + if (throwOnError) { + throw ex; + } } }; diff --git a/src/NfcManagerIOS.js b/src/NfcManagerIOS.js index 971c5e7..b527e0b 100644 --- a/src/NfcManagerIOS.js +++ b/src/NfcManagerIOS.js @@ -47,16 +47,28 @@ class NfcManagerIOS extends NfcManagerBase { } }; - cancelTechnologyRequest = async () => callNative('cancelTechnologyRequest'); + cancelTechnologyRequest = async (options = {}) => { + const {throwOnError = false} = options; + + try { + return await callNative('cancelTechnologyRequest'); + } catch (ex) { + if (throwOnError) { + throw ex; + } + } + }; // ------------------------------------- // public only for iOS // ------------------------------------- + setAlertMessage = (alertMessage) => { + // override the parent one + return callNative('setAlertMessage', [alertMessage]); + }; + setAlertMessageIOS = (alertMessage) => { - if (Platform.OS !== 'ios') { - return Promise.resolve(); //no-op - } - callNative('setAlertMessage', [alertMessage]); + return callNative('setAlertMessage', [alertMessage]); }; invalidateSessionIOS = () => callNative('invalidateSession'); diff --git a/src/__mocks__/NativeNfcManager.js b/src/__mocks__/NativeNfcManager.js index 238f365..8476fb0 100644 --- a/src/__mocks__/NativeNfcManager.js +++ b/src/__mocks__/NativeNfcManager.js @@ -1,6 +1,11 @@ +let _nextError = null; + const NativeNfcManager = { MIFARE_BLOCK_SIZE: 16, MIFARE_ULTRALIGHT_PAGE_SIZE: 4, + setNextError: (err) => { + _nextError = err; + }, }; const NfcManagerEmitterListener = {}; @@ -14,6 +19,12 @@ const NfcManagerEmitter = { }, }; -const callNative = jest.fn(); +const callNative = jest.fn((...args) => { + if (_nextError) { + const err = _nextError; + _nextError = null; + return Promise.reject(err); + } +}); export {NativeNfcManager, NfcManagerEmitter, callNative};