@@ -484,6 +484,146 @@ test.describe("WebAudioLayer Autoplay Policy Fix", () => {
484484 } )
485485} )
486486
487+ test . describe ( "WebAudioLayer Recording" , ( ) => {
488+ test . beforeEach ( async ( { page } ) => {
489+ await page . goto ( "http://localhost:3000/tests/browser/test-page.html" )
490+ } )
491+
492+ test ( "should return null stream before recording enabled" , async ( {
493+ page,
494+ } ) => {
495+ const result = await page . evaluate (
496+ `(async () => {
497+ ${ getAudioSetup ( ) }
498+
499+ return {
500+ stream: audio.getRecordingStream(),
501+ }
502+ })()` ,
503+ )
504+
505+ expect ( result . stream ) . toBeNull ( )
506+ } )
507+
508+ test ( "should enable recording and return MediaStream" , async ( { page } ) => {
509+ const result = await page . evaluate (
510+ `(async () => {
511+ ${ getAudioSetup ( ) }
512+
513+ audio.enableRecording()
514+ const stream = audio.getRecordingStream()
515+
516+ return {
517+ hasStream: stream !== null,
518+ isMediaStream: stream instanceof MediaStream,
519+ streamActive: stream ? stream.active : false,
520+ }
521+ })()` ,
522+ )
523+
524+ expect ( result . hasStream ) . toBe ( true )
525+ expect ( result . isMediaStream ) . toBe ( true )
526+ } )
527+
528+ test ( "should disable recording and return null stream" , async ( { page } ) => {
529+ const result = await page . evaluate (
530+ `(async () => {
531+ ${ getAudioSetup ( ) }
532+
533+ audio.enableRecording()
534+ const streamBefore = audio.getRecordingStream()
535+
536+ audio.disableRecording()
537+ const streamAfter = audio.getRecordingStream()
538+
539+ return {
540+ hadStreamBefore: streamBefore !== null,
541+ hasStreamAfter: streamAfter !== null,
542+ }
543+ })()` ,
544+ )
545+
546+ expect ( result . hadStreamBefore ) . toBe ( true )
547+ expect ( result . hasStreamAfter ) . toBe ( false )
548+ } )
549+
550+ test ( "should handle enable/disable cycle multiple times" , async ( {
551+ page,
552+ } ) => {
553+ const result = await page . evaluate (
554+ `(async () => {
555+ ${ getAudioSetup ( ) }
556+
557+ const states = []
558+
559+ for (let i = 0; i < 3; i++) {
560+ audio.enableRecording()
561+ states.push(audio.getRecordingStream() !== null)
562+ audio.disableRecording()
563+ states.push(audio.getRecordingStream() === null)
564+ }
565+
566+ return { states }
567+ })()` ,
568+ )
569+
570+ expect ( result . states ) . toEqual ( [ true , true , true , true , true , true ] )
571+ } )
572+
573+ test ( "should cleanup recording on destroy" , async ( { page } ) => {
574+ const result = await page . evaluate (
575+ `(async () => {
576+ ${ getAudioSetup ( ) }
577+
578+ audio.enableRecording()
579+ const streamBefore = audio.getRecordingStream()
580+
581+ audio.destroy()
582+ const streamAfter = audio.getRecordingStream()
583+
584+ return {
585+ hadStreamBefore: streamBefore !== null,
586+ hasStreamAfter: streamAfter !== null,
587+ }
588+ })()` ,
589+ )
590+
591+ expect ( result . hadStreamBefore ) . toBe ( true )
592+ expect ( result . hasStreamAfter ) . toBe ( false )
593+ } )
594+
595+ test ( "should allow sound playback while recording" , async ( { page } ) => {
596+ const result = await page . evaluate (
597+ `(async () => {
598+ ${ getAudioSetup ( ) }
599+ ${ CREATE_TEST_BUFFER }
600+
601+ const buffer = createTestBuffer(audio, 440, 0.05)
602+ audio.loadSoundFromBuffer("test-tone", buffer)
603+
604+ await audio.tryResumeOnce()
605+
606+ audio.enableRecording()
607+ const stream = audio.getRecordingStream()
608+
609+ audio.playSound("test-tone", 0.5, false)
610+
611+ await new Promise(resolve => setTimeout(resolve, 50))
612+
613+ audio.stopSound("test-tone")
614+
615+ return {
616+ hasStream: stream !== null,
617+ state: audio.getState(),
618+ }
619+ })()` ,
620+ )
621+
622+ expect ( result . hasStream ) . toBe ( true )
623+ expect ( result . state ) . toBe ( AudioContextState . RUNNING )
624+ } )
625+ } )
626+
487627test . describe ( "WebAudioLayer Data URL Loading" , ( ) => {
488628 test . beforeEach ( async ( { page } ) => {
489629 await page . goto ( "http://localhost:3000/tests/browser/test-page.html" )
0 commit comments