瀏覽代碼

Add tests for fetching contacts

Signed-off-by: sowjanyakch <sowjanya.kch@gmail.com>
sowjanyakch 1 年之前
父節點
當前提交
62b2ecd338

+ 5 - 0
app/build.gradle

@@ -158,6 +158,8 @@ ext {
     workVersion = "2.9.1"
     espressoVersion = "3.6.1"
     media3_version = "1.4.0"
+    coroutines_version = "1.3.9"
+    mockitoKotlinVersion = "4.1.0"
 }
 
 configurations.configureEach {
@@ -338,6 +340,9 @@ dependencies {
     testImplementation("junit:junit:4.13.2")
     androidTestImplementation(platform("androidx.compose:compose-bom:2024.06.00"))
     androidTestImplementation("androidx.compose.ui:ui-test-junit4")
+    testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion"
+    testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines_version"
+
 }
 
 tasks.register('installGitHooks', Copy) {

+ 1 - 0
app/src/main/java/com/nextcloud/talk/contacts/ContactsActivityCompose.kt

@@ -170,6 +170,7 @@ fun ContactsItem(contacts: List<AutocompleteUser>, contactsViewModel: ContactsVi
             }
             items(contactsForInitial) { contact ->
                 ContactItemRow(contact = contact, contactsViewModel = contactsViewModel, context = context)
+                Log.d(CompanionClass.TAG, "Contacts:$contact")
             }
         }
     }

+ 1 - 0
app/src/main/java/com/nextcloud/talk/contacts/ContactsRepository.kt

@@ -13,4 +13,5 @@ import com.nextcloud.talk.models.json.conversations.RoomOverall
 interface ContactsRepository {
     suspend fun getContacts(searchQuery: String?, shareTypes: List<String>): AutocompleteOverall
     suspend fun createRoom(roomType: String, sourceType: String, userId: String, conversationName: String?): RoomOverall
+    fun getImageUri(avatarId: String, requestBigSize: Boolean): String
 }

+ 8 - 0
app/src/main/java/com/nextcloud/talk/contacts/ContactsRepositoryImpl.kt

@@ -64,4 +64,12 @@ class ContactsRepositoryImpl(
         )
         return response
     }
+
+    override fun getImageUri(avatarId: String, requestBigSize: Boolean): String {
+        return ApiUtils.getUrlForAvatar(
+            _currentUser.baseUrl,
+            avatarId,
+            requestBigSize
+        )
+    }
 }

+ 2 - 13
app/src/main/java/com/nextcloud/talk/contacts/ContactsViewModel.kt

@@ -9,27 +9,21 @@ package com.nextcloud.talk.contacts
 
 import androidx.lifecycle.ViewModel
 import androidx.lifecycle.viewModelScope
-import com.nextcloud.talk.data.user.model.User
 import com.nextcloud.talk.models.json.autocomplete.AutocompleteUser
 import com.nextcloud.talk.models.json.conversations.Conversation
-import com.nextcloud.talk.users.UserManager
-import com.nextcloud.talk.utils.ApiUtils
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.launch
 import javax.inject.Inject
 
 class ContactsViewModel @Inject constructor(
-    private val repository: ContactsRepository,
-    private val userManager: UserManager
+    private val repository: ContactsRepository
 ) : ViewModel() {
 
     private val _contactsViewState = MutableStateFlow<ContactsUiState>(ContactsUiState.None)
     val contactsViewState: StateFlow<ContactsUiState> = _contactsViewState
     private val _roomViewState = MutableStateFlow<RoomUiState>(RoomUiState.None)
     val roomViewState: StateFlow<RoomUiState> = _roomViewState
-    private val _currentUser = userManager.currentUser.blockingGet()
-    val currentUser: User = _currentUser
     private val _searchQuery = MutableStateFlow("")
     val searchQuery: StateFlow<String> = _searchQuery
     private val shareTypes: MutableList<String> = mutableListOf(ShareType.User.shareType)
@@ -86,13 +80,8 @@ class ContactsViewModel @Inject constructor(
             }
         }
     }
-
     fun getImageUri(avatarId: String, requestBigSize: Boolean): String {
-        return ApiUtils.getUrlForAvatar(
-            _currentUser.baseUrl,
-            avatarId,
-            requestBigSize
-        )
+        return repository.getImageUri(avatarId, requestBigSize)
     }
 }
 

