react-native-navigation 7.23.1-snapshot.438 → 7.23.1-snapshot.440
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/android/app/src/main/java/com/reactnativenavigation/options/HardwareBackButtonOptions.kt +35 -2
- package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/bottomtabs/BottomTabsController.java +42 -2
- package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/bottomtabs/BottomTabsControllerTest.kt +572 -0
- package/lib/dist/interfaces/Options.d.ts +4 -0
- package/lib/src/interfaces/Options.ts +5 -0
- package/package.json +1 -1
- package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/bottomtabs/BottomTabsControllerTest.java +0 -514
package/lib/android/app/src/main/java/com/reactnativenavigation/options/HardwareBackButtonOptions.kt
CHANGED
|
@@ -6,10 +6,40 @@ import com.reactnativenavigation.options.parsers.BoolParser
|
|
|
6
6
|
import org.json.JSONObject
|
|
7
7
|
|
|
8
8
|
|
|
9
|
+
sealed class HwBackBottomTabsBehaviour {
|
|
10
|
+
object Undefined : HwBackBottomTabsBehaviour() {
|
|
11
|
+
override fun hasValue(): Boolean = false
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
object Exit : HwBackBottomTabsBehaviour()
|
|
15
|
+
object PrevSelection : HwBackBottomTabsBehaviour()
|
|
16
|
+
object JumpToFirst : HwBackBottomTabsBehaviour()
|
|
17
|
+
|
|
18
|
+
open fun hasValue(): Boolean = true
|
|
19
|
+
|
|
20
|
+
companion object {
|
|
21
|
+
private const val BEHAVIOUR_EXIT = "exit"
|
|
22
|
+
private const val BEHAVIOUR_PREV = "previous"
|
|
23
|
+
private const val BEHAVIOUR_FIRST = "first"
|
|
24
|
+
fun fromString(behaviour: String?): HwBackBottomTabsBehaviour {
|
|
25
|
+
return when (behaviour) {
|
|
26
|
+
BEHAVIOUR_PREV -> PrevSelection
|
|
27
|
+
BEHAVIOUR_FIRST -> JumpToFirst
|
|
28
|
+
BEHAVIOUR_EXIT -> Exit
|
|
29
|
+
else -> Undefined
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
9
35
|
open class HardwareBackButtonOptions(json: JSONObject? = null) {
|
|
10
36
|
|
|
11
|
-
@JvmField
|
|
12
|
-
|
|
37
|
+
@JvmField
|
|
38
|
+
var dismissModalOnPress: Bool = NullBool()
|
|
39
|
+
|
|
40
|
+
@JvmField
|
|
41
|
+
var popStackOnPress: Bool = NullBool()
|
|
42
|
+
var bottomTabOnPress: HwBackBottomTabsBehaviour = HwBackBottomTabsBehaviour.Undefined
|
|
13
43
|
|
|
14
44
|
init {
|
|
15
45
|
parse(json)
|
|
@@ -18,16 +48,19 @@ open class HardwareBackButtonOptions(json: JSONObject? = null) {
|
|
|
18
48
|
fun mergeWith(other: HardwareBackButtonOptions) {
|
|
19
49
|
if (other.dismissModalOnPress.hasValue()) dismissModalOnPress = other.dismissModalOnPress
|
|
20
50
|
if (other.popStackOnPress.hasValue()) popStackOnPress = other.popStackOnPress
|
|
51
|
+
if (other.bottomTabOnPress.hasValue()) bottomTabOnPress = other.bottomTabOnPress
|
|
21
52
|
}
|
|
22
53
|
|
|
23
54
|
fun mergeWithDefault(defaultOptions: HardwareBackButtonOptions) {
|
|
24
55
|
if (!dismissModalOnPress.hasValue()) dismissModalOnPress = defaultOptions.dismissModalOnPress
|
|
25
56
|
if (!popStackOnPress.hasValue()) popStackOnPress = defaultOptions.popStackOnPress
|
|
57
|
+
if (!bottomTabOnPress.hasValue()) bottomTabOnPress = defaultOptions.bottomTabOnPress
|
|
26
58
|
}
|
|
27
59
|
|
|
28
60
|
private fun parse(json: JSONObject?) {
|
|
29
61
|
json ?: return
|
|
30
62
|
dismissModalOnPress = BoolParser.parse(json, "dismissModalOnPress")
|
|
31
63
|
popStackOnPress = BoolParser.parse(json, "popStackOnPress")
|
|
64
|
+
bottomTabOnPress = HwBackBottomTabsBehaviour.fromString(json.optString("bottomTabsOnPress"))
|
|
32
65
|
}
|
|
33
66
|
}
|
|
@@ -13,6 +13,7 @@ import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
|
|
13
13
|
import com.aurelhubert.ahbottomnavigation.AHBottomNavigation;
|
|
14
14
|
import com.aurelhubert.ahbottomnavigation.AHBottomNavigationItem;
|
|
15
15
|
import com.reactnativenavigation.options.BottomTabOptions;
|
|
16
|
+
import com.reactnativenavigation.options.HwBackBottomTabsBehaviour;
|
|
16
17
|
import com.reactnativenavigation.options.Options;
|
|
17
18
|
import com.reactnativenavigation.react.CommandListener;
|
|
18
19
|
import com.reactnativenavigation.react.CommandListenerAdapter;
|
|
@@ -29,6 +30,8 @@ import com.reactnativenavigation.views.bottomtabs.BottomTabsContainer;
|
|
|
29
30
|
import com.reactnativenavigation.views.bottomtabs.BottomTabsLayout;
|
|
30
31
|
|
|
31
32
|
import java.util.Collection;
|
|
33
|
+
import java.util.Deque;
|
|
34
|
+
import java.util.LinkedList;
|
|
32
35
|
import java.util.List;
|
|
33
36
|
|
|
34
37
|
import static com.reactnativenavigation.utils.CollectionUtils.forEach;
|
|
@@ -39,6 +42,7 @@ public class BottomTabsController extends ParentController<BottomTabsLayout> imp
|
|
|
39
42
|
|
|
40
43
|
private BottomTabsContainer bottomTabsContainer;
|
|
41
44
|
private BottomTabs bottomTabs;
|
|
45
|
+
private final Deque<Integer> selectionStack;
|
|
42
46
|
private final List<ViewController<?>> tabs;
|
|
43
47
|
private final EventEmitter eventEmitter;
|
|
44
48
|
private final ImageLoader imageLoader;
|
|
@@ -66,6 +70,7 @@ public class BottomTabsController extends ParentController<BottomTabsLayout> imp
|
|
|
66
70
|
this.presenter = bottomTabsPresenter;
|
|
67
71
|
this.tabPresenter = bottomTabPresenter;
|
|
68
72
|
forEach(tabs, tab -> tab.setParentController(this));
|
|
73
|
+
selectionStack = new LinkedList<>();
|
|
69
74
|
}
|
|
70
75
|
|
|
71
76
|
@Override
|
|
@@ -156,7 +161,27 @@ public class BottomTabsController extends ParentController<BottomTabsLayout> imp
|
|
|
156
161
|
|
|
157
162
|
@Override
|
|
158
163
|
public boolean handleBack(CommandListener listener) {
|
|
159
|
-
|
|
164
|
+
final boolean childBack = !tabs.isEmpty() && tabs.get(bottomTabs.getCurrentItem()).handleBack(listener);
|
|
165
|
+
final Options options = resolveCurrentOptions();
|
|
166
|
+
if (!childBack) {
|
|
167
|
+
if (options.hardwareBack.getBottomTabOnPress() instanceof HwBackBottomTabsBehaviour.PrevSelection) {
|
|
168
|
+
if (!selectionStack.isEmpty()) {
|
|
169
|
+
final int prevSelectedTabIndex = selectionStack.poll();
|
|
170
|
+
selectTab(prevSelectedTabIndex, false);
|
|
171
|
+
return true;
|
|
172
|
+
}
|
|
173
|
+
} else if (options.hardwareBack.getBottomTabOnPress() instanceof HwBackBottomTabsBehaviour.JumpToFirst) {
|
|
174
|
+
if (getSelectedIndex() != 0) {
|
|
175
|
+
selectTab(0, false);
|
|
176
|
+
return true;
|
|
177
|
+
} else {
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
180
|
+
} else {
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return childBack;
|
|
160
185
|
}
|
|
161
186
|
|
|
162
187
|
@Override
|
|
@@ -203,7 +228,7 @@ public class BottomTabsController extends ParentController<BottomTabsLayout> imp
|
|
|
203
228
|
});
|
|
204
229
|
}
|
|
205
230
|
|
|
206
|
-
int getSelectedIndex() {
|
|
231
|
+
public int getSelectedIndex() {
|
|
207
232
|
return bottomTabs.getCurrentItem();
|
|
208
233
|
}
|
|
209
234
|
|
|
@@ -239,6 +264,12 @@ public class BottomTabsController extends ParentController<BottomTabsLayout> imp
|
|
|
239
264
|
|
|
240
265
|
@Override
|
|
241
266
|
public void selectTab(final int newIndex) {
|
|
267
|
+
final boolean enableSelectionHistory = resolveCurrentOptions().hardwareBack.getBottomTabOnPress() instanceof HwBackBottomTabsBehaviour.PrevSelection;
|
|
268
|
+
selectTab(newIndex, enableSelectionHistory);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
private void selectTab(int newIndex, boolean enableSelectionHistory) {
|
|
272
|
+
saveTabSelection(newIndex, enableSelectionHistory);
|
|
242
273
|
tabsAttacher.onTabSelected(tabs.get(newIndex));
|
|
243
274
|
getCurrentView().setVisibility(View.INVISIBLE);
|
|
244
275
|
bottomTabs.setCurrentItem(newIndex, false);
|
|
@@ -246,6 +277,15 @@ public class BottomTabsController extends ParentController<BottomTabsLayout> imp
|
|
|
246
277
|
getCurrentChild().onViewDidAppear();
|
|
247
278
|
}
|
|
248
279
|
|
|
280
|
+
private void saveTabSelection(int newIndex, boolean enableSelectionHistory) {
|
|
281
|
+
if (enableSelectionHistory) {
|
|
282
|
+
if (selectionStack.isEmpty()
|
|
283
|
+
|| selectionStack.peek() != newIndex
|
|
284
|
+
|| bottomTabs.getCurrentItem() != newIndex)
|
|
285
|
+
selectionStack.offerFirst(bottomTabs.getCurrentItem());
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
249
289
|
@NonNull
|
|
250
290
|
private ViewGroup getCurrentView() {
|
|
251
291
|
return tabs.get(bottomTabs.getCurrentItem()).getView();
|
|
@@ -0,0 +1,572 @@
|
|
|
1
|
+
package com.reactnativenavigation.viewcontrollers.bottomtabs
|
|
2
|
+
|
|
3
|
+
import android.app.Activity
|
|
4
|
+
import android.graphics.Color
|
|
5
|
+
import android.view.Gravity
|
|
6
|
+
import android.view.View
|
|
7
|
+
import android.view.ViewGroup.MarginLayoutParams
|
|
8
|
+
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
|
9
|
+
import com.aurelhubert.ahbottomnavigation.AHBottomNavigation.TitleState
|
|
10
|
+
import com.reactnativenavigation.BaseTest
|
|
11
|
+
import com.reactnativenavigation.TestUtils
|
|
12
|
+
import com.reactnativenavigation.mocks.ImageLoaderMock.mock
|
|
13
|
+
import com.reactnativenavigation.mocks.SimpleViewController
|
|
14
|
+
import com.reactnativenavigation.mocks.TypefaceLoaderMock
|
|
15
|
+
import com.reactnativenavigation.options.BottomTabsOptions
|
|
16
|
+
import com.reactnativenavigation.options.HwBackBottomTabsBehaviour
|
|
17
|
+
import com.reactnativenavigation.options.Options
|
|
18
|
+
import com.reactnativenavigation.options.params.*
|
|
19
|
+
import com.reactnativenavigation.react.CommandListenerAdapter
|
|
20
|
+
import com.reactnativenavigation.react.events.EventEmitter
|
|
21
|
+
import com.reactnativenavigation.utils.OptionHelper
|
|
22
|
+
import com.reactnativenavigation.utils.SystemUiUtils.getStatusBarHeight
|
|
23
|
+
import com.reactnativenavigation.utils.SystemUiUtils.saveStatusBarHeight
|
|
24
|
+
import com.reactnativenavigation.viewcontrollers.bottomtabs.attacher.BottomTabsAttacher
|
|
25
|
+
import com.reactnativenavigation.viewcontrollers.child.ChildControllersRegistry
|
|
26
|
+
import com.reactnativenavigation.viewcontrollers.fakes.FakeParentController
|
|
27
|
+
import com.reactnativenavigation.viewcontrollers.parent.ParentController
|
|
28
|
+
import com.reactnativenavigation.viewcontrollers.stack.StackController
|
|
29
|
+
import com.reactnativenavigation.viewcontrollers.viewcontroller.Presenter
|
|
30
|
+
import com.reactnativenavigation.viewcontrollers.viewcontroller.ViewController
|
|
31
|
+
import com.reactnativenavigation.views.bottomtabs.BottomTabs
|
|
32
|
+
import com.reactnativenavigation.views.bottomtabs.BottomTabsContainer
|
|
33
|
+
import com.reactnativenavigation.views.bottomtabs.BottomTabsLayout
|
|
34
|
+
import org.assertj.core.api.Java6Assertions
|
|
35
|
+
import org.junit.Test
|
|
36
|
+
import org.mockito.ArgumentCaptor
|
|
37
|
+
import org.mockito.ArgumentMatchers
|
|
38
|
+
import org.mockito.Mockito
|
|
39
|
+
import org.mockito.kotlin.any
|
|
40
|
+
import org.mockito.kotlin.eq
|
|
41
|
+
import org.mockito.kotlin.times
|
|
42
|
+
import java.util.*
|
|
43
|
+
|
|
44
|
+
class BottomTabsControllerTest : BaseTest() {
|
|
45
|
+
private lateinit var activity: Activity
|
|
46
|
+
private lateinit var bottomTabs: BottomTabs
|
|
47
|
+
private lateinit var bottomTabsContainer: BottomTabsContainer
|
|
48
|
+
private lateinit var uut: BottomTabsController
|
|
49
|
+
private val initialOptions = Options()
|
|
50
|
+
private lateinit var child1: ViewController<*>
|
|
51
|
+
private lateinit var child2: ViewController<*>
|
|
52
|
+
private lateinit var child3: ViewController<*>
|
|
53
|
+
private lateinit var stackChild: ViewController<*>
|
|
54
|
+
private lateinit var child4: StackController
|
|
55
|
+
private lateinit var child5: ViewController<*>
|
|
56
|
+
private val tabOptions = OptionHelper.createBottomTabOptions()
|
|
57
|
+
private val imageLoaderMock = mock()
|
|
58
|
+
private lateinit var eventEmitter: EventEmitter
|
|
59
|
+
private lateinit var childRegistry: ChildControllersRegistry
|
|
60
|
+
private lateinit var tabs: MutableList<ViewController<*>>
|
|
61
|
+
private lateinit var presenter: BottomTabsPresenter
|
|
62
|
+
private lateinit var bottomTabPresenter: BottomTabPresenter
|
|
63
|
+
private lateinit var tabsAttacher: BottomTabsAttacher
|
|
64
|
+
override fun beforeEach() {
|
|
65
|
+
super.beforeEach()
|
|
66
|
+
activity = newActivity()
|
|
67
|
+
childRegistry = ChildControllersRegistry()
|
|
68
|
+
eventEmitter = Mockito.mock(EventEmitter::class.java)
|
|
69
|
+
prepareViewsForTests()
|
|
70
|
+
saveStatusBarHeight(63)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
@Test
|
|
74
|
+
fun createView_checkProperStructure() {
|
|
75
|
+
idleMainLooper()
|
|
76
|
+
Java6Assertions.assertThat(uut.view).isInstanceOf(CoordinatorLayout::class.java)
|
|
77
|
+
Java6Assertions.assertThat(uut.view.getChildAt(uut.view.childCount - 1)).isInstanceOf(
|
|
78
|
+
BottomTabsContainer::class.java
|
|
79
|
+
)
|
|
80
|
+
Java6Assertions.assertThat((uut.bottomTabsContainer.layoutParams as CoordinatorLayout.LayoutParams).gravity)
|
|
81
|
+
.isEqualTo(Gravity.BOTTOM)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
@Test
|
|
85
|
+
fun createView_tabsWithoutIconsAreAccepted() {
|
|
86
|
+
tabOptions.bottomTabOptions.icon = NullText()
|
|
87
|
+
prepareViewsForTests()
|
|
88
|
+
Java6Assertions.assertThat(uut.bottomTabs.itemsCount).isEqualTo(tabs.size)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
@Test
|
|
92
|
+
fun createView_showTitlesWhenAllTabsDontHaveIcons() {
|
|
93
|
+
tabOptions.bottomTabOptions.icon = NullText()
|
|
94
|
+
Java6Assertions.assertThat(tabOptions.bottomTabsOptions.titleDisplayMode.hasValue()).isFalse
|
|
95
|
+
prepareViewsForTests()
|
|
96
|
+
presenter.applyOptions(Options.EMPTY)
|
|
97
|
+
Java6Assertions.assertThat(bottomTabsContainer.bottomTabs.titleState).isEqualTo(TitleState.ALWAYS_SHOW)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
@Test(expected = RuntimeException::class)
|
|
101
|
+
fun setTabs_ThrowWhenMoreThan5() {
|
|
102
|
+
tabs.add(SimpleViewController(activity, childRegistry, "6", tabOptions))
|
|
103
|
+
createBottomTabs()
|
|
104
|
+
idleMainLooper()
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
@Test
|
|
108
|
+
fun parentControllerIsSet() {
|
|
109
|
+
uut = createBottomTabs()
|
|
110
|
+
for (tab in tabs) {
|
|
111
|
+
Java6Assertions.assertThat(tab.parentController).isEqualTo(uut)
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
@Test
|
|
116
|
+
fun setTabs_allChildViewsAreAttachedToHierarchy() {
|
|
117
|
+
uut.onViewWillAppear()
|
|
118
|
+
Java6Assertions.assertThat(uut.view.childCount).isEqualTo(6)
|
|
119
|
+
for (child in uut.childControllers) {
|
|
120
|
+
Java6Assertions.assertThat(child.view.parent).isNotNull
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
@Test
|
|
125
|
+
fun setTabs_firstChildIsVisibleOtherAreGone() {
|
|
126
|
+
uut.onViewWillAppear()
|
|
127
|
+
for (i in uut.childControllers.indices) {
|
|
128
|
+
Java6Assertions.assertThat(uut.view.getChildAt(i)).isEqualTo(tabs[i].view)
|
|
129
|
+
Java6Assertions.assertThat(uut.view.getChildAt(i).visibility)
|
|
130
|
+
.isEqualTo(if (i == 0) View.VISIBLE else View.INVISIBLE)
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
@Test
|
|
135
|
+
fun onTabSelected() {
|
|
136
|
+
uut.ensureViewIsCreated()
|
|
137
|
+
Java6Assertions.assertThat(uut.selectedIndex).isZero
|
|
138
|
+
Java6Assertions.assertThat(((uut.childControllers as List<*>)[0] as ViewController<*>).view.visibility)
|
|
139
|
+
.isEqualTo(
|
|
140
|
+
View.VISIBLE
|
|
141
|
+
)
|
|
142
|
+
uut.onTabSelected(3, false)
|
|
143
|
+
Java6Assertions.assertThat(uut.selectedIndex).isEqualTo(3)
|
|
144
|
+
Java6Assertions.assertThat(((uut.childControllers as List<*>)[0] as ViewController<*>).view.visibility)
|
|
145
|
+
.isEqualTo(
|
|
146
|
+
View.INVISIBLE
|
|
147
|
+
)
|
|
148
|
+
Java6Assertions.assertThat(((uut.childControllers as List<*>)[3] as ViewController<*>).view.visibility)
|
|
149
|
+
.isEqualTo(
|
|
150
|
+
View.VISIBLE
|
|
151
|
+
)
|
|
152
|
+
Mockito.verify(eventEmitter).emitBottomTabSelected(0, 3)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
@Test
|
|
156
|
+
fun onTabReSelected() {
|
|
157
|
+
uut.ensureViewIsCreated()
|
|
158
|
+
Java6Assertions.assertThat(uut.selectedIndex).isZero
|
|
159
|
+
uut.onTabSelected(0, true)
|
|
160
|
+
Java6Assertions.assertThat(uut.selectedIndex).isEqualTo(0)
|
|
161
|
+
Java6Assertions.assertThat(((uut.childControllers as List<*>)[0] as ViewController<*>).view.parent).isNotNull
|
|
162
|
+
Mockito.verify(eventEmitter).emitBottomTabSelected(0, 0)
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
@Test
|
|
166
|
+
fun handleBack_DelegatesToSelectedChild() {
|
|
167
|
+
uut.ensureViewIsCreated()
|
|
168
|
+
Java6Assertions.assertThat(uut.handleBack(CommandListenerAdapter())).isFalse
|
|
169
|
+
uut.selectTab(4)
|
|
170
|
+
Java6Assertions.assertThat(uut.handleBack(CommandListenerAdapter())).isTrue
|
|
171
|
+
Mockito.verify(child5).handleBack(ArgumentMatchers.any())
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
@Test
|
|
175
|
+
fun `handleBack - PrevSelection - reselect tab selection history of navigation when root has bottom tabs`() {
|
|
176
|
+
val options = Options().apply {
|
|
177
|
+
hardwareBack.bottomTabOnPress = HwBackBottomTabsBehaviour.PrevSelection
|
|
178
|
+
}
|
|
179
|
+
prepareViewsForTests(options = options)
|
|
180
|
+
idleMainLooper()
|
|
181
|
+
Java6Assertions.assertThat(uut.selectedIndex).isEqualTo(0)
|
|
182
|
+
|
|
183
|
+
uut.selectTab(1)
|
|
184
|
+
Java6Assertions.assertThat(uut.selectedIndex).isEqualTo(1)
|
|
185
|
+
|
|
186
|
+
uut.selectTab(3)
|
|
187
|
+
Java6Assertions.assertThat(uut.selectedIndex).isEqualTo(3)
|
|
188
|
+
|
|
189
|
+
uut.selectTab(2)
|
|
190
|
+
Java6Assertions.assertThat(uut.selectedIndex).isEqualTo(2)
|
|
191
|
+
|
|
192
|
+
Java6Assertions.assertThat(uut.handleBack(CommandListenerAdapter())).isTrue
|
|
193
|
+
Java6Assertions.assertThat(uut.selectedIndex).isEqualTo(3)
|
|
194
|
+
|
|
195
|
+
Java6Assertions.assertThat(uut.handleBack(CommandListenerAdapter())).isTrue
|
|
196
|
+
Java6Assertions.assertThat(uut.selectedIndex).isEqualTo(1)
|
|
197
|
+
|
|
198
|
+
Java6Assertions.assertThat(uut.handleBack(CommandListenerAdapter())).isTrue
|
|
199
|
+
Java6Assertions.assertThat(uut.selectedIndex).isEqualTo(0)
|
|
200
|
+
|
|
201
|
+
Java6Assertions.assertThat(uut.handleBack(CommandListenerAdapter())).isFalse
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
@Test
|
|
205
|
+
fun `handleBack - JumpToFirst - reselect first tab`() {
|
|
206
|
+
val options = Options().apply {
|
|
207
|
+
hardwareBack.bottomTabOnPress = HwBackBottomTabsBehaviour.JumpToFirst
|
|
208
|
+
}
|
|
209
|
+
prepareViewsForTests(options = options)
|
|
210
|
+
idleMainLooper()
|
|
211
|
+
Java6Assertions.assertThat(uut.selectedIndex).isEqualTo(0)
|
|
212
|
+
|
|
213
|
+
uut.selectTab(1)
|
|
214
|
+
Java6Assertions.assertThat(uut.selectedIndex).isEqualTo(1)
|
|
215
|
+
|
|
216
|
+
uut.selectTab(3)
|
|
217
|
+
Java6Assertions.assertThat(uut.selectedIndex).isEqualTo(3)
|
|
218
|
+
|
|
219
|
+
uut.selectTab(2)
|
|
220
|
+
Java6Assertions.assertThat(uut.selectedIndex).isEqualTo(2)
|
|
221
|
+
|
|
222
|
+
Java6Assertions.assertThat(uut.handleBack(CommandListenerAdapter())).isTrue
|
|
223
|
+
Java6Assertions.assertThat(uut.selectedIndex).isEqualTo(0)
|
|
224
|
+
|
|
225
|
+
Java6Assertions.assertThat(uut.handleBack(CommandListenerAdapter())).isFalse
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
@Test
|
|
229
|
+
fun `handleBack - Default - should exit app with no reselection`() {
|
|
230
|
+
|
|
231
|
+
prepareViewsForTests()
|
|
232
|
+
idleMainLooper()
|
|
233
|
+
Java6Assertions.assertThat(uut.selectedIndex).isEqualTo(0)
|
|
234
|
+
|
|
235
|
+
uut.selectTab(1)
|
|
236
|
+
Java6Assertions.assertThat(uut.selectedIndex).isEqualTo(1)
|
|
237
|
+
|
|
238
|
+
uut.selectTab(3)
|
|
239
|
+
Java6Assertions.assertThat(uut.selectedIndex).isEqualTo(3)
|
|
240
|
+
|
|
241
|
+
uut.selectTab(2)
|
|
242
|
+
Java6Assertions.assertThat(uut.selectedIndex).isEqualTo(2)
|
|
243
|
+
|
|
244
|
+
Java6Assertions.assertThat(uut.handleBack(CommandListenerAdapter())).isFalse
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
@Test
|
|
248
|
+
fun `handleBack - Exit - reselect first tab`() {
|
|
249
|
+
val options = Options().apply {
|
|
250
|
+
hardwareBack.bottomTabOnPress = HwBackBottomTabsBehaviour.Exit
|
|
251
|
+
}
|
|
252
|
+
prepareViewsForTests(options = options)
|
|
253
|
+
idleMainLooper()
|
|
254
|
+
Java6Assertions.assertThat(uut.selectedIndex).isEqualTo(0)
|
|
255
|
+
|
|
256
|
+
uut.selectTab(1)
|
|
257
|
+
Java6Assertions.assertThat(uut.selectedIndex).isEqualTo(1)
|
|
258
|
+
|
|
259
|
+
uut.selectTab(3)
|
|
260
|
+
Java6Assertions.assertThat(uut.selectedIndex).isEqualTo(3)
|
|
261
|
+
|
|
262
|
+
uut.selectTab(2)
|
|
263
|
+
Java6Assertions.assertThat(uut.selectedIndex).isEqualTo(2)
|
|
264
|
+
|
|
265
|
+
Java6Assertions.assertThat(uut.handleBack(CommandListenerAdapter())).isFalse
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
@Test
|
|
269
|
+
fun applyChildOptions_bottomTabsOptionsAreClearedAfterApply() {
|
|
270
|
+
val parent = Mockito.mock(ParentController::class.java)
|
|
271
|
+
uut.parentController = parent
|
|
272
|
+
child1.options.bottomTabsOptions.backgroundColor = ThemeColour(Colour(Color.RED))
|
|
273
|
+
child1.onViewWillAppear()
|
|
274
|
+
val optionsCaptor = ArgumentCaptor.forClass(
|
|
275
|
+
Options::class.java
|
|
276
|
+
)
|
|
277
|
+
Mockito.verify(parent).applyChildOptions(optionsCaptor.capture(), ArgumentMatchers.any())
|
|
278
|
+
Java6Assertions.assertThat(optionsCaptor.value.bottomTabsOptions.backgroundColor.hasValue()).isFalse
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
@Test
|
|
282
|
+
fun applyOptions_bottomTabsCreateViewOnlyOnce() {
|
|
283
|
+
idleMainLooper()
|
|
284
|
+
Mockito.verify(presenter).applyOptions(any())
|
|
285
|
+
Mockito.verify(bottomTabsContainer.bottomTabs, times(2))
|
|
286
|
+
.superCreateItems() // first time when view is created, second time when options are applied
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
@Test
|
|
290
|
+
fun onSizeChanged_recreateItemsIfSizeHasChanged() {
|
|
291
|
+
val numberOfPreviousInvocations = 1
|
|
292
|
+
bottomTabs.onSizeChanged(0, 0, 0, 0)
|
|
293
|
+
Mockito.verify(bottomTabs, Mockito.times(numberOfPreviousInvocations)).superCreateItems()
|
|
294
|
+
bottomTabs.onSizeChanged(100, 0, 0, 0)
|
|
295
|
+
Mockito.verify(bottomTabs, Mockito.times(numberOfPreviousInvocations)).superCreateItems()
|
|
296
|
+
bottomTabs.onSizeChanged(1080, 147, 0, 0)
|
|
297
|
+
Mockito.verify(bottomTabs, Mockito.times(numberOfPreviousInvocations + 1)).superCreateItems()
|
|
298
|
+
bottomTabs.onSizeChanged(1920, 147, 0, 0)
|
|
299
|
+
Mockito.verify(bottomTabs, Mockito.times(numberOfPreviousInvocations + 2)).superCreateItems()
|
|
300
|
+
Mockito.`when`(bottomTabs.itemsCount).thenReturn(0)
|
|
301
|
+
bottomTabs.onSizeChanged(1080, 147, 0, 0)
|
|
302
|
+
Mockito.verify(bottomTabs, Mockito.times(numberOfPreviousInvocations + 2)).superCreateItems()
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
@Test
|
|
306
|
+
fun mergeOptions_currentTabIndex() {
|
|
307
|
+
uut.ensureViewIsCreated()
|
|
308
|
+
Java6Assertions.assertThat(uut.selectedIndex).isZero
|
|
309
|
+
val options = Options()
|
|
310
|
+
options.bottomTabsOptions.currentTabIndex = Number(1)
|
|
311
|
+
uut.mergeOptions(options)
|
|
312
|
+
Java6Assertions.assertThat(uut.selectedIndex).isOne
|
|
313
|
+
Mockito.verify(eventEmitter, Mockito.times(0)).emitBottomTabSelected(
|
|
314
|
+
ArgumentMatchers.any(
|
|
315
|
+
Int::class.java
|
|
316
|
+
), ArgumentMatchers.any(Int::class.java)
|
|
317
|
+
)
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
@Test
|
|
321
|
+
fun mergeOptions_drawBehind() {
|
|
322
|
+
Java6Assertions.assertThat(uut.getBottomInset(child1)).isEqualTo(uut.bottomTabs.height)
|
|
323
|
+
val o1 = Options()
|
|
324
|
+
o1.bottomTabsOptions.drawBehind = Bool(true)
|
|
325
|
+
child1.mergeOptions(o1)
|
|
326
|
+
Java6Assertions.assertThat(uut.getBottomInset(child1)).isEqualTo(0)
|
|
327
|
+
val o2 = Options()
|
|
328
|
+
o2.topBar.title.text = Text("Some text")
|
|
329
|
+
child1.mergeOptions(o1)
|
|
330
|
+
Java6Assertions.assertThat(uut.getBottomInset(child1)).isEqualTo(0)
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
@Test
|
|
334
|
+
fun mergeOptions_drawBehind_stack() {
|
|
335
|
+
uut.ensureViewIsCreated()
|
|
336
|
+
uut.selectTab(3)
|
|
337
|
+
Java6Assertions.assertThat((stackChild.view.layoutParams as MarginLayoutParams).bottomMargin).isEqualTo(
|
|
338
|
+
bottomTabs.height
|
|
339
|
+
)
|
|
340
|
+
val o1 = Options()
|
|
341
|
+
o1.bottomTabsOptions.drawBehind = Bool(true)
|
|
342
|
+
stackChild.mergeOptions(o1)
|
|
343
|
+
Java6Assertions.assertThat((stackChild.view.layoutParams as MarginLayoutParams).bottomMargin).isEqualTo(0)
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
@Test
|
|
347
|
+
fun mergeOptions_mergesBottomTabOptions() {
|
|
348
|
+
val options = Options()
|
|
349
|
+
uut.mergeOptions(options)
|
|
350
|
+
Mockito.verify(bottomTabPresenter).mergeOptions(options)
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
@Test
|
|
354
|
+
fun applyChildOptions_resolvedOptionsAreUsed() {
|
|
355
|
+
val childOptions = Options()
|
|
356
|
+
val pushedScreen = SimpleViewController(activity, childRegistry, "child4.1", childOptions)
|
|
357
|
+
disablePushAnimation(pushedScreen)
|
|
358
|
+
child4 = spyOnStack(pushedScreen)
|
|
359
|
+
tabs = ArrayList(listOf(child4))
|
|
360
|
+
tabsAttacher = BottomTabsAttacher(tabs, presenter, Options.EMPTY)
|
|
361
|
+
initialOptions.bottomTabsOptions.currentTabIndex = Number(0)
|
|
362
|
+
val resolvedOptions = Options()
|
|
363
|
+
uut = object : BottomTabsController(
|
|
364
|
+
activity,
|
|
365
|
+
tabs,
|
|
366
|
+
childRegistry,
|
|
367
|
+
eventEmitter,
|
|
368
|
+
imageLoaderMock,
|
|
369
|
+
"uut",
|
|
370
|
+
initialOptions,
|
|
371
|
+
Presenter(activity, Options()),
|
|
372
|
+
tabsAttacher,
|
|
373
|
+
presenter,
|
|
374
|
+
BottomTabPresenter(activity, tabs, mock(), TypefaceLoaderMock(), Options())
|
|
375
|
+
) {
|
|
376
|
+
override fun resolveCurrentOptions(): Options {
|
|
377
|
+
return resolvedOptions
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
override fun createBottomTabs(): BottomTabs {
|
|
381
|
+
return object : BottomTabs(activity) {
|
|
382
|
+
override fun createItems() {}
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
activity.setContentView(uut.view)
|
|
387
|
+
idleMainLooper()
|
|
388
|
+
Mockito.verify(presenter, Mockito.times(2))
|
|
389
|
+
.applyChildOptions(eq(resolvedOptions), any())
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
@Test
|
|
393
|
+
fun child_mergeOptions_currentTabIndex() {
|
|
394
|
+
uut.ensureViewIsCreated()
|
|
395
|
+
Java6Assertions.assertThat(uut.selectedIndex).isZero
|
|
396
|
+
val options = Options()
|
|
397
|
+
options.bottomTabsOptions.currentTabIndex = Number(1)
|
|
398
|
+
child1.mergeOptions(options)
|
|
399
|
+
Java6Assertions.assertThat(uut.selectedIndex).isOne
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
@Test
|
|
403
|
+
fun resolveCurrentOptions_returnsFirstTabIfInvokedBeforeViewIsCreated() {
|
|
404
|
+
uut = createBottomTabs()
|
|
405
|
+
Java6Assertions.assertThat(uut.currentChild).isEqualTo(tabs[0])
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
@Test
|
|
409
|
+
fun buttonPressInvokedOnCurrentTab() {
|
|
410
|
+
uut.ensureViewIsCreated()
|
|
411
|
+
uut.selectTab(4)
|
|
412
|
+
uut.sendOnNavigationButtonPressed("btn1")
|
|
413
|
+
Mockito.verify(child5, Mockito.times(1)).sendOnNavigationButtonPressed("btn1")
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
@Test
|
|
417
|
+
fun push() {
|
|
418
|
+
uut.selectTab(3)
|
|
419
|
+
val stackChild2 = SimpleViewController(activity, childRegistry, "stackChild2", Options())
|
|
420
|
+
disablePushAnimation(stackChild2)
|
|
421
|
+
TestUtils.hideBackButton(stackChild2)
|
|
422
|
+
Java6Assertions.assertThat(child4.size()).isEqualTo(1)
|
|
423
|
+
child4.push(stackChild2, CommandListenerAdapter())
|
|
424
|
+
Java6Assertions.assertThat(child4.size()).isEqualTo(2)
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
@Test
|
|
428
|
+
fun oneTimeOptionsAreAppliedOnce() {
|
|
429
|
+
val options = Options()
|
|
430
|
+
options.bottomTabsOptions.currentTabIndex = Number(1)
|
|
431
|
+
Java6Assertions.assertThat(uut.selectedIndex).isZero
|
|
432
|
+
uut.mergeOptions(options)
|
|
433
|
+
Java6Assertions.assertThat(uut.selectedIndex).isOne
|
|
434
|
+
Java6Assertions.assertThat(uut.options.bottomTabsOptions.currentTabIndex.hasValue()).isFalse
|
|
435
|
+
Java6Assertions.assertThat(uut.initialOptions.bottomTabsOptions.currentTabIndex.hasValue()).isFalse
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
@Test
|
|
439
|
+
fun selectTab() {
|
|
440
|
+
uut.selectTab(1)
|
|
441
|
+
Mockito.verify(tabsAttacher).onTabSelected(tabs[1])
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
@Test
|
|
445
|
+
fun selectTab_onViewDidAppearIsInvokedAfterSelection() {
|
|
446
|
+
uut.selectTab(1)
|
|
447
|
+
Mockito.verify(child2).onViewDidAppear()
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
@Test
|
|
451
|
+
fun creatingTabs_onViewDidAppearInvokedAfterInitialTabIndexSet() {
|
|
452
|
+
val options = Options.EMPTY.copy()
|
|
453
|
+
options.bottomTabsOptions.currentTabIndex = Number(1)
|
|
454
|
+
prepareViewsForTests(options.bottomTabsOptions)
|
|
455
|
+
idleMainLooper()
|
|
456
|
+
Mockito.verify(tabs[0], Mockito.times(0)).onViewDidAppear()
|
|
457
|
+
Mockito.verify(tabs[1], Mockito.times(1)).onViewDidAppear()
|
|
458
|
+
Mockito.verify(tabs[2], Mockito.times(0)).onViewDidAppear()
|
|
459
|
+
Mockito.verify(tabs[3], Mockito.times(0)).onViewDidAppear()
|
|
460
|
+
Mockito.verify(tabs[4], Mockito.times(0)).onViewDidAppear()
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
@Test
|
|
464
|
+
fun topInset() {
|
|
465
|
+
Java6Assertions.assertThat(child1.topInset).isEqualTo(statusBarHeight)
|
|
466
|
+
Java6Assertions.assertThat(child2.topInset).isEqualTo(statusBarHeight)
|
|
467
|
+
child1.options.statusBar.drawBehind = Bool(true)
|
|
468
|
+
Java6Assertions.assertThat(child1.topInset).isEqualTo(0)
|
|
469
|
+
Java6Assertions.assertThat(child2.topInset).isEqualTo(statusBarHeight)
|
|
470
|
+
Java6Assertions.assertThat(stackChild.topInset).isEqualTo(statusBarHeight + child4.topBar.height)
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
@Test
|
|
474
|
+
fun bottomInset_defaultOptionsAreTakenIntoAccount() {
|
|
475
|
+
val defaultOptions = Options()
|
|
476
|
+
defaultOptions.bottomTabsOptions.visible = Bool(false)
|
|
477
|
+
Java6Assertions.assertThat(uut.getBottomInset(child1)).isEqualTo(bottomTabs.height)
|
|
478
|
+
uut.setDefaultOptions(defaultOptions)
|
|
479
|
+
Java6Assertions.assertThat(uut.getBottomInset(child1)).isZero
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
@Test
|
|
483
|
+
fun destroy() {
|
|
484
|
+
uut.destroy()
|
|
485
|
+
Mockito.verify(tabsAttacher).destroy()
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
private fun prepareViewsForTests(
|
|
489
|
+
bottomTabsOptions: BottomTabsOptions = initialOptions.bottomTabsOptions,
|
|
490
|
+
options: Options = initialOptions, defaultOptions: Options = initialOptions
|
|
491
|
+
) {
|
|
492
|
+
if(::uut.isInitialized){
|
|
493
|
+
uut.destroy()
|
|
494
|
+
}
|
|
495
|
+
// ObjectUtils.perform(uut, { obj: BottomTabsController -> obj.destroy() })
|
|
496
|
+
bottomTabs = Mockito.spy(object : BottomTabs(activity) {
|
|
497
|
+
override fun superCreateItems() {}
|
|
498
|
+
})
|
|
499
|
+
bottomTabsContainer = Mockito.spy(BottomTabsContainer(activity, bottomTabs))
|
|
500
|
+
createChildren()
|
|
501
|
+
tabs = mutableListOf(child1, child2, child3, child4, child5)
|
|
502
|
+
defaultOptions.bottomTabsOptions = bottomTabsOptions
|
|
503
|
+
presenter = Mockito.spy(BottomTabsPresenter(tabs, defaultOptions, BottomTabsAnimator()))
|
|
504
|
+
bottomTabPresenter =
|
|
505
|
+
Mockito.spy(BottomTabPresenter(activity, tabs, mock(), TypefaceLoaderMock(), defaultOptions))
|
|
506
|
+
tabsAttacher = Mockito.spy(BottomTabsAttacher(tabs, presenter, defaultOptions))
|
|
507
|
+
uut = createBottomTabs(options = options, defaultOptions = defaultOptions)
|
|
508
|
+
activity.setContentView(FakeParentController(activity, childRegistry, uut).view)
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
private fun createChildren() {
|
|
512
|
+
child1 = Mockito.spy(SimpleViewController(activity, childRegistry, "child1", tabOptions))
|
|
513
|
+
child2 = Mockito.spy(SimpleViewController(activity, childRegistry, "child2", tabOptions))
|
|
514
|
+
child3 = Mockito.spy(SimpleViewController(activity, childRegistry, "child3", tabOptions))
|
|
515
|
+
stackChild = Mockito.spy(SimpleViewController(activity, childRegistry, "stackChild", tabOptions))
|
|
516
|
+
child4 = spyOnStack(stackChild)
|
|
517
|
+
child5 = Mockito.spy(SimpleViewController(activity, childRegistry, "child5", tabOptions))
|
|
518
|
+
Mockito.`when`(child5.handleBack(any())).thenReturn(true)
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
private fun spyOnStack(initialChild: ViewController<*>?): StackController {
|
|
522
|
+
val build = TestUtils.newStackController(activity)
|
|
523
|
+
.setInitialOptions(tabOptions)
|
|
524
|
+
.build()
|
|
525
|
+
val stack = Mockito.spy(build)
|
|
526
|
+
disablePushAnimation(initialChild)
|
|
527
|
+
stack.ensureViewIsCreated()
|
|
528
|
+
stack.push(initialChild, CommandListenerAdapter())
|
|
529
|
+
return stack
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
private fun createBottomTabs(
|
|
533
|
+
options: Options = initialOptions,
|
|
534
|
+
defaultOptions: Options = initialOptions
|
|
535
|
+
): BottomTabsController {
|
|
536
|
+
return object : BottomTabsController(
|
|
537
|
+
activity,
|
|
538
|
+
tabs,
|
|
539
|
+
childRegistry,
|
|
540
|
+
eventEmitter,
|
|
541
|
+
imageLoaderMock,
|
|
542
|
+
"uut",
|
|
543
|
+
options,
|
|
544
|
+
Presenter(activity, defaultOptions),
|
|
545
|
+
tabsAttacher,
|
|
546
|
+
presenter,
|
|
547
|
+
bottomTabPresenter
|
|
548
|
+
) {
|
|
549
|
+
override fun ensureViewIsCreated() {
|
|
550
|
+
super.ensureViewIsCreated()
|
|
551
|
+
uut.view.layout(0, 0, 1000, 1000)
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
override fun createView(): BottomTabsLayout {
|
|
555
|
+
val view = super.createView()
|
|
556
|
+
this@BottomTabsControllerTest.bottomTabs.layoutParams.height = 100
|
|
557
|
+
return view
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
override fun createBottomTabsContainer(): BottomTabsContainer {
|
|
561
|
+
return this@BottomTabsControllerTest.bottomTabsContainer
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
override fun createBottomTabs(): BottomTabs {
|
|
565
|
+
return this@BottomTabsControllerTest.bottomTabs
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
private val statusBarHeight: Int
|
|
571
|
+
get() = getStatusBarHeight(activity)
|
|
572
|
+
}
|
|
@@ -360,6 +360,10 @@ export interface HardwareBackButtonOptions {
|
|
|
360
360
|
* @default true
|
|
361
361
|
*/
|
|
362
362
|
popStackOnPress?: boolean;
|
|
363
|
+
/**
|
|
364
|
+
* Controls hardware back button bottom tab selection behaviour
|
|
365
|
+
*/
|
|
366
|
+
bottomTabsOnPress?: 'exit' | 'first' | 'previous';
|
|
363
367
|
}
|
|
364
368
|
export interface OptionsTopBarScrollEdgeAppearanceBackground {
|
|
365
369
|
/**
|
|
@@ -414,6 +414,11 @@ export interface HardwareBackButtonOptions {
|
|
|
414
414
|
* @default true
|
|
415
415
|
*/
|
|
416
416
|
popStackOnPress?: boolean;
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* Controls hardware back button bottom tab selection behaviour
|
|
420
|
+
*/
|
|
421
|
+
bottomTabsOnPress?: 'exit' | 'first' | 'previous';
|
|
417
422
|
}
|
|
418
423
|
|
|
419
424
|
export interface OptionsTopBarScrollEdgeAppearanceBackground {
|
package/package.json
CHANGED
|
@@ -1,514 +0,0 @@
|
|
|
1
|
-
package com.reactnativenavigation.viewcontrollers.bottomtabs;
|
|
2
|
-
|
|
3
|
-
import android.app.Activity;
|
|
4
|
-
import android.graphics.Color;
|
|
5
|
-
import android.view.Gravity;
|
|
6
|
-
import android.view.View;
|
|
7
|
-
import android.view.ViewGroup.MarginLayoutParams;
|
|
8
|
-
|
|
9
|
-
import com.aurelhubert.ahbottomnavigation.AHBottomNavigation;
|
|
10
|
-
import com.reactnativenavigation.BaseTest;
|
|
11
|
-
import com.reactnativenavigation.TestUtils;
|
|
12
|
-
import com.reactnativenavigation.mocks.ImageLoaderMock;
|
|
13
|
-
import com.reactnativenavigation.mocks.SimpleViewController;
|
|
14
|
-
import com.reactnativenavigation.mocks.TypefaceLoaderMock;
|
|
15
|
-
import com.reactnativenavigation.options.BottomTabsOptions;
|
|
16
|
-
import com.reactnativenavigation.options.Options;
|
|
17
|
-
import com.reactnativenavigation.options.params.Bool;
|
|
18
|
-
import com.reactnativenavigation.options.params.Colour;
|
|
19
|
-
import com.reactnativenavigation.options.params.NullText;
|
|
20
|
-
import com.reactnativenavigation.options.params.Number;
|
|
21
|
-
import com.reactnativenavigation.options.params.ThemeColour;
|
|
22
|
-
import com.reactnativenavigation.options.params.Text;
|
|
23
|
-
import com.reactnativenavigation.react.CommandListenerAdapter;
|
|
24
|
-
import com.reactnativenavigation.react.events.EventEmitter;
|
|
25
|
-
import com.reactnativenavigation.utils.ImageLoader;
|
|
26
|
-
import com.reactnativenavigation.utils.OptionHelper;
|
|
27
|
-
import com.reactnativenavigation.utils.SystemUiUtils;
|
|
28
|
-
import com.reactnativenavigation.viewcontrollers.bottomtabs.attacher.BottomTabsAttacher;
|
|
29
|
-
import com.reactnativenavigation.viewcontrollers.child.ChildControllersRegistry;
|
|
30
|
-
import com.reactnativenavigation.viewcontrollers.fakes.FakeParentController;
|
|
31
|
-
import com.reactnativenavigation.viewcontrollers.parent.ParentController;
|
|
32
|
-
import com.reactnativenavigation.viewcontrollers.stack.StackController;
|
|
33
|
-
import com.reactnativenavigation.viewcontrollers.viewcontroller.Presenter;
|
|
34
|
-
import com.reactnativenavigation.viewcontrollers.viewcontroller.ViewController;
|
|
35
|
-
import com.reactnativenavigation.views.bottomtabs.BottomTabs;
|
|
36
|
-
import com.reactnativenavigation.views.bottomtabs.BottomTabsContainer;
|
|
37
|
-
import com.reactnativenavigation.views.bottomtabs.BottomTabsLayout;
|
|
38
|
-
|
|
39
|
-
import org.junit.Test;
|
|
40
|
-
import org.mockito.ArgumentCaptor;
|
|
41
|
-
import org.mockito.Mockito;
|
|
42
|
-
|
|
43
|
-
import java.util.ArrayList;
|
|
44
|
-
import java.util.Arrays;
|
|
45
|
-
import java.util.Collections;
|
|
46
|
-
import java.util.List;
|
|
47
|
-
|
|
48
|
-
import androidx.annotation.NonNull;
|
|
49
|
-
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
import static com.reactnativenavigation.TestUtils.hideBackButton;
|
|
53
|
-
import static com.reactnativenavigation.utils.ObjectUtils.perform;
|
|
54
|
-
import static org.assertj.core.api.Java6Assertions.assertThat;
|
|
55
|
-
import static org.mockito.ArgumentMatchers.any;
|
|
56
|
-
import static org.mockito.ArgumentMatchers.eq;
|
|
57
|
-
import static org.mockito.Mockito.spy;
|
|
58
|
-
import static org.mockito.Mockito.times;
|
|
59
|
-
import static org.mockito.Mockito.verify;
|
|
60
|
-
import static org.mockito.Mockito.when;
|
|
61
|
-
|
|
62
|
-
public class BottomTabsControllerTest extends BaseTest {
|
|
63
|
-
|
|
64
|
-
private Activity activity;
|
|
65
|
-
private BottomTabs bottomTabs;
|
|
66
|
-
private BottomTabsContainer bottomTabsContainer;
|
|
67
|
-
private BottomTabsController uut;
|
|
68
|
-
private final Options initialOptions = new Options();
|
|
69
|
-
private ViewController<?> child1;
|
|
70
|
-
private ViewController<?> child2;
|
|
71
|
-
private ViewController<?> child3;
|
|
72
|
-
private ViewController<?> stackChild;
|
|
73
|
-
private StackController child4;
|
|
74
|
-
private ViewController<?> child5;
|
|
75
|
-
private final Options tabOptions = OptionHelper.createBottomTabOptions();
|
|
76
|
-
private final ImageLoader imageLoaderMock = ImageLoaderMock.mock();
|
|
77
|
-
private EventEmitter eventEmitter;
|
|
78
|
-
private ChildControllersRegistry childRegistry;
|
|
79
|
-
private List<ViewController<?>> tabs;
|
|
80
|
-
private BottomTabsPresenter presenter;
|
|
81
|
-
private BottomTabPresenter bottomTabPresenter;
|
|
82
|
-
private BottomTabsAttacher tabsAttacher;
|
|
83
|
-
|
|
84
|
-
@Override
|
|
85
|
-
public void beforeEach() {
|
|
86
|
-
activity = newActivity();
|
|
87
|
-
childRegistry = new ChildControllersRegistry();
|
|
88
|
-
eventEmitter = Mockito.mock(EventEmitter.class);
|
|
89
|
-
prepareViewsForTests();
|
|
90
|
-
SystemUiUtils.saveStatusBarHeight(63);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
@Test
|
|
94
|
-
public void createView_checkProperStructure() {
|
|
95
|
-
idleMainLooper();
|
|
96
|
-
assertThat(uut.getView()).isInstanceOf(CoordinatorLayout.class);
|
|
97
|
-
assertThat(uut.getView().getChildAt(uut.getView().getChildCount() - 1)).isInstanceOf(BottomTabsContainer.class);
|
|
98
|
-
assertThat(((CoordinatorLayout.LayoutParams) uut.getBottomTabsContainer().getLayoutParams()).gravity).isEqualTo(Gravity.BOTTOM);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
@Test
|
|
102
|
-
public void createView_tabsWithoutIconsAreAccepted() {
|
|
103
|
-
tabOptions.bottomTabOptions.icon = new NullText();
|
|
104
|
-
prepareViewsForTests();
|
|
105
|
-
assertThat(uut.getBottomTabs().getItemsCount()).isEqualTo(tabs.size());
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
@Test
|
|
109
|
-
public void createView_showTitlesWhenAllTabsDontHaveIcons() {
|
|
110
|
-
tabOptions.bottomTabOptions.icon = new NullText();
|
|
111
|
-
assertThat(tabOptions.bottomTabsOptions.titleDisplayMode.hasValue()).isFalse();
|
|
112
|
-
prepareViewsForTests();
|
|
113
|
-
presenter.applyOptions(Options.EMPTY);
|
|
114
|
-
assertThat(bottomTabsContainer.getBottomTabs().getTitleState()).isEqualTo(AHBottomNavigation.TitleState.ALWAYS_SHOW);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
@Test(expected = RuntimeException.class)
|
|
118
|
-
public void setTabs_ThrowWhenMoreThan5() {
|
|
119
|
-
tabs.add(new SimpleViewController(activity, childRegistry, "6", tabOptions));
|
|
120
|
-
createBottomTabs();
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
@Test
|
|
124
|
-
public void parentControllerIsSet() {
|
|
125
|
-
uut = createBottomTabs();
|
|
126
|
-
for (ViewController<?> tab : tabs) {
|
|
127
|
-
assertThat(tab.getParentController()).isEqualTo(uut);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
@Test
|
|
132
|
-
public void setTabs_allChildViewsAreAttachedToHierarchy() {
|
|
133
|
-
uut.onViewWillAppear();
|
|
134
|
-
assertThat(uut.getView().getChildCount()).isEqualTo(6);
|
|
135
|
-
for (ViewController<?> child : uut.getChildControllers()) {
|
|
136
|
-
assertThat(child.getView().getParent()).isNotNull();
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
@Test
|
|
141
|
-
public void setTabs_firstChildIsVisibleOtherAreGone() {
|
|
142
|
-
uut.onViewWillAppear();
|
|
143
|
-
for (int i = 0; i < uut.getChildControllers().size(); i++) {
|
|
144
|
-
assertThat(uut.getView().getChildAt(i)).isEqualTo(tabs.get(i).getView());
|
|
145
|
-
assertThat(uut.getView().getChildAt(i).getVisibility()).isEqualTo(i == 0 ? View.VISIBLE : View.INVISIBLE);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
@Test
|
|
150
|
-
public void onTabSelected() {
|
|
151
|
-
uut.ensureViewIsCreated();
|
|
152
|
-
assertThat(uut.getSelectedIndex()).isZero();
|
|
153
|
-
assertThat(((ViewController<?>) ((List<?>) uut.getChildControllers()).get(0)).getView().getVisibility()).isEqualTo(View.VISIBLE);
|
|
154
|
-
|
|
155
|
-
uut.onTabSelected(3, false);
|
|
156
|
-
|
|
157
|
-
assertThat(uut.getSelectedIndex()).isEqualTo(3);
|
|
158
|
-
assertThat(((ViewController<?>) ((List<?>) uut.getChildControllers()).get(0)).getView().getVisibility()).isEqualTo(View.INVISIBLE);
|
|
159
|
-
assertThat(((ViewController<?>) ((List<?>) uut.getChildControllers()).get(3)).getView().getVisibility()).isEqualTo(View.VISIBLE);
|
|
160
|
-
verify(eventEmitter).emitBottomTabSelected(0, 3);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
@Test
|
|
164
|
-
public void onTabReSelected() {
|
|
165
|
-
uut.ensureViewIsCreated();
|
|
166
|
-
assertThat(uut.getSelectedIndex()).isZero();
|
|
167
|
-
|
|
168
|
-
uut.onTabSelected(0, true);
|
|
169
|
-
|
|
170
|
-
assertThat(uut.getSelectedIndex()).isEqualTo(0);
|
|
171
|
-
assertThat(((ViewController<?>) ((List<?>) uut.getChildControllers()).get(0)).getView().getParent()).isNotNull();
|
|
172
|
-
verify(eventEmitter).emitBottomTabSelected(0, 0);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
@Test
|
|
176
|
-
public void handleBack_DelegatesToSelectedChild() {
|
|
177
|
-
uut.ensureViewIsCreated();
|
|
178
|
-
assertThat(uut.handleBack(new CommandListenerAdapter())).isFalse();
|
|
179
|
-
uut.selectTab(4);
|
|
180
|
-
assertThat(uut.handleBack(new CommandListenerAdapter())).isTrue();
|
|
181
|
-
verify(child5).handleBack(any());
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
@Test
|
|
185
|
-
public void applyChildOptions_bottomTabsOptionsAreClearedAfterApply() {
|
|
186
|
-
ParentController<?> parent = Mockito.mock(ParentController.class);
|
|
187
|
-
Mockito.when(parent.resolveChildOptions(uut)).thenReturn(Options.EMPTY);
|
|
188
|
-
Mockito.when(parent.resolveChildOptions(child1)).thenReturn(Options.EMPTY);
|
|
189
|
-
|
|
190
|
-
uut.setParentController(parent);
|
|
191
|
-
|
|
192
|
-
child1.options.bottomTabsOptions.backgroundColor = new ThemeColour(new Colour(Color.RED));
|
|
193
|
-
child1.onViewWillAppear();
|
|
194
|
-
|
|
195
|
-
ArgumentCaptor<Options> optionsCaptor = ArgumentCaptor.forClass(Options.class);
|
|
196
|
-
verify(parent).applyChildOptions(optionsCaptor.capture(), any());
|
|
197
|
-
assertThat(optionsCaptor.getValue().bottomTabsOptions.backgroundColor.hasValue()).isFalse();
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
@Test
|
|
201
|
-
public void applyOptions_bottomTabsCreateViewOnlyOnce() {
|
|
202
|
-
idleMainLooper();
|
|
203
|
-
verify(presenter).applyOptions(any());
|
|
204
|
-
verify(bottomTabsContainer.getBottomTabs(), times(2)).superCreateItems(); // first time when view is created, second time when options are applied
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
@Test
|
|
208
|
-
public void onSizeChanged_recreateItemsIfSizeHasChanged() {
|
|
209
|
-
int numberOfPreviousInvocations = 1;
|
|
210
|
-
bottomTabs.onSizeChanged(0, 0, 0, 0);
|
|
211
|
-
verify(bottomTabs, times(numberOfPreviousInvocations)).superCreateItems();
|
|
212
|
-
|
|
213
|
-
bottomTabs.onSizeChanged(100, 0, 0, 0);
|
|
214
|
-
verify(bottomTabs, times(numberOfPreviousInvocations)).superCreateItems();
|
|
215
|
-
|
|
216
|
-
bottomTabs.onSizeChanged(1080, 147, 0, 0);
|
|
217
|
-
verify(bottomTabs, times(numberOfPreviousInvocations + 1)).superCreateItems();
|
|
218
|
-
|
|
219
|
-
bottomTabs.onSizeChanged(1920, 147, 0, 0);
|
|
220
|
-
verify(bottomTabs, times(numberOfPreviousInvocations + 2)).superCreateItems();
|
|
221
|
-
|
|
222
|
-
when(bottomTabs.getItemsCount()).thenReturn(0);
|
|
223
|
-
bottomTabs.onSizeChanged(1080, 147, 0, 0);
|
|
224
|
-
verify(bottomTabs, times(numberOfPreviousInvocations + 2)).superCreateItems();
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
@Test
|
|
228
|
-
public void mergeOptions_currentTabIndex() {
|
|
229
|
-
uut.ensureViewIsCreated();
|
|
230
|
-
assertThat(uut.getSelectedIndex()).isZero();
|
|
231
|
-
|
|
232
|
-
Options options = new Options();
|
|
233
|
-
options.bottomTabsOptions.currentTabIndex = new Number(1);
|
|
234
|
-
uut.mergeOptions(options);
|
|
235
|
-
assertThat(uut.getSelectedIndex()).isOne();
|
|
236
|
-
verify(eventEmitter, times(0)).emitBottomTabSelected(any(Integer.class), any(Integer.class));
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
@Test
|
|
240
|
-
public void mergeOptions_drawBehind() {
|
|
241
|
-
assertThat(uut.getBottomInset(child1)).isEqualTo(uut.getBottomTabs().getHeight());
|
|
242
|
-
|
|
243
|
-
Options o1 = new Options();
|
|
244
|
-
o1.bottomTabsOptions.drawBehind = new Bool(true);
|
|
245
|
-
child1.mergeOptions(o1);
|
|
246
|
-
assertThat(uut.getBottomInset(child1)).isEqualTo(0);
|
|
247
|
-
|
|
248
|
-
Options o2 = new Options();
|
|
249
|
-
o2.topBar.title.text = new Text("Some text");
|
|
250
|
-
child1.mergeOptions(o1);
|
|
251
|
-
assertThat(uut.getBottomInset(child1)).isEqualTo(0);
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
@Test
|
|
255
|
-
public void mergeOptions_drawBehind_stack() {
|
|
256
|
-
uut.ensureViewIsCreated();
|
|
257
|
-
uut.selectTab(3);
|
|
258
|
-
|
|
259
|
-
assertThat(((MarginLayoutParams) stackChild.getView().getLayoutParams()).bottomMargin).isEqualTo(bottomTabs.getHeight());
|
|
260
|
-
|
|
261
|
-
Options o1 = new Options();
|
|
262
|
-
o1.bottomTabsOptions.drawBehind = new Bool(true);
|
|
263
|
-
stackChild.mergeOptions(o1);
|
|
264
|
-
|
|
265
|
-
assertThat(((MarginLayoutParams) stackChild.getView().getLayoutParams()).bottomMargin).isEqualTo(0);
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
@Test
|
|
269
|
-
public void mergeOptions_mergesBottomTabOptions() {
|
|
270
|
-
Options options = new Options();
|
|
271
|
-
uut.mergeOptions(options);
|
|
272
|
-
verify(bottomTabPresenter).mergeOptions(options);
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
@Test
|
|
276
|
-
public void applyChildOptions_resolvedOptionsAreUsed() {
|
|
277
|
-
Options childOptions = new Options();
|
|
278
|
-
SimpleViewController pushedScreen = new SimpleViewController(activity, childRegistry, "child4.1", childOptions);
|
|
279
|
-
disablePushAnimation(pushedScreen);
|
|
280
|
-
child4 = spyOnStack(pushedScreen);
|
|
281
|
-
|
|
282
|
-
tabs = new ArrayList<>(Collections.singletonList(child4));
|
|
283
|
-
tabsAttacher = new BottomTabsAttacher(tabs, presenter, Options.EMPTY);
|
|
284
|
-
|
|
285
|
-
initialOptions.bottomTabsOptions.currentTabIndex = new Number(0);
|
|
286
|
-
Options resolvedOptions = new Options();
|
|
287
|
-
uut = new BottomTabsController(activity,
|
|
288
|
-
tabs,
|
|
289
|
-
childRegistry,
|
|
290
|
-
eventEmitter,
|
|
291
|
-
imageLoaderMock,
|
|
292
|
-
"uut",
|
|
293
|
-
initialOptions,
|
|
294
|
-
new Presenter(activity, new Options()),
|
|
295
|
-
tabsAttacher,
|
|
296
|
-
presenter,
|
|
297
|
-
new BottomTabPresenter(activity, tabs, ImageLoaderMock.mock(), new TypefaceLoaderMock(), new Options())) {
|
|
298
|
-
@Override
|
|
299
|
-
public Options resolveCurrentOptions() {
|
|
300
|
-
return resolvedOptions;
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
@NonNull
|
|
304
|
-
@Override
|
|
305
|
-
protected BottomTabs createBottomTabs() {
|
|
306
|
-
return new BottomTabs(activity) {
|
|
307
|
-
@Override
|
|
308
|
-
protected void createItems() {
|
|
309
|
-
|
|
310
|
-
}
|
|
311
|
-
};
|
|
312
|
-
}
|
|
313
|
-
};
|
|
314
|
-
|
|
315
|
-
activity.setContentView(uut.getView());
|
|
316
|
-
idleMainLooper();
|
|
317
|
-
verify(presenter, times(2)).applyChildOptions(eq(resolvedOptions), any());
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
@Test
|
|
321
|
-
public void child_mergeOptions_currentTabIndex() {
|
|
322
|
-
uut.ensureViewIsCreated();
|
|
323
|
-
|
|
324
|
-
assertThat(uut.getSelectedIndex()).isZero();
|
|
325
|
-
|
|
326
|
-
Options options = new Options();
|
|
327
|
-
options.bottomTabsOptions.currentTabIndex = new Number(1);
|
|
328
|
-
child1.mergeOptions(options);
|
|
329
|
-
|
|
330
|
-
assertThat(uut.getSelectedIndex()).isOne();
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
@Test
|
|
334
|
-
public void resolveCurrentOptions_returnsFirstTabIfInvokedBeforeViewIsCreated() {
|
|
335
|
-
uut = createBottomTabs();
|
|
336
|
-
assertThat(uut.getCurrentChild()).isEqualTo(tabs.get(0));
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
@Test
|
|
340
|
-
public void buttonPressInvokedOnCurrentTab() {
|
|
341
|
-
uut.ensureViewIsCreated();
|
|
342
|
-
uut.selectTab(4);
|
|
343
|
-
|
|
344
|
-
uut.sendOnNavigationButtonPressed("btn1");
|
|
345
|
-
verify(child5, times(1)).sendOnNavigationButtonPressed("btn1");
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
@Test
|
|
349
|
-
public void push() {
|
|
350
|
-
uut.selectTab(3);
|
|
351
|
-
|
|
352
|
-
SimpleViewController stackChild2 = new SimpleViewController(activity, childRegistry, "stackChild2", new Options());
|
|
353
|
-
disablePushAnimation(stackChild2);
|
|
354
|
-
hideBackButton(stackChild2);
|
|
355
|
-
|
|
356
|
-
assertThat(child4.size()).isEqualTo(1);
|
|
357
|
-
child4.push(stackChild2, new CommandListenerAdapter());
|
|
358
|
-
assertThat(child4.size()).isEqualTo(2);
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
@Test
|
|
362
|
-
public void oneTimeOptionsAreAppliedOnce() {
|
|
363
|
-
Options options = new Options();
|
|
364
|
-
options.bottomTabsOptions.currentTabIndex = new Number(1);
|
|
365
|
-
|
|
366
|
-
assertThat(uut.getSelectedIndex()).isZero();
|
|
367
|
-
uut.mergeOptions(options);
|
|
368
|
-
assertThat(uut.getSelectedIndex()).isOne();
|
|
369
|
-
assertThat(uut.options.bottomTabsOptions.currentTabIndex.hasValue()).isFalse();
|
|
370
|
-
assertThat(uut.initialOptions.bottomTabsOptions.currentTabIndex.hasValue()).isFalse();
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
@Test
|
|
374
|
-
public void selectTab() {
|
|
375
|
-
uut.selectTab(1);
|
|
376
|
-
verify(tabsAttacher).onTabSelected(tabs.get(1));
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
@Test
|
|
380
|
-
public void selectTab_onViewDidAppearIsInvokedAfterSelection() {
|
|
381
|
-
uut.selectTab(1);
|
|
382
|
-
verify(child2).onViewDidAppear();
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
@Test
|
|
386
|
-
public void creatingTabs_onViewDidAppearInvokedAfterInitialTabIndexSet() {
|
|
387
|
-
Options options = Options.EMPTY.copy();
|
|
388
|
-
options.bottomTabsOptions.currentTabIndex = new Number(1);
|
|
389
|
-
prepareViewsForTests(options.bottomTabsOptions);
|
|
390
|
-
idleMainLooper();
|
|
391
|
-
verify(tabs.get(0), times(0)).onViewDidAppear();
|
|
392
|
-
verify(tabs.get(1), times(1)).onViewDidAppear();
|
|
393
|
-
verify(tabs.get(2), times(0)).onViewDidAppear();
|
|
394
|
-
verify(tabs.get(3), times(0)).onViewDidAppear();
|
|
395
|
-
verify(tabs.get(4), times(0)).onViewDidAppear();
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
@Test
|
|
399
|
-
public void getTopInset() {
|
|
400
|
-
assertThat(child1.getTopInset()).isEqualTo(getStatusBarHeight());
|
|
401
|
-
assertThat(child2.getTopInset()).isEqualTo(getStatusBarHeight());
|
|
402
|
-
|
|
403
|
-
child1.options.statusBar.drawBehind = new Bool(true);
|
|
404
|
-
assertThat(child1.getTopInset()).isEqualTo(0);
|
|
405
|
-
assertThat(child2.getTopInset()).isEqualTo(getStatusBarHeight());
|
|
406
|
-
|
|
407
|
-
assertThat(stackChild.getTopInset()).isEqualTo(getStatusBarHeight() + child4.getTopBar().getHeight());
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
@Test
|
|
411
|
-
public void getBottomInset_defaultOptionsAreTakenIntoAccount() {
|
|
412
|
-
Options defaultOptions = new Options();
|
|
413
|
-
defaultOptions.bottomTabsOptions.visible = new Bool(false);
|
|
414
|
-
|
|
415
|
-
assertThat(uut.getBottomInset(child1)).isEqualTo(bottomTabs.getHeight());
|
|
416
|
-
uut.setDefaultOptions(defaultOptions);
|
|
417
|
-
assertThat(uut.getBottomInset(child1)).isZero();
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
@Test
|
|
421
|
-
public void destroy() {
|
|
422
|
-
uut.destroy();
|
|
423
|
-
verify(tabsAttacher).destroy();
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
private void prepareViewsForTests() {
|
|
427
|
-
prepareViewsForTests(initialOptions.bottomTabsOptions);
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
private void prepareViewsForTests(BottomTabsOptions bottomTabsOptions) {
|
|
431
|
-
perform(uut, ViewController::destroy);
|
|
432
|
-
bottomTabs = spy(new BottomTabs(activity) {
|
|
433
|
-
@Override
|
|
434
|
-
public void superCreateItems() {
|
|
435
|
-
|
|
436
|
-
}
|
|
437
|
-
});
|
|
438
|
-
bottomTabsContainer = spy(new BottomTabsContainer(activity, bottomTabs));
|
|
439
|
-
|
|
440
|
-
createChildren();
|
|
441
|
-
tabs = Arrays.asList(child1, child2, child3, child4, child5);
|
|
442
|
-
initialOptions.bottomTabsOptions = bottomTabsOptions;
|
|
443
|
-
presenter = spy(new BottomTabsPresenter(tabs, initialOptions, new BottomTabsAnimator()));
|
|
444
|
-
bottomTabPresenter = spy(new BottomTabPresenter(activity, tabs, ImageLoaderMock.mock(), new TypefaceLoaderMock(), initialOptions));
|
|
445
|
-
tabsAttacher = spy(new BottomTabsAttacher(tabs, presenter, initialOptions));
|
|
446
|
-
uut = createBottomTabs();
|
|
447
|
-
activity.setContentView(new FakeParentController(activity, childRegistry, uut).getView());
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
private void createChildren() {
|
|
451
|
-
child1 = spy(new SimpleViewController(activity, childRegistry, "child1", tabOptions));
|
|
452
|
-
child2 = spy(new SimpleViewController(activity, childRegistry, "child2", tabOptions));
|
|
453
|
-
child3 = spy(new SimpleViewController(activity, childRegistry, "child3", tabOptions));
|
|
454
|
-
stackChild = spy(new SimpleViewController(activity, childRegistry, "stackChild", tabOptions));
|
|
455
|
-
child4 = spyOnStack(stackChild);
|
|
456
|
-
child5 = spy(new SimpleViewController(activity, childRegistry, "child5", tabOptions));
|
|
457
|
-
when(child5.handleBack(any())).thenReturn(true);
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
private StackController spyOnStack(ViewController<?> initialChild) {
|
|
461
|
-
StackController build = TestUtils.newStackController(activity)
|
|
462
|
-
.setInitialOptions(tabOptions)
|
|
463
|
-
.build();
|
|
464
|
-
StackController stack = spy(build);
|
|
465
|
-
disablePushAnimation(initialChild);
|
|
466
|
-
stack.ensureViewIsCreated();
|
|
467
|
-
stack.push(initialChild, new CommandListenerAdapter());
|
|
468
|
-
return stack;
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
private BottomTabsController createBottomTabs() {
|
|
472
|
-
return new BottomTabsController(activity,
|
|
473
|
-
tabs,
|
|
474
|
-
childRegistry,
|
|
475
|
-
eventEmitter,
|
|
476
|
-
imageLoaderMock,
|
|
477
|
-
"uut",
|
|
478
|
-
initialOptions,
|
|
479
|
-
new Presenter(activity, initialOptions),
|
|
480
|
-
tabsAttacher,
|
|
481
|
-
presenter,
|
|
482
|
-
bottomTabPresenter) {
|
|
483
|
-
@Override
|
|
484
|
-
public void ensureViewIsCreated() {
|
|
485
|
-
super.ensureViewIsCreated();
|
|
486
|
-
uut.getView().layout(0, 0, 1000, 1000);
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
@NonNull
|
|
490
|
-
@Override
|
|
491
|
-
public BottomTabsLayout createView() {
|
|
492
|
-
BottomTabsLayout view = super.createView();
|
|
493
|
-
bottomTabs.getLayoutParams().height = 100;
|
|
494
|
-
return view;
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
@NonNull
|
|
498
|
-
@Override
|
|
499
|
-
protected BottomTabsContainer createBottomTabsContainer() {
|
|
500
|
-
return bottomTabsContainer;
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
@NonNull
|
|
504
|
-
@Override
|
|
505
|
-
protected BottomTabs createBottomTabs() {
|
|
506
|
-
return bottomTabs;
|
|
507
|
-
}
|
|
508
|
-
};
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
private int getStatusBarHeight() {
|
|
512
|
-
return SystemUiUtils.getStatusBarHeight(activity);
|
|
513
|
-
}
|
|
514
|
-
}
|