annotate core/tests/Drupal/FunctionalJavascriptTests/Ajax/AjaxTest.php @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents 129ea1e6d783
children
rev   line source
Chris@0 1 <?php
Chris@0 2
Chris@0 3 namespace Drupal\FunctionalJavascriptTests\Ajax;
Chris@0 4
Chris@17 5 use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
Chris@0 6
Chris@0 7 /**
Chris@0 8 * Tests AJAX responses.
Chris@0 9 *
Chris@0 10 * @group Ajax
Chris@0 11 */
Chris@17 12 class AjaxTest extends WebDriverTestBase {
Chris@0 13
Chris@0 14 /**
Chris@0 15 * {@inheritdoc}
Chris@0 16 */
Chris@0 17 public static $modules = ['ajax_test'];
Chris@0 18
Chris@0 19 public function testAjaxWithAdminRoute() {
Chris@0 20 \Drupal::service('theme_installer')->install(['stable', 'seven']);
Chris@0 21 $theme_config = \Drupal::configFactory()->getEditable('system.theme');
Chris@0 22 $theme_config->set('admin', 'seven');
Chris@0 23 $theme_config->set('default', 'stable');
Chris@0 24 $theme_config->save();
Chris@0 25
Chris@0 26 $account = $this->drupalCreateUser(['view the administration theme']);
Chris@0 27 $this->drupalLogin($account);
Chris@0 28
Chris@0 29 // First visit the site directly via the URL. This should render it in the
Chris@0 30 // admin theme.
Chris@0 31 $this->drupalGet('admin/ajax-test/theme');
Chris@0 32 $assert = $this->assertSession();
Chris@0 33 $assert->pageTextContains('Current theme: seven');
Chris@0 34
Chris@0 35 // Now click the modal, which should also use the admin theme.
Chris@0 36 $this->drupalGet('ajax-test/dialog');
Chris@0 37 $assert->pageTextNotContains('Current theme: stable');
Chris@0 38 $this->clickLink('Link 8 (ajax)');
Chris@0 39 $assert->assertWaitOnAjaxRequest();
Chris@0 40
Chris@0 41 $assert->pageTextContains('Current theme: stable');
Chris@0 42 $assert->pageTextNotContains('Current theme: seven');
Chris@0 43 }
Chris@0 44
Chris@0 45 /**
Chris@0 46 * Test that AJAX loaded libraries are not retained between requests.
Chris@0 47 *
Chris@0 48 * @see https://www.drupal.org/node/2647916
Chris@0 49 */
Chris@0 50 public function testDrupalSettingsCachingRegression() {
Chris@0 51 $this->drupalGet('ajax-test/dialog');
Chris@0 52 $assert = $this->assertSession();
Chris@0 53 $session = $this->getSession();
Chris@0 54
Chris@0 55 // Insert a fake library into the already loaded library settings.
Chris@0 56 $fake_library = 'fakeLibrary/fakeLibrary';
Chris@0 57 $session->evaluateScript("drupalSettings.ajaxPageState.libraries = drupalSettings.ajaxPageState.libraries + ',$fake_library';");
Chris@0 58
Chris@0 59 $libraries = $session->evaluateScript('drupalSettings.ajaxPageState.libraries');
Chris@0 60 // Test that the fake library is set.
Chris@0 61 $this->assertContains($fake_library, $libraries);
Chris@0 62
Chris@0 63 // Click on the AJAX link.
Chris@0 64 $this->clickLink('Link 8 (ajax)');
Chris@0 65 $assert->assertWaitOnAjaxRequest();
Chris@0 66
Chris@0 67 // Test that the fake library is still set after the AJAX call.
Chris@0 68 $libraries = $session->evaluateScript('drupalSettings.ajaxPageState.libraries');
Chris@0 69 $this->assertContains($fake_library, $libraries);
Chris@0 70
Chris@0 71 // Reload the page, this should reset the loaded libraries and remove the
Chris@0 72 // fake library.
Chris@0 73 $this->drupalGet('ajax-test/dialog');
Chris@0 74 $libraries = $session->evaluateScript('drupalSettings.ajaxPageState.libraries');
Chris@0 75 $this->assertNotContains($fake_library, $libraries);
Chris@0 76
Chris@0 77 // Click on the AJAX link again, and the libraries should still not contain
Chris@0 78 // the fake library.
Chris@0 79 $this->clickLink('Link 8 (ajax)');
Chris@0 80 $assert->assertWaitOnAjaxRequest();
Chris@0 81 $libraries = $session->evaluateScript('drupalSettings.ajaxPageState.libraries');
Chris@0 82 $this->assertNotContains($fake_library, $libraries);
Chris@0 83 }
Chris@0 84
Chris@17 85 /**
Chris@17 86 * Tests that various AJAX responses with DOM elements are correctly inserted.
Chris@17 87 *
Chris@17 88 * After inserting DOM elements, Drupal JavaScript behaviors should be
Chris@17 89 * reattached and all top-level elements of type Node.ELEMENT_NODE need to be
Chris@17 90 * part of the context.
Chris@17 91 */
Chris@17 92 public function testInsertAjaxResponse() {
Chris@17 93 $render_single_root = [
Chris@17 94 'pre-wrapped-div' => '<div class="pre-wrapped">pre-wrapped<script> var test;</script></div>',
Chris@17 95 'pre-wrapped-span' => '<span class="pre-wrapped">pre-wrapped<script> var test;</script></span>',
Chris@17 96 'pre-wrapped-whitespace' => ' <div class="pre-wrapped-whitespace">pre-wrapped-whitespace</div>' . "\n",
Chris@17 97 'not-wrapped' => 'not-wrapped',
Chris@17 98 'comment-string-not-wrapped' => '<!-- COMMENT -->comment-string-not-wrapped',
Chris@17 99 'comment-not-wrapped' => '<!-- COMMENT --><div class="comment-not-wrapped">comment-not-wrapped</div>',
Chris@17 100 'svg' => '<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10"><rect x="0" y="0" height="10" width="10" fill="green"/></svg>',
Chris@17 101 'empty' => '',
Chris@17 102 ];
Chris@17 103 $render_multiple_root_unwrapper = [
Chris@17 104 'mixed' => ' foo <!-- COMMENT --> foo bar<div class="a class"><p>some string</p></div> additional not wrapped strings, <!-- ANOTHER COMMENT --> <p>final string</p>',
Chris@17 105 'top-level-only' => '<div>element #1</div><div>element #2</div>',
Chris@17 106 'top-level-only-pre-whitespace' => ' <div>element #1</div><div>element #2</div> ',
Chris@17 107 'top-level-only-middle-whitespace-span' => '<span>element #1</span> <span>element #2</span>',
Chris@17 108 'top-level-only-middle-whitespace-div' => '<div>element #1</div> <div>element #2</div>',
Chris@17 109 ];
Chris@17 110
Chris@17 111 // This is temporary behavior for BC reason.
Chris@17 112 $render_multiple_root_wrapper = [];
Chris@17 113 foreach ($render_multiple_root_unwrapper as $key => $render) {
Chris@17 114 $render_multiple_root_wrapper["$key--effect"] = '<div>' . $render . '</div>';
Chris@17 115 }
Chris@17 116
Chris@17 117 $expected_renders = array_merge(
Chris@17 118 $render_single_root,
Chris@17 119 $render_multiple_root_wrapper,
Chris@17 120 $render_multiple_root_unwrapper
Chris@17 121 );
Chris@17 122
Chris@17 123 // Checking default process of wrapping Ajax content.
Chris@17 124 foreach ($expected_renders as $render_type => $expected) {
Chris@17 125 $this->assertInsert($render_type, $expected);
Chris@17 126 }
Chris@17 127
Chris@17 128 // Checking custom ajaxWrapperMultipleRootElements wrapping.
Chris@17 129 $custom_wrapper_multiple_root = <<<JS
Chris@17 130 (function($, Drupal){
Chris@17 131 Drupal.theme.ajaxWrapperMultipleRootElements = function (elements) {
Chris@17 132 return $('<div class="my-favorite-div"></div>').append(elements);
Chris@17 133 };
Chris@17 134 }(jQuery, Drupal));
Chris@17 135 JS;
Chris@17 136 $expected = '<div class="my-favorite-div"><span>element #1</span> <span>element #2</span></div>';
Chris@17 137 $this->assertInsert('top-level-only-middle-whitespace-span--effect', $expected, $custom_wrapper_multiple_root);
Chris@17 138
Chris@17 139 // Checking custom ajaxWrapperNewContent wrapping.
Chris@17 140 $custom_wrapper_new_content = <<<JS
Chris@17 141 (function($, Drupal){
Chris@17 142 Drupal.theme.ajaxWrapperNewContent = function (elements) {
Chris@17 143 return $('<div class="div-wrapper-forever"></div>').append(elements);
Chris@17 144 };
Chris@17 145 }(jQuery, Drupal));
Chris@17 146 JS;
Chris@17 147 $expected = '<div class="div-wrapper-forever"></div>';
Chris@17 148 $this->assertInsert('empty', $expected, $custom_wrapper_new_content);
Chris@17 149 }
Chris@17 150
Chris@17 151 /**
Chris@17 152 * Assert insert.
Chris@17 153 *
Chris@17 154 * @param string $render_type
Chris@17 155 * Render type.
Chris@17 156 * @param string $expected
Chris@17 157 * Expected result.
Chris@17 158 * @param string $script
Chris@17 159 * Script for additional theming.
Chris@17 160 */
Chris@17 161 public function assertInsert($render_type, $expected, $script = '') {
Chris@17 162 // Check insert to block element.
Chris@17 163 $this->drupalGet('ajax-test/insert-block-wrapper');
Chris@17 164 $this->getSession()->executeScript($script);
Chris@17 165 $this->clickLink("Link html $render_type");
Chris@17 166 $this->assertWaitPageContains('<div class="ajax-target-wrapper"><div id="ajax-target">' . $expected . '</div></div>');
Chris@17 167
Chris@17 168 $this->drupalGet('ajax-test/insert-block-wrapper');
Chris@17 169 $this->getSession()->executeScript($script);
Chris@17 170 $this->clickLink("Link replaceWith $render_type");
Chris@17 171 $this->assertWaitPageContains('<div class="ajax-target-wrapper">' . $expected . '</div>');
Chris@17 172
Chris@17 173 // Check insert to inline element.
Chris@17 174 $this->drupalGet('ajax-test/insert-inline-wrapper');
Chris@17 175 $this->getSession()->executeScript($script);
Chris@17 176 $this->clickLink("Link html $render_type");
Chris@17 177 $this->assertWaitPageContains('<div class="ajax-target-wrapper"><span id="ajax-target-inline">' . $expected . '</span></div>');
Chris@17 178
Chris@17 179 $this->drupalGet('ajax-test/insert-inline-wrapper');
Chris@17 180 $this->getSession()->executeScript($script);
Chris@17 181 $this->clickLink("Link replaceWith $render_type");
Chris@17 182 $this->assertWaitPageContains('<div class="ajax-target-wrapper">' . $expected . '</div>');
Chris@17 183 }
Chris@17 184
Chris@17 185 /**
Chris@17 186 * Asserts that page contains an expected value after waiting.
Chris@17 187 *
Chris@17 188 * @param string $expected
Chris@17 189 * A needle text.
Chris@17 190 */
Chris@17 191 protected function assertWaitPageContains($expected) {
Chris@17 192 $page = $this->getSession()->getPage();
Chris@17 193 $this->assertTrue($page->waitFor(10, function () use ($page, $expected) {
Chris@17 194 // Clear content from empty styles and "processed" classes after effect.
Chris@17 195 $content = str_replace([' class="processed"', ' processed', ' style=""'], '', $page->getContent());
Chris@17 196 return stripos($content, $expected) !== FALSE;
Chris@17 197 }), "Page contains expected value: $expected");
Chris@17 198 }
Chris@17 199
Chris@0 200 }