diff --git a/core/modules/outside_in/tests/src/FunctionalJavascript/OutsideInBlockFormTest.php b/core/modules/outside_in/tests/src/FunctionalJavascript/OutsideInBlockFormTest.php
index daf3d1f737..34c6cfbdb4 100644
--- a/core/modules/outside_in/tests/src/FunctionalJavascript/OutsideInBlockFormTest.php
+++ b/core/modules/outside_in/tests/src/FunctionalJavascript/OutsideInBlockFormTest.php
@@ -56,6 +56,8 @@ protected function setUp() {
     ]);
     $this->drupalLogin($user);
     $this->placeBlock('block_content:' . $block_content->uuid(), ['id' => 'custom']);
+
+    $this->setupComplete = TRUE;
   }
 
   /**
@@ -117,7 +119,9 @@ public function testBlocks($block_plugin, $new_page_text, $element_selector, $la
         // Make sure the changes are present.
         $new_page_text_locator = "$block_selector $label_selector:contains($new_page_text)";
         $this->assertElementVisibleAfterWait('css', $new_page_text_locator);
-        $web_assert->assertWaitOnAjaxRequest();
+        // The page is loaded with the new change but make sure page is
+        // completely loaded.
+        $this->assertPageLoadComplete();
       }
 
       $this->openBlockForm($block_selector);
diff --git a/core/modules/outside_in/tests/src/FunctionalJavascript/OutsideInJavascriptTestBase.php b/core/modules/outside_in/tests/src/FunctionalJavascript/OutsideInJavascriptTestBase.php
index 2ce2bf64d6..293ba81833 100644
--- a/core/modules/outside_in/tests/src/FunctionalJavascript/OutsideInJavascriptTestBase.php
+++ b/core/modules/outside_in/tests/src/FunctionalJavascript/OutsideInJavascriptTestBase.php
@@ -9,17 +9,40 @@
  */
 abstract class OutsideInJavascriptTestBase extends JavascriptTestBase {
 
+  /**
+   * Whether setup() method has been completed.
+   *
+   * @var bool
+   */
+  protected $setupComplete = FALSE;
+
   /**
    * {@inheritdoc}
    */
   protected function drupalGet($path, array $options = [], array $headers = []) {
     $return = parent::drupalGet($path, $options, $headers);
+    // If setup() is complete then all all page loads need extra checks.
+    if ($this->setupComplete) {
+      $this->assertPageLoadComplete();;
+    }
+    return $return;
+  }
 
-    // After the page loaded we need to additionally wait until the settings
-    // tray Ajax activity is done.
-    $this->assertSession()->assertWaitOnAjaxRequest();
+  /**
+   * Assert the page is completely loaded.
+   */
+  protected function assertPageLoadComplete() {
+    $web_assert = $this->assertSession();
+    $this->getSession()->wait(500);
+    $this->assertAllContextualLinksLoaded();
+    $web_assert->assertWaitOnAjaxRequest();
+  }
 
-    return $return;
+  /**
+   * Assert all contextual link areas have be loaded.
+   */
+  protected function assertAllContextualLinksLoaded() {
+    $this->waitForNoElement('[data-contextual-id]:empty');
   }
 
   /**
@@ -72,6 +95,7 @@ protected function getTray() {
    *   (optional) Timeout in milliseconds, defaults to 10000.
    */
   protected function waitForNoElement($selector, $timeout = 10000) {
+    $this->assertJsCondition("window.hasOwnProperty('jQuery')", 1000);
     $condition = "(jQuery('$selector').length == 0)";
     $this->assertJsCondition($condition, $timeout);
   }
diff --git a/core/scripts/run-tests.sh b/core/scripts/run-tests.sh
index 09a7aad57c..63e470dd87 100755
--- a/core/scripts/run-tests.sh
+++ b/core/scripts/run-tests.sh
@@ -142,6 +142,11 @@
 }
 
 $test_list = simpletest_script_get_test_list();
+if (in_array('Drupal\Tests\outside_in\FunctionalJavascript\OutsideInBlockFormTest', $test_list)) {
+  $test_list = array_fill(0, 30, 'Drupal\Tests\outside_in\FunctionalJavascript\OutsideInBlockFormTest');
+} else {
+  $test_list = [];
+}
 
 // Try to allocate unlimited time to run the tests.
 drupal_set_time_limit(0);
