function SmartDefaultSettingsTest::test

Same name and namespace in other branches
  1. 9 core/modules/ckeditor5/tests/src/Kernel/SmartDefaultSettingsTest.php \Drupal\Tests\ckeditor5\Kernel\SmartDefaultSettingsTest::test()
  2. 11.x core/modules/ckeditor5/tests/src/Kernel/SmartDefaultSettingsTest.php \Drupal\Tests\ckeditor5\Kernel\SmartDefaultSettingsTest::test()

Tests the CKEditor 5 default settings conversion.

@dataProvider provider

Parameters

string $format_id: The existing text format/editor pair to switch to CKEditor 5.

array $filters_to_drop: An array of filter IDs to drop as the keys and either TRUE (fundamental compatibility error from CKEditor 5 expected) or FALSE (if optional to drop).

array $expected_ckeditor5_settings: The CKEditor 5 settings to test.

string $expected_superset: The default settings conversion may generate a superset of the original HTML restrictions. This lists the additional elements and attributes.

array $expected_fundamental_compatibility_violations: All expected fundamental compatibility violations for the given text format.

string[] $expected_db_logs: The expected database logs associated with the computed settings.

string[] $expected_messages: The expected messages associated with the computed settings.

array|null $expected_post_filter_drop_fundamental_compatibility_violations: All expected fundamental compatibility violations for the given text format, after dropping filters specified in $filters_to_drop.

array|null $expected_post_update_text_editor_violations: All expected media and filter settings violations for the given text format.

File

core/modules/ckeditor5/tests/src/Kernel/SmartDefaultSettingsTest.php, line 507

Class

SmartDefaultSettingsTest
@covers \Drupal\ckeditor5\SmartDefaultSettings::computeSmartDefaultSettings[[api-linebreak]] @group ckeditor5 @internal

Namespace

Drupal\Tests\ckeditor5\Kernel

Code