+ 53 - 0
app/src/test/java/com/nextcloud/talk/contacts/ContactsViewModelTest.kt

@@ -0,0 +1,53 @@
+/*
+ * Nextcloud Talk - Android Client
+ *
+ * SPDX-FileCopyrightText: 2024 Your Name <your@email.com>
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+package com.nextcloud.talk.contacts
+
+import com.nextcloud.talk.contacts.apiService.FakeItem
+import com.nextcloud.talk.contacts.repository.FakeRepositorySuccess
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestDispatcher
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import kotlinx.coroutines.test.resetMain
+import kotlinx.coroutines.test.runTest
+import kotlinx.coroutines.test.setMain
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+
+@OptIn(ExperimentalCoroutinesApi::class)
+class ContactsViewModelTest {
+    private lateinit var viewModel: ContactsViewModel
+    private val repository: ContactsRepository = FakeRepositorySuccess()
+
+    val dispatcher: TestDispatcher = UnconfinedTestDispatcher()
+
+    @Before
+    fun setup() {
+        Dispatchers.setMain(dispatcher)
+    }
+
+    @After
+    fun tearDown() {
+        Dispatchers.resetMain()
+    }
+
+    @Before
+    fun setUp()  {
+        viewModel = ContactsViewModel(repository)
+    }
+
+    @Test
+    fun `fetch contacts`() =
+        runTest {
+            viewModel.getContactsFromSearchParams()
+            assert(viewModel.contactsViewState.value is ContactsUiState.Success)
+            val successState = viewModel.contactsViewState.value as ContactsUiState.Success
+            assert(successState.contacts == FakeItem.contacts)
+        }
+}

+ 0 - 27
app/src/test/java/com/nextcloud/talk/contacts/apiService/FakeApiService.kt

@@ -1,27 +0,0 @@
-/*
- * Nextcloud Talk - Android Client
- *
- * SPDX-FileCopyrightText: 2024 Your Name <your@email.com>
- * SPDX-License-Identifier: GPL-3.0-or-later
- */
-
-package com.nextcloud.talk.contacts.apiService
-
-import com.nextcloud.talk.api.NcApiCoroutines
-import com.nextcloud.talk.models.json.autocomplete.AutocompleteOverall
-import com.nextcloud.talk.models.json.conversations.RoomOverall
-
-class FakeApiService() : NcApiCoroutines {
-    override suspend fun getContactsWithSearchParam(
-        authorization: String?,
-        url: String?,
-        listOfShareTypes: List<String>?,
-        options: Map<String, Any>?
-    ): AutocompleteOverall {
-        TODO("Not yet implemented")
-    }
-
-    override suspend fun createRoom(authorization: String?, url: String?, options: Map<String, String>?): RoomOverall {
-        TODO("Not yet implemented")
-    }
-}

+ 35 - 1
app/src/test/java/com/nextcloud/talk/contacts/apiService/FakeItem.kt

@@ -7,4 +7,38 @@
 
 package com.nextcloud.talk.contacts.apiService
 
-object FakeItem
+import com.nextcloud.talk.models.json.autocomplete.AutocompleteOCS
+import com.nextcloud.talk.models.json.autocomplete.AutocompleteOverall
+import com.nextcloud.talk.models.json.autocomplete.AutocompleteUser
+import com.nextcloud.talk.models.json.generic.GenericMeta
+
+object FakeItem {
+    val contacts: List<AutocompleteUser>? =
+        listOf(
+            AutocompleteUser(id = "android", label = "Android", source = "users"),
+            AutocompleteUser(id = "android1", label = "Android 1", source = "users"),
+            AutocompleteUser(id = "android2", label = "Android 2", source = "users"),
+            AutocompleteUser(id = "Benny", label = "Benny J", source = "users"),
+            AutocompleteUser(id = "Benjamin", label = "Benjamin Schmidt", source = "users"),
+            AutocompleteUser(id = "Chris", label = "Christoph Schmidt", source = "users"),
+            AutocompleteUser(id = "Daniel", label = "Daniel H", source = "users"),
+            AutocompleteUser(id = "Dennis", label = "Dennis Richard", source = "users"),
+            AutocompleteUser(id = "Emma", label = "Emma Jackson", source = "users"),
+            AutocompleteUser(id = "Emily", label = "Emily Jackson", source = "users"),
+            AutocompleteUser(id = "Mario", label = "Mario Schmidt", source = "users"),
+            AutocompleteUser(id = "Maria", label = "Maria Schmidt", source = "users"),
+            AutocompleteUser(id = "Samsung", label = "Samsung A52", source = "users"),
+            AutocompleteUser(id = "Tom", label = "Tom Müller", source = "users"),
+            AutocompleteUser(id = "Tony", label = "Tony Baker", source = "users")
+        )
+    val contactsOverall = AutocompleteOverall(
+        ocs = AutocompleteOCS(
+            meta = GenericMeta(
+                status = "ok",
+                statusCode = 200,
+                message = "OK"
+            ),
+            data = contacts
+        )
+    )
+}

