Cypress: Feature request: High-level way to assert whether the browser is playing an audio file

Created on 21 May 2018  路  7Comments  路  Source: cypress-io/cypress

Current behavior:

No high-level ability to test whether the browser is playing an audio file.

Desired behavior:

If possible, it'd be great to have a high-level way to check whether a specific audio file is currently being played by the browser, whether by an <audio> tag, the web audio API, or some other method that I don't know about.

This could be something like cy.audio('https://example.com/path/to/music/file.mp3').should('be.playing').

My app uses howler JS to play audio files, and all I've been able to come up with in terms of testing the music is to use cy.window() to access the Howler global. This works okay, but it'd be great if there was a better way to do this that wasn't so tied to the specific tool I'm using.

Most helpful comment

@nwshane you can use this if you want to ensure audio is playing for the client....if you we're using audio or video elements.

const expectPlayingAudio = () => {
  cy.get('audio,video').should((els)=>{
    let audible = false
    els.each((i, el)=>{
      console.log(el)
      console.log(el.duration, el.paused, el.muted)
      if (el.duration > 0 && !el.paused && !el.muted) {
        audible = true
      }

      // expect(el.duration > 0 && !el.paused && !el.muted).to.eq(false)
    })
    expect(audible).to.eq(true)
  })
}

describe('page', () => {
  it('works', () => {
    cy.visit('/')
    expectPlayingAudio()
  })
})

All 7 comments

Whenever a Chrome tab is playing music, it shows a little music icon next to the X tab button:

tab music icon

This makes me think that there must be a way of programmatically asking the browser, "Is this tab playing music?" and gives me hope that this should be possible to do (at least from the browser's perspective).

@nwshane you can use this if you want to ensure audio is playing for the client....if you we're using audio or video elements.

const expectPlayingAudio = () => {
  cy.get('audio,video').should((els)=>{
    let audible = false
    els.each((i, el)=>{
      console.log(el)
      console.log(el.duration, el.paused, el.muted)
      if (el.duration > 0 && !el.paused && !el.muted) {
        audible = true
      }

      // expect(el.duration > 0 && !el.paused && !el.muted).to.eq(false)
    })
    expect(audible).to.eq(true)
  })
}

describe('page', () => {
  it('works', () => {
    cy.visit('/')
    expectPlayingAudio()
  })
})

@Bkucera Thanks for the response! I'm playing the songs with howler JS though, so there's no audio element in the DOM.

@nwshane you can try stubbing the window.Audio contructor, which Howler uses. That way you can get access to the same elements that howlerjs is using:

    const audios = []

    cy.visit('/', {onBeforeLoad: (win)=> {
      const originalAudio = win.Audio
      cy.stub(win, 'Audio').callsFake(()=>{
        const aud = new originalAudio()
        audios.push(aud)
        return aud
      })
    }})

    cy.wrap(null).should(() => {
      audios.forEach(aud => {
        console.log(aud.paused, aud.muted)
        expect(aud.paused || aud.muted).eq(true)
      })
    })

@nwshane Were you able to get this to work?

Unfortunately we have to close this issue due to inactivity. Please comment if there is new information to provide concerning the original issue and we can reopen.

I was able to get this example working for a video player with some modification.

It would have been nice to have asserts and commands that do something similar to work with out of the box:

cy.get('video')
.playVideo()
.should('be.playingVideo')

For now this can be done with custom commands, but I think that these would be nice additions for some people.

Was this page helpful?
0 / 5 - 0 ratings