public function test(string $format_id, array $filters_to_drop, array $expected_ckeditor5_settings, string $expected_superset, array $expected_fundamental_compatibility_violations, array $expected_db_logs, array $expected_messages, ?array $expected_post_filter_drop_fundamental_compatibility_violations = NULL, ?array $expected_post_update_text_editor_violations = NULL) : void {
  $text_format = FilterFormat::load($format_id);
  $text_editor = Editor::load($format_id);
  // Check the pre-CKE5 switch validation errors in case of a minimal (empty)
  // CKEditor 5 text editor config entity, to allow us to detect fundamental
  // compatibility problems, such as incompatible filters.
  $minimal_valid_cke5_text_editor = Editor::create([
    'format' => $format_id,
    'editor' => 'ckeditor5',
    'settings' => [
      'toolbar' => [
        'items' => [],
      ],
    ],
  ]);
  $pre_ck5_validation_errors = $this->validatePairToViolationsArray($minimal_valid_cke5_text_editor, $text_format, FALSE);
  $this->assertSame($expected_fundamental_compatibility_violations, $pre_ck5_validation_errors);
  if (!empty($filters_to_drop)) {
    foreach ($filters_to_drop as $filter_name => $is_fundamentally_incompatible) {
      // Assert if it should appear in the pre-CKE5 switch validation errors.
      $this->assertSame($is_fundamentally_incompatible, mb_strpos(implode("\n\n", $pre_ck5_validation_errors[''] ?? []), $filter_name) !== FALSE);
      $text_format->setFilterConfig($filter_name, [
        'status' => FALSE,
      ]);
    }
    // If filters were dropped because of a fundamental compatibility problem,
    // validate the text format + minimal CKEditor 5 text editor config again
    // after dropping those filters from the text format. This allows us to be
    // confident that we have caught all fundamental compatibility problems.
    if (!empty(array_filter($filters_to_drop))) {
      $post_filter_drop_validation_errors = $this->validatePairToViolationsArray($minimal_valid_cke5_text_editor, $text_format, FALSE);
      $this->assertSame($expected_post_filter_drop_fundamental_compatibility_violations, $post_filter_drop_validation_errors);
    }
  }
  [
    $updated_text_editor,
    $messages,
  ] = $this->smartDefaultSettings
    ->computeSmartDefaultSettings($text_editor, $text_format);
  // Ensure that the result of ::computeSmartDefaultSettings() always complies
  // with the config schema.
  // TRICKY: because we're validating using `editor.editor.*` as the config
  // name, TextEditorObjectDependentValidatorTrait will load the stored filter
  // format. That has not yet been updated at this point, so in order for
  // validation to pass, it must first be saved.
  // @see \Drupal\ckeditor5\Plugin\Validation\Constraint\TextEditorObjectDependentValidatorTrait::createTextEditorObjectFromContext()
  // @todo Remove this work-around in https://www.drupal.org/project/drupal/issues/3231354
  $updated_text_editor->getFilterFormat()
    ->save();
  $this->assertConfigSchema($this->typedConfig, $updated_text_editor->getConfigDependencyName(), $updated_text_editor->toArray());
  // Save this to ensure the config export order is applied.
  // @see \Drupal\Core\Config\StorableConfigBase::castValue()
  $updated_text_editor->save();
  // We should now have the expected data in the Editor config entity.
  $this->assertSame('ckeditor5', $updated_text_editor->getEditor());
  $this->assertSame($expected_ckeditor5_settings, $updated_text_editor->getSettings());
  // If this text format already had a text editor, ensure that the settings
  // do not match the original settings, but the image upload settings should
  // not have been changed.
  if ($text_editor !== NULL) {
    $this->assertNotSame($text_editor->getSettings(), $updated_text_editor->getSettings());
    $this->assertSame($text_editor->getImageUploadSettings(), $updated_text_editor->getImageUploadSettings());
  }
  // The resulting Editor config entity should be valid.
  $violations = $this->validatePairToViolationsArray($updated_text_editor, $text_format, FALSE);
  // At this point, the fundamental compatibility errors do not matter, they
  // have been checked above; whatever remains is expected.
  if (isset($violations[''])) {
    unset($violations['']);
  }
  $this->assertSame([], $violations);
  // If the text format has HTML restrictions, ensure that a strict superset
  // is allowed after switching to CKEditor 5.
  $html_restrictions = $text_format->getHtmlRestrictions();
  if (is_array($html_restrictions) && array_key_exists('allowed', $html_restrictions)) {
    $allowed_tags = HTMLRestrictions::fromTextFormat($text_format);
    $enabled_plugins = array_keys($this->manager
      ->getEnabledDefinitions($updated_text_editor));
    $updated_allowed_tags = new HTMLRestrictions($this->manager
      ->getProvidedElements($enabled_plugins, $updated_text_editor));
    $unsupported_tags_attributes = $allowed_tags->diff($updated_allowed_tags);
    $superset_tags_attributes = $updated_allowed_tags->diff($allowed_tags);
    $this->assertSame($expected_superset, $superset_tags_attributes->toFilterHtmlAllowedTagsString());
    $this->assertTrue($unsupported_tags_attributes->allowsNothing(), "The following tags/attributes are not allowed in the updated text format:" . implode(' ', $unsupported_tags_attributes->toCKEditor5ElementsArray()));
    // Update the text format like ckeditor5_form_filter_format_form_alter()
    // would.
    $updated_text_format = clone $text_format;
    $filter_html_config = $text_format->filters('filter_html')
      ->getConfiguration();
    $filter_html_config['settings']['allowed_html'] = $updated_allowed_tags->toFilterHtmlAllowedTagsString();
    $updated_text_format->setFilterConfig('filter_html', $filter_html_config);
  }
  else {
    // No update.
    $updated_text_format = $text_format;
  }
  $updated_validation_errors = $this->validatePairToViolationsArray($updated_text_editor, $updated_text_format, TRUE);
  if (is_null($expected_post_update_text_editor_violations)) {
    // If a violation is not expected, it should be compared against an empty array.
    $this->assertSame([], $updated_validation_errors);
  }
  else {
    $this->assertSame($expected_post_update_text_editor_violations, $updated_validation_errors);
  }
  $db_logged = $this->database
    ->select('watchdog', 'w')
    ->fields('w', [
    'message',
    'variables',
    'severity',
  ])
    ->condition('type', 'ckeditor5')
    ->orderBy('wid')
    ->execute()
    ->fetchAll();
  $type_to_status = [
    6 => 'status',
    4 => 'warning',
  ];
  $db_logs = [];
  foreach ($db_logged as $log) {
    $variables = unserialize($log->variables);
    $message = new FormattableMarkup($log->message, $variables);
    $db_logs[$type_to_status[$log->severity]][] = (string) $message;
  }
  // Transforms TranslatableMarkup objects to string.
  foreach ($messages as $type => $messages_per_type) {
    foreach ($messages_per_type as $key => $message) {
      $messages[$type][$key] = (string) $message;
    }
  }
  $this->assertSame($expected_db_logs, $db_logs);
  $this->assertSame($expected_messages, $messages);
}

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