You are here

public function DateTimeFieldTest::testDatelistWidget in Drupal 9

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

Tests Date List Widget functionality.

File

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

Class

DateTimeFieldTest
Tests Datetime field functionality.

Namespace

Drupal\Tests\datetime\Functional

Code

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

  // Ensure field is set to a date only field.
  $this->fieldStorage
    ->setSetting('datetime_type', 'date');
  $this->fieldStorage
    ->save();

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

  // Change the widget to a datelist widget.
  $display_repository
    ->getFormDisplay($this->field
    ->getTargetEntityTypeId(), $this->field
    ->getTargetBundle())
    ->setComponent($field_name, [
    'type' => 'datetime_datelist',
    'settings' => [
      'date_order' => 'YMD',
    ],
  ])
    ->save();
  \Drupal::service('entity_field.manager')
    ->clearCachedFieldDefinitions();

  // Display creation form.
  $this
    ->drupalGet('entity_test/add');
  $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"]');

  // Assert that Hour and Minute Elements do not appear on Date Only
  $this
    ->assertSession()
    ->elementNotExists('xpath', "//*[@id=\"edit-{$field_name}-0-value-hour\"]");
  $this
    ->assertSession()
    ->elementNotExists('xpath', "//*[@id=\"edit-{$field_name}-0-value-minute\"]");

  // Go to the form display page to assert that increment option does not appear on Date Only
  $fieldEditUrl = 'entity_test/structure/entity_test/form-display';
  $this
    ->drupalGet($fieldEditUrl);

  // Click on the widget settings button to open the widget settings form.
  $this
    ->submitForm([], $field_name . "_settings_edit");
  $xpathIncr = "//select[starts-with(@id, \"edit-fields-{$field_name}-settings-edit-form-settings-increment\")]";
  $this
    ->assertSession()
    ->elementNotExists('xpath', $xpathIncr);

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

  // Change the widget to a datelist widget.
  $display_repository
    ->getFormDisplay($this->field
    ->getTargetEntityTypeId(), $this->field
    ->getTargetBundle())
    ->setComponent($field_name, [
    'type' => 'datetime_datelist',
    'settings' => [
      'increment' => 1,
      'date_order' => 'YMD',
      'time_type' => '12',
    ],
  ])
    ->save();
  \Drupal::service('entity_field.manager')
    ->clearCachedFieldDefinitions();

  // Go to the form display page to assert that increment option does appear on Date Time
  $fieldEditUrl = 'entity_test/structure/entity_test/form-display';
  $this
    ->drupalGet($fieldEditUrl);

  // Click on the widget settings button to open the widget settings form.
  $this
    ->submitForm([], $field_name . "_settings_edit");
  $this
    ->assertSession()
    ->elementExists('xpath', $xpathIncr);

  // Display creation form.
  $this
    ->drupalGet('entity_test/add');

  // Year element.
  $this
    ->assertSession()
    ->elementExists('xpath', "//*[@id=\"edit-{$field_name}-0-value-year\"]");
  $this
    ->assertTrue($this
    ->assertSession()
    ->optionExists("edit-{$field_name}-0-value-year", '')
    ->isSelected());
  $this
    ->assertSession()
    ->optionExists("edit-{$field_name}-0-value-year", 'Year');

  // Month element.
  $this
    ->assertSession()
    ->elementExists('xpath', "//*[@id=\"edit-{$field_name}-0-value-month\"]");
  $this
    ->assertTrue($this
    ->assertSession()
    ->optionExists("edit-{$field_name}-0-value-month", '')
    ->isSelected());
  $this
    ->assertSession()
    ->optionExists("edit-{$field_name}-0-value-month", 'Month');

  // Day element.
  $this
    ->assertSession()
    ->elementExists('xpath', "//*[@id=\"edit-{$field_name}-0-value-day\"]");
  $this
    ->assertTrue($this
    ->assertSession()
    ->optionExists("edit-{$field_name}-0-value-day", '')
    ->isSelected());
  $this
    ->assertSession()
    ->optionExists("edit-{$field_name}-0-value-day", 'Day');

  // Hour element.
  $this
    ->assertSession()
    ->elementExists('xpath', "//*[@id=\"edit-{$field_name}-0-value-hour\"]");
  $this
    ->assertTrue($this
    ->assertSession()
    ->optionExists("edit-{$field_name}-0-value-hour", '')
    ->isSelected());
  $this
    ->assertSession()
    ->optionExists("edit-{$field_name}-0-value-hour", 'Hour');

  // Minute element.
  $this
    ->assertSession()
    ->elementExists('xpath', "//*[@id=\"edit-{$field_name}-0-value-minute\"]");
  $this
    ->assertTrue($this
    ->assertSession()
    ->optionExists("edit-{$field_name}-0-value-minute", '')
    ->isSelected());
  $this
    ->assertSession()
    ->optionExists("edit-{$field_name}-0-value-minute", 'Minute');

  // No Second element.
  $this
    ->assertSession()
    ->elementNotExists('xpath', "//*[@id=\"edit-{$field_name}-0-value-second\"]");

  // AMPM element.
  $this
    ->assertSession()
    ->elementExists('xpath', "//*[@id=\"edit-{$field_name}-0-value-ampm\"]");
  $this
    ->assertTrue($this
    ->assertSession()
    ->optionExists("edit-{$field_name}-0-value-ampm", '')
    ->isSelected());
  $this
    ->assertSession()
    ->optionExists("edit-{$field_name}-0-value-ampm", 'AM/PM');

  // Submit a valid date and ensure it is accepted.
  $date_value = [
    'year' => 2012,
    'month' => 12,
    'day' => 31,
    'hour' => 5,
    'minute' => 15,
  ];
  $edit = [];

  // Add the ampm indicator since we are testing 12 hour time.
  $date_value['ampm'] = 'am';
  foreach ($date_value as $part => $value) {
    $edit["{$field_name}[0][value][{$part}]"] = $value;
  }
  $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
    ->assertTrue($this
    ->assertSession()
    ->optionExists("edit-{$field_name}-0-value-year", '2012')
    ->isSelected());
  $this
    ->assertTrue($this
    ->assertSession()
    ->optionExists("edit-{$field_name}-0-value-month", '12')
    ->isSelected());
  $this
    ->assertTrue($this
    ->assertSession()
    ->optionExists("edit-{$field_name}-0-value-day", '31')
    ->isSelected());
  $this
    ->assertTrue($this
    ->assertSession()
    ->optionExists("edit-{$field_name}-0-value-hour", '5')
    ->isSelected());
  $this
    ->assertTrue($this
    ->assertSession()
    ->optionExists("edit-{$field_name}-0-value-minute", '15')
    ->isSelected());
  $this
    ->assertTrue($this
    ->assertSession()
    ->optionExists("edit-{$field_name}-0-value-ampm", 'am')
    ->isSelected());

  // Test the widget using increment other than 1 and 24 hour mode.
  $display_repository
    ->getFormDisplay($this->field
    ->getTargetEntityTypeId(), $this->field
    ->getTargetBundle())
    ->setComponent($field_name, [
    'type' => 'datetime_datelist',
    'settings' => [
      'increment' => 15,
      'date_order' => 'YMD',
      'time_type' => '24',
    ],
  ])
    ->save();
  \Drupal::service('entity_field.manager')
    ->clearCachedFieldDefinitions();

  // Display creation form.
  $this
    ->drupalGet('entity_test/add');

  // Other elements are unaffected by the changed settings.
  $this
    ->assertSession()
    ->elementExists('xpath', "//*[@id=\"edit-{$field_name}-0-value-hour\"]");
  $this
    ->assertTrue($this
    ->assertSession()
    ->optionExists("edit-{$field_name}-0-value-hour", '')
    ->isSelected());
  $this
    ->assertSession()
    ->elementNotExists('xpath', "//*[@id=\"edit-{$field_name}-0-value-ampm\"]");

  // Submit a valid date and ensure it is accepted.
  $date_value = [
    'year' => 2012,
    'month' => 12,
    'day' => 31,
    'hour' => 17,
    'minute' => 15,
  ];
  $edit = [];
  foreach ($date_value as $part => $value) {
    $edit["{$field_name}[0][value][{$part}]"] = $value;
  }
  $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
    ->assertTrue($this
    ->assertSession()
    ->optionExists("edit-{$field_name}-0-value-year", '2012')
    ->isSelected());
  $this
    ->assertTrue($this
    ->assertSession()
    ->optionExists("edit-{$field_name}-0-value-month", '12')
    ->isSelected());
  $this
    ->assertTrue($this
    ->assertSession()
    ->optionExists("edit-{$field_name}-0-value-day", '31')
    ->isSelected());
  $this
    ->assertTrue($this
    ->assertSession()
    ->optionExists("edit-{$field_name}-0-value-hour", '17')
    ->isSelected());
  $this
    ->assertTrue($this
    ->assertSession()
    ->optionExists("edit-{$field_name}-0-value-minute", '15')
    ->isSelected());

  // Test the widget for partial completion of fields.
  $display_repository
    ->getFormDisplay($this->field
    ->getTargetEntityTypeId(), $this->field
    ->getTargetBundle())
    ->setComponent($field_name, [
    'type' => 'datetime_datelist',
    'settings' => [
      'increment' => 1,
      'date_order' => 'YMD',
      'time_type' => '24',
    ],
  ])
    ->save();
  \Drupal::service('entity_field.manager')
    ->clearCachedFieldDefinitions();

  // Test the widget for validation notifications.
  foreach ($this
    ->datelistDataProvider($field_label) as $data) {
    list($date_value, $expected) = $data;

    // Display creation form.
    $this
      ->drupalGet('entity_test/add');

    // Submit a partial date and ensure and error message is provided.
    $edit = [];
    foreach ($date_value as $part => $value) {
      $edit["{$field_name}[0][value][{$part}]"] = $value;
    }
    $this
      ->submitForm($edit, 'Save');
    $this
      ->assertSession()
      ->statusCodeEquals(200);
    foreach ($expected as $expected_text) {
      $this
        ->assertSession()
        ->pageTextContains($expected_text);
    }
  }

  // Test the widget for complete input with zeros as part of selections.
  $this
    ->drupalGet('entity_test/add');
  $date_value = [
    'year' => 2012,
    'month' => '12',
    'day' => '31',
    'hour' => '0',
    'minute' => '0',
  ];
  $edit = [];
  foreach ($date_value as $part => $value) {
    $edit["{$field_name}[0][value][{$part}]"] = $value;
  }
  $this
    ->submitForm($edit, 'Save');
  $this
    ->assertSession()
    ->statusCodeEquals(200);
  preg_match('|entity_test/manage/(\\d+)|', $this
    ->getUrl(), $match);
  $id = $match[1];
  $this
    ->assertSession()
    ->pageTextContains('entity_test ' . $id . ' has been created.');

  // Test the widget to ensure zeros are not deselected on validation.
  $this
    ->drupalGet('entity_test/add');
  $date_value = [
    'year' => 2012,
    'month' => '12',
    'day' => '31',
    'hour' => '',
    'minute' => '0',
  ];
  $edit = [];
  foreach ($date_value as $part => $value) {
    $edit["{$field_name}[0][value][{$part}]"] = $value;
  }
  $this
    ->submitForm($edit, 'Save');
  $this
    ->assertSession()
    ->statusCodeEquals(200);
  $this
    ->assertTrue($this
    ->assertSession()
    ->optionExists("edit-{$field_name}-0-value-minute", '0')
    ->isSelected());
}