diff --git a/core/modules/field/src/Tests/DisplayApiTest.php b/core/modules/field/src/Tests/DisplayApiTest.php index 0ee7c79abb2f23025361c240ac7271b2bcb61817..52bbdaaf581c847bc54d1c800a8a361cf3273169 100644 --- a/core/modules/field/src/Tests/DisplayApiTest.php +++ b/core/modules/field/src/Tests/DisplayApiTest.php @@ -126,8 +126,7 @@ function testFieldItemListView() { $items = $this->entity->get($this->field_name); // No display settings: check that default display settings are used. - $output = $items->view(); - $this->content = drupal_render($output); + $this->render($items->view()); $settings = \Drupal::service('plugin.manager.field.formatter')->getDefaultSettings('field_test_default'); $setting = $settings['test_formatter_setting']; $this->assertText($this->label, 'Label was displayed.'); @@ -144,8 +143,7 @@ function testFieldItemListView() { 'alter' => TRUE, ), ); - $output = $items->view($display); - $this->content = drupal_render($output); + $this->render($items->view($display)); $setting = $display['settings']['test_formatter_setting_multiple']; $this->assertNoText($this->label, 'Label was not displayed.'); $this->assertText('field_test_entity_display_build_alter', 'Alter fired, display passed.'); @@ -165,8 +163,7 @@ function testFieldItemListView() { 'alter' => TRUE, ), ); - $output = $items->view($display); - $this->content = drupal_render($output); + $this->render($items->view($display)); $setting = $display['settings']['test_formatter_setting_multiple']; $this->assertRaw('visually-hidden', 'Label was visually hidden.'); $this->assertText('field_test_entity_display_build_alter', 'Alter fired, display passed.'); @@ -185,9 +182,7 @@ function testFieldItemListView() { 'test_formatter_setting_additional' => $this->randomName(), ), ); - $output = $items->view($display); - $view = drupal_render($output); - $this->content = $view; + $this->render($items->view($display)); $setting = $display['settings']['test_formatter_setting_additional']; $this->assertNoText($this->label, 'Label was not displayed.'); $this->assertNoText('field_test_entity_display_build_alter', 'Alter not fired.'); @@ -197,8 +192,7 @@ function testFieldItemListView() { // View mode: check that display settings specified in the display object // are used. - $output = $items->view('teaser'); - $this->content = drupal_render($output); + $this->render($items->view('teaser')); $setting = $this->display_options['teaser']['settings']['test_formatter_setting']; $this->assertText($this->label, 'Label was displayed.'); foreach ($this->values as $delta => $value) { @@ -207,8 +201,7 @@ function testFieldItemListView() { // Unknown view mode: check that display settings for 'default' view mode // are used. - $output = $items->view('unknown_view_mode'); - $this->content = drupal_render($output); + $this->render($items->view('unknown_view_mode')); $setting = $this->display_options['default']['settings']['test_formatter_setting']; $this->assertText($this->label, 'Label was displayed.'); foreach ($this->values as $delta => $value) { @@ -225,8 +218,7 @@ function testFieldItemView() { $setting = $settings['test_formatter_setting']; foreach ($this->values as $delta => $value) { $item = $this->entity->{$this->field_name}[$delta]; - $output = $item->view(); - $this->content = drupal_render($output); + $this->render($item->view()); $this->assertText($setting . '|' . $value['value'], format_string('Value @delta was displayed with expected setting.', array('@delta' => $delta))); } @@ -240,8 +232,7 @@ function testFieldItemView() { $setting = $display['settings']['test_formatter_setting_multiple']; foreach ($this->values as $delta => $value) { $item = $this->entity->{$this->field_name}[$delta]; - $output = $item->view($display); - $this->content = drupal_render($output); + $this->render($item->view($display)); $this->assertText($setting . '|0:' . $value['value'], format_string('Value @delta was displayed with expected setting.', array('@delta' => $delta))); } @@ -255,8 +246,7 @@ function testFieldItemView() { $setting = $display['settings']['test_formatter_setting_additional']; foreach ($this->values as $delta => $value) { $item = $this->entity->{$this->field_name}[$delta]; - $output = $item->view($display); - $this->content = drupal_render($output); + $this->render($item->view($display)); $this->assertText($setting . '|' . $value['value'] . '|' . ($value['value'] + 1), format_string('Value @delta was displayed with expected setting.', array('@delta' => $delta))); } @@ -265,8 +255,7 @@ function testFieldItemView() { $setting = $this->display_options['teaser']['settings']['test_formatter_setting']; foreach ($this->values as $delta => $value) { $item = $this->entity->{$this->field_name}[$delta]; - $output = $item->view('teaser'); - $this->content = drupal_render($output); + $this->render($item->view('teaser')); $this->assertText($setting . '|' . $value['value'], format_string('Value @delta was displayed with expected setting.', array('@delta' => $delta))); } @@ -275,8 +264,7 @@ function testFieldItemView() { $setting = $this->display_options['default']['settings']['test_formatter_setting']; foreach ($this->values as $delta => $value) { $item = $this->entity->{$this->field_name}[$delta]; - $output = $item->view('unknown_view_mode'); - $this->content = drupal_render($output); + $this->render($item->view('unknown_view_mode')); $this->assertText($setting . '|' . $value['value'], format_string('Value @delta was displayed with expected setting.', array('@delta' => $delta))); } } @@ -295,9 +283,7 @@ function testFieldEmpty() { ); // $this->entity is set by the setUp() method and by default contains 4 // numeric values. We only want to test the display of this one field. - $output = $this->entity->get($this->field_name)->view($display); - $view = drupal_render($output); - $this->content = $view; + $this->render($this->entity->get($this->field_name)->view($display)); // The test field by default contains values, so should not display the // default "empty" text. $this->assertNoText($display['settings']['test_empty_string']); @@ -305,9 +291,7 @@ function testFieldEmpty() { // Now remove the values from the test field and retest. $this->entity->{$this->field_name} = array(); $this->entity->save(); - $output = $this->entity->get($this->field_name)->view($display); - $view = drupal_render($output); - $this->content = $view; + $this->render($this->entity->get($this->field_name)->view($display)); // This time, as the field values have been removed, we *should* show the // default "empty" text. $this->assertText($display['settings']['test_empty_string']); diff --git a/core/modules/field/src/Tests/FieldAttachOtherTest.php b/core/modules/field/src/Tests/FieldAttachOtherTest.php index 73a3b1e0324053b059d7aa71b3a6dc59a1d9b5ae..88ba6f7dfc04f732028bdbf372c81e7d50bb64d7 100644 --- a/core/modules/field/src/Tests/FieldAttachOtherTest.php +++ b/core/modules/field/src/Tests/FieldAttachOtherTest.php @@ -85,7 +85,7 @@ function testEntityDisplayBuild() { // View all fields. $content = $display->build($entity); - $this->content = drupal_render($content); + $this->render($content); $this->assertRaw($this->instance->getLabel(), "First field's label is displayed."); foreach ($values as $delta => $value) { $this->assertRaw("$formatter_setting|{$value['value']}", "Value $delta is displayed, formatter settings are applied."); @@ -100,14 +100,14 @@ function testEntityDisplayBuild() { $display_options['label'] = 'hidden'; $display->setComponent($this->field->getName(), $display_options); $content = $display->build($entity); - $this->content = drupal_render($content); + $this->render($content); $this->assertNoRaw($this->instance->getLabel(), "Hidden label: label is not displayed."); // Field hidden. $entity = clone($entity_init); $display->removeComponent($this->field->getName()); $content = $display->build($entity); - $this->content = drupal_render($content); + $this->render($content); $this->assertNoRaw($this->instance->getLabel(), "Hidden field: label is not displayed."); foreach ($values as $delta => $value) { $this->assertNoRaw("$formatter_setting|{$value['value']}", "Hidden field: value $delta is not displayed."); @@ -124,7 +124,7 @@ function testEntityDisplayBuild() { ), )); $content = $display->build($entity); - $this->content = drupal_render($content); + $this->render($content); $expected_output = $formatter_setting; foreach ($values as $delta => $value) { $expected_output .= "|$delta:{$value['value']}"; @@ -142,7 +142,7 @@ function testEntityDisplayBuild() { ), )); $content = $display->build($entity); - $this->content = drupal_render($content); + $this->render($content); foreach ($values as $delta => $value) { $expected = $formatter_setting . '|' . $value['value'] . '|' . ($value['value'] + 1); $this->assertRaw($expected, "Value $delta is displayed, formatter settings are applied."); diff --git a/core/modules/field/src/Tests/FieldUnitTestBase.php b/core/modules/field/src/Tests/FieldUnitTestBase.php index 21008333350ce6f8432ec19e59923c12a1840994..ecc278ab55515018902fd797d0adc44d57111308 100644 --- a/core/modules/field/src/Tests/FieldUnitTestBase.php +++ b/core/modules/field/src/Tests/FieldUnitTestBase.php @@ -7,7 +7,6 @@ namespace Drupal\field\Tests; -use Drupal\Component\Utility\Xss; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Language\LanguageInterface; use Drupal\simpletest\DrupalUnitTestBase; @@ -24,13 +23,6 @@ abstract class FieldUnitTestBase extends DrupalUnitTestBase { */ public static $modules = array('user', 'entity', 'system', 'field', 'text', 'entity_test', 'field_test'); - /** - * A string for assert raw and text helper methods. - * - * @var string - */ - protected $content; - /** * Set the default field storage backend for fields created during tests. */ @@ -162,104 +154,4 @@ function assertFieldValues(EntityInterface $entity, $field_name, $expected_value } } - /** - * Pass if the raw text IS found in set string. - * - * @param $raw - * Raw (HTML) string to look for. - * @param $message - * (optional) A message to display with the assertion. Do not translate - * messages: use format_string() to embed variables in the message text, not - * t(). If left blank, a default message will be displayed. - * @param $group - * (optional) The group this message is in, which is displayed in a column - * in test output. Use 'Debug' to indicate this is debugging output. Do not - * translate this string. Defaults to 'Other'; most tests do not override - * this default. - * - * @return - * TRUE on pass, FALSE on fail. - */ - protected function assertRaw($raw, $message = '', $group = 'Other') { - if (!$message) { - $message = t('Raw "@raw" found', array('@raw' => $raw)); - } - return $this->assert(strpos($this->content, $raw) !== FALSE, $message, $group); - } - - - /** - * Pass if the raw text IS NOT found in set string. - * - * @param $raw - * Raw (HTML) string to look for. - * @param $message - * (optional) A message to display with the assertion. Do not translate - * messages: use format_string() to embed variables in the message text, not - * t(). If left blank, a default message will be displayed. - * @param $group - * (optional) The group this message is in, which is displayed in a column - * in test output. Use 'Debug' to indicate this is debugging output. Do not - * translate this string. Defaults to 'Other'; most tests do not override - * this default. - * - * @return - * TRUE on pass, FALSE on fail. - */ - protected function assertNoRaw($raw, $message = '', $group = 'Other') { - if (!$message) { - $message = t('Raw "@raw" found', array('@raw' => $raw)); - } - return $this->assert(strpos($this->content, $raw) === FALSE, $message, $group); - } - - /** - * Pass if the text IS found in set string. - * - * @param $text - * Text to look for. - * @param $message - * (optional) A message to display with the assertion. Do not translate - * messages: use format_string() to embed variables in the message text, not - * t(). If left blank, a default message will be displayed. - * @param $group - * (optional) The group this message is in, which is displayed in a column - * in test output. Use 'Debug' to indicate this is debugging output. Do not - * translate this string. Defaults to 'Other'; most tests do not override - * this default. - * - * @return - * TRUE on pass, FALSE on fail. - */ - protected function assertText($text, $message = '', $group = 'Other') { - if (!$message) { - $message = t('Raw "@raw" found', array('@raw' => $text)); - } - return $this->assert(strpos(Xss::filter($this->content, array()), $text) !== FALSE, $message, $group); - } - - /** - * Pass if the text IS NOT found in set string. - * - * @param $text - * Text to look for. - * @param $message - * (optional) A message to display with the assertion. Do not translate - * messages: use format_string() to embed variables in the message text, not - * t(). If left blank, a default message will be displayed. - * @param $group - * (optional) The group this message is in, which is displayed in a column - * in test output. Use 'Debug' to indicate this is debugging output. Do not - * translate this string. Defaults to 'Other'; most tests do not override - * this default. - * - * @return - * TRUE on pass, FALSE on fail. - */ - protected function assertNoText($text, $message = '', $group = 'Other') { - if (!$message) { - $message = t('Raw "@raw" not found', array('@raw' => $text)); - } - return $this->assert(strpos(Xss::filter($this->content, array()), $text) === FALSE, $message, $group); - } } diff --git a/core/modules/field/src/Tests/FormTest.php b/core/modules/field/src/Tests/FormTest.php index 255c19dedb7610a9e5b80fe5f60a7d3063e10032..c8772e62fc9b6dca9660ca4b226ef7b740643d08 100644 --- a/core/modules/field/src/Tests/FormTest.php +++ b/core/modules/field/src/Tests/FormTest.php @@ -431,7 +431,7 @@ function testFieldFormJSAddMore() { // Press 'add more' button through Ajax, and place the expected HTML result // as the tested content. $commands = $this->drupalPostAjaxForm(NULL, $edit, $field_name . '_add_more'); - $this->content = $commands[1]['data']; + $this->setRawContent($commands[1]['data']); for ($delta = 0; $delta <= $delta_range; $delta++) { $this->assertFieldByName("{$field_name}[$delta][value]", $values[$delta], "Widget $delta is displayed and has the right value"); diff --git a/core/modules/node/src/Tests/NodeTypeRenameConfigImportTest.php b/core/modules/node/src/Tests/NodeTypeRenameConfigImportTest.php index 2bb230eb0f2b3018a2e9b13431e275a51dc2af3c..072e8f37b19811880715dcb86cf92f218dd92ced 100644 --- a/core/modules/node/src/Tests/NodeTypeRenameConfigImportTest.php +++ b/core/modules/node/src/Tests/NodeTypeRenameConfigImportTest.php @@ -9,7 +9,6 @@ use Drupal\Component\Utility\String; use Drupal\Component\Utility\Unicode; -use Drupal\Component\Utility\Xss; use Drupal\Core\Config\Entity\ConfigEntityStorage; use Drupal\simpletest\WebTestBase; @@ -126,27 +125,4 @@ public function testConfigurationRename() { $this->assertIdentical($staged_type, $content_type->type); } - /** - * Asserts that a Perl regex pattern is found in the text content. - * - * @param string $pattern - * Perl regex to look for including the regex delimiters. - * @param string $message - * (optional) A message to display with the assertion. - * - * @return bool - * TRUE on pass, FALSE on failure. - */ - protected function assertTextPattern($pattern, $message = NULL) { - // @see WebTestBase::assertTextHelper() - if ($this->plainTextContent === FALSE) { - $this->plainTextContent = Xss::filter($this->drupalGetContent(), array()); - } - // @see WebTestBase::assertPattern() - if (!$message) { - $message = String::format('Pattern "@pattern" found', array('@pattern' => $pattern)); - } - return $this->assert((bool) preg_match($pattern, $this->plainTextContent), $message); - } - } diff --git a/core/modules/simpletest/src/AssertContentTrait.php b/core/modules/simpletest/src/AssertContentTrait.php new file mode 100644 index 0000000000000000000000000000000000000000..4b9a4a727ffb6a309dfa6b955f643f0dea4ed29c --- /dev/null +++ b/core/modules/simpletest/src/AssertContentTrait.php @@ -0,0 +1,1243 @@ +<?php + +/** + * @file + * Contains \Drupal\simpletest\AssertContentTrait. + */ + +namespace Drupal\simpletest; + +use Drupal\Component\Serialization\Json; +use Drupal\Component\Utility\String; +use Drupal\Component\Utility\Xss; +use Symfony\Component\CssSelector\CssSelector; + +/** + * Provides test methods to assert content. + */ +trait AssertContentTrait { + + /** + * The current raw content. + * + * @var string + */ + protected $content; + + /** + * The plain-text content of raw $content (text nodes). + * + * @var string + */ + protected $plainTextContent; + + /** + * The drupalSettings value from the current raw $content. + * + * drupalSettings refers to the drupalSettings JavaScript variable. + * + * @var array + */ + protected $drupalSettings; + + /** + * The XML structure parsed from the current raw $content. + * + * @var \SimpleXMLElement + */ + protected $elements; + + /** + * Gets the current raw content. + */ + protected function getRawContent() { + return $this->content; + } + + /** + * Sets the raw content (e.g. HTML). + * + * @param string $content + * The raw content to set. + */ + protected function setRawContent($content) { + $this->content = $content; + $this->plainTextContent = NULL; + $this->elements = NULL; + $this->drupalSettings = array(); + if (preg_match('/var drupalSettings = (.*?);$/m', $content, $matches)) { + $this->drupalSettings = Json::decode($matches[1]); + } + } + + /** + * Retrieves the plain-text content from the current raw content. + */ + protected function getTextContent() { + if (!isset($this->plainTextContent)) { + $this->plainTextContent = Xss::filter($this->getRawContent(), array()); + } + return $this->plainTextContent; + } + + /** + * Removes all white-space between HTML tags from the raw content. + * + * White-space is only removed if there are no non-white-space characters + * between HTML tags. + * + * Use this (once) after performing an operation that sets new raw content, + * and when you want to use e.g. assertText() but ignore potential white-space + * caused by HTML output templates. + */ + protected function removeWhiteSpace() { + $this->content = preg_replace('@>\s+<@', '><', $this->content); + $this->plainTextContent = NULL; + $this->elements = NULL; + } + + /** + * Gets the value of drupalSettings for the currently-loaded page. + * + * drupalSettings refers to the drupalSettings JavaScript variable. + */ + protected function getDrupalSettings() { + return $this->drupalSettings; + } + + /** + * Sets the value of drupalSettings for the currently-loaded page. + * + * drupalSettings refers to the drupalSettings JavaScript variable. + */ + protected function setDrupalSettings($settings) { + $this->drupalSettings = $settings; + } + + /** + * Parse content returned from curlExec using DOM and SimpleXML. + * + * @return \SimpleXMLElement|FALSE + * A SimpleXMLElement or FALSE on failure. + */ + protected function parse() { + if (!isset($this->elements)) { + // DOM can load HTML soup. But, HTML soup can throw warnings, suppress + // them. + $html_dom = new \DOMDocument(); + @$html_dom->loadHTML('<?xml encoding="UTF-8">' . $this->getRawContent()); + if ($html_dom) { + $this->pass(String::format('Valid HTML found on "@path"', array('@path' => $this->getUrl())), 'Browser'); + // It's much easier to work with simplexml than DOM, luckily enough + // we can just simply import our DOM tree. + $this->elements = simplexml_import_dom($html_dom); + } + } + if ($this->elements === FALSE) { + $this->fail('Parsed page successfully.', 'Browser'); + } + + return $this->elements; + } + + /** + * Builds an XPath query. + * + * Builds an XPath query by replacing placeholders in the query by the value + * of the arguments. + * + * XPath 1.0 (the version supported by libxml2, the underlying XML library + * used by PHP) doesn't support any form of quotation. This function + * simplifies the building of XPath expression. + * + * @param string $xpath + * An XPath query, possibly with placeholders in the form ':name'. + * @param array $args + * An array of arguments with keys in the form ':name' matching the + * placeholders in the query. The values may be either strings or numeric + * values. + * + * @return string + * An XPath query with arguments replaced. + */ + protected function buildXPathQuery($xpath, array $args = array()) { + // Replace placeholders. + foreach ($args as $placeholder => $value) { + // XPath 1.0 doesn't support a way to escape single or double quotes in a + // string literal. We split double quotes out of the string, and encode + // them separately. + if (is_string($value)) { + // Explode the text at the quote characters. + $parts = explode('"', $value); + + // Quote the parts. + foreach ($parts as &$part) { + $part = '"' . $part . '"'; + } + + // Return the string. + $value = count($parts) > 1 ? 'concat(' . implode(', \'"\', ', $parts) . ')' : $parts[0]; + } + + // Use preg_replace_callback() instead of preg_replace() to prevent the + // regular expression engine from trying to substitute backreferences. + $replacement = function ($matches) use ($value) { + return $value; + }; + $xpath = preg_replace_callback('/' . preg_quote($placeholder) . '\b/', $replacement, $xpath); + } + return $xpath; + } + + /** + * Performs an xpath search on the contents of the internal browser. + * + * The search is relative to the root element (HTML tag normally) of the page. + * + * @param string $xpath + * The xpath string to use in the search. + * @param array $arguments + * An array of arguments with keys in the form ':name' matching the + * placeholders in the query. The values may be either strings or numeric + * values. + * + * @return array + * The return value of the xpath search. For details on the xpath string + * format and return values see the SimpleXML documentation, + * http://php.net/manual/function.simplexml-element-xpath.php. + */ + protected function xpath($xpath, array $arguments = array()) { + if ($this->parse()) { + $xpath = $this->buildXPathQuery($xpath, $arguments); + $result = $this->elements->xpath($xpath); + // Some combinations of PHP / libxml versions return an empty array + // instead of the documented FALSE. Forcefully convert any falsish values + // to an empty array to allow foreach(...) constructions. + return $result ? $result : array(); + } + else { + return FALSE; + } + } + + /** + * Searches elements using a CSS selector in the raw content. + * + * The search is relative to the root element (HTML tag normally) of the page. + * + * @param string $selector + * CSS selector to use in the search. + * + * @return \SimpleXMLElement + * The return value of the XPath search performed after converting the CSS + * selector to an XPath selector. + */ + protected function cssSelect($selector) { + return $this->xpath(CssSelector::toXPath($selector)); + } + + /** + * Get all option elements, including nested options, in a select. + * + * @param \SimpleXMLElement $element + * The element for which to get the options. + * + * @return \SimpleXmlElement[] + * Option elements in select. + */ + protected function getAllOptions(\SimpleXMLElement $element) { + $options = array(); + // Add all options items. + foreach ($element->option as $option) { + $options[] = $option; + } + + // Search option group children. + if (isset($element->optgroup)) { + foreach ($element->optgroup as $group) { + $options = array_merge($options, $this->getAllOptions($group)); + } + } + return $options; + } + + /** + * Passes if a link with the specified label is found. + * + * An optional link index may be passed. + * + * @param string $label + * Text between the anchor tags. + * @param int $index + * Link position counting from zero. + * @param string $message + * (optional) A message to display with the assertion. Do not translate + * messages: use format_string() to embed variables in the message text, not + * t(). If left blank, a default message will be displayed. + * @param string $group + * (optional) The gorup this message is in, which is displayed in a column + * in test output. Use 'Debug' to indicate this is debugging output. Do not + * translate this string. Defaults to 'Other'; most tests do not override + * this default. + * + * @return bool + * TRUE if the assertion succeeded, FALSE otherwise. + */ + protected function assertLink($label, $index = 0, $message = '', $group = 'Other') { + $links = $this->xpath('//a[normalize-space(text())=:label]', array(':label' => $label)); + $message = ($message ? $message : String::format('Link with label %label found.', array('%label' => $label))); + return $this->assert(isset($links[$index]), $message, $group); + } + + /** + * Passes if a link with the specified label is not found. + * + * @param string $label + * Text between the anchor tags. + * @param string $message + * (optional) A message to display with the assertion. Do not translate + * messages: use format_string() to embed variables in the message text, not + * t(). If left blank, a default message will be displayed. + * @param string $group + * (optional) The group this message is in, which is displayed in a column + * in test output. Use 'Debug' to indicate this is debugging output. Do not + * translate this string. Defaults to 'Other'; most tests do not override + * this default. + * + * @return bool + * TRUE if the assertion succeeded, FALSE otherwise. + */ + protected function assertNoLink($label, $message = '', $group = 'Other') { + $links = $this->xpath('//a[normalize-space(text())=:label]', array(':label' => $label)); + $message = ($message ? $message : String::format('Link with label %label not found.', array('%label' => $label))); + return $this->assert(empty($links), $message, $group); + } + + /** + * Passes if a link containing a given href (part) is found. + * + * @param string $href + * The full or partial value of the 'href' attribute of the anchor tag. + * @param string $index + * Link position counting from zero. + * @param string $message + * (optional) A message to display with the assertion. Do not translate + * messages: use format_string() to embed variables in the message text, not + * t(). If left blank, a default message will be displayed. + * @param string $group + * (optional) The group this message is in, which is displayed in a column + * in test output. Use 'Debug' to indicate this is debugging output. Do not + * translate this string. Defaults to 'Other'; most tests do not override + * this default. + * + * @return bool + * TRUE if the assertion succeeded, FALSE otherwise. + */ + protected function assertLinkByHref($href, $index = 0, $message = '', $group = 'Other') { + $links = $this->xpath('//a[contains(@href, :href)]', array(':href' => $href)); + $message = ($message ? $message : String::format('Link containing href %href found.', array('%href' => $href))); + return $this->assert(isset($links[$index]), $message, $group); + } + + /** + * Passes if a link containing a given href (part) is not found. + * + * @param string $href + * The full or partial value of the 'href' attribute of the anchor tag. + * @param string $message + * (optional) A message to display with the assertion. Do not translate + * messages: use format_string() to embed variables in the message text, not + * t(). If left blank, a default message will be displayed. + * @param string $group + * (optional) The group this message is in, which is displayed in a column + * in test output. Use 'Debug' to indicate this is debugging output. Do not + * translate this string. Defaults to 'Other'; most tests do not override + * this default. + * + * @return bool + * TRUE if the assertion succeeded, FALSE otherwise. + */ + protected function assertNoLinkByHref($href, $message = '', $group = 'Other') { + $links = $this->xpath('//a[contains(@href, :href)]', array(':href' => $href)); + $message = ($message ? $message : String::format('No link containing href %href found.', array('%href' => $href))); + return $this->assert(empty($links), $message, $group); + } + + /** + * Passes if the raw text IS found on the loaded page, fail otherwise. + * + * Raw text refers to the raw HTML that the page generated. + * + * @param string $raw + * Raw (HTML) string to look for. + * @param string $message + * (optional) A message to display with the assertion. Do not translate + * messages: use format_string() to embed variables in the message text, not + * t(). If left blank, a default message will be displayed. + * @param string $group + * (optional) The group this message is in, which is displayed in a column + * in test output. Use 'Debug' to indicate this is debugging output. Do not + * translate this string. Defaults to 'Other'; most tests do not override + * this default. + * + * @return bool + * TRUE on pass, FALSE on fail. + */ + protected function assertRaw($raw, $message = '', $group = 'Other') { + if (!$message) { + $message = String::format('Raw "@raw" found', array('@raw' => $raw)); + } + return $this->assert(strpos($this->getRawContent(), $raw) !== FALSE, $message, $group); + } + + /** + * Passes if the raw text is NOT found on the loaded page, fail otherwise. + * + * Raw text refers to the raw HTML that the page generated. + * + * @param string $raw + * Raw (HTML) string to look for. + * @param string $message + * (optional) A message to display with the assertion. Do not translate + * messages: use format_string() to embed variables in the message text, not + * t(). If left blank, a default message will be displayed. + * @param string $group + * (optional) The group this message is in, which is displayed in a column + * in test output. Use 'Debug' to indicate this is debugging output. Do not + * translate this string. Defaults to 'Other'; most tests do not override + * this default. + * + * @return bool + * TRUE on pass, FALSE on fail. + */ + protected function assertNoRaw($raw, $message = '', $group = 'Other') { + if (!$message) { + $message = String::format('Raw "@raw" not found', array('@raw' => $raw)); + } + return $this->assert(strpos($this->getRawContent(), $raw) === FALSE, $message, $group); + } + + /** + * Passes if the text IS found on the text version of the page. + * + * The text version is the equivalent of what a user would see when viewing + * through a web browser. In other words the HTML has been filtered out of the + * contents. + * + * @param string $text + * Plain text to look for. + * @param string $message + * (optional) A message to display with the assertion. Do not translate + * messages: use format_string() to embed variables in the message text, not + * t(). If left blank, a default message will be displayed. + * @param string $group + * (optional) The group this message is in, which is displayed in a column + * in test output. Use 'Debug' to indicate this is debugging output. Do not + * translate this string. Defaults to 'Other'; most tests do not override + * this default. + * + * @return bool + * TRUE on pass, FALSE on fail. + */ + protected function assertText($text, $message = '', $group = 'Other') { + return $this->assertTextHelper($text, $message, $group, FALSE); + } + + /** + * Passes if the text is NOT found on the text version of the page. + * + * The text version is the equivalent of what a user would see when viewing + * through a web browser. In other words the HTML has been filtered out of the + * contents. + * + * @param string $text + * Plain text to look for. + * @param string $message + * (optional) A message to display with the assertion. Do not translate + * messages: use format_string() to embed variables in the message text, not + * t(). If left blank, a default message will be displayed. + * @param string $group + * (optional) The group this message is in, which is displayed in a column + * in test output. Use 'Debug' to indicate this is debugging output. Do not + * translate this string. Defaults to 'Other'; most tests do not override + * this default. + * + * @return bool + * TRUE on pass, FALSE on fail. + */ + protected function assertNoText($text, $message = '', $group = 'Other') { + return $this->assertTextHelper($text, $message, $group, TRUE); + } + + /** + * Helper for assertText and assertNoText. + * + * It is not recommended to call this function directly. + * + * @param string $text + * Plain text to look for. + * @param string $message + * (optional) A message to display with the assertion. Do not translate + * messages: use format_string() to embed variables in the message text, not + * t(). If left blank, a default message will be displayed. + * @param string $group + * (optional) The group this message is in, which is displayed in a column + * in test output. Use 'Debug' to indicate this is debugging output. Do not + * translate this string. Defaults to 'Other'; most tests do not override + * this default. Defaults to 'Other'. + * @param bool $not_exists + * (optional) TRUE if this text should not exist, FALSE if it should. + * Defaults to TRUE. + * + * @return bool + * TRUE on pass, FALSE on fail. + */ + protected function assertTextHelper($text, $message = '', $group = 'Other', $not_exists = TRUE) { + if (!$message) { + $message = !$not_exists ? String::format('"@text" found', array('@text' => $text)) : String::format('"@text" not found', array('@text' => $text)); + } + return $this->assert($not_exists == (strpos($this->getTextContent(), (string) $text) === FALSE), $message, $group); + } + + /** + * Passes if the text is found ONLY ONCE on the text version of the page. + * + * The text version is the equivalent of what a user would see when viewing + * through a web browser. In other words the HTML has been filtered out of + * the contents. + * + * @param string $text + * Plain text to look for. + * @param string $message + * (optional) A message to display with the assertion. Do not translate + * messages: use format_string() to embed variables in the message text, not + * t(). If left blank, a default message will be displayed. + * @param string $group + * (optional) The group this message is in, which is displayed in a column + * in test output. Use 'Debug' to indicate this is debugging output. Do not + * translate this string. Defaults to 'Other'; most tests do not override + * this default. + * + * @return bool + * TRUE on pass, FALSE on fail. + */ + protected function assertUniqueText($text, $message = '', $group = 'Other') { + return $this->assertUniqueTextHelper($text, $message, $group, TRUE); + } + + /** + * Passes if the text is found MORE THAN ONCE on the text version of the page. + * + * The text version is the equivalent of what a user would see when viewing + * through a web browser. In other words the HTML has been filtered out of + * the contents. + * + * @param string $text + * Plain text to look for. + * @param string $message + * (optional) A message to display with the assertion. Do not translate + * messages: use format_string() to embed variables in the message text, not + * t(). If left blank, a default message will be displayed. + * @param string $group + * (optional) The group this message is in, which is displayed in a column + * in test output. Use 'Debug' to indicate this is debugging output. Do not + * translate this string. Defaults to 'Other'; most tests do not override + * this default. + * + * @return bool + * TRUE on pass, FALSE on fail. + */ + protected function assertNoUniqueText($text, $message = '', $group = 'Other') { + return $this->assertUniqueTextHelper($text, $message, $group, FALSE); + } + + /** + * Helper for assertUniqueText and assertNoUniqueText. + * + * It is not recommended to call this function directly. + * + * @param string $text + * Plain text to look for. + * @param string $message + * (optional) A message to display with the assertion. Do not translate + * messages: use format_string() to embed variables in the message text, not + * t(). If left blank, a default message will be displayed. + * @param string $group + * (optional) The group this message is in, which is displayed in a column + * in test output. Use 'Debug' to indicate this is debugging output. Do not + * translate this string. Defaults to 'Other'; most tests do not override + * this default. Defaults to 'Other'. + * @param bool $be_unique + * (optional) TRUE if this text should be found only once, FALSE if it + * should be found more than once. Defaults to FALSE. + * + * @return bool + * TRUE on pass, FALSE on fail. + */ + protected function assertUniqueTextHelper($text, $message = '', $group = 'Other', $be_unique = FALSE) { + if (!$message) { + $message = '"' . $text . '"' . ($be_unique ? ' found only once' : ' found more than once'); + } + $first_occurance = strpos($this->getTextContent(), $text); + if ($first_occurance === FALSE) { + return $this->assert(FALSE, $message, $group); + } + $offset = $first_occurance + strlen($text); + $second_occurance = strpos($this->getTextContent(), $text, $offset); + return $this->assert($be_unique == ($second_occurance === FALSE), $message, $group); + } + + /** + * Triggers a pass if the Perl regex pattern is found in the raw content. + * + * @param string $pattern + * Perl regex to look for including the regex delimiters. + * @param string $message + * (optional) A message to display with the assertion. Do not translate + * messages: use format_string() to embed variables in the message text, not + * t(). If left blank, a default message will be displayed. + * @param string $group + * (optional) The group this message is in, which is displayed in a column + * in test output. Use 'Debug' to indicate this is debugging output. Do not + * translate this string. Defaults to 'Other'; most tests do not override + * this default. + * + * @return bool + * TRUE on pass, FALSE on fail. + */ + protected function assertPattern($pattern, $message = '', $group = 'Other') { + if (!$message) { + $message = String::format('Pattern "@pattern" found', array('@pattern' => $pattern)); + } + return $this->assert((bool) preg_match($pattern, $this->getRawContent()), $message, $group); + } + + /** + * Triggers a pass if the perl regex pattern is not found in raw content. + * + * @param string $pattern + * Perl regex to look for including the regex delimiters. + * @param string $message + * (optional) A message to display with the assertion. Do not translate + * messages: use format_string() to embed variables in the message text, not + * t(). If left blank, a default message will be displayed. + * @param string $group + * (optional) The group this message is in, which is displayed in a column + * in test output. Use 'Debug' to indicate this is debugging output. Do not + * translate this string. Defaults to 'Other'; most tests do not override + * this default. + * + * @return bool + * TRUE on pass, FALSE on fail. + */ + protected function assertNoPattern($pattern, $message = '', $group = 'Other') { + if (!$message) { + $message = String::format('Pattern "@pattern" not found', array('@pattern' => $pattern)); + } + return $this->assert(!preg_match($pattern, $this->getRawContent()), $message, $group); + } + + /** + * Asserts that a Perl regex pattern is found in the plain-text content. + * + * @param string $pattern + * Perl regex to look for including the regex delimiters. + * @param string $message + * (optional) A message to display with the assertion. + * @param string $group + * (optional) The group this message is in, which is displayed in a column + * in test output. Use 'Debug' to indicate this is debugging output. Do not + * translate this string. Defaults to 'Other'; most tests do not override + * this default. + * + * @return bool + * TRUE on pass, FALSE on failure. + */ + protected function assertTextPattern($pattern, $message = NULL, $group = 'Other') { + if (!isset($message)) { + $message = String::format('Pattern "@pattern" found', array('@pattern' => $pattern)); + } + return $this->assert((bool) preg_match($pattern, $this->getTextContent()), $message, $group); + } + + /** + * Pass if the page title is the given string. + * + * @param string $title + * The string the title should be. + * @param string $message + * (optional) A message to display with the assertion. Do not translate + * messages: use format_string() to embed variables in the message text, not + * t(). If left blank, a default message will be displayed. + * @param string $group + * (optional) The group this message is in, which is displayed in a column + * in test output. Use 'Debug' to indicate this is debugging output. Do not + * translate this string. Defaults to 'Other'; most tests do not override + * this default. + * + * @return bool + * TRUE on pass, FALSE on fail. + */ + protected function assertTitle($title, $message = '', $group = 'Other') { + $actual = (string) current($this->xpath('//title')); + if (!$message) { + $message = String::format('Page title @actual is equal to @expected.', array( + '@actual' => var_export($actual, TRUE), + '@expected' => var_export($title, TRUE), + )); + } + return $this->assertEqual($actual, $title, $message, $group); + } + + /** + * Pass if the page title is not the given string. + * + * @param string $title + * The string the title should not be. + * @param string $message + * (optional) A message to display with the assertion. Do not translate + * messages: use format_string() to embed variables in the message text, not + * t(). If left blank, a default message will be displayed. + * @param string $group + * (optional) The group this message is in, which is displayed in a column + * in test output. Use 'Debug' to indicate this is debugging output. Do not + * translate this string. Defaults to 'Other'; most tests do not override + * this default. + * + * @return bool + * TRUE on pass, FALSE on fail. + */ + protected function assertNoTitle($title, $message = '', $group = 'Other') { + $actual = (string) current($this->xpath('//title')); + if (!$message) { + $message = String::format('Page title @actual is not equal to @unexpected.', array( + '@actual' => var_export($actual, TRUE), + '@unexpected' => var_export($title, TRUE), + )); + } + return $this->assertNotEqual($actual, $title, $message, $group); + } + + /** + * Asserts themed output. + * + * @param string $callback + * The name of the theme hook to invoke; e.g. 'links' for links.html.twig. + * @param string $variables + * An array of variables to pass to the theme function. + * @param string $expected + * The expected themed output string. + * @param string $message + * (optional) A message to display with the assertion. Do not translate + * messages: use format_string() to embed variables in the message text, not + * t(). If left blank, a default message will be displayed. + * @param string $group + * (optional) The group this message is in, which is displayed in a column + * in test output. Use 'Debug' to indicate this is debugging output. Do not + * translate this string. Defaults to 'Other'; most tests do not override + * this default. + * + * @return bool + * TRUE on pass, FALSE on fail. + */ + protected function assertThemeOutput($callback, array $variables = array(), $expected = '', $message = '', $group = 'Other') { + $output = _theme($callback, $variables); + $this->verbose('Variables:' . '<pre>' . String::checkPlain(var_export($variables, TRUE)) . '</pre>' + . '<hr />' . 'Result:' . '<pre>' . String::checkPlain(var_export($output, TRUE)) . '</pre>' + . '<hr />' . 'Expected:' . '<pre>' . String::checkPlain(var_export($expected, TRUE)) . '</pre>' + . '<hr />' . $output + ); + if (!$message) { + $message = '%callback rendered correctly.'; + } + $message = format_string($message, array('%callback' => 'theme_' . $callback . '()')); + return $this->assertIdentical($output, $expected, $message, $group); + } + + /** + * Asserts that a field exists in the current page by the given XPath. + * + * @param string $xpath + * XPath used to find the field. + * @param string $value + * (optional) Value of the field to assert. You may pass in NULL (default) + * to skip checking the actual value, while still checking that the field + * exists. + * @param string $message + * (optional) A message to display with the assertion. Do not translate + * messages: use format_string() to embed variables in the message text, not + * t(). If left blank, a default message will be displayed. + * @param string $group + * (optional) The group this message is in, which is displayed in a column + * in test output. Use 'Debug' to indicate this is debugging output. Do not + * translate this string. Defaults to 'Other'; most tests do not override + * this default. + * + * @return bool + * TRUE on pass, FALSE on fail. + */ + protected function assertFieldByXPath($xpath, $value = NULL, $message = '', $group = 'Other') { + $fields = $this->xpath($xpath); + + // If value specified then check array for match. + $found = TRUE; + if (isset($value)) { + $found = FALSE; + if ($fields) { + foreach ($fields as $field) { + if (isset($field['value']) && $field['value'] == $value) { + // Input element with correct value. + $found = TRUE; + } + elseif (isset($field->option) || isset($field->optgroup)) { + // Select element found. + $selected = $this->getSelectedItem($field); + if ($selected === FALSE) { + // No item selected so use first item. + $items = $this->getAllOptions($field); + if (!empty($items) && $items[0]['value'] == $value) { + $found = TRUE; + } + } + elseif ($selected == $value) { + $found = TRUE; + } + } + elseif ((string) $field == $value) { + // Text area with correct text. + $found = TRUE; + } + } + } + } + return $this->assertTrue($fields && $found, $message, $group); + } + + /** + * Get the selected value from a select field. + * + * @param \SimpleXmlElement $element + * SimpleXMLElement select element. + * + * @return bool + * The selected value or FALSE. + */ + protected function getSelectedItem(\SimpleXMLElement $element) { + foreach ($element->children() as $item) { + if (isset($item['selected'])) { + return $item['value']; + } + elseif ($item->getName() == 'optgroup') { + if ($value = $this->getSelectedItem($item)) { + return $value; + } + } + } + return FALSE; + } + + /** + * Asserts that a field does not exist or its value does not match, by XPath. + * + * @param string $xpath + * XPath used to find the field. + * @param string $value + * (optional) Value of the field, to assert that the field's value on the + * page does not match it. + * @param string $message + * (optional) A message to display with the assertion. Do not translate + * messages: use format_string() to embed variables in the message text, not + * t(). If left blank, a default message will be displayed. + * @param string $group + * (optional) The group this message is in, which is displayed in a column + * in test output. Use 'Debug' to indicate this is debugging output. Do not + * translate this string. Defaults to 'Other'; most tests do not override + * this default. + * + * @return bool + * TRUE on pass, FALSE on fail. + */ + protected function assertNoFieldByXPath($xpath, $value = NULL, $message = '', $group = 'Other') { + $fields = $this->xpath($xpath); + + // If value specified then check array for match. + $found = TRUE; + if (isset($value)) { + $found = FALSE; + if ($fields) { + foreach ($fields as $field) { + if ($field['value'] == $value) { + $found = TRUE; + } + } + } + } + return $this->assertFalse($fields && $found, $message, $group); + } + + /** + * Asserts that a field exists with the given name and value. + * + * @param string $name + * Name of field to assert. + * @param string $value + * (optional) Value of the field to assert. You may pass in NULL (default) + * to skip checking the actual value, while still checking that the field + * exists. + * @param string $message + * (optional) A message to display with the assertion. Do not translate + * messages: use format_string() to embed variables in the message text, not + * t(). If left blank, a default message will be displayed. + * @param string $group + * (optional) The group this message is in, which is displayed in a column + * in test output. Use 'Debug' to indicate this is debugging output. Do not + * translate this string. Defaults to 'Browser'; most tests do not override + * this default. + * + * @return bool + * TRUE on pass, FALSE on fail. + */ + protected function assertFieldByName($name, $value = NULL, $message = NULL, $group = 'Browser') { + if (!isset($message)) { + if (!isset($value)) { + $message = String::format('Found field with name @name', array( + '@name' => var_export($name, TRUE), + )); + } + else { + $message = String::format('Found field with name @name and value @value', array( + '@name' => var_export($name, TRUE), + '@value' => var_export($value, TRUE), + )); + } + } + return $this->assertFieldByXPath($this->constructFieldXpath('name', $name), $value, $message, $group); + } + + /** + * Asserts that a field does not exist with the given name and value. + * + * @param string $name + * Name of field to assert. + * @param string $value + * (optional) Value for the field, to assert that the field's value on the + * page doesn't match it. You may pass in NULL to skip checking the + * value, while still checking that the field doesn't exist. However, the + * default value ('') asserts that the field value is not an empty string. + * @param string $message + * (optional) A message to display with the assertion. Do not translate + * messages: use format_string() to embed variables in the message text, not + * t(). If left blank, a default message will be displayed. + * @param string $group + * (optional) The group this message is in, which is displayed in a column + * in test output. Use 'Debug' to indicate this is debugging output. Do not + * translate this string. Defaults to 'Browser'; most tests do not override + * this default. + * + * @return bool + * TRUE on pass, FALSE on fail. + */ + protected function assertNoFieldByName($name, $value = '', $message = '', $group = 'Browser') { + return $this->assertNoFieldByXPath($this->constructFieldXpath('name', $name), $value, $message ? $message : String::format('Did not find field by name @name', array('@name' => $name)), $group); + } + + /** + * Asserts that a field exists with the given ID and value. + * + * @param string $id + * ID of field to assert. + * @param string $value + * (optional) Value for the field to assert. You may pass in NULL to skip + * checking the value, while still checking that the field exists. + * However, the default value ('') asserts that the field value is an empty + * string. + * @param string $message + * (optional) A message to display with the assertion. Do not translate + * messages: use format_string() to embed variables in the message text, not + * t(). If left blank, a default message will be displayed. + * @param string $group + * (optional) The group this message is in, which is displayed in a column + * in test output. Use 'Debug' to indicate this is debugging output. Do not + * translate this string. Defaults to 'Browser'; most tests do not override + * this default. + * + * @return bool + * TRUE on pass, FALSE on fail. + */ + protected function assertFieldById($id, $value = '', $message = '', $group = 'Browser') { + return $this->assertFieldByXPath($this->constructFieldXpath('id', $id), $value, $message ? $message : String::format('Found field by id @id', array('@id' => $id)), $group); + } + + /** + * Asserts that a field does not exist with the given ID and value. + * + * @param string $id + * ID of field to assert. + * @param string $value + * (optional) Value for the field, to assert that the field's value on the + * page doesn't match it. You may pass in NULL to skip checking the value, + * while still checking that the field doesn't exist. However, the default + * value ('') asserts that the field value is not an empty string. + * @param string $message + * (optional) A message to display with the assertion. Do not translate + * messages: use format_string() to embed variables in the message text, not + * t(). If left blank, a default message will be displayed. + * @param string $group + * (optional) The group this message is in, which is displayed in a column + * in test output. Use 'Debug' to indicate this is debugging output. Do not + * translate this string. Defaults to 'Browser'; most tests do not override + * this default. + * + * @return bool + * TRUE on pass, FALSE on fail. + */ + protected function assertNoFieldById($id, $value = '', $message = '', $group = 'Browser') { + return $this->assertNoFieldByXPath($this->constructFieldXpath('id', $id), $value, $message ? $message : String::format('Did not find field by id @id', array('@id' => $id)), $group); + } + + /** + * Asserts that a checkbox field in the current page is checked. + * + * @param string $id + * ID of field to assert. + * @param string $message + * (optional) A message to display with the assertion. Do not translate + * messages: use format_string() to embed variables in the message text, not + * t(). If left blank, a default message will be displayed. + * @param string $group + * (optional) The group this message is in, which is displayed in a column + * in test output. Use 'Debug' to indicate this is debugging output. Do not + * translate this string. Defaults to 'Browser'; most tests do not override + * this default. + * + * @return bool + * TRUE on pass, FALSE on fail. + */ + protected function assertFieldChecked($id, $message = '', $group = 'Browser') { + $elements = $this->xpath('//input[@id=:id]', array(':id' => $id)); + return $this->assertTrue(isset($elements[0]) && !empty($elements[0]['checked']), $message ? $message : String::format('Checkbox field @id is checked.', array('@id' => $id)), $group); + } + + /** + * Asserts that a checkbox field in the current page is not checked. + * + * @param string $id + * ID of field to assert. + * @param string $message + * (optional) A message to display with the assertion. Do not translate + * messages: use format_string() to embed variables in the message text, not + * t(). If left blank, a default message will be displayed. + * @param string $group + * (optional) The group this message is in, which is displayed in a column + * in test output. Use 'Debug' to indicate this is debugging output. Do not + * translate this string. Defaults to 'Browser'; most tests do not override + * this default. + * + * @return bool + * TRUE on pass, FALSE on fail. + */ + protected function assertNoFieldChecked($id, $message = '', $group = 'Browser') { + $elements = $this->xpath('//input[@id=:id]', array(':id' => $id)); + return $this->assertTrue(isset($elements[0]) && empty($elements[0]['checked']), $message ? $message : String::format('Checkbox field @id is not checked.', array('@id' => $id)), $group); + } + + /** + * Asserts that a select option in the current page exists. + * + * @param string $id + * ID of select field to assert. + * @param string $option + * Option to assert. + * @param string $message + * (optional) A message to display with the assertion. Do not translate + * messages: use format_string() to embed variables in the message text, not + * t(). If left blank, a default message will be displayed. + * @param string $group + * (optional) The group this message is in, which is displayed in a column + * in test output. Use 'Debug' to indicate this is debugging output. Do not + * translate this string. Defaults to 'Browser'; most tests do not override + * this default. + * + * @return bool + * TRUE on pass, FALSE on fail. + */ + protected function assertOption($id, $option, $message = '', $group = 'Browser') { + $options = $this->xpath('//select[@id=:id]/option[@value=:option]', array(':id' => $id, ':option' => $option)); + return $this->assertTrue(isset($options[0]), $message ? $message : String::format('Option @option for field @id exists.', array('@option' => $option, '@id' => $id)), $group); + } + + /** + * Asserts that a select option in the current page does not exist. + * + * @param string $id + * ID of select field to assert. + * @param string $option + * Option to assert. + * @param string $message + * (optional) A message to display with the assertion. Do not translate + * messages: use format_string() to embed variables in the message text, not + * t(). If left blank, a default message will be displayed. + * @param string $group + * (optional) The group this message is in, which is displayed in a column + * in test output. Use 'Debug' to indicate this is debugging output. Do not + * translate this string. Defaults to 'Browser'; most tests do not override + * this default. + * + * @return bool + * TRUE on pass, FALSE on fail. + */ + protected function assertNoOption($id, $option, $message = '', $group = 'Browser') { + $selects = $this->xpath('//select[@id=:id]', array(':id' => $id)); + $options = $this->xpath('//select[@id=:id]/option[@value=:option]', array(':id' => $id, ':option' => $option)); + return $this->assertTrue(isset($selects[0]) && !isset($options[0]), $message ? $message : String::format('Option @option for field @id does not exist.', array('@option' => $option, '@id' => $id)), $group); + } + + /** + * Asserts that a select option in the current page is checked. + * + * @param string $id + * ID of select field to assert. + * @param string $option + * Option to assert. + * @param string $message + * (optional) A message to display with the assertion. Do not translate + * messages: use format_string() to embed variables in the message text, not + * t(). If left blank, a default message will be displayed. + * @param string $group + * (optional) The group this message is in, which is displayed in a column + * in test output. Use 'Debug' to indicate this is debugging output. Do not + * translate this string. Defaults to 'Browser'; most tests do not override + * this default. + * + * @return bool + * TRUE on pass, FALSE on fail. + * + * @todo $id is unusable. Replace with $name. + */ + protected function assertOptionSelected($id, $option, $message = '', $group = 'Browser') { + $elements = $this->xpath('//select[@id=:id]//option[@value=:option]', array(':id' => $id, ':option' => $option)); + return $this->assertTrue(isset($elements[0]) && !empty($elements[0]['selected']), $message ? $message : String::format('Option @option for field @id is selected.', array('@option' => $option, '@id' => $id)), $group); + } + + /** + * Asserts that a select option in the current page is not checked. + * + * @param string $id + * ID of select field to assert. + * @param string $option + * Option to assert. + * @param string $message + * (optional) A message to display with the assertion. Do not translate + * messages: use format_string() to embed variables in the message text, not + * t(). If left blank, a default message will be displayed. + * @param string $group + * (optional) The group this message is in, which is displayed in a column + * in test output. Use 'Debug' to indicate this is debugging output. Do not + * translate this string. Defaults to 'Browser'; most tests do not override + * this default. + * + * @return bool + * TRUE on pass, FALSE on fail. + */ + protected function assertNoOptionSelected($id, $option, $message = '', $group = 'Browser') { + $elements = $this->xpath('//select[@id=:id]//option[@value=:option]', array(':id' => $id, ':option' => $option)); + return $this->assertTrue(isset($elements[0]) && empty($elements[0]['selected']), $message ? $message : String::format('Option @option for field @id is not selected.', array('@option' => $option, '@id' => $id)), $group); + } + + /** + * Asserts that a field exists with the given name or ID. + * + * @param string $field + * Name or ID of field to assert. + * @param string $message + * (optional) A message to display with the assertion. Do not translate + * messages: use format_string() to embed variables in the message text, not + * t(). If left blank, a default message will be displayed. + * @param string $group + * (optional) The group this message is in, which is displayed in a column + * in test output. Use 'Debug' to indicate this is debugging output. Do not + * translate this string. Defaults to 'Other'; most tests do not override + * this default. + * + * @return bool + * TRUE on pass, FALSE on fail. + */ + protected function assertField($field, $message = '', $group = 'Other') { + return $this->assertFieldByXPath($this->constructFieldXpath('name', $field) . '|' . $this->constructFieldXpath('id', $field), NULL, $message, $group); + } + + /** + * Asserts that a field does not exist with the given name or ID. + * + * @param string $field + * Name or ID of field to assert. + * @param string $message + * (optional) A message to display with the assertion. Do not translate + * messages: use format_string() to embed variables in the message text, not + * t(). If left blank, a default message will be displayed. + * @param string $group + * (optional) The group this message is in, which is displayed in a column + * in test output. Use 'Debug' to indicate this is debugging output. Do not + * translate this string. Defaults to 'Other'; most tests do not override + * this default. + * + * @return bool + * TRUE on pass, FALSE on fail. + */ + protected function assertNoField($field, $message = '', $group = 'Other') { + return $this->assertNoFieldByXPath($this->constructFieldXpath('name', $field) . '|' . $this->constructFieldXpath('id', $field), NULL, $message, $group); + } + + /** + * Asserts that each HTML ID is used for just a single element. + * + * @param string $message + * (optional) A message to display with the assertion. Do not translate + * messages: use format_string() to embed variables in the message text, not + * t(). If left blank, a default message will be displayed. + * @param string $group + * (optional) The group this message is in, which is displayed in a column + * in test output. Use 'Debug' to indicate this is debugging output. Do not + * translate this string. Defaults to 'Other'; most tests do not override + * this default. + * @param array $ids_to_skip + * An optional array of ids to skip when checking for duplicates. It is + * always a bug to have duplicate HTML IDs, so this parameter is to enable + * incremental fixing of core code. Whenever a test passes this parameter, + * it should add a "todo" comment above the call to this function explaining + * the legacy bug that the test wishes to ignore and including a link to an + * issue that is working to fix that legacy bug. + * + * @return bool + * TRUE on pass, FALSE on fail. + */ + protected function assertNoDuplicateIds($message = '', $group = 'Other', $ids_to_skip = array()) { + $status = TRUE; + foreach ($this->xpath('//*[@id]') as $element) { + $id = (string) $element['id']; + if (isset($seen_ids[$id]) && !in_array($id, $ids_to_skip)) { + $this->fail(String::format('The HTML ID %id is unique.', array('%id' => $id)), $group); + $status = FALSE; + } + $seen_ids[$id] = TRUE; + } + return $this->assert($status, $message, $group); + } + + /** + * Helper: Constructs an XPath for the given set of attributes and value. + * + * @param string $attribute + * Field attributes. + * @param string $value + * Value of field. + * + * @return string + * XPath for specified values. + */ + protected function constructFieldXpath($attribute, $value) { + $xpath = '//textarea[@' . $attribute . '=:value]|//input[@' . $attribute . '=:value]|//select[@' . $attribute . '=:value]'; + return $this->buildXPathQuery($xpath, array(':value' => $value)); + } + +} diff --git a/core/modules/simpletest/src/KernelTestBase.php b/core/modules/simpletest/src/KernelTestBase.php index 65489f85c8ceda323fc3a475638ce9259c256aa4..4e6c0e2de39b8b4c7a0f58a4e1c28e05022daa71 100644 --- a/core/modules/simpletest/src/KernelTestBase.php +++ b/core/modules/simpletest/src/KernelTestBase.php @@ -36,6 +36,8 @@ */ abstract class KernelTestBase extends UnitTestBase { + use AssertContentTrait; + /** * Modules to enable. * @@ -534,4 +536,20 @@ protected function unregisterStreamWrapper($scheme, $type) { } } + /** + * Renders a render array. + * + * @param array $elements + * The elements to render. + * + * @return string + * The rendered string output (typically HTML). + */ + protected function render(array $elements) { + $content = drupal_render($elements); + $this->setRawContent($content); + $this->verbose('<pre style="white-space: pre-wrap">' . String::checkPlain($content)); + return $content; + } + } diff --git a/core/modules/simpletest/src/WebTestBase.php b/core/modules/simpletest/src/WebTestBase.php index 33c04b87b1da4fc7de866126c4265a1eb12e68e7..cb1fe970b4c4d504b8569838254506e8c6a12665 100644 --- a/core/modules/simpletest/src/WebTestBase.php +++ b/core/modules/simpletest/src/WebTestBase.php @@ -11,7 +11,6 @@ use Drupal\Component\Utility\Crypt; use Drupal\Component\Utility\NestedArray; use Drupal\Component\Utility\String; -use Drupal\Component\Utility\Xss; use Drupal\Core\DrupalKernel; use Drupal\Core\Database\Database; use Drupal\Core\Database\ConnectionNotDefinedException; @@ -25,7 +24,6 @@ use Drupal\Core\Datetime\DrupalDateTime; use Drupal\block\Entity\Block; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\CssSelector\CssSelector; /** * Test case for typical Drupal tests. @@ -34,6 +32,8 @@ */ abstract class WebTestBase extends TestBase { + use AssertContentTrait; + /** * The profile to install as a basis for testing. * @@ -72,36 +72,6 @@ abstract class WebTestBase extends TestBase { */ protected $dumpHeaders = FALSE; - /** - * The content of the page currently loaded in the internal browser. - * - * @var string - */ - protected $content; - - /** - * The plain-text content of the currently-loaded page. - * - * @var string - */ - protected $plainTextContent; - - /** - * The value of drupalSettings for the currently-loaded page. - * - * drupalSettings refers to the drupalSettings JavaScript variable. - * - * @var Array - */ - protected $drupalSettings; - - /** - * The parsed version of the page. - * - * @var \SimpleXMLElement - */ - protected $elements = NULL; - /** * The current user logged in using the internal browser. * @@ -1369,16 +1339,18 @@ protected function curlExec($curl_options, $redirect = FALSE) { } } - $this->drupalSetContent($content, isset($original_url) ? $original_url : curl_getinfo($this->curlHandle, CURLINFO_EFFECTIVE_URL)); + $this->setRawContent($content); + $this->url = isset($original_url) ? $original_url : curl_getinfo($this->curlHandle, CURLINFO_EFFECTIVE_URL); + $message_vars = array( '!method' => !empty($curl_options[CURLOPT_NOBODY]) ? 'HEAD' : (empty($curl_options[CURLOPT_POSTFIELDS]) ? 'GET' : 'POST'), '@url' => isset($original_url) ? $original_url : $url, '@status' => $status, - '!length' => format_size(strlen($this->drupalGetContent())) + '!length' => format_size(strlen($this->getRawContent())) ); $message = String::format('!method @url returned @status (!length).', $message_vars); - $this->assertTrue($this->drupalGetContent() !== FALSE, $message, 'Browser'); - return $this->drupalGetContent(); + $this->assertTrue($this->getRawContent() !== FALSE, $message, 'Browser'); + return $this->getRawContent(); } /** @@ -1457,32 +1429,6 @@ protected function isInChildSite() { return DRUPAL_TEST_IN_CHILD_SITE; } - /** - * Parse content returned from curlExec using DOM and SimpleXML. - * - * @return - * A SimpleXMLElement or FALSE on failure. - */ - protected function parse() { - if (!$this->elements) { - // DOM can load HTML soup. But, HTML soup can throw warnings, suppress - // them. - $htmlDom = new \DOMDocument(); - @$htmlDom->loadHTML('<?xml encoding="UTF-8">' . $this->drupalGetContent()); - if ($htmlDom) { - $this->pass(String::format('Valid HTML found on "@path"', array('@path' => $this->getUrl())), 'Browser'); - // It's much easier to work with simplexml than DOM, luckily enough - // we can just simply import our DOM tree. - $this->elements = simplexml_import_dom($htmlDom); - } - } - if (!$this->elements) { - $this->fail('Parsed page successfully.', 'Browser'); - } - - return $this->elements; - } - /** * Retrieves a Drupal path or an absolute path. * @@ -1495,7 +1441,7 @@ protected function parse() { * "name: value". * * @return - * The retrieved HTML string, also available as $this->drupalGetContent() + * The retrieved HTML string, also available as $this->getRawContent() */ protected function drupalGet($path, array $options = array(), array $headers = array()) { $options['absolute'] = TRUE; @@ -1956,8 +1902,8 @@ protected function drupalProcessAjaxResponse($content, array $ajax_response, arr } } $content = $dom->saveHTML(); - $this->drupalSetContent($content); - $this->drupalSetSettings($drupal_settings); + $this->setRawContent($content); + $this->setDrupalSettings($drupal_settings); } /** @@ -2077,7 +2023,7 @@ protected function cronRun() { * Either the new page content or FALSE. */ protected function checkForMetaRefresh() { - if (strpos($this->drupalGetContent(), '<meta ') && $this->parse()) { + if (strpos($this->getRawContent(), '<meta ') && $this->parse()) { $refresh = $this->xpath('//meta[@http-equiv="Refresh"]'); if (!empty($refresh)) { // Parse the content attribute of the meta tag for the format: @@ -2102,7 +2048,7 @@ protected function checkForMetaRefresh() { * "name: value". * * @return - * The retrieved headers, also available as $this->drupalGetContent() + * The retrieved headers, also available as $this->getRawContent() */ protected function drupalHead($path, array $options = array(), array $headers = array()) { $options['absolute'] = TRUE; @@ -2281,229 +2227,6 @@ protected function handleForm(&$post, &$edit, &$upload, $submit, $form) { return $submit_matches; } - /** - * Builds an XPath query. - * - * Builds an XPath query by replacing placeholders in the query by the value - * of the arguments. - * - * XPath 1.0 (the version supported by libxml2, the underlying XML library - * used by PHP) doesn't support any form of quotation. This function - * simplifies the building of XPath expression. - * - * @param string $xpath - * An XPath query, possibly with placeholders in the form ':name'. - * @param array $args - * An array of arguments with keys in the form ':name' matching the - * placeholders in the query. The values may be either strings or numeric - * values. - * - * @return string - * An XPath query with arguments replaced. - */ - protected function buildXPathQuery($xpath, array $args = array()) { - // Replace placeholders. - foreach ($args as $placeholder => $value) { - // XPath 1.0 doesn't support a way to escape single or double quotes in a - // string literal. We split double quotes out of the string, and encode - // them separately. - if (is_string($value)) { - // Explode the text at the quote characters. - $parts = explode('"', $value); - - // Quote the parts. - foreach ($parts as &$part) { - $part = '"' . $part . '"'; - } - - // Return the string. - $value = count($parts) > 1 ? 'concat(' . implode(', \'"\', ', $parts) . ')' : $parts[0]; - } - - // Use preg_replace_callback() instead of preg_replace() to prevent the - // regular expression engine from trying to substitute backreferences. - $replacement = function ($matches) use ($value) { - return $value; - }; - $xpath = preg_replace_callback('/' . preg_quote($placeholder) . '\b/', $replacement, $xpath); - } - return $xpath; - } - - /** - * Performs an xpath search on the contents of the internal browser. - * - * The search is relative to the root element (HTML tag normally) of the page. - * - * @param string $xpath - * The xpath string to use in the search. - * @param array $arguments - * An array of arguments with keys in the form ':name' matching the - * placeholders in the query. The values may be either strings or numeric - * values. - * - * @return array - * The return value of the xpath search. For details on the xpath string - * format and return values see the SimpleXML documentation, - * http://php.net/manual/function.simplexml-element-xpath.php. - */ - protected function xpath($xpath, array $arguments = array()) { - if ($this->parse()) { - $xpath = $this->buildXPathQuery($xpath, $arguments); - $result = $this->elements->xpath($xpath); - // Some combinations of PHP / libxml versions return an empty array - // instead of the documented FALSE. Forcefully convert any falsish values - // to an empty array to allow foreach(...) constructions. - return $result ? $result : array(); - } - else { - return FALSE; - } - } - - /** - * Performs a CSS selection based search on the contents of the internal - * browser. The search is relative to the root element (HTML tag normally) of - * the page. - * - * @param $selector string - * CSS selector to use in the search. - * - * @return \SimpleXMLElement - * The return value of the xpath search performed after converting the css - * selector to an XPath selector. - */ - protected function cssSelect($selector) { - return $this->xpath(CssSelector::toXPath($selector)); - } - - /** - * Get all option elements, including nested options, in a select. - * - * @param $element - * The element for which to get the options. - * - * @return - * Option elements in select. - */ - protected function getAllOptions(\SimpleXMLElement $element) { - $options = array(); - // Add all options items. - foreach ($element->option as $option) { - $options[] = $option; - } - - // Search option group children. - if (isset($element->optgroup)) { - foreach ($element->optgroup as $group) { - $options = array_merge($options, $this->getAllOptions($group)); - } - } - return $options; - } - - /** - * Passes if a link with the specified label is found. - * - * An optional link index may be passed. - * - * @param $label - * Text between the anchor tags. - * @param $index - * Link position counting from zero. - * @param $message - * (optional) A message to display with the assertion. Do not translate - * messages: use format_string() to embed variables in the message text, not - * t(). If left blank, a default message will be displayed. - * @param $group - * (optional) The gorup this message is in, which is displayed in a column - * in test output. Use 'Debug' to indicate this is debugging output. Do not - * translate this string. Defaults to 'Other'; most tests do not override - * this default. - * - * @return - * TRUE if the assertion succeeded, FALSE otherwise. - */ - protected function assertLink($label, $index = 0, $message = '', $group = 'Other') { - $links = $this->xpath('//a[normalize-space(text())=:label]', array(':label' => $label)); - $message = ($message ? $message : String::format('Link with label %label found.', array('%label' => $label))); - return $this->assert(isset($links[$index]), $message, $group); - } - - /** - * Passes if a link with the specified label is not found. - * - * @param $label - * Text between the anchor tags. - * @param $message - * (optional) A message to display with the assertion. Do not translate - * messages: use format_string() to embed variables in the message text, not - * t(). If left blank, a default message will be displayed. - * @param $group - * (optional) The group this message is in, which is displayed in a column - * in test output. Use 'Debug' to indicate this is debugging output. Do not - * translate this string. Defaults to 'Other'; most tests do not override - * this default. - * - * @return - * TRUE if the assertion succeeded, FALSE otherwise. - */ - protected function assertNoLink($label, $message = '', $group = 'Other') { - $links = $this->xpath('//a[normalize-space(text())=:label]', array(':label' => $label)); - $message = ($message ? $message : String::format('Link with label %label not found.', array('%label' => $label))); - return $this->assert(empty($links), $message, $group); - } - - /** - * Passes if a link containing a given href (part) is found. - * - * @param $href - * The full or partial value of the 'href' attribute of the anchor tag. - * @param $index - * Link position counting from zero. - * @param $message - * (optional) A message to display with the assertion. Do not translate - * messages: use format_string() to embed variables in the message text, not - * t(). If left blank, a default message will be displayed. - * @param $group - * (optional) The group this message is in, which is displayed in a column - * in test output. Use 'Debug' to indicate this is debugging output. Do not - * translate this string. Defaults to 'Other'; most tests do not override - * this default. - * - * @return - * TRUE if the assertion succeeded, FALSE otherwise. - */ - protected function assertLinkByHref($href, $index = 0, $message = '', $group = 'Other') { - $links = $this->xpath('//a[contains(@href, :href)]', array(':href' => $href)); - $message = ($message ? $message : String::format('Link containing href %href found.', array('%href' => $href))); - return $this->assert(isset($links[$index]), $message, $group); - } - - /** - * Passes if a link containing a given href (part) is not found. - * - * @param $href - * The full or partial value of the 'href' attribute of the anchor tag. - * @param $message - * (optional) A message to display with the assertion. Do not translate - * messages: use format_string() to embed variables in the message text, not - * t(). If left blank, a default message will be displayed. - * @param $group - * (optional) The group this message is in, which is displayed in a column - * in test output. Use 'Debug' to indicate this is debugging output. Do not - * translate this string. Defaults to 'Other'; most tests do not override - * this default. - * - * @return - * TRUE if the assertion succeeded, FALSE otherwise. - */ - protected function assertNoLinkByHref($href, $message = '', $group = 'Other') { - $links = $this->xpath('//a[contains(@href, :href)]', array(':href' => $href)); - $message = ($message ? $message : String::format('No link containing href %href found.', array('%href' => $href))); - return $this->assert(empty($links), $message, $group); - } - /** * Follows a link by name. * @@ -2666,18 +2389,22 @@ protected function drupalGetHeader($name, $all_requests = FALSE) { /** * Gets the current raw HTML of requested page. + * + * @deprecated 8.x + * Use getRawContent(). */ protected function drupalGetContent() { - return $this->content; + return $this->getRawContent(); } /** * Gets the value of drupalSettings for the currently-loaded page. * - * drupalSettings refers to the drupalSettings JavaScript variable. + * @deprecated 8.x + * Use getDrupalSettings(). */ protected function drupalGetSettings() { - return $this->drupalSettings; + return $this->getDrupalSettings(); } /** @@ -2709,31 +2436,21 @@ protected function drupalGetMails($filter = array()) { /** * Sets the raw HTML content. * - * This can be useful when a page has been fetched outside of the internal - * browser and assertions need to be made on the returned page. - * - * A good example would be when testing HTTP request made by Drupal. After - * fetching the page the content can be set and page elements can be checked - * to ensure that the function worked properly. + * @deprecated 8.x + * Use setRawContent(). */ - protected function drupalSetContent($content, $url = 'internal:') { - $this->content = $content; - $this->url = $url; - $this->plainTextContent = FALSE; - $this->elements = FALSE; - $this->drupalSettings = array(); - if (preg_match('/var drupalSettings = (.*?);$/m', $content, $matches)) { - $this->drupalSettings = Json::decode($matches[1]); - } + protected function drupalSetContent($content) { + $this->setRawContent($content); } /** * Sets the value of drupalSettings for the currently-loaded page. * - * drupalSettings refers to the drupalSettings JavaScript variable. + * @deprecated 8.x + * Use setDrupalSettings(). */ protected function drupalSetSettings($settings) { - $this->drupalSettings = $settings; + $this->setDrupalSettings($settings); } /** @@ -2770,865 +2487,6 @@ protected function assertUrl($path, array $options = array(), $message = '', $gr return $this->assertEqual($actual_url, $expected_url, $message, $group); } - /** - * Passes if the raw text IS found on the loaded page, fail otherwise. - * - * Raw text refers to the raw HTML that the page generated. - * - * @param $raw - * Raw (HTML) string to look for. - * @param $message - * (optional) A message to display with the assertion. Do not translate - * messages: use format_string() to embed variables in the message text, not - * t(). If left blank, a default message will be displayed. - * @param $group - * (optional) The group this message is in, which is displayed in a column - * in test output. Use 'Debug' to indicate this is debugging output. Do not - * translate this string. Defaults to 'Other'; most tests do not override - * this default. - * - * @return - * TRUE on pass, FALSE on fail. - */ - protected function assertRaw($raw, $message = '', $group = 'Other') { - if (!$message) { - $message = String::format('Raw "@raw" found', array('@raw' => $raw)); - } - return $this->assert(strpos($this->drupalGetContent(), $raw) !== FALSE, $message, $group); - } - - /** - * Passes if the raw text is NOT found on the loaded page, fail otherwise. - * - * Raw text refers to the raw HTML that the page generated. - * - * @param $raw - * Raw (HTML) string to look for. - * @param $message - * (optional) A message to display with the assertion. Do not translate - * messages: use format_string() to embed variables in the message text, not - * t(). If left blank, a default message will be displayed. - * @param $group - * (optional) The group this message is in, which is displayed in a column - * in test output. Use 'Debug' to indicate this is debugging output. Do not - * translate this string. Defaults to 'Other'; most tests do not override - * this default. - * - * @return - * TRUE on pass, FALSE on fail. - */ - protected function assertNoRaw($raw, $message = '', $group = 'Other') { - if (!$message) { - $message = String::format('Raw "@raw" not found', array('@raw' => $raw)); - } - return $this->assert(strpos($this->drupalGetContent(), $raw) === FALSE, $message, $group); - } - - /** - * Passes if the text IS found on the text version of the page. - * - * The text version is the equivalent of what a user would see when viewing - * through a web browser. In other words the HTML has been filtered out of the - * contents. - * - * @param $text - * Plain text to look for. - * @param $message - * (optional) A message to display with the assertion. Do not translate - * messages: use format_string() to embed variables in the message text, not - * t(). If left blank, a default message will be displayed. - * @param $group - * (optional) The group this message is in, which is displayed in a column - * in test output. Use 'Debug' to indicate this is debugging output. Do not - * translate this string. Defaults to 'Other'; most tests do not override - * this default. - * - * @return - * TRUE on pass, FALSE on fail. - */ - protected function assertText($text, $message = '', $group = 'Other') { - return $this->assertTextHelper($text, $message, $group, FALSE); - } - - /** - * Passes if the text is NOT found on the text version of the page. - * - * The text version is the equivalent of what a user would see when viewing - * through a web browser. In other words the HTML has been filtered out of the - * contents. - * - * @param $text - * Plain text to look for. - * @param $message - * (optional) A message to display with the assertion. Do not translate - * messages: use format_string() to embed variables in the message text, not - * t(). If left blank, a default message will be displayed. - * @param $group - * (optional) The group this message is in, which is displayed in a column - * in test output. Use 'Debug' to indicate this is debugging output. Do not - * translate this string. Defaults to 'Other'; most tests do not override - * this default. - * - * @return - * TRUE on pass, FALSE on fail. - */ - protected function assertNoText($text, $message = '', $group = 'Other') { - return $this->assertTextHelper($text, $message, $group, TRUE); - } - - /** - * Helper for assertText and assertNoText. - * - * It is not recommended to call this function directly. - * - * @param $text - * Plain text to look for. - * @param $message - * (optional) A message to display with the assertion. Do not translate - * messages: use format_string() to embed variables in the message text, not - * t(). If left blank, a default message will be displayed. - * @param $group - * The group this message is in, which is displayed in a column - * in test output. Use 'Debug' to indicate this is debugging output. Do not - * translate this string. Defaults to 'Other'; most tests do not override - * this default. - * @param $not_exists - * TRUE if this text should not exist, FALSE if it should. - * - * @return - * TRUE on pass, FALSE on fail. - */ - protected function assertTextHelper($text, $message = '', $group, $not_exists) { - if ($this->plainTextContent === FALSE) { - $this->plainTextContent = Xss::filter($this->drupalGetContent(), array()); - } - if (!$message) { - $message = !$not_exists ? String::format('"@text" found', array('@text' => $text)) : String::format('"@text" not found', array('@text' => $text)); - } - return $this->assert($not_exists == (strpos($this->plainTextContent, (string) $text) === FALSE), $message, $group); - } - - /** - * Passes if the text is found ONLY ONCE on the text version of the page. - * - * The text version is the equivalent of what a user would see when viewing - * through a web browser. In other words the HTML has been filtered out of - * the contents. - * - * @param $text - * Plain text to look for. - * @param $message - * (optional) A message to display with the assertion. Do not translate - * messages: use format_string() to embed variables in the message text, not - * t(). If left blank, a default message will be displayed. - * @param $group - * (optional) The group this message is in, which is displayed in a column - * in test output. Use 'Debug' to indicate this is debugging output. Do not - * translate this string. Defaults to 'Other'; most tests do not override - * this default. - * - * @return - * TRUE on pass, FALSE on fail. - */ - protected function assertUniqueText($text, $message = '', $group = 'Other') { - return $this->assertUniqueTextHelper($text, $message, $group, TRUE); - } - - /** - * Passes if the text is found MORE THAN ONCE on the text version of the page. - * - * The text version is the equivalent of what a user would see when viewing - * through a web browser. In other words the HTML has been filtered out of - * the contents. - * - * @param $text - * Plain text to look for. - * @param $message - * (optional) A message to display with the assertion. Do not translate - * messages: use format_string() to embed variables in the message text, not - * t(). If left blank, a default message will be displayed. - * @param $group - * (optional) The group this message is in, which is displayed in a column - * in test output. Use 'Debug' to indicate this is debugging output. Do not - * translate this string. Defaults to 'Other'; most tests do not override - * this default. - * - * @return - * TRUE on pass, FALSE on fail. - */ - protected function assertNoUniqueText($text, $message = '', $group = 'Other') { - return $this->assertUniqueTextHelper($text, $message, $group, FALSE); - } - - /** - * Helper for assertUniqueText and assertNoUniqueText. - * - * It is not recommended to call this function directly. - * - * @param $text - * Plain text to look for. - * @param $message - * (optional) A message to display with the assertion. Do not translate - * messages: use format_string() to embed variables in the message text, not - * t(). If left blank, a default message will be displayed. - * @param $group - * The group this message is in, which is displayed in a column - * in test output. Use 'Debug' to indicate this is debugging output. Do not - * translate this string. Defaults to 'Other'; most tests do not override - * this default. - * @param $be_unique - * TRUE if this text should be found only once, FALSE if it should be found - * more than once. - * - * @return - * TRUE on pass, FALSE on fail. - */ - protected function assertUniqueTextHelper($text, $message = '', $group, $be_unique) { - if ($this->plainTextContent === FALSE) { - $this->plainTextContent = Xss::filter($this->drupalGetContent(), array()); - } - if (!$message) { - $message = '"' . $text . '"' . ($be_unique ? ' found only once' : ' found more than once'); - } - $first_occurance = strpos($this->plainTextContent, $text); - if ($first_occurance === FALSE) { - return $this->assert(FALSE, $message, $group); - } - $offset = $first_occurance + strlen($text); - $second_occurance = strpos($this->plainTextContent, $text, $offset); - return $this->assert($be_unique == ($second_occurance === FALSE), $message, $group); - } - - /** - * Triggers a pass if the Perl regex pattern is found in the raw content. - * - * @param $pattern - * Perl regex to look for including the regex delimiters. - * @param $message - * (optional) A message to display with the assertion. Do not translate - * messages: use format_string() to embed variables in the message text, not - * t(). If left blank, a default message will be displayed. - * @param $group - * (optional) The group this message is in, which is displayed in a column - * in test output. Use 'Debug' to indicate this is debugging output. Do not - * translate this string. Defaults to 'Other'; most tests do not override - * this default. - * - * @return - * TRUE on pass, FALSE on fail. - */ - protected function assertPattern($pattern, $message = '', $group = 'Other') { - if (!$message) { - $message = String::format('Pattern "@pattern" found', array('@pattern' => $pattern)); - } - return $this->assert((bool) preg_match($pattern, $this->drupalGetContent()), $message, $group); - } - - /** - * Triggers a pass if the perl regex pattern is not found in raw content. - * - * @param $pattern - * Perl regex to look for including the regex delimiters. - * @param $message - * (optional) A message to display with the assertion. Do not translate - * messages: use format_string() to embed variables in the message text, not - * t(). If left blank, a default message will be displayed. - * @param $group - * (optional) The group this message is in, which is displayed in a column - * in test output. Use 'Debug' to indicate this is debugging output. Do not - * translate this string. Defaults to 'Other'; most tests do not override - * this default. - * - * @return - * TRUE on pass, FALSE on fail. - */ - protected function assertNoPattern($pattern, $message = '', $group = 'Other') { - if (!$message) { - $message = String::format('Pattern "@pattern" not found', array('@pattern' => $pattern)); - } - return $this->assert(!preg_match($pattern, $this->drupalGetContent()), $message, $group); - } - - /** - * Pass if the page title is the given string. - * - * @param $title - * The string the title should be. - * @param $message - * (optional) A message to display with the assertion. Do not translate - * messages: use format_string() to embed variables in the message text, not - * t(). If left blank, a default message will be displayed. - * @param $group - * (optional) The group this message is in, which is displayed in a column - * in test output. Use 'Debug' to indicate this is debugging output. Do not - * translate this string. Defaults to 'Other'; most tests do not override - * this default. - * - * @return - * TRUE on pass, FALSE on fail. - */ - protected function assertTitle($title, $message = '', $group = 'Other') { - $actual = (string) current($this->xpath('//title')); - if (!$message) { - $message = String::format('Page title @actual is equal to @expected.', array( - '@actual' => var_export($actual, TRUE), - '@expected' => var_export($title, TRUE), - )); - } - return $this->assertEqual($actual, $title, $message, $group); - } - - /** - * Pass if the page title is not the given string. - * - * @param $title - * The string the title should not be. - * @param $message - * (optional) A message to display with the assertion. Do not translate - * messages: use format_string() to embed variables in the message text, not - * t(). If left blank, a default message will be displayed. - * @param $group - * (optional) The group this message is in, which is displayed in a column - * in test output. Use 'Debug' to indicate this is debugging output. Do not - * translate this string. Defaults to 'Other'; most tests do not override - * this default. - * - * @return - * TRUE on pass, FALSE on fail. - */ - protected function assertNoTitle($title, $message = '', $group = 'Other') { - $actual = (string) current($this->xpath('//title')); - if (!$message) { - $message = String::format('Page title @actual is not equal to @unexpected.', array( - '@actual' => var_export($actual, TRUE), - '@unexpected' => var_export($title, TRUE), - )); - } - return $this->assertNotEqual($actual, $title, $message, $group); - } - - /** - * Asserts themed output. - * - * @param $callback - * The name of the theme hook to invoke; e.g. 'links' for links.html.twig. - * @param $variables - * An array of variables to pass to the theme function. - * @param $expected - * The expected themed output string. - * @param $message - * (optional) A message to display with the assertion. Do not translate - * messages: use format_string() to embed variables in the message text, not - * t(). If left blank, a default message will be displayed. - * @param $group - * (optional) The group this message is in, which is displayed in a column - * in test output. Use 'Debug' to indicate this is debugging output. Do not - * translate this string. Defaults to 'Other'; most tests do not override - * this default. - * - * @return - * TRUE on pass, FALSE on fail. - */ - protected function assertThemeOutput($callback, array $variables = array(), $expected, $message = '', $group = 'Other') { - $output = _theme($callback, $variables); - $this->verbose('Variables:' . '<pre>' . String::checkPlain(var_export($variables, TRUE)) . '</pre>' - . '<hr />' . 'Result:' . '<pre>' . String::checkPlain(var_export($output, TRUE)) . '</pre>' - . '<hr />' . 'Expected:' . '<pre>' . String::checkPlain(var_export($expected, TRUE)) . '</pre>' - . '<hr />' . $output - ); - if (!$message) { - $message = '%callback rendered correctly.'; - } - $message = format_string($message, array('%callback' => 'theme_' . $callback . '()')); - return $this->assertIdentical($output, $expected, $message, $group); - } - - /** - * Asserts that a field exists in the current page by the given XPath. - * - * @param $xpath - * XPath used to find the field. - * @param $value - * (optional) Value of the field to assert. You may pass in NULL (default) - * to skip checking the actual value, while still checking that the field - * exists. - * @param $message - * (optional) A message to display with the assertion. Do not translate - * messages: use format_string() to embed variables in the message text, not - * t(). If left blank, a default message will be displayed. - * @param $group - * (optional) The group this message is in, which is displayed in a column - * in test output. Use 'Debug' to indicate this is debugging output. Do not - * translate this string. Defaults to 'Other'; most tests do not override - * this default. - * - * @return - * TRUE on pass, FALSE on fail. - */ - protected function assertFieldByXPath($xpath, $value = NULL, $message = '', $group = 'Other') { - $fields = $this->xpath($xpath); - - // If value specified then check array for match. - $found = TRUE; - if (isset($value)) { - $found = FALSE; - if ($fields) { - foreach ($fields as $field) { - if (isset($field['value']) && $field['value'] == $value) { - // Input element with correct value. - $found = TRUE; - } - elseif (isset($field->option) || isset($field->optgroup)) { - // Select element found. - $selected = $this->getSelectedItem($field); - if ($selected === FALSE) { - // No item selected so use first item. - $items = $this->getAllOptions($field); - if (!empty($items) && $items[0]['value'] == $value) { - $found = TRUE; - } - } - elseif ($selected == $value) { - $found = TRUE; - } - } - elseif ((string) $field == $value) { - // Text area with correct text. - $found = TRUE; - } - } - } - } - return $this->assertTrue($fields && $found, $message, $group); - } - - /** - * Get the selected value from a select field. - * - * @param $element - * SimpleXMLElement select element. - * - * @return - * The selected value or FALSE. - */ - protected function getSelectedItem(\SimpleXMLElement $element) { - foreach ($element->children() as $item) { - if (isset($item['selected'])) { - return $item['value']; - } - elseif ($item->getName() == 'optgroup') { - if ($value = $this->getSelectedItem($item)) { - return $value; - } - } - } - return FALSE; - } - - /** - * Asserts that a field doesn't exist or its value doesn't match, by XPath. - * - * @param $xpath - * XPath used to find the field. - * @param $value - * (optional) Value for the field, to assert that the field's value on the - * page doesn't match it. - * @param $message - * (optional) A message to display with the assertion. Do not translate - * messages: use format_string() to embed variables in the message text, not - * t(). If left blank, a default message will be displayed. - * @param $group - * (optional) The group this message is in, which is displayed in a column - * in test output. Use 'Debug' to indicate this is debugging output. Do not - * translate this string. Defaults to 'Other'; most tests do not override - * this default. - * - * @return - * TRUE on pass, FALSE on fail. - */ - protected function assertNoFieldByXPath($xpath, $value = NULL, $message = '', $group = 'Other') { - $fields = $this->xpath($xpath); - - // If value specified then check array for match. - $found = TRUE; - if (isset($value)) { - $found = FALSE; - if ($fields) { - foreach ($fields as $field) { - if ($field['value'] == $value) { - $found = TRUE; - } - } - } - } - return $this->assertFalse($fields && $found, $message, $group); - } - - /** - * Asserts that a field exists with the given name and value. - * - * @param $name - * Name of field to assert. - * @param $value - * (optional) Value of the field to assert. You may pass in NULL (default) - * to skip checking the actual value, while still checking that the field - * exists. - * @param $message - * (optional) A message to display with the assertion. Do not translate - * messages: use format_string() to embed variables in the message text, not - * t(). If left blank, a default message will be displayed. - * @param $group - * (optional) The group this message is in, which is displayed in a column - * in test output. Use 'Debug' to indicate this is debugging output. Do not - * translate this string. Defaults to 'Browser'; most tests do not override - * this default. - * - * @return - * TRUE on pass, FALSE on fail. - */ - protected function assertFieldByName($name, $value = NULL, $message = NULL, $group = 'Browser') { - if (!isset($message)) { - if (!isset($value)) { - $message = String::format('Found field with name @name', array( - '@name' => var_export($name, TRUE), - )); - } - else { - $message = String::format('Found field with name @name and value @value', array( - '@name' => var_export($name, TRUE), - '@value' => var_export($value, TRUE), - )); - } - } - return $this->assertFieldByXPath($this->constructFieldXpath('name', $name), $value, $message, $group); - } - - /** - * Asserts that a field does not exist with the given name and value. - * - * @param $name - * Name of field to assert. - * @param $value - * (optional) Value for the field, to assert that the field's value on the - * page doesn't match it. You may pass in NULL to skip checking the - * value, while still checking that the field doesn't exist. However, the - * default value ('') asserts that the field value is not an empty string. - * @param $message - * (optional) A message to display with the assertion. Do not translate - * messages: use format_string() to embed variables in the message text, not - * t(). If left blank, a default message will be displayed. - * @param $group - * (optional) The group this message is in, which is displayed in a column - * in test output. Use 'Debug' to indicate this is debugging output. Do not - * translate this string. Defaults to 'Browser'; most tests do not override - * this default. - * - * @return - * TRUE on pass, FALSE on fail. - */ - protected function assertNoFieldByName($name, $value = '', $message = '', $group = 'Browser') { - return $this->assertNoFieldByXPath($this->constructFieldXpath('name', $name), $value, $message ? $message : String::format('Did not find field by name @name', array('@name' => $name)), $group); - } - - /** - * Asserts that a field exists with the given ID and value. - * - * @param $id - * ID of field to assert. - * @param $value - * (optional) Value for the field to assert. You may pass in NULL to skip - * checking the value, while still checking that the field exists. - * However, the default value ('') asserts that the field value is an empty - * string. - * @param $message - * (optional) A message to display with the assertion. Do not translate - * messages: use format_string() to embed variables in the message text, not - * t(). If left blank, a default message will be displayed. - * @param $group - * (optional) The group this message is in, which is displayed in a column - * in test output. Use 'Debug' to indicate this is debugging output. Do not - * translate this string. Defaults to 'Browser'; most tests do not override - * this default. - * - * @return - * TRUE on pass, FALSE on fail. - */ - protected function assertFieldById($id, $value = '', $message = '', $group = 'Browser') { - return $this->assertFieldByXPath($this->constructFieldXpath('id', $id), $value, $message ? $message : String::format('Found field by id @id', array('@id' => $id)), $group); - } - - /** - * Asserts that a field does not exist with the given ID and value. - * - * @param $id - * ID of field to assert. - * @param $value - * (optional) Value for the field, to assert that the field's value on the - * page doesn't match it. You may pass in NULL to skip checking the value, - * while still checking that the field doesn't exist. However, the default - * value ('') asserts that the field value is not an empty string. - * @param $message - * (optional) A message to display with the assertion. Do not translate - * messages: use format_string() to embed variables in the message text, not - * t(). If left blank, a default message will be displayed. - * @param $group - * (optional) The group this message is in, which is displayed in a column - * in test output. Use 'Debug' to indicate this is debugging output. Do not - * translate this string. Defaults to 'Browser'; most tests do not override - * this default. - * - * @return - * TRUE on pass, FALSE on fail. - */ - protected function assertNoFieldById($id, $value = '', $message = '', $group = 'Browser') { - return $this->assertNoFieldByXPath($this->constructFieldXpath('id', $id), $value, $message ? $message : String::format('Did not find field by id @id', array('@id' => $id)), $group); - } - - /** - * Asserts that a checkbox field in the current page is checked. - * - * @param $id - * ID of field to assert. - * @param $message - * (optional) A message to display with the assertion. Do not translate - * messages: use format_string() to embed variables in the message text, not - * t(). If left blank, a default message will be displayed. - * @param $group - * (optional) The group this message is in, which is displayed in a column - * in test output. Use 'Debug' to indicate this is debugging output. Do not - * translate this string. Defaults to 'Browser'; most tests do not override - * this default. - * - * @return - * TRUE on pass, FALSE on fail. - */ - protected function assertFieldChecked($id, $message = '', $group = 'Browser') { - $elements = $this->xpath('//input[@id=:id]', array(':id' => $id)); - return $this->assertTrue(isset($elements[0]) && !empty($elements[0]['checked']), $message ? $message : String::format('Checkbox field @id is checked.', array('@id' => $id)), $group); - } - - /** - * Asserts that a checkbox field in the current page is not checked. - * - * @param $id - * ID of field to assert. - * @param $message - * (optional) A message to display with the assertion. Do not translate - * messages: use format_string() to embed variables in the message text, not - * t(). If left blank, a default message will be displayed. - * @param $group - * (optional) The group this message is in, which is displayed in a column - * in test output. Use 'Debug' to indicate this is debugging output. Do not - * translate this string. Defaults to 'Browser'; most tests do not override - * this default. - * - * @return - * TRUE on pass, FALSE on fail. - */ - protected function assertNoFieldChecked($id, $message = '', $group = 'Browser') { - $elements = $this->xpath('//input[@id=:id]', array(':id' => $id)); - return $this->assertTrue(isset($elements[0]) && empty($elements[0]['checked']), $message ? $message : String::format('Checkbox field @id is not checked.', array('@id' => $id)), $group); - } - - /** - * Asserts that a select option in the current page exists. - * - * @param $id - * ID of select field to assert. - * @param $option - * Option to assert. - * @param $message - * (optional) A message to display with the assertion. Do not translate - * messages: use format_string() to embed variables in the message text, not - * t(). If left blank, a default message will be displayed. - * @param $group - * (optional) The group this message is in, which is displayed in a column - * in test output. Use 'Debug' to indicate this is debugging output. Do not - * translate this string. Defaults to 'Browser'; most tests do not override - * this default. - * - * @return - * TRUE on pass, FALSE on fail. - */ - protected function assertOption($id, $option, $message = '', $group = 'Browser') { - $options = $this->xpath('//select[@id=:id]/option[@value=:option]', array(':id' => $id, ':option' => $option)); - return $this->assertTrue(isset($options[0]), $message ? $message : String::format('Option @option for field @id exists.', array('@option' => $option, '@id' => $id)), $group); - } - - /** - * Asserts that a select option in the current page does not exist. - * - * @param $id - * ID of select field to assert. - * @param $option - * Option to assert. - * @param $message - * (optional) A message to display with the assertion. Do not translate - * messages: use format_string() to embed variables in the message text, not - * t(). If left blank, a default message will be displayed. - * @param $group - * (optional) The group this message is in, which is displayed in a column - * in test output. Use 'Debug' to indicate this is debugging output. Do not - * translate this string. Defaults to 'Browser'; most tests do not override - * this default. - * - * @return - * TRUE on pass, FALSE on fail. - */ - protected function assertNoOption($id, $option, $message = '', $group = 'Browser') { - $selects = $this->xpath('//select[@id=:id]', array(':id' => $id)); - $options = $this->xpath('//select[@id=:id]/option[@value=:option]', array(':id' => $id, ':option' => $option)); - return $this->assertTrue(isset($selects[0]) && !isset($options[0]), $message ? $message : String::format('Option @option for field @id does not exist.', array('@option' => $option, '@id' => $id)), $group); - } - - /** - * Asserts that a select option in the current page is checked. - * - * @param $id - * ID of select field to assert. - * @param $option - * Option to assert. - * @param $message - * (optional) A message to display with the assertion. Do not translate - * messages: use format_string() to embed variables in the message text, not - * t(). If left blank, a default message will be displayed. - * @param $group - * (optional) The group this message is in, which is displayed in a column - * in test output. Use 'Debug' to indicate this is debugging output. Do not - * translate this string. Defaults to 'Browser'; most tests do not override - * this default. - * - * @return - * TRUE on pass, FALSE on fail. - * - * @todo $id is unusable. Replace with $name. - */ - protected function assertOptionSelected($id, $option, $message = '', $group = 'Browser') { - $elements = $this->xpath('//select[@id=:id]//option[@value=:option]', array(':id' => $id, ':option' => $option)); - return $this->assertTrue(isset($elements[0]) && !empty($elements[0]['selected']), $message ? $message : String::format('Option @option for field @id is selected.', array('@option' => $option, '@id' => $id)), $group); - } - - /** - * Asserts that a select option in the current page is not checked. - * - * @param $id - * ID of select field to assert. - * @param $option - * Option to assert. - * @param $message - * (optional) A message to display with the assertion. Do not translate - * messages: use format_string() to embed variables in the message text, not - * t(). If left blank, a default message will be displayed. - * @param $group - * (optional) The group this message is in, which is displayed in a column - * in test output. Use 'Debug' to indicate this is debugging output. Do not - * translate this string. Defaults to 'Browser'; most tests do not override - * this default. - * - * @return - * TRUE on pass, FALSE on fail. - */ - protected function assertNoOptionSelected($id, $option, $message = '', $group = 'Browser') { - $elements = $this->xpath('//select[@id=:id]//option[@value=:option]', array(':id' => $id, ':option' => $option)); - return $this->assertTrue(isset($elements[0]) && empty($elements[0]['selected']), $message ? $message : String::format('Option @option for field @id is not selected.', array('@option' => $option, '@id' => $id)), $group); - } - - /** - * Asserts that a field exists with the given name or ID. - * - * @param $field - * Name or ID of field to assert. - * @param $message - * (optional) A message to display with the assertion. Do not translate - * messages: use format_string() to embed variables in the message text, not - * t(). If left blank, a default message will be displayed. - * @param $group - * (optional) The group this message is in, which is displayed in a column - * in test output. Use 'Debug' to indicate this is debugging output. Do not - * translate this string. Defaults to 'Other'; most tests do not override - * this default. - * - * @return - * TRUE on pass, FALSE on fail. - */ - protected function assertField($field, $message = '', $group = 'Other') { - return $this->assertFieldByXPath($this->constructFieldXpath('name', $field) . '|' . $this->constructFieldXpath('id', $field), NULL, $message, $group); - } - - /** - * Asserts that a field does not exist with the given name or ID. - * - * @param $field - * Name or ID of field to assert. - * @param $message - * (optional) A message to display with the assertion. Do not translate - * messages: use format_string() to embed variables in the message text, not - * t(). If left blank, a default message will be displayed. - * @param $group - * (optional) The group this message is in, which is displayed in a column - * in test output. Use 'Debug' to indicate this is debugging output. Do not - * translate this string. Defaults to 'Other'; most tests do not override - * this default. - * - * @return - * TRUE on pass, FALSE on fail. - */ - protected function assertNoField($field, $message = '', $group = 'Other') { - return $this->assertNoFieldByXPath($this->constructFieldXpath('name', $field) . '|' . $this->constructFieldXpath('id', $field), NULL, $message, $group); - } - - /** - * Asserts that each HTML ID is used for just a single element. - * - * @param $message - * (optional) A message to display with the assertion. Do not translate - * messages: use format_string() to embed variables in the message text, not - * t(). If left blank, a default message will be displayed. - * @param $group - * (optional) The group this message is in, which is displayed in a column - * in test output. Use 'Debug' to indicate this is debugging output. Do not - * translate this string. Defaults to 'Other'; most tests do not override - * this default. - * @param $ids_to_skip - * An optional array of ids to skip when checking for duplicates. It is - * always a bug to have duplicate HTML IDs, so this parameter is to enable - * incremental fixing of core code. Whenever a test passes this parameter, - * it should add a "todo" comment above the call to this function explaining - * the legacy bug that the test wishes to ignore and including a link to an - * issue that is working to fix that legacy bug. - * - * @return - * TRUE on pass, FALSE on fail. - */ - protected function assertNoDuplicateIds($message = '', $group = 'Other', $ids_to_skip = array()) { - $status = TRUE; - foreach ($this->xpath('//*[@id]') as $element) { - $id = (string) $element['id']; - if (isset($seen_ids[$id]) && !in_array($id, $ids_to_skip)) { - $this->fail(String::format('The HTML ID %id is unique.', array('%id' => $id)), $group); - $status = FALSE; - } - $seen_ids[$id] = TRUE; - } - return $this->assert($status, $message, $group); - } - - /** - * Helper: Constructs an XPath for the given set of attributes and value. - * - * @param $attribute - * Field attributes. - * @param $value - * Value of field. - * - * @return - * XPath for specified values. - */ - protected function constructFieldXpath($attribute, $value) { - $xpath = '//textarea[@' . $attribute . '=:value]|//input[@' . $attribute . '=:value]|//select[@' . $attribute . '=:value]'; - return $this->buildXPathQuery($xpath, array(':value' => $value)); - } - /** * Asserts the page responds with the specified response code. * diff --git a/core/modules/simpletest/tests/src/WebTestBaseTest.php b/core/modules/simpletest/tests/src/WebTestBaseTest.php index 6353310d529fdefe4c07b4f9b0c20f62bc7feb45..47bfe62ab84c981af8de278a532352edd13bf917 100644 --- a/core/modules/simpletest/tests/src/WebTestBaseTest.php +++ b/core/modules/simpletest/tests/src/WebTestBaseTest.php @@ -68,11 +68,11 @@ public function testAssertFieldByName($filename, $name, $value, $expected) { $web_test = $this->getMockBuilder('Drupal\simpletest\WebTestBase') ->disableOriginalConstructor() - ->setMethods(array('assertTrue', 'drupalGetContent', 'pass')) + ->setMethods(array('getRawContent', 'assertTrue', 'pass')) ->getMock(); $web_test->expects($this->any()) - ->method('drupalGetContent') + ->method('getRawContent') ->will($this->returnValue($content)); $web_test->expects($this->once()) diff --git a/core/modules/system/src/Tests/System/ScriptTest.php b/core/modules/system/src/Tests/System/ScriptTest.php index 1b56a2c625fdb96ad61e22615a481719adb790ea..d7129916773404bf2937f5e4b9ce3b5586df79fd 100644 --- a/core/modules/system/src/Tests/System/ScriptTest.php +++ b/core/modules/system/src/Tests/System/ScriptTest.php @@ -7,7 +7,6 @@ namespace Drupal\system\Tests\System; -use Drupal\Component\Utility\String; use Drupal\simpletest\DrupalUnitTestBase; /** @@ -44,7 +43,7 @@ public function testPasswordHashSh() { ); ob_start(); include DRUPAL_ROOT . '/core/scripts/password-hash.sh'; - $this->content = ob_get_contents(); + $this->setRawContent(ob_get_contents()); ob_end_clean(); $this->assertRaw('hash: $S$'); } @@ -66,22 +65,9 @@ public function testRebuildTokenCalculatorSh() { ); ob_start(); include DRUPAL_ROOT . '/core/scripts/rebuild_token_calculator.sh'; - $this->content = ob_get_contents(); + $this->setRawContent(ob_get_contents()); ob_end_clean(); $this->assertRaw('token='); } - /** - * Asserts that a given string is found in $this->content. - * - * @param string $string - * The raw string to assert. - */ - protected function assertRaw($string) { - return $this->assert(strpos($this->content, $string) !== FALSE, String::format('Raw @value found in @output.', array( - '@value' => var_export($string, TRUE), - '@output' => var_export($this->content, TRUE), - ))); - } - } diff --git a/core/modules/system/src/Tests/Theme/TableTest.php b/core/modules/system/src/Tests/Theme/TableTest.php index 60c28c8f3f6be9c4884e2f839965b3c92aa7f58b..f1eddfc1a7cc6738793f832301ace40ae5b9bec9 100644 --- a/core/modules/system/src/Tests/Theme/TableTest.php +++ b/core/modules/system/src/Tests/Theme/TableTest.php @@ -7,7 +7,6 @@ namespace Drupal\system\Tests\Theme; -use Drupal\Component\Utility\String; use Drupal\simpletest\DrupalUnitTestBase; /** @@ -211,59 +210,4 @@ public function testThemeTableResponsivePriority() { $this->assertRaw('<td>6</td>', 'Cell 3: no priority classes were applied.'); } - /** - * Renders a given render array. - * - * @param array $elements - * The render array elements to render. - * - * @return string - * The rendered HTML. - */ - protected function render(array $elements) { - $this->content = drupal_render($elements); - $this->verbose('<pre>' . String::checkPlain($this->content)); - } - - /** - * Removes all white-space between HTML tags from $this->content. - */ - protected function removeWhiteSpace() { - $this->content = preg_replace('@>\s+<@', '><', $this->content); - } - - /** - * Asserts that a raw string appears in $this->content. - * - * @param string $value - * The expected string. - * @param string $message - * (optional) A custom assertion message. - */ - protected function assertRaw($value, $message = NULL) { - if (!isset($message)) { - $message = String::format("Raw value @value found.", array( - '@value' => var_export($value, TRUE), - )); - } - $this->assert(strpos($this->content, $value) !== FALSE, $message); - } - - /** - * Asserts that a raw string does not appear in $this->content. - * - * @param string $value - * The not expected string. - * @param string $message - * (optional) A custom assertion message. - */ - protected function assertNoRaw($value, $message = NULL) { - if (!isset($message)) { - $message = String::format("Raw value @value not found.", array( - '@value' => var_export($value, TRUE), - )); - } - $this->assert(strpos($this->content, $value) === FALSE, $message); - } - } diff --git a/core/modules/text/src/Tests/Formatter/TextPlainUnitTest.php b/core/modules/text/src/Tests/Formatter/TextPlainUnitTest.php index 750dc4a8677aa95abf781511542a46b3e23a33c7..b3590145872652d0694146d58712b06a339ad7a9 100644 --- a/core/modules/text/src/Tests/Formatter/TextPlainUnitTest.php +++ b/core/modules/text/src/Tests/Formatter/TextPlainUnitTest.php @@ -29,13 +29,6 @@ class TextPlainUnitTest extends DrupalUnitTestBase { */ public static $modules = array('entity', 'field', 'text', 'entity_test', 'system', 'filter', 'user'); - /** - * Contains rendered content. - * - * @var string - */ - protected $content; - public static function getInfo() { return array( 'name' => 'Text field text_plain formatter', @@ -123,8 +116,8 @@ protected function createEntity($values = array()) { */ protected function renderEntityFields(ContentEntityInterface $entity, EntityViewDisplayInterface $display) { $content = $display->build($entity); - $this->content = drupal_render($content); - return $this->content; + $content = $this->render($content); + return $content; } /** diff --git a/core/modules/views/src/Tests/Plugin/RowEntityTest.php b/core/modules/views/src/Tests/Plugin/RowEntityTest.php index e5cb58fd1cc6a5a1f76de4be6c5743749e244c79..70511f32a6b110f9e65583437ac13c41427f15ed 100644 --- a/core/modules/views/src/Tests/Plugin/RowEntityTest.php +++ b/core/modules/views/src/Tests/Plugin/RowEntityTest.php @@ -7,7 +7,6 @@ namespace Drupal\views\Tests\Plugin; -use Drupal\Component\Utility\Xss; use Drupal\views\Views; use Drupal\views\Tests\ViewUnitTestBase; @@ -32,13 +31,6 @@ class RowEntityTest extends ViewUnitTestBase { */ public static $testViews = array('test_entity_row'); - /** - * A string for assert raw and text helper methods. - * - * @var string - */ - protected $content; - public static function getInfo() { return array( 'name' => 'Row: Entity', @@ -68,8 +60,7 @@ public function testEntityRow() { $term->save(); $view = Views::getView('test_entity_row'); - $this->content = $view->preview(); - $this->content = drupal_render($this->content); + $this->render($view->preview()); $this->assertText($term->getName(), 'The rendered entity appears as row in the view.'); @@ -82,28 +73,4 @@ public function testEntityRow() { $this->assertTrue(isset($form['view_mode']['#options']['default']), 'Ensure that the default view mode is available'); } - /** - * Pass if the text is found in set string. - * - * @param string $text - * Text to look for. - * @param string $message - * (optional) A message to display with the assertion. Do not translate - * messages: use format_string() to embed variables in the message text, not - * t(). If left blank, a default message will be displayed. - * @param string $group - * (optional) The group this message is in, which is displayed in a column - * in test output. Use 'Debug' to indicate this is debugging output. Do not - * translate this string. Defaults to 'Other'; most tests do not override - * this default. - * - * @return bool TRUE on pass, FALSE on fail. - */ - protected function assertText($text, $message = '', $group = 'Other') { - if (!$message) { - $message = t('Raw "@raw" found', array('@raw' => $text)); - } - return $this->assert(strpos(Xss::filter($this->content, array()), $text) !== FALSE, $message, $group); - } - } diff --git a/core/modules/views/src/Tests/Plugin/StyleGridTest.php b/core/modules/views/src/Tests/Plugin/StyleGridTest.php index e9132b17c33e24977895f366c99f30eebbfa3dc2..dfa4e30514e14a8d3ead7cd5ce2c678c94212eaf 100644 --- a/core/modules/views/src/Tests/Plugin/StyleGridTest.php +++ b/core/modules/views/src/Tests/Plugin/StyleGridTest.php @@ -83,7 +83,7 @@ protected function assertGrid(ViewExecutable $view, $alignment, $columns) { $this->executeView($view); $output = $view->preview(); $output = drupal_render($output); - $this->drupalSetContent($output, 'internal://test-grid'); + $this->drupalSetContent($output); if (!in_array($alignment, $this->alignmentsTested)) { $result = $this->xpath('//div[contains(@class, "views-view-grid") and contains(@class, :alignment) and contains(@class, :columns)]', array(':alignment' => $alignment, ':columns' => 'cols-' . $columns)); $this->assertTrue(count($result), ucfirst($alignment) . " grid markup detected.");