updated contrib modules

This commit is contained in:
Bachir Soussi Chiadmi
2017-11-14 16:12:58 +01:00
parent c2b4e25be4
commit b32fe9ef14
317 changed files with 4672 additions and 13347 deletions
@@ -5,6 +5,9 @@ use Drupal\Component\Uuid\Php;
use Drupal\Core\Utility\Token;
use Drush\Commands\DrushCommands;
use Drush\Exceptions\UserAbortException;
use Drush\Utils\StringUtils;
use Symfony\Component\Console\Input\Input;
use Symfony\Component\Console\Output\Output;
/**
* For commands that are parts of modules, Drush expects to find commandfiles in
@@ -21,11 +24,21 @@ class DevelCommands extends DrushCommands {
protected $eventDispatcher;
public function __construct(Token $token, $container, $eventDispatcher) {
protected $moduleHandler;
public function __construct(Token $token, $container, $eventDispatcher, $moduleHandler) {
parent::__construct();
$this->token = $token;
$this->container = $container;
$this->eventDispatcher = $eventDispatcher;
$this->moduleHandler = $moduleHandler;
}
/**
* @return \Drupal\Core\Extension\ModuleHandlerInterface
*/
public function getModuleHandler() {
return $this->moduleHandler;
}
/**
@@ -50,93 +63,110 @@ class DevelCommands extends DrushCommands {
}
/**
* Uninstall, and Install a list of modules.
* Uninstall, and Install modules.
* @command devel-reinstall
* @command devel:reinstall
* @param $modules A comma-separated list of module names.
* @aliases dre
* @aliases dre,devel-reinstall
* @allow-additional-options pm-uninstall,pm-enable
*/
public function reinstall($projects) {
$projects = _convert_csv_to_array($projects);
public function reinstall($modules) {
$modules = StringUtils::csvToArray($modules);
// This is faster than 3 separate bootstraps.
$args = array_merge(array('pm-uninstall'), $projects);
// @todo. Use $application dispatch instead of drush_invoke().
call_user_func_array('drush_invoke', $args);
$args = array_merge(array('pm-enable'), $projects);
call_user_func_array('drush_invoke', $args);
$modules_str = implode(',', $modules);
drush_invoke_process('@self', 'pm:uninstall', [$modules_str], []);
drush_invoke_process('@self', 'pm:enable', [$modules_str], []);
}
/**
* List implementations of a given hook and optionally edit one.
*
* @command devel-hook
* @command devel:hook
* @param $hook The name of the hook to explore.
* @param $implementation The name of the implementation to edit. Usually omitted.
* @usage devel-hook cron
* List implementations of hook_cron().
* @aliases fnh,fn-hook,hook
* @aliases fnh,fn-hook,hook,devel-hook
* @optionset_get_editor
*/
function hook($hook) {
function hook($hook, $implementation) {
// Get implementations in the .install files as well.
include_once './core/includes/install.inc';
drupal_load_updates();
$info = $this->codeLocate($implementation . "_$hook");
$exec = drush_get_editor();
drush_shell_exec_interactive($exec, $info['file']);
}
if ($hook_implementations = \Drupal::moduleHandler()->getImplementations($hook)) {
if ($choice = drush_choice(array_combine($hook_implementations, $hook_implementations), 'Enter the number of the hook implementation you wish to view.')) {
$info= $this->codeLocate($choice . "_$hook");
$exec = drush_get_editor();
drush_shell_exec_interactive($exec, $info['file']);
/**
* @hook interact hook
*/
public function hookInteract(Input $input, Output $output) {
if (!$input->getArgument('implementation')) {
if ($hook_implementations = $this->getModuleHandler()->getImplementations($input->getArgument('hook'))) {
if (!$choice = $this->io()->choice('Enter the number of the hook implementation you wish to view.', array_combine($hook_implementations, $hook_implementations))) {
throw new UserAbortException();
}
$input->setArgument('implementation', $choice);
}
else {
throw new \Exception(dt('No implementations'));
}
}
else {
$this->logger()->success(dt('No implementations.'));
}
}
/**
* List implementations of a given event and optionally edit one.
*
* @command devel-event
* @command devel:event
* @param $event The name of the event to explore. If omitted, a list of events is shown.
* @param $implementation The name of the implementation to show. Usually omitted.
* @usage devel-event
* Pick a Kernel event, then pick an implementation, and then view its source code.
* @usage devel-event kernel.terminate
* Pick a terminate subscribers and view its source code.
* Pick a terminate subscribers implementation and view its source code.
* @aliases fne,fn-event,event
*/
function event($event) {
function event($event, $implementation) {
$info= $this->codeLocate($implementation);
$exec = drush_get_editor();
drush_shell_exec_interactive($exec, $info['file']);
}
/**
* @hook interact devel:event
*/
public function interactEvent(Input $input, Output $output) {
$dispatcher = $this->getEventDispatcher();
if (empty($event)) {
// @todo Expand this list and move to interact().
if (!$input->getArgument('event')) {
// @todo Expand this list.
$events = array('kernel.controller', 'kernel.exception', 'kernel.request', 'kernel.response', 'kernel.terminate', 'kernel.view');
$events = array_combine($events, $events);
if (!$event = drush_choice($events, 'Enter the event you wish to explore.')) {
if (!$event = $this->io()->choice('Enter the event you wish to explore.', $events)) {
throw new UserAbortException();
}
$input->setArgument('event', $event);
}
if ($implementations = $dispatcher->getListeners($event)) {
foreach ($implementations as $implementation) {
$callable = get_class($implementation[0]) . '::' . $implementation[1];
$choices[$callable] = $callable;
}
if ($choice = drush_choice($choices, 'Enter the number of the implementation you wish to view.')) {
$info= $this->codeLocate($choice);
$exec = drush_get_editor();
drush_shell_exec_interactive($exec, $info['file']);
if (!$choice = $this->io()->choice('Enter the number of the implementation you wish to view.', $choices)) {
throw new UserAbortException();
}
$input->setArgument('implementation', $choice);
}
else {
$this->logger()->success(dt('No implementations.'));
throw new \Exception(dt('No implementations.'));
}
}
/**
* List available tokens.
*
* @command devel-token
* @aliases token
* @command devel:token
* @aliases token,devel-token
* @field-labels
* group: Group
* token: Token
@@ -162,8 +192,8 @@ class DevelCommands extends DrushCommands {
/**
* Generate a UUID.
*
* @command devel-uuid
* @aliases uuid
* @command devel:uuid
* @aliases uuid,devel-uuid
* @usage drush devel-uuid
* Outputs a Universally Unique Identifier.
*
@@ -203,9 +233,9 @@ class DevelCommands extends DrushCommands {
/**
* Get a list of available container services.
*
* @command devel-services
* @command devel:services
* @param $prefix A prefix to filter the service list by.
* @aliases devel-container-services,dcs
* @aliases devel-container-services,dcs,devel-services
* @usage drush devel-services
* Gets a list of all available container services
* @usage drush dcs plugin.manager
@@ -1,122 +0,0 @@
<?php
namespace Drupal\devel\Tests;
use Drupal\simpletest\WebTestBase;
/**
* Tests Devel controller.
*
* @group devel
*/
class DevelControllerTest extends WebTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('devel', 'node', 'entity_test', 'devel_entity_test', 'block');
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
// Create a test entity.
$random_label = $this->randomMachineName();
$data = array('type' => 'entity_test', 'name' => $random_label);
$this->entity = entity_create('entity_test', $data);
$this->entity->save();
// Create a test entity with only canonical route.
$random_label = $this->randomMachineName();
$data = array('type' => 'devel_entity_test_canonical', 'name' => $random_label);
$this->entity_canonical = entity_create('devel_entity_test_canonical', $data);
$this->entity_canonical->save();
// Create a test entity with only edit route.
$random_label = $this->randomMachineName();
$data = array('type' => 'devel_entity_test_edit', 'name' => $random_label);
$this->entity_edit = entity_create('devel_entity_test_edit', $data);
$this->entity_edit->save();
// Create a test entity with no routes.
$random_label = $this->randomMachineName();
$data = array('type' => 'devel_entity_test_no_links', 'name' => $random_label);
$this->entity_no_links = entity_create('devel_entity_test_no_links', $data);
$this->entity_no_links->save();
$this->drupalPlaceBlock('local_tasks_block');
$web_user = $this->drupalCreateUser(array(
'view test entity',
'administer entity_test content',
'access devel information',
));
$this->drupalLogin($web_user);
}
function testRouteGeneration() {
// Test Devel load and render routes for entities with both route
// definitions.
$this->drupalGet('entity_test/' . $this->entity->id());
$this->assertText('Devel', 'Devel tab is present');
$this->drupalGet('devel/entity_test/' . $this->entity->id());
$this->assertResponse(200);
$this->assertText('Definition', 'Devel definition tab is present');
$this->assertText('Load', 'Devel load tab is present');
$this->assertText('Render', 'Devel load tab is present');
$this->assertLinkByHref('devel/entity_test/' . $this->entity->id() . '/render');
$this->drupalGet('devel/entity_test/' . $this->entity->id() . '/render');
$this->assertResponse(200);
$this->assertLinkByHref('devel/entity_test/' . $this->entity->id() . '/definition');
$this->drupalGet('devel/entity_test/' . $this->entity->id() . '/definition');
$this->assertResponse(200);
// Test Devel load and render routes for entities with only canonical route
// definitions.
$this->drupalGet('devel_entity_test_canonical/' . $this->entity_canonical->id());
$this->assertText('Devel', 'Devel tab is present');
//TODO this fail since assertNoLinkByHref search by partial value.
//$this->assertNoLinkByHref('devel/devel_entity_test_canonical/' . $this->entity_canonical->id());
$this->assertLinkByHref('devel/devel_entity_test_canonical/' . $this->entity_canonical->id() . '/render');
$this->drupalGet('devel/devel_entity_test_canonical/' . $this->entity_canonical->id());
$this->assertResponse(404);
$this->drupalGet('devel/devel_entity_test_canonical/' . $this->entity_canonical->id() . '/render');
$this->assertResponse(200);
$this->assertLinkByHref('devel/devel_entity_test_canonical/' . $this->entity_canonical->id() . '/definition');
$this->drupalGet('devel/devel_entity_test_canonical/' . $this->entity_canonical->id() . '/definition');
$this->assertResponse(200);
// Test Devel load and render routes for entities with only edit route
// definitions.
$this->drupalGet('devel_entity_test_edit/manage/' . $this->entity_edit->id());
$this->assertText('Devel', 'Devel tab is present');
$this->assertLinkByHref('devel/devel_entity_test_edit/' . $this->entity_edit->id());
$this->assertNoLinkByHref('devel/devel_entity_test_edit/' . $this->entity_edit->id() . '/render');
$this->assertNoLinkByHref('devel/devel_entity_test_edit/' . $this->entity_edit->id() . '/definition');
$this->drupalGet('devel/devel_entity_test_edit/' . $this->entity_edit->id());
$this->assertResponse(200);
$this->drupalGet('devel/devel_entity_test_edit/' . $this->entity_edit->id() . '/render');
$this->assertResponse(404);
$this->drupalGet('devel/devel_entity_test_edit/' . $this->entity_edit->id() . '/definition');
$this->assertResponse(200);
// Test Devel load and render routes for entities with no route
// definitions.
$this->drupalGet('devel_entity_test_no_links/' . $this->entity_edit->id());
$this->assertNoText('Devel', 'Devel tab is not present');
$this->assertNoLinkByHref('devel/devel_entity_test_no_links/' . $this->entity_no_links->id());
$this->assertNoLinkByHref('devel/devel_entity_test_no_links/' . $this->entity_no_links->id() . '/render');
$this->assertNoLinkByHref('devel/devel_entity_test_no_links/' . $this->entity_no_links->id() . '/definition');
$this->drupalGet('devel/devel_entity_test_no_links/' . $this->entity_no_links->id());
$this->assertResponse(404);
$this->drupalGet('devel/devel_entity_test_no_links/' . $this->entity_no_links->id() . '/render');
$this->assertResponse(404);
$this->drupalGet('devel/devel_entity_test_no_links/' . $this->entity_no_links->id() . '/definition');
$this->assertResponse(404);
}
}
@@ -1,159 +0,0 @@
<?php
namespace Drupal\devel\Tests;
use Drupal\Component\Render\FormattableMarkup;
use Drupal\simpletest\WebTestBase;
/**
* Tests pluggable dumper feature.
*
* @group devel
*/
class DevelDumperTest extends WebTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['devel', 'devel_dumper_test'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$admin_user = $this->drupalCreateUser(['administer site configuration', 'access devel information']);
$this->drupalLogin($admin_user);
}
/**
* Test dumpers configuration page.
*/
public function testDumpersConfiguration() {
$this->drupalGet('admin/config/development/devel');
// Ensures that the dumper input is present on the config page.
$this->assertFieldByName('dumper');
// Ensures that the 'default' dumper is enabled by default.
$this->assertFieldChecked('edit-dumper-default');
// Ensures that all dumpers declared by devel are present on the config page
// and that only the available dumpers are selectable.
$dumpers = ['default', 'drupal_variable', 'firephp', 'chromephp', 'var_dumper'];
$available_dumpers = ['default', 'drupal_variable'];
foreach ($dumpers as $dumper) {
$this->assertFieldByXPath('//input[@type="radio" and @name="dumper"]', $dumper, new FormattableMarkup('Radio button for @dumper found.', ['@dumper' => $dumper]));
if (in_array($dumper, $available_dumpers)) {
$this->assertFieldByXPath('//input[@name="dumper" and not(@disabled="disabled")]', $dumper, new FormattableMarkup('Dumper @dumper is available.', ['@dumper' => $dumper]));
}
else {
$this->assertFieldByXPath('//input[@name="dumper" and @disabled="disabled"]', $dumper, new FormattableMarkup('Dumper @dumper is disabled.', ['@dumper' => $dumper]));
}
}
// Ensures that dumper plugins declared by other modules are present on the
// config page and that only the available dumpers are selectable.
$this->assertFieldByName('dumper', 'available_test_dumper');
$this->assertText('Available test dumper.', 'Available dumper label is present');
$this->assertText('Drupal dumper for testing purposes (available).', 'Available dumper description is present');
$this->assertFieldByXPath('//input[@name="dumper" and not(@disabled="disabled")]', 'available_test_dumper', 'Available dumper input not is disabled.');
$this->assertFieldByName('dumper', 'not_available_test_dumper');
$this->assertText('Not available test dumper.', 'Non available dumper label is present');
$this->assertText('Drupal dumper for testing purposes (not available).Not available. You may need to install external dependencies for use this plugin.', 'Non available dumper description is present');
$this->assertFieldByXPath('//input[@name="dumper" and @disabled="disabled"]', 'not_available_test_dumper', 'Non available dumper input is disabled.');
// Ensures that saving of the dumpers configuration works as expected.
$edit = [
'dumper' => 'drupal_variable',
];
$this->drupalPostForm('admin/config/development/devel', $edit, t('Save configuration'));
$this->assertText(t('The configuration options have been saved.'));
$config = \Drupal::config('devel.settings')->get('devel_dumper');
$this->assertEqual('drupal_variable', $config, 'The configuration options have been properly saved');
// Ensure that if the chosen dumper is not available (e.g. the module that
// provide it is uninstalled) the 'default' dumper appears selected in the
// config page.
\Drupal::service('module_installer')->install(['kint']);
$this->drupalGet('admin/config/development/devel');
$this->assertFieldByName('dumper', 'kint');
$edit = [
'dumper' => 'kint',
];
$this->drupalPostForm('admin/config/development/devel', $edit, t('Save configuration'));
$this->assertText(t('The configuration options have been saved.'));
$config = \Drupal::config('devel.settings')->get('devel_dumper');
$this->assertEqual('kint', $config, 'The configuration options have been properly saved');
\Drupal::service('module_installer')->uninstall(['kint']);
$this->drupalGet('admin/config/development/devel');
$this->assertNoFieldByName('dumper', 'kint');
$this->assertFieldChecked('edit-dumper-default');
}
/**
* Test variable is dumped in page.
*/
function testDumpersOutput() {
$edit = [
'dumper' => 'available_test_dumper',
];
$this->drupalPostForm('admin/config/development/devel', $edit, t('Save configuration'));
$this->assertText(t('The configuration options have been saved.'));
$this->drupalGet('devel_dumper_test/dump');
$elements = $this->xpath('//body/pre[contains(text(), :message)]', [':message' => 'AvailableTestDumper::dump() Test output']);
$this->assertTrue(!empty($elements), 'Dumped message is present.');
$this->drupalGet('devel_dumper_test/message');
$elements = $this->xpath('//div[contains(@class, "messages")]/pre[contains(text(), :message)]', [':message' => 'AvailableTestDumper::export() Test output']);
$this->assertTrue(!empty($elements), 'Dumped message is present.');
$this->drupalGet('devel_dumper_test/export');
$elements = $this->xpath('//div[@class="layout-content"]//pre[contains(text(), :message)]', [':message' => 'AvailableTestDumper::export() Test output']);
$this->assertTrue(!empty($elements), 'Dumped message is present.');
$this->drupalGet('devel_dumper_test/export_renderable');
$elements = $this->xpath('//div[@class="layout-content"]//pre[contains(text(), :message)]', [':message' => 'AvailableTestDumper::exportAsRenderable() Test output']);
$this->assertTrue(!empty($elements), 'Dumped message is present.');
// Ensures that plugins can add libraries to the page when the
// ::exportAsRenderable() method is used.
$this->assertRaw('devel_dumper_test/css/devel_dumper_test.css');
$this->assertRaw('devel_dumper_test/js/devel_dumper_test.js');
$debug_filename = file_directory_temp() . '/drupal_debug.txt';
$this->drupalGet('devel_dumper_test/debug');
$file_content = file_get_contents($debug_filename);
$expected = <<<EOF
<pre>AvailableTestDumper::export() Test output</pre>
EOF;
$this->assertEqual($file_content, $expected, 'Dumped message is present.');
// Ensures that the DevelDumperManager::debug() is not access checked and
// that the dump is written in the debug file even if the user has not the
// 'access devel information' permission.
file_put_contents($debug_filename, '');
$this->drupalLogout();
$this->drupalGet('devel_dumper_test/debug');
$file_content = file_get_contents($debug_filename);
$expected = <<<EOF
<pre>AvailableTestDumper::export() Test output</pre>
EOF;
$this->assertEqual($file_content, $expected, 'Dumped message is present.');
}
}
@@ -1,109 +0,0 @@
<?php
namespace Drupal\devel\Tests;
use Drupal\Core\Url;
use Drupal\simpletest\WebTestBase;
/**
* Tests devel menu links.
*
* @group devel
*/
class DevelMenuLinksTest extends WebTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['devel', 'block', 'devel_test'];
/**
* The user for tests.
*
* @var \Drupal\user\UserInterface
*/
protected $develUser;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
// Devel links currently appears only in the devel menu.
// Place the devel menu block so we can ensure that these link works
// properly.
$this->drupalPlaceBlock('system_menu_block:devel');
$this->drupalPlaceBlock('page_title_block');
$this->develUser = $this->drupalCreateUser(['access devel information', 'administer site configuration']);
$this->drupalLogin($this->develUser);
}
/**
* Tests CSFR protected links.
*/
public function testCsrfProtectedLinks() {
// Ensure CSRF link are not accessible directly.
$this->drupalGet('devel/run-cron');
$this->assertResponse(403);
$this->drupalGet('devel/cache/clear');
$this->assertResponse(403);
// Ensure clear cache link works properly.
$this->assertLink('Cache clear');
$this->clickLink('Cache clear');
$this->assertText('Cache cleared.');
// Ensure run cron link works properly.
$this->assertLink('Run cron');
$this->clickLink('Run cron');
$this->assertText('Cron ran successfully.');
// Ensure CSRF protected links work properly after change session.
$this->drupalLogout();
$this->drupalLogin($this->develUser);
$this->assertLink('Cache clear');
$this->clickLink('Cache clear');
$this->assertText('Cache cleared.');
$this->assertLink('Run cron');
$this->clickLink('Run cron');
$this->assertText('Cron ran successfully.');
}
/**
* Tests redirect destination links.
*/
public function testRedirectDestinationLinks() {
// By default, in the testing profile, front page is the user canonical URI.
// For better testing do not use the default frontpage.
$url = Url::fromRoute('devel.simple_page');
$destination = Url::fromRoute('devel.simple_page', [], ['absolute' => FALSE]);
$this->drupalGet($url);
$this->assertLink(t('Reinstall Modules'));
$this->clickLink(t('Reinstall Modules'));
$this->assertUrl('devel/reinstall', ['query' => ['destination' => $destination->toString()]]);
$this->drupalGet($url);
$this->assertLink(t('Rebuild Menu'));
$this->clickLink(t('Rebuild Menu'));
$this->assertUrl('devel/menu/reset', ['query' => ['destination' => $destination->toString()]]);
$this->drupalGet($url);
$this->assertLink(t('Cache clear'));
$this->clickLink(t('Cache clear'));
$this->assertText('Cache cleared.');
$this->assertUrl($url);
$this->drupalGet($url);
$this->assertLink(t('Run cron'));
$this->clickLink(t('Run cron'));
$this->assertText(t('Cron ran successfully.'));
$this->assertUrl($url);
}
}
@@ -1,60 +0,0 @@
<?php
namespace Drupal\devel\Tests;
use Drupal\simpletest\WebTestBase;
/**
* Tests reinstall modules.
*
* @group devel
*/
class DevelReinstallTest extends WebTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('devel');
/**
* The profile to install as a basis for testing.
*
* @var string
*/
protected $profile = 'minimal';
/**
* Set up test.
*/
protected function setUp() {
parent::setUp();
$web_user = $this->drupalCreateUser(array('administer site configuration'));
$this->drupalLogin($web_user);
}
/**
* Reinstall modules.
*/
public function testDevelReinstallModules() {
// Minimal profile enables only dblog, block and node.
$modules = array('dblog', 'block');
// Needed for compare correctly the message.
sort($modules);
$this->drupalGet('devel/reinstall');
// Prepare field data in an associative array
$edit = array();
foreach ($modules as $module) {
$edit["reinstall[$module]"] = TRUE;
}
$this->drupalPostForm('devel/reinstall', $edit, t('Reinstall'));
$this->assertText(t('Uninstalled and installed: @names.', array('@names' => implode(', ', $modules))));
}
}
@@ -1,313 +0,0 @@
<?php
namespace Drupal\devel\Tests;
use Drupal\Component\Render\FormattableMarkup;
use Drupal\simpletest\WebTestBase;
/**
* Tests switch user.
*
* @group devel
*/
class DevelSwitchUserTest extends WebTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['devel', 'block'];
/**
* The block used by this test.
*
* @var \Drupal\block\BlockInterface
*/
protected $block;
/**
* The devel user.
*
* @var \Drupal\user\Entity\User
*/
protected $develUser;
/**
* The switch user.
*
* @var \Drupal\user\Entity\User
*/
protected $switchUser;
/**
* The web user.
*
* @var \Drupal\user\Entity\User
*/
protected $webUser;
/**
* Set up test.
*/
protected function setUp() {
parent::setUp();
$this->block = $this->drupalPlaceBlock('devel_switch_user', ['id' => 'switch-user']);
$this->develUser = $this->drupalCreateUser(['access devel information', 'switch users']);
$this->switchUser = $this->drupalCreateUser(['switch users']);
$this->webUser = $this->drupalCreateUser();
}
/**
* Tests switch user.
*/
public function testSwitchUser() {
$this->drupalLogin($this->webUser);
$this->drupalGet('');
$this->assertNoText($this->block->label(), 'Block title was not found.');
// Ensure that a token is required to switch user.
$this->drupalGet('/devel/switch/' . $this->webUser->getDisplayName());
$this->assertResponse(403);
$this->drupalLogin($this->develUser);
$this->drupalGet('');
$this->assertText($this->block->label(), 'Block title was found.');
// Ensure that if name in not passed the controller returns access denied.
$this->drupalGet('/devel/switch');
$this->assertResponse(403);
// Ensure that a token is required to switch user.
$this->drupalGet('/devel/switch/' . $this->switchUser->getDisplayName());
$this->assertResponse(403);
// Switch to another user account.
$this->drupalGet('/user/' . $this->switchUser->id());
$this->clickLink($this->switchUser->getDisplayName());
$this->assertSessionByUid($this->switchUser->id());
$this->assertNoSessionByUid($this->develUser->id());
// Switch back to initial account.
$this->clickLink($this->develUser->getDisplayName());
$this->assertNoSessionByUid($this->switchUser->id());
$this->assertSessionByUid($this->develUser->id());
// Use the search form to switch to another account.
$edit = ['userid' => $this->switchUser->getDisplayName()];
$this->drupalPostForm(NULL, $edit, t('Switch'));
$this->assertSessionByUid($this->switchUser->id());
$this->assertNoSessionByUid($this->develUser->id());
}
/**
* Tests the switch user block configuration.
*/
public function testSwitchUserBlockConfiguration() {
$anonymous = \Drupal::config('user.settings')->get('anonymous');
// Create some users for the test.
for ($i = 0; $i < 12; $i++) {
$this->drupalCreateUser();
}
$this->drupalLogin($this->develUser);
$this->drupalGet('');
$this->assertText($this->block->label(), 'Block title was found.');
// Ensure that block default configuration is effectively used. The block
// default configuration is the following:
// - list_size : 12
// - include_anon : FALSE
// - show_form : TRUE
$this->assertSwitchUserSearchForm();
$this->assertSwitchUserListCount(12);
$this->assertSwitchUserListNoContainsUser($anonymous);
// Ensure that changing the list_size configuration property the number of
// user displayed in the list change.
$this->setBlockConfiguration('list_size', 4);
$this->drupalGet('');
$this->assertSwitchUserListCount(4);
// Ensure that changing the include_anon configuration property the
// anonymous user is displayed in the list.
$this->setBlockConfiguration('include_anon', TRUE);
$this->drupalGet('');
$this->assertSwitchUserListContainsUser($anonymous);
// Ensure that changing the show_form configuration property the
// form is not displayed.
$this->setBlockConfiguration('show_form', FALSE);
$this->drupalGet('');
$this->assertSwitchUserNoSearchForm();
}
/**
* Test the user list items.
*/
public function testSwitchUserListItems() {
$anonymous = \Drupal::config('user.settings')->get('anonymous');
$this->setBlockConfiguration('list_size', 2);
// Login as web user so we are sure that this account is prioritized
// in the list if not enougth user with 'switch users' permission are
// present.
$this->drupalLogin($this->webUser);
$this->drupalLogin($this->develUser);
$this->drupalGet('');
// Ensure that user with 'switch users' permission are prioritized.
$this->assertSwitchUserListCount(2);
$this->assertSwitchUserListContainsUser($this->develUser->getDisplayName());
$this->assertSwitchUserListContainsUser($this->switchUser->getDisplayName());
// Ensure that blocked users are not shown in the list.
$this->switchUser->set('status', 0)->save();
$this->drupalGet('');
$this->assertSwitchUserListCount(2);
$this->assertSwitchUserListContainsUser($this->develUser->getDisplayName());
$this->assertSwitchUserListContainsUser($this->webUser->getDisplayName());
$this->assertSwitchUserListNoContainsUser($this->switchUser->getDisplayName());
// Ensure that anonymous user are prioritized if include_anon is set to true.
$this->setBlockConfiguration('include_anon', TRUE);
$this->drupalGet('');
$this->assertSwitchUserListCount(2);
$this->assertSwitchUserListContainsUser($this->develUser->getDisplayName());
$this->assertSwitchUserListContainsUser($anonymous);
// Ensure that the switch user block works properly even if no prioritized
// users are found (special handling for user 1).
$this->drupalLogout();
$this->develUser->delete();
$this->drupalLogin($this->rootUser);
$this->drupalGet('');
$this->assertSwitchUserListCount(2);
$this->assertSwitchUserListContainsUser($this->rootUser->getDisplayName());
$this->assertSwitchUserListContainsUser($anonymous);
// Ensure that the switch user block works properly even if no roles have
// the 'switch users' permission associated (special handling for user 1).
$roles = user_roles(TRUE, 'switch users');
\Drupal::entityTypeManager()->getStorage('user_role')->delete($roles);
$this->drupalGet('');
$this->assertSwitchUserListCount(2);
$this->assertSwitchUserListContainsUser($this->rootUser->getDisplayName());
$this->assertSwitchUserListContainsUser($anonymous);
}
/**
* Helper function for verify the number of items shown in the user list.
*
* @param int $number
* The expected numer of items.
*/
public function assertSwitchUserListCount($number) {
$result = $this->xpath('//div[@id=:block]//ul/li/a', [':block' => 'block-switch-user']);
$this->assert(count($result) == $number, 'The number of users shown in switch user is correct.');
}
/**
* Helper function for verify if the user list contains a username.
*
* @param string $username
* The username to check.
*/
public function assertSwitchUserListContainsUser($username) {
$result = $this->xpath('//div[@id=:block]//ul/li/a[normalize-space()=:user]', [':block' => 'block-switch-user', ':user' => $username]);
$this->assert(count($result) > 0, new FormattableMarkup('User "%user" is included in the switch user list.', ['%user' => $username]));
}
/**
* Helper function for verify if the user list not contains a username.
*
* @param string $username
* The username to check.
*/
public function assertSwitchUserListNoContainsUser($username) {
$result = $this->xpath('//div[@id=:block]//ul/li/a[normalize-space()=:user]', [':block' => 'block-switch-user', ':user' => $username]);
$this->assert(count($result) == 0, new FormattableMarkup('User "%user" is not included in the switch user list.', ['%user' => $username]));
}
/**
* Helper function for verify if the search form is shown.
*/
public function assertSwitchUserSearchForm() {
$result = $this->xpath('//div[@id=:block]//form[contains(@class, :form)]', [':block' => 'block-switch-user', ':form' => 'devel-switchuser-form']);
$this->assert(count($result) > 0, 'The search form is shown.');
}
/**
* Helper function for verify if the search form is not shown.
*/
public function assertSwitchUserNoSearchForm() {
$result = $this->xpath('//div[@id=:block]//form[contains(@class, :form)]', [':block' => 'block-switch-user', ':form' => 'devel-switchuser-form']);
$this->assert(count($result) == 0, 'The search form is not shown.');
}
/**
* Protected helper method to set the test block's configuration.
*/
protected function setBlockConfiguration($key, $value) {
$block = $this->block->getPlugin();
$block->setConfigurationValue($key, $value);
$this->block->save();
}
/**
* Asserts that there is a session for a given user ID.
*
* Based off masquarade module.
*
* @param int $uid
* The user ID for which to find a session record.
*
* TODO find a cleaner way to do this check.
*/
protected function assertSessionByUid($uid) {
$query = \Drupal::database()->select('sessions');
$query->fields('sessions', array('uid'));
$query->condition('uid', $uid);
$result = $query->execute()->fetchAll();
if (empty($result)) {
$this->fail(new FormattableMarkup('No session found for uid @uid', array('@uid' => $uid)));
}
elseif (count($result) > 1) {
// If there is more than one session, then that must be unexpected.
$this->fail("Found more than 1 session for uid $uid.");
}
else {
$this->pass("Found session for uid $uid.");
}
}
/**
* Asserts that no session exists for a given uid.
*
* Based off masquarade module.
*
* @param int $uid
* The user ID to assert.
*
* TODO find a cleaner way to do this check.
*/
protected function assertNoSessionByUid($uid) {
$query = \Drupal::database()->select('sessions');
$query->fields('sessions', array('uid'));
$query->condition('uid', $uid);
$result = $query->execute()->fetchAll();
$this->assert(empty($result), "No session for uid $uid found.");
}
}