Skip to content

test(ui/streamStoreHelpers): cover performConnect, watch/mic warnings, status sync#446

Merged
streamer45 merged 1 commit into
mainfrom
devin/1778924687-test-streamStoreHelpers
May 16, 2026
Merged

test(ui/streamStoreHelpers): cover performConnect, watch/mic warnings, status sync#446
streamer45 merged 1 commit into
mainfrom
devin/1778924687-test-streamStoreHelpers

Conversation

@staging-devin-ai-integration
Copy link
Copy Markdown
Contributor

@staging-devin-ai-integration staging-devin-ai-integration Bot commented May 16, 2026

Summary

Phase 2 coverage sprint — ui/src/stores/streamStoreHelpers.ts had ~340 uncovered lines (the biggest single UI gap). This PR extends the existing streamStoreHelpers.test.ts with 17 behavioral tests for the previously-uncovered orchestration entry point (performConnect) and the helpers it composes (schedulePostConnectWarnings, setupConnectionStatusSync, setupWatchPath's status sync). No production code is modified.

All assertions are on observable behavior — the mutated ConnectableState (status, errorMessage, micStatus, isMicEnabled/isCameraEnabled, watchStatus) and side-effects on the broadcast-config (audio.enabled.set). Mock-call introspection is not the sole assertion in any test.

Behaviors covered

  • performConnect — abort-already-aborted short-circuit, watch-only happy path, watch+publish happy path (mic + camera enabled), deferred audio enable for combined audio+video publish, "requesting" mic status when source is initially unavailable, 12s relay-connection timeout sets disconnected + errorMessage, mid-connect abort doesn't overwrite store state, watch-setup throw cleans up the connection and reports the error.
  • schedulePostConnectWarnings (watch broadcast) — fires "not live yet" warning after 10s when watch status stays non-live, stays silent when already live, and bails out cleanly when the user disconnects before the threshold.
  • schedulePostConnectWarnings (microphone) — fires "microphone is not available" warning after 10s when mic source never resolves, stays silent when mic source is immediately ready, and stays silent when the mic-source signal fires before the threshold.
  • setupConnectionStatusSync — propagates relay disconnected status to a store-level disconnected + descriptive error message, and propagates relay connecting status to connecting without setting an error.

Files inspected

  • ui/src/stores/streamStoreHelpers.ts — production file under test (enumerated exports, traced performConnectcreateConnectionAndHealthsetupWatchPath/setupPublishPathschedulePostConnectWarnings).
  • ui/src/stores/streamStoreHelpers.test.ts — existing test scaffolding (re-used vi.mock('@moq/*') blocks, makeTrack factory, createMockSignal helper pattern, naming/sectioning style).

Commands run

  • bun run test:run ui/src/stores/streamStoreHelpers.test.ts81 passed (81) (64 pre-existing + 17 new)
  • bun run lintexit 0, 6 pre-existing warnings, no new warnings or errors

Follow-ups / observations

  • Audio-deferred-until-video test: defers audio publishing until the video catalog is ready asserts audio.enabled.set(true) is called. The companion assertion (initial broadcastConfig.audio.enabled === false) was not added to avoid asserting on the constructor-argument shape, which is a private contract between setupPublishPath and Publish.Broadcast. If the deferred-enable branch is intentionally broken in production, this test still fails (the .set(true) call never happens).
  • applyWatchResult / applyPublishResult / applySecondaryPublishResult: These are not module exports and have no direct accessor — they're only reachable through performConnect. Their state mutations (attempt.watch / attempt.publish / attempt.secondaryPublish wiring) are covered indirectly via the performConnect happy-path tests that assert the resulting state.isMicEnabled / state.isCameraEnabled / state.watchStatus. Adding direct tests would require exporting them or adding a __testInternals__ hook in production code, which is out of scope per the "no production-code edits" rule.
  • setupWatchPath teardown idempotency: Covered behaviorally by the connection-status-drop test (the disconnect path tears down both watch and publish via cleanupConnectAttempt, which the existing test suite already covers for idempotency). Adding a direct double-teardown test would also require exposing setupWatchPath.
  • No real bugs surfaced.

Review & Testing Checklist for Human

  • Confirm the new tests in ui/src/stores/streamStoreHelpers.test.ts follow the same style as the existing test sections (vi.mock blocks at top, no parallel scaffolding, no .skip/.todo).
  • Spot-check that intentionally breaking a covered branch in streamStoreHelpers.ts (e.g. removing publish.audio.enabled.set(true) from the deferred branch, or removing the set({ status: 'disconnected', errorMessage: ... }) in the connection-drop handler) makes the corresponding test fail.
  • Run bun run test:run locally to verify the full UI suite still passes.

Notes

Mocks for @moq/hang, @moq/publish, @moq/watch, @moq/signals are reused from the existing test file — no parallel mock setup was introduced. Constructor mocks use function () { return {...}; } rather than arrow functions because new invocation requires [[Construct]]. Fake timers are scoped per-test via vi.useFakeTimers() / afterEach(vi.useRealTimers) for deterministic timing.

Link to Devin session: https://staging.itsdev.in/sessions/9f38da412d794f6c83fe76b22153a19e
Requested by: @streamer45


Devin Review

Status Commit
🟢 Reviewed ff366ff
Open in Devin Review (Staging)

…, status sync

Adds 17 behavioral tests extending the existing test file:

- performConnect: abort short-circuits, watch-only happy path, watch+publish happy path, deferred audio enable, requesting mic status, connection timeout sets error+disconnected, mid-connect abort doesn't overwrite state, watch setup errors clean up the connection.

- schedulePostConnectWarnings (watch): warns after 10s when watchStatus stays non-live, stays silent when already live, bails out when the user disconnects before the threshold.

- schedulePostConnectWarnings (mic): warns after 10s when mic source never resolves, stays silent when ready immediately, stays silent when mic becomes ready before the threshold.

- setupConnectionStatusSync: propagates relay 'disconnected'/'connecting' status to the store with the expected error-message behavior.

Behaviors are asserted via the mutated ConnectableState (status, errorMessage, mic/cameraStatus, isMicEnabled/isCameraEnabled), not via mock-call introspection. Tests reuse the existing @moq/* vi.mock blocks and createMockSignal/makeTrack helpers — no parallel test scaffolding.

Signed-off-by: StreamKit Devin <devin@streamkit.dev>
Co-Authored-By: Claudio Costa <cstcld91@gmail.com>
@staging-devin-ai-integration
Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

@codecov
Copy link
Copy Markdown

codecov Bot commented May 16, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 63.23%. Comparing base (90d476c) to head (ff366ff).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #446      +/-   ##
==========================================
+ Coverage   62.90%   63.23%   +0.32%     
==========================================
  Files         215      215              
  Lines       55435    55435              
  Branches     1597     1597              
==========================================
+ Hits        34874    35055     +181     
+ Misses      20555    20374     -181     
  Partials        6        6              
Flag Coverage Δ
backend 62.79% <ø> (+0.02%) ⬆️
ui 67.42% <ø> (+3.20%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Components Coverage Δ
core 84.29% <ø> (ø)
engine 75.24% <ø> (ø)
api 84.73% <ø> (ø)
nodes 67.09% <ø> (+0.05%) ⬆️
server 50.64% <ø> (ø)
plugin-native 70.93% <ø> (ø)
plugin-wasm 6.37% <ø> (ø)
ui-services 70.19% <ø> (+5.98%) ⬆️
ui-components 60.49% <ø> (ø)
see 2 files with indirect coverage changes
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown
Contributor Author

@staging-devin-ai-integration staging-devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 3 potential issues.

Open in Devin Review (Staging)
Debug

Playground

Comment on lines +867 to +869
// ---------------------------------------------------------------------------
// performConnect
// ---------------------------------------------------------------------------
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

🟡 New section divider comment violates repository comment guidelines

The PR adds a performConnect section-divider banner even though AGENTS.md explicitly lists section dividers as comments not to write and says to use code structure instead. This is a repository-specific mandatory review rule violation in the changed test code.

Suggested change
// ---------------------------------------------------------------------------
// performConnect
// ---------------------------------------------------------------------------
Open in Devin Review (Staging)

Was this helpful? React with 👍 or 👎 to provide feedback.

Debug

Playground

Comment on lines +1013 to +1023
asMock(Hang.Moq.Connection.Reload).mockImplementation(function () {
return { established: connEstablished, status: connStatus, close: vi.fn() };
});
asMock(Effect).mockImplementation(function () {
return mockEffect;
});
asMock(Watch.Broadcast).mockImplementation(function () {
return { status: watchStatusSig, close: vi.fn() };
});
asMock(Watch.Sync).mockImplementation(function () {
return { close: vi.fn() };
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

📝 Info: performConnect tests intentionally use lightweight MoQ stand-ins

The new performConnect suite mocks MoQ constructors with minimal objects and does not configure Publish.Lite.Path.from / Watch.Lite.Path.from return values. I did not treat this as a bug because setupPublishPath and setupWatchPath only pass those values into mocked Publish.Broadcast / Watch.Broadcast constructors during these tests (ui/src/stores/streamStoreHelpers.ts:604-609, ui/src/stores/streamStoreHelpers.ts:411-416), and the assertions target store transitions, cleanup, status subscriptions, and timer warnings rather than path parsing behavior.

Open in Devin Review (Staging)

Was this helpful? React with 👍 or 👎 to provide feedback.

Debug

Playground

Comment on lines +1245 to +1248
// Simulate the store transitioning out of `connected` before the timer fires
// — the warning callback should bail out without setting an error message.
state.status = 'disconnected';
state.errorMessage = '';
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

📝 Info: New warning tests rely on direct state mutation to simulate disconnects

The post-connect warning tests mutate the local state object directly before advancing fake timers. This is acceptable for this helper-level test because get returns the same mutable object and schedulePostConnectWarnings gates on get().status (ui/src/stores/streamStoreHelpers.ts:870-877), but it means the test is specifically validating the helper callback's status check rather than a full Zustand disconnect flow.

Open in Devin Review (Staging)

Was this helpful? React with 👍 or 👎 to provide feedback.

Debug

Playground

@streamer45 streamer45 merged commit 6f78127 into main May 16, 2026
26 checks passed
@streamer45 streamer45 deleted the devin/1778924687-test-streamStoreHelpers branch May 16, 2026 14:12
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.

2 participants