refactor(player): E.3 — extract waveform/normalization/seek pure helpers (#566)

Three small tranches out of playerStore.ts:
- src/utils/waveformParse.ts — waveformBlobLenOk + coerceWaveformBins (the
  parser that handles number[] / Uint8Array / ArrayLike payloads Rust
  serializes as).
- src/utils/normalizationCompare.ts — normalizationAlmostEqual (tolerant
  null-aware dB comparison).
- src/utils/seekErrors.ts — isRecoverableSeekError (retry classifier for
  the Rust seek pipeline).

Each gets focused unit tests. All four were file-private, no external
callers — pure code move. playerStore 3556 → 3516 LOC.
This commit is contained in:
Frank Stellmacher
2026-05-12 11:45:09 +02:00
committed by GitHub
parent 1521e4ea8f
commit d24514d67e
7 changed files with 203 additions and 43 deletions
+28
View File
@@ -0,0 +1,28 @@
import { describe, expect, it } from 'vitest';
import { isRecoverableSeekError } from './seekErrors';
describe('isRecoverableSeekError', () => {
it.each([
'not seekable',
'audio sink not ready',
'audio seek busy',
'audio seek timeout',
])('classifies "%s" as recoverable', msg => {
expect(isRecoverableSeekError(msg)).toBe(true);
});
it('matches when the marker is embedded in a longer message', () => {
expect(isRecoverableSeekError('seek failed: audio sink not ready yet')).toBe(true);
expect(isRecoverableSeekError('error: audio seek timeout after 6000ms')).toBe(true);
});
it('returns false for unrelated errors', () => {
expect(isRecoverableSeekError('decoder failed')).toBe(false);
expect(isRecoverableSeekError('file not found')).toBe(false);
expect(isRecoverableSeekError('')).toBe(false);
});
it('is case-sensitive (Rust messages are stable)', () => {
expect(isRecoverableSeekError('Audio Sink Not Ready')).toBe(false);
});
});