custom_elements-8.x-2.x-dev/tests/src/Kernel/CustomElementGeneratorTest.php

tests/src/Kernel/CustomElementGeneratorTest.php
<?php

namespace Drupal\Tests\custom_elements\Kernel;

use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\Entity\EntityViewMode;
use Drupal\KernelTests\KernelTestBase;
use Drupal\Tests\node\Traits\NodeCreationTrait;
use Drupal\custom_elements\CustomElementGeneratorTrait;
use Drupal\custom_elements\Entity\EntityCeDisplay;
use Drupal\custom_elements\Entity\EntityCeDisplayInterface;
use Drupal\entity_test\Entity\EntityTest;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\Component\Utility\DeprecationHelper;

/**
 * Tests rendering of entityreference fields.
 *
 * @group custom_elements
 */
class CustomElementGeneratorTest extends KernelTestBase {

  use CustomElementGeneratorTrait;
  use NodeCreationTrait;

  /**
   * {@inheritdoc}
   *
   * @var bool
   * @todo Fix config schema for CE-displays and re-enable.
   */
  protected $strictConfigSchema = FALSE;

  /**
   * Default CE display, initialized/used by individual tests.
   */
  protected EntityCeDisplayInterface $defaultCeDisplay;

  /**
   * Full CE display, initialized/used by individual tests.
   */
  protected EntityCeDisplayInterface $fullCeDisplay;

  /**
   * Entity, initialized/used by individual tests.
   */
  protected ContentEntityInterface $testEntity;

  /**
   * View modes, initialized/used by individual tests.
   */
  protected array $coreViewModes = [];

  /**
   * Modules to install.
   *
   * @var string[]
   */
  protected static $modules = [
    'custom_elements',
    'entity_test',
    'field',
    'text',
    'block',
    'user',
    'layout_discovery',
    'layout_builder',
  ];

  /**
   * {@inheritdoc}
   */
  protected function setUp(): void {
    parent::setUp();
    // custom_elements_entity_type_alter() needs a layout_builder version.
    \Drupal::service('update.update_hook_registry')->setInstalledVersion('layout_builder', '12345');
    $this->installEntitySchema('user');
  }

  /**
   * Checks if Layout Builder clears content components (Drupal 11.3+).
   *
   * Starting with Drupal 11.3, Layout Builder automatically clears field
   * components from the content array when enabled. This is an acceptable
   * behavior change as it provides a better default UX when Layout Builder
   * is used - having an empty field list makes sense since fields should be
   * managed through the layout UI instead.
   *
   * This only affects autogenerated CE displays; sites with properly exported
   * configuration are unaffected.
   *
   * @return bool
   *   TRUE if running on Drupal 11.3 or later.
   *
   * @see https://www.drupal.org/project/drupal/issues/3385746
   * @see https://www.drupal.org/project/custom_elements/issues/3549949
   */
  protected function layoutBuilderClearsContentComponents() {
    return DeprecationHelper::backwardsCompatibleCall(
      currentVersion: \Drupal::VERSION,
      deprecatedVersion: '11.3',
      currentCallable: fn() => TRUE,
      deprecatedCallable: fn() => FALSE,
    );
  }

