Skip to content
Open
Show file tree
Hide file tree
Changes from 8 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
125 changes: 125 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.
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.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"screenshots":[{"name":"com.bottlerocketstudios.brarchitecture.HomeScreenUITest_homeScreenNoResultItemsScreenshot","testClassName":"com.bottlerocketstudios.brarchitecture.HomeScreenUITest","testName":"homeScreenNoResultItemsScreenshot"},{"name":"com.bottlerocketstudios.brarchitecture.HomeScreenUITest_homeScreenWithListItemsScreenshot","testClassName":"com.bottlerocketstudios.brarchitecture.HomeScreenUITest","testName":"homeScreenWithListItemsScreenshot"},{"name":"com.bottlerocketstudios.brarchitecture.PullRequestScreenshotTest_pullRequestWithListItemsScreenshot","testClassName":"com.bottlerocketstudios.brarchitecture.PullRequestScreenshotTest","testName":"pullRequestWithListItemsScreenshot"},{"name":"com.bottlerocketstudios.brarchitecture.PullRequestScreenshotTest_pullRequestNoResultItemsScreenshot","testClassName":"com.bottlerocketstudios.brarchitecture.PullRequestScreenshotTest","testName":"pullRequestNoResultItemsScreenshot"}]}
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("")
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package com.bottlerocketstudios.brarchitecture

import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onRoot
import com.bottlerocketstudios.compose.pullrequest.PullRequestItemState
import com.bottlerocketstudios.compose.pullrequest.PullRequestScreen
import com.bottlerocketstudios.compose.pullrequest.PullRequestScreenState
import com.bottlerocketstudios.compose.util.asMutableState
import com.karumi.shot.ScreenshotTest
import org.junit.Rule
import org.junit.Test

class PullRequestScreenshotTest : ScreenshotTest {

@get:Rule
val composeRule = createComposeRule()

@Test
fun pullRequestWithListItemsScreenshot() {
renderComponent(testList)
compareScreenshot(composeRule.onRoot())
}

@Test
fun pullRequestNoResultItemsScreenshot() {
renderComponent(emptyList)
compareScreenshot(composeRule.onRoot())
}

fun renderComponent(state: PullRequestScreenState? = null) {
composeRule.setContent {
if (state != null) PullRequestScreen(state)
}
}

// todo move somewhere that both UI test and Compose Preview
// can share it instead of setting it twice.
private val testList = PullRequestScreenState(
listOf(
PullRequestItemState(
prName = "ASAA-19/PR-Screen".asMutableState(),
prState = "Open".asMutableState(),
prCreation = "5 days ago".asMutableState(),
linesAdded = "0 Lines Added".asMutableState(),
linesRemoved = "0 Lines Removed".asMutableState()
),
PullRequestItemState(
prName = "ASAA-20/PR-Screen".asMutableState(),
prState = "Open".asMutableState(),
prCreation = "4 days ago".asMutableState(),
linesAdded = "0 Lines Added".asMutableState(),
linesRemoved = "0 Lines Removed".asMutableState()
),
PullRequestItemState(
prName = "ASAA-21/PR-Screen".asMutableState(),
prState = "Open".asMutableState(),
prCreation = "3 days ago".asMutableState(),
linesAdded = "0 Lines Added".asMutableState(),
linesRemoved = "0 Lines Removed".asMutableState()
),
PullRequestItemState(
prName = "ASAA-22/PR-Screen".asMutableState(),
prState = "Open".asMutableState(),
prCreation = "2 days ago".asMutableState(),
linesAdded = "0 Lines Added".asMutableState(),
linesRemoved = "0 Lines Removed".asMutableState()
)
).asMutableState(),
selectedText = "Open".asMutableState(),
selectionList = listOf("Open", "Merged", "Declined", "Superseded").asMutableState(),
onFilterSelectionClicked = {}
)

private val emptyList = PullRequestScreenState(
emptyList<PullRequestItemState>().asMutableState(),
selectedText = "Open".asMutableState(),
selectionList = listOf("Open", "Merged", "Declined", "Superseded").asMutableState(),
onFilterSelectionClicked = {}
)
}
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
Loading