Keep iPhone audio playing through background handoffs
This commit is contained in:
43
frontend/audio-continuity.test.js
Normal file
43
frontend/audio-continuity.test.js
Normal file
@@ -0,0 +1,43 @@
|
||||
const { test } = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const { progressiveSource, needsAlignment, create } = require('./audio-continuity');
|
||||
test('iPhone progressive audio uses saved/EQ sources before remote fallbacks', () => {
|
||||
assert.equal(progressiveSource({ localUrl: 'blob:saved', audioUrl: 'remote' }, 'mux'), 'blob:saved');
|
||||
assert.equal(progressiveSource({ eqAudioUrl: 'blob:eq', localUrl: 'blob:saved' }), 'blob:eq');
|
||||
assert.equal(progressiveSource({ audioUrl: 'audio' }, 'mux'), 'audio');
|
||||
assert.equal(progressiveSource({}, 'mux'), 'mux');
|
||||
});
|
||||
test('small drift and invalid clocks do not trigger an audible seek', () => {
|
||||
assert.equal(needsAlignment(50.05, 50), false);
|
||||
assert.equal(needsAlignment(49, 50), true);
|
||||
assert.equal(needsAlignment(NaN, 50), false);
|
||||
});
|
||||
test('simultaneous play, visibility and watchdog resumes share one pending play', async () => {
|
||||
let finish, calls = 0, seeks = 0;
|
||||
const audio = { paused: true, get currentTime() { return 10; }, set currentTime(value) { seeks++; }, play() { calls++; return new Promise(resolve => { finish = resolve; }); } };
|
||||
const controller = create();
|
||||
controller.resume(audio, { currentTime: 10.05 });
|
||||
controller.resume(audio, { currentTime: 12 });
|
||||
const pending = controller.play(audio);
|
||||
assert.equal(calls, 1); assert.equal(seeks, 0);
|
||||
finish(); await pending;
|
||||
controller.resume(audio, audio); // never seek an element to itself
|
||||
assert.equal(seeks, 0); assert.equal(calls, 2); finish();
|
||||
});
|
||||
test('rejected autoplay can retry and only paused, misaligned secondaries seek', async () => {
|
||||
const controller = create(); let calls = 0;
|
||||
const audio = { paused: true, currentTime: 0, play() { calls++; return Promise.reject(new Error('OS suspension')); } };
|
||||
await controller.play(audio); await controller.resume(audio, { currentTime: 4 });
|
||||
assert.equal(calls, 2); assert.equal(audio.currentTime, 4);
|
||||
audio.paused = false; controller.resume(audio, { currentTime: 10 });
|
||||
assert.equal(audio.currentTime, 4); assert.equal(calls, 2);
|
||||
});
|
||||
test('a new play after pause/source reset is not blocked by a stale promise', async () => {
|
||||
const controller = create(), finishes = []; let calls = 0;
|
||||
const audio = { paused: true, play() { calls++; return new Promise(resolve => finishes.push(resolve)); } };
|
||||
const old = controller.play(audio); controller.reset(audio);
|
||||
const fresh = controller.play(audio); assert.equal(calls, 2);
|
||||
finishes[0](); await old;
|
||||
assert.equal(controller.play(audio), fresh); // old completion cannot discard the new request
|
||||
finishes[1](); await fresh;
|
||||
});
|
||||
Reference in New Issue
Block a user