sergio-sastre / ComposablePreviewScanner

A library to help auto-generate screenshot tests from Composable Previews with any screenshot testing library: JVM-based (i.e. Paparazzi, Roborazzi) as well as Instrumentation-based (i.e. Shot, Dropshots, Android-Testify, etc.)
MIT License
131 stars 1 forks source link

Internal visibility not respected: Internal Previews returned even though executes in a different module #20

Open takahirom opened 1 month ago

takahirom commented 1 month ago

We are experiencing an issue where we encounter classes that we do not intend to see. Consider a scenario with modules such as feature/a, feature/b, and core/designsystem. The designsystem module contains some previews. When we aim to conduct Preview screenshot testing within a module for rapid updates, the previews from designsystem are captured multiple times. Therefore, my proposal is to support the internal modifier of Kotlin for Preview functions. If a Preview function is marked as internal, it should not be accessible from other modules. However, currently, we are uncertain how to determine if a function belongs to the same module.

sergio-sastre commented 1 month ago

I’m afraid that is unfortunately not possible. Internal modifier is converted to public in Java, and that is what ClassGraph sees. However, I can open an issue in ClassGraph and maybe there is some workaround for Kotlin…

For now, the best you can do is mark such internal previews with your own annotation e.g ExcludeForScreenshot then when used outside the module, use

AndroidComposablePreviewScanner()
   …
   .excludeIfAnnotatedWithAnyOf(
       ExcludeForScreenshot::class.java, 
    )
    …
    .getPreviews()
takahirom commented 1 month ago

I tried using Kotlin Reflect but couldn't find a solution. I was able to determine if a function is internal, but the challenging part is checking if it's in the same module. Here's the code I used: Class.forName(preview.declaringClass).declaredMethods.first { it.name == preview.methodName }.kotlinFunction?.visibility

takahirom commented 1 month ago

Well, I think we can work around this by specifying scanPackages() in each module as well.

sergio-sastre commented 1 month ago

Another elegant solution would be to make the previews private (I’m actually still thinking what is a valid use case for an internal preview 🧐), and use includePrivatePreviews() only in the module where you want to generate tests from those Previews

takahirom commented 1 month ago

I haven't tried it yet, but the current behavior of includePrivatePreviews() in feature/a will likely include private previews from core/designsystem as well. 👀

sergio-sastre commented 1 month ago

I think I am misunderstanding your use case 🧐

I’ll keep this open in case somebody wants to fix it, but I believe I’ll not prioritize this for now.