Version 1
[yaffs-website] / web / core / tests / Drupal / KernelTests / Core / Entity / Element / EntityAutocompleteElementFormTest.php
diff --git a/web/core/tests/Drupal/KernelTests/Core/Entity/Element/EntityAutocompleteElementFormTest.php b/web/core/tests/Drupal/KernelTests/Core/Entity/Element/EntityAutocompleteElementFormTest.php
new file mode 100644 (file)
index 0000000..5d7ea0e
--- /dev/null
@@ -0,0 +1,387 @@
+<?php
+
+namespace Drupal\KernelTests\Core\Entity\Element;
+
+use Drupal\Core\Entity\Element\EntityAutocomplete;
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Form\FormInterface;
+use Drupal\Core\Form\FormState;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\entity_test\Entity\EntityTest;
+use Drupal\entity_test\Entity\EntityTestStringId;
+use Drupal\KernelTests\Core\Entity\EntityKernelTestBase;
+use Drupal\user\Entity\User;
+
+/**
+ * Tests the EntityAutocomplete Form API element.
+ *
+ * @group Form
+ */
+class EntityAutocompleteElementFormTest extends EntityKernelTestBase implements FormInterface {
+
+  /**
+   * User for testing.
+   *
+   * @var \Drupal\user\UserInterface
+   */
+  protected $testUser;
+
+  /**
+   * User for autocreate testing.
+   *
+   * @var \Drupal\user\UserInterface
+   */
+  protected $testAutocreateUser;
+
+  /**
+   * An array of entities to be referenced in this test.
+   *
+   * @var \Drupal\Core\Entity\EntityInterface[]
+   */
+  protected $referencedEntities;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    $this->installSchema('system', ['key_value_expire']);
+    $this->installEntitySchema('entity_test_string_id');
+    \Drupal::service('router.builder')->rebuild();
+
+    $this->testUser = User::create([
+      'name' => 'foobar1',
+      'mail' => 'foobar1@example.com',
+    ]);
+    $this->testUser->save();
+    \Drupal::service('current_user')->setAccount($this->testUser);
+
+    $this->testAutocreateUser = User::create([
+      'name' => 'foobar2',
+      'mail' => 'foobar2@example.com',
+    ]);
+    $this->testAutocreateUser->save();
+
+    for ($i = 1; $i < 3; $i++) {
+      $entity = EntityTest::create([
+        'name' => $this->randomMachineName()
+      ]);
+      $entity->save();
+      $this->referencedEntities[] = $entity;
+    }
+
+    // Use special characters in the ID of some of the test entities so we can
+    // test if these are handled correctly.
+    for ($i = 0; $i < 2; $i++) {
+      $entity = EntityTestStringId::create([
+        'name' => $this->randomMachineName(),
+        'id' => $this->randomMachineName() . '&</\\:?',
+      ]);
+      $entity->save();
+      $this->referencedEntities[] = $entity;
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormId() {
+    return 'test_entity_autocomplete';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildForm(array $form, FormStateInterface $form_state) {
+    $form['single'] = [
+      '#type' => 'entity_autocomplete',
+      '#target_type' => 'entity_test',
+    ];
+    $form['single_autocreate'] = [
+      '#type' => 'entity_autocomplete',
+      '#target_type' => 'entity_test',
+      '#autocreate' => [
+        'bundle' => 'entity_test',
+      ],
+    ];
+    $form['single_autocreate_specific_uid'] = [
+      '#type' => 'entity_autocomplete',
+      '#target_type' => 'entity_test',
+      '#autocreate' => [
+        'bundle' => 'entity_test',
+        'uid' => $this->testAutocreateUser->id(),
+      ],
+    ];
+
+    $form['tags'] = [
+      '#type' => 'entity_autocomplete',
+      '#target_type' => 'entity_test',
+      '#tags' => TRUE,
+    ];
+    $form['tags_autocreate'] = [
+      '#type' => 'entity_autocomplete',
+      '#target_type' => 'entity_test',
+      '#tags' => TRUE,
+      '#autocreate' => [
+        'bundle' => 'entity_test',
+      ],
+    ];
+    $form['tags_autocreate_specific_uid'] = [
+      '#type' => 'entity_autocomplete',
+      '#target_type' => 'entity_test',
+      '#tags' => TRUE,
+      '#autocreate' => [
+        'bundle' => 'entity_test',
+        'uid' => $this->testAutocreateUser->id(),
+      ],
+    ];
+
+    $form['single_no_validate'] = [
+      '#type' => 'entity_autocomplete',
+      '#target_type' => 'entity_test',
+      '#validate_reference' => FALSE,
+    ];
+    $form['single_autocreate_no_validate'] = [
+      '#type' => 'entity_autocomplete',
+      '#target_type' => 'entity_test',
+      '#validate_reference' => FALSE,
+      '#autocreate' => [
+        'bundle' => 'entity_test',
+      ],
+    ];
+
+    $form['single_access'] = [
+      '#type' => 'entity_autocomplete',
+      '#target_type' => 'entity_test',
+      '#default_value' => $this->referencedEntities[0],
+    ];
+    $form['tags_access'] = [
+      '#type' => 'entity_autocomplete',
+      '#target_type' => 'entity_test',
+      '#tags' => TRUE,
+      '#default_value' => [$this->referencedEntities[0], $this->referencedEntities[1]],
+    ];
+
+    $form['single_string_id'] = [
+      '#type' => 'entity_autocomplete',
+      '#target_type' => 'entity_test_string_id',
+    ];
+    $form['tags_string_id'] = [
+      '#type' => 'entity_autocomplete',
+      '#target_type' => 'entity_test_string_id',
+      '#tags' => TRUE,
+    ];
+
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, FormStateInterface $form_state) { }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function validateForm(array &$form, FormStateInterface $form_state) { }
+
+  /**
+   * Tests valid entries in the EntityAutocomplete Form API element.
+   */
+  public function testValidEntityAutocompleteElement() {
+    $form_state = (new FormState())
+      ->setValues([
+        'single' => $this->getAutocompleteInput($this->referencedEntities[0]),
+        'single_autocreate' => 'single - autocreated entity label',
+        'single_autocreate_specific_uid' => 'single - autocreated entity label with specific uid',
+        'tags' => $this->getAutocompleteInput($this->referencedEntities[0]) . ', ' . $this->getAutocompleteInput($this->referencedEntities[1]),
+        'tags_autocreate' =>
+          $this->getAutocompleteInput($this->referencedEntities[0])
+          . ', tags - autocreated entity label, '
+          . $this->getAutocompleteInput($this->referencedEntities[1]),
+        'tags_autocreate_specific_uid' =>
+          $this->getAutocompleteInput($this->referencedEntities[0])
+          . ', tags - autocreated entity label with specific uid, '
+          . $this->getAutocompleteInput($this->referencedEntities[1]),
+        'single_string_id' => $this->getAutocompleteInput($this->referencedEntities[2]),
+        'tags_string_id' => $this->getAutocompleteInput($this->referencedEntities[2]) . ', ' . $this->getAutocompleteInput($this->referencedEntities[3]),
+      ]);
+    $form_builder = $this->container->get('form_builder');
+    $form_builder->submitForm($this, $form_state);
+
+    // Valid form state.
+    $this->assertEqual(count($form_state->getErrors()), 0);
+
+    // Test the 'single' element.
+    $this->assertEqual($form_state->getValue('single'), $this->referencedEntities[0]->id());
+
+    // Test the 'single_autocreate' element.
+    $value = $form_state->getValue('single_autocreate');
+    $this->assertEqual($value['entity']->label(), 'single - autocreated entity label');
+    $this->assertEqual($value['entity']->bundle(), 'entity_test');
+    $this->assertEqual($value['entity']->getOwnerId(), $this->testUser->id());
+
+    // Test the 'single_autocreate_specific_uid' element.
+    $value = $form_state->getValue('single_autocreate_specific_uid');
+    $this->assertEqual($value['entity']->label(), 'single - autocreated entity label with specific uid');
+    $this->assertEqual($value['entity']->bundle(), 'entity_test');
+    $this->assertEqual($value['entity']->getOwnerId(), $this->testAutocreateUser->id());
+
+    // Test the 'tags' element.
+    $expected = [
+      ['target_id' => $this->referencedEntities[0]->id()],
+      ['target_id' => $this->referencedEntities[1]->id()],
+    ];
+    $this->assertEqual($form_state->getValue('tags'), $expected);
+
+    // Test the 'single_autocreate' element.
+    $value = $form_state->getValue('tags_autocreate');
+    // First value is an existing entity.
+    $this->assertEqual($value[0]['target_id'], $this->referencedEntities[0]->id());
+    // Second value is an autocreated entity.
+    $this->assertTrue(!isset($value[1]['target_id']));
+    $this->assertEqual($value[1]['entity']->label(), 'tags - autocreated entity label');
+    $this->assertEqual($value[1]['entity']->getOwnerId(), $this->testUser->id());
+    // Third value is an existing entity.
+    $this->assertEqual($value[2]['target_id'], $this->referencedEntities[1]->id());
+
+    // Test the 'tags_autocreate_specific_uid' element.
+    $value = $form_state->getValue('tags_autocreate_specific_uid');
+    // First value is an existing entity.
+    $this->assertEqual($value[0]['target_id'], $this->referencedEntities[0]->id());
+    // Second value is an autocreated entity.
+    $this->assertTrue(!isset($value[1]['target_id']));
+    $this->assertEqual($value[1]['entity']->label(), 'tags - autocreated entity label with specific uid');
+    $this->assertEqual($value[1]['entity']->getOwnerId(), $this->testAutocreateUser->id());
+    // Third value is an existing entity.
+    $this->assertEqual($value[2]['target_id'], $this->referencedEntities[1]->id());
+
+    // Test the 'single_string_id' element.
+    $this->assertEquals($this->referencedEntities[2]->id(), $form_state->getValue('single_string_id'));
+
+    // Test the 'tags_string_id' element.
+    $expected = [
+      ['target_id' => $this->referencedEntities[2]->id()],
+      ['target_id' => $this->referencedEntities[3]->id()],
+    ];
+    $this->assertEquals($expected, $form_state->getValue('tags_string_id'));
+  }
+
+  /**
+   * Tests invalid entries in the EntityAutocomplete Form API element.
+   */
+  public function testInvalidEntityAutocompleteElement() {
+    $form_builder = $this->container->get('form_builder');
+
+    // Test 'single' with a entity label that doesn't exist
+    $form_state = (new FormState())
+      ->setValues([
+        'single' => 'single - non-existent label',
+      ]);
+    $form_builder->submitForm($this, $form_state);
+    $this->assertEqual(count($form_state->getErrors()), 1);
+    $this->assertEqual($form_state->getErrors()['single'], t('There are no entities matching "%value".', ['%value' => 'single - non-existent label']));
+
+    // Test 'single' with a entity ID that doesn't exist.
+    $form_state = (new FormState())
+      ->setValues([
+        'single' => 'single - non-existent label (42)',
+      ]);
+    $form_builder->submitForm($this, $form_state);
+    $this->assertEqual(count($form_state->getErrors()), 1);
+    $this->assertEqual($form_state->getErrors()['single'], t('The referenced entity (%type: %id) does not exist.', ['%type' => 'entity_test', '%id' => 42]));
+
+    // Do the same tests as above but on an element with '#validate_reference'
+    // set to FALSE.
+    $form_state = (new FormState())
+      ->setValues([
+        'single_no_validate' => 'single - non-existent label',
+        'single_autocreate_no_validate' => 'single - autocreate non-existent label'
+      ]);
+    $form_builder->submitForm($this, $form_state);
+
+    // The element without 'autocreate' support still has to emit a warning when
+    // the input doesn't end with an entity ID enclosed in parentheses.
+    $this->assertEqual(count($form_state->getErrors()), 1);
+    $this->assertEqual($form_state->getErrors()['single_no_validate'], t('There are no entities matching "%value".', ['%value' => 'single - non-existent label']));
+
+    $form_state = (new FormState())
+      ->setValues([
+        'single_no_validate' => 'single - non-existent label (42)',
+        'single_autocreate_no_validate' => 'single - autocreate non-existent label (43)'
+      ]);
+    $form_builder->submitForm($this, $form_state);
+
+    // The input is complete (i.e. contains an entity ID at the end), no errors
+    // are triggered.
+    $this->assertEqual(count($form_state->getErrors()), 0);
+  }
+
+  /**
+   * Tests that access is properly checked by the EntityAutocomplete element.
+   */
+  public function testEntityAutocompleteAccess() {
+    $form_builder = $this->container->get('form_builder');
+    $form = $form_builder->getForm($this);
+
+    // Check that the current user has proper access to view entity labels.
+    $expected = $this->referencedEntities[0]->label() . ' (' . $this->referencedEntities[0]->id() . ')';
+    $this->assertEqual($form['single_access']['#value'], $expected);
+
+    $expected .= ', ' . $this->referencedEntities[1]->label() . ' (' . $this->referencedEntities[1]->id() . ')';
+    $this->assertEqual($form['tags_access']['#value'], $expected);
+
+    // Set up a non-admin user that is *not* allowed to view test entities.
+    \Drupal::currentUser()->setAccount($this->createUser([], []));
+
+    // Rebuild the form.
+    $form = $form_builder->getForm($this);
+
+    $expected = t('- Restricted access -') . ' (' . $this->referencedEntities[0]->id() . ')';
+    $this->assertEqual($form['single_access']['#value'], $expected);
+
+    $expected .= ', ' . t('- Restricted access -') . ' (' . $this->referencedEntities[1]->id() . ')';
+    $this->assertEqual($form['tags_access']['#value'], $expected);
+  }
+
+  /**
+   * Tests ID input is handled correctly.
+   *
+   * E.g. This can happen with GET form parameters.
+   */
+  public function testEntityAutocompleteIdInput() {
+    /** @var \Drupal\Core\Form\FormBuilderInterface $form_builder */
+    $form_builder = $this->container->get('form_builder');
+    //$form = $form_builder->getForm($this);
+    $form_state = (new FormState())
+      ->setMethod('GET')
+      ->setValues([
+        'single' => [['target_id' => $this->referencedEntities[0]->id()]],
+        'single_no_validate' => [['target_id' => $this->referencedEntities[0]->id()]],
+      ]);
+
+    $form_builder->submitForm($this, $form_state);
+
+    $form = $form_state->getCompleteForm();
+
+    $expected_label = $this->getAutocompleteInput($this->referencedEntities[0]);
+    $this->assertSame($expected_label, $form['single']['#value']);
+    $this->assertSame($expected_label, $form['single_no_validate']['#value']);
+  }
+
+  /**
+   * Returns an entity label in the format needed by the EntityAutocomplete
+   * element.
+   *
+   * @param \Drupal\Core\Entity\EntityInterface $entity
+   *   A Drupal entity.
+   *
+   * @return string
+   *   A string that can be used as a value for EntityAutocomplete elements.
+   */
+  protected function getAutocompleteInput(EntityInterface $entity) {
+    return EntityAutocomplete::getEntityLabels([$entity]);
+  }
+
+}