  /**
   * Tests that getEntityCeDisplay() takes the default CE display as fallback.
   */
  public function testViewModeFallback() {
    EntityViewMode::create([
      'id' => 'entity_test.full',
      'targetEntityType' => 'entity_test',
    ])->save();
    $ceDisplayDefault = EntityCeDisplay::create([
      'targetEntityType' => 'entity_test',
      'customElementName' => 'ce-test',
      'bundle' => 'entity_test',
      'mode' => 'default',
    ]);
    $ceDisplayDefault->save();
    $loadedDisplay = $this->getCustomElementGenerator()->getEntityCeDisplay('entity_test', 'entity_test', 'full');
    $this->assertSame($ceDisplayDefault->getCustomElementName(), $loadedDisplay->getCustomElementName());

    $ceDisplayFull = EntityCeDisplay::create([
      'targetEntityType' => 'entity_test',
      'customElementName' => 'ce-test-full',
      'bundle' => 'entity_test',
      'mode' => 'full',
    ]);
    $ceDisplayFull->save();
    $loadedDisplay = $this->getCustomElementGenerator()->getEntityCeDisplay('entity_test', 'entity_test', 'full');
    $this->assertSame($ceDisplayFull->getCustomElementName(), $loadedDisplay->getCustomElementName());

    $ceDisplayFull->setStatus(FALSE)->save();
    $loadedDisplay = $this->getCustomElementGenerator()->getEntityCeDisplay('entity_test', 'entity_test', 'full');
    $this->assertSame($ceDisplayDefault->getCustomElementName(), $loadedDisplay->getCustomElementName());

    // When no CE displays are active, one is created on the fly for the
    // 'default' view mode, regardless of the requested mode.
    $ceDisplayDefault->setStatus(FALSE)->save();
    $loadedDisplay = $this->getCustomElementGenerator()->getEntityCeDisplay('entity_test', 'entity_test', 'full');
    $this->assertSame('entity-test-entity-test', $loadedDisplay->getCustomElementName());
    $this->assertSame('default', $loadedDisplay->getMode());
    $this->assertSame('entity_test.entity_test.default', $loadedDisplay->id());
  }

  /**
   * Tests building custom elements using generate(), without core displays.
   *
   * This is not a usual situation. See testGenerateDefaultCore().
   */
  public function testGenerateNoCore() {
    // With [array-key-part 1] CE displays enabled, build custom element in
    // [array-key-part 2] view mode. Expect [value] to be used for generating.
    $this->dotestGenerate([], [
      // No CE displays exist: one is auto-created with a name based on the
      // view mode and fields based on the core display - which also does not
      // exist / is auto-created, with just the "name" field.
      'neither:default' => 'ce-autogen-default--core-autogen',
      'neither:unknown' => 'ce-autogen-unknown--core-autogen',
      'neither:full'    => 'ce-autogen-full--core-autogen',

      // If a CE display exists, its name is always taken from the display, so
      // it doesn't change per view mode like the auto-created one above does.
      // (So, ":unknown" is always the same as ":default".)
      'default:default' => 'ce-default',
      'default:full'    => 'ce-default',
      'both:default'    => 'ce-default',
      'both:full'       => 'ce-full',

      // Test only once, skip in further tests: we can assume
      // that full:full == both:full and full:default == neither:default.
      'full:default'    => 'ce-autogen-default--core-autogen',
      'full:unknown'    => 'ce-autogen-unknown--core-autogen',
      'full:full'       => 'ce-full',
    ]);

    // Same, with 'auto processing' enabled in CE displays.
    $this->dotestGenerate(['forceAutoProcessing' => TRUE], [
      'default:default' => 'ce-autoprocessed-default--core-autogen',
      'default:full'    => 'ce-autoprocessed-default--core-autogen',
      'both:default'    => 'ce-autoprocessed-default--core-autogen',
      'both:full'       => 'ce-autoprocessed-full--core-autogen',
    ]);

    // No core entity view display present (i.e. default entity view display
    // autogenerted by core): useLayoutBuilder has no effect.
    $this->dotestGenerate(['useLayoutBuilder' => TRUE], [
      'default:default' => 'ce-default',
      'default:full'    => 'ce-default',
      'both:default'    => 'ce-default',
      'both:full'       => 'ce-full',
    ]);

    $this->dotestGenerate(['useLayoutBuilder' => TRUE, 'forceAutoProcessing' => TRUE], [
      'default:default' => 'ce-autoprocessed-default--core-autogen',
      'default:full'    => 'ce-autoprocessed-default--core-autogen',
      'both:default'    => 'ce-autoprocessed-default--core-autogen',
      'both:full'       => 'ce-autoprocessed-full--core-autogen',
    ]);
  }

