diff --git a/.travis.yml b/.travis.yml index ecc69a1167c..1cd1104afcb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,7 +12,7 @@ env: jobs: fast_finish: true include: - - php: 7.1 + - php: 7.3 env: - DB=MYSQL - REQUIRE_INSTALLER="$REQUIRE_RECIPE" @@ -20,36 +20,21 @@ jobs: - PHPUNIT_TEST=1 - PHPUNIT_SUITE="framework" - COMPOSER_INSTALL_ARG="--prefer-lowest" - - php: 7.2 - env: - - DB=PGSQL - - PDO=1 - - REQUIRE_INSTALLER="$REQUIRE_RECIPE" - - PHPUNIT_TEST=1 - - PHPUNIT_TEST="framework" - - php: 7.3 - env: - - DB=MYSQL - - PDO=1 - - REQUIRE_INSTALLER="$REQUIRE_RECIPE" - - PHPUNIT_TEST=1 - - PHPUNIT_SUITE="framework" - - php: 7.3 - env: - - DB=MYSQL - - REQUIRE_INSTALLER="$REQUIRE_RECIPE" - - PHPUNIT_TEST=1 - - PHPUNIT_SUITE="cms" + - php: 7.4 + env: + - DB=MYSQL + - REQUIRE_INSTALLER="$REQUIRE_RECIPE" + - PHPUNIT_TEST=1 + - PHPUNIT_SUITE="cms" - php: 7.4 env: - DB=MYSQL - REQUIRE_INSTALLER="$REQUIRE_RECIPE" - PHPUNIT_TEST=1 - PHPUNIT_SUITE="framework" - - php: nightly + - php: 8.0 env: - DB=MYSQL - REQUIRE_INSTALLER="$REQUIRE_RECIPE" - PHPUNIT_TEST=1 - PHPUNIT_SUITE="framework" - - COMPOSER_INSTALL_ARG="--ignore-platform-reqs" diff --git a/composer.json b/composer.json index 9ac73f3bdff..1f8b77b4cb7 100644 --- a/composer.json +++ b/composer.json @@ -39,7 +39,7 @@ "symfony/config": "^3.2 || ^4", "symfony/translation": "^2.8 || ^3 || ^4", "symfony/yaml": "^3.2 || ^4", - "php": "^7.1 || ^8", + "php": "^7.3 || ^8", "ext-ctype": "*", "ext-dom": "*", "ext-hash": "*", @@ -52,8 +52,8 @@ "ext-xml": "*" }, "require-dev": { - "sminnee/phpunit": "^5.7.29", - "sminnee/phpunit-mock-objects": "^3.4.9", + "phpunit/phpunit": "^9", + "dms/phpunit-arraysubset-asserts": "^0.3.0", "silverstripe/versioned": "^1", "squizlabs/php_codesniffer": "^3.5" }, @@ -64,6 +64,11 @@ "expose": [ "client/images", "client/styles" + ], + "project-files-installed": [ + "behat.yml", + "phpcs.xml.dist", + "phpunit.xml.dist" ] }, "autoload": { diff --git a/docs/en/02_Developer_Guides/06_Testing/00_Unit_Testing.md b/docs/en/02_Developer_Guides/06_Testing/00_Unit_Testing.md index c1db2b6c8ca..3e32c905409 100644 --- a/docs/en/02_Developer_Guides/06_Testing/00_Unit_Testing.md +++ b/docs/en/02_Developer_Guides/06_Testing/00_Unit_Testing.md @@ -56,7 +56,7 @@ you want to test a `Controller`, `Form` or anything that requires a web page. `FunctionalTest` is a subclass of `SapphireTest` so will inherit all of the behaviors. By subclassing `FunctionalTest` you gain the ability to load and test web pages on the site. -`SapphireTest` in turn, extends `PHPUnit_Framework_TestCase`. For more information on `PHPUnit_Framework_TestCase` see +`SapphireTest` in turn, extends `PHPUnit\Framework\TestCase`. For more information on `PHPUnit\Framework\TestCase` see the [PHPUnit](http://www.phpunit.de) documentation. It provides a lot of fundamental concepts that we build on in this documentation. [/info] @@ -115,7 +115,7 @@ class PageTest extends SapphireTest { protected $usesDatabase = true; - public function setUp() + protected function setUp(): void { parent::setUp(); @@ -152,14 +152,14 @@ use SilverStripe\Dev\SapphireTest; class PageTest extends SapphireTest { - public static function setUpBeforeClass() + public static function setUpBeforeClass(): void { parent::setUpBeforeClass(); // .. } - public static function tearDownAfterClass() + public static function tearDownAfterClass(): void { parent::tearDownAfterClass(); @@ -180,7 +180,7 @@ It's important to remember that the `parent::setUp();` functions will need to be ```php -public static function setUpBeforeClass() +public static function setUpBeforeClass(): void { parent::setUpBeforeClass(); //this will remain for the whole suite and be removed for any other tests diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 9f66d310f9e..464914469c6 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -4,15 +4,17 @@ Standard module phpunit configuration. Requires PHPUnit ^5.7 --> - - tests/php - - - tests/php - - - vendor/silverstripe/cms/tests - + + + tests/php + + + tests/php + + + vendor/silverstripe/cms/tests + + . diff --git a/src/Dev/Constraint/SSListContains.php b/src/Dev/Constraint/SSListContains.php index 51eff1785b3..c75880e210d 100644 --- a/src/Dev/Constraint/SSListContains.php +++ b/src/Dev/Constraint/SSListContains.php @@ -4,11 +4,165 @@ use PHPUnit_Framework_Constraint; use PHPUnit_Framework_ExpectationFailedException; +use PHPUnit\Framework\Constraint\Constraint; +use PHPUnit\Framework\ExpectationFailedException; use SilverStripe\Dev\SSListExporter; use SilverStripe\Dev\TestOnly; use SilverStripe\ORM\SS_List; use SilverStripe\View\ViewableData; +/* ------------------------------------------------- + * + * This version of SSListContains is for phpunit 9 + * The phpunit 5 version is lower down in this file + * phpunit 6, 7 and 8 are not supported + * + * See SapphireTest for a full explanation + * + * ------------------------------------------------- + */ + +if (class_exists(Constraint::class)) { + + /** + * Constraint for checking if a SS_List contains items matching the given + * key-value pairs. + */ + // Ignore multiple classes in same file + // @codingStandardsIgnoreStart + class SSListContains extends Constraint implements TestOnly + { + // @codingStandardsIgnoreEnd + /** + * @var array + */ + protected $matches = []; + + /** + * Check if the list has left over items that don't match + * + * @var bool + */ + protected $hasLeftoverItems = false; + + public function __construct(array $matches) + { + $this->exporter = new SSListExporter(); + + $this->matches = $matches; + } + + /** + * Evaluates the constraint for parameter $other + * + * If $returnResult is set to false (the default), an exception is thrown + * in case of a failure. null is returned otherwise. + * + * If $returnResult is true, the result of the evaluation is returned as + * a boolean value instead: true in case of success, false in case of a + * failure. + * + * @param SS_List $other Value or object to evaluate. + * @param string $description Additional information about the test + * @param bool $returnResult Whether to return a result or throw an exception + * + * @return null|bool + * + * @throws PHPUnit_Framework_ExpectationFailedException + */ + public function evaluate($other, $description = '', $returnResult = false): ?bool + { + $success = true; + + foreach ($other as $item) { + $this->checkIfItemEvaluatesRemainingMatches($item); + } + + //we have remaining matches? + if (count($this->matches) !== 0) { + $success = false; + $this->hasLeftoverItems = true; + } + + if ($returnResult) { + return $success; + } + + if (!$success) { + $this->fail($other, $description); + } + + return null; + } + + /** + * @param ViewableData $item + * @return bool + */ + protected function checkIfItemEvaluatesRemainingMatches(ViewableData $item): bool + { + $success = false; + foreach ($this->matches as $key => $match) { + $constraint = new ViewableDataContains($match); + + if ($constraint->evaluate($item, '', true)) { + $success = true; + unset($this->matches[$key]); + break; + } + } + + return $success; + } + + /** + * Returns a string representation of the object. + * + * @return string + */ + public function toString(): string + { + $matchToString = function ($key, $value) { + return ' "' . $key . '" is "' . $value . '"'; + }; + + $matchesToString = function ($matches) use ($matchToString) { + $matchesAsString = implode(' and ', array_map( + $matchToString, + array_keys($matches), + array_values($matches) + )); + + return '(' . $matchesAsString . ')'; + }; + + $allMatchesAsString = implode( + "\n or ", + array_map($matchesToString, $this->matches) + ); + + + return $this->getStubForToString() . $allMatchesAsString; + } + + /** + * @return string + */ + protected function getStubForToString(): string + { + return ' contains an item matching '; + } + } +} + +/* ------------------------------------------------- + * + * This version of FunctionalTest is for phpunit 5 + * The phpunit 9 verison is at the top of this file + * + * ------------------------------------------------- + */ + if (!class_exists(PHPUnit_Framework_Constraint::class)) { return; } @@ -17,8 +171,11 @@ * Constraint for checking if a SS_List contains items matching the given * key-value pairs. */ +// Ignore multiple classes in same file +// @codingStandardsIgnoreStart class SSListContains extends PHPUnit_Framework_Constraint implements TestOnly { + // @codingStandardsIgnoreEnd /** * @var array */ @@ -31,9 +188,8 @@ class SSListContains extends PHPUnit_Framework_Constraint implements TestOnly */ protected $hasLeftoverItems = false; - public function __construct($matches) + public function __construct(array $matches) { - parent::__construct(); $this->exporter = new SSListExporter(); $this->matches = $matches; @@ -55,9 +211,9 @@ public function __construct($matches) * * @return null|bool * - * @throws PHPUnit_Framework_ExpectationFailedException + * @throws ExpectationFailedException */ - public function evaluate($other, $description = '', $returnResult = false) + public function evaluate($other, $description = '', $returnResult = false): ?bool { $success = true; @@ -86,7 +242,7 @@ public function evaluate($other, $description = '', $returnResult = false) * @param ViewableData $item * @return bool */ - protected function checkIfItemEvaluatesRemainingMatches(ViewableData $item) + protected function checkIfItemEvaluatesRemainingMatches(ViewableData $item): bool { $success = false; foreach ($this->matches as $key => $match) { @@ -107,7 +263,7 @@ protected function checkIfItemEvaluatesRemainingMatches(ViewableData $item) * * @return string */ - public function toString() + public function toString(): string { $matchToString = function ($key, $value) { return ' "' . $key . '" is "' . $value . '"'; @@ -132,7 +288,10 @@ public function toString() return $this->getStubForToString() . $allMatchesAsString; } - protected function getStubForToString() + /** + * @return string + */ + protected function getStubForToString(): string { return ' contains an item matching '; } diff --git a/src/Dev/Constraint/SSListContainsOnly.php b/src/Dev/Constraint/SSListContainsOnly.php index 0be563ac9a6..9cfa34b512e 100644 --- a/src/Dev/Constraint/SSListContainsOnly.php +++ b/src/Dev/Constraint/SSListContainsOnly.php @@ -4,10 +4,21 @@ use PHPUnit_Framework_Constraint; use PHPUnit_Framework_ExpectationFailedException; +use PHPUnit\Framework\Constraint\Constraint; +use PHPUnit\Framework\ExpectationFailedException; use SilverStripe\Dev\TestOnly; use SilverStripe\ORM\SS_List; -if (!class_exists(PHPUnit_Framework_Constraint::class)) { +/* ------------------------------------------------- + * + * This version of SSListContains is for both phpunit5 and phpunit 9 because it extends SSListContains + * phpunit 6, 7 and 8 are not supported + * + * See SapphireTest for a full explanation + * + * ------------------------------------------------- + */ +if (!class_exists(Constraint::class) && !class_exists(PHPUnit_Framework_Constraint::class)) { return; } @@ -40,9 +51,9 @@ class SSListContainsOnly extends SSListContains implements TestOnly * * @return null|bool * - * @throws PHPUnit_Framework_ExpectationFailedException + * @throws PHPUnit_Framework_ExpectationFailedException|ExpectationFailedException */ - public function evaluate($other, $description = '', $returnResult = false) + public function evaluate($other, $description = '', $returnResult = false): ?bool { $success = true; @@ -71,7 +82,7 @@ public function evaluate($other, $description = '', $returnResult = false) return null; } - protected function getStubForToString() + protected function getStubForToString(): string { return $this->itemNotMatching ? parent::getStubForToString() diff --git a/src/Dev/Constraint/SSListContainsOnlyMatchingItems.php b/src/Dev/Constraint/SSListContainsOnlyMatchingItems.php index d17ec07e09b..18d2f47d4b6 100644 --- a/src/Dev/Constraint/SSListContainsOnlyMatchingItems.php +++ b/src/Dev/Constraint/SSListContainsOnlyMatchingItems.php @@ -4,20 +4,125 @@ use PHPUnit_Framework_Constraint; use PHPUnit_Framework_ExpectationFailedException; +use PHPUnit\Framework\Constraint\Constraint; +use PHPUnit\Framework\ExpectationFailedException; use SilverStripe\Dev\SSListExporter; use SilverStripe\Dev\TestOnly; use SilverStripe\ORM\SS_List; +/* ------------------------------------------------- + * + * This version of SSListContainsOnlyMatchingItems is for phpunit 9 + * The phpunit 5 version is lower down in this file + * phpunit 6, 7 and 8 are not supported + * + * See SapphireTest for a full explanation + * + * ------------------------------------------------- + */ + +if (class_exists(Constraint::class)) { + + /** + * Constraint for checking if every item in a SS_List matches a given match, + * e.g. every Member has isActive set to true + */ + // Ignore multiple classes in same file + // @codingStandardsIgnoreStart + class SSListContainsOnlyMatchingItems extends Constraint implements TestOnly + { + // @codingStandardsIgnoreEnd + /** + * @var array + */ + private $match; + + /** + * @var ViewableDataContains + */ + private $constraint; + + public function __construct($match) + { + $this->exporter = new SSListExporter(); + + $this->constraint = new ViewableDataContains($match); + $this->match = $match; + } + + /** + * Evaluates the constraint for parameter $other + * + * If $returnResult is set to false (the default), an exception is thrown + * in case of a failure. null is returned otherwise. + * + * If $returnResult is true, the result of the evaluation is returned as + * a boolean value instead: true in case of success, false in case of a + * failure. + * + * @param SS_List $other Value or object to evaluate. + * @param string $description Additional information about the test + * @param bool $returnResult Whether to return a result or throw an exception + * + * @return null|bool + * + * @throws ExpectationFailedException + */ + public function evaluate($other, $description = '', $returnResult = false): ?bool + { + $success = true; + + foreach ($other as $item) { + if (!$this->constraint->evaluate($item, '', true)) { + $success = false; + break; + } + } + + if ($returnResult) { + return $success; + } + + if (!$success) { + $this->fail($other, $description); + } + + return null; + } + + /** + * Returns a string representation of the object. + * + * @return string + */ + public function toString(): string + { + return 'contains only Objects where "' . key($this->match) . '" is "' . current($this->match) . '"'; + } + } +} + if (!class_exists(PHPUnit_Framework_Constraint::class)) { return; } +/* ------------------------------------------------- + * + * This version of SSListContainsOnlyMatchingItems is for phpunit 5 + * The phpunit 9 verison is at the top of this file + * + * ------------------------------------------------- + */ + /** * Constraint for checking if every item in a SS_List matches a given match, * e.g. every Member has isActive set to true */ +// Ignore multiple classes in same file +// @codingStandardsIgnoreStart class SSListContainsOnlyMatchingItems extends PHPUnit_Framework_Constraint implements TestOnly { + // @codingStandardsIgnoreEnd /** * @var array */ @@ -30,7 +135,6 @@ class SSListContainsOnlyMatchingItems extends PHPUnit_Framework_Constraint imple public function __construct($match) { - parent::__construct(); $this->exporter = new SSListExporter(); $this->constraint = new ViewableDataContains($match); @@ -55,7 +159,7 @@ public function __construct($match) * * @throws PHPUnit_Framework_ExpectationFailedException */ - public function evaluate($other, $description = '', $returnResult = false) + public function evaluate($other, $description = '', $returnResult = false): ?bool { $success = true; @@ -82,7 +186,7 @@ public function evaluate($other, $description = '', $returnResult = false) * * @return string */ - public function toString() + public function toString(): string { return 'contains only Objects where "' . key($this->match) . '" is "' . current($this->match) . '"'; } diff --git a/src/Dev/Constraint/ViewableDataContains.php b/src/Dev/Constraint/ViewableDataContains.php index 6665c0f46fb..b40100597f9 100644 --- a/src/Dev/Constraint/ViewableDataContains.php +++ b/src/Dev/Constraint/ViewableDataContains.php @@ -5,8 +5,117 @@ use PHPUnit_Framework_Constraint; use PHPUnit_Framework_ExpectationFailedException; use PHPUnit_Util_InvalidArgumentHelper; +use PHPUnit\Framework\Constraint\Constraint; +use PHPUnit\Framework\ExpectationFailedException; use SilverStripe\Dev\TestOnly; use SilverStripe\View\ViewableData; +use SilverStripe\Dev\SapphireTest; + +/* ------------------------------------------------- + * + * This version of ViewableDataContains is for phpunit 9 + * The phpunit 5 version is lower down in this file + * phpunit 6, 7 and 8 are not supported + * + * See SapphireTest for a full explanation + * + * ------------------------------------------------- + */ + +if (class_exists(Constraint::class)) { + + /** + * Constraint for checking if a ViewableData (e.g. ArrayData or any DataObject) contains fields matching the given + * key-value pairs. + */ + // Ignore multiple classes in same file + // @codingStandardsIgnoreStart + class ViewableDataContains extends Constraint implements TestOnly + { + // @codingStandardsIgnoreEnd + /** + * @var array + */ + private $match; + + /** + * ViewableDataContains constructor. + * @param array $match + */ + public function __construct(array $match) + { + if (!is_array($match)) { + throw SapphireTest::createInvalidArgumentException( + 1, + 'array' + ); + } + + $this->match = $match; + } + + /** + * Evaluates the constraint for parameter $other + * + * If $returnResult is set to false (the default), an exception is thrown + * in case of a failure. null is returned otherwise. + * + * If $returnResult is true, the result of the evaluation is returned as + * a boolean value instead: true in case of success, false in case of a + * failure. + * + * @param ViewableData $other Value or object to evaluate. + * @param string $description Additional information about the test + * @param bool $returnResult Whether to return a result or throw an exception + * + * @return null|bool + * + * @throws ExpectationFailedException + */ + public function evaluate($other, $description = '', $returnResult = false): ?bool + { + $success = true; + + foreach ($this->match as $fieldName => $value) { + if ($other->$fieldName != $value) { + $success = false; + break; + } + } + + if ($returnResult) { + return $success; + } + + if (!$success) { + $this->fail($other, $description); + } + + return null; + } + + + /** + * Returns a string representation of the object. + * + * @todo: add representation for more than one match + * + * @return string + */ + public function toString(): string + { + return 'contains only Objects where "' . key($this->match) . '" is "' . current($this->match) . '"'; + } + } +} + +/* ------------------------------------------------- + * + * This version of ViewableDataContains is for phpunit 5 + * The phpunit 9 verison is at the top of this file + * + * ------------------------------------------------- + */ if (!class_exists(PHPUnit_Framework_Constraint::class)) { return; @@ -16,8 +125,11 @@ * Constraint for checking if a ViewableData (e.g. ArrayData or any DataObject) contains fields matching the given * key-value pairs. */ +// Ignore multiple classes in same file +// @codingStandardsIgnoreStart class ViewableDataContains extends PHPUnit_Framework_Constraint implements TestOnly { + // @codingStandardsIgnoreEnd /** * @var array */ @@ -27,10 +139,8 @@ class ViewableDataContains extends PHPUnit_Framework_Constraint implements TestO * ViewableDataContains constructor. * @param array $match */ - public function __construct($match) + public function __construct(array $match) { - parent::__construct(); - if (!is_array($match)) { throw PHPUnit_Util_InvalidArgumentHelper::factory( 1, @@ -59,7 +169,7 @@ public function __construct($match) * * @throws PHPUnit_Framework_ExpectationFailedException */ - public function evaluate($other, $description = '', $returnResult = false) + public function evaluate($other, $description = '', $returnResult = false): ?bool { $success = true; @@ -81,7 +191,6 @@ public function evaluate($other, $description = '', $returnResult = false) return null; } - /** * Returns a string representation of the object. * @@ -89,7 +198,7 @@ public function evaluate($other, $description = '', $returnResult = false) * * @return string */ - public function toString() + public function toString(): string { return 'contains only Objects where "' . key($this->match) . '" is "' . current($this->match) . '"'; } diff --git a/src/Dev/FunctionalTest.php b/src/Dev/FunctionalTest.php index 0d9e7459d6a..a85bf3d3ac0 100644 --- a/src/Dev/FunctionalTest.php +++ b/src/Dev/FunctionalTest.php @@ -3,6 +3,9 @@ namespace SilverStripe\Dev; use PHPUnit_Framework_AssertionFailedError; +use PHPUnit_Extensions_GroupTestSuite; +use PHPUnit\Framework\AssertionFailedError; +use PHPUnit\Framework\Constraint\IsEqualCanonicalizing; use SilverStripe\Control\Director; use SilverStripe\Control\HTTPResponse; use SilverStripe\Control\Session; @@ -12,6 +15,463 @@ use SilverStripe\View\SSViewer; use SimpleXMLElement; +/* ------------------------------------------------- + * + * This version of FunctionalTest is for phpunit 9 + * The phpunit 5 version is lower down in this file + * phpunit 6, 7 and 8 are not supported + * + * See SapphireTest for a full explanation + * + * IsEqualCanonicalizing::class is a new class added in phpunit 9, testing that this class exists + * to ensure that we're not using a a prior, incompatible version of php + * + * ------------------------------------------------- + */ +if (class_exists(IsEqualCanonicalizing::class)) { + + /** + * SilverStripe-specific testing object designed to support functional testing of your web app. It simulates get/post + * requests, form submission, and can validate resulting HTML, looking up content by CSS selector. + * + * The example below shows how it works. + * + * + * public function testMyForm() { + * // Visit a URL + * $this->get("your/url"); + * + * // Submit a form on the page that you get in response + * $this->submitForm("MyForm_ID", "action_dologin", array("Email" => "invalid email ^&*&^")); + * + * // Validate the content that is returned + * $this->assertExactMatchBySelector("#MyForm_ID p.error", array("That email address is invalid.")); + * } + * + */ + // Ignore multiple classes in same file + // @codingStandardsIgnoreStart + class FunctionalTest extends SapphireTest implements TestOnly + { + // @codingStandardsIgnoreEnd + /** + * Set this to true on your sub-class to disable the use of themes in this test. + * This can be handy for functional testing of modules without having to worry about whether a user has changed + * behaviour by replacing the theme. + * + * @var bool + */ + protected static $disable_themes = false; + + /** + * Set this to true on your sub-class to use the draft site by default for every test in this class. + * + * @deprecated 4.2.0:5.0.0 Use ?stage=Stage in your ->get() querystring requests instead + * @var bool + */ + protected static $use_draft_site = false; + + /** + * @var TestSession + */ + protected $mainSession = null; + + /** + * CSSContentParser for the most recently requested page. + * + * @var CSSContentParser + */ + protected $cssParser = null; + + /** + * If this is true, then 30x Location headers will be automatically followed. + * If not, then you will have to manaully call $this->mainSession->followRedirection() to follow them. + * However, this will let you inspect the intermediary headers + * + * @var bool + */ + protected $autoFollowRedirection = true; + + /** + * Returns the {@link Session} object for this test + * + * @return Session + */ + public function session() + { + return $this->mainSession->session(); + } + + protected function setUp(): void + { + parent::setUp(); + + // Skip calling FunctionalTest directly. + if (static::class == __CLASS__) { + $this->markTestSkipped(sprintf('Skipping %s ', static::class)); + } + + $this->mainSession = new TestSession(); + + // Disable theme, if necessary + if (static::get_disable_themes()) { + SSViewer::config()->update('theme_enabled', false); + } + + // Flush user + $this->logOut(); + + // Switch to draft site, if necessary + // If you rely on this you should be crafting stage-specific urls instead though. + if (static::get_use_draft_site()) { + $this->useDraftSite(); + } + + // Unprotect the site, tests are running with the assumption it's off. They will enable it on a case-by-case + // basis. + BasicAuth::protect_entire_site(false); + + SecurityToken::disable(); + } + + protected function tearDown(): void + { + SecurityToken::enable(); + unset($this->mainSession); + parent::tearDown(); + } + + /** + * Run a test while mocking the base url with the provided value + * @param string $url The base URL to use for this test + * @param callable $callback The test to run + */ + protected function withBaseURL($url, $callback) + { + $oldBase = Config::inst()->get(Director::class, 'alternate_base_url'); + Config::modify()->set(Director::class, 'alternate_base_url', $url); + $callback($this); + Config::modify()->set(Director::class, 'alternate_base_url', $oldBase); + } + + /** + * Run a test while mocking the base folder with the provided value + * @param string $folder The base folder to use for this test + * @param callable $callback The test to run + */ + protected function withBaseFolder($folder, $callback) + { + $oldFolder = Config::inst()->get(Director::class, 'alternate_base_folder'); + Config::modify()->set(Director::class, 'alternate_base_folder', $folder); + $callback($this); + Config::modify()->set(Director::class, 'alternate_base_folder', $oldFolder); + } + + /** + * Submit a get request + * @uses Director::test() + * + * @param string $url + * @param Session $session + * @param array $headers + * @param array $cookies + * @return HTTPResponse + */ + public function get($url, $session = null, $headers = null, $cookies = null) + { + $this->cssParser = null; + $response = $this->mainSession->get($url, $session, $headers, $cookies); + if ($this->autoFollowRedirection && is_object($response) && $response->getHeader('Location')) { + $response = $this->mainSession->followRedirection(); + } + return $response; + } + + /** + * Submit a post request + * + * @uses Director::test() + * @param string $url + * @param array $data + * @param array $headers + * @param Session $session + * @param string $body + * @param array $cookies + * @return HTTPResponse + */ + public function post($url, $data, $headers = null, $session = null, $body = null, $cookies = null) + { + $this->cssParser = null; + $response = $this->mainSession->post($url, $data, $headers, $session, $body, $cookies); + if ($this->autoFollowRedirection && is_object($response) && $response->getHeader('Location')) { + $response = $this->mainSession->followRedirection(); + } + return $response; + } + + /** + * Submit the form with the given HTML ID, filling it out with the given data. + * Acts on the most recent response. + * + * Any data parameters have to be present in the form, with exact form field name + * and values, otherwise they are removed from the submission. + * + * Caution: Parameter names have to be formatted + * as they are in the form submission, not as they are interpreted by PHP. + * Wrong: array('mycheckboxvalues' => array(1 => 'one', 2 => 'two')) + * Right: array('mycheckboxvalues[1]' => 'one', 'mycheckboxvalues[2]' => 'two') + * + * @see http://www.simpletest.org/en/form_testing_documentation.html + * + * @param string $formID HTML 'id' attribute of a form (loaded through a previous response) + * @param string $button HTML 'name' attribute of the button (NOT the 'id' attribute) + * @param array $data Map of GET/POST data. + * @return HTTPResponse + */ + public function submitForm($formID, $button = null, $data = []) + { + $this->cssParser = null; + $response = $this->mainSession->submitForm($formID, $button, $data); + if ($this->autoFollowRedirection && is_object($response) && $response->getHeader('Location')) { + $response = $this->mainSession->followRedirection(); + } + return $response; + } + + /** + * Return the most recent content + * + * @return string + */ + public function content() + { + return $this->mainSession->lastContent(); + } + + /** + * Find an attribute in a SimpleXMLElement object by name. + * @param SimpleXMLElement $object + * @param string $attribute Name of attribute to find + * @return SimpleXMLElement object of the attribute + */ + public function findAttribute($object, $attribute) + { + $found = false; + foreach ($object->attributes() as $a => $b) { + if ($a == $attribute) { + $found = $b; + } + } + return $found; + } + + /** + * Return a CSSContentParser for the most recent content. + * + * @return CSSContentParser + */ + public function cssParser() + { + if (!$this->cssParser) { + $this->cssParser = new CSSContentParser($this->mainSession->lastContent()); + } + return $this->cssParser; + } + + /** + * Assert that the most recently queried page contains a number of content tags specified by a CSS selector. + * The given CSS selector will be applied to the HTML of the most recent page. The content of every matching tag + * will be examined. The assertion fails if one of the expectedMatches fails to appear. + * + * Note:   characters are stripped from the content; make sure that your assertions take this into account. + * + * @param string $selector A basic CSS selector, e.g. 'li.jobs h3' + * @param array|string $expectedMatches The content of at least one of the matched tags + * @param string $message + * @throws AssertionFailedError + */ + public function assertPartialMatchBySelector($selector, $expectedMatches, $message = null) + { + if (is_string($expectedMatches)) { + $expectedMatches = [$expectedMatches]; + } + + $items = $this->cssParser()->getBySelector($selector); + + $actuals = []; + if ($items) { + foreach ($items as $item) { + $actuals[trim(preg_replace('/\s+/', ' ', (string)$item))] = true; + } + } + + $message = $message ?: + "Failed asserting the CSS selector '$selector' has a partial match to the expected elements:\n'" + . implode("'\n'", $expectedMatches) . "'\n\n" + . "Instead the following elements were found:\n'" . implode("'\n'", array_keys($actuals)) . "'"; + + foreach ($expectedMatches as $match) { + $this->assertTrue(isset($actuals[$match]), $message); + } + } + + /** + * Assert that the most recently queried page contains a number of content tags specified by a CSS selector. + * The given CSS selector will be applied to the HTML of the most recent page. The full HTML of every matching tag + * will be examined. The assertion fails if one of the expectedMatches fails to appear. + * + * Note:   characters are stripped from the content; make sure that your assertions take this into account. + * + * @param string $selector A basic CSS selector, e.g. 'li.jobs h3' + * @param array|string $expectedMatches The content of *all* matching tags as an array + * @param string $message + * @throws AssertionFailedError + */ + public function assertExactMatchBySelector($selector, $expectedMatches, $message = null) + { + if (is_string($expectedMatches)) { + $expectedMatches = [$expectedMatches]; + } + + $items = $this->cssParser()->getBySelector($selector); + + $actuals = []; + if ($items) { + foreach ($items as $item) { + $actuals[] = trim(preg_replace('/\s+/', ' ', (string)$item)); + } + } + + $message = $message ?: + "Failed asserting the CSS selector '$selector' has an exact match to the expected elements:\n'" + . implode("'\n'", $expectedMatches) . "'\n\n" + . "Instead the following elements were found:\n'" . implode("'\n'", $actuals) . "'"; + + $this->assertTrue($expectedMatches == $actuals, $message); + } + + /** + * Assert that the most recently queried page contains a number of content tags specified by a CSS selector. + * The given CSS selector will be applied to the HTML of the most recent page. The content of every matching tag + * will be examined. The assertion fails if one of the expectedMatches fails to appear. + * + * Note:   characters are stripped from the content; make sure that your assertions take this into account. + * + * @param string $selector A basic CSS selector, e.g. 'li.jobs h3' + * @param array|string $expectedMatches The content of at least one of the matched tags + * @param string $message + * @throws AssertionFailedError + */ + public function assertPartialHTMLMatchBySelector($selector, $expectedMatches, $message = null) + { + if (is_string($expectedMatches)) { + $expectedMatches = [$expectedMatches]; + } + + $items = $this->cssParser()->getBySelector($selector); + + $actuals = []; + if ($items) { + /** @var SimpleXMLElement $item */ + foreach ($items as $item) { + $actuals[$item->asXML()] = true; + } + } + + $message = $message ?: + "Failed asserting the CSS selector '$selector' has a partial match to the expected elements:\n'" + . implode("'\n'", $expectedMatches) . "'\n\n" + . "Instead the following elements were found:\n'" . implode("'\n'", array_keys($actuals)) . "'"; + + foreach ($expectedMatches as $match) { + $this->assertTrue(isset($actuals[$match]), $message); + } + } + + /** + * Assert that the most recently queried page contains a number of content tags specified by a CSS selector. + * The given CSS selector will be applied to the HTML of the most recent page. The full HTML of every matching tag + * will be examined. The assertion fails if one of the expectedMatches fails to appear. + * + * Note:   characters are stripped from the content; make sure that your assertions take this into account. + * + * @param string $selector A basic CSS selector, e.g. 'li.jobs h3' + * @param array|string $expectedMatches The content of *all* matched tags as an array + * @param string $message + * @throws AssertionFailedError + */ + public function assertExactHTMLMatchBySelector($selector, $expectedMatches, $message = null) + { + $items = $this->cssParser()->getBySelector($selector); + + $actuals = []; + if ($items) { + /** @var SimpleXMLElement $item */ + foreach ($items as $item) { + $actuals[] = $item->asXML(); + } + } + + $message = $message ?: + "Failed asserting the CSS selector '$selector' has an exact match to the expected elements:\n'" + . implode("'\n'", $expectedMatches) . "'\n\n" + . "Instead the following elements were found:\n'" . implode("'\n'", $actuals) . "'"; + + $this->assertTrue($expectedMatches == $actuals, $message); + } + + /** + * Use the draft (stage) site for testing. + * This is helpful if you're not testing publication functionality and don't want "stage management" cluttering + * your test. + * + * @deprecated 4.2.0:5.0.0 Use ?stage=Stage querystring arguments instead of useDraftSite + * @param bool $enabled toggle the use of the draft site + */ + public function useDraftSite($enabled = true) + { + Deprecation::notice('5.0', 'Use ?stage=Stage querystring arguments instead of useDraftSite'); + if ($enabled) { + $this->session()->set('readingMode', 'Stage.Stage'); + $this->session()->set('unsecuredDraftSite', true); + } else { + $this->session()->clear('readingMode'); + $this->session()->clear('unsecuredDraftSite'); + } + } + + /** + * @return bool + */ + public static function get_disable_themes() + { + return static::$disable_themes; + } + + /** + * @deprecated 4.2.0:5.0.0 Use ?stage=Stage in your querystring arguments instead + * @return bool + */ + public static function get_use_draft_site() + { + return static::$use_draft_site; + } + } +} + +/* ------------------------------------------------- + * + * This version of FunctionalTest is for phpunit 5 + * The phpunit 9 verison is at the top of this file + * + * PHPUnit_Extensions_GroupTestSuite is a class that only exists in phpunit 5 + * + * ------------------------------------------------- + */ +if (!class_exists(PHPUnit_Extensions_GroupTestSuite::class)) { + return; +} + /** * SilverStripe-specific testing object designed to support functional testing of your web app. It simulates get/post * requests, form submission, and can validate resulting HTML, looking up content by CSS selector. @@ -31,8 +491,11 @@ * } * */ +// Ignore multiple classes in same file +// @codingStandardsIgnoreStart class FunctionalTest extends SapphireTest implements TestOnly { + // @codingStandardsIgnoreEnd /** * Set this to true on your sub-class to disable the use of themes in this test. * This can be handy for functional testing of modules without having to worry about whether a user has changed @@ -81,7 +544,7 @@ public function session() return $this->mainSession->session(); } - protected function setUp() + protected function setUp(): void { parent::setUp(); @@ -113,7 +576,7 @@ protected function setUp() SecurityToken::disable(); } - protected function tearDown() + protected function tearDown(): void { SecurityToken::enable(); unset($this->mainSession); diff --git a/src/Dev/SapphireTest.php b/src/Dev/SapphireTest.php index fb987006b55..57e19a74e0e 100644 --- a/src/Dev/SapphireTest.php +++ b/src/Dev/SapphireTest.php @@ -1,12 +1,21 @@ " notation + * between the fixtures, they act independent of each other. + * + * @var string|array + */ + protected static $fixture_file = null; + + /** + * @deprecated 4.0..5.0 Use FixtureTestState instead + * @var FixtureFactory + */ + protected $fixtureFactory; + + /** + * @var Boolean If set to TRUE, this will force a test database to be generated + * in {@link setUp()}. Note that this flag is overruled by the presence of a + * {@link $fixture_file}, which always forces a database build. + * + * @var bool + */ + protected $usesDatabase = null; + + /** + * This test will cleanup its state via transactions. + * If set to false a full schema is forced between tests, but at a performance cost. + * + * @var bool + */ + protected $usesTransactions = true; + + /** + * @var bool + */ + protected static $is_running_test = false; + + /** + * By default, setUp() does not require default records. Pass + * class names in here, and the require/augment default records + * function will be called on them. + * + * @var array + */ + protected $requireDefaultRecordsFrom = []; + + /** + * A list of extensions that can't be applied during the execution of this run. If they are + * applied, they will be temporarily removed and a database migration called. + * + * The keys of the are the classes that the extensions can't be applied the extensions to, and + * the values are an array of illegal extensions on that class. + * + * Set a class to `*` to remove all extensions (unadvised) + * + * @var array + */ + protected static $illegal_extensions = []; + + /** + * A list of extensions that must be applied during the execution of this run. If they are + * not applied, they will be temporarily added and a database migration called. + * + * The keys of the are the classes to apply the extensions to, and the values are an array + * of required extensions on that class. + * + * Example: + * + * array("MyTreeDataObject" => array("Versioned", "Hierarchy")) + * + * + * @var array + */ + protected static $required_extensions = []; + + /** + * By default, the test database won't contain any DataObjects that have the interface TestOnly. + * This variable lets you define additional TestOnly DataObjects to set up for this test. + * Set it to an array of DataObject subclass names. + * + * @var array + */ + protected static $extra_dataobjects = []; + + /** + * List of class names of {@see Controller} objects to register routes for + * Controllers must implement Link() method + * + * @var array + */ + protected static $extra_controllers = []; + + /** + * We need to disabling backing up of globals to avoid overriding + * the few globals SilverStripe relies on, like $lang for the i18n subsystem. + * + * @see http://sebastian-bergmann.de/archives/797-Global-Variables-and-PHPUnit.html + */ + protected $backupGlobals = false; + + /** + * State management container for SapphireTest + * + * @var SapphireTestState + */ + protected static $state = null; + + /** + * Temp database helper + * + * @var TempDatabase + */ + protected static $tempDB = null; + + /** + * @return TempDatabase + */ + public static function tempDB() + { + if (!class_exists(TempDatabase::class)) { + return null; + } + + if (!static::$tempDB) { + static::$tempDB = TempDatabase::create(); + } + return static::$tempDB; + } + + /** + * Gets illegal extensions for this class + * + * @return array + */ + public static function getIllegalExtensions() + { + return static::$illegal_extensions; + } + + /** + * Gets required extensions for this class + * + * @return array + */ + public static function getRequiredExtensions() + { + return static::$required_extensions; + } + + /** + * Check if test bootstrapping has been performed. Must not be relied on + * outside of unit tests. + * + * @return bool + */ + protected static function is_running_test() + { + return self::$is_running_test; + } + + /** + * Set test running state + * + * @param bool $bool + */ + protected static function set_is_running_test($bool) + { + self::$is_running_test = $bool; + } + + /** + * @return String + */ + public static function get_fixture_file() + { + return static::$fixture_file; + } + + /** + * @return bool + */ + public function getUsesDatabase() + { + return $this->usesDatabase; + } + + /** + * @return bool + */ + public function getUsesTransactions() + { + return $this->usesTransactions; + } + + /** + * @return array + */ + public function getRequireDefaultRecordsFrom() + { + return $this->requireDefaultRecordsFrom; + } + + /** + * Setup the test. + * Always sets up in order: + * - Reset php state + * - Nest + * - Custom state helpers + * + * User code should call parent::setUp() before custom setup code + */ + protected function setUp(): void + { + if (!defined('FRAMEWORK_PATH')) { + trigger_error( + 'Missing constants, did you remember to include the test bootstrap in your phpunit.xml file?', + E_USER_WARNING + ); + } + + // Call state helpers + static::$state->setUp($this); + + // We cannot run the tests on this abstract class. + if (static::class == __CLASS__) { + $this->markTestSkipped(sprintf('Skipping %s ', static::class)); + } + + // i18n needs to be set to the defaults or tests fail + if (class_exists(i18n::class)) { + i18n::set_locale(i18n::config()->uninherited('default_locale')); + } + + // Set default timezone consistently to avoid NZ-specific dependencies + date_default_timezone_set('UTC'); + + if (class_exists(Member::class)) { + Member::set_password_validator(null); + } + + if (class_exists(Cookie::class)) { + Cookie::config()->update('report_errors', false); + } + + if (class_exists(RootURLController::class)) { + RootURLController::reset(); + } + + if (class_exists(Security::class)) { + Security::clear_database_is_ready(); + } + + // Set up test routes + $this->setUpRoutes(); + + $fixtureFiles = $this->getFixturePaths(); + + if ($this->shouldSetupDatabaseForCurrentTest($fixtureFiles)) { + // Assign fixture factory to deprecated prop in case old tests use it over the getter + /** @var FixtureTestState $fixtureState */ + $fixtureState = static::$state->getStateByName('fixtures'); + $this->fixtureFactory = $fixtureState->getFixtureFactory(static::class); + + $this->logInWithPermission('ADMIN'); + } + + // turn off template debugging + if (class_exists(SSViewer::class)) { + SSViewer::config()->update('source_file_comments', false); + } + + // Set up the test mailer + if (class_exists(TestMailer::class)) { + Injector::inst()->registerService(new TestMailer(), Mailer::class); + } + + if (class_exists(Email::class)) { + Email::config()->remove('send_all_emails_to'); + Email::config()->remove('send_all_emails_from'); + Email::config()->remove('cc_all_emails_to'); + Email::config()->remove('bcc_all_emails_to'); + } + } + + + /** + * Helper method to determine if the current test should enable a test database + * + * @param $fixtureFiles + * @return bool + */ + protected function shouldSetupDatabaseForCurrentTest($fixtureFiles) + { + $databaseEnabledByDefault = $fixtureFiles || $this->usesDatabase; + + return ($databaseEnabledByDefault && !$this->currentTestDisablesDatabase()) + || $this->currentTestEnablesDatabase(); + } + + /** + * Helper method to check, if the current test uses the database. + * This can be switched on with the annotation "@useDatabase" + * + * @return bool + */ + protected function currentTestEnablesDatabase() + { + $annotations = $this->getAnnotations(); + + return array_key_exists('useDatabase', $annotations['method']) + && $annotations['method']['useDatabase'][0] !== 'false'; + } + + /** + * Helper method to check, if the current test uses the database. + * This can be switched on with the annotation "@useDatabase false" + * + * @return bool + */ + protected function currentTestDisablesDatabase() + { + $annotations = $this->getAnnotations(); + + return array_key_exists('useDatabase', $annotations['method']) + && $annotations['method']['useDatabase'][0] === 'false'; + } + + /** + * Called once per test case ({@link SapphireTest} subclass). + * This is different to {@link setUp()}, which gets called once + * per method. Useful to initialize expensive operations which + * don't change state for any called method inside the test, + * e.g. dynamically adding an extension. See {@link teardownAfterClass()} + * for tearing down the state again. + * + * Always sets up in order: + * - Reset php state + * - Nest + * - Custom state helpers + * + * User code should call parent::setUpBeforeClass() before custom setup code + * + * @throws Exception + */ + public static function setUpBeforeClass(): void + { + // Start tests + static::start(); + + if (!static::$state) { + throw new Exception('SapphireTest failed to bootstrap!'); + } + + // Call state helpers + static::$state->setUpOnce(static::class); + + // Build DB if we have objects + if (class_exists(DataObject::class) && static::getExtraDataObjects()) { + DataObject::reset(); + static::resetDBSchema(true, true); + } + } + + /** + * tearDown method that's called once per test class rather once per test method. + * + * Always sets up in order: + * - Custom state helpers + * - Unnest + * - Reset php state + * + * User code should call parent::tearDownAfterClass() after custom tear down code + */ + public static function tearDownAfterClass(): void + { + // Call state helpers + static::$state->tearDownOnce(static::class); + + // Reset DB schema + static::resetDBSchema(); + } + + /** + * @return FixtureFactory|false + * @deprecated 4.0.0:5.0.0 + */ + public function getFixtureFactory() + { + Deprecation::notice('5.0', __FUNCTION__ . ' is deprecated, use ' . FixtureTestState::class . ' instead'); + /** @var FixtureTestState $state */ + $state = static::$state->getStateByName('fixtures'); + return $state->getFixtureFactory(static::class); + } + + /** + * Sets a new fixture factory + * @param FixtureFactory $factory + * @return $this + * @deprecated 4.0.0:5.0.0 + */ + public function setFixtureFactory(FixtureFactory $factory) + { + Deprecation::notice('5.0', __FUNCTION__ . ' is deprecated, use ' . FixtureTestState::class . ' instead'); + /** @var FixtureTestState $state */ + $state = static::$state->getStateByName('fixtures'); + $state->setFixtureFactory($factory, static::class); + $this->fixtureFactory = $factory; + return $this; + } + + /** + * Get the ID of an object from the fixture. + * + * @param string $className The data class or table name, as specified in your fixture file. Parent classes won't work + * @param string $identifier The identifier string, as provided in your fixture file + * @return int + */ + protected function idFromFixture($className, $identifier) + { + /** @var FixtureTestState $state */ + $state = static::$state->getStateByName('fixtures'); + $id = $state->getFixtureFactory(static::class)->getId($className, $identifier); + + if (!$id) { + throw new InvalidArgumentException(sprintf( + "Couldn't find object '%s' (class: %s)", + $identifier, + $className + )); + } + + return $id; + } + + /** + * Return all of the IDs in the fixture of a particular class name. + * Will collate all IDs form all fixtures if multiple fixtures are provided. + * + * @param string $className The data class or table name, as specified in your fixture file + * @return array A map of fixture-identifier => object-id + */ + protected function allFixtureIDs($className) + { + /** @var FixtureTestState $state */ + $state = static::$state->getStateByName('fixtures'); + return $state->getFixtureFactory(static::class)->getIds($className); + } + + /** + * Get an object from the fixture. + * + * @param string $className The data class or table name, as specified in your fixture file. Parent classes won't work + * @param string $identifier The identifier string, as provided in your fixture file + * + * @return DataObject + */ + protected function objFromFixture($className, $identifier) + { + /** @var FixtureTestState $state */ + $state = static::$state->getStateByName('fixtures'); + $obj = $state->getFixtureFactory(static::class)->get($className, $identifier); + + if (!$obj) { + throw new InvalidArgumentException(sprintf( + "Couldn't find object '%s' (class: %s)", + $identifier, + $className + )); + } + + return $obj; + } + + /** + * Load a YAML fixture file into the database. + * Once loaded, you can use idFromFixture() and objFromFixture() to get items from the fixture. + * Doesn't clear existing fixtures. + * @param string $fixtureFile The location of the .yml fixture file, relative to the site base dir + * @deprecated 4.0.0:5.0.0 + * + */ + public function loadFixture($fixtureFile) + { + Deprecation::notice('5.0', __FUNCTION__ . ' is deprecated, use ' . FixtureTestState::class . ' instead'); + $fixture = Injector::inst()->create(YamlFixture::class, $fixtureFile); + $fixture->writeInto($this->getFixtureFactory()); + } + + /** + * Clear all fixtures which were previously loaded through + * {@link loadFixture()} + */ + public function clearFixtures() + { + /** @var FixtureTestState $state */ + $state = static::$state->getStateByName('fixtures'); + $state->getFixtureFactory(static::class)->clear(); + } + + /** + * Useful for writing unit tests without hardcoding folder structures. + * + * @return string Absolute path to current class. + */ + protected function getCurrentAbsolutePath() + { + $filename = ClassLoader::inst()->getItemPath(static::class); + if (!$filename) { + throw new LogicException('getItemPath returned null for ' . static::class + . '. Try adding flush=1 to the test run.'); + } + return dirname($filename); + } + + /** + * @return string File path relative to webroot + */ + protected function getCurrentRelativePath() + { + $base = Director::baseFolder(); + $path = $this->getCurrentAbsolutePath(); + if (substr($path, 0, strlen($base)) == $base) { + $path = preg_replace('/^\/*/', '', substr($path, strlen($base))); + } + return $path; + } + + /** + * Setup the test. + * Always sets up in order: + * - Custom state helpers + * - Unnest + * - Reset php state + * + * User code should call parent::tearDown() after custom tear down code + */ + protected function tearDown(): void + { + // Reset mocked datetime + if (class_exists(DBDatetime::class)) { + DBDatetime::clear_mock_now(); + } + + // Stop the redirection that might have been requested in the test. + // Note: Ideally a clean Controller should be created for each test. + // Now all tests executed in a batch share the same controller. + if (class_exists(Controller::class)) { + $controller = Controller::has_curr() ? Controller::curr() : null; + if ($controller && ($response = $controller->getResponse()) && $response->getHeader('Location')) { + $response->setStatusCode(200); + $response->removeHeader('Location'); + } + } + + // Call state helpers + static::$state->tearDown($this); + } + + /** + * Clear the log of emails sent + * + * @return bool True if emails cleared + */ + public function clearEmails() + { + /** @var Mailer $mailer */ + $mailer = Injector::inst()->get(Mailer::class); + if ($mailer instanceof TestMailer) { + $mailer->clearEmails(); + return true; + } + return false; + } + + /** + * Search for an email that was sent. + * All of the parameters can either be a string, or, if they start with "/", a PREG-compatible regular expression. + * @param string $to + * @param string $from + * @param string $subject + * @param string $content + * @return array|null Contains keys: 'Type', 'To', 'From', 'Subject', 'Content', 'PlainContent', 'AttachedFiles', + * 'HtmlContent' + */ + public static function findEmail($to, $from = null, $subject = null, $content = null) + { + /** @var Mailer $mailer */ + $mailer = Injector::inst()->get(Mailer::class); + if ($mailer instanceof TestMailer) { + return $mailer->findEmail($to, $from, $subject, $content); + } + return null; + } + + /** + * Assert that the matching email was sent since the last call to clearEmails() + * All of the parameters can either be a string, or, if they start with "/", a PREG-compatible regular expression. + * + * @param string $to + * @param string $from + * @param string $subject + * @param string $content + */ + public static function assertEmailSent($to, $from = null, $subject = null, $content = null) + { + $found = (bool)static::findEmail($to, $from, $subject, $content); + + $infoParts = ''; + $withParts = []; + if ($to) { + $infoParts .= " to '$to'"; + } + if ($from) { + $infoParts .= " from '$from'"; + } + if ($subject) { + $withParts[] = "subject '$subject'"; + } + if ($content) { + $withParts[] = "content '$content'"; + } + if ($withParts) { + $infoParts .= ' with ' . implode(' and ', $withParts); + } + + static::assertTrue( + $found, + "Failed asserting that an email was sent$infoParts." + ); + } + + + /** + * Assert that the given {@link SS_List} includes DataObjects matching the given key-value + * pairs. Each match must correspond to 1 distinct record. + * + * @param SS_List|array $matches The patterns to match. Each pattern is a map of key-value pairs. You can + * either pass a single pattern or an array of patterns. + * @param SS_List $list The {@link SS_List} to test. + * @param string $message + * + * Examples + * -------- + * Check that $members includes an entry with Email = sam@example.com: + * $this->assertListContains(['Email' => '...@example.com'], $members); + * + * Check that $members includes entries with Email = sam@example.com and with + * Email = ingo@example.com: + * $this->assertListContains([ + * ['Email' => '...@example.com'], + * ['Email' => 'i...@example.com'], + * ], $members); + */ + public static function assertListContains($matches, SS_List $list, $message = '') + { + if (!is_array($matches)) { + throw self::createInvalidArgumentException( + 1, + 'array' + ); + } + + static::assertThat( + $list, + new SSListContains( + $matches + ), + $message + ); + } + + /** + * @param $matches + * @param $dataObjectSet + * @deprecated 4.0.0:5.0.0 Use assertListContains() instead + * + */ + public function assertDOSContains($matches, $dataObjectSet) + { + Deprecation::notice('5.0', 'Use assertListContains() instead'); + static::assertListContains($matches, $dataObjectSet); + } + + /** + * Asserts that no items in a given list appear in the given dataobject list + * + * @param SS_List|array $matches The patterns to match. Each pattern is a map of key-value pairs. You can + * either pass a single pattern or an array of patterns. + * @param SS_List $list The {@link SS_List} to test. + * @param string $message + * + * Examples + * -------- + * Check that $members doesn't have an entry with Email = sam@example.com: + * $this->assertListNotContains(['Email' => '...@example.com'], $members); + * + * Check that $members doesn't have entries with Email = sam@example.com and with + * Email = ingo@example.com: + * $this->assertListNotContains([ + * ['Email' => '...@example.com'], + * ['Email' => 'i...@example.com'], + * ], $members); + */ + public static function assertListNotContains($matches, SS_List $list, $message = '') + { + if (!is_array($matches)) { + throw self::createInvalidArgumentException( + 1, + 'array' + ); + } + + $constraint = new LogicalNot( + new SSListContains( + $matches + ) + ); + + static::assertThat( + $list, + $constraint, + $message + ); + } + + /** + * @param $matches + * @param $dataObjectSet + * @deprecated 4.0.0:5.0.0 Use assertListNotContains() instead + * + */ + public static function assertNotDOSContains($matches, $dataObjectSet) + { + Deprecation::notice('5.0', 'Use assertListNotContains() instead'); + static::assertListNotContains($matches, $dataObjectSet); + } + + /** + * Assert that the given {@link SS_List} includes only DataObjects matching the given + * key-value pairs. Each match must correspond to 1 distinct record. + * + * Example + * -------- + * Check that *only* the entries Sam Minnee and Ingo Schommer exist in $members. Order doesn't + * matter: + * $this->assertListEquals([ + * ['FirstName' =>'Sam', 'Surname' => 'Minnee'], + * ['FirstName' => 'Ingo', 'Surname' => 'Schommer'], + * ], $members); + * + * @param mixed $matches The patterns to match. Each pattern is a map of key-value pairs. You can + * either pass a single pattern or an array of patterns. + * @param mixed $list The {@link SS_List} to test. + * @param string $message + */ + public static function assertListEquals($matches, SS_List $list, $message = '') + { + if (!is_array($matches)) { + throw self::createInvalidArgumentException( + 1, + 'array' + ); + } + + static::assertThat( + $list, + new SSListContainsOnly( + $matches + ), + $message + ); + } + + /** + * @param $matches + * @param SS_List $dataObjectSet + * @deprecated 4.0.0:5.0.0 Use assertListEquals() instead + * + */ + public function assertDOSEquals($matches, $dataObjectSet) + { + Deprecation::notice('5.0', 'Use assertListEquals() instead'); + static::assertListEquals($matches, $dataObjectSet); + } + + + /** + * Assert that the every record in the given {@link SS_List} matches the given key-value + * pairs. + * + * Example + * -------- + * Check that every entry in $members has a Status of 'Active': + * $this->assertListAllMatch(['Status' => 'Active'], $members); + * + * @param mixed $match The pattern to match. The pattern is a map of key-value pairs. + * @param mixed $list The {@link SS_List} to test. + * @param string $message + */ + public static function assertListAllMatch($match, SS_List $list, $message = '') + { + if (!is_array($match)) { + throw self::createInvalidArgumentException( + 1, + 'array' + ); + } + + static::assertThat( + $list, + new SSListContainsOnlyMatchingItems( + $match + ), + $message + ); + } + + /** + * @param $match + * @param SS_List $dataObjectSet + * @deprecated 4.0.0:5.0.0 Use assertListAllMatch() instead + * + */ + public function assertDOSAllMatch($match, SS_List $dataObjectSet) + { + Deprecation::notice('5.0', 'Use assertListAllMatch() instead'); + static::assertListAllMatch($match, $dataObjectSet); + } + + /** + * Removes sequences of repeated whitespace characters from SQL queries + * making them suitable for string comparison + * + * @param string $sql + * @return string The cleaned and normalised SQL string + */ + protected static function normaliseSQL($sql) + { + return trim(preg_replace('/\s+/m', ' ', $sql)); + } + + /** + * Asserts that two SQL queries are equivalent + * + * @param string $expectedSQL + * @param string $actualSQL + * @param string $message + */ + public static function assertSQLEquals( + $expectedSQL, + $actualSQL, + $message = '' + ) { + // Normalise SQL queries to remove patterns of repeating whitespace + $expectedSQL = static::normaliseSQL($expectedSQL); + $actualSQL = static::normaliseSQL($actualSQL); + + static::assertEquals($expectedSQL, $actualSQL, $message); + } + + /** + * Asserts that a SQL query contains a SQL fragment + * + * @param string $needleSQL + * @param string $haystackSQL + * @param string $message + */ + public static function assertSQLContains( + $needleSQL, + $haystackSQL, + $message = '' + ) { + $needleSQL = static::normaliseSQL($needleSQL); + $haystackSQL = static::normaliseSQL($haystackSQL); + if (is_iterable($haystackSQL)) { + /** @var iterable $iterableHaystackSQL */ + $iterableHaystackSQL = $haystackSQL; + static::assertContains($needleSQL, $iterableHaystackSQL, $message); + } else { + static::assertStringContainsString($needleSQL, $haystackSQL, $message); + } + } + + /** + * Asserts that a SQL query contains a SQL fragment + * + * @param string $needleSQL + * @param string $haystackSQL + * @param string $message + */ + public static function assertSQLNotContains( + $needleSQL, + $haystackSQL, + $message = '' + ) { + $needleSQL = static::normaliseSQL($needleSQL); + $haystackSQL = static::normaliseSQL($haystackSQL); + if (is_iterable($haystackSQL)) { + /** @var iterable $iterableHaystackSQL */ + $iterableHaystackSQL = $haystackSQL; + static::assertNotContains($needleSQL, $iterableHaystackSQL, $message); + } else { + static::assertNotStringContainsString($needleSQL, $haystackSQL, $message); + } + } + + /** + * Start test environment + */ + public static function start() + { + if (static::is_running_test()) { + return; + } + + // Health check + if (InjectorLoader::inst()->countManifests()) { + throw new LogicException('SapphireTest::start() cannot be called within another application'); + } + static::set_is_running_test(true); + + // Test application + $kernel = new TestKernel(BASE_PATH); + + if (class_exists(HTTPApplication::class)) { + // Mock request + $_SERVER['argv'] = ['vendor/bin/phpunit', '/']; + $request = CLIRequestBuilder::createFromEnvironment(); + + $app = new HTTPApplication($kernel); + $flush = array_key_exists('flush', $request->getVars()); + + // Custom application + $res = $app->execute($request, function (HTTPRequest $request) { + // Start session and execute + $request->getSession()->init($request); + + // Invalidate classname spec since the test manifest will now pull out new subclasses for each internal class + // (e.g. Member will now have various subclasses of DataObjects that implement TestOnly) + DataObject::reset(); + + // Set dummy controller; + $controller = Controller::create(); + $controller->setRequest($request); + $controller->pushCurrent(); + $controller->doInit(); + }, $flush); + + if ($res && $res->isError()) { + throw new LogicException($res->getBody()); + } + } else { + // Allow flush from the command line in the absence of HTTPApplication's special sauce + $flush = false; + foreach ($_SERVER['argv'] as $arg) { + if (preg_match('/^(--)?flush(=1)?$/', $arg)) { + $flush = true; + } + } + $kernel->boot($flush); + } + + // Register state + static::$state = SapphireTestState::singleton(); + // Register temp DB holder + static::tempDB(); + } + + /** + * Reset the testing database's schema, but only if it is active + * @param bool $includeExtraDataObjects If true, the extraDataObjects tables will also be included + * @param bool $forceCreate Force DB to be created if it doesn't exist + */ + public static function resetDBSchema($includeExtraDataObjects = false, $forceCreate = false) + { + if (!static::$tempDB) { + return; + } + + // Check if DB is active before reset + if (!static::$tempDB->isUsed()) { + if (!$forceCreate) { + return; + } + static::$tempDB->build(); + } + $extraDataObjects = $includeExtraDataObjects ? static::getExtraDataObjects() : []; + static::$tempDB->resetDBSchema((array)$extraDataObjects); + } + + /** + * A wrapper for automatically performing callbacks as a user with a specific permission + * + * @param string|array $permCode + * @param callable $callback + * @return mixed + */ + public function actWithPermission($permCode, $callback) + { + return Member::actAs($this->createMemberWithPermission($permCode), $callback); + } + + /** + * Create Member and Group objects on demand with specific permission code + * + * @param string|array $permCode + * @return Member + */ + protected function createMemberWithPermission($permCode) + { + if (is_array($permCode)) { + $permArray = $permCode; + $permCode = implode('.', $permCode); + } else { + $permArray = [$permCode]; + } + + // Check cached member + if (isset($this->cache_generatedMembers[$permCode])) { + $member = $this->cache_generatedMembers[$permCode]; + } else { + // Generate group with these permissions + $group = Group::create(); + $group->Title = "$permCode group"; + $group->write(); + + // Create each individual permission + foreach ($permArray as $permArrayItem) { + $permission = Permission::create(); + $permission->Code = $permArrayItem; + $permission->write(); + $group->Permissions()->add($permission); + } + + $member = Member::get()->filter([ + 'Email' => "$permCode@example.org", + ])->first(); + if (!$member) { + $member = Member::create(); + } + + $member->FirstName = $permCode; + $member->Surname = 'User'; + $member->Email = "$permCode@example.org"; + $member->write(); + $group->Members()->add($member); + + $this->cache_generatedMembers[$permCode] = $member; + } + return $member; + } + + /** + * Create a member and group with the given permission code, and log in with it. + * Returns the member ID. + * + * @param string|array $permCode Either a permission, or list of permissions + * @return int Member ID + */ + public function logInWithPermission($permCode = 'ADMIN') + { + $member = $this->createMemberWithPermission($permCode); + $this->logInAs($member); + return $member->ID; + } + + /** + * Log in as the given member + * + * @param Member|int|string $member The ID, fixture codename, or Member object of the member that you want to log in + */ + public function logInAs($member) + { + if (is_numeric($member)) { + $member = DataObject::get_by_id(Member::class, $member); + } elseif (!is_object($member)) { + $member = $this->objFromFixture(Member::class, $member); + } + Injector::inst()->get(IdentityStore::class)->logIn($member); + } + + /** + * Log out the current user + */ + public function logOut() + { + /** @var IdentityStore $store */ + $store = Injector::inst()->get(IdentityStore::class); + $store->logOut(); + } + + /** + * Cache for logInWithPermission() + */ + protected $cache_generatedMembers = []; + + /** + * Test against a theme. + * + * @param string $themeBaseDir themes directory + * @param string $theme Theme name + * @param callable $callback + * @throws Exception + */ + protected function useTestTheme($themeBaseDir, $theme, $callback) + { + Config::nest(); + if (strpos($themeBaseDir, BASE_PATH) === 0) { + $themeBaseDir = substr($themeBaseDir, strlen(BASE_PATH)); + } + SSViewer::config()->update('theme_enabled', true); + SSViewer::set_themes([$themeBaseDir . '/themes/' . $theme, '$default']); + + try { + $callback(); + } finally { + Config::unnest(); + } + } + + /** + * Get fixture paths for this test + * + * @return array List of paths + */ + protected function getFixturePaths() + { + $fixtureFile = static::get_fixture_file(); + if (empty($fixtureFile)) { + return []; + } + + $fixtureFiles = is_array($fixtureFile) ? $fixtureFile : [$fixtureFile]; + + return array_map(function ($fixtureFilePath) { + return $this->resolveFixturePath($fixtureFilePath); + }, $fixtureFiles); + } + + /** + * Return all extra objects to scaffold for this test + * @return array + */ + public static function getExtraDataObjects() + { + return static::$extra_dataobjects; + } + + /** + * Get additional controller classes to register routes for + * + * @return array + */ + public static function getExtraControllers() + { + return static::$extra_controllers; + } + + /** + * Map a fixture path to a physical file + * + * @param string $fixtureFilePath + * @return string + */ + protected function resolveFixturePath($fixtureFilePath) + { + // support loading via composer name path. + if (strpos($fixtureFilePath, ':') !== false) { + return ModuleResourceLoader::singleton()->resolvePath($fixtureFilePath); + } + + // Support fixture paths relative to the test class, rather than relative to webroot + // String checking is faster than file_exists() calls. + $resolvedPath = realpath($this->getCurrentAbsolutePath() . '/' . $fixtureFilePath); + if ($resolvedPath) { + return $resolvedPath; + } + + // Check if file exists relative to base dir + $resolvedPath = realpath(Director::baseFolder() . '/' . $fixtureFilePath); + if ($resolvedPath) { + return $resolvedPath; + } + + return $fixtureFilePath; + } + + protected function setUpRoutes() + { + if (!class_exists(Director::class)) { + return; + } + + // Get overridden routes + $rules = $this->getExtraRoutes(); + + // Add all other routes + foreach (Director::config()->uninherited('rules') as $route => $rule) { + if (!isset($rules[$route])) { + $rules[$route] = $rule; + } + } + + // Add default catch-all rule + $rules['$Controller//$Action/$ID/$OtherID'] = '*'; + + // Add controller-name auto-routing + Director::config()->set('rules', $rules); + } + + /** + * Get extra routes to merge into Director.rules + * + * @return array + */ + protected function getExtraRoutes() + { + $rules = []; + foreach ($this->getExtraControllers() as $class) { + $controllerInst = Controller::singleton($class); + $link = Director::makeRelative($controllerInst->Link()); + $route = rtrim($link, '/') . '//$Action/$ID/$OtherID'; + $rules[$route] = $class; + } + return $rules; + } + + /** + * Reimplementation of phpunit5 PHPUnit_Util_InvalidArgumentHelper::factory() + * + * @param $argument + * @param $type + * @param $value + */ + public static function createInvalidArgumentException($argument, $type, $value = null) + { + $stack = debug_backtrace(false); + + return new PHPUnitFrameworkException( + sprintf( + 'Argument #%d%sof %s::%s() must be a %s', + $argument, + $value !== null ? ' (' . gettype($value) . '#' . $value . ')' : ' (No Value) ', + $stack[1]['class'], + $stack[1]['function'], + $type + ) + ); + } + + /** + * Returns the annotations for this test. + * + * @return array + */ + public function getAnnotations() + { + return TestUtil::parseTestMethodAnnotations( + get_class($this), + $this->getName(false) + ); + } + } +} + +/* ------------------------------------------------- + * + * This version of SapphireTest is for phpunit 5 + * The phpunit 9 verison is at the top of this file + * + * PHPUnit_Extensions_GroupTestSuite is a class that only exists in phpunit 5 + * + * ------------------------------------------------- + */ +if (!class_exists(PHPUnit_Extensions_GroupTestSuite::class)) { return; } @@ -51,8 +1377,12 @@ * This class should not be used anywhere outside of unit tests, as phpunit may not be installed * in production sites. */ +// Ignore multiple classes in same file +// @codingStandardsIgnoreStart class SapphireTest extends PHPUnit_Framework_TestCase implements TestOnly { + // @codingStandardsIgnoreEnd + /** * Path to fixture data for this test run. * If passed as an array, multiple fixture files will be loaded. @@ -265,7 +1595,7 @@ public function getRequireDefaultRecordsFrom() * * User code should call parent::setUp() before custom setup code */ - protected function setUp() + protected function setUp(): void { if (!defined('FRAMEWORK_PATH')) { trigger_error( @@ -340,7 +1670,6 @@ protected function setUp() } - /** * Helper method to determine if the current test should enable a test database * @@ -400,7 +1729,7 @@ protected function currentTestDisablesDatabase() * * @throws Exception */ - public static function setUpBeforeClass() + public static function setUpBeforeClass(): void { // Start tests static::start(); @@ -429,7 +1758,7 @@ public static function setUpBeforeClass() * * User code should call parent::tearDownAfterClass() after custom tear down code */ - public static function tearDownAfterClass() + public static function tearDownAfterClass(): void { // Call state helpers static::$state->tearDownOnce(static::class); @@ -439,8 +1768,8 @@ public static function tearDownAfterClass() } /** - * @deprecated 4.0.0:5.0.0 * @return FixtureFactory|false + * @deprecated 4.0.0:5.0.0 */ public function getFixtureFactory() { @@ -452,9 +1781,9 @@ public function getFixtureFactory() /** * Sets a new fixture factory - * @deprecated 4.0.0:5.0.0 * @param FixtureFactory $factory * @return $this + * @deprecated 4.0.0:5.0.0 */ public function setFixtureFactory(FixtureFactory $factory) { @@ -533,9 +1862,9 @@ protected function objFromFixture($className, $identifier) * Load a YAML fixture file into the database. * Once loaded, you can use idFromFixture() and objFromFixture() to get items from the fixture. * Doesn't clear existing fixtures. + * @param string $fixtureFile The location of the .yml fixture file, relative to the site base dir * @deprecated 4.0.0:5.0.0 * - * @param string $fixtureFile The location of the .yml fixture file, relative to the site base dir */ public function loadFixture($fixtureFile) { @@ -592,7 +1921,7 @@ protected function getCurrentRelativePath() * * User code should call parent::tearDown() after custom tear down code */ - protected function tearDown() + protected function tearDown(): void { // Reset mocked datetime if (class_exists(DBDatetime::class)) { @@ -614,7 +1943,7 @@ protected function tearDown() static::$state->tearDown($this); } - public static function assertContains( + public static function assertStringContainsString( $needle, $haystack, $message = '', @@ -625,10 +1954,10 @@ public static function assertContains( if ($haystack instanceof DBField) { $haystack = (string)$haystack; } - parent::assertContains($needle, $haystack, $message, $ignoreCase, $checkForObjectIdentity, $checkForNonObjectIdentity); + parent::assertStringContainsString($needle, $haystack, $message, $ignoreCase, $checkForObjectIdentity, $checkForNonObjectIdentity); } - public static function assertNotContains( + public static function assertNotStringContainsString( $needle, $haystack, $message = '', @@ -639,7 +1968,7 @@ public static function assertNotContains( if ($haystack instanceof DBField) { $haystack = (string)$haystack; } - parent::assertNotContains($needle, $haystack, $message, $ignoreCase, $checkForObjectIdentity, $checkForNonObjectIdentity); + parent::assertNotStringContainsString($needle, $haystack, $message, $ignoreCase, $checkForObjectIdentity, $checkForNonObjectIdentity); } /** @@ -756,10 +2085,10 @@ public static function assertListContains($matches, SS_List $list, $message = '' } /** - * @deprecated 4.0.0:5.0.0 Use assertListContains() instead - * * @param $matches * @param $dataObjectSet + * @deprecated 4.0.0:5.0.0 Use assertListContains() instead + * */ public function assertDOSContains($matches, $dataObjectSet) { @@ -796,7 +2125,7 @@ public static function assertListNotContains($matches, SS_List $list, $message = ); } - $constraint = new PHPUnit_Framework_Constraint_Not( + $constraint = new PHPUnit_Framework_Constraint_Not( new SSListContains( $matches ) @@ -810,10 +2139,10 @@ public static function assertListNotContains($matches, SS_List $list, $message = } /** - * @deprecated 4.0.0:5.0.0 Use assertListNotContains() instead - * * @param $matches * @param $dataObjectSet + * @deprecated 4.0.0:5.0.0 Use assertListNotContains() instead + * */ public static function assertNotDOSContains($matches, $dataObjectSet) { @@ -858,10 +2187,10 @@ public static function assertListEquals($matches, SS_List $list, $message = '') } /** - * @deprecated 4.0.0:5.0.0 Use assertListEquals() instead - * * @param $matches * @param SS_List $dataObjectSet + * @deprecated 4.0.0:5.0.0 Use assertListEquals() instead + * */ public function assertDOSEquals($matches, $dataObjectSet) { @@ -902,10 +2231,10 @@ public static function assertListAllMatch($match, SS_List $list, $message = '') } /** - * @deprecated 4.0.0:5.0.0 Use assertListAllMatch() instead - * * @param $match * @param SS_List $dataObjectSet + * @deprecated 4.0.0:5.0.0 Use assertListAllMatch() instead + * */ public function assertDOSAllMatch($match, SS_List $dataObjectSet) { @@ -971,7 +2300,7 @@ public static function assertSQLContains( $needleSQL = static::normaliseSQL($needleSQL); $haystackSQL = static::normaliseSQL($haystackSQL); - static::assertContains($needleSQL, $haystackSQL, $message, $ignoreCase, $checkForObjectIdentity); + static::assertStringContainsString($needleSQL, $haystackSQL, $message, $ignoreCase, $checkForObjectIdentity); } /** @@ -993,7 +2322,7 @@ public static function assertSQLNotContains( $needleSQL = static::normaliseSQL($needleSQL); $haystackSQL = static::normaliseSQL($haystackSQL); - static::assertNotContains($needleSQL, $haystackSQL, $message, $ignoreCase, $checkForObjectIdentity); + static::assertNotStringContainsString($needleSQL, $haystackSQL, $message, $ignoreCase, $checkForObjectIdentity); } /** diff --git a/tests/behat/src/CmsFormsContext.php b/tests/behat/src/CmsFormsContext.php index 7f495d7e53f..125d18f3f34 100644 --- a/tests/behat/src/CmsFormsContext.php +++ b/tests/behat/src/CmsFormsContext.php @@ -7,6 +7,7 @@ use Behat\Mink\Exception\ElementHtmlException; use Behat\Gherkin\Node\TableNode; use Behat\Mink\Session; +use PHPUnit\Framework\Assert; use SilverStripe\BehatExtension\Context\MainContextAwareTrait; use SilverStripe\BehatExtension\Utility\StepHelper; use Symfony\Component\DomCrawler\Crawler; @@ -55,9 +56,9 @@ public function stepIShouldSeeAnEditPageForm($negative) $form = $page->find('css', '#Form_EditForm'); if (trim($negative)) { - assertNull($form, 'I should not see an edit page form'); + Assert::assertNull($form, 'I should not see an edit page form'); } else { - assertNotNull($form, 'I should see an edit page form'); + Assert::assertNotNull($form, 'I should see an edit page form'); } } @@ -154,20 +155,31 @@ public function stepContentInHtmlFieldShouldHaveFormatting($text, $field, $negat $matchedNode = $node; } } - assertNotNull($matchedNode); - - $assertFn = $negate ? 'assertNotEquals' : 'assertEquals'; - if($formatting == 'bold') { - call_user_func($assertFn, 'strong', $matchedNode->nodeName); - } else if($formatting == 'left aligned') { - if($matchedNode->getAttribute('class')) { - call_user_func($assertFn, 'text-left', $matchedNode->getAttribute('class')); - } - } else if($formatting == 'right aligned') { - call_user_func($assertFn, 'text-right', $matchedNode->getAttribute('class')); - } - } - // @codingStandardsIgnoreEnd + Assert::assertNotNull($matchedNode); + + if ($formatting == 'bold') { + if ($negate) { + Assert::assertNotEquals('strong', $matchedNode->nodeName); + } else { + Assert::assertEquals('strong', $matchedNode->nodeName); + } + } else if ($formatting == 'left aligned') { + if ($matchedNode->getAttribute('class')) { + if ($negate) { + Assert::assertNotEquals('text-left', $matchedNode->getAttribute('class')); + } else { + Assert::assertEquals('text-left', $matchedNode->getAttribute('class')); + } + } + } else if ($formatting == 'right aligned') { + if ($negate) { + Assert::assertNotEquals('text-right', $matchedNode->getAttribute('class')); + } else { + Assert::assertEquals('text-right', $matchedNode->getAttribute('class')); + } + } + } + // @codingStandardsIgnoreEnd /** * Selects the first textual match in the HTML editor. Does not support @@ -226,9 +238,9 @@ public function iShouldSeeAField($negative, $text) } if (trim($negative)) { - assertNull($matchedEl); + Assert::assertNull($matchedEl); } else { - assertNotNull($matchedEl); + Assert::assertNotNull($matchedEl); } } @@ -287,19 +299,19 @@ public function iSelectValueInTreeDropdown($text, $selector) $parentElement = null; $this->retryThrowable(function () use (&$parentElement, &$page, $selector) { $parentElement = $page->find('css', $selector); - assertNotNull($parentElement, sprintf('"%s" element not found', $selector)); + Assert::assertNotNull($parentElement, sprintf('"%s" element not found', $selector)); $page = $this->getSession()->getPage(); }); $this->retryThrowable(function () use ($parentElement, $selector) { $dropdown = $parentElement->find('css', '.Select-arrow'); - assertNotNull($dropdown, sprintf('Unable to find the dropdown in "%s"', $selector)); + Assert::assertNotNull($dropdown, sprintf('Unable to find the dropdown in "%s"', $selector)); $dropdown->click(); }); $this->retryThrowable(function () use ($text, $parentElement, $selector) { $element = $parentElement->find('xpath', sprintf('//*[count(*)=0 and contains(.,"%s")]', $text)); - assertNotNull($element, sprintf('"%s" not found in "%s"', $text, $selector)); + Assert::assertNotNull($element, sprintf('"%s" not found in "%s"', $text, $selector)); $element->click(); }); } @@ -322,7 +334,7 @@ protected function getHtmlField($locator) $element = $this->findInputByLabelContent($locator); } - assertNotNull($element, sprintf('HTML field "%s" not found', $locator)); + Assert::assertNotNull($element, sprintf('HTML field "%s" not found', $locator)); return $element; } @@ -335,7 +347,7 @@ protected function findInputByLabelContent($locator) return null; } - assertCount(1, $label, sprintf( + Assert::assertCount(1, $label, sprintf( 'Found more than one element containing the phrase "%s".', $locator )); @@ -406,7 +418,7 @@ public function stepMySessionExpires() public function assertIShouldSeeTheGridFieldButtonForRow($buttonLabel, $gridFieldName, $rowName) { $button = $this->getGridFieldButton($gridFieldName, $rowName, $buttonLabel); - assertNotNull($button, sprintf('Button "%s" not found', $buttonLabel)); + Assert::assertNotNull($button, sprintf('Button "%s" not found', $buttonLabel)); } /** @@ -418,7 +430,7 @@ public function assertIShouldSeeTheGridFieldButtonForRow($buttonLabel, $gridFiel public function assertIShouldNotSeeTheGridFieldButtonForRow($buttonLabel, $gridFieldName, $rowName) { $button = $this->getGridFieldButton($gridFieldName, $rowName, $buttonLabel); - assertNull($button, sprintf('Button "%s" found', $buttonLabel)); + Assert::assertNull($button, sprintf('Button "%s" found', $buttonLabel)); } /** @@ -430,7 +442,7 @@ public function assertIShouldNotSeeTheGridFieldButtonForRow($buttonLabel, $gridF public function stepIClickTheGridFieldButtonForRow($buttonLabel, $gridFieldName, $rowName) { $button = $this->getGridFieldButton($gridFieldName, $rowName, $buttonLabel); - assertNotNull($button, sprintf('Button "%s" not found', $buttonLabel)); + Assert::assertNotNull($button, sprintf('Button "%s" not found', $buttonLabel)); $button->click(); } @@ -447,7 +459,7 @@ protected function getGridFieldButton($gridFieldName, $rowName, $buttonLabel) { $page = $this->getSession()->getPage(); $gridField = $page->find('xpath', sprintf('//*[@data-name="%s"]', $gridFieldName)); - assertNotNull($gridField, sprintf('Gridfield "%s" not found', $gridFieldName)); + Assert::assertNotNull($gridField, sprintf('Gridfield "%s" not found', $gridFieldName)); $name = $gridField->find('xpath', sprintf('//*[count(*)=0 and contains(.,"%s")]', $rowName)); if (!$name) { @@ -472,12 +484,12 @@ public function stepIClickTheListBoxOption($optionLabel, $fieldName) { $page = $this->getSession()->getPage(); $listBox = $page->find('xpath', sprintf('//*[@name="%s[]"]', $fieldName)); - assertNotNull($listBox, sprintf('The listbox %s is not found', $fieldName)); + Assert::assertNotNull($listBox, sprintf('The listbox %s is not found', $fieldName)); $option = $listBox->getParent() ->find('css', '.chosen-choices') ->find('xpath', sprintf('//*[count(*)=0 and contains(.,"%s")]', $optionLabel)); - assertNotNull($option, sprintf('Option %s is not found', $optionLabel)); + Assert::assertNotNull($option, sprintf('Option %s is not found', $optionLabel)); $button = $option->getParent()->find('css', 'a'); diff --git a/tests/behat/src/CmsUiContext.php b/tests/behat/src/CmsUiContext.php index 6e5b3f08417..b3adb6922fe 100644 --- a/tests/behat/src/CmsUiContext.php +++ b/tests/behat/src/CmsUiContext.php @@ -8,6 +8,7 @@ use Behat\Mink\Element\NodeElement; use Behat\Mink\Selector\Xpath\Escaper; use Behat\Mink\Session; +use PHPUnit\Framework\Assert; use SilverStripe\BehatExtension\Context\MainContextAwareTrait; use SilverStripe\BehatExtension\Utility\StepHelper; @@ -72,7 +73,7 @@ public function iShouldSeeTheCms() { $page = $this->getSession()->getPage(); $cms_element = $page->find('css', '.cms'); - assertNotNull($cms_element, 'CMS not found'); + Assert::assertNotNull($cms_element, 'CMS not found'); } /** @@ -116,9 +117,9 @@ public function stepIClickTheToastAction($action) { $page = $this->getMainContext()->getSession()->getPage(); $toasts = $page->find('css', '.toasts'); - assertNotNull($toasts, "We have a toast container"); + Assert::assertNotNull($toasts, "We have a toast container"); $toastAction = $toasts->find('named', ['link_or_button', "'{$action}'"]); - assertNotNull($toastAction, "We have a $action toast action"); + Assert::assertNotNull($toastAction, "We have a $action toast action"); $toastAction->click(); } @@ -145,7 +146,7 @@ protected function getCmsTabsElement() $page = $this->getSession()->getPage(); $cms_content_header_tabs = $page->find('css', '.cms-content-header-tabs'); - assertNotNull($cms_content_header_tabs, 'CMS tabs not found'); + Assert::assertNotNull($cms_content_header_tabs, 'CMS tabs not found'); return $cms_content_header_tabs; } @@ -160,7 +161,7 @@ protected function getCmsContentToolbarElement() $page = $this->getSession()->getPage(); $cms_content_toolbar_element = $page->find('css', '.cms-content-toolbar'); - assertNotNull($cms_content_toolbar_element, 'CMS content toolbar not found'); + Assert::assertNotNull($cms_content_toolbar_element, 'CMS content toolbar not found'); return $cms_content_toolbar_element; } @@ -174,7 +175,7 @@ protected function getCmsTreeElement() $page = $this->getSession()->getPage(); $cms_tree_element = $page->find('css', '.cms-tree'); - assertNotNull($cms_tree_element, 'CMS tree not found'); + Assert::assertNotNull($cms_tree_element, 'CMS tree not found'); return $cms_tree_element; } @@ -187,7 +188,7 @@ public function iShouldSeeAButtonInCmsContentToolbar($text) $cms_content_toolbar_element = $this->getCmsContentToolbarElement(); $element = $cms_content_toolbar_element->find('named', ['link_or_button', "'$text'"]); - assertNotNull($element, sprintf('%s button not found', $text)); + Assert::assertNotNull($element, sprintf('%s button not found', $text)); } /** @@ -198,7 +199,7 @@ public function stepIShouldSeeInCmsTree($text) // Wait until visible $cmsTreeElement = $this->getCmsTreeElement(); $element = $cmsTreeElement->find('named', ['content', "'$text'"]); - assertNotNull($element, sprintf('%s not found', $text)); + Assert::assertNotNull($element, sprintf('%s not found', $text)); } /** @@ -209,7 +210,7 @@ public function stepIShouldNotSeeInCmsTree($text) // Wait until not visible $cmsTreeElement = $this->getCmsTreeElement(); $element = $cmsTreeElement->find('named', ['content', "'$text'"]); - assertNull($element, sprintf('%s found', $text)); + Assert::assertNull($element, sprintf('%s found', $text)); } /** @@ -224,14 +225,14 @@ public function stepIShouldSeeInCmsList($negate, $text) ); $page = $this->getSession()->getPage(); $cmsListElement = $page->find('css', '.cms-list'); - assertNotNull($cmsListElement, 'CMS list not found'); + Assert::assertNotNull($cmsListElement, 'CMS list not found'); // Check text within this element $element = $cmsListElement->find('named', ['content', "'$text'"]); if (strstr($negate, 'not')) { - assertNull($element, sprintf('Unexpected %s found in cms list', $text)); + Assert::assertNull($element, sprintf('Unexpected %s found in cms list', $text)); } else { - assertNotNull($element, sprintf('Expected %s not found in cms list', $text)); + Assert::assertNotNull($element, sprintf('Expected %s not found in cms list', $text)); } } @@ -241,7 +242,7 @@ public function stepIShouldSeeInCmsList($negate, $text) public function stepIShouldSeeInCMSContentTabs($text) { // Wait until visible - assertNotNull($this->getCmsTabElement($text), sprintf('%s content tab not found', $text)); + Assert::assertNotNull($this->getCmsTabElement($text), sprintf('%s content tab not found', $text)); } /** @@ -283,7 +284,7 @@ public function stepIClickOnElementInTheContextMenu($method, $link) "window.jQuery && window.jQuery('.jstree-apple-context').size() > 0" ); $regionObj = $context->getRegionObj('.jstree-apple-context'); - assertNotNull($regionObj, "Context menu could not be found"); + Assert::assertNotNull($regionObj, "Context menu could not be found"); $linkObj = $regionObj->findLink($link); if (empty($linkObj)) { @@ -304,7 +305,7 @@ public function stepIClickOnElementInTheTree($method, $text) { $treeEl = $this->getCmsTreeElement(); $treeNode = $treeEl->findLink($text); - assertNotNull($treeNode, sprintf('%s not found', $text)); + Assert::assertNotNull($treeNode, sprintf('%s not found', $text)); $this->interactWithElement($treeNode, $method); } @@ -314,7 +315,7 @@ public function stepIClickOnElementInTheTree($method, $text) public function stepIClickOnElementInTheHeaderTabs($method, $text) { $tabsNode = $this->getCmsTabElement($text); - assertNotNull($tabsNode, sprintf('%s not found', $text)); + Assert::assertNotNull($tabsNode, sprintf('%s not found', $text)); $this->interactWithElement($tabsNode, $method); } @@ -324,8 +325,8 @@ public function stepIClickOnElementInTheHeaderTabs($method, $text) public function theHeaderTabShouldBeActive($text) { $element = $this->getCmsTabElement($text); - assertNotNull($element); - assertTrue($element->hasClass('active')); + Assert::assertNotNull($element); + Assert::assertTrue($element->hasClass('active')); } /** @@ -334,8 +335,8 @@ public function theHeaderTabShouldBeActive($text) public function theHeaderTabShouldNotBeActive($text) { $element = $this->getCmsTabElement($text); - assertNotNull($element); - assertFalse($element->hasClass('active')); + Assert::assertNotNull($element); + Assert::assertFalse($element->hasClass('active')); } /** @@ -354,7 +355,7 @@ public function iExpandTheCmsPanel() //Tries to find the first visiable toggle in the page $page = $this->getSession()->getPage(); $toggle_elements = $page->findAll('css', '.toggle-expand'); - assertNotNull($toggle_elements, 'Panel toggle not found'); + Assert::assertNotNull($toggle_elements, 'Panel toggle not found'); /** @var NodeElement $toggle */ foreach ($toggle_elements as $toggle) { if ($toggle->isVisible()) { @@ -370,7 +371,7 @@ public function iExpandTheContentFilters($action) { $page = $this->getSession()->getPage(); $filterButton = $page->find('css', '.search-box__filter-trigger'); - assertNotNull($filterButton, sprintf('Filter button link not found')); + Assert::assertNotNull($filterButton, sprintf('Filter button link not found')); $filterButtonExpanded = $filterButton->getAttribute('aria-expanded'); @@ -421,20 +422,20 @@ public function iExpandInTheTree($action, $nodeText) //Tries to find the first visiable matched Node in the page $treeEl = $this->getCmsTreeElement(); $treeNode = $treeEl->findLink($nodeText); - assertNotNull($treeNode, sprintf('%s link not found', $nodeText)); + Assert::assertNotNull($treeNode, sprintf('%s link not found', $nodeText)); $cssIcon = $treeNode->getParent()->getAttribute("class"); if ($action == "expand") { //ensure it is collapsed if (false === strpos($cssIcon, 'jstree-open')) { $nodeIcon = $treeNode->getParent()->find('css', '.jstree-icon'); - assertTrue($nodeIcon->isVisible(), "CMS node '$nodeText' not found"); + Assert::assertTrue($nodeIcon->isVisible(), "CMS node '$nodeText' not found"); $nodeIcon->click(); } } else { //ensure it is expanded if (false === strpos($cssIcon, 'jstree-closed')) { $nodeIcon = $treeNode->getParent()->find('css', '.jstree-icon'); - assertTrue($nodeIcon->isVisible(), "CMS node '$nodeText' not found"); + Assert::assertTrue($nodeIcon->isVisible(), "CMS node '$nodeText' not found"); $nodeIcon->click(); } } @@ -452,7 +453,7 @@ public function iShouldSeeACmsTab($negate, $tab) $page = $this->getSession()->getPage(); $tabsets = $page->findAll('css', '.ui-tabs-nav'); - assertNotNull($tabsets, 'CMS tabs not found'); + Assert::assertNotNull($tabsets, 'CMS tabs not found'); $tab_element = null; /** @var NodeElement $tabset */ @@ -463,9 +464,9 @@ public function iShouldSeeACmsTab($negate, $tab) } } if ($negate) { - assertNull($tab_element, sprintf('%s tab found', $tab)); + Assert::assertNull($tab_element, sprintf('%s tab found', $tab)); } else { - assertNotNull($tab_element, sprintf('%s tab not found', $tab)); + Assert::assertNotNull($tab_element, sprintf('%s tab not found', $tab)); } } @@ -481,7 +482,7 @@ public function iClickTheCmsTab($tab) $page = $this->getSession()->getPage(); $tabsets = $page->findAll('css', '.ui-tabs-nav'); - assertNotNull($tabsets, 'CMS tabs not found'); + Assert::assertNotNull($tabsets, 'CMS tabs not found'); $tab_element = null; /** @var NodeElement $tabset */ @@ -491,7 +492,7 @@ public function iClickTheCmsTab($tab) } $tab_element = $tabset->find('named', ['link_or_button', "'$tab'"]); } - assertNotNull($tab_element, sprintf('%s tab not found', $tab)); + Assert::assertNotNull($tab_element, sprintf('%s tab not found', $tab)); $tab_element->click(); } @@ -544,13 +545,13 @@ public function iWaitForThePreviewToLoad() public function iSwitchThePreviewToMode($mode) { $controls = $this->getSession()->getPage()->find('css', '.cms-preview-controls'); - assertNotNull($controls, 'Preview controls not found'); + Assert::assertNotNull($controls, 'Preview controls not found'); $label = $controls->find('xpath', sprintf( './/*[count(*)=0 and contains(text(), \'%s\')]', $mode )); - assertNotNull($label, 'Preview mode switch not found'); + Assert::assertNotNull($label, 'Preview mode switch not found'); $label->click(); @@ -654,7 +655,7 @@ public function theIFillInTheDropdownWith($field, $value) } } - assertGreaterThan(0, count($formFields), sprintf( + Assert::assertGreaterThan(0, count($formFields), sprintf( 'Chosen.js dropdown named "%s" not found', $field )); @@ -669,11 +670,11 @@ public function theIFillInTheDropdownWith($field, $value) } } - assertNotNull($container, 'Chosen.js field container not found'); + Assert::assertNotNull($container, 'Chosen.js field container not found'); // Click on newly expanded list element, indirectly setting the dropdown value $linkEl = $container->find('xpath', './/a'); - assertNotNull($linkEl, 'Chosen.js link element not found'); + Assert::assertNotNull($linkEl, 'Chosen.js link element not found'); $this->getSession()->wait(100); // wait for dropdown overlay to appear $linkEl->click(); diff --git a/tests/behat/src/ConfigContext.php b/tests/behat/src/ConfigContext.php index 7da49e94bc9..0e10db85034 100644 --- a/tests/behat/src/ConfigContext.php +++ b/tests/behat/src/ConfigContext.php @@ -5,6 +5,7 @@ use Behat\Behat\Context\Context; use Behat\Behat\Hook\Scope\AfterScenarioScope; use InvalidArgumentException; +use PHPUnit\Framework\Assert; use SilverStripe\BehatExtension\Context\MainContextAwareTrait; use SilverStripe\Core\Injector\Injector; use SilverStripe\Core\Kernel; @@ -109,19 +110,19 @@ public function stepIHaveConfigFile($filename) // Ensure site is in dev mode /** @var Kernel $kernel */ $kernel = Injector::inst()->get(Kernel::class); - assertEquals(Kernel::DEV, $kernel->getEnvironment(), "Site is in dev mode"); + Assert::assertEquals(Kernel::DEV, $kernel->getEnvironment(), "Site is in dev mode"); // Ensure file exists in specified fixture dir $sourceDir = $this->getConfigPath(); $sourcePath = "{$sourceDir}/{$filename}"; - assertFileExists($sourcePath, "Config file {$filename} exists"); + Assert::assertFileExists($sourcePath, "Config file {$filename} exists"); // Get destination $project = ModuleManifest::config()->get('project') ?: 'mysite'; $mysite = ModuleLoader::getModule($project); - assertNotNull($mysite, 'Project exists'); + Assert::assertNotNull($mysite, 'Project exists'); $destPath = $mysite->getResource("_config/{$filename}")->getPath(); - assertFileNotExists($destPath, "Config file {$filename} hasn't aleady been loaded"); + Assert::assertFileDoesNotExist($destPath, "Config file {$filename} hasn't aleady been loaded"); // Load $this->activatedConfigFiles[] = $destPath; diff --git a/tests/php/Control/ControllerTest.php b/tests/php/Control/ControllerTest.php index 520f7ce5f13..fbdb11ba10c 100644 --- a/tests/php/Control/ControllerTest.php +++ b/tests/php/Control/ControllerTest.php @@ -42,7 +42,7 @@ class ControllerTest extends FunctionalTest UnsecuredController::class, ]; - protected function setUp() + protected function setUp(): void { parent::setUp(); Director::config()->update('alternate_base_url', '/'); @@ -60,7 +60,7 @@ public function testDefaultAction() { /* For a controller with a template, the default action will simple run that template. */ $response = $this->get("TestController/"); - $this->assertContains("This is the main template. Content is 'default content'", $response->getBody()); + $this->assertStringContainsString("This is the main template. Content is 'default content'", $response->getBody()); } public function testMethodActions() @@ -68,18 +68,18 @@ public function testMethodActions() /* The Action can refer to a method that is called on the object. If a method returns an array, then it * will be used to customise the template data */ $response = $this->get("TestController/methodaction"); - $this->assertContains("This is the main template. Content is 'methodaction content'.", $response->getBody()); + $this->assertStringContainsString("This is the main template. Content is 'methodaction content'.", $response->getBody()); /* If the method just returns a string, then that will be used as the response */ $response = $this->get("TestController/stringaction"); - $this->assertContains("stringaction was called.", $response->getBody()); + $this->assertStringContainsString("stringaction was called.", $response->getBody()); } public function testTemplateActions() { /* If there is no method, it can be used to point to an alternative template. */ $response = $this->get("TestController/templateaction"); - $this->assertContains( + $this->assertStringContainsString( "This is the template for templateaction. Content is 'default content'.", $response->getBody() ); @@ -262,12 +262,10 @@ public function testAllowedActions() $this->logOut(); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Invalid allowed_action '*' - */ public function testWildcardAllowedActions() { + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage("Invalid allowed_action '*'"); $this->get('AccessWildcardSecuredController'); } diff --git a/tests/php/Control/CookieTest.php b/tests/php/Control/CookieTest.php index d08bb975461..8f2a8eaaa2b 100644 --- a/tests/php/Control/CookieTest.php +++ b/tests/php/Control/CookieTest.php @@ -10,7 +10,7 @@ class CookieTest extends SapphireTest { - protected function setUp() + protected function setUp(): void { parent::setUp(); Injector::inst()->registerService(new CookieJar($_COOKIE), 'SilverStripe\\Control\\Cookie_Backend'); diff --git a/tests/php/Control/DirectorTest.php b/tests/php/Control/DirectorTest.php index 115b24c9a95..e6fdc26c872 100644 --- a/tests/php/Control/DirectorTest.php +++ b/tests/php/Control/DirectorTest.php @@ -29,7 +29,7 @@ class DirectorTest extends SapphireTest private $originalEnvType; - protected function setUp() + protected function setUp(): void { parent::setUp(); Director::config()->set('alternate_base_url', 'http://www.mysite.com:9090/'); @@ -44,10 +44,10 @@ protected function setUp() $this->expectedRedirect = null; } - protected function tearDown(...$args) + protected function tearDown(): void { Environment::setEnv('SS_ENVIRONMENT_TYPE', $this->originalEnvType); - parent::tearDown(...$args); + parent::tearDown(); } protected function getExtraRoutes() diff --git a/tests/php/Control/Email/EmailTest.php b/tests/php/Control/Email/EmailTest.php index 8857cfed616..ac13ca0cd8c 100644 --- a/tests/php/Control/Email/EmailTest.php +++ b/tests/php/Control/Email/EmailTest.php @@ -3,7 +3,7 @@ namespace SilverStripe\Control\Tests\Email; use DateTime; -use PHPUnit_Framework_MockObject_MockObject; +use PHPUnit\Framework\MockObject\MockObject; use SilverStripe\Control\Email\Email; use SilverStripe\Control\Email\Mailer; use SilverStripe\Control\Email\SwiftMailer; @@ -136,7 +136,7 @@ public function testSendPlain() public function testSend() { - /** @var Email|PHPUnit_Framework_MockObject_MockObject $email */ + /** @var Email|MockObject $email */ $email = $this->makeEmailMock('Test send HTML'); // email should not call render if a body is supplied @@ -166,7 +166,7 @@ public function testSend() public function testRenderedSend() { - /** @var Email|PHPUnit_Framework_MockObject_MockObject $email */ + /** @var Email|MockObject $email */ $email = $this->getMockBuilder(Email::class) ->enableProxyingToOriginalMethods() ->getMock(); @@ -193,7 +193,7 @@ public function testRenderedSendSubclass() '$default', ]); - /** @var Email|PHPUnit_Framework_MockObject_MockObject $email */ + /** @var Email|MockObject $email */ $email = $this->getMockBuilder(EmailSubClass::class) ->enableProxyingToOriginalMethods() ->getMock(); @@ -207,7 +207,7 @@ public function testRenderedSendSubclass() $email->send(); $this->assertTrue($email->hasPlainPart()); $this->assertNotEmpty($email->getBody()); - $this->assertContains('

Email Sub-class

', $email->getBody()); + $this->assertStringContainsString('

Email Sub-class

', $email->getBody()); } public function testConsturctor() @@ -223,15 +223,15 @@ public function testConsturctor() ); $this->assertCount(1, $email->getFrom()); - $this->assertContains('from@example.com', array_keys($email->getFrom())); + $this->assertStringContainsString('from@example.com', array_keys($email->getFrom())); $this->assertCount(1, $email->getTo()); - $this->assertContains('to@example.com', array_keys($email->getTo())); + $this->assertStringContainsString('to@example.com', array_keys($email->getTo())); $this->assertEquals('subject', $email->getSubject()); $this->assertEquals('body', $email->getBody()); $this->assertCount(1, $email->getCC()); - $this->assertContains('cc@example.com', array_keys($email->getCC())); + $this->assertStringContainsString('cc@example.com', array_keys($email->getCC())); $this->assertCount(1, $email->getBCC()); - $this->assertContains('bcc@example.com', array_keys($email->getBCC())); + $this->assertStringContainsString('bcc@example.com', array_keys($email->getBCC())); $this->assertEquals('bounce@example.com', $email->getReturnPath()); } @@ -251,15 +251,15 @@ public function testGetSwiftMessage() $this->assertInstanceOf(Swift_Message::class, $swiftMessage); $this->assertCount(1, $swiftMessage->getFrom()); - $this->assertContains('from@example.com', array_keys($swiftMessage->getFrom())); + $this->assertStringContainsString('from@example.com', array_keys($swiftMessage->getFrom())); $this->assertCount(1, $swiftMessage->getTo()); - $this->assertContains('to@example.com', array_keys($swiftMessage->getTo())); + $this->assertStringContainsString('to@example.com', array_keys($swiftMessage->getTo())); $this->assertEquals('subject', $swiftMessage->getSubject()); $this->assertEquals('body', $swiftMessage->getBody()); $this->assertCount(1, $swiftMessage->getCC()); - $this->assertContains('cc@example.com', array_keys($swiftMessage->getCc())); + $this->assertStringContainsString('cc@example.com', array_keys($swiftMessage->getCc())); $this->assertCount(1, $swiftMessage->getBCC()); - $this->assertContains('bcc@example.com', array_keys($swiftMessage->getBcc())); + $this->assertStringContainsString('bcc@example.com', array_keys($swiftMessage->getBcc())); $this->assertEquals('bounce@example.com', $swiftMessage->getReturnPath()); } @@ -274,7 +274,7 @@ public function testSetSwiftMessage() $dateTime->setTimestamp(DBDatetime::now()->getTimestamp()); $email->getSwiftMessage()->setDate($dateTime); $this->assertCount(1, $email->getFrom()); - $this->assertContains('admin@example.com', array_keys($swiftMessage->getFrom())); + $this->assertStringContainsString('admin@example.com', array_keys($swiftMessage->getFrom())); $this->assertEquals(strtotime('2017-01-01 07:00:00'), $swiftMessage->getDate()->getTimestamp()); $this->assertEquals($swiftMessage, $email->getSwiftMessage()); @@ -283,7 +283,7 @@ public function testSetSwiftMessage() $swiftMessage->setFrom('from@example.com'); $email->setSwiftMessage($swiftMessage); $this->assertCount(1, $email->getFrom()); - $this->assertContains('from@example.com', array_keys($email->getFrom())); + $this->assertStringContainsString('from@example.com', array_keys($email->getFrom())); } public function testAdminEmailApplied() @@ -292,35 +292,35 @@ public function testAdminEmailApplied() $email = new Email(); $this->assertCount(1, $email->getFrom()); - $this->assertContains('admin@example.com', array_keys($email->getFrom())); + $this->assertStringContainsString('admin@example.com', array_keys($email->getFrom())); } public function testGetFrom() { $email = new Email('from@example.com'); $this->assertCount(1, $email->getFrom()); - $this->assertContains('from@example.com', array_keys($email->getFrom())); + $this->assertStringContainsString('from@example.com', array_keys($email->getFrom())); } public function testSetFrom() { $email = new Email('from@example.com'); $this->assertCount(1, $email->getFrom()); - $this->assertContains('from@example.com', array_keys($email->getFrom())); + $this->assertStringContainsString('from@example.com', array_keys($email->getFrom())); $email->setFrom('new-from@example.com'); $this->assertCount(1, $email->getFrom()); - $this->assertContains('new-from@example.com', array_keys($email->getFrom())); + $this->assertStringContainsString('new-from@example.com', array_keys($email->getFrom())); } public function testAddFrom() { $email = new Email('from@example.com'); $this->assertCount(1, $email->getFrom()); - $this->assertContains('from@example.com', array_keys($email->getFrom())); + $this->assertStringContainsString('from@example.com', array_keys($email->getFrom())); $email->addFrom('new-from@example.com'); $this->assertCount(2, $email->getFrom()); - $this->assertContains('from@example.com', array_keys($email->getFrom())); - $this->assertContains('new-from@example.com', array_keys($email->getFrom())); + $this->assertStringContainsString('from@example.com', array_keys($email->getFrom())); + $this->assertStringContainsString('new-from@example.com', array_keys($email->getFrom())); } public function testSetGetSender() @@ -343,7 +343,7 @@ public function testSetGetTo() { $email = new Email('from@example.com', 'to@example.com'); $this->assertCount(1, $email->getTo()); - $this->assertContains('to@example.com', array_keys($email->getTo())); + $this->assertStringContainsString('to@example.com', array_keys($email->getTo())); $email->setTo('new-to@example.com', 'Silver Stripe'); $this->assertEquals(['new-to@example.com' => 'Silver Stripe'], $email->getTo()); } @@ -352,18 +352,18 @@ public function testAddTo() { $email = new Email('from@example.com', 'to@example.com'); $this->assertCount(1, $email->getTo()); - $this->assertContains('to@example.com', array_keys($email->getTo())); + $this->assertStringContainsString('to@example.com', array_keys($email->getTo())); $email->addTo('new-to@example.com'); $this->assertCount(2, $email->getTo()); - $this->assertContains('to@example.com', array_keys($email->getTo())); - $this->assertContains('new-to@example.com', array_keys($email->getTo())); + $this->assertStringContainsString('to@example.com', array_keys($email->getTo())); + $this->assertStringContainsString('new-to@example.com', array_keys($email->getTo())); } public function testSetGetCC() { $email = new Email('from@example.com', 'to@example.com', 'subject', 'body', 'cc@example.com'); $this->assertCount(1, $email->getCC()); - $this->assertContains('cc@example.com', array_keys($email->getCC())); + $this->assertStringContainsString('cc@example.com', array_keys($email->getCC())); $email->setCC('new-cc@example.com', 'Silver Stripe'); $this->assertEquals(['new-cc@example.com' => 'Silver Stripe'], $email->getCC()); } @@ -372,11 +372,11 @@ public function testAddCC() { $email = new Email('from@example.com', 'to@example.com', 'subject', 'body', 'cc@example.com'); $this->assertCount(1, $email->getCC()); - $this->assertContains('cc@example.com', array_keys($email->getCC())); + $this->assertStringContainsString('cc@example.com', array_keys($email->getCC())); $email->addCC('new-cc@example.com', 'Silver Stripe'); $this->assertCount(2, $email->getCC()); - $this->assertContains('cc@example.com', array_keys($email->getCC())); - $this->assertContains('new-cc@example.com', array_keys($email->getCC())); + $this->assertStringContainsString('cc@example.com', array_keys($email->getCC())); + $this->assertStringContainsString('new-cc@example.com', array_keys($email->getCC())); } public function testSetGetBCC() @@ -390,7 +390,7 @@ public function testSetGetBCC() 'bcc@example.com' ); $this->assertCount(1, $email->getBCC()); - $this->assertContains('bcc@example.com', array_keys($email->getBCC())); + $this->assertStringContainsString('bcc@example.com', array_keys($email->getBCC())); $email->setBCC('new-bcc@example.com', 'Silver Stripe'); $this->assertEquals(['new-bcc@example.com' => 'Silver Stripe'], $email->getBCC()); } @@ -406,11 +406,11 @@ public function testAddBCC() 'bcc@example.com' ); $this->assertCount(1, $email->getBCC()); - $this->assertContains('bcc@example.com', array_keys($email->getBCC())); + $this->assertStringContainsString('bcc@example.com', array_keys($email->getBCC())); $email->addBCC('new-bcc@example.com', 'Silver Stripe'); $this->assertCount(2, $email->getBCC()); - $this->assertContains('bcc@example.com', array_keys($email->getBCC())); - $this->assertContains('new-bcc@example.com', array_keys($email->getBCC())); + $this->assertStringContainsString('bcc@example.com', array_keys($email->getBCC())); + $this->assertStringContainsString('new-bcc@example.com', array_keys($email->getBCC())); } public function testReplyTo() @@ -421,8 +421,8 @@ public function testReplyTo() $this->assertEquals(['reply-to@example.com' => 'Silver Stripe'], $email->getReplyTo()); $email->addReplyTo('new-reply-to@example.com'); $this->assertCount(2, $email->getReplyTo()); - $this->assertContains('reply-to@example.com', array_keys($email->getReplyTo())); - $this->assertContains('new-reply-to@example.com', array_keys($email->getReplyTo())); + $this->assertStringContainsString('reply-to@example.com', array_keys($email->getReplyTo())); + $this->assertStringContainsString('new-reply-to@example.com', array_keys($email->getReplyTo())); } public function testSubject() @@ -527,7 +527,7 @@ public function testPlainTemplate() public function testGetFailedRecipients() { $mailer = new SwiftMailer(); - /** @var Swift_NullTransport|PHPUnit_Framework_MockObject_MockObject $transport */ + /** @var Swift_NullTransport|MockObject $transport */ $transport = $this->getMockBuilder(Swift_NullTransport::class)->getMock(); $transport->expects($this->once()) ->method('send') @@ -552,7 +552,7 @@ public function testRenderAgain() 'EmailContent' => 'my content', ]); $email->render(); - $this->assertContains('my content', $email->getBody()); + $this->assertStringContainsString('my content', $email->getBody()); $children = $email->getSwiftMessage()->getChildren(); $this->assertCount(1, $children); $plainPart = reset($children); @@ -570,7 +570,7 @@ public function testRerender() 'EmailContent' => 'my content', ]); $email->render(); - $this->assertContains('my content', $email->getBody()); + $this->assertStringContainsString('my content', $email->getBody()); $children = $email->getSwiftMessage()->getChildren(); $this->assertCount(1, $children); $plainPart = reset($children); @@ -581,19 +581,19 @@ public function testRerender() 'EmailContent' => 'your content' ]); $email->render(); - $this->assertContains('your content', $email->getBody()); + $this->assertStringContainsString('your content', $email->getBody()); // Ensure removing data causes a rerender $email->removeData('EmailContent'); $email->render(); - $this->assertNotContains('your content', $email->getBody()); + $this->assertStringNotContainsString('your content', $email->getBody()); // Ensure adding data causes a rerender $email->addData([ 'EmailContent' => 'their content' ]); $email->render(); - $this->assertContains('their content', $email->getBody()); + $this->assertStringContainsString('their content', $email->getBody()); } public function testRenderPlainOnly() @@ -631,8 +631,8 @@ public function testGeneratePlainPartFromBody() $children = $email->getSwiftMessage()->getChildren(); $this->assertCount(1, $children); $plainPart = reset($children); - $this->assertContains('Test', $plainPart->getBody()); - $this->assertNotContains('

Test

', $plainPart->getBody()); + $this->assertStringContainsString('Test', $plainPart->getBody()); + $this->assertStringNotContainsString('

Test

', $plainPart->getBody()); } public function testMultipleEmailSends() @@ -644,30 +644,30 @@ public function testMultipleEmailSends() $this->assertEmpty($email->getBody()); $this->assertEmpty($email->getSwiftMessage()->getChildren()); $email->send(); - $this->assertContains('Test', $email->getBody()); + $this->assertStringContainsString('Test', $email->getBody()); $this->assertCount(1, $email->getSwiftMessage()->getChildren()); $children = $email->getSwiftMessage()->getChildren(); /** @var \Swift_MimePart $plainPart */ $plainPart = reset($children); - $this->assertContains('Test', $plainPart->getBody()); + $this->assertStringContainsString('Test', $plainPart->getBody()); //send again $email->send(); - $this->assertContains('Test', $email->getBody()); + $this->assertStringContainsString('Test', $email->getBody()); $this->assertCount(1, $email->getSwiftMessage()->getChildren()); $children = $email->getSwiftMessage()->getChildren(); /** @var \Swift_MimePart $plainPart */ $plainPart = reset($children); - $this->assertContains('Test', $plainPart->getBody()); + $this->assertStringContainsString('Test', $plainPart->getBody()); } /** - * @return PHPUnit_Framework_MockObject_MockObject|Email + * @return MockObject|Email */ protected function makeEmailMock($subject) { - /** @var Email|PHPUnit_Framework_MockObject_MockObject $email */ + /** @var Email|MockObject $email */ $email = $this->getMockBuilder(Email::class) ->enableProxyingToOriginalMethods() ->getMock(); diff --git a/tests/php/Control/Email/SwiftPluginTest.php b/tests/php/Control/Email/SwiftPluginTest.php index da809552da8..455ab258fd4 100644 --- a/tests/php/Control/Email/SwiftPluginTest.php +++ b/tests/php/Control/Email/SwiftPluginTest.php @@ -9,7 +9,7 @@ class SwiftPluginTest extends SapphireTest { - protected function setUp() + protected function setUp(): void { parent::setUp(); @@ -45,9 +45,9 @@ public function testSendAllEmailsTo() $headers = $email->getSwiftMessage()->getHeaders(); $this->assertCount(1, $email->getTo()); - $this->assertContains('to@example.com', array_keys($email->getTo())); + $this->assertStringContainsString('to@example.com', array_keys($email->getTo())); $this->assertCount(1, $email->getFrom()); - $this->assertContains('original-from@example.com', array_keys($email->getFrom())); + $this->assertStringContainsString('original-from@example.com', array_keys($email->getFrom())); $this->assertTrue($headers->has('X-Original-To')); $this->assertTrue($headers->has('X-Original-Cc')); @@ -59,11 +59,11 @@ public function testSendAllEmailsTo() $originalBcc = array_keys($headers->get('X-Original-Bcc')->getFieldBodyModel()); $this->assertCount(1, $originalTo); - $this->assertContains('original-to@example.com', $originalTo); + $this->assertStringContainsString('original-to@example.com', $originalTo); $this->assertCount(1, $originalCc); - $this->assertContains('original-cc@example.com', $originalCc); + $this->assertStringContainsString('original-cc@example.com', $originalCc); $this->assertCount(1, $originalBcc); - $this->assertContains('original-bcc@example.com', $originalBcc); + $this->assertStringContainsString('original-bcc@example.com', $originalBcc); } public function testSendAllEmailsFrom() @@ -80,10 +80,10 @@ public function testSendAllEmailsFrom() $this->assertTrue($headers->has('X-Original-From')); $this->assertCount(1, $email->getFrom()); - $this->assertContains('from@example.com', array_keys($email->getFrom())); + $this->assertStringContainsString('from@example.com', array_keys($email->getFrom())); $this->assertCount(1, $headers->get('X-Original-From')->getFieldBodyModel()); - $this->assertContains('original-from@example.com', array_keys($headers->get('X-Original-From')->getFieldBodyModel())); + $this->assertStringContainsString('original-from@example.com', array_keys($headers->get('X-Original-From')->getFieldBodyModel())); } public function testCCAllEmailsTo() @@ -93,8 +93,8 @@ public function testCCAllEmailsTo() $this->getMailer()->send($email->getSwiftMessage()); $this->assertCount(2, $email->getCC()); - $this->assertContains('cc@example.com', array_keys($email->getCC())); - $this->assertContains('original-cc@example.com', array_keys($email->getCC())); + $this->assertStringContainsString('cc@example.com', array_keys($email->getCC())); + $this->assertStringContainsString('original-cc@example.com', array_keys($email->getCC())); } public function testBCCAllEmailsTo() @@ -104,7 +104,7 @@ public function testBCCAllEmailsTo() $this->getMailer()->send($email->getSwiftMessage()); $this->assertCount(2, $email->getBCC()); - $this->assertContains('bcc@example.com', array_keys($email->getBCC())); - $this->assertContains('original-bcc@example.com', array_keys($email->getBCC())); + $this->assertStringContainsString('bcc@example.com', array_keys($email->getBCC())); + $this->assertStringContainsString('original-bcc@example.com', array_keys($email->getBCC())); } } diff --git a/tests/php/Control/HTTPCacheControlIntegrationTest.php b/tests/php/Control/HTTPCacheControlIntegrationTest.php index 94b0f152793..ed2c8af8cc5 100644 --- a/tests/php/Control/HTTPCacheControlIntegrationTest.php +++ b/tests/php/Control/HTTPCacheControlIntegrationTest.php @@ -16,7 +16,7 @@ class HTTPCacheControlIntegrationTest extends FunctionalTest RuleController::class, ]; - protected function setUp() + protected function setUp(): void { parent::setUp(); HTTPCacheControlMiddleware::config() @@ -31,11 +31,11 @@ public function testFormCSRF() $response = $this->get('HTTPCacheControlIntegrationTest_SessionController/showform'); $header = $response->getHeader('Cache-Control'); $this->assertFalse($response->isError()); - $this->assertNotContains('public', $header); - $this->assertNotContains('private', $header); - $this->assertContains('no-cache', $header); - $this->assertContains('no-store', $header); - $this->assertContains('must-revalidate', $header); + $this->assertStringNotContainsString('public', $header); + $this->assertStringNotContainsString('private', $header); + $this->assertStringContainsString('no-cache', $header); + $this->assertStringContainsString('no-store', $header); + $this->assertStringContainsString('must-revalidate', $header); } public function testPublicForm() @@ -44,10 +44,10 @@ public function testPublicForm() $response = $this->get('HTTPCacheControlIntegrationTest_SessionController/showpublicform'); $header = $response->getHeader('Cache-Control'); $this->assertFalse($response->isError()); - $this->assertContains('public', $header); - $this->assertContains('must-revalidate', $header); - $this->assertNotContains('no-cache', $response->getHeader('Cache-Control')); - $this->assertNotContains('no-store', $response->getHeader('Cache-Control')); + $this->assertStringContainsString('public', $header); + $this->assertStringContainsString('must-revalidate', $header); + $this->assertStringNotContainsString('no-cache', $response->getHeader('Cache-Control')); + $this->assertStringNotContainsString('no-store', $response->getHeader('Cache-Control')); } public function testPrivateActionsError() @@ -56,9 +56,9 @@ public function testPrivateActionsError() $response = $this->get('HTTPCacheControlIntegrationTest_SessionController/privateaction'); $header = $response->getHeader('Cache-Control'); $this->assertTrue($response->isError()); - $this->assertContains('no-cache', $header); - $this->assertContains('no-store', $header); - $this->assertContains('must-revalidate', $header); + $this->assertStringContainsString('no-cache', $header); + $this->assertStringContainsString('no-store', $header); + $this->assertStringContainsString('must-revalidate', $header); } public function testPrivateActionsAuthenticated() @@ -68,10 +68,10 @@ public function testPrivateActionsAuthenticated() $response = $this->get('HTTPCacheControlIntegrationTest_SessionController/privateaction'); $header = $response->getHeader('Cache-Control'); $this->assertFalse($response->isError()); - $this->assertContains('private', $header); - $this->assertContains('must-revalidate', $header); - $this->assertNotContains('no-cache', $header); - $this->assertNotContains('no-store', $header); + $this->assertStringContainsString('private', $header); + $this->assertStringContainsString('must-revalidate', $header); + $this->assertStringNotContainsString('no-cache', $header); + $this->assertStringNotContainsString('no-store', $header); } public function testPrivateCache() @@ -79,10 +79,10 @@ public function testPrivateCache() $response = $this->get('HTTPCacheControlIntegrationTest_RuleController/privateaction'); $header = $response->getHeader('Cache-Control'); $this->assertFalse($response->isError()); - $this->assertContains('private', $header); - $this->assertContains('must-revalidate', $header); - $this->assertNotContains('no-cache', $header); - $this->assertNotContains('no-store', $header); + $this->assertStringContainsString('private', $header); + $this->assertStringContainsString('must-revalidate', $header); + $this->assertStringNotContainsString('no-cache', $header); + $this->assertStringNotContainsString('no-store', $header); } public function testPublicCache() @@ -90,11 +90,11 @@ public function testPublicCache() $response = $this->get('HTTPCacheControlIntegrationTest_RuleController/publicaction'); $header = $response->getHeader('Cache-Control'); $this->assertFalse($response->isError()); - $this->assertContains('public', $header); - $this->assertContains('must-revalidate', $header); - $this->assertNotContains('no-cache', $header); - $this->assertNotContains('no-store', $header); - $this->assertContains('max-age=9000', $header); + $this->assertStringContainsString('public', $header); + $this->assertStringContainsString('must-revalidate', $header); + $this->assertStringNotContainsString('no-cache', $header); + $this->assertStringNotContainsString('no-store', $header); + $this->assertStringContainsString('max-age=9000', $header); } public function testDisabledCache() @@ -102,10 +102,10 @@ public function testDisabledCache() $response = $this->get('HTTPCacheControlIntegrationTest_RuleController/disabledaction'); $header = $response->getHeader('Cache-Control'); $this->assertFalse($response->isError()); - $this->assertNotContains('public', $header); - $this->assertNotContains('private', $header); - $this->assertContains('no-cache', $header); - $this->assertContains('no-store', $header); - $this->assertContains('must-revalidate', $header); + $this->assertStringNotContainsString('public', $header); + $this->assertStringNotContainsString('private', $header); + $this->assertStringContainsString('no-cache', $header); + $this->assertStringContainsString('no-store', $header); + $this->assertStringContainsString('must-revalidate', $header); } } diff --git a/tests/php/Control/HTTPRequestTest.php b/tests/php/Control/HTTPRequestTest.php index 52ce61b4923..d9778f8a4d3 100644 --- a/tests/php/Control/HTTPRequestTest.php +++ b/tests/php/Control/HTTPRequestTest.php @@ -52,11 +52,10 @@ public function testWildCardMatch() /** * This test just asserts a warning is given if there is more than one wildcard parameter. Note that this isn't an * enforcement of an API and we an add new behaviour in the future to allow many wildcard params if we want to - * - * @expectedException \PHPUnit_Framework_Error_Warning */ public function testWildCardWithFurtherParams() { + $this->expectWarning(); $request = new HTTPRequest('GET', 'admin/crm/test'); // all parameters after the first wildcard parameter are ignored $request->match('admin/$Action/$@/$Other/$*', true); diff --git a/tests/php/Control/HTTPTest.php b/tests/php/Control/HTTPTest.php index 018c59ce1a8..03c37aca41f 100644 --- a/tests/php/Control/HTTPTest.php +++ b/tests/php/Control/HTTPTest.php @@ -19,7 +19,7 @@ */ class HTTPTest extends FunctionalTest { - protected function setUp() + protected function setUp(): void { parent::setUp(); // Set to disabled at null forcing level @@ -48,9 +48,9 @@ public function testAddCacheHeaders() HTTPCacheControlMiddleware::singleton()->setMaxAge(30); $response = new HTTPResponse($body, 200); $this->addCacheHeaders($response); - $this->assertContains('no-cache', $response->getHeader('Cache-Control')); - $this->assertContains('no-store', $response->getHeader('Cache-Control')); - $this->assertContains('must-revalidate', $response->getHeader('Cache-Control')); + $this->assertStringContainsString('no-cache', $response->getHeader('Cache-Control')); + $this->assertStringContainsString('no-store', $response->getHeader('Cache-Control')); + $this->assertStringContainsString('must-revalidate', $response->getHeader('Cache-Control')); // Ensure max-age setting is respected in production. HTTPCacheControlMiddleware::config() @@ -61,8 +61,8 @@ public function testAddCacheHeaders() HTTPCacheControlMiddleware::singleton()->setMaxAge(30); $response = new HTTPResponse($body, 200); $this->addCacheHeaders($response); - $this->assertContains('max-age=30', $response->getHeader('Cache-Control')); - $this->assertNotContains('max-age=0', $response->getHeader('Cache-Control')); + $this->assertStringContainsString('max-age=30', $response->getHeader('Cache-Control')); + $this->assertStringNotContainsString('max-age=0', $response->getHeader('Cache-Control')); // Still "live": Ensure header's aren't overridden if already set (using purposefully different values). $headers = [ @@ -93,11 +93,11 @@ public function testConfigVary() // Vary set properly $v = $response->getHeader('Vary'); - $this->assertContains("X-Forwarded-Protocol", $v); - $this->assertContains("X-Requested-With", $v); - $this->assertNotContains("Cookie", $v); - $this->assertNotContains("User-Agent", $v); - $this->assertNotContains("Accept", $v); + $this->assertStringContainsString("X-Forwarded-Protocol", $v); + $this->assertStringContainsString("X-Requested-With", $v); + $this->assertStringNotContainsString("Cookie", $v); + $this->assertStringNotContainsString("User-Agent", $v); + $this->assertStringNotContainsString("Accept", $v); // No vary HTTPCacheControlMiddleware::singleton() @@ -124,7 +124,7 @@ public function testDeprecatedVaryHandling() $response = new HTTPResponse('', 200); $this->addCacheHeaders($response); $header = $response->getHeader('Vary'); - $this->assertContains('X-Foo', $header); + $this->assertStringContainsString('X-Foo', $header); } public function testDeprecatedCacheControlHandling() @@ -143,8 +143,8 @@ public function testDeprecatedCacheControlHandling() $response = new HTTPResponse('', 200); $this->addCacheHeaders($response); $header = $response->getHeader('Cache-Control'); - $this->assertContains('no-store', $header); - $this->assertContains('no-cache', $header); + $this->assertStringContainsString('no-store', $header); + $this->assertStringContainsString('no-cache', $header); } public function testDeprecatedCacheControlHandlingOnMaxAge() @@ -164,15 +164,13 @@ public function testDeprecatedCacheControlHandlingOnMaxAge() $response = new HTTPResponse('', 200); $this->addCacheHeaders($response); $header = $response->getHeader('Cache-Control'); - $this->assertContains('max-age=99', $header); + $this->assertStringContainsString('max-age=99', $header); } - /** - * @expectedException \LogicException - * @expectedExceptionMessageRegExp /Found unsupported legacy directives in HTTP\.cache_control: unknown/ - */ public function testDeprecatedCacheControlHandlingThrowsWithUnknownDirectives() { + $this->expectException(\LogicException::class); + $this->expectExceptionMessageMatches('/Found unsupported legacy directives in HTTP\.cache_control: unknown/'); /** @var Config */ Config::modify()->set( HTTP::class, @@ -219,7 +217,7 @@ public function testGetLinksIn() sort($result); sort($expected); - $this->assertInternalType('array', $result); + $this->assertIsArray($result); $this->assertEquals($expected, $result, 'Test that all links within the content are found.'); } @@ -235,7 +233,7 @@ public function testSetGetVar() $controller->setRequest($request); $controller->pushCurrent(); try { - $this->assertContains( + $this->assertStringContainsString( 'relative/url?foo=bar', HTTP::setGetVar('foo', 'bar'), 'Omitting a URL falls back to current URL' @@ -263,7 +261,7 @@ public function testSetGetVar() 'Absolute URL without path and multipe existing query params, overwriting an existing parameter' ); - $this->assertContains( + $this->assertStringContainsString( 'http://test.com/?foo=new', HTTP::setGetVar('foo', 'new', 'http://test.com/?foo=&foo=old'), 'Absolute URL and empty query param' diff --git a/tests/php/Control/IPUtilsTest.php b/tests/php/Control/IPUtilsTest.php index bc82835d1d4..d872ce42118 100644 --- a/tests/php/Control/IPUtilsTest.php +++ b/tests/php/Control/IPUtilsTest.php @@ -17,14 +17,14 @@ class IPUtilsTest extends SapphireTest { /** - * @dataProvider testIPv4Provider + * @dataProvider iPv4Provider */ public function testIPv4($matches, $remoteAddr, $cidr) { $this->assertSame($matches, IPUtils::checkIP($remoteAddr, $cidr)); } - public function testIPv4Provider() + public function iPv4Provider() { return [ [true, '192.168.1.1', '192.168.1.1'], @@ -43,7 +43,7 @@ public function testIPv4Provider() } /** - * @dataProvider testIPv6Provider + * @dataProvider iPv6Provider */ public function testIPv6($matches, $remoteAddr, $cidr) { @@ -54,7 +54,7 @@ public function testIPv6($matches, $remoteAddr, $cidr) $this->assertSame($matches, IPUtils::checkIP($remoteAddr, $cidr)); } - public function testIPv6Provider() + public function iPv6Provider() { return [ [true, '2a01:198:603:0:396e:4789:8e99:890f', '2a01:198:603:0::/65'], @@ -71,11 +71,13 @@ public function testIPv6Provider() } /** - * @expectedException \RuntimeException * @requires extension sockets */ public function testAnIPv6WithOptionDisabledIPv6() { + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage(''); + $this->expectExceptionMessageMatches(''); if (defined('AF_INET6')) { $this->markTestSkipped('Only works when PHP is compiled with the option "disable-ipv6".'); } diff --git a/tests/php/Control/Middleware/CanonicalURLMiddlewareTest.php b/tests/php/Control/Middleware/CanonicalURLMiddlewareTest.php index e4e3caa56f8..f605b0e07f9 100644 --- a/tests/php/Control/Middleware/CanonicalURLMiddlewareTest.php +++ b/tests/php/Control/Middleware/CanonicalURLMiddlewareTest.php @@ -16,7 +16,7 @@ class CanonicalURLMiddlewareTest extends SapphireTest */ protected $middleware; - protected function setUp() + protected function setUp(): void { parent::setUp(); @@ -45,7 +45,7 @@ public function testHttpsIsForcedForBasicAuth() $this->assertNotSame($mockResponse, $result, 'New response is created and returned'); $this->assertEquals(301, $result->getStatusCode(), 'Basic auth responses are redirected'); - $this->assertContains('https://', $result->getHeader('Location'), 'HTTPS is in the redirect location'); + $this->assertStringContainsString('https://', $result->getHeader('Location'), 'HTTPS is in the redirect location'); } public function testMiddlewareDelegateIsReturnedWhenBasicAuthRedirectIsDisabled() diff --git a/tests/php/Control/Middleware/ConfirmationMiddleware/UrlTest.php b/tests/php/Control/Middleware/ConfirmationMiddleware/UrlTest.php index 5db6d39adc7..44f225263f4 100644 --- a/tests/php/Control/Middleware/ConfirmationMiddleware/UrlTest.php +++ b/tests/php/Control/Middleware/ConfirmationMiddleware/UrlTest.php @@ -24,15 +24,15 @@ public function testHttpMethods() { $url = new Url('/', ['PUT', 'DELETE']); $this->assertCount(2, $url->getHttpMethods()); - $this->assertContains('DELETE', $url->getHttpMethods()); - $this->assertContains('PUT', $url->getHttpMethods()); + $this->assertStringContainsString('DELETE', $url->getHttpMethods()); + $this->assertStringContainsString('PUT', $url->getHttpMethods()); $url->addHttpMethods('GET', 'POST'); $this->assertCount(4, $url->getHttpMethods()); - $this->assertContains('DELETE', $url->getHttpMethods()); - $this->assertContains('GET', $url->getHttpMethods()); - $this->assertContains('POST', $url->getHttpMethods()); - $this->assertContains('PUT', $url->getHttpMethods()); + $this->assertStringContainsString('DELETE', $url->getHttpMethods()); + $this->assertStringContainsString('GET', $url->getHttpMethods()); + $this->assertStringContainsString('POST', $url->getHttpMethods()); + $this->assertStringContainsString('PUT', $url->getHttpMethods()); } public function testBypass() diff --git a/tests/php/Control/Middleware/HTTPCacheControlMiddlewareTest.php b/tests/php/Control/Middleware/HTTPCacheControlMiddlewareTest.php index 1a8b3e4b24b..bd9adbfc920 100644 --- a/tests/php/Control/Middleware/HTTPCacheControlMiddlewareTest.php +++ b/tests/php/Control/Middleware/HTTPCacheControlMiddlewareTest.php @@ -8,7 +8,7 @@ class HTTPCacheControlMiddlewareTest extends SapphireTest { - protected function setUp() + protected function setUp(): void { parent::setUp(); // Set to disabled at null forcing level @@ -39,7 +39,7 @@ public function testCheckDefaultStates($state, $immutable) $response = new HTTPResponse(); $cc->applyToResponse($response); - $this->assertContains('must-revalidate', $response->getHeader('cache-control')); + $this->assertStringContainsString('must-revalidate', $response->getHeader('cache-control')); } /** @@ -62,9 +62,9 @@ public function testSetMaxAge($state, $immutable) if ($immutable) { $this->assertEquals($originalResponse->getHeader('cache-control'), $response->getHeader('cache-control')); } else { - $this->assertContains('max-age=300', $response->getHeader('cache-control')); - $this->assertNotContains('no-cache', $response->getHeader('cache-control')); - $this->assertNotContains('no-store', $response->getHeader('cache-control')); + $this->assertStringContainsString('max-age=300', $response->getHeader('cache-control')); + $this->assertStringNotContainsString('no-cache', $response->getHeader('cache-control')); + $this->assertStringNotContainsString('no-store', $response->getHeader('cache-control')); } } @@ -78,9 +78,9 @@ public function testEnableCacheWithMaxAge() $response = new HTTPResponse(); $cc->applyToResponse($response); - $this->assertContains('max-age=300', $response->getHeader('cache-control')); - $this->assertNotContains('no-cache', $response->getHeader('cache-control')); - $this->assertNotContains('no-store', $response->getHeader('cache-control')); + $this->assertStringContainsString('max-age=300', $response->getHeader('cache-control')); + $this->assertStringNotContainsString('no-cache', $response->getHeader('cache-control')); + $this->assertStringNotContainsString('no-store', $response->getHeader('cache-control')); } public function testEnableCacheWithMaxAgeAppliesWhenLevelDoesNot() @@ -94,7 +94,7 @@ public function testEnableCacheWithMaxAgeAppliesWhenLevelDoesNot() $response = new HTTPResponse(); $cc->applyToResponse($response); - $this->assertContains('max-age=300', $response->getHeader('cache-control')); + $this->assertStringContainsString('max-age=300', $response->getHeader('cache-control')); } public function testPublicCacheWithMaxAge() @@ -107,10 +107,10 @@ public function testPublicCacheWithMaxAge() $response = new HTTPResponse(); $cc->applyToResponse($response); - $this->assertContains('max-age=300', $response->getHeader('cache-control')); + $this->assertStringContainsString('max-age=300', $response->getHeader('cache-control')); // STATE_PUBLIC doesn't contain no-cache or no-store headers to begin with, // so can't test their removal effectively - $this->assertNotContains('no-cache', $response->getHeader('cache-control')); + $this->assertStringNotContainsString('no-cache', $response->getHeader('cache-control')); } public function testPublicCacheWithMaxAgeAppliesWhenLevelDoesNot() @@ -124,7 +124,7 @@ public function testPublicCacheWithMaxAgeAppliesWhenLevelDoesNot() $response = new HTTPResponse(); $cc->applyToResponse($response); - $this->assertContains('max-age=300', $response->getHeader('cache-control')); + $this->assertStringContainsString('max-age=300', $response->getHeader('cache-control')); } /** @@ -150,9 +150,9 @@ public function testSetNoStore($state, $immutable) if ($immutable) { $this->assertEquals($originalResponse->getHeader('cache-control'), $response->getHeader('cache-control')); } else { - $this->assertContains('no-store', $response->getHeader('cache-control')); - $this->assertNotContains('max-age', $response->getHeader('cache-control')); - $this->assertNotContains('s-maxage', $response->getHeader('cache-control')); + $this->assertStringContainsString('no-store', $response->getHeader('cache-control')); + $this->assertStringNotContainsString('max-age', $response->getHeader('cache-control')); + $this->assertStringNotContainsString('s-maxage', $response->getHeader('cache-control')); } } @@ -179,9 +179,9 @@ public function testSetNoCache($state, $immutable) if ($immutable) { $this->assertEquals($originalResponse->getHeader('cache-control'), $response->getHeader('cache-control')); } else { - $this->assertContains('no-cache', $response->getHeader('cache-control')); - $this->assertNotContains('max-age', $response->getHeader('cache-control')); - $this->assertNotContains('s-maxage', $response->getHeader('cache-control')); + $this->assertStringContainsString('no-cache', $response->getHeader('cache-control')); + $this->assertStringNotContainsString('max-age', $response->getHeader('cache-control')); + $this->assertStringNotContainsString('s-maxage', $response->getHeader('cache-control')); } } @@ -206,9 +206,9 @@ public function testSetSharedMaxAge($state, $immutable) if ($immutable) { $this->assertEquals($originalResponse->getHeader('cache-control'), $response->getHeader('cache-control')); } else { - $this->assertContains('s-maxage=300', $response->getHeader('cache-control')); - $this->assertNotContains('no-cache', $response->getHeader('cache-control')); - $this->assertNotContains('no-store', $response->getHeader('cache-control')); + $this->assertStringContainsString('s-maxage=300', $response->getHeader('cache-control')); + $this->assertStringNotContainsString('no-cache', $response->getHeader('cache-control')); + $this->assertStringNotContainsString('no-store', $response->getHeader('cache-control')); } } @@ -233,9 +233,9 @@ public function testSetMustRevalidate($state, $immutable) if ($immutable) { $this->assertEquals($originalResponse->getHeader('cache-control'), $response->getHeader('cache-control')); } else { - $this->assertContains('must-revalidate', $response->getHeader('cache-control')); - $this->assertNotContains('max-age', $response->getHeader('cache-control')); - $this->assertNotContains('s-maxage', $response->getHeader('cache-control')); + $this->assertStringContainsString('must-revalidate', $response->getHeader('cache-control')); + $this->assertStringNotContainsString('max-age', $response->getHeader('cache-control')); + $this->assertStringNotContainsString('s-maxage', $response->getHeader('cache-control')); } } diff --git a/tests/php/Control/Middleware/RateLimitMiddlewareTest.php b/tests/php/Control/Middleware/RateLimitMiddlewareTest.php index 23da5723914..23bda6331b7 100644 --- a/tests/php/Control/Middleware/RateLimitMiddlewareTest.php +++ b/tests/php/Control/Middleware/RateLimitMiddlewareTest.php @@ -17,7 +17,7 @@ class RateLimitMiddlewareTest extends FunctionalTest TestController::class, ]; - protected function setUp() + protected function setUp(): void { parent::setUp(); DBDatetime::set_mock_now('2017-09-27 00:00:00'); diff --git a/tests/php/Control/RSS/RSSFeedTest.php b/tests/php/Control/RSS/RSSFeedTest.php index 9e41abca07a..45d772ac54a 100644 --- a/tests/php/Control/RSS/RSSFeedTest.php +++ b/tests/php/Control/RSS/RSSFeedTest.php @@ -24,17 +24,17 @@ public function testRSSFeed() $rssFeed = new RSSFeed($list, "http://www.example.com", "Test RSS Feed", "Test RSS Feed Description"); $content = $rssFeed->outputToBrowser(); - $this->assertContains('http://www.example.org/item-a/', $content); - $this->assertContains('http://www.example.com/item-b.html', $content); - $this->assertContains('http://www.example.com/item-c.html', $content); + $this->assertStringContainsString('http://www.example.org/item-a/', $content); + $this->assertStringContainsString('http://www.example.com/item-b.html', $content); + $this->assertStringContainsString('http://www.example.com/item-c.html', $content); - $this->assertContains('ItemA', $content); - $this->assertContains('ItemB', $content); - $this->assertContains('ItemC', $content); + $this->assertStringContainsString('ItemA', $content); + $this->assertStringContainsString('ItemB', $content); + $this->assertStringContainsString('ItemC', $content); - $this->assertContains('ItemA Content', $content); - $this->assertContains('ItemB Content', $content); - $this->assertContains('ItemC Content', $content); + $this->assertStringContainsString('ItemA Content', $content); + $this->assertStringContainsString('ItemB Content', $content); + $this->assertStringContainsString('ItemC Content', $content); // Feed #2 - put Content() into and AltContent() into <description> @@ -48,13 +48,13 @@ public function testRSSFeed() ); $content = $rssFeed->outputToBrowser(); - $this->assertContains('<title>ItemA Content', $content); - $this->assertContains('ItemB Content', $content); - $this->assertContains('ItemC Content', $content); + $this->assertStringContainsString('ItemA Content', $content); + $this->assertStringContainsString('ItemB Content', $content); + $this->assertStringContainsString('ItemC Content', $content); - $this->assertContains('ItemA AltContent', $content); - $this->assertContains('ItemB AltContent', $content); - $this->assertContains('ItemC AltContent', $content); + $this->assertStringContainsString('ItemA AltContent', $content); + $this->assertStringContainsString('ItemB AltContent', $content); + $this->assertStringContainsString('ItemC AltContent', $content); } public function testLinkEncoding() @@ -62,7 +62,7 @@ public function testLinkEncoding() $list = new ArrayList(); $rssFeed = new RSSFeed($list, "http://www.example.com/?param1=true¶m2=true", "Test RSS Feed"); $content = $rssFeed->outputToBrowser(); - $this->assertContains('http://www.example.com/?param1=true&param2=true', $content); + $this->assertStringContainsString('http://www.example.com/?param1=true&param2=true', $content); } public function testRSSFeedWithShortcode() @@ -73,11 +73,11 @@ public function testRSSFeedWithShortcode() $rssFeed = new RSSFeed($list, "http://www.example.com", "Test RSS Feed", "Test RSS Feed Description"); $content = $rssFeed->outputToBrowser(); - $this->assertContains('http://www.example.org/item-d.html', $content); + $this->assertStringContainsString('http://www.example.org/item-d.html', $content); - $this->assertContains('ItemD', $content); + $this->assertStringContainsString('ItemD', $content); - $this->assertContains( + $this->assertStringContainsString( 'ItemD Content test shortcode output

]]>
', $content ); @@ -92,14 +92,14 @@ public function testRenderWithTemplate() $rssFeed->setTemplate('RSSFeedTest'); $content = $rssFeed->outputToBrowser(); - $this->assertContains('Test Custom Template', $content); + $this->assertStringContainsString('Test Custom Template', $content); $rssFeed->setTemplate(null); $content = $rssFeed->outputToBrowser(); - $this->assertNotContains('Test Custom Template', $content); + $this->assertStringNotContainsString('Test Custom Template', $content); } - protected function setUp() + protected function setUp(): void { parent::setUp(); Config::modify()->set(Director::class, 'alternate_base_url', '/'); @@ -116,7 +116,7 @@ function () { ); } - protected function tearDown() + protected function tearDown(): void { parent::tearDown(); $_SERVER['HTTP_HOST'] = self::$original_host; diff --git a/tests/php/Control/RequestHandlingTest.php b/tests/php/Control/RequestHandlingTest.php index 8dd90515d13..2f417fd9d69 100644 --- a/tests/php/Control/RequestHandlingTest.php +++ b/tests/php/Control/RequestHandlingTest.php @@ -357,7 +357,7 @@ public function testAllowedActionsEnforcedOnForm() $response = $this->post('ControllerFormWithAllowedActions/Form', $data); $this->assertEquals(403, $response->getStatusCode()); // Note: Looks for a specific 403 thrown by Form->httpSubmission(), not RequestHandler->handleRequest() - $this->assertContains('not allowed on form', $response->getBody()); + $this->assertStringContainsString('not allowed on form', $response->getBody()); } public function testActionHandlingOnField() diff --git a/tests/php/Control/SessionTest.php b/tests/php/Control/SessionTest.php index 79c74d682f9..a1024e703c6 100644 --- a/tests/php/Control/SessionTest.php +++ b/tests/php/Control/SessionTest.php @@ -18,10 +18,10 @@ class SessionTest extends SapphireTest */ protected $session = null; - protected function setUp() + protected function setUp(): void { $this->session = new Session([]); - return parent::setUp(); + parent::setUp(); } /** @@ -107,11 +107,11 @@ public function testStartUsesSecureCookieNameWithHttpsAndCookieSecureOn() /** * @runInSeparateProcess * @preserveGlobalState disabled - * @expectedException BadMethodCallException - * @expectedExceptionMessage Session has already started */ public function testStartErrorsWhenStartingTwice() { + $this->expectException(\BadMethodCallException::class); + $this->expectExceptionMessage('Session has already started'); $req = new HTTPRequest('GET', '/'); $session = new Session(null); // unstarted session $session->start($req); diff --git a/tests/php/Control/SimpleResourceURLGeneratorTest.php b/tests/php/Control/SimpleResourceURLGeneratorTest.php index bfe1a768fe4..93d92dd3a39 100644 --- a/tests/php/Control/SimpleResourceURLGeneratorTest.php +++ b/tests/php/Control/SimpleResourceURLGeneratorTest.php @@ -11,7 +11,7 @@ class SimpleResourceURLGeneratorTest extends SapphireTest { - protected function setUp() + protected function setUp(): void { parent::setUp(); Director::config()->set( diff --git a/tests/php/Core/Cache/CacheTest.php b/tests/php/Core/Cache/CacheTest.php index d034ed977b8..1853acf881f 100644 --- a/tests/php/Core/Cache/CacheTest.php +++ b/tests/php/Core/Cache/CacheTest.php @@ -13,7 +13,7 @@ class CacheTest extends SapphireTest { - protected function setUp() + protected function setUp(): void { parent::setUp(); diff --git a/tests/php/Core/Cache/RateLimiterTest.php b/tests/php/Core/Cache/RateLimiterTest.php index ec2a80527a9..011020067b7 100644 --- a/tests/php/Core/Cache/RateLimiterTest.php +++ b/tests/php/Core/Cache/RateLimiterTest.php @@ -11,7 +11,7 @@ class RateLimiterTest extends SapphireTest { - protected function setUp() + protected function setUp(): void { parent::setUp(); DBDatetime::set_mock_now('2017-09-27 00:00:00'); diff --git a/tests/php/Core/ClassInfoTest.php b/tests/php/Core/ClassInfoTest.php index 29721599bd9..1148eb56cb7 100644 --- a/tests/php/Core/ClassInfoTest.php +++ b/tests/php/Core/ClassInfoTest.php @@ -3,6 +3,7 @@ namespace SilverStripe\Core\Tests; use DateTime; +use Exception; use ReflectionException; use SilverStripe\Core\ClassInfo; use SilverStripe\Core\Tests\ClassInfoTest\BaseClass; @@ -42,7 +43,7 @@ class ClassInfoTest extends SapphireTest ExtendTest3::class, ]; - protected function setUp() + protected function setUp(): void { parent::setUp(); ClassInfo::reset_db_cache(); @@ -106,8 +107,8 @@ public function testClassName() public function testNonClassName() { - $this->expectException(ReflectionException::class); - $this->expectExceptionMessageRegExp('/Class "?IAmAClassThatDoesNotExist"? does not exist/'); + $this->expectException(Exception::class); + $this->expectExceptionMessageMatches('/Class "?IAmAClassThatDoesNotExist"? does not exist/'); $this->assertEquals('IAmAClassThatDoesNotExist', ClassInfo::class_name('IAmAClassThatDoesNotExist')); } @@ -119,7 +120,7 @@ public function testClassesForFolder() $classes, 'ClassInfo::classes_for_folder() returns classes matching the filename' ); - $this->assertContains( + $this->assertStringContainsString( ClassInfoTest::class, $classes, 'ClassInfo::classes_for_folder() returns classes matching the filename' @@ -129,7 +130,7 @@ public function testClassesForFolder() $classes, 'ClassInfo::classes_for_folder() returns additional classes not matching the filename' ); - $this->assertContains( + $this->assertStringContainsString( BaseClass::class, $classes, 'ClassInfo::classes_for_folder() returns additional classes not matching the filename' diff --git a/tests/php/Core/Config/ConfigTest.php b/tests/php/Core/Config/ConfigTest.php index d55d7fd8e9b..6da0236add2 100644 --- a/tests/php/Core/Config/ConfigTest.php +++ b/tests/php/Core/Config/ConfigTest.php @@ -216,17 +216,17 @@ public function testUninheritedStatic() Config::modify()->merge(ConfigTest\Second::class, 'first', ['test_2b']); // Check that it can be applied to parent and subclasses, and queried directly - $this->assertContains( + $this->assertStringContainsString( 'test_1b', Config::inst()->get(ConfigTest\First::class, 'first', Config::UNINHERITED) ); - $this->assertContains( + $this->assertStringContainsString( 'test_2b', Config::inst()->get(ConfigTest\Second::class, 'first', Config::UNINHERITED) ); // But it won't affect subclasses - this is *uninherited* static - $this->assertNotContains( + $this->assertStringNotContainsString( 'test_2b', Config::inst()->get(ConfigTest\Third::class, 'first', Config::UNINHERITED) ); @@ -236,7 +236,7 @@ public function testUninheritedStatic() // This also checks that set can be called after the first uninherited get() // call (which can be buggy due to caching) Config::modify()->merge(ConfigTest\Fourth::class, 'first', ['test_4b']); - $this->assertContains('test_4b', Config::inst()->get(ConfigTest\Fourth::class, 'first', Config::UNINHERITED)); + $this->assertStringContainsString('test_4b', Config::inst()->get(ConfigTest\Fourth::class, 'first', Config::UNINHERITED)); } public function testCombinedStatic() diff --git a/tests/php/Core/ConvertTest.php b/tests/php/Core/ConvertTest.php index b3dec037ab4..a5066fab270 100644 --- a/tests/php/Core/ConvertTest.php +++ b/tests/php/Core/ConvertTest.php @@ -19,14 +19,14 @@ class ConvertTest extends SapphireTest private $previousLocaleSetting = null; - public function setUp() + protected function setUp(): void { parent::setUp(); // clear the previous locale setting $this->previousLocaleSetting = null; } - public function tearDown() + protected function tearDown(): void { parent::tearDown(); // If a test sets the locale, reset it on teardown @@ -240,9 +240,9 @@ public function testJSON2Array() $val = '{"Joe":"Bloggs","Tom":"Jones","My":{"Complicated":"Structure"}}'; $decoded = Convert::json2array($val); $this->assertEquals(3, count($decoded), '3 items in the decoded array'); - $this->assertContains('Bloggs', $decoded, 'Contains "Bloggs" value in decoded array'); - $this->assertContains('Jones', $decoded, 'Contains "Jones" value in decoded array'); - $this->assertContains('Structure', $decoded['My']['Complicated']); + $this->assertStringContainsString('Bloggs', $decoded, 'Contains "Bloggs" value in decoded array'); + $this->assertStringContainsString('Jones', $decoded, 'Contains "Jones" value in decoded array'); + $this->assertStringContainsString('Structure', $decoded['My']['Complicated']); } /** diff --git a/tests/php/Core/CoreTest.php b/tests/php/Core/CoreTest.php index 9e82804f5b7..f2a546e55b1 100644 --- a/tests/php/Core/CoreTest.php +++ b/tests/php/Core/CoreTest.php @@ -15,7 +15,7 @@ class CoreTest extends SapphireTest protected $tempPath; - protected function setUp() + protected function setUp(): void { parent::setUp(); $this->tempPath = Director::baseFolder() . DIRECTORY_SEPARATOR . 'silverstripe-cache'; @@ -51,7 +51,7 @@ public function testGetTempPathInProject() } } - protected function tearDown() + protected function tearDown(): void { parent::tearDown(); $user = TempFolder::getTempFolderUsername(); diff --git a/tests/php/Core/Injector/InjectorTest.php b/tests/php/Core/Injector/InjectorTest.php index ac04d988e84..ee3a103bb22 100644 --- a/tests/php/Core/Injector/InjectorTest.php +++ b/tests/php/Core/Injector/InjectorTest.php @@ -2,7 +2,6 @@ namespace SilverStripe\Core\Tests\Injector; -use InvalidArgumentException; use SilverStripe\Core\Config\Config; use SilverStripe\Core\Injector\Factory; use SilverStripe\Core\Injector\Injector; @@ -44,14 +43,14 @@ class InjectorTest extends SapphireTest protected $nestingLevel = 0; - protected function setUp() + protected function setUp(): void { parent::setUp(); $this->nestingLevel = 0; } - protected function tearDown() + protected function tearDown(): void { while ($this->nestingLevel > 0) { @@ -910,11 +909,9 @@ public function testMethods() ); } - /** - * @expectedException InvalidArgumentException - */ public function testNonExistentMethods() { + $this->expectException(\InvalidArgumentException::class); $injector = new Injector(); $config = [ 'TestService' => [ @@ -929,11 +926,9 @@ public function testNonExistentMethods() $item = $injector->get('TestService'); } - /** - * @expectedException InvalidArgumentException - */ public function testProtectedMethods() { + $this->expectException(\InvalidArgumentException::class); $injector = new Injector(); $config = [ 'TestService' => [ @@ -948,11 +943,9 @@ public function testProtectedMethods() $item = $injector->get('TestService'); } - /** - * @expectedException InvalidArgumentException - */ public function testTooManyArrayValues() { + $this->expectException(\InvalidArgumentException::class); $injector = new Injector(); $config = [ 'TestService' => [ @@ -967,11 +960,9 @@ public function testTooManyArrayValues() $item = $injector->get('TestService'); } - /** - * @expectedException \SilverStripe\Core\Injector\InjectorNotFoundException - */ public function testGetThrowsOnNotFound() { + $this->expectException(InjectorNotFoundException::class); $injector = new Injector(); $injector->get('UnknownService'); } diff --git a/tests/php/Core/Manifest/ClassLoaderTest.php b/tests/php/Core/Manifest/ClassLoaderTest.php index 1525fdc3bbe..d0e3d9f8528 100644 --- a/tests/php/Core/Manifest/ClassLoaderTest.php +++ b/tests/php/Core/Manifest/ClassLoaderTest.php @@ -32,7 +32,7 @@ class ClassLoaderTest extends SapphireTest */ protected $testManifest2; - protected function setUp() + protected function setUp(): void { parent::setUp(); diff --git a/tests/php/Core/Manifest/ClassManifestErrorHandlerTest.php b/tests/php/Core/Manifest/ClassManifestErrorHandlerTest.php index 0a9ec22a5cf..075c35d9357 100644 --- a/tests/php/Core/Manifest/ClassManifestErrorHandlerTest.php +++ b/tests/php/Core/Manifest/ClassManifestErrorHandlerTest.php @@ -7,12 +7,10 @@ class ClassManifestErrorHandlerTest extends SapphireTest { - /** - * @expectedException \PhpParser\Error - * @expectedExceptionMessage my error in /my/path - */ public function testIncludesPathname() { + $this->expectException(Error::class); + $this->expectExceptionMessage('my error in /my/path'); $h = new ClassManifestErrorHandler('/my/path'); $e = new Error('my error'); $h->handleError($e); diff --git a/tests/php/Core/Manifest/ClassManifestTest.php b/tests/php/Core/Manifest/ClassManifestTest.php index 40955062f4a..736f767321a 100644 --- a/tests/php/Core/Manifest/ClassManifestTest.php +++ b/tests/php/Core/Manifest/ClassManifestTest.php @@ -27,7 +27,7 @@ class ClassManifestTest extends SapphireTest */ protected $manifestTests; - protected function setUp() + protected function setUp(): void { parent::setUp(); diff --git a/tests/php/Core/Manifest/ConfigManifestTest.php b/tests/php/Core/Manifest/ConfigManifestTest.php index fd2c5520798..1aaa76f1415 100644 --- a/tests/php/Core/Manifest/ConfigManifestTest.php +++ b/tests/php/Core/Manifest/ConfigManifestTest.php @@ -13,7 +13,7 @@ class ConfigManifestTest extends SapphireTest { - protected function setUp() + protected function setUp(): void { parent::setUp(); @@ -22,7 +22,7 @@ protected function setUp() ModuleLoader::inst()->pushManifest($moduleManifest); } - protected function tearDown() + protected function tearDown(): void { ModuleLoader::inst()->popManifest(); parent::tearDown(); @@ -225,7 +225,7 @@ public function testMultipleRules() 'Fragment is included if both blocks succeed.' ); } - + public function testExtensionLoaded() { $config = $this->getConfigFixtureValue('ExtensionLoaded'); diff --git a/tests/php/Core/Manifest/ManifestFileFinderTest.php b/tests/php/Core/Manifest/ManifestFileFinderTest.php index 1eb87bf3bcc..8efd3a1de00 100644 --- a/tests/php/Core/Manifest/ManifestFileFinderTest.php +++ b/tests/php/Core/Manifest/ManifestFileFinderTest.php @@ -41,7 +41,7 @@ public function assertFinderFinds(ManifestFileFinder $finder, $base, $expect, $m sort($expect); sort($found); - $this->assertEquals($expect, $found, $message); + $this->assertEquals($expect, $found, $message ?: ''); } public function testBasicOperation() diff --git a/tests/php/Core/Manifest/ModuleManifestTest.php b/tests/php/Core/Manifest/ModuleManifestTest.php index e77adbf997b..0106aa5c415 100644 --- a/tests/php/Core/Manifest/ModuleManifestTest.php +++ b/tests/php/Core/Manifest/ModuleManifestTest.php @@ -18,7 +18,7 @@ class ModuleManifestTest extends SapphireTest */ protected $manifest; - protected function setUp() + protected function setUp(): void { parent::setUp(); diff --git a/tests/php/Core/Manifest/ModuleResourceTest.php b/tests/php/Core/Manifest/ModuleResourceTest.php index d0d629fe860..c733b636c0f 100644 --- a/tests/php/Core/Manifest/ModuleResourceTest.php +++ b/tests/php/Core/Manifest/ModuleResourceTest.php @@ -18,7 +18,7 @@ class ModuleResourceTest extends SapphireTest */ protected $manifest; - protected function setUp() + protected function setUp(): void { parent::setUp(); diff --git a/tests/php/Core/Manifest/NamespacedClassManifestTest.php b/tests/php/Core/Manifest/NamespacedClassManifestTest.php index fa80e9c63b0..cb2d78da1bf 100644 --- a/tests/php/Core/Manifest/NamespacedClassManifestTest.php +++ b/tests/php/Core/Manifest/NamespacedClassManifestTest.php @@ -8,6 +8,7 @@ use SilverStripe\Core\Manifest\ClassLoader; use SilverStripe\Dev\SapphireTest; use ReflectionMethod; +use SilverStripe\ORM\DataQuery; use SilverStripe\Security\PermissionProvider; /** @@ -25,7 +26,7 @@ class NamespacedClassManifestTest extends SapphireTest */ protected $manifest; - protected function setUp() + protected function setUp(): void { parent::setUp(); @@ -35,7 +36,7 @@ protected function setUp() ClassLoader::inst()->pushManifest($this->manifest, false); } - protected function tearDown() + protected function tearDown(): void { parent::tearDown(); ClassLoader::inst()->popManifest(); @@ -43,8 +44,9 @@ protected function tearDown() public function testClassInfoIsCorrect() { - $this->assertContains( - 'SilverStripe\\Framework\\Tests\\ClassI', + $class = 'SilverStripe\\Framework\\Tests\\ClassI'; + $this->assertStringContainsString( + $class, ClassInfo::implementorsOf(PermissionProvider::class) ); @@ -53,8 +55,13 @@ public function testClassInfoIsCorrect() // including all core classes $method = new ReflectionMethod($this->manifest, 'coalesceDescendants'); $method->setAccessible(true); - $method->invoke($this->manifest, ModelAdmin::class); - $this->assertContains('SilverStripe\\Framework\\Tests\\ClassI', ClassInfo::subclassesFor(ModelAdmin::class)); + $method->invoke($this->manifest, DataQuery::class); + $classes = ClassInfo::subclassesFor(DataQuery::class); + $this->assertStringContainsString( + $class, + $classes, + $class . ' not contained in [' . implode(',', $classes) . ']' + ); } public function testGetItemPath() diff --git a/tests/php/Core/Manifest/PrioritySorterTest.php b/tests/php/Core/Manifest/PrioritySorterTest.php index 8c1f2c345e4..8166fd3b8fa 100644 --- a/tests/php/Core/Manifest/PrioritySorterTest.php +++ b/tests/php/Core/Manifest/PrioritySorterTest.php @@ -12,7 +12,7 @@ class PrioritySorterTest extends SapphireTest */ protected $sorter; - public function setUp() + protected function setUp(): void { parent::setUp(); $modules = [ diff --git a/tests/php/Core/Manifest/ThemeResourceLoaderTest.php b/tests/php/Core/Manifest/ThemeResourceLoaderTest.php index 043bdd5c337..206cd3fd892 100644 --- a/tests/php/Core/Manifest/ThemeResourceLoaderTest.php +++ b/tests/php/Core/Manifest/ThemeResourceLoaderTest.php @@ -33,7 +33,7 @@ class ThemeResourceLoaderTest extends SapphireTest /** * Set up manifest before each test */ - protected function setUp() + protected function setUp(): void { parent::setUp(); @@ -60,7 +60,7 @@ protected function setUp() ThemeResourceLoader::flush(); } - protected function tearDown() + protected function tearDown(): void { ModuleLoader::inst()->popManifest(); parent::tearDown(); diff --git a/tests/php/Core/Manifest/VersionProviderTest.php b/tests/php/Core/Manifest/VersionProviderTest.php index 5d230e0dc12..be4319a3e11 100644 --- a/tests/php/Core/Manifest/VersionProviderTest.php +++ b/tests/php/Core/Manifest/VersionProviderTest.php @@ -81,9 +81,9 @@ public function testGetVersion() 'silverstripe/framework' => 'Framework' ]); $result = $this->getMockProvider()->getVersion(); - $this->assertNotContains('SiteConfig: ', $result); - $this->assertContains('Framework: ', $result); - $this->assertNotContains(', ', $result); + $this->assertStringNotContainsString('SiteConfig: ', $result); + $this->assertStringContainsString('Framework: ', $result); + $this->assertStringNotContainsString(', ', $result); } public function testGetVersionNoRecipe() @@ -93,7 +93,7 @@ public function testGetVersionNoRecipe() Config::modify()->set(VersionProvider::class, 'modules', []); $result = $provider->getVersion(); - $this->assertContains('Framework: 1.2.3', $result); + $this->assertStringContainsString('Framework: 1.2.3', $result); Config::modify()->set(VersionProvider::class, 'modules', [ 'silverstripe/framework' => 'Framework', @@ -102,10 +102,10 @@ public function testGetVersionNoRecipe() 'silverstripe/recipe-cms' => 'CMS Recipe', ]); $result = $provider->getVersion(); - $this->assertNotContains('Framework: 1.2.3', $result); - $this->assertContains('CMS: 4.5.6', $result); - $this->assertNotContains('Core Recipe: 7.7.7', $result); - $this->assertNotContains('CMS Recipe: 8.8.8', $result); + $this->assertStringNotContainsString('Framework: 1.2.3', $result); + $this->assertStringContainsString('CMS: 4.5.6', $result); + $this->assertStringNotContainsString('Core Recipe: 7.7.7', $result); + $this->assertStringNotContainsString('CMS Recipe: 8.8.8', $result); } public function testGetVersionRecipeCore() @@ -119,10 +119,10 @@ public function testGetVersionRecipeCore() 'silverstripe/recipe-cms' => 'CMS Recipe', ]); $result = $provider->getVersion(); - $this->assertNotContains('Framework: 1.2.3', $result); - $this->assertNotContains('Core Recipe: 7.7.7', $result); - $this->assertContains('CMS: 4.5.6', $result); - $this->assertNotContains('CMS Recipe: 8.8.8', $result); + $this->assertStringNotContainsString('Framework: 1.2.3', $result); + $this->assertStringNotContainsString('Core Recipe: 7.7.7', $result); + $this->assertStringContainsString('CMS: 4.5.6', $result); + $this->assertStringNotContainsString('CMS Recipe: 8.8.8', $result); } public function testGetVersionRecipeCmsCore() @@ -139,11 +139,11 @@ public function testGetVersionRecipeCmsCore() ]); $result = $provider->getVersion(); - $this->assertNotContains('Framework: 1.2.3', $result); - $this->assertNotContains('CMS: 4.5.6', $result); - $this->assertNotContains('Core Recipe: 7.7.7', $result); - $this->assertContains('CMS Recipe: 8.8.8', $result); - $this->assertNotContains('CWP: 9.9.9', $result); + $this->assertStringNotContainsString('Framework: 1.2.3', $result); + $this->assertStringNotContainsString('CMS: 4.5.6', $result); + $this->assertStringNotContainsString('Core Recipe: 7.7.7', $result); + $this->assertStringContainsString('CMS Recipe: 8.8.8', $result); + $this->assertStringNotContainsString('CWP: 9.9.9', $result); Config::modify()->set(VersionProvider::class, 'modules', [ 'silverstripe/framework' => 'Framework', @@ -153,11 +153,11 @@ public function testGetVersionRecipeCmsCore() 'cwp/cwp-core' => 'CWP', ]); $result = $provider->getVersion(); - $this->assertNotContains('Framework: 1.2.3', $result); - $this->assertNotContains('CMS: 4.5.6', $result); - $this->assertNotContains('Core Recipe: 7.7.7', $result); - $this->assertContains('CMS Recipe:', $result); - $this->assertContains('CWP: 9.9.9', $result); + $this->assertStringNotContainsString('Framework: 1.2.3', $result); + $this->assertStringNotContainsString('CMS: 4.5.6', $result); + $this->assertStringNotContainsString('Core Recipe: 7.7.7', $result); + $this->assertStringContainsString('CMS Recipe:', $result); + $this->assertStringContainsString('CWP: 9.9.9', $result); } public function testGetModulesFromComposerLock() @@ -186,6 +186,6 @@ public function testGetModulesFromComposerLock() ]); $result = $mock->getVersion(); - $this->assertContains('Some Package: 1.2.3', $result); + $this->assertStringContainsString('Some Package: 1.2.3', $result); } } diff --git a/tests/php/Core/Manifest/fixtures/namespaced_classmanifest/module/classes/ClassI.php b/tests/php/Core/Manifest/fixtures/namespaced_classmanifest/module/classes/ClassI.php index 5ffe2948ccb..209e13ef390 100644 --- a/tests/php/Core/Manifest/fixtures/namespaced_classmanifest/module/classes/ClassI.php +++ b/tests/php/Core/Manifest/fixtures/namespaced_classmanifest/module/classes/ClassI.php @@ -4,7 +4,7 @@ //whitespace here is important for tests, please don't change it /** @skipUpgrade */ -use SilverStripe\Admin\ModelAdmin; +use SilverStripe\ORM\DataQuery; /** @skipUpgrade */ use SilverStripe\Control\Controller as Cont ; /** @skipUpgrade */ @@ -15,5 +15,5 @@ use \SilverStripe\Core\ClassInfo; /** @skipUpgrade */ -class ClassI extends ModelAdmin implements P { +class ClassI extends DataQuery implements P { } diff --git a/tests/php/Core/MemoryLimitTest.php b/tests/php/Core/MemoryLimitTest.php index 842e77645f5..562e349ce16 100644 --- a/tests/php/Core/MemoryLimitTest.php +++ b/tests/php/Core/MemoryLimitTest.php @@ -12,7 +12,7 @@ class MemoryLimitTest extends SapphireTest protected $origMemLimit; protected $origTimeLimit; - protected function setUp() + protected function setUp(): void { parent::setUp(); @@ -29,7 +29,7 @@ protected function setUp() } } - protected function tearDown() + protected function tearDown(): void { if (!in_array('suhosin', get_loaded_extensions())) { ini_set('memory_limit', $this->origMemLimit); diff --git a/tests/php/Core/ObjectTest.php b/tests/php/Core/ObjectTest.php index ab4ceae4ffd..cba0b11973a 100644 --- a/tests/php/Core/ObjectTest.php +++ b/tests/php/Core/ObjectTest.php @@ -31,7 +31,7 @@ class ObjectTest extends SapphireTest { - protected function setUp() + protected function setUp(): void { parent::setUp(); Injector::inst()->unregisterObjects([ diff --git a/tests/php/Core/PathTest.php b/tests/php/Core/PathTest.php index 3808b7f917c..c6ed6af9766 100644 --- a/tests/php/Core/PathTest.php +++ b/tests/php/Core/PathTest.php @@ -68,7 +68,7 @@ public function providerTestJoinPaths() */ public function testJoinPathsErrors($args, $error) { - $this->expectException(InvalidArgumentException::class); + $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage($error); Path::join($args); } diff --git a/tests/php/Core/PhpSyntaxTest.php b/tests/php/Core/PhpSyntaxTest.php index 465b2d5ae9b..10d51fd3f6b 100644 --- a/tests/php/Core/PhpSyntaxTest.php +++ b/tests/php/Core/PhpSyntaxTest.php @@ -9,7 +9,7 @@ */ class PhpSyntaxTest extends SapphireTest { - protected function setUp() + protected function setUp(): void { parent::setUp(); $this->markTestSkipped('This needs to be written to include only core php files, not test/thirdparty files'); diff --git a/tests/php/Dev/BulkLoaderResultTest.php b/tests/php/Dev/BulkLoaderResultTest.php index be0aa2f8a5b..c619eed72bc 100644 --- a/tests/php/Dev/BulkLoaderResultTest.php +++ b/tests/php/Dev/BulkLoaderResultTest.php @@ -13,7 +13,7 @@ class BulkLoaderResultTest extends SapphireTest Player::class, ]; - protected function setUp() + protected function setUp(): void { parent::setUp(); Player::create(['Name' => 'Vincent', 'Status' => 'Available'])->write(); diff --git a/tests/php/Dev/CLIDebugViewTest.php b/tests/php/Dev/CLIDebugViewTest.php index 7d8d06661e0..20241dcafc0 100644 --- a/tests/php/Dev/CLIDebugViewTest.php +++ b/tests/php/Dev/CLIDebugViewTest.php @@ -10,7 +10,7 @@ class CLIDebugViewTest extends SapphireTest { protected $caller = null; - protected function setUp() + protected function setUp(): void { parent::setUp(); diff --git a/tests/php/Dev/CSVParserTest.php b/tests/php/Dev/CSVParserTest.php index 0b2a72687b3..4b2cb62a3b9 100644 --- a/tests/php/Dev/CSVParserTest.php +++ b/tests/php/Dev/CSVParserTest.php @@ -15,7 +15,7 @@ class CSVParserTest extends SapphireTest */ protected $csvPath = null; - protected function setUp() + protected function setUp(): void { parent::setUp(); $this->csvPath = __DIR__ . '/CsvBulkLoaderTest/csv/'; diff --git a/tests/php/Dev/CsvBulkLoaderTest.php b/tests/php/Dev/CsvBulkLoaderTest.php index c7740fd22c8..d47c6754a21 100644 --- a/tests/php/Dev/CsvBulkLoaderTest.php +++ b/tests/php/Dev/CsvBulkLoaderTest.php @@ -31,7 +31,7 @@ class CsvBulkLoaderTest extends SapphireTest */ protected $csvPath = null; - protected function setUp() + protected function setUp(): void { parent::setUp(); $this->csvPath = __DIR__ . '/CsvBulkLoaderTest/csv/'; @@ -115,7 +115,7 @@ public function testLeadingTabs() ]; foreach (Player::get()->column('Biography') as $bio) { - $this->assertContains($bio, $expectedBios); + $this->assertStringContainsString($bio, $expectedBios); } $this->assertEquals(Player::get()->count(), count($expectedBios)); diff --git a/tests/php/Dev/DebugViewTest.php b/tests/php/Dev/DebugViewTest.php index edafe8bffb2..b0158646a6a 100644 --- a/tests/php/Dev/DebugViewTest.php +++ b/tests/php/Dev/DebugViewTest.php @@ -10,7 +10,7 @@ class DebugViewTest extends SapphireTest { protected $caller = null; - protected function setUp() + protected function setUp(): void { parent::setUp(); diff --git a/tests/php/Dev/DeprecationTest.php b/tests/php/Dev/DeprecationTest.php index 194d08dafa0..32bd64f61a9 100644 --- a/tests/php/Dev/DeprecationTest.php +++ b/tests/php/Dev/DeprecationTest.php @@ -2,7 +2,6 @@ namespace SilverStripe\Dev\Tests; -use PHPUnit_Framework_Error; use SilverStripe\Dev\Deprecation; use SilverStripe\Dev\SapphireTest; use SilverStripe\Dev\Tests\DeprecationTest\TestDeprecation; @@ -12,7 +11,7 @@ class DeprecationTest extends SapphireTest static $originalVersionInfo; - protected function setUp() + protected function setUp(): void { parent::setUp(); @@ -21,7 +20,7 @@ protected function setUp() Deprecation::set_enabled(true); } - protected function tearDown() + protected function tearDown(): void { Deprecation::restore_settings(self::$originalVersionInfo); parent::tearDown(); @@ -33,11 +32,9 @@ public function testLesserVersionTriggersNoNotice() $this->assertNull(Deprecation::notice('2.0', 'Deprecation test failed')); } - /** - * @expectedException PHPUnit_Framework_Error - */ public function testEqualVersionTriggersNotice() { + $this->expectError(); Deprecation::notification_version('2.0.0'); Deprecation::notice('2.0.0', 'Deprecation test passed'); } @@ -49,11 +46,9 @@ public function testBetaVersionDoesntTriggerNoticeWhenDeprecationDoesntSpecifyRe $this->assertNull(Deprecation::notice('2.0.0', 'Deprecation test failed')); } - /** - * @expectedException PHPUnit_Framework_Error - */ public function testGreaterVersionTriggersNotice() { + $this->expectError(); Deprecation::notification_version('3.0.0'); Deprecation::notice('2.0', 'Deprecation test passed'); } @@ -65,11 +60,9 @@ public function testNonMatchingModuleNotifcationVersionDoesntAffectNotice() $this->callThatOriginatesFromFramework(); } - /** - * @expectedException PHPUnit_Framework_Error - */ public function testMatchingModuleNotifcationVersionAffectsNotice() { + $this->expectError(); Deprecation::notification_version('1.0.0'); Deprecation::notification_version('3.0.0', 'silverstripe/framework'); $this->callThatOriginatesFromFramework(); @@ -83,32 +76,26 @@ public function testMethodNameCalculation() ); } - /** - * @expectedException PHPUnit_Framework_Error - * @expectedExceptionMessage DeprecationTest->testScopeMethod is deprecated. Method scope - */ public function testScopeMethod() { + $this->expectError(); + $this->expectErrorMessage('DeprecationTest->testScopeMethod is deprecated. Method scope'); Deprecation::notification_version('2.0.0'); Deprecation::notice('2.0.0', 'Method scope', Deprecation::SCOPE_METHOD); } - /** - * @expectedException PHPUnit_Framework_Error - * @expectedExceptionMessage DeprecationTest is deprecated. Class scope - */ public function testScopeClass() { + $this->expectError(); + $this->expectErrorMessage('DeprecationTest is deprecated. Class scope'); Deprecation::notification_version('2.0.0'); Deprecation::notice('2.0.0', 'Class scope', Deprecation::SCOPE_CLASS); } - /** - * @expectedException PHPUnit_Framework_Error - * @expectedExceptionMessage Global scope - */ public function testScopeGlobal() { + $this->expectError(); + $this->expectErrorMessage('Global scope'); Deprecation::notification_version('2.0.0'); Deprecation::notice('2.0.0', 'Global scope', Deprecation::SCOPE_GLOBAL); } diff --git a/tests/php/Dev/DevAdminControllerTest.php b/tests/php/Dev/DevAdminControllerTest.php index 9f12b5a33a4..8a64b3f71ad 100644 --- a/tests/php/Dev/DevAdminControllerTest.php +++ b/tests/php/Dev/DevAdminControllerTest.php @@ -14,7 +14,7 @@ class DevAdminControllerTest extends FunctionalTest { - protected function setUp() + protected function setUp(): void { parent::setUp(); @@ -43,8 +43,8 @@ public function testGoodRegisteredControllerOutput() { // Check for the controller running from the registered url above // (we use contains rather than equals because sometimes you get a warning) - $this->assertContains(Controller1::OK_MSG, $this->getCapture('/dev/x1')); - $this->assertContains(Controller1::OK_MSG, $this->getCapture('/dev/x1/y1')); + $this->assertStringContainsString(Controller1::OK_MSG, $this->getCapture('/dev/x1')); + $this->assertStringContainsString(Controller1::OK_MSG, $this->getCapture('/dev/x1/y1')); } public function testGoodRegisteredControllerStatus() diff --git a/tests/php/Dev/FixtureBlueprintTest.php b/tests/php/Dev/FixtureBlueprintTest.php index b51946d96dc..6224d578301 100644 --- a/tests/php/Dev/FixtureBlueprintTest.php +++ b/tests/php/Dev/FixtureBlueprintTest.php @@ -144,12 +144,10 @@ public function testCreateWithRelationship() $this->assertNotNull($obj2->HasManyRelation()->find('ID', $relation2->ID)); } - /** - * @expectedException InvalidArgumentException - * @expectedExceptionMessage No fixture definitions found - */ public function testCreateWithInvalidRelationName() { + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('No fixture definitions found'); $blueprint = new FixtureBlueprint(TestDataObject::class); $obj = $blueprint->createObject( @@ -165,12 +163,10 @@ public function testCreateWithInvalidRelationName() ); } - /** - * @expectedException InvalidArgumentException - * @expectedExceptionMessage No fixture definitions found - */ public function testCreateWithInvalidRelationIdentifier() { + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('No fixture definitions found'); $blueprint = new FixtureBlueprint(TestDataObject::class); $obj = $blueprint->createObject( @@ -186,12 +182,10 @@ public function testCreateWithInvalidRelationIdentifier() ); } - /** - * @expectedException InvalidArgumentException - * @expectedExceptionMessage Invalid format - */ public function testCreateWithInvalidRelationFormat() { + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('Invalid format'); $factory = new FixtureFactory(); $blueprint = new FixtureBlueprint(TestDataObject::class); diff --git a/tests/php/Dev/SSListExporterTest.php b/tests/php/Dev/SSListExporterTest.php index d4df477edf7..c236f209cd3 100644 --- a/tests/php/Dev/SSListExporterTest.php +++ b/tests/php/Dev/SSListExporterTest.php @@ -18,7 +18,7 @@ class SSListExporterTest extends SapphireTest */ private $exporter; - public function setUp() + protected function setUp(): void { parent::setUp(); $this->exporter = new SSListExporter(); diff --git a/tests/php/Dev/SapphireTestTest.php b/tests/php/Dev/SapphireTestTest.php index a29e7582131..3b571c3c1ae 100644 --- a/tests/php/Dev/SapphireTestTest.php +++ b/tests/php/Dev/SapphireTestTest.php @@ -2,6 +2,7 @@ namespace SilverStripe\Dev\Tests; +use PHPUnit\Framework\ExpectationFailedException; use SilverStripe\Dev\SapphireTest; use SilverStripe\ORM\ArrayList; use SilverStripe\Security\Member; @@ -122,11 +123,10 @@ private function generateArrayListFromItems($itemsForList) * @param $itemsForList * * @testdox assertion assertListAllMatch fails when not all items are matching - * - * @expectedException \PHPUnit_Framework_ExpectationFailedException */ public function testAssertListAllMatchFailsWhenNotMatchingAllItems($match, $itemsForList) { + $this->expectException(ExpectationFailedException::class); $list = $this->generateArrayListFromItems($itemsForList); $this->assertListAllMatch($match, $list); @@ -156,11 +156,10 @@ public function testAssertListContains($matches, $itemsForList) * * @param $matches * @param $itemsForList array - * - * @expectedException \PHPUnit_Framework_ExpectationFailedException */ public function testAssertListContainsFailsIfListDoesNotContainMatch($matches, $itemsForList) { + $this->expectException(ExpectationFailedException::class); $list = $this->generateArrayListFromItems($itemsForList); $list->push(Member::create(['FirstName' => 'Foo', 'Surname' => 'Foo'])); $list->push(Member::create(['FirstName' => 'Bar', 'Surname' => 'Bar'])); @@ -191,11 +190,10 @@ public function testAssertListNotContains($matches, $itemsForList) * @param $itemsForList * * @testdox assertion assertListNotContains throws a exception when a matching item is found in the list - * - * @expectedException \PHPUnit_Framework_ExpectationFailedException */ public function testAssertListNotContainsFailsWhenListContainsAMatch($matches, $itemsForList) { + $this->expectException(ExpectationFailedException::class); $list = $this->generateArrayListFromItems($itemsForList); $list->push(Member::create(['FirstName' => 'Foo', 'Surname' => 'Foo'])); $list->push(Member::create(['FirstName' => 'Bar', 'Surname' => 'Bar'])); @@ -224,11 +222,10 @@ public function testAssertListEquals($matches, $itemsForList) * * @param $matches * @param $itemsForList - * - * @expectedException \PHPUnit_Framework_ExpectationFailedException */ public function testAssertListEqualsFailsOnNonEqualLists($matches, $itemsForList) { + $this->expectException(ExpectationFailedException::class); $list = $this->generateArrayListFromItems($itemsForList); $this->assertListEquals($matches, $list); diff --git a/tests/php/Dev/YamlFixtureTest.php b/tests/php/Dev/YamlFixtureTest.php index 4349940dec4..c18fe391d32 100644 --- a/tests/php/Dev/YamlFixtureTest.php +++ b/tests/php/Dev/YamlFixtureTest.php @@ -45,11 +45,9 @@ public function testStringFixture() $this->assertNull($obj->getFixtureFile()); } - /** - * @expectedException InvalidArgumentException - */ public function testFailsWithInvalidFixturePath() { + $this->expectException(\InvalidArgumentException::class); $invalidPath = ltrim(FRAMEWORK_DIR . '/tests/testing/invalid.yml', '/'); $obj = Injector::inst()->create(YamlFixture::class, $invalidPath); } diff --git a/tests/php/Forms/CheckboxSetFieldMultiEnumTest.php b/tests/php/Forms/CheckboxSetFieldMultiEnumTest.php index 8cbbf813f4d..13c5c42385f 100644 --- a/tests/php/Forms/CheckboxSetFieldMultiEnumTest.php +++ b/tests/php/Forms/CheckboxSetFieldMultiEnumTest.php @@ -26,7 +26,7 @@ public static function getExtraDataObjects() } } - public function setUp() + protected function setUp(): void { if (!(DB::get_conn() instanceof MySQLDatabase)) { $this->markTestSkipped('DBMultiEnum only supported by MySQL'); @@ -35,7 +35,7 @@ public function setUp() parent::setUp(); } - public function tearDown() + protected function tearDown(): void { if (!(DB::get_conn() instanceof MySQLDatabase)) { return; diff --git a/tests/php/Forms/CheckboxSetFieldTest.php b/tests/php/Forms/CheckboxSetFieldTest.php index 63bca0ad892..9a723bcbaa6 100644 --- a/tests/php/Forms/CheckboxSetFieldTest.php +++ b/tests/php/Forms/CheckboxSetFieldTest.php @@ -359,13 +359,13 @@ public function testSafelyCast() ] ); $fieldHTML = (string)$field1->Field(); - $this->assertContains('One', $fieldHTML); - $this->assertContains('Two & Three', $fieldHTML); - $this->assertNotContains('Two & Three', $fieldHTML); - $this->assertContains('Four & Five & Six', $fieldHTML); - $this->assertNotContains('Four & Five & Six', $fieldHTML); - $this->assertContains('<firstname>', $fieldHTML); - $this->assertNotContains('', $fieldHTML); + $this->assertStringContainsString('One', $fieldHTML); + $this->assertStringContainsString('Two & Three', $fieldHTML); + $this->assertStringNotContainsString('Two & Three', $fieldHTML); + $this->assertStringContainsString('Four & Five & Six', $fieldHTML); + $this->assertStringNotContainsString('Four & Five & Six', $fieldHTML); + $this->assertStringContainsString('<firstname>', $fieldHTML); + $this->assertStringNotContainsString('', $fieldHTML); } /** diff --git a/tests/php/Forms/CompositeFieldTest.php b/tests/php/Forms/CompositeFieldTest.php index 6bc72cda452..1cc710ed06b 100644 --- a/tests/php/Forms/CompositeFieldTest.php +++ b/tests/php/Forms/CompositeFieldTest.php @@ -134,9 +134,9 @@ public function testExtraClass() $field->setColumnCount(3); $result = $field->extraClass(); - $this->assertContains('field', $result, 'Default class was not added'); - $this->assertContains('CompositeField', $result, 'Default class was not added'); - $this->assertContains('multicolumn', $result, 'Multi column field did not have extra class added'); + $this->assertStringContainsString('field', $result, 'Default class was not added'); + $this->assertStringContainsString('CompositeField', $result, 'Default class was not added'); + $this->assertStringContainsString('multicolumn', $result, 'Multi column field did not have extra class added'); } public function testGetAttributes() @@ -163,7 +163,7 @@ public function testGetAttributesReturnsEmptyTitleForFieldSets() public function testCollateDataFieldsThrowsErrorOnDuplicateChildren() { $this->expectException(\RuntimeException::class); - $this->expectExceptionMessageRegExp( + $this->expectExceptionMessageMatches( "/a field called 'Test' appears twice in your form.*TextField.*TextField/" ); @@ -266,8 +266,8 @@ public function testDebug() $field->setName('TestComposite'); $result = $field->debug(); - $this->assertContains(CompositeField::class . ' (TestComposite)', $result); - $this->assertContains('TestTextField', $result); - $this->assertContains(''); + $this->assertStringContainsString(CompositeField::class . ' (TestComposite)', $result); + $this->assertStringContainsString('TestTextField', $result); + $this->assertStringContainsString(''); } } diff --git a/tests/php/Forms/ConfirmedPasswordFieldTest.php b/tests/php/Forms/ConfirmedPasswordFieldTest.php index 2f4face19c6..20be818939e 100644 --- a/tests/php/Forms/ConfirmedPasswordFieldTest.php +++ b/tests/php/Forms/ConfirmedPasswordFieldTest.php @@ -16,7 +16,7 @@ class ConfirmedPasswordFieldTest extends SapphireTest { protected $usesDatabase = true; - protected function setUp() + protected function setUp(): void { parent::setUp(); @@ -67,12 +67,12 @@ public function testSetShowOnClick() //hide by default and display show/hide toggle button $field = new ConfirmedPasswordField('Test', 'Testing', 'valueA', null, true); $fieldHTML = $field->Field(); - $this->assertContains( + $this->assertStringContainsString( "showOnClickContainer", $fieldHTML, "Test class for hiding/showing the form contents is set" ); - $this->assertContains( + $this->assertStringContainsString( "showOnClick", $fieldHTML, "Test class for hiding/showing the form contents is set" @@ -81,12 +81,12 @@ public function testSetShowOnClick() //show all by default $field = new ConfirmedPasswordField('Test', 'Testing', 'valueA', null, false); $fieldHTML = $field->Field(); - $this->assertNotContains( + $this->assertStringNotContainsString( "showOnClickContainer", $fieldHTML, "Test class for hiding/showing the form contents is set" ); - $this->assertNotContains( + $this->assertStringNotContainsString( "showOnClick", $fieldHTML, "Test class for hiding/showing the form contents is set" @@ -200,7 +200,7 @@ public function testLengthValidation($minLength, $maxLength, $expectValid, $expe $this->assertSame($expectValid, $result, 'Validate method should return its result'); $this->assertSame($expectValid, $validator->getResult()->isValid()); if ($expectedMessage) { - $this->assertContains($expectedMessage, $validator->getResult()->serialize()); + $this->assertStringContainsString($expectedMessage, $validator->getResult()->serialize()); } } @@ -233,7 +233,7 @@ public function testStrengthValidation() $this->assertFalse($result, 'Validate method should return its result'); $this->assertFalse($validator->getResult()->isValid()); - $this->assertContains( + $this->assertStringContainsString( 'Passwords must have at least one digit and one alphanumeric character', $validator->getResult()->serialize() ); @@ -252,7 +252,7 @@ public function testCurrentPasswordValidation() $this->assertFalse($result, 'Validate method should return its result'); $this->assertFalse($validator->getResult()->isValid()); - $this->assertContains( + $this->assertStringContainsString( 'You must enter your current password', $validator->getResult()->serialize() ); @@ -274,7 +274,7 @@ public function testMustBeLoggedInToChangePassword() $this->assertFalse($result, 'Validate method should return its result'); $this->assertFalse($validator->getResult()->isValid()); - $this->assertContains( + $this->assertStringContainsString( 'You must be logged in to change your password', $validator->getResult()->serialize() ); @@ -300,7 +300,7 @@ public function testValidateCorrectPassword() $this->assertFalse($result, 'Validate method should return its result'); $this->assertFalse($validator->getResult()->isValid()); - $this->assertContains( + $this->assertStringContainsString( 'The current password you have entered is not correct', $validator->getResult()->serialize() ); @@ -357,7 +357,7 @@ public function testPerformReadonlyTransformation() $this->assertInstanceOf(ReadonlyField::class, $result); $this->assertSame('Change it', $result->Title()); - $this->assertContains('***', $result->Value()); + $this->assertStringContainsString('***', $result->Value()); } public function testPerformDisabledTransformation() diff --git a/tests/php/Forms/CurrencyFieldDisabledTest.php b/tests/php/Forms/CurrencyFieldDisabledTest.php index a36efec586c..6f1cc0c70c2 100644 --- a/tests/php/Forms/CurrencyFieldDisabledTest.php +++ b/tests/php/Forms/CurrencyFieldDisabledTest.php @@ -13,9 +13,9 @@ public function testFieldWithValue() $field = new CurrencyField_Disabled('Test', '', '$5.00'); $result = $field->Field(); - $this->assertContains('assertContains('disabled', $result, 'The input should be disabled'); - $this->assertContains('$5.00', $result, 'The value should be rendered'); + $this->assertStringContainsString('assertStringContainsString('disabled', $result, 'The input should be disabled'); + $this->assertStringContainsString('$5.00', $result, 'The value should be rendered'); } /** @@ -27,8 +27,8 @@ public function testFieldWithCustomisedCurrencySymbol() $field = new CurrencyField_Disabled('Test', '', '€5.00'); $result = $field->Field(); - $this->assertContains('assertContains('disabled', $result, 'The input should be disabled'); - $this->assertContains('€5.00', $result, 'The value should be rendered'); + $this->assertStringContainsString('assertStringContainsString('disabled', $result, 'The input should be disabled'); + $this->assertStringContainsString('€5.00', $result, 'The value should be rendered'); } } diff --git a/tests/php/Forms/CurrencyFieldReadonlyTest.php b/tests/php/Forms/CurrencyFieldReadonlyTest.php index d403126e7ab..0c998a8ef68 100644 --- a/tests/php/Forms/CurrencyFieldReadonlyTest.php +++ b/tests/php/Forms/CurrencyFieldReadonlyTest.php @@ -21,9 +21,9 @@ public function testFieldWithValue() $field = new CurrencyField_Readonly('Test', '', '$5.00'); $result = $field->Field(); - $this->assertContains('assertContains('readonly', $result, 'The input should be readonly'); - $this->assertContains('$5.00', $result, 'The value should be rendered'); + $this->assertStringContainsString('assertStringContainsString('readonly', $result, 'The input should be readonly'); + $this->assertStringContainsString('$5.00', $result, 'The value should be rendered'); } public function testFieldWithOutValue() @@ -32,9 +32,9 @@ public function testFieldWithOutValue() $field = new CurrencyField_Readonly('Test', '', null); $result = $field->Field(); - $this->assertContains('assertContains('readonly', $result, 'The input should be readonly'); - $this->assertContains('AUD0.00', $result, 'The value should be rendered'); + $this->assertStringContainsString('assertStringContainsString('readonly', $result, 'The input should be readonly'); + $this->assertStringContainsString('AUD0.00', $result, 'The value should be rendered'); } /** @@ -46,8 +46,8 @@ public function testFieldWithCustomisedCurrencySymbol() $field = new CurrencyField_Readonly('Test', '', '€5.00'); $result = $field->Field(); - $this->assertContains('assertContains('readonly', $result, 'The input should be readonly'); - $this->assertContains('€5.00', $result, 'The value should be rendered'); + $this->assertStringContainsString('assertStringContainsString('readonly', $result, 'The input should be readonly'); + $this->assertStringContainsString('€5.00', $result, 'The value should be rendered'); } } diff --git a/tests/php/Forms/CurrencyFieldTest.php b/tests/php/Forms/CurrencyFieldTest.php index dbb595996fe..02c4114e4d1 100644 --- a/tests/php/Forms/CurrencyFieldTest.php +++ b/tests/php/Forms/CurrencyFieldTest.php @@ -307,6 +307,6 @@ public function testInvalidCurrencySymbol() $this->assertFalse($result, 'Validation should fail since wrong currency was used'); $this->assertFalse($validator->getResult()->isValid(), 'Validator should receive failed state'); - $this->assertContains('Please enter a valid currency', $validator->getResult()->serialize()); + $this->assertStringContainsString('Please enter a valid currency', $validator->getResult()->serialize()); } } diff --git a/tests/php/Forms/DatalessFieldTest.php b/tests/php/Forms/DatalessFieldTest.php index a67cfc9a637..abfdf54acbd 100644 --- a/tests/php/Forms/DatalessFieldTest.php +++ b/tests/php/Forms/DatalessFieldTest.php @@ -2,7 +2,7 @@ namespace SilverStripe\Forms; -use PHPUnit_Framework_MockObject_MockObject; +use PHPUnit\Framework\MockObject\MockObject; use SilverStripe\Dev\SapphireTest; class DatalessFieldTest extends SapphireTest @@ -16,7 +16,7 @@ public function testGetAttributes() public function testFieldHolderAndSmallFieldHolderReturnField() { - /** @var DatalessField|PHPUnit_Framework_MockObject_MockObject $mock */ + /** @var DatalessField|MockObject $mock */ $mock = $this->getMockBuilder(DatalessField::class) ->disableOriginalConstructor() ->setMethods(['Field']) diff --git a/tests/php/Forms/DateFieldDisabledTest.php b/tests/php/Forms/DateFieldDisabledTest.php index 6fffdcd1364..b3f66b5c53c 100644 --- a/tests/php/Forms/DateFieldDisabledTest.php +++ b/tests/php/Forms/DateFieldDisabledTest.php @@ -12,7 +12,7 @@ */ class DateFieldDisabledTest extends SapphireTest { - protected function setUp() + protected function setUp(): void { parent::setUp(); i18n::set_locale('en_NZ'); @@ -79,7 +79,7 @@ public function testType() { $field = new DateField_Disabled('Test'); $result = $field->Type(); - $this->assertContains('readonly', $result, 'Disabled field should be treated as readonly'); - $this->assertContains('date_disabled', $result, 'Field should contain date_disabled class'); + $this->assertStringContainsString('readonly', $result, 'Disabled field should be treated as readonly'); + $this->assertStringContainsString('date_disabled', $result, 'Field should contain date_disabled class'); } } diff --git a/tests/php/Forms/DateFieldTest.php b/tests/php/Forms/DateFieldTest.php index 87065fc8a94..55bbb15abd5 100644 --- a/tests/php/Forms/DateFieldTest.php +++ b/tests/php/Forms/DateFieldTest.php @@ -3,6 +3,7 @@ namespace SilverStripe\Forms\Tests; use IntlDateFormatter; +use LogicException; use SilverStripe\Dev\SapphireTest; use SilverStripe\Forms\DateField; use SilverStripe\Forms\DateField_Disabled; @@ -16,7 +17,7 @@ */ class DateFieldTest extends SapphireTest { - protected function setUp() + protected function setUp(): void { parent::setUp(); i18n::set_locale('en_NZ'); @@ -192,36 +193,30 @@ public function testMDYFormat() ); } - /** - * @expectedException \LogicException - * @expectedExceptionMessageRegExp /Please opt-out .* if using setDateFormat/ - */ public function testHtml5WithCustomFormatThrowsException() { + $this->expectException(\LogicException::class); + $this->expectExceptionMessageMatches('/Please opt-out .* if using setDateFormat/'); $dateField = new DateField('Date', 'Date'); $dateField->setValue('2010-03-31'); $dateField->setDateFormat('d/M/y'); $dateField->Value(); } - /** - * @expectedException \LogicException - * @expectedExceptionMessageRegExp /Please opt-out .* if using setDateLength/ - */ public function testHtml5WithCustomDateLengthThrowsException() { + $this->expectException(\LogicException::class); + $this->expectExceptionMessageMatches('/Please opt-out .* if using setDateLength/'); $dateField = new DateField('Date', 'Date'); $dateField->setValue('2010-03-31'); $dateField->setDateLength(IntlDateFormatter::MEDIUM); $dateField->Value(); } - /** - * @expectedException \LogicException - * @expectedExceptionMessageRegExp /Please opt-out .* if using setLocale/ - */ public function testHtml5WithCustomLocaleThrowsException() { + $this->expectException(\LogicException::class); + $this->expectExceptionMessageMatches('/Please opt-out .* if using setLocale/'); $dateField = new DateField('Date', 'Date'); $dateField->setValue('2010-03-31'); $dateField->setLocale('de_DE'); diff --git a/tests/php/Forms/DatetimeFieldTest.php b/tests/php/Forms/DatetimeFieldTest.php index ec36a0ab803..6fa5e39a76b 100644 --- a/tests/php/Forms/DatetimeFieldTest.php +++ b/tests/php/Forms/DatetimeFieldTest.php @@ -17,7 +17,7 @@ class DatetimeFieldTest extends SapphireTest { protected $timezone = null; - protected function setUp() + protected function setUp(): void { parent::setUp(); i18n::set_locale('en_NZ'); @@ -26,7 +26,7 @@ protected function setUp() $this->timezone = date_default_timezone_get(); } - protected function tearDown() + protected function tearDown(): void { DBDatetime::clear_mock_now(); date_default_timezone_set($this->timezone); @@ -146,7 +146,7 @@ public function testSetValueWithLocalised() $this->assertEquals($datetimeField->dataValue(), '2003-03-29 23:00:00'); // Some localisation packages exclude the ',' in default medium format - $this->assertRegExp( + $this->assertMatchesRegularExpression( '#29/03/2003(,)? 11:00:00 (PM|pm)#', $datetimeField->Value(), 'User value is formatted, and in user timezone' @@ -490,12 +490,10 @@ public function testPerformReadonlyTransformation() $this->assertTrue($result->isReadonly()); } - /** - * @expectedException \BadMethodCallException - * @expectedExceptionMessage Can't change timezone after setting a value - */ public function testSetTimezoneThrowsExceptionWhenChangingTimezoneAfterSettingValue() { + $this->expectException(\BadMethodCallException::class); + $this->expectExceptionMessage("Can't change timezone after setting a value"); date_default_timezone_set('Europe/Berlin'); $field = new DatetimeField('Datetime', 'Time', '2003-03-29 23:59:38'); $field->setTimezone('Pacific/Auckland'); diff --git a/tests/php/Forms/DefaultFormFactoryTest.php b/tests/php/Forms/DefaultFormFactoryTest.php index c8ab715f33e..8e3efc67780 100644 --- a/tests/php/Forms/DefaultFormFactoryTest.php +++ b/tests/php/Forms/DefaultFormFactoryTest.php @@ -9,12 +9,10 @@ class DefaultFormFactoryTest extends SapphireTest { - /** - * @expectedException InvalidArgumentException - * @expectedExceptionMessageRegExp /Missing required context/ - */ public function testGetFormThrowsExceptionOnMissingContext() { + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessageMatches('/Missing required context/'); $factory = new DefaultFormFactory(); $factory->getForm(); } @@ -33,6 +31,6 @@ public function testGetForm() public function testGetRequiredContext() { $factory = new DefaultFormFactory(); - $this->assertContains('Record', $factory->getRequiredContext()); + $this->assertStringContainsString('Record', $factory->getRequiredContext()); } } diff --git a/tests/php/Forms/EmailFieldTest.php b/tests/php/Forms/EmailFieldTest.php index 85733d8a611..75e5e33dea0 100644 --- a/tests/php/Forms/EmailFieldTest.php +++ b/tests/php/Forms/EmailFieldTest.php @@ -5,7 +5,7 @@ use SilverStripe\Dev\FunctionalTest; use SilverStripe\Forms\EmailField; use Exception; -use PHPUnit_Framework_AssertionFailedError; +use PHPUnit\Framework\AssertionFailedError; use SilverStripe\Forms\Tests\EmailFieldTest\TestValidator; /** @@ -51,7 +51,7 @@ public function internalCheck($email, $checkText, $expectSuccess) // If we expect failure and processing gets here without an exception, the test failed $this->assertTrue($expectSuccess, $checkText . " (/$email/ passed validation, but not expected to)"); } catch (Exception $e) { - if ($e instanceof PHPUnit_Framework_AssertionFailedError) { + if ($e instanceof AssertionFailedError) { // re-throw assertion failure throw $e; } elseif ($expectSuccess) { @@ -77,6 +77,6 @@ public function testEmailFieldPopulation() ['Email' => 'test@test.com'] ); - $this->assertContains('Test save was successful', $response->getBody()); + $this->assertStringContainsString('Test save was successful', $response->getBody()); } } diff --git a/tests/php/Forms/FileFieldTest.php b/tests/php/Forms/FileFieldTest.php index 19779d986ec..8889d4a11cb 100644 --- a/tests/php/Forms/FileFieldTest.php +++ b/tests/php/Forms/FileFieldTest.php @@ -115,7 +115,7 @@ public function testGetAcceptFileTypes() $expected = ['.jpg', '.png', 'image/jpeg', 'image/png']; foreach ($expected as $extensionOrMime) { - $this->assertContains($extensionOrMime, $allowed); + $this->assertStringContainsString($extensionOrMime, $allowed); } } diff --git a/tests/php/Forms/FormActionTest.php b/tests/php/Forms/FormActionTest.php index 328aadb79ed..0ce07c27948 100644 --- a/tests/php/Forms/FormActionTest.php +++ b/tests/php/Forms/FormActionTest.php @@ -11,10 +11,10 @@ class FormActionTest extends SapphireTest public function testGetField() { $formAction = new FormAction('test'); - $this->assertContains('type="submit"', $formAction->getAttributesHTML()); + $this->assertStringContainsString('type="submit"', $formAction->getAttributesHTML()); $formAction->setAttribute('src', 'file.png'); - $this->assertContains('type="image"', $formAction->getAttributesHTML()); + $this->assertStringContainsString('type="image"', $formAction->getAttributesHTML()); } public function testGetTitle() diff --git a/tests/php/Forms/FormFactoryTest.php b/tests/php/Forms/FormFactoryTest.php index 67242c3e9a6..8cac9edc463 100644 --- a/tests/php/Forms/FormFactoryTest.php +++ b/tests/php/Forms/FormFactoryTest.php @@ -28,7 +28,7 @@ public static function getExtraDataObjects() return []; } - public function setUp() + protected function setUp(): void { parent::setUp(); diff --git a/tests/php/Forms/FormFieldTest.php b/tests/php/Forms/FormFieldTest.php index 8f60cddbbad..402b8246c65 100644 --- a/tests/php/Forms/FormFieldTest.php +++ b/tests/php/Forms/FormFieldTest.php @@ -2,10 +2,10 @@ namespace SilverStripe\Forms\Tests; +use LogicException; use ReflectionClass; use SilverStripe\Core\ClassInfo; use SilverStripe\Core\Config\Config; -use SilverStripe\Core\Convert; use SilverStripe\Dev\SapphireTest; use SilverStripe\Forms\CompositeField; use SilverStripe\Forms\FieldList; @@ -40,7 +40,7 @@ public function testDefaultClasses() $field = new FormField('MyField'); - $this->assertContains('class1', $field->extraClass(), 'Class list does not contain expected class'); + $this->assertStringContainsString('class1', $field->extraClass(), 'Class list does not contain expected class'); FormField::config()->update( 'default_classes', @@ -52,7 +52,7 @@ public function testDefaultClasses() $field = new FormField('MyField'); - $this->assertContains('class1 class2', $field->extraClass(), 'Class list does not contain expected class'); + $this->assertStringContainsString('class1 class2', $field->extraClass(), 'Class list does not contain expected class'); FormField::config()->update( 'default_classes', @@ -63,11 +63,11 @@ public function testDefaultClasses() $field = new FormField('MyField'); - $this->assertContains('class3', $field->extraClass(), 'Class list does not contain expected class'); + $this->assertStringContainsString('class3', $field->extraClass(), 'Class list does not contain expected class'); $field->removeExtraClass('class3'); - $this->assertNotContains('class3', $field->extraClass(), 'Class list contains unexpected class'); + $this->assertStringNotContainsString('class3', $field->extraClass(), 'Class list contains unexpected class'); TextField::config()->update( 'default_classes', @@ -79,8 +79,8 @@ public function testDefaultClasses() $field = new TextField('MyField'); //check default classes inherit - $this->assertContains('class3', $field->extraClass(), 'Class list does not contain inherited class'); - $this->assertContains('textfield-class', $field->extraClass(), 'Class list does not contain expected class'); + $this->assertStringContainsString('class3', $field->extraClass(), 'Class list does not contain inherited class'); + $this->assertStringContainsString('textfield-class', $field->extraClass(), 'Class list does not contain expected class'); Config::unnest(); } @@ -159,35 +159,35 @@ public function testAttributesHTML() $field = new FormField('MyField'); $field->setAttribute('foo', 'bar'); - $this->assertContains('foo="bar"', $field->getAttributesHTML()); + $this->assertStringContainsString('foo="bar"', $field->getAttributesHTML()); $field->setAttribute('foo', null); - $this->assertNotContains('foo=', $field->getAttributesHTML()); + $this->assertStringNotContainsString('foo=', $field->getAttributesHTML()); $field->setAttribute('foo', ''); - $this->assertNotContains('foo=', $field->getAttributesHTML()); + $this->assertStringNotContainsString('foo=', $field->getAttributesHTML()); $field->setAttribute('foo', false); - $this->assertNotContains('foo=', $field->getAttributesHTML()); + $this->assertStringNotContainsString('foo=', $field->getAttributesHTML()); $field->setAttribute('foo', true); - $this->assertContains('foo="foo"', $field->getAttributesHTML()); + $this->assertStringContainsString('foo="foo"', $field->getAttributesHTML()); $field->setAttribute('foo', 'false'); - $this->assertContains('foo="false"', $field->getAttributesHTML()); + $this->assertStringContainsString('foo="false"', $field->getAttributesHTML()); $field->setAttribute('foo', 'true'); - $this->assertContains('foo="true"', $field->getAttributesHTML()); + $this->assertStringContainsString('foo="true"', $field->getAttributesHTML()); $field->setAttribute('foo', 0); - $this->assertContains('foo="0"', $field->getAttributesHTML()); + $this->assertStringContainsString('foo="0"', $field->getAttributesHTML()); $field->setAttribute('one', 1); $field->setAttribute('two', 2); $field->setAttribute('three', 3); - $this->assertNotContains('one="1"', $field->getAttributesHTML('one', 'two')); - $this->assertNotContains('two="2"', $field->getAttributesHTML('one', 'two')); - $this->assertContains('three="3"', $field->getAttributesHTML('one', 'two')); + $this->assertStringNotContainsString('one="1"', $field->getAttributesHTML('one', 'two')); + $this->assertStringNotContainsString('two="2"', $field->getAttributesHTML('one', 'two')); + $this->assertStringContainsString('three="3"', $field->getAttributesHTML('one', 'two')); } /** @@ -241,18 +241,18 @@ public function testReadonly() { $field = new FormField('MyField'); $field->setReadonly(true); - $this->assertContains('readonly="readonly"', $field->getAttributesHTML()); + $this->assertStringContainsString('readonly="readonly"', $field->getAttributesHTML()); $field->setReadonly(false); - $this->assertNotContains('readonly="readonly"', $field->getAttributesHTML()); + $this->assertStringNotContainsString('readonly="readonly"', $field->getAttributesHTML()); } public function testDisabled() { $field = new FormField('MyField'); $field->setDisabled(true); - $this->assertContains('disabled="disabled"', $field->getAttributesHTML()); + $this->assertStringContainsString('disabled="disabled"', $field->getAttributesHTML()); $field->setDisabled(false); - $this->assertNotContains('disabled="disabled"', $field->getAttributesHTML()); + $this->assertStringNotContainsString('disabled="disabled"', $field->getAttributesHTML()); } public function testEveryFieldTransformsReadonlyAsClone() @@ -358,7 +358,7 @@ public function testGetSchemaDataDefaults() { $field = new FormField('MyField'); $schema = $field->getSchemaDataDefaults(); - $this->assertInternalType('array', $schema); + $this->assertIsArray($schema); } public function testGetSchemaDataDefaultsTitleTip() @@ -454,11 +454,9 @@ public function testLinkWithForm() $this->assertSame('foo/field/Test/bar', $field->Link('bar')); } - /** - * @expectedException \LogicException - */ public function testLinkWithoutForm() { + $this->expectException(\LogicException::class); $field = new FormField('Test'); $field->Link('bar'); } diff --git a/tests/php/Forms/FormSchemaTest.php b/tests/php/Forms/FormSchemaTest.php index 7af4d8d70e1..e873e5500b2 100644 --- a/tests/php/Forms/FormSchemaTest.php +++ b/tests/php/Forms/FormSchemaTest.php @@ -20,7 +20,7 @@ */ class FormSchemaTest extends SapphireTest { - protected function setUp() + protected function setUp(): void { parent::setUp(); @@ -38,7 +38,7 @@ public function testGetSchema() $expected = json_decode(file_get_contents(__DIR__ . '/FormSchemaTest/testGetSchema.json'), true); $schema = $formSchema->getSchema($form); - $this->assertInternalType('array', $schema); + $this->assertIsArray($schema); $this->assertEquals($expected, $schema); } @@ -62,7 +62,7 @@ public function testGetState() ]; $state = $formSchema->getState($form); - $this->assertInternalType('array', $state); + $this->assertIsArray($state); $this->assertEquals($expected, $state); } @@ -92,7 +92,7 @@ public function testGetStateWithFormMessages() ]; $state = $formSchema->getState($form); - $this->assertInternalType('array', $state); + $this->assertIsArray($state); $this->assertJsonStringEqualsJsonString(json_encode($expected), json_encode($state)); } @@ -136,7 +136,7 @@ public function testGetStateWithFieldValidationErrors() ]; $state = $formSchema->getState($form); - $this->assertInternalType('array', $state); + $this->assertIsArray($state); $this->assertJsonStringEqualsJsonString(json_encode($expected), json_encode($state)); } @@ -167,7 +167,7 @@ public function testGetNestedSchema() $expected = json_decode(file_get_contents(__DIR__ . '/FormSchemaTest/testGetNestedSchema.json'), true); $schema = $formSchema->getSchema($form); - $this->assertInternalType('array', $schema); + $this->assertIsArray($schema); $this->assertEquals($expected, $schema); } @@ -207,7 +207,7 @@ public function testSchemaValidation() $formSchema = new FormSchema(); $schema = $formSchema->getSchema($form); $expected = json_decode(file_get_contents(__DIR__ . '/FormSchemaTest/testSchemaValidation.json'), true); - $this->assertInternalType('array', $schema); + $this->assertIsArray($schema); $this->assertEquals($expected, $schema); } } diff --git a/tests/php/Forms/FormTest.php b/tests/php/Forms/FormTest.php index 8ee42df4bb1..f9fb8e51d2a 100644 --- a/tests/php/Forms/FormTest.php +++ b/tests/php/Forms/FormTest.php @@ -56,7 +56,7 @@ class FormTest extends FunctionalTest protected static $disable_themes = true; - protected function setUp() + protected function setUp(): void { parent::setUp(); @@ -140,16 +140,16 @@ public function testSubmitReadonlyFields() ); // Number field updates its value - $this->assertContains('getBody()); + $this->assertStringContainsString('getBody()); // Readonly field remains - $this->assertContains( + $this->assertStringContainsString( 'getBody() ); - $this->assertNotContains('hacxzored', $response->getBody()); + $this->assertStringNotContainsString('hacxzored', $response->getBody()); } public function testLoadDataFromUnchangedHandling() @@ -502,12 +502,12 @@ public function testSessionValidationMessage() 'Required fields show a notification on field when left blank' ); - $this->assertContains( + $this->assertStringContainsString( ''<a href="http://mysite.com">link</a>' is not a number, only numbers can be accepted for this field', $response->getBody(), "Validation messages are safely XML encoded" ); - $this->assertNotContains( + $this->assertStringNotContainsString( 'link', $response->getBody(), "Unsafe content is not emitted directly inside the response body" @@ -788,7 +788,7 @@ public function testDefaultClasses() $form = $this->getStubForm(); - $this->assertContains('class1', $form->extraClass(), 'Class list does not contain expected class'); + $this->assertStringContainsString('class1', $form->extraClass(), 'Class list does not contain expected class'); Form::config()->update( 'default_classes', @@ -800,7 +800,7 @@ public function testDefaultClasses() $form = $this->getStubForm(); - $this->assertContains('class1 class2', $form->extraClass(), 'Class list does not contain expected class'); + $this->assertStringContainsString('class1 class2', $form->extraClass(), 'Class list does not contain expected class'); Form::config()->update( 'default_classes', @@ -811,11 +811,11 @@ public function testDefaultClasses() $form = $this->getStubForm(); - $this->assertContains('class3', $form->extraClass(), 'Class list does not contain expected class'); + $this->assertStringContainsString('class3', $form->extraClass(), 'Class list does not contain expected class'); $form->removeExtraClass('class3'); - $this->assertNotContains('class3', $form->extraClass(), 'Class list contains unexpected class'); + $this->assertStringNotContainsString('class3', $form->extraClass(), 'Class list contains unexpected class'); } public function testAttributes() @@ -903,22 +903,22 @@ public function testAttributesHTML() $form = $this->getStubForm(); $form->setAttribute('foo', 'bar'); - $this->assertContains('foo="bar"', $form->getAttributesHTML()); + $this->assertStringContainsString('foo="bar"', $form->getAttributesHTML()); $form->setAttribute('foo', null); - $this->assertNotContains('foo="bar"', $form->getAttributesHTML()); + $this->assertStringNotContainsString('foo="bar"', $form->getAttributesHTML()); $form->setAttribute('foo', true); - $this->assertContains('foo="foo"', $form->getAttributesHTML()); + $this->assertStringContainsString('foo="foo"', $form->getAttributesHTML()); $form->setAttribute('one', 1); $form->setAttribute('two', 2); $form->setAttribute('three', 3); $form->setAttribute('', ''); - $this->assertNotContains('one="1"', $form->getAttributesHTML('one', 'two')); - $this->assertNotContains('two="2"', $form->getAttributesHTML('one', 'two')); - $this->assertContains('three="3"', $form->getAttributesHTML('one', 'two')); - $this->assertNotContains('', $form->getAttributesHTML()); + $this->assertStringNotContainsString('one="1"', $form->getAttributesHTML('one', 'two')); + $this->assertStringNotContainsString('two="2"', $form->getAttributesHTML('one', 'two')); + $this->assertStringContainsString('three="3"', $form->getAttributesHTML('one', 'two')); + $this->assertStringNotContainsString('', $form->getAttributesHTML()); } function testMessageEscapeHtml() @@ -927,7 +927,7 @@ function testMessageEscapeHtml() $form->setMessage('Escaped HTML', 'good', ValidationResult::CAST_TEXT); $parser = new CSSContentParser($form->forTemplate()); $messageEls = $parser->getBySelector('.message'); - $this->assertContains( + $this->assertStringContainsString( '<em>Escaped HTML</em>', $messageEls[0]->asXML() ); @@ -936,7 +936,7 @@ function testMessageEscapeHtml() $form->setMessage('Unescaped HTML', 'good', ValidationResult::CAST_HTML); $parser = new CSSContentParser($form->forTemplate()); $messageEls = $parser->getBySelector('.message'); - $this->assertContains( + $this->assertStringContainsString( 'Unescaped HTML', $messageEls[0]->asXML() ); @@ -948,7 +948,7 @@ public function testFieldMessageEscapeHtml() $form->Fields()->dataFieldByName('key1')->setMessage('Escaped HTML', 'good'); $parser = new CSSContentParser($result = $form->forTemplate()); $messageEls = $parser->getBySelector('#Form_Form_key1_Holder .message'); - $this->assertContains( + $this->assertStringContainsString( '<em>Escaped HTML</em>', $messageEls[0]->asXML() ); @@ -961,7 +961,7 @@ public function testFieldMessageEscapeHtml() ->setMessage('Unescaped HTML', 'good', ValidationResult::CAST_HTML); $parser = new CSSContentParser($form->forTemplate()); $messageEls = $parser->getBySelector('#Form_Form_key1_Holder .message'); - $this->assertContains( + $this->assertStringContainsString( 'Unescaped HTML', $messageEls[0]->asXML() ); @@ -1055,25 +1055,25 @@ public function testRestoreFromState() // Test our reloaded form field $body = $response->getBody(); - $this->assertContains( + $this->assertStringContainsString( 'assertContains( + $this->assertStringContainsString( 'clean($body), 'Our reloaded form should contain a SomeFrenchNumericField with the value "9 876,5432"' ); - $this->assertContains( + $this->assertStringContainsString( 'assertContains( + $this->assertStringContainsString( 'clean($body), 'Our reloaded form should contain a SomeFrenchMoneyField[Amount] with the value "9 876,54"' diff --git a/tests/php/Forms/GridField/GridFieldActionMenuTest.php b/tests/php/Forms/GridField/GridFieldActionMenuTest.php index 51794715916..4404b62542a 100644 --- a/tests/php/Forms/GridField/GridFieldActionMenuTest.php +++ b/tests/php/Forms/GridField/GridFieldActionMenuTest.php @@ -55,7 +55,7 @@ class GridFieldActionMenuTest extends SapphireTest Permissions::class, ]; - protected function setUp() + protected function setUp(): void { parent::setUp(); $this->list = new DataList(Team::class); diff --git a/tests/php/Forms/GridField/GridFieldDataColumnsTest.php b/tests/php/Forms/GridField/GridFieldDataColumnsTest.php index c1f5ca9d5cf..5424fd96fb0 100644 --- a/tests/php/Forms/GridField/GridFieldDataColumnsTest.php +++ b/tests/php/Forms/GridField/GridFieldDataColumnsTest.php @@ -2,6 +2,7 @@ namespace SilverStripe\Forms\Tests\GridField; +use InvalidArgumentException; use SilverStripe\Forms\GridField\GridFieldDataColumns; use SilverStripe\Security\Member; use SilverStripe\Dev\SapphireTest; @@ -41,11 +42,10 @@ public function testGridFieldCustomDisplayFields() /** * @covers \SilverStripe\Forms\GridField\GridFieldDataColumns::setDisplayFields * @covers \SilverStripe\Forms\GridField\GridFieldDataColumns::getDisplayFields - * - * @expectedException \InvalidArgumentException */ public function testGridFieldDisplayFieldsWithBadArguments() { + $this->expectException(\InvalidArgumentException::class); $obj = new GridField('testfield', 'testfield', Member::get()); $columns = $obj->getConfig()->getComponentByType(GridFieldDataColumns::class); $columns->setDisplayFields(new stdClass()); diff --git a/tests/php/Forms/GridField/GridFieldDeleteActionTest.php b/tests/php/Forms/GridField/GridFieldDeleteActionTest.php index 4f2005b03a8..a60bdfc36a1 100644 --- a/tests/php/Forms/GridField/GridFieldDeleteActionTest.php +++ b/tests/php/Forms/GridField/GridFieldDeleteActionTest.php @@ -56,7 +56,7 @@ class GridFieldDeleteActionTest extends SapphireTest Permissions::class, ]; - protected function setUp() + protected function setUp(): void { parent::setUp(); $this->list = new DataList(Team::class); @@ -92,7 +92,7 @@ public function testShowDeleteButtonsWithAdminPermission() public function testActionsRequireCSRF() { $this->logInWithPermission('ADMIN'); - $this->expectException(HTTPResponse_Exception::class); + $this->expectException(\HTTPResponse_Exception::class); $this->expectExceptionMessage(_t( "SilverStripe\\Forms\\Form.CSRF_FAILED_MESSAGE", "There seems to have been a technical problem. Please click the back button, " . "refresh your browser, and try again." diff --git a/tests/php/Forms/GridField/GridFieldEditButtonTest.php b/tests/php/Forms/GridField/GridFieldEditButtonTest.php index d5a14b90202..b3a08394cf7 100644 --- a/tests/php/Forms/GridField/GridFieldEditButtonTest.php +++ b/tests/php/Forms/GridField/GridFieldEditButtonTest.php @@ -52,7 +52,7 @@ class GridFieldEditButtonTest extends SapphireTest Permissions::class, ]; - protected function setUp() + protected function setUp(): void { parent::setUp(); $this->list = new DataList(Team::class); @@ -100,7 +100,7 @@ public function testDefaultClassesAreSet() $result = $button->getExtraClass(); foreach ($expected as $className) { - $this->assertContains($className, $result); + $this->assertStringContainsString($className, $result); } } @@ -109,15 +109,15 @@ public function testAddAndRemoveExtraClass() $button = new GridFieldEditButton; $button->addExtraClass('foobar'); - $this->assertContains('foobar', $button->getExtraClass()); + $this->assertStringContainsString('foobar', $button->getExtraClass()); $button->removeExtraClass('foobar'); - $this->assertNotContains('foobar', $button->getExtraClass()); + $this->assertStringNotContainsString('foobar', $button->getExtraClass()); // Check that duplicates are removed $button->addExtraClass('foobar'); $button->addExtraClass('foobar'); $button->removeExtraClass('foobar'); - $this->assertNotContains('foobar', $button->getExtraClass()); + $this->assertStringNotContainsString('foobar', $button->getExtraClass()); } } diff --git a/tests/php/Forms/GridField/GridFieldExportButtonTest.php b/tests/php/Forms/GridField/GridFieldExportButtonTest.php index 222d5f6575c..3496332b4cd 100644 --- a/tests/php/Forms/GridField/GridFieldExportButtonTest.php +++ b/tests/php/Forms/GridField/GridFieldExportButtonTest.php @@ -35,7 +35,7 @@ class GridFieldExportButtonTest extends SapphireTest NoView::class, ]; - protected function setUp() + protected function setUp(): void { parent::setUp(); diff --git a/tests/php/Forms/GridField/GridFieldFilterHeaderTest.php b/tests/php/Forms/GridField/GridFieldFilterHeaderTest.php index 91e1a14f3da..8ce32a97ae9 100644 --- a/tests/php/Forms/GridField/GridFieldFilterHeaderTest.php +++ b/tests/php/Forms/GridField/GridFieldFilterHeaderTest.php @@ -50,7 +50,7 @@ class GridFieldFilterHeaderTest extends SapphireTest Mom::class, ]; - protected function setUp() + protected function setUp(): void { parent::setUp(); $this->list = new DataList(Team::class); @@ -70,8 +70,8 @@ public function testRenderHeaders() $htmlFragment = $this->component->getHTMLFragments($this->gridField); // Check that the output is the new search field - $this->assertContains('
assertContains('Open search and filter', $htmlFragment['buttons-before-right']); + $this->assertStringContainsString('
assertStringContainsString('Open search and filter', $htmlFragment['buttons-before-right']); $this->gridField->getConfig()->removeComponentsByType(GridFieldFilterHeader::class); $this->gridField->getConfig()->addComponent(new GridFieldFilterHeader(true)); @@ -79,7 +79,7 @@ public function testRenderHeaders() $htmlFragment = $this->component->getHTMLFragments($this->gridField); // Check that the output is the legacy filter header - $this->assertContains( + $this->assertStringContainsString( '', $htmlFragment['header'] ); diff --git a/tests/php/Forms/GridField/GridFieldLazyLoaderTest.php b/tests/php/Forms/GridField/GridFieldLazyLoaderTest.php index 553f6ae0364..9789fe08c49 100644 --- a/tests/php/Forms/GridField/GridFieldLazyLoaderTest.php +++ b/tests/php/Forms/GridField/GridFieldLazyLoaderTest.php @@ -44,7 +44,7 @@ class GridFieldLazyLoaderTest extends SapphireTest Team::class, ]; - protected function setUp() + protected function setUp(): void { parent::setUp(); $this->list = DataList::create(Team::class); @@ -89,8 +89,8 @@ public function testGetHTMLFragmentsWithoutHeader() $gridField = $this->getHeaderlessGridField(); $actual = $this->component->getHTMLFragments($gridField); $this->assertEmpty($actual, 'getHTMLFragments should always return an array'); - $this->assertContains('grid-field--lazy-loadable', $gridField->extraClass()); - $this->assertNotContains('grid-field--lazy-loaded', $gridField->extraClass()); + $this->assertStringContainsString('grid-field--lazy-loadable', $gridField->extraClass()); + $this->assertStringNotContainsString('grid-field--lazy-loaded', $gridField->extraClass()); } public function testGetHTMLFragmentsWithoutTabSet() @@ -98,8 +98,8 @@ public function testGetHTMLFragmentsWithoutTabSet() $gridField = $this->getOutOfTabSetGridField(); $actual = $this->component->getHTMLFragments($gridField); $this->assertEmpty($actual, 'getHTMLFragments should always return an array'); - $this->assertContains('grid-field--lazy-loaded', $gridField->extraClass()); - $this->assertNotContains('grid-field--lazy-loadable', $gridField->extraClass()); + $this->assertStringContainsString('grid-field--lazy-loaded', $gridField->extraClass()); + $this->assertStringNotContainsString('grid-field--lazy-loadable', $gridField->extraClass()); } public function testGetHTMLFragmentsNonLazy() @@ -107,8 +107,8 @@ public function testGetHTMLFragmentsNonLazy() $gridField = $this->getNonLazyGridField(); $actual = $this->component->getHTMLFragments($gridField); $this->assertEmpty($actual, 'getHTMLFragments should always return an array'); - $this->assertContains('grid-field--lazy-loaded', $gridField->extraClass()); - $this->assertNotContains('grid-field--lazy-loadable', $gridField->extraClass()); + $this->assertStringContainsString('grid-field--lazy-loaded', $gridField->extraClass()); + $this->assertStringNotContainsString('grid-field--lazy-loadable', $gridField->extraClass()); } @@ -150,8 +150,8 @@ public function testReadOnlyGetHTMLFragmentsWithoutHeader() $gridField = $this->makeGridFieldReadonly($this->getHeaderlessGridField()); $actual = $this->component->getHTMLFragments($gridField); $this->assertEmpty($actual, 'getHTMLFragments should always return an array'); - $this->assertContains('grid-field--lazy-loadable', $gridField->extraClass()); - $this->assertNotContains('grid-field--lazy-loaded', $gridField->extraClass()); + $this->assertStringContainsString('grid-field--lazy-loadable', $gridField->extraClass()); + $this->assertStringNotContainsString('grid-field--lazy-loaded', $gridField->extraClass()); } public function testReadOnlyGetHTMLFragmentsWithoutTabSet() @@ -159,8 +159,8 @@ public function testReadOnlyGetHTMLFragmentsWithoutTabSet() $gridField = $this->makeGridFieldReadonly($this->getOutOfTabSetGridField()); $actual = $this->component->getHTMLFragments($gridField); $this->assertEmpty($actual, 'getHTMLFragments should always return an array'); - $this->assertContains('grid-field--lazy-loaded', $gridField->extraClass()); - $this->assertNotContains('grid-field--lazy-loadable', $gridField->extraClass()); + $this->assertStringContainsString('grid-field--lazy-loaded', $gridField->extraClass()); + $this->assertStringNotContainsString('grid-field--lazy-loadable', $gridField->extraClass()); } public function testReadOnlyGetHTMLFragmentsNonLazy() @@ -168,8 +168,8 @@ public function testReadOnlyGetHTMLFragmentsNonLazy() $gridField = $this->makeGridFieldReadonly($this->getNonLazyGridField()); $actual = $this->component->getHTMLFragments($gridField); $this->assertEmpty($actual, 'getHTMLFragments should always return an array'); - $this->assertContains('grid-field--lazy-loaded', $gridField->extraClass()); - $this->assertNotContains('grid-field--lazy-loadable', $gridField->extraClass()); + $this->assertStringContainsString('grid-field--lazy-loaded', $gridField->extraClass()); + $this->assertStringNotContainsString('grid-field--lazy-loadable', $gridField->extraClass()); } /** diff --git a/tests/php/Forms/GridField/GridFieldPaginatorTest.php b/tests/php/Forms/GridField/GridFieldPaginatorTest.php index f892d421d43..4504143c62e 100644 --- a/tests/php/Forms/GridField/GridFieldPaginatorTest.php +++ b/tests/php/Forms/GridField/GridFieldPaginatorTest.php @@ -49,7 +49,7 @@ class GridFieldPaginatorTest extends FunctionalTest Cheerleader::class, ]; - protected function setUp() + protected function setUp(): void { parent::setUp(); $this->list = new DataList(Team::class); diff --git a/tests/php/Forms/GridField/GridFieldPrintButtonTest.php b/tests/php/Forms/GridField/GridFieldPrintButtonTest.php index d428a80d35d..59e73a494ca 100644 --- a/tests/php/Forms/GridField/GridFieldPrintButtonTest.php +++ b/tests/php/Forms/GridField/GridFieldPrintButtonTest.php @@ -19,7 +19,7 @@ class GridFieldPrintButtonTest extends SapphireTest TestObject::class, ]; - protected function setUp() + protected function setUp(): void { parent::setUp(); diff --git a/tests/php/Forms/GridField/GridFieldSortableHeaderTest.php b/tests/php/Forms/GridField/GridFieldSortableHeaderTest.php index 3b58d0797a6..5973f1589a3 100644 --- a/tests/php/Forms/GridField/GridFieldSortableHeaderTest.php +++ b/tests/php/Forms/GridField/GridFieldSortableHeaderTest.php @@ -47,23 +47,23 @@ public function testRenderHeaders() $htmlFragment = $compontent->getHTMLFragments($gridField); // Check that the output shows name and hat as sortable fields, but not city - $this->assertContains('City', $htmlFragment['header']); - $this->assertContains( + $this->assertStringContainsString('City', $htmlFragment['header']); + $this->assertStringContainsString( 'value="Name" class="action grid-field__sort" id="action_SetOrderName"', $htmlFragment['header'] ); - $this->assertContains( + $this->assertStringContainsString( 'value="Cheerleader Hat" class="action grid-field__sort" id="action_SetOrderCheerleader-Hat-Colour"', $htmlFragment['header'] ); // Check inverse of above - $this->assertNotContains( + $this->assertStringNotContainsString( 'value="City" class="action grid-field__sort" id="action_SetOrderCity"', $htmlFragment['header'] ); - $this->assertNotContains('Name', $htmlFragment['header']); - $this->assertNotContains('Cheerleader Hat', $htmlFragment['header']); + $this->assertStringNotContainsString('Name', $htmlFragment['header']); + $this->assertStringNotContainsString('Cheerleader Hat', $htmlFragment['header']); } public function testGetManipulatedData() @@ -145,20 +145,20 @@ public function testInheritedGetManiplatedData() $relationListAsql = Convert::nl2os($relationListA->sql(), ' '); // Assert that all tables are joined properly - $this->assertContains('FROM "GridFieldSortableHeaderTest_Team"', $relationListAsql); - $this->assertContains( + $this->assertStringContainsString('FROM "GridFieldSortableHeaderTest_Team"', $relationListAsql); + $this->assertStringContainsString( 'LEFT JOIN "GridFieldSortableHeaderTest_TeamGroup" ' . 'ON "GridFieldSortableHeaderTest_TeamGroup"."ID" = "GridFieldSortableHeaderTest_Team"."ID"', $relationListAsql ); - $this->assertContains( + $this->assertStringContainsString( 'LEFT JOIN "GridFieldSortableHeaderTest_Cheerleader" ' . 'AS "cheerleader_GridFieldSortableHeaderTest_Cheerleader" ' . 'ON "cheerleader_GridFieldSortableHeaderTest_Cheerleader"."ID" = ' . '"GridFieldSortableHeaderTest_Team"."CheerleaderID"', $relationListAsql ); - $this->assertContains( + $this->assertStringContainsString( 'LEFT JOIN "GridFieldSortableHeaderTest_CheerleaderHat" ' . 'AS "cheerleader_hat_GridFieldSortableHeaderTest_CheerleaderHat" ' . 'ON "cheerleader_hat_GridFieldSortableHeaderTest_CheerleaderHat"."ID" = ' @@ -185,15 +185,15 @@ public function testInheritedGetManiplatedData() $relationListBsql = $relationListB->sql(); // Assert that subclasses are included in the query - $this->assertContains('FROM "GridFieldSortableHeaderTest_Team"', $relationListBsql); - $this->assertContains( + $this->assertStringContainsString('FROM "GridFieldSortableHeaderTest_Team"', $relationListBsql); + $this->assertStringContainsString( 'LEFT JOIN "GridFieldSortableHeaderTest_TeamGroup" ' . 'ON "GridFieldSortableHeaderTest_TeamGroup"."ID" = "GridFieldSortableHeaderTest_Team"."ID"', $relationListBsql ); // Joined tables are joined basetable first // Note: CheerLeader is base of Mom table, hence the alias - $this->assertContains( + $this->assertStringContainsString( 'LEFT JOIN "GridFieldSortableHeaderTest_Cheerleader" ' . 'AS "cheerleadersmom_GridFieldSortableHeaderTest_Cheerleader" ' . 'ON "cheerleadersmom_GridFieldSortableHeaderTest_Cheerleader"."ID" = ' @@ -201,14 +201,14 @@ public function testInheritedGetManiplatedData() $relationListBsql ); // Then the basetable of the joined record is joined to the specific subtable - $this->assertContains( + $this->assertStringContainsString( 'LEFT JOIN "GridFieldSortableHeaderTest_Mom" ' . 'AS "cheerleadersmom_GridFieldSortableHeaderTest_Mom" ' . 'ON "cheerleadersmom_GridFieldSortableHeaderTest_Cheerleader"."ID" = ' . '"cheerleadersmom_GridFieldSortableHeaderTest_Mom"."ID"', $relationListBsql ); - $this->assertContains( + $this->assertStringContainsString( 'LEFT JOIN "GridFieldSortableHeaderTest_CheerleaderHat" ' . 'AS "cheerleadersmom_hat_GridFieldSortableHeaderTest_CheerleaderHat" ' . 'ON "cheerleadersmom_hat_GridFieldSortableHeaderTest_CheerleaderHat"."ID" = ' diff --git a/tests/php/Forms/GridField/GridFieldTest.php b/tests/php/Forms/GridField/GridFieldTest.php index ee82cfd0e2e..fc4fb8de42b 100644 --- a/tests/php/Forms/GridField/GridFieldTest.php +++ b/tests/php/Forms/GridField/GridFieldTest.php @@ -2,6 +2,8 @@ namespace SilverStripe\Forms\Tests\GridField; +use InvalidArgumentException; +use LogicException; use SilverStripe\Dev\CSSContentParser; use SilverStripe\Dev\SapphireTest; use SilverStripe\Forms\FieldList; @@ -135,11 +137,10 @@ public function testGridFieldModelClass() /** * @covers \SilverStripe\Forms\GridField\GridField::getModelClass - * - * @expectedException \LogicException */ public function testGridFieldModelClassThrowsException() { + $this->expectException(\LogicException::class); $obj = new GridField('testfield', 'testfield', ArrayList::create()); $obj->getModelClass(); } @@ -260,11 +261,10 @@ public function testGetColumnContent() /** * @skipUpgrade * @covers \SilverStripe\Forms\GridField\GridField::getColumnContent - * - * @expectedException \InvalidArgumentException */ public function testGetColumnContentBadArguments() { + $this->expectException(\InvalidArgumentException::class); $list = new ArrayList( [ new Member(["ID" => 1, "Email" => "test@example.org"]) @@ -307,11 +307,10 @@ public function testGetColumnAttributes() /** * @covers \SilverStripe\Forms\GridField\GridField::getColumnAttributes - * - * @expectedException \InvalidArgumentException */ public function testGetColumnAttributesBadArguments() { + $this->expectException(\InvalidArgumentException::class); $list = new ArrayList( [ new Member(["ID" => 1, "Email" => "test@example.org"]) @@ -322,11 +321,9 @@ public function testGetColumnAttributesBadArguments() $obj->getColumnAttributes($list->first(), 'Non-existing'); } - /** - * @expectedException \LogicException - */ public function testGetColumnAttributesBadResponseFromComponent() { + $this->expectException(\LogicException::class); $list = new ArrayList( [ new Member(["ID" => 1, "Email" => "test@example.org"]) @@ -355,11 +352,10 @@ public function testGetColumnMetadata() /** * @covers \SilverStripe\Forms\GridField\GridField::getColumnMetadata - * - * @expectedException \LogicException */ public function testGetColumnMetadataBadResponseFromComponent() { + $this->expectException(\LogicException::class); $list = new ArrayList( [ new Member(["ID" => 1, "Email" => "test@example.org"]) @@ -372,11 +368,10 @@ public function testGetColumnMetadataBadResponseFromComponent() /** * @covers \SilverStripe\Forms\GridField\GridField::getColumnMetadata - * - * @expectedException \InvalidArgumentException */ public function testGetColumnMetadataBadArguments() { + $this->expectException(\InvalidArgumentException::class); $list = ArrayList::create(); $config = GridFieldConfig::create()->addComponent(new Component); $obj = new GridField('testfield', 'testfield', $list, $config); @@ -385,11 +380,10 @@ public function testGetColumnMetadataBadArguments() /** * @covers \SilverStripe\Forms\GridField\GridField::handleAction - * - * @expectedException \InvalidArgumentException */ public function testHandleActionBadArgument() { + $this->expectException(\InvalidArgumentException::class); $obj = new GridField('testfield', 'testfield'); $obj->handleAlterAction('prft', [], []); } @@ -482,7 +476,7 @@ public function testGridFieldCustomFragments() $field = new GridField('testfield', 'testfield', ArrayList::create(), $config); $form = new Form(null, 'testform', new FieldList([$field]), new FieldList()); - $this->assertContains( + $this->assertStringContainsString( "
rightone\nrighttwo
left
", $field->FieldHolder() ); @@ -518,7 +512,7 @@ public function testGridFieldCustomFragmentsNesting() $field = new GridField('testfield', 'testfield', ArrayList::create(), $config); $form = new Form(null, 'testform', new FieldList([$field]), new FieldList()); - $this->assertContains( + $this->assertStringContainsString( "
first\nsecond
", $field->FieldHolder() ); @@ -526,11 +520,10 @@ public function testGridFieldCustomFragmentsNesting() /** * Test that circular dependencies throw an exception - * - * @expectedException \LogicException */ public function testGridFieldCustomFragmentsCircularDependencyThrowsException() { + $this->expectException(\LogicException::class); $config = GridFieldConfig::create()->addComponents( new HTMLFragments( [ diff --git a/tests/php/Forms/GroupedDropdownFieldTest.php b/tests/php/Forms/GroupedDropdownFieldTest.php index 68b4a2b72ec..ccd06f7f50d 100644 --- a/tests/php/Forms/GroupedDropdownFieldTest.php +++ b/tests/php/Forms/GroupedDropdownFieldTest.php @@ -82,7 +82,7 @@ public function testEmptyString() ] ); - $this->assertRegExp( + $this->assertMatchesRegularExpression( '/