Browse Source

Add SplitView e2e tests (#6140)

* Add splitView layout screen to the playground app.
* Add splitView e2e tests.
Yogev Ben David 4 years ago
parent
commit
eb59eadac2
No account linked to committer's email address

+ 27
- 0
e2e/SplitView.test.js View File

@@ -0,0 +1,27 @@
1
+const Utils = require('./Utils');
2
+const TestIDs = require('../playground/src/testIDs');
3
+const cocktailsList = require('../playground/src/assets/cocktails').default;
4
+const { elementByLabel, elementById } = Utils;
5
+
6
+describe(':ios: SplitView', () => {
7
+  beforeEach(async () => {
8
+    await device.relaunchApp();
9
+    await elementById(TestIDs.SPLIT_VIEW_BUTTON).tap();
10
+  });
11
+
12
+  it('master screen updates details screen', async () => {
13
+    const secondCocktail = cocktailsList[1];
14
+    await elementById(secondCocktail.id).tap();
15
+    await expect(elementByLabel(secondCocktail.description)).toBeVisible();
16
+  });
17
+
18
+  it('push screen to master screen', async () => {
19
+    await elementById(TestIDs.PUSH_MASTER_BTN).tap();
20
+    await expect(elementByLabel('Pushed Screen')).toBeVisible();
21
+  });
22
+
23
+  it('push screen to detail screen', async () => {
24
+    await elementById(TestIDs.PUSH_DETAILS_BTN).tap();
25
+    await expect(elementByLabel('Pushed Screen')).toBeVisible();
26
+  });
27
+});

+ 4
- 1
e2e/config.json View File

@@ -2,5 +2,8 @@
2 2
   "setupTestFrameworkScriptFile" : "./init.js",
3 3
   "testEnvironment": "node",
4 4
   "bail": true,
5
-  "verbose": true
5
+  "verbose": true,
6
+  "moduleNameMapper": {
7
+    ".+\\.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)$": "identity-obj-proxy"
8
+  }
6 9
 }

+ 2
- 1
package.json View File

@@ -90,7 +90,8 @@
90 90
     "ts-node": "5.x.x",
91 91
     "tslint": "5.x.x",
92 92
     "typedoc": "0.x.x",
93
-    "typescript": "3.2.2"
93
+    "typescript": "3.2.2",
94
+    "identity-obj-proxy": "3.0.0"
94 95
   },
95 96
   "jest": {
96 97
     "preset": "react-native",

+ 14
- 8
playground/src/screens/LayoutsScreen.js View File

@@ -1,4 +1,5 @@
1 1
 const React = require('react');
2
+const { Platform } = require('react-native');
2 3
 const Root = require('../components/Root');
3 4
 const Button = require('../components/Button')
4 5
 const {
@@ -6,7 +7,8 @@ const {
6 7
   STACK_BTN,
7 8
   BOTTOM_TABS_BTN,
8 9
   BOTTOM_TABS,
9
-  SIDE_MENU_BTN
10
+  SIDE_MENU_BTN,
11
+  SPLIT_VIEW_BUTTON
10 12
 } = require('../testIDs');
11 13
 const Screens = require('./Screens');
12 14
 const Navigation = require('../services/Navigation');
@@ -30,6 +32,7 @@ class LayoutsScreen extends React.Component {
30 32
         <Button label='Stack' testID={STACK_BTN} onPress={this.stack} />
31 33
         <Button label='BottomTabs' testID={BOTTOM_TABS_BTN} onPress={this.bottomTabs} />
32 34
         <Button label='SideMenu' testID={SIDE_MENU_BTN} onPress={this.sideMenu} />
35
+        <Button label='SplitView' testID={SPLIT_VIEW_BUTTON} platform='ios' onPress={this.splitView} />
33 36
       </Root>
34 37
     );
35 38
   }
@@ -78,7 +81,7 @@ class LayoutsScreen extends React.Component {
78 81
     }
79 82
   });
80 83
 
