updated core

This commit is contained in:
Bachir Soussi Chiadmi
2018-01-24 13:36:32 +01:00
parent cd7dea45a9
commit f9374cf96d
1997 changed files with 5175 additions and 127715 deletions
@@ -1,77 +0,0 @@
<?php
namespace Drupal\block\Tests;
use Drupal\simpletest\WebTestBase;
/**
* Tests the block system with admin themes.
*
* @group block
*/
class BlockAdminThemeTest extends WebTestBase {
/**
* Modules to install.
*
* @var array
*/
public static $modules = ['block', 'contextual'];
/**
* Check for the accessibility of the admin theme on the block admin page.
*/
public function testAdminTheme() {
// Create administrative user.
$admin_user = $this->drupalCreateUser(['administer blocks', 'administer themes']);
$this->drupalLogin($admin_user);
// Ensure that access to block admin page is denied when theme is not
// installed.
$this->drupalGet('admin/structure/block/list/bartik');
$this->assertResponse(403);
// Install admin theme and confirm that tab is accessible.
\Drupal::service('theme_handler')->install(['bartik']);
$edit['admin_theme'] = 'bartik';
$this->drupalPostForm('admin/appearance', $edit, t('Save configuration'));
$this->drupalGet('admin/structure/block/list/bartik');
$this->assertResponse(200);
}
/**
* Ensure contextual links are disabled in Seven theme.
*/
public function testSevenAdminTheme() {
// Create administrative user.
$admin_user = $this->drupalCreateUser([
'access administration pages',
'administer themes',
'access contextual links',
'view the administration theme',
]);
$this->drupalLogin($admin_user);
// Install admin theme and confirm that tab is accessible.
\Drupal::service('theme_handler')->install(['seven']);
$edit['admin_theme'] = 'seven';
$this->drupalPostForm('admin/appearance', $edit, t('Save configuration'));
// Define our block settings.
$settings = [
'theme' => 'seven',
'region' => 'header',
];
// Place a block.
$block = $this->drupalPlaceBlock('local_tasks_block', $settings);
// Open admin page.
$this->drupalGet('admin');
// Check if contextual link classes are unavailable.
$this->assertNoRaw('<div data-contextual-id="block:block=' . $block->id() . ':langcode=en"></div>');
$this->assertNoRaw('contextual-region');
}
}
@@ -1,215 +0,0 @@
<?php
namespace Drupal\block\Tests;
use Drupal\Core\Cache\Cache;
use Drupal\simpletest\WebTestBase;
/**
* Tests block caching.
*
* @group block
*/
class BlockCacheTest extends WebTestBase {
/**
* Modules to install.
*
* @var array
*/
public static $modules = array('block', 'block_test', 'test_page_test');
/**
* A user with permission to create and edit books and to administer blocks.
*
* @var object
*/
protected $adminUser;
/**
* An authenticated user to test block caching.
*
* @var object
*/
protected $normalUser;
/**
* Another authenticated user to test block caching.
*
* @var object
*/
protected $normalUserAlt;
/**
* The block used by this test.
*
* @var \Drupal\block\BlockInterface
*/
protected $block;
protected function setUp() {
parent::setUp();
// Create an admin user, log in and enable test blocks.
$this->adminUser = $this->drupalCreateUser(array('administer blocks', 'access administration pages'));
$this->drupalLogin($this->adminUser);
// Create additional users to test caching modes.
$this->normalUser = $this->drupalCreateUser();
$this->normalUserAlt = $this->drupalCreateUser();
// Sync the roles, since drupalCreateUser() creates separate roles for
// the same permission sets.
$this->normalUserAlt->roles = $this->normalUser->getRoles();
$this->normalUserAlt->save();
// Enable our test block.
$this->block = $this->drupalPlaceBlock('test_cache');
}
/**
* Test "user.roles" cache context.
*/
function testCachePerRole() {
\Drupal::state()->set('block_test.cache_contexts', ['user.roles']);
// Enable our test block. Set some content for it to display.
$current_content = $this->randomMachineName();
\Drupal::state()->set('block_test.content', $current_content);
$this->drupalLogin($this->normalUser);
$this->drupalGet('');
$this->assertText($current_content, 'Block content displays.');
// Change the content, but the cached copy should still be served.
$old_content = $current_content;
$current_content = $this->randomMachineName();
\Drupal::state()->set('block_test.content', $current_content);
$this->drupalGet('');
$this->assertText($old_content, 'Block is served from the cache.');
// Clear the cache and verify that the stale data is no longer there.
Cache::invalidateTags(array('block_view'));
$this->drupalGet('');
$this->assertNoText($old_content, 'Block cache clear removes stale cache data.');
$this->assertText($current_content, 'Fresh block content is displayed after clearing the cache.');
// Test whether the cached data is served for the correct users.
$old_content = $current_content;
$current_content = $this->randomMachineName();
\Drupal::state()->set('block_test.content', $current_content);
$this->drupalLogout();
$this->drupalGet('');
$this->assertNoText($old_content, 'Anonymous user does not see content cached per-role for normal user.');
$this->drupalLogin($this->normalUserAlt);
$this->drupalGet('');
$this->assertText($old_content, 'User with the same roles sees per-role cached content.');
$this->drupalLogin($this->adminUser);
$this->drupalGet('');
$this->assertNoText($old_content, 'Admin user does not see content cached per-role for normal user.');
$this->drupalLogin($this->normalUser);
$this->drupalGet('');
$this->assertText($old_content, 'Block is served from the per-role cache.');
}
/**
* Test a cacheable block without any additional cache context.
*/
function testCachePermissions() {
// user.permissions is a required context, so a user with different
// permissions will see a different version of the block.
\Drupal::state()->set('block_test.cache_contexts', []);
$current_content = $this->randomMachineName();
\Drupal::state()->set('block_test.content', $current_content);
$this->drupalGet('');
$this->assertText($current_content, 'Block content displays.');
$old_content = $current_content;
$current_content = $this->randomMachineName();
\Drupal::state()->set('block_test.content', $current_content);
$this->drupalGet('user');
$this->assertText($old_content, 'Block content served from cache.');
$this->drupalLogout();
$this->drupalGet('user');
$this->assertText($current_content, 'Block content not served from cache.');
}
/**
* Test non-cacheable block.
*/
function testNoCache() {
\Drupal::state()->set('block_test.cache_max_age', 0);
$current_content = $this->randomMachineName();
\Drupal::state()->set('block_test.content', $current_content);
// If max_age = 0 has no effect, the next request would be cached.
$this->drupalGet('');
$this->assertText($current_content, 'Block content displays.');
// A cached copy should not be served.
$current_content = $this->randomMachineName();
\Drupal::state()->set('block_test.content', $current_content);
$this->drupalGet('');
$this->assertText($current_content, 'Maximum age of zero prevents blocks from being cached.');
}
/**
* Test "user" cache context.
*/
function testCachePerUser() {
\Drupal::state()->set('block_test.cache_contexts', ['user']);
$current_content = $this->randomMachineName();
\Drupal::state()->set('block_test.content', $current_content);
$this->drupalLogin($this->normalUser);
$this->drupalGet('');
$this->assertText($current_content, 'Block content displays.');
$old_content = $current_content;
$current_content = $this->randomMachineName();
\Drupal::state()->set('block_test.content', $current_content);
$this->drupalGet('');
$this->assertText($old_content, 'Block is served from per-user cache.');
$this->drupalLogin($this->normalUserAlt);
$this->drupalGet('');
$this->assertText($current_content, 'Per-user block cache is not served for other users.');
$this->drupalLogin($this->normalUser);
$this->drupalGet('');
$this->assertText($old_content, 'Per-user block cache is persistent.');
}
/**
* Test "url" cache context.
*/
function testCachePerPage() {
\Drupal::state()->set('block_test.cache_contexts', ['url']);
$current_content = $this->randomMachineName();
\Drupal::state()->set('block_test.content', $current_content);
$this->drupalGet('test-page');
$this->assertText($current_content, 'Block content displays on the test page.');
$old_content = $current_content;
$current_content = $this->randomMachineName();
\Drupal::state()->set('block_test.content', $current_content);
$this->drupalGet('user');
$this->assertResponse(200);
$this->assertNoText($old_content, 'Block content cached for the test page does not show up for the user page.');
$this->drupalGet('test-page');
$this->assertResponse(200);
$this->assertText($old_content, 'Block content cached for the test page.');
}
}
@@ -1,73 +0,0 @@
<?php
namespace Drupal\block\Tests;
use Drupal\Component\Utility\Crypt;
use Drupal\simpletest\WebTestBase;
/**
* Tests form in block caching.
*
* @group block
*/
class BlockFormInBlockTest extends WebTestBase {
/**
* Modules to install.
*
* @var array
*/
public static $modules = ['block', 'block_test', 'test_page_test'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
// Enable our test block.
$this->drupalPlaceBlock('test_form_in_block');
}
/**
* Test to see if form in block's redirect isn't cached.
*/
public function testCachePerPage() {
$form_values = ['email' => 'test@example.com'];
// Go to "test-page" and test if the block is enabled.
$this->drupalGet('test-page');
$this->assertResponse(200);
$this->assertText('Your .com email address.', 'form found');
// Make sure that we're currently still on /test-page after submitting the
// form.
$this->drupalPostForm(NULL, $form_values, t('Submit'));
$this->assertUrl('test-page');
$this->assertText(t('Your email address is @email', ['@email' => 'test@example.com']));
// Go to a different page and see if the block is enabled there as well.
$this->drupalGet('test-render-title');
$this->assertResponse(200);
$this->assertText('Your .com email address.', 'form found');
// Make sure that submitting the form didn't redirect us to the first page
// we submitted the form from after submitting the form from
// /test-render-title.
$this->drupalPostForm(NULL, $form_values, t('Submit'));
$this->assertUrl('test-render-title');
$this->assertText(t('Your email address is @email', ['@email' => 'test@example.com']));
}
/**
* Test the actual placeholders
*/
public function testPlaceholders() {
$this->drupalGet('test-multiple-forms');
$placeholder = 'form_action_' . Crypt::hashBase64('Drupal\Core\Form\FormBuilder::prepareForm');
$this->assertText('Form action: ' . $placeholder, 'placeholder found.');
}
}
@@ -1,73 +0,0 @@
<?php
namespace Drupal\block\Tests;
use Drupal\simpletest\WebTestBase;
/**
* Tests that a newly installed theme does not inherit blocks to its hidden
* regions.
*
* @group block
*/
class BlockHiddenRegionTest extends WebTestBase {
/**
* An administrative user to configure the test environment.
*/
protected $adminUser;
/**
* Modules to install.
*
* @var array
*/
public static $modules = array('block', 'block_test', 'search');
protected function setUp() {
parent::setUp();
// Create administrative user.
$this->adminUser = $this->drupalCreateUser(array(
'administer blocks',
'administer themes',
'search content',
)
);
$this->drupalLogin($this->adminUser);
$this->drupalPlaceBlock('search_form_block');
$this->drupalPlaceBlock('local_tasks_block');
}
/**
* Tests that hidden regions do not inherit blocks when a theme is installed.
*/
public function testBlockNotInHiddenRegion() {
// Ensure that the search form block is displayed.
$this->drupalGet('');
$this->assertText('Search', 'Block was displayed on the front page.');
// Install "block_test_theme" and set it as the default theme.
$theme = 'block_test_theme';
// We need to install a non-hidden theme so that there is more than one
// local task.
\Drupal::service('theme_handler')->install(array($theme, 'stark'));
$this->config('system.theme')
->set('default', $theme)
->save();
// Installing a theme will cause the kernel terminate event to rebuild the
// router. Simulate that here.
\Drupal::service('router.builder')->rebuildIfNeeded();
// Ensure that "block_test_theme" is set as the default theme.
$this->drupalGet('admin/structure/block');
$this->assertText('Block test theme(' . t('active tab') . ')', 'Default local task on blocks admin page is the block test theme.');
// Ensure that the search form block is displayed.
$this->drupalGet('');
$this->assertText('Search', 'Block was displayed on the front page.');
}
}
@@ -1,51 +0,0 @@
<?php
namespace Drupal\block\Tests;
use Drupal\Component\Utility\Unicode;
use Drupal\simpletest\WebTestBase;
/**
* Tests for Block module regarding hook_entity_operations_alter().
*
* @group block
*/
class BlockHookOperationTest extends WebTestBase {
/**
* Modules to install.
*
* @var array
*/
public static $modules = array('block', 'entity_test');
protected function setUp() {
parent::setUp();
$permissions = array(
'administer blocks',
);
// Create and log in user.
$admin_user = $this->drupalCreateUser($permissions);
$this->drupalLogin($admin_user);
}
/**
* Tests the block list to see if the test_operation link is added.
*/
public function testBlockOperationAlter() {
// Add a test block, any block will do.
// Set the machine name so the test_operation link can be built later.
$block_id = Unicode::strtolower($this->randomMachineName(16));
$this->drupalPlaceBlock('system_powered_by_block', array('id' => $block_id));
// Get the Block listing.
$this->drupalGet('admin/structure/block');
$test_operation_link = 'admin/structure/block/manage/' . $block_id . '/test_operation';
// Test if the test_operation link is on the page.
$this->assertLinkByHref($test_operation_link);
}
}
@@ -1,50 +0,0 @@
<?php
namespace Drupal\block\Tests;
use Drupal\simpletest\WebTestBase;
/**
* Tests block HTML ID validity.
*
* @group block
*/
class BlockHtmlTest extends WebTestBase {
/**
* Modules to install.
*
* @var array
*/
public static $modules = array('block', 'block_test');
protected function setUp() {
parent::setUp();
$this->drupalLogin($this->rootUser);
// Enable the test_html block, to test HTML ID and attributes.
\Drupal::state()->set('block_test.attributes', array('data-custom-attribute' => 'foo'));
\Drupal::state()->set('block_test.content', $this->randomMachineName());
$this->drupalPlaceBlock('test_html', array('id' => 'test_html_block'));
// Enable a menu block, to test more complicated HTML.
$this->drupalPlaceBlock('system_menu_block:admin');
}
/**
* Tests for valid HTML for a block.
*/
function testHtml() {
$this->drupalGet('');
// Ensure that a block's ID is converted to an HTML valid ID, and that
// block-specific attributes are added to the same DOM element.
$this->assertFieldByXPath('//div[@id="block-test-html-block" and @data-custom-attribute="foo"]', NULL, 'HTML ID and attributes for test block are valid and on the same DOM element.');
// Ensure expected markup for a menu block.
$elements = $this->xpath('//nav[contains(@class, :nav-class)]/ul[contains(@class, :ul-class)]/li', array(':nav-class' => 'block-menu', ':ul-class' => 'menu'));
$this->assertTrue(!empty($elements), 'The proper block markup was found.');
}
}
@@ -1,33 +0,0 @@
<?php
namespace Drupal\block\Tests;
use Drupal\simpletest\WebTestBase;
/**
* Tests block module's installation.
*
* @group block
*/
class BlockInstallTest extends WebTestBase {
public function testCacheTagInvalidationUponInstallation() {
// Warm the page cache.
$this->drupalGet('');
$this->assertNoText('Powered by Drupal');
$this->assertNoCacheTag('config:block_list');
// Install the block module, and place the "Powered by Drupal" block.
$this->container->get('module_installer')->install(['block', 'shortcut']);
$this->rebuildContainer();
$this->container->get('router.builder')->rebuild();
$this->drupalPlaceBlock('system_powered_by_block');
// Check the same page, block.module's hook_install() should have
// invalidated the 'rendered' cache tag to make blocks show up.
$this->drupalGet('');
$this->assertCacheTag('config:block_list');
$this->assertText('Powered by Drupal');
}
}
@@ -1,63 +0,0 @@
<?php
namespace Drupal\block\Tests;
use Drupal\simpletest\WebTestBase;
use Drupal\block\Entity\Block;
/**
* Tests that an active block assigned to a non-existing region triggers the
* warning message and is disabled.
*
* @group block
*/
class BlockInvalidRegionTest extends WebTestBase {
/**
* Modules to install.
*
* @var array
*/
public static $modules = array('block', 'block_test');
protected function setUp() {
parent::setUp();
// Create an admin user.
$admin_user = $this->drupalCreateUser(array(
'administer site configuration',
'access administration pages',
'administer blocks',
));
$this->drupalLogin($admin_user);
}
/**
* Tests that blocks assigned to invalid regions work correctly.
*/
function testBlockInInvalidRegion() {
// Enable a test block and place it in an invalid region.
$block = $this->drupalPlaceBlock('test_html');
$block->setRegion('invalid_region');
$block->save();
$warning_message = t('The block %info was assigned to the invalid region %region and has been disabled.', array('%info' => $block->id(), '%region' => 'invalid_region'));
// Clearing the cache should disable the test block placed in the invalid region.
$this->drupalPostForm('admin/config/development/performance', array(), 'Clear all caches');
$this->assertRaw($warning_message, 'Enabled block was in the invalid region and has been disabled.');
// Clear the cache to check if the warning message is not triggered.
$this->drupalPostForm('admin/config/development/performance', array(), 'Clear all caches');
$this->assertNoRaw($warning_message, 'Disabled block in the invalid region will not trigger the warning.');
// Place disabled test block in the invalid region of the default theme.
$block = Block::load($block->id());
$block->setRegion('invalid_region');
$block->save();
// Clear the cache to check if the warning message is not triggered.
$this->drupalPostForm('admin/config/development/performance', array(), 'Clear all caches');
$this->assertNoRaw($warning_message, 'Disabled block in the invalid region will not trigger the warning.');
}
}
@@ -1,77 +0,0 @@
<?php
namespace Drupal\block\Tests;
use Drupal\Component\Utility\Unicode;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\simpletest\WebTestBase;
/**
* Tests display of menu blocks with multiple languages.
*
* @group block
*/
class BlockLanguageCacheTest extends WebTestBase {
/**
* Modules to install.
*
* @var array
*/
public static $modules = ['block', 'language', 'menu_ui'];
/**
* List of langcodes.
*
* @var array
*/
protected $langcodes = [];
protected function setUp() {
parent::setUp();
// Create test languages.
$this->langcodes = [ConfigurableLanguage::load('en')];
for ($i = 1; $i < 3; ++$i) {
$language = ConfigurableLanguage::create([
'id' => 'l' . $i,
'label' => $this->randomString(),
]);
$language->save();
$this->langcodes[$i] = $language;
}
}
/**
* Creates a block in a language, check blocks page in all languages.
*/
public function testBlockLinks() {
// Create admin user to be able to access block admin.
$admin_user = $this->drupalCreateUser([
'administer blocks',
'access administration pages',
'administer menu',
]);
$this->drupalLogin($admin_user);
// Create the block cache for all languages.
foreach ($this->langcodes as $langcode) {
$this->drupalGet('admin/structure/block', ['language' => $langcode]);
$this->clickLinkPartialName('Place block');
}
// Create a menu in the default language.
$edit['label'] = $this->randomMachineName();
$edit['id'] = Unicode::strtolower($edit['label']);
$this->drupalPostForm('admin/structure/menu/add', $edit, t('Save'));
$this->assertText(t('Menu @label has been added.', ['@label' => $edit['label']]));
// Check that the block is listed for all languages.
foreach ($this->langcodes as $langcode) {
$this->drupalGet('admin/structure/block', ['language' => $langcode]);
$this->clickLinkPartialName('Place block');
$this->assertText($edit['label']);
}
}
}
@@ -1,185 +0,0 @@
<?php
namespace Drupal\block\Tests;
use Drupal\simpletest\WebTestBase;
use Drupal\block\Entity\Block;
/**
* Tests if a block can be configured to be only visible on a particular
* language.
*
* @group block
*/
class BlockLanguageTest extends WebTestBase {
/**
* An administrative user to configure the test environment.
*/
protected $adminUser;
/**
* Modules to install.
*
* @var array
*/
public static $modules = array('language', 'block', 'content_translation');
protected function setUp() {
parent::setUp();
// Create a new user, allow him to manage the blocks and the languages.
$this->adminUser = $this->drupalCreateUser(array('administer blocks', 'administer languages'));
$this->drupalLogin($this->adminUser);
// Add predefined language.
$edit = array(
'predefined_langcode' => 'fr',
);
$this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add language'));
$this->assertText('French', 'Language added successfully.');
}
/**
* Tests the visibility settings for the blocks based on language.
*/
public function testLanguageBlockVisibility() {
// Check if the visibility setting is available.
$default_theme = $this->config('system.theme')->get('default');
$this->drupalGet('admin/structure/block/add/system_powered_by_block' . '/' . $default_theme);
$this->assertField('visibility[language][langcodes][en]', 'Language visibility field is visible.');
$this->assertNoField('visibility[language][context_mapping][language]', 'Language type field is not visible.');
// Enable a standard block and set the visibility setting for one language.
$edit = array(
'visibility[language][langcodes][en]' => TRUE,
'id' => strtolower($this->randomMachineName(8)),
'region' => 'sidebar_first',
);
$this->drupalPostForm('admin/structure/block/add/system_powered_by_block' . '/' . $default_theme, $edit, t('Save block'));
// Change the default language.
$edit = array(
'site_default_language' => 'fr',
);
$this->drupalPostForm('admin/config/regional/language', $edit, t('Save configuration'));
// Check that a page has a block.
$this->drupalGet('en');
$this->assertText('Powered by Drupal', 'The body of the custom block appears on the page.');
// Check that a page doesn't has a block for the current language anymore.
$this->drupalGet('fr');
$this->assertNoText('Powered by Drupal', 'The body of the custom block does not appear on the page.');
}
/**
* Tests if the visibility settings are removed if the language is deleted.
*/
public function testLanguageBlockVisibilityLanguageDelete() {
// Enable a standard block and set the visibility setting for one language.
$edit = array(
'visibility' => array(
'language' => array(
'langcodes' => array(
'fr' => 'fr',
),
'context_mapping' => ['language' => '@language.current_language_context:language_interface'],
),
),
);
$block = $this->drupalPlaceBlock('system_powered_by_block', $edit);
// Check that we have the language in config after saving the setting.
$visibility = $block->getVisibility();
$this->assertEqual('fr', $visibility['language']['langcodes']['fr'], 'Language is set in the block configuration.');
// Delete the language.
$this->drupalPostForm('admin/config/regional/language/delete/fr', array(), t('Delete'));
// Check that the language is no longer stored in the configuration after
// it is deleted.
$block = Block::load($block->id());
$visibility = $block->getVisibility();
$this->assertTrue(empty($visibility['language']['langcodes']['fr']), 'Language is no longer not set in the block configuration after deleting the block.');
// Ensure that the block visibility for language is gone from the UI.
$this->drupalGet('admin/structure/block');
$this->clickLink('Configure');
$elements = $this->xpath('//details[@id="edit-visibility-language"]');
$this->assertTrue(empty($elements));
}
/**
* Tests block language visibility with different language types.
*/
public function testMultipleLanguageTypes() {
// Customize content language detection to be different from interface
// language detection.
$edit = [
// Interface language detection: only using session.
'language_interface[enabled][language-url]' => FALSE,
'language_interface[enabled][language-session]' => TRUE,
// Content language detection: only using URL.
'language_content[configurable]' => TRUE,
'language_content[enabled][language-url]' => TRUE,
'language_content[enabled][language-interface]' => FALSE,
];
$this->drupalPostForm('admin/config/regional/language/detection', $edit, t('Save settings'));
// Check if the visibility setting is available with a type setting.
$default_theme = $this->config('system.theme')->get('default');
$this->drupalGet('admin/structure/block/add/system_powered_by_block' . '/' . $default_theme);
$this->assertField('visibility[language][langcodes][en]', 'Language visibility field is visible.');
$this->assertField('visibility[language][context_mapping][language]', 'Language type field is visible.');
// Enable a standard block and set visibility to French only.
$block_id = strtolower($this->randomMachineName(8));
$edit = [
'visibility[language][context_mapping][language]' => '@language.current_language_context:language_interface',
'visibility[language][langcodes][fr]' => TRUE,
'id' => $block_id,
'region' => 'sidebar_first',
];
$this->drupalPostForm('admin/structure/block/add/system_powered_by_block' . '/' . $default_theme, $edit, t('Save block'));
// Interface negotiation depends on request arguments.
$this->drupalGet('node', ['query' => ['language' => 'en']]);
$this->assertNoText('Powered by Drupal', 'The body of the block does not appear on the page.');
$this->drupalGet('node', ['query' => ['language' => 'fr']]);
$this->assertText('Powered by Drupal', 'The body of the block appears on the page.');
// Log in again in order to clear the interface language stored in the
// session.
$this->drupalLogout();
$this->drupalLogin($this->adminUser);
// Content language does not depend on session/request arguments.
// It will fall back on English (site default) and not display the block.
$this->drupalGet('en');
$this->assertNoText('Powered by Drupal', 'The body of the block does not appear on the page.');
$this->drupalGet('fr');
$this->assertNoText('Powered by Drupal', 'The body of the block does not appear on the page.');
// Change visibility to now depend on content language for this block.
$edit = [
'visibility[language][context_mapping][language]' => '@language.current_language_context:language_content'
];
$this->drupalPostForm('admin/structure/block/manage/' . $block_id, $edit, t('Save block'));
// Content language negotiation does not depend on request arguments.
// It will fall back on English (site default) and not display the block.
$this->drupalGet('node', ['query' => ['language' => 'en']]);
$this->assertNoText('Powered by Drupal', 'The body of the block does not appear on the page.');
$this->drupalGet('node', ['query' => ['language' => 'fr']]);
$this->assertNoText('Powered by Drupal', 'The body of the block does not appear on the page.');
// Content language negotiation depends on path prefix.
$this->drupalGet('en');
$this->assertNoText('Powered by Drupal', 'The body of the block does not appear on the page.');
$this->drupalGet('fr');
$this->assertText('Powered by Drupal', 'The body of the block appears on the page.');
}
}
@@ -1,80 +0,0 @@
<?php
namespace Drupal\block\Tests;
use Drupal\Component\Utility\Html;
use Drupal\simpletest\WebTestBase;
/**
* Tests blocks are being rendered in order by weight.
*
* @group block
*/
class BlockRenderOrderTest extends WebTestBase {
/**
* Modules to install.
*
* @var array
*/
public static $modules = ['node', 'block'];
protected function setUp() {
parent::setUp();
// Create a test user.
$end_user = $this->drupalCreateUser([
'access content',
]);
$this->drupalLogin($end_user);
}
/**
* Tests the render order of the blocks.
*/
public function testBlockRenderOrder() {
// Enable test blocks and place them in the same region.
$region = 'header';
$test_blocks = [
'stark_powered' => [
'weight' => '-3',
'id' => 'stark_powered',
'label' => 'Test block A',
],
'stark_by' => [
'weight' => '3',
'id' => 'stark_by',
'label' => 'Test block C',
],
'stark_drupal' => [
'weight' => '3',
'id' => 'stark_drupal',
'label' => 'Test block B',
],
];
// Place the test blocks.
foreach ($test_blocks as $test_block) {
$this->drupalPlaceBlock('system_powered_by_block', [
'label' => $test_block['label'],
'region' => $region,
'weight' => $test_block['weight'],
'id' => $test_block['id'],
]);
}
$this->drupalGet('');
$test_content = $this->getRawContent('');
$controller = $this->container->get('entity_type.manager')->getStorage('block');
foreach ($controller->loadMultiple() as $return_block) {
$id = $return_block->id();
if ($return_block_weight = $return_block->getWeight()) {
$this->assertTrue($test_blocks[$id]['weight'] == $return_block_weight, 'Block weight is set as "' . $return_block_weight . '" for ' . $id . ' block.');
$position[$id] = strpos($test_content, Html::getClass('block-' . $test_blocks[$id]['id']));
}
}
$this->assertTrue($position['stark_powered'] < $position['stark_by'], 'Blocks with different weight are rendered in the correct order.');
$this->assertTrue($position['stark_drupal'] < $position['stark_by'], 'Blocks with identical weight are rendered in alphabetical order.');
}
}
@@ -1,119 +0,0 @@
<?php
namespace Drupal\block\Tests;
/**
* Tests branding block display.
*
* @group block
*/
class BlockSystemBrandingTest extends BlockTestBase {
/**
* Modules to install.
*
* @var array
*/
public static $modules = ['block', 'system'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
// Set a site slogan.
$this->config('system.site')
->set('slogan', 'Community plumbing')
->save();
// Add the system branding block to the page.
$this->drupalPlaceBlock('system_branding_block', ['region' => 'header', 'id' => 'site-branding']);
}
/**
* Tests system branding block configuration.
*/
public function testSystemBrandingSettings() {
$site_logo_xpath = '//div[@id="block-site-branding"]//a[@class="site-logo"]';
$site_name_xpath = '//div[@id="block-site-branding"]//div[@class="site-name"]';
$site_slogan_xpath = '//div[@id="block-site-branding"]//div[@class="site-slogan"]';
// Set default block settings.
$this->drupalGet('');
$site_logo_element = $this->xpath($site_logo_xpath);
$site_name_element = $this->xpath($site_name_xpath);
$site_slogan_element = $this->xpath($site_slogan_xpath);
// Test that all branding elements are displayed.
$this->assertTrue(!empty($site_logo_element), 'The branding block logo was found.');
$this->assertTrue(!empty($site_name_element), 'The branding block site name was found.');
$this->assertTrue(!empty($site_slogan_element), 'The branding block slogan was found.');
$this->assertCacheTag('config:system.site');
// Be sure the slogan is XSS-filtered.
$this->config('system.site')
->set('slogan', '<script>alert("Community carpentry");</script>')
->save();
$this->drupalGet('');
$site_slogan_element = $this->xpath($site_slogan_xpath);
$this->assertEqual($site_slogan_element[0], 'alert("Community carpentry");', 'The site slogan was XSS-filtered.');
// Turn just the logo off.
$this->config('block.block.site-branding')
->set('settings.use_site_logo', 0)
->save();
$this->drupalGet('');
$site_logo_element = $this->xpath($site_logo_xpath);
$site_name_element = $this->xpath($site_name_xpath);
$site_slogan_element = $this->xpath($site_slogan_xpath);
// Re-test all branding elements.
$this->assertTrue(empty($site_logo_element), 'The branding block logo was disabled.');
$this->assertTrue(!empty($site_name_element), 'The branding block site name was found.');
$this->assertTrue(!empty($site_slogan_element), 'The branding block slogan was found.');
$this->assertCacheTag('config:system.site');
// Turn just the site name off.
$this->config('block.block.site-branding')
->set('settings.use_site_logo', 1)
->set('settings.use_site_name', 0)
->save();
$this->drupalGet('');
$site_logo_element = $this->xpath($site_logo_xpath);
$site_name_element = $this->xpath($site_name_xpath);
$site_slogan_element = $this->xpath($site_slogan_xpath);
// Re-test all branding elements.
$this->assertTrue(!empty($site_logo_element), 'The branding block logo was found.');
$this->assertTrue(empty($site_name_element), 'The branding block site name was disabled.');
$this->assertTrue(!empty($site_slogan_element), 'The branding block slogan was found.');
$this->assertCacheTag('config:system.site');
// Turn just the site slogan off.
$this->config('block.block.site-branding')
->set('settings.use_site_name', 1)
->set('settings.use_site_slogan', 0)
->save();
$this->drupalGet('');
$site_logo_element = $this->xpath($site_logo_xpath);
$site_name_element = $this->xpath($site_name_xpath);
$site_slogan_element = $this->xpath($site_slogan_xpath);
// Re-test all branding elements.
$this->assertTrue(!empty($site_logo_element), 'The branding block logo was found.');
$this->assertTrue(!empty($site_name_element), 'The branding block site name was found.');
$this->assertTrue(empty($site_slogan_element), 'The branding block slogan was disabled.');
$this->assertCacheTag('config:system.site');
// Turn the site name and the site slogan off.
$this->config('block.block.site-branding')
->set('settings.use_site_name', 0)
->set('settings.use_site_slogan', 0)
->save();
$this->drupalGet('');
$site_logo_element = $this->xpath($site_logo_xpath);
$site_name_element = $this->xpath($site_name_xpath);
$site_slogan_element = $this->xpath($site_slogan_xpath);
// Re-test all branding elements.
$this->assertTrue(!empty($site_logo_element), 'The branding block logo was found.');
$this->assertTrue(empty($site_name_element), 'The branding block site name was disabled.');
$this->assertTrue(empty($site_slogan_element), 'The branding block slogan was disabled.');
$this->assertCacheTag('config:system.site');
}
}
@@ -1,48 +0,0 @@
<?php
namespace Drupal\block\Tests;
use Drupal\block\Entity\Block;
use Drupal\simpletest\WebTestBase;
/**
* Tests the block_theme_suggestions_block() function.
*
* @group block
*/
class BlockTemplateSuggestionsTest extends WebTestBase {
/**
* Modules to install.
*
* @var array
*/
public static $modules = array('block');
/**
* Tests template suggestions from block_theme_suggestions_block().
*/
function testBlockThemeHookSuggestions() {
// Define a block with a derivative to be preprocessed, which includes both
// an underscore (not transformed) and a hyphen (transformed to underscore),
// and generates possibilities for each level of derivative.
// @todo Clarify this comment.
$block = Block::create(array(
'plugin' => 'system_menu_block:admin',
'region' => 'footer',
'id' => 'machinename',
));
$variables = array();
$plugin = $block->getPlugin();
$variables['elements']['#configuration'] = $plugin->getConfiguration();
$variables['elements']['#plugin_id'] = $plugin->getPluginId();
$variables['elements']['#id'] = $block->id();
$variables['elements']['#base_plugin_id'] = $plugin->getBaseId();
$variables['elements']['#derivative_plugin_id'] = $plugin->getDerivativeId();
$variables['elements']['content'] = array();
$suggestions = block_theme_suggestions_block($variables);
$this->assertEqual($suggestions, array('block__system', 'block__system_menu_block', 'block__system_menu_block__admin', 'block__machinename'));
}
}
-551
View File
@@ -1,551 +0,0 @@
<?php
namespace Drupal\block\Tests;
use Drupal\Component\Utility\Html;
use Drupal\block\Entity\Block;
use Drupal\Core\Url;
use Drupal\user\Entity\Role;
use Drupal\user\RoleInterface;
/**
* Tests basic block functionality.
*
* @group block
*/
class BlockTest extends BlockTestBase {
/**
* Tests block visibility.
*/
public function testBlockVisibility() {
$block_name = 'system_powered_by_block';
// Create a random title for the block.
$title = $this->randomMachineName(8);
// Enable a standard block.
$default_theme = $this->config('system.theme')->get('default');
$edit = [
'id' => strtolower($this->randomMachineName(8)),
'region' => 'sidebar_first',
'settings[label]' => $title,
'settings[label_display]' => TRUE,
];
// Set the block to be hidden on any user path, and to be shown only to
// authenticated users.
$edit['visibility[request_path][pages]'] = '/user*';
$edit['visibility[request_path][negate]'] = TRUE;
$edit['visibility[user_role][roles][' . RoleInterface::AUTHENTICATED_ID . ']'] = TRUE;
$this->drupalGet('admin/structure/block/add/' . $block_name . '/' . $default_theme);
$this->assertFieldChecked('edit-visibility-request-path-negate-0');
$this->drupalPostForm(NULL, $edit, t('Save block'));
$this->assertText('The block configuration has been saved.', 'Block was saved');
$this->clickLink('Configure');
$this->assertFieldChecked('edit-visibility-request-path-negate-1');
$this->drupalGet('');
$this->assertText($title, 'Block was displayed on the front page.');
$this->drupalGet('user');
$this->assertNoText($title, 'Block was not displayed according to block visibility rules.');
// Confirm that the block is not displayed to anonymous users.
$this->drupalLogout();
$this->drupalGet('');
$this->assertNoText($title, 'Block was not displayed to anonymous users.');
// Confirm that an empty block is not displayed.
$this->assertNoText('Powered by Drupal', 'Empty block not displayed.');
$this->assertNoRaw('sidebar-first', 'Empty sidebar-first region is not displayed.');
}
/**
* Tests that visibility can be properly toggled.
*/
public function testBlockToggleVisibility() {
$block_name = 'system_powered_by_block';
// Create a random title for the block.
$title = $this->randomMachineName(8);
// Enable a standard block.
$default_theme = $this->config('system.theme')->get('default');
$edit = [
'id' => strtolower($this->randomMachineName(8)),
'region' => 'sidebar_first',
'settings[label]' => $title,
];
$block_id = $edit['id'];
// Set the block to be shown only to authenticated users.
$edit['visibility[user_role][roles][' . RoleInterface::AUTHENTICATED_ID . ']'] = TRUE;
$this->drupalPostForm('admin/structure/block/add/' . $block_name . '/' . $default_theme, $edit, t('Save block'));
$this->clickLink('Configure');
$this->assertFieldChecked('edit-visibility-user-role-roles-authenticated');
$edit = [
'visibility[user_role][roles][' . RoleInterface::AUTHENTICATED_ID . ']' => FALSE,
];
$this->drupalPostForm(NULL, $edit, 'Save block');
$this->clickLink('Configure');
$this->assertNoFieldChecked('edit-visibility-user-role-roles-authenticated');
// Ensure that no visibility is configured.
/** @var \Drupal\block\BlockInterface $block */
$block = Block::load($block_id);
$visibility_config = $block->getVisibilityConditions()->getConfiguration();
$this->assertIdentical([], $visibility_config);
$this->assertIdentical([], $block->get('visibility'));
}
/**
* Test block visibility when leaving "pages" textarea empty.
*/
public function testBlockVisibilityListedEmpty() {
$block_name = 'system_powered_by_block';
// Create a random title for the block.
$title = $this->randomMachineName(8);
// Enable a standard block.
$default_theme = $this->config('system.theme')->get('default');
$edit = [
'id' => strtolower($this->randomMachineName(8)),
'region' => 'sidebar_first',
'settings[label]' => $title,
'visibility[request_path][negate]' => TRUE,
];
// Set the block to be hidden on any user path, and to be shown only to
// authenticated users.
$this->drupalPostForm('admin/structure/block/add/' . $block_name . '/' . $default_theme, $edit, t('Save block'));
$this->assertText('The block configuration has been saved.', 'Block was saved');
$this->drupalGet('user');
$this->assertNoText($title, 'Block was not displayed according to block visibility rules.');
$this->drupalGet('USER');
$this->assertNoText($title, 'Block was not displayed according to block visibility rules regardless of path case.');
// Confirm that the block is not displayed to anonymous users.
$this->drupalLogout();
$this->drupalGet('');
$this->assertNoText($title, 'Block was not displayed to anonymous users on the front page.');
}
/**
* Tests adding a block from the library page with a weight query string.
*/
public function testAddBlockFromLibraryWithWeight() {
$default_theme = $this->config('system.theme')->get('default');
// Test one positive, zero, and one negative weight.
foreach (['7', '0', '-9'] as $weight) {
$options = [
'query' => [
'region' => 'sidebar_first',
'weight' => $weight,
],
];
$this->drupalGet(Url::fromRoute('block.admin_library', ['theme' => $default_theme], $options));
$block_name = 'system_powered_by_block';
$add_url = Url::fromRoute('block.admin_add', [
'plugin_id' => $block_name,
'theme' => $default_theme
]);
$links = $this->xpath('//a[contains(@href, :href)]', [':href' => $add_url->toString()]);
$this->assertEqual(1, count($links), 'Found one matching link.');
$this->assertEqual(t('Place block'), (string) $links[0], 'Found the expected link text.');
list($path, $query_string) = explode('?', $links[0]['href'], 2);
parse_str($query_string, $query_parts);
$this->assertEqual($weight, $query_parts['weight'], 'Found the expected weight query string.');
// Create a random title for the block.
$title = $this->randomMachineName(8);
$block_id = strtolower($this->randomMachineName(8));
$edit = [
'id' => $block_id,
'settings[label]' => $title,
];
// Create the block using the link parsed from the library page.
$this->drupalPostForm($this->getAbsoluteUrl($links[0]['href']), $edit, t('Save block'));
// Ensure that the block was created with the expected weight.
/** @var \Drupal\block\BlockInterface $block */
$block = Block::load($block_id);
$this->assertEqual($weight, $block->getWeight(), 'Found the block with expected weight.');
}
}
/**
* Test configuring and moving a module-define block to specific regions.
*/
public function testBlock() {
// Place page title block to test error messages.
$this->drupalPlaceBlock('page_title_block');
// Disable the block.
$this->drupalGet('admin/structure/block');
$this->clickLink('Disable');
// Select the 'Powered by Drupal' block to be configured and moved.
$block = [];
$block['id'] = 'system_powered_by_block';
$block['settings[label]'] = $this->randomMachineName(8);
$block['settings[label_display]'] = TRUE;
$block['theme'] = $this->config('system.theme')->get('default');
$block['region'] = 'header';
// Set block title to confirm that interface works and override any custom titles.
$this->drupalPostForm('admin/structure/block/add/' . $block['id'] . '/' . $block['theme'], ['settings[label]' => $block['settings[label]'], 'settings[label_display]' => $block['settings[label_display]'], 'id' => $block['id'], 'region' => $block['region']], t('Save block'));
$this->assertText(t('The block configuration has been saved.'), 'Block title set.');
// Check to see if the block was created by checking its configuration.
$instance = Block::load($block['id']);
$this->assertEqual($instance->label(), $block['settings[label]'], 'Stored block title found.');
// Check whether the block can be moved to all available regions.
foreach ($this->regions as $region) {
$this->moveBlockToRegion($block, $region);
}
// Disable the block.
$this->drupalGet('admin/structure/block');
$this->clickLink('Disable');
// Confirm that the block is now listed as disabled.
$this->assertText(t('The block settings have been updated.'), 'Block successfully moved to disabled region.');
// Confirm that the block instance title and markup are not displayed.
$this->drupalGet('node');
$this->assertNoText(t($block['settings[label]']));
// Check for <div id="block-my-block-instance-name"> if the machine name
// is my_block_instance_name.
$xpath = $this->buildXPathQuery('//div[@id=:id]/*', [':id' => 'block-' . str_replace('_', '-', strtolower($block['id']))]);
$this->assertNoFieldByXPath($xpath, FALSE, 'Block found in no regions.');
// Test deleting the block from the edit form.
$this->drupalGet('admin/structure/block/manage/' . $block['id']);
$this->clickLink(t('Remove block'));
$this->assertRaw(t('Are you sure you want to remove the block @name?', ['@name' => $block['settings[label]']]));
$this->drupalPostForm(NULL, [], t('Remove'));
$this->assertRaw(t('The block %name has been removed.', ['%name' => $block['settings[label]']]));
// Test deleting a block via "Configure block" link.
$block = $this->drupalPlaceBlock('system_powered_by_block');
$this->drupalGet('admin/structure/block/manage/' . $block->id(), ['query' => ['destination' => 'admin']]);
$this->clickLink(t('Remove block'));
$this->assertRaw(t('Are you sure you want to remove the block @name?', ['@name' => $block->label()]));
$this->drupalPostForm(NULL, [], t('Remove'));
$this->assertRaw(t('The block %name has been removed.', ['%name' => $block->label()]));
$this->assertUrl('admin');
$this->assertNoRaw($block->id());
}
/**
* Tests that the block form has a theme selector when not passed via the URL.
*/
public function testBlockThemeSelector() {
// Install all themes.
\Drupal::service('theme_handler')->install(['bartik', 'seven', 'stark']);
$theme_settings = $this->config('system.theme');
foreach (['bartik', 'seven', 'stark'] as $theme) {
$this->drupalGet('admin/structure/block/list/' . $theme);
$this->assertTitle(t('Block layout') . ' | Drupal');
// Select the 'Powered by Drupal' block to be placed.
$block = [];
$block['id'] = strtolower($this->randomMachineName());
$block['theme'] = $theme;
$block['region'] = 'content';
$this->drupalPostForm('admin/structure/block/add/system_powered_by_block', $block, t('Save block'));
$this->assertText(t('The block configuration has been saved.'));
$this->assertUrl('admin/structure/block/list/' . $theme . '?block-placement=' . Html::getClass($block['id']));
// Set the default theme and ensure the block is placed.
$theme_settings->set('default', $theme)->save();
$this->drupalGet('');
$elements = $this->xpath('//div[@id = :id]', [':id' => Html::getUniqueId('block-' . $block['id'])]);
$this->assertTrue(!empty($elements), 'The block was found.');
}
}
/**
* Test block display of theme titles.
*/
public function testThemeName() {
// Enable the help block.
$this->drupalPlaceBlock('help_block', ['region' => 'help']);
$this->drupalPlaceBlock('local_tasks_block');
// Explicitly set the default and admin themes.
$theme = 'block_test_specialchars_theme';
\Drupal::service('theme_handler')->install([$theme]);
\Drupal::service('router.builder')->rebuild();
$this->drupalGet('admin/structure/block');
$this->assertEscaped('<"Cat" & \'Mouse\'>');
$this->drupalGet('admin/structure/block/list/block_test_specialchars_theme');
$this->assertEscaped('Demonstrate block regions (<"Cat" & \'Mouse\'>)');
}
/**
* Test block title display settings.
*/
public function testHideBlockTitle() {
$block_name = 'system_powered_by_block';
// Create a random title for the block.
$title = $this->randomMachineName(8);
$id = strtolower($this->randomMachineName(8));
// Enable a standard block.
$default_theme = $this->config('system.theme')->get('default');
$edit = [
'id' => $id,
'region' => 'sidebar_first',
'settings[label]' => $title,
];
$this->drupalPostForm('admin/structure/block/add/' . $block_name . '/' . $default_theme, $edit, t('Save block'));
$this->assertText('The block configuration has been saved.', 'Block was saved');
$this->drupalGet('user');
$this->assertNoText($title, 'Block title was not displayed by default.');
$edit = [
'settings[label_display]' => TRUE,
];
$this->drupalPostForm('admin/structure/block/manage/' . $id, $edit, t('Save block'));
$this->assertText('The block configuration has been saved.', 'Block was saved');
$this->drupalGet('admin/structure/block/manage/' . $id);
$this->assertFieldChecked('edit-settings-label-display', 'The display_block option has the correct default value on the configuration form.');
$this->drupalGet('user');
$this->assertText($title, 'Block title was displayed when enabled.');
}
/**
* Moves a block to a given region via the UI and confirms the result.
*
* @param array $block
* An array of information about the block, including the following keys:
* - module: The module providing the block.
* - title: The title of the block.
* - delta: The block's delta key.
* @param string $region
* The machine name of the theme region to move the block to, for example
* 'header' or 'sidebar_first'.
*/
public function moveBlockToRegion(array $block, $region) {
// Set the created block to a specific region.
$block += ['theme' => $this->config('system.theme')->get('default')];
$edit = [];
$edit['blocks[' . $block['id'] . '][region]'] = $region;
$this->drupalPostForm('admin/structure/block', $edit, t('Save blocks'));
// Confirm that the block was moved to the proper region.
$this->assertText(t('The block settings have been updated.'), format_string('Block successfully moved to %region_name region.', [ '%region_name' => $region]));
// Confirm that the block is being displayed.
$this->drupalGet('');
$this->assertText(t($block['settings[label]']), 'Block successfully being displayed on the page.');
// Confirm that the custom block was found at the proper region.
$xpath = $this->buildXPathQuery('//div[@class=:region-class]//div[@id=:block-id]/*', [
':region-class' => 'region region-' . Html::getClass($region),
':block-id' => 'block-' . str_replace('_', '-', strtolower($block['id'])),
]);
$this->assertFieldByXPath($xpath, NULL, t('Block found in %region_name region.', ['%region_name' => Html::getClass($region)]));
}
/**
* Test that cache tags are properly set and bubbled up to the page cache.
*
* Verify that invalidation of these cache tags works:
* - "block:<block ID>"
* - "block_plugin:<block plugin ID>"
*/
public function testBlockCacheTags() {
// The page cache only works for anonymous users.
$this->drupalLogout();
// Enable page caching.
$config = $this->config('system.performance');
$config->set('cache.page.max_age', 300);
$config->save();
// Place the "Powered by Drupal" block.
$block = $this->drupalPlaceBlock('system_powered_by_block', ['id' => 'powered']);
// Prime the page cache.
$this->drupalGet('<front>');
$this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'MISS');
// Verify a cache hit, but also the presence of the correct cache tags in
// both the page and block caches.
$this->drupalGet('<front>');
$this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT');
$cid_parts = [\Drupal::url('<front>', [], ['absolute' => TRUE]), 'html'];
$cid = implode(':', $cid_parts);
$cache_entry = \Drupal::cache('render')->get($cid);
$expected_cache_tags = [
'config:block_list',
'block_view',
'config:block.block.powered',
'config:user.role.anonymous',
'http_response',
'rendered',
];
sort($expected_cache_tags);
$keys = \Drupal::service('cache_contexts_manager')->convertTokensToKeys(['languages:language_interface', 'theme', 'user.permissions'])->getKeys();
$this->assertIdentical($cache_entry->tags, $expected_cache_tags);
$cache_entry = \Drupal::cache('render')->get('entity_view:block:powered:' . implode(':', $keys));
$expected_cache_tags = [
'block_view',
'config:block.block.powered',
'rendered',
];
sort($expected_cache_tags);
$this->assertIdentical($cache_entry->tags, $expected_cache_tags);
// The "Powered by Drupal" block is modified; verify a cache miss.
$block->setRegion('content');
$block->save();
$this->drupalGet('<front>');
$this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'MISS');
// Now we should have a cache hit again.
$this->drupalGet('<front>');
$this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT');
// Place the "Powered by Drupal" block another time; verify a cache miss.
$block_2 = $this->drupalPlaceBlock('system_powered_by_block', ['id' => 'powered-2']);
$this->drupalGet('<front>');
$this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'MISS');
// Verify a cache hit, but also the presence of the correct cache tags.
$this->drupalGet('<front>');
$this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT');
$cid_parts = [\Drupal::url('<front>', [], ['absolute' => TRUE]), 'html'];
$cid = implode(':', $cid_parts);
$cache_entry = \Drupal::cache('render')->get($cid);
$expected_cache_tags = [
'config:block_list',
'block_view',
'config:block.block.powered',
'config:block.block.powered-2',
'config:user.role.anonymous',
'http_response',
'rendered',
];
sort($expected_cache_tags);
$this->assertEqual($cache_entry->tags, $expected_cache_tags);
$expected_cache_tags = [
'block_view',
'config:block.block.powered',
'rendered',
];
sort($expected_cache_tags);
$keys = \Drupal::service('cache_contexts_manager')->convertTokensToKeys(['languages:language_interface', 'theme', 'user.permissions'])->getKeys();
$cache_entry = \Drupal::cache('render')->get('entity_view:block:powered:' . implode(':', $keys));
$this->assertIdentical($cache_entry->tags, $expected_cache_tags);
$expected_cache_tags = [
'block_view',
'config:block.block.powered-2',
'rendered',
];
sort($expected_cache_tags);
$keys = \Drupal::service('cache_contexts_manager')->convertTokensToKeys(['languages:language_interface', 'theme', 'user.permissions'])->getKeys();
$cache_entry = \Drupal::cache('render')->get('entity_view:block:powered-2:' . implode(':', $keys));
$this->assertIdentical($cache_entry->tags, $expected_cache_tags);
// Now we should have a cache hit again.
$this->drupalGet('<front>');
$this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT');
// Delete the "Powered by Drupal" blocks; verify a cache miss.
entity_delete_multiple('block', ['powered', 'powered-2']);
$this->drupalGet('<front>');
$this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'MISS');
}
/**
* Tests that a link exists to block layout from the appearance form.
*/
public function testThemeAdminLink() {
$this->drupalPlaceBlock('help_block', ['region' => 'help']);
$theme_admin = $this->drupalCreateUser([
'administer blocks',
'administer themes',
'access administration pages',
]);
$this->drupalLogin($theme_admin);
$this->drupalGet('admin/appearance');
$this->assertText('You can place blocks for each theme on the block layout page');
$this->assertLinkByHref('admin/structure/block');
}
/**
* Tests that uninstalling a theme removes its block configuration.
*/
public function testUninstallTheme() {
/** @var \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler */
$theme_handler = \Drupal::service('theme_handler');
$theme_handler->install(['seven']);
$this->config('system.theme')->set('default', 'seven')->save();
$block = $this->drupalPlaceBlock('system_powered_by_block', ['theme' => 'seven', 'region' => 'help']);
$this->drupalGet('<front>');
$this->assertText('Powered by Drupal');
$this->config('system.theme')->set('default', 'classy')->save();
$theme_handler->uninstall(['seven']);
// Ensure that the block configuration does not exist anymore.
$this->assertIdentical(NULL, Block::load($block->id()));
}
/**
* Tests the block access.
*/
public function testBlockAccess() {
$this->drupalPlaceBlock('test_access', ['region' => 'help']);
$this->drupalGet('<front>');
$this->assertNoText('Hello test world');
\Drupal::state()->set('test_block_access', TRUE);
$this->drupalGet('<front>');
$this->assertText('Hello test world');
}
/**
* Tests block_user_role_delete.
*/
public function testBlockUserRoleDelete() {
$role1 = Role::create(['id' => 'test_role1', 'name' => $this->randomString()]);
$role1->save();
$role2 = Role::create(['id' => 'test_role2', 'name' => $this->randomString()]);
$role2->save();
$block = Block::create([
'id' => $this->randomMachineName(),
'plugin' => 'system_powered_by_block',
]);
$block->setVisibilityConfig('user_role', [
'roles' => [
$role1->id() => $role1->id(),
$role2->id() => $role2->id(),
],
]);
$block->save();
$this->assertEqual($block->getVisibility()['user_role']['roles'], [
$role1->id() => $role1->id(),
$role2->id() => $role2->id()
]);
$role1->delete();
$block = Block::load($block->id());
$this->assertEqual($block->getVisibility()['user_role']['roles'], [
$role2->id() => $role2->id()
]);
}
}
@@ -1,329 +0,0 @@
<?php
namespace Drupal\block\Tests;
use Drupal\Component\Utility\Html;
use Drupal\simpletest\WebTestBase;
/**
* Tests that the block configuration UI exists and stores data correctly.
*
* @group block
*/
class BlockUiTest extends WebTestBase {
/**
* Modules to install.
*
* @var array
*/
public static $modules = ['block', 'block_test', 'help', 'condition_test'];
protected $regions;
/**
* The submitted block values used by this test.
*
* @var array
*/
protected $blockValues;
/**
* The block entities used by this test.
*
* @var \Drupal\block\BlockInterface[]
*/
protected $blocks;
/**
* An administrative user to configure the test environment.
*/
protected $adminUser;
protected function setUp() {
parent::setUp();
// Create and log in an administrative user.
$this->adminUser = $this->drupalCreateUser([
'administer blocks',
'access administration pages',
]);
$this->drupalLogin($this->adminUser);
// Enable some test blocks.
$this->blockValues = [
[
'label' => 'Tools',
'tr' => '5',
'plugin_id' => 'system_menu_block:tools',
'settings' => ['region' => 'sidebar_second', 'id' => 'tools'],
'test_weight' => '-1',
],
[
'label' => 'Powered by Drupal',
'tr' => '16',
'plugin_id' => 'system_powered_by_block',
'settings' => ['region' => 'footer', 'id' => 'powered'],
'test_weight' => '0',
],
];
$this->blocks = [];
foreach ($this->blockValues as $values) {
$this->blocks[] = $this->drupalPlaceBlock($values['plugin_id'], $values['settings']);
}
}
/**
* Test block demo page exists and functions correctly.
*/
public function testBlockDemoUiPage() {
$this->drupalPlaceBlock('help_block', ['region' => 'help']);
$this->drupalGet('admin/structure/block');
$this->clickLink(t('Demonstrate block regions (@theme)', ['@theme' => 'Classy']));
$elements = $this->xpath('//div[contains(@class, "region-highlighted")]/div[contains(@class, "block-region") and contains(text(), :title)]', [':title' => 'Highlighted']);
$this->assertTrue(!empty($elements), 'Block demo regions are shown.');
\Drupal::service('theme_handler')->install(['test_theme']);
$this->drupalGet('admin/structure/block/demo/test_theme');
$this->assertEscaped('<strong>Test theme</strong>');
\Drupal::service('theme_handler')->install(['stable']);
$this->drupalGet('admin/structure/block/demo/stable');
$this->assertResponse(404, 'Hidden themes that are not the default theme are not supported by the block demo screen');
}
/**
* Test block admin page exists and functions correctly.
*/
public function testBlockAdminUiPage() {
// Visit the blocks admin ui.
$this->drupalGet('admin/structure/block');
// Look for the blocks table.
$blocks_table = $this->xpath("//table[@id='blocks']");
$this->assertTrue(!empty($blocks_table), 'The blocks table is being rendered.');
// Look for test blocks in the table.
foreach ($this->blockValues as $delta => $values) {
$block = $this->blocks[$delta];
$label = $block->label();
$element = $this->xpath('//*[@id="blocks"]/tbody/tr[' . $values['tr'] . ']/td[1]/text()');
$this->assertTrue((string) $element[0] == $label, 'The "' . $label . '" block title is set inside the ' . $values['settings']['region'] . ' region.');
// Look for a test block region select form element.
$this->assertField('blocks[' . $values['settings']['id'] . '][region]', 'The block "' . $values['label'] . '" has a region assignment field.');
// Move the test block to the header region.
$edit['blocks[' . $values['settings']['id'] . '][region]'] = 'header';
// Look for a test block weight select form element.
$this->assertField('blocks[' . $values['settings']['id'] . '][weight]', 'The block "' . $values['label'] . '" has a weight assignment field.');
// Change the test block's weight.
$edit['blocks[' . $values['settings']['id'] . '][weight]'] = $values['test_weight'];
}
$this->drupalPostForm('admin/structure/block', $edit, t('Save blocks'));
foreach ($this->blockValues as $values) {
// Check if the region and weight settings changes have persisted.
$this->assertOptionSelected(
'edit-blocks-' . $values['settings']['id'] . '-region',
'header',
'The block "' . $label . '" has the correct region assignment (header).'
);
$this->assertOptionSelected(
'edit-blocks-' . $values['settings']['id'] . '-weight',
$values['test_weight'],
'The block "' . $label . '" has the correct weight assignment (' . $values['test_weight'] . ').'
);
}
// Add a block with a machine name the same as a region name.
$this->drupalPlaceBlock('system_powered_by_block', ['region' => 'header', 'id' => 'header']);
$this->drupalGet('admin/structure/block');
$element = $this->xpath('//tr[contains(@class, :class)]', [':class' => 'region-title-header']);
$this->assertTrue(!empty($element));
// Ensure hidden themes do not appear in the UI. Enable another non base
// theme and place the local tasks block.
$this->assertTrue(\Drupal::service('theme_handler')->themeExists('classy'), 'The classy base theme is enabled');
$this->drupalPlaceBlock('local_tasks_block', ['region' => 'header']);
\Drupal::service('theme_installer')->install(['stable', 'stark']);
$this->drupalGet('admin/structure/block');
$theme_handler = \Drupal::service('theme_handler');
$this->assertLink($theme_handler->getName('classy'));
$this->assertLink($theme_handler->getName('stark'));
$this->assertNoLink($theme_handler->getName('stable'));
$this->drupalGet('admin/structure/block/list/stable');
$this->assertResponse(404, 'Placing blocks through UI is not possible for a hidden base theme.');
\Drupal::configFactory()->getEditable('system.theme')->set('admin', 'stable')->save();
\Drupal::service('router.builder')->rebuildIfNeeded();
$this->drupalPlaceBlock('local_tasks_block', ['region' => 'header', 'theme' => 'stable']);
$this->drupalGet('admin/structure/block');
$this->assertLink($theme_handler->getName('stable'));
$this->drupalGet('admin/structure/block/list/stable');
$this->assertResponse(200, 'Placing blocks through UI is possible for a hidden base theme that is the admin theme.');
}
/**
* Tests the block categories on the listing page.
*/
public function testCandidateBlockList() {
$arguments = [
':title' => 'Display message',
':category' => 'Block test',
':href' => 'admin/structure/block/add/test_block_instantiation/classy',
];
$pattern = '//tr[.//td/div[text()=:title] and .//td[text()=:category] and .//td//a[contains(@href, :href)]]';
$this->drupalGet('admin/structure/block');
$this->clickLinkPartialName('Place block');
$elements = $this->xpath($pattern, $arguments);
$this->assertTrue(!empty($elements), 'The test block appears in the category for its module.');
// Trigger the custom category addition in block_test_block_alter().
$this->container->get('state')->set('block_test_info_alter', TRUE);
$this->container->get('plugin.manager.block')->clearCachedDefinitions();
$this->drupalGet('admin/structure/block');
$this->clickLinkPartialName('Place block');
$arguments[':category'] = 'Custom category';
$elements = $this->xpath($pattern, $arguments);
$this->assertTrue(!empty($elements), 'The test block appears in a custom category controlled by block_test_block_alter().');
}
/**
* Tests the behavior of unsatisfied context-aware blocks.
*/
public function testContextAwareUnsatisfiedBlocks() {
$arguments = [
':category' => 'Block test',
':href' => 'admin/structure/block/add/test_context_aware_unsatisfied/classy',
':text' => 'Test context-aware unsatisfied block',
];
$this->drupalGet('admin/structure/block');
$this->clickLinkPartialName('Place block');
$elements = $this->xpath('//tr[.//td/div[text()=:text] and .//td[text()=:category] and .//td//a[contains(@href, :href)]]', $arguments);
$this->assertTrue(empty($elements), 'The context-aware test block does not appear.');
$definition = \Drupal::service('plugin.manager.block')->getDefinition('test_context_aware_unsatisfied');
$this->assertTrue(!empty($definition), 'The context-aware test block does not exist.');
}
/**
* Tests the behavior of context-aware blocks.
*/
public function testContextAwareBlocks() {
$expected_text = '<div id="test_context_aware--username">' . \Drupal::currentUser()->getUsername() . '</div>';
$this->drupalGet('');
$this->assertNoText('Test context-aware block');
$this->assertNoRaw($expected_text);
$block_url = 'admin/structure/block/add/test_context_aware/classy';
$arguments = [
':title' => 'Test context-aware block',
':category' => 'Block test',
':href' => $block_url,
];
$pattern = '//tr[.//td/div[text()=:title] and .//td[text()=:category] and .//td//a[contains(@href, :href)]]';
$this->drupalGet('admin/structure/block');
$this->clickLinkPartialName('Place block');
$elements = $this->xpath($pattern, $arguments);
$this->assertTrue(!empty($elements), 'The context-aware test block appears.');
$definition = \Drupal::service('plugin.manager.block')->getDefinition('test_context_aware');
$this->assertTrue(!empty($definition), 'The context-aware test block exists.');
$edit = [
'region' => 'content',
'settings[context_mapping][user]' => '@block_test.multiple_static_context:userB',
];
$this->drupalPostForm($block_url, $edit, 'Save block');
$this->drupalGet('');
$this->assertText('Test context-aware block');
$this->assertText('User context found.');
$this->assertRaw($expected_text);
// Test context mapping allows empty selection for optional contexts.
$this->drupalGet('admin/structure/block/manage/testcontextawareblock');
$edit = [
'settings[context_mapping][user]' => '',
];
$this->drupalPostForm(NULL, $edit, 'Save block');
$this->drupalGet('');
$this->assertText('No context mapping selected.');
$this->assertNoText('User context found.');
// Tests that conditions with missing context are not displayed.
$this->drupalGet('admin/structure/block/manage/testcontextawareblock');
$this->assertNoRaw('No existing type');
$this->assertNoFieldByXPath('//*[@name="visibility[condition_test_no_existing_type][negate]"]');
}
/**
* Tests that the BlockForm populates machine name correctly.
*/
public function testMachineNameSuggestion() {
$url = 'admin/structure/block/add/test_block_instantiation/classy';
$this->drupalGet($url);
$this->assertFieldByName('id', 'displaymessage', 'Block form uses raw machine name suggestion when no instance already exists.');
$edit = ['region' => 'content'];
$this->drupalPostForm($url, $edit, 'Save block');
$this->assertText('The block configuration has been saved.');
// Now, check to make sure the form starts by autoincrementing correctly.
$this->drupalGet($url);
$this->assertFieldByName('id', 'displaymessage_2', 'Block form appends _2 to plugin-suggested machine name when an instance already exists.');
$this->drupalPostForm($url, $edit, 'Save block');
$this->assertText('The block configuration has been saved.');
// And verify that it continues working beyond just the first two.
$this->drupalGet($url);
$this->assertFieldByName('id', 'displaymessage_3', 'Block form appends _3 to plugin-suggested machine name when two instances already exist.');
}
/**
* Tests the block placement indicator.
*/
public function testBlockPlacementIndicator() {
// Select the 'Powered by Drupal' block to be placed.
$block = [];
$block['id'] = strtolower($this->randomMachineName());
$block['theme'] = 'classy';
$block['region'] = 'content';
// After adding a block, it will indicate which block was just added.
$this->drupalPostForm('admin/structure/block/add/system_powered_by_block', $block, t('Save block'));
$this->assertUrl('admin/structure/block/list/classy?block-placement=' . Html::getClass($block['id']));
// Resaving the block page will remove the block indicator.
$this->drupalPostForm(NULL, [], t('Save blocks'));
$this->assertUrl('admin/structure/block/list/classy');
}
/**
* Tests if validation errors are passed plugin form to the parent form.
*/
public function testBlockValidateErrors() {
$this->drupalPostForm('admin/structure/block/add/test_settings_validation/classy', ['region' => 'content', 'settings[digits]' => 'abc'], t('Save block'));
$arguments = [':message' => 'Only digits are allowed'];
$pattern = '//div[contains(@class,"messages messages--error")]/div[contains(text()[2],:message)]';
$elements = $this->xpath($pattern, $arguments);
$this->assertTrue($elements, 'Plugin error message found in parent form.');
$error_class_pattern = '//div[contains(@class,"form-item-settings-digits")]/input[contains(@class,"error")]';
$error_class = $this->xpath($error_class_pattern);
$this->assertTrue($error_class, 'Plugin error class found in parent form.');
}
/**
* Tests that the enable/disable routes are protected from CSRF.
*/
public function testRouteProtection() {
// Get the first block generated in our setUp method.
/** @var \Drupal\block\BlockInterface $block */
$block = reset($this->blocks);
// Ensure that the enable and disable routes are protected.
$this->drupalGet('admin/structure/block/manage/' . $block->id() . '/disable');
$this->assertResponse(403);
$this->drupalGet('admin/structure/block/manage/' . $block->id() . '/enable');
$this->assertResponse(403);
}
}
@@ -1,167 +0,0 @@
<?php
namespace Drupal\block\Tests;
use Drupal\block_content\Entity\BlockContent;
use Drupal\block_content\Entity\BlockContentType;
use Drupal\Core\Url;
use Drupal\simpletest\WebTestBase;
use Drupal\system\Entity\Menu;
use Drupal\views\Entity\View;
/**
* Tests that the block module properly escapes block descriptions.
*
* @group block
*/
class BlockXssTest extends WebTestBase {
/**
* Modules to install.
*
* @var array
*/
public static $modules = ['block', 'block_content', 'menu_ui', 'views'];
/**
* Tests that nothing is escaped other than the blocks explicitly tested.
*/
public function testNoUnexpectedEscaping() {
$this->drupalLogin($this->drupalCreateUser(['administer blocks', 'access administration pages']));
$this->drupalGet(Url::fromRoute('block.admin_display'));
$this->clickLinkPartialName('Place block');
$this->assertNoEscaped('<');
}
/**
* Tests XSS in title.
*/
public function testXssInTitle() {
$this->container->get('module_installer')->install(['block_test']);
$this->drupalPlaceBlock('test_xss_title', ['label' => '<script>alert("XSS label");</script>']);
\Drupal::state()->set('block_test.content', $this->randomMachineName());
$this->drupalGet('');
$this->assertNoRaw('<script>alert("XSS label");</script>', 'The block title was properly sanitized when rendered.');
$this->drupalLogin($this->drupalCreateUser(['administer blocks', 'access administration pages']));
$default_theme = $this->config('system.theme')->get('default');
$this->drupalGet('admin/structure/block/list/' . $default_theme);
$this->assertNoRaw("<script>alert('XSS subject');</script>", 'The block title was properly sanitized in Block Plugin UI Admin page.');
}
/**
* Tests XSS in category.
*/
public function testXssInCategory() {
$this->container->get('module_installer')->install(['block_test']);
$this->drupalPlaceBlock('test_xss_title');
$this->drupalLogin($this->drupalCreateUser(['administer blocks', 'access administration pages']));
$this->drupalGet(Url::fromRoute('block.admin_display'));
$this->clickLinkPartialName('Place block');
$this->assertNoRaw("<script>alert('XSS category');</script>");
}
/**
* Tests various modules that provide blocks for XSS.
*/
public function testBlockXss() {
$this->drupalLogin($this->rootUser);
$this->doViewTest();
$this->doMenuTest();
$this->doBlockContentTest();
$this->drupalGet(Url::fromRoute('block.admin_display'));
$this->clickLinkPartialName('Place block');
$this->assertNoRaw('&amp;lt;', 'The page does not have double escaped HTML tags.');
}
/**
* Tests XSS coming from View block labels.
*/
protected function doViewTest() {
// Create a View without a custom label for its block Display. The
// admin_label of the block then becomes just the View's label.
$view = View::create([
'id' => $this->randomMachineName(),
'label' => '<script>alert("view1");</script>',
]);
$view->addDisplay('block');
$view->save();
// Create a View with a custom label for its block Display. The
// admin_label of the block then becomes the View's label combined with
// the Display's label.
$view = View::create([
'id' => $this->randomMachineName(),
'label' => '<script>alert("view2");</script>',
]);
$view->addDisplay('block', 'Fish & chips');
$view->save();
$this->drupalGet(Url::fromRoute('block.admin_display'));
$this->clickLinkPartialName('Place block');
// \Drupal\views\Plugin\Derivative\ViewsBlock::getDerivativeDefinitions()
// has a different code path for an admin label based only on the View
// label versus one based on both the View label and the Display label.
// Ensure that this test is covering both code paths by asserting the
// absence of a ":" for the first View and the presence of a ":" for the
// second one. Note that the second assertion is redundant with the one
// further down which also checks for the Display label, but is included
// here for clarity.
$this->assertNoEscaped('<script>alert("view1");</script>:');
$this->assertEscaped('<script>alert("view2");</script>:');
// Assert that the blocks have their admin labels escaped and
// don't appear anywhere unescaped.
$this->assertEscaped('<script>alert("view1");</script>');
$this->assertNoRaw('<script>alert("view1");</script>');
$this->assertEscaped('<script>alert("view2");</script>: Fish & chips');
$this->assertNoRaw('<script>alert("view2");</script>');
$this->assertNoRaw('Fish & chips');
// Assert the Display label doesn't appear anywhere double escaped.
$this->assertNoRaw('Fish & chips');
$this->assertNoRaw('Fish &amp;amp; chips');
}
/**
* Tests XSS coming from Menu block labels.
*/
protected function doMenuTest() {
Menu::create([
'id' => $this->randomMachineName(),
'label' => '<script>alert("menu");</script>',
])->save();
$this->drupalGet(Url::fromRoute('block.admin_display'));
$this->clickLinkPartialName('Place block');
$this->assertEscaped('<script>alert("menu");</script>');
$this->assertNoRaw('<script>alert("menu");</script>');
}
/**
* Tests XSS coming from Block Content block info.
*/
protected function doBlockContentTest() {
BlockContentType::create([
'id' => 'basic',
'label' => 'basic',
'revision' => TRUE,
])->save();
BlockContent::create([
'type' => 'basic',
'info' => '<script>alert("block_content");</script>',
])->save();
$this->drupalGet(Url::fromRoute('block.admin_display'));
$this->clickLinkPartialName('Place block');
$this->assertEscaped('<script>alert("block_content");</script>');
$this->assertNoRaw('<script>alert("block_content");</script>');
}
}
@@ -1,73 +0,0 @@
<?php
namespace Drupal\block\Tests;
use Drupal\simpletest\WebTestBase;
/**
* Tests that the new default theme gets blocks.
*
* @group block
*/
class NewDefaultThemeBlocksTest extends WebTestBase {
/**
* Modules to install.
*
* @var array
*/
public static $modules = array('block');
/**
* Check the enabled Bartik blocks are correctly copied over.
*/
function testNewDefaultThemeBlocks() {
$default_theme = $this->config('system.theme')->get('default');
// Add two instances of the user login block.
$this->drupalPlaceBlock('user_login_block', array(
'id' => $default_theme . '_' . strtolower($this->randomMachineName(8)),
));
$this->drupalPlaceBlock('user_login_block', array(
'id' => $default_theme . '_' . strtolower($this->randomMachineName(8)),
));
// Add an instance of a different block.
$this->drupalPlaceBlock('system_powered_by_block', array(
'id' => $default_theme . '_' . strtolower($this->randomMachineName(8)),
));
// Install a different theme.
$new_theme = 'bartik';
$this->assertFalse($new_theme == $default_theme, 'The new theme is different from the previous default theme.');
\Drupal::service('theme_handler')->install(array($new_theme));
$this->config('system.theme')
->set('default', $new_theme)
->save();
// Ensure that the new theme has all the blocks as the previous default.
$default_block_names = $this->container->get('entity.query')->get('block')
->condition('theme', $default_theme)
->execute();
$new_blocks = $this->container->get('entity.query')->get('block')
->condition('theme', $new_theme)
->execute();
$this->assertTrue(count($default_block_names) == count($new_blocks), 'The new default theme has the same number of blocks as the previous theme.');
foreach ($default_block_names as $default_block_name) {
// Remove the matching block from the list of blocks in the new theme.
// E.g., if the old theme has block.block.stark_admin,
// unset block.block.bartik_admin.
unset($new_blocks[str_replace($default_theme . '_', $new_theme . '_', $default_block_name)]);
}
$this->assertTrue(empty($new_blocks), 'The new theme has exactly the same blocks as the previous default theme.');
// Install a hidden base theme and ensure blocks are not copied.
$base_theme = 'test_basetheme';
\Drupal::service('theme_handler')->install([$base_theme]);
$new_blocks = $this->container->get('entity.query')->get('block')
->condition('theme', $base_theme)
->execute();
$this->assertTrue(empty($new_blocks), 'Installing a hidden base theme does not copy blocks from the default theme.');
}
}
@@ -1,42 +0,0 @@
<?php
namespace Drupal\block\Tests;
use Drupal\simpletest\WebTestBase;
/**
* Tests the block administration page for a non-default theme.
*
* @group block
*/
class NonDefaultBlockAdminTest extends WebTestBase {
/**
* Modules to install.
*
* @var array
*/
public static $modules = ['block'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->drupalPlaceBlock('local_tasks_block');
}
/**
* Test non-default theme admin.
*/
public function testNonDefaultBlockAdmin() {
$admin_user = $this->drupalCreateUser(['administer blocks', 'administer themes']);
$this->drupalLogin($admin_user);
$new_theme = 'bartik';
\Drupal::service('theme_handler')->install([$new_theme]);
$this->drupalGet('admin/structure/block/list/' . $new_theme);
$this->assertText('Bartik(' . t('active tab') . ')', 'Tab for non-default theme found.');
}
}
@@ -1,53 +0,0 @@
<?php
namespace Drupal\block\Tests\Update;
use Drupal\system\Tests\Update\UpdatePathTestBase;
/**
* Tests the upgrade path for block with conditions missing context.
*
* @see https://www.drupal.org/node/2811519
*
* @group Update
*/
class BlockConditionMissingSchemaUpdateTest extends UpdatePathTestBase {
/**
* This test does not have a failed update but the configuration has missing
* schema so can not do the full post update testing offered by
* UpdatePathTestBase.
*
* @var bool
*
* @see \Drupal\system\Tests\Update\UpdatePathTestBase::runUpdates()
*/
protected $checkFailedUpdates = FALSE;
/**
* {@inheritdoc}
*/
protected static $modules = ['block_test', 'language'];
/**
* {@inheritdoc}
*/
protected function setDatabaseDumpFiles() {
$this->databaseDumpFiles = [
__DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz',
__DIR__ . '/../../../tests/fixtures/update/drupal-8.block-test-enabled-missing-schema.php',
];
}
/**
* Tests that block context mapping is updated properly.
*/
public function testUpdateHookN() {
$this->runUpdates();
$this->drupalGet('<front>');
// If the block is fixed by block_post_update_fix_negate_in_conditions()
// then it will be visible.
$this->assertText('Test missing schema on conditions');
}
}
@@ -1,20 +0,0 @@
<?php
namespace Drupal\block\Tests\Update;
/**
* Runs BlockContextMappingUpdateTest with a dump filled with content.
*
* @group Update
*/
class BlockContextMappingUpdateFilledTest extends BlockContextMappingUpdateTest {
/**
* {@inheritdoc}
*/
protected function setDatabaseDumpFiles() {
parent::setDatabaseDumpFiles();
$this->databaseDumpFiles[0] = __DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.filled.standard.php.gz';
}
}
@@ -1,106 +0,0 @@
<?php
namespace Drupal\block\Tests\Update;
use Drupal\block\Entity\Block;
use Drupal\node\Entity\Node;
use Drupal\system\Tests\Update\UpdatePathTestBase;
/**
* Tests the upgrade path for block context mapping renames.
*
* @see https://www.drupal.org/node/2354889
*
* @group Update
*/
class BlockContextMappingUpdateTest extends UpdatePathTestBase {
/**
* {@inheritdoc}
*/
protected static $modules = ['block_test', 'language'];
/**
* {@inheritdoc}
*/
protected function setDatabaseDumpFiles() {
$this->databaseDumpFiles = [
__DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz',
__DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.block-context-manager-2354889.php',
__DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.language-enabled.php',
__DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.block-test-enabled.php',
];
}
/**
* Tests that block context mapping is updated properly.
*/
public function testUpdateHookN() {
$this->runUpdates();
$this->assertRaw('Encountered an unknown context mapping key coming probably from a contributed or custom module: One or more mappings could not be updated. Please manually review your visibility settings for the following blocks, which are disabled now:<ul><li>User login (Visibility: Baloney spam)</li></ul>');
// Disable maintenance mode.
\Drupal::state()->set('system.maintenance_mode', FALSE);
// We finished updating so we can log in the user now.
$this->drupalLogin($this->rootUser);
// The block that we are testing has the following visibility rules:
// - only visible on node pages
// - only visible to authenticated users.
$block_title = 'Test for 2354889';
// Create two nodes, a page and an article.
$page = Node::create([
'type' => 'page',
'title' => 'Page node',
]);
$page->save();
$article = Node::create([
'type' => 'article',
'title' => 'Article node',
]);
$article->save();
// Check that the block appears only on Page nodes for authenticated users.
$this->drupalGet('node/' . $page->id());
$this->assertRaw($block_title, 'Test block is visible on a Page node as an authenticated user.');
$this->drupalGet('node/' . $article->id());
$this->assertNoRaw($block_title, 'Test block is not visible on a Article node as an authenticated user.');
$this->drupalLogout();
// Check that the block does not appear on any page for anonymous users.
$this->drupalGet('node/' . $page->id());
$this->assertNoRaw($block_title, 'Test block is not visible on a Page node as an anonymous user.');
$this->drupalGet('node/' . $article->id());
$this->assertNoRaw($block_title, 'Test block is not visible on a Article node as an anonymous user.');
// Ensure that all the context mappings got updated properly.
$block = Block::load('testfor2354889');
$visibility = $block->get('visibility');
$this->assertEqual('@node.node_route_context:node', $visibility['node_type']['context_mapping']['node']);
$this->assertEqual('@user.current_user_context:current_user', $visibility['user_role']['context_mapping']['user']);
$this->assertEqual('@language.current_language_context:language_interface', $visibility['language']['context_mapping']['language']);
// Check that a block with invalid context is being disabled and that it can
// still be edited afterward.
$disabled_block = Block::load('thirdtestfor2354889');
$this->assertFalse($disabled_block->status(), 'Block with invalid context is disabled');
$this->assertEqual(['thirdtestfor2354889' => ['missing_context_ids' => ['baloney_spam' => ['node_type']], 'status' => TRUE]], \Drupal::keyValue('update_backup')->get('block_update_8001'));
$disabled_block_visibility = $disabled_block->get('visibility');
$this->assertTrue(!isset($disabled_block_visibility['node_type']), 'The problematic visibility condition has been removed.');
$admin_user = $this->drupalCreateUser(['administer blocks']);
$this->drupalLogin($admin_user);
$this->drupalGet('admin/structure/block/manage/thirdtestfor2354889');
$this->assertResponse('200');
}
}
@@ -1,57 +0,0 @@
<?php
namespace Drupal\block\Tests\Update;
use Drupal\system\Tests\Update\UpdatePathTestBase;
/**
* Tests the upgrade path for removal of disabled region.
*
* @see https://www.drupal.org/node/2513534
*
* @group Update
*/
class BlockRemoveDisabledRegionUpdateTest extends UpdatePathTestBase {
/**
* {@inheritdoc}
*/
protected static $modules = ['block_test', 'language'];
/**
* {@inheritdoc}
*/
protected function setDatabaseDumpFiles() {
$this->databaseDumpFiles = [
__DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz',
__DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.update-test-block-disabled-2513534.php',
];
}
/**
* Tests that block context mapping is updated properly.
*/
public function testUpdateHookN() {
$this->runUpdates();
// Disable maintenance mode.
\Drupal::state()->set('system.maintenance_mode', FALSE);
// We finished updating so we can login the user now.
$this->drupalLogin($this->rootUser);
// Verify that a disabled block is in the default region.
$this->drupalGet('admin/structure/block');
$element = $this->xpath("//tr[contains(@data-drupal-selector, :block) and contains(@class, :status)]//select/option[@selected and @value=:region]",
[':block' => 'edit-blocks-pagetitle-1', ':status' => 'block-disabled', ':region' => 'header']);
$this->assertTrue(!empty($element));
// Verify that an enabled block is now disabled and in the default region.
$this->drupalGet('admin/structure/block');
$element = $this->xpath("//tr[contains(@data-drupal-selector, :block) and contains(@class, :status)]//select/option[@selected and @value=:region]",
[':block' => 'edit-blocks-pagetitle-2', ':status' => 'block-disabled', ':region' => 'header']);
$this->assertTrue(!empty($element));
}
}
@@ -1,373 +0,0 @@
<?php
namespace Drupal\block\Tests\Views;
use Drupal\Component\Serialization\Json;
use Drupal\Core\Url;
use Drupal\system\Tests\Cache\AssertPageCacheContextsAndTagsTrait;
use Drupal\views\Entity\View;
use Drupal\views\Views;
use Drupal\views\Tests\ViewTestBase;
use Drupal\views\Tests\ViewTestData;
use Drupal\Core\Template\Attribute;
/**
* Tests the block display plugin.
*
* @group block
* @see \Drupal\block\Plugin\views\display\Block
*/
class DisplayBlockTest extends ViewTestBase {
use AssertPageCacheContextsAndTagsTrait;
/**
* Modules to install.
*
* @var array
*/
public static $modules = ['node', 'block_test_views', 'test_page_test', 'contextual', 'views_ui'];
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = ['test_view_block', 'test_view_block2'];
protected function setUp() {
parent::setUp();
ViewTestData::createTestViews(get_class($this), ['block_test_views']);
$this->enableViewsTestModule();
}
/**
* Tests default and custom block categories.
*/
public function testBlockCategory() {
$this->drupalLogin($this->drupalCreateUser(['administer views', 'administer blocks']));
// Create a new view in the UI.
$edit = [];
$edit['label'] = $this->randomString();
$edit['id'] = strtolower($this->randomMachineName());
$edit['show[wizard_key]'] = 'standard:views_test_data';
$edit['description'] = $this->randomString();
$edit['block[create]'] = TRUE;
$edit['block[style][row_plugin]'] = 'fields';
$this->drupalPostForm('admin/structure/views/add', $edit, t('Save and edit'));
$pattern = '//tr[.//td[text()=:category] and .//td//a[contains(@href, :href)]]';
// Test that the block was given a default category corresponding to its
// base table.
$arguments = [
':href' => \Drupal::Url('block.admin_add', [
'plugin_id' => 'views_block:' . $edit['id'] . '-block_1',
'theme' => 'classy',
]),
':category' => t('Lists (Views)'),
];
$this->drupalGet('admin/structure/block');
$this->clickLinkPartialName('Place block');
$elements = $this->xpath($pattern, $arguments);
$this->assertTrue(!empty($elements), 'The test block appears in the category for its base table.');
// Duplicate the block before changing the category.
$this->drupalPostForm('admin/structure/views/view/' . $edit['id'] . '/edit/block_1', [], t('Duplicate @display_title', ['@display_title' => 'Block']));
$this->assertUrl('admin/structure/views/view/' . $edit['id'] . '/edit/block_2');
// Change the block category to a random string.
$this->drupalGet('admin/structure/views/view/' . $edit['id'] . '/edit/block_1');
$link = $this->xpath('//a[@id="views-block-1-block-category" and normalize-space(text())=:category]', $arguments);
$this->assertTrue(!empty($link));
$this->clickLink(t('Lists (Views)'));
$category = $this->randomString();
$this->drupalPostForm(NULL, ['block_category' => $category], t('Apply'));
// Duplicate the block after changing the category.
$this->drupalPostForm(NULL, [], t('Duplicate @display_title', ['@display_title' => 'Block']));
$this->assertUrl('admin/structure/views/view/' . $edit['id'] . '/edit/block_3');
$this->drupalPostForm(NULL, [], t('Save'));
// Test that the blocks are listed under the correct categories.
$arguments[':category'] = $category;
$this->drupalGet('admin/structure/block');
$this->clickLinkPartialName('Place block');
$elements = $this->xpath($pattern, $arguments);
$this->assertTrue(!empty($elements), 'The test block appears in the custom category.');
$arguments = [
':href' => \Drupal::Url('block.admin_add', [
'plugin_id' => 'views_block:' . $edit['id'] . '-block_2',
'theme' => 'classy',
]),
':category' => t('Lists (Views)'),
];
$elements = $this->xpath($pattern, $arguments);
$this->assertTrue(!empty($elements), 'The first duplicated test block remains in the original category.');
$arguments = [
':href' => \Drupal::Url('block.admin_add', [
'plugin_id' => 'views_block:' . $edit['id'] . '-block_3',
'theme' => 'classy',
]),
':category' => $category,
];
$elements = $this->xpath($pattern, $arguments);
$this->assertTrue(!empty($elements), 'The second duplicated test block appears in the custom category.');
}
/**
* Tests removing a block display.
*/
public function testDeleteBlockDisplay() {
// To test all combinations possible we first place create two instances
// of the block display of the first view.
$block_1 = $this->drupalPlaceBlock('views_block:test_view_block-block_1', ['label' => 'test_view_block-block_1:1']);
$block_2 = $this->drupalPlaceBlock('views_block:test_view_block-block_1', ['label' => 'test_view_block-block_1:2']);
// Then we add one instance of blocks for each of the two displays of the
// second view.
$block_3 = $this->drupalPlaceBlock('views_block:test_view_block2-block_1', ['label' => 'test_view_block2-block_1']);
$block_4 = $this->drupalPlaceBlock('views_block:test_view_block2-block_2', ['label' => 'test_view_block2-block_2']);
$this->drupalGet('test-page');
$this->assertBlockAppears($block_1);
$this->assertBlockAppears($block_2);
$this->assertBlockAppears($block_3);
$this->assertBlockAppears($block_4);
$block_storage = $this->container->get('entity_type.manager')->getStorage('block');
// Remove the block display, so both block entities from the first view
// should both disappear.
$view = Views::getView('test_view_block');
$view->initDisplay();
$view->displayHandlers->remove('block_1');
$view->storage->save();
$this->assertFalse($block_storage->load($block_1->id()), 'The block for this display was removed.');
$this->assertFalse($block_storage->load($block_2->id()), 'The block for this display was removed.');
$this->assertTrue($block_storage->load($block_3->id()), 'A block from another view was unaffected.');
$this->assertTrue($block_storage->load($block_4->id()), 'A block from another view was unaffected.');
$this->drupalGet('test-page');
$this->assertNoBlockAppears($block_1);
$this->assertNoBlockAppears($block_2);
$this->assertBlockAppears($block_3);
$this->assertBlockAppears($block_4);
// Remove the first block display of the second view and ensure the block
// instance of the second block display still exists.
$view = Views::getView('test_view_block2');
$view->initDisplay();
$view->displayHandlers->remove('block_1');
$view->storage->save();
$this->assertFalse($block_storage->load($block_3->id()), 'The block for this display was removed.');
$this->assertTrue($block_storage->load($block_4->id()), 'A block from another display on the same view was unaffected.');
$this->drupalGet('test-page');
$this->assertNoBlockAppears($block_3);
$this->assertBlockAppears($block_4);
}
/**
* Test the block form for a Views block.
*/
public function testViewsBlockForm() {
$this->drupalLogin($this->drupalCreateUser(['administer blocks']));
$default_theme = $this->config('system.theme')->get('default');
$this->drupalGet('admin/structure/block/add/views_block:test_view_block-block_1/' . $default_theme);
$elements = $this->xpath('//input[@name="label"]');
$this->assertTrue(empty($elements), 'The label field is not found for Views blocks.');
// Test that that machine name field is hidden from display and has been
// saved as expected from the default value.
$this->assertNoFieldById('edit-machine-name', 'views_block__test_view_block_1', 'The machine name is hidden on the views block form.');
// Save the block.
$edit = ['region' => 'content'];
$this->drupalPostForm(NULL, $edit, t('Save block'));
$storage = $this->container->get('entity_type.manager')->getStorage('block');
$block = $storage->load('views_block__test_view_block_block_1');
// This will only return a result if our new block has been created with the
// expected machine name.
$this->assertTrue(!empty($block), 'The expected block was loaded.');
for ($i = 2; $i <= 3; $i++) {
// Place the same block again and make sure we have a new ID.
$this->drupalPostForm('admin/structure/block/add/views_block:test_view_block-block_1/' . $default_theme, $edit, t('Save block'));
$block = $storage->load('views_block__test_view_block_block_1_' . $i);
// This will only return a result if our new block has been created with the
// expected machine name.
$this->assertTrue(!empty($block), 'The expected block was loaded.');
}
// Tests the override capability of items per page.
$this->drupalGet('admin/structure/block/add/views_block:test_view_block-block_1/' . $default_theme);
$edit = ['region' => 'content'];
$edit['settings[override][items_per_page]'] = 10;
$this->drupalPostForm('admin/structure/block/add/views_block:test_view_block-block_1/' . $default_theme, $edit, t('Save block'));
$block = $storage->load('views_block__test_view_block_block_1_4');
$config = $block->getPlugin()->getConfiguration();
$this->assertEqual(10, $config['items_per_page'], "'Items per page' is properly saved.");
$edit['settings[override][items_per_page]'] = 5;
$this->drupalPostForm('admin/structure/block/manage/views_block__test_view_block_block_1_4', $edit, t('Save block'));
$block = $storage->load('views_block__test_view_block_block_1_4');
$config = $block->getPlugin()->getConfiguration();
$this->assertEqual(5, $config['items_per_page'], "'Items per page' is properly saved.");
// Tests the override of the label capability.
$edit = ['region' => 'content'];
$edit['settings[views_label_checkbox]'] = 1;
$edit['settings[views_label]'] = 'Custom title';
$this->drupalPostForm('admin/structure/block/add/views_block:test_view_block-block_1/' . $default_theme, $edit, t('Save block'));
$block = $storage->load('views_block__test_view_block_block_1_5');
$config = $block->getPlugin()->getConfiguration();
$this->assertEqual('Custom title', $config['views_label'], "'Label' is properly saved.");
}
/**
* Tests the actual rendering of the views block.
*/
public function testBlockRendering() {
// Create a block and set a custom title.
$block = $this->drupalPlaceBlock('views_block:test_view_block-block_1', ['label' => 'test_view_block-block_1:1', 'views_label' => 'Custom title']);
$this->drupalGet('');
$result = $this->xpath('//div[contains(@class, "region-sidebar-first")]/div[contains(@class, "block-views")]/h2');
$this->assertEqual((string) $result[0], 'Custom title');
// Don't override the title anymore.
$plugin = $block->getPlugin();
$plugin->setConfigurationValue('views_label', '');
$block->save();
$this->drupalGet('');
$result = $this->xpath('//div[contains(@class, "region-sidebar-first")]/div[contains(@class, "block-views")]/h2');
$this->assertEqual((string) $result[0], 'test_view_block');
// Hide the title.
$block->getPlugin()->setConfigurationValue('label_display', FALSE);
$block->save();
$this->drupalGet('');
$result = $this->xpath('//div[contains(@class, "region-sidebar-first")]/div[contains(@class, "block-views")]/h2');
$this->assertTrue(empty($result), 'The title is not visible.');
$this->assertCacheTags(array_merge($block->getCacheTags(), ['block_view', 'config:block_list', 'config:system.site', 'config:views.view.test_view_block' , 'http_response', 'rendered']));
}
/**
* Tests the various testcases of empty block rendering.
*/
public function testBlockEmptyRendering() {
$url = new Url('test_page_test.test_page');
// Remove all views_test_data entries.
\Drupal::database()->truncate('views_test_data')->execute();
/** @var \Drupal\views\ViewEntityInterface $view */
$view = View::load('test_view_block');
$view->invalidateCaches();
$block = $this->drupalPlaceBlock('views_block:test_view_block-block_1', ['label' => 'test_view_block-block_1:1', 'views_label' => 'Custom title']);
$this->drupalGet('');
$this->assertEqual(1, count($this->xpath('//div[contains(@class, "block-views-blocktest-view-block-block-1")]')));
$display = &$view->getDisplay('block_1');
$display['display_options']['block_hide_empty'] = TRUE;
$view->save();
$this->drupalGet($url);
$this->assertEqual(0, count($this->xpath('//div[contains(@class, "block-views-blocktest-view-block-block-1")]')));
// Ensure that the view cachability metadata is propagated even, for an
// empty block.
$this->assertCacheTags(array_merge($block->getCacheTags(), ['block_view', 'config:block_list', 'config:views.view.test_view_block' , 'http_response', 'rendered']));
$this->assertCacheContexts(['url.query_args:_wrapper_format']);
// Add a header displayed on empty result.
$display = &$view->getDisplay('block_1');
$display['display_options']['defaults']['header'] = FALSE;
$display['display_options']['header']['example'] = [
'field' => 'area_text_custom',
'id' => 'area_text_custom',
'table' => 'views',
'plugin_id' => 'text_custom',
'content' => 'test header',
'empty' => TRUE,
];
$view->save();
$this->drupalGet($url);
$this->assertEqual(1, count($this->xpath('//div[contains(@class, "block-views-blocktest-view-block-block-1")]')));
$this->assertCacheTags(array_merge($block->getCacheTags(), ['block_view', 'config:block_list', 'config:views.view.test_view_block' , 'http_response', 'rendered']));
$this->assertCacheContexts(['url.query_args:_wrapper_format']);
// Hide the header on empty results.
$display = &$view->getDisplay('block_1');
$display['display_options']['defaults']['header'] = FALSE;
$display['display_options']['header']['example'] = [
'field' => 'area_text_custom',
'id' => 'area_text_custom',
'table' => 'views',
'plugin_id' => 'text_custom',
'content' => 'test header',
'empty' => FALSE,
];
$view->save();
$this->drupalGet($url);
$this->assertEqual(0, count($this->xpath('//div[contains(@class, "block-views-blocktest-view-block-block-1")]')));
$this->assertCacheTags(array_merge($block->getCacheTags(), ['block_view', 'config:block_list', 'config:views.view.test_view_block', 'http_response', 'rendered']));
$this->assertCacheContexts(['url.query_args:_wrapper_format']);
// Add an empty text.
$display = &$view->getDisplay('block_1');
$display['display_options']['defaults']['empty'] = FALSE;
$display['display_options']['empty']['example'] = [
'field' => 'area_text_custom',
'id' => 'area_text_custom',
'table' => 'views',
'plugin_id' => 'text_custom',
'content' => 'test empty',
];
$view->save();
$this->drupalGet($url);
$this->assertEqual(1, count($this->xpath('//div[contains(@class, "block-views-blocktest-view-block-block-1")]')));
$this->assertCacheTags(array_merge($block->getCacheTags(), ['block_view', 'config:block_list', 'config:views.view.test_view_block', 'http_response', 'rendered']));
$this->assertCacheContexts(['url.query_args:_wrapper_format']);
}
/**
* Tests the contextual links on a Views block.
*/
public function testBlockContextualLinks() {
$this->drupalLogin($this->drupalCreateUser(['administer views', 'access contextual links', 'administer blocks']));
$block = $this->drupalPlaceBlock('views_block:test_view_block-block_1');
$cached_block = $this->drupalPlaceBlock('views_block:test_view_block-block_1');
$this->drupalGet('test-page');
$id = 'block:block=' . $block->id() . ':langcode=en|entity.view.edit_form:view=test_view_block:location=block&name=test_view_block&display_id=block_1&langcode=en';
$cached_id = 'block:block=' . $cached_block->id() . ':langcode=en|entity.view.edit_form:view=test_view_block:location=block&name=test_view_block&display_id=block_1&langcode=en';
// @see \Drupal\contextual\Tests\ContextualDynamicContextTest:assertContextualLinkPlaceHolder()
$this->assertRaw('<div' . new Attribute(['data-contextual-id' => $id]) . '></div>', format_string('Contextual link placeholder with id @id exists.', ['@id' => $id]));
$this->assertRaw('<div' . new Attribute(['data-contextual-id' => $cached_id]) . '></div>', format_string('Contextual link placeholder with id @id exists.', ['@id' => $cached_id]));
// Get server-rendered contextual links.
// @see \Drupal\contextual\Tests\ContextualDynamicContextTest:renderContextualLinks()
$post = ['ids[0]' => $id, 'ids[1]' => $cached_id];
$response = $this->drupalPostWithFormat('contextual/render', 'json', $post, ['query' => ['destination' => 'test-page']]);
$this->assertResponse(200);
$json = Json::decode($response);
$this->assertIdentical($json[$id], '<ul class="contextual-links"><li class="block-configure"><a href="' . base_path() . 'admin/structure/block/manage/' . $block->id() . '">Configure block</a></li><li class="entityviewedit-form"><a href="' . base_path() . 'admin/structure/views/view/test_view_block/edit/block_1">Edit view</a></li></ul>');
$this->assertIdentical($json[$cached_id], '<ul class="contextual-links"><li class="block-configure"><a href="' . base_path() . 'admin/structure/block/manage/' . $cached_block->id() . '">Configure block</a></li><li class="entityviewedit-form"><a href="' . base_path() . 'admin/structure/views/view/test_view_block/edit/block_1">Edit view</a></li></ul>');
}
}