Skip to content

Add Compose snapshot tests for redesigned components#6424

Merged
gpunto merged 3 commits intodevelopfrom
screenshot-tests
May 8, 2026
Merged

Add Compose snapshot tests for redesigned components#6424
gpunto merged 3 commits intodevelopfrom
screenshot-tests

Conversation

@gpunto
Copy link
Copy Markdown
Contributor

@gpunto gpunto commented May 7, 2026

Goal

Backfill Paparazzi snapshot coverage for Compose components introduced during the
redesigned. Also fixed the typing dot indicator's animation not being deterministic in snapshot
tests.

Implementation

  • Add snapshot tests for: StreamButton, CountBadge, MessageReactions, QuotedMessage.
  • Extend MessageFooterTest with an outgoing thread-start case to cover the MessageAlignment.End
    variant of MessageThreadFooter.
  • Replace System.currentTimeMillis() in TypingDrawable with a ValueAnimator. The drawable now
    implements Animatable and starts/stops via Drawable.setVisible, the standard hook ImageView
    already calls on attach/detach/visibility changes. Add Paparazzi's InstantAnimationsRule to
    PaparazziViewTest so the animator settles to a deterministic frame in tests.

Testing

  • New snapshot tests recorded and pass verifyPaparazziDebug.
  • Existing snapshots that include a ViewAnimator-based animation, now should show a deterministic
    frame the typing indicator. Re-running verifyPaparazziDebug should no longer produces drift.

Summary by CodeRabbit

  • Bug Fixes

    • Improved typing indicator animation reliability by optimizing animation lifecycle handling.
  • Tests

    • Added comprehensive snapshot tests for UI components including button styles, badge variants, message reactions, quoted messages, and poll answers to ensure visual consistency.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 7, 2026

PR checklist ✅

All required conditions are satisfied:

  • Title length is OK (or ignored by label).
  • At least one pr: label exists.
  • Sections ### Goal, ### Implementation, and ### Testing are filled (or ignored for dependabot PRs).

🎉 Great job! This PR is ready for review.

@gpunto gpunto added the pr:test Test-only changes label May 7, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 7, 2026

SDK Size Comparison 📏

SDK Before After Difference Status
stream-chat-android-client 5.82 MB 5.82 MB 0.00 MB 🟢
stream-chat-android-ui-components 11.02 MB 11.02 MB 0.00 MB 🟢
stream-chat-android-compose 12.38 MB 12.39 MB 0.01 MB 🟢

@gpunto gpunto force-pushed the screenshot-tests branch 4 times, most recently from 9c7c249 to fa0978a Compare May 7, 2026 13:21
Base automatically changed from waveform-slider-fix to develop May 7, 2026 14:22
@gpunto gpunto force-pushed the screenshot-tests branch 2 times, most recently from 1ae271a to 4f729f9 Compare May 7, 2026 15:39
@gpunto gpunto marked this pull request as ready for review May 8, 2026 07:29
@gpunto gpunto requested a review from a team as a code owner May 8, 2026 07:29
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 8, 2026

Review Change Stack

Walkthrough

This PR refactors Compose preview composables into granular, reusable helpers across multiple UI components, adds comprehensive Paparazzi snapshot tests for component variants, and refactors the typing indicator animation to use ValueAnimator-driven animation instead of System.currentTimeMillis()-based timing for deterministic control.

Changes

Compose Previews & Snapshot Testing

Layer / File(s) Summary
API Surface Updates
stream-chat-android-compose/api/stream-chat-android-compose.api
Synthetic lambda members in Compose singleton classes (StreamButtonKt, ContextualMenuKt, CountBadgeKt, UserReactionRowKt, MessageReactionsKt, QuotedMessageKt) are updated to reflect refactored preview implementations.
Preview Composable Refactoring
src/main/java/io/getstream/chat/android/compose/ui/components/button/StreamButton.kt, common/ContextualMenu.kt, common/CountBadge.kt, messageactions/UserReactionRow.kt, messages/MessageReactions.kt, messages/QuotedMessage.kt, poll/PollAnswers.kt
Monolithic previews are split into multiple themed preview entry points with reusable internal composables. StreamButton splits into enabled/disabled/size variants; CountBadge becomes size-focused; UserReactionRow expands to removable/non-removable/other user cases; MessageReactions covers clustered/segmented/overflow states; QuotedMessage adds scenarios for user source, text overflow, and attachments; PollAnswers covers content, current-user answer, and closed-anonymous states.
Paparazzi Snapshot Tests
src/test/kotlin/.../button/StreamButtonTest.kt, common/CountBadgeTest.kt, messages/MessageFooterTest.kt, messages/MessageReactionsTest.kt, messages/QuotedMessageTest.kt, poll/PollAnswersTest.kt
New snapshot test classes for component variants using Pixel 2 device configuration with SHRINK rendering mode and dark-mode coverage. MessageFooterTest adds a test for outgoing thread start with replies.
Test Infrastructure
stream-chat-android-ui-components/src/test/kotlin/io/getstream/chat/android/ui/PaparazziViewTest.kt
InstantAnimationsRule is added to PaparazziViewTest base class to enable deterministic animation handling in snapshot tests.

Typing Animation Refactoring

