BlockContentTypeTest.php 10.4 KB
Newer Older
1 2
<?php

3
namespace Drupal\Tests\block_content\Functional;
4

5
use Drupal\Component\Render\FormattableMarkup;
6
use Drupal\block_content\Entity\BlockContentType;
7
use Drupal\Component\Utility\Html;
8
use Drupal\Core\Url;
9
use Drupal\Tests\system\Functional\Menu\AssertBreadcrumbTrait;
10 11

/**
12 13 14
 * Ensures that custom block type functions work correctly.
 *
 * @group block_content
15
 */
16
class BlockContentTypeTest extends BlockContentTestBase {
17

18
  use AssertBreadcrumbTrait;
19 20 21 22 23
  /**
   * Modules to enable.
   *
   * @var array
   */
24
  public static $modules = ['field_ui'];
25

26 27 28 29 30
  /**
   * {@inheritdoc}
   */
  protected $defaultTheme = 'classy';

31 32 33 34 35
  /**
   * Permissions to grant admin user.
   *
   * @var array
   */
36
  protected $permissions = [
37
    'administer blocks',
38
    'administer block_content fields',
39
  ];
40

41 42 43 44 45 46 47
  /**
   * Whether or not to create an initial block type.
   *
   * @var bool
   */
  protected $autoCreateBasicBlockType = FALSE;

48 49 50 51 52 53
  protected function setUp() {
    parent::setUp();

    $this->drupalPlaceBlock('page_title_block');
  }

54 55 56
  /**
   * Tests creating a block type programmatically and via a form.
   */
57
  public function testBlockContentTypeCreation() {
58
    // Log in a test user.
59 60 61 62 63
    $this->drupalLogin($this->adminUser);

    // Test the page with no block-types.
    $this->drupalGet('block/add');
    $this->assertResponse(200);
64 65
    $this->assertText('You have not created any block types yet');
    $this->clickLink('block type creation page');
66 67

    // Create a block type via the user interface.
68
    $edit = [
69 70
      'id' => 'foo',
      'label' => 'title for foo',
71
    ];
72
    $this->drupalPostForm(NULL, $edit, t('Save'));
73
    $block_type = BlockContentType::load('foo');
74
    $this->assertInstanceOf(BlockContentType::class, $block_type);
75

76
    $field_definitions = \Drupal::service('entity_field.manager')->getFieldDefinitions('block_content', 'foo');
77
    $this->assertTrue(isset($field_definitions['body']), 'Body field created when using the UI to create block content types.');
78

79
    // Check that the block type was created in site default language.
80
    $default_langcode = \Drupal::languageManager()->getDefaultLanguage()->getId();
81
    $this->assertEqual($block_type->language()->getId(), $default_langcode);
82 83 84

    // Create block types programmatically.
    $this->createBlockContentType('basic', TRUE);
85
    $field_definitions = \Drupal::service('entity_field.manager')->getFieldDefinitions('block_content', 'basic');
86 87 88
    $this->assertTrue(isset($field_definitions['body']), "Body field for 'basic' block type created when using the testing API to create block content types.");

    $this->createBlockContentType('other');
89
    $field_definitions = \Drupal::service('entity_field.manager')->getFieldDefinitions('block_content', 'other');
90 91 92
    $this->assertFalse(isset($field_definitions['body']), "Body field for 'other' block type not created when using the testing API to create block content types.");

    $block_type = BlockContentType::load('other');
93
    $this->assertInstanceOf(BlockContentType::class, $block_type);
94 95 96

    $this->drupalGet('block/add/' . $block_type->id());
    $this->assertResponse(200);
97 98 99 100 101
  }