  /**
   * Tests generate() with default core display (not using Layout Builder).
   *
   * This is the default situation on a freshly installed site. (A default Core
   * entity view display is always saved into active configuration, which
   * ensures fields are output.)
   *
   * Difference with previous test: all ce-auto*-* are now using fields from
   * this core display, instead of an autogenerated one.
   */
  public function testGenerateCoreDefault() {
    $this->prepareTestGenerateCoreDisplays(['default-noLB']);

    $this->dotestGenerate([], [
      // Default core entity view display exisst: its fields are used in all
      // view modes.
      'neither:default' => 'ce-autogen-default--core-default',
      'neither:unknown' => 'ce-autogen-unknown--core-default',
      'neither:full'    => 'ce-autogen-full--core-default',

      'default:default' => 'ce-default',
      'default:full'    => 'ce-default',
      'both:default'    => 'ce-default',
      'both:full'       => 'ce-full',
    ]);

    $this->dotestGenerate(['forceAutoProcessing' => TRUE], [
      'default:default' => 'ce-autoprocessed-default--core-default',
      'default:full'    => 'ce-autoprocessed-default--core-default',
      'both:default'    => 'ce-autoprocessed-default--core-default',
      'both:full'       => 'ce-autoprocessed-full--core-default',
    ]);

    // useLayoutbuilder has no effect, i.e. all below have the same results as
    // in the first half.
    $this->dotestGenerate(['useLayoutBuilder' => TRUE], [
      'neither:default' => 'ce-autogen-default--core-default',
      'neither:unknown' => 'ce-autogen-unknown--core-default',
      'neither:full'    => 'ce-autogen-full--core-default',

      'default:default' => 'ce-default',
      'default:full'    => 'ce-default',
      'both:default'    => 'ce-default',
      'both:full'       => 'ce-full',
    ]);

    $this->dotestGenerate(['useLayoutBuilder' => TRUE, 'forceAutoProcessing' => TRUE], [
      'default:default' => 'ce-autoprocessed-default--core-default',
      'default:full'    => 'ce-autoprocessed-default--core-default',
      'both:default'    => 'ce-autoprocessed-default--core-default',
      'both:full'       => 'ce-autoprocessed-full--core-default',
    ]);
  }

  /**
   * Tests generate() with both core displays (not using Layout Builder).
   *
   * Difference with previous test: all ce-auto*-full--* are now using fields
   * from the "full" display.
   */
  public function testGenerateCoreBoth() {
    $this->prepareTestGenerateCoreDisplays(['default-noLB', 'full-noLB']);

    $this->dotestGenerate([], [
      'neither:default' => 'ce-autogen-default--core-default',
      'neither:unknown' => 'ce-autogen-unknown--core-default',
      'neither:full'    => 'ce-autogen-full--core-default',
      'default:default' => 'ce-default',
      'default:full'    => 'ce-default',
      'both:default'    => 'ce-default',
      'both:full'       => 'ce-full',
    ]);

    // Again: LB has no effect, only autoprocessing. Skip LB here.
    $this->dotestGenerate(['forceAutoProcessing' => TRUE], [
      'default:default' => 'ce-autoprocessed-default--core-default',
      'default:full'    => 'ce-autoprocessed-default--core-full',
      'both:default'    => 'ce-autoprocessed-default--core-default',
      'both:full'       => 'ce-autoprocessed-full--core-full',
    ]);
  }

  /**
   * Tests generate() with both core displays having Layout Builder enabled.
   */
  public function testGenerateCoreBothWithLayout() {
    $this->prepareTestGenerateCoreDisplays(['default-LB', 'full-LB']);

    // If Layout Builder is not enabled in CE display: same as previous test.
    $this->dotestGenerate([], [
      'neither:default' => 'ce-autogen-default--core-default',
      'neither:unknown' => 'ce-autogen-unknown--core-default',
      'neither:full'    => 'ce-autogen-full--core-default',

      'default:default' => 'ce-default',
      'default:full'    => 'ce-default',
      'both:default'    => 'ce-default',
      'both:full'       => 'ce-full',
    ]);

    // Again: LB has no effect, only autoprocessing. Skip LB here.
    $this->dotestGenerate(['forceAutoProcessing' => TRUE], [
      'default:default' => 'ce-autoprocessed-default--core-default',
      'default:full'    => 'ce-autoprocessed-default--core-full',
      'both:default'    => 'ce-autoprocessed-default--core-default',
      'both:full'       => 'ce-autoprocessed-full--core-full',
    ]);

    $this->dotestGenerate(['useLayoutBuilder' => TRUE], [
      'default:default' => 'ce-default-layout',
      // "unknown" view mode: fall back to default CE display, see LB enabled,
      // fall back to default core entity view display for LB setting + layout.
      // "full" view mode: fall back to default CE display, see LB enabled,
      // use LB setting + layout from "full" core entity view display.
      'default:full'    => 'ce-default-layout',
      'both:default'    => 'ce-default-layout',
      'both:full'       => 'ce-full-layout',
    ]);

    // forceAutoProcessing makes no difference: useLayoutBuilder has
    // precedence.
    $this->dotestGenerate(['useLayoutBuilder' => TRUE, 'forceAutoProcessing' => TRUE], [
      'default:default' => 'ce-default-layout',
      'default:full'    => 'ce-default-layout',
      'both:default'    => 'ce-default-layout',
      'both:full'       => 'ce-full-layout',
    ]);
  }

