paparazzi
paparazzi copied to clipboard
paparazzi.gif fails with IllegalArgumentException
Description Trying to run paparazzi.gif fails with this stacktrace:
java.lang.IllegalArgumentException: Component 1 width should be a multiple of 2 for colorspace: YUV420J
at org.jcodec.common.model.Picture.<init>(Picture.java:54)
at org.jcodec.common.model.Picture.createCropped(Picture.java:94)
at org.jcodec.common.model.Picture.create(Picture.java:75)
at org.jcodec.api.transcode.PixelStoreImpl.getPicture(PixelStoreImpl.java:25)
at org.jcodec.api.SequenceEncoder.encodeNativeFrame(SequenceEncoder.java:94)
at org.jcodec.api.awt.AWTSequenceEncoder.encodeImage(AWTSequenceEncoder.java:49)
at app.cash.paparazzi.HtmlReportWriter.writeVideo(HtmlReportWriter.kt:170)
at app.cash.paparazzi.HtmlReportWriter.access$writeVideo(HtmlReportWriter.kt:60)
at app.cash.paparazzi.HtmlReportWriter$newFrameHandler$1.close(HtmlReportWriter.kt:109)
at kotlin.io.CloseableKt.closeFinally(Closeable.kt:56)
at app.cash.paparazzi.Paparazzi.takeSnapshots(Paparazzi.kt:270)
at app.cash.paparazzi.Paparazzi.gif(Paparazzi.kt:217)
at app.cash.paparazzi.Paparazzi.gif$default(Paparazzi.kt:204)
at com.app.testapp.ui.ScreenshotRule.takeGifLocalized(ScreenshotRule.kt:52)
at com.app.testapp.ui.ScreenshotRule.takeGifLocalized$default(ScreenshotRule.kt:42)
at com.app.testapp.ui.login.LoginManualScreenshotTest.login_manual(LoginManualScreenshotTest.kt:17)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at app.cash.paparazzi.Paparazzi$apply$statement$1.evaluate(Paparazzi.kt:118)
at app.cash.paparazzi.agent.AgentTestRule$apply$1.evaluate(AgentTestRule.kt:17)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:110)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:38)
at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:62)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
at com.sun.proxy.$Proxy2.processTestClass(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker$2.run(TestWorker.java:176)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:133)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71)
at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
Steps to Reproduce Steps to reproduce are simple, just run a test and try to record a gif, even with very simple layout.
The test:
class SimpleGifTest {
@get:Rule
val screenshotRule = ScreenshotRule()
@Test
fun gifTest() {
screenshotRule.takeGifLocalized("simple_gif", R.layout.layout_settings_row, locale = "en")
}
}
The custom test rule:
class ScreenshotRule : TestRule {
private val paparazzi = Paparazzi(
deviceConfig = DeviceConfig.PIXEL_4,
theme = "MaterialTheme.Custom",
environment = detectEnvironment(),
supportsRtl = true
)
fun takeScreenshotLocalized(
screenshotName: String,
@LayoutRes viewResourceId: Int,
locale: String,
viewModeller: (view: View) -> View = { v -> v }
) {
paparazzi.unsafeUpdateConfig(deviceConfig = DeviceConfig.PIXEL_4.copy(locale = locale))
val view = paparazzi.inflate<View>(viewResourceId)
val modelledView = viewModeller(view)
paparazzi.snapshot(
modelledView,
name = "${screenshotName}_${locale}",
)
}
fun takeGifLocalized(
screenshotName: String,
@LayoutRes viewResourceId: Int,
locale: String,
viewModeller: (view: View) -> View = { v -> v }
) {
paparazzi.unsafeUpdateConfig(deviceConfig = DeviceConfig.PIXEL_4.copy(locale = locale))
val view = paparazzi.inflate<View>(viewResourceId)
val modelledView = viewModeller(view)
paparazzi.gif(
modelledView,
name = "${screenshotName}_${locale}",
)
}
override fun apply(base: Statement, description: Description): Statement {
return paparazzi.apply(base, description)
}
}
The layout:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingVertical="@dimen/default_margin">
<TextView
android:id="@+id/title_text_view"
style="@style/TextAppearance.Custom.Headline4"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="@dimen/default_margin"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/disclosure_image_view"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="This is a long title that may go on two lines and it is supposed to, isn't it?" />
<ImageView
android:id="@+id/disclosure_image_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/default_margin"
android:scaleType="fitEnd"
android:src="@drawable/ic_chevron_right_black"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Expected behavior Gif recorded
Additional information:
- Paparazzi Version: 1.2.0
- OS: MacOS Ventura 13.2.1
- Compile SDK: 33
- Gradle Version: 7.5.1
- Android Gradle Plugin Version: 7.3.1