瀏覽代碼

BREAKING events api

Daniel Zlotin 6 年之前
父節點
當前提交
104e3f97fd

+ 8
- 8
lib/src/adapters/NativeEventsReceiver.ts 查看文件

@@ -7,23 +7,23 @@ export class NativeEventsReceiver {
7 7
     this.emitter = new NativeEventEmitter(NativeModules.RNNEventEmitter);
8 8
   }
9 9
 
10
-  registerOnAppLaunched(callback: () => void): EventSubscription {
11
-    return this.emitter.addListener('RNN.onAppLaunched', callback);
10
+  public registerAppLaunchedListener(callback: () => void): EventSubscription {
11
+    return this.emitter.addListener('RNN.appLaunched', callback);
12 12
   }
13 13
 
14
-  registerComponentDidAppear(callback: (params) => void): EventSubscription {
14
+  public registerComponentDidAppearListener(callback: (data) => void): EventSubscription {
15 15
     return this.emitter.addListener('RNN.componentDidAppear', callback);
16 16
   }
17 17
 
18
-  registerComponentDidDisappear(callback: (params) => void): EventSubscription {
18
+  public registerComponentDidDisappearListener(callback: (data) => void): EventSubscription {
19 19
     return this.emitter.addListener('RNN.componentDidDisappear', callback);
20 20
   }
21 21
 
22
-  registerOnNavigationButtonPressed(callback: (params) => void): EventSubscription {
23
-    return this.emitter.addListener('RNN.onNavigationButtonPressed', callback);
22
+  public registerCommandCompletedListener(callback: (data) => void): EventSubscription {
23
+    return this.emitter.addListener('RNN.commandCompleted', callback);
24 24
   }
25 25
 
26
-  public registerOnNavigationEvent(callback: (params) => void): EventSubscription {
27
-    return this.emitter.addListener('RNN.onNavigationEvent', callback);
26
+  public registerNativeEventListener(callback: (data) => void): EventSubscription {
27
+    return this.emitter.addListener('RNN.nativeEvent', callback);
28 28
   }
29 29
 }

+ 35
- 20
lib/src/events/ComponentEventsObserver.test.ts 查看文件

@@ -1,7 +1,7 @@
1 1
 import { ComponentEventsObserver } from './ComponentEventsObserver';
2 2
 import { Store } from '../components/Store';
3 3
 
4
-describe(`ComponentEventRegistry`, () => {
4
+describe(`ComponentEventsObserver`, () => {
5 5
   let uut: ComponentEventsObserver;
6 6
   let eventRegistry;
7 7
   let store: Store;
@@ -10,9 +10,9 @@ describe(`ComponentEventRegistry`, () => {
10 10
 
11 11
   beforeEach(() => {
12 12
     eventRegistry = {
13
-      componentDidAppear: jest.fn(),
14
-      componentDidDisappear: jest.fn(),
15
-      onNavigationButtonPressed: jest.fn()
13
+      registerComponentDidAppearListener: jest.fn(),
14
+      registerComponentDidDisappearListener: jest.fn(),
15
+      registerNativeEventListener: jest.fn()
16 16
     };
17 17
 
18 18
     mockComponentRef = {
@@ -28,13 +28,13 @@ describe(`ComponentEventRegistry`, () => {
28 28
   });
29 29
 
30 30
   it('register for lifecycle events on eventRegistry', () => {
31
-    expect(eventRegistry.componentDidAppear).toHaveBeenCalledTimes(0);
32
-    expect(eventRegistry.componentDidDisappear).toHaveBeenCalledTimes(0);
33
-    expect(eventRegistry.onNavigationButtonPressed).toHaveBeenCalledTimes(0);
31
+    expect(eventRegistry.registerComponentDidAppearListener).toHaveBeenCalledTimes(0);
32
+    expect(eventRegistry.registerComponentDidDisappearListener).toHaveBeenCalledTimes(0);
33
+    expect(eventRegistry.registerNativeEventListener).toHaveBeenCalledTimes(0);
34 34
     uut.registerForAllComponents();
35
-    expect(eventRegistry.componentDidAppear).toHaveBeenCalledTimes(1);
36
-    expect(eventRegistry.componentDidDisappear).toHaveBeenCalledTimes(1);
37
-    expect(eventRegistry.onNavigationButtonPressed).toHaveBeenCalledTimes(1);
35
+    expect(eventRegistry.registerComponentDidAppearListener).toHaveBeenCalledTimes(1);
36
+    expect(eventRegistry.registerComponentDidDisappearListener).toHaveBeenCalledTimes(1);
37
+    expect(eventRegistry.registerNativeEventListener).toHaveBeenCalledTimes(1);
38 38
   });
39 39
 
40 40
   it('bubbles lifecycle to component from store', () => {
@@ -43,21 +43,36 @@ describe(`ComponentEventRegistry`, () => {
43 43
     expect(mockComponentRef.componentDidDisappear).toHaveBeenCalledTimes(0);
44 44
     expect(mockComponentRef.onNavigationButtonPressed).toHaveBeenCalledTimes(0);
45 45
     uut.registerForAllComponents();
46
-    eventRegistry.componentDidAppear.mock.calls[0][0](refId);
47
-    eventRegistry.componentDidDisappear.mock.calls[0][0](refId);
48
-    eventRegistry.onNavigationButtonPressed.mock.calls[0][0](refId, params);
46
+    eventRegistry.registerComponentDidAppearListener.mock.calls[0][0](refId);
47
+    eventRegistry.registerComponentDidDisappearListener.mock.calls[0][0](refId);
48
+    eventRegistry.registerNativeEventListener.mock.calls[0][0](refId, params);
49 49
     expect(mockComponentRef.componentDidAppear).toHaveBeenCalledTimes(1);
50 50
     expect(mockComponentRef.componentDidDisappear).toHaveBeenCalledTimes(1);
51
+    expect(mockComponentRef.onNavigationButtonPressed).toHaveBeenCalledTimes(0);
52
+  });
53
+
54
+  it('bubbles onNavigationButtonPressed to component by id', () => {
55
+    const params = {
56
+      componentId: refId,
57
+      buttonId: 'theButtonId'
58
+    };
59
+    expect(mockComponentRef.onNavigationButtonPressed).toHaveBeenCalledTimes(0);
60
+    uut.registerForAllComponents();
61
+
62
+    eventRegistry.registerNativeEventListener.mock.calls[0][0]('some other event name', params);
63
+    expect(mockComponentRef.onNavigationButtonPressed).toHaveBeenCalledTimes(0);
64
+
65
+    eventRegistry.registerNativeEventListener.mock.calls[0][0]('buttonPressed', params);
51 66
     expect(mockComponentRef.onNavigationButtonPressed).toHaveBeenCalledTimes(1);
52
-    expect(mockComponentRef.onNavigationButtonPressed).toHaveBeenCalledWith(params);
67
+    expect(mockComponentRef.onNavigationButtonPressed).toHaveBeenCalledWith('theButtonId');
53 68
   });
54 69
 
55 70
   it('defensive unknown id', () => {
56 71
     uut.registerForAllComponents();
57 72
     expect(() => {
58
-      eventRegistry.componentDidAppear.mock.calls[0][0]('bad id');
59
-      eventRegistry.componentDidDisappear.mock.calls[0][0]('bad id');
60
-      eventRegistry.onNavigationButtonPressed.mock.calls[0][0]('bad id', {});
73
+      eventRegistry.registerComponentDidAppearListener.mock.calls[0][0]('bad id');
74
+      eventRegistry.registerComponentDidDisappearListener.mock.calls[0][0]('bad id');
75
+      eventRegistry.registerNativeEventListener.mock.calls[0][0]('buttonPressed', { componentId: 'bad id' });
61 76
     }).not.toThrow();
62 77
   });
63 78
 
@@ -65,9 +80,9 @@ describe(`ComponentEventRegistry`, () => {
65 80
     store.setRefForId('myId', {});
66 81
     uut.registerForAllComponents();
67 82
     expect(() => {
68
-      eventRegistry.componentDidAppear.mock.calls[0][0]('myId');
69
-      eventRegistry.componentDidDisappear.mock.calls[0][0]('myId');
70
-      eventRegistry.onNavigationButtonPressed.mock.calls[0][0]('myId', {});
83
+      eventRegistry.registerComponentDidAppearListener.mock.calls[0][0]('myId');
84
+      eventRegistry.registerComponentDidDisappearListener.mock.calls[0][0]('myId');
85
+      eventRegistry.registerNativeEventListener.mock.calls[0][0]('bad event name', {});
71 86
     }).not.toThrow();
72 87
   });
73 88
 });

+ 12
- 8
lib/src/events/ComponentEventsObserver.ts 查看文件

@@ -1,17 +1,19 @@
1 1
 import { EventsRegistry } from './EventsRegistry';
2 2
 import { Store } from '../components/Store';
3 3
 
4
+const BUTTON_PRESSED_EVENT_NAME = 'buttonPressed';
5
+
4 6
 export class ComponentEventsObserver {
5 7
   constructor(private eventsRegistry: EventsRegistry, private store: Store) {
6 8
     this.componentDidAppear = this.componentDidAppear.bind(this);
7 9
     this.componentDidDisappear = this.componentDidDisappear.bind(this);
8
-    this.onNavigationButtonPressed = this.onNavigationButtonPressed.bind(this);
10
+    this.onNativeEvent = this.onNativeEvent.bind(this);
9 11
   }
10 12
 
11 13
   public registerForAllComponents(): void {
12
-    this.eventsRegistry.componentDidAppear(this.componentDidAppear);
13
-    this.eventsRegistry.componentDidDisappear(this.componentDidDisappear);
14
-    this.eventsRegistry.onNavigationButtonPressed(this.onNavigationButtonPressed);
14
+    this.eventsRegistry.registerComponentDidAppearListener(this.componentDidAppear);
15
+    this.eventsRegistry.registerComponentDidDisappearListener(this.componentDidDisappear);
16
+    this.eventsRegistry.registerNativeEventListener(this.onNativeEvent);
15 17
   }
16 18
 
17 19
   private componentDidAppear(componentId: string) {
@@ -28,10 +30,12 @@ export class ComponentEventsObserver {
28 30
     }
29 31
   }
30 32
 
31
-  private onNavigationButtonPressed(componentId: string, buttonId: string) {
32
-    const componentRef = this.store.getRefForId(componentId);
33
-    if (componentRef && componentRef.onNavigationButtonPressed) {
34
-      componentRef.onNavigationButtonPressed(buttonId);
33
+  private onNativeEvent(name: string, params: any) {
34
+    if (name === BUTTON_PRESSED_EVENT_NAME) {
35
+      const componentRef = this.store.getRefForId(params.componentId);
36
+      if (componentRef && componentRef.onNavigationButtonPressed) {
37
+        componentRef.onNavigationButtonPressed(params.buttonId);
38
+      }
35 39
     }
36 40
   }
37 41
 }

+ 32
- 40
lib/src/events/EventsRegistry.test.ts 查看文件

@@ -12,96 +12,88 @@ describe('EventsRegistry', () => {
12 12
     uut = new EventsRegistry(mockNativeEventsReceiver, commandsObserver);
13 13
   });
14 14
 
15
-  it('exposes onAppLaunched event', () => {
15
+  it('exposes appLaunched event', () => {
16 16
     const subscription = {};
17 17
     const cb = jest.fn();
18
-    mockNativeEventsReceiver.registerOnAppLaunched.mockReturnValueOnce(subscription);
18
+    mockNativeEventsReceiver.registerAppLaunchedListener.mockReturnValueOnce(subscription);
19 19
 
20
-    const result = uut.onAppLaunched(cb);
20
+    const result = uut.registerAppLaunchedListener(cb);
21 21
 
22 22
     expect(result).toBe(subscription);
23
-    expect(mockNativeEventsReceiver.registerOnAppLaunched).toHaveBeenCalledTimes(1);
24
-    expect(mockNativeEventsReceiver.registerOnAppLaunched).toHaveBeenCalledWith(cb);
23
+    expect(mockNativeEventsReceiver.registerAppLaunchedListener).toHaveBeenCalledTimes(1);
24
+    expect(mockNativeEventsReceiver.registerAppLaunchedListener).toHaveBeenCalledWith(cb);
25 25
   });
26 26
 
27 27
   it('exposes componentDidAppear event', () => {
28 28
     const subscription = {};
29 29
     const cb = jest.fn();
30
-    mockNativeEventsReceiver.registerComponentDidAppear.mockReturnValueOnce(subscription);
30
+    mockNativeEventsReceiver.registerComponentDidAppearListener.mockReturnValueOnce(subscription);
31 31
 
32
-    const result = uut.componentDidAppear(cb);
32
+    const result = uut.registerComponentDidAppearListener(cb);
33 33
 
34 34
     expect(result).toBe(subscription);
35
-    expect(mockNativeEventsReceiver.registerComponentDidAppear).toHaveBeenCalledTimes(1);
35
+    expect(mockNativeEventsReceiver.registerComponentDidAppearListener).toHaveBeenCalledTimes(1);
36 36
 
37
-    mockNativeEventsReceiver.registerComponentDidAppear.mock.calls[0][0]({ componentId: 'theId', componentName: 'theName' });
37
+    mockNativeEventsReceiver.registerComponentDidAppearListener.mock.calls[0][0]({ componentId: 'theId', componentName: 'theName' });
38 38
     expect(cb).toHaveBeenCalledWith('theId', 'theName');
39 39
   });
40 40
 
41 41
   it('exposes componentDidDisappear event', () => {
42 42
     const subscription = {};
43 43
     const cb = jest.fn();
44
-    mockNativeEventsReceiver.registerComponentDidDisappear.mockReturnValueOnce(subscription);
44
+    mockNativeEventsReceiver.registerComponentDidDisappearListener.mockReturnValueOnce(subscription);
45 45
 
46
-    const result = uut.componentDidDisappear(cb);
46
+    const result = uut.registerComponentDidDisappearListener(cb);
47 47
 
48 48
     expect(result).toBe(subscription);
49
-    expect(mockNativeEventsReceiver.registerComponentDidDisappear).toHaveBeenCalledTimes(1);
49
+    expect(mockNativeEventsReceiver.registerComponentDidDisappearListener).toHaveBeenCalledTimes(1);
50 50
 
51
-    mockNativeEventsReceiver.registerComponentDidDisappear.mock.calls[0][0]({ componentId: 'theId', componentName: 'theName' });
51
+    mockNativeEventsReceiver.registerComponentDidDisappearListener.mock.calls[0][0]({ componentId: 'theId', componentName: 'theName' });
52 52
     expect(cb).toHaveBeenCalledWith('theId', 'theName');
53 53
   });
54 54
 
55
-  it('exposes onNavigationButtonPressed event', () => {
56
-    const subscription = {};
55
+  it('exposes registerCommandListener registers listener to commandObserver', () => {
57 56
     const cb = jest.fn();
58
-    mockNativeEventsReceiver.registerOnNavigationButtonPressed.mockReturnValueOnce(subscription);
59
-
60
-    const result = uut.onNavigationButtonPressed(cb);
61
-
62
-    expect(result).toBe(subscription);
63
-    expect(mockNativeEventsReceiver.registerOnNavigationButtonPressed).toHaveBeenCalledTimes(1);
64
-
65
-    mockNativeEventsReceiver.registerOnNavigationButtonPressed.mock.calls[0][0]({ componentId: 'theId', buttonId: 'theBtnId' });
66
-    expect(cb).toHaveBeenCalledWith('theId', 'theBtnId');
67
-  });
68
-
69
-  it('exposes onNavigationCommand registers listener to commandObserver', () => {
70
-    const cb = jest.fn();
71
-    const result = uut.onNavigationCommand(cb);
57
+    const result = uut.registerCommandListener(cb);
72 58
     expect(result).toBeDefined();
73 59
     commandsObserver.notify('theCommandName', { x: 1 });
74 60
     expect(cb).toHaveBeenCalledTimes(1);
75 61
     expect(cb).toHaveBeenCalledWith('theCommandName', { x: 1 });
76 62
   });
77 63
 
78
-  it('onNavigationCommand unregister', () => {
64
+  it('registerCommandListener unregister', () => {
79 65
     const cb = jest.fn();
80
-    const result = uut.onNavigationCommand(cb);
66
+    const result = uut.registerCommandListener(cb);
81 67
     result.remove();
82 68
     commandsObserver.notify('theCommandName', { x: 1 });
83 69
     expect(cb).not.toHaveBeenCalled();
84 70
   });
85 71
 
86
-  it('onNavigationEvent', () => {
72
+  it('registerCommandCompletedListener', () => {
87 73
     const subscription = {};
88 74
     const cb = jest.fn();
89
-    mockNativeEventsReceiver.registerOnNavigationEvent.mockReturnValueOnce(subscription);
75
+    mockNativeEventsReceiver.registerCommandCompletedListener.mockReturnValueOnce(subscription);
90 76
 
91
-    const result = uut.onNavigationEvent(cb);
77
+    const result = uut.registerCommandCompletedListener(cb);
92 78
 
93 79
     expect(result).toBe(subscription);
94
-    expect(mockNativeEventsReceiver.registerOnNavigationEvent).toHaveBeenCalledTimes(1);
80
+    expect(mockNativeEventsReceiver.registerCommandCompletedListener).toHaveBeenCalledTimes(1);
95 81
 
96
-    mockNativeEventsReceiver.registerOnNavigationEvent.mock.calls[0][0]({ name: 'the event name', params: { a: 1 } });
97
-    expect(cb).toHaveBeenCalledWith('the event name', { a: 1 });
82
+    mockNativeEventsReceiver.registerCommandCompletedListener.mock.calls[0][0]({ commandId: 'theCommandId', completionTime: 12345, params: { a: 1 } });
83
+    expect(cb).toHaveBeenCalledWith('theCommandId', 12345, { a: 1 });
98 84
   });
99 85
 
100
-  it('onNavigationEvent unregister', () => {
86
+  it('registerNativeEventListener', () => {
101 87
     const subscription = {};
102 88
     const cb = jest.fn();
103
-    mockNativeEventsReceiver.registerOnNavigationEvent.mockReturnValueOnce(subscription);
104
-    const result = uut.onNavigationEvent(cb);
89
+    mockNativeEventsReceiver.registerNativeEventListener.mockReturnValueOnce(subscription);
90
+
91
+    const result = uut.registerNativeEventListener(cb);
92
+
105 93
     expect(result).toBe(subscription);
94
+    expect(mockNativeEventsReceiver.registerNativeEventListener).toHaveBeenCalledTimes(1);
95
+
96
+    mockNativeEventsReceiver.registerNativeEventListener.mock.calls[0][0]({ name: 'the event name', params: { a: 1 } });
97
+    expect(cb).toHaveBeenCalledWith('the event name', { a: 1 });
106 98
   });
107 99
 });

+ 12
- 12
lib/src/events/EventsRegistry.ts 查看文件

@@ -5,27 +5,27 @@ import { EventSubscription } from '../interfaces/EventSubscription';
5 5
 export class EventsRegistry {
6 6
   constructor(private nativeEventsReceiver: NativeEventsReceiver, private commandsObserver: CommandsObserver) { }
7 7
 
8
-  public onAppLaunched(callback: () => void): EventSubscription {
9
-    return this.nativeEventsReceiver.registerOnAppLaunched(callback);
8
+  public registerAppLaunchedListener(callback: () => void): EventSubscription {
9
+    return this.nativeEventsReceiver.registerAppLaunchedListener(callback);
10 10
   }
11 11
 
12
-  public componentDidAppear(callback: (componentId: string, componentName: string) => void): EventSubscription {
13
-    return this.nativeEventsReceiver.registerComponentDidAppear(({ componentId, componentName }) => callback(componentId, componentName));
12
+  public registerComponentDidAppearListener(callback: (componentId: string, componentName: string) => void): EventSubscription {
13
+    return this.nativeEventsReceiver.registerComponentDidAppearListener(({ componentId, componentName }) => callback(componentId, componentName));
14 14
   }
15 15
 
16
-  public componentDidDisappear(callback: (componentId: string, componentName: string) => void): EventSubscription {
17
-    return this.nativeEventsReceiver.registerComponentDidDisappear(({ componentId, componentName }) => callback(componentId, componentName));
16
+  public registerComponentDidDisappearListener(callback: (componentId: string, componentName: string) => void): EventSubscription {
17
+    return this.nativeEventsReceiver.registerComponentDidDisappearListener(({ componentId, componentName }) => callback(componentId, componentName));
18 18
   }
19 19
 
20
-  public onNavigationButtonPressed(callback: (componentId: string, buttonId: string) => void): EventSubscription {
21
-    return this.nativeEventsReceiver.registerOnNavigationButtonPressed(({ componentId, buttonId }) => callback(componentId, buttonId));
20
+  public registerCommandListener(callback: (name: string, params: any) => void): EventSubscription {
21
+    return this.commandsObserver.register(callback);
22 22
   }
23 23
 
24
-  public onNavigationCommand(callback: (name: string, params: any) => void): EventSubscription {
25
-    return this.commandsObserver.register(callback);
24
+  public registerCommandCompletedListener(callback: (commandId: string, completionTime: number, params: any) => void): EventSubscription {
25
+    return this.nativeEventsReceiver.registerCommandCompletedListener(({ commandId, completionTime, params }) => callback(commandId, completionTime, params));
26 26
   }
27 27
 
28
-  public onNavigationEvent(callback: (name: string, params: any) => void): EventSubscription {
29
-    return this.nativeEventsReceiver.registerOnNavigationEvent(({ name, params }) => callback(name, params));
28
+  public registerNativeEventListener(callback: (name: string, params: any) => void): EventSubscription {
29
+    return this.nativeEventsReceiver.registerNativeEventListener(({ name, params }) => callback(name, params));
30 30
   }
31 31
 }

+ 1
- 1
playground/src/screens/OptionsScreen.js 查看文件

@@ -103,7 +103,7 @@ class OptionsScreen extends Component {
103 103
   render() {
104 104
     return (
105 105
       <View style={styles.root}>
106
-        <View style={{width: 2, height: 2, backgroundColor: 'red', alignSelf: 'center'}}/>
106
+        <View style={{ width: 2, height: 2, backgroundColor: 'red', alignSelf: 'center' }} />
107 107
         <Text style={styles.h1} testID={testIDs.OPTIONS_SCREEN_HEADER}>{`Options Screen`}</Text>
108 108
         <Button title='Dynamic Options' testID={testIDs.DYNAMIC_OPTIONS_BUTTON} onPress={this.onClickDynamicOptions} />
109 109
         <Button title='Show Top Bar' testID={testIDs.SHOW_TOP_BAR_BUTTON} onPress={this.onClickShowTopBar} />