DialogTest.php 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. <?php
  2. namespace Drupal\FunctionalJavascriptTests\Ajax;
  3. use Drupal\ajax_test\Controller\AjaxTestController;
  4. use Drupal\Component\Render\FormattableMarkup;
  5. use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
  6. /**
  7. * Performs tests on opening and manipulating dialogs via AJAX commands.
  8. *
  9. * @group Ajax
  10. */
  11. class DialogTest extends WebDriverTestBase {
  12. /**
  13. * {@inheritdoc}
  14. */
  15. protected static $modules = ['ajax_test', 'ajax_forms_test', 'contact'];
  16. /**
  17. * {@inheritdoc}
  18. */
  19. protected $defaultTheme = 'classy';
  20. /**
  21. * Test sending non-JS and AJAX requests to open and manipulate modals.
  22. */
  23. public function testDialog() {
  24. $this->drupalLogin($this->drupalCreateUser(['administer contact forms']));
  25. // Ensure the elements render without notices or exceptions.
  26. $this->drupalGet('ajax-test/dialog');
  27. // Set up variables for this test.
  28. $dialog_renderable = AjaxTestController::dialogContents();
  29. $dialog_contents = \Drupal::service('renderer')->renderRoot($dialog_renderable);
  30. // Check that requesting a modal dialog without JS goes to a page.
  31. $this->drupalGet('ajax-test/dialog-contents');
  32. $this->assertSession()->responseContains($dialog_contents);
  33. // Visit the page containing the many test dialog links.
  34. $this->drupalGet('ajax-test/dialog');
  35. // Tests a basic modal dialog by verifying the contents of the dialog are as
  36. // expected.
  37. $this->getSession()->getPage()->clickLink('Link 1 (modal)');
  38. // Clicking the link triggers a AJAX request/response.
  39. // Opens a Dialog panel.
  40. $link1_dialog_div = $this->assertSession()->waitForElementVisible('css', 'div.ui-dialog');
  41. $this->assertNotNull($link1_dialog_div, 'Link was used to open a dialog ( modal )');
  42. $link1_modal = $link1_dialog_div->find('css', '#drupal-modal');
  43. $this->assertNotNull($link1_modal, 'Link was used to open a dialog ( non-modal )');
  44. $this->assertSession()->responseContains($dialog_contents);
  45. $dialog_title = $link1_dialog_div->find('css', "span.ui-dialog-title:contains('AJAX Dialog & contents')");
  46. $this->assertNotNull($dialog_title);
  47. $dialog_title_amp = $link1_dialog_div->find('css', "span.ui-dialog-title:contains('AJAX Dialog &amp; contents')");
  48. $this->assertNull($dialog_title_amp);
  49. // Close open dialog, return to the dialog links page.
  50. $close_button = $link1_dialog_div->findButton('Close');
  51. $this->assertNotNull($close_button);
  52. $close_button->press();
  53. // Tests a modal with a dialog-option.
  54. // Link 2 is similar to Link 1, except it submits additional width
  55. // information which must be echoed in the resulting DOM update.
  56. $this->getSession()->getPage()->clickLink('Link 2 (modal)');
  57. $dialog = $this->assertSession()->waitForElementVisible('css', 'div.ui-dialog');
  58. $this->assertNotNull($dialog, 'Link was used to open a dialog ( non-modal, with options )');
  59. $style = $dialog->getAttribute('style');
  60. $this->assertStringContainsString('width: 400px;', $style, new FormattableMarkup('Modal respected the dialog-options width parameter. Style = style', ['%style' => $style]));
  61. // Reset: Return to the dialog links page.
  62. $this->drupalGet('ajax-test/dialog');
  63. // Test a non-modal dialog ( with target ).
  64. $this->clickLink('Link 3 (non-modal)');
  65. $non_modal_dialog = $this->assertSession()->waitForElementVisible('css', 'div.ui-dialog');
  66. $this->assertNotNull($non_modal_dialog, 'Link opens a non-modal dialog.');
  67. // Tests the dialog contains a target element specified in the AJAX request.
  68. $non_modal_dialog->find('css', 'div#ajax-test-dialog-wrapper-1');
  69. $this->assertSession()->responseContains($dialog_contents);
  70. // Reset: Return to the dialog links page.
  71. $this->drupalGet('ajax-test/dialog');
  72. // Tests a non-modal dialog ( without target ).
  73. $this->clickLink('Link 7 (non-modal, no target)');
  74. $no_target_dialog = $this->assertSession()->waitForElementVisible('css', 'div.ui-dialog');
  75. $this->assertNotNull($no_target_dialog, 'Link opens a non-modal dialog.');
  76. $contents_no_target = $no_target_dialog->find('css', 'div.ui-dialog-content');
  77. $this->assertNotNull($contents_no_target, 'non-modal dialog opens ( no target ). ');
  78. $id = $contents_no_target->getAttribute('id');
  79. $partial_match = strpos($id, 'drupal-dialog-ajax-testdialog-contents') === 0;
  80. $this->assertTrue($partial_match, 'The non-modal ID has the expected prefix.');
  81. $no_target_button = $no_target_dialog->findButton('Close');
  82. $this->assertNotNull($no_target_button, 'Link dialog has a close button');
  83. $no_target_button->press();
  84. $this->getSession()->getPage()->findButton('Button 1 (modal)')->press();
  85. $button1_dialog = $this->assertSession()->waitForElementVisible('css', 'div.ui-dialog');
  86. $this->assertNotNull($button1_dialog, 'Button opens a modal dialog.');
  87. $button1_dialog_content = $button1_dialog->find('css', 'div.ui-dialog-content');
  88. $this->assertNotNull($button1_dialog_content, 'Button opens a modal dialog.');
  89. // Test the HTML escaping of & character.
  90. $button1_dialog_title = $button1_dialog->find('css', "span.ui-dialog-title:contains('AJAX Dialog & contents')");
  91. $this->assertNotNull($button1_dialog_title);
  92. $button1_dialog_title_amp = $button1_dialog->find('css', "span.ui-dialog-title:contains('AJAX Dialog &amp; contents')");
  93. $this->assertNull($button1_dialog_title_amp);
  94. // Reset: Close the dialog.
  95. $button1_dialog->findButton('Close')->press();
  96. // Abbreviated test for "normal" dialogs, testing only the difference.
  97. $this->getSession()->getPage()->findButton('Button 2 (non-modal)')->press();
  98. $button2_dialog = $this->assertSession()->waitForElementVisible('css', 'div.ui-dialog-content');
  99. $this->assertNotNull($button2_dialog, 'Non-modal content displays as expected.');
  100. // Use a link to close the pagnel opened by button 2.
  101. $this->getSession()->getPage()->clickLink('Link 4 (close non-modal if open)');
  102. // Form modal.
  103. $this->clickLink('Link 5 (form)');
  104. // Two links have been clicked in succession - This time wait for a change
  105. // in the title as the previous closing dialog may temporarily be open.
  106. $form_dialog_title = $this->assertSession()->waitForElementVisible('css', "span.ui-dialog-title:contains('Ajax Form contents')");
  107. $this->assertNotNull($form_dialog_title, 'Dialog form has the expected title.');
  108. // Locate the newly opened dialog.
  109. $form_dialog = $this->getSession()->getPage()->find('css', 'div.ui-dialog');
  110. $this->assertNotNull($form_dialog, 'Form dialog is visible');
  111. $form_contents = $form_dialog->find('css', "p:contains('Ajax Form contents description.')");
  112. $this->assertNotNull($form_contents, 'For has the expected text.');
  113. $do_it = $form_dialog->findButton('Do it');
  114. $this->assertNotNull($do_it, 'The dialog has a "Do it" button.');
  115. $preview = $form_dialog->findButton('Preview');
  116. $this->assertNotNull($preview, 'The dialog contains a "Preview" button.');
  117. // When a form with submit inputs is in a dialog, the form's submit inputs
  118. // are copied to the dialog buttonpane as buttons. The originals should have
  119. // their styles set to display: none.
  120. $hidden_buttons = $this->getSession()->getPage()->findAll('css', '.ajax-test-form [type="submit"]');
  121. $this->assertCount(2, $hidden_buttons);
  122. $hidden_button_text = [];
  123. foreach ($hidden_buttons as $button) {
  124. $styles = $button->getAttribute('style');
  125. $this->assertTrue((stripos($styles, 'display: none;') !== FALSE));
  126. $hidden_button_text[] = $button->getAttribute('value');
  127. }
  128. // The copied buttons should have the same text as the submit inputs they
  129. // were copied from.
  130. $moved_to_buttonpane_buttons = $this->getSession()->getPage()->findAll('css', '.ui-dialog-buttonpane button');
  131. $this->assertCount(2, $moved_to_buttonpane_buttons);
  132. foreach ($moved_to_buttonpane_buttons as $key => $button) {
  133. $this->assertEqual($button->getText(), $hidden_button_text[$key]);
  134. }
  135. // Reset: close the form.
  136. $form_dialog->findButton('Close')->press();
  137. // Non AJAX version of Link 6.
  138. $this->drupalGet('admin/structure/contact/add');
  139. // Check we get a chunk of the code, we can't test the whole form as form
  140. // build id and token with be different.
  141. $contact_form = $this->xpath("//form[@id='contact-form-add-form']");
  142. $this->assertTrue(!empty($contact_form), 'Non-JS entity form page present.');
  143. // Reset: Return to the dialog links page.
  144. $this->drupalGet('ajax-test/dialog');
  145. $this->clickLink('Link 6 (entity form)');
  146. $dialog_add = $this->assertSession()->waitForElementVisible('css', 'div.ui-dialog');
  147. $this->assertNotNull($dialog_add, 'Form dialog is visible');
  148. $form_add = $dialog_add->find('css', 'form.contact-form-add-form');
  149. $this->assertNotNull($form_add, 'Modal dialog JSON contains entity form.');
  150. $form_title = $dialog_add->find('css', "span.ui-dialog-title:contains('Add contact form')");
  151. $this->assertNotNull($form_title, 'The add form title is as expected.');
  152. }
  153. }