Browse Source

Android: More tab switching test coverage using refactor

Amit Davidi 7 years ago
parent
commit
133b3f235b

+ 4
- 2
android/app/src/main/java/com/reactnativenavigation/layout/LayoutFactory.java View File

@@ -49,11 +49,13 @@ public class LayoutFactory {
49 49
     }
50 50
 
51 51
     private View createBottomTabs(LayoutNode node) {
52
-        final BottomTabsContainer tabsContainer = new BottomTabsContainer(activity, bottomTabsCreator);
52
+        final BottomTabsContainer tabsContainer = new BottomTabsContainer(activity, bottomTabsCreator.create());
53 53
 
54
+        int i = 0;
54 55
         for (LayoutNode child : node.children) {
55 56
             final View tabContent = create(child);
56
-            tabsContainer.addTabContent(tabContent);
57
+            tabsContainer.addTabContent("#" + i, tabContent);
58
+            i++;
57 59
         }
58 60
         return tabsContainer;
59 61
     }

+ 21
- 52
android/app/src/main/java/com/reactnativenavigation/layout/bottomtabs/BottomTabs.java View File

@@ -7,95 +7,64 @@ import android.support.design.widget.BottomNavigationView;
7 7
 import android.view.Menu;
8 8
 import android.view.MenuItem;
9 9
 import android.view.View;
10
-import android.view.ViewGroup;
11 10
 import android.widget.RelativeLayout;
12 11
 import android.widget.RelativeLayout.LayoutParams;
13 12
 
14
-import java.util.ArrayList;
15
-import java.util.List;
16 13
 import java.util.concurrent.atomic.AtomicInteger;
17 14
 
18 15
 import static android.widget.RelativeLayout.ALIGN_PARENT_BOTTOM;
19 16
 
