sergio-sastre / AndroidUiTestingUtils

A set of TestRules, ActivityScenarios and utils to facilitate UI and screenshot testing under given configurations: FontSizes, Locales...
MIT License
293 stars 14 forks source link

Dimensions of captured Bitmap are limited to a device screen size #54

Closed davidbilik closed 1 year ago

davidbilik commented 1 year ago

Hello, I am using this test to screenshot test some composables

abstract class ScreenshotTest {

    @get:Rule
    val rule = ActivityScenarioForComposableRule(
        config = ComposableConfigItem(
            displaySize = NORMAL,
            orientation = PORTRAIT,
        )
    )

    protected fun snapshotComposable(
        name: String,
        composable: @Composable () -> Unit
    ) {
        rule.activityScenario
            .onActivity { activity ->
                activity.setContent {
                    composable()
               }
            }
        rule.activity
            .waitForComposeView()
            .captureToBitmap()
            .get()
            .writeToTestStorage(name)
    }
}

and I've noticed that if the rendered view is higher than the screen height it's cut. Is there any way to get a bitmap of the whole view regardless of the device size? I've tried to play with displaySize property of a ComposableConfigItem but it's only scaling the image not solving the issue. Is it even something your library can affect?

Thanks for the input :)

davidbilik commented 1 year ago

Ok so I rewrote my test like this, without using your library,

abstract class ScreenshotTest {

    @get:Rule
    val rule = createComposeRule()

    protected fun snapshotComposable(
        name: String,
        composable: @Composable () -> Unit
    ) {
        rule.setContent {
                composable()
        }
        rule.onAllNodes(isRoot())
            .onFirst()
            .captureToImage()
            .asAndroidBitmap()
            .writeToTestStorage(name)
    }
}

and it's still the same :(

sergio-sastre commented 1 year ago

Hi @davidbilik ! I'm afraid that is because you are using captureToBitmap() or captureToImage() Those methods limit the bitmap to the window size i.e what is visible on the screen.

However, this library provides view.drawToBitmap(), which uses Canvas, which should allow you to take screenshots that outsize the screen window.

e.g.

abstract class ScreenshotTest {

    @get:Rule
    val rule = ActivityScenarioForComposableRule(
        config = ComposableConfigItem(
            orientation = PORTRAIT,
        )
    )

    protected fun snapshotComposable(
        name: String,
        composable: @Composable () -> Unit
    ) {
        rule.activityScenario
            .onActivity { activity ->
                activity.setContent {
                    composable()
               }
            }
        rule.activity
            .waitForComposeView()
            .drawToBitmap() // this is the key
            .writeToTestStorage(name)
    }
}

The only disadvantage of that method, is that elevation elements (like shadows) are not drawn.

Alternatively, you could use

@get:Rule
val rule = ActivityScenarioForComposableRule(
       // make the composable smaller, 
       // to see whether it fits in the window, 
       // without sacrificing elevation
        config = ComposableConfigItem(
             displaySize = SMALL, 
        )
)  

Warning: the library also provides view.drawToBitmapWithElevation(), but that uses PixelCopy, which limits the screenshot to the window size :(

let me know if that helped :)

davidbilik commented 1 year ago

Hey Sergio, thanks for you answer :) I've tried to rewrite my test to this

protected fun snapshotComposable(
        name: String,
        composable: @Composable () -> Unit
    ) {
        rule.activityScenario
            .onActivity { activity ->
                activity.setContent {
                      composable()
                }
            }
        rule.activity
            .waitForComposeView()
            .drawToBitmap()
            .writeToTestStorage(name)
    }

and it's still limited to a screen size 🤔 But maybe i did something wrong because you've said

However, this library provides view.drawToBitmap(), which uses Canvas

and I did not find this method in your library, I've used the one from core-ktx.

sergio-sastre commented 1 year ago

@davidbilik Although it seems it is not related to this lib, could you share the problematic composable?

I could take a look at it and might find a solution to the problem

sergio-sastre commented 1 year ago

@davidbilik I'll close this issue seems it does not seem to be related to this lib