takahirom / roborazzi

Make JVM Android integration test visible 🤖📸
https://takahirom.github.io/roborazzi/
Apache License 2.0
654 stars 25 forks source link

Error in Compare Test for Dialog Composable #292

Closed yongsuk44 closed 3 months ago

yongsuk44 commented 3 months ago

While testing the 'AlertDialog Composable', changing the resizeScale leads to an error in the Compare test. Although not applying resizeScale avoids the issue, it makes it difficult to quickly understand the report due to visibility problems.

Below are the code and image :)

val DefaultRoborazziOptions =
    RoborazziOptions(
        compareOptions = CompareOptions(changeThreshold = 0f),
        recordOptions = RecordOptions(resizeScale = 0.5),
    )

@Test
fun settingsDialogAndroidThemeDark() {
    composeTestRule.activity.setContent {
        SettingsDialogDefaultTheme()
    }

    composeTestRule
        .onNodeWithTag("SettingsDialog")
        .captureRoboImage(
            "src/test/screenshots/SettingsDialogAndroidThemeDark.png",
            DefaultRoborazziOptions
        )
}

@Composable
private fun SettingsDialogDefaultTheme(
    darkMode: Boolean = false,
    androidTheme: Boolean = false,
    disableDynamicTheming: Boolean = true,
    settingsUiState: SettingsUiState = defaultSettingsUiState,
) {
    NiaTheme(
        darkTheme = darkMode,
        androidTheme = androidTheme,
        disableDynamicTheming = disableDynamicTheming,
    ) {
        SettingsDialog(
            modifier = Modifier.testTag("SettingsDialog"),
            onDismiss = {},
            settingsUiState = settingsUiState,
            onChangeThemeBrand = {},
            onChangeDynamicColorPreference = {},
            onChangeDarkThemeConfig = {},
        )
    }
}

SettingsDialogAndroidThemeDark_compare

takahirom commented 3 months ago

Thanks. It looks like the code is from "Now in Android". If you could provide the code that I can debug, that would be great.

yongsuk44 commented 3 months ago

@takahirom I discovered this while creating a new PR related to ScreenShot Test, not the existing code in the main branch. This PR does not use resizeScale in RoborazziOptions and generates the report in its original size.

takahirom commented 3 months ago

@yongsuk44 So, the procedure for reproduction would involve adding resizeScale, and then running both the record and verify tasks. Is that correct?

yongsuk44 commented 3 months ago

@takahirom Yes, that's correct. Just like the code written above, when I applied resizeScale and then performed the record followed by verify, the issue occurred

takahirom commented 3 months ago

I believe the issue is related to transparent colors. We are attempting to compare images with colors, but it seems we're unable to accurately compare transparent colors at the moment. The problem doesn't occur when using captureScreenRoboImage because it doesn’t capture transparent colors.

📝 settingsDialogLoading() x = 0, y = 33 leftColor Color(r=0.47058824, g=0.45490196, b=0.47058824, a=0.1254902) rightColor Color(r=0.47058824, g=0.47058824, b=0.47058824, a=0.1254902) delta: 0.015686274

right = golden left = newImage

image image
takahirom commented 3 months ago
val scaledColor = Color(r=0.47058824F, g=0.45490196F, b=0.47058824F, a=0.1254902F)
newRoboCanvas.save(File("test.png"), 0.5, mutableMapOf())
Color(AwtRoboCanvas.load(File("test.png"), 2).getPixel(0, 33))

result:

Color(r=0.47058824, g=0.47058824, b=0.47058824, a=0.1254902)

test.png -format "%[pixel:u.p{0, 33}]\n" info: srgba(120,116,120,0.12549)

116 = 0.4549019607843137


So the cause would be the loading file process. 👀

Record 00 -> scale -> 0.45490196F -> save as file -> 0.45490196 -> load file -> 0.47058824

takahirom commented 3 months ago

It looks like drawImage change the color. The default getComposite is SrcOver, and if we use Src for this. I think we can fix this problem.

BufferedImage defaultImage = new BufferedImage(
        loadedImage.getWidth(),
        loadedImage.getHeight(),
        bufferedImageType
);
Graphics2D graphics = defaultImage.createGraphics();
((Graphics)graphics).drawImage(loadedImage, 0, 0, null);
//graphics.setComposite();
graphics.dispose();

BufferedImage srcTypeImage = new BufferedImage(
        loadedImage.getWidth(),
        loadedImage.getHeight(),
        bufferedImageType
);
Graphics2D srcGraphics = srcTypeImage.createGraphics();
srcGraphics.setComposite(AlphaComposite.Src);
((Graphics)srcGraphics).drawImage(loadedImage, 0, 0, null);
//graphics.setComposite();
srcGraphics.dispose();

"drawed:"+ColorKt.Color(defaultImage.getRGB(0, 33)).toString()+"drawed with src:"+ColorKt.Color(srcTypeImage.getRGB(0, 33)).toString() +"\noriginal:"+ ColorKt.Color(loadedImage.getRGB(0, 33));

drawed:Color(r=0.47058824, g=0.47058824, b=0.47058824, a=0.1254902) drawed with src:Color(r=0.47058824, g=0.45490196, b=0.47058824, a=0.1254902) original:Color(r=0.47058824, g=0.45490196, b=0.47058824, a=0.1254902)

takahirom commented 3 months ago

The reason why scaling causes problems is that scaling introduces transparent colors along the edges

yongsuk44 commented 3 months ago

@takahirom Will this issue be addressed in the next release version? :)

takahirom commented 3 months ago

I'll release this within a few days.

takahirom commented 3 months ago

@yongsuk44 I released the new version! Thank you for reporting this issue!