From 1ef21617a2cfa0f21cc3ef3d08a79ba9beaefdec Mon Sep 17 00:00:00 2001 From: David Carver Date: Sun, 15 Dec 2024 22:22:30 -0500 Subject: [PATCH] test: Convert from Mockito to Mockk and Assertj to assertk --- emby-lib/build.gradle.kts | 3 +- .../emby/server/EmbyServerDiscoverTest.kt | 2 + .../serenity/emby/server/EmbyServerJobTest.kt | 10 +- .../emby/server/api/EmbyAPIClientTest.kt | 31 +- gradle/libs.versions.toml | 6 +- serenity-app/build.gradle.kts | 1 + .../nineworlds/serenity/MockkTestingModule.kt | 28 + .../ui/video/player/ExoplayerPresenterTest.kt | 118 ++- .../player/ExoplayerVideoActivityTest.kt | 142 ++- .../player/VideoKeyCodeHandlerDelegateTest.kt | 907 +++++++++--------- 10 files changed, 641 insertions(+), 607 deletions(-) create mode 100644 serenity-app/src/test/kotlin/us/nineworlds/serenity/MockkTestingModule.kt diff --git a/emby-lib/build.gradle.kts b/emby-lib/build.gradle.kts index b5b51b30d..0bb6fcd68 100644 --- a/emby-lib/build.gradle.kts +++ b/emby-lib/build.gradle.kts @@ -64,7 +64,6 @@ dependencies { debugImplementation(libs.toothpick.smoothie) releaseApi(libs.toothpick.javax.annotations) -// kapt(libs.toothpick.compiler) ksp(libs.toothpick.ksp.compiler) implementation(libs.android.priority.jobqueue) @@ -81,7 +80,9 @@ dependencies { testImplementation(libs.junit) testImplementation(libs.assertj.core) + testImplementation(libs.assertk.jvm) testImplementation(libs.mockito.core) + testImplementation(libs.mockk) testImplementation(libs.robolectric) testImplementation(libs.robolectric.shadows.framework) testImplementation(libs.robolectric.shadows.api) diff --git a/emby-lib/src/test/kotlin/us/nineworlds/serenity/emby/server/EmbyServerDiscoverTest.kt b/emby-lib/src/test/kotlin/us/nineworlds/serenity/emby/server/EmbyServerDiscoverTest.kt index 6940fd49d..4e9665f62 100644 --- a/emby-lib/src/test/kotlin/us/nineworlds/serenity/emby/server/EmbyServerDiscoverTest.kt +++ b/emby-lib/src/test/kotlin/us/nineworlds/serenity/emby/server/EmbyServerDiscoverTest.kt @@ -4,6 +4,7 @@ import kotlinx.coroutines.test.runTest import org.junit.Assert.* import org.junit.Before import org.junit.Test +import org.robolectric.shadows.ShadowLog class EmbyServerDiscoverTest { @@ -11,6 +12,7 @@ class EmbyServerDiscoverTest { @Before fun setUp() { + ShadowLog.stream = System.out serverDiscovery = EmbyServerDiscover() } diff --git a/emby-lib/src/test/kotlin/us/nineworlds/serenity/emby/server/EmbyServerJobTest.kt b/emby-lib/src/test/kotlin/us/nineworlds/serenity/emby/server/EmbyServerJobTest.kt index 8ed340d41..fef12dea0 100644 --- a/emby-lib/src/test/kotlin/us/nineworlds/serenity/emby/server/EmbyServerJobTest.kt +++ b/emby-lib/src/test/kotlin/us/nineworlds/serenity/emby/server/EmbyServerJobTest.kt @@ -1,6 +1,7 @@ package us.nineworlds.serenity.emby.server import android.content.Context +import io.mockk.mockk import org.greenrobot.eventbus.EventBus import org.junit.Before import org.junit.Test @@ -10,6 +11,7 @@ import org.mockito.MockitoAnnotations.initMocks import org.robolectric.RobolectricTestRunner import org.robolectric.RuntimeEnvironment import org.robolectric.annotation.Config +import org.robolectric.shadows.ShadowLog import toothpick.config.Module import us.nineworlds.serenity.common.android.injection.ApplicationContext import us.nineworlds.serenity.emby.test.InjectingTest @@ -18,17 +20,15 @@ import us.nineworlds.serenity.emby.test.InjectingTest @Config(sdk = [28]) class EmbyServerJobTest : InjectingTest() { - @Mock - lateinit var mockEventBus: EventBus - override val modules: List get() = mutableListOf(TestModule()) - lateinit var job: EmbyServerJob + private lateinit var job: EmbyServerJob @Before override fun setUp() { - initMocks(this) + ShadowLog.stream = System.out + super.setUp() job = EmbyServerJob() } diff --git a/emby-lib/src/test/kotlin/us/nineworlds/serenity/emby/server/api/EmbyAPIClientTest.kt b/emby-lib/src/test/kotlin/us/nineworlds/serenity/emby/server/api/EmbyAPIClientTest.kt index 6e3863f0e..f4e7352b5 100644 --- a/emby-lib/src/test/kotlin/us/nineworlds/serenity/emby/server/api/EmbyAPIClientTest.kt +++ b/emby-lib/src/test/kotlin/us/nineworlds/serenity/emby/server/api/EmbyAPIClientTest.kt @@ -1,7 +1,10 @@ package us.nineworlds.serenity.emby.server.api import androidx.test.core.app.ApplicationProvider -import org.assertj.core.api.Assertions.assertThat +import assertk.assertThat +import assertk.assertions.hasSize +import assertk.assertions.isNotEmpty +import assertk.assertions.isNotNull import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -15,37 +18,37 @@ import us.nineworlds.serenity.emby.server.model.AuthenticationResult @Config(sdk = [28]) class EmbyAPIClientTest { - lateinit var client: EmbyAPIClient + private lateinit var client: EmbyAPIClient @Before fun setUp() { ShadowLog.stream = System.out client = EmbyAPIClient(context = ApplicationProvider.getApplicationContext()) - client.updateBaseUrl("http://192.168.86.162:8096") + client.updateBaseUrl("http://192.168.68.95:8096") } @Test fun retrieveAllPublicUsers() { val result = client.fetchAllPublicUsers() - assertThat(result).isNotEmpty.hasSize(2) + assertThat(result).hasSize(2) } @Test fun loginAdminUser() { val authenticateResult = authenticate() assertThat(authenticateResult).isNotNull() - assertThat(authenticateResult.accesToken).isNotBlank() - assertThat(client.serverId).isNotBlank() - assertThat(client.accessToken).isNotBlank() - assertThat(client.userId).isNotBlank() + assertThat(authenticateResult.accesToken).isNotEmpty() + assertThat(client.serverId).isNotEmpty() + assertThat(client.accessToken).isNotNull() + assertThat(client.userId).isNotNull().isNotEmpty() } @Test fun testCurrentUsersViews() { authenticate() val result = client.currentUserViews() - assertThat(result.items).isNotEmpty + assertThat(result.items).isNotEmpty() } @Test fun availableFiltersForCurrentUser() { @@ -61,8 +64,8 @@ class EmbyAPIClientTest { authenticate() val result = client.retrieveRootData() - assertThat(result).isNotNull - assertThat(result!!.directories).isNotEmpty + assertThat(result).isNotNull() + assertThat(result.directories).isNotEmpty() } @Test fun createCategoriesForParentId() { @@ -74,7 +77,7 @@ class EmbyAPIClientTest { val categories = client.retrieveCategoriesById(parentId) - assertThat(categories.directories).isNotEmpty + assertThat(categories.directories).isNotEmpty() } @Test fun fetchAllMovies() { @@ -85,7 +88,7 @@ class EmbyAPIClientTest { val movies = client.retrieveItemByIdCategory(parentId, "all", Types.EPISODE) - assertThat(movies.videos).isNotEmpty + assertThat(movies.videos).isNotEmpty() } @Test fun fetchAllLatestMovies() { @@ -97,7 +100,7 @@ class EmbyAPIClientTest { val itemResult = client.retrieveItemByIdCategory(key, "recentlyAdded", Types.MOVIES) - assertThat(itemResult.videos).isNotEmpty + assertThat(itemResult.videos).isNotEmpty() } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index aff391784..6c127d02a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,7 +2,7 @@ appVersion = "3.0-M1" annotationVersion = "1.9.1" appcompatVersion = "1.7.0" -assertkJvmVersion = "0.24" +assertkJvmVersion = "0.28.1" cardviewVersion = "1.0.0" commonsIo = "2.13.0" commonsLang3Version = "3.7" @@ -55,6 +55,7 @@ easydeviceInfoVersion = "2.4.1" androidxTestCoreVersion = "1.6.1" androidxRecyclerViewVersion = "1.3.2" resourcefulVersion = "1.1.0" +mockkVersion = "1.13.13" [libraries] androidx-annotation = { module = "androidx.annotation:annotation", version.ref = "annotationVersion" } @@ -69,7 +70,6 @@ androidx-leanback-preference = { module = "androidx.leanback:leanback-preference androidx-legacy-support-v4 = { module = "androidx.legacy:legacy-support-v4", version.ref = "legacySupportV4Version" } androidx-percentlayout = { module = "androidx.percentlayout:percentlayout", version.ref = "percentlayoutVersion" } androidx-recycler-view = { module = "androidx.recyclerview:recyclerview", version.ref = "androidxRecyclerViewVersion"} -assertk-jvm = { module = "com.willowtreeapps.assertk:assertk-jvm", version.ref = "assertkJvmVersion" } commons-io = { module = "commons-io:commons-io", version.ref = "commonsIo" } commons-lang3 = { module = "org.apache.commons:commons-lang3", version.ref = "commonsLang3Version" } exoplayer-core = { module = "com.google.android.exoplayer:exoplayer-core", version.ref = "exoplayerVersion"} @@ -123,6 +123,7 @@ assertj-core = { group = "org.assertj", name = "assertj-core", version.ref = "as assertj-android = { group = "com.squareup.assertj", name = "assertj-android", version.ref = "assertJAndroidVersion"} mockito-core = { group = "org.mockito", name = "mockito-core", version.ref = "mockitoVersion" } mockito-kotlin = { module = "com.nhaarman.mockitokotlin2:mockito-kotlin", version = "2.2.0"} +mockk = { module = "io.mockk:mockk", version.ref = "mockkVersion" } robolectric = { group = "org.robolectric", name = "robolectric", version.ref = "robolectricVersion" } robolectric-shadows-framework = { group = "org.robolectric", name = "shadows-framework", version.ref = "robolectricVersion" } robolectric-shadows-api = { group = "org.robolectric", name = "shadowapi", version.ref = "robolectricVersion" } @@ -133,5 +134,6 @@ androidx-test-core = { group = "androidx.test", name = "core", version.ref = "an kotlin-coroutines-test = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-test", version.ref = "kotlinCoroutinesVersion" } toothpick-testing = { group = "com.github.stephanenicolas.toothpick", name = "toothpick-testing", version.ref = "toothPickVersion"} +assertk-jvm = { module = "com.willowtreeapps.assertk:assertk", version.ref = "assertkJvmVersion" } [plugins] diff --git a/serenity-app/build.gradle.kts b/serenity-app/build.gradle.kts index 02db005ba..296ae755b 100644 --- a/serenity-app/build.gradle.kts +++ b/serenity-app/build.gradle.kts @@ -191,6 +191,7 @@ dependencies { exclude(group = "xpp3") } + testImplementation(libs.mockk) testImplementation(libs.mockito.core) testImplementation(libs.mockito.kotlin) testImplementation(libs.commons.lang3) diff --git a/serenity-app/src/test/kotlin/us/nineworlds/serenity/MockkTestingModule.kt b/serenity-app/src/test/kotlin/us/nineworlds/serenity/MockkTestingModule.kt new file mode 100644 index 000000000..b903586a4 --- /dev/null +++ b/serenity-app/src/test/kotlin/us/nineworlds/serenity/MockkTestingModule.kt @@ -0,0 +1,28 @@ +package us.nineworlds.serenity + +import android.content.Context +import androidx.localbroadcastmanager.content.LocalBroadcastManager +import com.birbit.android.jobqueue.JobManager +import io.mockk.mockk +import toothpick.config.Module +import us.nineworlds.serenity.common.rest.SerenityClient +import us.nineworlds.serenity.core.logger.Logger +import us.nineworlds.serenity.core.util.AndroidHelper + +class MockkTestingModule : Module() { + companion object { + val mockJobManager: JobManager = mockk(relaxed = true) + val mockPlexAppFactory: SerenityClient = mockk(relaxed = true) + val mockLocalBroadcastManager: LocalBroadcastManager = mockk(relaxed = true) + var mockLogger: Logger = mockk(relaxed = true) + var mockAndroidHelper: AndroidHelper = mockk(relaxed = true) + } + + init { + bind(JobManager::class.java).toInstance(mockJobManager) + bind(SerenityClient::class.java).toInstance(mockPlexAppFactory) + bind(LocalBroadcastManager::class.java).toInstance(mockLocalBroadcastManager) + bind(Logger::class.java).toInstance(mockLogger) + bind(AndroidHelper::class.java).toInstance(mockAndroidHelper) + } +} \ No newline at end of file diff --git a/serenity-app/src/test/kotlin/us/nineworlds/serenity/ui/video/player/ExoplayerPresenterTest.kt b/serenity-app/src/test/kotlin/us/nineworlds/serenity/ui/video/player/ExoplayerPresenterTest.kt index aedf7fb7b..523850225 100644 --- a/serenity-app/src/test/kotlin/us/nineworlds/serenity/ui/video/player/ExoplayerPresenterTest.kt +++ b/serenity-app/src/test/kotlin/us/nineworlds/serenity/ui/video/player/ExoplayerPresenterTest.kt @@ -2,32 +2,29 @@ package us.nineworlds.serenity.ui.video.player import android.view.View import androidx.test.ext.junit.runners.AndroidJUnit4 +import assertk.assertThat +import assertk.assertions.isEmpty +import assertk.assertions.isEqualTo +import assertk.assertions.isFalse +import assertk.assertions.isNotNull +import assertk.assertions.isTrue import com.birbit.android.jobqueue.JobManager -import com.nhaarman.mockitokotlin2.atLeastOnce -import com.nhaarman.mockitokotlin2.doReturn -import com.nhaarman.mockitokotlin2.mock -import com.nhaarman.mockitokotlin2.never -import com.nhaarman.mockitokotlin2.spy -import com.nhaarman.mockitokotlin2.verify -import com.nhaarman.mockitokotlin2.whenever +import io.mockk.Runs +import io.mockk.clearAllMocks + +import io.mockk.every +import io.mockk.just +import io.mockk.mockk +import io.mockk.spyk +import io.mockk.verify import org.apache.commons.lang3.RandomStringUtils -import org.assertj.core.api.Java6Assertions.assertThat import org.greenrobot.eventbus.EventBus import org.junit.Before import org.junit.Ignore -import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith -import org.mockito.ArgumentMatchers.anyInt -import org.mockito.ArgumentMatchers.anyString -import org.mockito.ArgumentMatchers.eq -import org.mockito.Mock -import org.mockito.Mockito.any -import org.mockito.junit.MockitoJUnit -import org.mockito.junit.MockitoRule -import org.mockito.quality.Strictness.LENIENT import toothpick.config.Module -import us.nineworlds.serenity.TestingModule +import us.nineworlds.serenity.MockkTestingModule import us.nineworlds.serenity.common.rest.SerenityClient import us.nineworlds.serenity.core.logger.Logger import us.nineworlds.serenity.core.model.VideoContentInfo @@ -35,7 +32,6 @@ import us.nineworlds.serenity.core.model.impl.MoviePosterInfo import us.nineworlds.serenity.core.util.AndroidHelper import us.nineworlds.serenity.events.video.OnScreenDisplayEvent import us.nineworlds.serenity.injection.ForVideoQueue -import us.nineworlds.serenity.jobs.video.UpdatePlaybackPostionJob import us.nineworlds.serenity.jobs.video.WatchedStatusJob import us.nineworlds.serenity.test.InjectingTest import java.util.LinkedList @@ -45,72 +41,64 @@ import javax.inject.Inject @RunWith(AndroidJUnit4::class) class ExoplayerPresenterTest : InjectingTest() { - @Rule - @JvmField - var mockitoRule: MockitoRule = MockitoJUnit.rule().strictness(LENIENT) + private companion object { + private val mockVideoContentInfo = mockk(relaxed = true) + private val mockVideoQueue = LinkedList() + private val mockView: ExoplayerContract.ExoplayerView = mockk(relaxed = true) + private val mockEventBus: EventBus = mockk(relaxed = true) + private val mockOnScreenDisplayEvent: OnScreenDisplayEvent = mockk(relaxed = true) + private val mockAndroidHelper: AndroidHelper = mockk(relaxed = true) + } @Inject - lateinit var mockPlexFactory: SerenityClient + lateinit var mockSerenityClient: SerenityClient @Inject lateinit var mockJobManager: JobManager @Inject lateinit var mockLogger: Logger - private var mockVideoContentInfo = mock() - private var mockVideoQueue = LinkedList() - @Mock - lateinit var mockView: ExoplayerContract.ExoplayerView - @Mock - lateinit var mockEventBus: EventBus - @Mock - lateinit var mockOnScreenDisplayEvent: OnScreenDisplayEvent - - @Mock - lateinit var mockAndroidHelper: AndroidHelper - private lateinit var presenter: ExoplayerPresenter @Before override fun setUp() { + clearAllMocks() super.setUp() - presenter = spy(ExoplayerPresenter()) - presenter.attachView(mockView) + presenter = spyk(ExoplayerPresenter()) + every { presenter.viewState } returns mockView - doReturn(mockView).whenever(presenter).viewState + presenter.attachView(mockView) } @Test fun updateWatchedStatusAddsJobToJobmanager() { val expectedId = RandomStringUtils.randomNumeric(5) - var videoContentInfo = MoviePosterInfo() + val videoContentInfo = MoviePosterInfo() videoContentInfo.setId(expectedId) presenter.video = videoContentInfo presenter.updateWatchedStatus() - verify(mockJobManager).addJobInBackground(any(WatchedStatusJob::class.java)) + verify { mockJobManager.addJobInBackground(any())} } @Test fun onScreenDisplayEventShowsControllerWhenHidden() { - doReturn(false).whenever(mockOnScreenDisplayEvent).isShowing + every { mockOnScreenDisplayEvent.isShowing } returns false presenter.onOnScreenDisplayEvent(mockOnScreenDisplayEvent) - verify(mockView, never()).hideController() - verify(mockView).showController() - verify(mockOnScreenDisplayEvent).isShowing + verify(exactly = 0) { mockView.hideController() } + verify { mockView.showController() } + verify { mockOnScreenDisplayEvent.isShowing } } @Test fun onScreenDisplayEventHidesViewControlWhenShowing() { - doReturn(true).whenever(mockOnScreenDisplayEvent).isShowing - presenter.onOnScreenDisplayEvent(mockOnScreenDisplayEvent) + presenter.onOnScreenDisplayEvent(OnScreenDisplayEvent(true)) - verify(mockView).hideController() - verify(mockView, never()).showController() - verify(mockOnScreenDisplayEvent).isShowing + verify { mockView.hideController() } + verify(exactly = 0) { mockView.showController() } } @Test @@ -118,7 +106,7 @@ class ExoplayerPresenterTest : InjectingTest() { presenter.eventBus = mockEventBus presenter.detachView(mockView) - verify(mockEventBus).unregister(presenter) + verify { mockEventBus.unregister(presenter) } } @Test @@ -138,15 +126,17 @@ class ExoplayerPresenterTest : InjectingTest() { @Test fun updateServerPlaybackPositionSetsVideoOffestToExpectedPosition() { - var videoContentInfo = MoviePosterInfo() + val videoContentInfo = MoviePosterInfo() val expectedPosition = Random().nextInt() + every { mockJobManager.addJobInBackground(any()) } just Runs + presenter.video = videoContentInfo presenter.updateServerPlaybackPosition(expectedPosition.toLong()) assertThat(videoContentInfo.resumeOffset).isEqualTo(expectedPosition) - verify(mockJobManager).addJobInBackground(any(UpdatePlaybackPostionJob::class.java)) + verify { mockJobManager.addJobInBackground(any()) } } @Test @@ -154,7 +144,7 @@ class ExoplayerPresenterTest : InjectingTest() { presenter.playBackFromVideoQueue(true) assertThat(mockVideoQueue).isEmpty() - verify(mockView, never()).initializePlayer(anyString(), eq(0)) + verify (exactly = 0) { mockView.initializePlayer(any(), 0) } } @Test @@ -163,22 +153,23 @@ class ExoplayerPresenterTest : InjectingTest() { val expectedId = RandomStringUtils.randomNumeric(1) val expectedUrl = "http://www.example.com/start.mkv" - doReturn("avi").whenever(mockVideoContentInfo).container - doReturn(expectedId).whenever(mockVideoContentInfo).id() - doReturn(expectedUrl).whenever(mockPlexFactory).createTranscodeUrl(anyString(), anyInt()) + every { mockVideoContentInfo.container } returns "avi" + every { mockVideoContentInfo.id() } returns expectedId + every { mockVideoQueue.poll() } returns mockVideoContentInfo + every { mockSerenityClient.createTranscodeUrl(any(), any()) } returns expectedUrl presenter.playBackFromVideoQueue(true) - assertThat(presenter.video as VideoContentInfo).isNotNull.isEqualTo(mockVideoContentInfo) - //Truth.assertThat(presenter.video).isNotNull().isEqualTo(mockVideoContentInfo) - verify(mockVideoContentInfo, atLeastOnce()).container - verify(mockVideoContentInfo).id() - verify(mockPlexFactory).createTranscodeUrl(expectedId, 0) - verify(mockView).initializePlayer(expectedUrl, 0) + assertThat(presenter.video as VideoContentInfo).isNotNull().isEqualTo(mockVideoContentInfo) + + verify(atLeast = 1) { mockVideoContentInfo.container } + verify { mockVideoContentInfo.id() } + verify { mockSerenityClient.createTranscodeUrl(expectedId, 0)} + verify { mockView.initializePlayer(expectedUrl, 0) } } override fun installTestModules() { - scope.installTestModules(TestingModule(), TestModule()) + scope.installTestModules(MockkTestingModule(), TestModule()) } inner class TestModule : Module() { @@ -187,6 +178,7 @@ class ExoplayerPresenterTest : InjectingTest() { bind(LinkedList::class.java).withName(ForVideoQueue::class.java).toInstance(mockVideoQueue) bind(EventBus::class.java).toInstance(mockEventBus) bind(AndroidHelper::class.java).toInstance(mockAndroidHelper) + bind(JobManager::class.java).toInstance(mockk(relaxed = true)) } } } \ No newline at end of file diff --git a/serenity-app/src/test/kotlin/us/nineworlds/serenity/ui/video/player/ExoplayerVideoActivityTest.kt b/serenity-app/src/test/kotlin/us/nineworlds/serenity/ui/video/player/ExoplayerVideoActivityTest.kt index b3882f72b..ba723215e 100644 --- a/serenity-app/src/test/kotlin/us/nineworlds/serenity/ui/video/player/ExoplayerVideoActivityTest.kt +++ b/serenity-app/src/test/kotlin/us/nineworlds/serenity/ui/video/player/ExoplayerVideoActivityTest.kt @@ -2,38 +2,33 @@ package us.nineworlds.serenity.ui.video.player import android.net.Uri import android.view.KeyEvent +import assertk.assertThat +import assertk.assertions.isInstanceOf +import assertk.assertions.isNotNull +import assertk.assertions.isTrue import com.google.android.exoplayer2.Player import com.google.android.exoplayer2.SimpleExoPlayer -import com.google.android.exoplayer2.source.MediaSource import com.google.android.exoplayer2.trackselection.TrackSelectionArray import com.google.android.exoplayer2.trackselection.TrackSelector import com.google.android.exoplayer2.upstream.DataSource -import com.nhaarman.mockitokotlin2.anyOrNull -import com.nhaarman.mockitokotlin2.whenever -import org.assertj.android.api.Assertions -import org.assertj.core.api.Java6Assertions.assertThat +import io.mockk.Runs +import io.mockk.clearAllMocks +import io.mockk.every +import io.mockk.just +import io.mockk.mockk +import io.mockk.spyk +import io.mockk.verify import org.junit.Before import org.junit.Ignore -import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith -import org.mockito.Mock -import org.mockito.Mockito.any -import org.mockito.Mockito.doNothing -import org.mockito.Mockito.doReturn -import org.mockito.Mockito.never -import org.mockito.Mockito.spy -import org.mockito.Mockito.verify -import org.mockito.junit.MockitoJUnit -import org.mockito.junit.MockitoRule -import org.mockito.quality.Strictness.LENIENT import org.robolectric.Robolectric import org.robolectric.RobolectricTestRunner import org.robolectric.annotation.Config import toothpick.Scope import toothpick.Toothpick import toothpick.config.Module -import us.nineworlds.serenity.TestingModule +import us.nineworlds.serenity.MockkTestingModule import us.nineworlds.serenity.common.annotations.InjectionConstants import us.nineworlds.serenity.core.logger.Logger import us.nineworlds.serenity.core.util.AndroidHelper @@ -47,27 +42,14 @@ import javax.inject.Inject @Config(shadows = [ShadowSubtitleView::class]) open class ExoplayerVideoActivityTest : InjectingTest() { - @Rule - @JvmField - var mockitoRule: MockitoRule = MockitoJUnit.rule().strictness(LENIENT) - - @Mock - lateinit var mockExoPlayerPresenter: ExoplayerPresenter - - @Mock - lateinit var mockDataSourceFactory: DataSource.Factory - - @Mock - lateinit var mockMappingTrackSelector: TrackSelector - - @Mock - lateinit var mockLogger: Logger - - @Mock - lateinit var mockPlayer: SimpleExoPlayer - - @Mock - lateinit var mockTimeUtil: TimeUtil + companion object { + private val mockExoPlayerPresenter = mockk(relaxed = true) + private val mockDataSourceFactory = mockk(relaxed = true) + private val mockTrackSelector = mockk(relaxed = true) + private val mockLogger = mockk(relaxed = true) + private val mockPlayer = mockk(relaxed = true) + private val mockTimeUtil = mockk(relaxed = true) + } @Inject lateinit var mockAndroidHelper: AndroidHelper @@ -81,6 +63,7 @@ open class ExoplayerVideoActivityTest : InjectingTest() { @Before override fun setUp() { + clearAllMocks() super.setUp() activity = Robolectric.buildActivity(ExoplayerVideoActivity::class.java).create().get() activity.player = mockPlayer @@ -88,52 +71,50 @@ open class ExoplayerVideoActivityTest : InjectingTest() { @Test fun bindsSimpleExoPlayerView() { - Assertions.assertThat(activity.playerView).isNotNull + assertThat(activity.playerView).isNotNull() } @Test fun onStartDoesNotCallsPresenterPlayBackFromVideoQueueWhenOnAPI19OrHigher() { activity.onStart() - verify(mockExoPlayerPresenter, never()).playBackFromVideoQueue(anyOrNull()) + verify(exactly = 0) { mockExoPlayerPresenter.playBackFromVideoQueue(any()) } } @Test fun onPauseCallsReleasePlayser() { - val spy = spy(activity) - doNothing().whenever(spy).releasePlayer() - spy.onPause() + activity.onPause() - verify(spy).releasePlayer() + verify { mockPlayer.stop() } } @Test fun onPauseDoesNotCallsReleasePlayser() { - doReturn(24).whenever(mockAndroidHelper).buildNumber() - val spy = spy(activity) - doNothing().whenever(spy).releasePlayer() - spy.onPause() + every { mockAndroidHelper.buildNumber() } returns 24 + + activity.onPause() - verify(spy, never()).releasePlayer() + verify(exactly = 0) { mockPlayer.stop() } } @Test fun onStopDCallsReleasePlayser() { - doReturn(24).whenever(mockAndroidHelper).buildNumber() - val spy = spy(activity) - doNothing().whenever(spy).releasePlayer() + every { mockAndroidHelper.buildNumber() } returns 24 + val spy = spyk(activity) + every { spy.releasePlayer() } just Runs spy.onStop() - verify(spy).releasePlayer() + verify { spy.releasePlayer() } } @Test fun onStopDoesNotCallsReleasePlayser() { - val spy = spy(activity) - doNothing().whenever(spy).releasePlayer() + val spy = spyk(activity) + every { spy.releasePlayer() } just Runs + spy.onStop() - verify(spy, never()).releasePlayer() + verify(exactly = 0 ) { spy.releasePlayer() } } @Test @@ -144,24 +125,24 @@ open class ExoplayerVideoActivityTest : InjectingTest() { @Test @Ignore fun initializePlayerSetABunchOfRequiredItems() { - val spy = spy(activity) - doReturn(mockPlayer).whenever(spy).createSimpleExoplayer() - doReturn(TrackSelectionArray()).whenever(mockPlayer).getCurrentTrackSelections() + val spy = spyk(activity) + every { spy.createSimpleExoplayer() } returns mockPlayer + every { mockPlayer.currentTrackSelections } returns TrackSelectionArray() spy.initializePlayer("http://www.example.com/start.mkv", 0) assertThat(spy.player).isInstanceOf(SimpleExoPlayer::class.java) - verify(spy).createSimpleExoplayer() - verify(mockPlayer).addListener(any(Player.Listener::class.java)) - verify(mockPlayer).prepare(any(MediaSource::class.java)) + verify { spy.createSimpleExoplayer() } + verify { mockPlayer.addListener(any()) } + verify { mockPlayer.prepare(any())} } @Test fun releasePlayerReleasesWhenPlayerIsNotNull() { activity.releasePlayer() - verify(mockPlayer).release() + verify { mockPlayer.release() } } @Test @@ -171,43 +152,44 @@ open class ExoplayerVideoActivityTest : InjectingTest() { @Test fun onBackPressedStopsAndReleasesVideoPlayer() { - doReturn(Player.STATE_READY).whenever(mockPlayer).playbackState + every { mockPlayer.playbackState } returns Player.STATE_READY activity.onBackPressed() - verify(mockPlayer).playWhenReady = false - verify(mockExoPlayerPresenter).stopPlaying(anyOrNull()) - verify(mockPlayer).clearVideoSurface() - verify(mockPlayer).release() + verify { mockPlayer.playWhenReady = false } + verify { mockExoPlayerPresenter.stopPlaying(any()) } + verify { mockPlayer.clearVideoSurface() } + verify { mockPlayer.release() } } @Test fun onBackPressedStopsAndReleasesVideoPlayerWhenBuffering() { - doReturn(Player.STATE_BUFFERING).whenever(mockPlayer).playbackState + every { mockPlayer.playbackState } returns Player.STATE_BUFFERING activity.onBackPressed() - verify(mockPlayer).playWhenReady = false - verify(mockExoPlayerPresenter).stopPlaying(anyOrNull()) - verify(mockPlayer).clearVideoSurface() - verify(mockPlayer).release() + verify { mockPlayer.playWhenReady = false } + verify { mockExoPlayerPresenter.stopPlaying(any()) } + verify { mockPlayer.clearVideoSurface() } + verify { mockPlayer.release() } } @Test fun onKeyCodeDownHandlesHomeEvent() { - doReturn(Player.STATE_BUFFERING).whenever(mockPlayer).playbackState + every { mockPlayer.playbackState } returns Player.STATE_BUFFERING val result = activity.onKeyDown(KeyEvent.KEYCODE_HOME, null) assertThat(result).isTrue() - verify(mockPlayer).playWhenReady = false - verify(mockExoPlayerPresenter).stopPlaying(anyOrNull()) - verify(mockPlayer).clearVideoSurface() - verify(mockPlayer).release() + + verify { mockPlayer.playWhenReady = false } + verify { mockExoPlayerPresenter.stopPlaying(any()) } + verify { mockPlayer.clearVideoSurface() } + verify { mockPlayer.release() } } override fun installTestModules() { - scope.installTestModules(TestingModule(), TestModule()) + scope.installTestModules(MockkTestingModule(), TestModule()) } inner class TestModule : Module() { @@ -215,7 +197,7 @@ open class ExoplayerVideoActivityTest : InjectingTest() { init { bind(ExoplayerPresenter::class.java).toInstance(mockExoPlayerPresenter) bind(DataSource.Factory::class.java).toInstance(mockDataSourceFactory) - bind(TrackSelector::class.java).toInstance(mockMappingTrackSelector) + bind(TrackSelector::class.java).toInstance(mockTrackSelector) bind(Logger::class.java).toInstance(mockLogger) bind(TimeUtil::class.java).toInstance(mockTimeUtil) } diff --git a/serenity-app/src/test/kotlin/us/nineworlds/serenity/ui/video/player/VideoKeyCodeHandlerDelegateTest.kt b/serenity-app/src/test/kotlin/us/nineworlds/serenity/ui/video/player/VideoKeyCodeHandlerDelegateTest.kt index a6d41d48f..b97aecb83 100644 --- a/serenity-app/src/test/kotlin/us/nineworlds/serenity/ui/video/player/VideoKeyCodeHandlerDelegateTest.kt +++ b/serenity-app/src/test/kotlin/us/nineworlds/serenity/ui/video/player/VideoKeyCodeHandlerDelegateTest.kt @@ -2,462 +2,485 @@ package us.nineworlds.serenity.ui.video.player import android.content.SharedPreferences import android.view.KeyEvent +import assertk.assertThat +import assertk.assertions.isFalse +import assertk.assertions.isTrue import com.google.android.exoplayer2.SimpleExoPlayer -import org.assertj.core.api.Java6Assertions.assertThat +import io.mockk.Runs +import io.mockk.clearAllMocks +import io.mockk.every +import io.mockk.just +import io.mockk.mockk +import io.mockk.verify import org.junit.After import org.junit.Before import org.junit.Test import org.junit.runner.RunWith -import org.mockito.ArgumentMatchers.anyLong -import org.mockito.ArgumentMatchers.anyString -import org.mockito.ArgumentMatchers.eq -import org.mockito.Mock -import org.mockito.Mockito.doNothing -import org.mockito.Mockito.doReturn -import org.mockito.Mockito.verify -import org.mockito.MockitoAnnotations.initMocks import org.robolectric.Robolectric import org.robolectric.RobolectricTestRunner import org.robolectric.annotation.LooperMode import toothpick.config.Module -import us.nineworlds.serenity.TestingModule +import us.nineworlds.serenity.MockkTestingModule import us.nineworlds.serenity.test.InjectingTest @RunWith(RobolectricTestRunner::class) -@LooperMode(LooperMode.Mode.LEGACY) class VideoKeyCodeHandlerDelegateTest : InjectingTest() { - @Mock - internal lateinit var mockPreferences: SharedPreferences - - @Mock - internal lateinit var mockMediaPlayer: SimpleExoPlayer - - @Mock - internal lateinit var mockPresenter: ExoplayerContract.ExoplayerPresenter - - lateinit var keyCodeHandler: VideoKeyCodeHandlerDelegate - - @Mock - lateinit var mockActivity: ExoplayerVideoActivity - - @Before - @Throws(Exception::class) - override fun setUp() { - Robolectric.getBackgroundThreadScheduler().pause() - Robolectric.getForegroundThreadScheduler().pause() - - initMocks(this) - super.setUp() - - doReturn("5000").`when`(mockPreferences).getString("osd_display_time", "5000") - - keyCodeHandler = VideoKeyCodeHandlerDelegate(mockMediaPlayer, mockActivity, mockPresenter) - } - - @After - fun tearDown() { - if (mockActivity != null) { - mockActivity!!.finish() - } - } - - @Test - fun handlesKeyCodeInfo() { - val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_INFO, null) - assertThat(result).isTrue() - } - - @Test - fun handlesKeyCodeInfoWhenMenuKeyIsPressed() { - val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_MENU, null) - assertThat(result).isTrue() - } - - @Test - fun handlesKeyCodeInfoWhenIIsPressed() { - val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_I, null) - assertThat(result).isTrue() - } - - @Test - fun HandlesKeyCodeInfoWhenGameControllerButtonYIsPressed() { - val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_BUTTON_Y, null) - assertThat(result).isTrue() - } - - @Test - fun handlesKeyCodePauseWhenMediaPlayerIsPlaying() { - demandMediaPause() - val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_MEDIA_PAUSE, - null) - assertThat(result).isTrue() - } - - @Test - fun handlesKeyCodePauseWhenMediaPlayerIsPlayingKeyCodeP() { - demandMediaPause() - val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_P, null) - assertThat(result).isTrue() - } - - @Test - fun handlesKeyCodePauseWhenMediaPlayerIsPlayingKeyCodeSpace() { - demandMediaPause() - val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_SPACE, null) - assertThat(result).isTrue() - } - - @Test - fun handlesKeyCodePauseWhenMediaPlayerIsPlayingKeyCodeButtonA() { - demandMediaPause() - val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_BUTTON_A, null) - assertThat(result).isTrue() - } - - @Test - fun handlesKeyCodePauseWhenMediaPlayerIsPlayingKeyCodeMediaPlayPause() { - demandMediaPause() - val result = keyCodeHandler.onKeyDown( - KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, null) - assertThat(result).isTrue() - } - - @Test - fun handlesKeyCodePauseWhenMediaPlayerIsNotPlaying() { - demandMediaPauseWhenNotPlaying() - val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_MEDIA_PAUSE, null) - assertThat(result).isTrue() - } - - @Test - fun handlesKeyCodePlayPauseWhenMediaPlayerIsNotPlaying() { - demandMediaPauseWhenNotPlaying() - val result = keyCodeHandler.onKeyDown( - KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, null) - assertThat(result).isTrue() - } - - @Test - fun handlesKeyCodeMediaNextQueueEntryIsPlaying() { - demandNextQueue() - doReturn("queue").`when`(mockPreferences).getString( - eq("next_prev_behavior"), anyString()) - - val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_MEDIA_NEXT, null) - assertThat(result).isTrue() - verify(mockPreferences).getString("next_prev_behavior", "queue") - } - - @Test - fun handlesKeyCodeMediaNextQueueEntryIsNotPlaying() { - doReturn("queue").`when`(mockPreferences).getString( - eq("next_prev_behavior"), anyString()) - val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_MEDIA_NEXT, null) - assertThat(result).isTrue() - verify(mockPreferences).getString("next_prev_behavior", "queue") - } - - @Test - fun handlesKeyCodeMediaNextByPercentatage() { - demandByPercentage() - val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_MEDIA_NEXT, null) - - assertThat(result).isTrue() - verify(mockPreferences).getString("next_prev_behavior", "queue") - verify(mockMediaPlayer).seekTo(20) - } - - @Test - fun handlesKeyCodeMediaNextBySecondsUnderDuration() { - demandBySeconds("2000", 1000L) - val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_MEDIA_NEXT, null) - - assertThat(result).isTrue() - verify(mockPreferences).getString("next_prev_behavior", "queue") - verify(mockMediaPlayer).seekTo(3000) - } - - @Test - fun handlesKeyCodeMediaNextBySecondsGreaterThanDuration() { - demandBySeconds("11000", 1000L) - val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_MEDIA_NEXT, null) - - assertThat(result).isTrue() - verify(mockPreferences).getString("next_prev_behavior", "queue") - verify(mockMediaPlayer).seekTo(9999) - } - - @Test - fun handlesKeyCodeMediaNextBySecondsLessThanZero() { - demandBySeconds("-11000", 1000L) - val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_MEDIA_NEXT, null) - - assertThat(result).isTrue() - verify(mockPreferences).getString("next_prev_behavior", "queue") - verify(mockMediaPlayer).seekTo(0) - } - - @Test - fun handlesKeyCodeMediaPreviousWhenUsingPercentage() { - doReturn("10%").`when`(mockPreferences).getString( - eq("next_prev_behavior"), anyString()) - doNothing().`when`(mockMediaPlayer).seekTo(anyLong()) - doReturn(10L).`when`(mockMediaPlayer).getCurrentPosition() - doReturn(100L).`when`(mockMediaPlayer).getDuration() - - val result = keyCodeHandler.onKeyDown( - KeyEvent.KEYCODE_MEDIA_PREVIOUS, null) - assertThat(result).isTrue() - verify(mockMediaPlayer).seekTo(0) - } - - @Test - fun handlesKeyCodeMediaPreviousWhenUsingDuration() { - doReturn("2000").`when`(mockPreferences).getString( - eq("next_prev_behavior"), anyString()) - doNothing().`when`(mockMediaPlayer).seekTo(anyLong()) - doReturn(9000L).`when`(mockMediaPlayer).getCurrentPosition() - doReturn(10000L).`when`(mockMediaPlayer).getDuration() - - val result = keyCodeHandler.onKeyDown( - KeyEvent.KEYCODE_MEDIA_PREVIOUS, null) - assertThat(result).isTrue() - verify(mockMediaPlayer).seekTo(7000) - } - - @Test - fun handlesKeyCodeMediaFastForwardReceived() { - doReturn("0").`when`(mockPreferences).getString(eq("skip_forward_time"), - anyString()) - doNothing().`when`(mockMediaPlayer).seekTo(anyLong()) - val result = keyCodeHandler.onKeyDown( - KeyEvent.KEYCODE_MEDIA_FAST_FORWARD, null) - assertThat(result).isTrue() - } - - @Test - fun handlesKeyCodeFReceivedSkipsForward() { - doReturn("0").`when`(mockPreferences).getString(eq("skip_forward_time"), - anyString()) - doNothing().`when`(mockMediaPlayer).seekTo(anyLong()) - val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_F, null) - assertThat(result).isTrue() - } - - @Test - fun handlesKeyCodeButtonR1ReceivedSkipsForward() { - doReturn("0").`when`(mockPreferences).getString(eq("skip_forward_time"), - anyString()) - doNothing().`when`(mockMediaPlayer).seekTo(anyLong()) - val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_BUTTON_R1, null) - assertThat(result).isTrue() - } - - @Test - fun handlesKeyCodeButtonR2ReceivedSkipsForward() { - doReturn("0").`when`(mockPreferences).getString(eq("skip_forward_time"), - anyString()) - doNothing().`when`(mockMediaPlayer).seekTo(anyLong()) - val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_BUTTON_R2, null) - assertThat(result).isTrue() - } - - @Test - fun handlesKeyCodeMediaRewindSkipsBack() { - doReturn("0").`when`(mockPreferences).getString(eq("skip_backward_time"), - anyString()) - doNothing().`when`(mockMediaPlayer).seekTo(anyLong()) - val result = keyCodeHandler.onKeyDown( - KeyEvent.KEYCODE_MEDIA_REWIND, null) - assertThat(result).isTrue() - } - - @Test - fun handlesKeyCodeRSkipsBack() { - doReturn("0").`when`(mockPreferences).getString(eq("skip_backward_time"), - anyString()) - doNothing().`when`(mockMediaPlayer).seekTo(anyLong()) - val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_R, null) - assertThat(result).isTrue() - } - - @Test - fun handlesKeyCodeButtonL1SkipsBack() { - doReturn("0").`when`(mockPreferences).getString(eq("skip_backward_time"), - anyString()) - doNothing().`when`(mockMediaPlayer).seekTo(anyLong()) - val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_BUTTON_L1, null) - assertThat(result).isTrue() - } - - @Test - fun handlesKeyCodeButtonL2SkipsBack() { - doReturn("0").`when`(mockPreferences).getString(eq("skip_backward_time"), - anyString()) - doNothing().`when`(mockMediaPlayer).seekTo(anyLong()) - val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_BUTTON_L2, null) - assertThat(result).isTrue() - } - - @Test - fun handlesKeyCodeMediaStopPausesCurrentlyPlayingVideo() { - val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_MEDIA_STOP, null) - assertThat(result).isTrue() - } - - @Test - fun handlesKeyCodeMediaStopPausesCurrentlyPlayingVideoWhenMediaControllerNotShowingShowsMediaController() { - val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_MEDIA_STOP, null) - assertThat(result).isTrue() - } - - @Test - fun handlesKeyCodeMediaStopWhenMediaControllerShowing() { - val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_MEDIA_STOP, null) - assertThat(result).isTrue() - } - - @Test - fun handlesKeyCodeMediaStopWhenMediaControllerIsNotPlaying() { - val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_MEDIA_STOP, null) - assertThat(result).isTrue() - } - - @Test - fun handlesKeyCodeSPausesCurrentlyPlayingVideo() { - val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_S, null) - assertThat(result).isTrue() - } - - @Test - fun handlesKeyCode1ForSkipByPercentage() { - doReturn(1000L).`when`(mockMediaPlayer).duration - val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_1, null) - assertThat(result).isTrue() - verify(mockMediaPlayer).seekTo(100L) - } - - @Test - fun handlesKeyCode2ForSkipByPercentage() { - doReturn(1000L).`when`(mockMediaPlayer).duration - val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_2, null) - assertThat(result).isTrue() - verify(mockMediaPlayer).seekTo(200L) - } - - @Test - fun handlesKeyCode3ForSkipByPercentage() { - doReturn(1000L).`when`(mockMediaPlayer).duration - val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_3, null) - assertThat(result).isTrue() - verify(mockMediaPlayer).seekTo(300L) - } - - @Test - fun handlesKeyCode4ForSkipByPercentage() { - doReturn(1000L).`when`(mockMediaPlayer).duration - val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_4, null) - assertThat(result).isTrue() - verify(mockMediaPlayer).seekTo(400L) - } - - @Test - fun handlesKeyCode5ForSkipByPercentage() { - doReturn(1000L).`when`(mockMediaPlayer).duration - val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_5, null) - assertThat(result).isTrue() - verify(mockMediaPlayer).seekTo(500L) - } - - @Test - fun handlesKeyCode6ForSkipByPercentage() { - doReturn(1000L).`when`(mockMediaPlayer).duration - val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_6, null) - assertThat(result).isTrue() - verify(mockMediaPlayer).seekTo(600L) - } - - @Test - fun handlesKeyCode7ForSkipByPercentage() { - doReturn(1000L).`when`(mockMediaPlayer).getDuration() - val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_7, null) - assertThat(result).isTrue() - verify(mockMediaPlayer).seekTo(700L) - } - - @Test - fun handlesKeyCode8ForSkipByPercentage() { - doReturn(1000L).`when`(mockMediaPlayer).getDuration() - val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_8, null) - assertThat(result).isTrue() - verify(mockMediaPlayer).seekTo(800L) - } - - @Test - fun handlesKeyCode9ForSkipByPercentage() { - doReturn(1000L).`when`(mockMediaPlayer).getDuration() - val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_9, null) - assertThat(result).isTrue() - verify(mockMediaPlayer).seekTo(900L) - } - - @Test - fun handlesKeyCode0RestartsAtBeginning() { - doReturn(1000L).`when`(mockMediaPlayer).getDuration() - val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_0, null) - assertThat(result).isTrue() - verify(mockMediaPlayer).seekTo(0L) - } - - @Test - fun unhandledKeyCodeReturnsFalse() { - val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_AT, null) - assertThat(result).isFalse() - } - - private fun demandBySeconds(seconds: String, currentPosition: Long) { - doReturn(seconds).`when`(mockPreferences).getString( - eq("next_prev_behavior"), anyString()) - doReturn(currentPosition).`when`(mockMediaPlayer).getCurrentPosition() - doReturn(10000L).`when`(mockMediaPlayer).getDuration() - doNothing().`when`(mockMediaPlayer).seekTo(anyLong()) - } - - private fun demandByPercentage() { - doReturn("10%").`when`(mockPreferences).getString( - eq("next_prev_behavior"), anyString()) - doReturn(10L).`when`(mockMediaPlayer).currentPosition - doReturn(100L).`when`(mockMediaPlayer).duration - doNothing().`when`(mockMediaPlayer).seekTo(anyLong()) - } - - private fun demandNextQueue() { - doNothing().`when`(mockMediaPlayer).stop() - } - - private fun demandMediaPause() { - } - - private fun demandMediaPauseWhenNotPlaying() { - } - - @Test - fun handlesKeyCodeInfoWhenMediaPlayerControllerIsShowing() { - val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_INFO, null) - assertThat(result).isTrue() - } - - override fun installTestModules() { - scope.installTestModules(TestingModule(), TestModule()) - } - - inner class TestModule : Module() { - - init { - bind(SharedPreferences::class.java).toInstance(mockPreferences) - } - } + companion object { + private val mockPreferences = mockk(relaxed = true) + private val mockMediaPlayer = mockk(relaxed = true) + private val mockPresenter = mockk(relaxed = true) + private val mockActivity = mockk(relaxed = true) + } + + private lateinit var keyCodeHandler: VideoKeyCodeHandlerDelegate + + @Before + @Throws(Exception::class) + override fun setUp() { + clearAllMocks() + + super.setUp() + + every { mockPreferences.getString("osd_display_time", "5000") } returns "5000" + + keyCodeHandler = VideoKeyCodeHandlerDelegate(mockMediaPlayer, mockActivity, mockPresenter) + } + + @After + fun tearDown() { + mockActivity.finish() + } + + @Test + fun handlesKeyCodeInfo() { + val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_INFO, null) + assertThat(result).isTrue() + } + + @Test + fun handlesKeyCodeInfoWhenMenuKeyIsPressed() { + val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_MENU, null) + assertThat(result).isTrue() + } + + @Test + fun handlesKeyCodeInfoWhenIIsPressed() { + val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_I, null) + assertThat(result).isTrue() + } + + @Test + fun handlesKeyCodeInfoWhenGameControllerButtonYIsPressed() { + val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_BUTTON_Y, null) + assertThat(result).isTrue() + } + + @Test + fun handlesKeyCodePauseWhenMediaPlayerIsPlaying() { + demandMediaPause() + val result = keyCodeHandler.onKeyDown( + KeyEvent.KEYCODE_MEDIA_PAUSE, + null + ) + assertThat(result).isTrue() + } + + @Test + fun handlesKeyCodePauseWhenMediaPlayerIsPlayingKeyCodeP() { + demandMediaPause() + val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_P, null) + assertThat(result).isTrue() + } + + @Test + fun handlesKeyCodePauseWhenMediaPlayerIsPlayingKeyCodeSpace() { + demandMediaPause() + val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_SPACE, null) + assertThat(result).isTrue() + } + + @Test + fun handlesKeyCodePauseWhenMediaPlayerIsPlayingKeyCodeButtonA() { + demandMediaPause() + val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_BUTTON_A, null) + assertThat(result).isTrue() + } + + @Test + fun handlesKeyCodePauseWhenMediaPlayerIsPlayingKeyCodeMediaPlayPause() { + demandMediaPause() + val result = keyCodeHandler.onKeyDown( + KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, null + ) + assertThat(result).isTrue() + } + + @Test + fun handlesKeyCodePauseWhenMediaPlayerIsNotPlaying() { + demandMediaPauseWhenNotPlaying() + val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_MEDIA_PAUSE, null) + assertThat(result).isTrue() + } + + @Test + fun handlesKeyCodePlayPauseWhenMediaPlayerIsNotPlaying() { + demandMediaPauseWhenNotPlaying() + val result = keyCodeHandler.onKeyDown( + KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, null + ) + assertThat(result).isTrue() + } + + @Test + fun handlesKeyCodeMediaNextQueueEntryIsPlaying() { + demandNextQueue() + every { mockPreferences.getString("next_prev_behavior", any()) } returns "queue" + + val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_MEDIA_NEXT, null) + + assertThat(result).isTrue() + verify { mockPreferences.getString("next_prev_behavior", "queue") } + } + + @Test + fun handlesKeyCodeMediaNextQueueEntryIsNotPlaying() { + every { mockPreferences.getString("next_prev_behavior", any()) } returns "queue" + + val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_MEDIA_NEXT, null) + + assertThat(result).isTrue() + verify { mockPreferences.getString("next_prev_behavior", "queue") } + } + + @Test + fun handlesKeyCodeMediaNextByPercentatage() { + demandByPercentage() + val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_MEDIA_NEXT, null) + + assertThat(result).isTrue() + verify { mockPreferences.getString("next_prev_behavior", "queue") } + verify { mockMediaPlayer.seekTo(20) } + } + + @Test + fun handlesKeyCodeMediaNextBySecondsUnderDuration() { + demandBySeconds("2000", 1000L) + val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_MEDIA_NEXT, null) + + assertThat(result).isTrue() + + verify { mockPreferences.getString("next_prev_behavior", "queue") } + verify { mockMediaPlayer.seekTo(3000) } + } + + @Test + fun handlesKeyCodeMediaNextBySecondsGreaterThanDuration() { + demandBySeconds("11000", 1000L) + val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_MEDIA_NEXT, null) + + assertThat(result).isTrue() + + verify { mockPreferences.getString("next_prev_behavior", "queue") } + verify { mockMediaPlayer.seekTo(9999) } + } + + @Test + fun handlesKeyCodeMediaNextBySecondsLessThanZero() { + demandBySeconds("-11000", 1000L) + val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_MEDIA_NEXT, null) + + assertThat(result).isTrue() + + verify { mockPreferences.getString("next_prev_behavior", "queue") } + verify { mockMediaPlayer.seekTo(0) } + } + + @Test + fun handlesKeyCodeMediaPreviousWhenUsingPercentage() { + every { mockPreferences.getString("next_prev_behavior", any()) } returns "10%" + every { mockMediaPlayer.seekTo(any()) } just Runs + every { mockMediaPlayer.currentPosition } returns 10L + every { mockMediaPlayer.duration } returns 100L + + val result = keyCodeHandler.onKeyDown( + KeyEvent.KEYCODE_MEDIA_PREVIOUS, null + ) + assertThat(result).isTrue() + + verify { mockMediaPlayer.seekTo(0) } + } + + @Test + fun handlesKeyCodeMediaPreviousWhenUsingDuration() { + every { mockPreferences.getString(eq("next_prev_behavior"), any()) } returns "2000" + every { mockMediaPlayer.seekTo(any()) } just Runs + every { mockMediaPlayer.currentPosition } returns 9000L + every { mockMediaPlayer.duration } returns 10000L + + val result = keyCodeHandler.onKeyDown( + KeyEvent.KEYCODE_MEDIA_PREVIOUS, null + ) + assertThat(result).isTrue() + + verify { mockMediaPlayer.seekTo(7000) } + } + + @Test + fun handlesKeyCodeMediaFastForwardReceived() { + every { mockPreferences.getString(eq("skip_forward_time"), any()) } returns "0" + every { mockMediaPlayer.seekTo(any()) } just Runs + + val result = keyCodeHandler.onKeyDown( + KeyEvent.KEYCODE_MEDIA_FAST_FORWARD, null + ) + assertThat(result).isTrue() + } + + @Test + fun handlesKeyCodeFReceivedSkipsForward() { + every { mockPreferences.getString(eq("skip_forward_time"), any()) } returns "0" + every { mockMediaPlayer.seekTo(any()) } just Runs + + val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_F, null) + + assertThat(result).isTrue() + } + + @Test + fun handlesKeyCodeButtonR1ReceivedSkipsForward() { + every { mockPreferences.getString(eq("skip_forward_time"), any()) } returns "0" + every { mockMediaPlayer.seekTo(any()) } just Runs + + val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_BUTTON_R1, null) + + assertThat(result).isTrue() + } + + @Test + fun handlesKeyCodeButtonR2ReceivedSkipsForward() { + every { mockPreferences.getString(eq("skip_forward_time"), any()) } returns "0" + every { mockMediaPlayer.seekTo(any()) } just Runs + + val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_BUTTON_R2, null) + + assertThat(result).isTrue() + } + + @Test + fun handlesKeyCodeMediaRewindSkipsBack() { + every { mockPreferences.getString(eq("skip_backward_time"), any()) } returns "0" + every { mockMediaPlayer.seekTo(any()) } just Runs + + val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_MEDIA_REWIND, null) + + assertThat(result).isTrue() + } + + @Test + fun handlesKeyCodeRSkipsBack() { + every { mockPreferences.getString(eq("skip_backward_time"), any()) } returns "0" + every { mockMediaPlayer.seekTo(any()) } just Runs + + val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_R, null) + + assertThat(result).isTrue() + } + + @Test + fun handlesKeyCodeButtonL1SkipsBack() { + every { mockPreferences.getString(eq("skip_backward_time"), any()) } returns "0" + every { mockMediaPlayer.seekTo(any()) } just Runs + + val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_BUTTON_L1, null) + + assertThat(result).isTrue() + } + + @Test + fun handlesKeyCodeButtonL2SkipsBack() { + every { mockPreferences.getString(eq("skip_backward_time"), any()) } returns "0" + every { mockMediaPlayer.seekTo(any()) } just Runs + + val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_BUTTON_L2, null) + + assertThat(result).isTrue() + } + + @Test + fun handlesKeyCodeMediaStopPausesCurrentlyPlayingVideo() { + val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_MEDIA_STOP, null) + assertThat(result).isTrue() + } + + @Test + fun handlesKeyCodeMediaStopPausesCurrentlyPlayingVideoWhenMediaControllerNotShowingShowsMediaController() { + val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_MEDIA_STOP, null) + assertThat(result).isTrue() + } + + @Test + fun handlesKeyCodeMediaStopWhenMediaControllerShowing() { + val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_MEDIA_STOP, null) + assertThat(result).isTrue() + } + + @Test + fun handlesKeyCodeMediaStopWhenMediaControllerIsNotPlaying() { + val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_MEDIA_STOP, null) + assertThat(result).isTrue() + } + + @Test + fun handlesKeyCodeSPausesCurrentlyPlayingVideo() { + val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_S, null) + assertThat(result).isTrue() + } + + @Test + fun handlesKeyCode1ForSkipByPercentage() { + every { mockMediaPlayer.duration } returns 1000L + + val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_1, null) + + assertThat(result).isTrue() + verify { mockMediaPlayer.seekTo(100L) } + } + + @Test + fun handlesKeyCode2ForSkipByPercentage() { + every { mockMediaPlayer.duration } returns 1000L + + val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_2, null) + + assertThat(result).isTrue() + verify { mockMediaPlayer.seekTo(200L) } + } + + @Test + fun handlesKeyCode3ForSkipByPercentage() { + every { mockMediaPlayer.duration } returns 1000L + + val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_3, null) + + assertThat(result).isTrue() + verify { mockMediaPlayer.seekTo(300L) } + } + + @Test + fun handlesKeyCode4ForSkipByPercentage() { + every { mockMediaPlayer.duration } returns 1000L + + val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_4, null) + + assertThat(result).isTrue() + verify { mockMediaPlayer.seekTo(400L) } + } + + @Test + fun handlesKeyCode5ForSkipByPercentage() { + every { mockMediaPlayer.duration } returns 1000L + val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_5, null) + assertThat(result).isTrue() + verify { mockMediaPlayer.seekTo(500L) } + } + + @Test + fun handlesKeyCode6ForSkipByPercentage() { + every { mockMediaPlayer.duration } returns 1000L + + val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_6, null) + + assertThat(result).isTrue() + verify { mockMediaPlayer.seekTo(600L) } + } + + @Test + fun handlesKeyCode7ForSkipByPercentage() { + every { mockMediaPlayer.duration } returns 1000L + + val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_7, null) + + assertThat(result).isTrue() + verify { mockMediaPlayer.seekTo(700L) } + } + + @Test + fun handlesKeyCode8ForSkipByPercentage() { + every { mockMediaPlayer.duration } returns 1000L + + val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_8, null) + + assertThat(result).isTrue() + verify { mockMediaPlayer.seekTo(800L) } + } + + @Test + fun handlesKeyCode9ForSkipByPercentage() { + every { mockMediaPlayer.duration } returns 1000L // Assuming getDuration() is a getter for duration property + + val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_9, null) + + assertThat(result).isTrue() + verify { mockMediaPlayer.seekTo(900L) } + } + + @Test + fun handlesKeyCode0RestartsAtBeginning() { + every { mockMediaPlayer.duration } returns 1000L // Assuming getDuration() is a getter for duration property + + val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_0, null) + + assertThat(result).isTrue() + verify { mockMediaPlayer.seekTo(0L) } + } + + @Test + fun unhandledKeyCodeReturnsFalse() { + val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_AT, null) + assertThat(result).isFalse() + } + + private fun demandBySeconds(seconds: String, currentPosition: Long) { + every { mockPreferences.getString(eq("next_prev_behavior"), any()) } returns seconds + every { mockMediaPlayer.currentPosition } returns currentPosition + every { mockMediaPlayer.duration } returns 10000L + every { mockMediaPlayer.seekTo(any()) } just Runs + } + + private fun demandByPercentage() { + every { mockPreferences.getString(eq("next_prev_behavior"), any()) } returns "10%" + every { mockMediaPlayer.currentPosition } returns 10L + every { mockMediaPlayer.duration } returns 100L + every { mockMediaPlayer.seekTo(any()) } just Runs + } + + private fun demandNextQueue() { + every { mockMediaPlayer.stop() } just Runs + } + + private fun demandMediaPause() { + } + + private fun demandMediaPauseWhenNotPlaying() { + } + + @Test + fun handlesKeyCodeInfoWhenMediaPlayerControllerIsShowing() { + val result = keyCodeHandler.onKeyDown(KeyEvent.KEYCODE_INFO, null) + assertThat(result).isTrue() + } + + override fun installTestModules() { + scope.installTestModules(MockkTestingModule(), TestModule()) + } + + inner class TestModule : Module() { + + init { + bind(SharedPreferences::class.java).toInstance(mockPreferences) + } + } }