function CKEditor5Test::testListPlugin

Tests list plugin.

File

core/modules/ckeditor5/tests/src/FunctionalJavascript/CKEditor5Test.php, line 557

Class

CKEditor5Test
Tests for CKEditor 5.

Namespace

Drupal\Tests\ckeditor5\FunctionalJavascript

Code

public function testListPlugin() : void {
  FilterFormat::create([
    'format' => 'test_format',
    'name' => 'CKEditor 5 with list',
    'roles' => [
      RoleInterface::AUTHENTICATED_ID,
    ],
  ])->save();
  Editor::create([
    'format' => 'test_format',
    'editor' => 'ckeditor5',
    'image_upload' => [
      'status' => FALSE,
    ],
    'settings' => [
      'toolbar' => [
        'items' => [
          'sourceEditing',
          'numberedList',
          'bulletedList',
        ],
      ],
      'plugins' => [
        'ckeditor5_list' => [
          'properties' => [
            'reversed' => FALSE,
            'startIndex' => FALSE,
            'styles' => FALSE,
          ],
          'multiBlock' => TRUE,
        ],
        'ckeditor5_sourceEditing' => [
          'allowed_tags' => [],
        ],
      ],
    ],
  ])->save();
  $this->assertSame([], array_map(function (ConstraintViolationInterface $v) {
    return (string) $v->getMessage();
  }, iterator_to_array(CKEditor5::validatePair(Editor::load('test_format'), FilterFormat::load('test_format')))));
  $ordered_list_html = '<ol><li>apple</li><li>banana</li><li>cantaloupe</li></ol>';
  $page = $this->getSession()
    ->getPage();
  $assert_session = $this->assertSession();
  $this->drupalGet('node/add/page');
  $page->fillField('title[0][value]', 'My test content');
  $this->pressEditorButton('Source');
  $source_text_area = $assert_session->waitForElement('css', '.ck-source-editing-area textarea');
  $source_text_area->setValue($ordered_list_html);
  // Click source again to make source inactive and have the numbered list
  // splitbutton active.
  $this->pressEditorButton('Source');
  $numbered_list_dropdown_selector = '.ck-splitbutton__arrow';
  // Check that there is no dropdown available for the numbered list because
  // reversed, startIndex and styles are FALSE.
  $assert_session->elementNotExists('css', $numbered_list_dropdown_selector);
  // Save content so source content is kept after changing the editor config.
  $page->pressButton('Save');
  $edit_url = $this->getSession()
    ->getCurrentURL() . '/edit';
  $this->drupalGet($edit_url);
  $this->waitForEditor();
  // Enable the reversed functionality.
  $editor = Editor::load('test_format');
  $settings = $editor->getSettings();
  $settings['plugins']['ckeditor5_list']['properties']['reversed'] = TRUE;
  $editor->setSettings($settings);
  $editor->save();
  $this->getSession()
    ->reload();
  $this->waitForEditor();
  $this->click($numbered_list_dropdown_selector);
  $reversed_order_button_selector = '.ck.ck-button.ck-numbered-list-properties__reversed-order';
  $assert_session->elementExists('css', $reversed_order_button_selector);
  $assert_session->elementTextEquals('css', $reversed_order_button_selector, 'Reversed order');
  $start_index_element_selector = '.ck.ck-numbered-list-properties__start-index';
  $assert_session->elementNotExists('css', $start_index_element_selector);
  // Have both the reversed and the start index enabled.
  $editor = Editor::load('test_format');
  $settings = $editor->getSettings();
  $settings['plugins']['ckeditor5_list']['properties']['startIndex'] = TRUE;
  $editor->setSettings($settings);
  $editor->save();
  $this->getSession()
    ->reload();
  $this->waitForEditor();
  $this->click($numbered_list_dropdown_selector);
  $assert_session->elementExists('css', $reversed_order_button_selector);
  $assert_session->elementTextEquals('css', $reversed_order_button_selector, 'Reversed order');
  $assert_session->elementExists('css', $start_index_element_selector);
  // Enable list style types.
  $editor = Editor::load('test_format');
  $settings = $editor->getSettings();
  $settings['plugins']['ckeditor5_list']['properties']['styles'] = TRUE;
  $editor->setSettings($settings);
  $editor->save();
  $this->getSession()
    ->reload();
  $this->waitForEditor();
  $list_types = [
    'ol' => [
      'Lower-roman' => 'i',
      'Upper-roman' => 'I',
      'Lower-latin' => 'a',
      'Upper-latin' => 'A',
    ],
    'ul' => [
      'Square' => 'square',
      'Disc' => 'disc',
      'Circle' => 'circle',
    ],
  ];
  foreach ($list_types as $list_tag => $types) {
    foreach ($types as $type => $type_attribute) {
      $list_to_edit = $assert_session->waitForElementVisible('css', ".ck-editor__editable_inline > *:first-child");
      $list_to_edit->click();
      // Open the list type toolbar and choose a type.
      $list_button_tip_text = $list_tag === 'ol' ? 'Numbered List' : 'Bulleted List';
      $toolbar_selector = '[aria-label="' . str_replace(' L', ' l', $list_button_tip_text) . ' styles toolbar"]';
      $button_selector = '[data-cke-tooltip-text="' . $list_button_tip_text . '"]';
      $page->find('css', '[aria-expanded="false"]' . $button_selector)
        ->click();
      $open_splitbutton = $assert_session->waitForElementVisible('css', '[aria-expanded="true"]' . $button_selector);
      $this->assertNotNull($open_splitbutton, "{$list_button_tip_text} splitbutton is open");
      $toolbar = $assert_session->waitForElementVisible('css', $toolbar_selector);
      $this->assertNotNull($toolbar, "Toolbar for selecting {$type} is available at {$toolbar_selector} ");
      $toolbar_with_tips = $assert_session->waitForElementVisible('css', $toolbar_selector . ' [data-cke-tooltip-text]');
      $this->assertNotNull($toolbar_with_tips);
      $toolbar_buttons = $toolbar->findAll('css', 'button');
      // While this is a bit of an indirect way to find the correct button, it
      // accounts for the mixed dash characters and worked better than other
      // attempts.
      $toolbar_button_tips = array_map(fn($item) => str_replace('–', '-', $item->getAttribute('data-cke-tooltip-text')), $toolbar_buttons);
      $this->assertNotFalse(array_search($type, $toolbar_button_tips));
      $toolbar_buttons[array_search($type, $toolbar_button_tips)]->click();
      $widget_selector = '.ck-editor__editable_inline > ' . $list_tag . '[type="' . $type_attribute . '"]';
      $widget = $assert_session->waitForElementVisible('css', $widget_selector);
      $this->assertNotNull($widget, "The widget exists at {$widget_selector}");
      // Confirm the style applied in-editor is for the type of list chosen.
      $list_style_type = $this->getSession()
        ->evaluateScript('window.getComputedStyle(document.querySelector(\'' . $widget_selector . '\')).listStyleType');
      $this->assertSame(str_replace('latin', 'alpha', strtolower($type)), $list_style_type, "The {$list_style_type} list should have the correct style.");
      $page->pressButton('Save');
      $fe_list_style_type = $this->getSession()
        ->evaluateScript('window.getComputedStyle(document.querySelector(\'' . $list_tag . '[type]\')).listStyleType');
      // Confirm the style applied on the default theme is for the type of
      // list chosen.
      $this->assertSame(str_replace('latin', 'alpha', strtolower($type)), strtolower($fe_list_style_type));
      $this->drupalGet($edit_url);
      $this->waitForEditor();
    }
  }
}

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