Skip to content

test(llc): port the stream_chat_test algebra onto v11 - #2971

Draft
VelikovPetar wants to merge 112 commits into
v11from
port/test-algebra-to-v11-v2
Draft

VelikovPetar wants to merge 112 commits into
v11from
port/test-algebra-to-v11-v2

Conversation

@VelikovPetar

Copy link
Copy Markdown
Contributor

Note

Draft, and not expected to merge as-is. It exists to show that the stream_chat_test
algebra ports onto v11 without losing coverage, and to let the port be reviewed before
#2950 / #2954 land on master. See Landing this for real.

Brings master and the stream_chat_test test algebra onto v11, and ports the migrated suite
to v11's stream_core-based APIs.

What this contains

Three things, in this order:

what source
1 masterv11 — a clean merge, no conflicts. Carries #2945 (SyncManager) and #2966 (FLU-791, the removed-member read-state fix) merge/master-to-v11-base
2 the stream_chat_test harness package #2950 (feat/stream-chat-test-package)
3 the migrated stream_chat suite built on that harness #2954 (test/migrate-llc-tests-to-algebra)

…plus one commit of my own, test(llc): port the stream_chat_test algebra onto the v11 APIs, which
resolves the merge and ports both the harness and the migrated tests to v11's APIs.

Step 1 is on its own branch (merge/master-to-v11-base) rather than folded in, because it doubles
as the coverage baseline every number below is measured against.

Related

The port

v11 moved stream_chat onto stream_core across #2956#2963, so the migrated suite — written
against master's API — could not compile. The mapping was not invented: v11 had already performed
every one of these ports once, on master's version of the same files, and migrations/v11-migration.md
records the symbol map. Each resolution replays that port onto the migrated test.

Harness (packages/stream_chat_test/lib/, no conflicts but the load-bearing work):

  • TokenManager() + setTokenOrProviderTokenManager.unconfigured() + setTokenProvider(id, tokenProvider:)
  • TokenUserToken; createTestToken now builds the devtoken-signed JWT itself
  • logLevel: Level.OFFlogConfig: StreamLogConfig(priority: verbose, handler: silent), plus
    addTearDown(StreamLogger.reset) — the client configures the logger process-wide
  • StreamChatNetworkError/ChatErrorCodeStreamApiException/StreamErrorCode
  • createDefaultNetworkError's retriable: flag is gone: on v11 retriability is read off the
    status code, so each call site names the status the endpoint answers with
  • registerChatFallbackValues registers one filter and one sort-list fallback per query surface
    a filter carries its model in its type now, so a single Filter.empty() no longer covers them

Tests — 14 conflicted files, 117 content hunks + 2 modify/delete. Highlights:

  • Filter and Sort compare by identity on v11 (stream_core's are not Equatable; master's
    Filter was). The harness's convention is exact-argument stubbing, so every stub carrying a filter
    silently stops matching — it compiles and fails at runtime. Resolved with v11's isSameFilterAs
    (moved into the harness, where matchers.dart now lives) plus a new isSameSortAs sibling.
  • test/src/fakes.dart and auth_interceptor_test.dart are the two modify/delete conflicts; both
    resolve to the delete. Nothing imports fakes.dart on the migration branch, and AuthInterceptor
    moved to stream_core.
  • One behavioural change the suite caught by itself. Four .sendMessage tests used notAllowed
    errors marked "retriable". On master isRetriable meant "carries no response data"; on v11 it is
    read off the status code, and a 403 is a verdict. Those four now assert sending → sendingFailed and
    verify the send happened once — a stronger claim than the old "queued and retried", and the one
    v11's own rename ("should mark a refused send as failed") describes.

Evidence

packages/stream_chat/lib is byte-identical between merge/master-to-v11-base and this branch
(git diff is empty), so the coverage rows are a valid line-by-line comparison.

baseline (v11 + master) this branch
tests passing 1,787 1,792
lib/ lines covered 6,691 6,758
lines instrumented 7,873 7,873
lines covered on the baseline only 0
lines covered on this branch only 67
  • Zero lines lost, zero baseline test names lost (runner-level enumeration via the JSON
    reporter, not grep).
  • The 5 extra tests are the migration's documented additions: the channel.config getter on an
    initialized and a non-initialized channel, the channel-with-persistence lifecycle, the retry queue
    giving up when the policy declines, and the default REST wiring.
  • 16 test files differ from v11 — the ones resolved here plus fakes.dart/matchers.dart
    (deleted, now in the harness). Every other file under packages/stream_chat/test, including
    filter_registry_test.dart, sort_registry_test.dart, stream_chat_exception_test.dart and all the
    model tests, is byte-identical to v11's.

One real loss, found by the coverage diff and fixed

channel.dart:867 (state?.scheduleRetry) showed as baseline-only. Cause: v11 had added five
.sendMessage tests inside a group the migration rewrote wholesale, so the merge swallowed them.
All five are restored, re-expressed on the harness with the same assertions —
queues a failed send for retry when the failure is retriable,
does not queue a failed send when the failure is not retriable,
should re-send the message through the retry queue when the failure is retriable,
should not re-send the message when the failure is not retriable,
should report a superseded send as a cancelled request.
The two counts v11 wrote as called(greaterThan(1)) are times: 2 here, which is stricter.

