You are here

class XBBCodeStandardTest in Extensible BBCode 4.0.x

Same name and namespace in other branches
  1. 8.3 standard/tests/src/Kernel/XBBCodeStandardTest.php \Drupal\Tests\xbbcode_standard\Kernel\XBBCodeStandardTest

Test the standard tags provided by XBBCode.

@group xbbcode

Hierarchy

Expanded class hierarchy of XBBCodeStandardTest

File

standard/tests/src/Kernel/XBBCodeStandardTest.php, line 14

Namespace

Drupal\Tests\xbbcode_standard\Kernel
View source
class XBBCodeStandardTest extends KernelTestBase {

  /**
   * {@inheritdoc}
   */
  public static $modules = [
    'filter',
    'xbbcode',
    'xbbcode_standard',
    'system',
    'user',
  ];

  /**
   * {@inheritdoc}
   *
   * @throws \Drupal\Core\Entity\EntityStorageException
   */
  protected function setUp() : void {
    parent::setUp();
    $this
      ->installConfig([
      'xbbcode',
      'xbbcode_standard',
    ]);

    // Set up a BBCode filter format.
    $format = [
      'format' => 'xbbcode_test',
      'name' => 'XBBCode Test',
      'filters' => [
        'filter_html_escape' => [
          'status' => 1,
          'weight' => 0,
        ],
        'xbbcode' => [
          'status' => 1,
          'weight' => 1,
          'settings' => [
            'linebreaks' => FALSE,
          ],
        ],
      ],
    ];
    FilterFormat::create($format)
      ->save();
  }

  /**
   * Test all of the tags installed by this module.
   */
  public function testTags() : void {

    // Ten iterations, just in case of weird edge cases.
    for ($i = 0; $i < 10; $i++) {
      foreach ($this
        ->getTags() as $case) {
        $expected = self::stripSpaces($case[1]);
        $actual = self::stripSpaces(check_markup($case[0], 'xbbcode_test'));
        static::assertEquals($expected, $actual);
      }

      // The spoiler tag generates a random dynamic value.
      $input = $this
        ->randomString(2048) . '>\'"; email@example.com http://example.com/';
      $input = str_replace('<', '', $input);
      $escaped = Html::escape($input);
      $bbcode = "[spoiler]{$input}[/spoiler]";
      $element = $this
        ->checkMarkup($bbcode, 'xbbcode_test');
      preg_match('/id="xbbcode-spoiler-(\\d+)"/', $element['#markup'], $match);
      $key = $match[1];
      static::assertNotNull($key);
      $expected = "<input id=\"xbbcode-spoiler-{$key}\" type=\"checkbox\" class=\"xbbcode-spoiler\" />" . "<label class=\"xbbcode-spoiler\" for=\"xbbcode-spoiler-{$key}\">{$escaped}</label>";
      static::assertEquals($expected, $element['#markup']);
    }
  }

