You are here

public function DateTimeFieldTest::testDatetimeField in Drupal 10

Same name and namespace in other branches
  1. 8 core/modules/datetime/tests/src/Functional/DateTimeFieldTest.php \Drupal\Tests\datetime\Functional\DateTimeFieldTest::testDatetimeField()
  2. 9 core/modules/datetime/tests/src/Functional/DateTimeFieldTest.php \Drupal\Tests\datetime\Functional\DateTimeFieldTest::testDatetimeField()

Tests date and time field.

File

core/modules/datetime/tests/src/Functional/DateTimeFieldTest.php, line 242

Class

DateTimeFieldTest
Tests Datetime field functionality.

Namespace

Drupal\Tests\datetime\Functional

Code

public function testDatetimeField() {
  $field_name = $this->fieldStorage
    ->getName();
  $field_label = $this->field
    ->label();

  // Change the field to a datetime field.
  $this->fieldStorage
    ->setSetting('datetime_type', 'datetime');
  $this->fieldStorage
    ->save();

  // Display creation form.
  $this
    ->drupalGet('entity_test/add');
  $this
    ->assertSession()
    ->fieldValueEquals("{$field_name}[0][value][date]", '');
  $this
    ->assertSession()
    ->fieldValueEquals("{$field_name}[0][value][time]", '');
  $this
    ->assertSession()
    ->elementTextContains('xpath', '//fieldset[@id="edit-' . $field_name . '-0"]/legend', $field_label);
  $this
    ->assertSession()
    ->elementExists('xpath', '//fieldset[@aria-describedby="edit-' . $field_name . '-0--description"]');
  $this
    ->assertSession()
    ->elementExists('xpath', '//div[@id="edit-' . $field_name . '-0--description"]');

  // Build up a date in the UTC timezone.
  $value = '2012-12-31 00:00:00';
  $date = new DrupalDateTime($value, 'UTC');

  // Update the timezone to the system default.
  $date
    ->setTimezone(timezone_open(date_default_timezone_get()));

  // Submit a valid date and ensure it is accepted.
  $date_format = DateFormat::load('html_date')
    ->getPattern();
  $time_format = DateFormat::load('html_time')
    ->getPattern();
  $edit = [
    "{$field_name}[0][value][date]" => $date
      ->format($date_format),
    "{$field_name}[0][value][time]" => $date
      ->format($time_format),
  ];
  $this
    ->submitForm($edit, 'Save');
  preg_match('|entity_test/manage/(\\d+)|', $this
    ->getUrl(), $match);
  $id = $match[1];
  $this
    ->assertSession()
    ->pageTextContains('entity_test ' . $id . ' has been created.');
  $this
    ->assertSession()
    ->responseContains($date
    ->format($date_format));
  $this
    ->assertSession()
    ->responseContains($date
    ->format($time_format));

  /** @var \Drupal\Core\Entity\EntityDisplayRepositoryInterface $display_repository */
  $display_repository = \Drupal::service('entity_display.repository');

  // Verify that the date is output according to the formatter settings.
  $options = [
    'format_type' => [
      'short',
      'medium',
      'long',
    ],
  ];
  foreach ($options as $setting => $values) {
    foreach ($values as $new_value) {

      // Update the entity display settings.
      $this->displayOptions['settings'] = [
        $setting => $new_value,
      ] + $this->defaultSettings;
      $display_repository
        ->getViewDisplay($this->field
        ->getTargetEntityTypeId(), $this->field
        ->getTargetBundle(), 'full')
        ->setComponent($field_name, $this->displayOptions)
        ->save();
      $this
        ->renderTestEntity($id);
      switch ($setting) {
        case 'format_type':

          // Verify that a date is displayed.
          $date_formatter = $this->container
            ->get('date.formatter');
          $expected = $date_formatter
            ->format($date
            ->getTimestamp(), $new_value);
          $expected_iso = $date_formatter
            ->format($date
            ->getTimestamp(), 'custom', 'Y-m-d\\TH:i:s\\Z', 'UTC');
          $output = $this
            ->renderTestEntity($id);
          $expected_markup = '<time datetime="' . $expected_iso . '">' . $expected . '</time>';
          $this
            ->assertStringContainsString($expected_markup, $output, new FormattableMarkup('Formatted date field using %value format displayed as %expected with %expected_iso attribute.', [
            '%value' => $new_value,
            '%expected' => $expected,
            '%expected_iso' => $expected_iso,
          ]));
          break;
      }
    }
  }

  // Verify that the plain formatter works.
  $this->displayOptions['type'] = 'datetime_plain';
  $this->displayOptions['settings'] = $this->defaultSettings;
  $display_repository
    ->getViewDisplay($this->field
    ->getTargetEntityTypeId(), $this->field
    ->getTargetBundle(), 'full')
    ->setComponent($field_name, $this->displayOptions)
    ->save();
  $expected = $date
    ->format(DateTimeItemInterface::DATETIME_STORAGE_FORMAT);
  $output = $this
    ->renderTestEntity($id);
  $this
    ->assertStringContainsString($expected, $output, new FormattableMarkup('Formatted date field using plain format displayed as %expected.', [
    '%expected' => $expected,
  ]));

  // Verify that the 'datetime_custom' formatter works.
  $this->displayOptions['type'] = 'datetime_custom';
  $this->displayOptions['settings'] = [
    'date_format' => 'm/d/Y g:i:s A',
  ] + $this->defaultSettings;
  $display_repository
    ->getViewDisplay($this->field
    ->getTargetEntityTypeId(), $this->field
    ->getTargetBundle(), 'full')
    ->setComponent($field_name, $this->displayOptions)
    ->save();
  $expected = $date
    ->format($this->displayOptions['settings']['date_format']);
  $output = $this
    ->renderTestEntity($id);
  $this
    ->assertStringContainsString($expected, $output, new FormattableMarkup('Formatted date field using datetime_custom format displayed as %expected.', [
    '%expected' => $expected,
  ]));

  // Verify that the 'timezone_override' setting works.
  $this->displayOptions['type'] = 'datetime_custom';
  $this->displayOptions['settings'] = [
    'date_format' => 'm/d/Y g:i:s A',
    'timezone_override' => 'America/New_York',
  ] + $this->defaultSettings;
  $display_repository
    ->getViewDisplay($this->field
    ->getTargetEntityTypeId(), $this->field
    ->getTargetBundle(), 'full')
    ->setComponent($field_name, $this->displayOptions)
    ->save();
  $expected = $date
    ->format($this->displayOptions['settings']['date_format'], [
    'timezone' => 'America/New_York',
  ]);
  $output = $this
    ->renderTestEntity($id);
  $this
    ->assertStringContainsString($expected, $output, new FormattableMarkup('Formatted date field using datetime_custom format displayed as %expected.', [
    '%expected' => $expected,
  ]));

  // Verify that the 'datetime_time_ago' formatter works for intervals in the
  // past.  First update the test entity so that the date difference always
  // has the same interval.  Since the database always stores UTC, and the
  // interval will use this, force the test date to use UTC and not the local
  // or user timezone.
  $timestamp = REQUEST_TIME - 87654321;
  $entity = EntityTest::load($id);
  $field_name = $this->fieldStorage
    ->getName();
  $date = DrupalDateTime::createFromTimestamp($timestamp, 'UTC');
  $entity->{$field_name}->value = $date
    ->format(DateTimeItemInterface::DATETIME_STORAGE_FORMAT);
  $entity
    ->save();
  $this->displayOptions['type'] = 'datetime_time_ago';
  $this->displayOptions['settings'] = [
    'future_format' => '@interval from now',
    'past_format' => '@interval earlier',
    'granularity' => 3,
  ];
  $display_repository
    ->getViewDisplay($this->field
    ->getTargetEntityTypeId(), $this->field
    ->getTargetBundle(), 'full')
    ->setComponent($field_name, $this->displayOptions)
    ->save();
  $expected = new FormattableMarkup($this->displayOptions['settings']['past_format'], [
    '@interval' => $this->dateFormatter
      ->formatTimeDiffSince($timestamp, [
      'granularity' => $this->displayOptions['settings']['granularity'],
    ]),
  ]);
  $output = $this
    ->renderTestEntity($id);
  $this
    ->assertStringContainsString((string) $expected, $output, new FormattableMarkup('Formatted date field using datetime_time_ago format displayed as %expected.', [
    '%expected' => $expected,
  ]));

  // Verify that the 'datetime_time_ago' formatter works for intervals in the
  // future.  First update the test entity so that the date difference always
  // has the same interval.  Since the database always stores UTC, and the
  // interval will use this, force the test date to use UTC and not the local
  // or user timezone.
  $timestamp = REQUEST_TIME + 87654321;
  $entity = EntityTest::load($id);
  $field_name = $this->fieldStorage
    ->getName();
  $date = DrupalDateTime::createFromTimestamp($timestamp, 'UTC');
  $entity->{$field_name}->value = $date
    ->format(DateTimeItemInterface::DATETIME_STORAGE_FORMAT);
  $entity
    ->save();
  $display_repository
    ->getViewDisplay($this->field
    ->getTargetEntityTypeId(), $this->field
    ->getTargetBundle(), 'full')
    ->setComponent($field_name, $this->displayOptions)
    ->save();
  $expected = new FormattableMarkup($this->displayOptions['settings']['future_format'], [
    '@interval' => $this->dateFormatter
      ->formatTimeDiffUntil($timestamp, [
      'granularity' => $this->displayOptions['settings']['granularity'],
    ]),
  ]);
  $output = $this
    ->renderTestEntity($id);
  $this
    ->assertStringContainsString((string) $expected, $output, new FormattableMarkup('Formatted date field using datetime_time_ago format displayed as %expected.', [
    '%expected' => $expected,
  ]));
}