Commit c0e921c1 authored by yogevbd's avatar yogevbd

typescript WIP

parent f666b856
......@@ -109,7 +109,7 @@
formattedNotification[@"body"] = RCTNullIfNil(content.body);
formattedNotification[@"category"] = RCTNullIfNil(content.categoryIdentifier);
formattedNotification[@"thread"] = RCTNullIfNil(content.threadIdentifier);
[formattedNotification addEntriesFromDictionary:RCTNullIfNil(RCTJSONClean(content.userInfo))];
formattedNotification[@"data"] = [NSDictionary dictionaryWithDictionary:RCTNullIfNil(RCTJSONClean(content.userInfo))];
return formattedNotification;
}
......
......@@ -4,15 +4,11 @@
@implementation RNNotificationParser
+ (NSDictionary *)parseNotification:(UNNotification *)notification {
NSDictionary* notificationDict = @{@"identifier": notification.request.identifier,
@"payload": [RCTConvert UNNotificationPayload:notification]
};
return notificationDict;
return [RCTConvert UNNotificationPayload:notification];
}
+ (NSDictionary *)parseNotificationResponse:(UNNotificationResponse *)response {
NSDictionary* responseDict = @{@"payload": [RCTConvert UNNotificationPayload:response.notification], @"identifier": response.notification.request.identifier, @"action": [self parseNotificationResponseAction:response]};
NSDictionary* responseDict = @{@"notification": [RCTConvert UNNotificationPayload:response.notification], @"identifier": response.notification.request.identifier, @"action": [self parseNotificationResponseAction:response]};
return responseDict;
}
......
......@@ -6,90 +6,92 @@ import {
Button
} from 'react-native';
import React, {Component} from 'react';
import { Notifications } from '../lib/dist/index';
// let upvoteAction = new NotificationAction({
// activationMode: 'background',
// title: String.fromCodePoint(0x1F44D),
// identifier: 'UPVOTE_ACTION'
// });
// let replyAction = new NotificationAction({
// activationMode: 'background',
// title: 'Reply',
// authenticationRequired: true,
// textInput: {
// buttonTitle: 'Reply now',
// placeholder: 'Insert message'
// },
// identifier: 'REPLY_ACTION'
// });
class NotificationsExampleApp extends Component {
constructor() {
super();
this.state = {
notifications: []
};
Notifications.events().registerNotificationsReceived((notification) => {
alert(JSON.stringify(notification));
})
// NotificationsIOS.addEventListener('remoteNotificationsRegistered', this.onPushRegistered.bind(this));
// NotificationsIOS.addEventListener('remoteNotificationsRegistrationFailed', this.onPushRegisteredFailed.bind(this));
this.registerNotificationEvents();
}
// NotificationsIOS.addEventListener('pushKitRegistered', this.onPushKitRegistered.bind(this));
// NotificationsIOS.registerPushKit();
registerNotificationEvents() {
Notifications.events().registerNotificationReceived((notification, completion) => {
this.setState({
notifications: [...this.state.notifications, notification.data.link]
});
// NotificationsIOS.addEventListener('notificationReceivedForeground', this.onNotificationReceivedForeground.bind(this));
// NotificationsIOS.addEventListener('notificationOpened', this.onNotificationOpened.bind(this));
// NotificationsIOS.addEventListener('pushKitNotificationReceived', this.onPushKitNotificationReceived.bind(this));
}
completion({alert: true, sound: false, badge: false});
});
async componentDidMount() {
const initialNotification = await Notifications.getInitialNotification();
if (initialNotification) {
this.setState({notifications: [initialNotification.getData().link, ...this.state.notifications]});
}
Notifications.events().registerRemoteNotificationOpened((response, completion) => {
this.setState({
notifications: [...this.state.notifications, `Notification Clicked: ${response.notification.data.link}`]
});
completion();
});
}
onPushRegistered(deviceToken) {
console.log('Device Token Received: ' + deviceToken);
renderNotification(notification) {
return <Text>{`${notification}`}</Text>;
}
onPushRegisteredFailed(error) {
console.log('Remote notifiction registration failed: ' + error);
requestPermissions() {
Notifications.requestPermissions();
}
onPushKitRegistered(deviceToken) {
console.log('PushKit Token Received: ' + deviceToken);
}
setCategories() {
const upvoteAction = {
activationMode: 'background',
title: String.fromCodePoint(0x1F44D),
identifier: 'UPVOTE_ACTION'
};
const replyAction = {
activationMode: 'background',
title: 'Reply',
authenticationRequired: true,
textInput: {
buttonTitle: 'Reply now',
placeholder: 'Insert message'
},
identifier: 'REPLY_ACTION'
};
const category = {
identifier: 'SOME_CATEGORY',
actions: [upvoteAction, replyAction]
};
onPushKitNotificationReceived(notification) {
console.log('PushKit notification Received: ' + JSON.stringify(notification));
Notifications.setCategories([category]);
}
onNotificationReceivedForeground(notification, completion) {
console.log('Notification Received Foreground with title: ' + JSON.stringify(notification));
this.setState({
notifications: [...this.state.notifications, notification.getData().link]
sendLocalNotification() {
Notifications.localNotification({
body: 'Local notificiation!',
title: 'Local Notification Title',
sound: 'chime.aiff',
category: 'SOME_CATEGORY',
userInfo: { link: 'localNotificationLink' },
});
}
completion({alert: notification.getData().showAlert, sound: false, badge: false});
removeAllDeliveredNotifications() {
Notifications.removeAllDeliveredNotifications();
}
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();
async componentDidMount() {
const initialNotification = await Notifications.getInitialNotification();
if (initialNotification) {
this.setState({notifications: [initialNotification.data.link, ...this.state.notifications]});
}
}
renderNotification(notification) {
return <Text>{`${notification}`}</Text>;
componentWillUnmount() {
}
render() {
......@@ -109,35 +111,6 @@ class NotificationsExampleApp extends Component {
</View>
);
}
requestPermissions() {
// let cat = new NotificationCategory({
// identifier: 'SOME_CATEGORY',
// actions: [upvoteAction, replyAction]
// });
Notifications.requestPermissions(/*[cat]*/);
}
sendLocalNotification() {
Notifications.localNotification({
body: 'Local notificiation!',
title: 'Local Notification Title',
sound: 'chime.aiff',
category: 'SOME_CATEGORY',
userInfo: { link: 'localNotificationLink' },
});
}
removeAllDeliveredNotifications() {
// NotificationsIOS.removeAllDeliveredNotifications();
}
componentWillUnmount() {
// NotificationsIOS.removeEventListener('notificationReceivedForeground', this.onNotificationReceivedForeground.bind(this));
// NotificationsIOS.removeEventListener('notificationOpened', this.onNotificationOpened.bind(this));
// NotificationsIOS.removeEventListener('remoteNotificationsRegistered', this.onPushRegistered.bind(this));
// NotificationsIOS.removeEventListener('pushKitRegistered', this.onPushKitRegistered.bind(this));
}
}
const styles = StyleSheet.create({
......
......@@ -11,6 +11,7 @@
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
50CBD3CD22F2558C00142352 /* libRCTAnimation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 50CBD3A922F2556900142352 /* libRCTAnimation.a */; };
50F1F0CC22CE3B4700FD5829 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 50F1F06022CE3A6100FD5829 /* libReact.a */; };
50F1F0CD22CE3B6300FD5829 /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 50F1F08A22CE3AA000FD5829 /* libRCTActionSheet.a */; };
50F1F0CF22CE3B6300FD5829 /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 50F1F09522CE3ABE00FD5829 /* libRCTImage.a */; };
......@@ -27,6 +28,20 @@
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
50CBD3A822F2556900142352 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 50CBD3A222F2556900142352 /* RCTAnimation.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 134814201AA4EA6300B7C361;
remoteInfo = RCTAnimation;
};
50CBD3AA22F2556900142352 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 50CBD3A222F2556900142352 /* RCTAnimation.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 2D2A28201D9B03D100D4039D;
remoteInfo = "RCTAnimation-tvOS";
};
50E49F4022D1F06C007160C1 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
......@@ -283,6 +298,7 @@
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = NotificationsExampleApp/Info.plist; sourceTree = "<group>"; };
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = NotificationsExampleApp/main.m; sourceTree = "<group>"; };
146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = "../../node_modules/react-native/React/React.xcodeproj"; sourceTree = "<group>"; };
50CBD3A222F2556900142352 /* RCTAnimation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAnimation.xcodeproj; path = "../../node_modules/react-native/Libraries/NativeAnimation/RCTAnimation.xcodeproj"; sourceTree = "<group>"; };
50F1F08522CE3A9F00FD5829 /* RCTActionSheet.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTActionSheet.xcodeproj; path = "../../node_modules/react-native/Libraries/ActionSheetIOS/RCTActionSheet.xcodeproj"; sourceTree = "<group>"; };
50F1F0A022CE3B0600FD5829 /* RCTNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTNetwork.xcodeproj; path = "../../node_modules/react-native/Libraries/Network/RCTNetwork.xcodeproj"; sourceTree = "<group>"; };
78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = "../../node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj"; sourceTree = "<group>"; };
......@@ -296,6 +312,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
50CBD3CD22F2558C00142352 /* libRCTAnimation.a in Frameworks */,
50F1F0D722CE3C1E00FD5829 /* libcxxreact.a in Frameworks */,
50F1F0D622CE3C0F00FD5829 /* libyoga.a in Frameworks */,
50F1F0CD22CE3B6300FD5829 /* libRCTActionSheet.a in Frameworks */,
......@@ -346,6 +363,15 @@
name = NotificationsExampleApp;
sourceTree = "<group>";
};
50CBD3A322F2556900142352 /* Products */ = {
isa = PBXGroup;
children = (
50CBD3A922F2556900142352 /* libRCTAnimation.a */,
50CBD3AB22F2556900142352 /* libRCTAnimation.a */,
);
name = Products;
sourceTree = "<group>";
};
50F1F04D22CE3A6100FD5829 /* Products */ = {
isa = PBXGroup;
children = (
......@@ -444,6 +470,7 @@
832341AE1AAA6A7D00B99B32 /* Libraries */ = {
isa = PBXGroup;
children = (
50CBD3A222F2556900142352 /* RCTAnimation.xcodeproj */,
50F1F0A022CE3B0600FD5829 /* RCTNetwork.xcodeproj */,
D85498C21D97B31100DEEE06 /* RNNotifications.xcodeproj */,
146833FF1AC3E56700842450 /* React.xcodeproj */,
......@@ -542,6 +569,10 @@
ProductGroup = 50F1F08622CE3A9F00FD5829 /* Products */;
ProjectRef = 50F1F08522CE3A9F00FD5829 /* RCTActionSheet.xcodeproj */;
},
{
ProductGroup = 50CBD3A322F2556900142352 /* Products */;
ProjectRef = 50CBD3A222F2556900142352 /* RCTAnimation.xcodeproj */;
},
{
ProductGroup = 50F1F09022CE3ABE00FD5829 /* Products */;
ProjectRef = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */;
......@@ -587,6 +618,20 @@
/* End PBXProject section */
/* Begin PBXReferenceProxy section */
50CBD3A922F2556900142352 /* libRCTAnimation.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libRCTAnimation.a;
remoteRef = 50CBD3A822F2556900142352 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
50CBD3AB22F2556900142352 /* libRCTAnimation.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libRCTAnimation.a;
remoteRef = 50CBD3AA22F2556900142352 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
50E49F4122D1F06C007160C1 /* libjsi.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
......
......@@ -4,6 +4,7 @@ import { Commands } from './commands/Commands';
import { EventsRegistry } from './events/EventsRegistry';
import { Notification, NotificationCategory } from './interfaces/Notification';
import { UniqueIdProvider } from './adapters/UniqueIdProvider';
import { CompletionCallbackWrapper } from './adapters/CompletionCallbackWrapper';
export class NotificationsRoot {
private readonly nativeEventsReceiver: NativeEventsReceiver;
......@@ -11,16 +12,18 @@ export class NotificationsRoot {
private readonly commands: Commands;
private readonly eventsRegistry: EventsRegistry;
private readonly uniqueIdProvider: UniqueIdProvider;
private readonly completionCallbackWrapper: CompletionCallbackWrapper;
constructor() {
this.nativeEventsReceiver = new NativeEventsReceiver();
this.nativeCommandsSender = new NativeCommandsSender();
this.completionCallbackWrapper = new CompletionCallbackWrapper(this.nativeCommandsSender);
this.uniqueIdProvider = new UniqueIdProvider();
this.commands = new Commands(
this.nativeCommandsSender,
this.uniqueIdProvider
);
this.eventsRegistry = new EventsRegistry(this.nativeEventsReceiver);
this.eventsRegistry = new EventsRegistry(this.nativeEventsReceiver, this.completionCallbackWrapper);
}
/**
......@@ -45,7 +48,7 @@ export class NotificationsRoot {
}
/**
*
* getInitialNotification
*/
public getInitialNotification(): Promise<Notification> {
return this.commands.getInitialNotification();
......
import { NativeCommandsSender } from './NativeCommandsSender';
import { NotificationCompletion, Notification } from '../interfaces/Notification';
import { NotificationResponse } from '../interfaces/NotificationEvents';
export class CompletionCallbackWrapper {
constructor(
private readonly nativeCommandsSender: NativeCommandsSender
) {}
public wrapReceivedCallback(callback: Function): (notification: Notification) => void {
return (notification) => {
const completion = (response: NotificationCompletion) => {
this.nativeCommandsSender.finishPresentingNotification(notification.identifier, response);
};
callback(notification, completion);
}
}
public wrapOpenedCallback(callback: Function): (response: NotificationResponse) => void {
return (response) => {
const completion = () => {
this.nativeCommandsSender.finishHandlingAction(response.notification.identifier);
};
callback(response, completion);
}
}
}
export const { NativeCommandsSender } = jest.genMockFromModule('./NativeCommandsSender');
import { NativeModules } from 'react-native';
import { Notification, NotificationCategory, NotificationPermissions } from '../interfaces/Notification';
import { Notification, NotificationCategory, NotificationPermissions, NotificationCompletion } from '../interfaces/Notification';
interface NativeCommandsModule {
getInitialNotification(): Promise<Notification>;
......@@ -16,6 +16,8 @@ interface NativeCommandsModule {
removeDeliveredNotifications(identifiers: Array<string>): void;
removeAllDeliveredNotifications(): void;
setCategories(categories: [NotificationCategory?]): void;
finishPresentingNotification(notificationId: string, callback: NotificationCompletion): void;
finishHandlingAction(notificationId: string): void;
}
export class NativeCommandsSender {
......@@ -28,7 +30,7 @@ export class NativeCommandsSender {
return this.nativeCommandsModule.localNotification(notification, id);
}
getInitialNotification() {
getInitialNotification(): Promise<Notification> {
return this.nativeCommandsModule.getInitialNotification();
}
......@@ -79,4 +81,12 @@ export class NativeCommandsSender {
removeDeliveredNotifications(identifiers: Array<string>) {
return this.nativeCommandsModule.removeDeliveredNotifications(identifiers);
}
finishPresentingNotification(notificationId: string, notificationCompletion: NotificationCompletion): void {
this.nativeCommandsModule.finishPresentingNotification(notificationId, notificationCompletion);
}
finishHandlingAction(notificationId: string): void {
this.nativeCommandsModule.finishHandlingAction(notificationId);
}
}
import { NativeModules, NativeEventEmitter, EventEmitter, EmitterSubscription } from 'react-native';
import {
NotificationRegisteredEvent, NotificationReceived
Registered, RegistrationError, RegisteredPushKit, NotificationResponse
} from '../interfaces/NotificationEvents';
import { Notification } from '../interfaces/Notification';
export class NativeEventsReceiver {
private emitter: EventEmitter;
......@@ -9,11 +10,27 @@ export class NativeEventsReceiver {
this.emitter = new NativeEventEmitter(NativeModules.RNEventEmitter);
}
public registerRemoteNotificationsRegistered(callback: (event: NotificationRegisteredEvent) => void): EmitterSubscription {
public registerRemoteNotificationsRegistered(callback: (event: Registered) => void): EmitterSubscription {
return this.emitter.addListener('remoteNotificationsRegistered', callback);
}
public registerRemoteNotificationReceived(callback: (event: NotificationReceived) => void): EmitterSubscription {
public registerPushKitRegistered(callback: (event: RegisteredPushKit) => void): EmitterSubscription {
return this.emitter.addListener('pushKitRegistered', callback);
}
public registerRemoteNotificationReceived(callback: (notification: Notification) => void): EmitterSubscription {
return this.emitter.addListener('notificationReceivedForeground', callback);
}
public registerPushKitNotificationReceived(callback: (event: object) => void): EmitterSubscription {
return this.emitter.addListener('notificationReceivedForeground', callback);
}
public registerRemoteNotificationOpened(callback: (response: NotificationResponse, completion: () => void) => void): EmitterSubscription {
return this.emitter.addListener('notificationOpened', callback);
}
public registerRemoteNotificationsRegistrationFailed(callback: (event: RegistrationError) => void): EmitterSubscription {
return this.emitter.addListener('remoteNotificationsRegistrationFailed', callback);
}
}
import * as _ from 'lodash';
import { mock, verify, instance, deepEqual, when, anything, anyString } from 'ts-mockito';
import { mock, verify, instance, when, anything, anyString } from 'ts-mockito';
import { Commands } from './Commands';
import { NativeCommandsSender } from '../adapters/NativeCommandsSender';
......@@ -28,7 +28,7 @@ describe('Commands', () => {
});
it('returns a promise with the initial notification', async () => {
const expectedNotification: Notification = {data: {}, alert: 'alert'};
const expectedNotification: Notification = {identifier: 'id', data: {}, alert: 'alert'};
when(mockedNativeCommandsSender.getInitialNotification()).thenResolve(
expectedNotification
);
......@@ -75,19 +75,19 @@ describe('Commands', () => {
describe('sendLocalNotification', () => {
it('sends to native', () => {
const notification: Notification = {data: {}, alert: 'alert'};
const notification: Notification = {identifier: 'id', alert: 'alert', data: {}};
uut.sendLocalNotification(notification);
verify(mockedNativeCommandsSender.sendLocalNotification(notification, anyString())).called();
});
it('generates unique identifier', () => {
const notification: Notification = {data: {}, alert: 'alert'};
const notification: Notification = {identifier: 'id', data: {}, alert: 'alert'};
uut.sendLocalNotification(notification);
verify(mockedNativeCommandsSender.sendLocalNotification(notification, `Notification_+UNIQUE_ID`)).called();
});
it('use passed notification id', () => {
const notification: Notification = {data: {}, alert: 'alert'};
const notification: Notification = {identifier: 'id', data: {}, alert: 'alert'};
const passedId: string = "passedId";
uut.sendLocalNotification(notification, passedId);
verify(mockedNativeCommandsSender.sendLocalNotification(notification, passedId)).called();
......
......@@ -15,7 +15,7 @@ export class Commands {
return result;
}
public getInitialNotification() {
public getInitialNotification(): Promise<Notification> {
const result = this.nativeCommandsSender.getInitialNotification();
return result;
}
......
import { EventsRegistry } from './EventsRegistry';
import { NativeEventsReceiver } from '../adapters/NativeEventsReceiver.mock';
import { NotificationCompletion, Notification } from '../interfaces/Notification';
import { CompletionCallbackWrapper } from '../adapters/CompletionCallbackWrapper';
import { NativeCommandsSender } from '../adapters/NativeCommandsSender.mock';
import { NotificationResponse } from '../interfaces/NotificationEvents';
describe('EventsRegistry', () => {
let uut: EventsRegistry;
const mockNativeEventsReceiver = new NativeEventsReceiver();
const mockNativeCommandsSender = new NativeCommandsSender();
const completionCallbackWrapper = new CompletionCallbackWrapper(mockNativeCommandsSender);
beforeEach(() => {
uut = new EventsRegistry(mockNativeEventsReceiver, completionCallbackWrapper);
});
describe('registerRemoteNotificationsReceived', () => {
it('delegates to nativeEventsReceiver', () => {
const cb = jest.fn();
uut.registerNotificationReceived(cb);
expect(mockNativeEventsReceiver.registerRemoteNotificationReceived).toHaveBeenCalledTimes(1);
expect(mockNativeEventsReceiver.registerRemoteNotificationReceived).toHaveBeenCalledWith(expect.any(Function));
});
it('should wrap callback with completion block', () => {
const wrappedCallback = jest.fn();
const notification: Notification = {identifier: 'identifier', data: {}, alert: 'alert'}
uut.registerNotificationReceived(wrappedCallback);
const call = mockNativeEventsReceiver.registerRemoteNotificationReceived.mock.calls[0][0];
call(notification);
expect(wrappedCallback).toBeCalledWith(notification, expect.any(Function));
expect(wrappedCallback).toBeCalledTimes(1);
});
it('should wrap callback with completion block', () => {
const expectedNotification: Notification = {identifier: 'identifier', data: {}, alert: 'alert'}
uut.registerNotificationReceived((notification) => {
expect(notification).toEqual(expectedNotification);
});
const call = mockNativeEventsReceiver.registerRemoteNotificationReceived.mock.calls[0][0];
call(expectedNotification);
});
it('calling completion should invoke finishPresentingNotification', () => {
const notification: Notification = {identifier: 'notificationId', data: {}, alert: 'alert'}
const response: NotificationCompletion = {alert: true}
uut.registerNotificationReceived((notification, completion) => {
completion(response);
expect(mockNativeCommandsSender.finishPresentingNotification).toBeCalledWith(notification.identifier, response);
});
const call = mockNativeEventsReceiver.registerRemoteNotificationReceived.mock.calls[0][0];
call(notification);
});
});
describe('', () => {
it('delegates to nativeEventsReceiver', () => {
const cb = jest.fn();
uut.registerRemoteNotificationOpened(cb);
expect(mockNativeEventsReceiver.registerRemoteNotificationOpened).toHaveBeenCalledTimes(1);
expect(mockNativeEventsReceiver.registerRemoteNotificationOpened).toHaveBeenCalledWith(expect.any(Function));
});
it('should wrap callback with completion block', () => {
const wrappedCallback = jest.fn();
const notification: Notification = {identifier: 'identifier', data: {}, alert: 'alert'};
const response: NotificationResponse = {notification, identifier: 'responseId'};
uut.registerRemoteNotificationOpened(wrappedCallback);
const call = mockNativeEventsReceiver.registerRemoteNotificationOpened.mock.calls[0][0];
call(response);
expect(wrappedCallback).toBeCalledWith(response, expect.any(Function));
expect(wrappedCallback).toBeCalledTimes(1);
});
it('should wrap callback with completion block', () => {
const notification: Notification = {identifier: 'identifier', data: {}, alert: 'alert'}
const expectedResponse: NotificationResponse = {notification, identifier: 'responseId'}
uut.registerRemoteNotificationOpened((response) => {
expect(response).toEqual(expectedResponse);
});
const call = mockNativeEventsReceiver.registerRemoteNotificationOpened.mock.calls[0][0];
call(expectedResponse);
});
it('calling completion should invoke finishHandlingAction', () => {
const notification: Notification = {identifier: 'notificationId', data: {}, alert: 'alert'}
const expectedResponse: NotificationResponse = {identifier: 'responseId', notification};
uut.registerRemoteNotificationOpened((response, completion) => {
completion();
expect(response).toEqual(expectedResponse);
expect(mockNativeCommandsSender.finishHandlingAction).toBeCalledWith(notification.identifier);
});
const call = mockNativeEventsReceiver.registerRemoteNotificationOpened.mock.calls[0][0];
call(expectedResponse);
});
});
it('delegates registerRemoteNotificationsRegistered to nativeEventsReceiver', () => {
const cb = jest.fn();
uut.registerRemoteNotificationsRegistered(cb);
expect(mockNativeEventsReceiver.registerRemoteNotificationsRegistered).toHaveBeenCalledTimes(1);
expect(mockNativeEventsReceiver.registerRemoteNotificationsRegistered).toHaveBeenCalledWith(cb);
});
it('delegates registerPushKitRegistered to nativeEventsReceiver', () => {
const cb = jest.fn();
uut.registerPushKitRegistered(cb);
expect(mockNativeEventsReceiver.registerPushKitRegistered).toHaveBeenCalledTimes(1);
expect(mockNativeEventsReceiver.registerPushKitRegistered).toHaveBeenCalledWith(cb);
});
it('delegates registerPushKitNotificationReceived to nativeEventsReceiver', () => {
const cb = jest.fn();
uut.registerPushKitNotificationReceived(cb);
expect(mockNativeEventsReceiver.registerPushKitNotificationReceived).toHaveBeenCalledTimes(1);
expect(mockNativeEventsReceiver.registerPushKitNotificationReceived).toHaveBeenCalledWith(cb);
});
it('delegates registerRemoteNotificationsRegistrationFailed to nativeEventsReceiver', () => {
const cb = jest.fn();
uut.registerRemoteNotificationsRegistrationFailed(cb);
expect(mockNativeEventsReceiver.registerRemoteNotificationsRegistrationFailed).toHaveBeenCalledTimes(1);
expect(mockNativeEventsReceiver.registerRemoteNotificationsRegistrationFailed).toHaveBeenCalledWith(cb);
});
});
import { EventsRegistry } from './EventsRegistry';
import { NativeEventsReceiver } from '../adapters/NativeEventsReceiver.mock';
describe('EventsRegistry', () => {
let uut: EventsRegistry;
const mockNativeEventsReceiver = new NativeEventsReceiver();
beforeEach(() => {
uut = new EventsRegistry(mockNativeEventsReceiver);
});
it('delegates registerRemoteNotificationsRegistered to nativeEventsReceiver', () => {
const cb = jest.fn();
uut.registerRemoteNotificationsRegistered(cb);
expect(mockNativeEventsReceiver.registerRemoteNotificationsRegistered).toHaveBeenCalledTimes(1);
expect(mockNativeEventsReceiver.registerRemoteNotificationsRegistered).toHaveBeenCalledWith(cb);
});
it('delegates registerRemoteNotificationsReceived to nativeEventsReceiver', () => {
const cb = jest.fn();
uut.registerNotificationReceived(cb);
expect(mockNativeEventsReceiver.registerRemoteNotificationReceived).toHaveBeenCalledTimes(1);
expect(mockNativeEventsReceiver.registerRemoteNotificationReceived).toHaveBeenCalledWith(cb);
});
});
import { EmitterSubscription } from 'react-native';
import { NativeEventsReceiver } from '../adapters/NativeEventsReceiver';
import {
NotificationRegisteredEvent,
NotificationReceived
Registered,
RegistrationError,
RegisteredPushKit,
NotificationResponse
} from '../interfaces/NotificationEvents';
import { CompletionCallbackWrapper } from '../adapters/CompletionCallbackWrapper';
import { NotificationCompletion, Notification } from '../interfaces/Notification';
export class EventsRegistry {
constructor(private nativeEventsReceiver: NativeEventsReceiver) { }
constructor(
private nativeEventsReceiver: NativeEventsReceiver,
private completionCallbackWrapper: CompletionCallbackWrapper)
{}
public registerRemoteNotificationsRegistered(callback: (event: NotificationRegisteredEvent) => void): EmitterSubscription {
public registerRemoteNotificationsRegistered(callback: (event: Registered) => void): EmitterSubscription {
return this.nativeEventsReceiver.registerRemoteNotificationsRegistered(callback);
}
public registerNotificationReceived(callback: (event: NotificationReceived) => void): EmitterSubscription {
return this.nativeEventsReceiver.registerRemoteNotificationReceived(callback);
public registerPushKitRegistered(callback: (event: RegisteredPushKit) => void): EmitterSubscription {
return this.nativeEventsReceiver.registerPushKitRegistered(callback);
}
public registerNotificationReceived(callback: (notification: Notification, completion: (response: NotificationCompletion) => void) => void): EmitterSubscription {
return this.nativeEventsReceiver.registerRemoteNotificationReceived(this.completionCallbackWrapper.wrapReceivedCallback(callback));
}
public registerPushKitNotificationReceived(callback: (event: object) => void): EmitterSubscription {
return this.nativeEventsReceiver.registerPushKitNotificationReceived(callback);
}
public registerRemoteNotificationOpened(callback: (response: NotificationResponse, completion: () => void) => void): EmitterSubscription {
return this.nativeEventsReceiver.registerRemoteNotificationOpened(this.completionCallbackWrapper.wrapOpenedCallback(callback));
}
public registerRemoteNotificationsRegistrationFailed(callback: (event: RegistrationError) => void): EmitterSubscription {
return this.nativeEventsReceiver.registerRemoteNotificationsRegistrationFailed(callback);
}
}
export interface Notification {
identifier: string;
data: object;
alert: string
sound?: string;
......@@ -31,3 +32,14 @@ export interface NotificationAction {
authenticationRequired: boolean;
textInput: NotificationTextInput
}
export interface NotificationActionResponse {
identifier: string;
text: string;
}
export interface NotificationCompletion {
badge?: boolean;
alert?: boolean;
sound?: boolean;
}
import { Notification } from './Notification';
import { Notification, NotificationActionResponse } from './Notification';
export interface NotificationRegisteredEvent {
export interface Registered {
deviceToken: string;
}
export interface NotificationReceived {
export interface RegistrationError {
code: string;
domain: string;
localizedDescription: string;
}
export interface RegisteredPushKit {
pushKitToken: string;
}
export interface NotificationResponse {
identifier: string;
notification: Notification;
action?: NotificationActionResponse
}
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