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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class FilmPosterTest {
title = "Test Film",
releaseYear = "2020",
onClick = {},
onRerollClick = {},
)
}

Expand All @@ -80,6 +81,7 @@ class FilmPosterTest {
title = "Test Film",
releaseYear = "2020",
onClick = {},
onRerollClick = {},
)
}

Expand All @@ -105,6 +107,7 @@ class FilmPosterTest {
title = "Inception",
releaseYear = "2010",
onClick = { clicked = true },
onRerollClick = {},
)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.randomboxd.feature.random_film.presentation

import android.graphics.Bitmap
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.assertIsNotEnabled
import androidx.compose.ui.test.junit4.createComposeRule
Expand All @@ -10,13 +11,20 @@ import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performTextInput
import androidx.compose.ui.test.performTouchInput
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import coil3.ImageLoader
import coil3.SingletonImageLoader
import coil3.annotation.DelicateCoilApi
import coil3.asImage
import coil3.test.FakeImageLoaderEngine
import com.nacchofer31.randomboxd.core.domain.DataError
import com.nacchofer31.randomboxd.random_film.domain.model.Film
import com.nacchofer31.randomboxd.random_film.domain.model.FilmGenre
import com.nacchofer31.randomboxd.random_film.domain.model.UserName
import com.nacchofer31.randomboxd.random_film.presentation.RandomFilmScreen
import com.nacchofer31.randomboxd.random_film.presentation.RandomFilmScreenRoot
import kotlinx.coroutines.flow.MutableStateFlow
import org.junit.After
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
Expand All @@ -26,6 +34,20 @@ class RandomFilmScreenTest {
@get:Rule
val composeTestRule = createComposeRule()

private val context get() = InstrumentationRegistry.getInstrumentation().targetContext

@After
@OptIn(DelicateCoilApi::class)
fun resetImageLoader() {
SingletonImageLoader.reset()
}

private fun setImageLoader(engine: FakeImageLoaderEngine) {
SingletonImageLoader.setSafe {
ImageLoader.Builder(context).components { add(engine) }.build()
}
}

@Test
fun all_random_film_screen_initial_components_should_be_displayed() {
composeTestRule.setContent {
Expand Down Expand Up @@ -222,4 +244,72 @@ class RandomFilmScreenTest {

composeTestRule.onNodeWithTag("test-random-film-genre-badge").assertDoesNotExist()
}

@Test
fun reroll_button_click_triggers_reroll_action() {
val bitmap = Bitmap.createBitmap(200, 200, Bitmap.Config.ARGB_8888)
setImageLoader(
FakeImageLoaderEngine
.Builder()
.default(bitmap.asImage())
.build(),
)

var rerollClicked = false
composeTestRule.setContent {
val mutableUserNamesFlow = MutableStateFlow<List<UserName>>(emptyList())
RandomFilmScreen(
userNameList = mutableUserNamesFlow,
resultFilm =
Film(
slug = "test-slug",
name = "test-name",
releaseYear = 2000,
imageUrl = "test-image-url",
),
) { action ->
if (action is com.nacchofer31.randomboxd.random_film.presentation.viewmodel.RandomFilmAction.OnRerollClicked) {
rerollClicked = true
}
}
}

composeTestRule.waitForIdle()
composeTestRule.onNodeWithTag("test-reroll-button").performClick()
assert(rerollClicked)
}

@Test
fun film_poster_click_triggers_film_clicked_action() {
val bitmap = Bitmap.createBitmap(200, 200, Bitmap.Config.ARGB_8888)
setImageLoader(
FakeImageLoaderEngine
.Builder()
.default(bitmap.asImage())
.build(),
)

var filmClicked = false
composeTestRule.setContent {
val mutableUserNamesFlow = MutableStateFlow<List<UserName>>(emptyList())
RandomFilmScreen(
userNameList = mutableUserNamesFlow,
resultFilm =
Film(
slug = "test-slug",
name = "test-name",
releaseYear = 2000,
imageUrl = "test-image-url",
),
) { action ->
if (action is com.nacchofer31.randomboxd.random_film.presentation.viewmodel.RandomFilmAction.OnFilmClicked) {
filmClicked = true
}
}
}

composeTestRule.waitForIdle()
composeTestRule.onNodeWithTag("test-film-poster").performClick()
assert(filmClicked)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,5 @@
<string name="onboarding_genre_feature3">يعمل مع وضع المستخدم الواحد ووضع متعدد المستخدمين</string>
<string name="rolling_the_dice">جاري رمي النرد...</string>
<string name="finding_random_movie">جاري البحث عن فيلمك العشوائي</string>
<string name="reroll">إعادة الرمي</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,5 @@
<string name="onboarding_genre_feature3">Funciona amb els modes d\'un sol usuari i multiusuari</string>
<string name="rolling_the_dice">Llançant els daus...</string>
<string name="finding_random_movie">Trobar la teva pel·lícula aleatòria</string>
<string name="reroll">Tornar a tirar</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,5 @@
<string name="onboarding_genre_feature3">Funktioniert im Einzel- und Mehrbenutzermodus</string>
<string name="rolling_the_dice">Würfel rollen...</string>
<string name="finding_random_movie">Finde deinen zufälligen Film</string>
<string name="reroll">Neu würfeln</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,5 @@
<string name="onboarding_genre_feature3">Funciona con los modos de un solo usuario y multiusuario</string>
<string name="rolling_the_dice">Lanzando los dados...</string>
<string name="finding_random_movie">Encontrando tu película aleatoria</string>
<string name="reroll">Tirar de nuevo</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,5 @@
<string name="onboarding_genre_feature3">Fonctionne avec les modes utilisateur unique et multi-utilisateur</string>
<string name="rolling_the_dice">Lancement des dés...</string>
<string name="finding_random_movie">Trouver votre film aléatoire</string>
<string name="reroll">Relancer</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,5 @@
<string name="onboarding_genre_feature3">Funciona cos modos de usuario único e multiusuario</string>
<string name="rolling_the_dice">Lanzando os dados...</string>
<string name="finding_random_movie">Atopando o teu filme aleatorio</string>
<string name="reroll">Tirar de novo</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,5 @@
<string name="onboarding_genre_feature3">एकल उपयोगकर्ता और बहु-उपयोगकर्ता मोड दोनों के साथ काम करता है</string>
<string name="rolling_the_dice">पासा फेंक रहे हैं...</string>
<string name="finding_random_movie">आपकी यादृच्छिक फिल्म खोज रहे हैं</string>
<string name="reroll">फिर से फेंकें</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,5 @@
<string name="onboarding_genre_feature3">Funziona con le modalità utente singolo e multiutente</string>
<string name="rolling_the_dice">Lanciando i dadi...</string>
<string name="finding_random_movie">Trovare il tuo film casuale</string>
<string name="reroll">Rilancia</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,5 @@
<string name="onboarding_genre_feature3">シングルユーザーとマルチユーザーモードの両方で動作</string>
<string name="rolling_the_dice">サイコロを振っています...</string>
<string name="finding_random_movie">ランダム映画を探しています</string>
<string name="reroll">もう一度振る</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,5 @@
<string name="onboarding_genre_feature3">Funciona nos modos de usuário único e multiusuário</string>
<string name="rolling_the_dice">Lançando os dados...</string>
<string name="finding_random_movie">Encontrando seu filme aleatório</string>
<string name="reroll">Rolar novamente</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,5 @@
<string name="onboarding_genre_feature3">Работает в режимах одного и нескольких пользователей</string>
<string name="rolling_the_dice">Бросаем кубики...</string>
<string name="finding_random_movie">Ищем ваш случайный фильм</string>
<string name="reroll">Перебросить</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,5 @@
<string name="onboarding_genre_feature3">适用于单用户和多用户模式</string>
<string name="rolling_the_dice">掷骰子中...</string>
<string name="finding_random_movie">正在寻找您的随机电影</string>
<string name="reroll">重新掷骰</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,5 @@
<string name="onboarding_genre_feature3">Works with single user and multi-user modes</string>
<string name="rolling_the_dice">Rolling the dice...</string>
<string name="finding_random_movie">Finding your random movie</string>
<string name="reroll">Reroll</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -35,29 +35,27 @@ class RandomFilmScrappingRepository(
const val FILM_SCRIPT_QUERY = """script[type="application/ld+json"]"""
}

override suspend fun getRandomMovie(
override suspend fun getRandomMovies(
userName: String,
selectedGenres: Set<FilmGenre>,
): ResultData<Film, DataError.Remote> =
): ResultData<Set<Film>, DataError.Remote> =
withContext(Dispatchers.IO) {
val filmsResult = getFilmsFromUserWatchlist(userName, selectedGenres)
val films =
when (filmsResult) {
when (val filmsResult = getFilmsFromUserWatchlist(userName, selectedGenres)) {
is ResultData.Success -> filmsResult.data
is ResultData.Error -> return@withContext ResultData.Error(filmsResult.error)
}

if (films.isEmpty()) return@withContext ResultData.Error(DataError.Remote.NO_RESULTS)

val chosenFilm = films.random()
extractFilm(chosenFilm)
return@withContext ResultData.Success(films.toSet())
}

override suspend fun getRandomMoviesFromSearchList(
searchList: Set<String>,
filmSearchMode: FilmSearchMode,
selectedGenres: Set<FilmGenre>,
): ResultData<Film, DataError.Remote> =
): ResultData<Set<Film>, DataError.Remote> =
withContext(Dispatchers.IO) {
if (searchList.isEmpty()) return@withContext ResultData.Error(DataError.Remote.SERIALIZATION)

Expand Down Expand Up @@ -88,10 +86,11 @@ class RandomFilmScrappingRepository(

if (combinedFilms.isEmpty()) return@withContext ResultData.Error(DataError.Remote.NO_RESULTS)

val chosenFilm = combinedFilms.random()
extractFilm(chosenFilm)
return@withContext ResultData.Success(combinedFilms)
}

override suspend fun extractResultMovie(film: Film): ResultData<Film, DataError.Remote> = extractFilm(film)

private suspend fun getFilmsFromUserWatchlist(
userName: String,
selectedGenres: Set<FilmGenre> = emptySet(),
Expand All @@ -118,9 +117,8 @@ class RandomFilmScrappingRepository(
val films = mutableListOf<Film>()
for (page in 1..totalPages) {
val pageUrl = "$baseUrl/page/$page/"
val htmlResult = getWebPage(pageUrl)
val html =
when (htmlResult) {
when (val htmlResult = getWebPage(pageUrl)) {
is ResultData.Success -> htmlResult.data
is ResultData.Error -> return ResultData.Error(htmlResult.error)
}
Expand Down Expand Up @@ -156,21 +154,23 @@ class RandomFilmScrappingRepository(
return ResultData.Success(films)
}

private suspend fun extractFilm(film: Film): ResultData<Film, DataError.Remote> {
val posterResult = getPosterFromFilmPage(film.slug)
val finalImageUrl =
when (posterResult) {
is ResultData.Success -> posterResult.data.ifEmpty { film.imageUrl }
is ResultData.Error -> film.imageUrl
}
private suspend fun extractFilm(film: Film): ResultData<Film, DataError.Remote> =
try {
val finalImageUrl =
when (val posterResult = getPosterFromFilmPage(film.slug)) {
is ResultData.Success -> posterResult.data.ifEmpty { film.imageUrl }
is ResultData.Error -> film.imageUrl
}

return ResultData.Success(
film.copy(
imageUrl = finalImageUrl,
slug = RandomBoxdEndpoints.filmSlugUrl(film.slug),
),
)
}
ResultData.Success(
film.copy(
imageUrl = finalImageUrl,
slug = RandomBoxdEndpoints.filmSlugUrl(film.slug),
),
)
} catch (_: Exception) {
ResultData.Error(DataError.Remote.SERIALIZATION)
}

private fun buildPosterUrl(
filmId: String,
Expand All @@ -182,9 +182,8 @@ class RandomFilmScrappingRepository(

private suspend fun getPosterFromFilmPage(slug: String): ResultData<String, DataError.Remote> {
val url = RandomBoxdEndpoints.filmSlugUrl(slug)
val htmlResult = getWebPage(url)
val html =
when (htmlResult) {
when (val htmlResult = getWebPage(url)) {
is ResultData.Success -> htmlResult.data
is ResultData.Error -> return ResultData.Error(htmlResult.error)
}
Expand All @@ -207,9 +206,8 @@ class RandomFilmScrappingRepository(
}

private suspend fun getTotalPages(url: String): Int {
val htmlResult = getWebPage(url)
val html =
when (htmlResult) {
when (val htmlResult = getWebPage(url)) {
is ResultData.Success -> htmlResult.data
is ResultData.Error -> return 1
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,18 @@ import com.nacchofer31.randomboxd.random_film.domain.model.FilmGenre
import com.nacchofer31.randomboxd.random_film.domain.model.FilmSearchMode

interface RandomFilmRepository {
suspend fun getRandomMovie(
suspend fun getRandomMovies(
userName: String,
selectedGenres: Set<FilmGenre> = emptySet(),
): ResultData<Film, DataError.Remote>
): ResultData<Set<Film>, DataError.Remote>

suspend fun getRandomMoviesFromSearchList(
searchList: Set<String>,
filmSearchMode: FilmSearchMode = FilmSearchMode.INTERSECTION,
selectedGenres: Set<FilmGenre> = emptySet(),
): ResultData<Set<Film>, DataError.Remote>

suspend fun extractResultMovie(
film: Film,
): ResultData<Film, DataError.Remote>
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,8 @@ internal fun FilmDisplay(
onClick = {
onAction(RandomFilmAction.OnFilmClicked(film))
},
onRerollClick = {
onAction(RandomFilmAction.OnRerollClicked)
},
)
}
Loading
Loading