Capybara: Pretending to interact with the document

Posted . Visible to the public.

Browsers blocks abusable JavaScript API calls until the user has interacted with the document. Examples would be opening new tab or start playing video or audio.

E.g. if you attempt to call video.play() in a test, the call will reject with a message like this:

NotAllowedError: play() failed because the user didn't interact with the document first. https://goo.gl/xX8pDD

Workaround

To pretend document interaction in a test you can create an element, click on it, and remove the element again. This unblocks the entire JavaScript API for the current page.

You can include the following module in your test to get a method interact_with_page that does just that:

module InteractWithPage

  def interact_with_page
    create_empty_interaction_stub
    click_empty_interaction_stub
  ensure
    remove_empty_interaction_stub
  end

  private

  def create_empty_interaction_stub
    page.execute_script(<<~JS)
      let stub = document.createElement('div')
      stub.classList.add('empty-interaction')

      // Stop the click from bubbling up and closing any overlays
      stub.addEventListener('click', function(event) {
        event.stopImmediatePropagation()
        event.preventDefault()
      })

      // Make sure the stub has a clickable area
      stub.style.width = '1px'
      stub.style.height = '1px'
      stub.style.backgroundColor = 'blue'

      // Make sure the stub is positioned over any overlays to be clickable
      stub.style.position = 'fixed'
      stub.style.bottom = '0'
      stub.style.right = '0'
      stub.style.zIndex = '9999999999999999'

      document.body.appendChild(stub)
    JS
  end

  def click_empty_interaction_stub
    page.find('.empty-interaction').click
  end

  def remove_empty_interaction_stub
    page.execute_script(<<~JS)
      let stub = document.querySelector('.empty-interaction')
      if (stub) {
        stub.remove()
      }
    JS
  end

end

To use it in Cucumber:

World(InteractWithPage)

When 'I have interacted with the page' do
  interact_with_page
end
Henning Koch
Last edit
Henning Koch
License
Source code in this card is licensed under the MIT License.
Posted by Henning Koch to makandra dev (2021-03-10 10:04)