diff --git a/core/modules/system/src/Tests/Ajax/DialogTest.php b/core/modules/system/src/Tests/Ajax/DialogTest.php
deleted file mode 100644
index 76ab6fb160f5bc9b1c97cdf5b82fff61a14896fe..0000000000000000000000000000000000000000
--- a/core/modules/system/src/Tests/Ajax/DialogTest.php
+++ /dev/null
@@ -1,216 +0,0 @@
-<?php
-
-namespace Drupal\system\Tests\Ajax;
-
-use Drupal\ajax_test\Controller\AjaxTestController;
-use Drupal\Core\EventSubscriber\MainContentViewSubscriber;
-use Drupal\Core\Form\FormBuilderInterface;
-use Drupal\Core\Url;
-
-/**
- * Performs tests on opening and manipulating dialogs via AJAX commands.
- *
- * @group Ajax
- */
-class DialogTest extends AjaxTestBase {
-
-  /**
-   * Modules to enable.
-   *
-   * @var array
-   */
-  public static $modules = ['ajax_test', 'ajax_forms_test', 'contact'];
-
-  /**
-   * Test sending non-JS and AJAX requests to open and manipulate modals.
-   */
-  public function testDialog() {
-    $this->drupalLogin($this->drupalCreateUser(['administer contact forms']));
-    // Ensure the elements render without notices or exceptions.
-    $this->drupalGet('ajax-test/dialog');
-
-    // Set up variables for this test.
-    $dialog_renderable = AjaxTestController::dialogContents();
-    $dialog_contents = \Drupal::service('renderer')->renderRoot($dialog_renderable);
-    $modal_expected_response = [
-      'command' => 'openDialog',
-      'selector' => '#drupal-modal',
-      'settings' => NULL,
-      'data' => $dialog_contents,
-      'dialogOptions' => [
-        'modal' => TRUE,
-        'title' => 'AJAX Dialog & contents',
-      ],
-    ];
-    $form_expected_response = [
-      'command' => 'openDialog',
-      'selector' => '#drupal-modal',
-      'settings' => NULL,
-      'dialogOptions' => [
-        'modal' => TRUE,
-        'title' => 'Ajax Form contents',
-      ],
-    ];
-    $entity_form_expected_response = [
-      'command' => 'openDialog',
-      'selector' => '#drupal-modal',
-      'settings' => NULL,
-      'dialogOptions' => [
-        'modal' => TRUE,
-        'title' => 'Add contact form',
-      ],
-    ];
-    $normal_expected_response = [
-      'command' => 'openDialog',
-      'selector' => '#ajax-test-dialog-wrapper-1',
-      'settings' => NULL,
-      'data' => $dialog_contents,
-      'dialogOptions' => [
-        'modal' => FALSE,
-        'title' => 'AJAX Dialog & contents',
-      ],
-    ];
-    $no_target_expected_response = [
-      'command' => 'openDialog',
-      'selector' => '#drupal-dialog-ajax-testdialog-contents',
-      'settings' => NULL,
-      'data' => $dialog_contents,
-      'dialogOptions' => [
-        'modal' => FALSE,
-        'title' => 'AJAX Dialog & contents',
-      ],
-    ];
-    $close_expected_response = [
-      'command' => 'closeDialog',
-      'selector' => '#ajax-test-dialog-wrapper-1',
-      'persist' => FALSE,
-    ];
-
-    // Check that requesting a modal dialog without JS goes to a page.
-    $this->drupalGet('ajax-test/dialog-contents');
-    $this->assertRaw($dialog_contents, 'Non-JS modal dialog page present.');
-
-    // Check that requesting a modal dialog with XMLHttpRequest goes to a page.
-    $this->drupalGetXHR('ajax-test/dialog-contents');
-    $this->assertRaw($dialog_contents, 'Modal dialog page on XMLHttpRequest present.');
-
-    // Emulate going to the JS version of the page and check the JSON response.
-    $ajax_result = $this->drupalGetAjax('ajax-test/dialog-contents', ['query' => [MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_modal']]);
-    $this->assertEqual($modal_expected_response, $ajax_result[3], 'Modal dialog JSON response matches.');
-    // Test the HTML escaping of & character.
-    $this->assertEqual($ajax_result[3]['dialogOptions']['title'], 'AJAX Dialog & contents');
-    $this->assertNotEqual($ajax_result[3]['dialogOptions']['title'], 'AJAX Dialog &amp; contents');
-
-    // Check that requesting a "normal" dialog without JS goes to a page.
-    $this->drupalGet('ajax-test/dialog-contents');
-    $this->assertRaw($dialog_contents, 'Non-JS normal dialog page present.');
-
-    // Emulate going to the JS version of the page and check the JSON response.
-    // This needs to use WebTestBase::drupalPostAjaxForm() so that the correct
-    // dialog options are sent.
-    $ajax_result = $this->drupalPostAjaxForm('ajax-test/dialog', [
-        // We have to mock a form element to make drupalPost submit from a link.
-        'textfield' => 'test',
-      ], [], 'ajax-test/dialog-contents', ['query' => [MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_dialog']], [], NULL, [
-      'submit' => [
-        'dialogOptions[target]' => 'ajax-test-dialog-wrapper-1',
-      ],
-    ]);
-    $this->assertEqual($normal_expected_response, $ajax_result[3], 'Normal dialog JSON response matches.');
-
-    // Emulate going to the JS version of the page and check the JSON response.
-    // This needs to use WebTestBase::drupalPostAjaxForm() so that the correct
-    // dialog options are sent.
-    $ajax_result = $this->drupalPostAjaxForm('ajax-test/dialog', [
-        // We have to mock a form element to make drupalPost submit from a link.
-        'textfield' => 'test',
-      ], [], 'ajax-test/dialog-contents', ['query' => [MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_dialog']], [], NULL, [
-      // Don't send a target.
-      'submit' => [],
-    ]);
-    // Make sure the selector ID starts with the right string.
-    $this->assert(strpos($ajax_result[3]['selector'], $no_target_expected_response['selector']) === 0, 'Selector starts with right string.');
-    unset($ajax_result[3]['selector']);
-    unset($no_target_expected_response['selector']);
-    $this->assertEqual($no_target_expected_response, $ajax_result[3], 'Normal dialog with no target JSON response matches.');
-
-    // Emulate closing the dialog via an AJAX request. There is no non-JS
-    // version of this test.
-    $ajax_result = $this->drupalGetAjax('ajax-test/dialog-close');
-    $this->assertEqual($close_expected_response, $ajax_result[0], 'Close dialog JSON response matches.');
-
-    // Test submitting via a POST request through the button for modals. This
-    // approach more accurately reflects the real responses by Drupal because
-    // all of the necessary page variables are emulated.
-    $ajax_result = $this->drupalPostAjaxForm('ajax-test/dialog', [], 'button1');
-
-    // Check that CSS and JavaScript are "added" to the page dynamically.
-    $this->assertTrue(in_array('core/drupal.dialog.ajax', explode(',', $ajax_result[0]['settings']['ajaxPageState']['libraries'])), 'core/drupal.dialog.ajax library is added to the page.');
-    $dialog_css_exists = strpos($ajax_result[1]['data'], 'dialog.css') !== FALSE;
-    $this->assertTrue($dialog_css_exists, 'jQuery UI dialog CSS added to the page.');
-    $dialog_js_exists = strpos($ajax_result[2]['data'], 'dialog-min.js') !== FALSE;
-    $this->assertTrue($dialog_js_exists, 'jQuery UI dialog JS added to the page.');
-    $dialog_js_exists = strpos($ajax_result[2]['data'], 'dialog.ajax.js') !== FALSE;
-    $this->assertTrue($dialog_js_exists, 'Drupal dialog JS added to the page.');
-
-    // Check that the response matches the expected value.
-    $this->assertEqual($modal_expected_response, $ajax_result[4], 'POST request modal dialog JSON response matches.');
-    // Test the HTML escaping of & character.
-    $this->assertNotEqual($ajax_result[4]['dialogOptions']['title'], 'AJAX Dialog &amp; contents');
-
-    // Abbreviated test for "normal" dialogs, testing only the difference.
-    $ajax_result = $this->drupalPostAjaxForm('ajax-test/dialog', [], 'button2');
-    $this->assertEqual($normal_expected_response, $ajax_result[4], 'POST request normal dialog JSON response matches.');
-
-    // Check that requesting a form dialog without JS goes to a page.
-    $this->drupalGet('ajax-test/dialog-form');
-    // Check we get a chunk of the code, we can't test the whole form as form
-    // build id and token with be different.
-    $form = $this->xpath("//form[@id='ajax-test-form']");
-    $this->assertTrue(!empty($form), 'Non-JS form page present.');
-
-    // Emulate going to the JS version of the form and check the JSON response.
-    $ajax_result = $this->drupalGetAjax('ajax-test/dialog-form', ['query' => [MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_modal']]);
-    $expected_ajax_settings = [
-      'edit-preview' => [
-        'callback' => '::preview',
-        'event' => 'click',
-        'url' => Url::fromRoute('ajax_test.dialog_form', [], [
-          'query' => [
-            MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_modal',
-            FormBuilderInterface::AJAX_FORM_REQUEST => TRUE,
-          ],
-        ])->toString(),
-        'dialogType' => 'ajax',
-        'submit' => [
-          '_triggering_element_name' => 'op',
-          '_triggering_element_value' => 'Preview',
-        ],
-      ],
-    ];
-    $this->assertEqual($expected_ajax_settings, $ajax_result[0]['settings']['ajax']);
-    $this->setRawContent($ajax_result[3]['data']);
-    // Remove the data, the form build id and token will never match.
-    unset($ajax_result[3]['data']);
-    $form = $this->xpath("//form[@id='ajax-test-form']");
-    $this->assertTrue(!empty($form), 'Modal dialog JSON contains form.');
-    $this->assertEqual($form_expected_response, $ajax_result[3]);
-
-    // Check that requesting an entity form dialog without JS goes to a page.
-    $this->drupalGet('admin/structure/contact/add');
-    // Check we get a chunk of the code, we can't test the whole form as form
-    // build id and token with be different.
-    $form = $this->xpath("//form[@id='contact-form-add-form']");
-    $this->assertTrue(!empty($form), 'Non-JS entity form page present.');
-
-    // Emulate going to the JS version of the form and check the JSON response.
-    $ajax_result = $this->drupalGetAjax('admin/structure/contact/add', ['query' => [MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_modal']]);
-    $this->setRawContent($ajax_result[3]['data']);
-    // Remove the data, the form build id and token will never match.
-    unset($ajax_result[3]['data']);
-    $form = $this->xpath("//form[@id='contact-form-add-form']");
-    $this->assertTrue(!empty($form), 'Modal dialog JSON contains entity form.');
-    $this->assertEqual($entity_form_expected_response, $ajax_result[3]);
-  }
-
-}
diff --git a/core/tests/Drupal/FunctionalJavascriptTests/Ajax/DialogTest.php b/core/tests/Drupal/FunctionalJavascriptTests/Ajax/DialogTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..26bdd185e6c1ae73579c9238db47fd8e0e59c63b
--- /dev/null
+++ b/core/tests/Drupal/FunctionalJavascriptTests/Ajax/DialogTest.php
@@ -0,0 +1,167 @@
+<?php
+
+namespace Drupal\FunctionalJavascriptTests\Ajax;
+
+use Drupal\ajax_test\Controller\AjaxTestController;
+use Drupal\Component\Render\FormattableMarkup;
+use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
+
+/**
+ * Performs tests on opening and manipulating dialogs via AJAX commands.
+ *
+ * @group Ajax
+ */
+class DialogTest extends WebDriverTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = ['ajax_test', 'ajax_forms_test', 'contact'];
+
+  /**
+   * Test sending non-JS and AJAX requests to open and manipulate modals.
+   */
+  public function testDialog() {
+    $this->drupalLogin($this->drupalCreateUser(['administer contact forms']));
+    // Ensure the elements render without notices or exceptions.
+    $this->drupalGet('ajax-test/dialog');
+
+    // Set up variables for this test.
+    $dialog_renderable = AjaxTestController::dialogContents();
+    $dialog_contents = \Drupal::service('renderer')->renderRoot($dialog_renderable);
+
+    // Check that requesting a modal dialog without JS goes to a page.
+    $this->drupalGet('ajax-test/dialog-contents');
+    $this->assertSession()->responseContains($dialog_contents);
+
+    // Visit the page containing the many test dialog links.
+    $this->drupalGet('ajax-test/dialog');
+
+    // Tests a basic modal dialog by verifying the contents of the dialog are as
+    // expected.
+    $this->getSession()->getPage()->clickLink('Link 1 (modal)');
+
+    // Clicking the link triggers a AJAX request/response.
+    // Opens a Dialog panel.
+    $link1_dialog_div = $this->assertSession()->waitForElementVisible('css', 'div.ui-dialog');
+    $this->assertNotNull($link1_dialog_div, 'Link was used to open a dialog ( modal )');
+
+    $link1_modal = $link1_dialog_div->find('css', '#drupal-modal');
+    $this->assertNotNull($link1_modal, 'Link was used to open a dialog ( non-modal )');
+    $this->assertSession()->responseContains($dialog_contents);
+
+    $dialog_title = $link1_dialog_div->find('css', "span.ui-dialog-title:contains('AJAX Dialog & contents')");
+    $this->assertNotNull($dialog_title);
+    $dialog_title_amp = $link1_dialog_div->find('css', "span.ui-dialog-title:contains('AJAX Dialog &amp; contents')");
+    $this->assertNull($dialog_title_amp);
+
+    // Close open dialog, return to the dialog links page.
+    $close_button = $link1_dialog_div->findButton('Close');
+    $this->assertNotNull($close_button);
+    $close_button->press();
+
+    // Tests a modal with a dialog-option.
+    // Link 2 is similar to Link 1, except it submits additional width
+    // information which must be echoed in the resulting  DOM update.
+    $this->getSession()->getPage()->clickLink('Link 2 (modal)');
+    $dialog = $this->assertSession()->waitForElementVisible('css', 'div.ui-dialog');
+    $this->assertNotNull($dialog, 'Link was used to open a dialog ( non-modal, with options )');
+    $style = $dialog->getAttribute('style');
+    $this->assertContains('width: 400px;', $style, new FormattableMarkup('Modal respected the dialog-options width parameter.  Style = style', ['%style' => $style]));
+
+    // Reset: Return to the dialog links page.
+    $this->drupalGet('ajax-test/dialog');
+
+    // Test a non-modal dialog ( with target ).
+    $this->clickLink('Link 3 (non-modal)');
+    $non_modal_dialog = $this->assertSession()->waitForElementVisible('css', 'div.ui-dialog');
+    $this->assertNotNull($non_modal_dialog, 'Link opens a non-modal dialog.');
+
+    // Tests the dialog contains a target element specified in the AJAX request.
+    $non_modal_dialog->find('css', 'div#ajax-test-dialog-wrapper-1');
+    $this->assertSession()->responseContains($dialog_contents);
+
+    // Reset: Return to the dialog links page.
+    $this->drupalGet('ajax-test/dialog');
+
+    // Tests a non-modal dialog ( without target ).
+    $this->clickLink('Link 7 (non-modal, no target)');
+    $no_target_dialog = $this->assertSession()->waitForElementVisible('css', 'div.ui-dialog');
+    $this->assertNotNull($no_target_dialog, 'Link opens a non-modal dialog.');
+
+    $contents_no_target = $no_target_dialog->find('css', 'div.ui-dialog-content');
+    $this->assertNotNull($contents_no_target, 'non-modal dialog opens ( no target ). ');
+    $id = $contents_no_target->getAttribute('id');
+    $partial_match = strpos($id, 'drupal-dialog-ajax-testdialog-contents') === 0;
+    $this->assertTrue($partial_match, 'The non-modal ID has the expected prefix.');
+
+    $no_target_button = $no_target_dialog->findButton('Close');
+    $this->assertNotNull($no_target_button, 'Link dialog has a close button');
+    $no_target_button->press();
+
+    $this->getSession()->getPage()->findButton('Button 1 (modal)')->press();
+    $button1_dialog = $this->assertSession()->waitForElementVisible('css', 'div.ui-dialog');
+    $this->assertNotNull($button1_dialog, 'Button opens a modal dialog.');
+
+    $button1_dialog_content = $button1_dialog->find('css', 'div.ui-dialog-content');
+    $this->assertNotNull($button1_dialog_content, 'Button opens a modal dialog.');
+
+    // Test the HTML escaping of & character.
+    $button1_dialog_title = $button1_dialog->find('css', "span.ui-dialog-title:contains('AJAX Dialog & contents')");
+    $this->assertNotNull($button1_dialog_title);
+    $button1_dialog_title_amp = $button1_dialog->find('css', "span.ui-dialog-title:contains('AJAX Dialog &amp; contents')");
+    $this->assertNull($button1_dialog_title_amp);
+
+    // Reset: Close the dialog.
+    $button1_dialog->findButton('Close')->press();
+
+    // Abbreviated test for "normal" dialogs, testing only the difference.
+    $this->getSession()->getPage()->findButton('Button 2 (non-modal)')->press();
+    $button2_dialog = $this->assertSession()->waitForElementVisible('css', 'div.ui-dialog-content');
+    $this->assertNotNull($button2_dialog, 'Non-modal content displays as expected.');
+
+    // Use a link to close the pagnel opened by button 2.
+    $this->getSession()->getPage()->clickLink('Link 4 (close non-modal if open)');
+
+    // Form modal.
+    $this->clickLink('Link 5 (form)');
+    // Two links have been clicked in succession - This time wait for a change
+    // in the title as the previous closing dialog may temporarily be open.
+    $form_dialog_title = $this->assertSession()->waitForElementVisible('css', "span.ui-dialog-title:contains('Ajax Form contents')");
+    $this->assertNotNull($form_dialog_title, 'Dialog form has the expected title.');
+    // Locate the newly opened dialog.
+    $form_dialog = $this->getSession()->getPage()->find('css', 'div.ui-dialog');
+    $this->assertNotNull($form_dialog, 'Form dialog is visible');
+
+    $form_contents = $form_dialog->find('css', "p:contains('Ajax Form contents description.')");
+    $this->assertNotNull($form_contents, 'For has the expected text.');
+    $do_it = $form_dialog->findButton('Do it');
+    $this->assertNotNull($do_it, 'The dialog has a "Do it" button.');
+    $preview = $form_dialog->findButton('Preview');
+    $this->assertNotNull($preview, 'The dialog contains a "Preview" button.');
+
+    // Reset: close the form.
+    $form_dialog->findButton('Close')->press();
+
+    // Non AJAX version of Link 6.
+    $this->drupalGet('admin/structure/contact/add');
+    // Check we get a chunk of the code, we can't test the whole form as form
+    // build id and token with be different.
+    $contact_form = $this->xpath("//form[@id='contact-form-add-form']");
+    $this->assertTrue(!empty($contact_form), 'Non-JS entity form page present.');
+
+    // Reset: Return to the dialog links page.
+    $this->drupalGet('ajax-test/dialog');
+
+    $this->clickLink('Link 6 (entity form)');
+    $dialog_add = $this->assertSession()->waitForElementVisible('css', 'div.ui-dialog');
+    $this->assertNotNull($dialog_add, 'Form dialog is visible');
+
+    $form_add = $dialog_add->find('css', 'form.contact-form-add-form');
+    $this->assertNotNull($form_add, 'Modal dialog JSON contains entity form.');
+
+    $form_title = $dialog_add->find('css', "span.ui-dialog-title:contains('Add contact form')");
+    $this->assertNotNull($form_title, 'The add form title is as expected.');
+  }
+
+}