react-native-navigation 7.24.3 → 7.25.0

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 (115) hide show
  1. package/lib/android/app/build.gradle +12 -9
  2. package/lib/android/app/src/main/java/com/reactnativenavigation/options/Options.java +2 -0
  3. package/lib/android/app/src/main/java/com/reactnativenavigation/options/layout/LayoutInsets.kt +44 -0
  4. package/lib/android/app/src/main/java/com/reactnativenavigation/options/layout/LayoutOptions.kt +71 -0
  5. package/lib/android/app/src/main/java/com/reactnativenavigation/utils/PrimitiveExt.kt +9 -0
  6. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/component/ComponentViewController.java +4 -3
  7. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/navigator/Navigator.java +5 -0
  8. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/viewcontroller/Presenter.java +23 -7
  9. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/viewcontroller/ViewController.java +12 -3
  10. package/lib/dist/src/interfaces/Options.d.ts +10 -0
  11. package/lib/ios/RNNBasePresenter.m +17 -0
  12. package/lib/ios/RNNBottomTabsController.m +1 -0
  13. package/lib/ios/RNNComponentViewController.m +5 -0
  14. package/lib/ios/RNNLayoutOptions.h +2 -1
  15. package/lib/ios/RNNLayoutOptions.m +4 -0
  16. package/lib/ios/RNNStackPresenter.m +1 -0
  17. package/lib/src/interfaces/Options.ts +12 -0
  18. package/package.json +3 -1
  19. package/.buildkite/pipeline.yml +0 -59
  20. package/lib/android/app/src/main/java/com/reactnativenavigation/options/LayoutOptions.java +0 -48
  21. package/lib/android/app/src/test/java/com/reactnativenavigation/BaseTest.java +0 -178
  22. package/lib/android/app/src/test/java/com/reactnativenavigation/EnvironmentTest.java +0 -43
  23. package/lib/android/app/src/test/java/com/reactnativenavigation/TestActivity.java +0 -23
  24. package/lib/android/app/src/test/java/com/reactnativenavigation/TestApplication.java +0 -35
  25. package/lib/android/app/src/test/java/com/reactnativenavigation/TestUtils.java +0 -62
  26. package/lib/android/app/src/test/java/com/reactnativenavigation/fakes/IconResolverFake.kt +0 -8
  27. package/lib/android/app/src/test/java/com/reactnativenavigation/mocks/BackDrawable.java +0 -30
  28. package/lib/android/app/src/test/java/com/reactnativenavigation/mocks/ImageLoaderMock.kt +0 -49
  29. package/lib/android/app/src/test/java/com/reactnativenavigation/mocks/Mocks.kt +0 -18
  30. package/lib/android/app/src/test/java/com/reactnativenavigation/mocks/SimpleComponentViewController.java +0 -15
  31. package/lib/android/app/src/test/java/com/reactnativenavigation/mocks/SimpleOverlay.java +0 -54
  32. package/lib/android/app/src/test/java/com/reactnativenavigation/mocks/SimpleViewController.java +0 -113
  33. package/lib/android/app/src/test/java/com/reactnativenavigation/mocks/TestComponentLayout.java +0 -79
  34. package/lib/android/app/src/test/java/com/reactnativenavigation/mocks/TestComponentViewCreator.java +0 -18
  35. package/lib/android/app/src/test/java/com/reactnativenavigation/mocks/TestReactView.java +0 -71
  36. package/lib/android/app/src/test/java/com/reactnativenavigation/mocks/TitleBarButtonCreatorMock.java +0 -34
  37. package/lib/android/app/src/test/java/com/reactnativenavigation/mocks/TitleBarReactViewCreatorMock.java +0 -20
  38. package/lib/android/app/src/test/java/com/reactnativenavigation/mocks/TopBarBackgroundViewCreatorMock.java +0 -20
  39. package/lib/android/app/src/test/java/com/reactnativenavigation/mocks/TypefaceLoaderMock.kt +0 -21
  40. package/lib/android/app/src/test/java/com/reactnativenavigation/options/LayoutNodeParserTest.java +0 -51
  41. package/lib/android/app/src/test/java/com/reactnativenavigation/options/OptionsTest.java +0 -315
  42. package/lib/android/app/src/test/java/com/reactnativenavigation/options/OrientationOptionsTest.java +0 -81
  43. package/lib/android/app/src/test/java/com/reactnativenavigation/options/TopBarButtonsTest.kt +0 -95
  44. package/lib/android/app/src/test/java/com/reactnativenavigation/options/TransitionAnimationOptionsTest.kt +0 -122
  45. package/lib/android/app/src/test/java/com/reactnativenavigation/options/parsers/BoolParserTest.java +0 -28
  46. package/lib/android/app/src/test/java/com/reactnativenavigation/options/parsers/ColorParseTest.java +0 -50
  47. package/lib/android/app/src/test/java/com/reactnativenavigation/options/parsers/JSONParserTest.java +0 -64
  48. package/lib/android/app/src/test/java/com/reactnativenavigation/presentation/PresenterTest.java +0 -56
  49. package/lib/android/app/src/test/java/com/reactnativenavigation/presentation/RenderCheckerTest.java +0 -59
  50. package/lib/android/app/src/test/java/com/reactnativenavigation/presentation/SideMenuPresenterTest.java +0 -35
  51. package/lib/android/app/src/test/java/com/reactnativenavigation/react/NavigationModuleTest.java +0 -102
  52. package/lib/android/app/src/test/java/com/reactnativenavigation/react/ReloadListenerTest.java +0 -24
  53. package/lib/android/app/src/test/java/com/reactnativenavigation/utils/AnimationHelper.kt +0 -33
  54. package/lib/android/app/src/test/java/com/reactnativenavigation/utils/ButtonPresenterTest.java +0 -241
  55. package/lib/android/app/src/test/java/com/reactnativenavigation/utils/ButtonSpanTest.java +0 -57
  56. package/lib/android/app/src/test/java/com/reactnativenavigation/utils/CompatUtilsTest.java +0 -17
  57. package/lib/android/app/src/test/java/com/reactnativenavigation/utils/LayoutFactoryTest.java +0 -78
  58. package/lib/android/app/src/test/java/com/reactnativenavigation/utils/MotionEventTest.kt +0 -47
  59. package/lib/android/app/src/test/java/com/reactnativenavigation/utils/NativeCommandListenerTest.java +0 -60
  60. package/lib/android/app/src/test/java/com/reactnativenavigation/utils/OptionHelper.java +0 -16
  61. package/lib/android/app/src/test/java/com/reactnativenavigation/utils/ReflectionUtilsTest.java +0 -26
  62. package/lib/android/app/src/test/java/com/reactnativenavigation/utils/StringUtilsTest.java +0 -19
  63. package/lib/android/app/src/test/java/com/reactnativenavigation/utils/SystemUiUtilsTest.kt +0 -27
  64. package/lib/android/app/src/test/java/com/reactnativenavigation/utils/TitleAndButtonsMeasurerTest.kt +0 -357
  65. package/lib/android/app/src/test/java/com/reactnativenavigation/utils/TitleBarHelper.java +0 -54
  66. package/lib/android/app/src/test/java/com/reactnativenavigation/utils/UiThreadTest.java +0 -29
  67. package/lib/android/app/src/test/java/com/reactnativenavigation/utils/UiUtilsTest.java +0 -22
  68. package/lib/android/app/src/test/java/com/reactnativenavigation/utils/ViewHelper.java +0 -9
  69. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/OptionsApplyingTest.java +0 -149
  70. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/bottomtabs/BottomTabPresenterTest.java +0 -206
  71. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/bottomtabs/BottomTabsAttacherTest.java +0 -62
  72. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/bottomtabs/BottomTabsControllerTest.kt +0 -589
  73. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/bottomtabs/BottomTabsPresenterTest.kt +0 -173
  74. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/bottomtabs/attacher/modes/AfterInitialTabTest.java +0 -38
  75. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/bottomtabs/attacher/modes/AttachModeTest.java +0 -86
  76. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/bottomtabs/attacher/modes/OnSwitchToTabTest.java +0 -31
  77. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/bottomtabs/attacher/modes/TogetherTest.java +0 -20
  78. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/button/NavigationIconResolverTest.java +0 -78
  79. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/child/ChildControllerTest.java +0 -80
  80. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/child/ChildControllersRegistryTest.java +0 -56
  81. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/component/ComponentViewControllerTest.java +0 -216
  82. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/externalcomponent/ExternalComponentViewControllerTest.java +0 -97
  83. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/externalcomponent/FragmentCreatorMock.java +0 -34
  84. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/externalcomponent/SomeFragment.java +0 -8
  85. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/fakes/FakeParentController.kt +0 -33
  86. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/modal/ModalAnimatorMock.java +0 -40
  87. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/modal/ModalAnimatorTest.kt +0 -213
  88. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/modal/ModalPresenterTest.java +0 -319
  89. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/modal/ModalStackTest.java +0 -367
  90. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/navigator/NavigatorTest.java +0 -898
  91. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/navigator/RootPresenterTest.kt +0 -254
  92. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/overlay/OverlayManagerTest.java +0 -108
  93. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/parent/ParentControllerTest.java +0 -299
  94. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/sidemenu/SideMenuControllerTest.java +0 -446
  95. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/stack/BackButtonHelperTest.java +0 -77
  96. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/stack/FloatingActionButtonTest.java +0 -154
  97. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/stack/IdStackTest.java +0 -114
  98. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/stack/StackAnimatorTest.kt +0 -241
  99. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/stack/StackControllerTest.kt +0 -1165
  100. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/stack/StackPresenterTest.kt +0 -1081
  101. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/stack/TitleBarButtonControllerTest.java +0 -61
  102. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/stack/TitleBarReactViewControllerTest.java +0 -43
  103. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/stack/TopBarButtonControllerTest.java +0 -120
  104. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/stack/TopBarControllerTest.kt +0 -432
  105. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/toptabs/TopTabsViewControllerTest.java +0 -249
  106. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/viewcontroller/ViewControllerTest.java +0 -337
  107. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/viewcontroller/YellowBoxDelegateTest.java +0 -68
  108. package/lib/android/app/src/test/java/com/reactnativenavigation/views/OverlayTouchDelegateTest.java +0 -60
  109. package/lib/android/app/src/test/java/com/reactnativenavigation/views/TitleAndButtonsContainerTest.kt +0 -477
  110. package/lib/android/app/src/test/java/com/reactnativenavigation/views/TopBarTest.java +0 -82
  111. package/lib/android/app/src/test/java/com/reactnativenavigation/views/animations/BaseViewAnimatorTest.kt +0 -109
  112. package/lib/android/app/src/test/java/com/reactnativenavigation/views/animations/DefaultViewAnimatorCreatorFake.kt +0 -36
  113. package/lib/android/app/src/test/java/com/reactnativenavigation/views/bottomtabs/BottomTabsContainerTest.kt +0 -101
  114. package/lib/android/app/src/test/java/com/reactnativenavigation/views/bottomtabs/BottomTabsTest.kt +0 -40
  115. package/lib/android/app/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker +0 -1