Nothing was demoted to pass green

Two independent checks, because line coverage cannot see assertion strength.

Assertion-strength audit. Every removed assertion line has a one-for-one renamed replacement
(19 StreamChatNetworkErrorStreamApiException, 12 error-code equals, 7 StreamChatError
StreamClientException, 3 →StateError, 4 →StreamNetworkException). The only net assertion
removal in the whole merge is the three expects inside the deleted .devToken test. Zero skip:
anywhere. .called(n) counts unchanged. All 26 added any( are narrowing wrappers
(isSameFilterAs / isSameMessageAs) — no bare any() ever replaced an exact argument.

Mutation battery — 25 mutations over the lib/ files v11 changed: 18 caught, 7 survived, and every
survivor also survives on the baseline
, so each is a gap v11 already had rather than one this merge
introduced.

Caught: the retry-enqueue gate, cancelled-upload detection, the mark-read guards, the message-not-found
guard, _removeMember's read pruning (#2966), _removeWatcher's pruning, the event handler's
member-lookup filter field, all three ChannelDeliveryReporter entry points, both client.dart
connection guards, the sync refused-window branch, the quoted-message rewrite, the muted/blocked
model getters, members exact matching (#2963), connect-URI redaction, and effectiveSort.

Pre-existing v11 gaps this surfaced (not regressions — worth their own tickets)

Each survives the mutation on both this branch and the baseline:

  1. websocket.dart:403 — the token-expiry refresh-and-reconnect path is never exercised.
  2. websocket.dart:404 — nor is its static-token half (usesStaticProvider).
  3. channel.dart:273,280Channel.blocked / blockedStream, added by v11, have no test at all.
  4. retry_queue.dart:86retryIf's "not a StreamChatException ⇒ do not retry" early return.
  5. client.dart:801queryChannels' no-active-connection StateError. master's test asserted a
    stubbed throw rather than the real guard, so it was never covered on either side.
  6. channel_model.dart:259-262copyWith's safeCast<bool> fallback (the replacement path is
    tested, the fallback-to-this path is not).
  7. channel.dart:820,921 — the upload-failure message naming each attachment and its reason.

Orphans — tests dropped because their subject left the package

test where the subject went
Client … `.devToken` StreamChatClient.devToken removed on v11; Token/AuthType are stream_core's UserToken
`onError` should pass through an error response that is not a token expiry AuthInterceptor moved to stream_core; v11 deletes the file. stream_http_client_test.dart still pins that the interceptor is installed and correctly ordered

Everything else the migration branch carries but this merge does not is a file v11 deleted outright
(filter_test, sort_order_test, comparable_field_test, list_extensions_test,
string_sort_normalizer_test, stream_chat_error_test, token_test, token_manager_test,
system_environment_manager_test, in_flight_cache_test, stream_chat_dio_error_test) or a test v11
itself renamed in a file this merge takes from v11 unchanged.

Checks

  • dart analyze on packages/stream_chat_test: clean.
  • dart analyze on packages/stream_chat: 2 infos, both in lib/ and both pre-existing on the
    baseline
    (sync_manager.dart:223, websocket.dart:436, cascade_invocations). They will trip
    --fatal-infos in CI but did not come from here.
  • dart format --set-exit-if-changed: clean in both packages.
  • packages/stream_chat suite: 1,795 passing. packages/stream_chat_test self-tests: 31 passing.

Landing this for real

The repo squash-merges, so this merge would not be an ancestor of tomorrow's master and the same
14 files would conflict a second time. The plan is therefore: once #2950 and #2954 land on master,
branch off v11, git merge origin/master, replay the resolutions from this branch, and re-run the
evidence above. The thinking happens once; the second merge is mechanical.

🤖 Generated with Claude Code

VelikovPetar and others added 30 commits September 9, 2026 11:43
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…Enabled

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ream_chat_test

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…at_test

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…_test

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…test

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…chat_test

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…_state_test monolith

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…_test

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
VelikovPetar and others added 28 commits September 11, 2026 13:31
…el role in emitted messages

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ation claims

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… config

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… whole 0.1.0 surface

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… instead of a default

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…client sendEvent

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… not an isolation boundary

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…API call

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…iry error

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…at other tests

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…sting guides

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…sts-to-algebra

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…nto claude/stream-chat-flutter-test-migration-4e5041

# Conflicts:
#	packages/stream_chat/test/src/client/channel/channel_client_state_test.dart
#	packages/stream_chat/test/src/client/client_test.dart
#	packages/stream_chat/test/src/fakes.dart
#	packages/stream_chat/test/src/mocks.dart
… doubles

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ss client

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

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.

@VelikovPetar VelikovPetar changed the title test(llc): port the stream_chat_test algebra onto v11 test(llc): port the stream_chat_test algebra onto v11 Sep 17, 2026

This branch has not been deployed

No deployments
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