Commit 25b5baf8 authored by yogevbd's avatar yogevbd

Add e2e tests and final adjustments

parent 296c9cbf
#import "RNBridgeModule.h" #import "RNBridgeModule.h"
#import "RNCommandsHandler.h" #import "RNCommandsHandler.h"
#import "RCTConvert+Notifications.h" #import "RCTConvert+Notifications.h"
#import "RNNotifications.h" #import "RNNotificationsStore.h"
#import <React/RCTBridgeDelegate.h> #import <React/RCTBridgeDelegate.h>
@implementation RNBridgeModule { @implementation RNBridgeModule {
...@@ -24,7 +24,9 @@ RCT_EXPORT_MODULE(); ...@@ -24,7 +24,9 @@ RCT_EXPORT_MODULE();
- (void)setBridge:(RCTBridge *)bridge { - (void)setBridge:(RCTBridge *)bridge {
_bridge = 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 #pragma mark - JS interface
......
#import "RNCommandsHandler.h" #import "RNCommandsHandler.h"
#import "RNNotifications.h" #import "RNNotifications.h"
#import "RNNotificationsStore.h"
#import "RCTConvert+Notifications.h" #import "RCTConvert+Notifications.h"
@implementation RNCommandsHandler { @implementation RNCommandsHandler {
...@@ -17,15 +18,15 @@ ...@@ -17,15 +18,15 @@
} }
- (void)getInitialNotification:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject { - (void)getInitialNotification:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject {
resolve([[RNNotifications sharedInstance] initialNotification]); resolve([[RNNotificationsStore sharedInstance] initialNotification]);
} }
- (void)finishHandlingAction:(NSString *)completionKey { - (void)finishHandlingAction:(NSString *)completionKey {
[[RNNotifications sharedInstance] finishHandleActionKey:completionKey]; [[RNNotificationsStore sharedInstance] completeAction:completionKey];
} }
- (void)finishPresentingNotification:(NSString *)completionKey presentingOptions:(NSDictionary *)presentingOptions { - (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 { - (void)abandonPermissions {
......
...@@ -4,8 +4,6 @@ ...@@ -4,8 +4,6 @@
@interface RNNotifications : NSObject @interface RNNotifications : NSObject
@property (nonatomic, retain) NSDictionary* initialNotification;
+ (instancetype)sharedInstance; + (instancetype)sharedInstance;
+ (void)startMonitorNotifications; + (void)startMonitorNotifications;
...@@ -14,8 +12,4 @@ ...@@ -14,8 +12,4 @@
+ (void)didRegisterForRemoteNotificationsWithDeviceToken:(id)deviceToken; + (void)didRegisterForRemoteNotificationsWithDeviceToken:(id)deviceToken;
+ (void)didFailToRegisterForRemoteNotificationsWithError:(NSError *)error; + (void)didFailToRegisterForRemoteNotificationsWithError:(NSError *)error;
- (void)finishHandleNotificationKey:(NSString *)notificationKey presentingOptions:(UNNotificationPresentationOptions)presentingOptions;
- (void)finishHandleActionKey:(NSString *)actionKey;
@end @end
...@@ -12,13 +12,11 @@ ...@@ -12,13 +12,11 @@
RNNotificationEventHandler* _notificationEventHandler; RNNotificationEventHandler* _notificationEventHandler;
RNPushKitEventHandler* _pushKitEventHandler; RNPushKitEventHandler* _pushKitEventHandler;
RNEventEmitter* _eventEmitter; RNEventEmitter* _eventEmitter;
RNNotificationsStore* _store;
} }
- (instancetype)init { - (instancetype)init {
self = [super init]; self = [super init];
_store = [RNNotificationsStore new]; _notificationEventHandler = [[RNNotificationEventHandler alloc] initWithStore:[RNNotificationsStore new]];
_notificationEventHandler = [[RNNotificationEventHandler alloc] initWithStore:_store];
return self; return self;
} }
...@@ -65,16 +63,4 @@ ...@@ -65,16 +63,4 @@
[_notificationEventHandler didFailToRegisterForRemoteNotificationsWithError:error]; [_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 @end
...@@ -3,7 +3,9 @@ ...@@ -3,7 +3,9 @@
@interface RNNotificationsStore : NSObject @interface RNNotificationsStore : NSObject
@property NSDictionary* initialNotification; @property (nonatomic, retain) NSDictionary* initialNotification;
+ (instancetype)sharedInstance;
- (void)completeAction:(NSString *)completionKey; - (void)completeAction:(NSString *)completionKey;
- (void)completePresentation:(NSString *)completionKey withPresentationOptions:(UNNotificationPresentationOptions)presentationOptions; - (void)completePresentation:(NSString *)completionKey withPresentationOptions:(UNNotificationPresentationOptions)presentationOptions;
......
#import "RNNotificationsStore.h" #import "RNNotificationsStore.h"
@implementation RNNotificationsStore { @implementation RNNotificationsStore
NSMutableDictionary* _actionCompletionHandlers; NSMutableDictionary* _actionCompletionHandlers;
NSMutableDictionary* _presentationCompletionHandlers; NSMutableDictionary* _presentationCompletionHandlers;
+ (instancetype)sharedInstance {
static RNNotificationsStore *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[RNNotificationsStore alloc] init];
});
return sharedInstance;
} }
- (instancetype)init { - (instancetype)init {
......
...@@ -2,20 +2,43 @@ const Utils = require('./Utils'); ...@@ -2,20 +2,43 @@ const Utils = require('./Utils');
const { elementByLabel, elementById } = Utils; const { elementByLabel, elementById } = Utils;
describe('Notifications', () => { describe('Notifications', () => {
describe('Foreground', () => {
beforeEach(async () => { beforeEach(async () => {
await device.relaunchApp({permissions: {notifications: 'YES'}}); await device.relaunchApp({permissions: {notifications: 'YES'}});
}); });
it('Receive foreground notification', async () => { it('Receive notification', async () => {
await device.sendUserNotification(getNotification('explicit/external/link/test_parameter')); await device.sendUserNotification(createNotification({link: 'foreground/notification'}));
// await device.launchApp({newInstance: true, userNotification: getNotification('unknown/link', 'test/category', {parameter: 'test_body_param'})}); await expect(elementByLabel('foreground/notification')).toBeVisible();
// await elementById(TestIDs.SWITCH_TAB_BY_INDEX_BTN).tap(); });
// await expect(elementByLabel('First Tab')).toBeNotVisible();
// await expect(elementByLabel('Second Tab')).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();
});
});
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 { return {
trigger: { trigger: {
type: 'push' type: 'push'
...@@ -26,14 +49,8 @@ function getNotification(link, category = 'com.example.category', params = {}) { ...@@ -26,14 +49,8 @@ function getNotification(link, category = 'com.example.category', params = {}) {
badge: 1, badge: 1,
payload: { payload: {
appId: '14517e1a-3ff0-af98-408e-2bd6953c36a2', appId: '14517e1a-3ff0-af98-408e-2bd6953c36a2',
aps: { link,
alert: 'this is alert', showAlert
sound: 'chime.aiff' }
},
category,
link, ...params
},
'content-available': 0,
'action-identifier': 'default'
}; };
} }
...@@ -45,6 +45,14 @@ class NotificationsExampleApp extends Component { ...@@ -45,6 +45,14 @@ class NotificationsExampleApp extends Component {
NotificationsIOS.addEventListener('pushKitNotificationReceived', this.onPushKitNotificationReceived.bind(this)); 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) { onPushRegistered(deviceToken) {
console.log('Device Token Received: ' + deviceToken); console.log('Device Token Received: ' + deviceToken);
} }
...@@ -62,21 +70,24 @@ class NotificationsExampleApp extends Component { ...@@ -62,21 +70,24 @@ class NotificationsExampleApp extends Component {
} }
onNotificationReceivedForeground(notification, completion) { onNotificationReceivedForeground(notification, completion) {
console.log('Notification Received Foreground: ' + JSON.stringify(notification)); console.log('Notification Received Foreground with title: ' + JSON.stringify(notification));
this.setState({ 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) { onNotificationOpened(notification, completion, action) {
console.log('Notification Opened: ' + JSON.stringify(notification) + JSON.stringify(action)); console.log('Notification Opened: ' + JSON.stringify(notification) + JSON.stringify(action));
this.setState({
notifications: [...this.state.notifications, `Notification Clicked: ${notification.getData().link}`]
});
completion(); completion();
} }
renderNotification(notification) { renderNotification(notification) {
return <Text>{`${''} | ${JSON.stringify(notification)}`}</Text>; return <Text>{`${notification}`}</Text>;
} }
render() { render() {
......
...@@ -84,7 +84,7 @@ export default class NotificationsIOS { ...@@ -84,7 +84,7 @@ export default class NotificationsIOS {
} else if (type === DEVICE_NOTIFICATION_OPENED_EVENT) { } else if (type === DEVICE_NOTIFICATION_OPENED_EVENT) {
listener = DeviceEventEmitter.addListener( listener = DeviceEventEmitter.addListener(
type, type,
(payload, identifier, action) => handler(new IOSNotification(payload), () => { ({payload, identifier, action}) => handler(new IOSNotification(payload), () => {
NativeRNNotifications.finishHandlingAction(identifier); NativeRNNotifications.finishHandlingAction(identifier);
}, action) }, action)
); );
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment