Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Table of Contents

* [Changelog for unreleased](#changelog-for-owncloud-android-client-unreleased-unreleased)
* [Changelog for 4.7.0](#changelog-for-owncloud-android-client-470-2025-11-17)
* [Changelog for 4.6.2](#changelog-for-owncloud-android-client-462-2025-08-13)
* [Changelog for 4.6.1](#changelog-for-owncloud-android-client-461-2025-08-01)
Expand Down Expand Up @@ -30,6 +31,27 @@
* [Changelog for 2.18.1](#changelog-for-owncloud-android-client-2181-2021-07-20)
* [Changelog for 2.18.0](#changelog-for-owncloud-android-client-2180-2021-05-24)
* [Changelog for 2.17 versions and below](#changelog-for-217-versions-and-below)
# Changelog for ownCloud Android Client [unreleased] (UNRELEASED)

The following sections list the changes in ownCloud Android Client unreleased relevant to
ownCloud admins and users.

[unreleased]: https://github.com/owncloud/android/compare/v4.7.0...master

## Summary

* Change - Migrate tests to the new kotlinx-coroutines-test API: [#4710](https://github.com/owncloud/android/issues/4710)

## Details

* Change - Migrate tests to the new kotlinx-coroutines-test API: [#4710](https://github.com/owncloud/android/issues/4710)

Some tests from view model classes have been refactored in order to use the new
kotlinx-coroutines-test API.

https://github.com/owncloud/android/issues/4710
https://github.com/owncloud/android/pull/4722

# Changelog for ownCloud Android Client [4.7.0] (2025-11-17)

The following sections list the changes in ownCloud Android Client 4.7.0 relevant to
Expand Down
6 changes: 6 additions & 0 deletions changelog/unreleased/4722
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Change: Migrate tests to the new kotlinx-coroutines-test API

Some tests from view model classes have been refactored in order to use the new kotlinx-coroutines-test API.

https://github.com/owncloud/android/issues/4710
https://github.com/owncloud/android/pull/4722
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ glideToVectorYou = "v2.0.0"
junit4 = "4.13.2"
koin = "3.3.3"
kotlin = "1.9.20"
kotlinxCoroutines = "1.6.4"
kotlinxCoroutines = "1.9.0"
ksp = "1.9.20-1.0.14"
ktlint = "11.1.0"
markwon = "4.6.2"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ class DrawerViewModelTest : ViewModelTest() {
getUserQuotasUseCase = mockk()
localStorageProvider = mockk()

testCoroutineDispatcher.pauseDispatcher()

drawerViewModel = DrawerViewModel(
getStoredQuotaAsStreamUseCase = getStoredQuotaAsStreamUseCase,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import com.owncloud.android.testutil.livedata.getEmittedValues
import io.mockk.unmockkAll
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestCoroutineDispatcher
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.resetMain
import org.junit.After
import org.junit.Assert.assertEquals
Expand All @@ -41,7 +41,7 @@ open class ViewModelTest {
@JvmField
val instantExecutorRule = InstantTaskExecutorRule()

val testCoroutineDispatcher = TestCoroutineDispatcher()
val testCoroutineDispatcher = StandardTestDispatcher()
val coroutineDispatcherProvider: CoroutinesDispatcherProvider = CoroutinesDispatcherProvider(
io = testCoroutineDispatcher,
main = testCoroutineDispatcher,
Expand All @@ -51,18 +51,14 @@ open class ViewModelTest {
@After
open fun tearDown() {
Dispatchers.resetMain()
testCoroutineDispatcher.cleanupTestCoroutines()

unmockkAll()
}

fun <DomainModel> assertEmittedValues(
expectedValues: List<Event<UIResult<DomainModel>>>,
liveData: LiveData<Event<UIResult<DomainModel>>>
) {
val emittedValues = liveData.getEmittedValues(expectedValues.size) {
testCoroutineDispatcher.resumeDispatcher()
}
val emittedValues = liveData.getEmittedValues(expectedValues.size)
assertEquals(expectedValues, emittedValues)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ import io.mockk.mockkConstructor
import io.mockk.verify
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.advanceUntilIdle
import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.test.setMain
import org.junit.After
import org.junit.Before
Expand Down Expand Up @@ -129,7 +131,6 @@ class AuthenticationViewModelTest : ViewModelTest() {
every { contextProvider.getBoolean(R.bool.enforce_secure_connection) } returns false
every { contextProvider.getBoolean(R.bool.enforce_oidc) } returns false

testCoroutineDispatcher.pauseDispatcher()

authenticationViewModel = AuthenticationViewModel(
loginBasicAsyncUseCase = loginBasicAsyncUseCase,
Expand Down Expand Up @@ -157,63 +158,55 @@ class AuthenticationViewModelTest : ViewModelTest() {
}

@Test
fun getServerInfoOk() {
fun getServerInfoOk() = runTest {
every { getServerInfoAsyncUseCase(any()) } returns UseCaseResult.Success(OC_SECURE_SERVER_INFO_BASIC_AUTH)
authenticationViewModel.getServerInfo(OC_SECURE_SERVER_INFO_BASIC_AUTH.baseUrl)

authenticationViewModel.getServerInfo(OC_SECURE_SERVER_INFO_BASIC_AUTH.baseUrl)
advanceUntilIdle()
assertEmittedValues(
expectedValues = listOf(
Event(UIResult.Loading()),
Event(UIResult.Success(OC_SECURE_SERVER_INFO_BASIC_AUTH))
),
expectedValues = listOf(Event(UIResult.Success(OC_SECURE_SERVER_INFO_BASIC_AUTH))),
liveData = authenticationViewModel.serverInfo
)
}

@Test
fun getServerInfoException() {
fun getServerInfoException() = runTest {
every { getServerInfoAsyncUseCase(any()) } returns UseCaseResult.Error(commonException)
authenticationViewModel.getServerInfo(OC_SECURE_SERVER_INFO_BASIC_AUTH.baseUrl)

authenticationViewModel.getServerInfo(OC_SECURE_SERVER_INFO_BASIC_AUTH.baseUrl)
advanceUntilIdle()
assertEmittedValues(
expectedValues = listOf(
Event(UIResult.Loading()),
Event(UIResult.Error(commonException))
),
expectedValues = listOf(Event(UIResult.Error(commonException))),
liveData = authenticationViewModel.serverInfo
)
}

@Test
fun loginBasicOk() {
fun loginBasicOk() = runTest {
every { loginBasicAsyncUseCase(any()) } returns UseCaseResult.Success(OC_BASIC_USERNAME)
authenticationViewModel.loginBasic(OC_BASIC_USERNAME, OC_BASIC_PASSWORD, OC_ACCOUNT_NAME)

authenticationViewModel.loginBasic(OC_BASIC_USERNAME, OC_BASIC_PASSWORD, OC_ACCOUNT_NAME)
advanceUntilIdle()
assertEmittedValues(
expectedValues = listOf(
Event(UIResult.Loading()),
Event(UIResult.Success(OC_BASIC_USERNAME))
),
expectedValues = listOf(Event(UIResult.Success(OC_BASIC_USERNAME))),
liveData = authenticationViewModel.loginResult
)
}

@Test
fun loginBasicException() {
fun loginBasicException() = runTest {
every { loginBasicAsyncUseCase(any()) } returns UseCaseResult.Error(commonException)
authenticationViewModel.loginBasic(OC_BASIC_USERNAME, OC_BASIC_PASSWORD, null)

authenticationViewModel.loginBasic(OC_BASIC_USERNAME, OC_BASIC_PASSWORD, null)
advanceUntilIdle()
assertEmittedValues(
expectedValues = listOf(
Event(UIResult.Loading()),
Event(UIResult.Error(commonException))
),
expectedValues = listOf(Event(UIResult.Error(commonException))),
liveData = authenticationViewModel.loginResult
)
}

@Test
fun loginOAuthWebFingerInstancesOk() {
fun loginOAuthWebFingerInstancesOk() = runTest {
every { getServerInfoAsyncUseCase(any()) } returns UseCaseResult.Success(OC_SECURE_SERVER_INFO_BEARER_AUTH)
authenticationViewModel.getServerInfo(OC_SECURE_SERVER_INFO_BEARER_AUTH.baseUrl)

Expand All @@ -229,12 +222,9 @@ class AuthenticationViewModelTest : ViewModelTest() {
scope = OC_SCOPE,
clientRegistrationInfo = OC_CLIENT_REGISTRATION
)

advanceUntilIdle()
assertEmittedValues(
expectedValues = listOf(
Event(UIResult.Loading()),
Event(UIResult.Success(OC_BASIC_USERNAME))
),
expectedValues = listOf(Event(UIResult.Success(OC_BASIC_USERNAME))),
liveData = authenticationViewModel.loginResult
)

Expand All @@ -255,7 +245,7 @@ class AuthenticationViewModelTest : ViewModelTest() {
}

@Test
fun loginOAuthOk() {
fun loginOAuthOk() = runTest {
every { getServerInfoAsyncUseCase(any()) } returns UseCaseResult.Success(OC_SECURE_SERVER_INFO_BEARER_AUTH)
authenticationViewModel.getServerInfo(OC_SECURE_SERVER_INFO_BEARER_AUTH.baseUrl)

Expand All @@ -271,12 +261,9 @@ class AuthenticationViewModelTest : ViewModelTest() {
scope = OC_SCOPE,
clientRegistrationInfo = OC_CLIENT_REGISTRATION
)

advanceUntilIdle()
assertEmittedValues(
expectedValues = listOf(
Event(UIResult.Loading()),
Event(UIResult.Success(OC_BASIC_USERNAME))
),
expectedValues = listOf(Event(UIResult.Success(OC_BASIC_USERNAME))),
liveData = authenticationViewModel.loginResult
)

Expand All @@ -297,7 +284,7 @@ class AuthenticationViewModelTest : ViewModelTest() {
}

@Test
fun loginOAuthException() {
fun loginOAuthException() = runTest {
every { getServerInfoAsyncUseCase(any()) } returns UseCaseResult.Success(OC_SECURE_SERVER_INFO_BEARER_AUTH)
authenticationViewModel.getServerInfo(OC_SECURE_SERVER_INFO_BEARER_AUTH.baseUrl)

Expand All @@ -313,54 +300,55 @@ class AuthenticationViewModelTest : ViewModelTest() {
scope = OC_SCOPE,
clientRegistrationInfo = OC_CLIENT_REGISTRATION
)

advanceUntilIdle()
assertEmittedValues(
expectedValues = listOf(
Event(UIResult.Loading()),
Event(UIResult.Error(commonException))
),
expectedValues = listOf(Event(UIResult.Error(commonException))),
liveData = authenticationViewModel.loginResult
)
}

@Test
fun supportsOAuthOk() {
fun supportsOAuthOk() = runTest {
every { supportsOAuth2UseCase(any()) } returns UseCaseResult.Success(true)
authenticationViewModel.supportsOAuth2(OC_BASIC_USERNAME)

authenticationViewModel.supportsOAuth2(OC_BASIC_USERNAME)
advanceUntilIdle()
assertEmittedValues(
expectedValues = listOf<Event<UIResult<Boolean>>>(Event(UIResult.Success(true))),
liveData = authenticationViewModel.supportsOAuth2
)
}

@Test
fun supportsOAuthException() {
fun supportsOAuthException() = runTest {
every { supportsOAuth2UseCase(any()) } returns UseCaseResult.Error(commonException)
authenticationViewModel.supportsOAuth2(OC_BASIC_USERNAME)

authenticationViewModel.supportsOAuth2(OC_BASIC_USERNAME)
advanceUntilIdle()
assertEmittedValues(
expectedValues = listOf<Event<UIResult<Boolean>>>(Event(UIResult.Error(commonException))),
liveData = authenticationViewModel.supportsOAuth2
)
}

@Test
fun getBaseUrlOk() {
fun getBaseUrlOk() = runTest {
every { getBaseUrlUseCase(any()) } returns UseCaseResult.Success(OC_SECURE_BASE_URL)
authenticationViewModel.getBaseUrl(OC_BASIC_USERNAME)

authenticationViewModel.getBaseUrl(OC_BASIC_USERNAME)
advanceUntilIdle()
assertEmittedValues(
expectedValues = listOf<Event<UIResult<String>>>(Event(UIResult.Success(OC_SECURE_BASE_URL))),
liveData = authenticationViewModel.baseUrl
)
}

@Test
fun getBaseUrlException() {
fun getBaseUrlException() = runTest {
every { getBaseUrlUseCase(any()) } returns UseCaseResult.Error(commonException)
authenticationViewModel.getBaseUrl(OC_BASIC_USERNAME)

authenticationViewModel.getBaseUrl(OC_BASIC_USERNAME)
advanceUntilIdle()
assertEmittedValues(
expectedValues = listOf<Event<UIResult<String>>>(Event(UIResult.Error(commonException))),
liveData = authenticationViewModel.baseUrl
Expand Down
Loading
Loading