TestEtmViewModel.kt 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. /*
  2. * Nextcloud - Android Client
  3. *
  4. * SPDX-FileCopyrightText: 2020 Chris Narkiewicz <hello@ezaquarii.com>
  5. * SPDX-License-Identifier: AGPL-3.0-or-later
  6. */
  7. package com.nextcloud.client.etm
  8. import android.accounts.AccountManager
  9. import android.content.Context
  10. import android.content.SharedPreferences
  11. import android.content.res.Resources
  12. import androidx.arch.core.executor.testing.InstantTaskExecutorRule
  13. import androidx.lifecycle.LiveData
  14. import androidx.lifecycle.Observer
  15. import com.nextcloud.client.account.MockUser
  16. import com.nextcloud.client.account.UserAccountManager
  17. import com.nextcloud.client.etm.pages.EtmBackgroundJobsFragment
  18. import com.nextcloud.client.jobs.BackgroundJobManager
  19. import com.nextcloud.client.jobs.JobInfo
  20. import com.nextcloud.client.migrations.MigrationsDb
  21. import com.nextcloud.client.migrations.MigrationsManager
  22. import org.junit.Assert.assertEquals
  23. import org.junit.Assert.assertFalse
  24. import org.junit.Assert.assertNotNull
  25. import org.junit.Assert.assertNull
  26. import org.junit.Assert.assertSame
  27. import org.junit.Assert.assertTrue
  28. import org.junit.Before
  29. import org.junit.Rule
  30. import org.junit.Test
  31. import org.junit.runner.RunWith
  32. import org.junit.runners.Suite
  33. import org.mockito.kotlin.any
  34. import org.mockito.kotlin.anyOrNull
  35. import org.mockito.kotlin.eq
  36. import org.mockito.kotlin.inOrder
  37. import org.mockito.kotlin.mock
  38. import org.mockito.kotlin.never
  39. import org.mockito.kotlin.reset
  40. import org.mockito.kotlin.same
  41. import org.mockito.kotlin.times
  42. import org.mockito.kotlin.verify
  43. import org.mockito.kotlin.whenever
  44. @RunWith(Suite::class)
  45. @Suite.SuiteClasses(
  46. TestEtmViewModel.MainPage::class,
  47. TestEtmViewModel.PreferencesPage::class,
  48. TestEtmViewModel.BackgroundJobsPage::class
  49. )
  50. class TestEtmViewModel {
  51. internal abstract class Base {
  52. @get:Rule
  53. val rule = InstantTaskExecutorRule()
  54. protected lateinit var context: Context
  55. protected lateinit var platformAccountManager: AccountManager
  56. protected lateinit var accountManager: UserAccountManager
  57. protected lateinit var sharedPreferences: SharedPreferences
  58. protected lateinit var vm: EtmViewModel
  59. protected lateinit var resources: Resources
  60. protected lateinit var backgroundJobManager: BackgroundJobManager
  61. protected lateinit var migrationsManager: MigrationsManager
  62. protected lateinit var migrationsDb: MigrationsDb
  63. @Before
  64. fun setUpBase() {
  65. context = mock()
  66. sharedPreferences = mock()
  67. platformAccountManager = mock()
  68. accountManager = mock()
  69. resources = mock()
  70. backgroundJobManager = mock()
  71. migrationsManager = mock()
  72. migrationsDb = mock()
  73. whenever(resources.getString(any())).thenReturn("mock-account-type")
  74. whenever(accountManager.user).thenReturn(MockUser())
  75. vm = EtmViewModel(
  76. context,
  77. sharedPreferences,
  78. platformAccountManager,
  79. accountManager,
  80. resources,
  81. backgroundJobManager,
  82. migrationsManager,
  83. migrationsDb
  84. )
  85. }
  86. }
  87. internal class MainPage : Base() {
  88. @Test
  89. fun `current page is not set`() {
  90. // GIVEN
  91. // main page is displayed
  92. // THEN
  93. // current page is null
  94. assertNull(vm.currentPage.value)
  95. }
  96. @Test
  97. fun `back key is not handled`() {
  98. // GIVEN
  99. // main page is displayed
  100. // WHEN
  101. // back key is pressed
  102. val handled = vm.onBackPressed()
  103. // THEN
  104. // is not handled
  105. assertFalse(handled)
  106. }
  107. @Test
  108. fun `page is selected`() {
  109. val observer: Observer<EtmMenuEntry?> = mock()
  110. val selectedPageIndex = 0
  111. val expectedPage = vm.pages[selectedPageIndex]
  112. // GIVEN
  113. // main page is displayed
  114. // current page observer is registered
  115. vm.currentPage.observeForever(observer)
  116. reset(observer)
  117. // WHEN
  118. // page is selected
  119. vm.onPageSelected(selectedPageIndex)
  120. // THEN
  121. // current page is set
  122. // page observer is called once with selected entry
  123. assertNotNull(vm.currentPage.value)
  124. verify(observer, times(1)).onChanged(same(expectedPage))
  125. }
  126. @Test
  127. fun `out of range index is ignored`() {
  128. val maxIndex = vm.pages.size
  129. // GIVEN
  130. // observer is registered
  131. val observer: Observer<EtmMenuEntry?> = mock()
  132. vm.currentPage.observeForever(observer)
  133. reset(observer)
  134. // WHEN
  135. // out of range page index is selected
  136. vm.onPageSelected(maxIndex + 1)
  137. // THEN
  138. // nothing happens
  139. verify(observer, never()).onChanged(anyOrNull())
  140. assertNull(vm.currentPage.value)
  141. }
  142. }
  143. internal class PreferencesPage : Base() {
  144. @Before
  145. fun setUp() {
  146. vm.onPageSelected(0)
  147. }
  148. @Test
  149. fun `back goes back to main page`() {
  150. val observer: Observer<EtmMenuEntry?> = mock()
  151. // GIVEN
  152. // a page is selected
  153. // page observer is registered
  154. assertNotNull(vm.currentPage.value)
  155. vm.currentPage.observeForever(observer)
  156. // WHEN
  157. // back is pressed
  158. val handled = vm.onBackPressed()
  159. // THEN
  160. // back press is handled
  161. // observer is called with null page
  162. assertTrue(handled)
  163. verify(observer).onChanged(eq(null))
  164. }
  165. @Test
  166. fun `back is handled only once`() {
  167. // GIVEN
  168. // a page is selected
  169. assertNotNull(vm.currentPage.value)
  170. // WHEN
  171. // back is pressed twice
  172. val first = vm.onBackPressed()
  173. val second = vm.onBackPressed()
  174. // THEN
  175. // back is handled only once
  176. assertTrue(first)
  177. assertFalse(second)
  178. }
  179. @Test
  180. fun `preferences are loaded from shared preferences`() {
  181. // GIVEN
  182. // shared preferences contain values of different types
  183. val preferenceValues: Map<String, Any> = mapOf(
  184. "key1" to 1,
  185. "key2" to "value2",
  186. "key3" to false
  187. )
  188. whenever(sharedPreferences.all).thenReturn(preferenceValues)
  189. // WHEN
  190. // vm preferences are read
  191. val prefs = vm.preferences
  192. // THEN
  193. // all preferences are converted to strings
  194. assertEquals(preferenceValues.size, prefs.size)
  195. assertEquals("1", prefs["key1"])
  196. assertEquals("value2", prefs["key2"])
  197. assertEquals("false", prefs["key3"])
  198. }
  199. }
  200. internal class BackgroundJobsPage : Base() {
  201. @Before
  202. fun setUp() {
  203. vm.onPageSelected(EtmViewModel.PAGE_JOBS)
  204. assertEquals(EtmBackgroundJobsFragment::class, vm.currentPage.value?.pageClass)
  205. }
  206. @Test
  207. fun `prune jobs action is delegated to job manager`() {
  208. vm.pruneJobs()
  209. verify(backgroundJobManager).pruneJobs()
  210. }
  211. @Test
  212. fun `start stop test job actions are delegated to job manager`() {
  213. vm.startTestJob(true)
  214. vm.cancelTestJob()
  215. inOrder(backgroundJobManager).apply {
  216. verify(backgroundJobManager).scheduleTestJob()
  217. verify(backgroundJobManager).cancelTestJob()
  218. }
  219. }
  220. @Test
  221. fun `job info is taken from job manager`() {
  222. val jobInfo: LiveData<List<JobInfo>> = mock()
  223. whenever(backgroundJobManager.jobs).thenReturn(jobInfo)
  224. assertSame(jobInfo, vm.backgroundJobs)
  225. }
  226. }
  227. }