takahirom / roborazzi

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

Consider passing RoborazziOptions to Compose Preview Support #447

Open takahirom opened 1 month ago

takahirom commented 1 month ago

My suggestion is to create a roborazziOptions(): RoborazziOptions function in the tester interface to set up the RoborazziOptions. However, we might want to access the annotations of the Preview function within roborazziOptions(). We could pass a ComposablePreview instance as a parameter, but I'm unsure if there's a more efficient approach.

sergio-sastre commented 1 month ago

This would be for default options right? For options applying to a single Preview, I’d bet the best is to provide a @ RoborazziConfig annotation with params matching the options -and annotate your @ Previews with it.

then you can get that info via

AndroidComposablePreviewScanner()
  …
  .includeAnnotationInfoForAllOf(RoborazziConfig::class.java)

and map them in the tests with ComposablePreview<AndroidPreview>.getAnnotation<RoborazziConfig>()

You can find some examples here:

https://github.com/sergio-sastre/Android-screenshot-testing-playground/tree/master/lazycolumnscreen-previews/roborazzi/src

takahirom commented 1 month ago

Thanks! I believe we have two main use cases for this:

  1. Users can set up tests using @RoborazziConfig. We should add @RoborazziConfig to allow users to configure tests using a prepared annotation, as you suggested.
(In Roborazzi)
annotation class RoborazziConfig(xxxx)

class AndroidComposePreviewTester : ComposePreviewTester<AndroidPreviewInfo> {
  // This will be a new method of ComposePreviewTester
  override fun roborazziOptions(): RoborazziOptions {
     // How to access the composablePreview here?
     // options().composablePreview or passing as a parameter
     val someOptions = composablePreview.getAnnotation<RoborazziConfig>().xxxx
     return RoborazziOptions(xxx)
  }

  override fun test(composablePreview) {
      val roborazziOptions = roborazziOptions()
...
  }
}

https://github.com/takahirom/roborazzi/blob/main/roborazzi-compose-preview-scanner-support/src/main/java/com/github/takahirom/roborazzi/RoborazziPreviewScannerSupport.kt#L85C1-L85C34 (The current implementation of AndroidComposePreviewTester)

  1. Users want to set the default diff tolerance or their custom annotations
(In user project)
class MyCustomComposePreviewTester : ComposePreviewTester<AndroidPreviewInfo> by AndroidComposePreviewTester() {
  override fun roborazziOptions(): RoborazziOptions {
     // How to access the composablePreview here?
     // options().composablePreview or passing as a parameter
     val someOptions = composablePreview.getAnnotation<UserCustomConfig>().xxxx
     return RoborazziOptions(xxx)
  }
}

I think we need to consider adding a new roborazziOptions() method to the tester interface and determine how we can pass composablePreview to roborazziOptions(), or explore other approaches.

sergio-sastre commented 1 month ago

So for me there are 3 use cases then:

  1. Default Roborazzi options, set in the plugin
  2. Per test Roborazzi Options set via a @RoborazziConfig provided by Roborazzi
  3. Per test Roborazzi Options set via a custom annotation

I'd focus first on providing options 1 & 2 3rd is definitely harder to maintain and for more advanced users. I'd rather add it later, if ever.