Initial Drupal 11 with DDEV setup
This commit is contained in:
@ -0,0 +1,6 @@
|
||||
name: 'Configuration override test for Settings Tray'
|
||||
type: module
|
||||
package: Testing
|
||||
version: VERSION
|
||||
dependencies:
|
||||
- drupal:settings_tray
|
||||
@ -0,0 +1,5 @@
|
||||
services:
|
||||
settings_tray_override_test.overrider:
|
||||
class: Drupal\settings_tray_override_test\ConfigOverrider
|
||||
tags:
|
||||
- { name: config.factory.override }
|
||||
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\settings_tray_override_test;
|
||||
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
use Drupal\Core\Config\ConfigFactoryOverrideInterface;
|
||||
use Drupal\Core\Config\StorageInterface;
|
||||
|
||||
/**
|
||||
* Provides an overridden block for Settings Tray testing.
|
||||
*
|
||||
* @see \Drupal\Tests\settings_tray\FunctionalJavascript\SettingsTrayBlockFormTest::testOverriddenDisabled()
|
||||
*/
|
||||
class ConfigOverrider implements ConfigFactoryOverrideInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function loadOverrides($names) {
|
||||
$overrides = [];
|
||||
if (in_array('block.block.overridden_block', $names)) {
|
||||
if (\Drupal::state()->get('settings_tray_override_test.block')) {
|
||||
$overrides = $overrides + ['block.block.overridden_block' => ['settings' => ['label' => 'Now this will be the label.']]];
|
||||
}
|
||||
}
|
||||
if (in_array('system.site', $names)) {
|
||||
if (\Drupal::state()->get('settings_tray_override_test.site_name')) {
|
||||
$overrides = $overrides + ['system.site' => ['name' => 'Llama Fan Club']];
|
||||
}
|
||||
}
|
||||
if (in_array('system.menu.main', $names)) {
|
||||
if (\Drupal::state()->get('settings_tray_override_test.menu')) {
|
||||
$overrides = $overrides + ['system.menu.main' => ['label' => 'Foo label']];
|
||||
}
|
||||
}
|
||||
return $overrides;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheSuffix() {
|
||||
return 'ConfigOverrider';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function createConfigObject($name, $collection = StorageInterface::DEFAULT_COLLECTION) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheableMetadata($name) {
|
||||
return new CacheableMetadata();
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
name: 'Settings Tray Test'
|
||||
type: module
|
||||
description: 'Provides Settings Tray test functionality.'
|
||||
package: Testing
|
||||
version: VERSION
|
||||
dependencies:
|
||||
- drupal:block
|
||||
- drupal:settings_tray
|
||||
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\settings_tray_test\Form;
|
||||
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Plugin\PluginFormBase;
|
||||
use Drupal\Core\StringTranslation\StringTranslationTrait;
|
||||
|
||||
/**
|
||||
* @see \Drupal\settings_tray_test\Plugin\Block\SettingsTrayFormAnnotationIsClassBlock
|
||||
*/
|
||||
class SettingsTrayFormAnnotationIsClassBlockForm extends PluginFormBase {
|
||||
|
||||
use StringTranslationTrait;
|
||||
|
||||
/**
|
||||
* The block plugin.
|
||||
*
|
||||
* @var \Drupal\Core\Block\BlockPluginInterface
|
||||
*/
|
||||
protected $plugin;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
|
||||
$form = $this->plugin->buildConfigurationForm($form, $form_state);
|
||||
|
||||
$form['some_setting'] = [
|
||||
'#type' => 'select',
|
||||
'#title' => $this->t('Some setting'),
|
||||
'#options' => [
|
||||
'a' => 'A',
|
||||
'b' => 'B',
|
||||
],
|
||||
'#required' => TRUE,
|
||||
];
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {}
|
||||
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\settings_tray_test\Plugin\Block;
|
||||
|
||||
use Drupal\Core\Block\Attribute\Block;
|
||||
use Drupal\Core\Block\BlockBase;
|
||||
use Drupal\Core\StringTranslation\TranslatableMarkup;
|
||||
use Drupal\settings_tray_test\Form\SettingsTrayFormAnnotationIsClassBlockForm;
|
||||
|
||||
/**
|
||||
* Block that explicitly provides a "settings_tray" form class.
|
||||
*/
|
||||
#[Block(
|
||||
id: "settings_tray_test_class",
|
||||
admin_label: new TranslatableMarkup("Settings Tray test block: forms[settings_tray]=class"),
|
||||
forms: [
|
||||
'settings_tray' => SettingsTrayFormAnnotationIsClassBlockForm::class,
|
||||
]
|
||||
)]
|
||||
class SettingsTrayFormAnnotationIsClassBlock extends BlockBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function build() {
|
||||
return ['#markup' => '<span>class</span>'];
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\settings_tray_test\Plugin\Block;
|
||||
|
||||
use Drupal\Core\Block\Attribute\Block;
|
||||
use Drupal\Core\Block\BlockBase;
|
||||
use Drupal\Core\StringTranslation\TranslatableMarkup;
|
||||
|
||||
/**
|
||||
* Block that explicitly provides no "settings_tray" form, thus opting out.
|
||||
*/
|
||||
#[Block(
|
||||
id: "settings_tray_test_false",
|
||||
admin_label: new TranslatableMarkup("Settings Tray test block: forms[settings_tray]=FALSE"),
|
||||
forms: [
|
||||
'settings_tray' => FALSE,
|
||||
]
|
||||
)]
|
||||
class SettingsTrayFormAnnotationIsFalseBlock extends BlockBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function build() {
|
||||
return ['#markup' => '<span>FALSE</span>'];
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\settings_tray_test\Plugin\Block;
|
||||
|
||||
use Drupal\Core\Block\Attribute\Block;
|
||||
use Drupal\Core\Block\BlockBase;
|
||||
use Drupal\Core\StringTranslation\TranslatableMarkup;
|
||||
|
||||
/**
|
||||
* Block that does nothing explicit for Settings Tray.
|
||||
*/
|
||||
#[Block(
|
||||
id: "settings_tray_test_none",
|
||||
admin_label: new TranslatableMarkup("Settings Tray test block: forms[settings_tray] is not specified")
|
||||
)]
|
||||
class SettingsTrayFormAnnotationNoneBlock extends BlockBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function build() {
|
||||
return ['#markup' => '<span>none</span>'];
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\settings_tray_test\Plugin\Block;
|
||||
|
||||
use Drupal\Core\Block\Attribute\Block;
|
||||
use Drupal\Core\Block\BlockBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\StringTranslation\TranslatableMarkup;
|
||||
|
||||
/**
|
||||
* Provides a 'Block with validation error' test block.
|
||||
*/
|
||||
#[Block(
|
||||
id: "settings_tray_test_validation",
|
||||
admin_label: new TranslatableMarkup("Block with validation error"),
|
||||
)]
|
||||
class ValidationErrorBlock extends BlockBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function build() {
|
||||
return ['#markup' => '<span>If I had more time this would be very witty :(.</span>'];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
|
||||
parent::validateConfigurationForm($form, $form_state);
|
||||
$form_state->setError($form['label'], 'Sorry system error. Save again.');
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
.dialog-off-canvas-main-canvas.js-settings-tray-edit-mode a,
|
||||
.dialog-off-canvas-main-canvas.js-settings-tray-edit-mode input {
|
||||
pointer-events: inherit !important;
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
name: 'CSS Test fix'
|
||||
type: module
|
||||
description: 'Provides CSS fixes for tests.'
|
||||
package: Testing
|
||||
version: VERSION
|
||||
dependencies:
|
||||
- drupal:settings_tray
|
||||
@ -0,0 +1,5 @@
|
||||
drupal.css_fix:
|
||||
version: VERSION
|
||||
css:
|
||||
theme:
|
||||
css/css_fix.theme.css: {}
|
||||
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\settings_tray_test_css\Hook;
|
||||
|
||||
use Drupal\Core\Hook\Attribute\Hook;
|
||||
|
||||
/**
|
||||
* Hook implementations for settings_tray_test_css.
|
||||
*/
|
||||
class SettingsTrayTestCssHooks {
|
||||
|
||||
/**
|
||||
* Implements hook_page_attachments().
|
||||
*/
|
||||
#[Hook('page_attachments')]
|
||||
public function pageAttachments(array &$attachments): void {
|
||||
// Unconditionally attach an asset to the page.
|
||||
$attachments['#attached']['library'][] = 'settings_tray_test_css/drupal.css_fix';
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\settings_tray\Functional;
|
||||
|
||||
use Drupal\Tests\system\Functional\Module\GenericModuleTestBase;
|
||||
|
||||
/**
|
||||
* Generic module test for settings_tray.
|
||||
*
|
||||
* @group settings_tray
|
||||
*/
|
||||
class GenericTest extends GenericModuleTestBase {}
|
||||
@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\settings_tray\Functional;
|
||||
|
||||
use Drupal\block\Entity\Block;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
|
||||
/**
|
||||
* Tests opening and saving block forms in the off-canvas dialog.
|
||||
*
|
||||
* @group settings_tray
|
||||
*/
|
||||
class SettingsTrayTest extends BrowserTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = [
|
||||
'settings_tray',
|
||||
'settings_tray_test',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
/**
|
||||
* Gets the block CSS selector.
|
||||
*
|
||||
* @param \Drupal\block\Entity\Block $block
|
||||
* The block.
|
||||
*
|
||||
* @return string
|
||||
* The CSS selector.
|
||||
*/
|
||||
protected function getBlockSelector(Block $block): string {
|
||||
return '#block-' . $block->id();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the 3 possible forms[settings_tray] annotations: class, FALSE, none.
|
||||
*
|
||||
* There is also functional JS test coverage to ensure that the two blocks
|
||||
* that support Settings Tray (the "class" and "none" cases) do work
|
||||
* correctly.
|
||||
*
|
||||
* @see SettingsTrayBlockFormTest::testBlocks()
|
||||
*/
|
||||
public function testPossibleAnnotations(): void {
|
||||
$test_block_plugin_ids = [
|
||||
// Block that explicitly provides an "settings_tray" form class.
|
||||
'settings_tray_test_class',
|
||||
// Block that explicitly provides no "settings_tray" form, thus opting
|
||||
// out.
|
||||
'settings_tray_test_false',
|
||||
// Block that does nothing explicit for Settings Tray.
|
||||
'settings_tray_test_none',
|
||||
];
|
||||
|
||||
$placed_blocks = [];
|
||||
foreach ($test_block_plugin_ids as $plugin_id) {
|
||||
$placed_blocks[$plugin_id] = $this->placeBlock($plugin_id);
|
||||
}
|
||||
|
||||
$this->drupalGet('');
|
||||
$web_assert = $this->assertSession();
|
||||
foreach ($placed_blocks as $plugin_id => $placed_block) {
|
||||
$block_selector = $this->getBlockSelector($placed_block);
|
||||
|
||||
// All blocks are rendered.
|
||||
$web_assert->elementExists('css', $block_selector);
|
||||
|
||||
// All blocks except 'settings_tray_test_false' are editable. For more
|
||||
// detailed test coverage, which requires JS execution, see
|
||||
// \Drupal\Tests\settings_tray\FunctionalJavascript\SettingsTrayBlockFormTest::testBlocks().
|
||||
if ($plugin_id === 'settings_tray_test_false') {
|
||||
$web_assert->elementNotExists('css', "{$block_selector}[data-drupal-settingstray=\"editable\"]");
|
||||
}
|
||||
else {
|
||||
$web_assert->elementExists('css', "{$block_selector}[data-drupal-settingstray=\"editable\"]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that certain blocks opt out from Settings Tray.
|
||||
*/
|
||||
public function testOptOut(): void {
|
||||
$web_assert = $this->assertSession();
|
||||
|
||||
$non_excluded_block = $this->placeBlock('system_powered_by_block');
|
||||
$excluded_block_plugin_ids = ['page_title_block', 'system_main_block', 'settings_tray_test_false'];
|
||||
$block_selectors = [];
|
||||
// Place blocks that should be excluded.
|
||||
foreach ($excluded_block_plugin_ids as $excluded_block_plugin_id) {
|
||||
// The block HTML 'id' attribute will be "block-[block_id]".
|
||||
$block_selectors[] = $this->getBlockSelector($this->placeBlock($excluded_block_plugin_id));
|
||||
}
|
||||
$this->drupalGet('');
|
||||
// Assert that block has been marked as "editable" and contextual that
|
||||
// should exist does.
|
||||
$web_assert->elementExists('css', $this->getBlockSelector($non_excluded_block) . "[data-drupal-settingstray=\"editable\"]");
|
||||
// Assert that each block that has a "forms[settings_tray] = FALSE"
|
||||
// annotation:
|
||||
// - is still rendered on the page
|
||||
// - but is not marked as "editable" by settings_tray_preprocess_block()
|
||||
// - and does not have the Settings Tray contextual link.
|
||||
foreach ($block_selectors as $block_selector) {
|
||||
$web_assert->elementExists('css', $block_selector);
|
||||
$web_assert->elementNotExists('css', "{$block_selector}[data-drupal-settingstray=\"editable\"]");
|
||||
$web_assert->elementNotExists('css', "$block_selector [data-settings-tray-edit]");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,119 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\settings_tray\FunctionalJavascript;
|
||||
|
||||
use Drupal\menu_link_content\Entity\MenuLinkContent;
|
||||
use Drupal\user\Entity\Role;
|
||||
|
||||
/**
|
||||
* Tests handling of configuration overrides.
|
||||
*
|
||||
* @group settings_tray
|
||||
*/
|
||||
class ConfigAccessTest extends SettingsTrayTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = [
|
||||
'menu_link_content',
|
||||
'menu_ui',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$user = $this->createUser([
|
||||
'administer blocks',
|
||||
'access contextual links',
|
||||
'access toolbar',
|
||||
]);
|
||||
$this->drupalLogin($user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests access to block forms with related configuration is correct.
|
||||
*/
|
||||
public function testBlockConfigAccess(): void {
|
||||
$page = $this->getSession()->getPage();
|
||||
$web_assert = $this->assertSession();
|
||||
|
||||
// Confirm that System Branding block does not expose Site Name field
|
||||
// without permission.
|
||||
$block = $this->placeBlock('system_branding_block');
|
||||
$this->drupalGet('user');
|
||||
$this->enableEditMode();
|
||||
$this->openBlockForm($this->getBlockSelector($block));
|
||||
// The site name field should not appear because the user doesn't have
|
||||
// permission.
|
||||
$web_assert->fieldNotExists('settings[site_information][site_name]');
|
||||
$page_load_hash_1 = $this->getSession()->evaluateScript('window.performance.timeOrigin');
|
||||
$page->pressButton('Save Site branding');
|
||||
// Pressing the button triggered no validation errors and an AJAX redirect
|
||||
// that reloaded the page.
|
||||
$this->waitForOffCanvasToClose();
|
||||
$page_load_hash_2 = $this->getSession()->evaluateScript('window.performance.timeOrigin');
|
||||
$this->assertNotSame($page_load_hash_1, $page_load_hash_2);
|
||||
$web_assert->elementExists('css', 'div:contains(The block configuration has been saved)');
|
||||
// Confirm we did not save changes to the configuration.
|
||||
$this->assertEquals('Drupal', \Drupal::configFactory()->getEditable('system.site')->get('name'));
|
||||
|
||||
$this->grantPermissions(Role::load(Role::AUTHENTICATED_ID), ['administer site configuration']);
|
||||
$this->drupalGet('user');
|
||||
$this->openBlockForm($this->getBlockSelector($block));
|
||||
// The site name field should appear because the user does have permission.
|
||||
$web_assert->fieldExists('settings[site_information][site_name]');
|
||||
|
||||
// Confirm that the Menu block does not expose menu configuration without
|
||||
// permission.
|
||||
// Add a link or the menu will not render.
|
||||
$menu_link_content = MenuLinkContent::create([
|
||||
'title' => 'This is on the menu',
|
||||
'menu_name' => 'main',
|
||||
'link' => ['uri' => 'route:<front>'],
|
||||
]);
|
||||
$menu_link_content->save();
|
||||
$this->assertNotEmpty($menu_link_content->isEnabled());
|
||||
$menu_without_overrides = \Drupal::configFactory()->getEditable('system.menu.main')->get();
|
||||
$block = $this->placeBlock('system_menu_block:main');
|
||||
$this->drupalGet('user');
|
||||
$web_assert->pageTextContains('This is on the menu');
|
||||
$this->openBlockForm($this->getBlockSelector($block));
|
||||
// Edit menu form should not appear because the user doesn't have
|
||||
// permission.
|
||||
$web_assert->pageTextNotContains('Edit menu');
|
||||
$page_load_hash_3 = $this->getSession()->evaluateScript('window.performance.timeOrigin');
|
||||
$page->pressButton('Save Main navigation');
|
||||
$this->waitForOffCanvasToClose();
|
||||
// Pressing the button triggered no validation errors and an AJAX redirect
|
||||
// that reloaded the page.
|
||||
$page_load_hash_4 = $this->getSession()->evaluateScript('window.performance.timeOrigin');
|
||||
$this->assertNotSame($page_load_hash_3, $page_load_hash_4);
|
||||
$web_assert->elementExists('css', 'div:contains(The block configuration has been saved)');
|
||||
// Confirm we did not save changes to the menu or the menu link.
|
||||
$this->assertEquals($menu_without_overrides, \Drupal::configFactory()->getEditable('system.menu.main')->get());
|
||||
$menu_link_content = MenuLinkContent::load($menu_link_content->id());
|
||||
$this->assertNotEmpty($menu_link_content->isEnabled());
|
||||
// Confirm menu is still on the page.
|
||||
$this->drupalGet('user');
|
||||
$web_assert->pageTextContains('This is on the menu');
|
||||
|
||||
$this->grantPermissions(Role::load(Role::AUTHENTICATED_ID), ['administer menu']);
|
||||
$this->drupalGet('user');
|
||||
$web_assert->pageTextContains('This is on the menu');
|
||||
$this->openBlockForm($this->getBlockSelector($block));
|
||||
// Edit menu form should appear because the user does have permission.
|
||||
$web_assert->pageTextContains('Edit menu');
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,192 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\settings_tray\FunctionalJavascript;
|
||||
|
||||
use Drupal\block\Entity\Block;
|
||||
use Drupal\menu_link_content\Entity\MenuLinkContent;
|
||||
use Drupal\user\Entity\Role;
|
||||
|
||||
/**
|
||||
* Tests handling of configuration overrides.
|
||||
*
|
||||
* @group settings_tray
|
||||
*/
|
||||
class OverriddenConfigurationTest extends SettingsTrayTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = [
|
||||
'settings_tray_override_test',
|
||||
'menu_ui',
|
||||
'menu_link_content',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$user = $this->createUser([
|
||||
'administer blocks',
|
||||
'access contextual links',
|
||||
'access toolbar',
|
||||
]);
|
||||
$this->drupalLogin($user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests blocks with overridden related configuration removed when overridden.
|
||||
*/
|
||||
public function testOverriddenConfigurationRemoved(): void {
|
||||
$web_assert = $this->assertSession();
|
||||
$page = $this->getSession()->getPage();
|
||||
$this->grantPermissions(Role::load(Role::AUTHENTICATED_ID), ['administer site configuration', 'administer menu']);
|
||||
|
||||
// Confirm the branding block does include 'site_information' section when
|
||||
// the site name is not overridden.
|
||||
$branding_block = $this->placeBlock('system_branding_block');
|
||||
$this->drupalGet('user');
|
||||
$this->enableEditMode();
|
||||
$this->openBlockForm($this->getBlockSelector($branding_block));
|
||||
$web_assert->fieldExists('settings[site_information][site_name]');
|
||||
// Confirm the branding block does not include 'site_information' section
|
||||
// when the site name is overridden.
|
||||
$this->container->get('state')->set('settings_tray_override_test.site_name', TRUE);
|
||||
$this->drupalGet('user');
|
||||
$this->openBlockForm($this->getBlockSelector($branding_block));
|
||||
$web_assert->fieldNotExists('settings[site_information][site_name]');
|
||||
$page_load_hash_1 = $this->getSession()->evaluateScript('window.performance.timeOrigin');
|
||||
$page->pressButton('Save Site branding');
|
||||
// Pressing the button triggered no validation errors and an AJAX redirect
|
||||
// that reloaded the page.
|
||||
$this->waitForOffCanvasToClose();
|
||||
$page_load_hash_2 = $this->getSession()->evaluateScript('window.performance.timeOrigin');
|
||||
$this->assertNotSame($page_load_hash_1, $page_load_hash_2);
|
||||
$web_assert->elementExists('css', 'div:contains(The block configuration has been saved)');
|
||||
// Confirm we did not save changes to the configuration.
|
||||
$this->assertEquals('Llama Fan Club', \Drupal::configFactory()->get('system.site')->get('name'));
|
||||
$this->assertEquals('Drupal', \Drupal::configFactory()->getEditable('system.site')->get('name'));
|
||||
|
||||
// Add a link or the menu will not render.
|
||||
$menu_link_content = MenuLinkContent::create([
|
||||
'title' => 'This is on the menu',
|
||||
'menu_name' => 'main',
|
||||
'link' => ['uri' => 'route:<front>'],
|
||||
]);
|
||||
$menu_link_content->save();
|
||||
// Confirm the menu block does include menu section when the menu is not
|
||||
// overridden.
|
||||
$menu_block = $this->placeBlock('system_menu_block:main');
|
||||
$this->drupalGet('user');
|
||||
$web_assert->pageTextContains('This is on the menu');
|
||||
$this->openBlockForm($this->getBlockSelector($menu_block));
|
||||
$web_assert->elementExists('css', '#menu-overview');
|
||||
|
||||
// Confirm the menu block does not include menu section when the menu is
|
||||
// overridden.
|
||||
$this->container->get('state')->set('settings_tray_override_test.menu', TRUE);
|
||||
$this->drupalGet('user');
|
||||
$web_assert->pageTextContains('This is on the menu');
|
||||
$menu_with_overrides = \Drupal::configFactory()->get('system.menu.main')->get();
|
||||
$menu_without_overrides = \Drupal::configFactory()->getEditable('system.menu.main')->get();
|
||||
$this->openBlockForm($this->getBlockSelector($menu_block));
|
||||
$web_assert->elementNotExists('css', '#menu-overview');
|
||||
$page_load_hash_3 = $this->getSession()->evaluateScript('window.performance.timeOrigin');
|
||||
$page->pressButton('Save Main navigation');
|
||||
// Pressing the button triggered no validation errors and an AJAX redirect
|
||||
// that reloaded the page.
|
||||
$this->waitForOffCanvasToClose();
|
||||
$page_load_hash_4 = $this->getSession()->evaluateScript('window.performance.timeOrigin');
|
||||
$this->assertNotSame($page_load_hash_3, $page_load_hash_4);
|
||||
$web_assert->elementExists('css', 'div:contains(The block configuration has been saved)');
|
||||
// Confirm we did not save changes to the configuration.
|
||||
$this->assertEquals('Foo label', \Drupal::configFactory()->get('system.menu.main')->get('label'));
|
||||
$this->assertEquals('Main navigation', \Drupal::configFactory()->getEditable('system.menu.main')->get('label'));
|
||||
$this->assertEquals($menu_with_overrides, \Drupal::configFactory()->get('system.menu.main')->get());
|
||||
$this->assertEquals($menu_without_overrides, \Drupal::configFactory()->getEditable('system.menu.main')->get());
|
||||
$web_assert->pageTextContains('This is on the menu');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that blocks with configuration overrides are disabled.
|
||||
*/
|
||||
public function testOverriddenBlock(): void {
|
||||
$web_assert = $this->assertSession();
|
||||
$page = $this->getSession()->getPage();
|
||||
$overridden_block = $this->placeBlock('system_powered_by_block', [
|
||||
'id' => 'overridden_block',
|
||||
'label_display' => 1,
|
||||
'label' => 'This will be overridden.',
|
||||
]);
|
||||
$this->drupalGet('user');
|
||||
$block_selector = $this->getBlockSelector($overridden_block);
|
||||
// Confirm the block is marked as Settings Tray editable.
|
||||
$this->assertEquals('editable', $page->find('css', $block_selector)->getAttribute('data-drupal-settingstray'));
|
||||
// Confirm the label is not overridden.
|
||||
$web_assert->elementContains('css', $block_selector, 'This will be overridden.');
|
||||
$this->enableEditMode();
|
||||
$this->openBlockForm($block_selector);
|
||||
|
||||
// Confirm the block Settings Tray functionality is disabled when block is
|
||||
// overridden.
|
||||
$this->container->get('state')->set('settings_tray_override_test.block', TRUE);
|
||||
$overridden_block->save();
|
||||
$block_config = \Drupal::configFactory()->getEditable('block.block.overridden_block');
|
||||
$block_config->set('settings', $block_config->get('settings'))->save();
|
||||
|
||||
$this->drupalGet('user');
|
||||
$this->assertOverriddenBlockDisabled($overridden_block, 'Now this will be the label.');
|
||||
|
||||
// Test a non-overridden block does show the form in the off-canvas dialog.
|
||||
$block = $this->placeBlock('system_powered_by_block', [
|
||||
'label_display' => 1,
|
||||
'label' => 'Foo label',
|
||||
]);
|
||||
$this->drupalGet('user');
|
||||
$block_selector = $this->getBlockSelector($block);
|
||||
// Confirm the block is marked as Settings Tray editable.
|
||||
$this->assertEquals('editable', $page->find('css', $block_selector)->getAttribute('data-drupal-settingstray'));
|
||||
// Confirm the label is not overridden.
|
||||
$web_assert->elementContains('css', $block_selector, 'Foo label');
|
||||
$this->openBlockForm($block_selector);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that an overridden block has Settings Tray disabled.
|
||||
*
|
||||
* @param \Drupal\block\Entity\Block $overridden_block
|
||||
* The overridden block.
|
||||
* @param string $override_text
|
||||
* The override text that should appear in the block.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
protected function assertOverriddenBlockDisabled(Block $overridden_block, string $override_text): void {
|
||||
$web_assert = $this->assertSession();
|
||||
$page = $this->getSession()->getPage();
|
||||
$block_selector = $this->getBlockSelector($overridden_block);
|
||||
$block_id = $overridden_block->id();
|
||||
// Confirm the block does not have a quick edit link.
|
||||
$contextual_links = $page->findAll('css', "$block_selector .contextual-links li a");
|
||||
$this->assertNotEmpty($contextual_links);
|
||||
foreach ($contextual_links as $link) {
|
||||
$this->assertStringNotContainsString("/admin/structure/block/manage/$block_id/off-canvas", $link->getAttribute('href'));
|
||||
}
|
||||
// Confirm the block is not marked as Settings Tray editable.
|
||||
$this->assertFalse($page->find('css', $block_selector)
|
||||
->hasAttribute('data-drupal-settingstray'));
|
||||
|
||||
// Confirm the text is actually overridden.
|
||||
$web_assert->elementContains('css', $this->getBlockSelector($overridden_block), $override_text);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,291 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\settings_tray\FunctionalJavascript;
|
||||
|
||||
use Drupal\settings_tray_test\Plugin\Block\SettingsTrayFormAnnotationIsClassBlock;
|
||||
use Drupal\settings_tray_test\Plugin\Block\SettingsTrayFormAnnotationNoneBlock;
|
||||
use Drupal\user\Entity\Role;
|
||||
|
||||
/**
|
||||
* Testing opening and saving block forms in the off-canvas dialog.
|
||||
*
|
||||
* @group settings_tray
|
||||
*/
|
||||
class SettingsTrayBlockFormTest extends SettingsTrayTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = [
|
||||
'node',
|
||||
'search',
|
||||
'settings_tray_test',
|
||||
'off_canvas_test',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
if ($this->name() === 'testEditModeEnableDisable') {
|
||||
$this->markTestSkipped("Skipped due to frequent random test failures. See https://www.drupal.org/project/drupal/issues/3317520");
|
||||
}
|
||||
|
||||
parent::setUp();
|
||||
|
||||
$user = $this->createUser([
|
||||
'administer blocks',
|
||||
'access contextual links',
|
||||
'access toolbar',
|
||||
'administer nodes',
|
||||
'search content',
|
||||
]);
|
||||
$this->drupalLogin($user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests opening off-canvas dialog by click blocks and elements in the blocks.
|
||||
*/
|
||||
public function testBlocks(): void {
|
||||
foreach ($this->getBlockTests() as $test) {
|
||||
call_user_func_array([$this, 'doTestBlocks'], array_values($test));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests opening off-canvas dialog by click blocks and elements in the blocks.
|
||||
*/
|
||||
protected function doTestBlocks($theme, $block_plugin, $new_page_text, $element_selector, $label_selector, $button_text, $toolbar_item, $permissions): void {
|
||||
if ($permissions) {
|
||||
$this->grantPermissions(Role::load(Role::AUTHENTICATED_ID), $permissions);
|
||||
}
|
||||
if ($new_page_text) {
|
||||
// Some asserts can be based on this value, so it should not be the same
|
||||
// for different blocks, because it can be saved in the site config.
|
||||
$new_page_text = $new_page_text . ' ' . $theme . ' ' . $block_plugin;
|
||||
}
|
||||
$web_assert = $this->assertSession();
|
||||
$page = $this->getSession()->getPage();
|
||||
$this->enableTheme($theme);
|
||||
$block = $this->placeBlock($block_plugin);
|
||||
$block_selector = $this->getBlockSelector($block);
|
||||
$block_id = $block->id();
|
||||
$this->drupalGet('user');
|
||||
|
||||
$link = $web_assert->waitForElement('css', "$block_selector .contextual-links li a");
|
||||
$this->assertEquals('Quick edit', $link->getHtml(), "'Quick edit' is the first contextual link for the block.");
|
||||
$destination = (string) $this->loggedInUser->toUrl()->toString();
|
||||
$this->assertStringContainsString("/admin/structure/block/manage/$block_id/settings-tray?destination=$destination", $link->getAttribute('href'));
|
||||
|
||||
if (isset($toolbar_item)) {
|
||||
// Check that you can open a toolbar tray and it will be closed after
|
||||
// entering edit mode.
|
||||
if ($element = $page->find('css', "#toolbar-administration a.is-active")) {
|
||||
// If a tray was open from page load close it.
|
||||
$element->click();
|
||||
$web_assert->assertNoElementAfterWait('css', "#toolbar-administration a.is-active");
|
||||
}
|
||||
$page->find('css', $toolbar_item)->click();
|
||||
$this->assertElementVisibleAfterWait('css', "{$toolbar_item}.is-active");
|
||||
}
|
||||
$this->enableEditMode();
|
||||
if (isset($toolbar_item)) {
|
||||
$web_assert->assertNoElementAfterWait('css', "{$toolbar_item}.is-active");
|
||||
}
|
||||
$this->openBlockForm($block_selector);
|
||||
switch ($block_plugin) {
|
||||
case 'system_powered_by_block':
|
||||
// Confirm "Display Title" is not checked.
|
||||
$web_assert->checkboxNotChecked('settings[label_display]');
|
||||
// Confirm Title is not visible.
|
||||
$this->assertFalse($this->isLabelInputVisible(), 'Label is not visible');
|
||||
$page->checkField('settings[label_display]');
|
||||
$this->assertTrue($this->isLabelInputVisible(), 'Label is visible');
|
||||
// Fill out form, save the form.
|
||||
$page->fillField('settings[label]', $new_page_text);
|
||||
|
||||
break;
|
||||
|
||||
case 'system_branding_block':
|
||||
// Fill out form, save the form.
|
||||
$page->fillField('settings[site_information][site_name]', $new_page_text);
|
||||
break;
|
||||
|
||||
case 'settings_tray_test_class':
|
||||
$web_assert->elementExists('css', '[data-drupal-selector="edit-settings-some-setting"]');
|
||||
break;
|
||||
}
|
||||
|
||||
if (isset($new_page_text)) {
|
||||
$page->pressButton($button_text);
|
||||
// Make sure the changes are present.
|
||||
$new_page_text_locator = "$block_selector $label_selector:contains($new_page_text)";
|
||||
$this->assertNotEmpty($web_assert->waitForElementVisible('css', $new_page_text_locator));
|
||||
// The page is loaded with the new change but make sure page is
|
||||
// completely loaded.
|
||||
$this->assertPageLoadComplete();
|
||||
}
|
||||
|
||||
$this->openBlockForm($block_selector);
|
||||
|
||||
$this->disableEditMode();
|
||||
// Canvas should close when editing module is closed.
|
||||
$this->waitForOffCanvasToClose();
|
||||
|
||||
$this->enableEditMode();
|
||||
|
||||
// Open block form by clicking an element inside the block.
|
||||
// This confirms that default action for links and form elements is
|
||||
// suppressed.
|
||||
$this->openBlockForm("$block_selector {$element_selector}", $block_selector);
|
||||
$web_assert->elementTextContains('css', '.contextual-toolbar-tab button', 'Editing');
|
||||
$web_assert->elementAttributeContains('css', '.dialog-off-canvas-main-canvas', 'class', 'js-settings-tray-edit-mode');
|
||||
// Simulate press the Escape key.
|
||||
$this->getSession()->executeScript('jQuery("body").trigger(jQuery.Event("keyup", { keyCode: 27 }));');
|
||||
$this->waitForOffCanvasToClose();
|
||||
$this->getSession()->wait(100);
|
||||
$this->getSession()->getPage()->find('css', static::TOOLBAR_EDIT_LINK_SELECTOR)->mouseOver();
|
||||
$this->assertEditModeDisabled();
|
||||
$this->assertNotEmpty($web_assert->waitForElement('css', '#drupal-live-announce:contains(Exited edit mode)'));
|
||||
$web_assert->assertNoElementAfterWait('css', '.contextual-toolbar-tab button:contains(Editing)');
|
||||
$web_assert->elementAttributeNotContains('css', '.dialog-off-canvas-main-canvas', 'class', 'js-settings-tray-edit-mode');
|
||||
|
||||
// Clean up test data so each test does not impact the next.
|
||||
$block->delete();
|
||||
if ($permissions) {
|
||||
user_role_revoke_permissions(Role::AUTHENTICATED_ID, $permissions);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates tests for ::testBlocks().
|
||||
*/
|
||||
public function getBlockTests() {
|
||||
$blocks = [];
|
||||
foreach (static::getTestThemes() as $theme) {
|
||||
$blocks += [
|
||||
"$theme: block-powered" => [
|
||||
'theme' => $theme,
|
||||
'block_plugin' => 'system_powered_by_block',
|
||||
'new_page_text' => 'Can you imagine anyone showing the label on this block',
|
||||
'element_selector' => 'span a',
|
||||
'label_selector' => 'h2',
|
||||
'button_text' => 'Save Powered by Drupal',
|
||||
'toolbar_item' => '#toolbar-item-user',
|
||||
NULL,
|
||||
],
|
||||
"$theme: block-branding" => [
|
||||
'theme' => $theme,
|
||||
'block_plugin' => 'system_branding_block',
|
||||
'new_page_text' => 'The site that will live a very short life',
|
||||
'element_selector' => "a[rel='home']:last-child",
|
||||
'label_selector' => "a[rel='home']:last-child",
|
||||
'button_text' => 'Save Site branding',
|
||||
'toolbar_item' => '#toolbar-item-administration',
|
||||
['administer site configuration'],
|
||||
],
|
||||
"$theme: block-search" => [
|
||||
'theme' => $theme,
|
||||
'block_plugin' => 'search_form_block',
|
||||
'new_page_text' => NULL,
|
||||
'element_selector' => '[data-drupal-selector="edit-submit"]',
|
||||
'label_selector' => 'h2',
|
||||
'button_text' => 'Save Search form',
|
||||
'toolbar_item' => NULL,
|
||||
NULL,
|
||||
],
|
||||
// This is the functional JS test coverage accompanying
|
||||
// \Drupal\Tests\settings_tray\Functional\SettingsTrayTest::testPossibleAnnotations().
|
||||
"$theme: " . SettingsTrayFormAnnotationIsClassBlock::class => [
|
||||
'theme' => $theme,
|
||||
'block_plugin' => 'settings_tray_test_class',
|
||||
'new_page_text' => NULL,
|
||||
'element_selector' => 'span',
|
||||
'label_selector' => NULL,
|
||||
'button_text' => NULL,
|
||||
'toolbar_item' => NULL,
|
||||
NULL,
|
||||
],
|
||||
// This is the functional JS test coverage accompanying
|
||||
// \Drupal\Tests\settings_tray\Functional\SettingsTrayTest::testPossibleAnnotations().
|
||||
"$theme: " . SettingsTrayFormAnnotationNoneBlock::class => [
|
||||
'theme' => $theme,
|
||||
'block_plugin' => 'settings_tray_test_none',
|
||||
'new_page_text' => NULL,
|
||||
'element_selector' => 'span',
|
||||
'label_selector' => NULL,
|
||||
'button_text' => NULL,
|
||||
'toolbar_item' => NULL,
|
||||
NULL,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
return $blocks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests enabling and disabling Edit Mode.
|
||||
*/
|
||||
public function testEditModeEnableDisable(): void {
|
||||
foreach (static::getTestThemes() as $theme) {
|
||||
$this->enableTheme($theme);
|
||||
$block = $this->placeBlock('system_powered_by_block');
|
||||
foreach (['contextual_link', 'toolbar_link'] as $enable_option) {
|
||||
$this->drupalGet('user');
|
||||
$this->assertEditModeDisabled();
|
||||
switch ($enable_option) {
|
||||
// Enable Edit mode.
|
||||
case 'contextual_link':
|
||||
$this->clickContextualLink($this->getBlockSelector($block), "Quick edit");
|
||||
$this->waitForOffCanvasToOpen();
|
||||
$this->assertEditModeEnabled();
|
||||
break;
|
||||
|
||||
case 'toolbar_link':
|
||||
$this->enableEditMode();
|
||||
break;
|
||||
}
|
||||
$this->disableEditMode();
|
||||
|
||||
// Make another page request to ensure Edit mode is still disabled.
|
||||
$this->drupalGet('user');
|
||||
$this->assertEditModeDisabled();
|
||||
// Make sure on this page request it also re-enables and disables
|
||||
// correctly.
|
||||
$this->enableEditMode();
|
||||
$this->disableEditMode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that validation errors appear in the off-canvas dialog.
|
||||
*/
|
||||
public function testValidationMessages(): void {
|
||||
$page = $this->getSession()->getPage();
|
||||
$web_assert = $this->assertSession();
|
||||
foreach (static::getTestThemes() as $theme) {
|
||||
$this->enableTheme($theme);
|
||||
$block = $this->placeBlock('settings_tray_test_validation');
|
||||
$this->drupalGet('user');
|
||||
$this->enableEditMode();
|
||||
$this->openBlockForm($this->getBlockSelector($block));
|
||||
$page->pressButton('Save Block with validation error');
|
||||
$web_assert->assertWaitOnAjaxRequest();
|
||||
// The settings_tray_test_validation test plugin form always has a
|
||||
// validation error.
|
||||
$web_assert->elementContains('css', '#drupal-off-canvas', 'Sorry system error. Save again');
|
||||
$this->disableEditMode();
|
||||
$block->delete();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,191 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\settings_tray\FunctionalJavascript;
|
||||
|
||||
use Drupal\block\Entity\Block;
|
||||
use Drupal\Tests\contextual\FunctionalJavascript\ContextualLinkClickTrait;
|
||||
use Drupal\Tests\system\FunctionalJavascript\OffCanvasTestBase;
|
||||
|
||||
/**
|
||||
* Base class for Settings Tray tests.
|
||||
*/
|
||||
abstract class SettingsTrayTestBase extends OffCanvasTestBase {
|
||||
|
||||
use ContextualLinkClickTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = [
|
||||
'settings_tray',
|
||||
// Add test module to override CSS pointer-events properties because they
|
||||
// cause test failures.
|
||||
'settings_tray_test_css',
|
||||
];
|
||||
|
||||
const TOOLBAR_EDIT_LINK_SELECTOR = '#toolbar-bar div.contextual-toolbar-tab button';
|
||||
|
||||
const LABEL_INPUT_SELECTOR = 'input[data-drupal-selector="edit-settings-label"]';
|
||||
|
||||
/**
|
||||
* Open block form by clicking the element found with a css selector.
|
||||
*
|
||||
* @param string $block_selector
|
||||
* A css selector selects the block or an element within it.
|
||||
* @param string $contextual_link_container
|
||||
* The element that contains the contextual links. If none provide the
|
||||
* $block_selector will be used.
|
||||
*/
|
||||
protected function openBlockForm($block_selector, $contextual_link_container = '') {
|
||||
if (!$contextual_link_container) {
|
||||
$contextual_link_container = $block_selector;
|
||||
}
|
||||
// Ensure that contextual link element is present because this is required
|
||||
// to open the off-canvas dialog in edit mode.
|
||||
$contextual_link = $this->assertSession()->waitForElement('css', "$contextual_link_container .contextual-links a");
|
||||
$this->assertNotEmpty($contextual_link);
|
||||
// When page first loads Edit Mode is not triggered until first contextual
|
||||
// link is added.
|
||||
$this->assertNotEmpty($this->assertSession()->waitForElementVisible('css', '.dialog-off-canvas-main-canvas.js-settings-tray-edit-mode'));
|
||||
// @todo https://www.drupal.org/project/drupal/issues/3317520 Work why the
|
||||
// sleep is necessary in.
|
||||
usleep(100000);
|
||||
|
||||
$block = $this->getSession()->getPage()->find('css', $block_selector);
|
||||
$block->mouseOver();
|
||||
$block->click();
|
||||
$this->waitForOffCanvasToOpen();
|
||||
$this->assertOffCanvasBlockFormIsValid();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables edit mode by pressing edit button in the toolbar.
|
||||
*/
|
||||
protected function enableEditMode() {
|
||||
$this->pressToolbarEditButton();
|
||||
$this->assertEditModeEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables edit mode by pressing edit button in the toolbar.
|
||||
*/
|
||||
protected function disableEditMode() {
|
||||
$this->pressToolbarEditButton();
|
||||
$this->assertEditModeDisabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Press the toolbar Edit button provided by the contextual module.
|
||||
*/
|
||||
protected function pressToolbarEditButton() {
|
||||
$this->assertSession()->waitForElement('css', '[data-contextual-id] .contextual-links a');
|
||||
$edit_button = $this->getSession()
|
||||
->getPage()
|
||||
->find('css', static::TOOLBAR_EDIT_LINK_SELECTOR);
|
||||
$edit_button->mouseOver();
|
||||
$edit_button->press();
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that edit mode has been properly disabled.
|
||||
*/
|
||||
protected function assertEditModeDisabled() {
|
||||
$web_assert = $this->assertSession();
|
||||
$page = $this->getSession()->getPage();
|
||||
$page->find('css', static::TOOLBAR_EDIT_LINK_SELECTOR)->mouseOver();
|
||||
$this->assertTrue($page->waitFor(10, function ($page) {
|
||||
return !$page->find('css', '.contextual .trigger:not(.visually-hidden)');
|
||||
}));
|
||||
// Contextual triggers should be hidden.
|
||||
$web_assert->elementExists('css', '.contextual .trigger.visually-hidden');
|
||||
// No contextual triggers should be not hidden.
|
||||
$web_assert->elementNotExists('css', '.contextual .trigger:not(.visually-hidden)');
|
||||
// The toolbar edit button should read "Edit".
|
||||
$web_assert->elementContains('css', static::TOOLBAR_EDIT_LINK_SELECTOR, 'Edit');
|
||||
// The main canvas element should NOT have the "js-settings-tray-edit-mode"
|
||||
// class.
|
||||
$web_assert->elementNotExists('css', '.dialog-off-canvas-main-canvas.js-settings-tray-edit-mode');
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that edit mode has been properly enabled.
|
||||
*/
|
||||
protected function assertEditModeEnabled() {
|
||||
$web_assert = $this->assertSession();
|
||||
$page = $this->getSession()->getPage();
|
||||
// Move the mouse over the toolbar button so that isn't over a contextual
|
||||
// links area which cause the contextual link to be shown.
|
||||
$page->find('css', static::TOOLBAR_EDIT_LINK_SELECTOR)->mouseOver();
|
||||
$this->assertTrue($page->waitFor(10, function ($page) {
|
||||
return !$page->find('css', '.contextual .trigger.visually-hidden');
|
||||
}));
|
||||
// No contextual triggers should be hidden.
|
||||
$web_assert->elementNotExists('css', '.contextual .trigger.visually-hidden');
|
||||
// The toolbar edit button should read "Editing".
|
||||
$web_assert->elementContains('css', static::TOOLBAR_EDIT_LINK_SELECTOR, 'Editing');
|
||||
// The main canvas element should have the "js-settings-tray-edit-mode"
|
||||
// class.
|
||||
$web_assert->elementExists('css', '.dialog-off-canvas-main-canvas.js-settings-tray-edit-mode');
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that Off-Canvas block form is valid.
|
||||
*/
|
||||
protected function assertOffCanvasBlockFormIsValid() {
|
||||
$web_assert = $this->assertSession();
|
||||
// Confirm that Block title display label has been changed.
|
||||
$web_assert->elementTextContains('css', '.form-item-settings-label-display label', 'Display block title');
|
||||
// Confirm Block title label is shown if checkbox is checked.
|
||||
if ($this->getSession()->getPage()->find('css', 'input[name="settings[label_display]"]')->isChecked()) {
|
||||
$this->assertTrue($this->isLabelInputVisible(), 'Label is visible');
|
||||
$web_assert->elementTextContains('css', '.form-item-settings-label label', 'Block title');
|
||||
}
|
||||
else {
|
||||
$this->assertFalse($this->isLabelInputVisible(), 'Label is not visible');
|
||||
}
|
||||
|
||||
// Check that common block form elements exist.
|
||||
$web_assert->elementExists('css', static::LABEL_INPUT_SELECTOR);
|
||||
$web_assert->elementExists('css', 'input[data-drupal-selector="edit-settings-label-display"]');
|
||||
// Check that advanced block form elements do not exist.
|
||||
$web_assert->elementNotExists('css', 'input[data-drupal-selector="edit-visibility-request-path-pages"]');
|
||||
$web_assert->elementNotExists('css', 'select[data-drupal-selector="edit-region"]');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static function getTestThemes(): array {
|
||||
// Remove 'claro' theme. Settings Tray "Edit Mode" will not work with this
|
||||
// theme because it removes all contextual links.
|
||||
return array_filter(parent::getTestThemes(), function ($theme) {
|
||||
return ($theme !== 'claro');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the block CSS selector.
|
||||
*
|
||||
* @param \Drupal\block\Entity\Block $block
|
||||
* The block.
|
||||
*
|
||||
* @return string
|
||||
* The CSS selector.
|
||||
*/
|
||||
public function getBlockSelector(Block $block) {
|
||||
return '#block-' . str_replace('_', '-', $block->id());
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the label input is visible.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if the label is visible, FALSE if it is not.
|
||||
*/
|
||||
protected function isLabelInputVisible(): bool {
|
||||
return $this->getSession()->getPage()->find('css', static::LABEL_INPUT_SELECTOR)->isVisible();
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\settings_tray\Unit\Access;
|
||||
|
||||
use Drupal\block\BlockInterface;
|
||||
use Drupal\Core\Access\AccessResultAllowed;
|
||||
use Drupal\Core\Access\AccessResultInterface;
|
||||
use Drupal\Core\Access\AccessResultNeutral;
|
||||
use Drupal\Core\Block\BlockPluginInterface;
|
||||
use Drupal\Core\Plugin\PluginWithFormsInterface;
|
||||
use Drupal\settings_tray\Access\BlockPluginHasSettingsTrayFormAccessCheck;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Drupal\TestTools\Random;
|
||||
use Prophecy\Argument;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\settings_tray\Access\BlockPluginHasSettingsTrayFormAccessCheck
|
||||
* @group settings_tray
|
||||
*/
|
||||
class BlockPluginHasSettingsTrayFormAccessCheckTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* @covers ::access
|
||||
* @covers ::accessBlockPlugin
|
||||
* @dataProvider providerTestAccess
|
||||
*/
|
||||
public function testAccess($with_forms, array $plugin_definition, AccessResultInterface $expected_access_result): void {
|
||||
$block_plugin = $this->prophesize()->willImplement(BlockPluginInterface::class);
|
||||
|
||||
if ($with_forms) {
|
||||
$block_plugin->willImplement(PluginWithFormsInterface::class);
|
||||
$block_plugin->hasFormClass(Argument::type('string'))->will(function ($arguments) use ($plugin_definition) {
|
||||
return !empty($plugin_definition['forms'][$arguments[0]]);
|
||||
});
|
||||
}
|
||||
|
||||
$block = $this->prophesize(BlockInterface::class);
|
||||
$block->getPlugin()->willReturn($block_plugin->reveal());
|
||||
|
||||
$access_check = new BlockPluginHasSettingsTrayFormAccessCheck();
|
||||
$this->assertEquals($expected_access_result, $access_check->access($block->reveal()));
|
||||
$this->assertEquals($expected_access_result, $access_check->accessBlockPlugin($block_plugin->reveal()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for ::testAccess().
|
||||
*/
|
||||
public static function providerTestAccess() {
|
||||
$annotation_forms_settings_tray_class = [
|
||||
'forms' => [
|
||||
'settings_tray' => Random::machineName(),
|
||||
],
|
||||
];
|
||||
$annotation_forms_settings_tray_not_set = [];
|
||||
$annotation_forms_settings_tray_false = [
|
||||
'forms' => [
|
||||
'settings_tray' => FALSE,
|
||||
],
|
||||
];
|
||||
return [
|
||||
'block plugin with forms, forms[settings_tray] set to class' => [
|
||||
TRUE,
|
||||
$annotation_forms_settings_tray_class,
|
||||
new AccessResultAllowed(),
|
||||
],
|
||||
'block plugin with forms, forms[settings_tray] not set' => [
|
||||
TRUE,
|
||||
$annotation_forms_settings_tray_not_set,
|
||||
new AccessResultNeutral(),
|
||||
],
|
||||
'block plugin with forms, forms[settings_tray] set to FALSE' => [
|
||||
TRUE,
|
||||
$annotation_forms_settings_tray_false,
|
||||
new AccessResultNeutral(),
|
||||
],
|
||||
// In practice, all block plugins extend BlockBase, which means they all
|
||||
// implement PluginWithFormsInterface, but this may change in the future.
|
||||
// This ensures Settings Tray will continue to work correctly.
|
||||
'block plugin without forms, forms[settings_tray] set to class' => [
|
||||
FALSE,
|
||||
$annotation_forms_settings_tray_class,
|
||||
new AccessResultNeutral(),
|
||||
],
|
||||
'block plugin without forms, forms[settings_tray] not set' => [
|
||||
FALSE,
|
||||
$annotation_forms_settings_tray_not_set,
|
||||
new AccessResultNeutral(),
|
||||
],
|
||||
'block plugin without forms, forms[settings_tray] set to FALSE' => [
|
||||
FALSE,
|
||||
$annotation_forms_settings_tray_false,
|
||||
new AccessResultNeutral(),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user