How to make smart timeouts for behat events

Let me start by giving you some background for this problem. We have a lot of popups and other events happening on our frontend and we used timeouts to cover them. But they were always "guessing". Sometimes waiting 3 seconds was enough, but sometimes 5 wasn't enough. Depending on how slow your machine was.

So what we needed to do is create a smart timeout, one that would check if an element was ready, and if not wait a little longer with a maximum timeout. Here is how we did it.

STEP 2: Profit

For the complete class, with all our extra functions and default timeout you can take a look at my gist

Example:

@guided-tour
Feature: Check if the guided tour steps are working correctly.
Scenario: Start guided tour
Given I am logged in with user "user@example.com" and password "test"
When I follow "Guided tour"
When I wait until I see "Here you can filter between organisations."
When I follow "next"
When I wait until I see "This right here is your demo course"
When I follow "next"
When I wait until I see "These are your course modules"