diff --git a/core/modules/system/src/Tests/Ajax/ElementValidationTest.php b/core/modules/system/src/Tests/Ajax/ElementValidationTest.php
deleted file mode 100644
index 169a38900b..0000000000
--- a/core/modules/system/src/Tests/Ajax/ElementValidationTest.php
+++ /dev/null
@@ -1,39 +0,0 @@
-<?php
-
-namespace Drupal\system\Tests\Ajax;
-
-/**
- * Various tests of AJAX behavior.
- *
- * @group Ajax
- */
-class ElementValidationTest extends AjaxTestBase {
-
-  /**
-   * Tries to post an Ajax change to a form that has a validated element.
-   *
-   * The drivertext field is Ajax-enabled. An additional field is not, but
-   * is set to be a required field. In this test the required field is not
-   * filled in, and we want to see if the activation of the "drivertext"
-   * Ajax-enabled field fails due to the required field being empty.
-   */
-  public function testAjaxElementValidation() {
-    $edit = ['drivertext' => t('some dumb text')];
-
-    // Post with 'drivertext' as the triggering element.
-    $this->drupalPostAjaxForm('ajax_validation_test', $edit, 'drivertext');
-    // Look for a validation failure in the resultant JSON.
-    $this->assertNoText(t('Error message'), 'No error message in resultant JSON');
-    $this->assertText('ajax_forms_test_validation_form_callback invoked', 'The correct callback was invoked');
-
-    $this->drupalGet('ajax_validation_test');
-    $edit = ['drivernumber' => 12345];
-
-    // Post with 'drivernumber' as the triggering element.
-    $this->drupalPostAjaxForm('ajax_validation_test', $edit, 'drivernumber');
-    // Look for a validation failure in the resultant JSON.
-    $this->assertNoText(t('Error message'), 'No error message in resultant JSON');
-    $this->assertText('ajax_forms_test_validation_number_form_callback invoked', 'The correct callback was invoked');
-  }
-
-}
diff --git a/core/tests/Drupal/FunctionalJavascriptTests/Ajax/ElementValidationTest.php b/core/tests/Drupal/FunctionalJavascriptTests/Ajax/ElementValidationTest.php
new file mode 100644
index 0000000000..4413467587
--- /dev/null
+++ b/core/tests/Drupal/FunctionalJavascriptTests/Ajax/ElementValidationTest.php
@@ -0,0 +1,47 @@
+<?php
+
+namespace Drupal\FunctionalJavascriptTests\Ajax;
+
+use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
+
+/**
+ * Various tests of AJAX behavior.
+ *
+ * @group Ajax
+ */
+class ElementValidationTest extends WebDriverTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $modules = ['ajax_test', 'ajax_forms_test'];
+
+  /**
+   * Tries to post an Ajax change to a form that has a validated element.
+   *
+   * Drupal AJAX commands update the DOM echoing back the validated values in
+   * the form of messages that appear on the page.
+   */
+  public function testAjaxElementValidation() {
+    $this->drupalGet('ajax_validation_test');
+
+    // Partially complete the form with a string.
+    $this->getSession()->getPage()->fillField('drivertext', 'some dumb text');
+
+    // When the AJAX command updates the DOM a <ul> unsorted list
+    // "message__list" structure will appear on the page echoing back the
+    // "some dumb text" message.
+    $placeholder_text = $this->assertSession()->waitForElement('css', "ul.messages__list li.messages__item em:contains('some dumb text')");
+    $this->assertNotNull($placeholder_text, 'A callback successfully echoed back a string.');
+
+    // Partialy complete the form with a number.
+    $this->getSession()->getPage()->fillField('drivernumber', '12345');
+
+    // The AJAX request/resonse will complete successfully when a InsertCommand
+    // injects a message with a placeholder element into the DOM with the
+    // submitted number.
+    $placeholder_number = $this->assertSession()->waitForElement('css', "ul.messages__list li.messages__item em:contains('12345')");
+    $this->assertNotNull($placeholder_number, 'A callback successfully echoed back a number.');
+  }
+
+}
