Skip to content

Add per-user read state and the request-response endpoints - #53

Draft
andremion wants to merge 4 commits into
mainfrom
andrerego/and-1329-request-response-endpoints-and-read-state
Draft

Add per-user read state and the request-response endpoints#53
andremion wants to merge 4 commits into
mainfrom
andrerego/and-1329-request-response-endpoints-and-read-state

Conversation

@andremion

@andremion andremion commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Goal

Add mock server support for the request-response Compose features so the Android e2e suite can cover them. These features either call endpoints the mock does not implement (unhandled requests return 404) or need per-user read state the mock does not maintain.

Related: AND-1329. Companion PR with the Android tests: GetStream/stream-chat-android#6596 (this PR must merge first).

Implementation

  • Per-user read state (src/helpers/reads.rb). /mock seeds every channel with both users fully read. A new channel message increments unread_messages for the other members and advances the author's own read state, like the real backend. The mark-read endpoint stores last_read and last_read_message_id. The new mark-unread endpoint rewinds the state to the given message and broadcasts notification.mark_unread. /participant/read reuses the same helper.
  • New endpoints: pinned messages query, message search, threads query, reactions query, flag/unflag, mute and unmute user (broadcasts notification.mutes_updated), mute and unmute channel (broadcasts notification.channel_mutes_updated), block, unblock and list blocked users, channel delete (broadcasts channel.deleted), reminder create, update, delete and query, and an ACK for /channels/delivered (the Android SDK kept retrying it against the 404 every second).
  • New chat robot endpoint POST /create_reminder seeds a server-side reminder on the last message, because reminders cannot be created from the sample app UI.
  • All generated dates now have microsecond precision, like the real backend. The Android client drops read-state updates whose event timestamp is not strictly newer than the last processed one, so with second-precision dates only one unread increment per second survived: 25 participant messages sent over 13 seconds produced an unread count of 13 instead of 25.

Testing

  • bundle exec rubocop: no offenses.
  • curl smoke tests against a local server for every new endpoint and for the read-state flows: seeding, unread increments, mark read, mark unread, search, pinned messages, threads, reactions query, flag, mutes, block, reminders, channel delete.
  • Ran the Android UnreadMessagesTests locally against this branch: the three previously ignored tests (unread separator, jump to unread, dismiss indicator) plus a new mark-as-unread test are all green when run with per-test data isolation, matching how CI runs them. Against main these tests cannot pass because the mock serves no real read state.
  • Android and iOS e2e workflow runs on this branch will be linked in the comments.

Track read state per user per channel: sending a message advances the
author's read state and increments unread_messages for the other
members, mark-read stores last_read, and the new mark-unread endpoint
rewinds it and broadcasts notification.mark_unread.

New endpoints: pinned messages query, message search, threads query,
reactions query, flag, mute/unmute user, mute/unmute channel,
block/unblock/list blocked users, channel delete, reminder CRUD plus
query, mark-delivered ACK, and a /create_reminder chat robot endpoint
that seeds server-side reminders for tests.

Stamp all generated dates with microsecond precision like the real
backend: clients drop read-state updates whose event timestamp is not
strictly newer than the last processed one, so second-precision stamps
lose one unread increment per same-second event.
@andremion
andremion requested a review from testableapple July 28, 2026 12:20
@andremion

andremion commented Jul 28, 2026

Copy link
Copy Markdown
Contributor Author

Seeding the participant with last_read at mock time marked every seeded
message as read by the participant, flipping the delivery status
checkmarks the MessageDeliveryStatusTests and GiphyTests count. The
participant's read entry is created on demand by /participant/read,
like before.
The backend deletes read state when a member is removed from a channel.
Serving the stale entry on a later channel query re-added the removed
member as a reader and flipped the delivery status back to read.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant