From 25b5baf86fbda7b896c5b6d7ce057e944a94858d Mon Sep 17 00:00:00 2001 From: yogevbd Date: Wed, 10 Jul 2019 20:57:06 +0300 Subject: [PATCH] Add e2e tests and final adjustments --- RNNotifications/RNBridgeModule.m | 6 ++- RNNotifications/RNCommandsHandler.m | 7 ++-- RNNotifications/RNNotifications.h | 6 --- RNNotifications/RNNotifications.m | 16 +------- RNNotifications/RNNotificationsStore.h | 4 +- RNNotifications/RNNotificationsStore.m | 15 +++++-- e2e/Notifications.test.js | 55 +++++++++++++++++--------- example/index.ios.js | 19 +++++++-- lib/src/index.ios.js | 2 +- 9 files changed, 76 insertions(+), 54 deletions(-) diff --git a/RNNotifications/RNBridgeModule.m b/RNNotifications/RNBridgeModule.m index 9d43e66..32f7c6f 100644 --- a/RNNotifications/RNBridgeModule.m +++ b/RNNotifications/RNBridgeModule.m @@ -1,7 +1,7 @@ #import "RNBridgeModule.h" #import "RNCommandsHandler.h" #import "RCTConvert+Notifications.h" -#import "RNNotifications.h" +#import "RNNotificationsStore.h" #import @implementation RNBridgeModule { @@ -24,7 +24,9 @@ RCT_EXPORT_MODULE(); - (void)setBridge:(RCTBridge *)bridge { _bridge = bridge; - [[RNNotifications sharedInstance] setInitialNotification:[_bridge.launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]]; + if ([_bridge.launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]) { + [[RNNotificationsStore sharedInstance] setInitialNotification:[_bridge.launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]]; + } } #pragma mark - JS interface diff --git a/RNNotifications/RNCommandsHandler.m b/RNNotifications/RNCommandsHandler.m index 7509e38..fc56c57 100644 --- a/RNNotifications/RNCommandsHandler.m +++ b/RNNotifications/RNCommandsHandler.m @@ -1,5 +1,6 @@ #import "RNCommandsHandler.h" #import "RNNotifications.h" +#import "RNNotificationsStore.h" #import "RCTConvert+Notifications.h" @implementation RNCommandsHandler { @@ -17,15 +18,15 @@ } - (void)getInitialNotification:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject { - resolve([[RNNotifications sharedInstance] initialNotification]); + resolve([[RNNotificationsStore sharedInstance] initialNotification]); } - (void)finishHandlingAction:(NSString *)completionKey { - [[RNNotifications sharedInstance] finishHandleActionKey:completionKey]; + [[RNNotificationsStore sharedInstance] completeAction:completionKey]; } - (void)finishPresentingNotification:(NSString *)completionKey presentingOptions:(NSDictionary *)presentingOptions { - [[RNNotifications sharedInstance] finishHandleNotificationKey:completionKey presentingOptions:[RCTConvert UNNotificationPresentationOptions:presentingOptions]]; + [[RNNotificationsStore sharedInstance] completePresentation:completionKey withPresentationOptions:[RCTConvert UNNotificationPresentationOptions:presentingOptions]]; } - (void)abandonPermissions { diff --git a/RNNotifications/RNNotifications.h b/RNNotifications/RNNotifications.h index 3462e1d..2e27739 100644 --- a/RNNotifications/RNNotifications.h +++ b/RNNotifications/RNNotifications.h @@ -4,8 +4,6 @@ @interface RNNotifications : NSObject -@property (nonatomic, retain) NSDictionary* initialNotification; - + (instancetype)sharedInstance; + (void)startMonitorNotifications; @@ -14,8 +12,4 @@ + (void)didRegisterForRemoteNotificationsWithDeviceToken:(id)deviceToken; + (void)didFailToRegisterForRemoteNotificationsWithError:(NSError *)error; -- (void)finishHandleNotificationKey:(NSString *)notificationKey presentingOptions:(UNNotificationPresentationOptions)presentingOptions; -- (void)finishHandleActionKey:(NSString *)actionKey; - - @end diff --git a/RNNotifications/RNNotifications.m b/RNNotifications/RNNotifications.m index c94cf03..714a62a 100644 --- a/RNNotifications/RNNotifications.m +++ b/RNNotifications/RNNotifications.m @@ -12,13 +12,11 @@ RNNotificationEventHandler* _notificationEventHandler; RNPushKitEventHandler* _pushKitEventHandler; RNEventEmitter* _eventEmitter; - RNNotificationsStore* _store; } - (instancetype)init { self = [super init]; - _store = [RNNotificationsStore new]; - _notificationEventHandler = [[RNNotificationEventHandler alloc] initWithStore:_store]; + _notificationEventHandler = [[RNNotificationEventHandler alloc] initWithStore:[RNNotificationsStore new]]; return self; } @@ -65,16 +63,4 @@ [_notificationEventHandler didFailToRegisterForRemoteNotificationsWithError:error]; } -- (void)setInitialNotification:(NSDictionary *)notification { - [_store setInitialNotification:notification]; -} - -- (void)finishHandleActionKey:(NSString *)actionKey { - [_store completeAction:actionKey]; -} - -- (void)finishHandleNotificationKey:(NSString *)notificationKey presentingOptions:(UNNotificationPresentationOptions)presentingOptions { - [_store completePresentation:notificationKey withPresentationOptions:presentingOptions]; -} - @end diff --git a/RNNotifications/RNNotificationsStore.h b/RNNotifications/RNNotificationsStore.h index 56dcd0c..3e54aa1 100644 --- a/RNNotifications/RNNotificationsStore.h +++ b/RNNotifications/RNNotificationsStore.h @@ -3,7 +3,9 @@ @interface RNNotificationsStore : NSObject -@property NSDictionary* initialNotification; +@property (nonatomic, retain) NSDictionary* initialNotification; + ++ (instancetype)sharedInstance; - (void)completeAction:(NSString *)completionKey; - (void)completePresentation:(NSString *)completionKey withPresentationOptions:(UNNotificationPresentationOptions)presentationOptions; diff --git a/RNNotifications/RNNotificationsStore.m b/RNNotifications/RNNotificationsStore.m index 4b23543..624a5d3 100644 --- a/RNNotifications/RNNotificationsStore.m +++ b/RNNotifications/RNNotificationsStore.m @@ -1,8 +1,17 @@ #import "RNNotificationsStore.h" -@implementation RNNotificationsStore { - NSMutableDictionary* _actionCompletionHandlers; - NSMutableDictionary* _presentationCompletionHandlers; +@implementation RNNotificationsStore +NSMutableDictionary* _actionCompletionHandlers; +NSMutableDictionary* _presentationCompletionHandlers; + ++ (instancetype)sharedInstance { + static RNNotificationsStore *sharedInstance = nil; + static dispatch_once_t onceToken; + + dispatch_once(&onceToken, ^{ + sharedInstance = [[RNNotificationsStore alloc] init]; + }); + return sharedInstance; } - (instancetype)init { diff --git a/e2e/Notifications.test.js b/e2e/Notifications.test.js index 71b15ec..d60e3ac 100644 --- a/e2e/Notifications.test.js +++ b/e2e/Notifications.test.js @@ -2,20 +2,43 @@ const Utils = require('./Utils'); const { elementByLabel, elementById } = Utils; describe('Notifications', () => { - beforeEach(async () => { - await device.relaunchApp({permissions: {notifications: 'YES'}}); + describe('Foreground', () => { + beforeEach(async () => { + await device.relaunchApp({permissions: {notifications: 'YES'}}); + }); + + it('Receive notification', async () => { + await device.sendUserNotification(createNotification({link: 'foreground/notification'})); + await expect(elementByLabel('foreground/notification')).toBeVisible(); + }); + + it.only('Click notification', async () => { + await device.sendUserNotification(createNotification({link: 'foreground/notification/click', showAlert: true})); + await expect(elementByLabel('Notification Clicked: foreground/notification/click')).toBeVisible(); + }); + }); + + describe('Background', () => { + beforeEach(async () => { + await device.relaunchApp({permissions: {notifications: 'YES'}}); + }); + + it('Receive notification', async () => { + device.sendToHome(); + device.launchApp({newInstance: false, userNotification: createNotification({link: 'background/notification'})}); + await expect(elementByLabel('background/notification')).toBeVisible(); + }); }); - it('Receive foreground notification', async () => { - await device.sendUserNotification(getNotification('explicit/external/link/test_parameter')); - // await device.launchApp({newInstance: true, userNotification: getNotification('unknown/link', 'test/category', {parameter: 'test_body_param'})}); - // await elementById(TestIDs.SWITCH_TAB_BY_INDEX_BTN).tap(); - // await expect(elementByLabel('First Tab')).toBeNotVisible(); - // await expect(elementByLabel('Second Tab')).toBeVisible(); + describe('Dead state', () => { + it('Receive notification', async () => { + await device.launchApp({newInstance: true, userNotification: createNotification({link: 'deadState/notification'})}); + await expect(elementByLabel('deadState/notification')).toBeVisible(); + }); }); }); -function getNotification(link, category = 'com.example.category', params = {}) { +function createNotification({link, showAlert}) { return { trigger: { type: 'push' @@ -26,14 +49,8 @@ function getNotification(link, category = 'com.example.category', params = {}) { badge: 1, payload: { appId: '14517e1a-3ff0-af98-408e-2bd6953c36a2', - aps: { - alert: 'this is alert', - sound: 'chime.aiff' - }, - category, - link, ...params - }, - 'content-available': 0, - 'action-identifier': 'default' + link, + showAlert + } }; -} \ No newline at end of file +} diff --git a/example/index.ios.js b/example/index.ios.js index c9e90b9..a764bfa 100644 --- a/example/index.ios.js +++ b/example/index.ios.js @@ -45,6 +45,14 @@ class NotificationsExampleApp extends Component { NotificationsIOS.addEventListener('pushKitNotificationReceived', this.onPushKitNotificationReceived.bind(this)); } + async componentDidMount() { + const initialNotification = await NotificationsIOS.getInitialNotification(); + if (initialNotification) { + this.setState({notifications: [initialNotification.getData().link, ...this.state.notifications]}); + } + + } + onPushRegistered(deviceToken) { console.log('Device Token Received: ' + deviceToken); } @@ -62,21 +70,24 @@ class NotificationsExampleApp extends Component { } onNotificationReceivedForeground(notification, completion) { - console.log('Notification Received Foreground: ' + JSON.stringify(notification)); + console.log('Notification Received Foreground with title: ' + JSON.stringify(notification)); this.setState({ - notifications: [...this.state.notifications, notification] + notifications: [...this.state.notifications, notification.getData().link] }); - completion({alert: true, sound: false, badge: false}); + completion({alert: notification.getData().showAlert, sound: false, badge: false}); } onNotificationOpened(notification, completion, action) { console.log('Notification Opened: ' + JSON.stringify(notification) + JSON.stringify(action)); + this.setState({ + notifications: [...this.state.notifications, `Notification Clicked: ${notification.getData().link}`] + }); completion(); } renderNotification(notification) { - return {`${''} | ${JSON.stringify(notification)}`}; + return {`${notification}`}; } render() { diff --git a/lib/src/index.ios.js b/lib/src/index.ios.js index 171222d..d335c78 100644 --- a/lib/src/index.ios.js +++ b/lib/src/index.ios.js @@ -84,7 +84,7 @@ export default class NotificationsIOS { } else if (type === DEVICE_NOTIFICATION_OPENED_EVENT) { listener = DeviceEventEmitter.addListener( type, - (payload, identifier, action) => handler(new IOSNotification(payload), () => { + ({payload, identifier, action}) => handler(new IOSNotification(payload), () => { NativeRNNotifications.finishHandlingAction(identifier); }, action) ); -- 2.26.2