fix(MediaRecorder): guard pause/resume against inactive recorder to prevent InvalidStateError#3218
fix(MediaRecorder): guard pause/resume against inactive recorder to prevent InvalidStateError#3218MartinCupela wants to merge 2 commits into
Conversation
β¦revent InvalidStateError
|
No actionable comments were generated in the recent review. π βΉοΈ Recent review infoβοΈ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: π Files selected for processing (1)
π€ Files with no reviewable changes (1)
π WalkthroughWalkthroughAdds native-state guards to MediaRecorderController.pause() and .resume() to avoid calling native methods when the underlying MediaRecorder is not in the required state, and adds regression tests that simulate an ChangesMediaRecorder pause/resume state guards
Estimated code review effortπ― 3 (Moderate) | β±οΈ ~20 minutes Poem
π₯ Pre-merge checks | β 5β Passed checks (5 passed)
βοΈ Tip: You can configure your own custom pre-merge checks in the settings. β¨ Finishing Touchesπ Generate docstrings
π§ͺ Generate unit tests (beta)
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. Comment |
|
Size Change: +12 B (0%) Total Size: 656 kB π¦ View Changed
βΉοΈ View Unchanged
|
There was a problem hiding this comment.
π§Ή Nitpick comments (1)
src/components/MediaRecorder/classes/__tests__/MediaRecorderController.test.ts (1)
421-442: π€ Low valueMinor redundancy in test setup.
Line 429 sets
controller.recordingState.next(MediaRecordingState.PAUSED), but this is redundant since line 427controller.pause()already updates the recording state toPAUSED. While not a functional issue, removing it would reduce noise.β»οΈ Optional simplification
const controller = new MediaRecorderController(); await controller.start(); controller.pause(); const recorder = controller.mediaRecorder as unknown as MediaRecorderMockType; - controller.recordingState.next(MediaRecordingState.PAUSED); recorder.state = 'inactive';π€ Prompt for 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. In `@src/components/MediaRecorder/classes/__tests__/MediaRecorderController.test.ts` around lines 421 - 442, The test duplicates state setup: after calling controller.pause() the recording state is already PAUSED, so remove the redundant manual state mutation controller.recordingState.next(MediaRecordingState.PAUSED) in the test 'does not resume the native recorder when its state is inactive'; keep controller.pause(), the recorder mock setup (recorder.state = 'inactive' and recorder.resume.mockImplementation(...)), and the expect assertions intact to simplify the test while preserving behavior.
π€ 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.
Nitpick comments:
In
`@src/components/MediaRecorder/classes/__tests__/MediaRecorderController.test.ts`:
- Around line 421-442: The test duplicates state setup: after calling
controller.pause() the recording state is already PAUSED, so remove the
redundant manual state mutation
controller.recordingState.next(MediaRecordingState.PAUSED) in the test 'does not
resume the native recorder when its state is inactive'; keep controller.pause(),
the recorder mock setup (recorder.state = 'inactive' and
recorder.resume.mockImplementation(...)), and the expect assertions intact to
simplify the test while preserving behavior.
βΉοΈ Review info
βοΈ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 4c228558-9c9c-4759-9d8a-cd4f24f64094
π Files selected for processing (2)
src/components/MediaRecorder/classes/MediaRecorderController.tssrc/components/MediaRecorder/classes/__tests__/MediaRecorderController.test.ts
Codecov Reportβ
All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #3218 +/- ##
==========================================
- Coverage 83.95% 83.92% -0.03%
==========================================
Files 439 439
Lines 13222 13224 +2
Branches 4293 4295 +2
==========================================
- Hits 11100 11098 -2
- Misses 2122 2126 +4 β View full report in Codecov by Harness. π New features to boost your workflow:
|
π― Goal
Port changes from #3217 to v14.
π Implementation details
Root cause
In
MediaRecorderController,pause()guards only against the controller's internal state subject, then calls the native API unconditionally:The internal recordingState
BehaviorSubjectcan drift out of sync with the nativemediaRecorder.state. On iOS Safari the native MediaRecorder can transition to inactive on its own (interruptions, the stop button's nativestop(), track ending) while the React-driven recordingState subject still reads RECORDING. When the user taps stop then immediately pause,pause()passes its internal-state guard butthis.mediaRecorder.pause()hits an inactive recorder β InvalidStateError: The MediaRecorder's state cannot be inactive.Note the inconsistency:
stop()already guards against the nativethis.mediaRecorder?.state, butpause()/resume()guard only against the internal subject. That asymmetry is the bug.Summary by CodeRabbit