cashapp/Paparazzi
一言で表すと
物理デバイスやエミュレータなしで、画面をレンダーするやつ
概要
code:kotlin
class LaunchViewTest {
@get:Rule
val paparazzi = Paparazzi(
deviceConfig = PIXEL_5,
theme = "android:Theme.Material.Light.NoActionBar"
// ...see docs for more options
)
@Test
fun launchView() {
val view = paparazzi.inflate<LaunchView>(R.layout.launch)
// or...
// val view = LaunchView(paparazzi.context)
view.setModel(LaunchModel(title = "paparazzi"))
paparazzi.snapshot(view)
}
@Test
fun launchComposable() {
paparazzi.snapshot {
MyComposable()
}
}
}
Paparazzi() でテストルールを作成し、paparazzi.snapshot() なり、paparazzi.snapshot{}なりで snapshot を取れる
Paparazzi で指定できるconfig
code:kotlin
fun Paparazzi(
environment: Environment = detectEnvironment(),
deviceConfig: DeviceConfig = DeviceConfig.NEXUS_5,
theme: String = "android:Theme.Material.NoActionBar.Fullscreen",
renderingMode: SessionParams.RenderingMode = RenderingMode.NORMAL,
appCompatEnabled: Boolean = true,
maxPercentDifference: Double = 0.1,
snapshotHandler: SnapshotHandler = determineHandler(maxPercentDifference),
renderExtensions: Set<RenderExtension> = setOf()
)
地味に DeviceConfig はある程度指定できそう
code:kotlin
val screenHeight: Int = 1280,
val screenWidth: Int = 768,
val xdpi: Int = 320,
val ydpi: Int = 320,
val orientation: ScreenOrientation = ScreenOrientation.PORTRAIT,
val nightMode: NightMode = NOTNIGHT,
val density: Density = Density.XHIGH,
val fontScale: Float = 1f,
val layoutDirection: LayoutDirection = LayoutDirection.LTR,
val locale: String? = null,
val ratio: ScreenRatio = ScreenRatio.NOTLONG,
val size: ScreenSize = ScreenSize.NORMAL,
val keyboard: Keyboard = Keyboard.NOKEY,
val touchScreen: TouchScreen = TouchScreen.FINGER,
val keyboardState: KeyboardState = KeyboardState.SOFT,
val softButtons: Boolean = true,
val navigation: Navigation = Navigation.NONAV,
val released: String = "November 13, 2012"
どうやってviewを作ってるんだろう
Paparazzi.kt を上から読んで観る
layout inflator なるものは、RenderActionから作られている(これはなに?)
Composeもサポートしているが、基本的には中でAndroidViewに変換しているだけ。
code: kotlin
val hostView = ComposeView(context)
// During onAttachedToWindow, AbstractComposeView will attempt to resolve its parent's
// CompositionContext, which requires first finding the "content view", then using that to
// find a root view with a ViewTreeLifecycleOwner
val parent = FrameLayout(context).apply { id = android.R.id.content }
parent.addView(hostView, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
PaparazziComposeOwner.register(parent)
hostView.setContent(composable)
try {
snapshot(parent, name)
} finally {
forceReleaseComposeReferenceLeaks()
}
これすき𝑩𝑰𝑮 𝑳𝑶𝑽𝑬
code:kotlin
private val contentRoot = """
|<?xml version="1.0" encoding="utf-8"?>
| android:layout_width="match_parent"
| android:layout_height="match_parent"/>
""".trimMargin()
private fun takeSnapshots(...) が面白そうなので読む
farmeHandler をつくる(
気になるポイント
メモ
コメント
Go.icon Kotlinで書かれていて読みやすいですね