81
-  onClickSplitView = () => {
84
+  splitView = () => {
82 85
     Navigation.setRoot({
83 86
       root: {
84 87
         splitView: {
@@ -89,7 +92,7 @@ class LayoutsScreen extends React.Component {
89 92
               children: [
90 93
                 {
91 94
                   component: {
92
-                    name: 'navigation.playground.WelcomeScreen'
95
+                    name: Screens.CocktailsListMasterScreen
93 96
                   },
94 97
                 },
95 98
               ]
@@ -101,17 +104,20 @@ class LayoutsScreen extends React.Component {
101 104
               children: [
102 105
                 {
103 106
                   component: {
104
-                    name: 'navigation.playground.WelcomeScreen'
107
+                    id: 'DETAILS_COMPONENT_ID',
108
+                    name: Screens.CocktailDetailsScreen
105 109
                   },
106 110
                 },
107 111
               ]
108 112
             }
109 113
           },
110 114
           options: {
111
-            displayMode: 'auto',
112
-            primaryEdge: 'leading',
113
-            minWidth: 150,
114
-            maxWidth: 300,
115
+            layout: {
116
+              orientation: ['landscape']
117
+            },
118
+            splitView: {
119
+              displayMode: 'visible'
120
+            }
115 121
           },
116 122
         },
117 123
       },

+ 1
- 0
playground/src/screens/Screens.js View File

@@ -9,6 +9,7 @@ module.exports = {
9 9
   Buttons: 'Buttons',
10 10
   CocktailDetailsScreen: 'CocktailDetailsScreen',
11 11
   CocktailsListScreen: 'CocktailsListScreen',
12
+  CocktailsListMasterScreen: 'CocktailsListMasterScreen',
12 13
   ContextScreen: 'ContextScreen',
13 14
   ExternalComponent: 'ExternalComponent',
14 15
   FullScreenModal: 'FullScreenModal',

+ 2
- 1
playground/src/screens/index.js View File

@@ -11,7 +11,8 @@ const Screens = require('./Screens');
11 11
 function registerScreens() {
12 12
   Navigation.registerComponent(Screens.Alert, () => require('./Alert'));
13 13
   Navigation.registerComponent(Screens.CocktailDetailsScreen, () => require('./sharedElementTransition/CocktailDetailsScreen'));
14
-  Navigation.registerComponent(Screens.CocktailsListScreen, () => require('./sharedElementTransition/CocktailsList'));
14
+  Navigation.registerComponent(Screens.CocktailsListScreen, () => require('./sharedElementTransition/CocktailsListScreen'));
15
+  Navigation.registerComponent(Screens.CocktailsListMasterScreen, () => require('./splitView/CocktailsListMasterScreen'));
15 16
   Navigation.registerComponent(Screens.EventsOverlay, () => require('./StaticLifecycleOverlay'));
16 17
   Navigation.registerComponent(Screens.EventsScreen, () => require('./StaticEventsScreen'));
17 18
   Navigation.registerComponent(Screens.ExternalComponent, () => require('./ExternalComponentScreen'));

+ 28
- 6
playground/src/screens/sharedElementTransition/CocktailDetailsScreen.js View File

@@ -1,5 +1,11 @@
1 1
 const React = require('react');
2
-const { Image, Platform, SafeAreaView, StyleSheet, Text, View } = require('react-native');
2
+const { Image, Platform, ScrollView, StyleSheet, Text, View } = require('react-native');
3
+const {
4
+  COCKTAILS_DETAILS_HEADER,
5
+  PUSH_DETAILS_BTN
6
+} = require('../../testIDs');
7
+const Screens = require('../Screens');
8
+const Navigation = require('../../services/Navigation');
3 9
 
4 10
 class CocktailDetailsScreen extends React.Component {
5 11
   static options() {
@@ -14,17 +20,33 @@ class CocktailDetailsScreen extends React.Component {
14 20
       }),
15 21
       topBar: {
16 22
         title: {
17
-          text: 'Cocktails'
18
-        }
23
+          text: 'Cocktail Details'
24
+        },
25
+        rightButtons: [{
26
+          id: 'pushDetails',
27
+          testID: PUSH_DETAILS_BTN,
28
+          text: 'push'
29
+        }]
19 30
       }
20 31
     }
21 32
   }
22 33
 
34
+  constructor(props) {
35
+    super(props);
36
+    Navigation.events().bindComponent(this);
37
+  }
38
+
39
+  navigationButtonPressed({buttonId}) {
40
+    if (buttonId === 'pushDetails') {
41
+      Navigation.push(this, Screens.Pushed)
42
+    }
43
+  }
44
+
23 45
   render() {
24 46
     return (
25
-      <SafeAreaView style={styles.root}>
47
+      <ScrollView style={styles.root}>
26 48
         <View nativeID={'backdrop'} style={[styles.backdrop, { backgroundColor: this.props.color }]}/> 
27
-        <View style={styles.header}>
49
+        <View style={styles.header} testID={COCKTAILS_DETAILS_HEADER}>
28 50
           <Image
29 51
             source={this.props.image}
30 52
             nativeID={`image${this.props.id}Dest`}
@@ -37,7 +59,7 @@ class CocktailDetailsScreen extends React.Component {
37 59
           style={styles.description}>
38 60
           {this.props.description}
39 61
         </Text>
40
-      </SafeAreaView >
62
+      </ScrollView >
41 63
     );
42 64
   }
43 65
 }

+ 0
- 165
playground/src/screens/sharedElementTransition/CocktailsList.js View File

@@ -1,165 +0,0 @@
1
-const React = require('react');
2
-const { Component } = require('react');
3
-const { TouchableOpacity, FlatList, View, Image, Text, Platform, StyleSheet } = require('react-native');
4
-const Navigation = require('../../services/Navigation');
5
-const { slice } = require('lodash');
6
-const Screens = require('../Screens')
7
-const data = require('../../assets/cocktails').default;
8
-const MULTIPLIER = 1.15
9
-const LONG_DURATION = 350 * MULTIPLIER
10
-const SHORT_DURATION = 190 * MULTIPLIER
11
-
12
-class CocktailsList extends Component {
13
-  static options() {
14
-    return {
15
-      ...Platform.select({
16
-        android: {
17
-          statusBar: {
18
-            style: 'dark',
19
-            backgroundColor: 'white'
20
-          }
21
-        }
22
-      }),
23
-      topBar: {
24
-        title: {
25
-          text: 'Cocktails'
26
-        }
27
-      }
28
-    }
29
-  }
30
-
31
-  render() {
32
-    return (
33
-      <FlatList
34
-        style={styles.root}
35
-        data={data}
36
-        keyExtractor={this.keyExtractor}
37
-        ItemSeparatorComponent={this.separatorComponent}
38
-        renderItem={this.renderItem}
39
-      />
40
-    );
41
-  }
42
-
43
-  separatorComponent = () => <View style={styles.separator} />;
44
-
45
-  renderItem = ({ item }) => (
46
-    <TouchableOpacity
47
-      activeOpacity={0.75}
48
-      style={styles.itemContainer}
49
-      onPress={() => Navigation.push(
50
-        this,
51
-        {
52
-          component: {
53
-            name: Screens.CocktailDetailsScreen,
54
-            passProps: { ...item },
55
-            options: {
56
-              animations: {
57
-                push: {
58
-                  content: {
59
-                    alpha: {
60
-                      from: 0,
61
-                      to: 1,
62
-                      duration: LONG_DURATION
63
-                    }
64
-                  },
65
-                  sharedElementTransitions: [
66
-                    {
67
-                      fromId: `image${item.id}`,
68
-                      toId: `image${item.id}Dest`,
69
-                      duration: LONG_DURATION
70
-                    },
71
-                    {
72
-                      fromId: `title${item.id}`,
73
-                      toId: `title${item.id}Dest`,
74
-                      duration: LONG_DURATION
75
-                    },
76
-                    {
77
-                      fromId: `backdrop${item.id}`,
78
-                      toId: 'backdrop',
79
-                      duration: LONG_DURATION
80
-                    }
81
-                  ],
82
-                  elementTransitions: [
83
-                    {
84
-                      id: 'description',
85
-                      alpha: {
86
-                        from: 0,
87
-                        duration: SHORT_DURATION
88
-                      },
89
-                      translationY: {
90
-                        from: 16,
91
-                        duration: SHORT_DURATION
92
-                      }
93
-                    }
94
-                  ]
95
-                }
96
-              }
97
-            }
98
-          }
99
-        }
100
-      )}>
101
-      <View style={styles.overlayContainer}>
102
-        <Image
103
-          source={item.image}
104
-          nativeID={`image${item.id}`}
105
-          style={styles.image}
106
-          resizeMode={'contain'}
107
-        />
108
-        <View nativeID={`backdrop${item.id}`} style={[styles.backdrop, { backgroundColor: '#aaaaaa' }]} />
109
-      </View>
110
-      <View style={styles.textContainer}>
111
-        <Text style={styles.title} nativeID={`title${item.id}`}>{item.name}</Text>
112
-        <View style={{ flexDirection: 'row' }}>
113
-          <Text style={styles.ingredients}>{slice(item.ingredients, 0, 3).map(i => i.name).join(' • ')}</Text>
114
-        </View>
115
-      </View>
116
-    </TouchableOpacity>
117
-  )
118
-
119
-  keyExtractor = item => item.id;
120
-}
121
-module.exports = CocktailsList;
122
-const SIZE = 150;
123
-const styles = StyleSheet.create({
124
-  root: {
125
-    paddingTop: 16
126
-  },
127
-  itemContainer: {
128
-    backgroundColor: 'white',
129
-    marginLeft: 16,
130
-    marginRight: 16,
131
-    height: SIZE,
132
-    flexDirection: 'row',
133
-    padding: 16,
134
-    elevation: 4
135
-  },
136
-  image: {
137
-    backgroundColor: 'white',
138
-    height: '100%',
139
-    width: 118,
140
-    zIndex: 1,
141
-  },
142
-  backdrop: {
143
-    width: 118,
144
-    height: 118,
145
-    backgroundColor: 'green',
146
-    marginTop: -112,
147
-    marginLeft: 6
148
-  },
149
-  overlayContainer: {
150
-  },
151
-  textContainer: {
152
-    flex: 1,
153
-    marginLeft: 16,
154
-  },
155
-  title: {
156
-    fontSize: 22
157
-  },
158
-  ingredients: {
159
-    fontSize: 12,
160
-    marginTop: 8
161
-  },
162
-  separator: {
163
-    height: 16
164
-  }
165
-});

+ 97
- 0
playground/src/screens/sharedElementTransition/CocktailsListScreen.js View File

@@ -0,0 +1,97 @@
1
+const React = require('react');
2
+const { Component } = require('react');
3
+const CocktailsView = require('./CocktailsView')
4
+const { Platform } = require('react-native');
5
+const Navigation = require('../../services/Navigation');
6
+const Screens = require('../Screens')
7
+const MULTIPLIER = 1.15
8
+const LONG_DURATION = 350 * MULTIPLIER
9
+const SHORT_DURATION = 190 * MULTIPLIER
10
+
11
+class CocktailsListScreen extends Component {
12
+  static options() {
13
+    return {
14
+      ...Platform.select({
15
+        android: {
16
+          statusBar: {
17
+            style: 'dark',
18
+            backgroundColor: 'white'
19
+          }
20
+        }
21
+      }),
22
+      topBar: {
23
+        title: {
24
+          text: 'Cocktails'
25
+        }
26
+      }
27
+    }
28
+  }
29
+
30
+  render() {
31
+    return (
32
+      <CocktailsView 
33
+        onItemPress={this.pushCocktailDetails}
34
+      />
35
+    );
36
+  }
37
+
38
+  update = (item) => {
39
+    Navigation.updateProps('DETAILS_COMPONENT_ID', item);
40
+  }
41
+
42
+  pushCocktailDetails = (item) => {
43
+    Navigation.push(
44
+      this,
45
+      {
46
+        component: {
47
+          name: Screens.CocktailDetailsScreen,
48
+          passProps: { ...item },
49
+          options: {
50
+            animations: {
51
+              push: {
52
+                content: {
53
+                  alpha: {
54
+                    from: 0,
55
+                    to: 1,
56
+                    duration: LONG_DURATION
57
+                  }
58
+                },
59
+                sharedElementTransitions: [
60
+                  {
61
+                    fromId: `image${item.id}`,
62
+                    toId: `image${item.id}Dest`,
63
+                    duration: LONG_DURATION
64
+                  },
65
+                  {
66
+                    fromId: `title${item.id}`,
67
+                    toId: `title${item.id}Dest`,
68
+                    duration: LONG_DURATION
69
+                  },
70
+                  {
71
+                    fromId: `backdrop${item.id}`,
72
+                    toId: 'backdrop',
73
+                    duration: LONG_DURATION
74
+                  }
75
+                ],
76
+                elementTransitions: [
77
+                  {
78
+                    id: 'description',
79
+                    alpha: {
80
+                      from: 0,
81
+                      duration: SHORT_DURATION
82
+                    },
83
+                    translationY: {
84
+                      from: 16,
85
+                      duration: SHORT_DURATION
86
+                    }
87
+                  }
88
+                ]
89
+              }
90
+            }
91
+          }
92
+        }
93
+      }
94
+    )
95
+  }
96
+}
97
+module.exports = CocktailsListScreen;

+ 94
- 0
playground/src/screens/sharedElementTransition/CocktailsView.js View File

@@ -0,0 +1,94 @@
1
+const React = require('react');
2
+const { Component } = require('react');
3
+const { TouchableOpacity, FlatList, View, Image, Text, StyleSheet } = require('react-native');
4
+const { slice } = require('lodash');
5
+const data = require('../../assets/cocktails').default;
6
+
7
+class CocktailsView extends Component {
8
+  render() {
9
+    return (
10
+      <FlatList
11
+        style={styles.root}
12
+        data={data}
13
+        keyExtractor={this.keyExtractor}
14
+        ItemSeparatorComponent={this.separatorComponent}
15
+        renderItem={this.renderItem}
16
+      />
17
+    );
18
+  }
19
+
20
+  separatorComponent = () => <View style={styles.separator} />;
21
+
22
+  renderItem = ({ item }) => (
23
+    <TouchableOpacity
24
+      activeOpacity={0.75}
25
+      style={styles.itemContainer}
26
+      testID={item.id}
27
+      onPress={() => this.props.onItemPress(item)}
28
+      onLongPress={() => this.props.onItemLongPress(item)}>
29
+      <View style={styles.overlayContainer}>
30
+        <Image
31
+          source={item.image}
32
+          nativeID={`image${item.id}`}
33
+          style={styles.image}
34
+          resizeMode={'contain'}
35
+        />
36
+        <View nativeID={`backdrop${item.id}`} style={[styles.backdrop, { backgroundColor: '#aaaaaa' }]} />
37
+      </View>
38
+      <View style={styles.textContainer}>
39
+        <Text style={styles.title} nativeID={`title${item.id}`}>{item.name}</Text>
40
+        <View style={{ flexDirection: 'row' }}>
41
+          <Text style={styles.ingredients}>{slice(item.ingredients, 0, 3).map(i => i.name).join(' • ')}</Text>
42
+        </View>
43
+      </View>
44
+    </TouchableOpacity>
45
+  )
46
+
47
+  keyExtractor = item => item.id;
48
+}
49
+
50
+module.exports = CocktailsView;
51
+const SIZE = 150;
52
+const styles = StyleSheet.create({
53
+  root: {
54
+    paddingTop: 16
55
+  },
56
+  itemContainer: {
57
+    backgroundColor: 'white',
58
+    marginLeft: 16,
59
+    marginRight: 16,
60
+    height: SIZE,
61
+    flexDirection: 'row',
62
+    padding: 16,
63
+    elevation: 4
64
+  },
65
+  image: {
66
+    backgroundColor: 'white',
67
+    height: '100%',
68
+    width: 118,
69
+    zIndex: 1,
70
+  },
71
+  backdrop: {
72
+    width: 118,
73
+    height: 118,
74
+    backgroundColor: 'green',
75
+    marginTop: -112,
76
+    marginLeft: 6
77
+  },
78
+  overlayContainer: {
79
+  },
80
+  textContainer: {
81
+    flex: 1,
82
+    marginLeft: 16,
83
+  },
84
+  title: {
85
+    fontSize: 22
86
+  },
87
+  ingredients: {
88
+    fontSize: 12,
89
+    marginTop: 8
90
+  },
91
+  separator: {
92
+    height: 16
93
+  }
94
+});

+ 60
- 0
playground/src/screens/splitView/CocktailsListMasterScreen.js View File

@@ -0,0 +1,60 @@
1
+const React = require('react');
2
+const CocktailsView = require('../sharedElementTransition/CocktailsView')
3
+const { Platform } = require('react-native');
4
+const Navigation = require('../../services/Navigation');
5
+const Screens = require('../Screens');
6
+const CocktailsListScreen = require('../sharedElementTransition/CocktailsListScreen');
7
+const {
8
+  PUSH_MASTER_BTN
9
+} = require('../../testIDs');
10
+
11
+class CocktailsListMasterScreen extends CocktailsListScreen {
12
+  static options() {
13
+    return {
14
+      ...Platform.select({
15
+        android: {
16
+          statusBar: {
17
+            style: 'dark',
18
+            backgroundColor: 'white'
19
+          }
20
+        }
21
+      }),
22
+      topBar: {
23
+        title: {
24
+          text: 'Cocktails'
25
+        },
26
+        rightButtons: [{
27
+          id: 'pushMaster',
28
+          testID: PUSH_MASTER_BTN,
29
+          text: 'push'
30
+        }]
31
+      }
32
+    }
33
+  }
34
+
35
+  constructor(props) {
36
+    super(props);
37
+    Navigation.events().bindComponent(this);
38
+  }
39
+
40
+  navigationButtonPressed({buttonId}) {
41
+    if (buttonId === 'pushMaster') {
42
+      Navigation.push(this, Screens.Pushed)
43
+    }
44
+  }
45
+
46
+  render() {
47
+    return (
48
+      <CocktailsView 
49
+        onItemPress={this.updateDetailsScreen}
50
+        onItemLongPress={this.pushCocktailDetails}
51
+      />
52
+    );
53
+  }
54
+
55
+  updateDetailsScreen = (item) => {
56
+    Navigation.updateProps('DETAILS_COMPONENT_ID', item);
57
+  }
58
+}
59
+
60
+module.exports = CocktailsListMasterScreen;

+ 3
- 0
playground/src/testIDs.js View File

@@ -28,6 +28,8 @@ module.exports = {
28 28
   EXTERNAL_COMP_SCREEN_HEADER: 'EXTERNAL_COMPONENT_SCREEN_HEADER',
29 29
   TOP_BAR: 'TOP_BAR',
30 30
   PUSH_BTN: 'PUSH_BUTTON',
31
+  PUSH_DETAILS_BTN: 'PUSH_DETAILS_BUTTON',
32
+  PUSH_MASTER_BTN: 'PUSH_MASTER_BUTTON',
31 33
   PUSH_SIDE_MENU_BTN: 'PUSH_SIDE_MENU_BTN',
32 34
   SHOW_STATIC_EVENTS_SCREEN: 'SHOW_STATIC_EVENTS_SCREEN',
33 35
   POP_BTN: 'POP_BUTTON',
@@ -140,6 +142,7 @@ module.exports = {
140 142
   GOTO_BUTTONS_SCREEN: 'GOTO_BUTTONS_SCREEN',
141 143
   REGISTER_MODAL_DISMISS_EVENT_BTN: 'REGISTER_MODAL_DISMISS_EVENT_BTN',
142 144
   HIDE_PREVIOUS_SCREEN_TOP_BAR: 'HIDE_PREVIOUS_SCREEN_TOP_BAR',
145
+  COCKTAILS_DETAILS_HEADER: 'COCKTAILS_DETAILS_HEADER',
143 146
   
144 147
   //External Component Buttons
145 148
   EXTERNAL_DISMISS_MODAL_BTN: 'EXTERNAL_DISMISS_MODAL_BTN',