custom_elements-8.x-2.x-dev/tests/src/Kernel/EntityReferenceCeFieldFormatterTest.php
tests/src/Kernel/EntityReferenceCeFieldFormatterTest.php
<?php
namespace Drupal\Tests\custom_elements\Kernel;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\KernelTests\KernelTestBase;
use Drupal\Tests\user\Traits\UserCreationTrait;
use Drupal\custom_elements\CustomElementGeneratorTrait;
use Drupal\custom_elements\Entity\EntityCeDisplay;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\Tests\custom_elements\Traits\TestHelperTrait;
use Drupal\user\Entity\User;
use Drupal\paragraphs\Entity\ParagraphsType;
use Drupal\paragraphs\Entity\Paragraph;
/**
* Tests rendering of entityreference fields.
*
* @group custom_elements
*/
class EntityReferenceCeFieldFormatterTest extends KernelTestBase {
use CustomElementGeneratorTrait;
use UserCreationTrait;
use TestHelperTrait;
/**
* {@inheritdoc}
*
* @var bool
* @todo Fix config schema for CE-displays and re-enable.
*/
protected $strictConfigSchema = FALSE;
/**
* Modules to install.
*
* @var string[]
*/
protected static $modules = [
'custom_elements',
'user',
'field',
'file',
'paragraphs',
'entity_reference_revisions',
'system',
];
/**
* {@inheritdoc}
*/
protected function setUp(): void {
parent::setUp();
$this->installEntitySchema('user');
$this->installEntitySchema('paragraph');
$this->installConfig(['custom_elements']);
// These tests expect legacy format.
\Drupal::configFactory()
->getEditable('custom_elements.settings')
->set('json_format', 'legacy')
->save();
}
/**
* Creates user reference field, CE display and user(s).
*
* @param bool $multi_value
* Whether the field should be multi-value (cardinality >1).
* @param bool $multiple_values
* Whether multiple users should be referenced.
*/
protected function setupUser(bool $multi_value = FALSE, bool $multiple_values = FALSE): User {
$field_storage = FieldStorageConfig::create([
'field_name' => 'ref_user',
'type' => 'entity_reference',
'cardinality' => $multi_value ? FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED : 1,
'entity_type' => 'user',
'settings' => [
'target_type' => 'user',
],
]);
$field_storage->save();
$field = FieldConfig::create([
'field_name' => 'ref_user',
'entity_type' => 'user',
'bundle' => 'user',
'label' => 'Referenced user',
'settings' => [
'handler' => 'default',
],
]);
$field->save();
// Create CE config with is_slot=TRUE for the reference fields. Callers can
// change it.
EntityCeDisplay::create([
'targetEntityType' => 'user',
'customElementName' => 'user',
'bundle' => 'user',
'mode' => 'default',
])
->setComponent('name', [
'field_name' => 'name',
'is_slot' => FALSE,
'formatter' => 'flattened',
])
->setComponent('ref-user', [
'field_name' => 'ref_user',
'is_slot' => TRUE,
'formatter' => 'entity_ce_render',
'configuration' => [
'mode' => 'full',
],
])
->save();
$ref_user = $this->createUser([], 'target');
if ($multi_value && $multiple_values) {
$ref_user2 = $this->createUser([], 'target2');
$value = [$ref_user, $ref_user2];
}
else {
$value = [$ref_user];
}
$referrer = $this->createUser([], 'referrer', FALSE, ['ref_user' => $value]);
return $referrer;
}
/**
* Changes configuration of the 'ref_user' display component.
*
* @param bool $is_slot
* Value for is_slot property.
* @param array $config
* Other configuration values.
*/
protected function changeReferenceDisplayComponent(bool $is_slot, array $config = []): void {
EntityCeDisplay::load('user.user.default')
->setComponent('ref-user', [
'field_name' => 'ref_user',
'is_slot' => $is_slot,
'formatter' => 'entity_ce_render',
'configuration' => $config + ['mode' => 'full'],
])
->save();
}
/**
* Creates paragraph type, entity_reference_revisions field, CE display.
*/
protected function setupParagraph(): User {
// Create paragraph type.
ParagraphsType::create([
'id' => 'test_paragraph',
'label' => 'Test Paragraph',
])->save();
// Create entity_reference_revisions field storage.
$field_storage = FieldStorageConfig::create([
'field_name' => 'ref_paragraph',
'type' => 'entity_reference_revisions',
'cardinality' => 1,
'entity_type' => 'user',
'settings' => [
'target_type' => 'paragraph',
],
]);
$field_storage->save();
// Create field instance.
$field = FieldConfig::create([
'field_name' => 'ref_paragraph',
'entity_type' => 'user',
'bundle' => 'user',
'label' => 'Referenced paragraph',
'settings' => [
'handler' => 'default:paragraph',
'handler_settings' => [
'target_bundles' => [
'test_paragraph' => 'test_paragraph',
],
],
],
]);
$field->save();
// Create CE display for paragraph.
EntityCeDisplay::create([
'targetEntityType' => 'paragraph',
'customElementName' => 'test-paragraph',
'bundle' => 'test_paragraph',
'mode' => 'default',
])
->setComponent('id', [
'field_name' => 'id',
'is_slot' => FALSE,
'formatter' => 'auto',
])
->save();
// Create CE config for user with paragraph reference field.
EntityCeDisplay::create([
'targetEntityType' => 'user',
'customElementName' => 'user',
'bundle' => 'user',
'mode' => 'default',
])
->setComponent('name', [
'field_name' => 'name',
'is_slot' => FALSE,
'formatter' => 'flattened',
])
->setComponent('ref-paragraph', [
'field_name' => 'ref_paragraph',
'is_slot' => TRUE,
'formatter' => 'entity_ce_render',
'configuration' => [
'mode' => 'full',
],
])
->save();
// Create paragraph.
$paragraph = Paragraph::create([
'type' => 'test_paragraph',
]);
$paragraph->save();
// Create user with paragraph reference.
$user = $this->createUser([], 'paragraph_user', FALSE, ['ref_paragraph' => $paragraph]);
return $user;
}
/**
* Tests output for an entityreference field with cardinality 1.
*/
public function testSingleCardinality() {
// $referrer:
// - name="referrer"
// - ref_user field = user with name="target"
// CE display:
// - name = username (flattened)
// - ref-user = entityref-formatter: view mode = "full"
$referrer = $this->setupUser();
// Slot.
// @todo fix 'drupal-' prefix
$expected_markup = <<<EOF
<user name="referrer">
<user name="target" slot="ref-user"></user>
</user>
EOF;
$custom_element = $this->getCustomElementGenerator()->generate($referrer, 'full');
$tested_markup = $this->renderCustomElement($custom_element);
$this->assertMarkupEquals($expected_markup, $tested_markup);
// No slot. (Change ref-user config to is_slot = FALSE).
$this->changeReferenceDisplayComponent(FALSE);
$data = htmlspecialchars(json_encode([
'element' => 'user',
'name' => 'target',
]));
$expected_markup = <<<EOF
<user name="referrer" ref-user="$data"></user>
EOF;
$custom_element = $this->getCustomElementGenerator()->generate($referrer, 'full');
$tested_markup = $this->renderCustomElement($custom_element);
$this->assertMarkupEquals($expected_markup, $tested_markup);
// Flatten: all referenced fields are added in the current tag, prefixed by
// the configured element name ("ref-user").
$this->changeReferenceDisplayComponent(FALSE, ['flatten' => TRUE]);
$expected_markup = <<<EOF
<user name="referrer" ref-user-name="target"></user>
EOF;
$custom_element = $this->getCustomElementGenerator()->generate($referrer, 'full');
$tested_markup = $this->renderCustomElement($custom_element);
$this->assertMarkupEquals($expected_markup, $tested_markup);
// is_slot is ignored for 'flatten'.
$this->changeReferenceDisplayComponent(TRUE, ['flatten' => TRUE]);
$custom_element = $this->getCustomElementGenerator()->generate($referrer, 'full');
$tested_markup = $this->renderCustomElement($custom_element);
$this->assertMarkupEquals($expected_markup, $tested_markup);
// Rename component.
EntityCeDisplay::load('user.user.default')
->removeComponent('name')
->setComponent('user-name', [
'field_name' => 'name',
'is_slot' => FALSE,
'formatter' => 'flattened',
])
->save();
$expected_markup = <<<EOF
<user ref-user-user-name="target" user-name="referrer"></user>
EOF;
$custom_element = $this->getCustomElementGenerator()->generate($referrer, 'full');
$tested_markup = $this->renderCustomElement($custom_element);
$this->assertMarkupEquals($expected_markup, $tested_markup);
}
/**
* Tests output for a field with cardinality >1, with 1 value.
*
* Differences in the elements' structure are based on cardinality, not the
* number of referenced entities.
*/
public function testMultiValueFieldSingleValue() {
$referrer = $this->setupUser(TRUE);
// Slot: no difference with single-value field.
$expected_markup = <<<EOF
<user name="referrer">
<user name="target" slot="ref-user"></user>
</user>
EOF;
$custom_element = $this->getCustomElementGenerator()->generate($referrer, 'full');
$tested_markup = $this->renderCustomElement($custom_element);
$this->assertMarkupEquals($expected_markup, $tested_markup);
// No slot: array of elements, instead of a single element.
$this->changeReferenceDisplayComponent(FALSE);
$data = htmlspecialchars(json_encode([
['element' => 'user', 'name' => 'target'],
]));
$expected_markup = <<<EOF
<user name="referrer" ref-user="$data"></user>
EOF;
$custom_element = $this->getCustomElementGenerator()->generate($referrer, 'full');
$tested_markup = $this->renderCustomElement($custom_element);
$this->assertMarkupEquals($expected_markup, $tested_markup);
// 'Flatten' disregards cardinality, acts as single-value.
$this->changeReferenceDisplayComponent(FALSE, ['flatten' => TRUE]);
$expected_markup = <<<EOF
<user name="referrer" ref-user-name="target"></user>
EOF;
$custom_element = $this->getCustomElementGenerator()->generate($referrer, 'full');
$tested_markup = $this->renderCustomElement($custom_element);
$this->assertMarkupEquals($expected_markup, $tested_markup);
}
/**
* Tests output for a field with cardinality >1, with multiple values.
*
* Differences in the elements' structure are based on cardinality, not the
* number of referenced entities.
*/
public function testMultiValueFieldMultiValue() {
$referrer = $this->setupUser(TRUE, TRUE);
// Slot.
$expected_markup = <<<EOF
<user name="referrer">
<user name="target" slot="ref-user"></user>
<user name="target2" slot="ref-user"></user>
</user>
EOF;
$custom_element = $this->getCustomElementGenerator()->generate($referrer, 'full');
$tested_markup = $this->renderCustomElement($custom_element);
$this->assertMarkupEquals($expected_markup, $tested_markup);
// No slot: array of elements, instead of a single element.
$this->changeReferenceDisplayComponent(FALSE);
$data = htmlspecialchars(json_encode([
['element' => 'user', 'name' => 'target'],
['element' => 'user', 'name' => 'target2'],
]));
$expected_markup = <<<EOF
<user name="referrer" ref-user="$data"></user>
EOF;
$custom_element = $this->getCustomElementGenerator()->generate($referrer, 'full');
$tested_markup = $this->renderCustomElement($custom_element);
$this->assertMarkupEquals($expected_markup, $tested_markup);
// 'Flatten' disregards cardinality, acts as single-value.
$this->changeReferenceDisplayComponent(FALSE, ['flatten' => TRUE]);
$expected_markup = <<<EOF
<user name="referrer" ref-user-name="target"></user>
EOF;
$custom_element = $this->getCustomElementGenerator()->generate($referrer, 'full');
$tested_markup = $this->renderCustomElement($custom_element);
$this->assertMarkupEquals($expected_markup, $tested_markup);
}
/**
* Tests output for an entity_reference_revisions field with paragraph.
*/
public function testParagraphReferenceRevisions() {
$user = $this->setupParagraph();
// Get the paragraph ID for assertions.
$paragraph_id = $user->get('ref_paragraph')->entity->id();
// Test slot rendering - paragraph should render as child element with slot.
$expected_markup = <<<EOF
<user name="paragraph_user">
<test-paragraph id="$paragraph_id" slot="ref-paragraph"></test-paragraph>
</user>
EOF;
$custom_element = $this->getCustomElementGenerator()->generate($user, 'default');
$tested_markup = $this->renderCustomElement($custom_element);
$this->assertMarkupEquals($expected_markup, $tested_markup);
}
}
