function SmartDefaultSettingsTest::test

Same name 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 @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.