@@ -130,21 +130,21 @@ describe("scrubPreviewAudio", () => {
130130 audio . pause = vi . fn ( ) ;
131131 iframe . contentDocument . body . append ( audio ) ;
132132
133- scrubPreviewAudio ( iframe , 0.5 , "music" , 0.4 ) ;
133+ scrubPreviewAudio ( iframe , 0.5 , { id : "music" } , 0.4 ) ;
134134
135135 expect ( audio . volume ) . toBeCloseTo ( 0.1 ) ;
136136 stopScrubPreviewAudio ( ) ;
137137 } ) ;
138138
139139 /**
140140 * The preview document is a different realm, so `instanceof HTMLAudioElement`
141- * is false for every node in it. That threw the `musicId ` hint away and left
141+ * is false for every node in it. That threw the `music ` hint away and left
142142 * the first `<audio>` in the document as the only route — and the first
143143 * `<audio>` is often the voiceover, so scrubbing previewed the wrong track.
144144 * Two elements, music second, is what tells the two paths apart: with one
145145 * element the fallback reaches the right node by accident.
146146 */
147- it ( "previews the track named by musicId , not the first audio in the document" , ( ) => {
147+ it ( "previews the track named by the music row , not the first audio in the document" , ( ) => {
148148 const iframe = document . createElement ( "iframe" ) ;
149149 document . body . append ( iframe ) ;
150150 const previewDoc = iframe . contentDocument ;
@@ -165,13 +165,32 @@ describe("scrubPreviewAudio", () => {
165165 // The node really is cross-realm; this is the condition, not a contrivance.
166166 expect ( music instanceof HTMLAudioElement ) . toBe ( false ) ;
167167
168- scrubPreviewAudio ( iframe , 0.5 , "music-bed" , 1 ) ;
168+ scrubPreviewAudio ( iframe , 0.5 , { id : "music-bed" } , 1 ) ;
169169
170170 expect ( music . play ) . toHaveBeenCalled ( ) ;
171171 expect ( voiceover . play ) . not . toHaveBeenCalled ( ) ;
172172 stopScrubPreviewAudio ( ) ;
173173 } ) ;
174174
175+ it ( "previews the music row's own track when a sub-composition repeats its id" , ( ) => {
176+ const iframe = document . createElement ( "iframe" ) ;
177+ document . body . append ( iframe ) ;
178+ const previewDoc = iframe . contentDocument ;
179+ if ( ! previewDoc ?. body ) throw new Error ( "expected an iframe document" ) ;
180+ previewDoc . body . innerHTML =
181+ '<div data-composition-id="strip" data-composition-src="compositions/strip.html"><audio id="music"></audio></div>' +
182+ '<audio id="music" class="root"></audio>' ;
183+ const [ inner , root ] = Array . from ( previewDoc . querySelectorAll ( "audio" ) ) ;
184+ for ( const audio of [ inner , root ] )
185+ Object . assign ( audio ! , { play : vi . fn ( async ( ) => { } ) , pause : vi . fn ( ) } ) ;
186+
187+ scrubPreviewAudio ( iframe , 0.5 , { id : "music" } , 1 ) ;
188+
189+ expect ( root ! . play ) . toHaveBeenCalled ( ) ;
190+ expect ( inner ! . play ) . not . toHaveBeenCalled ( ) ;
191+ stopScrubPreviewAudio ( ) ;
192+ } ) ;
193+
175194 /** A scrub audition is media running under a paused clock, which the runtime now
176195 * stops on sight. So it borrows the element. That a leased element survives the
177196 * tick is asserted runtime-side in core's `transportPark.test.ts`; here the
@@ -192,7 +211,7 @@ describe("scrubPreviewAudio", () => {
192211 const releasePausedMedia = vi . fn ( ) ;
193212 ( previewDoc . defaultView as IframeWindow ) . __hf = { leasePausedMedia, releasePausedMedia } ;
194213
195- scrubPreviewAudio ( iframe , 0.5 , "music" , 1 ) ;
214+ scrubPreviewAudio ( iframe , 0.5 , { id : "music" } , 1 ) ;
196215
197216 expect ( leasePausedMedia ) . toHaveBeenCalledWith ( music ) ;
198217 expect ( releasePausedMedia ) . not . toHaveBeenCalled ( ) ;
0 commit comments