function DateTimeFieldTest::testDatetimeField

Same name in other branches
  1. 9 core/modules/datetime/tests/src/Functional/DateTimeFieldTest.php \Drupal\Tests\datetime\Functional\DateTimeFieldTest::testDatetimeField()
  2. 8.9.x core/modules/datetime/tests/src/Functional/DateTimeFieldTest.php \Drupal\Tests\datetime\Functional\DateTimeFieldTest::testDatetimeField()
  3. 10 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 225

Class

DateTimeFieldTest
Tests Datetime field functionality.

Namespace

Drupal\Tests\datetime\Functional

Code

public function testDatetimeField() : void {
    $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, "Formatted date field using {$new_value} format displayed as {$expected} with {$expected_iso} attribute.");
                    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, "Formatted date field using plain format displayed as {$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, "Formatted date field using datetime_custom format displayed as {$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, "Formatted date field using datetime_custom format displayed as {$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 = \Drupal::time()->getRequestTime() - 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, "Formatted date field using datetime_time_ago format displayed as {$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 = \Drupal::time()->getRequestTime() + 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, "Formatted date field using datetime_time_ago format displayed as {$expected}.");
    // Test the required field validation error message.
    $entity = EntityTest::create([
        'name' => 'test datetime required message',
    ]);
    $form = \Drupal::entityTypeManager()->getFormObject('entity_test', 'default')
        ->setEntity($entity);
    $form_state = new FormState();
    \Drupal::formBuilder()->submitForm($form, $form_state);
    $errors = $form_state->getErrors();
    $expected_error_message = new FormattableMarkup('The %field date is required.', [
        '%field' => $field_label,
    ]);
    $actual_error_message = $errors["{$field_name}][0][value"]->__toString();
    $this->assertEquals($expected_error_message->__toString(), $actual_error_message);
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.