diff --git a/composer.json b/composer.json index 8a78ac5..15d7c13 100644 --- a/composer.json +++ b/composer.json @@ -3,8 +3,21 @@ "description": "Drupal is an open source content management platform powering millions of websites and applications.", "type": "drupal-core", "license": "GPL-2.0+", + "repositories": [ + { + "type":"git", + "url": "https://github.com/larowlan/MinkGoutteDriver.git" + }, + { + "type":"git", + "url": "https://github.com/larowlan/guzzle.git" + } + ], "require": { "php": ">=5.4.2", + "behat/mink": "~1.5", + "behat/mink-goutte-driver": "dev-master", + "fabpot/goutte": "dev-master", "sdboyer/gliph": "0.1.*", "symfony/class-loader": "2.4.*", "symfony/css-selector": "2.4.*", @@ -19,7 +32,7 @@ "twig/twig": "1.15.*", "doctrine/common": "dev-master#a45d110f71c323e29f41eb0696fa230e3fa1b1b5", "doctrine/annotations": "dev-master#463d926a8dcc49271cb7db5a08364a70ed6e3cd3", - "guzzlehttp/guzzle": "4.1.*", + "guzzlehttp/guzzle": "dev-master", "kriswallsmith/assetic": "1.1.*@alpha", "symfony-cmf/routing": "1.1.*@alpha", "easyrdf/easyrdf": "0.8.*", diff --git a/composer.lock b/composer.lock index e99a1b9..a3192aa 100644 --- a/composer.lock +++ b/composer.lock @@ -1,12 +1,166 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", - "This file is @generated automatically" + "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file" ], "hash": "d89a37ea785ca09523298ff00ade2eca", "packages": [ { + "name": "behat/mink", + "version": "v1.5.0", + "source": { + "type": "git", + "url": "https://github.com/Behat/Mink.git", + "reference": "0769e6d9726c140a54dbf827a438c0f9912749fe" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Behat/Mink/zipball/0769e6d9726c140a54dbf827a438c0f9912749fe", + "reference": "0769e6d9726c140a54dbf827a438c0f9912749fe", + "shasum": "" + }, + "require": { + "php": ">=5.3.1", + "symfony/css-selector": "~2.0" + }, + "suggest": { + "behat/mink-browserkit-driver": "extremely fast headless driver for Symfony\\Kernel-based apps (Sf2, Silex)", + "behat/mink-goutte-driver": "fast headless driver for any app without JS emulation", + "behat/mink-selenium2-driver": "slow, but JS-enabled driver for any app (requires Selenium2)", + "behat/mink-zombie-driver": "fast and JS-enabled headless driver for any app (requires node.js)" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-develop": "1.5.x-dev" + } + }, + "autoload": { + "psr-0": { + "Behat\\Mink": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + } + ], + "description": "Web acceptance testing framework for PHP 5.3", + "homepage": "http://mink.behat.org/", + "keywords": [ + "browser", + "testing", + "web" + ], + "time": "2013-04-13 23:39:27" + }, + { + "name": "behat/mink-browserkit-driver", + "version": "v1.1.0", + "source": { + "type": "git", + "url": "https://github.com/Behat/MinkBrowserKitDriver.git", + "reference": "63960c8fcad4529faad1ff33e950217980baa64c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Behat/MinkBrowserKitDriver/zipball/63960c8fcad4529faad1ff33e950217980baa64c", + "reference": "63960c8fcad4529faad1ff33e950217980baa64c", + "shasum": "" + }, + "require": { + "behat/mink": "~1.5.0", + "php": ">=5.3.1", + "symfony/browser-kit": "~2.0", + "symfony/dom-crawler": "~2.0" + }, + "require-dev": { + "silex/silex": "@dev" + }, + "type": "mink-driver", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "autoload": { + "psr-0": { + "Behat\\Mink\\Driver": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + } + ], + "description": "Symfony2 BrowserKit driver for Mink framework", + "homepage": "http://mink.behat.org/", + "keywords": [ + "Mink", + "Symfony2", + "browser", + "testing" + ], + "time": "2013-04-13 23:46:30" + }, + { + "name": "behat/mink-goutte-driver", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/larowlan/MinkGoutteDriver.git", + "reference": "488f7f02b1e907888f4b156b635693daf51d760c" + }, + "require": { + "behat/mink": "~1.5@dev", + "behat/mink-browserkit-driver": "~1.1@dev", + "fabpot/goutte": "dev-master", + "php": ">=5.4" + }, + "type": "mink-driver", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "Behat\\Mink\\Driver": "src/" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + } + ], + "description": "Goutte driver for Mink framework", + "homepage": "http://mink.behat.org/", + "keywords": [ + "browser", + "goutte", + "headless", + "testing" + ], + "time": "2014-06-04 04:35:02" + }, + { "name": "doctrine/annotations", "version": "dev-master", "source": { @@ -458,20 +612,65 @@ "time": "2013-12-30 22:31:37" }, { - "name": "guzzlehttp/guzzle", - "version": "4.1.0", + "name": "fabpot/goutte", + "version": "dev-master", "source": { "type": "git", - "url": "https://github.com/guzzle/guzzle.git", - "reference": "85a0ba7de064493c928a8bcdc5eef01e0bde9953" + "url": "https://github.com/fabpot/Goutte.git", + "reference": "104ef44a9fc8a8dfe66fef5f8e8deb4567f3dc7c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/85a0ba7de064493c928a8bcdc5eef01e0bde9953", - "reference": "85a0ba7de064493c928a8bcdc5eef01e0bde9953", + "url": "https://api.github.com/repos/fabpot/Goutte/zipball/104ef44a9fc8a8dfe66fef5f8e8deb4567f3dc7c", + "reference": "104ef44a9fc8a8dfe66fef5f8e8deb4567f3dc7c", "shasum": "" }, "require": { + "guzzlehttp/guzzle": "4.*", + "php": ">=5.4.0", + "symfony/browser-kit": "~2.1", + "symfony/css-selector": "~2.1", + "symfony/dom-crawler": "~2.1" + }, + "type": "application", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "psr-0": { + "Goutte": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com", + "homepage": "http://fabien.potencier.org", + "role": "Lead Developer" + } + ], + "description": "A simple PHP Web Scraper", + "homepage": "https://github.com/fabpot/Goutte", + "keywords": [ + "scraper" + ], + "time": "2014-05-13 05:05:35" + }, + { + "name": "guzzlehttp/guzzle", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/larowlan/guzzle.git", + "reference": "56458c2819e2fe67d175bc11e9b9e472b1b6035f" + }, + "require": { "ext-json": "*", "guzzlehttp/streams": "~1.0", "php": ">=5.4.0" @@ -487,7 +686,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0.x-dev" + "dev-master": "4.1.x-dev" } }, "autoload": { @@ -498,7 +697,6 @@ "src/functions.php" ] }, - "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -512,15 +710,15 @@ "description": "Guzzle is a PHP HTTP client library and framework for building RESTful web service clients", "homepage": "http://guzzlephp.org/", "keywords": [ + "HTTP client", "client", "curl", "framework", "http", - "http client", "rest", "web service" ], - "time": "2014-05-28 05:13:19" + "time": "2014-06-04 04:09:52" }, { "name": "guzzlehttp/streams", @@ -1434,6 +1632,63 @@ "time": "2013-10-14 15:32:46" }, { + "name": "symfony/browser-kit", + "version": "v2.5.0", + "target-dir": "Symfony/Component/BrowserKit", + "source": { + "type": "git", + "url": "https://github.com/symfony/BrowserKit.git", + "reference": "cc1716dafa04277a0c987aee5bce8c3cf8939de3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/BrowserKit/zipball/cc1716dafa04277a0c987aee5bce8c3cf8939de3", + "reference": "cc1716dafa04277a0c987aee5bce8c3cf8939de3", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "symfony/dom-crawler": "~2.0" + }, + "require-dev": { + "symfony/css-selector": "~2.0", + "symfony/process": "~2.0" + }, + "suggest": { + "symfony/process": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.5-dev" + } + }, + "autoload": { + "psr-0": { + "Symfony\\Component\\BrowserKit\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com", + "homepage": "http://fabien.potencier.org", + "role": "Lead Developer" + }, + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + } + ], + "description": "Symfony BrowserKit Component", + "homepage": "http://symfony.com", + "time": "2014-05-12 09:28:39" + }, + { "name": "symfony/class-loader", "version": "v2.4.1", "target-dir": "Symfony/Component/ClassLoader", @@ -1650,6 +1905,61 @@ "time": "2014-01-01 09:02:49" }, { + "name": "symfony/dom-crawler", + "version": "v2.5.0", + "target-dir": "Symfony/Component/DomCrawler", + "source": { + "type": "git", + "url": "https://github.com/symfony/DomCrawler.git", + "reference": "6cda499120860286fe3d3d2fd631dacb7ae17f92" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/DomCrawler/zipball/6cda499120860286fe3d3d2fd631dacb7ae17f92", + "reference": "6cda499120860286fe3d3d2fd631dacb7ae17f92", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "symfony/css-selector": "~2.0" + }, + "suggest": { + "symfony/css-selector": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.5-dev" + } + }, + "autoload": { + "psr-0": { + "Symfony\\Component\\DomCrawler\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com", + "homepage": "http://fabien.potencier.org", + "role": "Lead Developer" + }, + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + } + ], + "description": "Symfony DomCrawler Component", + "homepage": "http://symfony.com", + "time": "2014-05-31 02:02:56" + }, + { "name": "symfony/event-dispatcher", "version": "v2.4.1", "target-dir": "Symfony/Component/EventDispatcher", @@ -2401,9 +2711,12 @@ ], "minimum-stability": "stable", "stability-flags": { + "behat/mink-goutte-driver": 20, + "fabpot/goutte": 20, "symfony/yaml": 20, "doctrine/common": 20, "doctrine/annotations": 20, + "guzzlehttp/guzzle": 20, "kriswallsmith/assetic": 15, "symfony-cmf/routing": 15, "phpunit/phpunit-mock-objects": 20 diff --git a/core/modules/action/src/Tests/ActionUninstallTest.php b/core/modules/action/src/Tests/ActionUninstallTest.php index f43bc0c..282e45b 100644 --- a/core/modules/action/src/Tests/ActionUninstallTest.php +++ b/core/modules/action/src/Tests/ActionUninstallTest.php @@ -7,7 +7,7 @@ namespace Drupal\action\Tests; -use Drupal\simpletest\WebTestBase; +use Drupal\simpletest\BrowserTestBase; /** * Tests that uninstalling actions does not remove other module's actions. @@ -15,7 +15,7 @@ * @group action * @see \Drupal\action\Plugin\views\field\BulkForm */ -class ActionUninstallTest extends WebTestBase { +class ActionUninstallTest extends BrowserTestBase { /** * Modules to enable. diff --git a/core/modules/action/src/Tests/BulkFormTest.php b/core/modules/action/src/Tests/BulkFormTest.php index 024780b..e4c4496 100644 --- a/core/modules/action/src/Tests/BulkFormTest.php +++ b/core/modules/action/src/Tests/BulkFormTest.php @@ -7,7 +7,7 @@ namespace Drupal\action\Tests; -use Drupal\simpletest\WebTestBase; +use Drupal\simpletest\BrowserTestBase; use Drupal\views\Views; /** @@ -16,7 +16,7 @@ * @group action * @see \Drupal\action\Plugin\views\field\BulkForm */ -class BulkFormTest extends WebTestBase { +class BulkFormTest extends BrowserTestBase { /** * Modules to enable. @@ -116,7 +116,7 @@ public function testBulkForm() { // Check the default title. $this->drupalGet('test_bulk_form'); $result = $this->xpath('//label[@for="edit-action"]'); - $this->assertEqual('With selection', (string) $result[0]); + $this->assertEqual('With selection', $result[0]->getText()); // Setup up a different bulk form title. $view = Views::getView('test_bulk_form'); @@ -126,7 +126,7 @@ public function testBulkForm() { $this->drupalGet('test_bulk_form'); $result = $this->xpath('//label[@for="edit-action"]'); - $this->assertEqual('Test title', (string) $result[0]); + $this->assertEqual('Test title', (string) $result[0]->getText()); } } diff --git a/core/modules/action/src/Tests/ConfigurationTest.php b/core/modules/action/src/Tests/ConfigurationTest.php index 512d075..fc0af8f 100644 --- a/core/modules/action/src/Tests/ConfigurationTest.php +++ b/core/modules/action/src/Tests/ConfigurationTest.php @@ -8,7 +8,7 @@ namespace Drupal\action\Tests; use Drupal\Component\Utility\Crypt; -use Drupal\simpletest\WebTestBase; +use Drupal\simpletest\BrowserTestBase; /** * Tests complex actions configuration by adding, editing, and deleting a @@ -16,7 +16,7 @@ * * @group action */ -class ConfigurationTest extends WebTestBase { +class ConfigurationTest extends BrowserTestBase { /** * Modules to enable. diff --git a/core/modules/block/src/Tests/BlockAdminThemeTest.php b/core/modules/block/src/Tests/BlockAdminThemeTest.php index 20b892c..e55c47b 100644 --- a/core/modules/block/src/Tests/BlockAdminThemeTest.php +++ b/core/modules/block/src/Tests/BlockAdminThemeTest.php @@ -7,14 +7,14 @@ namespace Drupal\block\Tests; -use Drupal\simpletest\WebTestBase; +use Drupal\simpletest\BrowserTestBase; /** * Tests the block system with admin themes. * * @group block */ -class BlockAdminThemeTest extends WebTestBase { +class BlockAdminThemeTest extends BrowserTestBase { /** * Modules to enable. diff --git a/core/modules/block/src/Tests/BlockCacheTest.php b/core/modules/block/src/Tests/BlockCacheTest.php index 635a03b..bc1ab74 100644 --- a/core/modules/block/src/Tests/BlockCacheTest.php +++ b/core/modules/block/src/Tests/BlockCacheTest.php @@ -8,14 +8,14 @@ namespace Drupal\block\Tests; use Drupal\Core\Cache\Cache; -use Drupal\simpletest\WebTestBase; +use Drupal\simpletest\BrowserTestBase; /** * Tests block caching. * * @group block */ -class BlockCacheTest extends WebTestBase { +class BlockCacheTest extends BrowserTestBase { /** * Modules to enable. diff --git a/core/modules/block/src/Tests/BlockHiddenRegionTest.php b/core/modules/block/src/Tests/BlockHiddenRegionTest.php index 3c7b238..21e709d 100644 --- a/core/modules/block/src/Tests/BlockHiddenRegionTest.php +++ b/core/modules/block/src/Tests/BlockHiddenRegionTest.php @@ -7,7 +7,7 @@ namespace Drupal\block\Tests; -use Drupal\simpletest\WebTestBase; +use Drupal\simpletest\BrowserTestBase; /** * Tests that a newly enabled theme does not inherit blocks to its hidden @@ -15,7 +15,7 @@ * * @group block */ -class BlockHiddenRegionTest extends WebTestBase { +class BlockHiddenRegionTest extends BrowserTestBase { /** * An administrative user to configure the test environment. diff --git a/core/modules/block/src/Tests/BlockHookOperationTest.php b/core/modules/block/src/Tests/BlockHookOperationTest.php index 8baf88a..12a426e 100644 --- a/core/modules/block/src/Tests/BlockHookOperationTest.php +++ b/core/modules/block/src/Tests/BlockHookOperationTest.php @@ -8,14 +8,14 @@ namespace Drupal\block\Tests; use Drupal\Component\Utility\Unicode; -use Drupal\simpletest\WebTestBase; +use Drupal\simpletest\BrowserTestBase; /** * Implement hook entity operations alter. * * @group block */ -class BlockHookOperationTest extends WebTestBase { +class BlockHookOperationTest extends BrowserTestBase { /** * Modules to enable. diff --git a/core/modules/block/src/Tests/BlockHtmlTest.php b/core/modules/block/src/Tests/BlockHtmlTest.php index 5e508e5..0e90b75 100644 --- a/core/modules/block/src/Tests/BlockHtmlTest.php +++ b/core/modules/block/src/Tests/BlockHtmlTest.php @@ -7,14 +7,14 @@ namespace Drupal\block\Tests; -use Drupal\simpletest\WebTestBase; +use Drupal\simpletest\BrowserTestBase; /** * Tests block HTML ID validity. * * @group block */ -class BlockHtmlTest extends WebTestBase { +class BlockHtmlTest extends BrowserTestBase { /** * Modules to enable. diff --git a/core/modules/block/src/Tests/BlockInvalidRegionTest.php b/core/modules/block/src/Tests/BlockInvalidRegionTest.php index ace9b01..1efce3a 100644 --- a/core/modules/block/src/Tests/BlockInvalidRegionTest.php +++ b/core/modules/block/src/Tests/BlockInvalidRegionTest.php @@ -7,7 +7,7 @@ namespace Drupal\block\Tests; -use Drupal\simpletest\WebTestBase; +use Drupal\simpletest\BrowserTestBase; /** * Tests that an active block assigned to a non-existing region triggers the @@ -15,7 +15,7 @@ * * @group block */ -class BlockInvalidRegionTest extends WebTestBase { +class BlockInvalidRegionTest extends BrowserTestBase { /** * Modules to enable. diff --git a/core/modules/block/src/Tests/BlockLanguageCacheTest.php b/core/modules/block/src/Tests/BlockLanguageCacheTest.php index f9e3bbc..35dd170 100644 --- a/core/modules/block/src/Tests/BlockLanguageCacheTest.php +++ b/core/modules/block/src/Tests/BlockLanguageCacheTest.php @@ -9,14 +9,14 @@ use Drupal\Component\Utility\Unicode; use Drupal\Core\Language\Language; -use Drupal\simpletest\WebTestBase; +use Drupal\simpletest\BrowserTestBase; /** * Tests display of menu blocks with multiple languages. * * @group block */ -class BlockLanguageCacheTest extends WebTestBase { +class BlockLanguageCacheTest extends BrowserTestBase { /** * Modules to enable. diff --git a/core/modules/block/src/Tests/BlockLanguageTest.php b/core/modules/block/src/Tests/BlockLanguageTest.php index 527cbf8..ab03311 100644 --- a/core/modules/block/src/Tests/BlockLanguageTest.php +++ b/core/modules/block/src/Tests/BlockLanguageTest.php @@ -7,7 +7,7 @@ namespace Drupal\block\Tests; -use Drupal\simpletest\WebTestBase; +use Drupal\simpletest\BrowserTestBase; /** * Tests if a block can be configure to be only visibile on a particular @@ -15,7 +15,7 @@ * * @group block */ -class BlockLanguageTest extends WebTestBase { +class BlockLanguageTest extends BrowserTestBase { /** * An administrative user to configure the test environment. diff --git a/core/modules/block/src/Tests/BlockPreprocessUnitTest.php b/core/modules/block/src/Tests/BlockPreprocessUnitTest.php index 9118e21..8112c52 100644 --- a/core/modules/block/src/Tests/BlockPreprocessUnitTest.php +++ b/core/modules/block/src/Tests/BlockPreprocessUnitTest.php @@ -7,14 +7,14 @@ namespace Drupal\block\Tests; -use Drupal\simpletest\WebTestBase; +use Drupal\simpletest\BrowserTestBase; /** * Tests the template_preprocess_block() function. * * @group block */ -class BlockPreprocessUnitTest extends WebTestBase { +class BlockPreprocessUnitTest extends BrowserTestBase { /** * Modules to enable. diff --git a/core/modules/block/src/Tests/BlockRenderOrderTest.php b/core/modules/block/src/Tests/BlockRenderOrderTest.php index bf7d0e7..6f964c5 100644 --- a/core/modules/block/src/Tests/BlockRenderOrderTest.php +++ b/core/modules/block/src/Tests/BlockRenderOrderTest.php @@ -7,14 +7,14 @@ namespace Drupal\block\Tests; -use Drupal\simpletest\WebTestBase; +use Drupal\simpletest\BrowserTestBase; /** * Tests blocks are being rendered in order by weight. * * @group block */ -class BlockRenderOrderTest extends WebTestBase { +class BlockRenderOrderTest extends BrowserTestBase { /** * Modules to enable. diff --git a/core/modules/block/src/Tests/BlockTemplateSuggestionsUnitTest.php b/core/modules/block/src/Tests/BlockTemplateSuggestionsUnitTest.php index 0a041ab..6e5b134 100644 --- a/core/modules/block/src/Tests/BlockTemplateSuggestionsUnitTest.php +++ b/core/modules/block/src/Tests/BlockTemplateSuggestionsUnitTest.php @@ -7,14 +7,14 @@ namespace Drupal\block\Tests; -use Drupal\simpletest\WebTestBase; +use Drupal\simpletest\BrowserTestBase; /** * Tests the block_theme_suggestions_block() function. * * @group block */ -class BlockTemplateSuggestionsUnitTest extends WebTestBase { +class BlockTemplateSuggestionsUnitTest extends BrowserTestBase { /** * Modules to enable. diff --git a/core/modules/block/src/Tests/BlockTestBase.php b/core/modules/block/src/Tests/BlockTestBase.php index 3ee504f..db3a481 100644 --- a/core/modules/block/src/Tests/BlockTestBase.php +++ b/core/modules/block/src/Tests/BlockTestBase.php @@ -7,12 +7,12 @@ namespace Drupal\block\Tests; -use Drupal\simpletest\WebTestBase; +use Drupal\simpletest\BrowserTestBase; /** * Provides setup and helper methods for block module tests. */ -abstract class BlockTestBase extends WebTestBase { +abstract class BlockTestBase extends BrowserTestBase { /** * Modules to enable. diff --git a/core/modules/block/src/Tests/BlockTitleXSSTest.php b/core/modules/block/src/Tests/BlockTitleXSSTest.php index c295857..dbca39f 100644 --- a/core/modules/block/src/Tests/BlockTitleXSSTest.php +++ b/core/modules/block/src/Tests/BlockTitleXSSTest.php @@ -7,14 +7,14 @@ namespace Drupal\block\Tests; -use Drupal\simpletest\WebTestBase; +use Drupal\simpletest\BrowserTestBase; /** * Tests block XSS in title. * * @group block */ -class BlockTitleXSSTest extends WebTestBase { +class BlockTitleXSSTest extends BrowserTestBase { /** * Modules to enable. diff --git a/core/modules/block/src/Tests/BlockUiTest.php b/core/modules/block/src/Tests/BlockUiTest.php index d2408da..89929b7 100644 --- a/core/modules/block/src/Tests/BlockUiTest.php +++ b/core/modules/block/src/Tests/BlockUiTest.php @@ -7,14 +7,14 @@ namespace Drupal\block\Tests; -use Drupal\simpletest\WebTestBase; +use Drupal\simpletest\BrowserTestBase; /** * Tests that the block configuration UI exists and stores data correctly. * * @group block */ -class BlockUiTest extends WebTestBase { +class BlockUiTest extends BrowserTestBase { /** * Modules to enable. @@ -100,8 +100,8 @@ function testBlockAdminUiPage() { foreach ($this->blockValues as $delta => $values) { $block = $this->blocks[$delta]; $label = $block->label(); - $element = $this->xpath('//*[@id="blocks"]/tbody/tr[' . $values['tr'] . ']/td[1]/text()'); - $this->assertTrue((string) $element[0] == $label, 'The "' . $label . '" block title is set inside the ' . $values['settings']['region'] . ' region.'); + $element = $this->xpath('//*[@id="blocks"]/tbody/tr[' . $values['tr'] . ']/td[1]'); + $this->assertTrue($element[0]->getText() == $label, 'The "' . $label . '" block title is set inside the ' . $values['settings']['region'] . ' region.'); // Look for a test block region select form element. $this->assertField('blocks[' . $values['settings']['id'] . '][region]', 'The block "' . $values['label'] . '" has a region assignment field.'); // Move the test block to the header region. diff --git a/core/modules/block/src/Tests/NewDefaultThemeBlocksTest.php b/core/modules/block/src/Tests/NewDefaultThemeBlocksTest.php index cc4f911..d0385ac 100644 --- a/core/modules/block/src/Tests/NewDefaultThemeBlocksTest.php +++ b/core/modules/block/src/Tests/NewDefaultThemeBlocksTest.php @@ -7,14 +7,14 @@ namespace Drupal\block\Tests; -use Drupal\simpletest\WebTestBase; +use Drupal\simpletest\BrowserTestBase; /** * Tests that the new default theme gets blocks. * * @group block */ -class NewDefaultThemeBlocksTest extends WebTestBase { +class NewDefaultThemeBlocksTest extends BrowserTestBase { /** * Modules to enable. diff --git a/core/modules/block/src/Tests/NonDefaultBlockAdminTest.php b/core/modules/block/src/Tests/NonDefaultBlockAdminTest.php index f7ffd37..08df8d2 100644 --- a/core/modules/block/src/Tests/NonDefaultBlockAdminTest.php +++ b/core/modules/block/src/Tests/NonDefaultBlockAdminTest.php @@ -7,14 +7,14 @@ namespace Drupal\block\Tests; -use Drupal\simpletest\WebTestBase; +use Drupal\simpletest\BrowserTestBase; /** * Tests the block administration page for a non-default theme. * * @group block */ -class NonDefaultBlockAdminTest extends WebTestBase { +class NonDefaultBlockAdminTest extends BrowserTestBase { /** * Modules to enable. diff --git a/core/modules/block_content/src/Tests/BlockContentCreationTest.php b/core/modules/block_content/src/Tests/BlockContentCreationTest.php index 9b3d914..89b2007 100644 --- a/core/modules/block_content/src/Tests/BlockContentCreationTest.php +++ b/core/modules/block_content/src/Tests/BlockContentCreationTest.php @@ -68,7 +68,7 @@ public function testBlockContentCreation() { // Go to the configure page and verify that the new view mode is correct. $this->drupalGet('admin/structure/block/manage/testblock'); - $this->assertFieldByXPath('//select[@name="settings[block_content][view_mode]"]/option[@selected="selected"]/@value', 'test_view_mode', 'View mode changed to Test View Mode'); + $this->assertFieldByXPath('//select[@name="settings[block_content][view_mode]"]/option[@selected="selected"]', 'test_view_mode', 'View mode changed to Test View Mode'); // Test the available view mode options. $this->assertOption('edit-settings-block-content-view-mode', 'default', 'The default view mode is available.'); diff --git a/core/modules/block_content/src/Tests/BlockContentTestBase.php b/core/modules/block_content/src/Tests/BlockContentTestBase.php index 4f77de4..b22df8b 100644 --- a/core/modules/block_content/src/Tests/BlockContentTestBase.php +++ b/core/modules/block_content/src/Tests/BlockContentTestBase.php @@ -7,12 +7,12 @@ namespace Drupal\block_content\Tests; -use Drupal\simpletest\WebTestBase; +use Drupal\simpletest\BrowserTestBase; /** * Sets up page and article content types. */ -abstract class BlockContentTestBase extends WebTestBase { +abstract class BlockContentTestBase extends BrowserTestBase { /** * Profile to use. diff --git a/core/modules/book/src/Tests/BookTest.php b/core/modules/book/src/Tests/BookTest.php index b72a046..a25f867 100644 --- a/core/modules/book/src/Tests/BookTest.php +++ b/core/modules/book/src/Tests/BookTest.php @@ -8,14 +8,14 @@ namespace Drupal\book\Tests; use Drupal\Core\Entity\EntityInterface; -use Drupal\simpletest\WebTestBase; +use Drupal\simpletest\BrowserTestBase; /** * Create a book, add pages, and test book interface. * * @group book */ -class BookTest extends WebTestBase { +class BookTest extends BrowserTestBase { /** * Modules to enable. @@ -209,7 +209,7 @@ function checkBookNode(EntityInterface $node, $nodes, $previous = FALSE, $up = F $links = $this->xpath('//nav[@class="breadcrumb"]/ol/li/a'); $got_breadcrumb = array(); foreach ($links as $link) { - $got_breadcrumb[] = (string) $link['href']; + $got_breadcrumb[] = $link->getAttribute('href'); } // Compare expected and got breadcrumbs. diff --git a/core/modules/ckeditor/src/Tests/CKEditorAdminTest.php b/core/modules/ckeditor/src/Tests/CKEditorAdminTest.php index 8dfe587..fd78bbb 100644 --- a/core/modules/ckeditor/src/Tests/CKEditorAdminTest.php +++ b/core/modules/ckeditor/src/Tests/CKEditorAdminTest.php @@ -9,14 +9,14 @@ use Drupal\editor\Entity\Editor; use Drupal\filter\FilterFormatInterface; -use Drupal\simpletest\WebTestBase; +use Drupal\simpletest\BrowserTestBase; /** * Tests administration of CKEditor. * * @group ckeditor */ -class CKEditorAdminTest extends WebTestBase { +class CKEditorAdminTest extends BrowserTestBase { /** * Modules to enable. @@ -61,9 +61,9 @@ function testExistingFormat() { $this->assertTrue(count($select) === 1, 'The Text Editor select exists.'); $this->assertTrue(count($select_is_disabled) === 0, 'The Text Editor select is not disabled.'); $this->assertTrue(count($options) === 2, 'The Text Editor select has two options.'); - $this->assertTrue(((string) $options[0]) === 'None', 'Option 1 in the Text Editor select is "None".'); - $this->assertTrue(((string) $options[1]) === 'CKEditor', 'Option 2 in the Text Editor select is "CKEditor".'); - $this->assertTrue(((string) $options[0]['selected']) === 'selected', 'Option 1 ("None") is selected.'); + $this->assertTrue(($options[0]->getText()) === 'None', 'Option 1 in the Text Editor select is "None".'); + $this->assertTrue(($options[1]->getText()) === 'CKEditor', 'Option 2 in the Text Editor select is "CKEditor".'); + $this->assertTrue(($options[0]->getAttribute('selected')) === 'selected', 'Option 1 ("None") is selected.'); // Select the "CKEditor" editor and click the "Save configuration" button. $edit = array( diff --git a/core/modules/config/src/Tests/ConfigSingleImportExportTest.php b/core/modules/config/src/Tests/ConfigSingleImportExportTest.php index 5609f8f..17d40ac 100644 --- a/core/modules/config/src/Tests/ConfigSingleImportExportTest.php +++ b/core/modules/config/src/Tests/ConfigSingleImportExportTest.php @@ -8,14 +8,14 @@ namespace Drupal\config\Tests; use Drupal\Component\Serialization\Yaml; -use Drupal\simpletest\WebTestBase; +use Drupal\simpletest\BrowserTestBase; /** * Tests the user interface for importing/exporting a single configuration. * * @group config */ -class ConfigSingleImportExportTest extends WebTestBase { +class ConfigSingleImportExportTest extends BrowserTestBase { /** * Modules to enable. @@ -130,13 +130,14 @@ public function testExport() { $element = $this->xpath('//select[@name="config_name"]'); $options = $this->getAllOptions($element[0]); $expected_options = array('system.site', 'user.settings'); - foreach ($options as &$option) { - $option = (string) $option; + $option_values = array(); + foreach ($options as $option) { + $option_values[] = $option->getAttribute('value'); } - $this->assertIdentical($expected_options, array_intersect($expected_options, $options), 'The expected configuration files are listed.'); + $this->assertIdentical($expected_options, array_intersect($expected_options, $option_values), 'The expected configuration files are listed.'); $this->drupalGet('admin/config/development/configuration/single/export/system.simple/system.image'); - $this->assertFieldByXPath('//textarea[@name="export"]', "toolkit: gd\n", 'The expected system configuration is displayed.'); + $this->assertTextArea('export', "toolkit: gd\n", 'The expected system configuration is displayed.'); $this->drupalGet('admin/config/development/configuration/single/export/date_format'); $this->assertFieldByXPath('//select[@name="config_type"]//option[@selected="selected"]', t('Date format'), 'The date format entity type is selected when specified in the URL.'); @@ -146,7 +147,41 @@ public function testExport() { $fallback_date = \Drupal::entityManager()->getStorage('date_format')->load('fallback'); $data = Yaml::encode($fallback_date->toArray()); - $this->assertFieldByXPath('//textarea[@name="export"]', $data, 'The fallback date format config entity export code is displayed.'); + $this->assertTextArea('export', $data, 'The fallback date format config entity export code is displayed.'); } + /** + * Assert textarea matches an expected value. + * + * BrowserKitDriver expects a form to have a submit button. Configuration + * export does not, therefore this is work around to testing textarea value. + * + * @param string $name + * Name of textarea field. + * @param string $value + * Expected value. + * @param string $message + * A message to display with the assertion. + * + * @return bool + * TRUE if the assertion succeeded, FALSE otherwise. + */ + protected function assertTextArea($name, $value, $message) { + // @todo Remove this hack, as may want to use another driver for example. + $xpath = '//textarea[@name="' . $name . '"]/text()'; + $xpath = $this->buildXPathQuery($xpath); + $elements = $this->getSession()->getPage()->findAll('xpath', $xpath); + if (empty($elements)) { + return $this->assert(FALSE, $message); + } + $reflection = new \ReflectionClass($this->getSession()->getDriver()); + $method = $reflection->getMethod('getCrawler'); + $method->setAccessible(TRUE); + $crawler = $method->invoke($this->getSession()->getDriver()); + $text = ''; + foreach ($elements as $element) { + $text .= $crawler->filterXPath($element->getXpath())->eq(0)->text(); + } + return $this->assertEqual($value, $text, $message); + } } diff --git a/core/modules/dblog/src/Tests/DbLogTest.php b/core/modules/dblog/src/Tests/DbLogTest.php index 683479f..ecd8e33 100644 --- a/core/modules/dblog/src/Tests/DbLogTest.php +++ b/core/modules/dblog/src/Tests/DbLogTest.php @@ -9,7 +9,8 @@ use Drupal\Component\Utility\Xss; use Drupal\dblog\Controller\DbLogController; -use Drupal\simpletest\WebTestBase; +use Drupal\simpletest\MinkNodeElementDecorator; +use Drupal\simpletest\BrowserTestBase; /** * Generate events and verify dblog entries; verify user access to log reports @@ -17,7 +18,7 @@ * * @group dblog */ -class DbLogTest extends WebTestBase { +class DbLogTest extends BrowserTestBase { /** * Modules to enable. @@ -278,15 +279,13 @@ private function doUser() { if ($links = $this->xpath('//a[text()="' . html_entity_decode($message_text) . '"]')) { // Found link with the message text. $links = array_shift($links); - foreach ($links->attributes() as $attr => $value) { - if ($attr == 'href') { + if ($links->hasAttribute('href')) { + $value = $links->getAttribute('href'); // Extract link to details page. - $link = drupal_substr($value, strpos($value, 'admin/reports/dblog/event/')); - $this->drupalGet($link); - // Check for full message text on the details page. - $this->assertRaw($message, 'DBLog event details was found: [delete user]'); - break; - } + $link = drupal_substr($value, strpos($value, 'admin/reports/dblog/event/')); + $this->drupalGet($link); + // Check for full message text on the details page. + $this->assertRaw($message, 'DBLog event details was found: [delete user]'); } } $this->assertTrue($link, 'DBLog event was recorded: [delete user]'); @@ -605,11 +604,11 @@ protected function getSeverityConstant($class) { * @return string * Extracted text. */ - protected function asText(\SimpleXMLElement $element) { + protected function asText(MinkNodeElementDecorator $element) { if (!is_object($element)) { return $this->fail('The element is not an element.'); } - return trim(html_entity_decode(strip_tags($element->asXML()))); + return trim(html_entity_decode(strip_tags($element->getHtml()))); } /** diff --git a/core/modules/dblog/src/Tests/Rest/DbLogResourceTest.php b/core/modules/dblog/src/Tests/Rest/DbLogResourceTest.php index f216ee6..a215ebf 100644 --- a/core/modules/dblog/src/Tests/Rest/DbLogResourceTest.php +++ b/core/modules/dblog/src/Tests/Rest/DbLogResourceTest.php @@ -47,7 +47,7 @@ public function testWatchdog() { $response = $this->httpRequest("dblog/$id", 'GET', NULL, $this->defaultMimeType); $this->assertResponse(200); - $this->assertHeader('content-type', $this->defaultMimeType); + $this->assertHeader('Content-Type', $this->defaultMimeType); $log = Json::decode($response); $this->assertEqual($log['wid'], $id, 'Log ID is correct.'); $this->assertEqual($log['type'], 'rest', 'Type of log message is correct.'); diff --git a/core/modules/entity_reference/src/Tests/EntityReferenceAdminTest.php b/core/modules/entity_reference/src/Tests/EntityReferenceAdminTest.php index 348bf4a..13015dd 100644 --- a/core/modules/entity_reference/src/Tests/EntityReferenceAdminTest.php +++ b/core/modules/entity_reference/src/Tests/EntityReferenceAdminTest.php @@ -7,14 +7,14 @@ namespace Drupal\entity_reference\Tests; -use Drupal\simpletest\WebTestBase; +use Drupal\simpletest\BrowserTestBase; /** * Tests for the administrative UI. * * @group entity_reference */ -class EntityReferenceAdminTest extends WebTestBase { +class EntityReferenceAdminTest extends BrowserTestBase { /** * Modules to enable. @@ -128,23 +128,17 @@ protected function assertFieldSelectOptions($name, array $expected_options) { /** * Extracts all options from a select element. * - * @param \SimpleXMLElement $element + * @param $element * The select element field information. * * @return array * An array of option values as strings. */ - protected function getAllOptionsList(\SimpleXMLElement $element) { + protected function getAllOptionsList($element) { $options = array(); - // Add all options items. - foreach ($element->option as $option) { - $options[] = (string) $option['value']; + foreach ($this->getAllOptions($element) as $opt_element) { + $options[] = $opt_element->getAttribute('value'); } - - if (isset($element->optgroup)) { - $options += $this->getAllOptionsList($element->optgroup); - } - return $options; } diff --git a/core/modules/filter/src/Tests/FilterAdminTest.php b/core/modules/filter/src/Tests/FilterAdminTest.php index e438162..ac2033a 100644 --- a/core/modules/filter/src/Tests/FilterAdminTest.php +++ b/core/modules/filter/src/Tests/FilterAdminTest.php @@ -8,14 +8,14 @@ namespace Drupal\filter\Tests; use Drupal\Component\Utility\String; -use Drupal\simpletest\WebTestBase; +use Drupal\simpletest\BrowserTestBase; /** * Thoroughly test the administrative interface of the filter module. * * @group filter */ -class FilterAdminTest extends WebTestBase { +class FilterAdminTest extends BrowserTestBase { /** * {@inheritdoc} @@ -244,9 +244,9 @@ function testFilterAdmin() { $format = entity_load('filter_format', $edit['format']); $this->assertNotNull($format, 'Format found in database.'); $this->drupalGet('admin/config/content/formats/manage/' . $format->format); - $this->assertFieldByName('roles[' . DRUPAL_AUTHENTICATED_RID . ']', '', 'Role found.'); - $this->assertFieldByName('filters[' . $second_filter . '][status]', '', 'Line break filter found.'); - $this->assertFieldByName('filters[' . $first_filter . '][status]', '', 'Url filter found.'); + $this->assertFieldByName('roles[' . DRUPAL_AUTHENTICATED_RID . ']', DRUPAL_AUTHENTICATED_RID, 'Role found.'); + $this->assertFieldByName('filters[' . $second_filter . '][status]', TRUE, 'Line break filter found.'); + $this->assertFieldByName('filters[' . $first_filter . '][status]', TRUE, 'Url filter found.'); // Disable new filter. $this->drupalPostForm('admin/config/content/formats/manage/' . $format->format . '/disable', array(), t('Disable')); diff --git a/core/modules/filter/src/Tests/FilterFormTest.php b/core/modules/filter/src/Tests/FilterFormTest.php index 676e193..ca8d361 100644 --- a/core/modules/filter/src/Tests/FilterFormTest.php +++ b/core/modules/filter/src/Tests/FilterFormTest.php @@ -8,14 +8,14 @@ namespace Drupal\filter\Tests; use Drupal\Component\Utility\String; -use Drupal\simpletest\WebTestBase; +use Drupal\simpletest\BrowserTestBase; /** * Tests form elements with associated text formats. * * @group filter */ -class FilterFormTest extends WebTestBase { +class FilterFormTest extends BrowserTestBase { /** * Modules to enable for this test. @@ -198,13 +198,13 @@ protected function assertNoSelect($id) { protected function assertOptions($id, array $expected_options, $selected) { $select = $this->xpath('//select[@id=:id]', array(':id' => $id)); $select = reset($select); - $passed = $this->assertTrue($select instanceof \SimpleXMLElement, String::format('Field @id exists.', array( + $passed = $this->assertTrue($select->getAttribute('id') == $id, String::format('Field @id exists.', array( '@id' => $id, ))); $found_options = $this->getAllOptions($select); foreach ($found_options as $found_key => $found_option) { - $expected_key = array_search($found_option->attributes()->value, $expected_options); + $expected_key = array_search($found_option->getAttribute('value'), $expected_options); if ($expected_key !== FALSE) { $this->pass(String::format('Option @option for field @id exists.', array( '@option' => $expected_options[$expected_key], @@ -226,7 +226,7 @@ protected function assertOptions($id, array $expected_options, $selected) { } foreach ($found_options as $found_option) { $this->fail(String::format('Option @option for field @id does not exist.', array( - '@option' => $found_option->attributes()->value, + '@option' => $found_option->getAttribute('value'), '@id' => $id, ))); $passed = FALSE; @@ -252,7 +252,7 @@ protected function assertRequiredSelectAndOptions($id, array $options) { ':id' => $id, )); $select = reset($select); - $passed = $this->assertTrue($select instanceof \SimpleXMLElement, String::format('Required field @id exists.', array( + $passed = $this->assertTrue($select->getAttribute('id') == $id, String::format('Required field @id exists.', array( '@id' => $id, ))); // A required select element has a "- Select -" option whose key is an empty @@ -275,7 +275,7 @@ protected function assertEnabledTextarea($id) { ':id' => $id, )); $textarea = reset($textarea); - return $this->assertTrue($textarea instanceof \SimpleXMLElement, String::format('Enabled field @id exists.', array( + $this->assertTrue($textarea->getAttribute('id') == $id, String::format('Enabled field @id exists.', array( '@id' => $id, ))); } @@ -294,7 +294,7 @@ protected function assertDisabledTextarea($id) { ':id' => $id, )); $textarea = reset($textarea); - $passed = $this->assertTrue($textarea instanceof \SimpleXMLElement, String::format('Disabled field @id exists.', array( + $passed = $this->assertTrue($textarea->getAttribute('id') == $id, String::format('Disabled field @id exists.', array( '@id' => $id, ))); $expected = 'This field has been disabled because you do not have sufficient permissions to edit it.'; diff --git a/core/modules/filter/src/Tests/FilterFormatAccessTest.php b/core/modules/filter/src/Tests/FilterFormatAccessTest.php index 9f4234f..cedce2d 100644 --- a/core/modules/filter/src/Tests/FilterFormatAccessTest.php +++ b/core/modules/filter/src/Tests/FilterFormatAccessTest.php @@ -7,14 +7,14 @@ namespace Drupal\filter\Tests; -use Drupal\simpletest\WebTestBase; +use Drupal\simpletest\BrowserTestBase; /** * Tests access to text formats. * * @group filter */ -class FilterFormatAccessTest extends WebTestBase { +class FilterFormatAccessTest extends BrowserTestBase { /** * Modules to enable. @@ -145,7 +145,7 @@ function testFormatPermissions() { )); $options = array(); foreach ($elements as $element) { - $options[(string) $element['value']] = $element; + $options[$element->getValue()] = $element; } $this->assertTrue(isset($options[$this->allowed_format->format]), 'The allowed text format appears as an option when adding a new node.'); $this->assertFalse(isset($options[$this->disallowed_format->format]), 'The disallowed text format does not appear as an option when adding a new node.'); diff --git a/core/modules/filter/src/Tests/FilterHtmlImageSecureTest.php b/core/modules/filter/src/Tests/FilterHtmlImageSecureTest.php index 9876f51..db1a51e 100644 --- a/core/modules/filter/src/Tests/FilterHtmlImageSecureTest.php +++ b/core/modules/filter/src/Tests/FilterHtmlImageSecureTest.php @@ -8,14 +8,14 @@ namespace Drupal\filter\Tests; use Drupal\Core\StreamWrapper\PublicStream; -use Drupal\simpletest\WebTestBase; +use Drupal\simpletest\BrowserTestBase; /** * Tests restriction of IMG tags in HTML input. * * @group filter */ -class FilterHtmlImageSecureTest extends WebTestBase { +class FilterHtmlImageSecureTest extends BrowserTestBase { /** * Modules to enable. @@ -135,14 +135,14 @@ function testImageSource() { foreach ($this->xpath('//img[@testattribute="' . hash('sha256', $image) . '"]') as $element) { $found = TRUE; if ($converted == $red_x_image) { - $this->assertEqual((string) $element['src'], $red_x_image); - $this->assertEqual((string) $element['alt'], $alt_text); - $this->assertEqual((string) $element['title'], $title_text); - $this->assertEqual((string) $element['height'], '16'); - $this->assertEqual((string) $element['width'], '16'); + $this->assertEqual($element->getAttribute('src'), $red_x_image); + $this->assertEqual($element->getAttribute('alt'), $alt_text); + $this->assertEqual($element->getAttribute('title'), $title_text); + $this->assertEqual($element->getAttribute('height'), '16'); + $this->assertEqual($element->getAttribute('width'), '16'); } else { - $this->assertEqual((string) $element['src'], $converted); + $this->assertEqual($element->getAttribute('src'), $converted); } } $this->assertTrue($found, format_string('@image was found.', array('@image' => $image))); diff --git a/core/modules/forum/src/Tests/ForumTest.php b/core/modules/forum/src/Tests/ForumTest.php index e1d6749..97c0a64 100644 --- a/core/modules/forum/src/Tests/ForumTest.php +++ b/core/modules/forum/src/Tests/ForumTest.php @@ -155,7 +155,7 @@ function testForum() { $forum_arg = array(':forum' => 'forum-list-' . $this->forum['tid']); // Topics cell contains number of topics and number of unread topics. - $xpath = $this->buildXPathQuery('//tr[@id=:forum]//td[@class="topics"]', $forum_arg); + $xpath = $this->buildXPathQuery('//tr[@id=:forum]//td[@class="topics"]/text()[1]', $forum_arg); $topics = $this->xpath($xpath); $topics = trim($topics[0]); $this->assertEqual($topics, '6', 'Number of topics found.'); @@ -163,7 +163,7 @@ function testForum() { // Verify the number of unread topics. $unread_topics = $this->container->get('forum_manager')->unreadTopics($this->forum['tid'], $this->edit_any_topics_user->id()); $unread_topics = format_plural($unread_topics, '1 new post', '@count new posts'); - $xpath = $this->buildXPathQuery('//tr[@id=:forum]//td[@class="topics"]//a', $forum_arg); + $xpath = $this->buildXPathQuery('//tr[@id=:forum]//td[@class="topics"]//a/text()[1]', $forum_arg); $this->assertFieldByXPath($xpath, $unread_topics, 'Number of unread topics found.'); // Verify that the forum name is in the unread topics text. $xpath = $this->buildXPathQuery('//tr[@id=:forum]//em[@class="placeholder"]', $forum_arg); diff --git a/core/modules/history/src/Tests/HistoryTest.php b/core/modules/history/src/Tests/HistoryTest.php index 9010511..238b8e6 100644 --- a/core/modules/history/src/Tests/HistoryTest.php +++ b/core/modules/history/src/Tests/HistoryTest.php @@ -27,7 +27,7 @@ class HistoryTest extends WebTestBase { /** * The main user for testing. * - * @var objec + * @var object */ protected $user; diff --git a/core/modules/language/src/Tests/LanguageUILanguageNegotiationTest.php b/core/modules/language/src/Tests/LanguageUILanguageNegotiationTest.php index d111000..5cdf310 100644 --- a/core/modules/language/src/Tests/LanguageUILanguageNegotiationTest.php +++ b/core/modules/language/src/Tests/LanguageUILanguageNegotiationTest.php @@ -12,7 +12,7 @@ use Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationUrl; use Drupal\user\Plugin\LanguageNegotiation\LanguageNegotiationUser; use Drupal\user\Plugin\LanguageNegotiation\LanguageNegotiationUserAdmin; -use Drupal\simpletest\WebTestBase; +use Drupal\simpletest\BrowserTestBase; use Drupal\Core\Language\Language; use Drupal\Core\Language\LanguageInterface; use Symfony\Component\HttpFoundation\Request; @@ -46,7 +46,7 @@ * * @group language */ -class LanguageUILanguageNegotiationTest extends WebTestBase { +class LanguageUILanguageNegotiationTest extends BrowserTestBase { /** * Modules to enable. @@ -122,7 +122,7 @@ function testUILanguageNegotiation() { ); $this->drupalPostForm('admin/config/regional/translate', $search, t('Filter')); $textarea = current($this->xpath('//textarea')); - $lid = (string) $textarea[0]['name']; + $lid = $textarea->getAttribute('name'); $edit = array( $lid => $language_browser_fallback_string, ); @@ -134,7 +134,7 @@ function testUILanguageNegotiation() { ); $this->drupalPostForm('admin/config/regional/translate', $search, t('Filter')); $textarea = current($this->xpath('//textarea')); - $lid = (string) $textarea[0]['name']; + $lid = $textarea->getAttribute('name'); $edit = array( $lid => $language_string, ); diff --git a/core/modules/locale/src/Tests/LocaleTranslationUiTest.php b/core/modules/locale/src/Tests/LocaleTranslationUiTest.php index 9e65440..2ec7733 100644 --- a/core/modules/locale/src/Tests/LocaleTranslationUiTest.php +++ b/core/modules/locale/src/Tests/LocaleTranslationUiTest.php @@ -7,7 +7,7 @@ namespace Drupal\locale\Tests; -use Drupal\simpletest\WebTestBase; +use Drupal\simpletest\BrowserTestBase; use Drupal\Core\Language\Language; use Drupal\Core\Language\LanguageInterface; use Drupal\Component\Utility\String; @@ -18,7 +18,7 @@ * * @group locale */ -class LocaleTranslationUiTest extends WebTestBase { +class LocaleTranslationUiTest extends BrowserTestBase { /** * Modules to enable. @@ -496,7 +496,7 @@ function testUICustomizedStrings(){ // Submit the translations without changing the translation. $textarea = current($this->xpath('//textarea')); - $lid = (string) $textarea[0]['name']; + $lid = $textarea->getAttribute('name'); $edit = array( $lid => $translation->getString(), ); @@ -514,7 +514,7 @@ function testUICustomizedStrings(){ // Submit the translations with a new translation. $textarea = current($this->xpath('//textarea')); - $lid = (string) $textarea[0]['name']; + $lid = $textarea->getAttribute('name'); $edit = array( $lid => $this->randomName(100), ); diff --git a/core/modules/rest/src/Tests/CreateTest.php b/core/modules/rest/src/Tests/CreateTest.php index 5476dbf..1417026 100644 --- a/core/modules/rest/src/Tests/CreateTest.php +++ b/core/modules/rest/src/Tests/CreateTest.php @@ -48,11 +48,11 @@ public function testCreate() { // Get the new entity ID from the location header and try to read it from // the database. - $location_url = $this->drupalGetHeader('location'); + $location_url = $this->drupalGetHeader('Location'); $url_parts = explode('/', $location_url); $id = end($url_parts); $loaded_entity = entity_load($entity_type, $id); - $this->assertNotIdentical(FALSE, $loaded_entity, 'The new ' . $entity_type . ' was found in the database.'); + $this->assertNotIdentical(NULL, $loaded_entity, 'The new ' . $entity_type . ' was found in the database.'); $this->assertEqual($entity->uuid(), $loaded_entity->uuid(), 'UUID of created entity is correct.'); // @todo Remove the user reference field for now until deserialization for // entity references is implemented. diff --git a/core/modules/rest/src/Tests/Views/StyleSerializerTest.php b/core/modules/rest/src/Tests/Views/StyleSerializerTest.php index fa2e954..bac2ef6 100644 --- a/core/modules/rest/src/Tests/Views/StyleSerializerTest.php +++ b/core/modules/rest/src/Tests/Views/StyleSerializerTest.php @@ -94,7 +94,7 @@ public function testSerializerResponses() { $this->assertIdentical($actual_json, drupal_render($output), 'The expected JSON preview output was found.'); // Test a 403 callback. - $this->drupalGet('test/serialize/denied'); + $this->drupalGet('test/serialize/denied', array(), array('Accept: application/json')); $this->assertResponse(403); // Test the entity rows. diff --git a/core/modules/simpletest/src/WebTestBase.php b/core/modules/simpletest/src/BrowserTestBase.php similarity index 75% copy from core/modules/simpletest/src/WebTestBase.php copy to core/modules/simpletest/src/BrowserTestBase.php index ac2f0a0..71a2dcc 100644 --- a/core/modules/simpletest/src/WebTestBase.php +++ b/core/modules/simpletest/src/BrowserTestBase.php @@ -2,18 +2,17 @@ /** * @file - * Definition of \Drupal\simpletest\WebTestBase. + * Definition of \Drupal\simpletest\BrowserTestBase. */ namespace Drupal\simpletest; +use Behat\Mink\Element\NodeElement; use Drupal\Component\Serialization\Json; use Drupal\Component\Utility\Crypt; -use Drupal\Component\Utility\NestedArray; use Drupal\Component\Utility\String; use Drupal\Core\DrupalKernel; use Drupal\Core\Database\Database; -use Drupal\Core\Database\ConnectionNotDefinedException; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Language\LanguageInterface; use Drupal\Core\Session\AccountInterface; @@ -21,16 +20,27 @@ use Drupal\Core\Session\UserSession; use Drupal\Core\Site\Settings; use Drupal\Core\StreamWrapper\PublicStream; -use Drupal\Core\Datetime\DrupalDateTime; use Drupal\block\Entity\Block; +use Behat\Mink\Driver\Goutte\Client; +use GuzzleHttp\Event\AbstractTransferEvent; +use GuzzleHttp\Event\BeforeEvent; +use GuzzleHttp\Event\RequestEvents; +use GuzzleHttp\Event\SubscriberInterface; +use GuzzleHttp\Exception\RequestException; +use GuzzleHttp\Post\PostFile; use Symfony\Component\HttpFoundation\Request; +use Behat\Mink\Mink; +use Behat\Mink\Session; +use Behat\Mink\Driver\GoutteDriver; +use GuzzleHttp\Client as GuzzleClient; +use Symfony\Component\CssSelector\CssSelector; /** * Test case for typical Drupal tests. * * @ingroup testing */ -abstract class WebTestBase extends TestBase { +abstract class BrowserTestBase extends TestBase implements SubscriberInterface { use AssertContentTrait; @@ -49,13 +59,6 @@ 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 @@ -73,6 +76,13 @@ protected $dumpHeaders = FALSE; /** + * The response code for the last request. + * + * @var int + */ + protected $responseCode = NULL; + + /** * The current user logged in using the internal browser. * * @var bool @@ -164,6 +174,11 @@ protected $curlCookies = array(); /** + * Cookies send back in headers. + */ + protected $cookies = array(); + + /** * An array of custom translations suitable for drupal_rewrite_settings(). * * @var array @@ -171,19 +186,90 @@ protected $customTranslations; /** + * Current mink object. + * + * @var \Behat\Mink\Mink + */ + protected $mink; + + /** * Constructor for \Drupal\simpletest\WebTestBase. */ - function __construct($test_id = NULL) { + public function __construct($test_id = NULL) { parent::__construct($test_id); $this->skipClasses[__CLASS__] = TRUE; } /** + * Resets the mink sessions. + */ + protected function resetMink() { + $this->getMink()->resetSessions(); + } + + /** + * Initializes Mink session. + */ + protected function initMink() { + global $base_url; + $defaults = array( + 'timeout' => 30, + 'verify' => FALSE, + 'headers' => array( + 'User-Agent' => $this->databasePrefix, + ), + ); + $guzzle = new GuzzleClient(array('base_url' => $base_url, 'defaults' => $defaults)); + $guzzle->getEmitter()->attach($this); + $client = new Client(); + $client->setClient($guzzle); + $client->setHeader('User-Agent', $this->databasePrefix); + $client->followRedirects(FALSE); + + if (isset($this->httpauth_credentials)) { + list($username, $password) = explode(':', $this->httpauth_credentials); + $client->setAuth($username, $password, $this->httpauth_method); + } + $this->mink = new Mink(array( + 'goutte' => new Session(new GoutteDriver($client)), + )); + $this->mink->setDefaultSessionName('goutte'); + // Set the User agent. + $this->getMink()->getSession()->setRequestHeader('User-Agent', $this->databasePrefix); + } + + /** + * Returns the current mink object. + * + * @return \Behat\Mink\Mink + * Current mink session. + */ + protected function getMink() { + if (!isset($this->mink)) { + $this->initMink(); + } + return $this->mink; + } + + /** + * Returns the named Mink session. + * + * @param string $name + * (optional) Mink session name. Defaults to null. + * + * @return \Behat\Mink\Session + * The active session. + */ + protected function getSession($name = NULL) { + return $this->getMink()->getSession($name); + } + + /** * Get a node from the database based on its title. * - * @param $title + * @param string $title * A node title, usually generated by $this->randomName(). - * @param $reset + * @param bool $reset * (optional) Whether to reset the entity cache. * * @return \Drupal\node\NodeInterface @@ -448,7 +534,7 @@ protected function assertNoBlockAppears(Block $block) { * The result from the xpath query. */ protected function findBlockInstance(Block $block) { - return $this->xpath('//div[@id = :id]', array(':id' => 'block-' . $block->id())); + return $this->getSession()->getPage()->find('css', '#block-' . $block->id()); } /** @@ -1176,6 +1262,8 @@ protected function tearDown() { // testing so test classes containing multiple tests are not polluted. $this->curlClose(); $this->curlCookies = array(); + $this->cookies = array(); + $this->resetMink(); } /** @@ -1188,43 +1276,15 @@ protected function tearDown() { */ protected function curlInitialize() { global $base_url; + $this->responseCode = NULL; - if (!isset($this->curlHandle)) { - $this->curlHandle = curl_init(); - - // Some versions/configurations of cURL break on a NULL cookie jar, so - // supply a real file. - if (empty($this->cookieFile)) { - $this->cookieFile = $this->public_files_directory . '/cookie.jar'; - } - - $curl_options = array( - CURLOPT_COOKIEJAR => $this->cookieFile, - CURLOPT_URL => $base_url, - CURLOPT_FOLLOWLOCATION => FALSE, - CURLOPT_RETURNTRANSFER => TRUE, - // Required to make the tests run on HTTPS. - CURLOPT_SSL_VERIFYPEER => FALSE, - // Required to make the tests run on HTTPS. - CURLOPT_SSL_VERIFYHOST => FALSE, - 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() returns FALSE if any of the specified options - // cannot be set, and stops processing any further options. - $result = curl_setopt_array($this->curlHandle, $this->additionalCurlOptions + $curl_options); - if (!$result) { - throw new \UnexpectedValueException('One or more cURL options could not be set.'); - } + if (!isset($this->mink)) { + $this->initMink(); } // 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])); + $this->getMink()->getSession()->setRequestHeader('User-Agent', drupal_generate_test_ua($matches[0])); } } @@ -1259,7 +1319,7 @@ protected function curlExec($curl_options, $redirect = FALSE) { } } - $url = empty($curl_options[CURLOPT_URL]) ? curl_getinfo($this->curlHandle, CURLINFO_EFFECTIVE_URL) : $curl_options[CURLOPT_URL]; + $url = empty($curl_options[CURLOPT_URL]) ? $this->getSession()->getCurrentUrl() : $curl_options[CURLOPT_URL]; if (!empty($curl_options[CURLOPT_POST])) { // This is a fix for the Curl library to prevent Expect: 100-continue @@ -1312,7 +1372,20 @@ protected function curlExec($curl_options, $redirect = FALSE) { $curl_options[CURLOPT_COOKIE] .= implode('; ', $cookies) . ';'; } - curl_setopt_array($this->curlHandle, $this->additionalCurlOptions + $curl_options); + // Set request headers + if (!empty($curl_options[CURLOPT_HTTPHEADER])) { + $http_headers = array(); + foreach ($curl_options[CURLOPT_HTTPHEADER] as $header) { + $pos = strpos($header, ':'); + $header_name = substr($header, 0, $pos); + $header_value = trim(substr($header, $pos + 1)); + $http_headers[$header_name] = $header_value; + $this->getSession()->setRequestHeader($header_name, $header_value); + } + } + + // Set client options on Goutte's Guzzle client. + $this->setClientOptions($this->additionalCurlOptions + $curl_options); if (!$redirect) { // Reset headers, the session ID and the redirect counter. @@ -1321,9 +1394,21 @@ protected function curlExec($curl_options, $redirect = FALSE) { $this->redirect_count = 0; } - $content = curl_exec($this->curlHandle); - $status = curl_getinfo($this->curlHandle, CURLINFO_HTTP_CODE); + $this->getSession()->visit($url); + + if (isset($http_headers)) { + foreach ($http_headers as $header_name => $header_value) { + $this->getSession()->setRequestHeader($header_name, NULL); + } + } + + $content = $this->getSession()->getPage()->getContent(); + $status = $this->getSession()->getStatusCode(); + $this->responseCode = $status; + /** + * May not be needed. @todo larowlan confirm + * // 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 @@ -1338,9 +1423,9 @@ protected function curlExec($curl_options, $redirect = FALSE) { return $this->curlExec($curl_options, TRUE); } } + */ - $this->setRawContent($content); - $this->url = isset($original_url) ? $original_url : curl_getinfo($this->curlHandle, CURLINFO_EFFECTIVE_URL); + $this->drupalSetContent($content, isset($original_url) ? $original_url : $this->getSession()->getCurrentUrl()); $message_vars = array( '!method' => !empty($curl_options[CURLOPT_NOBODY]) ? 'HEAD' : (empty($curl_options[CURLOPT_POSTFIELDS]) ? 'GET' : 'POST'), @@ -1356,52 +1441,49 @@ protected function curlExec($curl_options, $redirect = FALSE) { /** * Reads headers and registers errors received from the tested site. * - * @param $curlHandler - * The cURL handler. - * @param $header - * An header. + * @param \GuzzleHttp\Event\AbstractTransferEvent $event + * Complete event for request * * @see _drupal_log_error(). */ - 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 \Drupal\simpletest\WebTestBase::error(). - if (preg_match('/^X-Drupal-Assertion-[0-9]+: (.*)$/', $header, $matches)) { - // Call \Drupal\simpletest\WebTestBase::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; + public function curlHeaderCallback(AbstractTransferEvent $event) { + if ($response = $event->getResponse()) { + $headers = $response->getHeaders(); + foreach ($headers as $name => $value) { + $this->headers[$name] = implode(";", $value); + + // Errors are being sent via X-Drupal-Assertion-* headers, + // generated by _drupal_log_error() in the exact form required + // by \Drupal\simpletest\WebTestBase::error(). + if (preg_match('/^X-Drupal-Assertion-[0-9]+$/', $name)) { + // Call \Drupal\simpletest\WebTestBase::error() with the parameters from + // the header. + foreach ($value as $v) { + call_user_func_array(array(&$this, 'error'), unserialize(urldecode($v))); + } } - else { - $this->session_id = NULL; + + // Save cookies. + if ($name === 'Set-Cookie') { + foreach ($value as $cookie) { + if (preg_match('/^([^=]+)=(.+)/', $cookie, $matches)) { + $cookie_name = $matches[1]; + $parts = array_map('trim', explode(';', $matches[2])); + $cookie_value = array_shift($parts); + $this->cookies[$cookie_name] = array('value' => $cookie_value, 'secure' => in_array('secure', $parts)); + if ($cookie_name == $this->session_name) { + if ($cookie_value != 'deleted') { + $this->session_id = $cookie_value; + } + else { + $this->session_id = NULL; + } + } + } + } } } } - - // This is required by cURL. - return strlen($header); } /** @@ -1595,13 +1677,12 @@ protected function drupalGetAJAX($path, array $options = array(), array $headers * POST data, so it must already be urlencoded and contain a leading "&" * (e.g., "&extra_var1=hello+world&extra_var2=you%26me"). */ - protected function drupalPostForm($path, $edit, $submit, array $options = array(), array $headers = array(), $form_html_id = NULL, $extra_post = NULL) { + protected function drupalPostForm($path, $edit, $submit, array $options = array(), array $headers = array(), $form_html_id = NULL, $extra_post = array()) { $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. @@ -1609,24 +1690,26 @@ protected function drupalPostForm($path, $edit, $submit, array $options = array( if (!empty($form_html_id)) { $xpath .= "[@id='" . $form_html_id . "']"; } + /** @var \Behat\Mink\Element\NodeElement[] $forms */ $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(); + $submit_element = $this->handleForm($post, $edit, $upload, $ajax ? NULL : $submit, $form); + $action = $form->getAttribute('action') ? $this->getAbsoluteUrl($form->getAttribute('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; + // @todo this needs to be an Element. + $submit_element = TRUE; } // We post only if we managed to handle every field in edit and the // submit button matches. - if (!$edit && ($submit_matches || !isset($submit))) { + if (!$edit && ($submit_element || !isset($submit))) { $post_array = $post; if ($upload) { foreach ($upload as $key => $file) { @@ -1644,10 +1727,20 @@ protected function drupalPostForm($path, $edit, $submit, array $options = array( } } } + if (!$ajax) { + $submit_element->press(); + $out = $this->getSession()->getPage()->getContent(); + } else { - $post = $this->serializePostValues($post) . $extra_post; + // Guzzle only supports strings for submitted values. + $post = $post + ($extra_post ?: array()); + foreach ($post as $key => $value) { + if (is_bool($value)) { + $post[$key] = '1'; + } + } + $out = $this->drupalPost($action, 'application/vnd.drupal-ajax', $post, $options, $upload); } - $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(); @@ -1658,6 +1751,10 @@ protected function drupalPostForm($path, $edit, $submit, array $options = array( $out = $new; } + if ($session_id = $this->getSession()->getCookie($this->getSessionName())) { + $this->session_id = $session_id; + } + $verbose = 'POST request to: ' . $path; $verbose .= '
Ending URL: ' . $this->getUrl(); if ($this->dumpHeaders) { @@ -1667,6 +1764,7 @@ protected function drupalPostForm($path, $edit, $submit, array $options = array( $verbose .= '
' . $out; $this->verbose($verbose); + $this->drupalSetContent($out, $this->getUrl()); return $out; } } @@ -1747,7 +1845,7 @@ protected function drupalPostAjaxForm($path, $edit, $triggering_element, $ajax_p $xpath = '//form[@id="' . $form_html_id . '"]' . $xpath; } $element = $this->xpath($xpath); - $element_id = (string) $element[0]['id']; + $element_id = $element[0]->getAttribute('id'); $ajax_settings = $drupal_settings['ajax'][$element_id]; } @@ -1760,14 +1858,12 @@ protected function drupalPostAjaxForm($path, $edit, $triggering_element, $ajax_p } $ajax_html_ids = array(); foreach ($this->xpath('//*[@id]') as $element) { - $ajax_html_ids[] = (string) $element['id']; + $ajax_html_ids[] = $element->getAttribute('id'); } if (!empty($ajax_html_ids)) { $extra_post['ajax_html_ids'] = implode(' ', $ajax_html_ids); } $extra_post += $this->getAjaxPageStatePostData(); - // Now serialize all the $extra_post values, and prepend it with an '&'. - $extra_post = '&' . $this->serializePostValues($extra_post); // Unless a particular path is specified, use the one specified by the // Ajax settings, or else 'system/ajax'. @@ -1816,7 +1912,7 @@ protected function drupalPostAjaxForm($path, $edit, $triggering_element, $ajax_p * @see ajax.js */ protected function drupalProcessAjaxResponse($content, array $ajax_response, array $ajax_settings, array $drupal_settings) { - + // @todo larowlan refactor around Mink // ajax.js applies some defaults to the settings object, so do the same // for what's used by this function. $ajax_settings += array( @@ -1903,8 +1999,16 @@ protected function drupalProcessAjaxResponse($content, array $ajax_response, arr } } $content = $dom->saveHTML(); - $this->setRawContent($content); - $this->setDrupalSettings($drupal_settings); + $this->drupalSetContent($content); + $this->drupalSetSettings($drupal_settings); + // Hack this into the mink session. When we use a real JavaScript driver we + // can remove this nastiness. + $reflection = new \ReflectionClass($this->getSession()->getDriver()); + $method = $reflection->getMethod('getCrawler'); + $method->setAccessible(TRUE); + $crawler = $method->invoke($this->getSession()->getDriver()); + $crawler->clear(); + $crawler->addContent($content, 'text/html'); } /** @@ -1923,24 +2027,56 @@ protected function drupalProcessAjaxResponse($content, array $ajax_response, arr * @param array $options * (optional) Options to be forwarded to the url generator. The 'absolute' * option will automatically be enabled. + * @param array $files + * (optional) Array of files to upload. * - * @return - * The content returned from the call to curl_exec(). + * @return string + * The content returned from the Guzzle call. * * @see WebTestBase::getAjaxPageStatePostData() - * @see WebTestBase::curlExec() * @see url() */ - protected function drupalPost($path, $accept, array $post, $options = array()) { - return $this->curlExec(array( - CURLOPT_URL => url($path, $options + array('absolute' => TRUE)), - CURLOPT_POST => TRUE, - CURLOPT_POSTFIELDS => $this->serializePostValues($post), - CURLOPT_HTTPHEADER => array( - 'Accept: ' . $accept, - 'Content-Type: application/x-www-form-urlencoded', - ), + protected function drupalPost($path, $accept, array $post, $options = array(), $files = array()) { + /** @var \GuzzleHttp\Client $guzzle */ + $guzzle = $this->getSession()->getDriver()->getClient()->getClient(); + $cookies = []; + if ($session_id = $this->getSession()->getCookie($this->session_name)) { + $cookies[$this->session_name] = $session_id; + } + $request = $guzzle->createRequest('POST', url($path, $options + array('absolute' => TRUE)), array( + 'body' => $post, + 'cookies' => $cookies, + 'allow_redirects' => FALSE, + 'timeout' => 30 )); + if ($accept) { + $request->addHeader('Accept', $accept); + } + $request->addHeader('Content-Type', 'application/x-www-form-urlencoded'); + if (preg_match('/simpletest\d+/', $this->databasePrefix, $matches)) { + $request->setHeader('User-Agent', drupal_generate_test_ua($matches[0])); + } + foreach ($files as $name => $file) { + $request->getBody()->addFile(new PostFile($name, fopen($file, 'r'))); + } + try { + $response = $guzzle->send($request); + $this->drupalSetContent($response->getBody()); + $this->responseCode = $response->getStatusCode(); + } + catch (RequestException $e) { + $response = $e->getResponse(); + if ($response == NULL) { + $this->fail($e->getMessage()); + } + else { + $this->drupalSetContent($response->getBody()); + $this->responseCode = $response->getStatusCode(); + } + } + $this->verbose('POST request to: ' . $path . + '
' . $this->content); + return $this->content; } /** @@ -1950,16 +2086,17 @@ protected function drupalPost($path, $accept, array $post, $options = array()) { * The Ajax page state POST data. */ protected function getAjaxPageStatePostData() { + // @todo larowlan refactor around Mink $post = array(); $drupal_settings = $this->drupalSettings; if (isset($drupal_settings['ajaxPageState'])) { $post['ajax_page_state[theme]'] = $drupal_settings['ajaxPageState']['theme']; $post['ajax_page_state[theme_token]'] = $drupal_settings['ajaxPageState']['theme_token']; foreach ($drupal_settings['ajaxPageState']['css'] as $key => $value) { - $post["ajax_page_state[css][$key]"] = 1; + $post["ajax_page_state[css][$key]"] = '1'; } foreach ($drupal_settings['ajaxPageState']['js'] as $key => $value) { - $post["ajax_page_state[js][$key]"] = 1; + $post["ajax_page_state[js][$key]"] = '1'; } } return $post; @@ -2024,12 +2161,13 @@ protected function cronRun() { * Either the new page content or FALSE. */ protected function checkForMetaRefresh() { - if (strpos($this->getRawContent(), 'parse()) { + // @todo larowlan refactor around Mink + 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=(?.*)/i', $refresh[0]['content'], $match)) { + if (preg_match('/\d+;\s*URL=(?.*)/i', $refresh[0]->getAttribute('content'), $match)) { return $this->drupalGet($this->getAbsoluteUrl(decode_entities($match['url']))); } } @@ -2052,6 +2190,7 @@ protected function checkForMetaRefresh() { * The retrieved headers, also available as $this->getRawContent() */ protected function drupalHead($path, array $options = array(), array $headers = array()) { + // @todo larowlan refactor around Mink $options['absolute'] = TRUE; $url = $this->container->get('url_generator')->generateFromPath($path, $options); $out = $this->curlExec(array(CURLOPT_NOBODY => TRUE, CURLOPT_URL => $url, CURLOPT_HTTPHEADER => $headers)); @@ -2073,29 +2212,32 @@ protected function drupalHead($path, array $options = array(), array $headers = * Ensure that the specified fields exist and attempt to create POST data in * the correct manner for the particular field type. * - * @param $post + * @param array $post * Reference to array of post values. - * @param $edit + * @param array $edit * Reference to array of edit values to be checked against the form. - * @param $submit + * @param array $upload + * Array of file uploads + * @param string $submit * Form submit button value. - * @param $form + * @param \Behat\Mink\Element\NodeElement|\Drupal\simpletest\MinkNodeElementDecorator $form * Array of form elements. * - * @return - * Submit value matches a valid submit input in the form. + * @return \Behat\Mink\Element\NodeElement|\Drupal\simpletest\MinkNodeElementDecorator|bool + * The submit button for the form to trigger the POST. */ protected function handleForm(&$post, &$edit, &$upload, $submit, $form) { // Retrieve the form elements. - $elements = $form->xpath('.//input[not(@disabled)]|.//textarea[not(@disabled)]|.//select[not(@disabled)]'); + /** @var \Behat\Mink\Element\NodeElement[] $elements */ + $elements = $form->findAll('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']; + $name = $element->getAttribute('name'); // This can either be the type of or the name of the tag itself // for