@@ -6,7 +6,7 @@ import { Future } from '../../utils.js';
66import { ParticipantAudioOutput } from './_output.js' ;
77
88describe ( 'ParticipantAudioOutput waitForPlayoutTask' , ( ) => {
9- it ( 'preserves duration queued by overlapping next segment ' , async ( ) => {
9+ it ( 'resets tracked duration after non-interrupted playout ' , async ( ) => {
1010 let resolvePlayout ! : ( ) => void ;
1111 const waitForPlayout = new Promise < void > ( ( resolve ) => {
1212 resolvePlayout = resolve ;
@@ -38,15 +38,61 @@ describe('ParticipantAudioOutput waitForPlayoutTask', () => {
3838
3939 const task = output . waitForPlayoutTask ( new AbortController ( ) ) ;
4040
41- // Simulate a new overlapping segment that starts before the previous flush completes.
42- output . pushedDuration += 0.5 ;
4341 resolvePlayout ( ) ;
4442 await task ;
4543
46- expect ( output . pushedDuration ) . toBe ( 0.5 ) ;
44+ expect ( output . pushedDuration ) . toBe ( 0 ) ;
4745 expect ( onPlaybackFinished ) . toHaveBeenCalledWith ( {
4846 playbackPosition : 1.0 ,
4947 interrupted : false ,
5048 } ) ;
5149 } ) ;
50+
51+ it ( 'resets duration to queue state when interrupted flush clears overlap' , async ( ) => {
52+ let resolvePlayout ! : ( ) => void ;
53+ const waitForPlayout = new Promise < void > ( ( resolve ) => {
54+ resolvePlayout = resolve ;
55+ } ) ;
56+
57+ const output = Object . create ( ParticipantAudioOutput . prototype ) as ParticipantAudioOutput & {
58+ pushedDuration : number ;
59+ interruptedFuture : Future < void > ;
60+ firstFrameEmitted : boolean ;
61+ audioSource : {
62+ waitForPlayout : ( ) => Promise < void > ;
63+ queuedDuration : number ;
64+ clearQueue : ( ) => void ;
65+ } ;
66+ onPlaybackFinished : ( event : { playbackPosition : number ; interrupted : boolean } ) => void ;
67+ waitForPlayoutTask : ( abortController : AbortController ) => Promise < void > ;
68+ } ;
69+
70+ const onPlaybackFinished = vi . fn ( ) ;
71+ output . pushedDuration = 1.0 ;
72+ output . interruptedFuture = new Future < void > ( ) ;
73+ output . firstFrameEmitted = true ;
74+ output . onPlaybackFinished = onPlaybackFinished ;
75+ output . audioSource = {
76+ waitForPlayout : ( ) => waitForPlayout ,
77+ queuedDuration : 500 ,
78+ clearQueue : vi . fn ( ( ) => {
79+ output . audioSource . queuedDuration = 0 ;
80+ } ) ,
81+ } ;
82+
83+ const task = output . waitForPlayoutTask ( new AbortController ( ) ) ;
84+
85+ // Overlap from the next segment arrives before interruption.
86+ output . pushedDuration += 0.5 ;
87+ output . interruptedFuture . resolve ( ) ;
88+ resolvePlayout ( ) ;
89+ await task ;
90+
91+ // interrupted path clears queued overlap, so duration should not retain stale overlap time.
92+ expect ( output . pushedDuration ) . toBe ( 0 ) ;
93+ expect ( onPlaybackFinished ) . toHaveBeenCalledWith ( {
94+ playbackPosition : 0.5 ,
95+ interrupted : true ,
96+ } ) ;
97+ } ) ;
5298} ) ;
0 commit comments