Daniel Zlotin 7 anni fa
parent
commit
07a66e5db9

+ 5
- 0
playground/e2e/app.test.js Vedi File

@@ -38,6 +38,11 @@ describe('app', () => {
38 38
     elementByLabel('Pop').tap();
39 39
     expect(elementByLabel('React Native Navigation!')).toBeVisible();
40 40
   });
41
+
42
+  it('show modal', () => {
43
+    elementByLabel('Show Modal').tap();
44
+    expect(elementByLabel('Modal screen')).toBeVisible();
45
+  });
41 46
 });
42 47
 
43 48
 function elementByLabel(label) {

+ 10
- 0
playground/src/containers/WelcomeScreen.js Vedi File

@@ -17,6 +17,7 @@ class WelcomeScreen extends Component {
17 17
         <Button title="Switch to app with side menus" onPress={this.onClickSwitchToSideMenus} />
18 18
         <Button title="Switch to lifecycle screen" onPress={this.onClickLifecycleScreen} />
19 19
         <Button title="Push" onPress={this.onClickPush} />
20
+        <Button title="Show Modal" onPress={this.onClickShowModal} />
20 21
         <Text style={styles.footer}>{`this.props.id = ${this.props.id}`}</Text>
21 22
       </View>
22 23
     );
@@ -102,6 +103,15 @@ class WelcomeScreen extends Component {
102 103
       }
103 104
     });
104 105
   }
106
+
107
+  onClickShowModal() {
108
+    Navigation.showModal({
109
+      name: 'navigation.playground.SimpleScreen',
110
+      passProps: {
111
+        text: 'Modal screen'
112
+      }
113
+    });
114
+  }
105 115
 }
106 116
 
107 117
 export default WelcomeScreen;

+ 4
- 0
src/Navigation.js Vedi File

@@ -34,6 +34,10 @@ class Navigation {
34 34
     return this.appCommands.setRoot(params);
35 35
   }
36 36
 
37
+  showModal(params) {
38
+    return this.appCommands.showModal(params);
39
+  }
40
+
37 41
   events() {
38 42
     return this.publicEventsRegistry;
39 43
   }

+ 9
- 0
src/Navigation.test.js Vedi File

@@ -30,6 +30,15 @@ describe('Navigation', () => {
30 30
     expect(Navigation.appCommands.setRoot).toHaveBeenCalledWith(params);
31 31
   });
32 32
 
33
+  it('showModal delegates to AppCommands', async () => {
34
+    Navigation.appCommands.showModal.mockReturnValue(Promise.resolve('result'));
35
+    const params = {};
36
+    const result = await Navigation.showModal(params);
37
+    expect(result).toEqual('result');
38
+    expect(Navigation.appCommands.showModal).toHaveBeenCalledTimes(1);
39
+    expect(Navigation.appCommands.showModal).toHaveBeenCalledWith(params);
40
+  });
41
+
33 42
   it('events return public events', () => {
34 43
     const cb = jest.fn();
35 44
     Navigation.events().onAppLaunched(cb);

+ 5
- 0
src/adapters/NativeCommandsSender.js Vedi File

@@ -19,5 +19,10 @@ export default class NativeCommandsSender {
19 19
     this.nativeCommandsModule.pop(containerId);
20 20
     return Promise.resolve(containerId);
21 21
   }
22
+
23
+  showModal(layout) {
24
+    this.nativeCommandsModule.showModal(layout);
25
+    return Promise.resolve(layout);
26
+  }
22 27
 }
23 28
 

+ 8
- 1
src/adapters/NativeCommandsSender.test.js Vedi File

@@ -8,7 +8,8 @@ describe('NativeCommandsSender', () => {
8 8
     mockNativeModule = {
9 9
       setRoot: jest.fn(),
10 10
       push: jest.fn(),
11
-      pop: jest.fn()
11
+      pop: jest.fn(),
12
+      showModal: jest.fn()
12 13
     };
13 14
     NativeModules.RNNBridgeModule = mockNativeModule;
14 15
     uut = new NativeCommandsSender();
@@ -36,4 +37,10 @@ describe('NativeCommandsSender', () => {
36 37
     expect(mockNativeModule.pop).toHaveBeenCalledTimes(1);
37 38
     expect(result).toBeDefined();
38 39
   });
40
+
41
+  it('showModal sends to native', async () => {
42
+    const result = await uut.showModal({});
43
+    expect(mockNativeModule.showModal).toHaveBeenCalledTimes(1);
44
+    expect(result).toBeDefined();
45
+  });
39 46
 });

+ 7
- 0
src/commands/AppCommands.js Vedi File

@@ -13,5 +13,12 @@ export default class AppCommands {
13 13
     this.layoutTreeCrawler.crawl(layout);
14 14
     return this.nativeCommandsSender.setRoot(layout);
15 15
   }
16
+
17
+  showModal(simpleApi) {
18
+    const input = _.cloneDeep(simpleApi);
19
+    const layout = this.layoutTreeParser.createContainer(input);
20
+    this.layoutTreeCrawler.crawl(layout);
21
+    return this.nativeCommandsSender.showModal(layout);
22
+  }
16 23
 }
17 24
 

+ 39
- 0
src/commands/AppCommands.test.js Vedi File

@@ -62,4 +62,43 @@ describe('AppCommands', () => {
62 62
       expect(result).toEqual('the resolved layout');
63 63
     });
64 64
   });
65
+
66
+
67
+  describe('showModal', () => {
68
+    it('sends command to native after parsing into a correct layout tree', () => {
69
+      uut.showModal({
70
+        name: 'com.example.MyScreen'
71
+      });
72
+      expect(mockCommandsSender.showModal).toHaveBeenCalledTimes(1);
73
+      expect(mockCommandsSender.showModal).toHaveBeenCalledWith({
74
+        type: 'Container',
75
+        id: 'Container+UNIQUE_ID',
76
+        children: [],
77
+        data: {
78
+          name: 'com.example.MyScreen'
79
+        }
80
+      });
81
+    });
82
+
83
+    it('deep clones input to avoid mutation errors', () => {
84
+      const obj = {};
85
+      uut.showModal({ inner: obj });
86
+      expect(mockCommandsSender.showModal.mock.calls[0][0].data.inner).not.toBe(obj);
87
+    });
88
+
89
+    it('passProps into containers', () => {
90
+      expect(store.getPropsForContainerId('Container+UNIQUE_ID')).toEqual({});
91
+      uut.showModal({
92
+        name: 'com.example.MyScreen',
93
+        passProps: SimpleLayouts.passProps
94
+      });
95
+      expect(store.getPropsForContainerId('Container+UNIQUE_ID')).toEqual(SimpleLayouts.passProps);
96
+    });
97
+
98
+    it('returns a promise with the resolved layout', async () => {
99
+      mockCommandsSender.showModal.mockReturnValue(Promise.resolve('the resolved layout'));
100
+      const result = await uut.showModal({ container: { name: 'com.example.MyScreen' } });
101
+      expect(result).toEqual('the resolved layout');
102
+    });
103
+  });
65 104
 });