name-8.x-1.x-dev/tests/src/Functional/NameFormatterTest.php

tests/src/Functional/NameFormatterTest.php
<?php

declare(strict_types=1);

namespace Drupal\Tests\name\Functional;

use Drupal\Core\Url;
use Drupal\node\Entity\NodeType;
use Drupal\name\Entity\NameFormat;
use Drupal\name\Entity\NameListFormat;
use Drupal\Component\Utility\DeprecationHelper;

/**
 * Functional tests for the NameFormatter service.
 *
 * Tests the NameFormatter service through the web interface and with real
 * user interactions, including field display, node creation, and formatting
 * through the UI.
 *
 * @group name
 * @coversDefaultClass \Drupal\name\NameFormatter
 */
class NameFormatterTest extends NameTestBase {

  /**
   * {@inheritdoc}
   */
  protected static $modules = [
    'field',
    'field_ui',
    'node',
    'name',
    'views',
  ];

  /**
   * The name formatter service.
   *
   * @var \Drupal\name\NameFormatter
   */
  protected $nameFormatter;

  /**
   * Test content type.
   *
   * @var \Drupal\node\Entity\NodeType
   */
  protected $contentType;

  /**
   * Test name field.
   *
   * @var string
   */
  protected $fieldName = 'field_test_name';

  /**
   * {@inheritdoc}
   */
  public function setUp(): void {
    parent::setUp();

    // Get the name formatter service.
    $this->nameFormatter = $this->container->get('name.formatter');

    // Create a test content type.
    $this->contentType = NodeType::create([
      'type' => 'test_content',
      'name' => 'Test Content',
    ]);
    $this->contentType->save();

    // Create a name field on the content type.
    $this->createNameField();
  }

  /**
   * Creates a name field on the test content type.
   */
  protected function createNameField(): void {
    $this->drupalLogin($this->adminUser);

    // Add the name field.
    $this->drupalGet('admin/structure/types/manage/test_content/fields/add-field');

    DeprecationHelper::backwardsCompatibleCall(
      \Drupal::VERSION,
      '11.2.2',
      fn() => $this->getSession()->getPage()->clickLink('Name'),
      fn() => !$this->getSession()->getPage()->fillField('new_storage_type', 'name') && $this->getSession()->getPage()->pressButton('Continue')
    );

    $field_settings = [
      'label' => 'Test Name',
      'field_name' => 'test_name',
    ];
    $this->submitForm($field_settings, 'Continue');

    // Configure the field storage settings.
    $storage_settings = [
      'settings[components][title]' => TRUE,
      'settings[components][given]' => TRUE,
      'settings[components][middle]' => TRUE,
      'settings[components][family]' => TRUE,
      'settings[components][generational]' => TRUE,
      'settings[components][credentials]' => TRUE,
      'settings[minimum_components][given]' => TRUE,
      'settings[minimum_components][family]' => TRUE,
      'settings[labels][title]' => 'Title',
      'settings[labels][given]' => 'Given name',
      'settings[labels][middle]' => 'Middle name',
      'settings[labels][family]' => 'Family name',
      'settings[labels][generational]' => 'Generational',
      'settings[labels][credentials]' => 'Credentials',
      'settings[max_length][title]' => 31,
      'settings[max_length][given]' => 63,
      'settings[max_length][middle]' => 127,
      'settings[max_length][family]' => 63,
      'settings[max_length][generational]' => 15,
      'settings[max_length][credentials]' => 255,
      'settings[title_options]' => "-- --\nMr.\nMrs.\nMiss\nDr.\nProf.",
      'settings[generational_options]' => "-- --\nJr.\nSr.\nI\nII\nIII\nIV",
    ];

    // Submit the storage settings and check for errors.
    DeprecationHelper::backwardsCompatibleCall(
      \Drupal::VERSION,
      '11.2.2',
      fn() => $this->submitForm($storage_settings, 'Save'),
      fn() => $this->submitForm($storage_settings, 'Save settings')
    );

    // Wait for the field to be fully created and clear caches.
    $this->resetAll();

    // Verify the field was created by checking the field list.
    $this->drupalGet('admin/structure/types/manage/test_content/fields');
    $this->assertSession()->pageTextContains('Test Name');

    // Also verify the field is accessible on the node add form.
    $this->drupalGet('node/add/test_content');
    $this->assertSession()->pageTextContains('Test Name');

    // Wait a bit more for the field to be fully available.
    sleep(1);

    // Final verification that the field components are accessible.
    $this->drupalGet('node/add/test_content');

    $this->assertSession()->fieldExists($this->fieldName . '[0][title]');
    $this->assertSession()->fieldExists($this->fieldName . '[0][given]');
    $this->assertSession()->fieldExists($this->fieldName . '[0][family]');
  }

