Skip to content

Commit

Permalink
Improve app UI experience part1 (#93)
Browse files Browse the repository at this point in the history
* Fixed Image loading glitch, fixed auth skip loading glitch, added frame around SummaryActionButton, limited recommendations and home category summaries to 5, made weekly summary functional

* Fixed Detekt violations

* Fixed CI failure

* Added new SummariesByCategoryScreen feature

* Fixed detekt violation

* Fixed detekt violation

* Removed jacoco from :code-checks to fix CI

* test(core-ui): Fixed DotsAnimation ui tests

* test(core-ui): add Compose UI tests for TangaButton, TangaLinedButton, TangaButtonRightIcon, TangaButtonLeftIcon, SummaryActionButton, and SearchButton

* Added ui tests for SearchScreen

* Fixed category state issue on SearchScreen

* Fixed category state issue on SearchScreen

* Added tests for CategoriesSection and SummaryGrid

* Renamed SummaryByCategoryViewModel.kt to SummariesByCategoryViewModel
  • Loading branch information
rygelouv authored Jan 5, 2024
1 parent 12881f5 commit bb183ed
Show file tree
Hide file tree
Showing 57 changed files with 5,315 additions and 144 deletions.
1 change: 1 addition & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ android {
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
signingConfig = signingConfigs.getByName("debug")
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class AuthScreenTest {

launchAuthScreen(state = state)

composeTestRule.onNodeWithTag("ProgressIndicator").assertExists()
composeTestRule.onNodeWithTag("ProgressIndicator", useUnmergedTree = true).assertExists()
}

@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package app.books.tanga.components

import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import app.books.tanga.coreui.theme.TangaTheme
import app.books.tanga.feature.search.CategoriesSection
import app.books.tanga.feature.search.CategoryUi
import app.books.tanga.fixtures.FakeUiData
import junit.framework.TestCase.assertEquals
import kotlinx.collections.immutable.toImmutableList
import org.junit.Rule
import org.junit.Test

class CategoriesSectionTest {

@get:Rule
val composeTestRule = createComposeRule()

@Test
fun categoriesSection_displaysCategories() {
val categories = FakeUiData.categories()

composeTestRule.setContent {
TangaTheme {
CategoriesSection(categories = categories.toImmutableList())
}
}

categories.forEach { category ->
composeTestRule.onNodeWithText(category.name).assertExists()
}
}

@Test
fun categoriesSection_triggersOnCategorySelect() {
var selectedCategory: CategoryUi? = null
var unselectedCategory: CategoryUi? = null
val categories = FakeUiData.categories()

composeTestRule.setContent {
TangaTheme {
CategoriesSection(
categories = categories.toImmutableList(),
onCategorySelect = { selectedCategory = it },
onCategoryUnselect = { unselectedCategory = it }
)
}
}

val firstCategory = categories.first()
composeTestRule.onNodeWithText(firstCategory.name).performClick()
assertEquals(selectedCategory, firstCategory)
composeTestRule.onNodeWithText(firstCategory.name).performClick()
assertEquals(unselectedCategory, firstCategory)
}

@Test
fun categoriesSection_triggersOnCategoryUnselectOnPreselectedCategories() {
var didSelectedCategory = false
var didUnselectedCategory = false
var unselectCounter = 0
val categories = FakeUiData.categories()

composeTestRule.setContent {
TangaTheme {
CategoriesSection(
categories = categories.toImmutableList(),
selectedCategories = listOf(categories.first(), categories.last()).toImmutableList(),
onCategorySelect = { didSelectedCategory = true },
onCategoryUnselect = {
didUnselectedCategory = true
unselectCounter++
}
)
}
}

val firstCategory = categories.first()
val lastCategory = categories.last()
composeTestRule.onNodeWithText(firstCategory.name).performClick()
composeTestRule.onNodeWithText(categories[categories.lastIndex - 1].name).performClick()
composeTestRule.onNodeWithText(lastCategory.name).performClick()
assertEquals(didSelectedCategory, true)
assertEquals(didUnselectedCategory, true)
assertEquals(unselectCounter, 2)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package app.books.tanga.components

import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performScrollToIndex
import app.books.tanga.R
import app.books.tanga.coreui.components.InfoCard
import app.books.tanga.coreui.components.TangaButton
import app.books.tanga.coreui.theme.TangaTheme
import app.books.tanga.feature.summary.list.SummaryGrid
import app.books.tanga.fixtures.FakeUiData
import kotlinx.collections.immutable.toImmutableList
import org.junit.Rule
import org.junit.Test

class SummaryGridTest {

@get:Rule
val composeTestRule = createComposeRule()

@Test
fun summaryGrid_displaysHeaderAndFooter_whenEmptyList() {
val allSummaries = FakeUiData.allSummaries()
composeTestRule.setContent {
TangaTheme {
SummaryGrid(
summaries = allSummaries.toImmutableList(),
header = { InfoCard(image = R.drawable.graphic_pricing) },
footer = { TangaButton(text = "Button", onClick = { }) },
onSummaryClick = {}
)
}
}

composeTestRule.onNodeWithTag("info_card").assertExists()
composeTestRule.onNodeWithText(allSummaries.first().title).assertExists()
composeTestRule.onNodeWithTag("SummaryGrid").performScrollToIndex(allSummaries.lastIndex)
composeTestRule.onNodeWithText("Button").assertExists()
}

@Test
fun summaryGrid_displaysAllSummaries() {
val allSummaries = FakeUiData.allSummaries()

composeTestRule.setContent {
TangaTheme {
SummaryGrid(
summaries = allSummaries.toImmutableList(),
onSummaryClick = {}
)
}
}

allSummaries.forEachIndexed { index, summary ->
composeTestRule.onNodeWithTag("SummaryGrid").performScrollToIndex(index)
composeTestRule.onNodeWithText(summary.title).assertExists()
}
}
}
166 changes: 166 additions & 0 deletions app/src/androidTest/java/app/books/tanga/fixtures/FakeUiData.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
package app.books.tanga.fixtures

import app.books.tanga.R
import app.books.tanga.entity.SummaryId
import app.books.tanga.feature.search.CategoryUi
import app.books.tanga.feature.summary.SummaryUi
import java.util.UUID

object FakeUiData {
fun categories() =
buildList {
add(
CategoryUi(
id = "1",
name = "Business",
icon = app.books.tanga.coreui.R.drawable.ic_business
)
)
add(
CategoryUi(
id = "2",
name = "Personal Development",
icon = app.books.tanga.coreui.R.drawable.ic_self_development
)
)
add(
CategoryUi(
id = "3",
name = "Psychology",
icon = app.books.tanga.coreui.R.drawable.ic_productivity
)
)
add(
CategoryUi(
id = "4",
name = "Financial Education",
icon = app.books.tanga.coreui.R.drawable.ic_financial_education
)
)
}

fun allSummaries() =
buildList<SummaryUi> {
add(
SummaryUi(
id = SummaryId(UUID.randomUUID().toString()),
cover = app.books.tanga.coreui.R.drawable.atomic_habits_cover,
title = "It doesn't have to be crazy at work",
author = "Jason Fried and David Heinemeir Hannson",
duration = "10",
hasGraphic = true,
authorPictureUrl = null
)
)
add(
SummaryUi(
id = SummaryId(UUID.randomUUID().toString()),
cover = R.drawable.cover_atomic_habit,
title = "Atomic Habits",
author = "James Clear",
duration = "15",
hasVideo = true,
authorPictureUrl = null
)
)
add(
SummaryUi(
id = SummaryId(UUID.randomUUID().toString()),
cover = R.drawable.cover_deep_work,
title = "Deep Work",
author = "Cal Newport",
duration = "9",
hasGraphic = true,
authorPictureUrl = null
)
)
add(
SummaryUi(
id = SummaryId(UUID.randomUUID().toString()),
cover = R.drawable.cover_ego_is_enemy,
title = "Ego is the Enemy",
author = "Ryan Holiday",
duration = "13",
hasVideo = true,
authorPictureUrl = null
)
)
add(
SummaryUi(
id = SummaryId(UUID.randomUUID().toString()),
cover = R.drawable.cover_so_good_they_cant_ignore_you,
title = "So Good They Can't Ignore You",
author = "Cal Newport",
duration = "11",
authorPictureUrl = null
)
)
add(
SummaryUi(
id = SummaryId(UUID.randomUUID().toString()),
cover = R.drawable.cover_good_to_great,
title = "Good To Great",
author = "Jim Collins",
duration = "8",
authorPictureUrl = null
)
)
add(
SummaryUi(
id = SummaryId(UUID.randomUUID().toString()),
cover = R.drawable.cover_never_split_difference,
title = "Never Split The Difference",
author = "Chris Voss",
duration = "10",
authorPictureUrl = null
)
)
add(
SummaryUi(
id = SummaryId(UUID.randomUUID().toString()),
cover = R.drawable.cover_obstacle_is_the_way,
title = "The Obstacle Is the Way",
author = "Ryan Holiday",
duration = "10",
hasGraphic = true,
hasVideo = true,
authorPictureUrl = null
)
)
add(
SummaryUi(
id = SummaryId(UUID.randomUUID().toString()),
cover = R.drawable.cover_psychology_of_money,
title = "Psychology Of Money",
author = "Morgan Housel",
duration = "10",
hasGraphic = true,
authorPictureUrl = null
)
)
add(
SummaryUi(
id = SummaryId(UUID.randomUUID().toString()),
cover = R.drawable.cover_rework,
title = "Rework",
author = "Jason Fried and David Heinemeir Hannson",
duration = "11",
hasGraphic = true,
hasVideo = true,
authorPictureUrl = null
)
)
add(
SummaryUi(
id = SummaryId(UUID.randomUUID().toString()),
cover = R.drawable.cover_subtle_art_not_giving_fuck,
title = "The Subtle Art Of Not Giving A Fuck",
author = "Mark Manson",
duration = "9",
hasGraphic = true,
hasVideo = true,
authorPictureUrl = null
)
)
}
}
Loading

0 comments on commit bb183ed

Please sign in to comment.