Skip to content

Commit

Permalink
Merge pull request #527 from takahirom/takahirom/extension-changeable…
Browse files Browse the repository at this point in the history
…/2024-10-31

Make image extension changeable
  • Loading branch information
takahirom authored Nov 6, 2024
2 parents d1c65c0 + a5f7d45 commit ccc74c6
Show file tree
Hide file tree
Showing 23 changed files with 419 additions and 256 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/CompareScreenshotComment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ jobs:
shell: bash
run: |
# Find all the files ending with _compare.png
mapfile -t files_to_add < <(find . -type f -name "*_compare.png")
mapfile -t files_to_add < <(find . -type f -name "*_compare.*")
# Check for invalid file names and add only valid ones
exist_valid_files="false"
Expand All @@ -79,7 +79,7 @@ jobs:
BRANCH_NAME: companion_${{ github.event.workflow_run.head_branch }}
run: |
# Find all the files ending with _compare.png
files_to_add=$(find . -type f -name "*_compare.png")
files_to_add=$(find . -type f -name "*_compare.*")
# Check for invalid file names and add only valid ones
for file in $files_to_add; do
Expand All @@ -99,7 +99,7 @@ jobs:
shell: bash
run: |
# Find all the files ending with _compare.png in roborazzi folder
files=$(find . -type f -name "*_compare.png" | grep "roborazzi/" | grep -E "^[a-zA-Z0-9_./-]+$")
files=$(find . -type f -name "*_compare.*" | grep "roborazzi/" | grep -E "^[a-zA-Z0-9_./-]+$")
delimiter="$(openssl rand -hex 8)"
{
echo "reports<<${delimiter}"
Expand Down
128 changes: 38 additions & 90 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -692,7 +692,7 @@ fun captureRoboGifSample() {
<img width="350" src="https://user-images.githubusercontent.com/1386930/226362212-35d34c9e-6df1-4671-8949-10fad7ad98c9.gif" />
### Automatically generate gif with test rule
### Generate gif with test rule
> **Note**
> You **don't need to use RoborazziRule** if you're using captureRoboImage().
Expand Down Expand Up @@ -732,7 +732,7 @@ class RuleTestWithOnlyFail {
}
```
### Automatically generate Jetpack Compose gif with test rule
### Generate Jetpack Compose gif with test rule
Test target
Expand Down Expand Up @@ -869,94 +869,6 @@ class RoborazziRule private constructor(
}
```
### Roborazzi options
```kotlin
data class RoborazziOptions(
val captureType: CaptureType = if (isNativeGraphicsEnabled()) CaptureType.Screenshot() else CaptureType.Dump(),
val compareOptions: CompareOptions = CompareOptions(),
val recordOptions: RecordOptions = RecordOptions(),
) {
sealed interface CaptureType {
class Screenshot : CaptureType
data class Dump(
val takeScreenShot: Boolean = isNativeGraphicsEnabled(),
val basicSize: Int = 600,
val depthSlideSize: Int = 30,
val query: ((RoboComponent) -> Boolean)? = null,
val explanation: ((RoboComponent) -> String?) = DefaultExplanation,
) : CaptureType {
companion object {
val DefaultExplanation: ((RoboComponent) -> String) = {
it.text
}
val AccessibilityExplanation: ((RoboComponent) -> String) = {
it.accessibilityText
}
}
}
}
data class CompareOptions(
val roborazziCompareReporter: RoborazziCompareReporter = RoborazziCompareReporter(),
val resultValidator: (result: ImageComparator.ComparisonResult) -> Boolean,
) {
constructor(
roborazziCompareReporter: RoborazziCompareReporter = RoborazziCompareReporter(),
/**
* This value determines the threshold of pixel change at which the diff image is output or not.
* The value should be between 0 and 1
*/
changeThreshold: Float = 0.01F,
) : this(roborazziCompareReporter, ThresholdValidator(changeThreshold))
}
interface RoborazziCompareReporter {
fun report(compareReportCaptureResult: CompareReportCaptureResult)
companion object {
operator fun invoke(): RoborazziCompareReporter {
...
}
}
class JsonOutputRoborazziCompareReporter : RoborazziCompareReporter {
...
override fun report(compareReportCaptureResult: CompareReportCaptureResult) {
...
}
}
class VerifyRoborazziCompareReporter : RoborazziCompareReporter {
override fun report(compareReportCaptureResult: CompareReportCaptureResult) {
...
}
}
}
data class RecordOptions(
val resizeScale: Double = roborazziDefaultResizeScale(),
val applyDeviceCrop: Boolean = false,
val pixelBitConfig: PixelBitConfig = PixelBitConfig.Argb8888,
)
enum class PixelBitConfig {
Argb8888,
Rgb565;
fun toBitmapConfig(): Bitmap.Config {
...
}
fun toBufferedImageType(): Int {
...
}
}
}
```
#### Image comparator custom settings
When comparing images, you may encounter differences due to minor changes related to antialiasing. You can use the options below to avoid this.
```kotlin
Expand All @@ -977,12 +889,48 @@ val roborazziRule = RoborazziRule(
)
```
### Experimental WebP support and other image formats
You can set `roborazzi.record.image.extension` to `webp` in your `gradle.properties` file to generate WebP images.
```kotlin
roborazzi.record.image.extension=webp
```
WebP is a lossy image format by default, which can make managing image differences challenging. To address this, we provide a lossless WebP image comparison feature.
To enable WebP support, add `testImplementation("io.github.darkxanter:webp-imageio:0.3.3")` to your `build.gradle.kts` file.
```kotlin
onView(ViewMatchers.withId(R.id.textview_first))
.captureRoboImage(
roborazziOptions = RoborazziOptions(
recordOptions = RoborazziOptions.RecordOptions(
imageIoFormat = LosslessWebPImageIoFormat(),
),
)
)
```
You can also use other image formats by implementing your own `AwtImageWriter` and `AwtImageLoader`.
```kotlin
data class JvmImageIoFormat(
val awtImageWriter: AwtImageWriter,
val awtImageLoader: AwtImageLoader
) : ImageIoFormat
```
### Dump mode
If you are having trouble debugging your test, try Dump mode as follows.
![image](https://user-images.githubusercontent.com/1386930/226364158-a07a0fb0-d8e7-46b7-a495-8dd217faaadb.png)
### Roborazzi options
Please check out [RoborazziOptions](https://github.com/takahirom/roborazzi/blob/main/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/RoborazziOptions.kt) for available Roborazzi options.
</div>
<div name="topic_preview_support">
Expand Down
128 changes: 38 additions & 90 deletions docs/topics/how_to_use.md
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ fun captureRoboGifSample() {
<img width="350" src="https://user-images.githubusercontent.com/1386930/226362212-35d34c9e-6df1-4671-8949-10fad7ad98c9.gif" />
### Automatically generate gif with test rule
### Generate gif with test rule
> **Note**
> You **don't need to use RoborazziRule** if you're using captureRoboImage().
Expand Down Expand Up @@ -409,7 +409,7 @@ class RuleTestWithOnlyFail {
}
```
### Automatically generate Jetpack Compose gif with test rule
### Generate Jetpack Compose gif with test rule
Test target
Expand Down Expand Up @@ -546,94 +546,6 @@ class RoborazziRule private constructor(
}
```
### Roborazzi options
```kotlin
data class RoborazziOptions(
val captureType: CaptureType = if (isNativeGraphicsEnabled()) CaptureType.Screenshot() else CaptureType.Dump(),
val compareOptions: CompareOptions = CompareOptions(),
val recordOptions: RecordOptions = RecordOptions(),
) {
sealed interface CaptureType {
class Screenshot : CaptureType
data class Dump(
val takeScreenShot: Boolean = isNativeGraphicsEnabled(),
val basicSize: Int = 600,
val depthSlideSize: Int = 30,
val query: ((RoboComponent) -> Boolean)? = null,
val explanation: ((RoboComponent) -> String?) = DefaultExplanation,
) : CaptureType {
companion object {
val DefaultExplanation: ((RoboComponent) -> String) = {
it.text
}
val AccessibilityExplanation: ((RoboComponent) -> String) = {
it.accessibilityText
}
}
}
}
data class CompareOptions(
val roborazziCompareReporter: RoborazziCompareReporter = RoborazziCompareReporter(),
val resultValidator: (result: ImageComparator.ComparisonResult) -> Boolean,
) {
constructor(
roborazziCompareReporter: RoborazziCompareReporter = RoborazziCompareReporter(),
/**
* This value determines the threshold of pixel change at which the diff image is output or not.
* The value should be between 0 and 1
*/
changeThreshold: Float = 0.01F,
) : this(roborazziCompareReporter, ThresholdValidator(changeThreshold))
}
interface RoborazziCompareReporter {
fun report(compareReportCaptureResult: CompareReportCaptureResult)
companion object {
operator fun invoke(): RoborazziCompareReporter {
...
}
}
class JsonOutputRoborazziCompareReporter : RoborazziCompareReporter {
...
override fun report(compareReportCaptureResult: CompareReportCaptureResult) {
...
}
}
class VerifyRoborazziCompareReporter : RoborazziCompareReporter {
override fun report(compareReportCaptureResult: CompareReportCaptureResult) {
...
}
}
}
data class RecordOptions(
val resizeScale: Double = roborazziDefaultResizeScale(),
val applyDeviceCrop: Boolean = false,
val pixelBitConfig: PixelBitConfig = PixelBitConfig.Argb8888,
)
enum class PixelBitConfig {
Argb8888,
Rgb565;
fun toBitmapConfig(): Bitmap.Config {
...
}
fun toBufferedImageType(): Int {
...
}
}
}
```
#### Image comparator custom settings
When comparing images, you may encounter differences due to minor changes related to antialiasing. You can use the options below to avoid this.
```kotlin
Expand All @@ -654,8 +566,44 @@ val roborazziRule = RoborazziRule(
)
```
### Experimental WebP support and other image formats
You can set `roborazzi.record.image.extension` to `webp` in your `gradle.properties` file to generate WebP images.
```kotlin
roborazzi.record.image.extension=webp
```
WebP is a lossy image format by default, which can make managing image differences challenging. To address this, we provide a lossless WebP image comparison feature.
To enable WebP support, add `testImplementation("io.github.darkxanter:webp-imageio:0.3.3")` to your `build.gradle.kts` file.
```kotlin
onView(ViewMatchers.withId(R.id.textview_first))
.captureRoboImage(
roborazziOptions = RoborazziOptions(
recordOptions = RoborazziOptions.RecordOptions(
imageIoFormat = LosslessWebPImageIoFormat(),
),
)
)
```
You can also use other image formats by implementing your own `AwtImageWriter` and `AwtImageLoader`.
```kotlin
data class JvmImageIoFormat(
val awtImageWriter: AwtImageWriter,
val awtImageLoader: AwtImageLoader
) : ImageIoFormat
```
### Dump mode
If you are having trouble debugging your test, try Dump mode as follows.
![image](https://user-images.githubusercontent.com/1386930/226364158-a07a0fb0-d8e7-46b7-a495-8dd217faaadb.png)
### Roborazzi options
Please check out [RoborazziOptions](https://github.com/takahirom/roborazzi/blob/main/include-build/roborazzi-core/src/commonJvmMain/kotlin/com/github/takahirom/roborazzi/RoborazziOptions.kt) for available Roborazzi options.
2 changes: 2 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ kotlinx-io = "0.3.3"
webjar-material-design-icons = "4.0.0"
webjar-materialize = "1.0.0"
webjars-locator-lite = "0.0.6"
webpImageio = "0.3.3"

composable-preview-scanner = "0.4.0"

Expand Down Expand Up @@ -110,3 +111,4 @@ kotlinx-io-core = { module = "org.jetbrains.kotlinx:kotlinx-io-core", version.re
webjars-material-design-icons = { module = "org.webjars:material-design-icons", version.ref = "webjar-material-design-icons" }
webjars-materialize = { module = "org.webjars:materializecss", version.ref = "webjar-materialize" }
webjars-locator-lite = { module = "org.webjars:webjars-locator-lite", version.ref = "webjars-locator-lite" }
webp-imageio = { module = "io.github.darkxanter:webp-imageio", version.ref = "webpImageio" }
3 changes: 3 additions & 0 deletions include-build/roborazzi-core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ kotlin {
commonJvmMain {
dependencies {
implementation libs.junit
// The library is a little bit heavy, so we use compileOnly here.
// Users need to add this library to their dependencies.
compileOnly(libs.webp.imageio)
}
}
commonJvmTest {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ object DefaultFileNameGenerator {
}

@InternalRoborazziApi
fun generateFilePath(extension: String): String {
fun generateFilePath(extension: String = provideRoborazziContext().imageExtension): String {
val roborazziContext = provideRoborazziContext()
val fileCreator = roborazziContext.fileProvider
val description = roborazziContext.description
Expand Down
Loading

0 comments on commit ccc74c6

Please sign in to comment.