  /**
   * Tests generate() with default core display having Layout Builder enabled.
   */
  public function testGenerateCoreDefaultWithLayout() {
    $this->prepareTestGenerateCoreDisplays(['default-LB']);

    $this->dotestGenerate(['useLayoutBuilder' => TRUE], [
      // "neither:*" behaves the same as when LB is disabled in Core display
      // (testGenerateCoreDefault()).
      'neither:default' => 'ce-autogen-default--core-default',
      'neither:unknown' => 'ce-autogen-unknown--core-default',
      'neither:full'    => 'ce-autogen-full--core-default',

      'default:default' => 'ce-default-layout',
      // Fall back to default CE display, see LB enabled, fall back to default
      // core entity view display for LB setting + layout.
      'default:full'    => 'ce-default-layout',
      'both:default'    => 'ce-default-layout',
      'both:full'       => 'ce-full-layout',
    ]);

    $this->dotestGenerate(['useLayoutBuilder' => TRUE, 'forceAutoProcessing' => TRUE], [
      'default:default' => 'ce-default-layout',
      'default:full'    => 'ce-default-layout',
      'both:default'    => 'ce-default-layout',
      'both:full'       => 'ce-full-layout',
    ]);
  }

  /**
   * Tests generate() with default display having LB enabled, and full disabled.
   */
  public function testGenerateCoreDefaultWithLayoutFullWithout() {
    $this->prepareTestGenerateCoreDisplays(['default-LB', 'full-noLB']);

    $this->dotestGenerate(['useLayoutBuilder' => TRUE], [
      'default:default' => 'ce-default-layout',
      // Fall back to default CE display, see LB enabled, check full core
      // display, do not see LB enabled, fall back to building using CE display.
      'default:full'    => 'ce-default',
      'both:default'    => 'ce-default-layout',
      'both:full'       => 'ce-full',
    ]);

    $this->dotestGenerate(['useLayoutBuilder' => TRUE, 'forceAutoProcessing' => TRUE], [
      'default:default' => 'ce-default-layout',
      'default:full'    => 'ce-autoprocessed-default--core-full',
      'both:default'    => 'ce-default-layout',
      'both:full'       => 'ce-autoprocessed-full--core-full',
    ]);
  }

  /**
   * Tests generate() with default display having LB disabled, and full enabled.
   */
  public function testGenerateCoreDefaultWithoutLayoutFullWith() {
    $this->prepareTestGenerateCoreDisplays(['default-noLB', 'full-LB']);

    $this->dotestGenerate(['useLayoutBuilder' => TRUE], [
      'default:default' => 'ce-default',
      // "unknown" view mode: fall back to default CE display, see LB enabled,
      // fall back to default core entity view display for LB setting and see
      // it disabled -> ce-default.
      // "full" view mode: fall back to default CE display, see LB enabled,
      // use LB setting + layout from "full" core entity view display.
      'default:full'    => 'ce-default-layout',
      'both:default'    => 'ce-default',
      'both:full'       => 'ce-full-layout',
    ]);

    $this->dotestGenerate(['useLayoutBuilder' => TRUE, 'forceAutoProcessing' => TRUE], [
      'default:default' => 'ce-autoprocessed-default--core-default',
      'default:full'    => 'ce-default-layout',
      'both:default'    => 'ce-autoprocessed-default--core-default',
      'both:full'       => 'ce-full-layout',
    ]);
  }

