Skip to content

XML: render dark/light modes in a single paparazzi snapshot instance.#6506

Open
kanake10 wants to merge 3 commits into
GetStream:developfrom
kanake10:render-diff-snapshot-in-one-instance
Open

XML: render dark/light modes in a single paparazzi snapshot instance.#6506
kanake10 wants to merge 3 commits into
GetStream:developfrom
kanake10:render-diff-snapshot-in-one-instance

Conversation

@kanake10

@kanake10 kanake10 commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Goal

Dark and light mode snapshots in PaparazziViewTest were not rendering correctly. Both halves of the combined snapshot appeared identical because createConfigurationContext is ignored by Paparazzi, so the night mode flag had no effect.

Implementation

Replace createConfigurationContext with paparazzi.unsafeUpdateConfig, passing a DeviceConfig with the correct NightMode before each view is inflated.

@andremion

🎨 UI Changes

Add relevant screenshots

Before After
img img

Add relevant videos

Before After

Testing

Explain how this change can be tested (or why it can't be tested)

Provide a patch below if it is necessary for testing

Provide the patch summary here
Provide the patch code here

☑️Contributor Checklist

General

  • [ x] I have signed the Stream CLA (required)
  • [ x] Assigned a person / code owner group (required)
  • Thread with the PR link started in a respective Slack channel (required internally)
  • PR targets the develop branch
  • PR is linked to the GitHub issue it resolves

Code & documentation

  • New code is covered by unit tests
  • Comparison screenshots added for visual changes
  • Affected documentation updated (KDocs, docusaurus, tutorial)

☑️Reviewer Checklist

  • UI Components sample runs & works
  • Compose sample runs & works
  • UI Changes correct (before & after images)
  • Bugs validated (bugfixes)
  • New feature tested and works
  • All code we touched has new or updated KDocs
  • Check the SDK Size Comparison table in the CI logs

🎉 GIF

Please provide a suitable gif that describes your work on this pull request

Summary by CodeRabbit

  • Tests
    • Improved snapshot testing efficiency by generating light and dark mode snapshots within a single test instance. Night-mode configuration now updates at runtime, reducing test redundancy and streamlining testing workflows.

@kanake10 kanake10 requested a review from a team as a code owner June 18, 2026 13:32
@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

PaparazziViewTest is refactored to toggle Paparazzi's device night-mode configuration at runtime using paparazzi.unsafeUpdateConfig with a new applyNightMode helper and overridable baseDeviceConfig property, replacing the previous separate light/dark context approach.

Changes

Runtime Night-Mode Snapshot Support

Layer / File(s) Summary
Imports and baseDeviceConfig property
stream-chat-android-ui-components/src/test/kotlin/io/getstream/chat/android/ui/PaparazziViewTest.kt
Adds DeviceConfig and NightMode imports and introduces the open val baseDeviceConfig property (defaulting to DeviceConfig.PIXEL_4A) as the baseline for night-mode config copies.
applyNightMode helper and snapshot flow
stream-chat-android-ui-components/src/test/kotlin/io/getstream/chat/android/ui/PaparazziViewTest.kt
snapshot now calls applyNightMode before capturing. snapshotLightAndDark builds lightView and darkView by toggling night mode between viewFactory(paparazzi.context) calls. applyNightMode drives the change via paparazzi.unsafeUpdateConfig(baseDeviceConfig.copy(nightMode=...)).

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Suggested labels

pr:test

Suggested reviewers

  • VelikovPetar

Poem

🐇 Hop hop, the night falls and rises with ease,
No more two contexts to juggle and please.
One config to copy, one flag to flip true,
Dark views and light views now rendered anew!
I snapshot the world in both moonlight and sun~ 🌙☀️

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description check ✅ Passed The description includes the required Goal and Implementation sections explaining the problem and solution, but UI Changes, Testing, and several checklist items are incomplete or empty.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly describes the main change: modifying how dark/light mode snapshots are rendered in Paparazzi tests to use a single instance instead of separate contexts.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@andremion andremion left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for working on this. The approach is right: createConfigurationContext is ignored by Paparazzi, so calling unsafeUpdateConfig before each inflation is the correct way to do it, and the regenerated header golden confirms light and dark now render together.

One blocking issue: the device config is set in two places that can differ, so one test renders on the wrong device. I left the details inline. After the fix, the affected goldens need re-recording. Nothing else is required to merge.

@get:Rule
val instantAnimations = InstantAnimationsRule()

open val baseDeviceConfig: DeviceConfig = DeviceConfig.PIXEL_4A

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

baseDeviceConfig defaults to PIXEL_4A, but ChannelListHeaderViewTest builds its rule with Paparazzi(deviceConfig = DeviceConfig.PIXEL_2) and does not override baseDeviceConfig. So the first applyNightMode call replaces PIXEL_2 with PIXEL_4A, and the header is snapshotted on the wrong device. You can see it in the regenerated golden: the header image went from 562x1000 (PIXEL_2 ratio) to 461x1000 (PIXEL_4A ratio).

The cause is that the device config is now defined in two places that can differ: the Paparazzi rule and baseDeviceConfig. Could we define the device config once and reuse it in the rule, so the two stay the same? Something like:

Base:

abstract val deviceConfig: DeviceConfig

private fun applyNightMode(isDark: Boolean) {
    paparazzi.unsafeUpdateConfig(
        deviceConfig = deviceConfig.copy(
            nightMode = if (isDark) NightMode.NIGHT else NightMode.NOTNIGHT,
        ),
    )
}

Subclass (declare deviceConfig before paparazzi so the rule reads the set value):

override val deviceConfig = DeviceConfig.PIXEL_2

@get:Rule
override val paparazzi = Paparazzi(deviceConfig = deviceConfig)

This keeps each subclass in control of its own Paparazzi(...) call (so a test that also passes renderingMode still works), removes the default device that can be inherited by mistake, and keeps one definition of the device. The header goldens will need re-recording back to PIXEL_2 after the change (./gradlew :stream-chat-android-ui-components:recordPaparazziDebug).

applyNightMode(true)
val darkView = viewFactory(paparazzi.context)

applyNightMode(false)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional: a one line comment here would help. Resetting to light before building the container is intentional (so the container and final snapshot render in light mode after the dark view was inflated), but it reads as redundant without a note.

@andremion

Copy link
Copy Markdown
Contributor

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@andremion andremion added the pr:test Test-only changes label Jun 18, 2026
@andremion andremion changed the title render dark/light modes in a single paparazzi snapshot instance. XML: render dark/light modes in a single paparazzi snapshot instance. Jun 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr:test Test-only changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants