Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -495,12 +495,22 @@ private fun ApplicationVariant.configureSnapshotsTasks(
"io.github.sergio-sastre.ComposablePreviewScanner:android:0.8.1",
)

val paparazziMajorVersion =
project.provider {
val dep =
project.configurations.findByName("testImplementation")?.allDependencies?.find {
it.group == "app.cash.paparazzi" && it.name == "paparazzi"
}
parseMajorVersion(dep?.version)
}

val generateTask =
GenerateSnapshotTestsTask.register(
project,
extension.snapshots,
android,
this@configureSnapshotsTasks,
paparazziMajorVersion,
)

if (AgpVersions.isAGP90(AgpVersions.CURRENT)) {
Expand Down Expand Up @@ -537,6 +547,9 @@ private fun ApplicationVariant.configureSnapshotsTasks(
}
}

internal fun parseMajorVersion(version: String?, defaultVersion: Int = 2): Int =
version?.trimStart()?.takeWhile { it.isDigit() }?.toIntOrNull() ?: defaultVersion

/**
* Configure the upload AAB and APK tasks and set them up as finalizers on the respective producer
* tasks
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import org.gradle.api.Project
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.provider.ListProperty
import org.gradle.api.provider.Property
import org.gradle.api.provider.Provider
import org.gradle.api.tasks.CacheableTask
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.Optional
Expand All @@ -31,6 +32,8 @@ abstract class GenerateSnapshotTestsTask : DefaultTask() {

@get:Input @get:Optional abstract val theme: Property<String>

@get:Input abstract val paparazziMajorVersion: Property<Int>

@get:OutputDirectory abstract val outputDir: DirectoryProperty

@TaskAction
Expand All @@ -48,6 +51,7 @@ abstract class GenerateSnapshotTestsTask : DefaultTask() {
includePrivatePreviews = includePrivatePreviews.get(),
packageTrees = packageTrees.get(),
theme = theme.orNull,
paparazziMajorVersion = paparazziMajorVersion.get(),
)
File(packageDir, "$CLASS_NAME.kt").writeText(content)
logger.lifecycle("Generated snapshot test: ${packageDir.absolutePath}/$CLASS_NAME.kt")
Expand All @@ -62,13 +66,15 @@ abstract class GenerateSnapshotTestsTask : DefaultTask() {
extension: SnapshotsExtension,
android: BaseExtension,
variant: ApplicationVariant,
paparazziMajorVersion: Provider<Int>,
): TaskProvider<GenerateSnapshotTestsTask> {
return project.tasks.register(
"sentryGenerateSnapshotsTests${variant.name.capitalized}",
GenerateSnapshotTestsTask::class.java,
) { task ->
task.includePrivatePreviews.set(extension.includePrivatePreviews)
task.theme.set(extension.theme)
task.paparazziMajorVersion.value(paparazziMajorVersion)
// Fall back to the Android namespace when the user doesn't configure packageTrees
// TODO do we actually need this?
task.packageTrees.set(
Expand All @@ -87,6 +93,7 @@ abstract class GenerateSnapshotTestsTask : DefaultTask() {
includePrivatePreviews: Boolean,
packageTrees: List<String>,
theme: String? = null,
paparazziMajorVersion: Int = 2,
): String {
val includePrivateExpr =
if (includePrivatePreviews) "\n .includePrivatePreviews()" else ""
Expand Down Expand Up @@ -217,17 +224,17 @@ private class TestNameOverrideHandler(

private object PaparazziPreviewRule {
const val UNDEFINED_API_LEVEL = -1
const val MAX_API_LEVEL = 36

fun createFor(preview: ComposablePreview<AndroidPreviewInfo>): Paparazzi {
val previewInfo = preview.previewInfo
val previewApiLevel = when (previewInfo.apiLevel == UNDEFINED_API_LEVEL) {
true -> MAX_API_LEVEL
false -> previewInfo.apiLevel
val env = detectEnvironment()
val environment = when (previewInfo.apiLevel == UNDEFINED_API_LEVEL) {
true -> env
false -> env.copy(compileSdkVersion = previewInfo.apiLevel)
}
val tolerance = 0.0
return Paparazzi(
environment = detectEnvironment().copy(compileSdkVersion = previewApiLevel),
environment = environment,
deviceConfig = DeviceConfigBuilder.build(preview.previewInfo),
${if (theme != null) "theme = \"$theme\"," else ""}
supportsRtl = true,
Expand All @@ -240,7 +247,7 @@ private object PaparazziPreviewRule {
snapshotHandler = TestNameOverrideHandler(
when (System.getProperty("paparazzi.test.verify")?.toBoolean() == true) {
true -> SnapshotVerifier(maxPercentDifference = tolerance)
false -> HtmlReportWriter(maxPercentDifference = tolerance)
false -> ${if (paparazziMajorVersion >= 2) "HtmlReportWriter(maxPercentDifference = tolerance)" else "HtmlReportWriter()"}
}
),
maxPercentDifference = tolerance,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package io.sentry.android.gradle.snapshot

import io.sentry.android.gradle.parseMajorVersion
import java.io.File
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertTrue
import org.gradle.testfixtures.ProjectBuilder
Expand Down Expand Up @@ -124,11 +126,47 @@ class GenerateSnapshotTestsTaskTest {
)
}

@Test
fun `parseMajorVersion extracts major from standard semver`() {
assertEquals(1, parseMajorVersion("1.3.5"))
assertEquals(2, parseMajorVersion("2.0.0-alpha01"))
}

@Test
fun `parseMajorVersion extracts major from dynamic versions`() {
assertEquals(1, parseMajorVersion("1.+"))
assertEquals(2, parseMajorVersion("2.+"))
}

@Test
fun `parseMajorVersion returns default for unparseable versions`() {
assertEquals(2, parseMajorVersion("latest.release"))
assertEquals(2, parseMajorVersion(null))
assertEquals(2, parseMajorVersion("+"))
}

@Test
fun `generated file uses HtmlReportWriter without maxPercentDifference for paparazzi 1`() {
val content = generateAndRead(packageTrees = listOf("com.example"), paparazziMajorVersion = 1)

assertTrue(content.contains("HtmlReportWriter()"))
assertFalse(content.contains("HtmlReportWriter(maxPercentDifference"))
}

@Test
fun `generated file uses HtmlReportWriter with maxPercentDifference for paparazzi 2`() {
val content = generateAndRead(packageTrees = listOf("com.example"), paparazziMajorVersion = 2)

assertTrue(content.contains("HtmlReportWriter(maxPercentDifference = tolerance)"))
assertFalse(content.contains("HtmlReportWriter()"))
}

private fun generateAndRead(
packageTrees: List<String>,
includePrivatePreviews: Boolean = false,
paparazziMajorVersion: Int = 2,
): String {
val task = createTask(packageTrees, includePrivatePreviews)
val task = createTask(packageTrees, includePrivatePreviews, paparazziMajorVersion)
task.generate()
val file =
File(task.outputDir.get().asFile, "io/sentry/snapshot/ComposablePreviewSnapshotTest.kt")
Expand All @@ -138,12 +176,14 @@ class GenerateSnapshotTestsTaskTest {
private fun createTask(
packageTrees: List<String>,
includePrivatePreviews: Boolean = false,
paparazziMajorVersion: Int = 2,
): GenerateSnapshotTestsTask {
val project = ProjectBuilder.builder().build()
return project.tasks
.register("testGenerateSnapshotTests", GenerateSnapshotTestsTask::class.java) { task ->
task.includePrivatePreviews.set(includePrivatePreviews)
task.packageTrees.set(packageTrees)
task.paparazziMajorVersion.set(paparazziMajorVersion)
task.outputDir.set(tmpDir.newFolder("output"))
}
.get()
Expand Down
Loading