react-native-navigation 8.2.1 → 8.2.2

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.
Files changed (25) hide show
  1. package/lib/android/app/build.gradle +29 -0
  2. package/lib/android/app/src/androidTest/AndroidManifest.xml +17 -0
  3. package/lib/android/app/src/androidTest/java/com/reactnativenavigation/BaseAndroidTest.kt +4 -0
  4. package/lib/android/app/src/androidTest/java/com/reactnativenavigation/TestActivity.kt +4 -0
  5. package/lib/android/app/src/androidTest/java/com/reactnativenavigation/TestApplication.kt +40 -0
  6. package/lib/android/app/src/androidTest/java/com/reactnativenavigation/TestUtils.java +65 -0
  7. package/lib/android/app/src/androidTest/java/com/reactnativenavigation/fakes/IconResolverFake.kt +8 -0
  8. package/lib/android/app/src/androidTest/java/com/reactnativenavigation/mocks/BackDrawable.java +30 -0
  9. package/lib/android/app/src/androidTest/java/com/reactnativenavigation/mocks/ImageLoaderMock.kt +49 -0
  10. package/lib/android/app/src/androidTest/java/com/reactnativenavigation/mocks/SimpleViewController.java +110 -0
  11. package/lib/android/app/src/androidTest/java/com/reactnativenavigation/mocks/TitleBarButtonCreatorMock.java +26 -0
  12. package/lib/android/app/src/androidTest/java/com/reactnativenavigation/mocks/TitleBarReactViewCreatorMock.java +8 -0
  13. package/lib/android/app/src/androidTest/java/com/reactnativenavigation/mocks/TopBarBackgroundViewCreatorMock.java +8 -0
  14. package/lib/android/app/src/androidTest/java/com/reactnativenavigation/mocks/TypefaceLoaderMock.java +34 -0
  15. package/lib/android/app/src/androidTest/java/com/reactnativenavigation/utils/ButtonPresenterTest.kt +379 -0
  16. package/lib/android/app/src/androidTest/java/com/reactnativenavigation/viewcontrollers/bottomtabs/attacher/modes/AfterInitialTabTest.kt +42 -0
  17. package/lib/android/app/src/androidTest/java/com/reactnativenavigation/viewcontrollers/bottomtabs/attacher/modes/AttachModeTest.kt +98 -0
  18. package/lib/android/app/src/androidTest/java/com/reactnativenavigation/viewcontrollers/bottomtabs/attacher/modes/OnSwitchToTabTest.kt +32 -0
  19. package/lib/android/app/src/androidTest/java/com/reactnativenavigation/viewcontrollers/bottomtabs/attacher/modes/TogetherTest.kt +19 -0
  20. package/lib/android/app/src/androidTest/java/com/reactnativenavigation/viewcontrollers/child/ChildControllerTest.java +102 -0
  21. package/lib/android/app/src/androidTest/java/com/reactnativenavigation/viewcontrollers/child/ChildControllersRegistryTest.java +67 -0
  22. package/lib/android/app/src/androidTest/java/com/reactnativenavigation/viewcontrollers/parent/ParentControllerTest.java +349 -0
  23. package/lib/android/app/src/androidTest/java/com/reactnativenavigation/views/TitleSubTitleLayoutTest.kt +51 -0
  24. package/lib/ios/RNNAppDelegate.mm +0 -22
  25. package/package.json +1 -1