+ 6 - 2
app/src/test/java/com/nextcloud/talk/contacts/repository/FakeRepositoryError.kt

@@ -13,7 +13,7 @@ import com.nextcloud.talk.models.json.conversations.RoomOverall
 
 class FakeRepositoryError() : ContactsRepository {
     override suspend fun getContacts(searchQuery: String?, shareTypes: List<String>): AutocompleteOverall {
-        TODO("Not yet implemented")
+        throw Exception("unknown error occurred")
     }
 
     override suspend fun createRoom(
@@ -22,6 +22,10 @@ class FakeRepositoryError() : ContactsRepository {
         userId: String,
         conversationName: String?
     ): RoomOverall {
-        TODO("Not yet implemented")
+        throw Exception("unknown error occurred")
+    }
+
+    override fun getImageUri(avatarId: String, requestBigSize: Boolean): String {
+        throw Exception("unknown error occurred")
     }
 }

+ 6 - 1
app/src/test/java/com/nextcloud/talk/contacts/repository/FakeRepositorySuccess.kt

@@ -8,12 +8,13 @@
 package com.nextcloud.talk.contacts.repository
 
 import com.nextcloud.talk.contacts.ContactsRepository
+import com.nextcloud.talk.contacts.apiService.FakeItem
 import com.nextcloud.talk.models.json.autocomplete.AutocompleteOverall
 import com.nextcloud.talk.models.json.conversations.RoomOverall
 
 class FakeRepositorySuccess() : ContactsRepository {
     override suspend fun getContacts(searchQuery: String?, shareTypes: List<String>): AutocompleteOverall {
-        TODO("Not yet implemented")
+        return FakeItem.contactsOverall
     }
 
     override suspend fun createRoom(
@@ -24,4 +25,8 @@ class FakeRepositorySuccess() : ContactsRepository {
     ): RoomOverall {
         TODO("Not yet implemented")
     }
+
+    override fun getImageUri(avatarId: String, requestBigSize: Boolean): String {
+        TODO("Not yet implemented")
+    }
 }

+ 28 - 2
gradle/verification-metadata.xml

@@ -7,10 +7,10 @@
          <trust group="com.android.tools.build" name="aapt2" version="8.4.1-11315950" reason="ships OS specific artifacts (win/linux) - temp global trust"/>
          <trust group="com.github.nextcloud-deps" name="android-talk-webrtc" version="110.5481.0" reason="ships OS specific artifacts (win/linux) - temp global trust"/>
          <trust file=".*-sources[.]jar" regex="true"/>
-		 <trust file="tensorflow-lite-metadata-0.1.0-rc2.pom" reason="differing hash on every CI run - temp global trust"/>
           <trust group="com.google.dagger" />
           <trust group="org.javassist" name="javassist" version="3.26.0-GA" reason="java assist"/>
           <trust group="androidx.fragment"/>
+		 <trust file="tensorflow-lite-metadata-0.1.0-rc2.pom" reason="differing hash on every CI run - temp global trust"/>
       </trusted-artifacts>
       <ignored-keys>
          <ignored-key id="0AA3E5C3D232E79B" reason="Key couldn't be downloaded from any key server"/>
@@ -39,7 +39,10 @@
          <trusted-key id="0F07D1201BDDAB67CFB84EB479752DB6C966F0B8" group="com.google.android" name="annotations" version="4.1.1.4"/>
          <trusted-key id="10F3C7A02ECA55E502BADCF3991EFB94DB91127D" group="org.ow2" name="ow2" version="1.5.1"/>
          <trusted-key id="120D6F34E627ED3A772EBBFE55C7E5E701832382" group="org.snakeyaml" name="snakeyaml-engine" version="2.6"/>
-         <trusted-key id="147B691A19097624902F4EA9689CBE64F4BC997F" group="org.mockito"/>
+         <trusted-key id="147B691A19097624902F4EA9689CBE64F4BC997F">
+            <trusting group="org.mockito"/>
+            <trusting group="org.mockito.kotlin" name="mockito-kotlin" version="4.1.0"/>
+         </trusted-key>
          <trusted-key id="1597AB231B7ADD7E14B1D9C43F00DB67AE236E2E" group="org.conscrypt" name="conscrypt-android" version="2.5.2"/>
          <trusted-key id="190D5A957FF22273E601F7A7C92C5FEC70161C62" group="org.apache" name="apache" version="18"/>
          <trusted-key id="19BEAB2D799C020F17C69126B16698A4ADF4D638" group="org.checkerframework"/>
@@ -156,6 +159,7 @@
          <trusted-key id="8756C4F765C9AC3CB6B85D62379CE192D401AB61">
             <trusting group="eu.davidea"/>
             <trusting group="org.jetbrains.intellij.deps"/>
+            <trusting group="org.jetbrains.kotlinx"/>
          </trusted-key>
          <trusted-key id="8E3A02905A1AE67E7B0F9ACD3967D4EDA591B991" group="org.jetbrains.kotlinx" name="kotlinx-html-jvm" version="0.8.1"/>
          <trusted-key id="8F9A3C6D105B9F57844A721D79E193516BE7998F" group="org.dom4j" name="dom4j" version="2.1.4"/>
@@ -295,6 +299,14 @@
             <sha256 value="f7a29bcba338575dcf89a553cff9cfad3f140340eaf2b56fd0193244da602c0a" origin="Generated by Gradle" reason="Artifact is not signed"/>
          </artifact>
       </component>
+      <component group="androidx.activity" name="activity-compose" version="1.7.0">
+         <artifact name="activity-compose-1.7.0.aar">
+            <sha256 value="caa72885d1ce7979c1d6c59a8b255c6097b770780d4d4da95d56979a348646cd" origin="Generated by Gradle" reason="Artifact is not signed"/>
+         </artifact>
+         <artifact name="activity-compose-1.7.0.module">
+            <sha256 value="f7a29bcba338575dcf89a553cff9cfad3f140340eaf2b56fd0193244da602c0a" origin="Generated by Gradle" reason="Artifact is not signed"/>
+         </artifact>
+      </component>
       <component group="androidx.annotation" name="annotation" version="1.0.0">
          <artifact name="annotation-1.0.0.jar">
             <sha256 value="0baae9755f7caf52aa80cd04324b91ba93af55d4d1d17dcc9a7b53d99ef7c016" origin="Generated by Gradle" reason="Artifact is not signed"/>
@@ -412,6 +424,20 @@
        <artifact name="annotation-experimental-1.1.0-rc01.module">
            <sha256 value="d45ac493e84d968aabb2bea2b7744031a98cf5074447c0f3b862d600fc44b55c" origin="Generated by Gradle" reason="Artifact is not signed"/>
        </artifact>
+       </component>
+      <component group="androidx.annotation" name="annotation-experimental" version="1.1.0-rc01">
+         <artifact name="annotation-experimental-1.1.0-rc01.module">
+            <sha256 value="d45ac493e84d968aabb2bea2b7744031a98cf5074447c0f3b862d600fc44b55c" origin="Generated by Gradle" reason="Artifact is not signed"/>
+         </artifact>
+      </component>
+      <component group="androidx.annotation" name="annotation-experimental" version="1.3.0">
+         <artifact name="annotation-experimental-1.3.0.aar">
+            <sha256 value="abfd29c8556e5bd0325a9f769ab9e9d154ff4a5515c476cdd5a2a8285b1b19dc" origin="Generated by Gradle" reason="Artifact is not signed"/>
+         </artifact>
+         <artifact name="annotation-experimental-1.3.0.module">
+            <sha256 value="5eebeaff01d042e06dcf292abf8964ad391e4b0159f0090f16253d6045d38da0" origin="Generated by Gradle" reason="Artifact is not signed"/>
+         </artifact>
+      </component>
       <component group="androidx.annotation" name="annotation-experimental" version="1.3.1">
          <artifact name="annotation-experimental-1.3.1.aar">
             <sha256 value="e4d49dc3880b7b7437ea54ce71461e02897faa4e1ecc53e63ecadb1a14c20c9c" origin="Generated by Gradle" reason="Artifact is not signed"/>