From 841b866ce8ea8d6d46220339c03f2502e6d95c35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Sastre=20Fl=C3=B3rez?= Date: Sun, 17 Nov 2024 18:36:48 +0100 Subject: [PATCH] Prepare CrossLibrary features for 2.6.0 Paparazzi & Roborazzi - overrideForDefaultAccessibility() to easy enable Accessibility - support custom Density when defining Device Paparazzi: - Support 2.3.5 - Support useDeviceResolution & validateAccessibility Roborazzi: - Support 1.32.2 - Support record WebP & aiAssertions --- android-testify/build.gradle | 2 +- .../android_testify/AndroidTestifyConfig.kt | 3 +- dropshots/build.gradle | 2 +- .../uitesting/dropshots/DropshotsConfig.kt | 2 +- mapper-paparazzi/build.gradle | 2 +- .../mapper/paparazzi/PaparazziConfig.kt | 19 ++++++- .../mapper/paparazzi/wrapper/Density.kt | 51 +++++++++-------- .../mapper/paparazzi/wrapper/DeviceConfig.kt | 11 +++- .../mapper/paparazzi/wrapper/Environment.kt | 1 - mapper-roborazzi/build.gradle | 2 +- .../mapper/roborazzi/RoborazziConfig.kt | 10 ++++ .../mapper/roborazzi/wrapper/AiAssertion.kt | 8 +++ .../mapper/roborazzi/wrapper/CaptureType.kt | 2 +- .../mapper/roborazzi/wrapper/ImageIoFormat.kt | 6 ++ .../mapper/roborazzi/wrapper/RecordOptions.kt | 3 +- .../roborazzi/wrapper/RoborazziOptions.kt | 7 +++ .../roborazzi/wrapper/screen/DeviceScreen.kt | 2 +- .../roborazzi/wrapper/screen/ScreenDensity.kt | 51 +++++++++-------- paparazzi/build.gradle | 4 +- .../PaparazziForComposableTestRuleBuilder.kt | 2 + .../config/PaparazziWrapperConfigAdapter.kt | 2 +- robolectric/build.gradle | 4 +- .../config/RobolectricQualifiersBuilder.kt | 2 +- .../robolectric/config/screen/DeviceScreen.kt | 2 +- .../config/screen/ScreenDensity.kt | 57 +++++++++++-------- roborazzi/build.gradle | 11 ++-- .../config/RoborazziSharedTestAdapter.kt | 35 +++++++++++- shot/build.gradle | 2 +- .../sastre/uitesting/shot/ShotConfig.kt | 2 +- utils/build.gradle | 2 +- 30 files changed, 207 insertions(+), 102 deletions(-) create mode 100644 mapper-roborazzi/src/main/java/sergio/sastre/uitesting/mapper/roborazzi/wrapper/AiAssertion.kt create mode 100644 mapper-roborazzi/src/main/java/sergio/sastre/uitesting/mapper/roborazzi/wrapper/ImageIoFormat.kt diff --git a/android-testify/build.gradle b/android-testify/build.gradle index bcfe6f5..4dd09ed 100644 --- a/android-testify/build.gradle +++ b/android-testify/build.gradle @@ -65,7 +65,7 @@ publishing { release(MavenPublication) { groupId = 'com.github.sergio-sastre' artifactId = "android-testify" - version = '2.5.0' + version = '2.6.0' afterEvaluate { from components.release diff --git a/android-testify/src/main/java/sergio/sastre/uitesting/android_testify/AndroidTestifyConfig.kt b/android-testify/src/main/java/sergio/sastre/uitesting/android_testify/AndroidTestifyConfig.kt index c97f6a2..d9a419f 100644 --- a/android-testify/src/main/java/sergio/sastre/uitesting/android_testify/AndroidTestifyConfig.kt +++ b/android-testify/src/main/java/sergio/sastre/uitesting/android_testify/AndroidTestifyConfig.kt @@ -1,14 +1,13 @@ package sergio.sastre.uitesting.android_testify import android.graphics.Rect -import android.view.ViewGroup import androidx.annotation.ColorInt import dev.testify.CompareMethod import dev.testify.core.ExclusionRectProvider import sergio.sastre.uitesting.utils.crosslibrary.config.BitmapCaptureMethod import sergio.sastre.uitesting.utils.crosslibrary.config.LibraryConfig -class AndroidTestifyConfig( +data class AndroidTestifyConfig( val bitmapCaptureMethod: BitmapCaptureMethod? = null, val exactness: Float = 0.9f, val enableReporter: Boolean = false, diff --git a/dropshots/build.gradle b/dropshots/build.gradle index d7a88d4..0fe6b83 100644 --- a/dropshots/build.gradle +++ b/dropshots/build.gradle @@ -64,7 +64,7 @@ publishing { release(MavenPublication) { groupId = 'com.github.sergio-sastre' artifactId = "dropshots" - version = '2.5.0' + version = '2.6.0' afterEvaluate { from components.release diff --git a/dropshots/src/main/java/sergio/sastre/uitesting/dropshots/DropshotsConfig.kt b/dropshots/src/main/java/sergio/sastre/uitesting/dropshots/DropshotsConfig.kt index f4f2a65..b81f93d 100644 --- a/dropshots/src/main/java/sergio/sastre/uitesting/dropshots/DropshotsConfig.kt +++ b/dropshots/src/main/java/sergio/sastre/uitesting/dropshots/DropshotsConfig.kt @@ -8,7 +8,7 @@ import com.dropbox.dropshots.ResultValidator import sergio.sastre.uitesting.utils.crosslibrary.config.BitmapCaptureMethod import sergio.sastre.uitesting.utils.crosslibrary.config.LibraryConfig -class DropshotsConfig( +data class DropshotsConfig( val resultValidator: ResultValidator = CountValidator(0), val imageComparator: ImageComparator = SimpleImageComparator(maxDistance = 0.004f), val bitmapCaptureMethod: BitmapCaptureMethod? = null, diff --git a/mapper-paparazzi/build.gradle b/mapper-paparazzi/build.gradle index 4e7f71d..3825e6b 100644 --- a/mapper-paparazzi/build.gradle +++ b/mapper-paparazzi/build.gradle @@ -49,7 +49,7 @@ publishing { release(MavenPublication) { groupId = 'com.github.sergio-sastre' artifactId = "mapper-paparazzi" - version = '2.5.0' + version = '2.6.0' afterEvaluate { from components.release diff --git a/mapper-paparazzi/src/main/java/sergio/sastre/uitesting/mapper/paparazzi/PaparazziConfig.kt b/mapper-paparazzi/src/main/java/sergio/sastre/uitesting/mapper/paparazzi/PaparazziConfig.kt index 2061c51..ad05497 100644 --- a/mapper-paparazzi/src/main/java/sergio/sastre/uitesting/mapper/paparazzi/PaparazziConfig.kt +++ b/mapper-paparazzi/src/main/java/sergio/sastre/uitesting/mapper/paparazzi/PaparazziConfig.kt @@ -1,5 +1,6 @@ package sergio.sastre.uitesting.mapper.paparazzi +import sergio.sastre.uitesting.mapper.paparazzi.wrapper.AccessibilityRenderExtension import sergio.sastre.uitesting.mapper.paparazzi.wrapper.DeviceConfig import sergio.sastre.uitesting.mapper.paparazzi.wrapper.Environment import sergio.sastre.uitesting.mapper.paparazzi.wrapper.RenderExtension @@ -18,9 +19,9 @@ import sergio.sastre.uitesting.utils.crosslibrary.config.LibraryConfig * considering the orientation (e.g. width and height switched for Landscape) * @param softButtons: false for all wrapped DeviceConfigs, contrary to Paparazzi's default. * That's because of this default renderingMode: if softButtons == true, they overlap - * the view, and are displaded on top of it. + * the view, and are displaced on top of it. */ -class PaparazziConfig( +data class PaparazziConfig( val maxPercentageDiff: Double = 0.1, val deviceConfig: DeviceConfig = DeviceConfig.NEXUS_5, val deviceSystemUiVisibility: DeviceSystemUiVisibility = DeviceSystemUiVisibility(), @@ -28,7 +29,19 @@ class PaparazziConfig( val snapshotViewOffsetMillis: Long = 0L, val renderingMode: RenderingMode? = null, val renderExtensions: Set = emptySet(), -) : LibraryConfig + val useDeviceResolution: Boolean = false, + val validateAccessibility: Boolean = false, +) : LibraryConfig { + + fun overrideForDefaultAccessibility(): PaparazziConfig { + return this.copy( + deviceConfig = this.deviceConfig.increaseWidthForAccessibilityExtension(), + renderingMode = RenderingMode.NORMAL, + renderExtensions = setOf(AccessibilityRenderExtension()), + validateAccessibility = false, // Paparazzi does not support it together with RenderExtensions + ) + } +} data class DeviceSystemUiVisibility( val softButtons: Boolean = false, diff --git a/mapper-paparazzi/src/main/java/sergio/sastre/uitesting/mapper/paparazzi/wrapper/Density.kt b/mapper-paparazzi/src/main/java/sergio/sastre/uitesting/mapper/paparazzi/wrapper/Density.kt index 2f10623..26d86c2 100644 --- a/mapper-paparazzi/src/main/java/sergio/sastre/uitesting/mapper/paparazzi/wrapper/Density.kt +++ b/mapper-paparazzi/src/main/java/sergio/sastre/uitesting/mapper/paparazzi/wrapper/Density.kt @@ -1,26 +1,31 @@ package sergio.sastre.uitesting.mapper.paparazzi.wrapper -enum class Density { - XXXHIGH, - DPI_560, - XXHIGH, - DPI_440, - DPI_420, - DPI_400, - DPI_360, - XHIGH, - DPI_260, - DPI_280, - DPI_300, - DPI_340, - HIGH, - DPI_220, - TV, - DPI_200, - DPI_180, - MEDIUM, - DPI_140, - LOW, - ANYDPI, - NODPI, +interface DpiDensity { + val dpi: Int + class Value(override val dpi: Int) : DpiDensity +} + +enum class Density(override val dpi: Int) : DpiDensity { + XXXHIGH(640), + DPI_560(560), + XXHIGH(480), + DPI_440(440), + DPI_420(420), + DPI_400(400), + DPI_360(360), + XHIGH(480), + DPI_260(260), + DPI_280(280), + DPI_300(300), + DPI_340(340), + HIGH(240), + DPI_220(220), + TV(213), + DPI_200(200), + DPI_180(180), + MEDIUM(160), + DPI_140(140), + LOW(120), + ANYDPI(0xFFFE), + NODPI(0xFFFF) } diff --git a/mapper-paparazzi/src/main/java/sergio/sastre/uitesting/mapper/paparazzi/wrapper/DeviceConfig.kt b/mapper-paparazzi/src/main/java/sergio/sastre/uitesting/mapper/paparazzi/wrapper/DeviceConfig.kt index eed0c45..56b2159 100644 --- a/mapper-paparazzi/src/main/java/sergio/sastre/uitesting/mapper/paparazzi/wrapper/DeviceConfig.kt +++ b/mapper-paparazzi/src/main/java/sergio/sastre/uitesting/mapper/paparazzi/wrapper/DeviceConfig.kt @@ -5,13 +5,22 @@ data class DeviceConfig( val screenWidth: Int = 768, val xdpi: Int = 320, val ydpi: Int = 320, - val density: Density = Density.XHIGH, + val density: DpiDensity = Density.XHIGH, val ratio: ScreenRatio = ScreenRatio.NOTLONG, val size: ScreenSize = ScreenSize.NORMAL, val navigation: Navigation = Navigation.NONAV, val released: String = "November 13, 2012" ) { + /** + * The accessibilityExtension takes up half the width, therefore use this to expand it + */ + fun increaseWidthForAccessibilityExtension() : DeviceConfig { + return copy( + screenWidth = this.screenWidth * 2 + ) + } + companion object { @JvmField val NEXUS_4 = DeviceConfig() diff --git a/mapper-paparazzi/src/main/java/sergio/sastre/uitesting/mapper/paparazzi/wrapper/Environment.kt b/mapper-paparazzi/src/main/java/sergio/sastre/uitesting/mapper/paparazzi/wrapper/Environment.kt index a645713..3d4f86b 100644 --- a/mapper-paparazzi/src/main/java/sergio/sastre/uitesting/mapper/paparazzi/wrapper/Environment.kt +++ b/mapper-paparazzi/src/main/java/sergio/sastre/uitesting/mapper/paparazzi/wrapper/Environment.kt @@ -3,7 +3,6 @@ package sergio.sastre.uitesting.mapper.paparazzi.wrapper import java.util.* data class Environment( - val platformDir: String? = null, val compileSdkVersion: Int? = null, val appTestDir: String? = null, val packageName: String? = null, diff --git a/mapper-roborazzi/build.gradle b/mapper-roborazzi/build.gradle index b9221fa..7a3b16a 100644 --- a/mapper-roborazzi/build.gradle +++ b/mapper-roborazzi/build.gradle @@ -50,7 +50,7 @@ publishing { release(MavenPublication) { groupId = 'com.github.sergio-sastre' artifactId = "mapper-roborazzi" - version = '2.5.0' + version = '2.6.0' afterEvaluate { from components.release diff --git a/mapper-roborazzi/src/main/java/sergio/sastre/uitesting/mapper/roborazzi/RoborazziConfig.kt b/mapper-roborazzi/src/main/java/sergio/sastre/uitesting/mapper/roborazzi/RoborazziConfig.kt index 510aceb..a25b552 100644 --- a/mapper-roborazzi/src/main/java/sergio/sastre/uitesting/mapper/roborazzi/RoborazziConfig.kt +++ b/mapper-roborazzi/src/main/java/sergio/sastre/uitesting/mapper/roborazzi/RoborazziConfig.kt @@ -1,6 +1,8 @@ package sergio.sastre.uitesting.mapper.roborazzi import androidx.annotation.ColorInt +import sergio.sastre.uitesting.mapper.roborazzi.wrapper.CaptureType +import sergio.sastre.uitesting.mapper.roborazzi.wrapper.DumpExplanation.AccessibilityExplanation import sergio.sastre.uitesting.mapper.roborazzi.wrapper.RoborazziOptions import sergio.sastre.uitesting.mapper.roborazzi.wrapper.screen.DeviceScreen import sergio.sastre.uitesting.utils.crosslibrary.config.BitmapCaptureMethod @@ -14,6 +16,14 @@ data class RoborazziConfig( val bitmapCaptureMethod: BitmapCaptureMethod? = null, ) : LibraryConfig { + fun overrideForDefaultAccessibility(): RoborazziConfig { + return copy( + roborazziOptions = roborazziOptions.copy( + captureType = CaptureType.Dump(AccessibilityExplanation) + ), + ) + } + companion object { const val DEFAULT_ROBORAZZI_OUTPUT_DIR_PATH = "build/outputs/roborazzi" } diff --git a/mapper-roborazzi/src/main/java/sergio/sastre/uitesting/mapper/roborazzi/wrapper/AiAssertion.kt b/mapper-roborazzi/src/main/java/sergio/sastre/uitesting/mapper/roborazzi/wrapper/AiAssertion.kt new file mode 100644 index 0000000..95532bd --- /dev/null +++ b/mapper-roborazzi/src/main/java/sergio/sastre/uitesting/mapper/roborazzi/wrapper/AiAssertion.kt @@ -0,0 +1,8 @@ +package sergio.sastre.uitesting.mapper.roborazzi.wrapper + +data class AiAssertion( + val assertionPrompt: String, + val requiredFulfillmentPercent: Int, + val failIfNotFulfilled: Boolean = true +) + diff --git a/mapper-roborazzi/src/main/java/sergio/sastre/uitesting/mapper/roborazzi/wrapper/CaptureType.kt b/mapper-roborazzi/src/main/java/sergio/sastre/uitesting/mapper/roborazzi/wrapper/CaptureType.kt index 086abab..111cd0b 100644 --- a/mapper-roborazzi/src/main/java/sergio/sastre/uitesting/mapper/roborazzi/wrapper/CaptureType.kt +++ b/mapper-roborazzi/src/main/java/sergio/sastre/uitesting/mapper/roborazzi/wrapper/CaptureType.kt @@ -3,7 +3,7 @@ package sergio.sastre.uitesting.mapper.roborazzi.wrapper import sergio.sastre.uitesting.mapper.roborazzi.wrapper.DumpExplanation.DefaultExplanation sealed interface CaptureType { - object Screenshot : CaptureType + data object Screenshot : CaptureType data class Dump(val explanation: DumpExplanation = DefaultExplanation) : CaptureType } diff --git a/mapper-roborazzi/src/main/java/sergio/sastre/uitesting/mapper/roborazzi/wrapper/ImageIoFormat.kt b/mapper-roborazzi/src/main/java/sergio/sastre/uitesting/mapper/roborazzi/wrapper/ImageIoFormat.kt new file mode 100644 index 0000000..a883b0d --- /dev/null +++ b/mapper-roborazzi/src/main/java/sergio/sastre/uitesting/mapper/roborazzi/wrapper/ImageIoFormat.kt @@ -0,0 +1,6 @@ +package sergio.sastre.uitesting.mapper.roborazzi.wrapper + +enum class ImageIoFormat { + LosslessWebPImageIoFormat, + ImageIoFormat +} \ No newline at end of file diff --git a/mapper-roborazzi/src/main/java/sergio/sastre/uitesting/mapper/roborazzi/wrapper/RecordOptions.kt b/mapper-roborazzi/src/main/java/sergio/sastre/uitesting/mapper/roborazzi/wrapper/RecordOptions.kt index 1b3ea96..d27b4f8 100644 --- a/mapper-roborazzi/src/main/java/sergio/sastre/uitesting/mapper/roborazzi/wrapper/RecordOptions.kt +++ b/mapper-roborazzi/src/main/java/sergio/sastre/uitesting/mapper/roborazzi/wrapper/RecordOptions.kt @@ -3,5 +3,6 @@ package sergio.sastre.uitesting.mapper.roborazzi.wrapper data class RecordOptions( val resizeScale: Double = checkNotNull(System.getProperty("roborazzi.record.resizeScale", "1.0")).toDouble(), - val applyDeviceCrop: Boolean = false + val applyDeviceCrop: Boolean = false, + val imageIoFormat: ImageIoFormat = ImageIoFormat.ImageIoFormat, ) diff --git a/mapper-roborazzi/src/main/java/sergio/sastre/uitesting/mapper/roborazzi/wrapper/RoborazziOptions.kt b/mapper-roborazzi/src/main/java/sergio/sastre/uitesting/mapper/roborazzi/wrapper/RoborazziOptions.kt index cccaa05..cdcf31b 100644 --- a/mapper-roborazzi/src/main/java/sergio/sastre/uitesting/mapper/roborazzi/wrapper/RoborazziOptions.kt +++ b/mapper-roborazzi/src/main/java/sergio/sastre/uitesting/mapper/roborazzi/wrapper/RoborazziOptions.kt @@ -1,8 +1,15 @@ package sergio.sastre.uitesting.mapper.roborazzi.wrapper +/** + * WARNING: + * @param aiAssertions requires you to add the corresponding Roborazzi module, namely one of these: + * 1. roborazzi-ai-gemini -> testImplementation(io.github.takahirom.roborazzi:roborazzi-ai-gemini) + * 2. roborazzi-ai-openai -> testImplementation(io.github.takahirom.roborazzi:roborazzi-ai-openai) + */ data class RoborazziOptions( val captureType: CaptureType = CaptureType.Screenshot, val compareOptions: CompareOptions = CompareOptions(), val recordOptions: RecordOptions = RecordOptions(), val contextData: Map = emptyMap(), + val aiAssertions: List = emptyList() ) diff --git a/mapper-roborazzi/src/main/java/sergio/sastre/uitesting/mapper/roborazzi/wrapper/screen/DeviceScreen.kt b/mapper-roborazzi/src/main/java/sergio/sastre/uitesting/mapper/roborazzi/wrapper/screen/DeviceScreen.kt index 5962478..a7aa209 100644 --- a/mapper-roborazzi/src/main/java/sergio/sastre/uitesting/mapper/roborazzi/wrapper/screen/DeviceScreen.kt +++ b/mapper-roborazzi/src/main/java/sergio/sastre/uitesting/mapper/roborazzi/wrapper/screen/DeviceScreen.kt @@ -5,7 +5,7 @@ data class DeviceScreen( val heightDp: Int, val size: ScreenSize = ScreenSize.NORMAL, val aspect: ScreenAspect = ScreenAspect.NOTLONG, - val density: ScreenDensity = ScreenDensity.MDPI, + val density: DpiDensity = ScreenDensity.MDPI, val defaultOrientation: ScreenOrientation = ScreenOrientation.PORTRAIT, val round: RoundScreen? = null, val type: ScreenType? = null, diff --git a/mapper-roborazzi/src/main/java/sergio/sastre/uitesting/mapper/roborazzi/wrapper/screen/ScreenDensity.kt b/mapper-roborazzi/src/main/java/sergio/sastre/uitesting/mapper/roborazzi/wrapper/screen/ScreenDensity.kt index ee665bc..b3c64e0 100644 --- a/mapper-roborazzi/src/main/java/sergio/sastre/uitesting/mapper/roborazzi/wrapper/screen/ScreenDensity.kt +++ b/mapper-roborazzi/src/main/java/sergio/sastre/uitesting/mapper/roborazzi/wrapper/screen/ScreenDensity.kt @@ -1,26 +1,31 @@ package sergio.sastre.uitesting.mapper.roborazzi.wrapper.screen -enum class ScreenDensity(val qualifier: String) { - XXXHDPI("xxxhdpi"), - DPI_560("560dpi"), - XXHDPI("xxhdpi"), - DPI_440("440dpi"), - DPI_420("420dpi"), - DPI_400("400dpi"), - DPI_360("360dpi"), - XHDPI("xhdpi"), - DPI_260("260dpi"), - DPI_280("280dpi"), - DPI_300("300dpi"), - DPI_340("340dpi"), - HDPI("hdpi"), - DPI_220("220dpi"), - TVDPI("tvdpi"), - DPI_200("200dpi"), - DPI_180("180dpi"), - MDPI("mdpi"), - DPI_140("140dpi"), - LDPI("ldpi"), - ANYDPI("anydpi"), - NODPI("nodpi"), +interface DpiDensity { + val dpi: Int + class Value(override val dpi: Int) : DpiDensity +} + +enum class ScreenDensity(val qualifier: String, override val dpi: Int): DpiDensity { + XXXHDPI("xxxhdpi", 640), + DPI_560("560dpi", 560), + XXHDPI("xxhdpi", 480), + DPI_440("440dpi", 440), + DPI_420("420dpi", 420), + DPI_400("400dpi", 400), + DPI_360("360dpi", 360), + XHDPI("xhdpi", 480), + DPI_260("260dpi", 260), + DPI_280("280dpi", 280), + DPI_300("300dpi", 300), + DPI_340("340dpi", 340), + HDPI("hdpi", 240), + DPI_220("220dpi", 220), + TVDPI("tvdpi", 213), + DPI_200("200dpi", 200), + DPI_180("180dpi", 180), + MDPI("mdpi", 160), + DPI_140("140dpi", 140), + LDPI("ldpi", 120), + ANYDPI("anydpi", 0xFFFE), + NODPI("nodpi", 0xFFFF), } diff --git a/paparazzi/build.gradle b/paparazzi/build.gradle index 5496f92..0962b51 100644 --- a/paparazzi/build.gradle +++ b/paparazzi/build.gradle @@ -48,7 +48,7 @@ android { dependencies { implementation project(':utils') api project(':mapper-paparazzi') - api('app.cash.paparazzi:paparazzi:1.3.4') + api('app.cash.paparazzi:paparazzi:1.3.5') } //https://www.talentica.com/blogs/publish-your-android-library-on-jitpack-for-better-reachability/ @@ -57,7 +57,7 @@ publishing { release(MavenPublication) { groupId = 'com.github.sergio-sastre' artifactId = "paparazzi" - version = '2.5.0' + version = '2.6.0' afterEvaluate { from components.release diff --git a/paparazzi/src/main/java/sergio/sastre/uitesting/paparazzi/config/PaparazziForComposableTestRuleBuilder.kt b/paparazzi/src/main/java/sergio/sastre/uitesting/paparazzi/config/PaparazziForComposableTestRuleBuilder.kt index 6fa08f0..f93a462 100644 --- a/paparazzi/src/main/java/sergio/sastre/uitesting/paparazzi/config/PaparazziForComposableTestRuleBuilder.kt +++ b/paparazzi/src/main/java/sergio/sastre/uitesting/paparazzi/config/PaparazziForComposableTestRuleBuilder.kt @@ -36,6 +36,8 @@ class PaparazziForComposableTestRuleBuilder { maxPercentDifference = paparazziConfig.maxPercentageDiff, environment = sharedTestAdapter.asEnvironment(), renderExtensions = sharedTestAdapter.asRenderExtensions(), + useDeviceResolution = paparazziConfig.useDeviceResolution, + validateAccessibility = paparazziConfig.validateAccessibility, ) } } \ No newline at end of file diff --git a/paparazzi/src/main/java/sergio/sastre/uitesting/paparazzi/config/PaparazziWrapperConfigAdapter.kt b/paparazzi/src/main/java/sergio/sastre/uitesting/paparazzi/config/PaparazziWrapperConfigAdapter.kt index 86cf5c3..afacd4c 100644 --- a/paparazzi/src/main/java/sergio/sastre/uitesting/paparazzi/config/PaparazziWrapperConfigAdapter.kt +++ b/paparazzi/src/main/java/sergio/sastre/uitesting/paparazzi/config/PaparazziWrapperConfigAdapter.kt @@ -61,6 +61,7 @@ internal class PaparazziWrapperConfigAdapter( PaparazziWrapperDensity.LOW -> Density.LOW PaparazziWrapperDensity.ANYDPI -> Density.ANYDPI PaparazziWrapperDensity.NODPI -> Density.NODPI + else -> Density(config.density.dpi) } fun asPaparazziScreenRatio(): ScreenRatio = @@ -99,7 +100,6 @@ internal class PaparazziWrapperConfigAdapter( val environment = detectEnvironment() val configEnvironment = paparazziConfig.environment return environment.copy( - platformDir = configEnvironment?.platformDir ?: environment.platformDir, compileSdkVersion = configEnvironment?.compileSdkVersion ?: environment.compileSdkVersion, appTestDir = configEnvironment?.appTestDir ?: environment.appTestDir, diff --git a/robolectric/build.gradle b/robolectric/build.gradle index 2c479c4..7b0efc9 100644 --- a/robolectric/build.gradle +++ b/robolectric/build.gradle @@ -41,7 +41,7 @@ android { dependencies { implementation project(':utils') - implementation "org.robolectric:robolectric:4.13" + implementation "org.robolectric:robolectric:4.14" } //https://www.talentica.com/blogs/publish-your-android-library-on-jitpack-for-better-reachability/ @@ -50,7 +50,7 @@ publishing { release(MavenPublication) { groupId = 'com.github.sergio-sastre' artifactId = "robolectric" - version = '2.5.0' + version = '2.6.0' afterEvaluate { from components.release diff --git a/robolectric/src/main/java/sergio/sastre/uitesting/robolectric/config/RobolectricQualifiersBuilder.kt b/robolectric/src/main/java/sergio/sastre/uitesting/robolectric/config/RobolectricQualifiersBuilder.kt index 9e4614b..95d3455 100644 --- a/robolectric/src/main/java/sergio/sastre/uitesting/robolectric/config/RobolectricQualifiersBuilder.kt +++ b/robolectric/src/main/java/sergio/sastre/uitesting/robolectric/config/RobolectricQualifiersBuilder.kt @@ -20,7 +20,7 @@ object RobolectricQualifiersBuilder { round?.let { listOfQualifiers.add(it.qualifier) } orientationQualifier(configOrientation).let { listOfQualifiers.add(it) } type?.let { listOfQualifiers.add(it.qualifier) } - density.let { listOfQualifiers.add(it.qualifier) } + density.let { listOfQualifiers.add(it.valueAsQualifier()) } setQualifiers(listOfQualifiers.joinToString(separator = "-")) } diff --git a/robolectric/src/main/java/sergio/sastre/uitesting/robolectric/config/screen/DeviceScreen.kt b/robolectric/src/main/java/sergio/sastre/uitesting/robolectric/config/screen/DeviceScreen.kt index d9a69d3..ddfe7de 100644 --- a/robolectric/src/main/java/sergio/sastre/uitesting/robolectric/config/screen/DeviceScreen.kt +++ b/robolectric/src/main/java/sergio/sastre/uitesting/robolectric/config/screen/DeviceScreen.kt @@ -9,7 +9,7 @@ data class DeviceScreen( val heightDp: Int, val size: ScreenSize = ScreenSize.NORMAL, val aspect: ScreenAspect = ScreenAspect.NOTLONG, - val density: ScreenDensity = ScreenDensity.MDPI, + val density: DpiDensity = ScreenDensity.MDPI, val defaultOrientation: ScreenOrientation = ScreenOrientation.PORTRAIT, val round: RoundScreen? = null, val type: ScreenType? = null, diff --git a/robolectric/src/main/java/sergio/sastre/uitesting/robolectric/config/screen/ScreenDensity.kt b/robolectric/src/main/java/sergio/sastre/uitesting/robolectric/config/screen/ScreenDensity.kt index e941f64..bdc06d1 100644 --- a/robolectric/src/main/java/sergio/sastre/uitesting/robolectric/config/screen/ScreenDensity.kt +++ b/robolectric/src/main/java/sergio/sastre/uitesting/robolectric/config/screen/ScreenDensity.kt @@ -1,26 +1,37 @@ package sergio.sastre.uitesting.robolectric.config.screen -enum class ScreenDensity(val qualifier: String) { - XXXHDPI("xxxhdpi"), - DPI_560("560dpi"), - XXHDPI("xxhdpi"), - DPI_440("440dpi"), - DPI_420("420dpi"), - DPI_400("400dpi"), - DPI_360("360dpi"), - XHDPI("xhdpi"), - DPI_260("260dpi"), - DPI_280("280dpi"), - DPI_300("300dpi"), - DPI_340("340dpi"), - HDPI("hdpi"), - DPI_220("220dpi"), - TVDPI("tvdpi"), - DPI_200("200dpi"), - DPI_180("180dpi"), - MDPI("mdpi"), - DPI_140("140dpi"), - LDPI("ldpi"), - ANYDPI("anydpi"), - NODPI("nodpi"), +interface DpiDensity { + val dpi: Int + class Value(override val dpi: Int) : DpiDensity + + fun valueAsQualifier(): String = + when (this is ScreenDensity) { + true -> this.qualifier + false -> this.dpi.toString() + "dpi" + } +} + +enum class ScreenDensity(val qualifier: String, override val dpi: Int): DpiDensity { + XXXHDPI("xxxhdpi", 640), + DPI_560("560dpi", 560), + XXHDPI("xxhdpi", 480), + DPI_440("440dpi", 440), + DPI_420("420dpi", 420), + DPI_400("400dpi", 400), + DPI_360("360dpi", 360), + XHDPI("xhdpi", 480), + DPI_260("260dpi", 260), + DPI_280("280dpi", 280), + DPI_300("300dpi", 300), + DPI_340("340dpi", 340), + HDPI("hdpi", 240), + DPI_220("220dpi", 220), + TVDPI("tvdpi", 213), + DPI_200("200dpi", 200), + DPI_180("180dpi", 180), + MDPI("mdpi", 160), + DPI_140("140dpi", 140), + LDPI("ldpi", 120), + ANYDPI("anydpi", 0xFFFE), + NODPI("nodpi", 0xFFFF), } diff --git a/roborazzi/build.gradle b/roborazzi/build.gradle index d40c011..53ae775 100644 --- a/roborazzi/build.gradle +++ b/roborazzi/build.gradle @@ -51,11 +51,12 @@ dependencies { implementation project(':robolectric') implementation project(':mapper-roborazzi') - api 'io.github.takahirom.roborazzi:roborazzi:1.26.0' - api 'androidx.test.espresso:espresso-core:3.5.1' - api 'org.hamcrest:hamcrest:2.2' + implementation("org.hamcrest:hamcrest:2.2") + implementation("io.github.darkxanter:webp-imageio:0.3.3") + implementation("androidx.activity:activity-compose:1.9.2") - api 'androidx.activity:activity-compose:1.9.2' + api 'io.github.takahirom.roborazzi:roborazzi:1.32.2' + api 'androidx.test.espresso:espresso-core:3.5.1' } //https://www.talentica.com/blogs/publish-your-android-library-on-jitpack-for-better-reachability/ @@ -64,7 +65,7 @@ publishing { release(MavenPublication) { groupId = 'com.github.sergio-sastre' artifactId = "roborazzi" - version = '2.5.0' + version = '2.6.0' afterEvaluate { from components.release diff --git a/roborazzi/src/main/java/sergio/sastre/uitesting/roborazzi/config/RoborazziSharedTestAdapter.kt b/roborazzi/src/main/java/sergio/sastre/uitesting/roborazzi/config/RoborazziSharedTestAdapter.kt index 7c403d2..49de3b3 100644 --- a/roborazzi/src/main/java/sergio/sastre/uitesting/roborazzi/config/RoborazziSharedTestAdapter.kt +++ b/roborazzi/src/main/java/sergio/sastre/uitesting/roborazzi/config/RoborazziSharedTestAdapter.kt @@ -2,10 +2,13 @@ package sergio.sastre.uitesting.roborazzi.config import com.dropbox.differ.ImageComparator import com.dropbox.differ.SimpleImageComparator +import com.github.takahirom.roborazzi.AiAssertionOptions import com.github.takahirom.roborazzi.Dump import com.github.takahirom.roborazzi.Dump.Companion.AccessibilityExplanation import com.github.takahirom.roborazzi.Dump.Companion.DefaultExplanation import com.github.takahirom.roborazzi.ExperimentalRoborazziApi +import com.github.takahirom.roborazzi.JvmImageIoFormat +import com.github.takahirom.roborazzi.LosslessWebPImageIoFormat import com.github.takahirom.roborazzi.RoborazziOptions import com.github.takahirom.roborazzi.ThresholdValidator import sergio.sastre.uitesting.robolectric.config.screen.DeviceScreen @@ -16,8 +19,12 @@ import sergio.sastre.uitesting.robolectric.config.screen.ScreenOrientation import sergio.sastre.uitesting.robolectric.config.screen.ScreenSize import sergio.sastre.uitesting.robolectric.config.screen.ScreenType import sergio.sastre.uitesting.mapper.roborazzi.RoborazziConfig +import sergio.sastre.uitesting.mapper.roborazzi.wrapper.AiAssertion import sergio.sastre.uitesting.mapper.roborazzi.wrapper.ComparisonStyle import sergio.sastre.uitesting.mapper.roborazzi.wrapper.DumpExplanation +import sergio.sastre.uitesting.mapper.roborazzi.wrapper.ImageIoFormat.* +import sergio.sastre.uitesting.robolectric.config.screen.DpiDensity +import sergio.sastre.uitesting.robolectric.config.screen.DpiDensity.* import sergio.sastre.uitesting.mapper.roborazzi.wrapper.CaptureType as WrapperCaptureType import sergio.sastre.uitesting.mapper.roborazzi.wrapper.screen.RoundScreen as WrapperRoundScreen import sergio.sastre.uitesting.mapper.roborazzi.wrapper.screen.ScreenDensity as WrapperDensity @@ -76,6 +83,10 @@ internal class RoborazziSharedTestAdapter( RoborazziOptions.RecordOptions( resizeScale = it.recordOptions.resizeScale, applyDeviceCrop = it.recordOptions.applyDeviceCrop, + imageIoFormat = when (it.recordOptions.imageIoFormat) { + ImageIoFormat -> JvmImageIoFormat() + LosslessWebPImageIoFormat -> LosslessWebPImageIoFormat() + } ) return RoborazziOptions( @@ -83,10 +94,27 @@ internal class RoborazziSharedTestAdapter( compareOptions = adaptedCompareOptions, contextData = it.contextData, recordOptions = adaptedRecordOptions, - ) + ).addedAiAssertions(it.aiAssertions) } } + @OptIn(ExperimentalRoborazziApi::class) + private fun RoborazziOptions.addedAiAssertions( + aiAssertions: List + ) : RoborazziOptions = + if (aiAssertions.isEmpty()) { + this + } else { + val addedAiAssertions = aiAssertions.map { aiAssertion -> + AiAssertionOptions.AiAssertion( + assertionPrompt = aiAssertion.assertionPrompt, + requiredFulfillmentPercent = aiAssertion.requiredFulfillmentPercent, + failIfNotFulfilled = true + ) + }.toTypedArray() + addedAiAssertions(*addedAiAssertions) + } + @ExperimentalRoborazziApi private fun asComparisonStyle(): RoborazziOptions.CompareOptions.ComparisonStyle = when ( @@ -146,12 +174,12 @@ internal class RoborazziSharedTestAdapter( } } ?: ScreenSize.NORMAL - private fun asDensity(): ScreenDensity = + private fun asDensity(): DpiDensity = config?.let { when (it.density) { WrapperDensity.XXXHDPI -> ScreenDensity.XXXHDPI WrapperDensity.DPI_560 -> ScreenDensity.DPI_560 - WrapperDensity.XXHDPI -> ScreenDensity.XXXHDPI + WrapperDensity.XXHDPI -> ScreenDensity.XXHDPI WrapperDensity.DPI_440 -> ScreenDensity.DPI_440 WrapperDensity.DPI_420 -> ScreenDensity.DPI_420 WrapperDensity.DPI_400 -> ScreenDensity.DPI_400 @@ -171,6 +199,7 @@ internal class RoborazziSharedTestAdapter( WrapperDensity.LDPI -> ScreenDensity.LDPI WrapperDensity.ANYDPI -> ScreenDensity.ANYDPI WrapperDensity.NODPI -> ScreenDensity.NODPI + else -> Value(it.density.dpi) } } ?: ScreenDensity.MDPI diff --git a/shot/build.gradle b/shot/build.gradle index d1a8ec4..e62f192 100644 --- a/shot/build.gradle +++ b/shot/build.gradle @@ -61,7 +61,7 @@ publishing { release(MavenPublication) { groupId = 'com.github.sergio-sastre' artifactId = "shot" - version = '2.5.0' + version = '2.6.0' afterEvaluate { from components.release diff --git a/shot/src/main/java/sergio/sastre/uitesting/shot/ShotConfig.kt b/shot/src/main/java/sergio/sastre/uitesting/shot/ShotConfig.kt index 7871904..d4f2aee 100644 --- a/shot/src/main/java/sergio/sastre/uitesting/shot/ShotConfig.kt +++ b/shot/src/main/java/sergio/sastre/uitesting/shot/ShotConfig.kt @@ -10,7 +10,7 @@ import sergio.sastre.uitesting.utils.crosslibrary.config.LibraryConfig * 1. Requires bitmapCaptureMethod = null * 2. Works only with Views, not with Composables */ -class ShotConfig( +data class ShotConfig( val ignoredViews: List = emptyList(), val prepareUIForScreenshot: () -> Unit = {}, val bitmapCaptureMethod: BitmapCaptureMethod? = null, diff --git a/utils/build.gradle b/utils/build.gradle index 41b0bfc..8091bfb 100644 --- a/utils/build.gradle +++ b/utils/build.gradle @@ -71,7 +71,7 @@ publishing { release(MavenPublication) { groupId = 'com.github.sergio-sastre' artifactId = "utils" - version = '2.5.0' + version = '2.6.0' afterEvaluate { from components.release