mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2026-05-16 08:21:29 +00:00
110 lines
3.3 KiB
JavaScript
110 lines
3.3 KiB
JavaScript
import LocalAudioPlayer from '../../../players/LocalAudioPlayer'
|
|
|
|
describe('LocalAudioPlayer', () => {
|
|
let mockPort;
|
|
let mockAudioContext;
|
|
let mockAudioWorkletNode;
|
|
|
|
beforeEach(() => {
|
|
// Mock for AudioWorkletNode message port
|
|
mockPort = {
|
|
onmessage: null,
|
|
postMessage: cy.stub()
|
|
};
|
|
|
|
// Mock AudioWorkletNode
|
|
mockAudioWorkletNode = {
|
|
port: mockPort,
|
|
connect: cy.stub(),
|
|
disconnect: cy.stub()
|
|
};
|
|
|
|
// 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({
|
|
data: {
|
|
type: 'silence-start',
|
|
time: 5000 // 5 seconds
|
|
}
|
|
});
|
|
|
|
// 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({
|
|
data: {
|
|
type: 'silence-end',
|
|
time: 8000 // 8 seconds
|
|
}
|
|
});
|
|
|
|
// Should return to default 1.0
|
|
expect(localPlayer.player.playbackRate).to.equal(1.0);
|
|
});
|
|
});
|
|
|
|
it('maps currentTime, duration, and seek through the same Smart Speed wall-clock contract', () => {
|
|
const localPlayer = new LocalAudioPlayer({});
|
|
|
|
localPlayer.audioTracks = [{ startOffset: 0, duration: 12 }];
|
|
localPlayer.currentTrackIndex = 0;
|
|
localPlayer.enableSmartSpeed = true;
|
|
localPlayer.smartSpeedRatio = 2.0;
|
|
localPlayer.silenceMap.addRegion(2000, 6000);
|
|
localPlayer.updateSmartSpeedRegions();
|
|
|
|
localPlayer.player.currentTime = 8;
|
|
|
|
expect(localPlayer.getCurrentTime()).to.equal(6);
|
|
expect(localPlayer.getDuration()).to.equal(10);
|
|
|
|
localPlayer.seek(6, false);
|
|
expect(localPlayer.player.currentTime).to.equal(8);
|
|
});
|
|
});
|