From 6222b24df63ecbca181c475a94671bdffedc82ee Mon Sep 17 00:00:00 2001 From: Phillip Thelen Date: Fri, 13 Jan 2023 12:05:29 +0100 Subject: [PATCH] Fix some tests --- Habitica/res/layout/activity_main_content.xml | 1 + Habitica/res/values/strings.xml | 1 + .../ui/fragments/PartyDetailFragmentTest.kt | 4 +- .../ui/fragments/StatsFragmentTest.kt | 15 +- .../inventory/stable/PetDetailFragmentTest.kt | 28 +- .../stable/StableRecyclerFragmentTest.kt | 6 +- .../android/habitica/data/TaskRepository.kt | 1 + .../data/implementation/TaskRepositoryImpl.kt | 2 + .../ui/activities/BirthdayActivity.kt | 489 ++++++++++-------- .../social/guilds/GuildDetailFragment.kt | 2 +- .../implementation/TaskRepositoryImplTest.kt | 93 ++-- 11 files changed, 330 insertions(+), 312 deletions(-) diff --git a/Habitica/res/layout/activity_main_content.xml b/Habitica/res/layout/activity_main_content.xml index 08a09a097..3203655ea 100644 --- a/Habitica/res/layout/activity_main_content.xml +++ b/Habitica/res/layout/activity_main_content.xml @@ -96,6 +96,7 @@ app:layout_collapseMode="pin" app:tabGravity="fill" app:tabIndicatorColor="?textColorPrimary" + app:tabSelectedTextColor="?textColorPrimary" app:tabMode="fixed" /> 20 Gems Background Birthday Set + You equipped %s You diff --git a/Habitica/src/androidTest/java/com/habitrpg/android/habitica/ui/fragments/PartyDetailFragmentTest.kt b/Habitica/src/androidTest/java/com/habitrpg/android/habitica/ui/fragments/PartyDetailFragmentTest.kt index e0933e63e..82687b6de 100644 --- a/Habitica/src/androidTest/java/com/habitrpg/android/habitica/ui/fragments/PartyDetailFragmentTest.kt +++ b/Habitica/src/androidTest/java/com/habitrpg/android/habitica/ui/fragments/PartyDetailFragmentTest.kt @@ -17,7 +17,7 @@ import io.github.kakaocup.kakao.text.KTextView import io.mockk.every import io.mockk.mockk import io.mockk.spyk -import io.reactivex.rxjava3.core.Flowable +import kotlinx.coroutines.flow.flowOf import org.junit.Test import org.junit.runner.RunWith @@ -38,7 +38,7 @@ class PartyDetailFragmentTest : FragmentTestCase() { @@ -35,12 +37,12 @@ class PetDetailScreen : Screen() { internal class PetDetailRecyclerFragmentTest : FragmentTestCase(false) { override fun makeFragment() { - every { inventoryRepository.getOwnedPets() } returns Flowable.just(user.items?.pets!!) - every { inventoryRepository.getOwnedMounts() } returns Flowable.just(user.items?.mounts!!) - every { inventoryRepository.getOwnedItems("food") } returns Flowable.just(user.items?.food!!.filter { it.numberOwned > 0 }) + every { inventoryRepository.getOwnedPets() } returns flowOf(user.items?.pets!!) + every { inventoryRepository.getOwnedMounts() } returns flowOf(user.items?.mounts!!) + every { inventoryRepository.getOwnedItems("food") } returns flowOf(user.items?.food!!.filter { it.numberOwned > 0 }) val saddle = OwnedItem() saddle.numberOwned = 1 - every { inventoryRepository.getOwnedItems(true) } returns Flowable.just( + every { inventoryRepository.getOwnedItems(true) } returns flowOf( mapOf( Pair( "Saddle-food", @@ -69,21 +71,21 @@ internal class PetDetailRecyclerFragmentTest : @Test fun canFeedPet() { val slot = CapturingSlot() - every { feedPetUseCase.callInteractor(capture(slot)) } returns mockk(relaxed = true) + coEvery { feedPetUseCase.callInteractor(capture(slot)) } returns mockk(relaxed = true) every { inventoryRepository.getPets( any(), any(), any() ) - } returns Flowable.just(content.pets.filter { it.animal == "Cactus" }) + } returns flowOf(content.pets.filter { it.animal == "Cactus" }) every { inventoryRepository.getMounts( any(), any(), any() ) - } returns Flowable.just(content.mounts.filter { it.animal == "Cactus" }) + } returns flowOf(content.mounts.filter { it.animal == "Cactus" }) launchFragment( PetDetailRecyclerFragmentArgs.Builder("cactus", "drop", "").build().toBundle() ) @@ -92,7 +94,7 @@ internal class PetDetailRecyclerFragmentTest : childWith { withContentDescription("Skeleton Cactus") }.click() KView { withText(R.string.feed) }.click() KView { withText("Meat") }.click() - verify { feedPetUseCase.callInteractor(any()) } + coVerify { feedPetUseCase.callInteractor(any()) } slot.captured.pet.key shouldBe "Cactus-Skeleton" slot.captured.food.key shouldBe "Meat" } @@ -102,27 +104,27 @@ internal class PetDetailRecyclerFragmentTest : @Test fun canUseSaddle() { val slot = CapturingSlot() - every { feedPetUseCase.callInteractor(capture(slot)) } returns mockk(relaxed = true) + coEvery { feedPetUseCase.callInteractor(capture(slot)) } returns mockk(relaxed = true) every { inventoryRepository.getPets( any(), any(), any() ) - } returns Flowable.just(content.pets.filter { it.animal == "Fox" }) + } returns flowOf(content.pets.filter { it.animal == "Fox" }) every { inventoryRepository.getMounts( any(), any(), any() ) - } returns Flowable.just(content.mounts.filter { it.animal == "Fox" }) + } returns flowOf(content.mounts.filter { it.animal == "Fox" }) launchFragment(PetDetailRecyclerFragmentArgs.Builder("fox", "drop", "").build().toBundle()) screen { recycler { childWith { withContentDescription("Shade Fox") }.click() KView { withText(R.string.use_saddle) }.click() - verify { feedPetUseCase.callInteractor(any()) } + coVerify { feedPetUseCase.callInteractor(any()) } slot.captured.pet.key shouldBe "Fox-Shade" slot.captured.food.key shouldBe "Saddle" } diff --git a/Habitica/src/androidTest/java/com/habitrpg/android/habitica/ui/fragments/inventory/stable/StableRecyclerFragmentTest.kt b/Habitica/src/androidTest/java/com/habitrpg/android/habitica/ui/fragments/inventory/stable/StableRecyclerFragmentTest.kt index 11e44c7d8..fcfbee05a 100644 --- a/Habitica/src/androidTest/java/com/habitrpg/android/habitica/ui/fragments/inventory/stable/StableRecyclerFragmentTest.kt +++ b/Habitica/src/androidTest/java/com/habitrpg/android/habitica/ui/fragments/inventory/stable/StableRecyclerFragmentTest.kt @@ -15,7 +15,7 @@ import io.github.kakaocup.kakao.text.KTextView import io.mockk.every import io.mockk.spyk import io.mockk.verify -import io.reactivex.rxjava3.core.Flowable +import kotlinx.coroutines.flow.flowOf import org.hamcrest.Matcher import org.junit.Test @@ -40,8 +40,8 @@ class StableScreen : Screen() { internal class StableRecyclerFragmentTest : FragmentTestCase(false) { override fun makeFragment() { - every { inventoryRepository.getOwnedPets() } returns Flowable.just(user.items?.pets!!) - every { inventoryRepository.getOwnedMounts() } returns Flowable.just(user.items?.mounts!!) + every { inventoryRepository.getOwnedPets() } returns flowOf(user.items?.pets!!) + every { inventoryRepository.getOwnedMounts() } returns flowOf(user.items?.mounts!!) fragment = spyk() fragment.shouldInitializeComponent = false fragment.itemType = "pets" diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/TaskRepository.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/TaskRepository.kt index b768f2623..b0d8a7676 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/TaskRepository.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/TaskRepository.kt @@ -68,4 +68,5 @@ interface TaskRepository : BaseRepository { fun getTasksForChallenge(challengeID: String?): Flow> suspend fun bulkScoreTasks(data: List>): BulkTaskScoringData? suspend fun markTaskNeedsWork(task: Task, userID: String) + } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/TaskRepositoryImpl.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/TaskRepositoryImpl.kt index c08f94933..bb752f7a7 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/TaskRepositoryImpl.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/TaskRepositoryImpl.kt @@ -196,7 +196,9 @@ class TaskRepositoryImpl( override suspend fun markTaskNeedsWork(task: Task, userID: String) { val savedTask = apiClient.markTaskNeedsWork(task.id ?: "", userID) if (savedTask != null) { + savedTask.id = task.id savedTask.position = task.position + savedTask.group?.assignedUsersDetail?.firstOrNull { it.assignedUserID == userID }?.completed = false localRepository.save(savedTask) } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/BirthdayActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/BirthdayActivity.kt index e3805a069..26fe4e7d4 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/BirthdayActivity.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/BirthdayActivity.kt @@ -1,6 +1,7 @@ package com.habitrpg.android.habitica.ui.activities import android.app.Activity +import android.content.res.Configuration.UI_MODE_NIGHT_YES import android.os.Bundle import androidx.activity.compose.setContent import androidx.compose.foundation.Image @@ -20,9 +21,16 @@ import androidx.compose.foundation.verticalScroll import androidx.compose.material.Button import androidx.compose.material.ButtonDefaults import androidx.compose.material.CircularProgressIndicator +import androidx.compose.material.DrawerState +import androidx.compose.material.DrawerValue import androidx.compose.material.ProvideTextStyle +import androidx.compose.material.Scaffold +import androidx.compose.material.ScaffoldState +import androidx.compose.material.SnackbarHostState import androidx.compose.material.Text +import androidx.compose.material.rememberScaffoldState import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.mutableStateOf import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -49,6 +57,7 @@ import androidx.compose.ui.unit.sp import androidx.lifecycle.lifecycleScope import coil.compose.AsyncImage import com.android.billingclient.api.ProductDetails +import com.google.accompanist.systemuicontroller.rememberSystemUiController import com.habitrpg.android.habitica.R import com.habitrpg.android.habitica.components.UserComponent import com.habitrpg.android.habitica.data.InventoryRepository @@ -81,6 +90,7 @@ class BirthdayActivity : BaseActivity() { @Inject lateinit var configManager: AppConfigManager + val scaffoldState: ScaffoldState = ScaffoldState(DrawerState(DrawerValue.Closed), SnackbarHostState()) private val isPurchasing = mutableStateOf(false) private val price = mutableStateOf("") private val hasGryphatrice = mutableStateOf(false) @@ -94,6 +104,7 @@ class BirthdayActivity : BaseActivity() { setContent { HabiticaTheme { BirthdayActivityView( + scaffoldState, isPurchasing.value, hasGryphatrice.value, price.value, @@ -114,12 +125,13 @@ class BirthdayActivity : BaseActivity() { userRepository.retrieveUser(false, true) isPurchasing.value = false } - }, - { - lifecycleScope.launchCatching { - inventoryRepository.equip("pet", "Gryphatrice-Jubilant") - } - }) + } + ) { + lifecycleScope.launchCatching { + inventoryRepository.equip("pet", "Gryphatrice-Jubilant") + scaffoldState.snackbarHostState.showSnackbar(getString(R.string.you_equipped_x, getString(R.string.animated_gryphatrice_pet))) + } + } } } @@ -177,6 +189,7 @@ fun BirthdayTitle(text: String) { @Composable fun BirthdayActivityView( + scaffoldState: ScaffoldState, isPurchasing: Boolean, hasGryphatrice: Boolean, price: String, @@ -191,250 +204,269 @@ fun BirthdayActivityView( val textColor = Color.White val specialTextColor = colorResource(R.color.yellow_50) - Column( - horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier - .background( - Brush.verticalGradient( - Pair(0.0f, colorResource(id = R.color.brand_300)), - Pair(1.0f, colorResource(id = R.color.brand_200)) - ) - ) - .fillMaxWidth() - .verticalScroll(rememberScrollState()) - ) { - Button( - onClick = { - if (activity != null) { - activity.finish() - return@Button - } - MainNavigationController.navigateBack() - }, - colors = ButtonDefaults.textButtonColors(contentColor = textColor), - elevation = ButtonDefaults.elevation(0.dp, 0.dp), - modifier = Modifier.align(Alignment.Start) - ) { - Image( - painterResource(R.drawable.arrow_back), - stringResource(R.string.action_back), - colorFilter = ColorFilter.tint( - textColor - ) - ) - } + val systemUiController = rememberSystemUiController() + val statusbarColor = colorResource(R.color.brand_300) + val navigationbarColor = colorResource(R.color.brand_50) + DisposableEffect(systemUiController) { + systemUiController.setStatusBarColor(statusbarColor, darkIcons = false) + systemUiController.setNavigationBarColor(navigationbarColor) + onDispose {} + } + + Scaffold( + scaffoldState = scaffoldState + ) { padding -> Column( horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier - .padding(horizontal = 20.dp) - .fillMaxWidth() - ) { - Image( - painterResource(R.drawable.birthday_header), - null, - Modifier.padding(bottom = 8.dp) - ) - Row(verticalAlignment = Alignment.CenterVertically) { - Image(painterResource(R.drawable.birthday_gifts), null) - Column( - horizontalAlignment = Alignment.CenterHorizontally, - modifier = Modifier.padding(horizontal = 22.dp) - ) { - Text( - stringResource(id = R.string.limited_event).toUpperCase(Locale.current), - fontSize = 12.sp, - color = specialTextColor, - fontWeight = FontWeight.Bold + .background( + Brush.verticalGradient( + Pair(0.0f, colorResource(id = R.color.brand_300)), + Pair(1.0f, colorResource(id = R.color.brand_200)) ) + ) + .fillMaxWidth() + .verticalScroll(rememberScrollState()) + .padding(padding) + ) { + Button( + onClick = { + if (activity != null) { + activity.finish() + return@Button + } + MainNavigationController.navigateBack() + }, + colors = ButtonDefaults.textButtonColors(contentColor = textColor), + elevation = ButtonDefaults.elevation(0.dp, 0.dp), + modifier = Modifier.align(Alignment.Start) + ) { + Image( + painterResource(R.drawable.arrow_back), + stringResource(R.string.action_back), + colorFilter = ColorFilter.tint( + textColor + ) + ) + } + Column( + horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier + .padding(horizontal = 20.dp) + .fillMaxWidth() + ) { + Image( + painterResource(R.drawable.birthday_header), + null, + Modifier.padding(bottom = 8.dp) + ) + Row(verticalAlignment = Alignment.CenterVertically) { + Image(painterResource(R.drawable.birthday_gifts), null) + Column( + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier.padding(horizontal = 22.dp) + ) { + Text( + stringResource(id = R.string.limited_event).toUpperCase(Locale.current), + fontSize = 12.sp, + color = specialTextColor, + fontWeight = FontWeight.Bold + ) + Text( + stringResource( + R.string.x_to_y, + dateFormat.format(startDate), + dateFormat.format(endDate) + ), + fontSize = 12.sp, + color = textColor, + fontWeight = FontWeight.Bold + ) + } + // right image should be flipped + Image( + painterResource(id = R.drawable.birthday_gifts), + null, + modifier = Modifier.scale(-1f, 1f) + ) + } + Text( + stringResource(R.string.birthday_title_description), + fontSize = 16.sp, + color = specialTextColor, + fontWeight = FontWeight.SemiBold, + textAlign = TextAlign.Center, + modifier = Modifier.padding(top = 22.dp) + ) + BirthdayTitle(stringResource(id = R.string.animated_gryphatrice_pet)) + Box( + Modifier + .size(161.dp, 129.dp) + .padding(vertical = 20.dp) + .background(colorResource(R.color.brand_50), RoundedCornerShape(8.dp)) + ) { + + } + Text( + stringResource(R.string.limited_edition).toUpperCase(Locale.current), + fontSize = 12.sp, + color = specialTextColor, + fontWeight = FontWeight.Bold + ) + Text( + stringResource(R.string.gryphatrice_description), + fontSize = 16.sp, + color = textColor, + textAlign = TextAlign.Center, + lineHeight = 20.sp, + modifier = Modifier.padding(bottom = 16.dp) + ) + if (hasGryphatrice) { Text( - stringResource( - R.string.x_to_y, - dateFormat.format(startDate), - dateFormat.format(endDate) - ), + stringResource(R.string.thanks_for_support), fontSize = 12.sp, color = textColor, - fontWeight = FontWeight.Bold + fontWeight = FontWeight.SemiBold ) + HabiticaButton( + Color.White, + colorResource(R.color.brand_200), + { + onEquipClick() + }, + modifier = Modifier.padding(top = 20.dp) + ) { + Text(stringResource(R.string.equip)) + } + } else if (isPurchasing) { + CircularProgressIndicator() + } else { + Text(buildAnnotatedString { + append("Buy for ") + withStyle(SpanStyle(fontWeight = FontWeight.Bold)) { + append(price) + } + append(" or ") + withStyle(SpanStyle(fontWeight = FontWeight.Bold)) { + append("60 Gems") + } + }, color = Color.White) + HabiticaButton( + Color.White, + colorResource(R.color.brand_200), + { + onPurchaseClick() + }, + modifier = Modifier.padding(top = 20.dp) + ) { + Text(stringResource(R.string.buy_for_x, price)) + } + HabiticaButton( + Color.White, + colorResource(R.color.brand_200), + { + onGemPurchaseClick() + }, + modifier = Modifier.padding(top = 20.dp) + ) { + Row(verticalAlignment = Alignment.CenterVertically) { + Text(stringResource(R.string.buy_for)) + CurrencyText(currency = "gems", value = 60) + } + } } - // right image should be flipped - Image( - painterResource(id = R.drawable.birthday_gifts), - null, - modifier = Modifier.scale(-1f, 1f) - ) - } - Text( - stringResource(R.string.birthday_title_description), - fontSize = 16.sp, - color = specialTextColor, - fontWeight = FontWeight.SemiBold, - textAlign = TextAlign.Center, - modifier = Modifier.padding(top = 22.dp) - ) - BirthdayTitle(stringResource(id = R.string.animated_gryphatrice_pet)) - Box( - Modifier - .size(161.dp, 129.dp) - .padding(vertical = 20.dp) - .background(colorResource(R.color.brand_50), RoundedCornerShape(8.dp)) - ) { - - } - Text( - stringResource(R.string.limited_edition).toUpperCase(Locale.current), - fontSize = 12.sp, - color = specialTextColor, - fontWeight = FontWeight.Bold - ) - Text( - stringResource(R.string.gryphatrice_description), - fontSize = 16.sp, - color = textColor, - textAlign = TextAlign.Center, - lineHeight = 20.sp, - modifier = Modifier.padding(bottom = 16.dp) - ) - if (hasGryphatrice) { + BirthdayTitle(stringResource(id = R.string.plenty_of_potions)) Text( - stringResource(R.string.thanks_for_support), - fontSize = 12.sp, + stringResource(R.string.plenty_of_potions_description), + fontSize = 16.sp, color = textColor, - fontWeight = FontWeight.SemiBold + textAlign = TextAlign.Center, + lineHeight = 20.sp ) - HabiticaButton( - Color.White, - colorResource(R.color.brand_200), - {}, - modifier = Modifier.padding(top = 20.dp) - ) { - Text(stringResource(R.string.equip)) - } - } else if (isPurchasing) { - CircularProgressIndicator() - } else { - Text(buildAnnotatedString { - append("Buy for ") - withStyle(SpanStyle(fontWeight = FontWeight.Bold)) { - append(price) - } - append(" or ") - withStyle(SpanStyle(fontWeight = FontWeight.Bold)) { - append("60 Gems") - } - }, color = Color.White) + PotionGrid() HabiticaButton( Color.White, colorResource(R.color.brand_200), { - onPurchaseClick() + MainScope().launchCatching { + activity?.finish() + delay(500) + MainNavigationController.navigate(R.id.marketFragment) + } }, modifier = Modifier.padding(top = 20.dp) ) { - Text(stringResource(R.string.buy_for_x, "")) + Text(stringResource(R.string.visit_the_market)) } - HabiticaButton( - Color.White, - colorResource(R.color.brand_200), - { - onGemPurchaseClick() - }, - modifier = Modifier.padding(top = 20.dp) + BirthdayTitle(stringResource(id = R.string.for_for_free)) + Text( + stringResource(R.string.for_for_free_description), + fontSize = 16.sp, + color = textColor, + textAlign = TextAlign.Center, + lineHeight = 20.sp + ) + Column( + verticalArrangement = Arrangement.spacedBy(14.dp), + modifier = Modifier.padding(vertical = 20.dp) ) { - Row(verticalAlignment = Alignment.CenterVertically) { - Text(stringResource(R.string.buy_for)) - CurrencyText(currency = "gems", value = 60) + Row( + horizontalArrangement = Arrangement.spacedBy(14.dp), + modifier = Modifier.fillMaxWidth() + ) { + FourFreeItem( + day = 1, + title = stringResource(R.string.a_party_robe), + imageName = "", + modifier = Modifier.weight(1f) + ) + FourFreeItem( + day = 1, + title = stringResource(R.string.twenty_gems), + imageName = "", + modifier = Modifier.weight(1f) + ) + } + Row( + horizontalArrangement = Arrangement.spacedBy(14.dp), + modifier = Modifier.fillMaxWidth() + ) { + FourFreeItem( + day = 5, + title = stringResource(R.string.birthday_set), + imageName = "", + modifier = Modifier.weight(1f) + ) + FourFreeItem( + day = 10, + title = stringResource(R.string.background), + imageName = "", + modifier = Modifier.weight(1f) + ) } } } - BirthdayTitle(stringResource(id = R.string.plenty_of_potions)) - Text( - stringResource(R.string.plenty_of_potions_description), - fontSize = 16.sp, - color = textColor, - textAlign = TextAlign.Center, - lineHeight = 20.sp - ) - PotionGrid() - HabiticaButton( - Color.White, - colorResource(R.color.brand_200), - { - MainScope().launchCatching { - activity?.finish() - delay(500) - MainNavigationController.navigate(R.id.marketFragment) - } - }, - modifier = Modifier.padding(top = 20.dp) + Column( + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier + .padding(top = 20.dp) + .background(colorResource(R.color.brand_50)) + .padding(horizontal = 20.dp) + .padding(top = 20.dp, bottom = 60.dp) ) { - Text(stringResource(R.string.visit_the_market)) + Text( + stringResource(R.string.limitations), + fontSize = 16.sp, + color = colorResource(R.color.brand_600), + fontWeight = FontWeight.Bold, + textAlign = TextAlign.Center + ) + Text( + stringResource(R.string.birthday_limitations), + fontSize = 14.sp, + color = colorResource(R.color.brand_600), + lineHeight = 20.sp, + textAlign = TextAlign.Center + ) } - BirthdayTitle(stringResource(id = R.string.for_for_free)) - Text( - stringResource(R.string.for_for_free_description), - fontSize = 16.sp, - color = textColor, - textAlign = TextAlign.Center, - lineHeight = 20.sp - ) - Column(verticalArrangement = Arrangement.spacedBy(14.dp), modifier = Modifier.padding(vertical = 20.dp)) { - Row( - horizontalArrangement = Arrangement.spacedBy(14.dp), - modifier = Modifier.fillMaxWidth() - ) { - FourFreeItem( - day = 1, - title = stringResource(R.string.a_party_robe), - imageName = "", - modifier = Modifier.weight(1f) - ) - FourFreeItem( - day = 1, - title = stringResource(R.string.twenty_gems), - imageName = "", - modifier = Modifier.weight(1f) - ) - } - Row( - horizontalArrangement = Arrangement.spacedBy(14.dp), - modifier = Modifier.fillMaxWidth() - ) { - FourFreeItem( - day = 5, - title = stringResource(R.string.birthday_set), - imageName = "", - modifier = Modifier.weight(1f) - ) - FourFreeItem( - day = 10, - title = stringResource(R.string.background), - imageName = "", - modifier = Modifier.weight(1f) - ) - } - } - } - Column( - horizontalAlignment = Alignment.CenterHorizontally, - modifier = Modifier - .padding(top = 20.dp) - .background(colorResource(R.color.brand_50)) - .padding(horizontal = 20.dp) - .padding(top = 20.dp, bottom = 60.dp) - ) { - Text( - stringResource(R.string.limitations), - fontSize = 16.sp, - color = colorResource(R.color.brand_600), - fontWeight = FontWeight.Bold, - textAlign = TextAlign.Center - ) - Text( - stringResource(R.string.birthday_limitations), - fontSize = 14.sp, - color = colorResource(R.color.brand_600), - lineHeight = 20.sp, - textAlign = TextAlign.Center - ) } } } @@ -532,9 +564,10 @@ fun HabiticaButton( } @Preview(device = Devices.PIXEL_4) +@Preview(device = Devices.PIXEL_4, uiMode = UI_MODE_NIGHT_YES) @Composable private fun Preview() { - BirthdayActivityView(true, false, "", Date(), Date(), { - - }, {}, {}) + val scaffoldState = rememberScaffoldState() + BirthdayActivityView(scaffoldState, true, false, "", Date(), Date(), { + }, {}) {} } \ No newline at end of file diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/guilds/GuildDetailFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/guilds/GuildDetailFragment.kt index c06830de5..4559e8305 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/guilds/GuildDetailFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/guilds/GuildDetailFragment.kt @@ -199,7 +199,7 @@ class GuildDetailFragment : BaseFragment() { binding?.guildSummary?.setMarkdown(guild?.summary) binding?.guildDescription?.setMarkdown(guild?.description) - binding?.inviteButton?.isVisible = guild?.isGroupPlan == true + binding?.inviteButton?.isVisible = guild?.isGroupPlan != true } companion object { diff --git a/Habitica/src/test/java/com/habitrpg/android/habitica/data/implementation/TaskRepositoryImplTest.kt b/Habitica/src/test/java/com/habitrpg/android/habitica/data/implementation/TaskRepositoryImplTest.kt index bfa0ada14..8c03c44d4 100644 --- a/Habitica/src/test/java/com/habitrpg/android/habitica/data/implementation/TaskRepositoryImplTest.kt +++ b/Habitica/src/test/java/com/habitrpg/android/habitica/data/implementation/TaskRepositoryImplTest.kt @@ -4,27 +4,27 @@ import com.habitrpg.android.habitica.data.ApiClient import com.habitrpg.android.habitica.data.TaskRepository import com.habitrpg.android.habitica.data.local.TaskLocalRepository import com.habitrpg.android.habitica.models.BaseObject -import com.habitrpg.shared.habitica.models.responses.TaskDirectionData -import com.habitrpg.shared.habitica.models.responses.TaskScoringResult import com.habitrpg.android.habitica.models.tasks.Task import com.habitrpg.android.habitica.models.tasks.TaskList -import com.habitrpg.shared.habitica.models.tasks.TaskType -import com.habitrpg.shared.habitica.models.tasks.TasksOrder import com.habitrpg.android.habitica.models.user.Stats import com.habitrpg.android.habitica.models.user.User +import com.habitrpg.shared.habitica.models.responses.TaskDirectionData +import com.habitrpg.shared.habitica.models.tasks.TaskType +import com.habitrpg.shared.habitica.models.tasks.TasksOrder import io.kotest.common.ExperimentalKotest import io.kotest.core.spec.style.WordSpec import io.kotest.framework.concurrency.eventually import io.kotest.matchers.shouldBe import io.mockk.clearAllMocks +import io.mockk.coEvery +import io.mockk.coVerify import io.mockk.every import io.mockk.mockk import io.mockk.slot import io.mockk.spyk import io.mockk.verify -import io.reactivex.rxjava3.core.Flowable -import io.reactivex.subscribers.TestSubscriber import io.realm.Realm +import kotlinx.coroutines.flow.flowOf import java.util.UUID @OptIn(ExperimentalKotest::class) @@ -52,12 +52,10 @@ class TaskRepositoryImplTest : WordSpec({ "retrieveTasks" should { "save tasks locally" { val list = TaskList() - every { apiClient.tasks } returns Flowable.just(list) + coEvery { apiClient.getTasks() } returns list every { localRepository.saveTasks("", any(), any()) } returns Unit val order = TasksOrder() - val subscriber = TestSubscriber() - repository.retrieveTasks("", order).subscribe(subscriber) - subscriber.assertComplete() + repository.retrieveTasks("", order) verify { localRepository.saveTasks("", order, list) } } } @@ -70,32 +68,25 @@ class TaskRepositoryImplTest : WordSpec({ user.stats = Stats() } "debounce" { - every { apiClient.postTaskDirection(any(), "up") } returns Flowable.just( - TaskDirectionData() - ) - repository.taskChecked(user, task, true, false, null).subscribe() - repository.taskChecked(user, task, true, false, null).subscribe() - verify(exactly = 1) { apiClient.postTaskDirection(any(), any()) } + coEvery { apiClient.postTaskDirection(any(), "up") } returns TaskDirectionData() + repository.taskChecked(user, task, true, false, null) + repository.taskChecked(user, task, true, false, null) + coVerify(exactly = 1) { apiClient.postTaskDirection(any(), any()) } } "get user if not passed" { - every { apiClient.postTaskDirection(any(), "up") } returns Flowable.just( - TaskDirectionData() - ) - every { localRepository.getUserFlowable("") } returns Flowable.just(user) + coEvery { apiClient.postTaskDirection(any(), "up") } returns TaskDirectionData() + coEvery { localRepository.getUser("") } returns flowOf(user) repository.taskChecked(null, task, true, false, null) eventually(5000) { - localRepository.getUserFlowable("") + localRepository.getUser("") } } "does not update user for team tasks" { val data = TaskDirectionData() data.lvl = 0 - every { apiClient.postTaskDirection(any(), "up") } returns Flowable.just(data) - val subscriber = TestSubscriber() - repository.taskChecked(user, task, true, false, null).subscribe(subscriber) - subscriber.assertComplete() + coEvery { apiClient.postTaskDirection(any(), "up") } returns data + repository.taskChecked(user, task, true, false, null) verify(exactly = 0) { user.stats } - subscriber.values().first().level shouldBe null } "builds task result correctly" { val data = TaskDirectionData() @@ -106,67 +97,53 @@ class TaskRepositoryImplTest : WordSpec({ user.stats?.lvl = 10 user.stats?.hp = 8.0 user.stats?.mp = 4.0 - every { apiClient.postTaskDirection(any(), "up") } returns Flowable.just(data) - val subscriber = TestSubscriber() - repository.taskChecked(user, task, true, false, null).subscribe(subscriber) - subscriber.assertComplete() - subscriber.values().first().level shouldBe 10 - subscriber.values().first().healthDelta shouldBe 12.0 - subscriber.values().first().manaDelta shouldBe 26.0 - subscriber.values().first().hasLeveledUp shouldBe false + coEvery { apiClient.postTaskDirection(any(), "up") } returns data + val result = repository.taskChecked(user, task, true, false, null) + result?.level shouldBe 10 + result?.healthDelta shouldBe 12.0 + result?.manaDelta shouldBe 26.0 + result?.hasLeveledUp shouldBe false } "set hasLeveledUp correctly" { - val subscriber = TestSubscriber() val data = TaskDirectionData() data.lvl = 11 user.stats?.lvl = 10 - every { apiClient.postTaskDirection(any(), "up") } returns Flowable.just(data) - repository.taskChecked(user, task, true, false, null).subscribe(subscriber) - - subscriber.assertComplete() - subscriber.values().first().level shouldBe 11 - subscriber.values().first().hasLeveledUp shouldBe true + coEvery { apiClient.postTaskDirection(any(), "up") } returns data + val result = repository.taskChecked(user, task, true, false, null) + result?.level shouldBe 11 + result?.hasLeveledUp shouldBe true } "handle stats not being there" { - val subscriber = TestSubscriber() val data = TaskDirectionData() data.lvl = 1 user.stats = null - every { apiClient.postTaskDirection(any(), "up") } returns Flowable.just(data) - repository.taskChecked(user, task, true, false, null).subscribe(subscriber) - subscriber.assertComplete() + coEvery { apiClient.postTaskDirection(any(), "up") } returns data + repository.taskChecked(user, task, true, false, null) } "update daily streak" { - val subscriber = TestSubscriber() val data = TaskDirectionData() data.delta = 1.0f data.lvl = 1 task.type = TaskType.DAILY task.value = 0.0 - every { apiClient.postTaskDirection(any(), "up") } returns Flowable.just(data) - repository.taskChecked(user, task, true, false, null).subscribe(subscriber) - - subscriber.assertComplete() + coEvery { apiClient.postTaskDirection(any(), "up") } returns data + repository.taskChecked(user, task, true, false, null) task.streak shouldBe 1 task.completed shouldBe true } "update habit counter" { - val subscriber = TestSubscriber() val data = TaskDirectionData() data.delta = 1.0f data.lvl = 1 task.type = TaskType.HABIT task.value = 0.0 - every { apiClient.postTaskDirection(any(), "up") } returns Flowable.just(data) - repository.taskChecked(user, task, true, false, null).subscribe(subscriber) - subscriber.assertComplete() + coEvery { apiClient.postTaskDirection(any(), "up") } returns data + repository.taskChecked(user, task, true, false, null) task.counterUp shouldBe 1 data.delta = -10.0f - every { apiClient.postTaskDirection(any(), "down") } returns Flowable.just(data) - val downSubscriber = TestSubscriber() - repository.taskChecked(user, task, false, true, null).subscribe(downSubscriber) - downSubscriber.assertComplete() + coEvery { apiClient.postTaskDirection(any(), "down") } returns data + repository.taskChecked(user, task, false, true, null) task.counterUp shouldBe 1 task.counterDown shouldBe 1 }