Skip to content
Open
Show file tree
Hide file tree
Changes from 7 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
111 changes: 111 additions & 0 deletions .idea/androidTestResultsUserPreferences.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 10 additions & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ plugins {
kotlin(Config.ApplyPlugins.Kotlin.ANDROID)
id(Config.ApplyPlugins.KSP)
id(Config.ApplyPlugins.PARCELIZE)
id(Config.ApplyPlugins.KARUMI_SHOT_TESTING)
}

extra.set("jacocoCoverageThreshold", 0.40.toBigDecimal()) // module specific code coverage verification threshold
Expand Down Expand Up @@ -34,7 +35,10 @@ android {
targetSdk = Config.AndroidSdkVersions.TARGET_SDK
versionCode = BuildInfoManager.APP_VERSION.versionCode
versionName = BuildInfoManager.APP_VERSION.versionName
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"

// testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"

testInstrumentationRunner = "com.karumi.shot.ShotTestRunner"
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
Expand Down Expand Up @@ -127,6 +131,10 @@ android {
testOptions {
unitTests.isIncludeAndroidResources = true
}
shot {
applicationId = "com.bottlerocketstudios.brarchitecture.test"
// tolerance = 1.1
}
}

// Declare configurations per variant to use in the dependencies block below. See :data module for examples if needed here in the :app module.
Expand Down Expand Up @@ -178,4 +186,5 @@ dependencies {
espressoDependencies()
extJunitRunnerDependencies()
androidxCoreDependencies()
composeUITestingDependencies()
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions app/src/androidTest/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.bottlerocketstudios.brarchitecture.test"
android:sharedUserId="com.bottlerocketstudios.brarchitecture.uid">

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package com.bottlerocketstudios.brarchitecture

import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onRoot
import com.bottlerocketstudios.brarchitecture.domain.models.GitRepository
import com.bottlerocketstudios.brarchitecture.domain.models.Link
import com.bottlerocketstudios.brarchitecture.domain.models.Links
import com.bottlerocketstudios.brarchitecture.domain.models.User
import com.bottlerocketstudios.brarchitecture.domain.models.Workspace
import com.bottlerocketstudios.compose.home.HomeScreen
import com.bottlerocketstudios.compose.home.HomeScreenState
import com.bottlerocketstudios.compose.home.UserRepositoryUiModel
import com.bottlerocketstudios.compose.util.StringIdHelper
import com.bottlerocketstudios.compose.util.asMutableState
import com.karumi.shot.ScreenshotTest
import org.junit.Rule
import org.junit.Test
import java.time.ZonedDateTime

class HomeScreenUITest : ScreenshotTest {

@get:Rule
val composeRule = createComposeRule()

@Test
fun homeScreenWithListItemsScreenshot() {
renderComponent(
HomeScreenState(
repositories = listOf(testCard1, testCard2).asMutableState(),
itemSelected = {}
)
)

compareScreenshot(composeRule.onRoot())
}

@Test
fun homeScreenNoResultItemsScreenshot() {
renderComponent(
HomeScreenState(
repositories = emptyList<UserRepositoryUiModel>().asMutableState(),
itemSelected = {}
)
)

compareScreenshot(composeRule.onRoot())
}

fun renderComponent(state: HomeScreenState? = null) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Br-DiorD Think I figured out our issue. We should wrap HomeScreen like this:

ArchitectureDemoTheme {
HomeScreen(state)
}

Also, Could HomeScreenState in function signature be non null?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@BottleRocket-Colin nice! I'll give it a shot after this meeting. I do wonder why it is only an issue on certain screenshots because the Pull RequestScreenshot shot is fine.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Br-DiorD _ would say that the PR request screenshot is probably not correct but just closer to being correct. It's a matter of where our h4 and h5 typographies are closer to the default sizes but our h1 is very small compared to the h1 default. So some screens will show closer to correct than others depending on which typography elements are being used.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@BottleRocket-Colin fixed. Sorry for the delay :)

composeRule.setContent {
if (state != null) HomeScreen(state)
}
}

// todo move somewhere that both UI test and Compose Preview
// can share it instead of setting it twice.
internal val testCard1 = UserRepositoryUiModel(
GitRepository(
scm = "scm1",
name = "name1",
owner = User(
username = "username1",
nickname = "nickname1",
accountStatus = "accountStatus1",
displayName = "displayName1",
createdOn = "createdOn1",
uuid = "uuid1",
links = Links(
avatar = Link(
href = "href1", name = ""
)
),
avatarUrl = "avatarUrl1"
),
workspace = Workspace(
slug = "slug1",
name = "name1",
uuid = "uuid1"
),
isPrivate = false,
description = "description1",
updated = ZonedDateTime.now()
),
formattedLastUpdatedTime = StringIdHelper.Raw("")
)
internal val testCard2 = UserRepositoryUiModel(
GitRepository(
scm = "scm2",
name = "name2",
owner = User(
username = "username2",
nickname = "nickname2",
accountStatus = "accountStatus2",
displayName = "displayName2",
createdOn = "createdOn2",
uuid = "uuid2",
links = Links(
avatar = Link(
href = "href2", name = ""
)
),
avatarUrl = "avatarUrl2"
),
workspace = Workspace(
slug = "slug2",
name = "name2",
uuid = "uuid2"
),
isPrivate = false,
description = "description2",
updated = ZonedDateTime.now()
),
formattedLastUpdatedTime = StringIdHelper.Raw("")
)
}
6 changes: 4 additions & 2 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
<!-- TODO: TEMPLATE - Refactor this packagename when creating a new project -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.bottlerocketstudios.brarchitecture">
package="com.bottlerocketstudios.brarchitecture"
android:sharedUserId="com.bottlerocketstudios.brarchitecture.uid">

