View source  
  <?php
namespace Drupal\Tests\contextual\FunctionalJavascript;
use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
class EditModeTest extends WebDriverTestBase {
  
  const ANNOUNCE_SELECTOR = '#drupal-live-announce';
  
  protected static $modules = [
    'node',
    'block',
    'user',
    'system',
    'breakpoint',
    'toolbar',
    'contextual',
  ];
  
  protected $defaultTheme = 'stark';
  
  protected function setUp() : void {
    parent::setUp();
    $this
      ->drupalLogin($this
      ->createUser([
      'administer blocks',
      'access contextual links',
      'access toolbar',
    ]));
    $this
      ->placeBlock('system_powered_by_block', [
      'id' => 'powered',
    ]);
  }
  
  public function testEditModeEnableDisable() {
    $web_assert = $this
      ->assertSession();
    $page = $this
      ->getSession()
      ->getPage();
    
    for ($page_get_count = 0; $page_get_count < 2; $page_get_count++) {
      $this
        ->drupalGet('user');
      $expected_restricted_tab_count = 1 + count($page
        ->findAll('css', '[data-contextual-id]'));
      
      $web_assert
        ->assertWaitOnAjaxRequest();
      if ($page_get_count == 0) {
        $unrestricted_tab_count = $this
          ->getTabbableElementsCount();
        $this
          ->assertGreaterThan($expected_restricted_tab_count, $unrestricted_tab_count);
        
        $this
          ->pressToolbarEditButton();
      }
      $this
        ->assertAnnounceEditMode();
      $this
        ->assertSame($expected_restricted_tab_count, $this
        ->getTabbableElementsCount());
      
      $this
        ->pressToolbarEditButton();
      $this
        ->assertAnnounceLeaveEditMode();
      $this
        ->assertSame($unrestricted_tab_count, $this
        ->getTabbableElementsCount());
      
      $this
        ->pressToolbarEditButton();
      
      $this
        ->assertAnnounceEditMode();
      $this
        ->assertSame($expected_restricted_tab_count, $this
        ->getTabbableElementsCount());
    }
  }
  
  protected function pressToolbarEditButton() {
    $edit_button = $this
      ->getSession()
      ->getPage()
      ->find('css', '#toolbar-bar div.contextual-toolbar-tab button');
    $edit_button
      ->press();
  }
  
  protected function assertAnnounceEditMode() : void {
    $web_assert = $this
      ->assertSession();
    
    $web_assert
      ->waitForElementVisible('css', '.contextual trigger');
    $web_assert
      ->elementContains('css', static::ANNOUNCE_SELECTOR, 'Tabbing is constrained to a set of');
    $web_assert
      ->elementNotContains('css', static::ANNOUNCE_SELECTOR, 'Tabbing is no longer constrained by the Contextual module.');
  }
  
  protected function assertAnnounceLeaveEditMode() : void {
    $web_assert = $this
      ->assertSession();
    $page = $this
      ->getSession()
      ->getPage();
    
    $page
      ->waitFor(1, function () use ($page, $web_assert) {
      return empty($page
        ->find('css', '.contextual .trigger.visually-hidden'));
    });
    $web_assert
      ->elementContains('css', static::ANNOUNCE_SELECTOR, 'Tabbing is no longer constrained by the Contextual module.');
    $web_assert
      ->elementNotContains('css', static::ANNOUNCE_SELECTOR, 'Tabbing is constrained to a set of');
  }
  
  protected function getTabbableElementsCount() {
    
    $this
      ->getSession()
      ->executeScript("jQuery(window.tabbable.tabbable(document.body)).attr('data-marked', '');");
    
    $count = count($this
      ->getSession()
      ->getPage()
      ->findAll('css', "[data-marked]"));
    
    $this
      ->getSession()
      ->executeScript("jQuery('[data-marked]').removeAttr('data-marked');");
    return $count;
  }
}