  /**
   * Data provider that generates test input/output for standard tags.
   *
   * @return string[][]
   *   Array of arrays, each array consisting of two strings:
   *   - The filter input.
   *   - The expected filter output.
   */
  private function getTags() : array {
    $input = $this
      ->randomString(128);

    // Add a long run of backslashes to check for backtracking.
    $input .= str_repeat('\\', 128);

    // Add a pathological mix of raw and encoded characters.
    $input .= '<>&&amp;&quot;&amp;amp;amp;quot;&gt;';

    // Mask any existing tag names that happen to be generated.
    $names = [
      'align',
      'b',
      'color',
      'font',
      'i',
      'url',
      'list',
      'quote',
      'size',
      's',
      'sub',
      'sup',
      'u',
      'code',
      'img',
      'table',
    ];
    $replacement = mb_strtolower($this
      ->randomMachineName());
    $input = preg_replace('/(\\[\\/?)(' . implode('|', $names) . ')(?!\\w+)/', '$0' . $replacement, $input);

    // Also mask any list item delimiters.
    $input = str_replace('[*]', '[**]', $input);
    $content = Html::escape($input);

    // The option must escape square brackets.
    $option = preg_replace('/[\\[\\]\\\\]/', '\\\\$0', $input);

    // If the option starts with a quote, add a backslash.
    if (preg_match('/^[\'\\"]/', $option)) {
      $option = '\\' . $option;
    }

    // Attribute has escaped quotes.
    // Also, all semicolons must be part of character entities.
    $style = Html::escape(str_replace(';', '', $input));
    $tags[] = [
      "[align={$option}]{$input}[/align]",
      "<p style=\"text-align:{$style}\">{$content}</p>",
    ];
    $tags[] = [
      "[b]{$input}[/b]",
      "<strong>{$content}</strong>",
    ];
    $tags[] = [
      "[color={$option}]{$input}[/color]",
      "<span style=\"color:{$style}\">{$content}</span>",
    ];
    $tags[] = [
      "[font={$option}]{$input}[/font]",
      "<span style=\"font-family:{$style}\">{$content}</span>",
    ];
    $tags[] = [
      "[i]{$input}[/i]",
      "<em>{$content}</em>",
    ];
    $tags[] = [
      "[url={$option}]{$input}[/url]",
      "<a href=\"{$content}\" title=\"{$content}\">{$content}</a>",
    ];
    $tags[] = [
      "[quote]{$input}[/quote]",
      "<blockquote>{$content}</blockquote>",
    ];
    $tags[] = [
      "[size={$option}]{$input}[/size]",
      "<span style=\"font-size:{$style}\">{$content}</span>",
    ];
    $tags[] = [
      "[s]{$input}[/s]",
      "<s>{$content}</s>",
    ];
    $tags[] = [
      "[sub]{$input}[/sub]",
      "<sub>{$content}</sub>",
    ];
    $tags[] = [
      "[sup]{$input}[/sup]",
      "<sup>{$content}</sup>",
    ];
    $tags[] = [
      "[u]{$input}[/u]",
      "<span style=\"text-decoration:underline\">{$content}</span>",
    ];
    $tags[] = [
      "[code][b]{$input}[/b][/code]",
      "<code>[b]{$content}[/b]</code>",
    ];
    try {

      // Exhaustively test cases here.
      $width = random_int(0, 1000);
      $height = random_int(0, 1000);
    } catch (\Exception $e) {

      // Chosen by fair dice roll. Guaranteed to be random.
      $width = 4;
      $height = 4;
    }
    $tags[] = [
      "[img={$width}x{$height}]{$input}[/img]",
      "<img src=\"{$content}\" alt=\"{$content}\" style=\"width:{$width}px;height:{$height}px;\" />",
    ];
    $tags[] = [
      "[img width={$width} height={$height}]{$input}[/img]",
      "<img src=\"{$content}\" alt=\"{$content}\" style=\"width:{$width}px;height:{$height}px;\" />",
    ];
    $tags[] = [
      "[img={$width}x]{$input}[/img]",
      "<img src=\"{$content}\" alt=\"{$content}\" style=\"width:{$width}px;\" />",
    ];
    $tags[] = [
      "[img width={$width}]{$input}[/img]",
      "<img src=\"{$content}\" alt=\"{$content}\" style=\"width:{$width}px;\" />",
    ];
    $tags[] = [
      "[img=x{$height}]{$input}[/img]",
      "<img src=\"{$content}\" alt=\"{$content}\" style=\"height:{$height}px;\" />",
    ];
    $tags[] = [
      "[img height={$height}]{$input}[/img]",
      "<img src=\"{$content}\" alt=\"{$content}\" style=\"height:{$height}px;\" />",
    ];

    // Tables have an extra backslash level, which is applied first.
    $cell = preg_replace('/[\'\\",\\\\]/', '\\\\$0', $input);
    $header = preg_replace('/[\\s\\[\\]\\\\]/', '\\\\$0', $cell);
    $attribute = preg_replace('/[\'\\"\\s\\[\\]\\\\]/', '\\\\$0', $input);
    $headers = "~{$header}0,\\ {$header}1,!{$header}2,#{$header}3";
    if (preg_match('/^[\'\\"]/', $headers[0])) {
      $headers = '\\' . $headers;
      $attribute = '\\' . $attribute;
    }
    $row = implode(',', array_fill(0, 4, $cell));
    $output_row = <<<DOC
<tr>
  <td style="text-align:left">{<span class="php-variable">$content</span>}</td>
  <td>{<span class="php-variable">$content</span>}</td>
  <td style="text-align:center">{<span class="php-variable">$content</span>}</td>
  <td style="text-align:right">{<span class="php-variable">$content</span>}</td>
</tr>
DOC;
    $table_body = str_repeat("{$row}\n", 5);
    $output = str_repeat($output_row, 5);
    $table = <<<DOC
<table class="responsive-enabled" data-striping="1">
  <caption>{<span class="php-variable">$content</span>}-caption</caption>
  <thead>
    <tr>
      <th>{<span class="php-variable">$content</span>}0</th>
      <th>{<span class="php-variable">$content</span>}1</th>
      <th>{<span class="php-variable">$content</span>}2</th>
      <th>{<span class="php-variable">$content</span>}3</th>
    </tr>
  </thead>
  <tbody>
    {<span class="php-variable">$output</span>}
  </tbody>
</table>
DOC;
    $tags[] = [
      "[table header={$headers} caption={$attribute}-caption]\n{$table_body}[/table]",
      $table,
    ];
    return $tags;
  }

