Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CaptureScreenRobot #31

Merged
merged 1 commit into from
Jun 1, 2024
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
1 change: 1 addition & 0 deletions app-android/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -111,5 +111,6 @@ dependencies {
implementation(libs.kermit)
implementation(libs.androidxSplashScreen)
implementation(libs.firebaseDynamicLinks)
debugImplementation(projects.core.testingManifest)
testImplementation(projects.core.testing)
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import com.github.takahirom.roborazzi.RobolectricDeviceQualifiers
import dagger.hilt.android.testing.BindValue
import dagger.hilt.android.testing.HiltAndroidTest
import io.github.droidkaigi.confsched.model.DroidKaigi2023Day
import io.github.droidkaigi.confsched.testing.RobotTestRule
import io.github.droidkaigi.confsched.testing.category.ScreenshotTests
import io.github.droidkaigi.confsched.testing.robot.KaigiAppRobot
Expand All @@ -28,7 +27,7 @@ import javax.inject.Inject
class KaigiAppTest {

@get:Rule
@BindValue val robotTestRule: RobotTestRule = RobotTestRule<MainActivity>(this)
@BindValue val robotTestRule: RobotTestRule = RobotTestRule(MainActivity::class, this)

@Inject lateinit var kaigiAppRobot: KaigiAppRobot

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,6 @@ class KmpFeaturePlugin : Plugin<Project> {
apply("droidkaigi.primitive.kmp.roborazzi")
apply("droidkaigi.primitive.detekt")
}

tasks.withType<KotlinCompile>().configureEach {
kotlinOptions {
freeCompilerArgs = freeCompilerArgs + buildComposeMetricsParameters()
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package io.github.droidkaigi.confsched.primitive

import io.github.droidkaigi.confsched.convention.buildComposeMetricsParameters
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.get
import org.gradle.kotlin.dsl.withType
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

@Suppress("unused")
class KmpComposePlugin : Plugin<Project> {
Expand Down Expand Up @@ -47,6 +50,11 @@ class KmpComposePlugin : Plugin<Project> {
}
}

tasks.withType<KotlinCompile>().configureEach {
kotlinOptions {
freeCompilerArgs = freeCompilerArgs + buildComposeMetricsParameters()
}
}
}
}
}
1 change: 1 addition & 0 deletions core/testing-manifest/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
11 changes: 11 additions & 0 deletions core/testing-manifest/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
plugins {
id("droidkaigi.primitive.android")
id("droidkaigi.primitive.android.kotlin")
id("droidkaigi.primitive.android.hilt")
}

android.namespace = "io.github.droidkaigi.confsched.core.testing"

dependencies {
implementation(projects.core.ui)
}
21 changes: 21 additions & 0 deletions core/testing-manifest/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.kts.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
17 changes: 17 additions & 0 deletions core/testing-manifest/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
>
<application>
<activity
android:name="io.github.droidkaigi.confsched.testing.HiltTestActivity"
android:theme="@style/Theme.AppCompat.NoActionBar"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
1 change: 1 addition & 0 deletions core/testing/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ dependencies {
implementation(libs.daggerHiltAndroidTesting)
implementation(libs.roborazzi)
implementation(libs.kermit)
api(projects.core.testingManifest)
api(libs.roborazziRule)
api(libs.robolectric)
api(libs.composeUiTestJunit4)
Expand Down
16 changes: 1 addition & 15 deletions core/testing/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,16 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
>
<application>
<activity
android:name="io.github.droidkaigi.confsched.testing.HiltTestActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
<manifest />
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package io.github.droidkaigi.confsched.testing

interface CaptureScreenRobot {
fun captureScreenWithChecks(checks: () -> Unit)
}

fun todoChecks(@Suppress("UNUSED_PARAMETER") reason: String): () -> Unit {
return {}
}

class DefaultCaptureScreenRobot(private val robotTestRule: RobotTestRule) : CaptureScreenRobot {
override fun captureScreenWithChecks(checks: () -> Unit) {
robotTestRule.captureScreen()
checks()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,39 +15,58 @@ import com.github.takahirom.roborazzi.RoborazziOptions.PixelBitConfig
import com.github.takahirom.roborazzi.RoborazziOptions.RecordOptions
import com.github.takahirom.roborazzi.RoborazziRule
import com.github.takahirom.roborazzi.RoborazziRule.Options
import com.github.takahirom.roborazzi.captureScreenRoboImage
import dagger.hilt.EntryPoint
import dagger.hilt.EntryPoints
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import io.github.droidkaigi.confsched.data.di.RepositoryProvider
import io.github.droidkaigi.confsched.ui.Inject
import org.junit.rules.RuleChain
import org.junit.rules.TestRule
import org.junit.rules.TestWatcher
import org.junit.runner.Description
import org.junit.runners.model.Statement
import kotlin.reflect.KClass

inline fun <reified A : ComponentActivity> RobotTestRule(
fun RobotTestRule(
testInstance: Any,
bundle: Bundle? = null,
): RobotTestRule {
val composeTestRule = AndroidComposeTestRule<ActivityScenarioRule<A>, A>(
activityRule = ActivityScenarioRule(
Intent(
ApplicationProvider.getApplicationContext(),
A::class.java,
).apply {
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
if (bundle != null) {
putExtras(bundle)
return RobotTestRule<HiltTestActivity>(
HiltTestActivity::class,
testInstance,
bundle,
)
}

inline fun<reified T: ComponentActivity> RobotTestRule(
activityClass: KClass<T>,
testInstance: Any,
bundle: Bundle? = null,
): RobotTestRule {
val composeTestRule =
AndroidComposeTestRule<ActivityScenarioRule<T>, T>(
activityRule = ActivityScenarioRule(
Intent(
ApplicationProvider.getApplicationContext(),
activityClass.java,
).apply {
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
if (bundle != null) {
putExtras(bundle)
}
},
),
activityProvider = { rule ->
var activity: T? = null
rule.scenario.onActivity { activity = it }
if (activity == null) {
error("Activity was not set in the ActivityScenarioRule!")
}
return@AndroidComposeTestRule activity as T
},
),
activityProvider = { rule ->
var activity: A? = null
rule.scenario.onActivity { activity = it }
if (activity == null) {
error("Activity was not set in the ActivityScenarioRule!")
}
return@AndroidComposeTestRule activity!!
},
)
)
return RobotTestRule(
testInstance,
composeTestRule as AndroidComposeTestRule<ActivityScenarioRule<*>, *>,
Expand Down Expand Up @@ -89,6 +108,29 @@ class RobotTestRule(
.around(composeTestRule)
.apply(base, description)
}

@EntryPoint
@InstallIn(SingletonComponent::class)
interface RepositoryProviderEntryPoint {
fun getRepositoryProvider(): RepositoryProvider
}

fun setContent(content: @Composable () -> Unit) {
val repositoryProvider = EntryPoints.get(
composeTestRule.activity.application,
RepositoryProviderEntryPoint::class.java
)
.getRepositoryProvider()
composeTestRule.setContent {
repositoryProvider.Provide {
content()
}
}
}

fun captureScreen() {
captureScreenRoboImage()
}
}

class RobotTestEnvironment @Inject constructor(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ import io.github.droidkaigi.confsched.sessions.TimetableScreen
import io.github.droidkaigi.confsched.sessions.TimetableScreenTestTag
import io.github.droidkaigi.confsched.sessions.TimetableUiTypeChangeButtonTestTag
import io.github.droidkaigi.confsched.sessions.section.TimetableTabTestTag
import io.github.droidkaigi.confsched.testing.RobotTestEnvironment
import io.github.droidkaigi.confsched.testing.CaptureScreenRobot
import io.github.droidkaigi.confsched.testing.DefaultCaptureScreenRobot
import io.github.droidkaigi.confsched.testing.RobotTestRule
import io.github.droidkaigi.confsched.testing.coroutines.runTestWithLogging
import io.github.droidkaigi.confsched.ui.compositionlocal.FakeClock
import io.github.droidkaigi.confsched.ui.compositionlocal.LocalClock
Expand All @@ -30,16 +32,15 @@ import javax.inject.Inject
import kotlin.time.Duration.Companion.seconds

class TimetableScreenRobot @Inject constructor(
private val robotTestRule: RobotTestRule,
private val testDispatcher: TestDispatcher,
) {
@Inject lateinit var robotTestEnvironment: RobotTestEnvironment
private val composeTestRule
get() = robotTestEnvironment.composeTestRule

) : CaptureScreenRobot by DefaultCaptureScreenRobot(robotTestRule) {
@Inject lateinit var sessionsApiClient: SessionsApiClient
val fakeSessionsApiClient: FakeSessionsApiClient
private val fakeSessionsApiClient: FakeSessionsApiClient
get() = sessionsApiClient as FakeSessionsApiClient

private val composeTestRule get() = robotTestRule.composeTestRule

operator fun invoke(
block: TimetableScreenRobot.() -> Unit,
) {
Expand All @@ -49,7 +50,7 @@ class TimetableScreenRobot @Inject constructor(
}

fun setupTimetableScreenContent() {
robotTestEnvironment.setContent {
robotTestRule.setContent {
CompositionLocalProvider(LocalClock provides FakeClock) {
KaigiTheme {
TimetableScreen(
Expand Down Expand Up @@ -124,12 +125,6 @@ class TimetableScreenRobot @Inject constructor(
.assertIsDisplayed()
}

fun checkScreenCapture() {
composeTestRule
.onNode(isRoot())
.captureRoboImage()
}

fun checkTimetableListCapture() {
composeTestRule
.onNode(hasTestTag(TimetableScreenTestTag))
Expand Down
5 changes: 5 additions & 0 deletions feature/contributors/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,10 @@ kotlin {
implementation(libs.moleculeRuntime)
}
}
androidUnitTest {
dependencies {
implementation(projects.core.testing)
}
}
}
}
Loading