Unverified Commit 7ff9cbf0 authored by Lauri Timmanee's avatar Lauri Timmanee
Browse files

Issue #3032275 by alexpott, dww, bendeguz.csirmaz, tedbow: Create a...

Issue #3032275 by alexpott, dww, bendeguz.csirmaz, tedbow: Create a fault-tolerant method for interacting with links and fields in Javascript tests
parent d90527ba
Loading
Loading
Loading
Loading
+6 −38
Original line number Diff line number Diff line
@@ -2,10 +2,8 @@

namespace Drupal\Tests\layout_builder\FunctionalJavascript;

use Behat\Mink\Element\NodeElement;
use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
use Drupal\Tests\contextual\FunctionalJavascript\ContextualLinkClickTrait;
use WebDriver\Exception\UnknownError;

/**
 * Tests that messages appear in the off-canvas dialog with configuring blocks.
@@ -59,14 +57,14 @@ public function testValidationMessage() {
    // Enable layout builder.
    $this->drupalGet($field_ui_prefix . '/display/default');
    $this->submitForm(['layout[enabled]' => TRUE], 'Save');
    $this->clickElementWhenClickable($page->findLink('Manage layout'));
    $page->findLink('Manage layout')->click();
    $assert_session->addressEquals($field_ui_prefix . '/display/default/layout');
    $this->clickElementWhenClickable($page->findLink('Add block'));
    $page->findLink('Add block')->click();
    $this->assertNotEmpty($assert_session->waitForElementVisible('css', '#drupal-off-canvas .block-categories'));
    $this->clickElementWhenClickable($page->findLink('Powered by Drupal'));
    $page->findLink('Powered by Drupal')->click();
    $this->assertNotEmpty($assert_session->waitForElementVisible('css', '#drupal-off-canvas [name="settings[label]"]'));
    $page->findField('Title')->setValue('');
    $this->clickElementWhenClickable($page->findButton('Add block'));
    $page->findButton('Add block')->click();
    $this->assertMessagesDisplayed();
    $page->findField('Title')->setValue('New title');
    $page->pressButton('Add block');
@@ -76,7 +74,7 @@ public function testValidationMessage() {
    $assert_session->assertNoElementAfterWait('css', '#drupal-off-canvas');
    $assert_session->assertWaitOnAjaxRequest();
    $this->drupalGet($this->getUrl());
    $this->clickElementWhenClickable($page->findButton('Save layout'));
    $page->findButton('Save layout')->click();
    $this->assertNotEmpty($assert_session->waitForElement('css', 'div:contains("The layout has been saved")'));

    // Ensure that message are displayed when configuring an existing block.
@@ -85,7 +83,7 @@ public function testValidationMessage() {
    $this->clickContextualLink($block_css_locator, 'Configure', TRUE);
    $this->assertNotEmpty($assert_session->waitForElementVisible('css', '#drupal-off-canvas [name="settings[label]"]'));
    $page->findField('Title')->setValue('');
    $this->clickElementWhenClickable($page->findButton('Update'));
    $page->findButton('Update')->click();
    $this->assertMessagesDisplayed();
  }

@@ -106,34 +104,4 @@ protected function assertMessagesDisplayed() {
    $this->assertGreaterThan(4, count($top_form_elements));
  }

  /**
   * Attempts to click an element until it is in a clickable state.
   *
   * @param \Behat\Mink\Element\NodeElement $element
   *   The element to click.
   * @param int $timeout
   *   (Optional) Timeout in milliseconds, defaults to 10000.
   *
   * @todo Replace this method with general solution for random click() test
   *   failures in https://www.drupal.org/node/3032275.
   */
  protected function clickElementWhenClickable(NodeElement $element, $timeout = 10000) {
    $page = $this->getSession()->getPage();

    $result = $page->waitFor($timeout / 1000, function () use ($element) {
      try {
        $element->click();
        return TRUE;
      }
      catch (UnknownError $exception) {
        if (strstr($exception->getMessage(), 'not clickable') === FALSE) {
          // Rethrow any unexpected UnknownError exceptions.
          throw $exception;
        }
        return NULL;
      }
    });
    $this->assertTrue($result);
  }

}
+2 −2
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@
use Drupal\block_content\Entity\BlockContent;
use Drupal\block_content\Entity\BlockContentType;
use Drupal\Component\Render\FormattableMarkup;
use Drupal\FunctionalJavascriptTests\JSWebAssert;
use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
use Drupal\Tests\contextual\FunctionalJavascript\ContextualLinkClickTrait;

@@ -181,8 +182,7 @@ protected function assertElementUnclickable(NodeElement $element) {
      $this->fail(new FormattableMarkup("@tag_name was clickable when it shouldn't have been", ['@tag_name' => $tag_name]));
    }
    catch (\Exception $e) {
      // cspell:ignore interactable
      $this->assertMatchesRegularExpression('/(is not clickable at point|element not interactable)/', $e->getMessage());
      $this->assertTrue(JSWebAssert::isExceptionNotClickable($e));
    }
  }

+13 −0
Original line number Diff line number Diff line
.blocker-element {
  /* Position the box over the target. */
  position: relative;
  z-index: 1;
  top: -30px;
  left: -5px;
  /* Size the box to cover the target. */
  width: 500px;
  height: 40px;
  opacity: 0.5;
  /* Make the blocker element visible. */
  background-color: black;
}
+38 −0
Original line number Diff line number Diff line
/**
 * @file
 *  Testing behavior for JSInteractionTest.
 */

(({ behaviors }) => {
  /**
   * @type {Drupal~behavior}
   *
   * @prop {Drupal~behaviorAttach} attach
   *   Attaches the click listener on the trigger link.
   */
  behaviors.js_interaction_test_trigger_link = {
    attach() {
      const removeBlockerTrigger = once(
        'remove-blocker-trigger',
        '.remove-blocker-trigger',
      ).shift();
      removeBlockerTrigger.addEventListener('click', (event) => {
        event.preventDefault();
        setTimeout(() => {
          document.querySelector('.blocker-element').remove();
        }, 100);
      });

      const enableFieldTrigger = once(
        'enable-field-trigger',
        '.enable-field-trigger',
      ).shift();
      enableFieldTrigger.addEventListener('click', (event) => {
        event.preventDefault();
        setTimeout(() => {
          document.querySelector('input[name="target_field"]').disabled = false;
        }, 100);
      });
    },
  };
})(Drupal);
+28 −0
Original line number Diff line number Diff line
/**
* DO NOT EDIT THIS FILE.
* See the following change record for more information,
* https://www.drupal.org/node/2815083
* @preserve
**/

(function (_ref) {
  var behaviors = _ref.behaviors;
  behaviors.js_interaction_test_trigger_link = {
    attach: function attach() {
      var removeBlockerTrigger = once('remove-blocker-trigger', '.remove-blocker-trigger').shift();
      removeBlockerTrigger.addEventListener('click', function (event) {
        event.preventDefault();
        setTimeout(function () {
          document.querySelector('.blocker-element').remove();
        }, 100);
      });
      var enableFieldTrigger = once('enable-field-trigger', '.enable-field-trigger').shift();
      enableFieldTrigger.addEventListener('click', function (event) {
        event.preventDefault();
        setTimeout(function () {
          document.querySelector('input[name="target_field"]').disabled = false;
        }, 100);
      });
    }
  };
})(Drupal);
 No newline at end of file
Loading