Update Composer, update everything
This commit is contained in:
parent
ea3e94409f
commit
dda5c284b6
19527 changed files with 1135420 additions and 351004 deletions
|
@ -0,0 +1,8 @@
|
|||
name: 'Contextual Test'
|
||||
type: module
|
||||
description: 'Provides test contextual links.'
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
dependencies:
|
||||
- drupal:contextual
|
|
@ -0,0 +1,12 @@
|
|||
contextual_test:
|
||||
title: 'Test Link'
|
||||
route_name: 'contextual_test'
|
||||
group: 'contextual_test'
|
||||
contextual_test_ajax:
|
||||
title: 'Test Link with Ajax'
|
||||
route_name: 'contextual_test'
|
||||
group: 'contextual_test'
|
||||
options:
|
||||
attributes:
|
||||
class: ['use-ajax']
|
||||
data-dialog-type: 'modal'
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Provides test contextual link on blocks.
|
||||
*/
|
||||
|
||||
use Drupal\Core\Block\BlockPluginInterface;
|
||||
|
||||
/**
|
||||
* Implements hook_block_view_alter().
|
||||
*/
|
||||
function contextual_test_block_view_alter(array &$build, BlockPluginInterface $block) {
|
||||
$build['#contextual_links']['contextual_test'] = [
|
||||
'route_parameters' => [],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_contextual_links_view_alter().
|
||||
*
|
||||
* @todo Apparently this too late to attach the library?
|
||||
* It won't work without contextual_test_page_attachments_alter()
|
||||
* Is that a problem? Should the contextual module itself do the attaching?
|
||||
*/
|
||||
function contextual_test_contextual_links_view_alter(&$element, $items) {
|
||||
if (isset($element['#links']['contextual-test-ajax'])) {
|
||||
$element['#attached']['library'][] = 'core/drupal.dialog.ajax';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_page_attachments_alter().
|
||||
*/
|
||||
function contextual_test_page_attachments_alter(array &$attachments) {
|
||||
$attachments['#attached']['library'][] = 'core/drupal.dialog.ajax';
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
contextual_test:
|
||||
path: '/contextual-tests'
|
||||
defaults:
|
||||
_controller: '\Drupal\contextual_test\Controller\TestController::render'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\contextual_test\Controller;
|
||||
|
||||
/**
|
||||
* Test controller to provide a callback for the contextual link.
|
||||
*/
|
||||
class TestController {
|
||||
|
||||
/**
|
||||
* Callback for the contextual link.
|
||||
*
|
||||
* @return array
|
||||
* Render array.
|
||||
*/
|
||||
public function render() {
|
||||
return [
|
||||
'#type' => 'markup',
|
||||
'#markup' => 'Everything is contextual!',
|
||||
];
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,267 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\contextual\Functional;
|
||||
|
||||
use Drupal\Component\Serialization\Json;
|
||||
use Drupal\Component\Utility\Crypt;
|
||||
use Drupal\Core\Site\Settings;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
|
||||
/**
|
||||
* Tests if contextual links are showing on the front page depending on
|
||||
* permissions.
|
||||
*
|
||||
* @group contextual
|
||||
*/
|
||||
class ContextualDynamicContextTest extends BrowserTestBase {
|
||||
|
||||
/**
|
||||
* A user with permission to access contextual links and edit content.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $editorUser;
|
||||
|
||||
/**
|
||||
* An authenticated user with permission to access contextual links.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $authenticatedUser;
|
||||
|
||||
/**
|
||||
* A simulated anonymous user with access only to node content.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $anonymousUser;
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['contextual', 'node', 'views', 'views_ui', 'language', 'menu_test'];
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']);
|
||||
$this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']);
|
||||
|
||||
ConfigurableLanguage::createFromLangcode('it')->save();
|
||||
$this->rebuildContainer();
|
||||
|
||||
$this->editorUser = $this->drupalCreateUser(['access content', 'access contextual links', 'edit any article content']);
|
||||
$this->authenticatedUser = $this->drupalCreateUser(['access content', 'access contextual links']);
|
||||
$this->anonymousUser = $this->drupalCreateUser(['access content']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests contextual links with different permissions.
|
||||
*
|
||||
* Ensures that contextual link placeholders always exist, even if the user is
|
||||
* not allowed to use contextual links.
|
||||
*/
|
||||
public function testDifferentPermissions() {
|
||||
$this->drupalLogin($this->editorUser);
|
||||
|
||||
// Create three nodes in the following order:
|
||||
// - An article, which should be user-editable.
|
||||
// - A page, which should not be user-editable.
|
||||
// - A second article, which should also be user-editable.
|
||||
$node1 = $this->drupalCreateNode(['type' => 'article', 'promote' => 1]);
|
||||
$node2 = $this->drupalCreateNode(['type' => 'page', 'promote' => 1]);
|
||||
$node3 = $this->drupalCreateNode(['type' => 'article', 'promote' => 1]);
|
||||
|
||||
// Now, on the front page, all article nodes should have contextual links
|
||||
// placeholders, as should the view that contains them.
|
||||
$ids = [
|
||||
'node:node=' . $node1->id() . ':changed=' . $node1->getChangedTime() . '&langcode=en',
|
||||
'node:node=' . $node2->id() . ':changed=' . $node2->getChangedTime() . '&langcode=en',
|
||||
'node:node=' . $node3->id() . ':changed=' . $node3->getChangedTime() . '&langcode=en',
|
||||
'entity.view.edit_form:view=frontpage:location=page&name=frontpage&display_id=page_1&langcode=en',
|
||||
];
|
||||
|
||||
// Editor user: can access contextual links and can edit articles.
|
||||
$this->drupalGet('node');
|
||||
for ($i = 0; $i < count($ids); $i++) {
|
||||
$this->assertContextualLinkPlaceHolder($ids[$i]);
|
||||
}
|
||||
$response = $this->renderContextualLinks([], 'node');
|
||||
$this->assertSame(400, $response->getStatusCode());
|
||||
$this->assertContains('No contextual ids specified.', (string) $response->getBody());
|
||||
$response = $this->renderContextualLinks($ids, 'node');
|
||||
$this->assertSame(200, $response->getStatusCode());
|
||||
$json = Json::decode((string) $response->getBody());
|
||||
$this->assertIdentical($json[$ids[0]], '<ul class="contextual-links"><li class="entitynodeedit-form"><a href="' . base_path() . 'node/1/edit">Edit</a></li></ul>');
|
||||
$this->assertIdentical($json[$ids[1]], '');
|
||||
$this->assertIdentical($json[$ids[2]], '<ul class="contextual-links"><li class="entitynodeedit-form"><a href="' . base_path() . 'node/3/edit">Edit</a></li></ul>');
|
||||
$this->assertIdentical($json[$ids[3]], '');
|
||||
|
||||
// Verify that link language is properly handled.
|
||||
$node3->addTranslation('it')->set('title', $this->randomString())->save();
|
||||
$id = 'node:node=' . $node3->id() . ':changed=' . $node3->getChangedTime() . '&langcode=it';
|
||||
$this->drupalGet('node', ['language' => ConfigurableLanguage::createFromLangcode('it')]);
|
||||
$this->assertContextualLinkPlaceHolder($id);
|
||||
|
||||
// Authenticated user: can access contextual links, cannot edit articles.
|
||||
$this->drupalLogin($this->authenticatedUser);
|
||||
$this->drupalGet('node');
|
||||
for ($i = 0; $i < count($ids); $i++) {
|
||||
$this->assertContextualLinkPlaceHolder($ids[$i]);
|
||||
}
|
||||
$response = $this->renderContextualLinks([], 'node');
|
||||
$this->assertSame(400, $response->getStatusCode());
|
||||
$this->assertContains('No contextual ids specified.', (string) $response->getBody());
|
||||
$response = $this->renderContextualLinks($ids, 'node');
|
||||
$this->assertSame(200, $response->getStatusCode());
|
||||
$json = Json::decode((string) $response->getBody());
|
||||
$this->assertIdentical($json[$ids[0]], '');
|
||||
$this->assertIdentical($json[$ids[1]], '');
|
||||
$this->assertIdentical($json[$ids[2]], '');
|
||||
$this->assertIdentical($json[$ids[3]], '');
|
||||
|
||||
// Anonymous user: cannot access contextual links.
|
||||
$this->drupalLogin($this->anonymousUser);
|
||||
$this->drupalGet('node');
|
||||
for ($i = 0; $i < count($ids); $i++) {
|
||||
$this->assertNoContextualLinkPlaceHolder($ids[$i]);
|
||||
}
|
||||
$response = $this->renderContextualLinks([], 'node');
|
||||
$this->assertSame(403, $response->getStatusCode());
|
||||
$this->renderContextualLinks($ids, 'node');
|
||||
$this->assertSame(403, $response->getStatusCode());
|
||||
|
||||
// Get a page where contextual links are directly rendered.
|
||||
$this->drupalGet(Url::fromRoute('menu_test.contextual_test'));
|
||||
$this->assertEscaped("<script>alert('Welcome to the jungle!')</script>");
|
||||
$this->assertRaw('<li class="menu-testcontextual-hidden-manage-edit"><a href="' . base_path() . 'menu-test-contextual/1/edit" class="use-ajax" data-dialog-type="modal" data-is-something>Edit menu - contextual</a></li>');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the contextual placeholder content is protected by a token.
|
||||
*/
|
||||
public function testTokenProtection() {
|
||||
$this->drupalLogin($this->editorUser);
|
||||
|
||||
// Create a node that will have a contextual link.
|
||||
$node1 = $this->drupalCreateNode(['type' => 'article', 'promote' => 1]);
|
||||
|
||||
// Now, on the front page, all article nodes should have contextual links
|
||||
// placeholders, as should the view that contains them.
|
||||
$id = 'node:node=' . $node1->id() . ':changed=' . $node1->getChangedTime() . '&langcode=en';
|
||||
|
||||
// Editor user: can access contextual links and can edit articles.
|
||||
$this->drupalGet('node');
|
||||
$this->assertContextualLinkPlaceHolder($id);
|
||||
|
||||
$http_client = $this->getHttpClient();
|
||||
$url = Url::fromRoute('contextual.render', [], [
|
||||
'query' => [
|
||||
'_format' => 'json',
|
||||
'destination' => 'node',
|
||||
],
|
||||
])->setAbsolute()->toString();
|
||||
|
||||
$response = $http_client->request('POST', $url, [
|
||||
'cookies' => $this->getSessionCookies(),
|
||||
'form_params' => ['ids' => [$id], 'tokens' => []],
|
||||
'http_errors' => FALSE,
|
||||
]);
|
||||
$this->assertEquals('400', $response->getStatusCode());
|
||||
$this->assertContains('No contextual ID tokens specified.', (string) $response->getBody());
|
||||
|
||||
$response = $http_client->request('POST', $url, [
|
||||
'cookies' => $this->getSessionCookies(),
|
||||
'form_params' => ['ids' => [$id], 'tokens' => ['wrong_token']],
|
||||
'http_errors' => FALSE,
|
||||
]);
|
||||
$this->assertEquals('400', $response->getStatusCode());
|
||||
$this->assertContains('Invalid contextual ID specified.', (string) $response->getBody());
|
||||
|
||||
$response = $http_client->request('POST', $url, [
|
||||
'cookies' => $this->getSessionCookies(),
|
||||
'form_params' => ['ids' => [$id], 'tokens' => ['wrong_key' => $this->createContextualIdToken($id)]],
|
||||
'http_errors' => FALSE,
|
||||
]);
|
||||
$this->assertEquals('400', $response->getStatusCode());
|
||||
$this->assertContains('Invalid contextual ID specified.', (string) $response->getBody());
|
||||
|
||||
$response = $http_client->request('POST', $url, [
|
||||
'cookies' => $this->getSessionCookies(),
|
||||
'form_params' => ['ids' => [$id], 'tokens' => [$this->createContextualIdToken($id)]],
|
||||
'http_errors' => FALSE,
|
||||
]);
|
||||
$this->assertEquals('200', $response->getStatusCode());
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that a contextual link placeholder with the given id exists.
|
||||
*
|
||||
* @param string $id
|
||||
* A contextual link id.
|
||||
*/
|
||||
protected function assertContextualLinkPlaceHolder($id) {
|
||||
$this->assertSession()->elementAttributeContains(
|
||||
'css',
|
||||
'div[data-contextual-id="' . $id . '"]',
|
||||
'data-contextual-token',
|
||||
$this->createContextualIdToken($id)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that a contextual link placeholder with the given id does not exist.
|
||||
*
|
||||
* @param string $id
|
||||
* A contextual link id.
|
||||
*/
|
||||
protected function assertNoContextualLinkPlaceHolder($id) {
|
||||
$this->assertSession()->elementNotExists('css', 'div[data-contextual-id="' . $id . '"]');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get server-rendered contextual links for the given contextual link ids.
|
||||
*
|
||||
* @param array $ids
|
||||
* An array of contextual link ids.
|
||||
* @param string $current_path
|
||||
* The Drupal path for the page for which the contextual links are rendered.
|
||||
*
|
||||
* @return \Psr\Http\Message\ResponseInterface
|
||||
* The response object.
|
||||
*/
|
||||
protected function renderContextualLinks($ids, $current_path) {
|
||||
$tokens = array_map([$this, 'createContextualIdToken'], $ids);
|
||||
$http_client = $this->getHttpClient();
|
||||
$url = Url::fromRoute('contextual.render', [], [
|
||||
'query' => [
|
||||
'_format' => 'json',
|
||||
'destination' => $current_path,
|
||||
],
|
||||
]);
|
||||
|
||||
return $http_client->request('POST', $this->buildUrl($url), [
|
||||
'cookies' => $this->getSessionCookies(),
|
||||
'form_params' => ['ids' => $ids, 'tokens' => $tokens],
|
||||
'http_errors' => FALSE,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a contextual ID token.
|
||||
*
|
||||
* @param string $id
|
||||
* The contextual ID to create a token for.
|
||||
*
|
||||
* @return string
|
||||
* The contextual ID token.
|
||||
*/
|
||||
protected function createContextualIdToken($id) {
|
||||
return Crypt::hmacBase64($id, Settings::getHashSalt() . $this->container->get('private_key')->get());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\contextual\FunctionalJavascript;
|
||||
|
||||
/**
|
||||
* Functions for testing contextual links.
|
||||
*/
|
||||
trait ContextualLinkClickTrait {
|
||||
|
||||
/**
|
||||
* Clicks a contextual link.
|
||||
*
|
||||
* @param string $selector
|
||||
* The selector for the element that contains the contextual link.
|
||||
* @param string $link_locator
|
||||
* The link id, title, or text.
|
||||
* @param bool $force_visible
|
||||
* If true then the button will be forced to visible so it can be clicked.
|
||||
*/
|
||||
protected function clickContextualLink($selector, $link_locator, $force_visible = TRUE) {
|
||||
$page = $this->getSession()->getPage();
|
||||
$page->waitFor(10, function () use ($page, $selector) {
|
||||
return $page->find('css', "$selector .contextual-links");
|
||||
});
|
||||
|
||||
if ($force_visible) {
|
||||
$this->toggleContextualTriggerVisibility($selector);
|
||||
}
|
||||
|
||||
$element = $this->getSession()->getPage()->find('css', $selector);
|
||||
$element->find('css', '.contextual button')->press();
|
||||
$element->findLink($link_locator)->click();
|
||||
|
||||
if ($force_visible) {
|
||||
$this->toggleContextualTriggerVisibility($selector);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles the visibility of a contextual trigger.
|
||||
*
|
||||
* @param string $selector
|
||||
* The selector for the element that contains the contextual link.
|
||||
*/
|
||||
protected function toggleContextualTriggerVisibility($selector) {
|
||||
// Hovering over the element itself with should be enough, but does not
|
||||
// work. Manually remove the visually-hidden class.
|
||||
$this->getSession()->executeScript("jQuery('{$selector} .contextual .trigger').toggleClass('visually-hidden');");
|
||||
}
|
||||
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace Drupal\Tests\contextual\FunctionalJavascript;
|
||||
|
||||
use Drupal\FunctionalJavascriptTests\JavascriptTestBase;
|
||||
use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
|
||||
use Drupal\user\Entity\Role;
|
||||
|
||||
/**
|
||||
|
@ -10,7 +10,9 @@ use Drupal\user\Entity\Role;
|
|||
*
|
||||
* @group contextual
|
||||
*/
|
||||
class ContextualLinksTest extends JavascriptTestBase {
|
||||
class ContextualLinksTest extends WebDriverTestBase {
|
||||
|
||||
use ContextualLinkClickTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
|
@ -23,6 +25,7 @@ class ContextualLinksTest extends JavascriptTestBase {
|
|||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->drupalLogin($this->createUser(['access contextual links']));
|
||||
$this->placeBlock('system_branding_block', ['id' => 'branding']);
|
||||
}
|
||||
|
||||
|
@ -30,10 +33,6 @@ class ContextualLinksTest extends JavascriptTestBase {
|
|||
* Tests the visibility of contextual links.
|
||||
*/
|
||||
public function testContextualLinksVisibility() {
|
||||
$this->drupalLogin($this->drupalCreateUser([
|
||||
'access contextual links'
|
||||
]));
|
||||
|
||||
$this->drupalGet('user');
|
||||
$contextualLinks = $this->assertSession()->waitForElement('css', '.contextual button');
|
||||
$this->assertEmpty($contextualLinks);
|
||||
|
@ -59,4 +58,53 @@ class ContextualLinksTest extends JavascriptTestBase {
|
|||
$this->assertNotEmpty($contextualLinks);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test clicking contextual links.
|
||||
*/
|
||||
public function testContextualLinksClick() {
|
||||
$this->container->get('module_installer')->install(['contextual_test']);
|
||||
// Test clicking contextual link without toolbar.
|
||||
$this->drupalGet('user');
|
||||
$this->assertSession()->assertWaitOnAjaxRequest();
|
||||
$this->clickContextualLink('#block-branding', 'Test Link');
|
||||
$this->assertSession()->pageTextContains('Everything is contextual!');
|
||||
|
||||
// Test click a contextual link that uses ajax.
|
||||
$this->drupalGet('user');
|
||||
$this->assertSession()->assertWaitOnAjaxRequest();
|
||||
$current_page_string = 'NOT_RELOADED_IF_ON_PAGE';
|
||||
$this->getSession()->executeScript('document.body.appendChild(document.createTextNode("' . $current_page_string . '"));');
|
||||
$this->clickContextualLink('#block-branding', 'Test Link with Ajax');
|
||||
$this->assertNotEmpty($this->assertSession()->waitForElementVisible('css', '#drupal-modal'));
|
||||
$this->assertSession()->elementContains('css', '#drupal-modal', 'Everything is contextual!');
|
||||
// Check to make sure that page was not reloaded.
|
||||
$this->assertSession()->pageTextContains($current_page_string);
|
||||
|
||||
// Test clicking contextual link with toolbar.
|
||||
$this->container->get('module_installer')->install(['toolbar']);
|
||||
$this->grantPermissions(Role::load(Role::AUTHENTICATED_ID), ['access toolbar']);
|
||||
$this->drupalGet('user');
|
||||
$this->assertSession()->assertWaitOnAjaxRequest();
|
||||
|
||||
// Click "Edit" in toolbar to show contextual links.
|
||||
$this->getSession()->getPage()->find('css', '.contextual-toolbar-tab button')->press();
|
||||
$this->clickContextualLink('#block-branding', 'Test Link', FALSE);
|
||||
$this->assertSession()->pageTextContains('Everything is contextual!');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the contextual links destination.
|
||||
*/
|
||||
public function testContextualLinksDestination() {
|
||||
$this->grantPermissions(Role::load(Role::AUTHENTICATED_ID), [
|
||||
'access contextual links',
|
||||
'administer blocks',
|
||||
]);
|
||||
$this->drupalGet('user');
|
||||
$this->assertSession()->waitForElement('css', '.contextual button');
|
||||
$expected_destination_value = (string) $this->loggedInUser->toUrl()->toString();
|
||||
$contextual_link_url_parsed = parse_url($this->getSession()->getPage()->findLink('Configure block')->getAttribute('href'));
|
||||
$this->assertEquals("destination=$expected_destination_value", $contextual_link_url_parsed['query']);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,137 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\contextual\FunctionalJavascript;
|
||||
|
||||
use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
|
||||
|
||||
/**
|
||||
* Tests edit mode.
|
||||
*
|
||||
* @group contextual
|
||||
*/
|
||||
class EditModeTest extends WebDriverTestBase {
|
||||
|
||||
/**
|
||||
* CSS selector for Drupal's announce element.
|
||||
*/
|
||||
const ANNOUNCE_SELECTOR = '#drupal-live-announce';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = [
|
||||
'node',
|
||||
'block',
|
||||
'user',
|
||||
'system',
|
||||
'breakpoint',
|
||||
'toolbar',
|
||||
'contextual',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->drupalLogin($this->createUser([
|
||||
'administer blocks',
|
||||
'access contextual links',
|
||||
'access toolbar',
|
||||
]));
|
||||
$this->placeBlock('system_powered_by_block', ['id' => 'powered']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests enabling and disabling edit mode.
|
||||
*/
|
||||
public function testEditModeEnableDisalbe() {
|
||||
$web_assert = $this->assertSession();
|
||||
$page = $this->getSession()->getPage();
|
||||
// Get the page twice to ensure edit mode remains enabled after a new page
|
||||
// request.
|
||||
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]'));
|
||||
|
||||
// After the page loaded we need to additionally wait until the settings
|
||||
// tray Ajax activity is done.
|
||||
$web_assert->assertWaitOnAjaxRequest();
|
||||
|
||||
if ($page_get_count == 0) {
|
||||
$unrestricted_tab_count = $this->getTabbableElementsCount();
|
||||
$this->assertGreaterThan($expected_restricted_tab_count, $unrestricted_tab_count);
|
||||
|
||||
// Enable edit mode.
|
||||
// After the first page load the page will be in edit mode when loaded.
|
||||
$this->pressToolbarEditButton();
|
||||
}
|
||||
|
||||
$this->assertAnnounceEditMode();
|
||||
$this->assertSame($expected_restricted_tab_count, $this->getTabbableElementsCount());
|
||||
|
||||
// Disable edit mode.
|
||||
$this->pressToolbarEditButton();
|
||||
$this->assertAnnounceLeaveEditMode();
|
||||
$this->assertSame($unrestricted_tab_count, $this->getTabbableElementsCount());
|
||||
// Enable edit mode again.
|
||||
$this->pressToolbarEditButton();
|
||||
// Finally assert that the 'edit mode enabled' announcement is still
|
||||
// correct after toggling the edit mode at least once.
|
||||
$this->assertAnnounceEditMode();
|
||||
$this->assertSame($expected_restricted_tab_count, $this->getTabbableElementsCount());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Presses the toolbar edit mode.
|
||||
*/
|
||||
protected function pressToolbarEditButton() {
|
||||
$edit_button = $this->getSession()->getPage()->find('css', '#toolbar-bar div.contextual-toolbar-tab button');
|
||||
$edit_button->press();
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the correct message was announced when entering edit mode.
|
||||
*/
|
||||
protected function assertAnnounceEditMode() {
|
||||
$web_assert = $this->assertSession();
|
||||
// Wait for contextual trigger button.
|
||||
$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.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the correct message was announced when leaving edit mode.
|
||||
*/
|
||||
protected function assertAnnounceLeaveEditMode() {
|
||||
$web_assert = $this->assertSession();
|
||||
$page = $this->getSession()->getPage();
|
||||
// Wait till all the contextual links are hidden.
|
||||
$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');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of elements that are tabbable.
|
||||
*
|
||||
* @return int
|
||||
* The number of tabbable elements.
|
||||
*/
|
||||
protected function getTabbableElementsCount() {
|
||||
// Mark all tabbable elements.
|
||||
$this->getSession()->executeScript("jQuery(':tabbable').attr('data-marked', '');");
|
||||
// Count all marked elements.
|
||||
$count = count($this->getSession()->getPage()->findAll('css', "[data-marked]"));
|
||||
// Remove set attributes.
|
||||
$this->getSession()->executeScript("jQuery('[data-marked]').removeAttr('data-marked');");
|
||||
return $count;
|
||||
}
|
||||
|
||||
}
|
|
@ -65,7 +65,7 @@ class ContextualUnitTest extends KernelTestBase {
|
|||
'links' => [
|
||||
'views_ui_edit' => [
|
||||
'route_parameters' => [
|
||||
'view' => 'frontpage'
|
||||
'view' => 'frontpage',
|
||||
],
|
||||
'metadata' => [
|
||||
'location' => 'page',
|
||||
|
|
Reference in a new issue