  /**
   * Tests basic name formatting through the web interface.
   */
  public function testNameFormattingThroughWebInterface(): void {
    $this->drupalLogin($this->adminUser);

    // Create a test node with a name field.
    $node = $this->createTestNode();

    // View the node and verify the name is formatted correctly.
    $this->drupalGet('node/' . $node->id());
    $this->assertSession()->pageTextContains('Dr. John Michael Smith Jr., PhD');
  }

  /**
   * Tests name formatting with different format types.
   */
  public function testNameFormattingWithDifferentFormats(): void {
    // Create custom name formats for testing.
    $this->createCustomNameFormats();

    // Test the formatter service directly with different formats.
    $components = [
      'title' => 'Dr.',
      'given' => 'John',
      'middle' => 'Michael',
      'family' => 'Smith',
      'generational' => 'Jr.',
      'credentials' => 'PhD',
    ];

    // Test default format.
    $formatted = $this->nameFormatter->format($components, 'default');
    $this->assertStringContainsString('Dr. John Michael Smith Jr., PhD', (string) $formatted);

    // Test full format.
    $formatted = $this->nameFormatter->format($components, 'full');
    $this->assertStringContainsString('Dr. John Michael Smith Jr., PhD', (string) $formatted);

    // Test formal format.
    $formatted = $this->nameFormatter->format($components, 'test_formal');
    $this->assertStringContainsString('Dr. Smith', (string) $formatted);

    // Test family format.
    $formatted = $this->nameFormatter->format($components, 'test_family');
    $this->assertStringContainsString('Smith', (string) $formatted);
  }

  /**
   * Tests name list formatting functionality.
   */
  public function testNameListFormatting(): void {
    // Create custom list formats for testing.
    $this->createCustomListFormats();

    $names = [
      [
        'title' => 'Dr.',
        'given' => 'John',
        'family' => 'Smith',
        'credentials' => 'PhD',
      ],
      [
        'title' => 'Prof.',
        'given' => 'Jane',
        'family' => 'Doe',
        'credentials' => 'MD',
      ],
      [
        'title' => 'Mr.',
        'given' => 'Bob',
        'family' => 'Johnson',
      ],
    ];

    // Test default list format.
    $formatted = $this->nameFormatter->formatList($names, 'default', 'default');
    $this->assertStringContainsString('Dr. John Smith, PhD', (string) $formatted);
    $this->assertStringContainsString('Prof. Jane Doe, MD', (string) $formatted);
    $this->assertStringContainsString('Mr. Bob Johnson', (string) $formatted);

    // Test with et al formatting.
    $formatted = $this->nameFormatter->formatList($names, 'default', 'et_al');
    $this->assertStringContainsString('Dr. John Smith, PhD, et al', (string) $formatted);
  }

  /**
   * Tests name formatting with URL components.
   */
  public function testNameFormattingWithUrl(): void {
    $components = [
      'title' => 'Dr.',
      'given' => 'John',
      'family' => 'Smith',
      'url' => Url::fromUri('https://example.com/john-smith'),
    ];

    $formatted = $this->nameFormatter->format($components);
    $this->assertStringContainsString('<a href="https://example.com/john-smith">', (string) $formatted);
    $this->assertStringContainsString('Dr. John Smith', (string) $formatted);
    $this->assertStringContainsString('</a>', (string) $formatted);
  }

  /**
   * Tests name formatting settings.
   */
  public function testNameFormattingSettings(): void {
    // Test default settings.
    $this->assertEquals(' ', $this->nameFormatter->getSetting('sep1'));
    $this->assertEquals(', ', $this->nameFormatter->getSetting('sep2'));
    $this->assertEquals('', $this->nameFormatter->getSetting('sep3'));
    $this->assertEquals('none', $this->nameFormatter->getSetting('markup'));

    // Test setting custom values.
    $this->nameFormatter->setSetting('sep1', ' - ');
    $this->assertEquals(' - ', $this->nameFormatter->getSetting('sep1'));

    $this->nameFormatter->setSetting('markup', 'html');
    $this->assertEquals('html', $this->nameFormatter->getSetting('markup'));
  }

  /**
   * Tests delimiter type options.
   */
  public function testDelimiterTypeOptions(): void {
    $types = $this->nameFormatter->getLastDelimiterTypes(TRUE);
    $this->assertArrayHasKey('text', $types);
    $this->assertArrayHasKey('symbol', $types);
    $this->assertArrayHasKey('inherit', $types);

    $types_no_examples = $this->nameFormatter->getLastDelimiterTypes(FALSE);
    $this->assertArrayHasKey('text', $types_no_examples);
    $this->assertArrayHasKey('symbol', $types_no_examples);
    $this->assertArrayHasKey('inherit', $types_no_examples);
  }

