Skip to content

Commit 87566a2

Browse files
Merge pull request #131 from sergio-sastre/release/2.4.0
Release/2.4.0
2 parents 4257340 + a548cae commit 87566a2

File tree

23 files changed

+397
-105
lines changed

23 files changed

+397
-105
lines changed

android-testify/build.gradle

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,12 @@ android {
5151

5252
dependencies {
5353
implementation project(':utils')
54-
implementation 'androidx.test:rules:1.5.0'
55-
api 'dev.testify:testify:2.0.0'
56-
api 'androidx.activity:activity-compose:1.8.2'
54+
//noinspection GradleDependency
55+
implementation ('androidx.test:rules:1.5.0') {
56+
because "1.6.x makes tests fail when running Gradle Managed Devices"
57+
}
58+
api 'dev.testify:testify:3.2.0'
59+
api 'androidx.activity:activity-compose:1.9.2'
5760
}
5861

5962
//https://www.talentica.com/blogs/publish-your-android-library-on-jitpack-for-better-reachability/
@@ -62,7 +65,7 @@ publishing {
6265
release(MavenPublication) {
6366
groupId = 'com.github.sergio-sastre'
6467
artifactId = "android-testify"
65-
version = '2.3.5'
68+
version = '2.4.0'
6669

6770
afterEvaluate {
6871
from components.release
Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,28 @@
11
package sergio.sastre.uitesting.android_testify
22

3+
import android.graphics.Rect
4+
import android.view.ViewGroup
35
import androidx.annotation.ColorInt
6+
import dev.testify.CompareMethod
7+
import dev.testify.core.ExclusionRectProvider
48
import sergio.sastre.uitesting.utils.crosslibrary.config.BitmapCaptureMethod
59
import sergio.sastre.uitesting.utils.crosslibrary.config.LibraryConfig
610

711
class AndroidTestifyConfig(
812
val bitmapCaptureMethod: BitmapCaptureMethod? = null,
913
val exactness: Float = 0.9f,
1014
val enableReporter: Boolean = false,
11-
val initialTouchMode: Boolean = false,
1215
val generateDiffs: Boolean = true,
1316
val animationsDisabled: Boolean = true,
17+
val hideCursor: Boolean = true,
18+
val hidePasswords: Boolean = true,
19+
val hideScrollbars: Boolean = true,
20+
val hideSoftKeyboard: Boolean = true,
21+
val hideTextSuggestions: Boolean = true,
22+
val useSoftwareRenderer: Boolean = false,
23+
val exclusionRects: MutableSet<Rect> = HashSet(),
24+
val exclusionRectProvider: ExclusionRectProvider? = null,
25+
val compareMethod: CompareMethod? = null,
26+
val pauseForInspection: Boolean = false,
1427
@ColorInt val backgroundColor: Int? = null,
1528
) : LibraryConfig

android-testify/src/main/java/sergio/sastre/uitesting/android_testify/AndroidTestifyScreenshotTestRuleForComposable.kt

Lines changed: 0 additions & 52 deletions
This file was deleted.

android-testify/src/main/java/sergio/sastre/uitesting/android_testify/ScreenshotRuleExt.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ fun <T : Activity> ScreenshotRule<T>.waitForIdleSync(): ScreenshotRule<T> = appl
5151

5252
// We need to ensure the view is attached to the screenshotRule activity window for testify to
5353
// take the screenshot. This is especially important for dialogs
54-
internal fun <T : Activity> ScreenshotRule<T>.setViewUnderTest(
54+
internal fun <T : Activity> ScreenshotRule<T>.setDialogViewUnderTest(
5555
view: View,
5656
): ScreenshotRule<T> = apply {
5757
setScreenshotViewProvider {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package sergio.sastre.uitesting.android_testify.screenshotscenario
2+
3+
import androidx.activity.compose.setContent
4+
import androidx.compose.runtime.Composable
5+
import sergio.sastre.uitesting.utils.activityscenario.ActivityScenarioForComposableRule
6+
7+
fun ActivityScenarioForComposableRule.setContent(
8+
composable: @Composable () -> Unit,
9+
): ActivityScenarioForComposableRule {
10+
this.activityScenario
11+
.onActivity {
12+
it.setContent { composable.invoke() }
13+
}
14+
15+
return this
16+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package sergio.sastre.uitesting.android_testify.screenshotscenario
2+
3+
import android.app.Activity
4+
import android.graphics.Bitmap
5+
import android.view.View
6+
import android.view.ViewGroup
7+
import androidx.core.view.drawToBitmap
8+
import androidx.test.platform.app.InstrumentationRegistry
9+
import dev.testify.TestDescription
10+
import dev.testify.TestifyFeatures
11+
import dev.testify.scenario.ScreenshotScenarioRule
12+
import dev.testify.testDescription
13+
import sergio.sastre.uitesting.utils.crosslibrary.config.BitmapCaptureMethod
14+
import sergio.sastre.uitesting.utils.utils.drawToBitmapWithElevation
15+
import sergio.sastre.uitesting.utils.utils.waitForMeasuredView
16+
17+
fun ScreenshotScenarioRule.assertSame(name: String?) {
18+
if (name != null) {
19+
// this is how to change the name of the screenshot file
20+
InstrumentationRegistry.getInstrumentation().testDescription = TestDescription(
21+
methodName = name,
22+
testClass = InstrumentationRegistry.getInstrumentation().testDescription.testClass
23+
)
24+
}
25+
assertSame()
26+
}
27+
28+
fun ScreenshotScenarioRule.waitForIdleSync(): ScreenshotScenarioRule = apply {
29+
InstrumentationRegistry.getInstrumentation().waitForIdleSync()
30+
}
31+
32+
internal fun ScreenshotScenarioRule.setDialogViewUnderTest(
33+
view: View,
34+
): ScreenshotScenarioRule = apply {
35+
setScreenshotViewProvider {
36+
InstrumentationRegistry.getInstrumentation().run {
37+
runOnMainSync {
38+
(view.parent as ViewGroup?)?.removeAllViews()
39+
}
40+
waitForIdleSync()
41+
42+
runOnMainSync {
43+
(activity.window.decorView as ViewGroup).addView(view)
44+
}
45+
waitForIdleSync()
46+
}
47+
waitForMeasuredView { view }
48+
}
49+
}
50+
51+
internal fun ScreenshotScenarioRule.setViewUnderTest(
52+
view: View,
53+
): ScreenshotScenarioRule = apply {
54+
setScreenshotViewProvider {
55+
waitForMeasuredView { view }
56+
}
57+
}
58+
59+
internal fun ScreenshotScenarioRule.setBitmapCaptureMethod(
60+
bitmapCaptureMethod: BitmapCaptureMethod?,
61+
): ScreenshotScenarioRule = apply {
62+
when (bitmapCaptureMethod) {
63+
is BitmapCaptureMethod.Canvas -> {
64+
fun canvas(activity: Activity, targetView: View?): Bitmap? {
65+
return targetView?.drawToBitmap(bitmapCaptureMethod.config)
66+
}
67+
configure { captureMethod = ::canvas }
68+
}
69+
70+
is BitmapCaptureMethod.PixelCopy -> {
71+
fun pixelCopy(activity: Activity, targetView: View?): Bitmap? {
72+
return targetView?.drawToBitmapWithElevation(
73+
activity = activity,
74+
config = bitmapCaptureMethod.config
75+
)
76+
}
77+
configure { captureMethod = ::pixelCopy }
78+
}
79+
80+
null -> { /*no-op*/ }
81+
}
82+
}
83+
84+
fun ScreenshotScenarioRule.generateDiffs(
85+
generate: Boolean,
86+
): ScreenshotScenarioRule = apply {
87+
if (generate) {
88+
TestifyFeatures.GenerateDiffs.setEnabled(true)
89+
}
90+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package sergio.sastre.uitesting.android_testify.screenshotscenario
2+
3+
import androidx.compose.runtime.Composable
4+
import dev.testify.core.TestifyConfiguration
5+
import dev.testify.scenario.ScreenshotScenarioRule
6+
import org.junit.rules.RuleChain
7+
import org.junit.runner.Description
8+
import org.junit.runners.model.Statement
9+
import sergio.sastre.uitesting.android_testify.AndroidTestifyConfig
10+
import sergio.sastre.uitesting.utils.activityscenario.ActivityScenarioForComposableRule
11+
import sergio.sastre.uitesting.utils.crosslibrary.config.LibraryConfig
12+
import sergio.sastre.uitesting.utils.crosslibrary.config.ScreenshotConfigForComposable
13+
import sergio.sastre.uitesting.utils.crosslibrary.testrules.ScreenshotTestRuleForComposable
14+
import sergio.sastre.uitesting.utils.testrules.animations.DisableAnimationsRule
15+
16+
class ScreenshotScenarioRuleForComposable(
17+
override val config: ScreenshotConfigForComposable = ScreenshotConfigForComposable(),
18+
) : ScreenshotTestRuleForComposable(config) {
19+
20+
private val screenshotRule: ScreenshotScenarioRule by lazy {
21+
ScreenshotScenarioRule(
22+
configuration = TestifyConfiguration(
23+
exactness = androidTestifyConfig.exactness,
24+
hideCursor = androidTestifyConfig.hideCursor,
25+
hidePasswords = androidTestifyConfig.hidePasswords,
26+
hideScrollbars = androidTestifyConfig.hideScrollbars,
27+
hideSoftKeyboard = androidTestifyConfig.hideSoftKeyboard,
28+
hideTextSuggestions = androidTestifyConfig.hideTextSuggestions,
29+
useSoftwareRenderer = androidTestifyConfig.useSoftwareRenderer,
30+
exclusionRects = androidTestifyConfig.exclusionRects,
31+
exclusionRectProvider = androidTestifyConfig.exclusionRectProvider,
32+
pauseForInspection = androidTestifyConfig.pauseForInspection,
33+
compareMethod = androidTestifyConfig.compareMethod,
34+
),
35+
enableReporter = androidTestifyConfig.enableReporter,
36+
)
37+
}
38+
39+
// Use only for the context and inflate methods, because for ScreenshotRule it would crash...
40+
private val activityScenarioRule by lazy {
41+
ActivityScenarioForComposableRule(
42+
backgroundColor = androidTestifyConfig.backgroundColor,
43+
config = config.toComposableConfig()
44+
)
45+
}
46+
47+
private var androidTestifyConfig: AndroidTestifyConfig = AndroidTestifyConfig()
48+
49+
override fun apply(
50+
base: Statement,
51+
description: Description,
52+
): Statement =
53+
when (androidTestifyConfig.animationsDisabled) {
54+
true -> RuleChain
55+
.outerRule(DisableAnimationsRule())
56+
.around(activityScenarioRule)
57+
.around(screenshotRule)
58+
.apply(base, description)
59+
false -> RuleChain
60+
.outerRule(activityScenarioRule)
61+
.around(screenshotRule)
62+
.apply(base, description)
63+
}
64+
65+
override fun snapshot(composable: @Composable () -> Unit) {
66+
screenshotRule
67+
.withScenario(activityScenarioRule.activityScenario)
68+
.setScreenshotViewProvider {
69+
activityScenarioRule.setContent { composable() }.composeView
70+
}
71+
.setBitmapCaptureMethod(androidTestifyConfig.bitmapCaptureMethod)
72+
.generateDiffs(androidTestifyConfig.generateDiffs)
73+
.assertSame(null)
74+
}
75+
76+
override fun snapshot(name: String?, composable: @Composable () -> Unit) {
77+
screenshotRule
78+
.withScenario(activityScenarioRule.activityScenario)
79+
.setScreenshotViewProvider {
80+
activityScenarioRule.setContent { composable() }.composeView
81+
}
82+
.setBitmapCaptureMethod(androidTestifyConfig.bitmapCaptureMethod)
83+
.generateDiffs(androidTestifyConfig.generateDiffs)
84+
.assertSame(name = name)
85+
}
86+
87+
override fun configure(config: LibraryConfig): ScreenshotTestRuleForComposable {
88+
if (config is AndroidTestifyConfig) {
89+
androidTestifyConfig = config
90+
}
91+
return this
92+
}
93+
}

0 commit comments

Comments
 (0)