Layer / File(s) Summary
Animation Implementation
stream-chat-android-ui-components/src/main/kotlin/.../TypingIndicatorAnimationView.kt
TypingDrawable refactored to use ValueAnimator instead of System.currentTimeMillis() for animation timing. Implements Animatable interface and adds lifecycle methods (start(), stop(), isRunning(), setVisible()). Animator update listener drives invalidateSelf() redraws, and calculateAlpha() now accepts animator phase for deterministic dot animation.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 Bouncing through the preview refactor stash,
Splitting monoliths into composable cache,
Paparazzi snapshots smile bright,
Animator phases dance just right! 🎬✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 6.12% 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
Title check ✅ Passed The PR title 'Add Compose snapshot tests for redesigned components' clearly and concisely summarizes the primary change of adding snapshot test coverage for Compose UI components.
Description check ✅ Passed The PR description covers Goal (why), Implementation (what), and Testing (how tested), addressing the core required sections. However, it lacks UI Changes (screenshots/videos) and the Contributor/Reviewer checklists from the template.
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.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch screenshot-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.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/poll/PollAnswers.kt`:
- Around line 388-417: The previewPollWithAnswers() function uses Date() (now)
for createdAt/updatedAt which causes snapshot drift; replace the dynamic now
with a fixed Date/Instant constant (e.g., a single fixed epoch value) and use
that constant for all Answer.createdAt and updatedAt values so PollAnswersItem
rendering is deterministic for Paparazzi snapshots.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 61dfb668-96e0-4675-a5cc-4377c602df6f

📥 Commits

Reviewing files that changed from the base of the PR and between cf0b562 and 4f729f9.

⛔ Files ignored due to path filters (22)
  • stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.components.button_StreamButtonTest_button_sizes.png is excluded by !**/*.png
  • stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.components.button_StreamButtonTest_disabled_buttons.png is excluded by !**/*.png
  • stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.components.button_StreamButtonTest_enabled_buttons.png is excluded by !**/*.png
  • stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.components.common_CountBadgeTest_count_badge_sizes.png is excluded by !**/*.png
  • stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.components.messages_MessageFooterTest_outgoing_thread_start_with_replies.png is excluded by !**/*.png
  • stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.components.messages_MessageReactionsTest_clustered_reactions.png is excluded by !**/*.png
  • stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.components.messages_MessageReactionsTest_overflow_segmented_reactions.png is excluded by !**/*.png
  • stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.components.messages_MessageReactionsTest_overflow_segmented_reactions_in_dark_mode.png is excluded by !**/*.png
  • stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.components.messages_MessageReactionsTest_segmented_reactions.png is excluded by !**/*.png
  • stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.components.messages_QuotedMessageTest_from_other_user.png is excluded by !**/*.png
  • stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.components.messages_QuotedMessageTest_from_self.png is excluded by !**/*.png
  • stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.components.messages_QuotedMessageTest_in_composer.png is excluded by !**/*.png
  • stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.components.messages_QuotedMessageTest_with_file_attachment.png is excluded by !**/*.png
  • stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.components.messages_QuotedMessageTest_with_image_attachment.png is excluded by !**/*.png
  • stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.components.messages_QuotedMessageTest_with_long_text.png is excluded by !**/*.png
  • stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.components.poll_PollAnswersTest_closed_anonymous.png is excluded by !**/*.png
  • stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.components.poll_PollAnswersTest_content.png is excluded by !**/*.png
  • stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.components.poll_PollAnswersTest_with_current_user_answer.png is excluded by !**/*.png
  • stream-chat-android-ui-components/src/test/snapshots/images/io.getstream.chat.android.ui.feature.channels.header_ChannelListHeaderViewTest_connecting,_no_user.png is excluded by !**/*.png
  • stream-chat-android-ui-components/src/test/snapshots/images/io.getstream.chat.android.ui.feature.channels.header_ChannelListHeaderViewTest_connecting,_with_user.png is excluded by !**/*.png
  • stream-chat-android-ui-components/src/test/snapshots/images/io.getstream.chat.android.ui.feature.channels.list_ChannelListViewTest_loaded_channels.png is excluded by !**/*.png
  • stream-chat-android-ui-components/src/test/snapshots/images/io.getstream.chat.android.ui.feature.channels.list_ChannelListViewTest_loading_channels.png is excluded by !**/*.png
📒 Files selected for processing (16)
  • stream-chat-android-compose/api/stream-chat-android-compose.api
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/button/StreamButton.kt
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/common/ContextualMenu.kt
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/common/CountBadge.kt
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/messageactions/UserReactionRow.kt
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/messages/MessageReactions.kt
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/messages/QuotedMessage.kt
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/poll/PollAnswers.kt
  • stream-chat-android-compose/src/test/kotlin/io/getstream/chat/android/compose/ui/components/button/StreamButtonTest.kt
  • stream-chat-android-compose/src/test/kotlin/io/getstream/chat/android/compose/ui/components/common/CountBadgeTest.kt
  • stream-chat-android-compose/src/test/kotlin/io/getstream/chat/android/compose/ui/components/messages/MessageFooterTest.kt
  • stream-chat-android-compose/src/test/kotlin/io/getstream/chat/android/compose/ui/components/messages/MessageReactionsTest.kt
  • stream-chat-android-compose/src/test/kotlin/io/getstream/chat/android/compose/ui/components/messages/QuotedMessageTest.kt
  • stream-chat-android-compose/src/test/kotlin/io/getstream/chat/android/compose/ui/components/poll/PollAnswersTest.kt
  • stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/widgets/typing/internal/TypingIndicatorAnimationView.kt
  • stream-chat-android-ui-components/src/test/kotlin/io/getstream/chat/android/ui/PaparazziViewTest.kt

@gpunto gpunto force-pushed the screenshot-tests branch from 4f729f9 to a9e5781 Compare May 8, 2026 07:43
@gpunto gpunto force-pushed the screenshot-tests branch from a9e5781 to 406153c Compare May 8, 2026 10:18
@gpunto gpunto enabled auto-merge (squash) May 8, 2026 10:18
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented May 8, 2026

@gpunto gpunto merged commit 9630b94 into develop May 8, 2026
16 checks passed
@gpunto gpunto deleted the screenshot-tests branch May 8, 2026 10:57
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