Commit 829cd7ff authored by Ben Mullins's avatar Ben Mullins
Browse files

Issue #3091478 by Tim Bozeman, lauriii, malcomio, EclipseGc, larowlan,...

Issue #3091478 by Tim Bozeman, lauriii, malcomio, EclipseGc, larowlan, tim.plunkett, amateescu, dpi: Improve StringItem::generateSampleValue()
parent 563b977e
Loading
Loading
Loading
Loading
+44 −1
Original line number Diff line number Diff line
@@ -72,7 +72,50 @@ public function getConstraints() {
   */
  public static function generateSampleValue(FieldDefinitionInterface $field_definition) {
    $random = new Random();
    $values['value'] = $random->word(mt_rand(1, $field_definition->getSetting('max_length')));
    $max_length = $field_definition->getSetting('max_length');

    // When the maximum length is less than 15, generate a random word instead
    // of sentences.
    if ($max_length <= 15) {
      $values['value'] = ucfirst($random->word($max_length));

      return $values;
    }

    // The minimum length is either 10% of the maximum length, or 15 characters
    // long, whichever is greater.
    $min_length = max(ceil($max_length * 0.10), 15);

    // The random value is generated multiple times to create a slight
    // preference towards values that are closer to the minimum length of the
    // string. For values larger than 255 (which is the default maximum value),
    // the bias towards minimum length is increased. This is because the default
    // maximum length of 255 is often used for fields that include shorter
    // values (i.e. title).
    $length = mt_rand($min_length, mt_rand($min_length, $max_length >= 255 ? mt_rand($min_length, $max_length) : $max_length));

    $string = $random->sentences(1);
    while (mb_strlen($string) < $length) {
      $string .= " {$random->sentences(1)}";
    }

    // If the length of the generated string is longer than the maximum length,
    // re-create the string word by word to reduce the chances of the string
    // ending middle of a word.
    if (mb_strlen($string) > $max_length) {
      $words = explode(' ', $string);
      $string = array_reduce($words, function ($current, $item) use ($length) {
        return mb_strlen($current) > $length ? $current : "$current$item ";
      }, '');
    }

    // Normalize the string to be shorter than the maximum length.
    $normalized_value = rtrim(mb_substr($string, 0, $max_length - 1), ' .');

    // Ensure that the string ends with a full stop if there are multiple
    // sentences.
    $values['value'] = $normalized_value . (str_contains($normalized_value, '.') ? '.' : '');

    return $values;
  }

+19 −0
Original line number Diff line number Diff line
@@ -28,4 +28,23 @@ class WorkspaceJsonAnonTest extends WorkspaceResourceTestBase {
   */
  protected $defaultTheme = 'stark';

  /**
   * {@inheritdoc}
   */
  protected function getModifiedEntityForPostTesting(): array {
    $values = parent::getModifiedEntityForPostTesting();
    // The ID field for a workspace uses a string field, with a validation
    // constraint that applies a regex pattern that prevents whitespace.
    // \Drupal\Core\Field\Plugin\Field\FieldType\StringItem::generateSampleValue
    // used in the parent implementation of ::getModifiedEntityForPostTesting
    // can generate whitespace, so we use the same regex pattern here to ensure
    // the generated value is valid for the sake of the test.
    //
    // @see \Drupal\Core\Field\Plugin\Field\FieldType\StringItem::generateSampleValue
    // @see \Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase::getModifiedEntityForPostTesting
    // @see \Drupal\workspaces\Entity\Workspace::baseFieldDefinitions
    $values['id'] = preg_replace('/[^a-z0-9_]/', '', $values['id']);
    return $values;
  }

}
+50 −0
Original line number Diff line number Diff line
<?php

namespace Drupal\Tests\Core\Field;

use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\Plugin\Field\FieldType\StringItem;
use Drupal\Tests\UnitTestCase;

/**
 * Defines a test for the StringItem field-type.
 *
 * @group Field
 * @coversDefaultClass \Drupal\Core\Field\Plugin\Field\FieldType\StringItem
 */
class StringItemTest extends UnitTestCase {

  /**
   * Tests generating sample values.
   *
   * @param int $max_length
   *   Maximum field length.
   *
   * @covers ::generateSampleValue
   * @dataProvider providerMaxLength
   */
  public function testGenerateSampleValue(int $max_length): void {
    $definition = $this->prophesize(FieldDefinitionInterface::class);
    $definition->getSetting('max_length')->willReturn($max_length);
    $sample_value = StringItem::generateSampleValue($definition->reveal());
    $this->assertLessThanOrEqual($max_length, mb_strlen($sample_value['value']));
  }

  /**
   * Data provider for maximum-lengths.
   *
   * @return array
   *   Test cases.
   */
  public function providerMaxLength(): array {
    return [
      '32' => [32],
      '255' => [255],
      '500' => [500],
      '15' => [15],
      '4' => [4],
      '64' => [64],
    ];
  }

}