FieldWidgetConstraintValidatorTest.php 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. <?php
  2. namespace Drupal\KernelTests\Core\Entity;
  3. use Drupal\Component\Render\FormattableMarkup;
  4. use Drupal\Core\Entity\EntityInterface;
  5. use Drupal\Core\Form\FormState;
  6. use Drupal\entity_test\Entity\EntityTestCompositeConstraint;
  7. use Drupal\KernelTests\KernelTestBase;
  8. /**
  9. * Tests validation constraints for FieldWidgetConstraintValidatorTest.
  10. *
  11. * @group Entity
  12. */
  13. class FieldWidgetConstraintValidatorTest extends KernelTestBase {
  14. public static $modules = ['entity_test', 'field', 'field_test', 'user', 'system'];
  15. /**
  16. * {@inheritdoc}
  17. */
  18. protected function setUp() {
  19. parent::setUp();
  20. $this->installSchema('system', ['key_value']);
  21. $this->container->get('router.builder')->rebuild();
  22. $this->installEntitySchema('user');
  23. $this->installEntitySchema('entity_test_composite_constraint');
  24. }
  25. /**
  26. * Tests widget constraint validation.
  27. */
  28. public function testValidation() {
  29. $entity_type = 'entity_test_constraint_violation';
  30. $entity = $this->container->get('entity_type.manager')
  31. ->getStorage($entity_type)
  32. ->create(['id' => 1, 'revision_id' => 1]);
  33. $display = entity_get_form_display($entity_type, $entity_type, 'default');
  34. $form = [];
  35. $form_state = new FormState();
  36. $display->buildForm($entity, $form, $form_state);
  37. // Pretend the form has been built.
  38. $form_state->setFormObject(\Drupal::entityManager()->getFormObject($entity_type, 'default'));
  39. \Drupal::formBuilder()->prepareForm('field_test_entity_form', $form, $form_state);
  40. \Drupal::formBuilder()->processForm('field_test_entity_form', $form, $form_state);
  41. // Validate the field constraint.
  42. $form_state->getFormObject()->setEntity($entity)->setFormDisplay($display, $form_state);
  43. $entity = $form_state->getFormObject()->buildEntity($form, $form_state);
  44. $display->validateFormValues($entity, $form, $form_state);
  45. $errors = $form_state->getErrors();
  46. $this->assertEqual($errors['name'], 'Widget constraint has failed.', 'Constraint violation at the field items list level is generated correctly');
  47. $this->assertEqual($errors['test_field'], 'Widget constraint has failed.', 'Constraint violation at the field items list level is generated correctly for an advanced widget');
  48. }
  49. /**
  50. * Gets the form errors for a given entity.
  51. *
  52. * @param \Drupal\Core\Entity\EntityInterface $entity
  53. * The entity
  54. * @param array $hidden_fields
  55. * (optional) A list of hidden fields.
  56. *
  57. * @return array
  58. * The form errors.
  59. */
  60. protected function getErrorsForEntity(EntityInterface $entity, $hidden_fields = []) {
  61. $entity_type_id = 'entity_test_composite_constraint';
  62. $display = entity_get_form_display($entity_type_id, $entity_type_id, 'default');
  63. foreach ($hidden_fields as $hidden_field) {
  64. $display->removeComponent($hidden_field);
  65. }
  66. $form = [];
  67. $form_state = new FormState();
  68. $display->buildForm($entity, $form, $form_state);
  69. $form_state->setFormObject(\Drupal::entityManager()->getFormObject($entity_type_id, 'default'));
  70. \Drupal::formBuilder()->prepareForm('field_test_entity_form', $form, $form_state);
  71. \Drupal::formBuilder()->processForm('field_test_entity_form', $form, $form_state);
  72. // Validate the field constraint.
  73. /** @var \Drupal\Core\Entity\ContentEntityFormInterface $form_object */
  74. $form_object = $form_state->getFormObject();
  75. $form_object
  76. ->setEntity($entity)
  77. ->setFormDisplay($display, $form_state)
  78. ->validateForm($form, $form_state);
  79. return $form_state->getErrors();
  80. }
  81. /**
  82. * Tests widget constraint validation with composite constraints.
  83. */
  84. public function testValidationWithCompositeConstraint() {
  85. // First provide a valid value, this should cause no validation.
  86. $entity = EntityTestCompositeConstraint::create([
  87. 'name' => 'valid-value',
  88. ]);
  89. $entity->save();
  90. $errors = $this->getErrorsForEntity($entity);
  91. $this->assertFalse(isset($errors['name']));
  92. $this->assertFalse(isset($errors['type']));
  93. // Provide an invalid value for the name field.
  94. $entity = EntityTestCompositeConstraint::create([
  95. 'name' => 'failure-field-name',
  96. ]);
  97. $errors = $this->getErrorsForEntity($entity);
  98. $this->assertTrue(isset($errors['name']));
  99. $this->assertFalse(isset($errors['type']));
  100. // Hide the second field (type) and ensure the validation still happens. The
  101. // error message appears on the first field (name).
  102. $entity = EntityTestCompositeConstraint::create([
  103. 'name' => 'failure-field-name',
  104. ]);
  105. $errors = $this->getErrorsForEntity($entity, ['type']);
  106. $this->assertTrue(isset($errors['name']));
  107. $this->assertFalse(isset($errors['type']));
  108. // Provide a violation again, but this time hide the first field (name).
  109. // Ensure that the validation still happens and the error message is moved
  110. // from the field to the second field and have a custom error message.
  111. $entity = EntityTestCompositeConstraint::create([
  112. 'name' => 'failure-field-name',
  113. ]);
  114. $errors = $this->getErrorsForEntity($entity, ['name']);
  115. $this->assertFalse(isset($errors['name']));
  116. $this->assertTrue(isset($errors['type']));
  117. $this->assertEqual($errors['type'], new FormattableMarkup('The validation failed because the value conflicts with the value in %field_name, which you cannot access.', ['%field_name' => 'name']));
  118. }
  119. /**
  120. * Tests entity level constraint validation.
  121. */
  122. public function testEntityLevelConstraintValidation() {
  123. $entity = EntityTestCompositeConstraint::create([
  124. 'name' => 'entity-level-violation',
  125. ]);
  126. $entity->save();
  127. $errors = $this->getErrorsForEntity($entity);
  128. $this->assertEqual($errors[''], 'Entity level validation');
  129. $entity->name->value = 'entity-level-violation-with-path';
  130. $errors = $this->getErrorsForEntity($entity);
  131. $this->assertEqual($errors['test][form][element'], 'Entity level validation');
  132. }
  133. }