@@ -0,0 +1,379 @@
1
+ package com.reactnativenavigation.utils
2
+
3
+ import android.app.Activity
4
+ import android.app.Application
5
+ import android.content.res.Configuration
6
+ import android.graphics.Color
7
+ import android.graphics.PorterDuff
8
+ import android.graphics.PorterDuffColorFilter
9
+ import android.text.SpannableString
10
+ import android.view.Menu
11
+ import android.view.MenuItem
12
+ import android.widget.TextView
13
+ import androidx.appcompat.widget.ActionMenuView
14
+ import androidx.test.espresso.Espresso
15
+ import androidx.test.ext.junit.rules.ActivityScenarioRule
16
+ import androidx.test.ext.junit.runners.AndroidJUnit4
17
+ import androidx.test.platform.app.InstrumentationRegistry
18
+ import com.reactnativenavigation.BaseAndroidTest
19
+ import com.reactnativenavigation.TestActivity
20
+ import com.reactnativenavigation.fakes.IconResolverFake
21
+ import com.reactnativenavigation.mocks.ImageLoaderMock.mock
22
+ import com.reactnativenavigation.options.ButtonOptions
23
+ import com.reactnativenavigation.options.IconBackgroundOptions
24
+ import com.reactnativenavigation.options.params.Bool
25
+ import com.reactnativenavigation.options.params.Colour
26
+ import com.reactnativenavigation.options.params.Number
27
+ import com.reactnativenavigation.options.params.Text
28
+ import com.reactnativenavigation.options.params.ThemeColour
29
+ import com.reactnativenavigation.viewcontrollers.stack.topbar.button.ButtonController
30
+ import com.reactnativenavigation.viewcontrollers.stack.topbar.button.ButtonPresenter
31
+ import com.reactnativenavigation.views.stack.topbar.titlebar.ButtonBar
32
+ import com.reactnativenavigation.views.stack.topbar.titlebar.IconBackgroundDrawable
33
+ import com.reactnativenavigation.views.stack.topbar.titlebar.TitleBarButtonCreator
34
+ import org.assertj.core.api.Java6Assertions
35
+ import org.junit.Before
36
+ import org.junit.Rule
37
+ import org.junit.Test
38
+ import org.junit.runner.RunWith
39
+ import org.mockito.Mockito
40
+ import java.util.Objects
41
+
42
+ @RunWith(AndroidJUnit4::class)
43
+ class ButtonPresenterTest : BaseAndroidTest() {
44
+ private lateinit var titleBar: ButtonBar
45
+ private lateinit var uut: ButtonPresenter
46
+ private lateinit var buttonController: ButtonController
47
+ private lateinit var button: ButtonOptions
48
+ private lateinit var activity: Activity
49
+
50
+ @get:Rule
51
+ val rule = ActivityScenarioRule(TestActivity::class.java)
52
+
53
+ @Before
54
+ fun beforeEach() {
55
+ rule.scenario.onActivity { activity: TestActivity ->
56
+ this.activity =
57
+ activity
58
+ titleBar = ButtonBar(activity)
59
+ activity.setContentView(titleBar)
60
+ button = createButton()
61
+
62
+ val imageLoaderMock =
63
+ mock()
64
+ initUUt(imageLoaderMock)
65
+ }
66
+ }
67
+
68
+ private fun initUUt(imageLoaderMock: ImageLoader) {
69
+ val iconResolver = IconResolverFake(
70
+ activity, imageLoaderMock
71
+ )
72
+ uut = ButtonPresenter(activity, button, iconResolver)
73
+ buttonController = ButtonController(
74
+ activity,
75
+ uut,
76
+ button,
77
+ Mockito.mock(TitleBarButtonCreator::class.java),
78
+ Mockito.mock(
79
+ ButtonController.OnClickListener::class.java
80
+ )
81
+ )
82
+ }
83
+
84
+ @Test
85
+ fun applyOptions_buttonIsAddedToMenu() {
86
+ InstrumentationRegistry.getInstrumentation().runOnMainSync {
87
+ addButtonAndApplyOptions()
88
+ Java6Assertions.assertThat(findButtonView().text.toString())
89
+ .isEqualTo(BTN_TEXT)
90
+ }
91
+ }
92
+
93
+ @Test
94
+ fun applyOptions_appliesColorOnButtonTextView() {
95
+ InstrumentationRegistry.getInstrumentation().runOnMainSync {
96
+ button.color =
97
+ ThemeColour(Colour(Color.RED), Colour(Color.RED))
98
+ addButtonAndApplyOptions()
99
+ }
100
+ Espresso.onIdle()
101
+ Java6Assertions.assertThat(findButtonView().currentTextColor).isEqualTo(Color.RED)
102
+ }
103
+
104
+ @Test
105
+ fun applyOptions_appliesColorOnButtonTextViewOnDarkMode() {
106
+ val application = InstrumentationRegistry.getInstrumentation().targetContext.applicationContext as Application
107
+ application.resources.configuration.uiMode = Configuration.UI_MODE_NIGHT_NO
108
+ button.color = ThemeColour(Colour(Color.RED), Colour(Color.BLACK))
109
+ var menuItem: MenuItem? = null
110
+ InstrumentationRegistry.getInstrumentation().runOnMainSync {
111
+ menuItem = addButtonAndApplyOptions()
112
+ }
113
+ Espresso.onIdle()
114
+ Java6Assertions.assertThat(findButtonView().currentTextColor).isEqualTo(Color.RED)
115
+
116
+ InstrumentationRegistry.getInstrumentation().runOnMainSync {
117
+ application.resources.configuration.uiMode = Configuration.UI_MODE_NIGHT_YES
118
+ uut.applyOptions(titleBar, menuItem!!) { buttonController.view }
119
+ }
120
+ Espresso.onIdle()
121
+ Java6Assertions.assertThat(findButtonView().currentTextColor).isEqualTo(Color.BLACK)
122
+ }
123
+
124
+ @Test
125
+ fun apply_disabledColor() {
126
+ InstrumentationRegistry.getInstrumentation().runOnMainSync {
127
+ button.enabled = Bool(false)
128
+ addButtonAndApplyOptions()
129
+ }
130
+ Espresso.onIdle()
131
+ Java6Assertions.assertThat(findButtonView().currentTextColor)
132
+ .isEqualTo(ButtonPresenter.DISABLED_COLOR)
133
+ }
134
+
135
+ @Test
136
+ fun applyColor_shouldChangeColor() {
137
+ InstrumentationRegistry.getInstrumentation().runOnMainSync {
138
+ val menuItem = addMenuButton()
139
+ uut.applyOptions(titleBar, menuItem) { buttonController.view }
140
+ val color =
141
+ ThemeColour(Colour(Color.RED), Colour(Color.RED))
142
+ uut.applyColor(titleBar, menuItem, color)
143
+ }
144
+ Espresso.onIdle()
145
+ Java6Assertions.assertThat(findButtonView().currentTextColor).isEqualTo(Color.RED)
146
+ }
147
+
148
+ @Test
149
+ fun applyBackgroundColor_shouldChangeBackgroundColor() {
150
+ InstrumentationRegistry.getInstrumentation().runOnMainSync {
151
+ val mockD = Mockito.mock(
152
+ IconBackgroundDrawable::class.java
153
+ )
154
+ initUUt(mock(mockD))
155
+ button.enabled = Bool(true)
156
+ button.icon = Text("icon")
157
+ button.color =
158
+ ThemeColour(Colour(Color.RED), Colour(Color.RED))
159
+ val iconBackground = IconBackgroundOptions()
160
+ iconBackground.color = ThemeColour(
161
+ Colour(Color.GREEN),
162
+ Colour(Color.GREEN)
163
+ )
164
+ button.iconBackground = iconBackground
165
+ val menuItem = Mockito.spy(addMenuButton())
166
+ uut.applyOptions(titleBar, menuItem) { buttonController.view }
167
+
168
+ Java6Assertions.assertThat((menuItem.icon as IconBackgroundDrawable).backgroundColor)
169
+ .isEqualTo(Color.GREEN)
170
+
171
+ uut.applyBackgroundColor(
172
+ titleBar, menuItem,
173
+ ThemeColour(
174
+ Colour(Color.BLACK),
175
+ Colour(Color.BLACK)
176
+ )
177
+ )
178
+ Java6Assertions.assertThat((menuItem.icon as IconBackgroundDrawable).backgroundColor)
179
+ .isEqualTo(Color.BLACK)
180
+ }
181
+ }
182
+
183
+ @Test
184
+ fun applyOptions_shouldChangeIconColorTint() {
185
+ InstrumentationRegistry.getInstrumentation().runOnMainSync {
186
+ val mockD = Mockito.mock(
187
+ IconBackgroundDrawable::class.java
188
+ )
189
+ initUUt(mock(mockD))
190
+ button.enabled = Bool(true)
191
+ button.icon = Text("icon")
192
+ button.color =
193
+ ThemeColour(Colour(Color.RED), Colour(Color.RED))
194
+ val menuItem = Mockito.spy(addMenuButton())
195
+ uut.applyOptions(titleBar, menuItem) { buttonController.view }
196
+
197
+ val icon = menuItem.icon
198
+ Java6Assertions.assertThat(
199
+ icon
200
+ ).isNotNull()
201
+ Mockito.verify(icon)?.colorFilter =
202
+ PorterDuffColorFilter(Color.RED, PorterDuff.Mode.SRC_IN)
203
+ }
204
+ }
205
+
206
+ @Test
207
+ fun applyOptions_shouldChangeIconDisabledColorTint() {
208
+ InstrumentationRegistry.getInstrumentation().runOnMainSync {
209
+ val mockD = Mockito.mock(
210
+ IconBackgroundDrawable::class.java
211
+ )
212
+ initUUt(mock(mockD))
213
+ button.enabled = Bool(false)
214
+ button.icon = Text("icon")
215
+ button.color =
216
+ ThemeColour(Colour(Color.RED), Colour(Color.RED))
217
+ button.disabledColor = ThemeColour(
218
+ Colour(Color.YELLOW),
219
+ Colour(Color.YELLOW)
220
+ )
221
+ val menuItem = Mockito.spy(addMenuButton())
222
+ uut.applyOptions(titleBar, menuItem) { buttonController.view }
223
+
224
+ val icon = menuItem.icon
225
+ Java6Assertions.assertThat(
226
+ icon
227
+ ).isNotNull()
228
+ Mockito.verify(icon)?.colorFilter =
229
+ PorterDuffColorFilter(Color.YELLOW, PorterDuff.Mode.SRC_IN)
230
+ }
231
+ }
232
+
233
+ @Test
234
+ fun applyOptions_shouldChangeIconColorBackground() {
235
+ InstrumentationRegistry.getInstrumentation().runOnMainSync {
236
+ val mockD = Mockito.mock(
237
+ IconBackgroundDrawable::class.java
238
+ )
239
+ initUUt(mock(mockD))
240
+ button.enabled = Bool(true)
241
+ button.icon = Text("icon")
242
+ button.color =
243
+ ThemeColour(Colour(Color.RED), Colour(Color.RED))
244
+ val iconBackground = IconBackgroundOptions()
245
+ iconBackground.color = ThemeColour(
246
+ Colour(Color.GREEN),
247
+ Colour(Color.GREEN)
248
+ )
249
+ button.iconBackground = iconBackground
250
+ val menuItem = Mockito.spy(addMenuButton())
251
+ uut.applyOptions(titleBar, menuItem) { buttonController.view }
252
+
253
+ val icon = menuItem.icon
254
+ Java6Assertions.assertThat(
255
+ icon
256
+ ).isNotNull()
257
+ Java6Assertions.assertThat(
258
+ icon
259
+ ).isInstanceOf(
260
+ IconBackgroundDrawable::class.java
261
+ )
262
+ val modifed = icon as IconBackgroundDrawable?
263
+ Mockito.verify(modifed!!.getWrappedDrawable()).colorFilter =
264
+ PorterDuffColorFilter(Color.RED, PorterDuff.Mode.SRC_IN)
265
+ Java6Assertions.assertThat(modifed.backgroundColor)
266
+ .isEqualTo(Color.GREEN)
267
+ }
268
+ }
269
+
270
+ @Test
271
+ fun applyOptions_shouldChangeIconDisabledColorBackground() {
272
+ InstrumentationRegistry.getInstrumentation().runOnMainSync {
273
+ val mockD = Mockito.mock(
274
+ IconBackgroundDrawable::class.java
275
+ )
276
+ initUUt(mock(mockD))
277
+ button.enabled = Bool(false)
278
+ button.icon = Text("icon")
279
+ button.color =
280
+ ThemeColour(Colour(Color.RED), Colour(Color.RED))
281
+ button.disabledColor = ThemeColour(
282
+ Colour(Color.YELLOW),
283
+ Colour(Color.YELLOW)
284
+ )
285
+ val iconBackground = IconBackgroundOptions()
286
+ iconBackground.color = ThemeColour(
287
+ Colour(Color.GREEN),
288
+ Colour(Color.GREEN)
289
+ )
290
+ iconBackground.disabledColor = ThemeColour(
291
+ Colour(Color.CYAN),
292
+ Colour(Color.CYAN)
293
+ )
294
+ button.iconBackground = iconBackground
295
+ val menuItem = Mockito.spy(addMenuButton())
296
+ uut.applyOptions(titleBar, menuItem) { buttonController.view }
297
+
298
+ val icon = menuItem.icon
299
+ Java6Assertions.assertThat(
300
+ icon
301
+ ).isNotNull()
302
+ Java6Assertions.assertThat(
303
+ icon
304
+ ).isInstanceOf(
305
+ IconBackgroundDrawable::class.java
306
+ )
307
+ val modifed = icon as IconBackgroundDrawable?
308
+ Mockito.verify(modifed!!.getWrappedDrawable()).colorFilter =
309
+ PorterDuffColorFilter(Color.YELLOW, PorterDuff.Mode.SRC_IN)
310
+ Java6Assertions.assertThat(modifed.backgroundColor)
311
+ .isEqualTo(Color.CYAN)
312
+ }
313
+ }
314
+
315
+ @Test
316
+ fun applyColor_shouldChangeDisabledColor() {
317
+ InstrumentationRegistry.getInstrumentation().runOnMainSync {
318
+ button.enabled = Bool(false)
319
+ val menuItem = addMenuButton()
320
+ uut.applyOptions(titleBar, menuItem) { buttonController.view }
321
+ val disabledColor = ThemeColour(
322
+ Colour(Color.BLUE),
323
+ Colour(Color.BLUE)
324
+ )
325
+ uut.applyDisabledColor(titleBar, menuItem, disabledColor)
326
+ }
327
+ Espresso.onIdle()
328
+ Java6Assertions.assertThat(findButtonView().currentTextColor).isEqualTo(Color.BLUE)
329
+ }
330
+
331
+ @Test
332
+ fun apply_allCaps() {
333
+ InstrumentationRegistry.getInstrumentation().runOnMainSync {
334
+ button.allCaps = Bool(false)
335
+ addButtonAndApplyOptions()
336
+ Java6Assertions.assertThat(findButtonView().isAllCaps)
337
+ .isEqualTo(false)
338
+ }
339
+ }
340
+
341
+ private fun addButtonAndApplyOptions(): MenuItem {
342
+ val menuItem = addMenuButton()
343
+ uut.applyOptions(titleBar, menuItem) { buttonController.view }
344
+ return menuItem
345
+ }
346
+
347
+ private fun addMenuButton(): MenuItem {
348
+ return titleBar.addButton(
349
+ Menu.NONE,
350
+ 1,
351
+ 0,
352
+ SpannableString.valueOf(button.text["text"])
353
+ ) ?: throw IllegalStateException("MenuItem should not be null")
354
+ }
355
+
356
+ private fun findButtonView(): TextView {
357
+ return ViewUtils.findChildrenByClass(
358
+ Objects.requireNonNull(
359
+ ViewUtils.findChildByClass(
360
+ titleBar,
361
+ ActionMenuView::class.java
362
+ )
363
+ ),
364
+ TextView::class.java
365
+ ) { child: Any? -> true }[0] as TextView
366
+ }
367
+
368
+ private fun createButton(): ButtonOptions {
369
+ val b = ButtonOptions()
370
+ b.id = "btn1"
371
+ b.text = Text(BTN_TEXT)
372
+ b.showAsAction = Number(MenuItem.SHOW_AS_ACTION_ALWAYS)
373
+ return b
374
+ }
375
+
376
+ companion object {
377
+ private const val BTN_TEXT = "button1"
378
+ }
379
+ }
@@ -0,0 +1,42 @@
1
+ package com.reactnativenavigation.viewcontrollers.bottomtabs.attacher.modes
2
+
3
+ import androidx.test.espresso.Espresso
4
+ import androidx.test.platform.app.InstrumentationRegistry
5
+ import org.junit.Before
6
+ import org.junit.Test
7
+ import org.mockito.Mockito.verify
8
+ import org.mockito.kotlin.any
9
+
10
+ class AfterInitialTabTest : AttachModeTest() {
11
+
12
+ @Before
13
+ override fun setup() {
14
+ super.setup()
15
+ uut = AfterInitialTab(parent, tabs, presenter, options)
16
+ }
17
+
18
+ @Test
19
+ fun attach_initialTabIsAttached() {
20
+ uut.attach()
21
+ assertIsChild(parent, tab2)
22
+ }
23
+
24
+ @Test
25
+ fun attach_otherTabsAreAttachedAfterInitialTab() {
26
+ InstrumentationRegistry.getInstrumentation().runOnMainSync {
27
+ uut.attach()
28
+
29
+ assertNotChildOf(parent, *otherTabs())
30
+
31
+ initialTab().onViewWillAppear()
32
+ }
33
+ Espresso.onIdle()
34
+ assertIsChild(parent, *otherTabs())
35
+ }
36
+
37
+ @Test
38
+ fun destroy() {
39
+ uut.destroy()
40
+ verify(initialTab()).removeOnAppearedListener(any())
41
+ }
42
+ }
@@ -0,0 +1,98 @@
1
+ package com.reactnativenavigation.viewcontrollers.bottomtabs.attacher.modes
2
+
3
+ import android.view.View
4
+ import android.view.ViewGroup
5
+ import androidx.coordinatorlayout.widget.CoordinatorLayout
6
+ import androidx.test.ext.junit.rules.ActivityScenarioRule
7
+ import androidx.test.ext.junit.runners.AndroidJUnit4
8
+ import com.reactnativenavigation.TestActivity
9
+ import com.reactnativenavigation.mocks.SimpleViewController
10
+ import com.reactnativenavigation.options.Options
11
+ import com.reactnativenavigation.options.params.Number
12
+ import com.reactnativenavigation.viewcontrollers.bottomtabs.BottomTabsPresenter
13
+ import com.reactnativenavigation.viewcontrollers.child.ChildControllersRegistry
14
+ import com.reactnativenavigation.viewcontrollers.viewcontroller.ViewController
15
+ import com.reactnativenavigation.views.bottomtabs.BottomTabsBehaviour
16
+ import org.assertj.core.api.AssertionsForInterfaceTypes.assertThat
17
+ import org.junit.Before
18
+ import org.junit.Rule
19
+ import org.junit.Test
20
+ import org.junit.runner.RunWith
21
+ import org.mockito.Mockito
22
+ import org.mockito.Mockito.spy
23
+
24
+ @RunWith(AndroidJUnit4::class)
25
+ abstract class AttachModeTest {
26
+ private val INITIAL_TAB = 1
27
+
28
+ private lateinit var childRegistry: ChildControllersRegistry
29
+ protected lateinit var parent: ViewGroup
30
+ protected lateinit var tab1: ViewController<*>
31
+ protected lateinit var tab2: ViewController<*>
32
+ protected lateinit var tabs: List<ViewController<*>>
33
+ protected lateinit var options: Options
34
+ protected lateinit var presenter: BottomTabsPresenter
35
+ protected lateinit var uut: AttachMode
36
+
37
+ @get:Rule
38
+ val rule = ActivityScenarioRule(TestActivity::class.java)
39
+
40
+ @Before
41
+ open fun setup() {
42
+ rule.scenario.onActivity { activity ->
43
+ childRegistry = ChildControllersRegistry()
44
+ parent = CoordinatorLayout(activity)
45
+ tabs = createTabs(activity)
46
+ }
47
+ options = Options()
48
+ options.bottomTabsOptions.currentTabIndex = Number(INITIAL_TAB)
49
+ presenter = Mockito.mock(BottomTabsPresenter::class.java)
50
+ }
51
+
52
+ @Test
53
+ fun attach_layoutOptionsAreApplied() {
54
+ uut.attach(tab1)
55
+ val lp = tab1.getView().layoutParams as CoordinatorLayout.LayoutParams
56
+ assertThat(lp).isNotNull
57
+ assertThat(lp.behavior).isInstanceOf(BottomTabsBehaviour::class.java)
58
+ }
59
+
60
+ @Test
61
+ fun attach_initialTabIsVisible() {
62
+ uut.attach(initialTab())
63
+ assertThat(initialTab().getView().visibility).isEqualTo(View.VISIBLE)
64
+ }
65
+
66
+ @Test
67
+ fun attach_otherTabsAreInvisibleWhenAttached() {
68
+ otherTabs().forEach { t -> uut.attach(t) }
69
+ otherTabs().forEach { t -> assertThat(t.getView().visibility).isEqualTo(View.INVISIBLE) }
70
+ }
71
+
72
+ protected fun otherTabs(): Array<ViewController<*>> {
73
+ return tabs.filter { t -> t != initialTab() }.toTypedArray()
74
+ }
75
+
76
+ protected fun initialTab(): ViewController<*> {
77
+ return tabs[INITIAL_TAB]
78
+ }
79
+
80
+ private fun createTabs(activity: android.app.Activity): List<ViewController<*>> {
81
+ tab1 = SimpleViewController(activity, childRegistry, "child1", Options())
82
+ tab2 = spy(SimpleViewController(activity, childRegistry, "child2", Options()))
83
+ val tab3 = SimpleViewController(activity, childRegistry, "child3", Options())
84
+ return listOf(tab1, tab2, tab3)
85
+ }
86
+
87
+ protected fun assertIsChild(parent: ViewGroup, vararg children: ViewController<*>) {
88
+ children.forEach { child ->
89
+ assertThat(child.getView().parent).isEqualTo(parent)
90
+ }
91
+ }
92
+
93
+ protected fun assertNotChildOf(parent: ViewGroup, vararg children: ViewController<*>) {
94
+ children.forEach { child ->
95
+ assertThat(child.getView().parent).isNotEqualTo(parent)
96
+ }
97
+ }
98
+ }
@@ -0,0 +1,32 @@
1
+ package com.reactnativenavigation.viewcontrollers.bottomtabs.attacher.modes
2
+
3
+ import org.junit.Before
4
+ import org.junit.Test
5
+
6
+ class OnSwitchToTabTest : AttachModeTest() {
7
+
8
+ @Before
9
+ override fun setup() {
10
+ super.setup()
11
+ uut = OnSwitchToTab(parent, tabs, presenter, options)
12
+ }
13
+
14
+ @Test
15
+ fun attach_onlyInitialTabIsAttached() {
16
+ uut.attach()
17
+ assertIsChild(parent, initialTab())
18
+ assertNotChildOf(parent, *otherTabs())
19
+ }
20
+
21
+ @Test
22
+ fun onTabSelected_initialTabIsNotHandled() {
23
+ uut.onTabSelected(initialTab())
24
+ assertNotChildOf(parent, initialTab())
25
+ }
26
+
27
+ @Test
28
+ fun onTabSelected_otherTabIsAttached() {
29
+ uut.onTabSelected(tab1)
30
+ assertIsChild(parent, tab1)
31
+ }
32
+ }
@@ -0,0 +1,19 @@
1
+ package com.reactnativenavigation.viewcontrollers.bottomtabs.attacher.modes
2
+
3
+ import org.junit.Before
4
+ import org.junit.Test
5
+
6
+ class TogetherTest : AttachModeTest() {
7
+
8
+ @Before
9
+ override fun setup() {
10
+ super.setup()
11
+ uut = Together(parent, tabs, presenter, options)
12
+ }
13
+
14
+ @Test
15
+ fun attach_allTabsAreAttached() {
16
+ uut.attach()
17
+ assertIsChild(parent, *tabs.toTypedArray())
18
+ }
19
+ }
@@ -0,0 +1,102 @@
1
+ package com.reactnativenavigation.viewcontrollers.child;
2
+
3
+ import androidx.test.ext.junit.rules.ActivityScenarioRule;
4
+ import androidx.test.ext.junit.runners.AndroidJUnit4;
5
+ import androidx.test.platform.app.InstrumentationRegistry;
6
+ import androidx.test.core.app.ActivityScenario;
7
+
8
+ import com.reactnativenavigation.BaseAndroidTest;
9
+ import com.reactnativenavigation.TestActivity;
10
+ import com.reactnativenavigation.mocks.SimpleViewController;
11
+ import com.reactnativenavigation.options.Options;
12
+ import com.reactnativenavigation.viewcontrollers.viewcontroller.Presenter;
13
+ import com.reactnativenavigation.viewcontrollers.parent.ParentController;
14
+
15
+ import org.junit.Before;
16
+ import org.junit.Rule;
17
+ import org.junit.Test;
18
+ import org.junit.runner.RunWith;
19
+ import org.mockito.Mockito;
20
+
21
+ import static org.mockito.ArgumentMatchers.any;
22
+ import static org.mockito.Mockito.spy;
23
+ import static org.mockito.Mockito.times;
24
+ import static org.mockito.Mockito.verify;
25
+
26
+ @RunWith(AndroidJUnit4.class)
27
+ public class ChildControllerTest extends BaseAndroidTest {
28
+ private ChildController<?> uut;
29
+ private ChildControllersRegistry childRegistry;
30
+ private Presenter presenter;
31
+ private Options resolvedOptions = new Options();
32
+
33
+ @Rule
34
+ public ActivityScenarioRule<TestActivity> rule = new ActivityScenarioRule<>(TestActivity.class);
35
+
36
+ @Before
37
+ public void beforeEach() {
38
+ rule.getScenario().onActivity(activity -> {
39
+ childRegistry = spy(new ChildControllersRegistry());
40
+ presenter = Mockito.mock(Presenter.class);
41
+ uut = new SimpleViewController(activity, childRegistry, "childId", presenter, new Options()) {
42
+ @Override
43
+ public Options resolveCurrentOptions() {
44
+ return resolvedOptions;
45
+ }
46
+ };
47
+ ParentController<?> parent = Mockito.mock(ParentController.class);
48
+ Mockito.when(parent.resolveChildOptions(uut)).thenReturn(Options.EMPTY);
49
+ uut.setParentController(parent);
50
+ });
51
+ }
52
+
53
+ @Test
54
+ public void onViewAppeared() {
55
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> uut.onViewWillAppear());
56
+ verify(childRegistry, times(1)).onViewAppeared(uut);
57
+ }
58
+
59
+ @Test
60
+ public void onViewDisappear() {
61
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
62
+ uut.onViewWillAppear();
63
+ uut.onViewDisappear();
64
+ });
65
+ verify(childRegistry, times(1)).onViewDisappear(uut);
66
+ }
67
+
68
+ @Test
69
+ public void mergeOptions() {
70
+ try (ActivityScenario<TestActivity> scenario = ActivityScenario.launch(TestActivity.class)) {
71
+ scenario.onActivity(activity -> {
72
+ activity.setContentView(uut.getView());
73
+ Options options = new Options();
74
+ uut.mergeOptions(options);
75
+ verify(presenter).mergeOptions(uut, options);
76
+ });
77
+ }
78
+ }
79
+
80
+ @Test
81
+ public void mergeOptions_emptyOptionsAreIgnored() {
82
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
83
+ uut.mergeOptions(Options.EMPTY);
84
+ verify(presenter, times(0)).mergeOptions(any(), any());
85
+ });
86
+ }
87
+
88
+ @Test
89
+ public void mergeOptions_mergeWithParentViewController() {
90
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
91
+ Options options = new Options();
92
+ uut.mergeOptions(options);
93
+ verify(uut.getParentController()).mergeChildOptions(options, uut);
94
+ });
95
+ }
96
+
97
+ @Test
98
+ public void destroy() {
99
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> uut.destroy());
100
+ verify(childRegistry).onChildDestroyed(uut);
101
+ }
102
+ }