date_recur-8.x-2.2/tests/src/Functional/DateRecurBasicWidgetTest.php

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

declare(strict_types=1);

namespace Drupal\Tests\date_recur\Functional;

use Drupal\Core\Field\Entity\BaseFieldOverride;
use Drupal\Core\Url;
use Drupal\date_recur\Plugin\Field\FieldType\DateRecurFieldItemList;
use Drupal\date_recur\Plugin\Field\FieldType\DateRecurItem;
use Drupal\date_recur_entity_test\Entity\DrEntityTestEntity as DrEntityTest;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\Tests\BrowserTestBase;

/**
 * Tests date recur basic widget.
 *
 * For some reason there are problems (as of Oct 2018) with filling date and
 * time fields with WebDriver. Using BTB in the mean time.
 *
 * @group date_recur
 * @coversDefaultClass \Drupal\date_recur\Plugin\Field\FieldWidget\DateRecurBasicWidget
 */
class DateRecurBasicWidgetTest extends BrowserTestBase {

  /**
   * {@inheritdoc}
   */
  protected $defaultTheme = 'stark';

  /**
   * {@inheritdoc}
   */
  protected static $modules = [
    'date_recur_basic_widget_test',
    'date_recur_entity_test',
    'entity_test',
    'datetime',
    'datetime_range',
    'date_recur',
    'field',
    'user',
    'system',
  ];

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

    $display = \Drupal::service('entity_display.repository')->getFormDisplay('dr_entity_test', 'dr_entity_test', 'default');
    $component = $display->getComponent('dr');
    $component['region'] = 'content';
    $component['type'] = 'date_recur_basic_widget';
    $component['settings'] = [];
    $display->setComponent('dr', $component);
    $display->save();

    $user = $this->drupalCreateUser(['administer entity_test content']);
    $user->timezone = 'Asia/Singapore';
    $user->save();
    $this->drupalLogin($user);
  }

  /**
   * Test value from DB displays correctly.
   */
  public function testEditForm(): void {
    $entity = DrEntityTest::create();
    $rrule = 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR';
    $timeZone = 'Indian/Christmas';
    $entity->dr = [
      [
        // 10am-4pm weekdaily.
        'value' => '2008-06-15T22:00:00',
        'end_value' => '2008-06-17T06:00:00',
        'rrule' => $rrule,
        // UTC+7.
        'timezone' => $timeZone,
      ],
    ];
    $entity->save();

    $this->drupalGet($entity->toUrl('edit-form'));
    $this->assertSession()->fieldValueEquals('dr[0][value][date]', '2008-06-16');
    $this->assertSession()->fieldValueEquals('dr[0][value][time]', '05:00:00');
    $this->assertSession()->fieldValueEquals('dr[0][end_value][date]', '2008-06-17');
    $this->assertSession()->fieldValueEquals('dr[0][end_value][time]', '13:00:00');
    $this->assertSession()->fieldValueEquals('dr[0][timezone]', $timeZone);
    $this->assertSession()->fieldValueEquals('dr[0][rrule]', $rrule);
  }

  /**
   * Tests submitted values make it into database for new entities.
   */
  public function testSavedFormNew(): void {
    $rrule = 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR';
    // UTC-5.
    $timeZone = 'America/Bogota';
    $edit = [
      'dr[0][value][date]' => '2008-06-17',
      // This is the time in Bogota.
      'dr[0][value][time]' => '03:00:01',
      'dr[0][end_value][date]' => '2008-06-17',
      'dr[0][end_value][time]' => '12:00:04',
      'dr[0][timezone]' => $timeZone,
      'dr[0][rrule]' => $rrule,
    ];

    $url = Url::fromRoute('entity.dr_entity_test.add_form', ['type' => 'dr_entity_test']);
    $this->drupalGet($url);
    $this->submitForm($edit, 'Save');
    $this->assertSession()->pageTextContains('has been created.');

    $entity = $this->getLastSavedDrEntityTest();
    $expected = [
      'value' => '2008-06-17T08:00:01',
      'end_value' => '2008-06-17T17:00:04',
      'rrule' => $rrule,
      'timezone' => $timeZone,
      'infinite' => TRUE,
    ];
    static::assertEquals($expected, $entity->dr[0]->toArray());
  }

  /**
   * Tests submitted values make it into database for pre-existing entities.
   */
  public function testSavedFormEdit(): void {
    $entity = DrEntityTest::create();
    $rrule = 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR';
    $timeZone = 'America/Bogota';
    $value = [
      'value' => '2008-06-17T08:00:01',
      'end_value' => '2008-06-17T17:00:04',
      'rrule' => $rrule,
      'timezone' => $timeZone,
      'infinite' => TRUE,
    ];
    $entity->dr = [$value];
    $entity->save();

    $this->drupalGet($entity->toUrl('edit-form'));
    // Submit the values as is.
    $this->submitForm([], 'Save');
    $this->assertSession()->pageTextContains('has been updated.');

    // Reload the entity from storage.
    $entity = $this->getLastSavedDrEntityTest();
    static::assertEquals($value, $entity->dr[0]->toArray());
  }

  /**
   * Tests form field submission.
   *
   * Tests simple form success and failure without testing the saved entity.
   *
   * @param array $edit
   *   Form field values.
   * @param bool $isSuccess
   *   Whether submitting the form results in success.
   * @param string|null $errorMessage
   *   The the form submission results in failure, assert the error message.
   *
   * @dataProvider providerFields
   */
  public function testFields(array $edit, bool $isSuccess, ?string $errorMessage = NULL): void {
    $this->drupalGet(Url::fromRoute('entity.dr_entity_test.add_form', ['type' => 'dr_entity_test']));
    $this->submitForm($edit, 'Save');

    if ($isSuccess) {
      $this->assertSession()->pageTextContains('dr_entity_test 1 has been created.');
    }
    else {
      $this->assertSession()->pageTextNotContains('dr_entity_test 1 has been created.');
      $this->assertSession()->pageTextContains($errorMessage);
    }
  }

  /**
   * Data provider for testFields.
   *
   * @return array
   *   Data for testing.
   */
  public static function providerFields(): array {
    $scenarios = [];

    $scenarios['Test no failures if nothing is filled.'] = [
      [
        'dr[0][value][date]' => '',
        'dr[0][value][time]' => '',
        'dr[0][end_value][date]' => '',
        'dr[0][end_value][time]' => '',
        'dr[0][timezone]' => '',
        'dr[0][rrule]' => '',
      ],
      TRUE,
    ];

    $scenarios['Test failure when only start date field filled.'] = [
      [
        'dr[0][value][date]' => '2008-06-17',
        'dr[0][value][time]' => '',
        'dr[0][end_value][date]' => '',
        'dr[0][end_value][time]' => '',
        'dr[0][timezone]' => '',
        'dr[0][rrule]' => '',
      ],
      FALSE,
      'Missing time zone for date.',
    ];

    $scenarios['Test failure when only start time field filled.'] = [
      [
        'dr[0][value][date]' => '',
        'dr[0][value][time]' => '10:00:00',
        'dr[0][end_value][date]' => '',
        'dr[0][end_value][time]' => '',
        'dr[0][timezone]' => '',
        'dr[0][rrule]' => '',
      ],
      FALSE,
      'Missing time zone for date.',
    ];

    $scenarios['Test failure when start date and time field filled.'] = [
      [
        'dr[0][value][date]' => '2008-06-17',
        'dr[0][value][time]' => '10:00:00',
        'dr[0][end_value][date]' => '',
        'dr[0][end_value][time]' => '',
        'dr[0][timezone]' => '',
        'dr[0][rrule]' => '',
      ],
      FALSE,
      'Missing time zone for date.',
    ];

    $scenarios['Test failure when end date filled.'] = [
      [
        'dr[0][value][date]' => '',
        'dr[0][value][time]' => '',
        'dr[0][end_value][date]' => '2008-06-17',
        'dr[0][end_value][time]' => '',
        'dr[0][timezone]' => '',
        'dr[0][rrule]' => '',
      ],
      FALSE,
      'Missing time zone for date.',
    ];

    $scenarios['Test failure when end time filled.'] = [
      [
        'dr[0][value][date]' => '',
        'dr[0][value][time]' => '',
        'dr[0][end_value][date]' => '',
        'dr[0][end_value][time]' => '10:00:00',
        'dr[0][timezone]' => '',
        'dr[0][rrule]' => '',
      ],
      FALSE,
      'Missing time zone for date.',
    ];

    $scenarios['Test success when start date and time and time zone field filled.'] = [
      [
        'dr[0][value][date]' => '2008-06-17',
        'dr[0][value][time]' => '10:00:00',
        'dr[0][end_value][date]' => '',
        'dr[0][end_value][time]' => '',
        'dr[0][timezone]' => 'Australia/Sydney',
        'dr[0][rrule]' => '',
      ],
      TRUE,
    ];

    $scenarios['Test failure when end date and time and time zone field filled.'] = [
      [
        'dr[0][value][date]' => '',
        'dr[0][value][time]' => '',
        'dr[0][end_value][date]' => '2008-06-17',
        'dr[0][end_value][time]' => '10:00:00',
        'dr[0][timezone]' => 'Australia/Sydney',
        'dr[0][rrule]' => '',
      ],
      FALSE,
      'Start date must be set if end date is set.',
    ];

    $scenarios['Tests failure on invalid rule.'] = [
      [
        'dr[0][value][date]' => '2008-06-17',
        'dr[0][value][time]' => '12:00:00',
        'dr[0][end_value][date]' => '2008-06-17',
        'dr[0][end_value][time]' => '12:00:00',
        'dr[0][timezone]' => 'America/Chicago',
        'dr[0][rrule]' => 'invalid-rule',
      ],
      FALSE,
      'Repeat rule is formatted incorrectly.',
    ];

    // Tests validation that comes automatically from date range. Specifically,
    // assert end date comes on or after start date.
    $scenarios['Tests inherited validation: end before start'] = [
      [
        'dr[0][value][date]' => '2008-06-17',
        'dr[0][value][time]' => '03:00:00',
        'dr[0][end_value][date]' => '2008-06-15',
        'dr[0][end_value][time]' => '03:00:00',
        'dr[0][timezone]' => 'America/Chicago',
        'dr[0][rrule]' => 'FREQ=DAILY',
      ],
      FALSE,
      'end date cannot be before the start date',
    ];

    return $scenarios;
  }

  /**
   * Tests default values appear in widget.
   *
   * @dataProvider providerDefaultValues
   */
  public function testDefaultValues(array $baseFieldValue, array $assertFieldValues): void {
    /** @var \Drupal\Core\Entity\EntityFieldManagerInterface $entityFieldManager */
    $entityFieldManager = \Drupal::service('entity_field.manager');
    $baseFields = $entityFieldManager->getBaseFieldDefinitions('dr_entity_test');
    $baseFieldOverride = BaseFieldOverride::createFromBaseFieldDefinition($baseFields['dr'], 'dr_entity_test');
    // Default values need to evaluate FALSE per DateRecurItem::isEmpty
    // otherwise the values will be cleared out before display.
    $baseFieldOverride->setDefaultValue($baseFieldValue);
    $baseFieldOverride->save();

    $url = Url::fromRoute('entity.dr_entity_test.add_form', ['type' => 'dr_entity_test']);
    $this->drupalGet($url);

    foreach ($assertFieldValues as [$fieldName, $fieldValue]) {
      $this->assertSession()->fieldValueEquals($fieldName, $fieldValue);
    }
  }

  /**
   * Data provider for testFields.
   *
   * @return array
   *   Data for testing.
   */
  public static function providerDefaultValues(): array {
    $scenarios = [];

    $scenarios['all values'] = [
      // 3pm/4pm Oslo (UTC+2) -> 8pm/9pm Christmas (UTC+7).
      [
        [
          'default_date_type' => 'relative',
          'default_date' => '12th April 2013 3pm',
          'default_end_date_type' => 'relative',
          'default_end_date' => '12th April 2013 4pm',
          'default_date_time_zone' => 'Europe/Oslo',
          'default_time_zone' => 'Indian/Christmas',
          'default_time_zone_source' => DateRecurFieldItemList::DEFAULT_TIME_ZONE_SOURCE_FIXED,
          'default_rrule' => 'FREQ=WEEKLY;COUNT=995',
        ],
      ],
      [
        ['dr[0][value][date]', '2013-04-12'],
        ['dr[0][value][time]', '20:00:00'],
        ['dr[0][end_value][date]', '2013-04-12'],
        ['dr[0][end_value][time]', '21:00:00'],
        ['dr[0][timezone]', 'Indian/Christmas'],
        ['dr[0][rrule]', 'FREQ=WEEKLY;COUNT=995'],
      ],
    ];

    $scenarios['only time zone'] = [
      [
        [
          'default_time_zone' => 'Indian/Christmas',
          'default_time_zone_source' => DateRecurFieldItemList::DEFAULT_TIME_ZONE_SOURCE_FIXED,
        ],
      ],
      [
        ['dr[0][value][date]', ''],
        ['dr[0][value][time]', ''],
        ['dr[0][end_value][date]', ''],
        ['dr[0][end_value][time]', ''],
        ['dr[0][timezone]', 'Indian/Christmas'],
        ['dr[0][rrule]', ''],
      ],
    ];

    $scenarios['only start'] = [
      [
        [
          'default_date_type' => 'relative',
          'default_date' => '12th April 2013 3pm',
          'default_date_time_zone' => 'Europe/Oslo',
          'default_time_zone' => 'Indian/Christmas',
          'default_time_zone_source' => DateRecurFieldItemList::DEFAULT_TIME_ZONE_SOURCE_FIXED,
        ],
      ],
      [
        ['dr[0][value][date]', '2013-04-12'],
        ['dr[0][value][time]', '20:00:00'],
        ['dr[0][end_value][date]', ''],
        ['dr[0][end_value][time]', ''],
        ['dr[0][timezone]', 'Indian/Christmas'],
        ['dr[0][rrule]', ''],
      ],
    ];

    return $scenarios;
  }

  /**
   * Tests if field is set to required, only start date is required.
   *
   * End date must never be required, value is copied over from start date.
   */
  public function testRequiredField(): void {
    $field_storage = FieldStorageConfig::create([
      'entity_type' => 'entity_test',
      'field_name' => 'foo',
      'type' => 'date_recur',
      'settings' => [
        'datetime_type' => DateRecurItem::DATETIME_TYPE_DATETIME,
      ],
    ]);
    $field_storage->save();

    $field = [
      'field_name' => 'foo',
      'entity_type' => 'entity_test',
      'bundle' => 'entity_test',
      // Set instance to required.
      'required' => TRUE,
    ];
    FieldConfig::create($field)->save();

    $display = \Drupal::service('entity_display.repository')->getFormDisplay('entity_test', 'entity_test', 'default');
    $component = $display->getComponent('foo');
    $component['region'] = 'content';
    $component['type'] = 'date_recur_basic_widget';
    $component['settings'] = [];
    $display->setComponent('foo', $component);
    $display->save();

    $edit = [
      'foo[0][value][date]' => '',
      'foo[0][value][time]' => '',
      'foo[0][end_value][date]' => '',
      'foo[0][end_value][time]' => '',
      'foo[0][timezone]' => 'America/Chicago',
      'foo[0][rrule]' => 'FREQ=DAILY',
    ];

    $this->drupalGet(Url::fromRoute('entity.entity_test.add_form', ['type' => 'entity_test']));
    $this->submitForm($edit, 'Save');

    $this->assertSession()->pageTextContains('The Start date is required.');
    $this->assertSession()->pageTextNotContains('The End date is required.');
  }

  /**
   * Tests if time zone is programmatically hidden, default value is used.
   *
   * Field default time zone will be populated behind the scenes..
   */
  public function testHiddenTimeZoneField(): void {
    /** @var \Drupal\Core\Entity\EntityFieldManagerInterface $entityFieldManager */
    $entityFieldManager = \Drupal::service('entity_field.manager');
    $baseFields = $entityFieldManager->getBaseFieldDefinitions('dr_entity_test');
    $baseFieldOverride = BaseFieldOverride::createFromBaseFieldDefinition($baseFields['dr'], 'dr_entity_test');
    $baseFieldOverride->setDefaultValue([
      [
        'default_time_zone' => 'Asia/Singapore',
        'default_time_zone_source' => DateRecurFieldItemList::DEFAULT_TIME_ZONE_SOURCE_FIXED,
      ],
    ]);
    $baseFieldOverride->save();

    \Drupal::state()->set('DATE_RECUR_BASIC_WIDGET_TEST_HIDDEN_TIMEZONE_FIELD_HOOK_FORM_ALTER', TRUE);

    $this->drupalGet(Url::fromRoute('entity.dr_entity_test.add_form', ['type' => 'dr_entity_test']));

    // Time zone field should be hidden.
    $this->assertSession()->fieldNotExists('dr[0][timezone]');
    // Make sure something exists.
    $this->assertSession()->fieldExists('dr[0][rrule]');

    $edit = [
      // No time zone here, but the time zone is set from field defaults.
      'dr[0][value][date]' => '2008-06-17',
      'dr[0][value][time]' => '12:00:00',
      'dr[0][end_value][date]' => '2008-06-17',
      'dr[0][end_value][time]' => '12:00:00',
      'dr[0][rrule]' => 'FREQ=DAILY;COUNT=10',
    ];

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

    // The form would previously would not submit, an error was displayed.
    $this->assertSession()->pageTextContains('dr_entity_test 1 has been created.');

    $entity = $this->getLastSavedDrEntityTest();
    static::assertEquals([
      'value' => '2008-06-17T04:00:00',
      'end_value' => '2008-06-17T04:00:00',
      'rrule' => 'FREQ=DAILY;COUNT=10',
      'timezone' => 'Asia/Singapore',
      'infinite' => FALSE,
    ], $entity->dr[0]->toArray());
  }

  /**
   * Tests an error is displayed if a long RRULE is submitted.
   */
  public function testRruleMaxLengthError(): void {
    $field_storage = FieldStorageConfig::create([
      'entity_type' => 'entity_test',
      'field_name' => 'foo',
      'type' => 'date_recur',
      'settings' => [
        'datetime_type' => DateRecurItem::DATETIME_TYPE_DATETIME,
        // Test a super short length.
        'rrule_max_length' => 20,
      ],
    ]);
    $field_storage->save();

    $field = [
      'field_name' => 'foo',
      'entity_type' => 'entity_test',
      'bundle' => 'entity_test',
    ];
    FieldConfig::create($field)->save();

    $display = \Drupal::service('entity_display.repository')->getFormDisplay('entity_test', 'entity_test', 'default');
    $component = $display->getComponent('foo');
    $component['region'] = 'content';
    $component['type'] = 'date_recur_basic_widget';
    $component['settings'] = [];
    $display->setComponent('foo', $component);
    $display->save();

    $edit = [
      'foo[0][value][date]' => '2008-06-17',
      'foo[0][value][time]' => '12:00:00',
      'foo[0][end_value][date]' => '2008-06-17',
      'foo[0][end_value][time]' => '12:00:00',
      'foo[0][timezone]' => 'America/Chicago',
      'foo[0][rrule]' => 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR;COUNT=3',
    ];
    $this->drupalGet(Url::fromRoute('entity.entity_test.add_form', ['type' => 'entity_test']));
    $this->submitForm($edit, 'Save');

    $this->assertSession()->pageTextContains('This value is too long. It should have 20 characters or less.');
  }

  /**
   * Get last saved Dr Entity Test entity.
   *
   * @return \Drupal\date_recur_entity_test\Entity\DrEntityTestEntity|null
   *   The entity or null if none exist.
   */
  protected function getLastSavedDrEntityTest(): ?DrEntityTest {
    $query = \Drupal::database()->query('SELECT MAX(id) FROM {dr_entity_test}');
    $query->execute();
    $maxId = $query->fetchField();
    return DrEntityTest::load($maxId);
  }

}

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

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