- HlsPlayer: drive onPlaying from the <video> element's own `playing` event on BOTH the hls.js and Safari-native paths instead of MANIFEST_PARSED, which fires before any media has decoded (an HttpLiveStreamingDirect manifest always parses, even over a black video). MANIFEST_PARSED now only kicks play(). Restore `void video.play().catch(...)` at both call sites and stub HTMLMediaElement.prototype.play in setupTests.ts instead, so the `?.` that existed only to survive jsdom is gone from production code. - HlsPlayer.test.tsx: assert the auto-recovery guard against hls.js's own startLoad()/recoverMediaError(), not just loadSource's call count. - ChannelPreviewPanel: reuse existing ctv-* classes (ctv-channels-error, ctv-settings-warn-callout, ctv-detail-actions, ctv-detail-infogrid) instead of five undefined ctv-preview-* classes; add the two genuinely new rules (ctv-preview-video max-width, spacing tweaks) to shell.css. - Add an exported ChannelPreviewAvailability union (web/src/api/channels.ts) so a typo like 'ForcedHLSOnly' fails to compile instead of silently disabling a branch forever; use it in ChannelPreviewPanel's prop type and at the ChannelsScreen comparison sites.
22 lines
906 B
TypeScript
22 lines
906 B
TypeScript
import '@testing-library/jest-dom/vitest';
|
|
|
|
// jsdom has no real media pipeline: HTMLMediaElement.prototype.play is unimplemented and returns
|
|
// undefined rather than a Promise, which would otherwise force production code (HlsPlayer) to guard
|
|
// every call site with `?.` purely to survive tests. Stub it to behave like a real browser instead —
|
|
// tests that need an autoplay-blocked rejection can override it with vi.spyOn(...).mockRejectedValue.
|
|
HTMLMediaElement.prototype.play = () => Promise.resolve();
|
|
|
|
if (!window.localStorage) {
|
|
const storage = new Map<string, string>();
|
|
|
|
Object.defineProperty(window, 'localStorage', {
|
|
configurable: true,
|
|
value: {
|
|
clear: () => storage.clear(),
|
|
getItem: (key: string) => storage.get(key) ?? null,
|
|
removeItem: (key: string) => storage.delete(key),
|
|
setItem: (key: string, value: string) => storage.set(key, value)
|
|
}
|
|
});
|
|
}
|