test: harden Smart Speed worklet coverage

This commit is contained in:
Jonathan Baldie 2026-05-07 20:43:30 +01:00
parent 76a04065df
commit b4a9f8ad59
9 changed files with 183 additions and 1041 deletions

View file

@ -1,93 +1,42 @@
import LocalAudioPlayer from '../../../players/LocalAudioPlayer'
describe('LocalAudioPlayer', () => {
let mockPort;
let mockAudioContext;
let mockAudioWorkletNode;
it('increases playbackRate during silence with the real Web Audio pipeline', () => {
const localPlayer = new LocalAudioPlayer({})
beforeEach(() => {
// Mock for AudioWorkletNode message port
mockPort = {
onmessage: null,
postMessage: cy.stub()
};
expect(localPlayer.player.playbackRate).to.equal(1)
// Mock AudioWorkletNode
mockAudioWorkletNode = {
port: mockPort,
connect: cy.stub(),
disconnect: cy.stub()
};
cy.wrap(localPlayer.setSmartSpeed(true)).then(() => {
expect(localPlayer.enableSmartSpeed).to.be.true
expect(localPlayer.usingWebAudio).to.be.true
expect(localPlayer.audioContext).to.not.be.null
expect(localPlayer.audioSourceNode).to.not.be.null
expect(localPlayer.silenceDetectorNode).to.not.be.null
expect(localPlayer.silenceDetectorNode.constructor.name).to.equal('AudioWorkletNode')
// Mock AudioContext
mockAudioContext = {
audioWorklet: {
addModule: cy.stub().resolves()
},
createMediaElementSource: cy.stub().returns({
connect: cy.stub(),
disconnect: cy.stub()
}),
destination: {},
state: 'running',
currentTime: 10
};
// Make AudioWorkletNode available globally so `new AudioWorkletNode` works
if (!window.AudioWorkletNode) {
window.AudioWorkletNode = function() { return mockAudioWorkletNode; };
} else {
cy.stub(window, 'AudioWorkletNode').returns(mockAudioWorkletNode);
}
if (!window.AudioContext) {
window.AudioContext = function() { return mockAudioContext; };
} else {
cy.stub(window, 'AudioContext').returns(mockAudioContext);
}
if (window.webkitAudioContext) {
cy.stub(window, 'webkitAudioContext').returns(mockAudioContext);
}
});
it('increases playbackRate during silence', () => {
const localPlayer = new LocalAudioPlayer({});
// Default playback rate should be 1
expect(localPlayer.player.playbackRate).to.equal(1);
cy.wrap(localPlayer).should('have.property', 'usingWebAudio', true).then(() => {
// Enable smart speed (this should trigger initSilenceDetector)
return localPlayer.setSmartSpeed(true);
}).then(() => {
expect(localPlayer.enableSmartSpeed).to.be.true;
expect(mockAudioContext.audioWorklet.addModule).to.have.been.calledWith('/client/players/smart-speed/SilenceDetectorProcessor.js');
expect(localPlayer.silenceDetectorNode).to.equal(mockAudioWorkletNode);
// Simulate silence start
mockPort.onmessage({
localPlayer.player.currentTime = 5
localPlayer.silenceDetectorNode.port.onmessage({
data: {
type: 'silence-start',
time: 5000 // 5 seconds
time: localPlayer.audioContext.currentTime * 1000
}
});
// The smartSpeedRatio is 2.0 by default, so playbackRate should be 2.0
expect(localPlayer.player.playbackRate).to.equal(2.0);
// Simulate silence end
mockPort.onmessage({
})
expect(localPlayer.player.playbackRate).to.equal(2.0)
localPlayer.player.currentTime = 8
localPlayer.silenceDetectorNode.port.onmessage({
data: {
type: 'silence-end',
time: 8000 // 8 seconds
time: localPlayer.audioContext.currentTime * 1000
}
});
// Should return to default 1.0
expect(localPlayer.player.playbackRate).to.equal(1.0);
});
});
})
expect(localPlayer.player.playbackRate).to.equal(1.0)
localPlayer.destroy()
})
})
it('maps currentTime, duration, and seek through the same Smart Speed wall-clock contract', () => {
const localPlayer = new LocalAudioPlayer({});