<uses-permission android:name="android.permission.INTERNET" />

Expand All @@ -13,7 +14,8 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:networkSecurityConfig="@xml/network_security_config"
android:theme="@style/AppTheme">
android:theme="@style/AppTheme"
android:requestLegacyExternalStorage="true">
<!-- Note: Adjust window mode dynamically per composable screen at runtime -->
<activity
android:name=".ui.ComposeActivity"
Expand Down
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ buildscript {
classpath(Config.BuildScriptPlugins.ANDROID_GRADLE)
classpath(Config.BuildScriptPlugins.KOTLIN_GRADLE)
classpath(Config.BuildScriptPlugins.GRADLE_VERSIONS)
classpath(Config.BuildScriptPlugins.KARUMI_SCREENSHOT_TESTING)

// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle.kts files
Expand Down
22 changes: 22 additions & 0 deletions buildSrc/src/main/kotlin/Dependencies.kt
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import Config.Compose.COMPOSE_VERSION
import TestLibraries.COMPOSE_UI_JUNIT
import TestLibraries.COMPOSE_UI_MANIFEST
import TestLibraries.COMPOSE_UI_TEST
import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.dsl.DependencyHandler
import java.util.Locale
Expand Down Expand Up @@ -63,6 +67,10 @@ object Config {
// Gradle version plugin; use dependencyUpdates task to view third party dependency updates via `./gradlew dependencyUpdates` or AS Gradle -> [project]] -> Tasks -> help -> dependencyUpdates
// https://github.com/ben-manes/gradle-versions-plugin/releases
const val GRADLE_VERSIONS = "com.github.ben-manes:gradle-versions-plugin:0.41.0"

// Gradle plugin and a core android library thought to run screenshot tests for Android
// https://github.com/pedrovgs/Shot
const val KARUMI_SCREENSHOT_TESTING = "com.karumi:shot:5.14.0"
}

/**
Expand All @@ -78,6 +86,7 @@ object Config {
// const val JACOCO = "jacoco" // https://docs.gradle.org/current/userguide/jacoco_plugin.html - Helper jacoco gradle files manage applying the jacoco plugin
const val PARCELIZE = "kotlin-parcelize"
const val KSP = "com.google.devtools.ksp"
const val KARUMI_SHOT_TESTING = "shot"
object Kotlin {
const val ANDROID = "android"
}
Expand Down Expand Up @@ -314,6 +323,7 @@ private object TestLibraries {
const val ANDROIDX_TEST_CORE = "androidx.test:core:1.4.0"
const val ANDROIDX_TEST_CORE_KTX = "androidx.test:core-ktx:1.4.0"
const val ESPRESSO_CORE = "androidx.test.espresso:espresso-core:3.4.0"
const val ESPRESSO_CONTRIB = "androidx.test.espresso:espresso-contrib:3.4.0"
const val JUNIT_EXT_RUNNER = "androidx.test.ext:junit:1.1.3"
const val JUNIT_EXT_RUNNER_KTX = "androidx.test.ext:junit-ktx:1.1.3"

Expand All @@ -325,6 +335,12 @@ private object TestLibraries {
// https://github.com/cashapp/turbine/blob/trunk/CHANGELOG.md
// https://github.com/cashapp/turbine/releases
const val TURBINE = "app.cash.turbine:turbine:0.8.0"

// Compose testing dependencies

const val COMPOSE_UI_TEST = "androidx.compose.ui:ui-test:$COMPOSE_VERSION"
const val COMPOSE_UI_JUNIT = "androidx.compose.ui:ui-test-junit4:$COMPOSE_VERSION"
const val COMPOSE_UI_MANIFEST = "androidx.compose.ui:ui-test-manifest:$COMPOSE_VERSION"
}

//// Dependency Groups - to be used inside dependencies {} block instead of declaring all necessary lines for a particular dependency
Expand Down Expand Up @@ -491,3 +507,9 @@ fun DependencyHandler.kotlinxCoroutineTestingDependencies() {
fun DependencyHandler.turbineDependencies() {
testImplementation(TestLibraries.TURBINE)
}

fun DependencyHandler.composeUITestingDependencies() {
androidTestImplementation(COMPOSE_UI_TEST)
androidTestImplementation(COMPOSE_UI_JUNIT)
debugImplementation(COMPOSE_UI_MANIFEST)
}
2 changes: 1 addition & 1 deletion compose/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ android {
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
isCoreLibraryDesugaringEnabled = true
isCoreLibraryDesugaringEnabled = false
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_11.toString()
Expand Down