MultipleWidgetFormTest.php

Same filename and directory in other branches
  1. 11.x core/modules/field/tests/src/Functional/MultipleWidgetFormTest.php

Namespace

Drupal\Tests\field\Functional

File

core/modules/field/tests/src/Functional/MultipleWidgetFormTest.php

View source
<?php

declare (strict_types=1);
namespace Drupal\Tests\field\Functional;

use Drupal\Core\Entity\Entity\EntityFormDisplay;
use Drupal\entity_test\Entity\EntityTest;
use Drupal\entity_test\Entity\EntityTestBaseFieldDisplay;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;

/**
 * Tests field form handling.
 *
 * @group field
 */
class MultipleWidgetFormTest extends FieldTestBase {
  
  /**
   * Modules to install.
   *
   * Locale is installed so that TranslatableMarkup actually does something.
   *
   * @var array
   */
  protected static $modules = [
    'field_test',
    'options',
    'entity_test',
    'locale',
    'field_ui',
  ];
  
  /**
   * {@inheritdoc}
   */
  protected $defaultTheme = 'stark';
  
  /**
   * An array of values defining a field multiple.
   *
   * @var array
   */
  protected $fieldStorageMultiple;
  
  /**
   * An array of values defining a field.
   *
   * @var array
   */
  protected $field;
  
  /**
   * {@inheritdoc}
   */
  protected function setUp() : void {
    parent::setUp();
    $web_user = $this->drupalCreateUser([
      'view test entity',
      'administer entity_test content',
      'administer entity_test fields',
    ]);
    $this->drupalLogin($web_user);
    $this->fieldStorageMultiple = [
      'field_name' => 'field_multiple',
      'entity_type' => 'entity_test',
      'type' => 'test_field',
      'cardinality' => 4,
    ];
    $this->field = [
      'entity_type' => 'entity_test',
      'bundle' => 'entity_test',
      'label' => $this->randomMachineName() . '_label',
      'description' => '[site:name]_description',
      'weight' => mt_rand(0, 127),
      'settings' => [
        'test_field_setting' => $this->randomMachineName(),
      ],
    ];
  }
  
  /**
   * Tests widgets handling multiple values.
   */
  public function testFieldFormMultipleWidget() : void {
    // Create a field with fixed cardinality, configure the form to use a
    // "multiple" widget.
    $field_storage = $this->fieldStorageMultiple;
    $field_name = $field_storage['field_name'];
    $this->field['field_name'] = $field_name;
    FieldStorageConfig::create($field_storage)->save();
    FieldConfig::create($this->field)
      ->save();
    $form = \Drupal::service('entity_display.repository')->getFormDisplay($this->field['entity_type'], $this->field['bundle'], 'default')
      ->setComponent($field_name, [
      'type' => 'test_field_widget_multiple',
    ]);
    $form->save();
    $session = $this->assertSession();
    // Display creation form.
    $this->drupalGet('entity_test/add');
    $this->assertSession()
      ->fieldValueEquals($field_name, '');
    // Create entity with three values.
    $edit = [
      $field_name => '1, 2, 3',
    ];
    $this->submitForm($edit, 'Save');
    preg_match('|entity_test/manage/(\\d+)|', $this->getUrl(), $match);
    $id = $match[1];
    // Check that the values were saved.
    $entity_init = EntityTest::load($id);
    $this->assertFieldValues($entity_init, $field_name, [
      1,
      2,
      3,
    ]);
    // Display the form, check that the values are correctly filled in.
    $this->drupalGet('entity_test/manage/' . $id . '/edit');
    $this->assertSession()
      ->fieldValueEquals($field_name, '1, 2, 3');
    // Submit the form with more values than the field accepts.
    $edit = [
      $field_name => '1, 2, 3, 4, 5',
    ];
    $this->submitForm($edit, 'Save');
    $this->assertSession()
      ->pageTextContains('this field cannot hold more than 4 values');
    // Check that the field values were not submitted.
    $this->assertFieldValues($entity_init, $field_name, [
      1,
      2,
      3,
    ]);
    // Check that Attributes are rendered on the multivalue container if it is
    // a multiple widget form.
    $form->setComponent($field_name, [
      'type' => 'entity_reference_autocomplete',
    ])
      ->save();
    $this->drupalGet('entity_test/manage/' . $id . '/edit');
    $name = str_replace('_', '-', $field_name);
    $session->responseContains('data-drupal-selector="edit-' . $name . '"');
  }
  
