import { waitFor , act } from '@testing-library/react' ; import { renderHook } from '@testing-library/react-hooks' ; import useAudio from './useAudio' ; import { CreateAudioArgs } from './useAudio.types' ; describe ( 'useAudio' , ( ) => { beforeAll ( ( ) => { window . HTMLMediaElement . prototype . load = jest . fn ( ) ; } ) ; describe ( 'onCreateAudio' , ( ) => { test ( 'should create audio element' , async ( ) => { let audio = undefined ; const { result } = renderHook ( ( ) => useAudio ( ) ) ; const args = { src : 'https://storage.googleapis.com/media-session/elephants-dream/the-wires.mp3' , preload : 'auto' , autoplay : true , volume : 1.0 , rate : 1.0 , mute : false , loop : false } ; await waitFor ( async ( ) => { audio = await result . current . onCreateAudio ( args ) ; } ) ; expect ( audio ) . toBeInstanceOf ( HTMLAudioElement ) ; expect ( audio ) . toHaveProperty ( 'preload' , args . preload ) ; expect ( audio ) . toHaveProperty ( 'autoplay' , args . autoplay ) ; expect ( audio ) . toHaveProperty ( 'volume' , args . volume ) ; expect ( audio ) . toHaveProperty ( 'playbackRate' , args . rate ) ; expect ( audio ) . toHaveProperty ( 'muted' , args . mute ) ; expect ( audio ) . toHaveProperty ( 'loop' , args . loop ) ; } ) ; test ( 'should create audio element with preload equal "metadata"' , async ( ) => { const { result } = renderHook ( ( ) => useAudio ( ) ) ; const args = { src : 'https://storage.googleapis.com/media-session/elephants-dream/the-wires.mp3' , preload : 'none' , autoplay : true , volume : 1.0 , rate : 1.0 , mute : false , loop : false } ; const audio = await result . current . onCreateAudio ( args ) ; expect ( audio ) . toBeInstanceOf ( HTMLAudioElement ) ; expect ( audio ) . toHaveProperty ( 'preload' , args . preload ) ; expect ( audio ) . toHaveProperty ( 'autoplay' , args . autoplay ) ; expect ( audio ) . toHaveProperty ( 'volume' , args . volume ) ; expect ( audio ) . toHaveProperty ( 'playbackRate' , args . rate ) ; expect ( audio ) . toHaveProperty ( 'muted' , args . mute ) ; expect ( audio ) . toHaveProperty ( 'loop' , args . loop ) ; } ) ; test ( 'should create audio element with preload equal "none"' , async ( ) => { const { result } = renderHook ( ( ) => useAudio ( ) ) ; const args = { src : 'https://storage.googleapis.com/media-session/elephants-dream/the-wires.mp3' , preload : 'none' , autoplay : true , volume : 1.0 , rate : 1.0 , mute : false , loop : false } ; const audio = await result . current . onCreateAudio ( args ) ; expect ( audio ) . toBeInstanceOf ( HTMLAudioElement ) ; expect ( audio ) . toHaveProperty ( 'preload' , args . preload ) ; expect ( audio ) . toHaveProperty ( 'autoplay' , args . autoplay ) ; expect ( audio ) . toHaveProperty ( 'volume' , args . volume ) ; expect ( audio ) . toHaveProperty ( 'playbackRate' , args . rate ) ; expect ( audio ) . toHaveProperty ( 'muted' , args . mute ) ; expect ( audio ) . toHaveProperty ( 'loop' , args . loop ) ; } ) ; test ( 'should create audio element with autoplay equal "false"' , async ( ) => { const { result } = renderHook ( ( ) => useAudio ( ) ) ; const args = { src : 'https://storage.googleapis.com/media-session/elephants-dream/the-wires.mp3' , preload : 'auto' , autoplay : false , volume : 1.0 , rate : 1.0 , mute : false , loop : false } ; const audio = await result . current . onCreateAudio ( args ) ; expect ( audio ) . toBeInstanceOf ( HTMLAudioElement ) ; expect ( audio ) . toHaveProperty ( 'preload' , args . preload ) ; expect ( audio ) . toHaveProperty ( 'autoplay' , args . autoplay ) ; expect ( audio ) . toHaveProperty ( 'volume' , args . volume ) ; expect ( audio ) . toHaveProperty ( 'playbackRate' , args . rate ) ; expect ( audio ) . toHaveProperty ( 'muted' , args . mute ) ; expect ( audio ) . toHaveProperty ( 'loop' , args . loop ) ; } ) ; test ( 'should create audio element with volume equal "0.5"' , async ( ) => { const { result } = renderHook ( ( ) => useAudio ( ) ) ; const args = { src : 'https://storage.googleapis.com/media-session/elephants-dream/the-wires.mp3' , preload : 'auto' , autoplay : true , volume : 0.5 , rate : 1.0 , mute : false , loop : false } ; const audio = await result . current . onCreateAudio ( args ) ; expect ( audio ) . toBeInstanceOf ( HTMLAudioElement ) ; expect ( audio ) . toHaveProperty ( 'preload' , args . preload ) ; expect ( audio ) . toHaveProperty ( 'autoplay' , args . autoplay ) ; expect ( audio ) . toHaveProperty ( 'volume' , args . volume ) ; expect ( audio ) . toHaveProperty ( 'playbackRate' , args . rate ) ; expect ( audio ) . toHaveProperty ( 'muted' , args . mute ) ; expect ( audio ) . toHaveProperty ( 'loop' , args . loop ) ; } ) ; test ( 'should create audio element with rate equal "0.5"' , async ( ) => { const { result } = renderHook ( ( ) => useAudio ( ) ) ; const args = { src : 'https://storage.googleapis.com/media-session/elephants-dream/the-wires.mp3' , preload : 'auto' , autoplay : true , volume : 1.0 , rate : 0.5 , mute : false , loop : false } ; const audio = await result . current . onCreateAudio ( args ) ; expect ( audio ) . toBeInstanceOf ( HTMLAudioElement ) ; expect ( audio ) . toHaveProperty ( 'preload' , args . preload ) ; expect ( audio ) . toHaveProperty ( 'autoplay' , args . autoplay ) ; expect ( audio ) . toHaveProperty ( 'volume' , args . volume ) ; expect ( audio ) . toHaveProperty ( 'playbackRate' , args . rate ) ; expect ( audio ) . toHaveProperty ( 'muted' , args . mute ) ; expect ( audio ) . toHaveProperty ( 'loop' , args . loop ) ; } ) ; test ( 'should create audio element with muted equal "true"' , async ( ) => { const { result } = renderHook ( ( ) => useAudio ( ) ) ; const args = { src : 'https://storage.googleapis.com/media-session/elephants-dream/the-wires.mp3' , preload : 'auto' , autoplay : true , volume : 1.0 , rate : 1.0 , mute : true , loop : false } ; const audio = await result . current . onCreateAudio ( args ) ; expect ( audio ) . toBeInstanceOf ( HTMLAudioElement ) ; expect ( audio ) . toHaveProperty ( 'preload' , args . preload ) ; expect ( audio ) . toHaveProperty ( 'autoplay' , args . autoplay ) ; expect ( audio ) . toHaveProperty ( 'volume' , args . volume ) ; expect ( audio ) . toHaveProperty ( 'playbackRate' , args . rate ) ; expect ( audio ) . toHaveProperty ( 'muted' , args . mute ) ; expect ( audio ) . toHaveProperty ( 'loop' , args . loop ) ; } ) ; test ( 'should create audio element with loop equal "true"' , async ( ) => { const { result } = renderHook ( ( ) => useAudio ( ) ) ; const args = { src : 'https://storage.googleapis.com/media-session/elephants-dream/the-wires.mp3' , preload : 'auto' , autoplay : true , volume : 1.0 , rate : 1.0 , mute : false , loop : true } ; const audio = await result . current . onCreateAudio ( args ) ; expect ( audio ) . toBeInstanceOf ( HTMLAudioElement ) ; expect ( audio ) . toHaveProperty ( 'preload' , args . preload ) ; expect ( audio ) . toHaveProperty ( 'autoplay' , args . autoplay ) ; expect ( audio ) . toHaveProperty ( 'volume' , args . volume ) ; expect ( audio ) . toHaveProperty ( 'playbackRate' , args . rate ) ; expect ( audio ) . toHaveProperty ( 'muted' , args . mute ) ; expect ( audio ) . toHaveProperty ( 'loop' , args . loop ) ; } ) ; } ) ; describe ( 'onLoadAudio' , ( ) => { test ( 'should create audio and load it' , async ( ) => { const { result } = renderHook ( ( ) => useAudio ( ) ) ; const args = { src : 'https://storage.googleapis.com/media-session/elephants-dream/the-wires.mp3' , preload : 'auto' , autoplay : true , volume : 1.0 , rate : 1.0 , mute : false , loop : true } ; const audio = await result . current . onLoadAudio ( undefined , args ) ; expect ( audio ) . toBeInstanceOf ( HTMLAudioElement ) ; expect ( audio ) . toHaveProperty ( 'preload' , args . preload ) ; expect ( audio ) . toHaveProperty ( 'autoplay' , args . autoplay ) ; expect ( audio ) . toHaveProperty ( 'volume' , args . volume ) ; expect ( audio ) . toHaveProperty ( 'playbackRate' , args . rate ) ; expect ( audio ) . toHaveProperty ( 'muted' , args . mute ) ; expect ( audio ) . toHaveProperty ( 'loop' , args . loop ) ; } ) ; test ( 'should change audio src' , async ( ) => { const { result } = renderHook ( ( ) => useAudio ( ) ) ; const firstArgs = { src : 'https://www.theincomparable.com/podcast/batmanuniversity302.mp3' , preload : 'auto' , autoplay : true , volume : 1.0 , rate : 1.0 , mute : false , loop : true } ; const secondArgs = { src : 'https://storage.googleapis.com/media-session/elephants-dream/the-wires.mp3' , preload : 'auto' , autoplay : true , volume : 1.0 , rate : 1.0 , mute : false , loop : true } ; act ( ( ) => { const audio = result . current . onLoadAudio ( undefined , firstArgs ) ; expect ( audio ) . toBeInstanceOf ( HTMLAudioElement ) ; expect ( audio ) . toHaveProperty ( 'preload' , firstArgs . preload ) ; expect ( audio ) . toHaveProperty ( 'autoplay' , firstArgs . autoplay ) ; expect ( audio ) . toHaveProperty ( 'volume' , firstArgs . volume ) ; expect ( audio ) . toHaveProperty ( 'playbackRate' , firstArgs . rate ) ; expect ( audio ) . toHaveProperty ( 'muted' , firstArgs . mute ) ; expect ( audio ) . toHaveProperty ( 'loop' , firstArgs . loop ) ; result . current . onLoadAudio ( audio , secondArgs ) ; expect ( audio ) . toBeInstanceOf ( HTMLAudioElement ) ; expect ( audio ) . toHaveProperty ( 'preload' , secondArgs . preload ) ; expect ( audio ) . toHaveProperty ( 'autoplay' , secondArgs . autoplay ) ; expect ( audio ) . toHaveProperty ( 'volume' , secondArgs . volume ) ; expect ( audio ) . toHaveProperty ( 'playbackRate' , secondArgs . rate ) ; expect ( audio ) . toHaveProperty ( 'muted' , secondArgs . mute ) ; expect ( audio ) . toHaveProperty ( 'loop' , secondArgs . loop ) ; } ) ; } ) ; } ) ; describe ( 'onDestroyAudio' , ( ) => { test ( 'should destroy audio' , async ( ) => { const { result } = renderHook ( ( ) => useAudio ( ) ) ; const args = { src : 'https://storage.googleapis.com/media-session/elephants-dream/the-wires.mp3' , preload : 'auto' , autoplay : true , volume : 1.0 , rate : 1.0 , mute : false , loop : true } ; let audio = await result . current . onCreateAudio ( args ) ; expect ( audio ) . toBeInstanceOf ( HTMLAudioElement ) ; expect ( audio ) . toHaveProperty ( 'preload' , args . preload ) ; expect ( audio ) . toHaveProperty ( 'autoplay' , args . autoplay ) ; expect ( audio ) . toHaveProperty ( 'volume' , args . volume ) ; expect ( audio ) . toHaveProperty ( 'playbackRate' , args . rate ) ; expect ( audio ) . toHaveProperty ( 'muted' , args . mute ) ; expect ( audio ) . toHaveProperty ( 'loop' , args . loop ) ; audio = await result . current . onDestroyAudio ( audio ) ; expect ( audio ) . toBeUndefined ( ) ; } ) ; test ( 'should not destroy audio and return undefined when there is no audio' , async ( ) => { const { result } = renderHook ( ( ) => useAudio ( ) ) ; const destroyFn = await result . current . onDestroyAudio ( undefined ) ; expect ( destroyFn ) . toBeUndefined ( ) ; } ) ; } ) ; } ) ;