From 57f1f1a480e1276b6ce23b1f832c406d8bf95ff1 Mon Sep 17 00:00:00 2001 From: Alex Pott <alex.a.pott@googlemail.com> Date: Thu, 31 Jan 2019 01:02:35 +0000 Subject: [PATCH] Issue #2215857 by michielnugter, Lendude, gmercer, tim.plunkett, cferthorney, marabak, olli, ericmulder1980, TwoD, sanduhrs, stella, dww, nod_: Behaviors get attached to removed forms --- core/misc/ajax.es6.js | 9 +++-- core/misc/ajax.js | 6 +-- .../FilterCriteriaTest.php | 40 +++++++++++++++---- .../Ajax/CommandsTest.php | 20 ++++++---- 4 files changed, 54 insertions(+), 21 deletions(-) diff --git a/core/misc/ajax.es6.js b/core/misc/ajax.es6.js index 440e5906dcd7..39784c403c2a 100644 --- a/core/misc/ajax.es6.js +++ b/core/misc/ajax.es6.js @@ -774,7 +774,7 @@ // when there is a form such that this.$form.ajaxSubmit() is used instead of // $.ajax(). When there is no form and $.ajax() is used, beforeSerialize() // isn't called, but don't rely on that: explicitly check this.$form. - if (this.$form) { + if (this.$form && document.contains(this.$form.get(0))) { const settings = this.settings || drupalSettings; Drupal.detachBehaviors(this.$form.get(0), settings, 'serialize'); } @@ -1020,7 +1020,7 @@ // attachBehaviors() called on the new content from processing the response // commands is not sufficient, because behaviors from the entire form need // to be reattached. - if (this.$form) { + if (this.$form && document.contains(this.$form.get(0))) { const settings = this.settings || drupalSettings; Drupal.attachBehaviors(this.$form.get(0), settings); } @@ -1088,8 +1088,9 @@ $(this.wrapper).show(); // Re-enable the element. $(this.element).prop('disabled', false); - // Reattach behaviors, if they were detached in beforeSerialize(). - if (this.$form) { + // Reattach behaviors, if they were detached in beforeSerialize(), and the + // form is still part of the document. + if (this.$form && document.contains(this.$form.get(0))) { const settings = this.settings || drupalSettings; Drupal.attachBehaviors(this.$form.get(0), settings); } diff --git a/core/misc/ajax.js b/core/misc/ajax.js index 73b4dcca69e4..79aac05e8520 100644 --- a/core/misc/ajax.js +++ b/core/misc/ajax.js @@ -339,7 +339,7 @@ function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr }; Drupal.Ajax.prototype.beforeSerialize = function (element, options) { - if (this.$form) { + if (this.$form && document.contains(this.$form.get(0))) { var settings = this.settings || drupalSettings; Drupal.detachBehaviors(this.$form.get(0), settings, 'serialize'); } @@ -451,7 +451,7 @@ function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr } } - if (this.$form) { + if (this.$form && document.contains(this.$form.get(0))) { var settings = this.settings || drupalSettings; Drupal.attachBehaviors(this.$form.get(0), settings); } @@ -493,7 +493,7 @@ function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr $(this.element).prop('disabled', false); - if (this.$form) { + if (this.$form && document.contains(this.$form.get(0))) { var settings = this.settings || drupalSettings; Drupal.attachBehaviors(this.$form.get(0), settings); } diff --git a/core/modules/views_ui/tests/src/FunctionalJavascript/FilterCriteriaTest.php b/core/modules/views_ui/tests/src/FunctionalJavascript/FilterCriteriaTest.php index 9e303dfb9222..a9ec2475b6b5 100644 --- a/core/modules/views_ui/tests/src/FunctionalJavascript/FilterCriteriaTest.php +++ b/core/modules/views_ui/tests/src/FunctionalJavascript/FilterCriteriaTest.php @@ -42,13 +42,7 @@ public function testFilterCriteriaDialog() { $assert_session = $this->assertSession(); $page = $this->getSession()->getPage(); - // Use the 'And/Or Rearrange' link for fields to open a dialog. - $dropbutton = $page->find('css', '.views-ui-display-tab-bucket.filter .dropbutton-toggle button'); - $dropbutton->click(); - $add_link = $page->findById('views-rearrange-filter'); - $this->assertTrue($add_link->isVisible(), 'And/Or Rearrange button found.'); - $add_link->click(); - $assert_session->assertWaitOnAjaxRequest(); + $this->openFilterDialog(); // Add a new filter group. $create_new_filter_group = $page->findById('views-add-group-link'); @@ -71,6 +65,38 @@ public function testFilterCriteriaDialog() { $this->drupalGet('admin/structure/views/view/who_s_online'); $page = $this->getSession()->getPage(); $this->assertNotNull($page->findLink('User: Last access (>= -15 minutes)')); + + // Add group again to test drag-n-drop. + $this->openFilterDialog(); + + $this->assertSession()->waitForLink('Create new filter group', 20000); + $create_new_filter_group = $page->findLink('Create new filter group'); + $this->assertTrue($create_new_filter_group->isVisible(), 'Add group link found.'); + $create_new_filter_group->click(); + $assert_session->assertWaitOnAjaxRequest(); + + // Validate dragging works correctly and the new group will contain the new + // filter. + $dragged = $page->find('css', ".tabledrag-handle"); + $target = $page->find('css', '.filter-group-operator-row'); + $dragged->dragTo($target); + + $remove_link = $page->findLink('Remove group'); + $this->assertFalse($remove_link->isVisible(), 'Remove group should be invisible after drag.'); + } + + /** + * Uses the 'And/Or Rearrange' link for filters to open a dialog. + */ + protected function openFilterDialog() { + $assert_session = $this->assertSession(); + $page = $this->getSession()->getPage(); + $dropbutton = $page->find('css', '.views-ui-display-tab-bucket.filter .dropbutton-toggle button'); + $dropbutton->click(); + $add_link = $page->findById('views-rearrange-filter'); + $this->assertTrue($add_link->isVisible(), 'And/Or Rearrange button found.'); + $add_link->click(); + $assert_session->assertWaitOnAjaxRequest(); } } diff --git a/core/tests/Drupal/FunctionalJavascriptTests/Ajax/CommandsTest.php b/core/tests/Drupal/FunctionalJavascriptTests/Ajax/CommandsTest.php index 0db5e5f74e4d..f2e957704823 100644 --- a/core/tests/Drupal/FunctionalJavascriptTests/Ajax/CommandsTest.php +++ b/core/tests/Drupal/FunctionalJavascriptTests/Ajax/CommandsTest.php @@ -37,14 +37,20 @@ public function testAjaxCommands() { $this->assertWaitPageContains('<div id="after_div">Something can be inserted after this</div>This will be placed after'); // Tests the 'alert' command. - $test_alert_command = <<<JS -window.alert = function() { - document.body.innerHTML += '<div class="alert-command">Alert</div>'; -}; -JS; - $session->executeScript($test_alert_command); $page->pressButton("AJAX 'Alert': Click to alert"); - $this->assertWaitPageContains('<div class="alert-command">Alert</div>'); + // Wait for the alert to appear. + $page->waitFor(10, function () use ($session) { + try { + $session->getDriver()->getWebDriverSession()->getAlert_text(); + return TRUE; + } + catch (\Exception $e) { + return FALSE; + } + }); + $alert_text = $this->getSession()->getDriver()->getWebDriverSession()->getAlert_text(); + $this->assertEquals('Alert', $alert_text); + $this->getSession()->getDriver()->getWebDriverSession()->accept_alert(); // Tests the 'append' command. $page->pressButton("AJAX 'Append': Click to append something"); -- GitLab