3 namespace Drupal\Tests\contextual\FunctionalJavascript;
5 use Drupal\FunctionalJavascriptTests\JavascriptTestBase;
12 class EditModeTest extends JavascriptTestBase {
15 * CSS selector for Drupal's announce element.
17 const ANNOUNCE_SELECTOR = '#drupal-live-announce';
22 public static $modules = [
35 protected function setUp() {
38 $this->drupalLogin($this->createUser([
40 'access contextual links',
43 $this->placeBlock('system_powered_by_block', ['id' => 'powered']);
47 * Tests enabling and disabling edit mode.
49 public function testEditModeEnableDisalbe() {
50 $web_assert = $this->assertSession();
51 $page = $this->getSession()->getPage();
52 // Get the page twice to ensure edit mode remains enabled after a new page
54 for ($page_get_count = 0; $page_get_count < 2; $page_get_count++) {
55 $this->drupalGet('user');
56 $expected_restricted_tab_count = 1 + count($page->findAll('css', '[data-contextual-id]'));
58 // After the page loaded we need to additionally wait until the settings
59 // tray Ajax activity is done.
60 $web_assert->assertWaitOnAjaxRequest();
62 if ($page_get_count == 0) {
63 $unrestricted_tab_count = $this->getTabbableElementsCount();
64 $this->assertGreaterThan($expected_restricted_tab_count, $unrestricted_tab_count);
67 // After the first page load the page will be in edit mode when loaded.
68 $this->pressToolbarEditButton();
71 $this->assertAnnounceEditMode();
72 $this->assertSame($expected_restricted_tab_count, $this->getTabbableElementsCount());
75 $this->pressToolbarEditButton();
76 $this->assertAnnounceLeaveEditMode();
77 $this->assertSame($unrestricted_tab_count, $this->getTabbableElementsCount());
78 // Enable edit mode again.
79 $this->pressToolbarEditButton();
80 // Finally assert that the 'edit mode enabled' announcement is still
81 // correct after toggling the edit mode at least once.
82 $this->assertAnnounceEditMode();
83 $this->assertSame($expected_restricted_tab_count, $this->getTabbableElementsCount());
89 * Presses the toolbar edit mode.
91 protected function pressToolbarEditButton() {
92 $edit_button = $this->getSession()->getPage()->find('css', '#toolbar-bar div.contextual-toolbar-tab button');
93 $edit_button->press();
97 * Asserts that the correct message was announced when entering edit mode.
99 protected function assertAnnounceEditMode() {
100 $web_assert = $this->assertSession();
101 // Wait for contextual trigger button.
102 $web_assert->waitForElementVisible('css', '.contextual trigger');
103 $web_assert->elementContains('css', static::ANNOUNCE_SELECTOR, 'Tabbing is constrained to a set of');
104 $web_assert->elementNotContains('css', static::ANNOUNCE_SELECTOR, 'Tabbing is no longer constrained by the Contextual module.');
108 * Assert that the correct message was announced when leaving edit mode.
110 protected function assertAnnounceLeaveEditMode() {
111 $web_assert = $this->assertSession();
112 $page = $this->getSession()->getPage();
113 // Wait till all the contextual links are hidden.
114 $page->waitFor(1, function () use ($page, $web_assert) {
115 return empty($page->find('css', '.contextual .trigger.visually-hidden'));
117 $web_assert->elementContains('css', static::ANNOUNCE_SELECTOR, 'Tabbing is no longer constrained by the Contextual module.');
118 $web_assert->elementNotContains('css', static::ANNOUNCE_SELECTOR, 'Tabbing is constrained to a set of');
122 * Gets the number of elements that are tabbable.
125 * The number of tabbable elements.
127 protected function getTabbableElementsCount() {
128 // Mark all tabbable elements.
129 $this->getSession()->executeScript("jQuery(':tabbable').attr('data-marked', '');");
130 // Count all marked elements.
131 $count = count($this->getSession()->getPage()->findAll('css', "[data-marked]"));
132 // Remove set attributes.
133 $this->getSession()->executeScript("jQuery('[data-marked]').removeAttr('data-marked');");