  /**
   * Tests editing a block type using the UI.
   */
102
  public function testBlockContentTypeEditing() {
103
    $this->drupalPlaceBlock('system_breadcrumb_block');
104 105 106
    // Now create an initial block-type.
    $this->createBlockContentType('basic', TRUE);

107 108
    $this->drupalLogin($this->adminUser);
    // We need two block types to prevent /block/add redirecting.
109
    $this->createBlockContentType('other');
110

111
    $field_definitions = \Drupal::service('entity_field.manager')->getFieldDefinitions('block_content', 'other');
112
    $this->assertFalse(isset($field_definitions['body']), 'Body field was not created when using the API to create block content types.');
113 114 115 116

    // Verify that title and body fields are displayed.
    $this->drupalGet('block/add/basic');
    $this->assertRaw('Block description', 'Block info field was found.');
117
    $this->assertNotEmpty($this->cssSelect('#edit-body-0-value'), 'Body field was found.');
118 119

    // Change the block type name.
120
    $edit = [
121
      'label' => 'Bar',
122
    ];
123
    $this->drupalGet('admin/structure/block/block-content/manage/basic');
124
    $this->assertTitle(new FormattableMarkup('Edit @type custom block type | Drupal', ['@type' => 'basic']));
125
    $this->drupalPostForm(NULL, $edit, t('Save'));
126 127 128 129 130
    $front_page_path = Url::fromRoute('<front>')->toString();
    $this->assertBreadcrumb('admin/structure/block/block-content/manage/basic/fields', [
      $front_page_path => 'Home',
      'admin/structure/block' => 'Block layout',
      'admin/structure/block/block-content' => 'Custom block library',
131
      'admin/structure/block/block-content/manage/basic' => 'Edit Bar',
132
    ]);
133
    \Drupal::service('entity_field.manager')->clearCachedFieldDefinitions();
134 135 136 137

    $this->drupalGet('block/add');
    $this->assertRaw('Bar', 'New name was displayed.');
    $this->clickLink('Bar');
138
    $this->assertUrl(Url::fromRoute('block_content.add_form', ['block_content_type' => 'basic'], ['absolute' => TRUE])->toString(), [], 'Original machine name was used in URL.');
139 140

    // Remove the body field.
141
    $this->drupalPostForm('admin/structure/block/block-content/manage/basic/fields/block_content.basic.body/delete', [], t('Delete'));
142
    // Resave the settings for this type.
143
    $this->drupalPostForm('admin/structure/block/block-content/manage/basic', [], t('Save'));
144 145
    // Check that the body field doesn't exist.
    $this->drupalGet('block/add/basic');
146
    $this->assertEmpty($this->cssSelect('#edit-body-0-value'), 'Body field was not found.');
147 148 149 150 151
  }

