Skip to content

Commit

Permalink
test: add deeplink tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Divinelink committed Jul 12, 2024
1 parent f1cacf0 commit 9a4b059
Show file tree
Hide file tree
Showing 16 changed files with 375 additions and 60 deletions.
4 changes: 2 additions & 2 deletions app/src/main/kotlin/com/andreolas/movierama/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class MainActivity : ComponentActivity() {

setContent {
val darkTheme = shouldUseDarkTheme(
uiState = viewModel.viewState.collectAsState().value,
uiState = viewModel.uiState.collectAsState().value,
selectedTheme = viewModel.theme.collectAsState().value,
)

Expand All @@ -42,7 +42,7 @@ class MainActivity : ComponentActivity() {
blackBackground = viewModel.blackBackgrounds.collectAsState().value,
) {
MovieApp(
uiState = viewModel.viewState.collectAsState().value,
uiState = viewModel.uiState.collectAsState().value,
uiEvent = viewModel.uiEvent.collectAsState().value,
onConsumeEvent = viewModel::consumeUiEvent,
)
Expand Down
31 changes: 18 additions & 13 deletions app/src/main/kotlin/com/andreolas/movierama/MainViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.andreolas.movierama
import androidx.lifecycle.ViewModel
import com.andreolas.movierama.ui.ThemedActivityDelegate
import com.divinelink.core.commons.extensions.extractDetailsFromDeepLink
import com.divinelink.core.model.media.MediaType
import com.divinelink.feature.details.ui.DetailsNavArguments
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
Expand All @@ -14,9 +15,9 @@ class MainViewModel @Inject constructor(themedActivityDelegate: ThemedActivityDe
ViewModel(),
ThemedActivityDelegate by themedActivityDelegate {

private val _viewState: MutableStateFlow<MainUiState> =
private val _uiState: MutableStateFlow<MainUiState> =
MutableStateFlow(MainUiState.Completed)
val viewState: StateFlow<MainUiState> = _viewState
val uiState: StateFlow<MainUiState> = _uiState

private val _uiEvent: MutableStateFlow<MainUiEvent> = MutableStateFlow(MainUiEvent.None)
val uiEvent: StateFlow<MainUiEvent> = _uiEvent
Expand All @@ -32,15 +33,19 @@ class MainViewModel @Inject constructor(themedActivityDelegate: ThemedActivityDe
fun handleDeepLink(url: String?) {
val (id, mediaType) = url.extractDetailsFromDeepLink() ?: return

updateUiEvent(
MainUiEvent.NavigateToDetails(
DetailsNavArguments(
id = id,
mediaType = mediaType,
isFavorite = false,
if (MediaType.from(mediaType) != MediaType.UNKNOWN) {
updateUiEvent(
MainUiEvent.NavigateToDetails(
DetailsNavArguments(
id = id,
mediaType = mediaType,
isFavorite = false,
),
),
),
)
)
} else {
updateUiEvent(MainUiEvent.None)
}
}

/**
Expand All @@ -58,14 +63,14 @@ class MainViewModel @Inject constructor(themedActivityDelegate: ThemedActivityDe
}
private fun setRemoteConfig() {
_viewState.value = MainViewState.Loading
_uiState.value = MainViewState.Loading
viewModelScope.launch {
val result = setRemoteConfigUseCase.invoke(Unit)
if (result.isSuccess) {
_viewState.value = MainViewState.Completed
_uiState.value = MainViewState.Completed
} else {
_viewState.value = MainViewState.Error(
_uiState.value = MainViewState.Error(
UIText.StringText("Something went wrong. Trying again..."),
)
}
Expand Down
2 changes: 0 additions & 2 deletions app/src/main/kotlin/com/andreolas/movierama/ui/MovieApp.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.andreolas.movierama.ui

import android.annotation.SuppressLint
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Icon
Expand Down Expand Up @@ -34,7 +33,6 @@ import com.ramcosta.composedestinations.utils.navGraph
import com.ramcosta.composedestinations.utils.rememberDestinationsNavigator

@Composable
@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
fun MovieApp(
uiState: MainUiState,
uiEvent: MainUiEvent,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.andreolas.movierama.main.ui

import com.andreolas.movierama.MainUiEvent
import com.andreolas.movierama.MainUiState
import com.andreolas.movierama.MainViewModel
import com.andreolas.movierama.fakes.usecase.FakeSetRemoteConfigUseCase
Expand All @@ -23,8 +24,20 @@ class MainViewModelRobot {
)
}

fun assertViewState(expectedViewState: MainUiState) = apply {
assertThat(viewModel.viewState.value).isEqualTo(expectedViewState)
fun onHandleDeeplink(uri: String?) = apply {
viewModel.handleDeepLink(uri)
}

fun onConsumeUiEvent() = apply {
viewModel.consumeUiEvent()
}

fun assertUiState(expectedUiState: MainUiState) = apply {
assertThat(viewModel.uiState.value).isEqualTo(expectedUiState)
}

fun assertUiEvent(expectedUiEvent: MainUiEvent) = apply {
assertThat(viewModel.uiEvent.value).isEqualTo(expectedUiEvent)
}

fun mockSetRemoteConfigResult(result: Unit) = apply {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.andreolas.movierama.main.ui

import com.andreolas.movierama.MainUiEvent
import com.andreolas.movierama.MainUiState
import com.divinelink.core.testing.MainDispatcherRule
import com.divinelink.feature.details.ui.DetailsNavArguments
import org.junit.Rule
import org.junit.Test

Expand All @@ -17,11 +19,87 @@ class MainViewModelTest {
robot
.mockSetRemoteConfigResult(Unit)
.buildViewModel()
.assertViewState(
.assertUiState(
MainUiState.Completed,
)
}

@Test
fun `test handleDeepLink with movie deeplink`() {
val url = "https://www.themoviedb.org/movie/693134-dune-part-two"

robot
.buildViewModel()
.assertUiEvent(MainUiEvent.None)
.onHandleDeeplink(url)
.assertUiEvent(
MainUiEvent.NavigateToDetails(
DetailsNavArguments(
id = 693134,
mediaType = "movie",
isFavorite = false,
),
),
)
.onConsumeUiEvent()
.assertUiEvent(MainUiEvent.None)
}

@Test
fun `test handleDeepLink with tv deeplink`() {
val url = "https://www.themoviedb.org/tv/693134-dune-part-two"

robot
.buildViewModel()
.assertUiEvent(MainUiEvent.None)
.onHandleDeeplink(url)
.assertUiEvent(
MainUiEvent.NavigateToDetails(
DetailsNavArguments(
id = 693134,
mediaType = "tv",
isFavorite = false,
),
),
)
.onConsumeUiEvent()
.assertUiEvent(MainUiEvent.None)
}

@Test
fun `test handleDeepLink with person deeplink`() {
val url = "https://www.themoviedb.org/person/693134-dune-part-two"

robot
.buildViewModel()
.assertUiEvent(MainUiEvent.None)
.onHandleDeeplink(url)
.assertUiEvent(
MainUiEvent.NavigateToDetails(
DetailsNavArguments(
id = 693134,
mediaType = "person",
isFavorite = false,
),
),
)
.onConsumeUiEvent()
.assertUiEvent(MainUiEvent.None)
}

@Test
fun `test handleDeepLink with invalid deeplink`() {
val url = "https://www.themoviedb.org/invalid/693134-dune-part-two"

robot
.buildViewModel()
.assertUiEvent(MainUiEvent.None)
.onHandleDeeplink(url)
.assertUiEvent(MainUiEvent.None)
.onConsumeUiEvent()
.assertUiEvent(MainUiEvent.None)
}

// @Test
// fun errorTest() {
// robot
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ import androidx.compose.ui.test.onNodeWithContentDescription
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import com.divinelink.core.testing.ComposeTest
import com.divinelink.core.testing.getString
import com.divinelink.core.testing.navigator.FakeDestinationsNavigator
import com.divinelink.feature.settings.R
import com.divinelink.feature.settings.app.SettingsScreen
import com.divinelink.feature.settings.screens.destinations.AccountSettingsScreenDestination
import com.divinelink.feature.settings.screens.destinations.AppearanceSettingsScreenDestination
import com.divinelink.feature.settings.screens.destinations.HelpSettingsScreenDestination
import com.divinelink.feature.settings.screens.destinations.LinkHandlingSettingsScreenDestination
import com.divinelink.feature.settings.screens.destinations.SettingsScreenDestination
import org.junit.Test
import com.divinelink.core.ui.R as uiR
Expand Down Expand Up @@ -79,6 +81,33 @@ class SettingsScreenTest : ComposeTest() {
)
}

@Test
fun `test navigate to link handling screen`() {
val destinationsNavigator = FakeDestinationsNavigator()

destinationsNavigator.navigate(
direction = SettingsScreenDestination(),
)

composeTestRule.setContent {
SettingsScreen(
navigator = destinationsNavigator,
)
}

val linkHandlingSetting = getString(R.string.feature_settings_link_handling)

with(composeTestRule) {
onNodeWithText(linkHandlingSetting).assertExists()

onNodeWithText(linkHandlingSetting).performClick()
}

destinationsNavigator.verifyNavigatedToDirection(
LinkHandlingSettingsScreenDestination,
)
}

@Test
fun `test navigate to help screen`() {
val destinationsNavigator = FakeDestinationsNavigator()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.divinelink.core.commons

object ApiConstants {
const val TMDB_URL = BuildConfig.TMDB_BASE_URL
const val TMDB_IMAGE_URL = BuildConfig.TMDB_IMAGE_URL
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.divinelink.core.commons

interface BuildConfigProvider {
val isDebug: Boolean
val buildType: String
}

object DefaultBuildConfigProvider : BuildConfigProvider {
override val isDebug: Boolean = BuildConfig.DEBUG
override val buildType: String = BuildConfig.BUILD_TYPE
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.divinelink.core.commons.util

import android.content.Context
import android.content.Intent
import android.net.Uri
import android.provider.Settings
import androidx.core.content.ContextCompat.startActivity

object AppSettingsUtil {
private const val PACKAGE_SCHEME = "package"

fun openAppDetails(context: Context) {
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
data = Uri.fromParts(PACKAGE_SCHEME, context.packageName, null)
}
startActivity(context, intent, null)

Check warning on line 16 in core/commons/src/main/kotlin/com/divinelink/core/commons/util/AppSettingsUtil.kt

View check run for this annotation

Codecov / codecov/patch

core/commons/src/main/kotlin/com/divinelink/core/commons/util/AppSettingsUtil.kt#L13-L16

Added lines #L13 - L16 were not covered by tests
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.divinelink.core.commons.extensions

import com.google.common.truth.Truth.assertThat
import org.junit.Test

class StringExtensionsTest {

@Test
fun `test extractDetailsFromDeeplink with valid url`() {
val url = "https://www.themoviedb.org/tv/693134-dune-part-two"

val result = url.extractDetailsFromDeepLink()

val expected = Pair(693134, "tv")
assertThat(expected).isEqualTo(result)
}

@Test
fun `test extractDetailsFromDeeplink with invalid url`() {
val url = "https://www.themoviedb.org/tv/"

val result = url.extractDetailsFromDeepLink()

assertThat(result).isNull()
}
}
6 changes: 6 additions & 0 deletions core/ui/src/main/kotlin/com/divinelink/core/ui/TestTags.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ object TestTags {
const val SCROLL_TO_TOP_BUTTON = "SCROLL_TO_TOP_BUTTON_TAG"
const val LOADING_PROGRESS = "Loading Progress Bar"

const val LAZY_COLUMN = "Lazy Column"

object Details {
const val YOUR_RATING = "Details Your Rating"
const val RATE_DIALOG = "Details Rate Dialog"
Expand Down Expand Up @@ -53,6 +55,10 @@ object TestTags {
const val JELLYSEERR_LOGIN_BUTTON = "Jellyseerr Login Button"
const val JELLYSEERR_LOGOUT_BUTTON = "Jellyseerr Logout Button"
}

object LinkHandling {
const val DIRECTIONS_TEXT = "Link Handling Directions"
}
}

object Menu {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import com.divinelink.core.commons.BuildConfig
import com.divinelink.core.commons.BuildConfigProvider
import com.divinelink.core.commons.DefaultBuildConfigProvider
import com.divinelink.core.ui.UIText
import com.divinelink.core.ui.getString
import com.divinelink.feature.settings.R
Expand All @@ -16,15 +18,18 @@ import com.divinelink.core.commons.R as commonR

@Composable
@Destination<SettingsGraph>
fun HelpSettingsScreen(navigator: DestinationsNavigator) {
fun HelpSettingsScreen(
navigator: DestinationsNavigator,
buildConfigProvider: BuildConfigProvider = DefaultBuildConfigProvider,
) {
SettingsScaffold(
title = stringResource(id = R.string.HelpSettingsFragment__help),
onNavigationClick = navigator::navigateUp,
) { paddingValues ->

val version = UIText.ResourceText(commonR.string.version_name)

val buildVersion = if (BuildConfig.DEBUG) {
val buildVersion = if (buildConfigProvider.isDebug) {
UIText.StringText(version.getString() + " ${BuildConfig.BUILD_TYPE}")
} else {
version
Expand Down
Loading

0 comments on commit 9a4b059

Please sign in to comment.