  /**
   * Tests delimiter behavior options.
   */
  public function testDelimiterBehaviorOptions(): void {
    $behaviors = $this->nameFormatter->getLastDelimiterBehaviors(TRUE);
    $this->assertArrayHasKey('never', $behaviors);
    $this->assertArrayHasKey('always', $behaviors);
    $this->assertArrayHasKey('contextual', $behaviors);

    $behaviors_no_examples = $this->nameFormatter->getLastDelimiterBehaviors(FALSE);
    $this->assertArrayHasKey('never', $behaviors_no_examples);
    $this->assertArrayHasKey('always', $behaviors_no_examples);
    $this->assertArrayHasKey('contextual', $behaviors_no_examples);
  }

  /**
   * Tests name formatting through node creation and editing.
   */
  public function testNameFormattingInNodeOperations(): void {
    $this->drupalLogin($this->adminUser);

    // Create a node with a name field.
    $edit = [
      'title[0][value]' => 'Test Node with Name',
      $this->fieldName . '[0][title]' => 'Dr.',
      $this->fieldName . '[0][given]' => 'John',
      $this->fieldName . '[0][middle]' => 'Michael',
      $this->fieldName . '[0][family]' => 'Smith',
      $this->fieldName . '[0][generational]' => 'Jr.',
      $this->fieldName . '[0][credentials]' => 'PhD',
    ];

    $this->drupalGet('node/add/test_content');
    $this->submitForm($edit, 'Save');

    // Verify the node was created and the name is displayed correctly.
    $this->assertSession()->pageTextContains('Test Node with Name');
    $this->assertSession()->pageTextContains('Dr. John Michael Smith Jr., PhD');

    // Edit the node and change the name.
    $node = $this->getTestNodeByTitle('Test Node with Name');
    $this->drupalGet('node/' . $node->id() . '/edit');

    $edit = [
      $this->fieldName . '[0][title]' => 'Prof.',
      $this->fieldName . '[0][given]' => 'Jane',
      $this->fieldName . '[0][middle]' => '',
      $this->fieldName . '[0][family]' => 'Doe',
      $this->fieldName . '[0][generational]' => '_none',
      $this->fieldName . '[0][credentials]' => 'MD',
    ];

    $this->submitForm($edit, 'Save');

    // Verify the updated name is displayed correctly.
    $this->assertSession()->pageTextContains('Prof. Jane Doe, MD');
  }

  /**
   * Creates a test node with name field data.
   *
   * @return \Drupal\node\Entity\Node
   *   The created test node.
   */
  protected function createTestNode() {
    $edit = [
      'title[0][value]' => 'Test Node',
      $this->fieldName . '[0][title]' => 'Dr.',
      $this->fieldName . '[0][given]' => 'John',
      $this->fieldName . '[0][middle]' => 'Michael',
      $this->fieldName . '[0][family]' => 'Smith',
      $this->fieldName . '[0][generational]' => 'Jr.',
      $this->fieldName . '[0][credentials]' => 'PhD',
    ];

    $this->drupalGet('node/add/test_content');

    // Debug: Check if the form fields are present.
    $this->assertSession()->fieldExists('title[0][value]');

    // Check if the name field components are present.
    $this->assertSession()->fieldExists($this->fieldName . '[0][title]');
    $this->assertSession()->fieldExists($this->fieldName . '[0][given]');
    $this->assertSession()->fieldExists($this->fieldName . '[0][family]');

    $this->submitForm($edit, 'Save');

    return $this->getTestNodeByTitle('Test Node');
  }

  /**
   * Creates custom name formats for testing.
   */
  protected function createCustomNameFormats(): void {
    // Create a formal format.
    $formal_format = NameFormat::create([
      'id' => 'test_formal',
      'label' => 'Formal',
      'pattern' => 't+if',
      'status' => TRUE,
    ]);
    $formal_format->save();

    // Create a family format.
    $family_format = NameFormat::create([
      'id' => 'test_family',
      'label' => 'Family Only',
      'pattern' => 'if',
      'status' => TRUE,
    ]);
    $family_format->save();
  }

  /**
   * Creates custom list formats for testing.
   */
  protected function createCustomListFormats(): void {
    // Create an et al format.
    $et_al_format = NameListFormat::create([
      'id' => 'et_al',
      'label' => 'Et Al',
      'delimiter' => ', ',
      'and' => 'text',
      'delimiter_precedes_last' => 'never',
      'el_al_min' => 2,
      'el_al_first' => 1,
      'status' => TRUE,
    ]);
    $et_al_format->save();
  }

  /**
   * Gets a test node by its title.
   *
   * @param string $title
   *   The node title.
   *
   * @return \Drupal\node\Entity\Node|null
   *   The node entity or null if not found.
   */
  protected function getTestNodeByTitle(string $title) {
    $nodes = \Drupal::entityTypeManager()
      ->getStorage('node')
      ->loadByProperties(['title' => $title]);
    return !empty($nodes) ? reset($nodes) : NULL;
  }

}

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

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