From 0f2313abe372087927cf71de6d28d9941b0b151a Mon Sep 17 00:00:00 2001
From: catch <catch@35733.no-reply.drupal.org>
Date: Thu, 29 Apr 2021 16:44:38 +0100
Subject: [PATCH] Issue #3211164 by alexpott: Random errors in Javascript
 Testing

---
 .../WebDriverCurlService.php                  | 24 +++++++++++++++++--
 .../WebDriverTestBase.php                     | 10 ++++++++
 2 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/core/tests/Drupal/FunctionalJavascriptTests/WebDriverCurlService.php b/core/tests/Drupal/FunctionalJavascriptTests/WebDriverCurlService.php
index a5df8c610819..32bba6d44d54 100644
--- a/core/tests/Drupal/FunctionalJavascriptTests/WebDriverCurlService.php
+++ b/core/tests/Drupal/FunctionalJavascriptTests/WebDriverCurlService.php
@@ -14,6 +14,25 @@
  */
 class WebDriverCurlService extends CurlService {
 
+  /**
+   * The maximum number of times to try in the event of a stale element
+   * reference error.
+   *
+   * @var int
+   */
+  private static $maxRetries = 10;
+
+  /**
+   * Sets the maximum number of retries.
+   *
+   * @param int $max_retries
+   *   The maximum number of times to try in the event of a stale element
+   *   reference error. This number must be greater than 10.
+   */
+  public static function setMaxRetries(int $max_retries) {
+    static::$maxRetries = max($max_retries, static::$maxRetries);
+  }
+
   /**
    * {@inheritdoc}
    */
@@ -22,7 +41,7 @@ public function execute($requestMethod, $url, $parameters = NULL, $extraOptions
       CURLOPT_FAILONERROR => TRUE,
     ];
     $retries = 0;
-    while ($retries < 10) {
+    while ($retries < static::$maxRetries) {
       try {
         $customHeaders = [
           'Content-Type: application/json;charset=UTF-8',
@@ -104,8 +123,9 @@ public function execute($requestMethod, $url, $parameters = NULL, $extraOptions
 
         $result = json_decode($rawResult, TRUE);
         if (isset($result['status']) && $result['status'] === WebDriverException::STALE_ELEMENT_REFERENCE) {
-          usleep(100000);
           $retries++;
+          // Wait a bit longer each time a stale reference error has occurred.
+          usleep(100000 * $retries);
           continue;
         }
         return [$rawResult, $info];
diff --git a/core/tests/Drupal/FunctionalJavascriptTests/WebDriverTestBase.php b/core/tests/Drupal/FunctionalJavascriptTests/WebDriverTestBase.php
index 78f6bf235d26..22efe94eb110 100644
--- a/core/tests/Drupal/FunctionalJavascriptTests/WebDriverTestBase.php
+++ b/core/tests/Drupal/FunctionalJavascriptTests/WebDriverTestBase.php
@@ -31,6 +31,15 @@ abstract class WebDriverTestBase extends BrowserTestBase {
    */
   protected $minkDefaultDriverClass = DrupalSelenium2Driver::class;
 
+  /**
+   * The maximum number of times to try a webdriver request.
+   *
+   * @var int
+   *
+   * @see \Drupal\FunctionalJavascriptTests\WebDriverCurlService::$maxRetries
+   */
+  protected const WEBDRIVER_RETRIES = 10;
+
   /**
    * {@inheritdoc}
    */
@@ -39,6 +48,7 @@ protected function initMink() {
       throw new \UnexpectedValueException(sprintf("%s has to be an instance of %s", $this->minkDefaultDriverClass, DrupalSelenium2Driver::class));
     }
     $this->minkDefaultDriverArgs = ['chrome', NULL, 'http://localhost:4444'];
+    WebDriverCurlService::setMaxRetries(max((int) getenv('WEBDRIVER_RETRIES'), static::WEBDRIVER_RETRIES));
 
     try {
       return parent::initMink();
-- 
GitLab