Skip to content

Commit

Permalink
gif snapshot handler
Browse files Browse the repository at this point in the history
  • Loading branch information
stevePanella committed Jan 24, 2024
1 parent f456b8b commit f3e4d87
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 7 deletions.
71 changes: 71 additions & 0 deletions paparazzi/src/main/java/app/cash/paparazzi/GifSnapshotHandler.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* Copyright (C) 2020 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package app.cash.paparazzi

import app.cash.paparazzi.SnapshotHandler.FrameHandler
import app.cash.paparazzi.internal.ImageUtils
import java.awt.image.BufferedImage
import java.io.File
import javax.imageio.ImageIO

class GifSnapshotHandler @JvmOverloads constructor(
private val maxPercentDifference: Double = 0.1,
rootDirectory: File = File(System.getProperty("paparazzi.snapshot.dir"))
) : SnapshotHandler {
private val imagesDirectory: File = File(rootDirectory, "images")
private val videosDirectory: File = File(rootDirectory, "videos")

init {
imagesDirectory.mkdirs()
videosDirectory.mkdirs()
}

override fun newFrameHandler(
snapshot: Snapshot,
frameCount: Int,
fps: Int
): FrameHandler {
return object : FrameHandler {
override fun handle(
image: BufferedImage,
frameIndex: Int?,
) {
// handle() gets called with each image when gif() is used
val expected = File(
imagesDirectory,
snapshot.toFileName(
extension = "png",
frameIndex = frameIndex
)
)
if (!expected.exists()) {
throw AssertionError("File $expected does not exist")
}
val goldenImage = ImageIO.read(expected)
ImageUtils.assertImageSimilar(
relativePath = expected.path,
image = image,
goldenImage = goldenImage,
maxPercentDifferent = maxPercentDifference
)
}

override fun close() = Unit
}
}

override fun close() = Unit
}
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ class HtmlReportWriter @JvmOverloads constructor(
return object : FrameHandler {
val hashes = mutableListOf<String>()

override fun handle(image: BufferedImage) {
override fun handle(image: BufferedImage, frameIndex: Int?) {
hashes += writeImage(image)
}

Expand All @@ -111,7 +111,8 @@ class HtmlReportWriter @JvmOverloads constructor(
if (isRecording) {
for ((index, frameHash) in hashes.withIndex()) {
val originalFrame = File(imagesDirectory, "$frameHash.png")
val frameSnapshot = snapshot.copy(name = "${snapshot.name} $index")
val name = snapshot.name?.let { "$it $index" } ?: "$index"
val frameSnapshot = snapshot.copy(name = name)
val goldenFile = File(goldenImagesDirectory, frameSnapshot.toFileName("_", "png"))
if (!goldenFile.exists()) {
originalFrame.copyTo(goldenFile)
Expand Down
9 changes: 8 additions & 1 deletion paparazzi/src/main/java/app/cash/paparazzi/Paparazzi.kt
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ class Paparazzi @JvmOverloads constructor(
}
validateLayoutAccessibility(modifiedView, image)
}
frameHandler.handle(scaleImage(frameImage(image)))
frameHandler.handle(scaleImage(frameImage(image)), frame)
}
}
} finally {
Expand Down Expand Up @@ -659,5 +659,12 @@ class Paparazzi @JvmOverloads constructor(
} else {
HtmlReportWriter()
}

fun determineGifHandler(maxPercentDifference: Double = 0.1): SnapshotHandler =
if (isVerifying) {
GifSnapshotHandler(maxPercentDifference)
} else {
HtmlReportWriter()
}
}
}
10 changes: 8 additions & 2 deletions paparazzi/src/main/java/app/cash/paparazzi/Snapshot.kt
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,18 @@ data class Snapshot(

internal fun Snapshot.toFileName(
delimiter: String = "_",
extension: String
extension: String,
frameIndex: Int? = null,
): String {
val formattedLabel = if (name != null) {
"$delimiter${name.toLowerCase(Locale.US).replace("\\s".toRegex(), delimiter)}"
} else {
""
}
return "${testName.packageName}${delimiter}${testName.className}${delimiter}${testName.methodName}$formattedLabel.$extension"
return if (frameIndex != null) {
"${testName.packageName}${delimiter}${testName.className}${delimiter}${testName.methodName}_$frameIndex.$extension"
} else {
"${testName.packageName}${delimiter}${testName.className}${delimiter}${testName.methodName}$formattedLabel.$extension"
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,6 @@ interface SnapshotHandler : Closeable {
): FrameHandler

interface FrameHandler : Closeable {
fun handle(image: BufferedImage)
fun handle(image: BufferedImage, frameIndex: Int? = null)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class SnapshotVerifier @JvmOverloads constructor(
fps: Int
): FrameHandler {
return object : FrameHandler {
override fun handle(image: BufferedImage) {
override fun handle(image: BufferedImage, frameIndex: Int?) {
// Note: does not handle videos or its frames at the moment
val expected = File(imagesDirectory, snapshot.toFileName(extension = "png"))
if (!expected.exists()) {
Expand Down

0 comments on commit f3e4d87

Please sign in to comment.