@@ -1,1165 +0,0 @@
1
- package com.reactnativenavigation.viewcontrollers.stack
2
-
3
- import android.animation.AnimatorSet
4
- import android.app.Activity
5
- import android.content.Context
6
- import android.view.View
7
- import android.widget.FrameLayout
8
- import androidx.coordinatorlayout.widget.CoordinatorLayout
9
- import org.mockito.kotlin.*
10
- import com.reactnativenavigation.BaseTest
11
- import com.reactnativenavigation.TestUtils
12
- import com.reactnativenavigation.mocks.*
13
- import com.reactnativenavigation.mocks.SimpleViewController.SimpleView
14
- import com.reactnativenavigation.options.Options
15
- import com.reactnativenavigation.options.StackAnimationOptions
16
- import com.reactnativenavigation.options.params.Bool
17
- import com.reactnativenavigation.options.params.Text
18
- import com.reactnativenavigation.react.CommandListenerAdapter
19
- import com.reactnativenavigation.react.events.EventEmitter
20
- import com.reactnativenavigation.utils.*
21
- import com.reactnativenavigation.viewcontrollers.child.ChildControllersRegistry
22
- import com.reactnativenavigation.viewcontrollers.parent.ParentController
23
- import com.reactnativenavigation.viewcontrollers.stack.topbar.TopBarAnimator
24
- import com.reactnativenavigation.viewcontrollers.stack.topbar.TopBarController
25
- import com.reactnativenavigation.viewcontrollers.stack.topbar.button.BackButtonHelper
26
- import com.reactnativenavigation.viewcontrollers.stack.topbar.button.IconResolver
27
- import com.reactnativenavigation.viewcontrollers.viewcontroller.ViewController
28
- import com.reactnativenavigation.views.stack.StackBehaviour
29
- import com.reactnativenavigation.views.stack.StackLayout
30
- import com.reactnativenavigation.views.stack.topbar.ScrollDIsabledBehavior
31
- import com.reactnativenavigation.views.stack.topbar.TopBar
32
- import org.assertj.core.api.Java6Assertions.assertThat
33
- import org.assertj.core.api.iterable.Extractor
34
- import org.json.JSONObject
35
- import org.junit.Ignore
36
- import org.junit.Test
37
- import org.robolectric.Robolectric
38
- import org.robolectric.shadows.ShadowLooper
39
- import java.util.*
40
- import kotlin.test.fail
41
-
42
- class StackControllerTest : BaseTest() {
43
- private lateinit var activity: Activity
44
- private lateinit var childRegistry: ChildControllersRegistry
45
- private lateinit var uut: StackController
46
- private lateinit var child1: ViewController<*>
47
- private lateinit var child1a: ViewController<*>
48
- private lateinit var child2: ViewController<*>
49
- private lateinit var child3: ViewController<*>
50
- private var child3View: SimpleView? = null
51
- private lateinit var child4: ViewController<*>
52
- private lateinit var animator: StackAnimator
53
- private lateinit var topBarAnimator: TopBarAnimator
54
- private lateinit var topBarController: TopBarController
55
- private lateinit var presenter: StackPresenter
56
- private lateinit var backButtonHelper: BackButtonHelper
57
- private lateinit var eventEmitter: EventEmitter
58
-
59
- override fun beforeEach() {
60
- super.beforeEach()
61
- eventEmitter = mock()
62
- backButtonHelper = spy(BackButtonHelper())
63
- activity = newActivity()
64
- SystemUiUtils.saveStatusBarHeight(63)
65
- animator = spy(StackAnimator(activity))
66
- childRegistry = ChildControllersRegistry()
67
- presenter = spy(StackPresenter(
68
- activity,
69
- TitleBarReactViewCreatorMock(),
70
- TopBarBackgroundViewCreatorMock(),
71
- TitleBarButtonCreatorMock(),
72
- IconResolver(activity, ImageLoaderMock.mock()),
73
- TypefaceLoaderMock(),
74
- RenderChecker(),
75
- Options()
76
- )
77
- )
78
- createChildren()
79
- uut = createStack()
80
- activity.setContentView(uut.view)
81
- }
82
-
83
- private fun createChildren() {
84
- child1 = spy(SimpleViewController(activity, childRegistry, "child1", Options()))
85
- child1a = spy(SimpleViewController(activity, childRegistry, "child1", Options()))
86
- child2 = spy(SimpleViewController(activity, childRegistry, "child2", Options()))
87
- child3 = spy(object : SimpleViewController(activity, childRegistry, "child3", Options()) {
88
- override fun createView(): SimpleView {
89
- return child3View ?: super.createView()
90
- }
91
- })
92
- child4 = spy(SimpleViewController(activity, childRegistry, "child4", Options()))
93
- }
94
-
95
- @Test
96
- fun isAViewController() {
97
- assertThat(uut).isInstanceOf(ViewController::class.java)
98
- }
99
-
100
- @Test
101
- fun childrenMustBeUniqueById() {
102
- try {
103
- val uut: StackController = createStack(listOf(child1, child2, child1))
104
- fail("Stack should not have duplicate ids!")
105
- } catch (e: IllegalArgumentException) {
106
- assertThat(e.message).contains(child1.id)
107
- }
108
- }
109
-
110
- @Test
111
- fun childrenAreAssignedParent() {
112
- val uut: StackController = createStack(listOf(child1, child2))
113
- for (child in uut.childControllers) {
114
- assertThat(child.parentController == uut).isTrue()
115
- }
116
- }
117
-
118
- @Test
119
- fun constructor_backButtonIsAddedToChild() {
120
- createStack(listOf(child1, child2, child3))
121
- assertThat(child2.options.topBar.buttons.back.visible[false]).isTrue()
122
- assertThat(child3.options.topBar.buttons.back.visible[false]).isTrue()
123
- }
124
-
125
- @Test
126
- fun createView_currentChildIsAdded() {
127
- val uut: StackController = createStack(listOf(child1, child2, child3, child4))
128
- assertThat(uut.childControllers.size).isEqualTo(4)
129
- assertThat(uut.view.childCount).isEqualTo(2)
130
- assertThat(uut.view.getChildAt(0)).isEqualTo(child4.view)
131
- }
132
-
133
- @Test
134
- fun createView_topBarScrollIsDisabled() {
135
- val behavior = (uut.topBar.layoutParams as CoordinatorLayout.LayoutParams).behavior
136
- assertThat(behavior is ScrollDIsabledBehavior).isTrue()
137
- }
138
-
139
- @Test
140
- fun holdsAStackOfViewControllers() {
141
- assertThat(uut.isEmpty).isTrue()
142
- uut.push(child1, CommandListenerAdapter())
143
- uut.push(child2, CommandListenerAdapter())
144
- uut.push(child3, CommandListenerAdapter())
145
- assertThat(uut.peek()).isEqualTo(child3)
146
- assertContainsOnlyId(child1.id, child2.id, child3.id)
147
- }
148
-
149
- @Test
150
- fun isRendered_falseIfStackIsEmpty() {
151
- assertThat(uut.size()).isZero()
152
- assertThat(uut.isRendered).isFalse()
153
- }
154
-
155
- @Test
156
- fun isRendered() {
157
- disablePushAnimation(child1)
158
- uut.push(child1, CommandListenerAdapter())
159
- assertThat(uut.isRendered).isTrue()
160
- child1.setWaitForRender(Bool(true))
161
- assertThat(uut.isRendered).isFalse()
162
- child1.view.addView(View(activity))
163
- assertThat(uut.isRendered).isTrue()
164
- whenever(presenter.isRendered(child1.view)).then { false }
165
- assertThat(uut.isRendered).isFalse()
166
- }
167
-
168
- @Test
169
- fun push() {
170
- assertThat(uut.isEmpty).isTrue()
171
- val listener = spy(CommandListenerAdapter())
172
- uut.push(child1, listener)
173
- assertContainsOnlyId(child1.id)
174
- assertThat((child1.view.layoutParams as CoordinatorLayout.LayoutParams).behavior).isInstanceOf(StackBehaviour::class.java)
175
- verify(listener).onSuccess(child1.id)
176
- }
177
-
178
- @Test
179
- fun push_backButtonIsNotAddedIfScreenContainsLeftButton() {
180
- disablePushAnimation(child1, child2)
181
- uut.push(child1, CommandListenerAdapter())
182
- child2.options.topBar.buttons.left = ArrayList(setOf(TitleBarHelper.iconButton("someButton", "icon.png")))
183
- uut.push(child2, CommandListenerAdapter())
184
- ShadowLooper.idleMainLooper()
185
- assertThat(topBarController.leftButtonCount).isOne()
186
- verify(topBarController.view, never()).setBackButton(any())
187
- }
188
-
189
- @Test
190
- fun push_backButtonIsNotAddedIfScreenClearsLeftButton() {
191
- child1.options.topBar.buttons.left = ArrayList()
192
- uut.push(child1, CommandListenerAdapter())
193
- verify(child1, never()).mergeOptions(any())
194
- }
195
-
196
- @Test
197
- fun setRoot_pushDuringSetRootAnimationShouldNotCrash() {
198
- uut.push(child1, CommandListenerAdapter())
199
- uut.push(child2, CommandListenerAdapter())
200
- idleMainLooper()
201
- uut.setRoot(listOf(child1), CommandListenerAdapter())
202
- uut.push(child3, CommandListenerAdapter())
203
- assertThat(uut.currentChild).isEqualTo(child3)
204
- }
205
-
206
- @Test
207
- fun push_backButtonAddedBeforeChildViewIsCreated() {
208
- disablePopAnimation(child1, child2)
209
- uut.push(child1, CommandListenerAdapter())
210
- uut.push(child2, CommandListenerAdapter())
211
- val inOrder = inOrder(backButtonHelper, child2)
212
- inOrder.verify(backButtonHelper)!!.addToPushedChild(child2)
213
- inOrder.verify(child2)!!.parentController = uut
214
- inOrder.verify(child2, atLeastOnce())!!.view // creates view
215
- }
216
-
217
- @Test
218
- fun push_waitForRender() {
219
- disablePushAnimation(child1)
220
- uut.push(child1, CommandListenerAdapter())
221
- assertThat(child1.view.parent).isEqualTo(uut.view)
222
- child2.options.animations.push.waitForRender = Bool(true)
223
- uut.push(child2, CommandListenerAdapter())
224
-
225
- // Both children are attached
226
- assertThat(child1.view.parent).isEqualTo(uut.view)
227
- assertThat(child2.view.parent).isEqualTo(uut.view)
228
- assertThat(child2.isViewShown).isFalse()
229
- verify(child2, never()).onViewWillAppear()
230
- child2.view.addView(View(activity))
231
- ShadowLooper.idleMainLooper()
232
- verify(child2).onViewWillAppear()
233
- assertThat(child2.isViewShown).isTrue()
234
- animator.endPushAnimation(child2)
235
- assertThat(child1.view.parent).isNull()
236
- }
237
-
238
- @Test
239
- fun push_backPressedDuringPushAnimationDestroysPushedScreenImmediately() {
240
- backPressedDuringPushAnimation(false)
241
- }
242
-
243
- @Test
244
- @Ignore
245
- fun push_backPressedDuringPushAnimationDestroysPushedScreenImmediatelyWaitForRender() {
246
- backPressedDuringPushAnimation(true)
247
- }
248
-
249
- private fun backPressedDuringPushAnimation(waitForRender: Boolean) {
250
- disablePushAnimation(child1)
251
- uut.push(child1, CommandListenerAdapter())
252
- val pushListener = spy(CommandListenerAdapter())
253
- child2.options.animations.push.waitForRender = Bool(waitForRender)
254
- uut.push(child2, pushListener)
255
- // both children are attached
256
- assertThat(child1.view.parent).isEqualTo(uut.view)
257
- assertThat(child2.view.parent).isEqualTo(uut.view)
258
- val backListener = spy(CommandListenerAdapter())
259
- uut.handleBack(backListener)
260
- assertThat(uut.size()).isOne()
261
- assertThat(child1.view.parent).isEqualTo(uut.view)
262
- assertThat(child2.isDestroyed).isTrue()
263
- val inOrder = inOrder(pushListener, backListener)
264
- inOrder.verify(pushListener).onSuccess(any())
265
- inOrder.verify(backListener).onSuccess(any())
266
- }
267
-
268
- @Test
269
- fun push_rejectIfStackContainsChildWithId() {
270
- disablePushAnimation(child1)
271
- uut.push(child1, CommandListenerAdapter())
272
- assertThat(uut.size()).isEqualTo(1)
273
- val listener = spy(CommandListenerAdapter())
274
- uut.push(child1a, listener)
275
- verify(listener).onError(any())
276
- assertThat(uut.size()).isEqualTo(1)
277
- }
278
-
279
- @Test
280
- fun push_onViewDidAppearInvokedOnPushedScreen() {
281
- disablePushAnimation(child1, child2)
282
- uut.push(child1, CommandListenerAdapter()) // Initialize stack with a child
283
- uut.push(child2, CommandListenerAdapter())
284
- idleMainLooper()
285
- verify(child2).onViewDidAppear()
286
- }
287
-
288
- @Test
289
- fun `push - should make push when stack is not yet created`() {
290
- val child11 = spy(child1)
291
- val child21 = spy(child2)
292
- disablePushAnimation(child11, child21)
293
- uut.view = null
294
- uut.push(child11, mock())
295
- assertThat(uut.size()).isEqualTo(1)
296
- uut.push(child21, mock())
297
- assertThat(uut.size()).isEqualTo(2)
298
- verify(child11, never()).view
299
- verify(child21, never()).view
300
- }
301
-
302
- @Test
303
- fun animateSetRoot() {
304
- disablePushAnimation(child1, child2, child3)
305
- assertThat(uut.isEmpty).isTrue()
306
- uut.push(child1, CommandListenerAdapter())
307
- uut.push(child2, CommandListenerAdapter())
308
- uut.setRoot(listOf(child3), object : CommandListenerAdapter() {
309
- override fun onSuccess(childId: String) {
310
- assertContainsOnlyId(child3.id)
311
- }
312
- })
313
- }
314
-
315
- @Test
316
- fun setRoot_singleChild() {
317
- activity.setContentView(uut.view)
318
- disablePushAnimation(child1, child2, child3)
319
- assertThat(uut.isEmpty).isTrue()
320
- uut.push(child1, CommandListenerAdapter())
321
- uut.push(child2, CommandListenerAdapter())
322
- ShadowLooper.idleMainLooper()
323
- assertThat(uut.topBar.navigationIcon).isNotNull()
324
- uut.setRoot(listOf(child3), object : CommandListenerAdapter() {
325
- override fun onSuccess(childId: String) {
326
- assertContainsOnlyId(child3.id)
327
- ShadowLooper.idleMainLooper()
328
- assertThat(uut.topBar.navigationIcon).isNull()
329
- }
330
- })
331
- }
332
-
333
- @Test
334
- fun setRoot_multipleChildren() {
335
- Robolectric.getForegroundThreadScheduler().pause()
336
- activity.setContentView(uut.view)
337
- disablePushAnimation(child1, child2, child3, child4)
338
- disablePopAnimation(child4)
339
- assertThat(uut.isEmpty).isTrue()
340
- uut.push(child1, CommandListenerAdapter())
341
- uut.push(child2, CommandListenerAdapter())
342
- ShadowLooper.idleMainLooper()
343
- assertThat(uut.topBar.navigationIcon).isNotNull()
344
- uut.setRoot(listOf(child3, child4), object : CommandListenerAdapter() {
345
- override fun onSuccess(childId: String) {
346
- assertContainsOnlyId(child3.id, child4.id)
347
- assertThat(child4.isViewShown).isTrue()
348
- assertThat(child3.isViewShown).isFalse()
349
- assertThat(uut.currentChild).isEqualTo(child4)
350
- uut.pop(Options.EMPTY, CommandListenerAdapter())
351
- ShadowLooper.idleMainLooper()
352
- assertThat(uut.topBar.leftButtonBar.navigationIcon).isNull()
353
- assertThat(uut.currentChild).isEqualTo(child3)
354
- }
355
- })
356
- }
357
-
358
- @Test
359
- fun setRoot_backButtonIsAddedToAllChildren() {
360
- Robolectric.getForegroundThreadScheduler().pause()
361
- activity.setContentView(uut.view)
362
- disablePushAnimation(child1, child2)
363
- uut.setRoot(listOf(child1, child2), CommandListenerAdapter())
364
- assertThat(child1.options.topBar.buttons.back.visible[false]).isFalse()
365
- assertThat(child2.options.topBar.buttons.back.visible[false]).isTrue()
366
- }
367
-
368
- @Test
369
- fun setRoot_doesNotCrashWhenCalledInQuickSuccession() {
370
- disablePushAnimation(child1)
371
- uut.setRoot(listOf(child1), CommandListenerAdapter())
372
- uut.setRoot(listOf(child2), CommandListenerAdapter())
373
- uut.setRoot(listOf(child3), CommandListenerAdapter())
374
- animator.endPushAnimation(child2)
375
- animator.endPushAnimation(child3)
376
- assertContainsOnlyId(child3.id)
377
- }
378
-
379
- @Test
380
- fun setRoot_doesNotCrashWhenCalledWithSameId() {
381
- disablePushAnimation(child1, child1a)
382
- uut.setRoot(listOf(child1), CommandListenerAdapter())
383
- uut.setRoot(listOf(child1a), CommandListenerAdapter())
384
- assertContainsOnlyId(child1a.id)
385
- }
386
-
387
- @Test
388
- fun setRoot_topScreenIsStartedThenTheRest() {
389
- disablePushAnimation(child1, child2, child3)
390
- child3View = spy(SimpleView(activity))
391
- uut.setRoot(listOf(child1, child2, child3), CommandListenerAdapter())
392
- ShadowLooper.idleMainLooper()
393
- val inOrder = inOrder(child3View!!, child2, child1)
394
- inOrder.verify(child3View)!!.start()
395
- inOrder.verify(child2)!!.start()
396
- inOrder.verify(child1)!!.start()
397
- }
398
-
399
- @Test
400
- fun setRoot_onViewDidAppearIsInvokedOnAppearingChild() {
401
- disablePushAnimation(child1)
402
- uut.setRoot(listOf(child1), CommandListenerAdapter())
403
- verify(child1).onViewDidAppear()
404
- }
405
-
406
- @Test
407
- fun `setRoot - should change stack children, no view creation, when stack is not yet created`() {
408
- val spyChild = spy(child1)
409
- val spyChild2 = spy(child2)
410
- uut.view = null
411
-
412
- uut.setRoot(listOf(spyChild), CommandListenerAdapter())
413
- verify(spyChild, never()).view
414
- verify(spyChild).parentController = uut
415
- assertThat(uut.size()).isEqualTo(1)
416
-
417
- val listOf = listOf(spyChild, spyChild2)
418
- uut.setRoot(listOf, CommandListenerAdapter())
419
- verify(spyChild, never()).view
420
- verify(spyChild2, never()).view
421
- verify(spyChild2).parentController = uut
422
-
423
- assertThat(uut.size()).isEqualTo(2)
424
- assertThat(uut.childControllers).isEqualTo(listOf)
425
- }
426
-
427
- @Test
428
- fun setRoot_onViewDidAppearIsInvokedBeforePreviousRootIsDestroyed() {
429
- disablePushAnimation(child1, child2, child3)
430
- uut.push(child1, CommandListenerAdapter())
431
- uut.setRoot(listOf(child2, child3), CommandListenerAdapter())
432
- ShadowLooper.idleMainLooper()
433
- val inOrder = inOrder(child2, child3, child1)
434
- inOrder.verify(child3)!!.onViewDidAppear()
435
- inOrder.verify(child1)!!.onViewDisappear()
436
- verify(child2, never()).onViewDidAppear()
437
- }
438
-
439
- @Test
440
- fun pop() {
441
- disablePushAnimation(child1, child2)
442
- uut.push(child1, CommandListenerAdapter())
443
- uut.push(child2, object : CommandListenerAdapter() {
444
- override fun onSuccess(childId: String) {
445
- assertContainsOnlyId(child2.id, child1.id)
446
- uut.pop(Options.EMPTY, CommandListenerAdapter())
447
- assertContainsOnlyId(child1.id)
448
- }
449
- })
450
- }
451
-
452
- @Test
453
- fun `pop - should make pop when stack is not yet created`() {
454
- val child11 = spy(child1)
455
- val child21 = spy(child2)
456
- disablePushAnimation(child11, child21)
457
- uut.view = null
458
- uut.push(child11, mock())
459
- uut.push(child21, mock())
460
- uut.pop(Options.EMPTY, mock())
461
- assertThat(uut.size()).isEqualTo(1)
462
- verify(child11, never()).view
463
- verify(child21, never()).view
464
- }
465
- @Test
466
- fun pop_screenCurrentlyBeingPushedIsPopped() {
467
- disablePushAnimation(child1, child2)
468
- uut.push(child1, mock())
469
- uut.push(child2, mock())
470
- uut.push(child3, mock())
471
- uut.pop(Options.EMPTY, mock())
472
- assertThat(uut.size()).isEqualTo(2)
473
- assertContainsOnlyId(child1.id, child2.id)
474
- }
475
-
476
- @Test
477
- fun pop_appliesOptionsAfterPop() {
478
- disablePushAnimation(child1, child2)
479
- uut.push(child1, CommandListenerAdapter())
480
- uut.push(child2, CommandListenerAdapter())
481
-
482
- uut.pop(Options.EMPTY, CommandListenerAdapter())
483
- dispatchOnGlobalLayout(child1.view)
484
- verify(presenter).applyChildOptions(any(), eq(uut), eq(child1))
485
- }
486
-
487
- @Test
488
- fun pop_popEventIsEmitted() {
489
- disablePushAnimation(child1, child2)
490
- disablePopAnimation(child2)
491
- uut.push(child1, CommandListenerAdapter())
492
- uut.push(child2, CommandListenerAdapter())
493
- uut.pop(Options.EMPTY, CommandListenerAdapter())
494
- verify(eventEmitter).emitScreenPoppedEvent(child2.id)
495
- }
496
-
497
- @Test
498
- fun popToRoot_popEventIsEmitted() {
499
- disablePushAnimation(child1, child2, child3)
500
- disablePopAnimation(child2, child3)
501
- uut.push(child1, CommandListenerAdapter())
502
- uut.push(child2, CommandListenerAdapter())
503
- uut.push(child3, CommandListenerAdapter())
504
- uut.pop(Options.EMPTY, CommandListenerAdapter())
505
- verify(eventEmitter).emitScreenPoppedEvent(child3.id)
506
- verifyNoMoreInteractions(eventEmitter)
507
- }
508
-
509
- @Test
510
- fun stackOperations() {
511
- assertThat(uut.peek()).isNull()
512
- assertThat(uut.size()).isZero()
513
- assertThat(uut.isEmpty).isTrue()
514
- uut.push(child1, CommandListenerAdapter())
515
- assertThat(uut.peek()).isEqualTo(child1)
516
- assertThat(uut.size()).isEqualTo(1)
517
- assertThat(uut.isEmpty).isFalse()
518
- }
519
-
520
- @Test
521
- fun onChildDestroyed() {
522
- uut.onChildDestroyed(child2)
523
- verify(presenter).onChildDestroyed(child2)
524
- }
525
-
526
- @Test
527
- fun handleBack_PopsUnlessSingleChild() {
528
- assertThat(uut.isEmpty).isTrue()
529
- assertThat(uut.handleBack(CommandListenerAdapter())).isFalse()
530
- uut.push(child1, CommandListenerAdapter())
531
- assertThat(uut.size()).isEqualTo(1)
532
- assertThat(uut.handleBack(CommandListenerAdapter())).isFalse()
533
- uut.push(child2, object : CommandListenerAdapter() {
534
- override fun onSuccess(childId: String) {
535
- assertThat(uut.size()).isEqualTo(2)
536
- assertThat(uut.handleBack(CommandListenerAdapter())).isTrue()
537
- assertThat(uut.size()).isEqualTo(1)
538
- assertThat(uut.handleBack(CommandListenerAdapter())).isFalse()
539
- }
540
- })
541
- }
542
-
543
- @Test
544
- fun pop_doesNothingWhenZeroOrOneChild() {
545
- assertThat(uut.isEmpty).isTrue()
546
- uut.pop(Options.EMPTY, CommandListenerAdapter())
547
- assertThat(uut.isEmpty).isTrue()
548
- uut.push(child1, CommandListenerAdapter())
549
- uut.pop(Options.EMPTY, CommandListenerAdapter())
550
- assertContainsOnlyId(child1.id)
551
- }
552
-
553
- @Test
554
- fun pop_animationOptionsAreMergedCorrectlyToDisappearingChild() {
555
- disablePushAnimation(child1, child2)
556
- uut.push(child1, CommandListenerAdapter())
557
- uut.push(child2, CommandListenerAdapter())
558
-
559
- val mergeOptions = Options()
560
- mergeOptions.animations.pop.content = createEnterExitAnimation(duration = 123)
561
- uut.pop(mergeOptions, CommandListenerAdapter())
562
-
563
- val captor = argumentCaptor<Options>()
564
- verify(animator).pop(any(), any(), captor.capture(), any(), any())
565
- val animator = captor.firstValue.animations.pop.content.exit
566
- .getAnimation(mockView(activity))
567
- assertThat((animator as AnimatorSet).childAnimations.first().duration).isEqualTo(123)
568
- }
569
-
570
- @Test
571
- fun pop_animationOptionsAreMergedCorrectlyToDisappearingChildWithDefaultOptions() {
572
- disablePushAnimation(child1, child2)
573
- uut.push(child1, CommandListenerAdapter())
574
- uut.push(child2, CommandListenerAdapter())
575
-
576
- val defaultOptions = Options()
577
- defaultOptions.animations.pop.content = createEnterExitAnimation(duration = 123)
578
- uut.setDefaultOptions(defaultOptions)
579
- uut.pop(Options.EMPTY, CommandListenerAdapter())
580
- val captor = argumentCaptor<Options>()
581
- verify(animator).pop(any(), any(), captor.capture(), any(), any())
582
- val animator = captor.firstValue.animations.pop.content.exit
583
- .getAnimation(mockView(activity))
584
- assertThat((animator as AnimatorSet).childAnimations.first().duration).isEqualTo(123)
585
- }
586
-
587
- @Test
588
- fun canPopWhenSizeIsMoreThanOne() {
589
- assertThat(uut.isEmpty).isTrue()
590
- assertThat(uut.canPop()).isFalse()
591
- uut.push(child1, CommandListenerAdapter())
592
- assertContainsOnlyId(child1.id)
593
- assertThat(uut.canPop()).isFalse()
594
- uut.push(child2, CommandListenerAdapter())
595
- assertContainsOnlyId(child1.id, child2.id)
596
- assertThat(uut.canPop()).isTrue()
597
- }
598
-
599
- @Test
600
- fun push_addsToViewTree() {
601
- assertNotChildOf(uut.view, child1.view)
602
- uut.push(child1, CommandListenerAdapter())
603
- assertIsChild(uut.view, child1.view)
604
- }
605
-
606
- @Test
607
- fun push_removesPreviousFromTree() {
608
- disablePushAnimation(child1, child2)
609
- assertNotChildOf(uut.view, child1.view)
610
- uut.push(child1, CommandListenerAdapter())
611
- assertIsChild(uut.view, child1.view)
612
- idleMainLooper()
613
- uut.push(child2, CommandListenerAdapter())
614
- idleMainLooper()
615
- assertIsChild(uut.view, child2)
616
- assertNotChildOf(uut.view, child1)
617
- }
618
-
619
- @Test
620
- fun push_assignsRefToSelfOnPushedController() {
621
- assertThat(child1.parentController).isNull()
622
- uut.push(child1, CommandListenerAdapter())
623
- assertThat(child1.parentController).isEqualTo(uut)
624
- val anotherNavController = createStack("another")
625
- anotherNavController.ensureViewIsCreated()
626
- anotherNavController.push(child2, CommandListenerAdapter())
627
- assertThat(child2.parentController).isEqualTo(anotherNavController)
628
- }
629
-
630
- @Test
631
- fun push_doesNotAnimateTopBarIfScreenIsPushedWithoutAnimation() {
632
- uut.ensureViewIsCreated()
633
- child1.ensureViewIsCreated()
634
- child1.options.topBar.visible = Bool(false)
635
- child1.options.topBar.animate = Bool(false)
636
- disablePushAnimation(child1, child2)
637
-
638
- uut.push(child1, CommandListenerAdapter())
639
- child1.onViewWillAppear()
640
- assertThat(uut.topBar.visibility).isEqualTo(View.GONE)
641
-
642
- uut.push(child2, CommandListenerAdapter())
643
- child2.onViewWillAppear()
644
- verify(topBarController, never()).showAnimate(any(), any())
645
- assertThat(uut.topBar.visibility).isEqualTo(View.VISIBLE)
646
- verify(topBarController.view).resetViewProperties()
647
- }
648
-
649
- @Test
650
- fun push_animatesAndClearsPreviousAnimationValues() {
651
- uut.ensureViewIsCreated()
652
- child1.options.topBar.visible = Bool(false)
653
- child1.options.topBar.animate = Bool(false)
654
- child1.options.animations.push.enabled = Bool(false)
655
- uut.push(child1, CommandListenerAdapter())
656
- uut.push(child2, CommandListenerAdapter())
657
- verify(topBarController.view).resetViewProperties()
658
- }
659
-
660
- @Test
661
- fun pop_replacesViewWithPrevious() {
662
- disablePushAnimation(child1, child2)
663
- disablePopAnimation(child2)
664
- val child2View: View = child2.view
665
- val child1View: View = child1.view
666
- uut.push(child1, CommandListenerAdapter())
667
- uut.push(child2, CommandListenerAdapter())
668
- idleMainLooper()
669
- assertIsChild(uut.view, child2View)
670
- assertNotChildOf(uut.view, child1View)
671
- uut.pop(Options.EMPTY, CommandListenerAdapter())
672
- assertNotChildOf(uut.view, child2View)
673
- assertIsChild(uut.view, child1View)
674
- }
675
-
676
- @Test
677
- fun popTo_PopsTopUntilControllerIsNewTop() {
678
- uut.push(child1, CommandListenerAdapter())
679
- uut.push(child2, CommandListenerAdapter())
680
- uut.push(child3, object : CommandListenerAdapter() {
681
- override fun onSuccess(childId: String) {
682
- assertThat(uut.size()).isEqualTo(3)
683
- assertThat(uut.peek()).isEqualTo(child3)
684
- uut.popTo(child1, Options.EMPTY, CommandListenerAdapter())
685
- assertThat(uut.size()).isEqualTo(1)
686
- assertThat(uut.peek()).isEqualTo(child1)
687
- }
688
- })
689
- }
690
-
691
- @Test
692
- fun popTo_optionsAreMergedOnTopChild() {
693
- disablePushAnimation(child1, child2)
694
- uut.push(child1, CommandListenerAdapter())
695
- val mergeOptions = Options()
696
- uut.popTo(child2, mergeOptions, CommandListenerAdapter())
697
- uut.popTo(child1, mergeOptions, CommandListenerAdapter())
698
- verify(child1, never()).mergeOptions(mergeOptions)
699
- uut.push(child2, CommandListenerAdapter())
700
- uut.popTo(child1, mergeOptions, CommandListenerAdapter())
701
- verify(child2).mergeOptions(mergeOptions)
702
- }
703
-
704
- @Test
705
- fun popTo_NotAChildOfThisStack_DoesNothing() {
706
- uut.push(child1, CommandListenerAdapter())
707
- uut.push(child3, CommandListenerAdapter())
708
- assertThat(uut.size()).isEqualTo(2)
709
- uut.popTo(child2, Options.EMPTY, CommandListenerAdapter())
710
- assertThat(uut.size()).isEqualTo(2)
711
- }
712
-
713
- @Test
714
- fun popTo_animatesTopController() {
715
- disablePushAnimation(child1, child2, child3, child4)
716
- uut.push(child1, CommandListenerAdapter())
717
- uut.push(child2, CommandListenerAdapter())
718
- uut.push(child3, CommandListenerAdapter())
719
- uut.push(child4, CommandListenerAdapter())
720
- idleMainLooper()
721
- uut.popTo(child2, Options.EMPTY, CommandListenerAdapter())
722
- verify(animator, never()).pop(any(), eq(child1), any(), any(), any())
723
- verify(animator, never()).pop(any(), eq(child2), any(), any(), any())
724
- verify(animator, never()).pop(any(), eq(child3), any(), any(), any())
725
- verify(animator).pop(any(), eq(child4), any(), any(), any())
726
- }
727
-
728
- @Test
729
- fun popTo_pushAnimationIsCancelled() {
730
- disablePushAnimation(child1, child2)
731
- uut.push(child1, mock())
732
- uut.push(child2, mock())
733
- uut.push(child3, mock())
734
- idleMainLooper()
735
- uut.popTo(child1, Options.EMPTY, mock())
736
- animator.endPushAnimation(child3)
737
- assertContainsOnlyId(child1.id)
738
- }
739
-
740
- @Test
741
- fun popToRoot_PopsEverythingAboveFirstController() {
742
- child1.options.animations.push.enabled = Bool(false)
743
- child2.options.animations.push.enabled = Bool(false)
744
- uut.push(child1, CommandListenerAdapter())
745
- uut.push(child2, CommandListenerAdapter())
746
- uut.push(child3, object : CommandListenerAdapter() {
747
- override fun onSuccess(childId: String) {
748
- assertThat(uut.size()).isEqualTo(3)
749
- assertThat(uut.peek()).isEqualTo(child3)
750
- uut.popToRoot(Options.EMPTY, object : CommandListenerAdapter() {
751
- override fun onSuccess(childId: String) {
752
- assertThat(uut.size()).isEqualTo(1)
753
- assertThat(uut.peek()).isEqualTo(child1)
754
- }
755
- })
756
- }
757
- })
758
- }
759
-
760
- @Test
761
- fun popToRoot_onlyTopChildIsAnimated() {
762
- disablePushAnimation(child1, child2, child3)
763
- uut.push(child1, CommandListenerAdapter())
764
- uut.push(child2, CommandListenerAdapter())
765
- uut.push(child3, CommandListenerAdapter())
766
- idleMainLooper()
767
- uut.popToRoot(Options.EMPTY, object : CommandListenerAdapter() {
768
- override fun onSuccess(childId: String) {
769
- verify(animator).pop(eq(child1), eq(child3), any(), any(), any())
770
- }
771
- })
772
- }
773
-
774
- @Test
775
- fun popToRoot_topChildrenAreDestroyed() {
776
- child1.options.animations.push.enabled = Bool(false)
777
- child2.options.animations.push.enabled = Bool(false)
778
- child3.options.animations.push.enabled = Bool(false)
779
- uut.push(child1, CommandListenerAdapter())
780
- uut.push(child2, CommandListenerAdapter())
781
- uut.push(child3, CommandListenerAdapter())
782
- idleMainLooper()
783
- uut.popToRoot(Options.EMPTY, object : CommandListenerAdapter() {
784
- override fun onSuccess(childId: String) {
785
- verify(child1, never()).destroy()
786
- verify(child2).destroy()
787
- verify(child3).destroy()
788
- }
789
- })
790
- }
791
-
792
- @Test
793
- fun popToRoot_EmptyStackDoesNothing() {
794
- assertThat(uut.isEmpty).isTrue()
795
- val listener = spy(CommandListenerAdapter())
796
- uut.popToRoot(Options.EMPTY, listener)
797
- assertThat(uut.isEmpty).isTrue()
798
- verify(listener).onSuccess("")
799
- }
800
-
801
- @Test
802
- fun popToRoot_optionsAreMergedOnTopChild() {
803
- disablePushAnimation(child1, child2)
804
- uut.push(child1, CommandListenerAdapter())
805
- uut.push(child2, CommandListenerAdapter())
806
- val mergeOptions = Options()
807
- uut.popToRoot(mergeOptions, CommandListenerAdapter())
808
- verify(child2).mergeOptions(mergeOptions)
809
- verify(child1, never()).mergeOptions(mergeOptions)
810
- }
811
-
812
- @Test
813
- fun popToRoot_screenPushedBeforePopAnimationCompletesIsPopped() {
814
- disablePushAnimation(child1, child2)
815
- uut.push(child1, mock())
816
- uut.push(child2, mock())
817
- uut.push(child3, mock())
818
- idleMainLooper()
819
- uut.popToRoot(Options.EMPTY, mock())
820
- animator.endPushAnimation(child3)
821
- assertContainsOnlyId(child1.id)
822
- }
823
-
824
- @Test
825
- fun findControllerById_ReturnsSelfOrChildrenById() {
826
- assertThat(uut.findController("123")).isNull()
827
- assertThat(uut.findController(uut.id)).isEqualTo(uut)
828
- uut.push(child1, CommandListenerAdapter())
829
- assertThat(uut.findController(child1.id)).isEqualTo(child1)
830
- }
831
-
832
- @Test
833
- fun findControllerById_Deeply() {
834
- val stack = createStack("another")
835
- stack.ensureViewIsCreated()
836
- stack.push(child2, CommandListenerAdapter())
837
- uut.push(stack, CommandListenerAdapter())
838
- assertThat(uut.findController(child2.id)).isEqualTo(child2)
839
- }
840
-
841
- @Test
842
- fun pop_callsDestroyOnPoppedChild() {
843
- child2 = spy(child2)
844
- uut.push(child1, CommandListenerAdapter())
845
- uut.push(child2, CommandListenerAdapter())
846
-
847
- verify(child2, never()).destroy()
848
- uut.pop(Options.EMPTY, CommandListenerAdapter())
849
- verify(child2).destroy()
850
- }
851
-
852
- @Test
853
- fun pop_callWillDisappear() {
854
- disablePushAnimation(child1, child2)
855
- uut.push(child1, CommandListenerAdapter())
856
- uut.push(child2, CommandListenerAdapter())
857
- uut.pop(Options.EMPTY, CommandListenerAdapter())
858
- verify(child2).onViewWillDisappear()
859
- }
860
-
861
- @Test
862
- fun pop_callDidAppear() {
863
- disablePushAnimation(child1, child2)
864
- disablePopAnimation(child2)
865
- uut.push(child1, CommandListenerAdapter())
866
- uut.push(child2, CommandListenerAdapter())
867
- uut.pop(Options.EMPTY, CommandListenerAdapter())
868
- verify(child1).onViewDidAppear()
869
- }
870
-
871
- @Test
872
- fun pop_animatesTopBar() {
873
- uut.ensureViewIsCreated()
874
- disablePushAnimation(child1, child2)
875
- child1.options.topBar.visible = Bool(false)
876
-
877
- uut.push(child1, CommandListenerAdapter())
878
- child1.onViewWillAppear()
879
- assertThat(uut.topBar.visibility).isEqualTo(View.GONE)
880
-
881
- uut.push(child2, CommandListenerAdapter())
882
- child2.onViewWillAppear()
883
- assertThat(uut.topBar.visibility).isEqualTo(View.VISIBLE)
884
-
885
- uut.pop(Options.EMPTY, CommandListenerAdapter())
886
- assertThat(topBarAnimator.isAnimatingHide()).isTrue()
887
- }
888
-
889
- @Test
890
- fun pop_doesNotAnimateTopBarIfScreenIsPushedWithoutAnimation() {
891
- disablePushAnimation(child1)
892
- child1.options.topBar.visible = Bool(false)
893
- child1.options.topBar.animate = Bool(false)
894
-
895
- assertThat(uut.topBar.visibility).isEqualTo(View.VISIBLE)
896
- uut.push(child1, CommandListenerAdapter())
897
- child1.onViewWillAppear()
898
- assertThat(topBarAnimator.isAnimatingHide()).isFalse()
899
- assertThat(uut.topBar.visibility).isEqualTo(View.GONE)
900
- }
901
-
902
- @Test
903
- fun popTo_CallsDestroyOnPoppedChild() {
904
- child1 = spy(child1)
905
- child2 = spy(child2)
906
- child3 = spy(child3)
907
- uut.push(child1, CommandListenerAdapter())
908
- uut.push(child2, CommandListenerAdapter())
909
- uut.push(child3, object : CommandListenerAdapter() {
910
- override fun onSuccess(childId: String) {
911
- verify(child2, never()).destroy()
912
- verify(child3, never()).destroy()
913
- uut.popTo(child1, Options.EMPTY, object : CommandListenerAdapter() {
914
- override fun onSuccess(childId: String) {
915
- verify(child2).destroy()
916
- verify(child3).destroy()
917
- }
918
- })
919
- }
920
- })
921
- }
922
-
923
- @Test
924
- fun stackCanBePushed() {
925
- uut.view.removeFromParent()
926
- val parent = createStack("someStack")
927
- parent.ensureViewIsCreated()
928
- parent.push(uut, CommandListenerAdapter())
929
- uut.onViewWillAppear()
930
- assertThat(parent.view.getChildAt(0)).isEqualTo(uut.view)
931
- }
932
-
933
- @Test
934
- fun applyOptions_applyOnlyOnFirstStack() {
935
- uut.view.removeFromParent()
936
- val parent = spy(createStack("someStack"))
937
- parent.ensureViewIsCreated()
938
- parent.push(uut, CommandListenerAdapter())
939
- val childOptions = Options()
940
- childOptions.topBar.title.text = Text("Something")
941
- child1.options = childOptions
942
- uut.push(child1, CommandListenerAdapter())
943
- child1.ensureViewIsCreated()
944
- child1.onViewWillAppear()
945
- val optionsCaptor = argumentCaptor<Options>()
946
- val viewCaptor = argumentCaptor<ViewController<*>>()
947
- verify(parent).applyChildOptions(optionsCaptor.capture(), viewCaptor.capture())
948
- assertThat(optionsCaptor.firstValue.topBar.title.text.hasValue()).isFalse()
949
- }
950
-
951
- @Test
952
- fun applyOptions_topTabsAreNotVisibleIfNoTabsAreDefined() {
953
- uut.ensureViewIsCreated()
954
- uut.push(child1, CommandListenerAdapter())
955
- child1.ensureViewIsCreated()
956
- child1.onViewWillAppear()
957
- assertThat(ViewHelper.isVisible(uut.topBar.topTabs)).isFalse()
958
- }
959
-
960
- @Test
961
- fun buttonPressInvokedOnCurrentStack() {
962
- uut.ensureViewIsCreated()
963
- uut.push(child1, CommandListenerAdapter())
964
- uut.sendOnNavigationButtonPressed("btn1")
965
- verify(child1).sendOnNavigationButtonPressed("btn1")
966
- }
967
-
968
- @Test
969
- fun mergeChildOptions_updatesViewWithNewOptions() {
970
- val uut = spy(TestUtils.newStackController(activity)
971
- .setId("stack")
972
- .build())
973
- val optionsToMerge = Options()
974
- val vc = mock<ViewController<*>>()
975
- uut.mergeChildOptions(optionsToMerge, vc)
976
- verify(uut).mergeChildOptions(optionsToMerge, vc)
977
- }
978
-
979
- @Test
980
- fun mergeOptions_doesNotMergeOptionsIfViewIsNotVisible() {
981
- uut.mergeOptions(Options.EMPTY)
982
- verify(presenter, never()).mergeOptions(any(), any(), any())
983
- }
984
-
985
- @Test
986
- fun mergeChildOptions_updatesParentControllerWithNewOptions() {
987
- val uut = TestUtils.newStackController(activity)
988
- .setId("stack")
989
- .build()
990
- val parentController = mock<ParentController<*>>()
991
- uut.parentController = parentController
992
- uut.ensureViewIsCreated()
993
- val optionsToMerge = Options()
994
- optionsToMerge.topBar.testId = Text("topBarID")
995
- optionsToMerge.bottomTabsOptions.testId = Text("bottomTabsID")
996
- val vc = mock<ViewController<*>>()
997
- uut.mergeChildOptions(optionsToMerge, vc)
998
- val captor = argumentCaptor<Options>()
999
- verify(parentController).mergeChildOptions(captor.capture(), eq(vc))
1000
- assertThat(captor.firstValue.topBar.testId.hasValue()).isFalse()
1001
- assertThat(captor.firstValue.bottomTabsOptions.testId.get()).isEqualTo(optionsToMerge.bottomTabsOptions.testId.get())
1002
- }
1003
-
1004
- @Test
1005
- fun mergeChildOptions_StackRelatedOptionsAreCleared() {
1006
- uut.ensureViewIsCreated()
1007
- val parentController = mock<ParentController<*>>()
1008
- uut.parentController = parentController
1009
- val options = Options()
1010
- options.animations.push = StackAnimationOptions(JSONObject())
1011
- options.topBar.testId = Text("id")
1012
- options.fabOptions.id = Text("fabId")
1013
- val vc = mock<ViewController<*>>()
1014
- assertThat(options.fabOptions.hasValue()).isTrue()
1015
- uut.mergeChildOptions(options, vc)
1016
- val captor = argumentCaptor<Options>()
1017
- verify(parentController).mergeChildOptions(captor.capture(), eq(vc))
1018
- assertThat(captor.firstValue.animations.push.hasEnterValue()).isFalse()
1019
- assertThat(captor.firstValue.topBar.testId.hasValue()).isFalse()
1020
- assertThat(captor.firstValue.fabOptions.hasValue()).isFalse()
1021
- }
1022
-
1023
- @Test
1024
- fun applyChildOptions_appliesResolvedOptions() {
1025
- disablePushAnimation(child1, child2)
1026
- uut.push(child1, CommandListenerAdapter())
1027
- assertThat(uut.topBar.title).isNullOrEmpty()
1028
- val uutOptions = Options()
1029
- uutOptions.topBar.title.text = Text("UUT")
1030
- uut.mergeOptions(uutOptions)
1031
- assertThat(uut.topBar.title).isEqualTo("UUT")
1032
- uut.push(child2, CommandListenerAdapter())
1033
- assertThat(uut.topBar.title).isEqualTo("UUT")
1034
- }
1035
-
1036
- @Test
1037
- fun mergeChildOptions_presenterDoesNotApplyOptionsIfViewIsNotShown() {
1038
- val vc = mock<ViewController<*>>()
1039
- whenever(vc.isViewShown).then { true }
1040
- uut.mergeChildOptions(Options(), vc)
1041
- verify(presenter, never()).mergeChildOptions(any(), any(), any(), any())
1042
- }
1043
-
1044
- @Test
1045
- fun mergeChildOptions_presenterMergesOptionsOnlyForCurrentChild() {
1046
- val vc = mock<ViewController<*>>()
1047
- whenever(vc.isViewShown).then { true }
1048
- uut.mergeChildOptions(Options(), vc)
1049
- verify(presenter, never()).mergeChildOptions(any(), any(), any(), any())
1050
- }
1051
-
1052
- @Test
1053
- fun resolvedOptionsAreAppliedWhenStackIsAttachedToParentAndNotVisible() {
1054
- val parent = FrameLayout(activity)
1055
- activity.setContentView(parent)
1056
-
1057
- val child = SimpleViewController(activity, childRegistry, "child1", Options())
1058
- val stack = createStack(Collections.singletonList(child))
1059
- stack.view.visibility = View.INVISIBLE
1060
-
1061
- parent.addView(stack.view)
1062
-
1063
- ShadowLooper.idleMainLooper()
1064
- verify(presenter).applyChildOptions(any(), eq(stack), eq(child))
1065
- }
1066
-
1067
- @Test
1068
- fun onAttachToParent_doesNotCrashWhenCalledAfterDestroy() {
1069
- Robolectric.getForegroundThreadScheduler().pause()
1070
- val spy = spy(createStack())
1071
- val view = spy.view
1072
- spy.push(child1, CommandListenerAdapter())
1073
- activity.setContentView(view)
1074
- child1.destroy()
1075
- ShadowLooper.idleMainLooper()
1076
- verify(spy).onAttachToParent()
1077
- }
1078
-
1079
- @Test
1080
- fun onDependentViewChanged_delegatesToPresenter() {
1081
- val parent = mock<CoordinatorLayout>()
1082
- uut.push(child1, CommandListenerAdapter())
1083
- assertThat(uut.onDependentViewChanged(parent, child1.view, mock<TopBar>())).isFalse()
1084
- verify(presenter).applyTopInsets(eq(uut), eq(child1))
1085
- }
1086
-
1087
- @Test
1088
- fun onDependentViewChanged_TopBarIsRenderedBellowStatusBar() {
1089
- disablePushAnimation(child1)
1090
- uut.push(child1, CommandListenerAdapter())
1091
- ShadowLooper.idleMainLooper()
1092
- assertThat(ViewUtils.topMargin(uut.topBar)).isEqualTo(SystemUiUtils.getStatusBarHeight(activity))
1093
- }
1094
-
1095
- @Test
1096
- fun onDependentViewChanged_TopBarIsRenderedBehindStatusBar() {
1097
- uut.initialOptions.statusBar.visible = Bool(false)
1098
- disablePushAnimation(child1)
1099
- uut.push(child1, CommandListenerAdapter())
1100
- ShadowLooper.idleMainLooper()
1101
- assertThat(uut.topBar.y).isEqualTo(0f)
1102
- }
1103
-
1104
- @Test
1105
- fun topInset() {
1106
- disablePushAnimation(child1)
1107
- uut.push(child1, CommandListenerAdapter())
1108
- assertThat(uut.getTopInset(child1)).isEqualTo(topBarController.height)
1109
- val options = Options()
1110
- options.topBar.drawBehind = Bool(true)
1111
- child1.mergeOptions(options)
1112
- assertThat(uut.getTopInset(child1)).isEqualTo(0)
1113
- }
1114
-
1115
- @Test
1116
- fun topInset_defaultOptionsAreTakenIntoAccount() {
1117
- assertThat(uut.getTopInset(child1)).isEqualTo(topBarController.height)
1118
- val defaultOptions = Options()
1119
- defaultOptions.topBar.drawBehind = Bool(true)
1120
- uut.setDefaultOptions(defaultOptions)
1121
- assertThat(uut.getTopInset(child1)).isZero()
1122
- }
1123
-
1124
- private fun assertContainsOnlyId(vararg ids: String) {
1125
- assertThat(uut.size()).isEqualTo(ids.size)
1126
- assertThat(uut.childControllers).extracting(Extractor { obj: ViewController<*> -> obj.id } as Extractor<ViewController<*>, String>)
1127
- .containsOnly(*ids)
1128
- }
1129
-
1130
- private fun createStack(): StackController {
1131
- return createStackBuilder("stack", ArrayList()).build()
1132
- }
1133
-
1134
- private fun createStack(id: String): StackController {
1135
- return createStackBuilder(id, ArrayList()).build()
1136
- }
1137
-
1138
- private fun createStack(children: List<ViewController<*>>): StackController {
1139
- return createStackBuilder("stack", children).build()
1140
- }
1141
-
1142
- private fun createStackBuilder(id: String, children: List<ViewController<*>>): StackControllerBuilder {
1143
- createTopBarController()
1144
- return TestUtils.newStackController(activity)
1145
- .setEventEmitter(eventEmitter)
1146
- .setChildren(children)
1147
- .setId(id)
1148
- .setTopBarController(topBarController)
1149
- .setChildRegistry(childRegistry)
1150
- .setAnimator(animator)
1151
- .setStackPresenter(presenter)
1152
- .setBackButtonHelper(backButtonHelper)
1153
- }
1154
-
1155
- private fun createTopBarController() {
1156
- topBarAnimator = TopBarAnimator()
1157
- topBarController = spy(object : TopBarController(topBarAnimator) {
1158
- override fun createTopBar(context: Context, stackLayout: StackLayout): TopBar {
1159
- val spy = spy(super.createTopBar(context, stackLayout))
1160
- spy.layout(0, 0, 1000, UiUtils.getTopBarHeight(activity))
1161
- return spy
1162
- }
1163
- })
1164
- }
1165
- }