  /**
   * Tests deleting a block type that still has content.
   */
152
  public function testBlockContentTypeDeletion() {
153 154 155
    // Now create an initial block-type.
    $this->createBlockContentType('basic', TRUE);

156
    // Create a block type programmatically.
157
    $type = $this->createBlockContentType('foo');
158 159 160 161

    $this->drupalLogin($this->adminUser);

    // Add a new block of this type.
162
    $block = $this->createBlockContent(FALSE, 'foo');
163
    // Attempt to delete the block type, which should not be allowed.
164
    $this->drupalGet('admin/structure/block/block-content/manage/' . $type->id() . '/delete');
165
    $this->assertRaw(
166
      t('%label is used by 1 custom block on your site. You can not remove this block type until you have removed all of the %label blocks.', ['%label' => $type->label()]),
167 168
      'The block type will not be deleted until all blocks of that type are removed.'
    );
169
    $this->assertNoText(t('This action cannot be undone.'), 'The block type deletion confirmation form is not available.');
170 171 172 173

    // Delete the block.
    $block->delete();
    // Attempt to delete the block type, which should now be allowed.
174
    $this->drupalGet('admin/structure/block/block-content/manage/' . $type->id() . '/delete');
175
    $this->assertRaw(
176
      t('Are you sure you want to delete the custom block type %type?', ['%type' => $type->id()]),
177 178 179 180 181
      'The block type is available for deletion.'
    );
    $this->assertText(t('This action cannot be undone.'), 'The custom block type deletion confirmation form is available.');
  }

182 183 184
  /**
   * Tests that redirects work as expected when multiple block types exist.
   */
185
  public function testsBlockContentAddTypes() {
186 187 188
    // Now create an initial block-type.
    $this->createBlockContentType('basic', TRUE);

189 190
    $this->drupalLogin($this->adminUser);
    // Create two block types programmatically.
191 192
    $type = $this->createBlockContentType('foo');
    $type = $this->createBlockContentType('bar');
193

194 195
    // Get the custom block storage.
    $storage = $this->container
196
      ->get('entity_type.manager')
197
      ->getStorage('block_content');
198

199
    // Install all themes.
200
    \Drupal::service('theme_installer')->install(['bartik', 'seven', 'stark']);
201
    $theme_settings = $this->config('system.theme');
202
    foreach (['bartik', 'seven', 'stark'] as $default_theme) {
203 204
      // Change the default theme.
      $theme_settings->set('default', $default_theme)->save();
205
      $this->drupalPlaceBlock('local_actions_block');
206
      \Drupal::service('router.builder')->rebuild();
207

208
      // For each installed theme, go to its block page and test the redirects.
209
      foreach (['bartik', 'seven', 'stark'] as $theme) {
210 211 212 213
        // Test that adding a block from the 'place blocks' form sends you to the
        // block configure form.
        $path = $theme == $default_theme ? 'admin/structure/block' : "admin/structure/block/list/$theme";
        $this->drupalGet($path);
214
        $this->clickLink('Place block');
215 216 217
        $this->clickLink(t('Add custom block'));
        // The seven theme has markup inside the link, we cannot use clickLink().
        if ($default_theme == 'seven') {
218
          $options = $theme != $default_theme ? ['query' => ['theme' => $theme]] : [];
219
          $this->assertLinkByHref(Url::fromRoute('block_content.add_form', ['block_content_type' => 'foo'], $options)->toString());
220 221 222 223 224 225
          $this->drupalGet('block/add/foo', $options);
        }
        else {
          $this->clickLink('foo');
        }
        // Create a new block.
226
        $edit = ['info[0][value]' => $this->randomMachineName(8)];
227
        $this->drupalPostForm(NULL, $edit, t('Save'));
228
        $blocks = $storage->loadByProperties(['info' => $edit['info[0][value]']]);
229 230
        if (!empty($blocks)) {
          $block = reset($blocks);
231
          $this->assertUrl(Url::fromRoute('block.admin_add', ['plugin_id' => 'block_content:' . $block->uuid(), 'theme' => $theme], ['absolute' => TRUE])->toString());
232
          $this->drupalPostForm(NULL, ['region' => 'content'], t('Save block'));
233
          $this->assertUrl(Url::fromRoute('block.admin_display_theme', ['theme' => $theme], ['absolute' => TRUE, 'query' => ['block-placement' => Html::getClass($edit['info[0][value]'])]])->toString());
234 235 236 237 238
        }
        else {
          $this->fail('Could not load created block.');
        }
      }
239 240 241 242
    }

    // Test that adding a block from the 'custom blocks list' doesn't send you
    // to the block configure form.
243
    $this->drupalGet('admin/structure/block/block-content');
244 245
    $this->clickLink(t('Add custom block'));
    $this->clickLink('foo');
246
    $edit = ['info[0][value]' => $this->randomMachineName(8)];
247
    $this->drupalPostForm(NULL, $edit, t('Save'));
248
    $blocks = $storage->loadByProperties(['info' => $edit['info[0][value]']]);
249
    if (!empty($blocks)) {
250
      $this->assertUrl(Url::fromRoute('entity.block_content.collection', [], ['absolute' => TRUE])->toString());
251 252 253 254 255 256
    }
    else {
      $this->fail('Could not load created block.');
    }
  }

257
}