20 17
 public class BottomTabs implements BottomNavigationView.OnNavigationItemSelectedListener {
21 18
 
19
+    public interface BottomTabsSelectionListener {
20
+        void onTabSelected(int index);
21
+    }
22
+
22 23
     private static final AtomicInteger viewId = new AtomicInteger(1);
23 24
 
24 25
     private BottomNavigationView bottomNavigationView;
25
-    private List<View> tabsContent;
26
-    private int currentTabId;
26
+    private BottomTabsSelectionListener listener;
27 27
 
28 28
     public void attach(RelativeLayout parentLayout) {
29 29
         createBottomNavigation(parentLayout);
30 30
         addButtomNavigationToParent(parentLayout);
31
-        bottomNavigationView.setOnNavigationItemSelectedListener(this);
32
-        tabsContent = new ArrayList<>(bottomNavigationView.getMaxItemCount());
33 31
     }
34 32
 
35
-    public void addTab(String label, View tabContent) {
33
+    public void setSelectionListener(BottomTabsSelectionListener listener) {
34
+        this.listener = listener;
35
+    }
36
+
37
+    public void add(String label) {
36 38
         int tabId = getTabsCount();
37 39
         bottomNavigationView.getMenu().add(0, tabId, Menu.NONE, label);
38
-
39
-        attachTabContent(tabContent);
40
-        tabsContent.add(tabContent);
41
-
42
-        if (isFirstTabEver()) {
43
-            currentTabId = 0;
44
-            showCurrentTab();
45
-        } else {
46
-            hideTab(tabId);
47
-        }
48 40
     }
49 41
 
50 42
     public int getTabsCount() {
51 43
         return bottomNavigationView.getMenu().size();
52 44
     }
53 45
 
46
+    public int getViewId() {
47
+        return bottomNavigationView.getId();
48
+    }
49
+
54 50
     @Override
55 51
     public boolean onNavigationItemSelected(@NonNull MenuItem item) {
56
-        final int id = item.getItemId();
57
-
58
-        hideCurrentTab();
59
-        currentTabId = id;
60
-        showCurrentTab();
52
+        listener.onTabSelected(item.getItemId());
61 53
         return true;
62 54
     }
63 55
 
64
-    private void addButtomNavigationToParent(RelativeLayout parentLayout) {
65
-        LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
66
-        lp.addRule(ALIGN_PARENT_BOTTOM);
67
-        bottomNavigationView.setLayoutParams(lp);
68
-        parentLayout.addView(bottomNavigationView, lp);
69
-    }
70
-
71 56
     private void createBottomNavigation(RelativeLayout parentLayout) {
72 57
         bottomNavigationView = new BottomNavigationView(parentLayout.getContext());
73 58
         bottomNavigationView.setId(generateViewId());
74 59
         bottomNavigationView.setBackgroundColor(Color.DKGRAY);
60
+        bottomNavigationView.setOnNavigationItemSelectedListener(this);
75 61
     }
76 62
 
77
-    private boolean isFirstTabEver() {
78
-        return bottomNavigationView.getMenu().size() == 1;
79
-    }
80
-
81
-    private void attachTabContent(View tabContent) {
82
-        LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
83
-        params.addRule(RelativeLayout.ABOVE, bottomNavigationView.getId());
84
-
85
-        ViewGroup parent = (ViewGroup) bottomNavigationView.getParent();
86
-        parent.addView(tabContent, params);
87
-    }
88
-
89
-    private void showCurrentTab() {
90
-        tabsContent.get(currentTabId).setVisibility(View.VISIBLE);
91
-    }
92
-
93
-    private void hideCurrentTab() {
94
-        hideTab(currentTabId);
95
-    }
96
-
97
-    private void hideTab(int tabId) {
98
-        tabsContent.get(tabId).setVisibility(View.GONE);
63
+    private void addButtomNavigationToParent(RelativeLayout parentLayout) {
64
+        LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
65
+        lp.addRule(ALIGN_PARENT_BOTTOM);
66
+        bottomNavigationView.setLayoutParams(lp);
67
+        parentLayout.addView(bottomNavigationView, lp);
99 68
     }
100 69
 
101 70
     private int generateViewId() {

+ 45
- 8
android/app/src/main/java/com/reactnativenavigation/layout/bottomtabs/BottomTabsContainer.java View File

@@ -4,21 +4,58 @@ import android.app.Activity;
4 4
 import android.view.View;
5 5
 import android.widget.RelativeLayout;
6 6
 
7
-public class BottomTabsContainer extends RelativeLayout {
7
+import java.util.ArrayList;
8
+import java.util.List;
8 9
 
10
+public class BottomTabsContainer extends RelativeLayout implements BottomTabs.BottomTabsSelectionListener {
11
+
12
+    private List<View> tabsContent;
9 13
     private BottomTabs bottomTabs;
14
+    private int currentTab;
10 15
 
11
-    public BottomTabsContainer(Activity activity, BottomTabsCreator bottomTabsCreator) {
16
+    public BottomTabsContainer(Activity activity, BottomTabs bottomTabs) {
12 17
         super(activity);
13
-        createBottomTabs(bottomTabsCreator);
18
+
19
+        initBottomTabs(bottomTabs);
14 20
     }
15 21
 
16
-    public void addTabContent(View tabContent) {
17
-        bottomTabs.addTab("#" + bottomTabs.getTabsCount(), tabContent);
22
+    public void addTabContent(String label, View tabContent) {
23
+        bottomTabs.add(label);
24
+        attachTabContent(tabContent);
25
+        tabsContent.add(tabContent);
26
+
27
+        if (tabsContent.size() > 1) {
28
+            tabContent.setVisibility(View.GONE);
29
+        }
18 30
     }
19 31
 
20
-    private void createBottomTabs(BottomTabsCreator bottomTabsCreator) {
21
-        bottomTabs = bottomTabsCreator.create();
22
-        bottomTabs.attach(this);
32
+    @Override
33
+    public void onTabSelected(int index) {
34
+        hideTab(currentTab);
35
+        currentTab = index;
36
+        showTab(currentTab);
23 37
     }
38
+
39
+    private void initBottomTabs(BottomTabs bottomTabs) {
40
+        this.bottomTabs = bottomTabs;
41
+        this.bottomTabs.attach(this);
42
+        this.bottomTabs.setSelectionListener(this);
43
+
44
+        tabsContent = new ArrayList<>();
45
+    }
46
+
47
+    private void attachTabContent(View tabContent) {
48
+        LayoutParams tabParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
49
+        tabParams.addRule(ABOVE, bottomTabs.getViewId());
50
+        addView(tabContent, tabParams);
51
+    }
52
+
53
+    private void showTab(int tabId) {
54
+        tabsContent.get(tabId).setVisibility(View.VISIBLE);
55
+    }
56
+
57
+    private void hideTab(int tabId) {
58
+        tabsContent.get(tabId).setVisibility(View.GONE);
59
+    }
60
+
24 61
 }

+ 118
- 0
android/app/src/test/java/com/reactnativenavigation/BottomTabsContainerTest.java View File

@@ -0,0 +1,118 @@
1
+package com.reactnativenavigation;
2
+
3
+import android.app.Activity;
4
+import android.view.View;
5
+
6
+import com.reactnativenavigation.layout.bottomtabs.BottomTabs;
7
+import com.reactnativenavigation.layout.bottomtabs.BottomTabsContainer;
8
+
9
+import org.junit.Before;
10
+import org.junit.Test;
11
+import org.junit.runner.RunWith;
12
+import org.robolectric.Robolectric;
13
+import org.robolectric.RobolectricTestRunner;
14
+
15
+import static org.assertj.core.api.Java6Assertions.assertThat;
16
+import static org.mockito.Mockito.mock;
17
+import static org.mockito.Mockito.verify;
18
+
19
+@RunWith(RobolectricTestRunner.class)
20
+public class BottomTabsContainerTest {
21
+
22
+    private static final String TAB_NAME = "myTab";
23
+    private static final String OTHER_TAB_NAME = "myOtherTab";
24
+
25
+    private BottomTabs bottomTabs;
26
+    private Activity activity;
27
+
28
+    @Before
29
+    public void setUp() throws Exception {
30
+        bottomTabs = mock(BottomTabs.class);
31
+        activity = Robolectric.buildActivity(Activity.class).get();
32
+    }
33
+
34
+    @Test
35
+    public void addsTabToBottomTabs() throws Exception {
36
+        View tabContent = new View(activity);
37
+
38
+        BottomTabsContainer bottomTabsContainer = createBottomTabsContainer();
39
+        bottomTabsContainer.addTabContent(TAB_NAME, tabContent);
40
+
41
+        verify(bottomTabs).add(TAB_NAME);
42
+    }
43
+
44
+    @Test
45
+    public void addsTabContentToLayout() throws Exception {
46
+        View tabContent = new View(activity);
47
+
48
+        BottomTabsContainer bottomTabsContainer = createBottomTabsContainer();
49
+        bottomTabsContainer.addTabContent(TAB_NAME, tabContent);
50
+
51
+        verify(bottomTabs).attach(bottomTabsContainer);
52
+        TestUtils.assertViewChildren(bottomTabsContainer, tabContent);
53
+    }
54
+
55
+    @Test
56
+    public void addsTwoTabsContentToLayout() throws Exception {
57
+        View tabContent = new View(activity);
58
+        View otherTabContent = new View(activity);
59
+
60
+        BottomTabsContainer bottomTabsContainer = createBottomTabsContainer();
61
+        bottomTabsContainer.addTabContent(TAB_NAME, tabContent);
62
+        bottomTabsContainer.addTabContent(OTHER_TAB_NAME, otherTabContent);
63
+
64
+        TestUtils.assertViewChildren(bottomTabsContainer, tabContent, otherTabContent);
65
+    }
66
+
67
+    @Test
68
+    public void onlyFirstTabShouldBeVisible() throws Exception {
69
+        View tabContent = new View(activity);
70
+        View otherTabContent = new View(activity);
71
+
72
+        BottomTabsContainer bottomTabsContainer = createBottomTabsContainer();
73
+        bottomTabsContainer.addTabContent(TAB_NAME, tabContent);
74
+        bottomTabsContainer.addTabContent(OTHER_TAB_NAME, otherTabContent);
75
+
76
+        assertThat(tabContent.getVisibility()).isEqualTo(View.VISIBLE);
77
+        assertThat(otherTabContent.getVisibility()).isEqualTo(View.GONE);
78
+    }
79
+
80
+    @Test
81
+    public void listensToTabsSwitchingEvents() throws Exception {
82
+        BottomTabsContainer bottomTabsContainer = createBottomTabsContainer();
83
+        verify(bottomTabs).setSelectionListener(bottomTabsContainer);
84
+    }
85
+
86
+    @Test
87
+    public void switchesBetweenFirstAndSecondTabs() throws Exception {
88
+        View tabContent = new View(activity);
89
+        View otherTabContent = new View(activity);
90
+
91
+        BottomTabsContainer bottomTabsContainer = createBottomTabsContainer();
92
+        bottomTabsContainer.addTabContent(TAB_NAME, tabContent);
93
+        bottomTabsContainer.addTabContent(OTHER_TAB_NAME, otherTabContent);
94
+        bottomTabsContainer.onTabSelected(1);
95
+
96
+        assertThat(tabContent.getVisibility()).isEqualTo(View.GONE);
97
+        assertThat(otherTabContent.getVisibility()).isEqualTo(View.VISIBLE);
98
+    }
99
+
100
+    @Test
101
+    public void switchesBetweenSecondAndFirstTabs() throws Exception {
102
+        View tabContent = new View(activity);
103
+        View otherTabContent = new View(activity);
104
+
105
+        BottomTabsContainer bottomTabsContainer = createBottomTabsContainer();
106
+        bottomTabsContainer.addTabContent(TAB_NAME, tabContent);
107
+        bottomTabsContainer.addTabContent(OTHER_TAB_NAME, otherTabContent);
108
+        bottomTabsContainer.onTabSelected(1);
109
+        bottomTabsContainer.onTabSelected(0);
110
+
111
+        assertThat(tabContent.getVisibility()).isEqualTo(View.VISIBLE);
112
+        assertThat(otherTabContent.getVisibility()).isEqualTo(View.GONE);
113
+    }
114
+
115
+    private BottomTabsContainer createBottomTabsContainer() {
116
+        return new BottomTabsContainer(activity, bottomTabs);
117
+    }
118
+}

+ 12
- 31
android/app/src/test/java/com/reactnativenavigation/LayoutFactoryTest.java View File

@@ -16,18 +16,15 @@ import com.reactnativenavigation.layout.bottomtabs.BottomTabsCreator;
16 16
 import org.junit.Before;
17 17
 import org.junit.Test;
18 18
 import org.junit.runner.RunWith;
19
-import org.mockito.ArgumentCaptor;
20 19
 import org.robolectric.Robolectric;
21 20
 import org.robolectric.RobolectricTestRunner;
22 21
 
23
-import java.util.ArrayList;
24 22
 import java.util.Arrays;
25 23
 import java.util.Collections;
26 24
 import java.util.HashMap;
27 25
 import java.util.List;
28 26
 
29 27
 import static org.assertj.core.api.Java6Assertions.assertThat;
30
-import static org.mockito.ArgumentMatchers.any;
31 28
 import static org.mockito.ArgumentMatchers.eq;
32 29
 import static org.mockito.Mockito.mock;
33 30
 import static org.mockito.Mockito.verify;
@@ -63,7 +60,7 @@ public class LayoutFactoryTest {
63 60
         final ViewGroup result = (ViewGroup) createLayoutFactory().create(node);
64 61
 
65 62
         assertThat(result).isInstanceOf(Container.class);
66
-        assertViewChildren(result, mockView);
63
+        TestUtils.assertViewChildren(result, mockView);
67 64
     }
68 65
 
69 66
     @Test
@@ -75,8 +72,8 @@ public class LayoutFactoryTest {
75 72
         final ViewGroup result = (ViewGroup) createLayoutFactory().create(stackNode);
76 73
 
77 74
         assertThat(result).isInstanceOf(ContainerStack.class);
78
-        ViewGroup container = (ViewGroup) assertViewChildrenCount(result, 1).get(0);
79
-        assertViewChildren(container, mockView);
75
+        ViewGroup container = (ViewGroup) TestUtils.assertViewChildrenCount(result, 1).get(0);
76
+        TestUtils.assertViewChildren(container, mockView);
80 77
     }
81 78
 
82 79
     @Test
@@ -93,11 +90,11 @@ public class LayoutFactoryTest {
93 90
         final ViewGroup result = (ViewGroup) createLayoutFactory().create(stackNode);
94 91
 
95 92
         assertThat(result).isInstanceOf(ContainerStack.class);
96
-        List<View> containers = assertViewChildrenCount(result, 2);
93
+        List<View> containers = TestUtils.assertViewChildrenCount(result, 2);
97 94
         ViewGroup container1 = (ViewGroup) containers.get(0);
98 95
         ViewGroup container2 = (ViewGroup) containers.get(1);
99
-        assertViewChildren(container1, mockView1);
100
-        assertViewChildren(container2, mockView2);
96
+        TestUtils.assertViewChildren(container1, mockView1);
97
+        TestUtils.assertViewChildren(container2, mockView2);
101 98
     }
102 99
 
103 100
     @Test
@@ -111,12 +108,11 @@ public class LayoutFactoryTest {
111 108
 
112 109
         final View result = createLayoutFactory(bottomTabsMock).create(tabNode);
113 110
 
114
-        assertThat(result).isInstanceOf(BottomTabsContainer.class);
111
+        verify(bottomTabsMock).add("#0");
115 112
 
116
-        ArgumentCaptor<Container> containerCaptor = ArgumentCaptor.forClass(Container.class);
117
-        verify(bottomTabsMock).addTab(eq("#0"), containerCaptor.capture());
118
-        Container container = containerCaptor.getValue();
119
-        View view = assertViewChildrenCount(container, 1).get(0);
113
+        assertThat(result).isInstanceOf(BottomTabsContainer.class);
114
+        Container container = (Container) TestUtils.assertViewChildrenCount((BottomTabsContainer) result, 1).get(0);
115
+        View view = TestUtils.assertViewChildrenCount(container, 1).get(0);
120 116
         assertThat(view).isEqualTo(mockView);
121 117
     }
122 118
 
@@ -136,8 +132,8 @@ public class LayoutFactoryTest {
136 132
         final View result = createLayoutFactory(bottomTabsMock).create(tabNode);
137 133
 
138 134
         assertThat(result).isInstanceOf(BottomTabsContainer.class);
139
-        verify(bottomTabsMock).addTab(eq("#0"), any(Container.class));
140
-        verify(bottomTabsMock).addTab(eq("#1"), any(ContainerStack.class));
135
+        verify(bottomTabsMock).add(eq("#0"));
136
+        verify(bottomTabsMock).add(eq("#1"));
141 137
     }
142 138
 
143 139
     @Test(expected = IllegalArgumentException.class)
@@ -183,19 +179,4 @@ public class LayoutFactoryTest {
183 179
         node.children = Arrays.asList(children);
184 180
         return node;
185 181
     }
186
-
187
-    private List<View> assertViewChildrenCount(ViewGroup view, int count) {
188
-        assertThat(view.getChildCount()).isEqualTo(count);
189
-
190
-        final List<View> children = new ArrayList<>(count);
191
-        for (int i = 0; i < count; i++) {
192
-            children.add(view.getChildAt(i));
193
-        }
194
-        return children;
195
-    }
196
-
197
-    private void assertViewChildren(ViewGroup view, View... children) {
198
-        final List<View> childViews = assertViewChildrenCount(view, children.length);
199
-        assertThat(childViews).isEqualTo(Arrays.asList(children));
200
-    }
201 182
 }

+ 27
- 0
android/app/src/test/java/com/reactnativenavigation/TestUtils.java View File

@@ -0,0 +1,27 @@
1
+package com.reactnativenavigation;
2
+
3
+import android.view.View;
4
+import android.view.ViewGroup;
5
+
6
+import java.util.ArrayList;
7
+import java.util.Arrays;
8
+import java.util.List;
9
+
10
+import static org.assertj.core.api.Java6Assertions.assertThat;
11
+
12
+public class TestUtils {
13
+    public static List<View> assertViewChildrenCount(ViewGroup view, int count) {
14
+        assertThat(view.getChildCount()).isEqualTo(count);
15
+
16
+        final List<View> children = new ArrayList<>(count);
17
+        for (int i = 0; i < count; i++) {
18
+            children.add(view.getChildAt(i));
19
+        }
20
+        return children;
21
+    }
22
+
23
+    public static void assertViewChildren(ViewGroup view, View... children) {
24
+        final List<View> childViews = assertViewChildrenCount(view, children.length);
25
+        assertThat(childViews).isEqualTo(Arrays.asList(children));
26
+    }
27
+}