  /**
   * A variant of check_markup that returns the full element.
   *
   * This is needed to check the #attached key.
   *
   * @param string $text
   *   The input text.
   * @param string $format_id
   *   The format ID.
   *
   * @return array
   *   The render array representing the processed text.
   */
  private function checkMarkup(string $text, string $format_id) : array {
    $build = [
      '#type' => 'processed_text',
      '#text' => $text,
      '#format' => $format_id,
      '#filter_types_to_skip' => [],
      '#langcode' => '',
    ];
    \Drupal::service('renderer')
      ->renderPlain($build);
    return $build;
  }

  /**
   * Strip interstitial white space between tags.
   *
   * This produces a normal form for templates that use odd indentation.
   *
   * @param string $html
   *   The HTML input.
   *
   * @return string
   *   The HTML with all the following whitespace removed:
   *   - between > and <
   *   - between the start and <
   *   - between > and the end
   */
  private static function stripSpaces(string $html) : string {
    return preg_replace('/(?<=^|>)\\s+(?=<|$)/', '', $html);
  }

}

Members

Namesort descending Modifiers Type Description Overrides
AssertContentTrait::$content protected property The current raw content.
AssertContentTrait::$drupalSettings protected property The drupalSettings value from the current raw $content.
AssertContentTrait::$elements protected property The XML structure parsed from the current raw $content. 1
AssertContentTrait::$plainTextContent protected property The plain-text content of raw $content (text nodes).
AssertContentTrait::assertEscaped protected function Passes if the raw text IS found escaped on the loaded page, fail otherwise.
AssertContentTrait::assertField protected function Asserts that a field exists with the given name or ID.
AssertContentTrait::assertFieldById protected function Asserts that a field exists with the given ID and value.
AssertContentTrait::assertFieldByName protected function Asserts that a field exists with the given name and value.
AssertContentTrait::assertFieldByXPath protected function Asserts that a field exists in the current page by the given XPath.
AssertContentTrait::assertFieldChecked protected function Asserts that a checkbox field in the current page is checked.
AssertContentTrait::assertFieldsByValue protected function Asserts that a field exists in the current page with a given Xpath result.
AssertContentTrait::assertLink protected function Passes if a link with the specified label is found.
AssertContentTrait::assertLinkByHref protected function Passes if a link containing a given href (part) is found.
AssertContentTrait::assertNoDuplicateIds protected function Asserts that each HTML ID is used for just a single element.
AssertContentTrait::assertNoEscaped protected function Passes if the raw text IS NOT found escaped on the loaded page, fail otherwise.
AssertContentTrait::assertNoField protected function Asserts that a field does not exist with the given name or ID.
AssertContentTrait::assertNoFieldById protected function Asserts that a field does not exist with the given ID and value.
AssertContentTrait::assertNoFieldByName protected function Asserts that a field does not exist with the given name and value.
AssertContentTrait::assertNoFieldByXPath protected function Asserts that a field does not exist or its value does not match, by XPath.
AssertContentTrait::assertNoFieldChecked protected function Asserts that a checkbox field in the current page is not checked.
AssertContentTrait::assertNoLink protected function Passes if a link with the specified label is not found.
AssertContentTrait::assertNoLinkByHref protected function Passes if a link containing a given href (part) is not found.
AssertContentTrait::assertNoLinkByHrefInMainRegion protected function Passes if a link containing a given href is not found in the main region.
AssertContentTrait::assertNoOption protected function Asserts that a select option in the current page does not exist.
AssertContentTrait::assertNoOptionSelected protected function Asserts that a select option in the current page is not checked.
AssertContentTrait::assertNoPattern protected function Triggers a pass if the perl regex pattern is not found in raw content.
AssertContentTrait::assertNoRaw protected function Passes if the raw text is NOT found on the loaded page, fail otherwise.
AssertContentTrait::assertNoText protected function Passes if the page (with HTML stripped) does not contains the text.
AssertContentTrait::assertNoTitle protected function Pass if the page title is not the given string.
AssertContentTrait::assertNoUniqueText protected function Passes if the text is found MORE THAN ONCE on the text version of the page.
AssertContentTrait::assertOption protected function Asserts that a select option in the current page exists.
AssertContentTrait::assertOptionByText protected function Asserts that a select option with the visible text exists.
AssertContentTrait::assertOptionSelected protected function Asserts that a select option in the current page is checked.
AssertContentTrait::assertOptionSelectedWithDrupalSelector protected function Asserts that a select option in the current page is checked.
AssertContentTrait::assertOptionWithDrupalSelector protected function Asserts that a select option in the current page exists.
AssertContentTrait::assertPattern protected function Triggers a pass if the Perl regex pattern is found in the raw content.
AssertContentTrait::assertRaw protected function Passes if the raw text IS found on the loaded page, fail otherwise.
AssertContentTrait::assertText protected function Passes if the page (with HTML stripped) contains the text.
AssertContentTrait::assertTextHelper protected function Helper for assertText and assertNoText.
AssertContentTrait::assertTextPattern protected function Asserts that a Perl regex pattern is found in the plain-text content.
AssertContentTrait::assertThemeOutput protected function Asserts themed output.
AssertContentTrait::assertTitle protected function Pass if the page title is the given string.
AssertContentTrait::assertUniqueText protected function Passes if the text is found ONLY ONCE on the text version of the page.
AssertContentTrait::assertUniqueTextHelper protected function Helper for assertUniqueText and assertNoUniqueText.
AssertContentTrait::buildXPathQuery protected function Builds an XPath query.
AssertContentTrait::constructFieldXpath protected function Helper: Constructs an XPath for the given set of attributes and value.
AssertContentTrait::cssSelect protected function Searches elements using a CSS selector in the raw content.
AssertContentTrait::getAllOptions protected function Get all option elements, including nested options, in a select.
AssertContentTrait::getDrupalSettings protected function Gets the value of drupalSettings for the currently-loaded page.
AssertContentTrait::getRawContent protected function Gets the current raw content.
AssertContentTrait::getSelectedItem protected function Get the selected value from a select field.
AssertContentTrait::getTextContent protected function Retrieves the plain-text content from the current raw content.
AssertContentTrait::getUrl protected function Get the current URL from the cURL handler. 1
AssertContentTrait::parse protected function Parse content returned from curlExec using DOM and SimpleXML.
AssertContentTrait::removeWhiteSpace protected function Removes all white-space between HTML tags from the raw content.
AssertContentTrait::setDrupalSettings protected function Sets the value of drupalSettings for the currently-loaded page.
AssertContentTrait::setRawContent protected function Sets the raw content (e.g. HTML).
AssertContentTrait::xpath protected function Performs an xpath search on the contents of the internal browser.
AssertLegacyTrait::assert Deprecated protected function
AssertLegacyTrait::assertEqual Deprecated protected function
AssertLegacyTrait::assertIdentical Deprecated protected function
AssertLegacyTrait::assertIdenticalObject Deprecated protected function
AssertLegacyTrait::assertNotEqual Deprecated protected function
AssertLegacyTrait::assertNotIdentical Deprecated protected function
AssertLegacyTrait::pass Deprecated protected function
AssertLegacyTrait::verbose Deprecated protected function
ConfigTestTrait::configImporter protected function Returns a ConfigImporter object to import test configuration.
ConfigTestTrait::copyConfig protected function Copies configuration objects from source storage to target storage.
ExtensionListTestTrait::getModulePath protected function Gets the path for the specified module.
ExtensionListTestTrait::getThemePath protected function Gets the path for the specified theme.
KernelTestBase::$backupGlobals protected property Back up and restore any global variables that may be changed by tests.
KernelTestBase::$backupStaticAttributes protected property Back up and restore static class properties that may be changed by tests.
KernelTestBase::$backupStaticAttributesBlacklist protected property Contains a few static class properties for performance.
KernelTestBase::$classLoader protected property
KernelTestBase::$configImporter protected property @todo Move into Config test base class. 7
KernelTestBase::$configSchemaCheckerExclusions protected static property An array of config object names that are excluded from schema checking.
KernelTestBase::$container protected property
KernelTestBase::$databasePrefix protected property
KernelTestBase::$preserveGlobalState protected property Do not forward any global state from the parent process to the processes that run the actual tests.
KernelTestBase::$root protected property The app root.
KernelTestBase::$runTestInSeparateProcess protected property Kernel tests are run in separate processes because they allow autoloading of code from extensions. Running the test in a separate process isolates this behavior from other tests. Subclasses should not override this property.
KernelTestBase::$siteDirectory protected property
KernelTestBase::$strictConfigSchema protected property Set to TRUE to strict check all configuration saved. 6
KernelTestBase::$vfsRoot protected property The virtual filesystem root directory.
KernelTestBase::assertPostConditions protected function 1
KernelTestBase::bootEnvironment protected function Bootstraps a basic test environment.
KernelTestBase::bootKernel private function Bootstraps a kernel for a test.
KernelTestBase::config protected function Configuration accessor for tests. Returns non-overridden configuration.
KernelTestBase::disableModules protected function Disables modules for this test.
KernelTestBase::enableModules protected function Enables modules for this test.
KernelTestBase::getConfigSchemaExclusions protected function Gets the config schema exclusions for this test.
KernelTestBase::getDatabaseConnectionInfo protected function Returns the Database connection info to be used for this test. 3
KernelTestBase::getDatabasePrefix public function
KernelTestBase::getExtensionsForModules private function Returns Extension objects for $modules to enable.
KernelTestBase::getModulesToEnable private static function Returns the modules to enable for this test.
KernelTestBase::initFileCache protected function Initializes the FileCache component.
KernelTestBase::installConfig protected function Installs default configuration for a given list of modules.
KernelTestBase::installEntitySchema protected function Installs the storage schema for a specific entity type.
KernelTestBase::installSchema protected function Installs database tables from a module schema definition.
KernelTestBase::prepareTemplate protected function
KernelTestBase::register public function Registers test-specific services. Overrides ServiceProviderInterface::register 24
KernelTestBase::render protected function Renders a render array. 1
KernelTestBase::setInstallProfile protected function Sets the install profile and rebuilds the container to update it.
KernelTestBase::setSetting protected function Sets an in-memory Settings variable.
KernelTestBase::setUpBeforeClass public static function 1
KernelTestBase::setUpFilesystem protected function Sets up the filesystem, so things like the file directory. 2
KernelTestBase::stop protected function Stops test execution.
KernelTestBase::tearDown protected function 4
KernelTestBase::tearDownCloseDatabaseConnection public function @after
KernelTestBase::vfsDump protected function Dumps the current state of the virtual filesystem to STDOUT.
KernelTestBase::__sleep public function Prevents serializing any properties.
PhpUnitWarnings::$deprecationWarnings private static property Deprecation warnings from PHPUnit to raise with @trigger_error().
PhpUnitWarnings::addWarning public function Converts PHPUnit deprecation warnings to E_USER_DEPRECATED.
RandomGeneratorTrait::$randomGenerator protected property The random generator.
RandomGeneratorTrait::getRandomGenerator protected function Gets the random generator for the utility methods.
RandomGeneratorTrait::randomMachineName protected function Generates a unique random string containing letters and numbers. 1
RandomGeneratorTrait::randomObject public function Generates a random PHP object.
RandomGeneratorTrait::randomString public function Generates a pseudo-random string of ASCII characters of codes 32 to 126.
RandomGeneratorTrait::randomStringValidate public function Callback for random string validation.
StorageCopyTrait::replaceStorageContents protected static function Copy the configuration from one storage to another and remove stale items.
TestRequirementsTrait::checkModuleRequirements private function Checks missing module requirements.
TestRequirementsTrait::checkRequirements protected function Check module requirements for the Drupal use case. 1
TestRequirementsTrait::getDrupalRoot protected static function Returns the Drupal root directory.
XBBCodeStandardTest::$modules public static property Modules to enable. Overrides KernelTestBase::$modules
XBBCodeStandardTest::checkMarkup private function A variant of check_markup that returns the full element.
XBBCodeStandardTest::getTags private function Data provider that generates test input/output for standard tags.
XBBCodeStandardTest::setUp protected function Overrides KernelTestBase::setUp
XBBCodeStandardTest::stripSpaces private static function Strip interstitial white space between tags.
XBBCodeStandardTest::testTags public function Test all of the tags installed by this module.