diff --git a/roborazzi-compose/src/main/java/com/github/takahirom/roborazzi/RoborazziCompose.kt b/roborazzi-compose/src/main/java/com/github/takahirom/roborazzi/RoborazziCompose.kt index df91a1c0..23f92e6e 100644 --- a/roborazzi-compose/src/main/java/com/github/takahirom/roborazzi/RoborazziCompose.kt +++ b/roborazzi-compose/src/main/java/com/github/takahirom/roborazzi/RoborazziCompose.kt @@ -106,19 +106,17 @@ private fun ActivityScenario.captureRoboImage( // Views needs to be laid out before we can capture them Espresso.onIdle() - val windowRoots = fetchRobolectricWindowRoots() - if (windowRoots.size <= 1) { - val composeView = activity.window.decorView - .findViewById(android.R.id.content) - .getChildAt(0) as ComposeView - @SuppressLint("VisibleForTests") - val viewRootForTest = composeView.getChildAt(0) as ViewRootForTest - viewRootForTest.view.captureRoboImage(file, roborazziOptions) - } else { - // Dialog case - roborazziReportLog("It seems that there are multiple windows." + - "We merge all windows using captureScreenRoboImage().") - captureScreenRoboImage(file, roborazziOptions) - } + captureScreenIfMultipleWindows( + file = file, + roborazziOptions = roborazziOptions, + captureSingleComponent = { + val composeView = activity.window.decorView + .findViewById(android.R.id.content) + .getChildAt(0) as ComposeView + @SuppressLint("VisibleForTests") + val viewRootForTest = composeView.getChildAt(0) as ViewRootForTest + viewRootForTest.view.captureRoboImage(file, roborazziOptions) + } + ) } } \ No newline at end of file diff --git a/roborazzi/src/main/java/com/github/takahirom/roborazzi/Roborazzi.kt b/roborazzi/src/main/java/com/github/takahirom/roborazzi/Roborazzi.kt index e86b2b86..3a4212a8 100644 --- a/roborazzi/src/main/java/com/github/takahirom/roborazzi/Roborazzi.kt +++ b/roborazzi/src/main/java/com/github/takahirom/roborazzi/Roborazzi.kt @@ -173,19 +173,38 @@ fun captureRootsInternal( } } +@InternalRoborazziApi +fun captureScreenIfMultipleWindows( + file: File, + roborazziOptions: RoborazziOptions, + captureSingleComponent: () -> Unit +) { + if (fetchRobolectricWindowRoots().size > 1) { + roborazziReportLog( + "It seems that there are multiple windows." + + "We capture all windows using captureScreenRoboImage(). " + + "We can add a flag to disable this behavior so please let us know if you need it." + ) + captureScreenRoboImage(file, roborazziOptions) + } else { + captureSingleComponent() + } +} + @InternalRoborazziApi fun fetchRobolectricWindowRoots(): List { try { @Suppress("INACCESSIBLE_TYPE") val rootsOracle = RootsOracle_Factory({ Looper.getMainLooper() }) .get() // Invoke rootOracle.listActiveRoots() via reflection - @Suppress("INACCESSIBLE_TYPE") val listActiveRoots = rootsOracle.javaClass.getMethod("listActiveRoots") + @Suppress("INACCESSIBLE_TYPE") val listActiveRoots = + rootsOracle.javaClass.getMethod("listActiveRoots") listActiveRoots.isAccessible = true @Suppress("UNCHECKED_CAST", "INACCESSIBLE_TYPE") val roots: List = (listActiveRoots.invoke(rootsOracle) as List ).sortedBy { it.windowLayoutParams.get()?.type } return roots - } catch(e: Throwable) { + } catch (e: Throwable) { e.printStackTrace() return emptyList() } @@ -300,20 +319,26 @@ fun SemanticsNodeInteraction.captureRoboImage( roborazziOptions: RoborazziOptions = provideRoborazziContext().options, ) { if (!roborazziOptions.taskType.isEnabled()) return - capture( - rootComponent = RoboComponent.Compose( - node = this.fetchSemanticsNode("fail to captureRoboImage"), - roborazziOptions = roborazziOptions - ), + captureScreenIfMultipleWindows( + file = file, roborazziOptions = roborazziOptions, - ) { canvas -> - processOutputImageAndReportWithDefaults( - canvas = canvas, - goldenFile = file, - roborazziOptions = roborazziOptions - ) - canvas.release() - } + captureSingleComponent = { + capture( + rootComponent = RoboComponent.Compose( + node = this.fetchSemanticsNode("fail to captureRoboImage"), + roborazziOptions = roborazziOptions + ), + roborazziOptions = roborazziOptions, + ) { canvas -> + processOutputImageAndReportWithDefaults( + canvas = canvas, + goldenFile = file, + roborazziOptions = roborazziOptions + ) + canvas.release() + } + } + ) } fun SemanticsNodeInteraction.captureRoboGif(