version updates
This commit is contained in:
parent
12e6f01d29
commit
b256cb9bf2
28 changed files with 302 additions and 234 deletions
|
|
@ -6,13 +6,12 @@ plugins {
|
|||
apply from: 'signing.config.gradle'
|
||||
|
||||
android {
|
||||
compileSdkVersion 30
|
||||
buildToolsVersion "30.0.2"
|
||||
compileSdk 31
|
||||
|
||||
defaultConfig {
|
||||
applicationId "org.fnives.tiktokdownloader"
|
||||
minSdkVersion 23
|
||||
targetSdkVersion 30
|
||||
minSdk 23
|
||||
targetSdk 31
|
||||
versionCode 1
|
||||
versionName "1.0.0"
|
||||
|
||||
|
|
@ -51,41 +50,65 @@ android {
|
|||
lintOptions {
|
||||
abortOnError true
|
||||
}
|
||||
|
||||
testOptions.unitTests {
|
||||
includeAndroidResources = true
|
||||
all {
|
||||
useJUnitPlatform()
|
||||
testLogging {
|
||||
events 'started', 'passed', 'skipped', 'failed'
|
||||
exceptionFormat "full"
|
||||
showStandardStreams true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.configureEach { task ->
|
||||
if (task.taskIdentity.type.toString() == "class org.jetbrains.kotlin.gradle.tasks.KotlinCompile") {
|
||||
task.kotlinOptions {
|
||||
freeCompilerArgs += "-opt-in=kotlin.RequiresOptIn"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
implementation "androidx.core:core-ktx:1.3.2"
|
||||
implementation "androidx.appcompat:appcompat:1.2.0"
|
||||
implementation "androidx.activity:activity-ktx:1.2.0-beta01"
|
||||
implementation "androidx.fragment:fragment-ktx:1.3.0-beta01"
|
||||
implementation "com.google.android.material:material:1.2.1"
|
||||
implementation "androidx.constraintlayout:constraintlayout:2.0.4"
|
||||
implementation "androidx.core:core-ktx:1.7.0"
|
||||
implementation "androidx.appcompat:appcompat:1.4.1"
|
||||
implementation "androidx.activity:activity-ktx:1.4.0"
|
||||
implementation "androidx.fragment:fragment-ktx:1.4.1"
|
||||
implementation "com.google.android.material:material:1.5.0"
|
||||
implementation "androidx.constraintlayout:constraintlayout:2.1.3"
|
||||
|
||||
// Coroutines
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.0-M1"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.9"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9"
|
||||
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0"
|
||||
implementation "androidx.fragment:fragment-ktx:1.2.5"
|
||||
def coroutine_version = "1.6.0"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutine_version"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutine_version"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutine_version"
|
||||
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.1"
|
||||
implementation "androidx.fragment:fragment-ktx:1.4.1"
|
||||
|
||||
implementation "com.github.bumptech.glide:glide:4.11.0"
|
||||
kapt "com.github.bumptech.glide:compiler:4.11.0"
|
||||
def glide_version = "4.11.0"
|
||||
implementation "com.github.bumptech.glide:glide:$glide_version"
|
||||
kapt "com.github.bumptech.glide:compiler:$glide_version"
|
||||
|
||||
def okhttp_version = "4.9.3"
|
||||
implementation "com.squareup.retrofit2:retrofit:2.9.0"
|
||||
implementation "com.squareup.okhttp3:logging-interceptor:4.7.2"
|
||||
implementation 'com.pierfrancescosoffritti.androidyoutubeplayer:core:10.0.5'
|
||||
implementation "com.squareup.okhttp3:logging-interceptor:$okhttp_version"
|
||||
implementation 'com.pierfrancescosoffritti.androidyoutubeplayer:core:11.0.1'
|
||||
|
||||
testImplementation "org.junit.jupiter:junit-jupiter-engine:5.7.0"
|
||||
testImplementation "org.junit.jupiter:junit-jupiter-params:5.7.0"
|
||||
testImplementation 'com.jraska.livedata:testing-ktx:1.1.2'
|
||||
testImplementation "com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0"
|
||||
testImplementation "com.squareup.okhttp3:mockwebserver:4.2.1"
|
||||
def junit_version = "5.7.0"
|
||||
testImplementation "org.junit.jupiter:junit-jupiter-engine:$junit_version"
|
||||
testImplementation "org.junit.jupiter:junit-jupiter-params:$junit_version"
|
||||
testImplementation 'com.jraska.livedata:testing-ktx:1.2.0'
|
||||
testImplementation "org.mockito.kotlin:mockito-kotlin:4.0.0"
|
||||
testImplementation "com.squareup.okhttp3:mockwebserver:$okhttp_version"
|
||||
testImplementation "commons-io:commons-io:2.8.0"
|
||||
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.4.0-M1"
|
||||
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutine_version"
|
||||
testImplementation "androidx.arch.core:core-testing:2.1.0"
|
||||
|
||||
androidTestImplementation "androidx.test.ext:junit:1.1.2"
|
||||
androidTestImplementation "androidx.test.espresso:espresso-core:3.3.0"
|
||||
androidTestImplementation "androidx.test.ext:junit:1.1.3"
|
||||
androidTestImplementation "androidx.test.espresso:espresso-core:3.4.0"
|
||||
}
|
||||
|
|
@ -13,19 +13,23 @@
|
|||
<application
|
||||
android:name=".App"
|
||||
android:allowBackup="true"
|
||||
android:fullBackupContent="false"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:fullBackupContent="false"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.TikTokDownloader">
|
||||
<activity android:name=".ui.main.MainActivity">
|
||||
<activity
|
||||
android:name=".ui.main.MainActivity"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name=".ui.service.DownloadIntentReceiverActivity"
|
||||
<activity
|
||||
android:name=".ui.service.DownloadIntentReceiverActivity"
|
||||
android:exported="true"
|
||||
android:theme="@style/NoDisplayTheme">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEND" />
|
||||
|
|
@ -35,6 +39,7 @@
|
|||
<data android:mimeType="message/*" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<service android:name=".ui.service.QueueService" />
|
||||
</application>
|
||||
|
||||
|
|
|
|||
|
|
@ -39,10 +39,10 @@ class SharedPreferencesManagerImpl private constructor(private val sharedPrefere
|
|||
override fun getValue(thisRef: SharedPreferencesManagerImpl, property: KProperty<*>): Flow<Set<String>> =
|
||||
callbackFlow {
|
||||
val listener = SharedPreferences.OnSharedPreferenceChangeListener { _, _ ->
|
||||
offer(thisRef.getValues())
|
||||
trySend(thisRef.getValues())
|
||||
}
|
||||
thisRef.sharedPreferences.registerOnSharedPreferenceChangeListener(listener)
|
||||
offer(thisRef.getValues())
|
||||
trySend(thisRef.getValues())
|
||||
|
||||
awaitClose {
|
||||
thisRef.sharedPreferences.unregisterOnSharedPreferenceChangeListener(listener)
|
||||
|
|
|
|||
|
|
@ -5,6 +5,6 @@ import org.fnives.tiktokdownloader.data.network.parsing.response.VideoResponse
|
|||
|
||||
class VideoResponseConverter : ParsingExceptionThrowingConverter<VideoResponse>() {
|
||||
|
||||
override fun convertSafely(value: ResponseBody): VideoResponse? =
|
||||
VideoResponse(value.contentType(), value.byteStream())
|
||||
override fun convertSafely(responseBody: ResponseBody): VideoResponse? =
|
||||
VideoResponse(responseBody.contentType(), responseBody.byteStream())
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
package org.fnives.tiktokdownloader.data.usecase
|
||||
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.FlowPreview
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.debounce
|
||||
|
|
@ -16,6 +16,7 @@ import org.fnives.tiktokdownloader.data.model.VideoInPending
|
|||
import org.fnives.tiktokdownloader.data.model.VideoInProgress
|
||||
import org.fnives.tiktokdownloader.data.model.VideoState
|
||||
|
||||
@OptIn(FlowPreview::class)
|
||||
class StateOfVideosObservableUseCase(
|
||||
videoInProgressLocalSource: VideoInProgressLocalSource,
|
||||
videoInPendingLocalSource: VideoInPendingLocalSource,
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package org.fnives.tiktokdownloader.data.usecase
|
|||
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.FlowPreview
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
|
|
@ -30,6 +31,7 @@ import org.fnives.tiktokdownloader.data.network.exceptions.CaptchaRequiredExcept
|
|||
import org.fnives.tiktokdownloader.data.network.exceptions.NetworkException
|
||||
import org.fnives.tiktokdownloader.data.network.exceptions.ParsingException
|
||||
|
||||
@OptIn(FlowPreview::class)
|
||||
class VideoDownloadingProcessorUseCase(
|
||||
private val tikTokDownloadRemoteSource: TikTokDownloadRemoteSource,
|
||||
private val videoInProgressLocalSource: VideoInProgressLocalSource,
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ class ViewModelFactory(
|
|||
private val viewModelModule: ViewModelModule,
|
||||
) : AbstractSavedStateViewModelFactory(savedStateRegistryOwner, defaultArgs) {
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : ViewModel?> create(key: String, modelClass: Class<T>, handle: SavedStateHandle): T {
|
||||
val viewModel = when (modelClass) {
|
||||
MainViewModel::class.java -> viewModelModule.mainViewModel(handle)
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import android.os.Bundle
|
|||
import android.view.MenuItem
|
||||
import android.view.animation.AccelerateDecelerateInterpolator
|
||||
import android.view.animation.OvershootInterpolator
|
||||
import androidx.activity.viewModels
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
|
|
@ -43,28 +42,28 @@ class MainActivity : AppCompatActivity() {
|
|||
animateFabClicked(downloadFab)
|
||||
viewModel.onFetchDownloadClicked()
|
||||
}
|
||||
viewModel.refreshActionVisibility.observe(this, {
|
||||
viewModel.refreshActionVisibility.observe(this) {
|
||||
animateFabVisibility(downloadFab, it == true)
|
||||
})
|
||||
viewModel.errorMessage.observe(this, {
|
||||
}
|
||||
viewModel.errorMessage.observe(this) {
|
||||
val stringRes = it?.item?.stringRes ?: return@observe
|
||||
Snackbar.make(snackBarAnchor, stringRes, Snackbar.LENGTH_SHORT).show()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupBottomNavigationView(bottomNavigationView: BottomNavigationView, savedInstanceState: Bundle?) {
|
||||
bottomNavigationView.setOnNavigationItemSelectedListener(BottomNavigationView.OnNavigationItemSelectedListener { item ->
|
||||
bottomNavigationView.setOnItemSelectedListener { item ->
|
||||
val fragment = when (item.itemId) {
|
||||
R.id.help_menu_item -> HelpFragment.newInstance()
|
||||
R.id.queue_menu_item -> QueueFragment.newInstance()
|
||||
else -> return@OnNavigationItemSelectedListener false
|
||||
else -> return@setOnItemSelectedListener false
|
||||
}
|
||||
item.toScreen()?.let(viewModel::onScreenSelected)
|
||||
supportFragmentManager.beginTransaction()
|
||||
.replace(R.id.fragment_holder, fragment)
|
||||
.commit()
|
||||
return@OnNavigationItemSelectedListener true
|
||||
})
|
||||
return@setOnItemSelectedListener true
|
||||
}
|
||||
if (savedInstanceState == null) {
|
||||
bottomNavigationView.selectedItemId = R.id.queue_menu_item
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ class QueueService : Service() {
|
|||
.setSmallIcon(R.drawable.ic_download)
|
||||
.setContentIntent(buildMainPendingIntent(this))
|
||||
.setAutoCancel(true)
|
||||
.setNotificationSilent()
|
||||
.setSilent(true)
|
||||
.build()
|
||||
NotificationState.Finish -> {
|
||||
stopSelf()
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/default_padding"
|
||||
app:autoPlay="false"
|
||||
app:showFullScreenButton="false"
|
||||
app:enableAutomaticInitialization="true"
|
||||
app:handleNetworkEvents="true"
|
||||
app:videoId="NXv3JpmwA8Y" />
|
||||
|
|
@ -82,7 +81,6 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/default_padding"
|
||||
app:autoPlay="false"
|
||||
app:showFullScreenButton="false"
|
||||
app:enableAutomaticInitialization="true"
|
||||
app:handleNetworkEvents="true"
|
||||
app:videoId="jxaxffE8c4c" />
|
||||
|
|
|
|||
|
|
@ -1,20 +1,22 @@
|
|||
package org.fnives.tiktokdownloader.data.local
|
||||
|
||||
import com.nhaarman.mockitokotlin2.spy
|
||||
import org.fnives.tiktokdownloader.data.local.persistent.SharedPreferencesManager
|
||||
import org.fnives.tiktokdownloader.helper.mock.InMemorySharedPreferencesManager
|
||||
import org.junit.jupiter.api.Assertions
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.Timeout
|
||||
import org.mockito.kotlin.spy
|
||||
|
||||
@Suppress("TestFunctionName")
|
||||
@Timeout(value = 2)
|
||||
class CaptchaTimeoutLocalSourceTest {
|
||||
|
||||
private lateinit var mockSharedPreferencesManager: SharedPreferencesManager
|
||||
private lateinit var sut: CaptchaTimeoutLocalSource
|
||||
|
||||
@BeforeEach
|
||||
fun setup(){
|
||||
fun setup() {
|
||||
mockSharedPreferencesManager = spy(InMemorySharedPreferencesManager())
|
||||
sut = CaptchaTimeoutLocalSource(mockSharedPreferencesManager, 60)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,9 @@
|
|||
package org.fnives.tiktokdownloader.data.local
|
||||
|
||||
import com.nhaarman.mockitokotlin2.anyOrNull
|
||||
import com.nhaarman.mockitokotlin2.doReturn
|
||||
import com.nhaarman.mockitokotlin2.mock
|
||||
import com.nhaarman.mockitokotlin2.verifyZeroInteractions
|
||||
import com.nhaarman.mockitokotlin2.whenever
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.coroutines.TimeoutCancellationException
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.take
|
||||
import kotlinx.coroutines.flow.toList
|
||||
|
|
@ -26,9 +20,16 @@ import org.fnives.tiktokdownloader.helper.mock.InMemorySharedPreferencesManager
|
|||
import org.junit.jupiter.api.Assertions
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.Timeout
|
||||
import org.mockito.kotlin.anyOrNull
|
||||
import org.mockito.kotlin.doReturn
|
||||
import org.mockito.kotlin.mock
|
||||
import org.mockito.kotlin.verifyNoInteractions
|
||||
import org.mockito.kotlin.whenever
|
||||
import java.io.InputStream
|
||||
|
||||
@Suppress("TestFunctionName")
|
||||
|
||||
@Timeout(value = 2)
|
||||
class VideoDownloadedLocalSourceTest {
|
||||
|
||||
private lateinit var sut: VideoDownloadedLocalSource
|
||||
|
|
@ -52,8 +53,8 @@ class VideoDownloadedLocalSourceTest {
|
|||
@Test
|
||||
fun GIVEN_observing_saved_videos_WHEN_initialized_THEN_emptylist_is_emitted() = runBlocking<Unit> {
|
||||
Assertions.assertEquals(emptyList<VideoDownloaded>(), sut.savedVideos.first())
|
||||
verifyZeroInteractions(mockSaveVideoFile)
|
||||
verifyZeroInteractions(mockVerifyFileForUriExists)
|
||||
verifyNoInteractions(mockSaveVideoFile)
|
||||
verifyNoInteractions(mockVerifyFileForUriExists)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -15,8 +15,10 @@ import org.fnives.tiktokdownloader.data.model.VideoInPending
|
|||
import org.junit.jupiter.api.Assertions
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.Timeout
|
||||
|
||||
@Suppress("TestFunctionName")
|
||||
|
||||
@Timeout(value = 2)
|
||||
class VideoInPendingLocalSourceTest {
|
||||
|
||||
private lateinit var sut: VideoInPendingLocalSource
|
||||
|
|
|
|||
|
|
@ -13,8 +13,10 @@ import org.fnives.tiktokdownloader.data.model.VideoInProgress
|
|||
import org.junit.jupiter.api.Assertions
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.Timeout
|
||||
|
||||
@Suppress("TestFunctionName")
|
||||
|
||||
@Timeout(value = 2)
|
||||
class VideoInProgressLocalSourceTest {
|
||||
|
||||
private lateinit var sut: VideoInProgressLocalSource
|
||||
|
|
|
|||
|
|
@ -14,12 +14,14 @@ import org.junit.jupiter.api.AfterEach
|
|||
import org.junit.jupiter.api.Assertions
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.Timeout
|
||||
import org.junit.jupiter.params.ParameterizedTest
|
||||
import org.junit.jupiter.params.provider.Arguments
|
||||
import org.junit.jupiter.params.provider.MethodSource
|
||||
import java.util.stream.Stream
|
||||
|
||||
@Suppress("TestFunctionName")
|
||||
|
||||
@Timeout(value = 2)
|
||||
class TikTokDownloadRemoteSourceTest {
|
||||
|
||||
private lateinit var mockWebServer: MockWebServer
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import org.junit.jupiter.api.Assertions
|
|||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Disabled
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.Timeout
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
|
|
@ -16,7 +17,8 @@ import java.io.File
|
|||
* Since the website may change anytime without any notice, this test verifies with actual request going out.
|
||||
* However this makes the test shaky, because if the device has no proper connection it may fail.
|
||||
*/
|
||||
@Suppress("TestFunctionName")
|
||||
|
||||
@Timeout(value = 2)
|
||||
class TikTokDownloadRemoteSourceUpToDateTest {
|
||||
|
||||
private lateinit var sut: TikTokDownloadRemoteSource
|
||||
|
|
|
|||
|
|
@ -1,20 +1,22 @@
|
|||
package org.fnives.tiktokdownloader.data.usecase
|
||||
|
||||
import com.nhaarman.mockitokotlin2.anyOrNull
|
||||
import com.nhaarman.mockitokotlin2.doReturn
|
||||
import com.nhaarman.mockitokotlin2.mock
|
||||
import com.nhaarman.mockitokotlin2.times
|
||||
import com.nhaarman.mockitokotlin2.verify
|
||||
import com.nhaarman.mockitokotlin2.verifyNoMoreInteractions
|
||||
import com.nhaarman.mockitokotlin2.verifyZeroInteractions
|
||||
import com.nhaarman.mockitokotlin2.whenever
|
||||
import org.fnives.tiktokdownloader.data.local.VideoInPendingLocalSource
|
||||
import org.fnives.tiktokdownloader.data.model.VideoInPending
|
||||
import org.junit.jupiter.api.Assertions
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.Timeout
|
||||
import org.mockito.kotlin.anyOrNull
|
||||
import org.mockito.kotlin.doReturn
|
||||
import org.mockito.kotlin.mock
|
||||
import org.mockito.kotlin.times
|
||||
import org.mockito.kotlin.verify
|
||||
import org.mockito.kotlin.verifyNoInteractions
|
||||
import org.mockito.kotlin.verifyNoMoreInteractions
|
||||
import org.mockito.kotlin.whenever
|
||||
|
||||
@Suppress("TestFunctionName")
|
||||
@Timeout(value = 2)
|
||||
class AddVideoToQueueUseCaseTest {
|
||||
|
||||
private lateinit var sut: AddVideoToQueueUseCase
|
||||
|
|
@ -30,8 +32,8 @@ class AddVideoToQueueUseCaseTest {
|
|||
|
||||
@Test
|
||||
fun GIVEN_no_action_THEN_the_local_source_and_verifier_is_not_touched() {
|
||||
verifyZeroInteractions(mockUrlVerificationUseCase)
|
||||
verifyZeroInteractions(mockVideoInPendingLocalSource)
|
||||
verifyNoInteractions(mockUrlVerificationUseCase)
|
||||
verifyNoInteractions(mockVideoInPendingLocalSource)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -83,6 +85,6 @@ class AddVideoToQueueUseCaseTest {
|
|||
Assertions.assertFalse(actual, "Url is Saved while it should NOT be")
|
||||
verify(mockUrlVerificationUseCase, times(1)).invoke(expectedUrl)
|
||||
verifyNoMoreInteractions(mockUrlVerificationUseCase)
|
||||
verifyZeroInteractions(mockVideoInPendingLocalSource)
|
||||
verifyNoInteractions(mockVideoInPendingLocalSource)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,19 +1,15 @@
|
|||
package org.fnives.tiktokdownloader.data.usecase
|
||||
|
||||
import com.nhaarman.mockitokotlin2.doReturn
|
||||
import com.nhaarman.mockitokotlin2.mock
|
||||
import com.nhaarman.mockitokotlin2.times
|
||||
import com.nhaarman.mockitokotlin2.verify
|
||||
import com.nhaarman.mockitokotlin2.verifyNoMoreInteractions
|
||||
import com.nhaarman.mockitokotlin2.verifyZeroInteractions
|
||||
import com.nhaarman.mockitokotlin2.whenever
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.take
|
||||
import kotlinx.coroutines.flow.toList
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.test.TestCoroutineDispatcher
|
||||
import kotlinx.coroutines.test.StandardTestDispatcher
|
||||
import kotlinx.coroutines.test.TestDispatcher
|
||||
|
||||
import org.fnives.tiktokdownloader.data.local.VideoDownloadedLocalSource
|
||||
import org.fnives.tiktokdownloader.data.local.VideoInPendingLocalSource
|
||||
import org.fnives.tiktokdownloader.data.local.VideoInProgressLocalSource
|
||||
|
|
@ -21,14 +17,26 @@ import org.fnives.tiktokdownloader.data.model.VideoDownloaded
|
|||
import org.fnives.tiktokdownloader.data.model.VideoInPending
|
||||
import org.fnives.tiktokdownloader.data.model.VideoInProgress
|
||||
import org.fnives.tiktokdownloader.data.model.VideoState
|
||||
import org.fnives.tiktokdownloader.helper.advanceTimeBy
|
||||
import org.fnives.tiktokdownloader.helper.advanceUntilIdle
|
||||
import org.junit.jupiter.api.Assertions
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.Timeout
|
||||
import org.mockito.kotlin.doReturn
|
||||
import org.mockito.kotlin.mock
|
||||
import org.mockito.kotlin.times
|
||||
import org.mockito.kotlin.verify
|
||||
import org.mockito.kotlin.verifyNoInteractions
|
||||
import org.mockito.kotlin.verifyNoMoreInteractions
|
||||
import org.mockito.kotlin.whenever
|
||||
|
||||
@Suppress("TestFunctionName")
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
@Timeout(value = 2)
|
||||
class StateOfVideosObservableUseCaseTest {
|
||||
|
||||
private lateinit var testDispatcher: TestCoroutineDispatcher
|
||||
private lateinit var testDispatcher: TestDispatcher
|
||||
private lateinit var mockVideoInProgressLocalSource: VideoInProgressLocalSource
|
||||
private lateinit var mockVideoInPendingLocalSource: VideoInPendingLocalSource
|
||||
private lateinit var mockVideoDownloadedLocalSource: VideoDownloadedLocalSource
|
||||
|
|
@ -48,7 +56,7 @@ class StateOfVideosObservableUseCaseTest {
|
|||
whenever(mockVideoInProgressLocalSource.videoInProcessFlow).doReturn(videoInProgressMutableFlow)
|
||||
whenever(mockVideoInPendingLocalSource.pendingVideos).doReturn(videoInPendingMutableFlow)
|
||||
whenever(mockVideoDownloadedLocalSource.savedVideos).doReturn(videoDownloadedMutableFlow)
|
||||
testDispatcher = TestCoroutineDispatcher()
|
||||
testDispatcher = StandardTestDispatcher()
|
||||
sut = StateOfVideosObservableUseCase(
|
||||
videoInProgressLocalSource = mockVideoInProgressLocalSource,
|
||||
videoInPendingLocalSource = mockVideoInPendingLocalSource,
|
||||
|
|
@ -59,13 +67,13 @@ class StateOfVideosObservableUseCaseTest {
|
|||
|
||||
@Test
|
||||
fun WHEN_no_invoke_is_called_THEN_no_dependency_is_called() {
|
||||
verifyZeroInteractions(mockVideoDownloadedLocalSource)
|
||||
verifyZeroInteractions(mockVideoInPendingLocalSource)
|
||||
verifyZeroInteractions(mockVideoInProgressLocalSource)
|
||||
verifyNoInteractions(mockVideoDownloadedLocalSource)
|
||||
verifyNoInteractions(mockVideoInPendingLocalSource)
|
||||
verifyNoInteractions(mockVideoInProgressLocalSource)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun GIVEN_no_inProgress_AND_empty_pending_AND_empty_saved_THEN_emptyList_is_emitted() = runBlocking(testDispatcher) {
|
||||
fun GIVEN_no_inProgress_AND_empty_pending_AND_empty_saved_THEN_emptyList_is_emitted() = runBlocking {
|
||||
videoInProgressMutableFlow.value = null
|
||||
videoInPendingMutableFlow.value = emptyList()
|
||||
videoDownloadedMutableFlow.value = emptyList()
|
||||
|
|
@ -83,7 +91,7 @@ class StateOfVideosObservableUseCaseTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun GIVEN_inProgress_AND_empty_pending_AND_empty_saved_THEN_inProgress_is_emitted() = runBlocking(testDispatcher) {
|
||||
fun GIVEN_inProgress_AND_empty_pending_AND_empty_saved_THEN_inProgress_is_emitted() = runBlocking {
|
||||
val videoInProgress = VideoInProgress("alma", "url")
|
||||
val expected = listOf<VideoState>(VideoState.InProcess(videoInProgress))
|
||||
val expectedList = listOf(emptyList(), expected)
|
||||
|
|
@ -109,7 +117,7 @@ class StateOfVideosObservableUseCaseTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun GIVEN_inProgress_AND_pendingWithSameId_AND_empty_saved_THEN_inProgress_is_emitted() = runBlocking(testDispatcher) {
|
||||
fun GIVEN_inProgress_AND_pendingWithSameId_AND_empty_saved_THEN_inProgress_is_emitted() = runBlocking {
|
||||
val videoInProgress = VideoInProgress("alma", "url")
|
||||
val videoInPending = VideoInPending(id = videoInProgress.id, url = videoInProgress.url)
|
||||
val expected = listOf<VideoState>(VideoState.InProcess(videoInProgress))
|
||||
|
|
@ -130,7 +138,7 @@ class StateOfVideosObservableUseCaseTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun GIVEN_in_pending_AND_nothing_inprogress_AND_empty_saved_THEN_inPending_is_emitted() = runBlocking(testDispatcher) {
|
||||
fun GIVEN_in_pending_AND_nothing_inprogress_AND_empty_saved_THEN_inPending_is_emitted() = runBlocking {
|
||||
val videoInPending = VideoInPending(id = "alma", url = "url")
|
||||
val expected = listOf<VideoState>(VideoState.InPending(videoInPending))
|
||||
val expectedList = listOf(emptyList(), expected)
|
||||
|
|
@ -151,7 +159,7 @@ class StateOfVideosObservableUseCaseTest {
|
|||
|
||||
@Test
|
||||
fun GIVEN_inProgress_AND_pendingWithSameId_AND_savedWithSameId_THEN_inProgress_And_saved_is_emitted() =
|
||||
runBlocking(testDispatcher) {
|
||||
runBlocking {
|
||||
val videoInProgress = VideoInProgress("alma", "url")
|
||||
val videoInPending = VideoInPending(id = videoInProgress.id, url = videoInProgress.url)
|
||||
val videoDownloaded = VideoDownloaded(id = videoInProgress.id, url = videoInProgress.url, uri = "uri")
|
||||
|
|
@ -173,7 +181,7 @@ class StateOfVideosObservableUseCaseTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun GIVEN_new_item_faster_than_debounce_THEN_only_the_last_items_are_emitted() = runBlocking(testDispatcher) {
|
||||
fun GIVEN_new_item_faster_than_debounce_THEN_only_the_last_items_are_emitted() = runBlocking {
|
||||
val videoInProgress = VideoInProgress("alma", "url")
|
||||
val expected = listOf(VideoState.InProcess(videoInProgress))
|
||||
val expectedList = listOf(expected)
|
||||
|
|
@ -194,7 +202,7 @@ class StateOfVideosObservableUseCaseTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun GIVEN_new_item_slower_than_debounce_THEN_both_list_is_emitted() = runBlocking(testDispatcher) {
|
||||
fun GIVEN_new_item_slower_than_debounce_THEN_both_list_is_emitted() = runBlocking {
|
||||
val videoInProgress = VideoInProgress("alma", "url")
|
||||
val expected = listOf(VideoState.InProcess(videoInProgress))
|
||||
val expectedList = listOf(emptyList(), expected)
|
||||
|
|
@ -215,7 +223,7 @@ class StateOfVideosObservableUseCaseTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun GIVEN_processing_LATER_pendingWithSameId_THEN_no_new_emition_happens() = runBlocking(testDispatcher) {
|
||||
fun GIVEN_processing_LATER_pendingWithSameId_THEN_no_new_emition_happens() = runBlocking {
|
||||
val videoInProgress = VideoInProgress("alma", "url")
|
||||
val videoInPendingSameAsProgress = VideoInPending(id = videoInProgress.id, url = videoInProgress.url)
|
||||
val videoInPendingOther = VideoInPending(id = "alma2", url = "url2")
|
||||
|
|
|
|||
|
|
@ -3,8 +3,10 @@ package org.fnives.tiktokdownloader.data.usecase
|
|||
import org.junit.jupiter.api.Assertions
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.Timeout
|
||||
|
||||
@Suppress("TestFunctionName")
|
||||
|
||||
@Timeout(value = 2)
|
||||
class UrlVerificationUseCaseTest {
|
||||
|
||||
private lateinit var sut: UrlVerificationUseCase
|
||||
|
|
|
|||
|
|
@ -1,21 +1,15 @@
|
|||
package org.fnives.tiktokdownloader.data.usecase
|
||||
|
||||
import com.nhaarman.mockitokotlin2.anyOrNull
|
||||
import com.nhaarman.mockitokotlin2.doReturn
|
||||
import com.nhaarman.mockitokotlin2.mock
|
||||
import com.nhaarman.mockitokotlin2.times
|
||||
import com.nhaarman.mockitokotlin2.verify
|
||||
import com.nhaarman.mockitokotlin2.verifyNoMoreInteractions
|
||||
import com.nhaarman.mockitokotlin2.verifyZeroInteractions
|
||||
import com.nhaarman.mockitokotlin2.whenever
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.cancelAndJoin
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.take
|
||||
import kotlinx.coroutines.flow.toList
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.test.TestCoroutineDispatcher
|
||||
import kotlinx.coroutines.test.runBlockingTest
|
||||
import kotlinx.coroutines.test.StandardTestDispatcher
|
||||
import kotlinx.coroutines.test.TestDispatcher
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.fnives.tiktokdownloader.data.local.CaptchaTimeoutLocalSource
|
||||
import org.fnives.tiktokdownloader.data.local.VideoDownloadedLocalSource
|
||||
import org.fnives.tiktokdownloader.data.local.VideoInPendingLocalSource
|
||||
|
|
@ -30,15 +24,27 @@ import org.fnives.tiktokdownloader.data.network.TikTokDownloadRemoteSource
|
|||
import org.fnives.tiktokdownloader.data.network.exceptions.CaptchaRequiredException
|
||||
import org.fnives.tiktokdownloader.data.network.exceptions.NetworkException
|
||||
import org.fnives.tiktokdownloader.data.network.exceptions.ParsingException
|
||||
import org.fnives.tiktokdownloader.helper.advanceTimeBy
|
||||
import org.fnives.tiktokdownloader.helper.advanceUntilIdle
|
||||
import org.junit.jupiter.api.Assertions
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.mockito.kotlin.anyOrNull
|
||||
import org.mockito.kotlin.doReturn
|
||||
import org.mockito.kotlin.mock
|
||||
import org.mockito.kotlin.times
|
||||
import org.mockito.kotlin.verify
|
||||
import org.mockito.kotlin.verifyNoInteractions
|
||||
import org.mockito.kotlin.verifyNoMoreInteractions
|
||||
import org.mockito.kotlin.whenever
|
||||
import java.io.InputStream
|
||||
|
||||
@Suppress("TestFunctionName")
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
//@Timeout(value = 2)
|
||||
class VideoDownloadingProcessorUseCaseTest {
|
||||
|
||||
private lateinit var testDispatcher: TestCoroutineDispatcher
|
||||
private lateinit var testDispatcher: TestDispatcher
|
||||
private lateinit var mockVideoInProgressLocalSource: VideoInProgressLocalSource
|
||||
private lateinit var mockVideoInPendingLocalSource: VideoInPendingLocalSource
|
||||
private lateinit var mockVideoDownloadedLocalSource: VideoDownloadedLocalSource
|
||||
|
|
@ -62,7 +68,7 @@ class VideoDownloadingProcessorUseCaseTest {
|
|||
whenever(mockVideoInProgressLocalSource.videoInProcessFlow).doReturn(videoInProgressMutableFlow)
|
||||
whenever(mockVideoInPendingLocalSource.pendingVideos).doReturn(videoInPendingMutableFlow)
|
||||
whenever(mockVideoDownloadedLocalSource.savedVideos).doReturn(videoDownloadedMutableFlow)
|
||||
testDispatcher = TestCoroutineDispatcher()
|
||||
testDispatcher = StandardTestDispatcher()
|
||||
sut = VideoDownloadingProcessorUseCase(
|
||||
videoInProgressLocalSource = mockVideoInProgressLocalSource,
|
||||
videoInPendingLocalSource = mockVideoInPendingLocalSource,
|
||||
|
|
@ -75,24 +81,24 @@ class VideoDownloadingProcessorUseCaseTest {
|
|||
|
||||
@Test
|
||||
fun WHEN_no_method_invoked_THEN_no_interaction_with_dependencies() {
|
||||
verifyZeroInteractions(mockVideoInProgressLocalSource)
|
||||
verifyZeroInteractions(mockVideoInPendingLocalSource)
|
||||
verifyZeroInteractions(mockVideoDownloadedLocalSource)
|
||||
verifyZeroInteractions(mockTikTokDownloadRemoteSource)
|
||||
verifyNoInteractions(mockVideoInProgressLocalSource)
|
||||
verifyNoInteractions(mockVideoInPendingLocalSource)
|
||||
verifyNoInteractions(mockVideoDownloadedLocalSource)
|
||||
verifyNoInteractions(mockTikTokDownloadRemoteSource)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun GIVEN_not_observing_WHEN_fetching_THEN_nothing_happens() {
|
||||
sut.fetchVideoInState()
|
||||
|
||||
verifyZeroInteractions(mockVideoInProgressLocalSource)
|
||||
verifyZeroInteractions(mockVideoInPendingLocalSource)
|
||||
verifyZeroInteractions(mockVideoDownloadedLocalSource)
|
||||
verifyZeroInteractions(mockTikTokDownloadRemoteSource)
|
||||
verifyNoInteractions(mockVideoInProgressLocalSource)
|
||||
verifyNoInteractions(mockVideoInPendingLocalSource)
|
||||
verifyNoInteractions(mockVideoDownloadedLocalSource)
|
||||
verifyNoInteractions(mockTikTokDownloadRemoteSource)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun GIVEN_empty_pendingVideos_WHEN_observing_THEN_error_is_emited() = runBlocking(testDispatcher) {
|
||||
fun GIVEN_empty_pendingVideos_WHEN_observing_THEN_error_is_emited() = runBlocking {
|
||||
videoInPendingMutableFlow.value = emptyList()
|
||||
val expected = ProcessState.Finished
|
||||
val expectedList = listOf(expected)
|
||||
|
|
@ -103,13 +109,12 @@ class VideoDownloadingProcessorUseCaseTest {
|
|||
Assertions.assertEquals(expectedList, resultList.await())
|
||||
verify(mockVideoInPendingLocalSource, times(1)).pendingVideos
|
||||
verifyNoMoreInteractions(mockVideoInPendingLocalSource)
|
||||
verifyZeroInteractions(mockVideoInPendingLocalSource)
|
||||
verifyZeroInteractions(mockVideoDownloadedLocalSource)
|
||||
verifyZeroInteractions(mockTikTokDownloadRemoteSource)
|
||||
verifyNoInteractions(mockVideoDownloadedLocalSource)
|
||||
verifyNoInteractions(mockTikTokDownloadRemoteSource)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun GIVEN_one_pending_video_AND_network_error_WHEN_observing_THEN_error_is_emited() = runBlocking(testDispatcher) {
|
||||
fun GIVEN_one_pending_video_AND_network_error_WHEN_observing_THEN_error_is_emited() = runBlocking {
|
||||
val videoInPending = VideoInPending("alma", "banan")
|
||||
videoInPendingMutableFlow.value = listOf(videoInPending)
|
||||
whenever(mockTikTokDownloadRemoteSource.getVideo(videoInPending)).then { throw NetworkException() }
|
||||
|
|
@ -126,11 +131,10 @@ class VideoDownloadingProcessorUseCaseTest {
|
|||
verify(mockVideoDownloadedLocalSource, times(1)).savedVideos
|
||||
verifyNoMoreInteractions(mockTikTokDownloadRemoteSource)
|
||||
verifyNoMoreInteractions(mockVideoDownloadedLocalSource)
|
||||
verifyZeroInteractions(mockVideoInPendingLocalSource)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun GIVEN_one_pending_video_AND_parsing_error_WHEN_observing_THEN_parsingError_is_emited() = runBlocking(testDispatcher) {
|
||||
fun GIVEN_one_pending_video_AND_parsing_error_WHEN_observing_THEN_parsingError_is_emited() = runBlocking {
|
||||
val videoInPending = VideoInPending("alma", "banan")
|
||||
videoInPendingMutableFlow.value = listOf(videoInPending)
|
||||
whenever(mockTikTokDownloadRemoteSource.getVideo(videoInPending)).then { throw ParsingException() }
|
||||
|
|
@ -144,7 +148,7 @@ class VideoDownloadingProcessorUseCaseTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun GIVEN_one_pending_video_AND_unexpected_error_WHEN_observing_THEN_unknown_error_is_emitted() = runBlockingTest(testDispatcher) {
|
||||
fun GIVEN_one_pending_video_AND_unexpected_error_WHEN_observing_THEN_unknown_error_is_emitted() = runTest(testDispatcher) {
|
||||
val videoInPending = VideoInPending("alma", "banan")
|
||||
videoInPendingMutableFlow.value = listOf(videoInPending)
|
||||
whenever(mockTikTokDownloadRemoteSource.getVideo(videoInPending)).then { throw Throwable() }
|
||||
|
|
@ -158,7 +162,7 @@ class VideoDownloadingProcessorUseCaseTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun GIVEN_one_pending_video_AND_network_errors_WHILE_observing_WHEN_fetching_THEN_it_retries() = runBlocking<Unit>(testDispatcher) {
|
||||
fun GIVEN_one_pending_video_AND_network_errors_WHILE_observing_WHEN_fetching_THEN_it_retries() = runBlocking<Unit> {
|
||||
val videoInPending = VideoInPending("alma", "banan")
|
||||
videoInPendingMutableFlow.value = listOf(videoInPending)
|
||||
var specificException = true
|
||||
|
|
@ -177,7 +181,7 @@ class VideoDownloadingProcessorUseCaseTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun GIVEN_one_pending_video_AND_parsing_errors_WHILE_observing_WHEN_fetching_THEN_it_retries() = runBlocking<Unit>(testDispatcher) {
|
||||
fun GIVEN_one_pending_video_AND_parsing_errors_WHILE_observing_WHEN_fetching_THEN_it_retries() = runBlocking<Unit> {
|
||||
val videoInPending = VideoInPending("alma", "banan")
|
||||
videoInPendingMutableFlow.value = listOf(videoInPending)
|
||||
var specificException = true
|
||||
|
|
@ -196,7 +200,7 @@ class VideoDownloadingProcessorUseCaseTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun GIVEN_one_pending_video_AND_unknown_errors_WHILE_observing_WHEN_fetching_THEN_it_retries() = runBlocking<Unit>(testDispatcher) {
|
||||
fun GIVEN_one_pending_video_AND_unknown_errors_WHILE_observing_WHEN_fetching_THEN_it_retries() = runBlocking<Unit> {
|
||||
val videoInPending = VideoInPending("alma", "banan")
|
||||
videoInPendingMutableFlow.value = listOf(videoInPending)
|
||||
var specificException = true
|
||||
|
|
@ -216,7 +220,7 @@ class VideoDownloadingProcessorUseCaseTest {
|
|||
|
||||
// verify that fetching even while request is running doesn't matter, only after error is emitted
|
||||
@Test
|
||||
fun GIVEN_one_pending_video_AND_delaying_until_fetch_WHILE_observing_WHEN_fetching_THEN_emition_happens_only_once() = runBlocking<Unit>(testDispatcher) {
|
||||
fun GIVEN_one_pending_video_AND_delaying_until_fetch_WHILE_observing_WHEN_fetching_THEN_emition_happens_only_once() = runBlocking<Unit> {
|
||||
val videoInPending = VideoInPending("alma", "banan")
|
||||
videoInPendingMutableFlow.value = listOf(videoInPending)
|
||||
var specificException = true
|
||||
|
|
@ -242,7 +246,7 @@ class VideoDownloadingProcessorUseCaseTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun GIVEN_one_pending_video_AND_failing_request_WHEN_observing_THEN_video_is_marked_processing_then_unprocessing() = runBlocking<Unit>(testDispatcher) {
|
||||
fun GIVEN_one_pending_video_AND_failing_request_WHEN_observing_THEN_video_is_marked_processing_then_unprocessing() = runBlocking<Unit> {
|
||||
val videoInPending = VideoInPending("alma", "banan")
|
||||
videoInPendingMutableFlow.value = listOf(videoInPending)
|
||||
whenever(mockTikTokDownloadRemoteSource.getVideo(videoInPending)).then {
|
||||
|
|
@ -261,10 +265,10 @@ class VideoDownloadingProcessorUseCaseTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun GIVEN_one_pending_video_AND_successful_request_AND_storage_error_WHEN_observing_THEN_video_is_saved_called_and_error_is_propogated() = runBlocking(testDispatcher) {
|
||||
fun GIVEN_one_pending_video_AND_successful_request_AND_storage_error_WHEN_observing_THEN_video_is_saved_called_and_error_is_propogated() = runBlocking {
|
||||
val videoInPending = VideoInPending("alma", "banan")
|
||||
videoInPendingMutableFlow.value = listOf(videoInPending)
|
||||
val videoInSavingIntoFile = VideoInSavingIntoFile("x","u",VideoInSavingIntoFile.ContentType("a","b"), FalseInputStream())
|
||||
val videoInSavingIntoFile = VideoInSavingIntoFile("x", "u", VideoInSavingIntoFile.ContentType("a", "b"), FalseInputStream())
|
||||
whenever(mockTikTokDownloadRemoteSource.getVideo(videoInPending)).doReturn(videoInSavingIntoFile)
|
||||
whenever(mockVideoDownloadedLocalSource.saveVideo(anyOrNull())).then {
|
||||
throw StorageException()
|
||||
|
|
@ -282,10 +286,10 @@ class VideoDownloadingProcessorUseCaseTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun GIVEN_one_pending_video_AND_successful_request_AND_unexpected_error_WHEN_observing_THEN_video_is_saved_called_and_error_is_propogated() = runBlocking(testDispatcher) {
|
||||
fun GIVEN_one_pending_video_AND_successful_request_AND_unexpected_error_WHEN_observing_THEN_video_is_saved_called_and_error_is_propogated() = runBlocking {
|
||||
val videoInPending = VideoInPending("alma", "banan")
|
||||
videoInPendingMutableFlow.value = listOf(videoInPending)
|
||||
val videoInSavingIntoFile = VideoInSavingIntoFile("x","u",VideoInSavingIntoFile.ContentType("a","b"), FalseInputStream())
|
||||
val videoInSavingIntoFile = VideoInSavingIntoFile("x", "u", VideoInSavingIntoFile.ContentType("a", "b"), FalseInputStream())
|
||||
whenever(mockTikTokDownloadRemoteSource.getVideo(videoInPending)).doReturn(videoInSavingIntoFile)
|
||||
whenever(mockVideoDownloadedLocalSource.saveVideo(anyOrNull())).then {
|
||||
throw Throwable()
|
||||
|
|
@ -303,11 +307,11 @@ class VideoDownloadingProcessorUseCaseTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun GIVEN_one_pending_video_AND_successful_request_AND_successful_file_save_WHEN_observing_THEN_pending_is_removed() = runBlocking(testDispatcher) {
|
||||
fun GIVEN_one_pending_video_AND_successful_request_AND_successful_file_save_WHEN_observing_THEN_pending_is_removed() = runBlocking {
|
||||
val videoInPending = VideoInPending("alma", "banan")
|
||||
val videoDownloaded = VideoDownloaded("zz","yy","xx")
|
||||
val videoDownloaded = VideoDownloaded("zz", "yy", "xx")
|
||||
videoInPendingMutableFlow.value = listOf(videoInPending)
|
||||
val videoInSavingIntoFile = VideoInSavingIntoFile("x","u",VideoInSavingIntoFile.ContentType("a","b"), FalseInputStream())
|
||||
val videoInSavingIntoFile = VideoInSavingIntoFile("x", "u", VideoInSavingIntoFile.ContentType("a", "b"), FalseInputStream())
|
||||
whenever(mockTikTokDownloadRemoteSource.getVideo(videoInPending)).doReturn(videoInSavingIntoFile)
|
||||
whenever(mockVideoDownloadedLocalSource.saveVideo(anyOrNull())).doReturn(videoDownloaded)
|
||||
val expectedList = listOf(
|
||||
|
|
@ -325,7 +329,7 @@ class VideoDownloadingProcessorUseCaseTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun GIVEN_one_pending_video_AND_captcha_timeout_WHEN_observing_THEN_captcha_timeout_is_emited() = runBlocking(testDispatcher) {
|
||||
fun GIVEN_one_pending_video_AND_captcha_timeout_WHEN_observing_THEN_captcha_timeout_is_emited() = runBlocking {
|
||||
val videoInPending = VideoInPending("alma", "banan")
|
||||
videoInPendingMutableFlow.value = listOf(videoInPending)
|
||||
whenever(mockCaptchaTimeoutLocalSource.isInCaptchaTimeout()).doReturn(true)
|
||||
|
|
@ -344,33 +348,34 @@ class VideoDownloadingProcessorUseCaseTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun GIVEN_one_pending_video_AND_successful_request_AND_successful_file_save_WHEN_observing_with_2_THEN_pending_is_removed_AND_only_once_executed() = runBlocking(testDispatcher) {
|
||||
val videoInPending = VideoInPending("alma", "banan")
|
||||
val videoDownloaded = VideoDownloaded("zz","yy","xx")
|
||||
videoInPendingMutableFlow.value = listOf(videoInPending)
|
||||
val videoInSavingIntoFile = VideoInSavingIntoFile("x","u",VideoInSavingIntoFile.ContentType("a","b"), FalseInputStream())
|
||||
whenever(mockTikTokDownloadRemoteSource.getVideo(videoInPending)).doReturn(videoInSavingIntoFile)
|
||||
whenever(mockVideoDownloadedLocalSource.saveVideo(anyOrNull())).doReturn(videoDownloaded)
|
||||
val expectedList = listOf(
|
||||
ProcessState.Processing(videoInPending),
|
||||
ProcessState.Processed(videoDownloaded)
|
||||
)
|
||||
fun GIVEN_one_pending_video_AND_successful_request_AND_successful_file_save_WHEN_observing_with_2_THEN_pending_is_removed_AND_only_once_executed() =
|
||||
runBlocking {
|
||||
val videoInPending = VideoInPending("alma", "banan")
|
||||
val videoDownloaded = VideoDownloaded("zz", "yy", "xx")
|
||||
videoInPendingMutableFlow.value = listOf(videoInPending)
|
||||
val videoInSavingIntoFile = VideoInSavingIntoFile("x", "u", VideoInSavingIntoFile.ContentType("a", "b"), FalseInputStream())
|
||||
whenever(mockTikTokDownloadRemoteSource.getVideo(videoInPending)).doReturn(videoInSavingIntoFile)
|
||||
whenever(mockVideoDownloadedLocalSource.saveVideo(anyOrNull())).doReturn(videoDownloaded)
|
||||
val expectedList = listOf(
|
||||
ProcessState.Processing(videoInPending),
|
||||
ProcessState.Processed(videoDownloaded)
|
||||
)
|
||||
|
||||
val resultList1 = async(testDispatcher) { sut.processState.take(2).toList() }
|
||||
val resultList2 = async(testDispatcher) { sut.processState.take(2).toList() }
|
||||
testDispatcher.advanceUntilIdle()
|
||||
val resultList1 = async(testDispatcher) { sut.processState.take(2).toList() }
|
||||
val resultList2 = async(testDispatcher) { sut.processState.take(2).toList() }
|
||||
testDispatcher.advanceUntilIdle()
|
||||
|
||||
Assertions.assertEquals(expectedList, resultList1.await())
|
||||
Assertions.assertEquals(expectedList, resultList2.await())
|
||||
verify(mockVideoInPendingLocalSource, times(1)).removeVideoFromQueue(videoInPending)
|
||||
verify(mockVideoInPendingLocalSource, times(1)).pendingVideos
|
||||
verifyNoMoreInteractions(mockVideoInPendingLocalSource)
|
||||
}
|
||||
Assertions.assertEquals(expectedList, resultList1.await())
|
||||
Assertions.assertEquals(expectedList, resultList2.await())
|
||||
verify(mockVideoInPendingLocalSource, times(1)).removeVideoFromQueue(videoInPending)
|
||||
verify(mockVideoInPendingLocalSource, times(1)).pendingVideos
|
||||
verifyNoMoreInteractions(mockVideoInPendingLocalSource)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun GIVEN_one_pending_video_BUT_already_downloaded_WHEN_observing_THEN_processed_is_emitted_but_no_request_call() = runBlocking(testDispatcher) {
|
||||
fun GIVEN_one_pending_video_BUT_already_downloaded_WHEN_observing_THEN_processed_is_emitted_but_no_request_call() = runBlocking {
|
||||
val videoInPending = VideoInPending("alma", "banan")
|
||||
val videoDownloaded = VideoDownloaded("alma","banan","xx")
|
||||
val videoDownloaded = VideoDownloaded("alma", "banan", "xx")
|
||||
videoInPendingMutableFlow.value = listOf(videoInPending)
|
||||
videoDownloadedMutableFlow.value = listOf(videoDownloaded)
|
||||
val expectedList = listOf(
|
||||
|
|
@ -389,13 +394,13 @@ class VideoDownloadingProcessorUseCaseTest {
|
|||
verifyNoMoreInteractions(mockVideoInPendingLocalSource)
|
||||
verifyNoMoreInteractions(mockVideoDownloadedLocalSource)
|
||||
verifyNoMoreInteractions(mockVideoInProgressLocalSource)
|
||||
verifyZeroInteractions(mockTikTokDownloadRemoteSource)
|
||||
verifyNoInteractions(mockTikTokDownloadRemoteSource)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun GIVEN_one_pending_video_BUT_already_downloaded_AND_captcha_timeout_WHEN_observing_THEN_processed_is_emitted_but_no_request_call() = runBlocking(testDispatcher) {
|
||||
fun GIVEN_one_pending_video_BUT_already_downloaded_AND_captcha_timeout_WHEN_observing_THEN_processed_is_emitted_but_no_request_call() = runBlocking {
|
||||
val videoInPending = VideoInPending("alma", "banan")
|
||||
val videoDownloaded = VideoDownloaded("alma","banan","xx")
|
||||
val videoDownloaded = VideoDownloaded("alma", "banan", "xx")
|
||||
videoInPendingMutableFlow.value = listOf(videoInPending)
|
||||
videoDownloadedMutableFlow.value = listOf(videoDownloaded)
|
||||
whenever(mockCaptchaTimeoutLocalSource.isInCaptchaTimeout()).doReturn(true)
|
||||
|
|
@ -415,11 +420,11 @@ class VideoDownloadingProcessorUseCaseTest {
|
|||
verifyNoMoreInteractions(mockVideoInPendingLocalSource)
|
||||
verifyNoMoreInteractions(mockVideoDownloadedLocalSource)
|
||||
verifyNoMoreInteractions(mockVideoInProgressLocalSource)
|
||||
verifyZeroInteractions(mockTikTokDownloadRemoteSource)
|
||||
verifyNoInteractions(mockTikTokDownloadRemoteSource)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun GIVEN_one_pending_video_BUT_CaptchaTimeoutException_WHEN_observing_THEN_its_saved_and_captchaError_emitted() = runBlocking(testDispatcher) {
|
||||
fun GIVEN_one_pending_video_BUT_CaptchaTimeoutException_WHEN_observing_THEN_its_saved_and_captchaError_emitted() = runBlocking {
|
||||
val videoInPending = VideoInPending("alma", "banan")
|
||||
videoInPendingMutableFlow.value = listOf(videoInPending)
|
||||
videoDownloadedMutableFlow.value = listOf()
|
||||
|
|
@ -451,7 +456,7 @@ class VideoDownloadingProcessorUseCaseTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun GIVEN_one_pending_video_AND_not_advancing_enough_WHILE_observing_WHEN_fetching_THEN_nothing_is_called() = runBlocking<Unit>(testDispatcher) {
|
||||
fun GIVEN_one_pending_video_AND_not_advancing_enough_WHILE_observing_WHEN_fetching_THEN_nothing_is_called() = runBlocking<Unit> {
|
||||
val videoInPending = VideoInPending("alma", "banan")
|
||||
videoInPendingMutableFlow.value = listOf(videoInPending)
|
||||
whenever(mockTikTokDownloadRemoteSource.getVideo(videoInPending)).then { throw NetworkException() }
|
||||
|
|
@ -459,21 +464,23 @@ class VideoDownloadingProcessorUseCaseTest {
|
|||
val resultList = async(testDispatcher) { sut.processState.take(2).toList() }
|
||||
testDispatcher.advanceTimeBy(199)
|
||||
|
||||
verifyZeroInteractions(mockTikTokDownloadRemoteSource)
|
||||
verifyNoInteractions(mockTikTokDownloadRemoteSource)
|
||||
testDispatcher.advanceUntilIdle()
|
||||
resultList.cancelAndJoin()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun GIVEN_one_pending_video_AND_but_advancing_enough_WHILE_observing_WHEN_fetching_THEN_nothing_is_called() = runBlocking<Unit>(testDispatcher) {
|
||||
fun GIVEN_one_pending_video_AND_but_advancing_enough_WHILE_observing_WHEN_fetching_THEN_nothing_is_called() = runBlocking<Unit> {
|
||||
val videoInPending = VideoInPending("alma", "banan")
|
||||
videoInPendingMutableFlow.value = listOf(videoInPending)
|
||||
whenever(mockTikTokDownloadRemoteSource.getVideo(videoInPending)).then { throw NetworkException() }
|
||||
|
||||
val resultList = async(testDispatcher) { sut.processState.take(2).toList() }
|
||||
testDispatcher.advanceTimeBy(200)
|
||||
testDispatcher.advanceTimeBy(201)
|
||||
|
||||
verify(mockTikTokDownloadRemoteSource, times(1)).getVideo(videoInPending)
|
||||
verifyNoMoreInteractions(mockTikTokDownloadRemoteSource)
|
||||
testDispatcher.advanceUntilIdle()
|
||||
resultList.cancelAndJoin()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,6 @@
|
|||
package org.fnives.tiktokdownloader.di
|
||||
|
||||
import android.content.Context
|
||||
import com.nhaarman.mockitokotlin2.anyOrNull
|
||||
import com.nhaarman.mockitokotlin2.doReturn
|
||||
import com.nhaarman.mockitokotlin2.mock
|
||||
import com.nhaarman.mockitokotlin2.whenever
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.test.resetMain
|
||||
import kotlinx.coroutines.test.setMain
|
||||
|
|
@ -14,10 +10,16 @@ import org.fnives.tiktokdownloader.ui.main.queue.QueueViewModel
|
|||
import org.junit.jupiter.api.AfterEach
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.Timeout
|
||||
import org.mockito.kotlin.anyOrNull
|
||||
import org.mockito.kotlin.doReturn
|
||||
import org.mockito.kotlin.mock
|
||||
import org.mockito.kotlin.whenever
|
||||
|
||||
@Timeout(value = 2)
|
||||
class ServiceLocatorTest {
|
||||
|
||||
private lateinit var mockContext : Context
|
||||
private lateinit var mockContext: Context
|
||||
|
||||
@BeforeEach
|
||||
fun setup() {
|
||||
|
|
@ -30,7 +32,7 @@ class ServiceLocatorTest {
|
|||
}
|
||||
|
||||
@AfterEach
|
||||
fun tearDown(){
|
||||
fun tearDown() {
|
||||
Dispatchers.resetMain()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
package org.fnives.tiktokdownloader.helper
|
||||
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.test.TestDispatcher
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
fun TestDispatcher.advanceUntilIdle() = scheduler.advanceUntilIdle()
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
fun TestDispatcher.advanceTimeBy(delayTimeMillis: Long) = scheduler.advanceTimeBy(delayTimeMillis)
|
||||
|
|
@ -3,7 +3,7 @@ package org.fnives.tiktokdownloader.helper.mock
|
|||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.savedstate.SavedStateRegistry
|
||||
import androidx.savedstate.SavedStateRegistryOwner
|
||||
import com.nhaarman.mockitokotlin2.mock
|
||||
import org.mockito.kotlin.mock
|
||||
|
||||
class MockSavedStateRegistryOwner(
|
||||
private val lifecycle: Lifecycle = MockLifecycle(),
|
||||
|
|
|
|||
|
|
@ -2,14 +2,7 @@ package org.fnives.tiktokdownloader.ui.main
|
|||
|
||||
import androidx.lifecycle.SavedStateHandle
|
||||
import com.jraska.livedata.test
|
||||
import com.nhaarman.mockitokotlin2.doReturn
|
||||
import com.nhaarman.mockitokotlin2.mock
|
||||
import com.nhaarman.mockitokotlin2.times
|
||||
import com.nhaarman.mockitokotlin2.verify
|
||||
import com.nhaarman.mockitokotlin2.verifyNoMoreInteractions
|
||||
import com.nhaarman.mockitokotlin2.whenever
|
||||
import kotlinx.coroutines.channels.ConflatedBroadcastChannel
|
||||
import kotlinx.coroutines.flow.asFlow
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import org.fnives.tiktokdownloader.data.model.ProcessState
|
||||
import org.fnives.tiktokdownloader.data.model.VideoDownloaded
|
||||
import org.fnives.tiktokdownloader.data.model.VideoInPending
|
||||
|
|
@ -24,23 +17,29 @@ import org.junit.jupiter.api.extension.ExtendWith
|
|||
import org.junit.jupiter.params.ParameterizedTest
|
||||
import org.junit.jupiter.params.provider.Arguments
|
||||
import org.junit.jupiter.params.provider.MethodSource
|
||||
import org.mockito.kotlin.doReturn
|
||||
import org.mockito.kotlin.mock
|
||||
import org.mockito.kotlin.times
|
||||
import org.mockito.kotlin.verify
|
||||
import org.mockito.kotlin.verifyNoMoreInteractions
|
||||
import org.mockito.kotlin.whenever
|
||||
import java.util.stream.Stream
|
||||
|
||||
@Suppress("TestFunctionName")
|
||||
@ExtendWith(InstantExecutorExtension::class, MainDispatcherExtension::class)
|
||||
class MainViewModelTest {
|
||||
|
||||
private lateinit var conflatedBroadcastChannel: ConflatedBroadcastChannel<ProcessState>
|
||||
private lateinit var processStateFlow: MutableSharedFlow<ProcessState>
|
||||
private lateinit var mockVideoDownloadingProcessorUseCase: VideoDownloadingProcessorUseCase
|
||||
private lateinit var mockAddVideoToQueueUseCase: AddVideoToQueueUseCase
|
||||
private lateinit var sut: MainViewModel
|
||||
|
||||
@BeforeEach
|
||||
fun setup() {
|
||||
conflatedBroadcastChannel = ConflatedBroadcastChannel()
|
||||
processStateFlow = MutableSharedFlow(replay = 1)
|
||||
mockVideoDownloadingProcessorUseCase = mock()
|
||||
mockAddVideoToQueueUseCase = mock()
|
||||
whenever(mockVideoDownloadingProcessorUseCase.processState).doReturn(conflatedBroadcastChannel.asFlow())
|
||||
whenever(mockVideoDownloadingProcessorUseCase.processState).doReturn(processStateFlow)
|
||||
sut = MainViewModel(mockVideoDownloadingProcessorUseCase, mockAddVideoToQueueUseCase, SavedStateHandle())
|
||||
}
|
||||
|
||||
|
|
@ -95,7 +94,7 @@ class MainViewModelTest {
|
|||
|
||||
val testObserver = sut.refreshActionVisibility.test()
|
||||
|
||||
conflatedBroadcastChannel.offer(processState)
|
||||
processStateFlow.tryEmit(processState)
|
||||
|
||||
testObserver.assertHistorySize(2).assertValueHistory(false, expected)
|
||||
verify(mockVideoDownloadingProcessorUseCase, times(1)).processState
|
||||
|
|
@ -114,7 +113,7 @@ class MainViewModelTest {
|
|||
|
||||
val testObserver = sut.errorMessage.test()
|
||||
|
||||
conflatedBroadcastChannel.offer(processState)
|
||||
processStateFlow.tryEmit(processState)
|
||||
|
||||
testObserver.assertHistorySize(2).assertValueHistory(null, expected?.let(::Event))
|
||||
verify(mockVideoDownloadingProcessorUseCase, times(1)).processState
|
||||
|
|
|
|||
|
|
@ -1,15 +1,7 @@
|
|||
package org.fnives.tiktokdownloader.ui.main.queue
|
||||
|
||||
import com.jraska.livedata.test
|
||||
import com.nhaarman.mockitokotlin2.doReturn
|
||||
import com.nhaarman.mockitokotlin2.mock
|
||||
import com.nhaarman.mockitokotlin2.times
|
||||
import com.nhaarman.mockitokotlin2.verify
|
||||
import com.nhaarman.mockitokotlin2.verifyNoMoreInteractions
|
||||
import com.nhaarman.mockitokotlin2.verifyZeroInteractions
|
||||
import com.nhaarman.mockitokotlin2.whenever
|
||||
import kotlinx.coroutines.channels.ConflatedBroadcastChannel
|
||||
import kotlinx.coroutines.flow.asFlow
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import org.fnives.tiktokdownloader.data.model.VideoInPending
|
||||
import org.fnives.tiktokdownloader.data.model.VideoState
|
||||
import org.fnives.tiktokdownloader.data.usecase.AddVideoToQueueUseCase
|
||||
|
|
@ -21,13 +13,19 @@ import org.fnives.tiktokdownloader.ui.shared.Event
|
|||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.extension.ExtendWith
|
||||
import kotlin.math.exp
|
||||
import org.mockito.kotlin.doReturn
|
||||
import org.mockito.kotlin.mock
|
||||
import org.mockito.kotlin.times
|
||||
import org.mockito.kotlin.verify
|
||||
import org.mockito.kotlin.verifyNoInteractions
|
||||
import org.mockito.kotlin.verifyNoMoreInteractions
|
||||
import org.mockito.kotlin.whenever
|
||||
|
||||
@Suppress("TestFunctionName")
|
||||
@ExtendWith(InstantExecutorExtension::class, MainDispatcherExtension::class)
|
||||
class QueueViewModelTest {
|
||||
|
||||
private lateinit var stateOfVideosConflatedBroadcastChannel: ConflatedBroadcastChannel<List<VideoState>>
|
||||
private lateinit var stateOfVideosFlow: MutableSharedFlow<List<VideoState>>
|
||||
private lateinit var mockStateOfVideosObservableUseCase: StateOfVideosObservableUseCase
|
||||
private lateinit var mockAddVideoToQueueUseCase: AddVideoToQueueUseCase
|
||||
private lateinit var mockVideoDownloadingProcessorUseCase: VideoDownloadingProcessorUseCase
|
||||
|
|
@ -35,9 +33,9 @@ class QueueViewModelTest {
|
|||
|
||||
@BeforeEach
|
||||
fun setup() {
|
||||
stateOfVideosConflatedBroadcastChannel = ConflatedBroadcastChannel()
|
||||
stateOfVideosFlow = MutableSharedFlow(replay = 1)
|
||||
mockStateOfVideosObservableUseCase = mock()
|
||||
whenever(mockStateOfVideosObservableUseCase.invoke()).doReturn(stateOfVideosConflatedBroadcastChannel.asFlow())
|
||||
whenever(mockStateOfVideosObservableUseCase.invoke()).doReturn(stateOfVideosFlow)
|
||||
mockAddVideoToQueueUseCase = mock()
|
||||
mockVideoDownloadingProcessorUseCase = mock()
|
||||
sut = QueueViewModel(mockStateOfVideosObservableUseCase, mockAddVideoToQueueUseCase, mockVideoDownloadingProcessorUseCase)
|
||||
|
|
@ -48,37 +46,37 @@ class QueueViewModelTest {
|
|||
sut.downloads.test().assertNoValue()
|
||||
verify(mockStateOfVideosObservableUseCase, times(1)).invoke()
|
||||
verifyNoMoreInteractions(mockStateOfVideosObservableUseCase)
|
||||
verifyZeroInteractions(mockAddVideoToQueueUseCase)
|
||||
verifyZeroInteractions(mockVideoDownloadingProcessorUseCase)
|
||||
verifyNoInteractions(mockAddVideoToQueueUseCase)
|
||||
verifyNoInteractions(mockVideoDownloadingProcessorUseCase)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun GIVEN_initialized_AND_observing_WHEN_emitting_a_emptyList_THEN_it_is_sent_out() {
|
||||
val expected = listOf<VideoState>()
|
||||
stateOfVideosConflatedBroadcastChannel.offer(expected)
|
||||
stateOfVideosFlow.tryEmit(expected)
|
||||
|
||||
sut.downloads.test().assertValue(expected)
|
||||
verify(mockStateOfVideosObservableUseCase, times(1)).invoke()
|
||||
verifyNoMoreInteractions(mockStateOfVideosObservableUseCase)
|
||||
verifyZeroInteractions(mockAddVideoToQueueUseCase)
|
||||
verifyZeroInteractions(mockVideoDownloadingProcessorUseCase)
|
||||
verifyNoInteractions(mockAddVideoToQueueUseCase)
|
||||
verifyNoInteractions(mockVideoDownloadingProcessorUseCase)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun GIVEN_initialized_AND_observing_WHEN_emitting_two_list_THEN_both_are_sent_out_in_order() {
|
||||
val expected1 = listOf(VideoState.InPending(VideoInPending("a1","b1")))
|
||||
val expected2 = listOf(VideoState.InPending(VideoInPending("a2","b2")))
|
||||
val expected1 = listOf(VideoState.InPending(VideoInPending("a1", "b1")))
|
||||
val expected2 = listOf(VideoState.InPending(VideoInPending("a2", "b2")))
|
||||
val testObserver = sut.downloads.test()
|
||||
|
||||
stateOfVideosConflatedBroadcastChannel.offer(expected1)
|
||||
stateOfVideosConflatedBroadcastChannel.offer(expected2)
|
||||
stateOfVideosFlow.tryEmit(expected1)
|
||||
stateOfVideosFlow.tryEmit(expected2)
|
||||
|
||||
testObserver.assertHistorySize(2).assertHasValue()
|
||||
.assertValueHistory(expected1, expected2)
|
||||
verify(mockStateOfVideosObservableUseCase, times(1)).invoke()
|
||||
verifyNoMoreInteractions(mockStateOfVideosObservableUseCase)
|
||||
verifyZeroInteractions(mockAddVideoToQueueUseCase)
|
||||
verifyZeroInteractions(mockVideoDownloadingProcessorUseCase)
|
||||
verifyNoInteractions(mockAddVideoToQueueUseCase)
|
||||
verifyNoInteractions(mockVideoDownloadingProcessorUseCase)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -1,16 +1,7 @@
|
|||
package org.fnives.tiktokdownloader.ui.service
|
||||
|
||||
import com.jraska.livedata.test
|
||||
import com.nhaarman.mockitokotlin2.anyOrNull
|
||||
import com.nhaarman.mockitokotlin2.doReturn
|
||||
import com.nhaarman.mockitokotlin2.mock
|
||||
import com.nhaarman.mockitokotlin2.times
|
||||
import com.nhaarman.mockitokotlin2.verify
|
||||
import com.nhaarman.mockitokotlin2.verifyNoMoreInteractions
|
||||
import com.nhaarman.mockitokotlin2.verifyZeroInteractions
|
||||
import com.nhaarman.mockitokotlin2.whenever
|
||||
import kotlinx.coroutines.channels.ConflatedBroadcastChannel
|
||||
import kotlinx.coroutines.flow.asFlow
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import org.fnives.tiktokdownloader.R
|
||||
import org.fnives.tiktokdownloader.data.model.ProcessState
|
||||
import org.fnives.tiktokdownloader.data.model.VideoDownloaded
|
||||
|
|
@ -25,22 +16,30 @@ import org.junit.jupiter.api.extension.ExtendWith
|
|||
import org.junit.jupiter.params.ParameterizedTest
|
||||
import org.junit.jupiter.params.provider.Arguments
|
||||
import org.junit.jupiter.params.provider.MethodSource
|
||||
import org.mockito.kotlin.anyOrNull
|
||||
import org.mockito.kotlin.doReturn
|
||||
import org.mockito.kotlin.mock
|
||||
import org.mockito.kotlin.times
|
||||
import org.mockito.kotlin.verify
|
||||
import org.mockito.kotlin.verifyNoInteractions
|
||||
import org.mockito.kotlin.verifyNoMoreInteractions
|
||||
import org.mockito.kotlin.whenever
|
||||
import java.util.stream.Stream
|
||||
|
||||
@Suppress("TestFunctionName")
|
||||
@ExtendWith(InstantExecutorExtension::class, MainDispatcherExtension::class)
|
||||
class QueueServiceViewModelTest {
|
||||
|
||||
private lateinit var videoDownloadingProcessorChannel: ConflatedBroadcastChannel<ProcessState>
|
||||
private lateinit var videoDownloadingProcessorFlow: MutableSharedFlow<ProcessState>
|
||||
private lateinit var mockVideoDownloadingProcessorUseCase: VideoDownloadingProcessorUseCase
|
||||
private lateinit var mockAddVideoToQueueUseCase: AddVideoToQueueUseCase
|
||||
private lateinit var sut: QueueServiceViewModel
|
||||
|
||||
@BeforeEach
|
||||
fun setup() {
|
||||
videoDownloadingProcessorChannel = ConflatedBroadcastChannel()
|
||||
videoDownloadingProcessorFlow = MutableSharedFlow(replay = 1)
|
||||
mockVideoDownloadingProcessorUseCase = mock()
|
||||
whenever(mockVideoDownloadingProcessorUseCase.processState).doReturn(videoDownloadingProcessorChannel.asFlow())
|
||||
whenever(mockVideoDownloadingProcessorUseCase.processState).doReturn(videoDownloadingProcessorFlow)
|
||||
mockAddVideoToQueueUseCase = mock()
|
||||
sut = QueueServiceViewModel(mockAddVideoToQueueUseCase, mockVideoDownloadingProcessorUseCase)
|
||||
}
|
||||
|
|
@ -64,7 +63,7 @@ class QueueServiceViewModelTest {
|
|||
|
||||
verify(mockAddVideoToQueueUseCase, times(1)).invoke("url.com")
|
||||
verifyNoMoreInteractions(mockAddVideoToQueueUseCase)
|
||||
verifyZeroInteractions(mockVideoDownloadingProcessorUseCase)
|
||||
verifyNoInteractions(mockVideoDownloadingProcessorUseCase)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -89,7 +88,7 @@ class QueueServiceViewModelTest {
|
|||
) {
|
||||
whenever(mockAddVideoToQueueUseCase.invoke(anyOrNull())).doReturn(true)
|
||||
sut.onUrlReceived("")
|
||||
videoDownloadingProcessorChannel.offer(processState)
|
||||
videoDownloadingProcessorFlow.tryEmit(processState)
|
||||
|
||||
sut.notificationState.test()
|
||||
.assertHistorySize(1)
|
||||
|
|
@ -101,7 +100,7 @@ class QueueServiceViewModelTest {
|
|||
sut.onClear()
|
||||
|
||||
sut.onUrlReceived("alma")
|
||||
videoDownloadingProcessorChannel.offer(ProcessState.UnknownError)
|
||||
videoDownloadingProcessorFlow.tryEmit(ProcessState.UnknownError)
|
||||
|
||||
sut.notificationState.test().assertNoValue()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
buildscript {
|
||||
ext.kotlin_version = "1.4.10"
|
||||
ext.kotlin_version = "1.6.20"
|
||||
repositories {
|
||||
mavenCentral()
|
||||
google()
|
||||
jcenter()
|
||||
maven { url "https://plugins.gradle.org/m2/" }
|
||||
}
|
||||
dependencies {
|
||||
classpath "com.android.tools.build:gradle:4.1.0"
|
||||
classpath 'com.android.tools.build:gradle:7.1.3'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
|
|
@ -16,8 +17,8 @@ buildscript {
|
|||
|
||||
allprojects {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
6
gradle/wrapper/gradle-wrapper.properties
vendored
6
gradle/wrapper/gradle-wrapper.properties
vendored
|
|
@ -1,6 +1,6 @@
|
|||
#Sat Oct 31 22:42:23 EET 2020
|
||||
#Thu Jan 27 21:44:07 EET 2022
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue