You are here

public function LinkFieldTest::testURLValidation in Drupal 9

Same name and namespace in other branches
  1. 8 core/modules/link/tests/src/Functional/LinkFieldTest.php \Drupal\Tests\link\Functional\LinkFieldTest::testURLValidation()

Tests link field URL validation.

File

core/modules/link/tests/src/Functional/LinkFieldTest.php, line 71

Class

LinkFieldTest
Tests link field widgets and formatters.

Namespace

Drupal\Tests\link\Functional

Code

public function testURLValidation() {
  $field_name = mb_strtolower($this
    ->randomMachineName());

  // Create a field with settings to validate.
  $this->fieldStorage = FieldStorageConfig::create([
    'field_name' => $field_name,
    'entity_type' => 'entity_test',
    'type' => 'link',
  ]);
  $this->fieldStorage
    ->save();
  $this->field = FieldConfig::create([
    'field_storage' => $this->fieldStorage,
    'bundle' => 'entity_test',
    'settings' => [
      'title' => DRUPAL_DISABLED,
      'link_type' => LinkItemInterface::LINK_GENERIC,
    ],
  ]);
  $this->field
    ->save();

  /** @var \Drupal\Core\Entity\EntityDisplayRepositoryInterface $display_repository */
  $display_repository = \Drupal::service('entity_display.repository');
  $display_repository
    ->getFormDisplay('entity_test', 'entity_test')
    ->setComponent($field_name, [
    'type' => 'link_default',
    'settings' => [
      'placeholder_url' => 'http://example.com',
    ],
  ])
    ->save();
  $display_repository
    ->getViewDisplay('entity_test', 'entity_test', 'full')
    ->setComponent($field_name, [
    'type' => 'link',
  ])
    ->save();

  // Display creation form.
  $this
    ->drupalGet('entity_test/add');
  $this
    ->assertSession()
    ->fieldValueEquals("{$field_name}[0][uri]", '');
  $this
    ->assertSession()
    ->responseContains('placeholder="http://example.com"');

  // Create a path alias.
  $this
    ->createPathAlias('/admin', '/a/path/alias');

  // Create a node to test the link widget.
  $node = $this
    ->drupalCreateNode();
  $restricted_node = $this
    ->drupalCreateNode([
    'status' => NodeInterface::NOT_PUBLISHED,
  ]);

  // Define some valid URLs (keys are the entered values, values are the
  // strings displayed to the user).
  $valid_external_entries = [
    'http://www.example.com/' => 'http://www.example.com/',
    // Strings within parenthesis without leading space char.
    'http://www.example.com/strings_(string_within_parenthesis)' => 'http://www.example.com/strings_(string_within_parenthesis)',
    // Numbers within parenthesis without leading space char.
    'http://www.example.com/numbers_(9999)' => 'http://www.example.com/numbers_(9999)',
  ];
  $valid_internal_entries = [
    '/entity_test/add' => '/entity_test/add',
    '/a/path/alias' => '/a/path/alias',
    // Front page, with query string and fragment.
    '/' => '<front>',
    '/?example=llama' => '<front>?example=llama',
    '/#example' => '<front>#example',
    // Trailing spaces should be ignored.
    '/ ' => '<front>',
    '/path with spaces ' => '/path with spaces',
    // @todo '<front>' is valid input for BC reasons, may be removed by
    //   https://www.drupal.org/node/2421941
    '<front>' => '&lt;front&gt;',
    '<front>#example' => '&lt;front&gt;#example',
    '<front>?example=llama' => '&lt;front&gt;?example=llama',
    // Text-only links.
    '<nolink>' => '&lt;nolink&gt;',
    'route:<nolink>' => '&lt;nolink&gt;',
    '<none>' => '&lt;none&gt;',
    // Query string and fragment.
    '?example=llama' => '?example=llama',
    '#example' => '#example',
    // Entity reference autocomplete value.
    $node
      ->label() . ' (1)' => $node
      ->label() . ' (1)',
    // Entity URI displayed as ER autocomplete value when displayed in a form.
    'entity:node/1' => $node
      ->label() . ' (1)',
    // URI for an entity that exists, but is not accessible by the user.
    'entity:node/' . $restricted_node
      ->id() => '- Restricted access - (' . $restricted_node
      ->id() . ')',
    // URI for an entity that doesn't exist, but with a valid ID.
    'entity:user/999999' => 'entity:user/999999',
  ];

  // Define some invalid URLs.
  $validation_error_1 = "The path '@link_path' is invalid.";
  $validation_error_2 = 'Manually entered paths should start with one of the following characters: / ? #';
  $validation_error_3 = "The path '@link_path' is inaccessible.";
  $invalid_external_entries = [
    // Invalid protocol
    'invalid://not-a-valid-protocol' => $validation_error_1,
    // Missing host name
    'http://' => $validation_error_1,
  ];
  $invalid_internal_entries = [
    'no-leading-slash' => $validation_error_2,
    'entity:non_existing_entity_type/yar' => $validation_error_1,
    // URI for an entity that doesn't exist, with an invalid ID.
    'entity:user/invalid-parameter' => $validation_error_1,
  ];

  // Test external and internal URLs for 'link_type' = LinkItemInterface::LINK_GENERIC.
  $this
    ->assertValidEntries($field_name, $valid_external_entries + $valid_internal_entries);
  $this
    ->assertInvalidEntries($field_name, $invalid_external_entries + $invalid_internal_entries);

  // Test external URLs for 'link_type' = LinkItemInterface::LINK_EXTERNAL.
  $this->field
    ->setSetting('link_type', LinkItemInterface::LINK_EXTERNAL);
  $this->field
    ->save();
  $this
    ->assertValidEntries($field_name, $valid_external_entries);
  $this
    ->assertInvalidEntries($field_name, $valid_internal_entries + $invalid_external_entries);

  // Test external URLs for 'link_type' = LinkItemInterface::LINK_INTERNAL.
  $this->field
    ->setSetting('link_type', LinkItemInterface::LINK_INTERNAL);
  $this->field
    ->save();
  $this
    ->assertValidEntries($field_name, $valid_internal_entries);
  $this
    ->assertInvalidEntries($field_name, $valid_external_entries + $invalid_internal_entries);

  // Ensure that users with 'link to any page', don't apply access checking.
  $this
    ->drupalLogin($this
    ->drupalCreateUser([
    'view test entity',
    'administer entity_test content',
  ]));
  $this
    ->assertValidEntries($field_name, [
    '/entity_test/add' => '/entity_test/add',
  ]);
  $this
    ->assertInValidEntries($field_name, [
    '/admin' => $validation_error_3,
  ]);
}