code: @ConditionBlock
    public void within(double seconds, Closure<?> conditions) throws InterruptedException  {
      long timeoutMillis = toMillis(seconds);
      long start = System.currentTimeMillis();
      long lastAttempt = 0;
      Thread.sleep(toMillis(initialDelay));
  
      long currDelay = toMillis(delay);
      int attempts = 0;
  
      while(true) {
        try {
          attempts++;
          lastAttempt = System.currentTimeMillis();
          GroovyRuntimeUtil.invokeClosure(conditions);
          return;
        } catch (Throwable e) {
          long elapsedTime = lastAttempt - start;
          if (elapsedTime >= timeoutMillis) {
            String msg = String.format("Condition not satisfied after %1.2f seconds and %d attempts", elapsedTime / 1000d, attempts);
            throw new SpockTimeoutError(seconds, msg, e);
          }
          final long timeout = Math.min(currDelay, start + timeoutMillis - System.currentTimeMillis());
          if (timeout > 0) {
            Thread.sleep(timeout);
          }
          currDelay *= factor;
        }
      }
    }
docs: Repeatedly evaluates the specified conditions until they are satisfied or the specified timeout (in seconds) has elapsed.
  
  @param conditions the conditions to evaluate
  
  @throws InterruptedException if evaluation is interrupted