  /**
   * Tests the form display of the label for multi-value fields.
   */
  public function testLabelOnMultiValueFields() : void {
    $user = $this->drupalCreateUser([
      'administer entity_test content',
    ]);
    $this->drupalLogin($user);
    // Ensure that the 'bar' bundle exists, to avoid config validation errors.
    entity_test_create_bundle('bar', entity_type: 'entity_test_base_field_display');
    FieldStorageConfig::create([
      'entity_type' => 'entity_test_base_field_display',
      'field_name' => 'foo',
      'type' => 'text',
      'cardinality' => FieldStorageConfig::CARDINALITY_UNLIMITED,
    ])->save();
    FieldConfig::create([
      'entity_type' => 'entity_test_base_field_display',
      'bundle' => 'bar',
      'field_name' => 'foo',
      // Set a dangerous label to test XSS filtering.
'label' => "<script>alert('a configurable field');</script>",
    ])->save();
    EntityFormDisplay::create([
      'targetEntityType' => 'entity_test_base_field_display',
      'bundle' => 'bar',
      'mode' => 'default',
    ])->setComponent('foo', [
      'type' => 'text_textfield',
    ])
      ->enable()
      ->save();
    $entity = EntityTestBaseFieldDisplay::create([
      'type' => 'bar',
    ]);
    $entity->save();
    $this->drupalGet('entity_test_base_field_display/manage/' . $entity->id());
    $this->assertSession()
      ->statusCodeEquals(200);
    $this->assertSession()
      ->pageTextContains('A field with multiple values');
    // Test if labels were XSS filtered.
    $this->assertSession()
      ->assertEscaped("<script>alert('a configurable field');</script>");
  }
  
  /**
   * Tests hook_field_widget_complete_form_alter().
   */
  public function testFieldFormMultipleWidgetAlter() : void {
    $this->widgetAlterTest('hook_field_widget_complete_form_alter', 'test_field_widget_multiple');
  }
  
  /**
   * Tests hook_field_widget_complete_form_alter() with single value elements.
   */
  public function testFieldFormMultipleWidgetAlterSingleValues() : void {
    $this->widgetAlterTest('hook_field_widget_complete_form_alter', 'test_field_widget_multiple_single_value');
  }
  
  /**
   * Tests hook_field_widget_complete_WIDGET_TYPE_form_alter().
   */
  public function testFieldFormMultipleWidgetTypeAlter() : void {
    $this->widgetAlterTest('hook_field_widget_complete_WIDGET_TYPE_form_alter', 'test_field_widget_multiple');
  }
  
  /**
   * Tests hook_field_widget_complete_WIDGET_TYPE_form_alter() with single value elements.
   */
  public function testFieldFormMultipleWidgetTypeAlterSingleValues() : void {
    $this->widgetAlterTest('hook_field_widget_complete_WIDGET_TYPE_form_alter', 'test_field_widget_multiple_single_value');
  }
  
  /**
   * Tests widget alter hooks for a given hook name.
   */
  protected function widgetAlterTest($hook, $widget) {
    // Create a field with fixed cardinality, configure the form to use a
    // "multiple" widget.
    $field_storage = $this->fieldStorageMultiple;
    $field_name = $field_storage['field_name'];
    $this->field['field_name'] = $field_name;
    FieldStorageConfig::create($field_storage)->save();
    FieldConfig::create($this->field)
      ->save();
    // Set a flag in state so that the hook implementations will run.
    \Drupal::state()->set("field_test.widget_alter_test", [
      'hook' => $hook,
      'field_name' => $field_name,
      'widget' => $widget,
    ]);
    \Drupal::service('entity_display.repository')->getFormDisplay($this->field['entity_type'], $this->field['bundle'], 'default')
      ->setComponent($field_name, [
      'type' => $widget,
    ])
      ->save();
    // We need to rebuild hook information after setting the component through
    // the API.
    $this->rebuildAll();
    $this->drupalGet('entity_test/add');
    $this->assertSession()
      ->pageTextMatchesCount(1, '/From ' . $hook . '.* prefix on ' . $field_name . ' parent element\\./');
    if ($widget === 'test_field_widget_multiple_single_value') {
      $suffix_text = "From {$hook}(): suffix on {$field_name} child element.";
      $this->assertEquals($field_storage['cardinality'], substr_count($this->getTextContent(), $suffix_text), "'{$suffix_text}' was found {$field_storage['cardinality']} times  using widget {$widget}");
    }
  }

}

Classes

Title Deprecated Summary
MultipleWidgetFormTest Tests field form handling.

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.