  /**
   * Tests generate() with full core display having Layout Builder enabled.
   *
   * This is unrealistic (there's always a default core display in practice),
   * but do just for almost-completeness. (There is no test for ['full-noLB'].)
   */
  public function testGenerateCoreFullWithLayout() {
    $this->prepareTestGenerateCoreDisplays(['full-LB']);

    $this->dotestGenerate(['useLayoutBuilder' => TRUE], [
      'neither:default' => 'ce-autogen-default--core-autogen',
      'neither:unknown' => 'ce-autogen-unknown--core-autogen',
      'neither:full'    => 'ce-autogen-full--core-autogen',

      // Same as ['default-noLB', 'full-LB']:
      'default:default' => 'ce-default',
      'default:full'    => 'ce-default-layout',
      'both:default'    => 'ce-default',
      'both:full'       => 'ce-full-layout',
    ]);

    $this->dotestGenerate(['useLayoutBuilder' => TRUE, 'forceAutoProcessing' => TRUE], [
      'default:default' => 'ce-autoprocessed-default--core-autogen',
      'default:full'    => 'ce-default-layout',
      'both:default'    => 'ce-autoprocessed-default--core-autogen',
      'both:full'       => 'ce-full-layout',
    ]);
  }

  /**
   * Prepares doTestGenerate(), can be called only once per test.
   *
   * @param string[] $viewModes
   *   View modes to create core displays for; ending in '*' if the display
   *   should not have Layout Builder enabled.
   */
  protected function prepareTestGenerateCoreDisplays(array $viewModes) {
    // Entity view displays can only be created after the view mode is created,
    // so store in class variable. This is a separate method, as a reminder
    // that these entity view displays are only created in the first
    // doTestGenerate() call, so repeated calls cannot handle entity view
    // displays with different settings.
    $this->coreViewModes = $viewModes;
  }

