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