Commit 573068f9 authored by alexpott's avatar alexpott

Issue #2003568 by dawehner, jhedstrom: Convert tags,attributes, diff and url...

Issue #2003568 by dawehner, jhedstrom: Convert tags,attributes, diff and url validation unit tests to phpunit.
parent 81f4bc82
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
use Drupal\Component\Utility\Crypt; use Drupal\Component\Utility\Crypt;
use Drupal\Component\Utility\String; use Drupal\Component\Utility\String;
use Drupal\Component\Utility\Tags;
use Drupal\Component\Utility\UrlValidator; use Drupal\Component\Utility\UrlValidator;
use Drupal\Component\Utility\Xss; use Drupal\Component\Utility\Xss;
use Drupal\Core\Cache\Cache; use Drupal\Core\Cache\Cache;
...@@ -14,6 +15,7 @@ ...@@ -14,6 +15,7 @@
use Drupal\Component\PhpStorage\PhpStorageFactory; use Drupal\Component\PhpStorage\PhpStorageFactory;
use Drupal\Component\Utility\MapArray; use Drupal\Component\Utility\MapArray;
use Drupal\Component\Utility\NestedArray; use Drupal\Component\Utility\NestedArray;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Datetime\DrupalDateTime; use Drupal\Core\Datetime\DrupalDateTime;
use Drupal\Core\Database\Database; use Drupal\Core\Database\Database;
...@@ -789,6 +791,8 @@ function valid_email_address($mail) { ...@@ -789,6 +791,8 @@ function valid_email_address($mail) {
* TRUE if the URL is in a valid format. * TRUE if the URL is in a valid format.
* *
* @see \Drupal\Component\Utility\UrlValidator::isValid() * @see \Drupal\Component\Utility\UrlValidator::isValid()
*
* @deprecated as of Drupal 8.0. Use UrlValidator::isValid() instead.
*/ */
function valid_url($url, $absolute = FALSE) { function valid_url($url, $absolute = FALSE) {
return UrlValidator::isValid($url, $absolute); return UrlValidator::isValid($url, $absolute);
...@@ -5508,44 +5512,24 @@ function watchdog_severity_levels() { ...@@ -5508,44 +5512,24 @@ function watchdog_severity_levels() {
* Explodes a string of tags into an array. * Explodes a string of tags into an array.
* *
* @see drupal_implode_tags() * @see drupal_implode_tags()
* @see \Drupal\Component\Utility\String::explodeTags().
*
* @deprecated as of Drupal 8.0. Use Tags::explode() instead.
*/ */
function drupal_explode_tags($tags) { function drupal_explode_tags($tags) {
// This regexp allows the following types of user input: return Tags::explode($tags);
// this, "somecompany, llc", "and ""this"" w,o.rks", foo bar
$regexp = '%(?:^|,\ *)("(?>[^"]*)(?>""[^"]* )*"|(?: [^",]*))%x';
preg_match_all($regexp, $tags, $matches);
$typed_tags = array_unique($matches[1]);
$tags = array();
foreach ($typed_tags as $tag) {
// If a user has escaped a term (to demonstrate that it is a group,
// or includes a comma or quote character), we remove the escape
// formatting so to save the term into the database as the user intends.
$tag = trim(str_replace('""', '"', preg_replace('/^"(.*)"$/', '\1', $tag)));
if ($tag != "") {
$tags[] = $tag;
}
}
return $tags;
} }
/** /**
* Implodes an array of tags into a string. * Implodes an array of tags into a string.
* *
* @see drupal_explode_tags() * @see drupal_explode_tags()
* @see \Drupal\Component\Utility\String::implodeTags().
*
* @deprecated as of Drupal 8.0. Use Tags::implode() instead.
*/ */
function drupal_implode_tags($tags) { function drupal_implode_tags($tags) {
$encoded_tags = array(); return Tags::implode($tags);
foreach ($tags as $tag) {
// Commas and quotes in tag names are special cases, so encode them.
if (strpos($tag, ',') !== FALSE || strpos($tag, '"') !== FALSE) {
$tag = '"' . str_replace('"', '""', $tag) . '"';
}
$encoded_tags[] = $tag;
}
return implode(', ', $encoded_tags);
} }
/** /**
......
<?php
/**
* @file
* Contains \Drupal\Component\Utility\Tags.
*/
namespace Drupal\Component\Utility;
/**
* Defines a class that can explode and implode tags.
*/
class Tags {
/**
* Explodes a string of tags into an array.
*
* @param string $tags
* A string to explode.
*
* @return array
* An array of tags.
*/
public static function explode($tags) {
// This regexp allows the following types of user input:
// this, "somecompany, llc", "and ""this"" w,o.rks", foo bar
$regexp = '%(?:^|,\ *)("(?>[^"]*)(?>""[^"]* )*"|(?: [^",]*))%x';
preg_match_all($regexp, $tags, $matches);
$typed_tags = array_unique($matches[1]);
$tags = array();
foreach ($typed_tags as $tag) {
// If a user has escaped a term (to demonstrate that it is a group,
// or includes a comma or quote character), we remove the escape
// formatting so to save the term into the database as the user intends.
$tag = trim(str_replace('""', '"', preg_replace('/^"(.*)"$/', '\1', $tag)));
if ($tag != "") {
$tags[] = $tag;
}
}
return $tags;
}
/**
* Implodes an array of tags into a string.
*
* @param array $tags
* An array of tags.
*
* @return string
* The imploded string.
*/
public static function implode($tags) {
$encoded_tags = array();
foreach ($tags as $tag) {
// Commas and quotes in tag names are special cases, so encode them.
if (strpos($tag, ',') !== FALSE || strpos($tag, '"') !== FALSE) {
$tag = '"' . str_replace('"', '""', $tag) . '"';
}
$encoded_tags[] = $tag;
}
return implode(', ', $encoded_tags);
}
}
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
namespace Drupal\Core\Template; namespace Drupal\Core\Template;
use Drupal\Component\Utility\String;
/** /**
* A class that defines a type of Attribute that can be added to as an array. * A class that defines a type of Attribute that can be added to as an array.
...@@ -66,7 +67,7 @@ public function offsetExists($offset) { ...@@ -66,7 +67,7 @@ public function offsetExists($offset) {
*/ */
public function __toString() { public function __toString() {
$this->printed = TRUE; $this->printed = TRUE;
return implode(' ', array_map('check_plain', $this->value)); return implode(' ', array_map(array('Drupal\Component\Utility\String', 'checkPlain'), $this->value));
} }
/** /**
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
namespace Drupal\Core\Template; namespace Drupal\Core\Template;
use Drupal\Component\Utility\String;
/** /**
* A class that represents most standard HTML attributes. * A class that represents most standard HTML attributes.
* *
...@@ -29,7 +31,7 @@ class AttributeString extends AttributeValueBase { ...@@ -29,7 +31,7 @@ class AttributeString extends AttributeValueBase {
*/ */
public function __toString() { public function __toString() {
$this->printed = TRUE; $this->printed = TRUE;
return check_plain($this->value); return String::checkPlain($this->value);
} }
} }
<?php
/**
* @file
* Definition of Drupal\system\Tests\Common\AttributesUnitTest.
*/
namespace Drupal\system\Tests\Common;
use Drupal\Core\Template\Attribute;
use Drupal\simpletest\UnitTestBase;
/**
* Tests the Drupal\Core\Template\Attribute functionality.
*/
class AttributesUnitTest extends UnitTestBase {
public static function getInfo() {
return array(
'name' => 'HTML Attributes',
'description' => 'Tests the Drupal\Core\Template\Attribute functionality.',
'group' => 'Common',
);
}
/**
* Tests that drupal_html_class() cleans the class name properly.
*/
function testDrupalAttributes() {
// Verify that special characters are HTML encoded.
$this->assertIdentical((string) new Attribute(array('title' => '&"\'<>')), ' title="&amp;&quot;&#039;&lt;&gt;"', 'HTML encode attribute values.');
// Verify multi-value attributes are concatenated with spaces.
$attributes = array('class' => array('first', 'last'));
$this->assertIdentical((string) new Attribute(array('class' => array('first', 'last'))), ' class="first last"', 'Concatenate multi-value attributes.');
// Verify empty attribute values are rendered.
$this->assertIdentical((string) new Attribute(array('alt' => '')), ' alt=""', 'Empty attribute value #1.');
$this->assertIdentical((string) new Attribute(array('alt' => NULL)), ' alt=""', 'Empty attribute value #2.');
// Verify multiple attributes are rendered.
$attributes = array(
'id' => 'id-test',
'class' => array('first', 'last'),
'alt' => 'Alternate',
);
$this->assertIdentical((string) new Attribute($attributes), ' id="id-test" class="first last" alt="Alternate"', 'Multiple attributes.');
// Verify empty attributes array is rendered.
$this->assertIdentical((string) new Attribute(array()), '', 'Empty attributes array.');
$attribute = new Attribute(array('key1' => 'value1'));
foreach($attribute as $value) {
$this->assertIdentical((string) $value, 'value1', 'Iterate over attribute.');
}
}
}
<?php
/**
* @file
* Contains \Drupal\Tests\Core\Common\AttributesTest.
*/
namespace Drupal\Tests\Core\Common;
use Drupal\Core\Template\Attribute;
use Drupal\Tests\UnitTestCase;
/**
* Tests the Drupal\Core\Template\Attribute functionality.
*/
class AttributesTest extends UnitTestCase {
public static function getInfo() {
return array(
'name' => 'HTML Attributes',
'description' => 'Tests the Drupal\Core\Template\Attribute functionality.',
'group' => 'Common',
);
}
/**
* Provides data for the Attribute test.
*
* @return array
*/
public function providerTestAttributeData() {
return array(
// Verify that special characters are HTML encoded.
array(array('title' => '&"\'<>'), ' title="&amp;&quot;&#039;&lt;&gt;"', 'HTML encode attribute values.'),
// Verify multi-value attributes are concatenated with spaces.
array(array('class' => array('first', 'last')), ' class="first last"', 'Concatenate multi-value attributes.'),
// Verify empty attribute values are rendered.
array(array('alt' => ''), ' alt=""', 'Empty attribute value #1.'),
array(array('alt' => NULL), ' alt=""', 'Empty attribute value #2.'),
// Verify multiple attributes are rendered.
array(
array(
'id' => 'id-test',
'class' => array('first', 'last'),
'alt' => 'Alternate',
),
' id="id-test" class="first last" alt="Alternate"',
'Multiple attributes.'
),
// Verify empty attributes array is rendered.
array(array(), '', 'Empty attributes array.'),
);
}
/**
* Tests casting an Attribute object to a string.
*
* @see \Drupal\Core\Template\Attribute::__toString()
*
* @dataProvider providerTestAttributeData
*/
function testDrupalAttributes($attributes, $expected, $message) {
$this->assertSame($expected, (string) new Attribute($attributes), $message);
}
/**
* Test attribute iteration
*/
public function testAttributeIteration() {
$attribute = new Attribute(array('key1' => 'value1'));
foreach ($attribute as $value) {
$this->assertSame((string) $value, 'value1', 'Iterate over attribute.');
}
}
}
...@@ -2,18 +2,18 @@ ...@@ -2,18 +2,18 @@
/** /**
* @file * @file
* Contains \Drupal\system\Tests\Common\DiffArrayUnitTest. * Contains \Drupal\Tests\Core\Common\DiffArrayTest.
*/ */
namespace Drupal\system\Tests\Common; namespace Drupal\Tests\Core\Common;
use Drupal\Component\Utility\DiffArray; use Drupal\Component\Utility\DiffArray;
use Drupal\simpletest\UnitTestBase; use Drupal\Tests\UnitTestCase;
/** /**
* Tests the DiffArray helper class. * Tests the DiffArray helper class.
*/ */
class DiffArrayUnitTest extends UnitTestBase { class DiffArrayTest extends UnitTestCase {
/** /**
* Array to use for testing. * Array to use for testing.
...@@ -77,7 +77,7 @@ public function testDiffAssocRecursive() { ...@@ -77,7 +77,7 @@ public function testDiffAssocRecursive() {
'new' => 'new', 'new' => 'new',
); );
$this->assertIdentical(DiffArray::diffAssocRecursive($this->array1, $this->array2), $expected); $this->assertSame(DiffArray::diffAssocRecursive($this->array1, $this->array2), $expected);
} }
} }
...@@ -2,18 +2,20 @@ ...@@ -2,18 +2,20 @@
/** /**
* @file * @file
* Definition of Drupal\system\Tests\Common\AutocompleteTagsUnitTest. * Contains \Drupal\Tests\Core\Common\TagsTest.
*/ */
namespace Drupal\system\Tests\Common; namespace Drupal\Tests\Core\Common;
use Drupal\simpletest\UnitTestBase; use Drupal\Component\Utility\Tags;
use Drupal\Tests\UnitTestCase;
/** /**
* Tests drupal_explode_tags() and drupal_implode_tags(). * Tests Tags::explodeTags and Tags::implodeTags().
*/ */
class AutocompleteTagsUnitTest extends UnitTestBase { class TagsTest extends UnitTestCase {
var $validTags = array(
protected $validTags = array(
'Drupal' => 'Drupal', 'Drupal' => 'Drupal',
'Drupal with some spaces' => 'Drupal with some spaces', 'Drupal with some spaces' => 'Drupal with some spaces',
'"Legendary Drupal mascot of doom: ""Druplicon"""' => 'Legendary Drupal mascot of doom: "Druplicon"', '"Legendary Drupal mascot of doom: ""Druplicon"""' => 'Legendary Drupal mascot of doom: "Druplicon"',
...@@ -31,21 +33,21 @@ public static function getInfo() { ...@@ -31,21 +33,21 @@ public static function getInfo() {
/** /**
* Explodes a series of tags. * Explodes a series of tags.
*/ */
function testDrupalExplodeTags() { public function explodeTags() {
$string = implode(', ', array_keys($this->validTags)); $string = implode(', ', array_keys($this->validTags));
$tags = drupal_explode_tags($string); $tags = Tags::explode($string);
$this->assertTags($tags); $this->assertTags($tags);
} }
/** /**
* Implodes a series of tags. * Implodes a series of tags.
*/ */
function testDrupalImplodeTags() { public function testImplodeTags() {
$tags = array_values($this->validTags); $tags = array_values($this->validTags);
// Let's explode and implode to our heart's content. // Let's explode and implode to our heart's content.
for ($i = 0; $i < 10; $i++) { for ($i = 0; $i < 10; $i++) {
$string = drupal_implode_tags($tags); $string = Tags::implode($tags);
$tags = drupal_explode_tags($string); $tags = Tags::explode($string);
} }
$this->assertTags($tags); $this->assertTags($tags);
} }
...@@ -53,15 +55,16 @@ function testDrupalImplodeTags() { ...@@ -53,15 +55,16 @@ function testDrupalImplodeTags() {
/** /**
* Helper function: asserts that the ending array of tags is what we wanted. * Helper function: asserts that the ending array of tags is what we wanted.
*/ */
function assertTags($tags) { protected function assertTags($tags) {
$original = $this->validTags; $original = $this->validTags;
foreach ($tags as $tag) { foreach ($tags as $tag) {
$key = array_search($tag, $original); $key = array_search($tag, $original);
$this->assertTrue($key, format_string('Make sure tag %tag shows up in the final tags array (originally %original)', array('%tag' => $tag, '%original' => $key))); $this->assertTrue((bool) $key, $tag, sprintf('Make sure tag %s shows up in the final tags array (originally %s)', $tag, $key));
unset($original[$key]); unset($original[$key]);
} }
foreach ($original as $leftover) { foreach ($original as $leftover) {
$this->fail(format_string('Leftover tag %leftover was left over.', array('%leftover' => $leftover))); $this->fail(sprintf('Leftover tag %s was left over.', $leftover));
} }
} }
} }
...@@ -2,17 +2,20 @@ ...@@ -2,17 +2,20 @@
/** /**
* @file * @file
* Definition of Drupal\system\Tests\Common\ValidUrlUnitTest. * Contains \Drupal\Tests\Core\Common\UrlValidatorTest.
*/ */
namespace Drupal\system\Tests\Common; namespace Drupal\Tests\Core\Common;
use Drupal\simpletest\UnitTestBase; use Drupal\Component\Utility\String;
use Drupal\Component\Utility\UrlValidator;
use Drupal\Tests\UnitTestCase;
/** /**
* Tests URL validation by valid_url(). * Tests URL validation by valid_url().
*/ */
class ValidUrlUnitTest extends UnitTestBase { class UrlValidatorTest extends UnitTestCase {
public static function getInfo() { public static function getInfo() {
return array( return array(
'name' => 'URL validation', 'name' => 'URL validation',
...@@ -22,16 +25,15 @@ public static function getInfo() { ...@@ -22,16 +25,15 @@ public static function getInfo() {
} }
/** /**
* Tests valid absolute URLs. * Data provider for absolute URLs.
*/ */
function testValidAbsolute() { public function providerTestValidAbsoluteData() {
$url_schemes = array('http', 'https', 'ftp'); $urls = array(
$valid_absolute_urls = array(
'example.com', 'example.com',
'www.example.com', 'www.example.com',
'ex-ample.com', 'ex-ample.com',
'3xampl3.com', '3xampl3.com',
'example.com/paren(the)sis', 'example.com/parenthesis',
'example.com/index.html#pagetop', 'example.com/index.html#pagetop',
'example.com:8080', 'example.com:8080',
'subdomain.example.com', 'subdomain.example.com',
...@@ -47,40 +49,58 @@ function testValidAbsolute() { ...@@ -47,40 +49,58 @@ function testValidAbsolute() {
'[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html', '[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html',
); );
foreach ($url_schemes as $scheme) { return $this->dataEnhanceWithScheme($urls);
foreach ($valid_absolute_urls as $url) {
$test_url = $scheme . '://' . $url;
$valid_url = valid_url($test_url, TRUE);
$this->assertTrue($valid_url, format_string('@url is a valid URL.', array('@url' => $test_url)));
}
}
} }
/** /**
* Tests invalid absolute URLs. * Tests valid absolute URLs.
*
* @param string $url
* The url to test.
* @param string $scheme
* The scheme to test.
*
* @dataProvider providerTestValidAbsoluteData
*/ */
function testInvalidAbsolute() { public function testValidAbsolute($url, $scheme) {
$url_schemes = array('http', 'https', 'ftp'); $test_url = $scheme . '://' . $url;
$invalid_ablosule_urls = array( $valid_url = UrlValidator::isValid($test_url, TRUE);
$this->assertTrue($valid_url, String::format('@url is a valid URL.', array('@url' => $test_url)));
}
/**
* Provides invalid absolute URLs.
*/
public function providerTestInvalidAbsolute() {
$data = array(
'', '',
'ex!ample.com', 'ex!ample.com',
'ex%ample.com', 'ex%ample.com',
); );
return $this->dataEnhanceWithScheme($data);
}
foreach ($url_schemes as $scheme) { /**
foreach ($invalid_ablosule_urls as $url) { * Tests invalid absolute URLs.
$test_url = $scheme . '://' . $url; *
$valid_url = valid_url($test_url, TRUE); * @param string $url
$this->assertFalse($valid_url, format_string('@url is NOT a valid URL.', array('@url' => $test_url))); * The url to test.
} * @param string $scheme
} * The scheme to test.
*
* @dataProvider providerTestInvalidAbsolute
*/
public function testInvalidAbsolute($url, $scheme) {
$test_url = $scheme . '://' . $url;
$valid_url = UrlValidator::isValid($test_url, TRUE);
$this->assertFalse($valid_url, String::format('@url is NOT a valid URL.', array('@url' => $test_url)));
} }
/** /**
* Tests valid relative URLs. * Provides valid relative URLs
*/ */
function testValidRelative() { public function providerTestValidRelativeData() {
$valid_relative_urls = array( $data = array(
'paren(the)sis', 'paren(the)sis',
'index.html#pagetop', 'index.html#pagetop',
'index.php/node', 'index.php/node',
...@@ -88,31 +108,92 @@ function testValidRelative() { ...@@ -88,31 +108,92 @@ function testValidRelative() {
'login.php?do=login&style=%23#pagetop', 'login.php?do=login&style=%23#pagetop',
); );
foreach (array('', '/') as $front) { return $this->dataEnhanceWithPrefix($data);
foreach ($valid_relative_urls as $url) {
$test_url = $front . $url;
$valid_url = valid_url($test_url);