  /**
   * Perform tests on generate() with set conditions.
   *
   * If core display view modes are needed, prepareTestGenerate() must be
   * called beforehand.
   *
   * @param array $ceDisplayAddConfig
   *   Configuration values to set for CE display, in addition to standard
   *   values as set in this method.
   * @param array $conditions
   *   An array with expected results that signify which display was used for
   *   generating a custom element, having a fixed set of required keys that
   *   describe conditions. Examples:
   *   'both:full':    with both default & full displays enabled, build full.
   *   'default:full': with only default display enabled, build full display.
   */
  protected function doTestGenerate(array $ceDisplayAddConfig, array $conditions): void {
    if (isset($this->fullCeDisplay)) {
      // Do not reinitialize fields / core displays; delete CE displays so they
      // are reinitialized.
      $this->fullCeDisplay->delete();
      $this->defaultCeDisplay->delete();
    }
    else {
      // See doTestGenerateAssertions() for details of field/display setup.
      FieldStorageConfig::create([
        'entity_type' => 'entity_test',
        'field_name' => 'field_string',
        'type' => 'string',
        'cardinality' => 1,
      ])->save();
      FieldConfig::create([
        'entity_type' => 'entity_test',
        'field_name' => 'field_string',
        'bundle' => 'entity_test',
        'label' => 'Test string field',
        'translatable' => FALSE,
      ])->save();
      FieldStorageConfig::create([
        'entity_type' => 'entity_test',
        'field_name' => 'field_string2',
        'type' => 'string',
        'cardinality' => 1,
      ])->save();
      FieldConfig::create([
        'entity_type' => 'entity_test',
        'field_name' => 'field_string2',
        'bundle' => 'entity_test',
        'label' => 'Test string field2',
        'translatable' => FALSE,
      ])->save();
      $this->testEntity = EntityTest::create([
        'type' => 'entity_test',
        'name' => 'Test Entity',
        'field_string' => 'This is a test',
        'field_string2' => 'Show me in full mode',
      ]);

      EntityViewMode::create([
        'id' => 'entity_test.full',
        'targetEntityType' => 'entity_test',
      ])->save();

      foreach ($this->coreViewModes as $viewMode) {
        // Accept only two kinds of strings; others are considered an incorrect
        // test definition.
        $this->assertTrue(str_ends_with($viewMode, '-LB') || str_ends_with($viewMode, '-noLB'));
        $layoutBuilderEnabled = str_ends_with($viewMode, '-LB');
        $viewMode = substr($viewMode, 0, strlen($viewMode) - ($layoutBuilderEnabled ? 3 : 5));
        /** @var \Drupal\Core\Entity\EntityDisplayRepositoryInterface $coreDisplayRepository */
        $coreDisplayRepository = $this->container->get('entity_display.repository');
        $display = $coreDisplayRepository->getViewDisplay('entity_test', 'entity_test', $viewMode);
        if ($layoutBuilderEnabled) {
          $display->setThirdPartySetting('layout_builder', 'enabled', TRUE);
        }
        // Add one of the fields. ('name' in the output cannot be customized.)
        $display->setComponent($viewMode === 'full' ? 'field_string2' : 'field_string');

        $display->save();
      }
    }

    if (isset($conditions['neither:default']) || isset($conditions['neither:full']) || isset($conditions['neither:unknown'])) {
      // Three conditions must always exist together; if they don't, this is
      // considered an incorrect test definition.
      $this->assertTrue(isset($conditions['neither:default'], $conditions['neither:full'], $conditions['neither:unknown']));
      $this->doTestGenerateAssertions('default', $conditions['neither:default']);
      $this->doTestGenerateAssertions('unknown', $conditions['neither:unknown']);
      $this->doTestGenerateAssertions('full', $conditions['neither:full']);
    }

    // Create default CE display with field_string as a different name.
    $this->defaultCeDisplay = EntityCeDisplay::create($ceDisplayAddConfig + [
      'targetEntityType' => 'entity_test',
      'customElementName' => 'ce-test',
      'bundle' => 'entity_test',
      'mode' => 'default',
    ])
      ->removeComponent('name')
      ->removeComponent('string')
      ->removeComponent('string2')
      ->setComponent('text', ['field_name' => 'field_string', 'formatter' => 'auto']);
    $this->defaultCeDisplay->save();
    $this->doTestGenerateAssertions('default', $conditions['default:default']);
    // Unknown view mode must always have the same result as default (if a CE
    // display for "default" exists), so do not expect it to be defined but
    // always test the "unknown" view mode. Note if ":unkonwn" is explicitly
    // defined, then this is apparently not true anymore; take that instead.
    $this->doTestGenerateAssertions('unknown', $conditions['default:unknown'] ?? $conditions['default:default']);
    $this->doTestGenerateAssertions('full', $conditions['default:full']);

    $this->fullCeDisplay = EntityCeDisplay::create($ceDisplayAddConfig + [
      'targetEntityType' => 'entity_test',
      'customElementName' => 'ce-test-full',
      'bundle' => 'entity_test',
      'mode' => 'full',
    ])
      ->removeComponent('name')
      ->removeComponent('string')
      ->removeComponent('string2')
      ->setComponent('text', ['field_name' => 'field_string2', 'formatter' => 'auto']);
    $this->fullCeDisplay->save();
    $this->doTestGenerateAssertions('default', $conditions['both:default']);
    $this->doTestGenerateAssertions('unknown', $conditions['both:unknown'] ?? $conditions['both:default']);
    $this->doTestGenerateAssertions('full', $conditions['both:full']);

    if (isset($conditions['full:default']) || isset($conditions['full:full']) || isset($conditions['full:unknown'])) {
      $this->assertTrue(isset($conditions['full:default'], $conditions['full:full'], $conditions['full:unknown']));
      $this->defaultCeDisplay->setStatus(FALSE)->save();
      $this->doTestGenerateAssertions('default', $conditions['full:default']);
      $this->doTestGenerateAssertions('unknown', $conditions['full:unknown']);
      $this->doTestGenerateAssertions('full', $conditions['full:full']);
    }

    // Run "neither:" tests again, to prove that nonexistent and disabled
    // displays behave the same.
    if (isset($conditions['neither:default']) || isset($conditions['neither:full']) || isset($conditions['neither:unknown'])) {
      $this->assertTrue(isset($conditions['neither:default'], $conditions['neither:full'], $conditions['neither:unknown']));
      $this->defaultCeDisplay->setStatus(FALSE)->save();
      $this->fullCeDisplay->setStatus(FALSE)->save();
      $this->doTestGenerateAssertions('default', $conditions['neither:default']);
      $this->doTestGenerateAssertions('unknown', $conditions['neither:unknown']);
      $this->doTestGenerateAssertions('full', $conditions['neither:full']);
    }
  }

