diff --git a/core/modules/aggregator/aggregator.test b/core/modules/aggregator/aggregator.test
index 61ad16b..d73c52d 100644
--- a/core/modules/aggregator/aggregator.test
+++ b/core/modules/aggregator/aggregator.test
@@ -5,7 +5,9 @@
* Tests for aggregator.module.
*/
-class AggregatorTestCase extends DrupalWebTestCase {
+use Drupal\simpletest\WebTest;
+
+class AggregatorTestCase extends WebTest {
function setUp() {
parent::setUp(array('node', 'block', 'aggregator', 'aggregator_test'));
diff --git a/core/modules/block/block.test b/core/modules/block/block.test
index 4af6240..58b7f31 100644
--- a/core/modules/block/block.test
+++ b/core/modules/block/block.test
@@ -5,7 +5,10 @@
* Tests for block.module.
*/
-class BlockTestCase extends DrupalWebTestCase {
+use Drupal\simpletest\WebTest;
+use Drupal\simpletest\UnitTest;
+
+class BlockTestCase extends WebTest {
protected $regions;
protected $admin_user;
@@ -398,7 +401,7 @@ class BlockTestCase extends DrupalWebTestCase {
}
}
-class NonDefaultBlockAdmin extends DrupalWebTestCase {
+class NonDefaultBlockAdmin extends WebTest {
public static function getInfo() {
return array(
'name' => 'Non default theme admin',
@@ -426,7 +429,7 @@ class NonDefaultBlockAdmin extends DrupalWebTestCase {
/**
* Test blocks correctly initialized when picking a new default theme.
*/
-class NewDefaultThemeBlocks extends DrupalWebTestCase {
+class NewDefaultThemeBlocks extends WebTest {
public static function getInfo() {
return array(
'name' => 'New default theme blocks',
@@ -481,7 +484,7 @@ class NewDefaultThemeBlocks extends DrupalWebTestCase {
/**
* Test the block system with admin themes.
*/
-class BlockAdminThemeTestCase extends DrupalWebTestCase {
+class BlockAdminThemeTestCase extends WebTest {
public static function getInfo() {
return array(
'name' => 'Admin theme block admin accessibility',
@@ -517,7 +520,7 @@ class BlockAdminThemeTestCase extends DrupalWebTestCase {
/**
* Test block caching.
*/
-class BlockCacheTestCase extends DrupalWebTestCase {
+class BlockCacheTestCase extends WebTest {
protected $admin_user;
protected $normal_user;
protected $normal_user_alt;
@@ -704,7 +707,7 @@ class BlockCacheTestCase extends DrupalWebTestCase {
/**
* Test block HTML id validity.
*/
-class BlockHTMLIdTestCase extends DrupalWebTestCase {
+class BlockHTMLIdTestCase extends WebTest {
public static function getInfo() {
return array(
@@ -743,7 +746,7 @@ class BlockHTMLIdTestCase extends DrupalWebTestCase {
/**
* Unit tests for template_preprocess_block().
*/
-class BlockTemplateSuggestionsUnitTest extends DrupalUnitTestCase {
+class BlockTemplateSuggestionsUnitTest extends UnitTest {
public static function getInfo() {
return array(
'name' => 'Block template suggestions',
@@ -788,7 +791,7 @@ class BlockTemplateSuggestionsUnitTest extends DrupalUnitTestCase {
/**
* Tests that hidden regions do not inherit blocks when a theme is enabled.
*/
-class BlockHiddenRegionTestCase extends DrupalWebTestCase {
+class BlockHiddenRegionTestCase extends WebTest {
public static function getInfo() {
return array(
'name' => 'Blocks not in hidden region',
diff --git a/core/modules/book/book.test b/core/modules/book/book.test
index 54444b2..7a339ca 100644
--- a/core/modules/book/book.test
+++ b/core/modules/book/book.test
@@ -5,7 +5,10 @@
* Tests for book.module.
*/
-class BookTestCase extends DrupalWebTestCase {
+
+use Drupal\simpletest\WebTest;
+
+class BookTestCase extends WebTest {
protected $book;
// $book_author is a user with permission to create and edit books.
protected $book_author;
diff --git a/core/modules/color/color.test b/core/modules/color/color.test
index 616d19a..15846ad 100644
--- a/core/modules/color/color.test
+++ b/core/modules/color/color.test
@@ -5,10 +5,12 @@
* Tests for color module.
*/
+use Drupal\simpletest\WebTest;
+
/**
* Tests the Color module functionality.
*/
-class ColorTestCase extends DrupalWebTestCase {
+class ColorTestCase extends WebTest {
protected $big_user;
protected $themes;
protected $colorTests;
diff --git a/core/modules/comment/comment.test b/core/modules/comment/comment.test
index 259e420..f06ef6f 100644
--- a/core/modules/comment/comment.test
+++ b/core/modules/comment/comment.test
@@ -5,7 +5,9 @@
* Tests for the Comment module.
*/
-class CommentHelperCase extends DrupalWebTestCase {
+use Drupal\simpletest\WebTest;
+
+class CommentHelperCase extends WebTest {
protected $profile = 'standard';
protected $admin_user;
@@ -814,7 +816,7 @@ class CommentInterfaceTest extends CommentHelperCase {
user_role_change_permissions($rid, $perms);
// Output verbose debugging information.
- // @see DrupalTestCase::error()
+ // @see Drupal\simpletest\Test::error()
$t_form = array(
COMMENT_FORM_BELOW => 'below',
COMMENT_FORM_SEPARATE_PAGE => 'separate page',
@@ -1511,7 +1513,7 @@ class CommentNodeAccessTest extends CommentHelperCase {
}
function setUp() {
- DrupalWebTestCase::setUp('comment', 'search', 'node_access_test');
+ WebTest::setUp('comment', 'search', 'node_access_test');
node_access_rebuild();
// Create users and test node.
diff --git a/core/modules/config/config.test b/core/modules/config/config.test
index a164108..60c74ca 100644
--- a/core/modules/config/config.test
+++ b/core/modules/config/config.test
@@ -6,11 +6,12 @@
*/
use Drupal\Core\Config\SignedFileStorage;
+use Drupal\simpletest\WebTest;
/**
* Tests the secure file writer.
*/
-class ConfigFileSecurityTestCase extends DrupalWebTestCase {
+class ConfigFileSecurityTestCase extends WebTest {
protected $profile = 'testing';
protected $filename = 'foo.bar';
@@ -89,7 +90,7 @@ class ConfigFileSecurityTestCase extends DrupalWebTestCase {
/**
* Tests reading and writing file contents.
*/
-class ConfigFileContentTestCase extends DrupalWebTestCase {
+class ConfigFileContentTestCase extends WebTest {
protected $profile = 'testing';
protected $fileExtension = 'xml';
@@ -272,7 +273,7 @@ class ConfigFileContentTestCase extends DrupalWebTestCase {
/**
* Tests configuration overriding from settings.php.
*/
-class ConfOverrideTestCase extends DrupalWebTestCase {
+class ConfOverrideTestCase extends WebTest {
protected $testContent = 'Good morning, Denver!';
public static function getInfo() {
@@ -300,7 +301,7 @@ class ConfOverrideTestCase extends DrupalWebTestCase {
/**
* Tests function providing configuration upgrade from Drupal 7 to 8.
*/
-class ConfUpdate7to8TestCase extends DrupalWebTestCase {
+class ConfUpdate7to8TestCase extends WebTest {
protected $testContent = 'Olá, Sao Paulo!';
public static function getInfo() {
diff --git a/core/modules/contact/contact.test b/core/modules/contact/contact.test
index d7f26ac..7f3c174 100644
--- a/core/modules/contact/contact.test
+++ b/core/modules/contact/contact.test
@@ -4,10 +4,12 @@
* Tests for the Contact module.
*/
+use Drupal\simpletest\WebTest;
+
/**
* Tests the site-wide contact form.
*/
-class ContactSitewideTestCase extends DrupalWebTestCase {
+class ContactSitewideTestCase extends WebTest {
public static function getInfo() {
return array(
'name' => 'Site-wide contact form',
@@ -298,7 +300,7 @@ class ContactSitewideTestCase extends DrupalWebTestCase {
/**
* Tests the personal contact form.
*/
-class ContactPersonalTestCase extends DrupalWebTestCase {
+class ContactPersonalTestCase extends WebTest {
private $admin_user;
private $web_user;
private $contact_user;
diff --git a/core/modules/contextual/contextual.test b/core/modules/contextual/contextual.test
index 734f7cf..60cb832 100644
--- a/core/modules/contextual/contextual.test
+++ b/core/modules/contextual/contextual.test
@@ -5,10 +5,12 @@
* Tests for contextual.module.
*/
+use Drupal\simpletest\WebTest;
+
/**
* Tests accessible links after inaccessible links on dynamic context.
*/
-class ContextualDynamicContextTestCase extends DrupalWebTestCase {
+class ContextualDynamicContextTestCase extends WebTest {
public static function getInfo() {
return array(
'name' => 'Contextual links on node lists',
diff --git a/core/modules/dashboard/dashboard.test b/core/modules/dashboard/dashboard.test
index ff37d57..8ed8c83 100644
--- a/core/modules/dashboard/dashboard.test
+++ b/core/modules/dashboard/dashboard.test
@@ -5,10 +5,13 @@
* Tests for dashboard.module.
*/
+
+use Drupal\simpletest\WebTest;
+
/**
* Tests the Dashboard module blocks.
*/
-class DashboardBlocksTestCase extends DrupalWebTestCase {
+class DashboardBlocksTestCase extends WebTest {
public static function getInfo() {
return array(
'name' => 'Dashboard blocks',
@@ -106,7 +109,7 @@ class DashboardBlocksTestCase extends DrupalWebTestCase {
}
}
-class DashboardBlockAvailabilityTestCase extends DrupalWebTestCase {
+class DashboardBlockAvailabilityTestCase extends WebTest {
protected $profile = 'standard';
public static function getInfo() {
diff --git a/core/modules/dblog/dblog.test b/core/modules/dblog/dblog.test
index 77765d7..44871a3 100644
--- a/core/modules/dblog/dblog.test
+++ b/core/modules/dblog/dblog.test
@@ -5,7 +5,10 @@
* Tests for dblog.module.
*/
-class DBLogTestCase extends DrupalWebTestCase {
+
+use Drupal\simpletest\WebTest;
+
+class DBLogTestCase extends WebTest {
protected $profile = 'standard';
protected $big_user;
diff --git a/core/modules/entity/tests/entity.test b/core/modules/entity/tests/entity.test
index 57600a3..6f78bbb 100644
--- a/core/modules/entity/tests/entity.test
+++ b/core/modules/entity/tests/entity.test
@@ -5,10 +5,12 @@
* Entity CRUD API tests.
*/
+use Drupal\simpletest\WebTest;
+
/**
* Tests the basic Entity API.
*/
-class EntityAPITestCase extends DrupalWebTestCase {
+class EntityAPITestCase extends WebTest {
public static function getInfo() {
return array(
@@ -92,7 +94,7 @@ class EntityAPITestCase extends DrupalWebTestCase {
/**
* Tests entity translation.
*/
-class EntityTranslationTestCase extends DrupalWebTestCase {
+class EntityTranslationTestCase extends WebTest {
public static function getInfo() {
return array(
@@ -202,7 +204,7 @@ class EntityTranslationTestCase extends DrupalWebTestCase {
/**
* Tests Entity API base functionality.
*/
-class EntityAPIInfoTestCase extends DrupalWebTestCase {
+class EntityAPIInfoTestCase extends WebTest {
public static function getInfo() {
return array(
diff --git a/core/modules/entity/tests/entity_crud_hook_test.test b/core/modules/entity/tests/entity_crud_hook_test.test
index be59e99..be352e4 100644
--- a/core/modules/entity/tests/entity_crud_hook_test.test
+++ b/core/modules/entity/tests/entity_crud_hook_test.test
@@ -5,6 +5,8 @@
* CRUD hook tests for the Entity CRUD API.
*/
+use Drupal\simpletest\WebTest;
+
/**
* Tests invocation of hooks when performing an action.
*
@@ -17,7 +19,7 @@
* As well as all type-specific hooks, like hook_node_insert(),
* hook_comment_update(), etc.
*/
-class EntityCrudHookTestCase extends DrupalWebTestCase {
+class EntityCrudHookTestCase extends WebTest {
protected $ids = array();
diff --git a/core/modules/entity/tests/entity_query.test b/core/modules/entity/tests/entity_query.test
index fb5dc14..b6d9227 100644
--- a/core/modules/entity/tests/entity_query.test
+++ b/core/modules/entity/tests/entity_query.test
@@ -5,10 +5,12 @@
* Unit test file for the entity API.
*/
+use Drupal\simpletest\WebTest;
+
/**
* Tests EntityFieldQuery.
*/
-class EntityFieldQueryTestCase extends DrupalWebTestCase {
+class EntityFieldQueryTestCase extends WebTest {
public static function getInfo() {
return array(
diff --git a/core/modules/field/modules/field_sql_storage/field_sql_storage.test b/core/modules/field/modules/field_sql_storage/field_sql_storage.test
index 87c388a..4dab1b3 100644
--- a/core/modules/field/modules/field_sql_storage/field_sql_storage.test
+++ b/core/modules/field/modules/field_sql_storage/field_sql_storage.test
@@ -1,6 +1,7 @@
'Field SQL Storage tests',
diff --git a/core/modules/field/modules/list/tests/list.test b/core/modules/field/modules/list/tests/list.test
index 988f6a3..671bd0a 100644
--- a/core/modules/field/modules/list/tests/list.test
+++ b/core/modules/field/modules/list/tests/list.test
@@ -5,6 +5,8 @@
* Tests for list.module.
*/
+use Drupal\simpletest\WebTest;
+
/**
* Tests for the 'List' field types.
*/
diff --git a/core/modules/field/modules/number/number.test b/core/modules/field/modules/number/number.test
index 99ec6f0..a5f805d 100644
--- a/core/modules/field/modules/number/number.test
+++ b/core/modules/field/modules/number/number.test
@@ -5,10 +5,12 @@
* Tests for number.module.
*/
+use Drupal\simpletest\WebTest;
+
/**
* Tests for number field types.
*/
-class NumberFieldTestCase extends DrupalWebTestCase {
+class NumberFieldTestCase extends WebTest {
protected $field;
protected $instance;
protected $web_user;
diff --git a/core/modules/field/modules/options/options.test b/core/modules/field/modules/options/options.test
index b945949..1d5d4d1 100644
--- a/core/modules/field/modules/options/options.test
+++ b/core/modules/field/modules/options/options.test
@@ -5,6 +5,8 @@
* Tests for options.module.
*/
+use Drupal\simpletest\WebTest;
+
class OptionsWidgetsTestCase extends FieldTestCase {
public static function getInfo() {
return array(
diff --git a/core/modules/field/modules/text/text.test b/core/modules/field/modules/text/text.test
index 0dbaccc..7c97a65 100644
--- a/core/modules/field/modules/text/text.test
+++ b/core/modules/field/modules/text/text.test
@@ -5,7 +5,9 @@
* Tests for text.module.
*/
-class TextFieldTestCase extends DrupalWebTestCase {
+use Drupal\simpletest\WebTest;
+
+class TextFieldTestCase extends WebTest {
protected $instance;
protected $admin_user;
protected $web_user;
@@ -237,7 +239,7 @@ class TextFieldTestCase extends DrupalWebTestCase {
}
}
-class TextSummaryTestCase extends DrupalWebTestCase {
+class TextSummaryTestCase extends WebTest {
protected $profile = 'standard';
public static function getInfo() {
@@ -407,7 +409,7 @@ class TextSummaryTestCase extends DrupalWebTestCase {
}
}
-class TextTranslationTestCase extends DrupalWebTestCase {
+class TextTranslationTestCase extends WebTest {
protected $profile = 'standard';
public static function getInfo() {
diff --git a/core/modules/field/tests/field.test b/core/modules/field/tests/field.test
index fc277a5..d473957 100644
--- a/core/modules/field/tests/field.test
+++ b/core/modules/field/tests/field.test
@@ -5,10 +5,12 @@
* Tests for field.module.
*/
+use Drupal\simpletest\WebTest;
+
/**
* Parent class for Field API tests.
*/
-class FieldTestCase extends DrupalWebTestCase {
+class FieldTestCase extends WebTest {
var $default_storage = 'field_sql_storage';
/**
@@ -16,7 +18,7 @@ class FieldTestCase extends DrupalWebTestCase {
*/
function setUp() {
// Since this is a base class for many test cases, support the same
- // flexibility that DrupalWebTestCase::setUp() has for the modules to be
+ // flexibility that WebTest::setUp() has for the modules to be
// passed in as either an array or a variable number of string arguments.
$modules = func_get_args();
if (isset($modules[0]) && is_array($modules[0])) {
@@ -74,7 +76,7 @@ class FieldTestCase extends DrupalWebTestCase {
class FieldAttachTestCase extends FieldTestCase {
function setUp() {
// Since this is a base class for many test cases, support the same
- // flexibility that DrupalWebTestCase::setUp() has for the modules to be
+ // flexibility that WebTest::setUp() has for the modules to be
// passed in as either an array or a variable number of string arguments.
$modules = func_get_args();
if (isset($modules[0]) && is_array($modules[0])) {
diff --git a/core/modules/field_ui/field_ui.test b/core/modules/field_ui/field_ui.test
index 9b71064..c53e949 100644
--- a/core/modules/field_ui/field_ui.test
+++ b/core/modules/field_ui/field_ui.test
@@ -5,14 +5,16 @@
* Tests for field_ui.module.
*/
+use Drupal\simpletest\WebTest;
+
/**
* Provides common functionality for the Field UI test classes.
*/
-class FieldUITestCase extends DrupalWebTestCase {
+class FieldUITestCase extends WebTest {
function setUp() {
// Since this is a base class for many test cases, support the same
- // flexibility that DrupalWebTestCase::setUp() has for the modules to be
+ // flexibility that WebTest::setUp() has for the modules to be
// passed in as either an array or a variable number of string arguments.
$modules = func_get_args();
if (isset($modules[0]) && is_array($modules[0])) {
@@ -683,7 +685,7 @@ class FieldUIManageDisplayTestCase extends FieldUITestCase {
$output = drupal_render($element);
$this->verbose(t('Rendered node - view mode: @view_mode', array('@view_mode' => $view_mode)) . '
'. $output);
- // Assign content so that DrupalWebTestCase functions can be used.
+ // Assign content so that WebTest functions can be used.
$this->drupalSetContent($output);
$method = ($not_exists ? 'assertNoText' : 'assertText');
$return = $this->{$method}((string) $text, $message);
@@ -698,7 +700,7 @@ class FieldUIManageDisplayTestCase extends FieldUITestCase {
/**
* Tests custom widget hooks and callbacks on the field administration pages.
*/
-class FieldUIAlterTestCase extends DrupalWebTestCase {
+class FieldUIAlterTestCase extends WebTest {
public static function getInfo() {
return array(
'name' => 'Widget customization',
diff --git a/core/modules/file/tests/file.test b/core/modules/file/tests/file.test
index 05083fc..8caa348 100644
--- a/core/modules/file/tests/file.test
+++ b/core/modules/file/tests/file.test
@@ -5,17 +5,19 @@
* Tests for file.module.
*/
+use Drupal\simpletest\WebTest;
+
/**
* Provides methods specifically for testing File module's field handling.
*/
-class FileFieldTestCase extends DrupalWebTestCase {
+class FileFieldTestCase extends WebTest {
protected $profile = 'standard';
protected $admin_user;
function setUp() {
// Since this is a base class for many test cases, support the same
- // flexibility that DrupalWebTestCase::setUp() has for the modules to be
+ // flexibility that WebTest::setUp() has for the modules to be
// passed in as either an array or a variable number of string arguments.
$modules = func_get_args();
if (isset($modules[0]) && is_array($modules[0])) {
diff --git a/core/modules/filter/filter.test b/core/modules/filter/filter.test
index a387f1f..c3e5865 100644
--- a/core/modules/filter/filter.test
+++ b/core/modules/filter/filter.test
@@ -5,10 +5,13 @@
* Tests for filter.module.
*/
+use Drupal\simpletest\WebTest;
+use Drupal\simpletest\UnitTest;
+
/**
* Tests for text format and filter CRUD operations.
*/
-class FilterCRUDTestCase extends DrupalWebTestCase {
+class FilterCRUDTestCase extends WebTest {
public static function getInfo() {
return array(
'name' => 'Filter CRUD operations',
@@ -160,7 +163,7 @@ class FilterCRUDTestCase extends DrupalWebTestCase {
}
}
-class FilterAdminTestCase extends DrupalWebTestCase {
+class FilterAdminTestCase extends WebTest {
protected $profile = 'standard';
public static function getInfo() {
@@ -415,7 +418,7 @@ class FilterAdminTestCase extends DrupalWebTestCase {
}
}
-class FilterFormatAccessTestCase extends DrupalWebTestCase {
+class FilterFormatAccessTestCase extends WebTest {
protected $admin_user;
protected $filter_admin_user;
protected $web_user;
@@ -662,7 +665,7 @@ class FilterFormatAccessTestCase extends DrupalWebTestCase {
}
}
-class FilterDefaultFormatTestCase extends DrupalWebTestCase {
+class FilterDefaultFormatTestCase extends WebTest {
public static function getInfo() {
return array(
'name' => 'Default text format functionality',
@@ -722,7 +725,7 @@ class FilterDefaultFormatTestCase extends DrupalWebTestCase {
}
}
-class FilterNoFormatTestCase extends DrupalWebTestCase {
+class FilterNoFormatTestCase extends WebTest {
public static function getInfo() {
return array(
'name' => 'Unassigned text format functionality',
@@ -745,7 +748,7 @@ class FilterNoFormatTestCase extends DrupalWebTestCase {
/**
* Security tests for missing/vanished text formats or filters.
*/
-class FilterSecurityTestCase extends DrupalWebTestCase {
+class FilterSecurityTestCase extends WebTest {
public static function getInfo() {
return array(
'name' => 'Security',
@@ -809,7 +812,7 @@ class FilterSecurityTestCase extends DrupalWebTestCase {
/**
* Unit tests for core filters.
*/
-class FilterUnitTestCase extends DrupalUnitTestCase {
+class FilterUnitTestCase extends UnitTest {
public static function getInfo() {
return array(
'name' => 'Filter module filters',
@@ -1795,7 +1798,7 @@ body {color:red}
/**
* Tests for filter hook invocation.
*/
-class FilterHooksTestCase extends DrupalWebTestCase {
+class FilterHooksTestCase extends WebTest {
public static function getInfo() {
return array(
'name' => 'Filter format hooks',
@@ -1857,7 +1860,7 @@ class FilterHooksTestCase extends DrupalWebTestCase {
/**
* Tests filter settings.
*/
-class FilterSettingsTestCase extends DrupalWebTestCase {
+class FilterSettingsTestCase extends WebTest {
protected $profile = 'testing';
public static function getInfo() {
diff --git a/core/modules/forum/forum.test b/core/modules/forum/forum.test
index 4991752..2a69f6e 100644
--- a/core/modules/forum/forum.test
+++ b/core/modules/forum/forum.test
@@ -5,7 +5,9 @@
* Tests for forum.module.
*/
-class ForumTestCase extends DrupalWebTestCase {
+use Drupal\simpletest\WebTest;
+
+class ForumTestCase extends WebTest {
protected $admin_user;
protected $edit_own_topics_user;
protected $edit_any_topics_user;
diff --git a/core/modules/help/help.test b/core/modules/help/help.test
index 7bffe70..b1e205d 100644
--- a/core/modules/help/help.test
+++ b/core/modules/help/help.test
@@ -5,10 +5,12 @@
* Tests for help.module.
*/
+use Drupal\simpletest\WebTest;
+
/**
* Tests help display and user access for all modules implementing help.
*/
-class HelpTestCase extends DrupalWebTestCase {
+class HelpTestCase extends WebTest {
// Tests help implementations of many arbitrary core modules.
protected $profile = 'standard';
@@ -108,7 +110,7 @@ class HelpTestCase extends DrupalWebTestCase {
/**
* Tests a module without help to verify it is not listed in the help page.
*/
-class NoHelpTestCase extends DrupalWebTestCase {
+class NoHelpTestCase extends WebTest {
/**
* The user who will be created.
*/
diff --git a/core/modules/image/image.test b/core/modules/image/image.test
index 2c422a7..3ecff38 100644
--- a/core/modules/image/image.test
+++ b/core/modules/image/image.test
@@ -5,6 +5,9 @@
* Tests for image.module.
*/
+use Drupal\simpletest\WebTest;
+use Drupal\simpletest\UnitTest;
+
/**
* TODO: Test the following functions.
*
@@ -28,7 +31,7 @@
/**
* This class provides methods specifically for testing Image's field handling.
*/
-class ImageFieldTestCase extends DrupalWebTestCase {
+class ImageFieldTestCase extends WebTest {
protected $admin_user;
function setUp() {
@@ -118,7 +121,7 @@ class ImageFieldTestCase extends DrupalWebTestCase {
/**
* Tests the functions for generating paths and URLs for image styles.
*/
-class ImageStylesPathAndUrlUnitTest extends DrupalWebTestCase {
+class ImageStylesPathAndUrlUnitTest extends WebTest {
protected $style_name;
protected $image_info;
protected $image_filepath;
@@ -881,7 +884,7 @@ class ImageFieldValidateTestCase extends ImageFieldTestCase {
/**
* Tests that images have correct dimensions when styled.
*/
-class ImageDimensionsUnitTest extends DrupalWebTestCase {
+class ImageDimensionsUnitTest extends WebTest {
protected $profile = 'testing';
public static function getInfo() {
@@ -1104,7 +1107,7 @@ class ImageDimensionsUnitTest extends DrupalWebTestCase {
/**
* Tests image_dimensions_scale().
*/
-class ImageDimensionsScaleTestCase extends DrupalUnitTestCase {
+class ImageDimensionsScaleTestCase extends UnitTest {
public static function getInfo() {
return array(
'name' => 'image_dimensions_scale()',
diff --git a/core/modules/language/language.test b/core/modules/language/language.test
index 7209dc0..74e86c5 100644
--- a/core/modules/language/language.test
+++ b/core/modules/language/language.test
@@ -9,10 +9,12 @@
* - comparison of $GLOBALS default language against dependency injection;
*/
+use Drupal\simpletest\WebTest;
+
/**
* Functional tests for the language list configuration forms.
*/
-class LanguageListTest extends DrupalWebTestCase {
+class LanguageListTest extends WebTest {
public static function getInfo() {
return array(
'name' => 'Language list configuration',
@@ -183,7 +185,7 @@ class LanguageListTest extends DrupalWebTestCase {
/**
* Test for dependency injected language object.
*/
-class LanguageDependencyInjectionTest extends DrupalWebTestCase {
+class LanguageDependencyInjectionTest extends WebTest {
public static function getInfo() {
return array(
'name' => 'Language dependency injection',
@@ -271,7 +273,7 @@ class LanguageDependencyInjectionTest extends DrupalWebTestCase {
/**
* Functional tests for the language list configuration forms.
*/
-class LanguageBlockVisibilityTest extends DrupalWebTestCase {
+class LanguageBlockVisibilityTest extends WebTest {
public static function getInfo() {
return array(
'name' => 'Language block visibility',
diff --git a/core/modules/locale/locale.test b/core/modules/locale/locale.test
index bb3c6e7..4df7e94 100644
--- a/core/modules/locale/locale.test
+++ b/core/modules/locale/locale.test
@@ -20,11 +20,13 @@
* - a functional test fot language types/negotiation info.
*/
+use Drupal\simpletest\WebTest;
+use Drupal\simpletest\UnitTest;
/**
* Functional tests for language configuration's effect on negotiation setup.
*/
-class LocaleConfigurationTest extends DrupalWebTestCase {
+class LocaleConfigurationTest extends WebTest {
public static function getInfo() {
return array(
'name' => 'Language negotiation autoconfiguration',
@@ -90,7 +92,7 @@ class LocaleConfigurationTest extends DrupalWebTestCase {
/**
* Functional tests for JavaScript parsing for translatable strings.
*/
-class LocaleJavascriptTranslationTest extends DrupalWebTestCase {
+class LocaleJavascriptTranslationTest extends WebTest {
public static function getInfo() {
return array(
'name' => 'Javascript translation',
@@ -179,7 +181,7 @@ class LocaleJavascriptTranslationTest extends DrupalWebTestCase {
/**
* Functional test for string translation and validation.
*/
-class LocaleTranslationFunctionalTest extends DrupalWebTestCase {
+class LocaleTranslationFunctionalTest extends WebTest {
public static function getInfo() {
return array(
'name' => 'String translate, search and validate',
@@ -587,7 +589,7 @@ class LocaleTranslationFunctionalTest extends DrupalWebTestCase {
/**
* Tests plural format handling functionality.
*/
-class LocalePluralFormatTest extends DrupalWebTestCase {
+class LocalePluralFormatTest extends WebTest {
public static function getInfo() {
return array(
'name' => 'Plural handling',
@@ -900,7 +902,7 @@ EOF;
/**
* Functional tests for the import of translation files.
*/
-class LocaleImportFunctionalTest extends DrupalWebTestCase {
+class LocaleImportFunctionalTest extends WebTest {
public static function getInfo() {
return array(
'name' => 'Translation import',
@@ -1377,7 +1379,7 @@ EOF;
/**
* Functional tests for the export of translation files.
*/
-class LocaleExportFunctionalTest extends DrupalWebTestCase {
+class LocaleExportFunctionalTest extends WebTest {
public static function getInfo() {
return array(
'name' => 'Translation export',
@@ -1519,7 +1521,7 @@ EOF;
/**
* Tests for the st() function.
*/
-class LocaleInstallTest extends DrupalWebTestCase {
+class LocaleInstallTest extends WebTest {
public static function getInfo() {
return array(
'name' => 'String translation using st()',
@@ -1548,7 +1550,7 @@ class LocaleInstallTest extends DrupalWebTestCase {
/**
* Locale uninstall with English UI functional test.
*/
-class LocaleUninstallFunctionalTest extends DrupalWebTestCase {
+class LocaleUninstallFunctionalTest extends WebTest {
public static function getInfo() {
return array(
'name' => 'Locale uninstall (EN)',
@@ -1694,7 +1696,7 @@ class LocaleUninstallFrenchFunctionalTest extends LocaleUninstallFunctionalTest
/**
* Functional tests for the language switching feature.
*/
-class LocaleLanguageSwitchingFunctionalTest extends DrupalWebTestCase {
+class LocaleLanguageSwitchingFunctionalTest extends WebTest {
public static function getInfo() {
return array(
@@ -1772,7 +1774,7 @@ class LocaleLanguageSwitchingFunctionalTest extends DrupalWebTestCase {
/**
* Test browser language detection.
*/
-class LocaleBrowserDetectionTest extends DrupalUnitTestCase {
+class LocaleBrowserDetectionTest extends UnitTest {
public static function getInfo() {
return array(
@@ -1893,7 +1895,7 @@ class LocaleBrowserDetectionTest extends DrupalUnitTestCase {
/**
* Functional tests for a user's ability to change their default language.
*/
-class LocaleUserLanguageFunctionalTest extends DrupalWebTestCase {
+class LocaleUserLanguageFunctionalTest extends WebTest {
public static function getInfo() {
return array(
'name' => 'User language settings',
@@ -1978,7 +1980,7 @@ class LocaleUserLanguageFunctionalTest extends DrupalWebTestCase {
/**
* Functional test for language handling during user creation.
*/
-class LocaleUserCreationTest extends DrupalWebTestCase {
+class LocaleUserCreationTest extends WebTest {
public static function getInfo() {
return array(
@@ -2082,7 +2084,7 @@ class LocaleUserCreationTest extends DrupalWebTestCase {
/**
* Functional tests for configuring a different path alias per language.
*/
-class LocalePathFunctionalTest extends DrupalWebTestCase {
+class LocalePathFunctionalTest extends WebTest {
public static function getInfo() {
return array(
'name' => 'Path language settings',
@@ -2221,7 +2223,7 @@ class LocalePathFunctionalTest extends DrupalWebTestCase {
/**
* Functional tests for multilingual support on nodes.
*/
-class LocaleContentFunctionalTest extends DrupalWebTestCase {
+class LocaleContentFunctionalTest extends WebTest {
protected $profile = 'standard';
public static function getInfo() {
@@ -2465,7 +2467,7 @@ class LocaleContentFunctionalTest extends DrupalWebTestCase {
* http://example.cn/admin/config
* UI language in Chinese
*/
-class LocaleUILanguageNegotiationTest extends DrupalWebTestCase {
+class LocaleUILanguageNegotiationTest extends WebTest {
public static function getInfo() {
return array(
'name' => 'UI language negotiation',
@@ -2759,7 +2761,7 @@ class LocaleUILanguageNegotiationTest extends DrupalWebTestCase {
/**
* Test that URL rewriting works as expected.
*/
-class LocaleUrlRewritingTest extends DrupalWebTestCase {
+class LocaleUrlRewritingTest extends WebTest {
public static function getInfo() {
return array(
'name' => 'URL rewriting',
@@ -2844,7 +2846,7 @@ class LocaleUrlRewritingTest extends DrupalWebTestCase {
/**
* Functional test for multilingual fields.
*/
-class LocaleMultilingualFieldsFunctionalTest extends DrupalWebTestCase {
+class LocaleMultilingualFieldsFunctionalTest extends WebTest {
public static function getInfo() {
return array(
'name' => 'Multilingual fields',
@@ -2971,7 +2973,7 @@ class LocaleMultilingualFieldsFunctionalTest extends DrupalWebTestCase {
/**
* Functional tests for comment language.
*/
-class LocaleCommentLanguageFunctionalTest extends DrupalWebTestCase {
+class LocaleCommentLanguageFunctionalTest extends WebTest {
protected $profile = 'standard';
public static function getInfo() {
@@ -3066,7 +3068,7 @@ class LocaleCommentLanguageFunctionalTest extends DrupalWebTestCase {
/**
* Functional tests for localizing date formats.
*/
-class LocaleDateFormatsFunctionalTest extends DrupalWebTestCase {
+class LocaleDateFormatsFunctionalTest extends WebTest {
public static function getInfo() {
return array(
@@ -3138,7 +3140,7 @@ class LocaleDateFormatsFunctionalTest extends DrupalWebTestCase {
/**
* Functional test for language types/negotiation info.
*/
-class LocaleLanguageNegotiationInfoFunctionalTest extends DrupalWebTestCase {
+class LocaleLanguageNegotiationInfoFunctionalTest extends WebTest {
public static function getInfo() {
return array(
diff --git a/core/modules/menu/menu.test b/core/modules/menu/menu.test
index e1f2aa9..42788a9 100644
--- a/core/modules/menu/menu.test
+++ b/core/modules/menu/menu.test
@@ -5,7 +5,9 @@
* Tests for menu.module.
*/
-class MenuTestCase extends DrupalWebTestCase {
+use Drupal\simpletest\WebTest;
+
+class MenuTestCase extends WebTest {
protected $profile = 'standard';
protected $big_user;
@@ -583,7 +585,7 @@ class MenuTestCase extends DrupalWebTestCase {
/**
* Test menu settings for nodes.
*/
-class MenuNodeTestCase extends DrupalWebTestCase {
+class MenuNodeTestCase extends WebTest {
protected $profile = 'standard';
public static function getInfo() {
diff --git a/core/modules/node/node.test b/core/modules/node/node.test
index 058e0e7..7fc2c84 100644
--- a/core/modules/node/node.test
+++ b/core/modules/node/node.test
@@ -1,13 +1,14 @@
'Node feed',
@@ -1932,7 +1933,7 @@ class NodeBlockFunctionalTest extends NodeWebTestCase {
/**
* Test multistep node forms basic options.
*/
-class MultiStepNodeFormBasicOptionsTest extends DrupalWebTestCase {
+class MultiStepNodeFormBasicOptionsTest extends WebTest {
public static function getInfo() {
return array(
'name' => 'Multistep node form basic options',
@@ -2428,7 +2429,7 @@ class NodeRevisionPermissionsTestCase extends NodeWebTestCase {
/**
* Tests pagination with a node access module enabled.
*/
-class NodeAccessPagerTestCase extends DrupalWebTestCase {
+class NodeAccessPagerTestCase extends WebTest {
public static function getInfo() {
return array(
diff --git a/core/modules/openid/openid.test b/core/modules/openid/openid.test
index 24e643f..dc01fdd 100644
--- a/core/modules/openid/openid.test
+++ b/core/modules/openid/openid.test
@@ -5,10 +5,12 @@
* Tests for openid.module.
*/
+use Drupal\simpletest\WebTest;
+
/**
* Base class for OpenID tests.
*/
-abstract class OpenIDWebTestCase extends DrupalWebTestCase {
+abstract class OpenIDWebTestCase extends WebTest {
function setUp() {
$modules = func_get_args();
if (isset($modules[0]) && is_array($modules[0])) {
@@ -695,7 +697,7 @@ class OpenIDRegistrationTestCase extends OpenIDWebTestCase {
/**
* Test internal helper functions.
*/
-class OpenIDUnitTest extends DrupalWebTestCase {
+class OpenIDUnitTest extends WebTest {
public static function getInfo() {
return array(
'name' => 'OpenID helper functions',
diff --git a/core/modules/path/path.test b/core/modules/path/path.test
index 4dcd611..14c66a6 100644
--- a/core/modules/path/path.test
+++ b/core/modules/path/path.test
@@ -5,10 +5,12 @@
* Tests for the Path module.
*/
+use Drupal\simpletest\WebTest;
+
/**
* Provides a base class for testing the Path module.
*/
-class PathTestCase extends DrupalWebTestCase {
+class PathTestCase extends WebTest {
function setUp() {
$modules = func_get_args();
if (isset($modules[0]) && is_array($modules[0])) {
diff --git a/core/modules/php/php.test b/core/modules/php/php.test
index f6009c7..f9abe8c 100644
--- a/core/modules/php/php.test
+++ b/core/modules/php/php.test
@@ -5,10 +5,12 @@
* Tests for php.module.
*/
+use Drupal\simpletest\WebTest;
+
/**
* Defines a base PHP test case class.
*/
-class PHPTestCase extends DrupalWebTestCase {
+class PHPTestCase extends WebTest {
protected $php_code_format;
function setUp() {
diff --git a/core/modules/poll/poll.test b/core/modules/poll/poll.test
index 3ab570c..851e2a8 100644
--- a/core/modules/poll/poll.test
+++ b/core/modules/poll/poll.test
@@ -5,7 +5,9 @@
* Tests for poll.module.
*/
-class PollWebTestCase extends DrupalWebTestCase {
+use Drupal\simpletest\WebTest;
+
+class PollWebTestCase extends WebTest {
function setUp() {
$modules = func_get_args();
if (isset($modules[0]) && is_array($modules[0])) {
@@ -93,7 +95,7 @@ class PollWebTestCase extends DrupalWebTestCase {
* @return
* An indexed array containing:
* - The generated POST values, suitable for
- * DrupalWebTestCase::drupalPost().
+ * WebTest::drupalPost().
* - The number of poll choices contained in 'edit', for potential re-usage
* in subsequent invocations of this function.
*/
@@ -434,7 +436,7 @@ class PollBlockTestCase extends PollWebTestCase {
/**
* Test adding new choices.
*/
-class PollJSAddChoice extends DrupalWebTestCase {
+class PollJSAddChoice extends WebTest {
public static function getInfo() {
return array(
diff --git a/core/modules/rdf/rdf.test b/core/modules/rdf/rdf.test
index 6c7635f..165aaf6 100644
--- a/core/modules/rdf/rdf.test
+++ b/core/modules/rdf/rdf.test
@@ -5,7 +5,9 @@
* Tests for rdf.module.
*/
-class RdfMappingHookTestCase extends DrupalWebTestCase {
+use Drupal\simpletest\WebTest;
+
+class RdfMappingHookTestCase extends WebTest {
public static function getInfo() {
return array(
'name' => 'RDF mapping hook',
@@ -41,7 +43,7 @@ class RdfMappingHookTestCase extends DrupalWebTestCase {
/**
* Test RDFa markup generation.
*/
-class RdfRdfaMarkupTestCase extends DrupalWebTestCase {
+class RdfRdfaMarkupTestCase extends WebTest {
protected $profile = 'standard';
public static function getInfo() {
@@ -210,7 +212,7 @@ class RdfRdfaMarkupTestCase extends DrupalWebTestCase {
}
}
-class RdfCrudTestCase extends DrupalWebTestCase {
+class RdfCrudTestCase extends WebTest {
public static function getInfo() {
return array(
'name' => 'RDF mapping CRUD functions',
@@ -576,7 +578,7 @@ class RdfCommentAttributesTestCase extends CommentHelperCase {
}
}
-class RdfTrackerAttributesTestCase extends DrupalWebTestCase {
+class RdfTrackerAttributesTestCase extends WebTest {
protected $profile = 'standard';
public static function getInfo() {
@@ -693,7 +695,7 @@ class RdfTrackerAttributesTestCase extends DrupalWebTestCase {
/**
* Tests for RDF namespaces declaration with hook_rdf_namespaces().
*/
-class RdfGetRdfNamespacesTestCase extends DrupalWebTestCase {
+class RdfGetRdfNamespacesTestCase extends WebTest {
public static function getInfo() {
return array(
'name' => 'RDF namespaces',
@@ -723,7 +725,7 @@ class RdfGetRdfNamespacesTestCase extends DrupalWebTestCase {
/**
* Tests for RDF namespaces XML serialization.
*/
-class DrupalGetRdfNamespacesTestCase extends DrupalWebTestCase {
+class DrupalGetRdfNamespacesTestCase extends WebTest {
public static function getInfo() {
return array(
'name' => 'RDF namespaces serialization test',
diff --git a/core/modules/search/search.test b/core/modules/search/search.test
index 3fcfb0c..2582a46 100644
--- a/core/modules/search/search.test
+++ b/core/modules/search/search.test
@@ -11,7 +11,10 @@ const SEARCH_TYPE = '_test_';
const SEARCH_TYPE_2 = '_test2_';
const SEARCH_TYPE_JPN = '_test3_';
-class SearchWebTestCase extends DrupalWebTestCase {
+use Drupal\simpletest\WebTest;
+use Drupal\simpletest\UnitTest;
+
+class SearchWebTestCase extends WebTest {
function setUp() {
$modules = func_get_args();
if (isset($modules[0]) && is_array($modules[0])) {
@@ -965,7 +968,7 @@ class SearchCommentTestCase extends SearchWebTestCase {
*
* @see http://drupal.org/node/419388 (issue)
*/
-class SearchExpressionInsertExtractTestCase extends DrupalUnitTestCase {
+class SearchExpressionInsertExtractTestCase extends UnitTest {
public static function getInfo() {
return array(
'name' => 'Search expression insert/extract',
@@ -1583,7 +1586,7 @@ class SearchConfigSettingsForm extends SearchWebTestCase {
/**
* Tests the search_excerpt() function.
*/
-class SearchExcerptTestCase extends DrupalUnitTestCase {
+class SearchExcerptTestCase extends UnitTest {
public static function getInfo() {
return array(
'name' => 'Search excerpt extraction',
diff --git a/core/modules/shortcut/shortcut.test b/core/modules/shortcut/shortcut.test
index 550c10c..fc1b933 100644
--- a/core/modules/shortcut/shortcut.test
+++ b/core/modules/shortcut/shortcut.test
@@ -5,10 +5,12 @@
* Tests for shortcut.module.
*/
+use Drupal\simpletest\WebTest;
+
/**
* Defines base class for shortcut test cases.
*/
-class ShortcutTestCase extends DrupalWebTestCase {
+class ShortcutTestCase extends WebTest {
/**
* User with permission to administer shortcuts.
diff --git a/core/modules/simpletest/drupal_web_test_case.php b/core/modules/simpletest/drupal_web_test_case.php
deleted file mode 100644
index 591e8a1..0000000
--- a/core/modules/simpletest/drupal_web_test_case.php
+++ /dev/null
@@ -1,3596 +0,0 @@
- 0,
- '#fail' => 0,
- '#exception' => 0,
- '#debug' => 0,
- );
-
- /**
- * Assertions thrown in that test case.
- *
- * @var Array
- */
- protected $assertions = array();
-
- /**
- * This class is skipped when looking for the source of an assertion.
- *
- * When displaying which function an assert comes from, it's not too useful
- * to see "drupalWebTestCase->drupalLogin()', we would like to see the test
- * that called it. So we need to skip the classes defining these helper
- * methods.
- */
- protected $skipClasses = array(__CLASS__ => TRUE);
-
- /**
- * Flag to indicate whether the test has been set up.
- *
- * The setUp() method isolates the test from the parent Drupal site by
- * creating a random prefix for the database and setting up a clean file
- * storage directory. The tearDown() method then cleans up this test
- * environment. We must ensure that setUp() has been run. Otherwise,
- * tearDown() will act on the parent Drupal site rather than the test
- * environment, destroying live data.
- */
- protected $setup = FALSE;
-
- /**
- * Constructor for DrupalTestCase.
- *
- * @param $test_id
- * Tests with the same id are reported together.
- */
- public function __construct($test_id = NULL) {
- $this->testId = $test_id;
- }
-
- /**
- * Checks the matching requirements for DrupalTestCase.
- *
- * @return
- * Array of errors containing a list of unmet requirements.
- */
- protected function checkRequirements() {
- return array();
- }
-
- /**
- * Internal helper: stores the assert.
- *
- * @param $status
- * Can be 'pass', 'fail', 'exception'.
- * TRUE is a synonym for 'pass', FALSE for 'fail'.
- * @param $message
- * The message string.
- * @param $group
- * Which group this assert belongs to.
- * @param $caller
- * By default, the assert comes from a function whose name starts with
- * 'test'. Instead, you can specify where this assert originates from
- * by passing in an associative array as $caller. Key 'file' is
- * the name of the source file, 'line' is the line number and 'function'
- * is the caller function itself.
- */
- protected function assert($status, $message = '', $group = 'Other', array $caller = NULL) {
- // Convert boolean status to string status.
- if (is_bool($status)) {
- $status = $status ? 'pass' : 'fail';
- }
-
- // Increment summary result counter.
- $this->results['#' . $status]++;
-
- // Get the function information about the call to the assertion method.
- if (!$caller) {
- $caller = $this->getAssertionCall();
- }
-
- // Creation assertion array that can be displayed while tests are running.
- $this->assertions[] = $assertion = array(
- 'test_id' => $this->testId,
- 'test_class' => get_class($this),
- 'status' => $status,
- 'message' => $message,
- 'message_group' => $group,
- 'function' => $caller['function'],
- 'line' => $caller['line'],
- 'file' => $caller['file'],
- );
-
- // Store assertion for display after the test has completed.
- try {
- $connection = Database::getConnection('default', 'simpletest_original_default');
- }
- catch (ConnectionNotDefinedException $e) {
- // If the test was not set up, the simpletest_original_default
- // connection does not exist.
- $connection = Database::getConnection('default', 'default');
- }
- $connection
- ->insert('simpletest')
- ->fields($assertion)
- ->execute();
-
- // We do not use a ternary operator here to allow a breakpoint on
- // test failure.
- if ($status == 'pass') {
- return TRUE;
- }
- else {
- return FALSE;
- }
- }
-
- /**
- * Store an assertion from outside the testing context.
- *
- * This is useful for inserting assertions that can only be recorded after
- * the test case has been destroyed, such as PHP fatal errors. The caller
- * information is not automatically gathered since the caller is most likely
- * inserting the assertion on behalf of other code. In all other respects
- * the method behaves just like DrupalTestCase::assert() in terms of storing
- * the assertion.
- *
- * @return
- * Message ID of the stored assertion.
- *
- * @see DrupalTestCase::assert()
- * @see DrupalTestCase::deleteAssert()
- */
- public static function insertAssert($test_id, $test_class, $status, $message = '', $group = 'Other', array $caller = array()) {
- // Convert boolean status to string status.
- if (is_bool($status)) {
- $status = $status ? 'pass' : 'fail';
- }
-
- $caller += array(
- 'function' => t('Unknown'),
- 'line' => 0,
- 'file' => t('Unknown'),
- );
-
- $assertion = array(
- 'test_id' => $test_id,
- 'test_class' => $test_class,
- 'status' => $status,
- 'message' => $message,
- 'message_group' => $group,
- 'function' => $caller['function'],
- 'line' => $caller['line'],
- 'file' => $caller['file'],
- );
-
- return db_insert('simpletest')
- ->fields($assertion)
- ->execute();
- }
-
- /**
- * Delete an assertion record by message ID.
- *
- * @param $message_id
- * Message ID of the assertion to delete.
- * @return
- * TRUE if the assertion was deleted, FALSE otherwise.
- *
- * @see DrupalTestCase::insertAssert()
- */
- public static function deleteAssert($message_id) {
- return (bool) db_delete('simpletest')
- ->condition('message_id', $message_id)
- ->execute();
- }
-
- /**
- * Cycles through backtrace until the first non-assertion method is found.
- *
- * @return
- * Array representing the true caller.
- */
- protected function getAssertionCall() {
- $backtrace = debug_backtrace();
-
- // The first element is the call. The second element is the caller.
- // We skip calls that occurred in one of the methods of our base classes
- // or in an assertion function.
- while (($caller = $backtrace[1]) &&
- ((isset($caller['class']) && isset($this->skipClasses[$caller['class']])) ||
- substr($caller['function'], 0, 6) == 'assert')) {
- // We remove that call.
- array_shift($backtrace);
- }
-
- return _drupal_get_last_caller($backtrace);
- }
-
- /**
- * Check to see if a value is not false (not an empty string, 0, NULL, or FALSE).
- *
- * @param $value
- * The value on which the assertion is to be done.
- * @param $message
- * The message to display along with the assertion.
- * @param $group
- * The type of assertion - examples are "Browser", "PHP".
- * @return
- * TRUE if the assertion succeeded, FALSE otherwise.
- */
- protected function assertTrue($value, $message = '', $group = 'Other') {
- return $this->assert((bool) $value, $message ? $message : t('Value @value is TRUE.', array('@value' => var_export($value, TRUE))), $group);
- }
-
- /**
- * Check to see if a value is false (an empty string, 0, NULL, or FALSE).
- *
- * @param $value
- * The value on which the assertion is to be done.
- * @param $message
- * The message to display along with the assertion.
- * @param $group
- * The type of assertion - examples are "Browser", "PHP".
- * @return
- * TRUE if the assertion succeeded, FALSE otherwise.
- */
- protected function assertFalse($value, $message = '', $group = 'Other') {
- return $this->assert(!$value, $message ? $message : t('Value @value is FALSE.', array('@value' => var_export($value, TRUE))), $group);
- }
-
- /**
- * Check to see if a value is NULL.
- *
- * @param $value
- * The value on which the assertion is to be done.
- * @param $message
- * The message to display along with the assertion.
- * @param $group
- * The type of assertion - examples are "Browser", "PHP".
- * @return
- * TRUE if the assertion succeeded, FALSE otherwise.
- */
- protected function assertNull($value, $message = '', $group = 'Other') {
- return $this->assert(!isset($value), $message ? $message : t('Value @value is NULL.', array('@value' => var_export($value, TRUE))), $group);
- }
-
- /**
- * Check to see if a value is not NULL.
- *
- * @param $value
- * The value on which the assertion is to be done.
- * @param $message
- * The message to display along with the assertion.
- * @param $group
- * The type of assertion - examples are "Browser", "PHP".
- * @return
- * TRUE if the assertion succeeded, FALSE otherwise.
- */
- protected function assertNotNull($value, $message = '', $group = 'Other') {
- return $this->assert(isset($value), $message ? $message : t('Value @value is not NULL.', array('@value' => var_export($value, TRUE))), $group);
- }
-
- /**
- * Check to see if two values are equal.
- *
- * @param $first
- * The first value to check.
- * @param $second
- * The second value to check.
- * @param $message
- * The message to display along with the assertion.
- * @param $group
- * The type of assertion - examples are "Browser", "PHP".
- * @return
- * TRUE if the assertion succeeded, FALSE otherwise.
- */
- protected function assertEqual($first, $second, $message = '', $group = 'Other') {
- return $this->assert($first == $second, $message ? $message : t('Value @first is equal to value @second.', array('@first' => var_export($first, TRUE), '@second' => var_export($second, TRUE))), $group);
- }
-
- /**
- * Check to see if two values are not equal.
- *
- * @param $first
- * The first value to check.
- * @param $second
- * The second value to check.
- * @param $message
- * The message to display along with the assertion.
- * @param $group
- * The type of assertion - examples are "Browser", "PHP".
- * @return
- * TRUE if the assertion succeeded, FALSE otherwise.
- */
- protected function assertNotEqual($first, $second, $message = '', $group = 'Other') {
- return $this->assert($first != $second, $message ? $message : t('Value @first is not equal to value @second.', array('@first' => var_export($first, TRUE), '@second' => var_export($second, TRUE))), $group);
- }
-
- /**
- * Check to see if two values are identical.
- *
- * @param $first
- * The first value to check.
- * @param $second
- * The second value to check.
- * @param $message
- * The message to display along with the assertion.
- * @param $group
- * The type of assertion - examples are "Browser", "PHP".
- * @return
- * TRUE if the assertion succeeded, FALSE otherwise.
- */
- protected function assertIdentical($first, $second, $message = '', $group = 'Other') {
- return $this->assert($first === $second, $message ? $message : t('Value @first is identical to value @second.', array('@first' => var_export($first, TRUE), '@second' => var_export($second, TRUE))), $group);
- }
-
- /**
- * Check to see if two values are not identical.
- *
- * @param $first
- * The first value to check.
- * @param $second
- * The second value to check.
- * @param $message
- * The message to display along with the assertion.
- * @param $group
- * The type of assertion - examples are "Browser", "PHP".
- * @return
- * TRUE if the assertion succeeded, FALSE otherwise.
- */
- protected function assertNotIdentical($first, $second, $message = '', $group = 'Other') {
- return $this->assert($first !== $second, $message ? $message : t('Value @first is not identical to value @second.', array('@first' => var_export($first, TRUE), '@second' => var_export($second, TRUE))), $group);
- }
-
- /**
- * Fire an assertion that is always positive.
- *
- * @param $message
- * The message to display along with the assertion.
- * @param $group
- * The type of assertion - examples are "Browser", "PHP".
- * @return
- * TRUE.
- */
- protected function pass($message = NULL, $group = 'Other') {
- return $this->assert(TRUE, $message, $group);
- }
-
- /**
- * Fire an assertion that is always negative.
- *
- * @param $message
- * The message to display along with the assertion.
- * @param $group
- * The type of assertion - examples are "Browser", "PHP".
- * @return
- * FALSE.
- */
- protected function fail($message = NULL, $group = 'Other') {
- return $this->assert(FALSE, $message, $group);
- }
-
- /**
- * Fire an error assertion.
- *
- * @param $message
- * The message to display along with the assertion.
- * @param $group
- * The type of assertion - examples are "Browser", "PHP".
- * @param $caller
- * The caller of the error.
- * @return
- * FALSE.
- */
- protected function error($message = '', $group = 'Other', array $caller = NULL) {
- if ($group == 'User notice') {
- // Since 'User notice' is set by trigger_error() which is used for debug
- // set the message to a status of 'debug'.
- return $this->assert('debug', $message, 'Debug', $caller);
- }
-
- return $this->assert('exception', $message, $group, $caller);
- }
-
- /**
- * Logs verbose message in a text file.
- *
- * The a link to the vebose message will be placed in the test results via
- * as a passing assertion with the text '[verbose message]'.
- *
- * @param $message
- * The verbose message to be stored.
- *
- * @see simpletest_verbose()
- */
- protected function verbose($message) {
- if ($id = simpletest_verbose($message)) {
- $url = file_create_url($this->originalFileDirectory . '/simpletest/verbose/' . get_class($this) . '-' . $id . '.html');
- $this->error(l(t('Verbose message'), $url, array('attributes' => array('target' => '_blank'))), 'User notice');
- }
- }
-
- /**
- * Run all tests in this class.
- *
- * Regardless of whether $methods are passed or not, only method names
- * starting with "test" are executed.
- *
- * @param $methods
- * (optional) A list of method names in the test case class to run; e.g.,
- * array('testFoo', 'testBar'). By default, all methods of the class are
- * taken into account, but it can be useful to only run a few selected test
- * methods during debugging.
- */
- public function run(array $methods = array()) {
- // Initialize verbose debugging.
- simpletest_verbose(NULL, variable_get('file_public_path', conf_path() . '/files'), get_class($this));
-
- // HTTP auth settings (:) for the simpletest browser
- // when sending requests to the test site.
- $this->httpauth_method = variable_get('simpletest_httpauth_method', CURLAUTH_BASIC);
- $username = variable_get('simpletest_httpauth_username', NULL);
- $password = variable_get('simpletest_httpauth_password', NULL);
- if ($username && $password) {
- $this->httpauth_credentials = $username . ':' . $password;
- }
-
- set_error_handler(array($this, 'errorHandler'));
- $class = get_class($this);
- // Iterate through all the methods in this class, unless a specific list of
- // methods to run was passed.
- $class_methods = get_class_methods($class);
- if ($methods) {
- $class_methods = array_intersect($class_methods, $methods);
- }
- $missing_requirements = $this->checkRequirements();
- if (!empty($missing_requirements)) {
- $missing_requirements_object = new ReflectionObject($this);
- $caller = array(
- 'file' => $missing_requirements_object->getFileName(),
- );
- foreach ($missing_requirements as $missing_requirement) {
- DrupalTestCase::insertAssert($this->testId, $class, FALSE, $missing_requirement, 'Requirements check.', $caller);
- }
- }
- else {
- foreach ($class_methods as $method) {
- // If the current method starts with "test", run it - it's a test.
- if (strtolower(substr($method, 0, 4)) == 'test') {
- // Insert a fail record. This will be deleted on completion to ensure
- // that testing completed.
- $method_info = new ReflectionMethod($class, $method);
- $caller = array(
- 'file' => $method_info->getFileName(),
- 'line' => $method_info->getStartLine(),
- 'function' => $class . '->' . $method . '()',
- );
- $completion_check_id = DrupalTestCase::insertAssert($this->testId, $class, FALSE, t('The test did not complete due to a fatal error.'), 'Completion check', $caller);
- $this->setUp();
- if ($this->setup) {
- try {
- $this->$method();
- // Finish up.
- }
- catch (Exception $e) {
- $this->exceptionHandler($e);
- }
- $this->tearDown();
- }
- else {
- $this->fail(t("The test cannot be executed because it has not been set up properly."));
- }
- // Remove the completion check record.
- DrupalTestCase::deleteAssert($completion_check_id);
- }
- }
- }
- // Clear out the error messages and restore error handler.
- drupal_get_messages();
- restore_error_handler();
- }
-
- /**
- * Handle errors during test runs.
- *
- * Because this is registered in set_error_handler(), it has to be public.
- * @see set_error_handler
- */
- public function errorHandler($severity, $message, $file = NULL, $line = NULL) {
- if ($severity & error_reporting()) {
- $error_map = array(
- E_STRICT => 'Run-time notice',
- E_WARNING => 'Warning',
- E_NOTICE => 'Notice',
- E_CORE_ERROR => 'Core error',
- E_CORE_WARNING => 'Core warning',
- E_USER_ERROR => 'User error',
- E_USER_WARNING => 'User warning',
- E_USER_NOTICE => 'User notice',
- E_RECOVERABLE_ERROR => 'Recoverable error',
- );
-
- $backtrace = debug_backtrace();
- $this->error($message, $error_map[$severity], _drupal_get_last_caller($backtrace));
- }
- return TRUE;
- }
-
- /**
- * Handle exceptions.
- *
- * @see set_exception_handler
- */
- protected function exceptionHandler($exception) {
- $backtrace = $exception->getTrace();
- // Push on top of the backtrace the call that generated the exception.
- array_unshift($backtrace, array(
- 'line' => $exception->getLine(),
- 'file' => $exception->getFile(),
- ));
- require_once DRUPAL_ROOT . '/core/includes/errors.inc';
- // The exception message is run through check_plain() by _drupal_decode_exception().
- $this->error(t('%type: !message in %function (line %line of %file).', _drupal_decode_exception($exception)), 'Uncaught exception', _drupal_get_last_caller($backtrace));
- }
-
- /**
- * Generates a random string of ASCII characters of codes 32 to 126.
- *
- * The generated string includes alpha-numeric characters and common misc
- * characters. Use this method when testing general input where the content
- * is not restricted.
- *
- * @param $length
- * Length of random string to generate.
- * @return
- * Randomly generated string.
- */
- public static function randomString($length = 8) {
- $str = '';
- for ($i = 0; $i < $length; $i++) {
- $str .= chr(mt_rand(32, 126));
- }
- return $str;
- }
-
- /**
- * Generates a random string containing letters and numbers.
- *
- * The string will always start with a letter. The letters may be upper or
- * lower case. This method is better for restricted inputs that do not
- * accept certain characters. For example, when testing input fields that
- * require machine readable values (i.e. without spaces and non-standard
- * characters) this method is best.
- *
- * @param $length
- * Length of random string to generate.
- * @return
- * Randomly generated string.
- */
- public static function randomName($length = 8) {
- $values = array_merge(range(65, 90), range(97, 122), range(48, 57));
- $max = count($values) - 1;
- $str = chr(mt_rand(97, 122));
- for ($i = 1; $i < $length; $i++) {
- $str .= chr($values[mt_rand(0, $max)]);
- }
- return $str;
- }
-
- /**
- * Converts a list of possible parameters into a stack of permutations.
- *
- * Takes a list of parameters containing possible values, and converts all of
- * them into a list of items containing every possible permutation.
- *
- * Example:
- * @code
- * $parameters = array(
- * 'one' => array(0, 1),
- * 'two' => array(2, 3),
- * );
- * $permutations = $this->permute($parameters);
- * // Result:
- * $permutations == array(
- * array('one' => 0, 'two' => 2),
- * array('one' => 1, 'two' => 2),
- * array('one' => 0, 'two' => 3),
- * array('one' => 1, 'two' => 3),
- * )
- * @endcode
- *
- * @param $parameters
- * An associative array of parameters, keyed by parameter name, and whose
- * values are arrays of parameter values.
- *
- * @return
- * A list of permutations, which is an array of arrays. Each inner array
- * contains the full list of parameters that have been passed, but with a
- * single value only.
- */
- public static function generatePermutations($parameters) {
- $all_permutations = array(array());
- foreach ($parameters as $parameter => $values) {
- $new_permutations = array();
- // Iterate over all values of the parameter.
- foreach ($values as $value) {
- // Iterate over all existing permutations.
- foreach ($all_permutations as $permutation) {
- // Add the new parameter value to existing permutations.
- $new_permutations[] = $permutation + array($parameter => $value);
- }
- }
- // Replace the old permutations with the new permutations.
- $all_permutations = $new_permutations;
- }
- return $all_permutations;
- }
-}
-
-/**
- * Test case for Drupal unit tests.
- *
- * These tests can not access the database nor files. Calling any Drupal
- * function that needs the database will throw exceptions. These include
- * watchdog(), module_implements(), module_invoke_all() etc.
- */
-class DrupalUnitTestCase extends DrupalTestCase {
-
- /**
- * Constructor for DrupalUnitTestCase.
- */
- function __construct($test_id = NULL) {
- parent::__construct($test_id);
- $this->skipClasses[__CLASS__] = TRUE;
- }
-
- /**
- * Sets up unit test environment.
- *
- * Unlike DrupalWebTestCase::setUp(), DrupalUnitTestCase::setUp() does not
- * install modules because tests are performed without accessing the database.
- * Any required files must be explicitly included by the child class setUp()
- * method.
- */
- protected function setUp() {
- global $conf;
-
- // Store necessary current values before switching to the test environment.
- $this->originalFileDirectory = variable_get('file_public_path', conf_path() . '/files');
-
- // Reset all statics so that test is performed with a clean environment.
- drupal_static_reset();
-
- // Generate temporary prefixed database to ensure that tests have a clean starting point.
- $this->databasePrefix = Database::getConnection()->prefixTables('{simpletest' . mt_rand(1000, 1000000) . '}');
-
- // Create test directory.
- $public_files_directory = $this->originalFileDirectory . '/simpletest/' . substr($this->databasePrefix, 10);
- file_prepare_directory($public_files_directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
- $conf['file_public_path'] = $public_files_directory;
-
- // Clone the current connection and replace the current prefix.
- $connection_info = Database::getConnectionInfo('default');
- Database::renameConnection('default', 'simpletest_original_default');
- foreach ($connection_info as $target => $value) {
- $connection_info[$target]['prefix'] = array(
- 'default' => $value['prefix']['default'] . $this->databasePrefix,
- );
- }
- Database::addConnectionInfo('default', 'default', $connection_info['default']);
-
- // Set user agent to be consistent with web test case.
- $_SERVER['HTTP_USER_AGENT'] = $this->databasePrefix;
-
- // If locale is enabled then t() will try to access the database and
- // subsequently will fail as the database is not accessible.
- $module_list = module_list();
- if (isset($module_list['locale'])) {
- $this->originalModuleList = $module_list;
- unset($module_list['locale']);
- module_list(TRUE, FALSE, FALSE, $module_list);
- }
- $this->setup = TRUE;
- }
-
- protected function tearDown() {
- global $conf;
-
- // Get back to the original connection.
- Database::removeConnection('default');
- Database::renameConnection('simpletest_original_default', 'default');
-
- $conf['file_public_path'] = $this->originalFileDirectory;
- // Restore modules if necessary.
- if (isset($this->originalModuleList)) {
- module_list(TRUE, FALSE, FALSE, $this->originalModuleList);
- }
- }
-}
-
-/**
- * Test case for typical Drupal tests.
- */
-class DrupalWebTestCase extends DrupalTestCase {
- /**
- * The profile to install as a basis for testing.
- *
- * @var string
- */
- protected $profile = 'testing';
-
- /**
- * The URL currently loaded in the internal browser.
- *
- * @var string
- */
- protected $url;
-
- /**
- * The handle of the current cURL connection.
- *
- * @var resource
- */
- protected $curlHandle;
-
- /**
- * The headers of the page currently loaded in the internal browser.
- *
- * @var Array
- */
- protected $headers;
-
- /**
- * The content of the page currently loaded in the internal browser.
- *
- * @var string
- */
- protected $content;
-
- /**
- * The content of the page currently loaded in the internal browser (plain text version).
- *
- * @var string
- */
- protected $plainTextContent;
-
- /**
- * The value of the Drupal.settings JavaScript variable for the page currently loaded in the internal browser.
- *
- * @var Array
- */
- protected $drupalSettings;
-
- /**
- * The parsed version of the page.
- *
- * @var SimpleXMLElement
- */
- protected $elements = NULL;
-
- /**
- * The current user logged in using the internal browser.
- *
- * @var bool
- */
- protected $loggedInUser = FALSE;
-
- /**
- * The current cookie file used by cURL.
- *
- * We do not reuse the cookies in further runs, so we do not need a file
- * but we still need cookie handling, so we set the jar to NULL.
- */
- protected $cookieFile = NULL;
-
- /**
- * Additional cURL options.
- *
- * DrupalWebTestCase itself never sets this but always obeys what is set.
- */
- protected $additionalCurlOptions = array();
-
- /**
- * The original user, before it was changed to a clean uid = 1 for testing purposes.
- *
- * @var object
- */
- protected $originalUser = NULL;
-
- /**
- * The original shutdown handlers array, before it was cleaned for testing purposes.
- *
- * @var array
- */
- protected $originalShutdownCallbacks = array();
-
- /**
- * HTTP authentication method
- */
- protected $httpauth_method = CURLAUTH_BASIC;
-
- /**
- * HTTP authentication credentials (:).
- */
- protected $httpauth_credentials = NULL;
-
- /**
- * The current session name, if available.
- */
- protected $session_name = NULL;
-
- /**
- * The current session ID, if available.
- */
- protected $session_id = NULL;
-
- /**
- * Whether the files were copied to the test files directory.
- */
- protected $generatedTestFiles = FALSE;
-
- /**
- * The number of redirects followed during the handling of a request.
- */
- protected $redirect_count;
-
- /**
- * Constructor for DrupalWebTestCase.
- */
- function __construct($test_id = NULL) {
- parent::__construct($test_id);
- $this->skipClasses[__CLASS__] = TRUE;
- }
-
- /**
- * Get a node from the database based on its title.
- *
- * @param $title
- * A node title, usually generated by $this->randomName().
- * @param $reset
- * (optional) Whether to reset the internal node_load() cache.
- *
- * @return
- * A node object matching $title.
- */
- function drupalGetNodeByTitle($title, $reset = FALSE) {
- $nodes = node_load_multiple(array(), array('title' => $title), $reset);
- // Load the first node returned from the database.
- $returned_node = reset($nodes);
- return $returned_node;
- }
-
- /**
- * Creates a node based on default settings.
- *
- * @param $settings
- * An associative array of settings to change from the defaults, keys are
- * node properties, for example 'title' => 'Hello, world!'.
- * @return
- * Created node object.
- */
- protected function drupalCreateNode($settings = array()) {
- // Populate defaults array.
- $settings += array(
- 'body' => array(LANGUAGE_NOT_SPECIFIED => array(array())),
- 'title' => $this->randomName(8),
- 'comment' => 2,
- 'changed' => REQUEST_TIME,
- 'moderate' => 0,
- 'promote' => 0,
- 'revision' => 1,
- 'log' => '',
- 'status' => 1,
- 'sticky' => 0,
- 'type' => 'page',
- 'revisions' => NULL,
- 'langcode' => LANGUAGE_NOT_SPECIFIED,
- );
-
- // Use the original node's created time for existing nodes.
- if (isset($settings['created']) && !isset($settings['date'])) {
- $settings['date'] = format_date($settings['created'], 'custom', 'Y-m-d H:i:s O');
- }
-
- // If the node's user uid is not specified manually, use the currently
- // logged in user if available, or else the user running the test.
- if (!isset($settings['uid'])) {
- if ($this->loggedInUser) {
- $settings['uid'] = $this->loggedInUser->uid;
- }
- else {
- global $user;
- $settings['uid'] = $user->uid;
- }
- }
-
- // Merge body field value and format separately.
- $body = array(
- 'value' => $this->randomName(32),
- 'format' => filter_default_format(),
- );
- $settings['body'][$settings['langcode']][0] += $body;
-
- $node = (object) $settings;
- node_save($node);
-
- // Small hack to link revisions to our test user.
- db_update('node_revision')
- ->fields(array('uid' => $node->uid))
- ->condition('vid', $node->vid)
- ->execute();
- return $node;
- }
-
- /**
- * Creates a custom content type based on default settings.
- *
- * @param $settings
- * An array of settings to change from the defaults.
- * Example: 'type' => 'foo'.
- * @return
- * Created content type.
- */
- protected function drupalCreateContentType($settings = array()) {
- // Find a non-existent random type name.
- do {
- $name = strtolower($this->randomName(8));
- } while (node_type_get_type($name));
-
- // Populate defaults array.
- $defaults = array(
- 'type' => $name,
- 'name' => $name,
- 'base' => 'node_content',
- 'description' => '',
- 'help' => '',
- 'title_label' => 'Title',
- 'body_label' => 'Body',
- 'has_title' => 1,
- 'has_body' => 1,
- );
- // Imposed values for a custom type.
- $forced = array(
- 'orig_type' => '',
- 'old_type' => '',
- 'module' => 'node',
- 'custom' => 1,
- 'modified' => 1,
- 'locked' => 0,
- );
- $type = $forced + $settings + $defaults;
- $type = (object) $type;
-
- $saved_type = node_type_save($type);
- node_types_rebuild();
- menu_rebuild();
- node_add_body_field($type);
-
- $this->assertEqual($saved_type, SAVED_NEW, t('Created content type %type.', array('%type' => $type->type)));
-
- // Reset permissions so that permissions for this content type are available.
- $this->checkPermissions(array(), TRUE);
-
- return $type;
- }
-
- /**
- * Get a list files that can be used in tests.
- *
- * @param $type
- * File type, possible values: 'binary', 'html', 'image', 'javascript', 'php', 'sql', 'text'.
- * @param $size
- * File size in bytes to match. Please check the tests/files folder.
- * @return
- * List of files that match filter.
- */
- protected function drupalGetTestFiles($type, $size = NULL) {
- if (empty($this->generatedTestFiles)) {
- // Generate binary test files.
- $lines = array(64, 1024);
- $count = 0;
- foreach ($lines as $line) {
- simpletest_generate_file('binary-' . $count++, 64, $line, 'binary');
- }
-
- // Generate text test files.
- $lines = array(16, 256, 1024, 2048, 20480);
- $count = 0;
- foreach ($lines as $line) {
- simpletest_generate_file('text-' . $count++, 64, $line);
- }
-
- // Copy other test files from simpletest.
- $original = drupal_get_path('module', 'simpletest') . '/files';
- $files = file_scan_directory($original, '/(html|image|javascript|php|sql)-.*/');
- foreach ($files as $file) {
- file_unmanaged_copy($file->uri, variable_get('file_public_path', conf_path() . '/files'));
- }
-
- $this->generatedTestFiles = TRUE;
- }
-
- $files = array();
- // Make sure type is valid.
- if (in_array($type, array('binary', 'html', 'image', 'javascript', 'php', 'sql', 'text'))) {
- $files = file_scan_directory('public://', '/' . $type . '\-.*/');
-
- // If size is set then remove any files that are not of that size.
- if ($size !== NULL) {
- foreach ($files as $file) {
- $stats = stat($file->uri);
- if ($stats['size'] != $size) {
- unset($files[$file->uri]);
- }
- }
- }
- }
- usort($files, array($this, 'drupalCompareFiles'));
- return $files;
- }
-
- /**
- * Compare two files based on size and file name.
- */
- protected function drupalCompareFiles($file1, $file2) {
- $compare_size = filesize($file1->uri) - filesize($file2->uri);
- if ($compare_size) {
- // Sort by file size.
- return $compare_size;
- }
- else {
- // The files were the same size, so sort alphabetically.
- return strnatcmp($file1->name, $file2->name);
- }
- }
-
- /**
- * Create a user with a given set of permissions.
- *
- * @param array $permissions
- * Array of permission names to assign to user. Note that the user always
- * has the default permissions derived from the "authenticated users" role.
- *
- * @return object|false
- * A fully loaded user object with pass_raw property, or FALSE if account
- * creation fails.
- */
- protected function drupalCreateUser(array $permissions = array()) {
- // Create a role with the given permission set, if any.
- $rid = FALSE;
- if ($permissions) {
- $rid = $this->drupalCreateRole($permissions);
- if (!$rid) {
- return FALSE;
- }
- }
-
- // Create a user assigned to that role.
- $edit = array();
- $edit['name'] = $this->randomName();
- $edit['mail'] = $edit['name'] . '@example.com';
- $edit['pass'] = user_password();
- $edit['status'] = 1;
- if ($rid) {
- $edit['roles'] = array($rid => $rid);
- }
-
- $account = user_save(drupal_anonymous_user(), $edit);
-
- $this->assertTrue(!empty($account->uid), t('User created with name %name and pass %pass', array('%name' => $edit['name'], '%pass' => $edit['pass'])), t('User login'));
- if (empty($account->uid)) {
- return FALSE;
- }
-
- // Add the raw password so that we can log in as this user.
- $account->pass_raw = $edit['pass'];
- return $account;
- }
-
- /**
- * Internal helper function; Create a role with specified permissions.
- *
- * @param $permissions
- * Array of permission names to assign to role.
- * @param $name
- * (optional) String for the name of the role. Defaults to a random string.
- * @return
- * Role ID of newly created role, or FALSE if role creation failed.
- */
- protected function drupalCreateRole(array $permissions, $name = NULL) {
- // Generate random name if it was not passed.
- if (!$name) {
- $name = $this->randomName();
- }
-
- // Check the all the permissions strings are valid.
- if (!$this->checkPermissions($permissions)) {
- return FALSE;
- }
-
- // Create new role.
- $role = new stdClass();
- $role->name = $name;
- user_role_save($role);
- user_role_grant_permissions($role->rid, $permissions);
-
- $this->assertTrue(isset($role->rid), t('Created role of name: @name, id: @rid', array('@name' => $name, '@rid' => (isset($role->rid) ? $role->rid : t('-n/a-')))), t('Role'));
- if ($role && !empty($role->rid)) {
- $count = db_query('SELECT COUNT(*) FROM {role_permission} WHERE rid = :rid', array(':rid' => $role->rid))->fetchField();
- $this->assertTrue($count == count($permissions), t('Created permissions: @perms', array('@perms' => implode(', ', $permissions))), t('Role'));
- return $role->rid;
- }
- else {
- return FALSE;
- }
- }
-
- /**
- * Check to make sure that the array of permissions are valid.
- *
- * @param $permissions
- * Permissions to check.
- * @param $reset
- * Reset cached available permissions.
- * @return
- * TRUE or FALSE depending on whether the permissions are valid.
- */
- protected function checkPermissions(array $permissions, $reset = FALSE) {
- $available = &drupal_static(__FUNCTION__);
-
- if (!isset($available) || $reset) {
- $available = array_keys(module_invoke_all('permission'));
- }
-
- $valid = TRUE;
- foreach ($permissions as $permission) {
- if (!in_array($permission, $available)) {
- $this->fail(t('Invalid permission %permission.', array('%permission' => $permission)), t('Role'));
- $valid = FALSE;
- }
- }
- return $valid;
- }
-
- /**
- * Log in a user with the internal browser.
- *
- * If a user is already logged in, then the current user is logged out before
- * logging in the specified user.
- *
- * Please note that neither the global $user nor the passed-in user object is
- * populated with data of the logged in user. If you need full access to the
- * user object after logging in, it must be updated manually. If you also need
- * access to the plain-text password of the user (set by drupalCreateUser()),
- * e.g. to log in the same user again, then it must be re-assigned manually.
- * For example:
- * @code
- * // Create a user.
- * $account = $this->drupalCreateUser(array());
- * $this->drupalLogin($account);
- * // Load real user object.
- * $pass_raw = $account->pass_raw;
- * $account = user_load($account->uid);
- * $account->pass_raw = $pass_raw;
- * @endcode
- *
- * @param $user
- * User object representing the user to log in.
- *
- * @see drupalCreateUser()
- */
- protected function drupalLogin(stdClass $user) {
- if ($this->loggedInUser) {
- $this->drupalLogout();
- }
-
- $edit = array(
- 'name' => $user->name,
- 'pass' => $user->pass_raw
- );
- $this->drupalPost('user', $edit, t('Log in'));
-
- // If a "log out" link appears on the page, it is almost certainly because
- // the login was successful.
- $pass = $this->assertLink(t('Log out'), 0, t('User %name successfully logged in.', array('%name' => $user->name)), t('User login'));
-
- if ($pass) {
- $this->loggedInUser = $user;
- }
- }
-
- /**
- * Generate a token for the currently logged in user.
- */
- protected function drupalGetToken($value = '') {
- $private_key = drupal_get_private_key();
- return drupal_hmac_base64($value, $this->session_id . $private_key);
- }
-
- /*
- * Logs a user out of the internal browser, then check the login page to confirm logout.
- */
- protected function drupalLogout() {
- // Make a request to the logout page, and redirect to the user page, the
- // idea being if you were properly logged out you should be seeing a login
- // screen.
- $this->drupalGet('user/logout');
- $this->drupalGet('user');
- $pass = $this->assertField('name', t('Username field found.'), t('Logout'));
- $pass = $pass && $this->assertField('pass', t('Password field found.'), t('Logout'));
-
- if ($pass) {
- $this->loggedInUser = FALSE;
- }
- }
-
- /**
- * Generates a random database prefix, runs the install scripts on the
- * prefixed database and enable the specified modules. After installation
- * many caches are flushed and the internal browser is setup so that the
- * page requests will run on the new prefix. A temporary files directory
- * is created with the same name as the database prefix.
- *
- * @param ...
- * List of modules to enable for the duration of the test. This can be
- * either a single array or a variable number of string arguments.
- */
- protected function setUp() {
- global $user, $language_interface, $conf;
-
- // Generate a temporary prefixed database to ensure that tests have a clean starting point.
- $this->databasePrefix = 'simpletest' . mt_rand(1000, 1000000);
- db_update('simpletest_test_id')
- ->fields(array('last_prefix' => $this->databasePrefix))
- ->condition('test_id', $this->testId)
- ->execute();
-
- // Reset all statics and variables to perform tests in a clean environment.
- $conf = array();
- drupal_static_reset();
-
- // Clone the current connection and replace the current prefix.
- $connection_info = Database::getConnectionInfo('default');
- Database::renameConnection('default', 'simpletest_original_default');
- foreach ($connection_info as $target => $value) {
- $connection_info[$target]['prefix'] = array(
- 'default' => $value['prefix']['default'] . $this->databasePrefix,
- );
- }
- Database::addConnectionInfo('default', 'default', $connection_info['default']);
-
- // Store necessary current values before switching to prefixed database.
- $this->originalLanguage = $language_interface;
- $this->originalLanguageDefault = variable_get('language_default');
- $this->originalConfigDirectory = $GLOBALS['config_directory_name'];
- $this->originalConfigSignatureKey = $GLOBALS['config_signature_key'];
- $this->originalFileDirectory = variable_get('file_public_path', conf_path() . '/files');
- $this->originalProfile = drupal_get_profile();
- $clean_url_original = variable_get('clean_url', 0);
-
- // Set to English to prevent exceptions from utf8_truncate() from t()
- // during install if the current language is not 'en'.
- // The following array/object conversion is copied from language_default().
- $language = (object) array(
- 'langcode' => 'en',
- 'name' => 'English',
- 'direction' => 0,
- 'enabled' => 1,
- 'weight' => 0,
- );
-
- // Save and clean shutdown callbacks array because it static cached and
- // will be changed by the test run. If we don't, then it will contain
- // callbacks from both environments. So testing environment will try
- // to call handlers from original environment.
- $callbacks = &drupal_register_shutdown_function();
- $this->originalShutdownCallbacks = $callbacks;
- $callbacks = array();
-
- // Create test directory ahead of installation so fatal errors and debug
- // information can be logged during installation process.
- // Use temporary files directory with the same prefix as the database.
- $public_files_directory = $this->originalFileDirectory . '/simpletest/' . substr($this->databasePrefix, 10);
- $private_files_directory = $public_files_directory . '/private';
- $temp_files_directory = $private_files_directory . '/temp';
-
- // Create the directories
- file_prepare_directory($public_files_directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
- file_prepare_directory($private_files_directory, FILE_CREATE_DIRECTORY);
- file_prepare_directory($temp_files_directory, FILE_CREATE_DIRECTORY);
- $this->generatedTestFiles = FALSE;
-
- // Create and set a new configuration directory and signature key.
- // The child site automatically adjusts the global $config_directory_name to
- // a test-prefix-specific directory within the public files directory.
- // @see config_get_config_directory()
- $GLOBALS['config_directory_name'] = 'simpletest/' . substr($this->databasePrefix, 10) . '/config';
- $this->configFileDirectory = $this->originalFileDirectory . '/' . $GLOBALS['config_directory_name'];
- file_prepare_directory($this->configFileDirectory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
- $GLOBALS['config_signature_key'] = drupal_hash_base64(drupal_random_bytes(55));
-
- // Log fatal errors.
- ini_set('log_errors', 1);
- ini_set('error_log', $public_files_directory . '/error.log');
-
- // Set the test information for use in other parts of Drupal.
- $test_info = &$GLOBALS['drupal_test_info'];
- $test_info['test_run_id'] = $this->databasePrefix;
- $test_info['in_child_site'] = FALSE;
-
- // Preset the 'install_profile' system variable, so the first call into
- // system_rebuild_module_data() (in drupal_install_system()) will register
- // the test's profile as a module. Without this, the installation profile of
- // the parent site (executing the test) is registered, and the test
- // profile's hook_install() and other hook implementations are never invoked.
- $conf['install_profile'] = $this->profile;
-
- include_once DRUPAL_ROOT . '/core/includes/install.inc';
- drupal_install_system();
-
- $this->preloadRegistry();
-
- // Set path variables.
- variable_set('file_public_path', $public_files_directory);
- variable_set('file_private_path', $private_files_directory);
- variable_set('file_temporary_path', $temp_files_directory);
-
- // Set the 'simpletest_parent_profile' variable to add the parent profile's
- // search path to the child site's search paths.
- // @see drupal_system_listing()
- // @todo This may need to be primed like 'install_profile' above.
- variable_set('simpletest_parent_profile', $this->originalProfile);
-
- // Include the testing profile.
- variable_set('install_profile', $this->profile);
- $profile_details = install_profile_info($this->profile, 'en');
-
- // Install the modules specified by the testing profile.
- module_enable($profile_details['dependencies'], FALSE);
-
- // Install modules needed for this test. This could have been passed in as
- // either a single array argument or a variable number of string arguments.
- // @todo Remove this compatibility layer in Drupal 8, and only accept
- // $modules as a single array argument.
- $modules = func_get_args();
- if (isset($modules[0]) && is_array($modules[0])) {
- $modules = $modules[0];
- }
- if ($modules) {
- $success = module_enable($modules, TRUE);
- $this->assertTrue($success, t('Enabled modules: %modules', array('%modules' => implode(', ', $modules))));
- }
-
- // Run the profile tasks.
- $install_profile_module_exists = db_query("SELECT 1 FROM {system} WHERE type = 'module' AND name = :name", array(
- ':name' => $this->profile,
- ))->fetchField();
- if ($install_profile_module_exists) {
- module_enable(array($this->profile), FALSE);
- }
-
- // Reset/rebuild all data structures after enabling the modules.
- $this->resetAll();
-
- // Run cron once in that environment, as install.php does at the end of
- // the installation process.
- drupal_cron_run();
-
- // Log in with a clean $user.
- $this->originalUser = $user;
- drupal_save_session(FALSE);
- $user = user_load(1);
-
- // Restore necessary variables.
- variable_set('install_task', 'done');
- variable_set('clean_url', $clean_url_original);
- variable_set('site_mail', 'simpletest@example.com');
- variable_set('date_default_timezone', date_default_timezone_get());
- // Set up English language.
- unset($GLOBALS['conf']['language_default']);
- $language_interface = language_default();
-
- // Use the test mail class instead of the default mail handler class.
- variable_set('mail_system', array('default-system' => 'Drupal\Core\Mail\VariableLog'));
-
- drupal_set_time_limit($this->timeLimit);
- $this->setup = TRUE;
- }
-
- /**
- * Preload the registry from the testing site.
- *
- * This method is called by DrupalWebTestCase::setUp(), and preloads the
- * registry from the testing site to cut down on the time it takes to
- * set up a clean environment for the current test run.
- */
- protected function preloadRegistry() {
- // Use two separate queries, each with their own connections: copy the
- // {registry} and {registry_file} tables over from the parent installation
- // to the child installation.
- $original_connection = Database::getConnection('default', 'simpletest_original_default');
- $test_connection = Database::getConnection();
-
- foreach (array('registry', 'registry_file') as $table) {
- // Find the records from the parent database.
- $source_query = $original_connection
- ->select($table, array(), array('fetch' => PDO::FETCH_ASSOC))
- ->fields($table);
-
- $dest_query = $test_connection->insert($table);
-
- $first = TRUE;
- foreach ($source_query->execute() as $row) {
- if ($first) {
- $dest_query->fields(array_keys($row));
- $first = FALSE;
- }
- // Insert the records into the child database.
- $dest_query->values($row);
- }
-
- $dest_query->execute();
- }
- }
-
- /**
- * Reset all data structures after having enabled new modules.
- *
- * This method is called by DrupalWebTestCase::setUp() after enabling
- * the requested modules. It must be called again when additional modules
- * are enabled later.
- */
- protected function resetAll() {
- // Reset all static variables.
- drupal_static_reset();
- // Reset the list of enabled modules.
- module_list(TRUE);
-
- // Reset cached schema for new database prefix. This must be done before
- // drupal_flush_all_caches() so rebuilds can make use of the schema of
- // modules enabled on the cURL side.
- drupal_get_schema(NULL, TRUE);
-
- // Perform rebuilds and flush remaining caches.
- drupal_flush_all_caches();
-
- // Reload global $conf array and permissions.
- $this->refreshVariables();
- $this->checkPermissions(array(), TRUE);
- }
-
- /**
- * Refresh the in-memory set of variables. Useful after a page request is made
- * that changes a variable in a different thread.
- *
- * In other words calling a settings page with $this->drupalPost() with a changed
- * value would update a variable to reflect that change, but in the thread that
- * made the call (thread running the test) the changed variable would not be
- * picked up.
- *
- * This method clears the variables cache and loads a fresh copy from the database
- * to ensure that the most up-to-date set of variables is loaded.
- */
- protected function refreshVariables() {
- global $conf;
- cache('bootstrap')->delete('variables');
- $conf = variable_initialize();
- }
-
- /**
- * Delete created files and temporary files directory, delete the tables created by setUp(),
- * and reset the database prefix.
- */
- protected function tearDown() {
- global $user, $language_interface;
-
- // In case a fatal error occurred that was not in the test process read the
- // log to pick up any fatal errors.
- simpletest_log_read($this->testId, $this->databasePrefix, get_class($this), TRUE);
-
- $emailCount = count(variable_get('drupal_test_email_collector', array()));
- if ($emailCount) {
- $message = format_plural($emailCount, '1 e-mail was sent during this test.', '@count e-mails were sent during this test.');
- $this->pass($message, t('E-mail'));
- }
-
- // Delete temporary files directory.
- file_unmanaged_delete_recursive($this->originalFileDirectory . '/simpletest/' . substr($this->databasePrefix, 10));
-
- // Remove all prefixed tables (all the tables in the schema).
- $schema = drupal_get_schema(NULL, TRUE);
- foreach ($schema as $name => $table) {
- db_drop_table($name);
- }
-
- // Get back to the original connection.
- Database::removeConnection('default');
- Database::renameConnection('simpletest_original_default', 'default');
-
- // Restore original shutdown callbacks array to prevent original
- // environment of calling handlers from test run.
- $callbacks = &drupal_register_shutdown_function();
- $callbacks = $this->originalShutdownCallbacks;
-
- // Return the user to the original one.
- $user = $this->originalUser;
- drupal_save_session(TRUE);
-
- // Ensure that internal logged in variable and cURL options are reset.
- $this->loggedInUser = FALSE;
- $this->additionalCurlOptions = array();
-
- // Reload module list and implementations to ensure that test module hooks
- // aren't called after tests.
- module_list(TRUE);
- module_implements_reset();
-
- // Reset the Field API.
- field_cache_clear();
-
- // Rebuild caches.
- $this->refreshVariables();
-
- // Reset configuration globals.
- $GLOBALS['config_directory_name'] = $this->originalConfigDirectory;
- $GLOBALS['config_signature_key'] = $this->originalConfigSignatureKey;
-
- // Reset language.
- $language_interface = $this->originalLanguage;
- if ($this->originalLanguageDefault) {
- $GLOBALS['conf']['language_default'] = $this->originalLanguageDefault;
- }
-
- // Close the CURL handler.
- $this->curlClose();
- }
-
- /**
- * Initializes the cURL connection.
- *
- * If the simpletest_httpauth_credentials variable is set, this function will
- * add HTTP authentication headers. This is necessary for testing sites that
- * are protected by login credentials from public access.
- * See the description of $curl_options for other options.
- */
- protected function curlInitialize() {
- global $base_url;
-
- if (!isset($this->curlHandle)) {
- $this->curlHandle = curl_init();
- $curl_options = array(
- CURLOPT_COOKIEJAR => $this->cookieFile,
- CURLOPT_URL => $base_url,
- CURLOPT_FOLLOWLOCATION => FALSE,
- CURLOPT_RETURNTRANSFER => TRUE,
- CURLOPT_SSL_VERIFYPEER => FALSE, // Required to make the tests run on https.
- CURLOPT_SSL_VERIFYHOST => FALSE, // Required to make the tests run on https.
- CURLOPT_HEADERFUNCTION => array(&$this, 'curlHeaderCallback'),
- CURLOPT_USERAGENT => $this->databasePrefix,
- );
- if (isset($this->httpauth_credentials)) {
- $curl_options[CURLOPT_HTTPAUTH] = $this->httpauth_method;
- $curl_options[CURLOPT_USERPWD] = $this->httpauth_credentials;
- }
- curl_setopt_array($this->curlHandle, $this->additionalCurlOptions + $curl_options);
-
- // By default, the child session name should be the same as the parent.
- $this->session_name = session_name();
- }
- // We set the user agent header on each request so as to use the current
- // time and a new uniqid.
- if (preg_match('/simpletest\d+/', $this->databasePrefix, $matches)) {
- curl_setopt($this->curlHandle, CURLOPT_USERAGENT, drupal_generate_test_ua($matches[0]));
- }
- }
-
- /**
- * Initializes and executes a cURL request.
- *
- * @param $curl_options
- * An associative array of cURL options to set, where the keys are constants
- * defined by the cURL library. For a list of valid options, see
- * http://www.php.net/manual/function.curl-setopt.php
- * @param $redirect
- * FALSE if this is an initial request, TRUE if this request is the result
- * of a redirect.
- *
- * @return
- * The content returned from the call to curl_exec().
- *
- * @see curlInitialize()
- */
- protected function curlExec($curl_options, $redirect = FALSE) {
- $this->curlInitialize();
-
- // cURL incorrectly handles URLs with a fragment by including the
- // fragment in the request to the server, causing some web servers
- // to reject the request citing "400 - Bad Request". To prevent
- // this, we strip the fragment from the request.
- // TODO: Remove this for Drupal 8, since fixed in curl 7.20.0.
- if (!empty($curl_options[CURLOPT_URL]) && strpos($curl_options[CURLOPT_URL], '#')) {
- $original_url = $curl_options[CURLOPT_URL];
- $curl_options[CURLOPT_URL] = strtok($curl_options[CURLOPT_URL], '#');
- }
-
- $url = empty($curl_options[CURLOPT_URL]) ? curl_getinfo($this->curlHandle, CURLINFO_EFFECTIVE_URL) : $curl_options[CURLOPT_URL];
-
- if (!empty($curl_options[CURLOPT_POST])) {
- // This is a fix for the Curl library to prevent Expect: 100-continue
- // headers in POST requests, that may cause unexpected HTTP response
- // codes from some webservers (like lighttpd that returns a 417 error
- // code). It is done by setting an empty "Expect" header field that is
- // not overwritten by Curl.
- $curl_options[CURLOPT_HTTPHEADER][] = 'Expect:';
- }
- curl_setopt_array($this->curlHandle, $this->additionalCurlOptions + $curl_options);
-
- if (!$redirect) {
- // Reset headers, the session ID and the redirect counter.
- $this->session_id = NULL;
- $this->headers = array();
- $this->redirect_count = 0;
- }
-
- $content = curl_exec($this->curlHandle);
- $status = curl_getinfo($this->curlHandle, CURLINFO_HTTP_CODE);
-
- // cURL incorrectly handles URLs with fragments, so instead of
- // letting cURL handle redirects we take of them ourselves to
- // to prevent fragments being sent to the web server as part
- // of the request.
- // TODO: Remove this for Drupal 8, since fixed in curl 7.20.0.
- if (in_array($status, array(300, 301, 302, 303, 305, 307)) && $this->redirect_count < variable_get('simpletest_maximum_redirects', 5)) {
- if ($this->drupalGetHeader('location')) {
- $this->redirect_count++;
- $curl_options = array();
- $curl_options[CURLOPT_URL] = $this->drupalGetHeader('location');
- $curl_options[CURLOPT_HTTPGET] = TRUE;
- return $this->curlExec($curl_options, TRUE);
- }
- }
-
- $this->drupalSetContent($content, 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()))
- );
- $message = t('!method @url returned @status (!length).', $message_vars);
- $this->assertTrue($this->drupalGetContent() !== FALSE, $message, t('Browser'));
- return $this->drupalGetContent();
- }
-
- /**
- * Reads headers and registers errors received from the tested site.
- *
- * @see _drupal_log_error().
- *
- * @param $curlHandler
- * The cURL handler.
- * @param $header
- * An header.
- */
- protected function curlHeaderCallback($curlHandler, $header) {
- // Header fields can be extended over multiple lines by preceding each
- // extra line with at least one SP or HT. They should be joined on receive.
- // Details are in RFC2616 section 4.
- if ($header[0] == ' ' || $header[0] == "\t") {
- // Normalize whitespace between chucks.
- $this->headers[] = array_pop($this->headers) . ' ' . trim($header);
- }
- else {
- $this->headers[] = $header;
- }
-
- // Errors are being sent via X-Drupal-Assertion-* headers,
- // generated by _drupal_log_error() in the exact form required
- // by DrupalWebTestCase::error().
- if (preg_match('/^X-Drupal-Assertion-[0-9]+: (.*)$/', $header, $matches)) {
- // Call DrupalWebTestCase::error() with the parameters from the header.
- call_user_func_array(array(&$this, 'error'), unserialize(urldecode($matches[1])));
- }
-
- // Save cookies.
- if (preg_match('/^Set-Cookie: ([^=]+)=(.+)/', $header, $matches)) {
- $name = $matches[1];
- $parts = array_map('trim', explode(';', $matches[2]));
- $value = array_shift($parts);
- $this->cookies[$name] = array('value' => $value, 'secure' => in_array('secure', $parts));
- if ($name == $this->session_name) {
- if ($value != 'deleted') {
- $this->session_id = $value;
- }
- else {
- $this->session_id = NULL;
- }
- }
- }
-
- // This is required by cURL.
- return strlen($header);
- }
-
- /**
- * Close the cURL handler and unset the handler.
- */
- protected function curlClose() {
- if (isset($this->curlHandle)) {
- curl_close($this->curlHandle);
- unset($this->curlHandle);
- }
- }
-
- /**
- * 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('' . $this->drupalGetContent());
- if ($htmlDom) {
- $this->pass(t('Valid HTML found on "@path"', array('@path' => $this->getUrl())), t('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(t('Parsed page successfully.'), t('Browser'));
- }
-
- return $this->elements;
- }
-
- /**
- * Retrieves a Drupal path or an absolute path.
- *
- * @param $path
- * Drupal path or URL to load into internal browser
- * @param $options
- * Options to be forwarded to url().
- * @param $headers
- * An array containing additional HTTP request headers, each formatted as
- * "name: value".
- * @return
- * The retrieved HTML string, also available as $this->drupalGetContent()
- */
- protected function drupalGet($path, array $options = array(), array $headers = array()) {
- $options['absolute'] = TRUE;
-
- // We re-using a CURL connection here. If that connection still has certain
- // options set, it might change the GET into a POST. Make sure we clear out
- // previous options.
- $out = $this->curlExec(array(CURLOPT_HTTPGET => TRUE, CURLOPT_URL => url($path, $options), CURLOPT_NOBODY => FALSE, CURLOPT_HTTPHEADER => $headers));
- $this->refreshVariables(); // Ensure that any changes to variables in the other thread are picked up.
-
- // Replace original page output with new output from redirected page(s).
- if ($new = $this->checkForMetaRefresh()) {
- $out = $new;
- }
- $this->verbose('GET request to: ' . $path .
- 'Ending URL: ' . $this->getUrl() .
- '' . $out);
- return $out;
- }
-
- /**
- * Retrieve a Drupal path or an absolute path and JSON decode the result.
- */
- protected function drupalGetAJAX($path, array $options = array(), array $headers = array()) {
- return drupal_json_decode($this->drupalGet($path, $options, $headers));
- }
-
- /**
- * Execute a POST request on a Drupal page.
- * It will be done as usual POST request with SimpleBrowser.
- *
- * @param $path
- * Location of the post form. Either a Drupal path or an absolute path or
- * NULL to post to the current page. For multi-stage forms you can set the
- * path to NULL and have it post to the last received page. Example:
- *
- * @code
- * // First step in form.
- * $edit = array(...);
- * $this->drupalPost('some_url', $edit, t('Save'));
- *
- * // Second step in form.
- * $edit = array(...);
- * $this->drupalPost(NULL, $edit, t('Save'));
- * @endcode
- * @param $edit
- * Field data in an associative array. Changes the current input fields
- * (where possible) to the values indicated. A checkbox can be set to
- * TRUE to be checked and FALSE to be unchecked. Note that when a form
- * contains file upload fields, other fields cannot start with the '@'
- * character.
- *
- * Multiple select fields can be set using name[] and setting each of the
- * possible values. Example:
- * @code
- * $edit = array();
- * $edit['name[]'] = array('value1', 'value2');
- * @endcode
- * @param $submit
- * Value of the submit button whose click is to be emulated. For example,
- * t('Save'). The processing of the request depends on this value. For
- * example, a form may have one button with the value t('Save') and another
- * button with the value t('Delete'), and execute different code depending
- * on which one is clicked.
- *
- * This function can also be called to emulate an Ajax submission. In this
- * case, this value needs to be an array with the following keys:
- * - path: A path to submit the form values to for Ajax-specific processing,
- * which is likely different than the $path parameter used for retrieving
- * the initial form. Defaults to 'system/ajax'.
- * - triggering_element: If the value for the 'path' key is 'system/ajax' or
- * another generic Ajax processing path, this needs to be set to the name
- * of the element. If the name doesn't identify the element uniquely, then
- * this should instead be an array with a single key/value pair,
- * corresponding to the element name and value. The callback for the
- * generic Ajax processing path uses this to find the #ajax information
- * for the element, including which specific callback to use for
- * processing the request.
- *
- * This can also be set to NULL in order to emulate an Internet Explorer
- * submission of a form with a single text field, and pressing ENTER in that
- * textfield: under these conditions, no button information is added to the
- * POST data.
- * @param $options
- * Options to be forwarded to url().
- * @param $headers
- * An array containing additional HTTP request headers, each formatted as
- * "name: value".
- * @param $form_html_id
- * (optional) HTML ID of the form to be submitted. On some pages
- * there are many identical forms, so just using the value of the submit
- * button is not enough. For example: 'trigger-node-presave-assign-form'.
- * Note that this is not the Drupal $form_id, but rather the HTML ID of the
- * form, which is typically the same thing but with hyphens replacing the
- * underscores.
- * @param $extra_post
- * (optional) A string of additional data to append to the POST submission.
- * This can be used to add POST data for which there are no HTML fields, as
- * is done by drupalPostAJAX(). This string is literally appended to the
- * POST data, so it must already be urlencoded and contain a leading "&"
- * (e.g., "&extra_var1=hello+world&extra_var2=you%26me").
- */
- protected function drupalPost($path, $edit, $submit, array $options = array(), array $headers = array(), $form_html_id = NULL, $extra_post = NULL) {
- $submit_matches = FALSE;
- $ajax = is_array($submit);
- if (isset($path)) {
- $this->drupalGet($path, $options);
- }
- if ($this->parse()) {
- $edit_save = $edit;
- // Let's iterate over all the forms.
- $xpath = "//form";
- if (!empty($form_html_id)) {
- $xpath .= "[@id='" . $form_html_id . "']";
- }
- $forms = $this->xpath($xpath);
- foreach ($forms as $form) {
- // We try to set the fields of this form as specified in $edit.
- $edit = $edit_save;
- $post = array();
- $upload = array();
- $submit_matches = $this->handleForm($post, $edit, $upload, $ajax ? NULL : $submit, $form);
- $action = isset($form['action']) ? $this->getAbsoluteUrl((string) $form['action']) : $this->getUrl();
- if ($ajax) {
- $action = $this->getAbsoluteUrl(!empty($submit['path']) ? $submit['path'] : 'system/ajax');
- // Ajax callbacks verify the triggering element if necessary, so while
- // we may eventually want extra code that verifies it in the
- // handleForm() function, it's not currently a requirement.
- $submit_matches = TRUE;
- }
-
- // We post only if we managed to handle every field in edit and the
- // submit button matches.
- if (!$edit && ($submit_matches || !isset($submit))) {
- $post_array = $post;
- if ($upload) {
- // TODO: cURL handles file uploads for us, but the implementation
- // is broken. This is a less than elegant workaround. Alternatives
- // are being explored at #253506.
- foreach ($upload as $key => $file) {
- $file = drupal_realpath($file);
- if ($file && is_file($file)) {
- $post[$key] = '@' . $file;
- }
- }
- }
- else {
- foreach ($post as $key => $value) {
- // Encode according to application/x-www-form-urlencoded
- // Both names and values needs to be urlencoded, according to
- // http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4.1
- $post[$key] = urlencode($key) . '=' . urlencode($value);
- }
- $post = implode('&', $post) . $extra_post;
- }
- $out = $this->curlExec(array(CURLOPT_URL => $action, CURLOPT_POST => TRUE, CURLOPT_POSTFIELDS => $post, CURLOPT_HTTPHEADER => $headers));
- // Ensure that any changes to variables in the other thread are picked up.
- $this->refreshVariables();
-
- // Replace original page output with new output from redirected page(s).
- if ($new = $this->checkForMetaRefresh()) {
- $out = $new;
- }
- $this->verbose('POST request to: ' . $path .
- 'Ending URL: ' . $this->getUrl() .
- 'Fields: ' . highlight_string('' . $out);
- return $out;
- }
- }
- // We have not found a form which contained all fields of $edit.
- foreach ($edit as $name => $value) {
- $this->fail(t('Failed to set field @name to @value', array('@name' => $name, '@value' => $value)));
- }
- if (!$ajax && isset($submit)) {
- $this->assertTrue($submit_matches, t('Found the @submit button', array('@submit' => $submit)));
- }
- $this->fail(t('Found the requested form fields at @path', array('@path' => $path)));
- }
- }
-
- /**
- * Execute an Ajax submission.
- *
- * This executes a POST as ajax.js does. It uses the returned JSON data, an
- * array of commands, to update $this->content using equivalent DOM
- * manipulation as is used by ajax.js. It also returns the array of commands.
- *
- * @param $path
- * Location of the form containing the Ajax enabled element to test. Can be
- * either a Drupal path or an absolute path or NULL to use the current page.
- * @param $edit
- * Field data in an associative array. Changes the current input fields
- * (where possible) to the values indicated.
- * @param $triggering_element
- * The name of the form element that is responsible for triggering the Ajax
- * functionality to test. May be a string or, if the triggering element is
- * a button, an associative array where the key is the name of the button
- * and the value is the button label. i.e.) array('op' => t('Refresh')).
- * @param $ajax_path
- * (optional) Override the path set by the Ajax settings of the triggering
- * element. In the absence of both the triggering element's Ajax path and
- * $ajax_path 'system/ajax' will be used.
- * @param $options
- * (optional) Options to be forwarded to url().
- * @param $headers
- * (optional) An array containing additional HTTP request headers, each
- * formatted as "name: value". Forwarded to drupalPost().
- * @param $form_html_id
- * (optional) HTML ID of the form to be submitted, use when there is more
- * than one identical form on the same page and the value of the triggering
- * element is not enough to identify the form. Note this is not the Drupal
- * ID of the form but rather the HTML ID of the form.
- * @param $ajax_settings
- * (optional) An array of Ajax settings which if specified will be used in
- * place of the Ajax settings of the triggering element.
- *
- * @return
- * An array of Ajax commands.
- *
- * @see drupalPost()
- * @see ajax.js
- */
- protected function drupalPostAJAX($path, $edit, $triggering_element, $ajax_path = NULL, array $options = array(), array $headers = array(), $form_html_id = NULL, $ajax_settings = NULL) {
- // Get the content of the initial page prior to calling drupalPost(), since
- // drupalPost() replaces $this->content.
- if (isset($path)) {
- $this->drupalGet($path, $options);
- }
- $content = $this->content;
- $drupal_settings = $this->drupalSettings;
-
- // Get the Ajax settings bound to the triggering element.
- if (!isset($ajax_settings)) {
- if (is_array($triggering_element)) {
- $xpath = '//*[@name="' . key($triggering_element) . '" and @value="' . current($triggering_element) . '"]';
- }
- else {
- $xpath = '//*[@name="' . $triggering_element . '"]';
- }
- if (isset($form_html_id)) {
- $xpath = '//form[@id="' . $form_html_id . '"]' . $xpath;
- }
- $element = $this->xpath($xpath);
- $element_id = (string) $element[0]['id'];
- $ajax_settings = $drupal_settings['ajax'][$element_id];
- }
-
- // Add extra information to the POST data as ajax.js does.
- $extra_post = '';
- if (isset($ajax_settings['submit'])) {
- foreach ($ajax_settings['submit'] as $key => $value) {
- $extra_post .= '&' . urlencode($key) . '=' . urlencode($value);
- }
- }
- foreach ($this->xpath('//*[@id]') as $element) {
- $id = (string) $element['id'];
- $extra_post .= '&' . urlencode('ajax_html_ids[]') . '=' . urlencode($id);
- }
- if (isset($drupal_settings['ajaxPageState'])) {
- $extra_post .= '&' . urlencode('ajax_page_state[theme]') . '=' . urlencode($drupal_settings['ajaxPageState']['theme']);
- $extra_post .= '&' . urlencode('ajax_page_state[theme_token]') . '=' . urlencode($drupal_settings['ajaxPageState']['theme_token']);
- foreach ($drupal_settings['ajaxPageState']['css'] as $key => $value) {
- $extra_post .= '&' . urlencode("ajax_page_state[css][$key]") . '=1';
- }
- foreach ($drupal_settings['ajaxPageState']['js'] as $key => $value) {
- $extra_post .= '&' . urlencode("ajax_page_state[js][$key]") . '=1';
- }
- }
-
- // Unless a particular path is specified, use the one specified by the
- // Ajax settings, or else 'system/ajax'.
- if (!isset($ajax_path)) {
- $ajax_path = isset($ajax_settings['url']) ? $ajax_settings['url'] : 'system/ajax';
- }
-
- // Submit the POST request.
- $return = drupal_json_decode($this->drupalPost(NULL, $edit, array('path' => $ajax_path, 'triggering_element' => $triggering_element), $options, $headers, $form_html_id, $extra_post));
-
- // Change the page content by applying the returned commands.
- if (!empty($ajax_settings) && !empty($return)) {
- // ajax.js applies some defaults to the settings object, so do the same
- // for what's used by this function.
- $ajax_settings += array(
- 'method' => 'replaceWith',
- );
- // DOM can load HTML soup. But, HTML soup can throw warnings, suppress
- // them.
- $dom = new DOMDocument();
- @$dom->loadHTML($content);
- // XPath allows for finding wrapper nodes better than DOM does.
- $xpath = new DOMXPath($dom);
- foreach ($return as $command) {
- switch ($command['command']) {
- case 'settings':
- $drupal_settings = drupal_array_merge_deep($drupal_settings, $command['settings']);
- break;
-
- case 'insert':
- $wrapperNode = NULL;
- // When a command doesn't specify a selector, use the
- // #ajax['wrapper'] which is always an HTML ID.
- if (!isset($command['selector'])) {
- $wrapperNode = $xpath->query('//*[@id="' . $ajax_settings['wrapper'] . '"]')->item(0);
- }
- // @todo Ajax commands can target any jQuery selector, but these are
- // hard to fully emulate with XPath. For now, just handle 'head'
- // and 'body', since these are used by ajax_render().
- elseif (in_array($command['selector'], array('head', 'body'))) {
- $wrapperNode = $xpath->query('//' . $command['selector'])->item(0);
- }
- if ($wrapperNode) {
- // ajax.js adds an enclosing DIV to work around a Safari bug.
- $newDom = new DOMDocument();
- $newDom->loadHTML('
' . $command['data'] . '
');
- $newNode = $dom->importNode($newDom->documentElement->firstChild->firstChild, TRUE);
- $method = isset($command['method']) ? $command['method'] : $ajax_settings['method'];
- // The "method" is a jQuery DOM manipulation function. Emulate
- // each one using PHP's DOMNode API.
- switch ($method) {
- case 'replaceWith':
- $wrapperNode->parentNode->replaceChild($newNode, $wrapperNode);
- break;
- case 'append':
- $wrapperNode->appendChild($newNode);
- break;
- case 'prepend':
- // If no firstChild, insertBefore() falls back to
- // appendChild().
- $wrapperNode->insertBefore($newNode, $wrapperNode->firstChild);
- break;
- case 'before':
- $wrapperNode->parentNode->insertBefore($newNode, $wrapperNode);
- break;
- case 'after':
- // If no nextSibling, insertBefore() falls back to
- // appendChild().
- $wrapperNode->parentNode->insertBefore($newNode, $wrapperNode->nextSibling);
- break;
- case 'html':
- foreach ($wrapperNode->childNodes as $childNode) {
- $wrapperNode->removeChild($childNode);
- }
- $wrapperNode->appendChild($newNode);
- break;
- }
- }
- break;
-
- // @todo Add suitable implementations for these commands in order to
- // have full test coverage of what ajax.js can do.
- case 'remove':
- break;
- case 'changed':
- break;
- case 'css':
- break;
- case 'data':
- break;
- case 'restripe':
- break;
- }
- }
- $content = $dom->saveHTML();
- }
- $this->drupalSetContent($content);
- $this->drupalSetSettings($drupal_settings);
- return $return;
- }
-
- /**
- * Runs cron in the Drupal installed by Simpletest.
- */
- protected function cronRun() {
- $this->drupalGet($GLOBALS['base_url'] . '/core/cron.php', array('external' => TRUE, 'query' => array('cron_key' => variable_get('cron_key', 'drupal'))));
- }
-
- /**
- * Check for meta refresh tag and if found call drupalGet() recursively. This
- * function looks for the http-equiv attribute to be set to "Refresh"
- * and is case-sensitive.
- *
- * @return
- * Either the new page content or FALSE.
- */
- protected function checkForMetaRefresh() {
- if (strpos($this->drupalGetContent(), 'parse()) {
- $refresh = $this->xpath('//meta[@http-equiv="Refresh"]');
- if (!empty($refresh)) {
- // Parse the content attribute of the meta tag for the format:
- // "[delay]: URL=[page_to_redirect_to]".
- if (preg_match('/\d+;\s*URL=(?P.*)/i', $refresh[0]['content'], $match)) {
- return $this->drupalGet($this->getAbsoluteUrl(decode_entities($match['url'])));
- }
- }
- }
- return FALSE;
- }
-
- /**
- * Retrieves only the headers for a Drupal path or an absolute path.
- *
- * @param $path
- * Drupal path or URL to load into internal browser
- * @param $options
- * Options to be forwarded to url().
- * @param $headers
- * An array containing additional HTTP request headers, each formatted as
- * "name: value".
- * @return
- * The retrieved headers, also available as $this->drupalGetContent()
- */
- protected function drupalHead($path, array $options = array(), array $headers = array()) {
- $options['absolute'] = TRUE;
- $out = $this->curlExec(array(CURLOPT_NOBODY => TRUE, CURLOPT_URL => url($path, $options), CURLOPT_HTTPHEADER => $headers));
- $this->refreshVariables(); // Ensure that any changes to variables in the other thread are picked up.
- return $out;
- }
-
- /**
- * Handle form input related to drupalPost(). Ensure that the specified fields
- * exist and attempt to create POST data in the correct manner for the particular
- * field type.
- *
- * @param $post
- * Reference to array of post values.
- * @param $edit
- * Reference to array of edit values to be checked against the form.
- * @param $submit
- * Form submit button value.
- * @param $form
- * Array of form elements.
- * @return
- * Submit value matches a valid submit input in the form.
- */
- protected function handleForm(&$post, &$edit, &$upload, $submit, $form) {
- // Retrieve the form elements.
- $elements = $form->xpath('.//input[not(@disabled)]|.//textarea[not(@disabled)]|.//select[not(@disabled)]');
- $submit_matches = FALSE;
- foreach ($elements as $element) {
- // SimpleXML objects need string casting all the time.
- $name = (string) $element['name'];
- // This can either be the type of or the name of the tag itself
- // for