  /**
   * Checks which display was used for building an entity into a custom element.
   */
  protected function doTestGenerateAssertions(string $viewMode, string $expectedDisplayUsage): void {
    $customElement = $this->getCustomElementGenerator()->generate($this->testEntity, $viewMode);

    // The actual asserts are abstracted away into here, because they are not
    // very interesting. doTestGenerate() must create/configure test entity and
    // displays exactly as needed here. The fields (disregarding element name)
    // are set as follows:
    // - auto-created CE display based on auto-created entity view display:
    //   name=label. (Auto-created 'full' vs 'default' displays cannot be
    //   distinguished by fields, only by element name.)
    // - (auto-created CE display / autoprocessing=on, based on) default Core:
    //   name=label + string=field_string. (auto-created vs autoprocessing
    //   cannot be distinguished by fields, only by element name.)
    // - (auto-created CE display / autoprocessing=on, based on) full Core:
    //   name=label + string2=field_string2
    // - default CE display:
    //   text=field_string.
    // - full CE display:
    //   text=field_string2.
    // - layout (i.e. both CE and core display have "use LB" enabled):
    //   None. (Tests do not distinguish different layouts yet.)
    $expectedCoreDisplayUsage = '';
    switch ($expectedDisplayUsage) {
      case 'ce-autogen-default--core-autogen':
      case 'ce-autogen-default--core-default':
      case 'ce-autogen-unknown--core-autogen':
      case 'ce-autogen-unknown--core-default':
      case 'ce-autogen-full--core-autogen':
      case 'ce-autogen-full--core-default':
      case 'ce-autogen-full--core-full':
        // Element name: type + bundle + non-default view mode for the CE
        // display (as retrieved from the above string; assumption: starting at
        // position 11.)
        $pos = strpos($expectedDisplayUsage, '--core-');
        if ($pos === FALSE) {
          throw new \LogicException('doTestGenerateAssertions() has incorrect $expectedDisplayUsage usage.');
        }

        $expectedTag = 'entity-test-entity-test';
        $this->assertSame($expectedTag, $customElement->getTag());

        // Fields as set up in the core display. (Setup varies them by display.)
        $expectedCoreDisplayUsage = TRUE;
        break;

      case 'ce-autoprocessed-default--core-autogen':
      case 'ce-autoprocessed-default--core-default':
      case 'ce-autoprocessed-default--core-full':
        // Element name: as set up in the CE display. Fields: as set up in the
        // core display. (Setup varies them by display.)
        $this->assertSame($this->defaultCeDisplay->getCustomElementName(), $customElement->getTag());
        $expectedCoreDisplayUsage = TRUE;
        break;

      case 'ce-autoprocessed-full--core-autogen':
      case 'ce-autoprocessed-full--core-default':
      case 'ce-autoprocessed-full--core-full':
        $this->assertSame($this->fullCeDisplay->getCustomElementName(), $customElement->getTag());
        $expectedCoreDisplayUsage = TRUE;
        break;

      case 'ce-default':
        $this->assertSame($this->defaultCeDisplay->getCustomElementName(), $customElement->getTag());
        $this->assertNull($customElement->getAttribute('name'));
        $this->assertSame('This is a test', $customElement->getAttribute('text'));
        $this->assertNull($customElement->getAttribute('string'));
        $this->assertNull($customElement->getAttribute('string2'));
        $this->assertEmpty($customElement->getSlots());
        break;

      case 'ce-default-layout':
        // Tests do not distinguish yet between default vs full layouts. They
        // only distinguish the name that is used from the CE display.
        $this->assertSame($this->defaultCeDisplay->getCustomElementName(), $customElement->getTag());
        // When layout builder is enabled, the sections slot must be there,
        // else the output must be as without layout builder.
        $this->assertArrayHasKey('sections', $customElement->getSlots());
        $this->assertNull($customElement->getAttribute('name'));
        $this->assertSame('This is a test', $customElement->getAttribute('text'));
        $this->assertNull($customElement->getAttribute('string'));
        $this->assertNull($customElement->getAttribute('string2'));
        break;

      case 'ce-full':
        $this->assertSame($this->fullCeDisplay->getCustomElementName(), $customElement->getTag());
        $this->assertNull($customElement->getAttribute('name'));
        $this->assertSame('Show me in full mode', $customElement->getAttribute('text'));
        $this->assertNull($customElement->getAttribute('string'));
        $this->assertNull($customElement->getAttribute('string2'));
        $this->assertEmpty($customElement->getSlots());
        break;

      case 'ce-full-layout':
        $this->assertSame($this->fullCeDisplay->getCustomElementName(), $customElement->getTag());
        // When layout builder is enabled, the sections slot must be there,
        // else the output must be as without layout builder.
        $this->assertArrayHasKey('sections', $customElement->getSlots());
        $this->assertNull($customElement->getAttribute('name'));
        $this->assertSame('Show me in full mode', $customElement->getAttribute('text'));
        $this->assertNull($customElement->getAttribute('string'));
        $this->assertNull($customElement->getAttribute('string2'));
        break;

      default:
        throw new \LogicException("doTestGenerateAssertions() must define '$expectedDisplayUsage' as CE display option.");
    }

    if ($expectedCoreDisplayUsage) {
      if ($expectedCoreDisplayUsage === TRUE) {
        // Set from the input parameter, just after "--core-".
        $pos = strpos($expectedDisplayUsage, '--core-');
        if ($pos === FALSE) {
          throw new \LogicException('doTestGenerateAssertions() has incorrect $expectedDisplayUsage+$expectedCoreDisplayUsage usage.');
        }
        $expectedCoreDisplayUsage = substr($expectedDisplayUsage, $pos + 7);
      }
      switch ($expectedCoreDisplayUsage) {
        case 'default':
          $this->assertSame('Test Entity', $customElement->getAttribute('name'));
          $this->assertNull($customElement->getAttribute('text'));
          // Drupal 11.3+ clears content components when Layout Builder is
          // enabled. This is acceptable - autogenerated displays have no fields
          // to copy. Saved CE displays are unaffected.
          if ($this->layoutBuilderClearsContentComponents() && in_array('default-LB', $this->coreViewModes)) {
            $this->assertNull($customElement->getAttribute('string'));
          }
          else {
            $this->assertSame('This is a test', $customElement->getAttribute('string'));
          }
          $this->assertNull($customElement->getAttribute('string2'));
          $this->assertEmpty($customElement->getSlots());
          break;

        case 'full':
          $this->assertSame('Test Entity', $customElement->getAttribute('name'));
          $this->assertNull($customElement->getAttribute('text'));
          $this->assertNull($customElement->getAttribute('string'));
          // Drupal 11.3+ clears content components when Layout Builder is
          // enabled. This is acceptable - autogenerated displays have no fields
          // to copy. Saved CE displays are unaffected.
          if ($this->layoutBuilderClearsContentComponents() && in_array('full-LB', $this->coreViewModes)) {
            $this->assertNull($customElement->getAttribute('string2'));
          }
          else {
            $this->assertSame('Show me in full mode', $customElement->getAttribute('string2'));
          }
          $this->assertEmpty($customElement->getSlots());
          break;

        case 'autogen':
          $this->assertSame('Test Entity', $customElement->getAttribute('name'));
          $this->assertNull($customElement->getAttribute('text'));
          $this->assertNull($customElement->getAttribute('string'));
          $this->assertNull($customElement->getAttribute('string2'));
          $this->assertEmpty($customElement->getSlots());
          break;

        default:
          throw new \LogicException("doTestGenerateAssertions() must define '$expectedCoreDisplayUsage' as core display option.");
      }
    }
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc