From 0532baa45d74447d9add97b9c4fe7efa18303860 Mon Sep 17 00:00:00 2001 From: Michael Bodnarchuk Date: Mon, 26 Feb 2018 20:30:54 +0200 Subject: [PATCH 001/395] Phpunit wrapper (#4817) * changed build process for phar * Switched to use phpunit-wrapper * loading shim * fixed REST * Switched to use phpunit-wrapper * Fixed tests * Switched to use phpunit-wrapper * Fixed zend expressive - to not install dev deps * Switched to use phpunit-wrapper * no dev dependencies for project * Fixed laravel event tests * fixed Laravel event mocking * Removed PHP 5.4 and PHP 5.5 tests from Travis CI --- .travis.yml | 66 +- autoload.php | 20 - composer.json | 6 +- phpunit5-loggers.php | 589 ------------------ shim.php | 119 +--- src/Codeception/Codecept.php | 6 +- src/Codeception/Command/Console.php | 2 +- src/Codeception/Command/DryRun.php | 2 +- src/Codeception/Command/Run.php | 2 +- src/Codeception/Configuration.php | 4 +- .../Coverage/DummyCodeCoverage.php | 13 - src/Codeception/Coverage/Filter.php | 16 +- .../Coverage/Subscriber/Printer.php | 20 +- src/Codeception/Coverage/SuiteSubscriber.php | 12 +- src/Codeception/Event/FailEvent.php | 2 +- src/Codeception/Event/PrintResultEvent.php | 10 +- src/Codeception/Event/SuiteEvent.php | 10 +- src/Codeception/Event/TestEvent.php | 4 +- src/Codeception/Example.php | 2 +- .../Exception/ConditionalAssertionFailed.php | 2 +- src/Codeception/Exception/ContentNotFound.php | 2 +- src/Codeception/Exception/ElementNotFound.php | 2 +- src/Codeception/Exception/Fail.php | 2 +- src/Codeception/Exception/Incomplete.php | 2 +- src/Codeception/Exception/Skip.php | 2 +- src/Codeception/Lib/Connector/Laravel5.php | 10 +- src/Codeception/Lib/Connector/ZF2.php | 2 +- src/Codeception/Lib/Driver/Beanstalk.php | 4 +- src/Codeception/Lib/Driver/Iron.php | 8 +- src/Codeception/Lib/GroupManager.php | 12 +- src/Codeception/Lib/InnerBrowser.php | 4 +- src/Codeception/Module/Cli.php | 10 +- src/Codeception/Module/Filesystem.php | 16 +- src/Codeception/Module/MongoDb.php | 14 +- src/Codeception/Module/REST.php | 20 +- src/Codeception/Module/SOAP.php | 2 +- src/Codeception/Module/WebDriver.php | 4 +- src/Codeception/Module/XMLRPC.php | 4 +- src/Codeception/Module/ZendExpressive.php | 2 +- src/Codeception/PHPUnit/ConsolePrinter.php | 15 - .../PHPUnit/Constraint/Crawler.php | 74 --- .../PHPUnit/Constraint/CrawlerNot.php | 40 -- .../PHPUnit/Constraint/JsonContains.php | 70 --- .../PHPUnit/Constraint/JsonType.php | 64 -- src/Codeception/PHPUnit/Constraint/Page.php | 80 --- .../PHPUnit/Constraint/WebDriver.php | 79 --- .../PHPUnit/Constraint/WebDriverNot.php | 41 -- src/Codeception/PHPUnit/FilterTest.php | 31 - src/Codeception/PHPUnit/Listener.php | 133 ---- src/Codeception/PHPUnit/Log/JUnit.php | 43 -- src/Codeception/PHPUnit/Overrides/Filter.php | 117 ---- src/Codeception/PHPUnit/README.md | 4 - src/Codeception/PHPUnit/ResultPrinter.php | 83 --- .../PHPUnit/ResultPrinter/HTML.php | 303 --------- .../PHPUnit/ResultPrinter/Report.php | 58 -- src/Codeception/PHPUnit/ResultPrinter/UI.php | 95 --- .../ResultPrinter/template/fail.html.dist | 5 - .../ResultPrinter/template/scenario.html.dist | 22 - .../template/scenario_header.html.dist | 2 - .../template/scenarios.html.dist | 250 -------- .../ResultPrinter/template/step.html.dist | 4 - .../ResultPrinter/template/substeps.html.dist | 12 - .../ResultPrinter/template/suite.html.dist | 5 - src/Codeception/PHPUnit/Runner.php | 184 ------ src/Codeception/README.md | 2 +- src/Codeception/Scenario.php | 4 +- src/Codeception/Step/ConditionalAssertion.php | 2 +- src/Codeception/Step/Incomplete.php | 2 +- src/Codeception/Step/Skip.php | 2 +- .../Subscriber/BeforeAfterTest.php | 8 +- src/Codeception/Subscriber/Console.php | 24 +- src/Codeception/Subscriber/ErrorHandler.php | 4 +- src/Codeception/Suite.php | 2 +- src/Codeception/SuiteManager.php | 6 +- src/Codeception/Test/Cest.php | 8 +- src/Codeception/Test/Descriptor.php | 24 +- .../Test/Feature/AssertionCounter.php | 4 +- src/Codeception/Test/Feature/CodeCoverage.php | 2 +- src/Codeception/Test/Feature/ErrorLogger.php | 2 +- .../Test/Feature/IgnoreIfMetadataBlocked.php | 6 +- .../Test/Interfaces/Descriptive.php | 2 +- src/Codeception/Test/Loader/Cest.php | 2 +- src/Codeception/Test/Loader/Unit.php | 10 +- src/Codeception/Test/Test.php | 20 +- src/Codeception/Test/Unit.php | 2 +- src/Codeception/TestInterface.php | 2 +- src/Codeception/Util/Shared/Asserts.php | 78 +-- tests/cli/RunCest.php | 17 +- ...estIsExecutedWhenTheFirstTestFailsCest.php | 3 + tests/cli/UnitCept.php | 2 +- tests/data/SimpleTest.php | 2 +- tests/data/app/db | 2 +- tests/data/claypit/c3.php | 86 ++- tests/data/claypit/composer.json | 2 +- tests/data/claypit/composer.lock | 26 +- tests/data/claypit/tests/_bootstrap.php | 5 +- .../claypit/tests/_data/MyReportPrinter.php | 12 +- .../data/claypit/tests/dummy/AnotherTest.php | 2 +- .../claypit/tests/order/ParsedLoadedTest.php | 2 +- .../data/claypit/tests/unit/ExceptionTest.php | 2 +- tests/data/claypit/tests/unit/FailingTest.php | 2 +- .../tests/_support/CustomReporter.php | 6 +- .../pianist/tests/_helpers/TestHelper.php | 2 +- .../jazz/tests/_helpers/TestHelper.php | 2 +- .../included_mix/tests/unit/SimpleTest.php | 2 +- tests/data/php55Test | 2 +- tests/data/php70Test | 2 +- tests/data/sqlite.db | Bin 36864 -> 0 bytes tests/facebook/FacebookTest.php | 2 +- tests/unit/C3Test.php | 2 +- tests/unit/Codeception/ApplicationTest.php | 2 +- .../Codeception/Command/BaseCommandRunner.php | 2 +- .../Command/MyCustomCommandTest.php | 2 +- tests/unit/Codeception/ConfigurationTest.php | 2 +- .../Constraints/CrawlerConstraintTest.php | 8 +- .../Constraints/CrawlerNotConstraintTest.php | 8 +- .../Constraints/WebDriverConstraintTest.php | 10 +- .../WebDriverNotConstraintTest.php | 10 +- .../unit/Codeception/Coverage/FilterTest.php | 41 +- .../Exception/ModuleConfigTest.php | 2 +- tests/unit/Codeception/Module/AMQPTest.php | 2 +- tests/unit/Codeception/Module/AssertsTest.php | 4 +- .../Codeception/Module/BeanstalkdTest.php | 2 +- tests/unit/Codeception/Module/FTPTest.php | 2 +- .../Codeception/Module/FilesystemTest.php | 12 +- .../Codeception/Module/FrameworksTest.php | 4 +- .../Codeception/Module/MongoDbLegacyTest.php | 6 +- tests/unit/Codeception/Module/MongoDbTest.php | 4 +- .../Codeception/Module/PhpBrowserRestTest.php | 6 +- .../Codeception/Module/PhpBrowserTest.php | 2 +- tests/unit/Codeception/Module/RedisTest.php | 2 +- tests/unit/Codeception/Module/RestTest.php | 10 +- tests/unit/Codeception/Module/SFTPTest.php | 2 +- tests/unit/Codeception/Module/SoapTest.php | 2 +- tests/unit/Codeception/Module/TestsForWeb.php | 22 +- tests/unit/Codeception/ModuleTest.php | 2 +- tests/unit/Codeception/ScenarioTest.php | 2 +- .../Step/ConditionalAssertionTest.php | 2 +- tests/unit/Codeception/Step/ExecutorTest.php | 2 +- tests/unit/Codeception/StepTest.php | 2 +- .../Subscriber/ErrorHandlerTest.php | 2 +- tests/unit/Codeception/SuiteManagerTest.php | 8 +- tests/unit/Codeception/TestLoaderTest.php | 2 +- .../unit/Codeception/Util/AnnotationTest.php | 2 +- tests/unit/Codeception/Util/AutoloadTest.php | 2 +- tests/unit/Codeception/Util/LocatorTest.php | 2 +- tests/unit/Codeception/Util/StubTest.php | 4 +- tests/unit/Codeception/Util/TemplateTest.php | 2 +- 148 files changed, 479 insertions(+), 2970 deletions(-) delete mode 100644 phpunit5-loggers.php delete mode 100644 src/Codeception/Coverage/DummyCodeCoverage.php delete mode 100644 src/Codeception/PHPUnit/ConsolePrinter.php delete mode 100644 src/Codeception/PHPUnit/Constraint/Crawler.php delete mode 100644 src/Codeception/PHPUnit/Constraint/CrawlerNot.php delete mode 100644 src/Codeception/PHPUnit/Constraint/JsonContains.php delete mode 100644 src/Codeception/PHPUnit/Constraint/JsonType.php delete mode 100644 src/Codeception/PHPUnit/Constraint/Page.php delete mode 100644 src/Codeception/PHPUnit/Constraint/WebDriver.php delete mode 100644 src/Codeception/PHPUnit/Constraint/WebDriverNot.php delete mode 100644 src/Codeception/PHPUnit/FilterTest.php delete mode 100644 src/Codeception/PHPUnit/Listener.php delete mode 100644 src/Codeception/PHPUnit/Log/JUnit.php delete mode 100644 src/Codeception/PHPUnit/Overrides/Filter.php delete mode 100644 src/Codeception/PHPUnit/README.md delete mode 100644 src/Codeception/PHPUnit/ResultPrinter.php delete mode 100644 src/Codeception/PHPUnit/ResultPrinter/HTML.php delete mode 100644 src/Codeception/PHPUnit/ResultPrinter/Report.php delete mode 100644 src/Codeception/PHPUnit/ResultPrinter/UI.php delete mode 100644 src/Codeception/PHPUnit/ResultPrinter/template/fail.html.dist delete mode 100644 src/Codeception/PHPUnit/ResultPrinter/template/scenario.html.dist delete mode 100644 src/Codeception/PHPUnit/ResultPrinter/template/scenario_header.html.dist delete mode 100644 src/Codeception/PHPUnit/ResultPrinter/template/scenarios.html.dist delete mode 100644 src/Codeception/PHPUnit/ResultPrinter/template/step.html.dist delete mode 100644 src/Codeception/PHPUnit/ResultPrinter/template/substeps.html.dist delete mode 100644 src/Codeception/PHPUnit/ResultPrinter/template/suite.html.dist delete mode 100644 src/Codeception/PHPUnit/Runner.php diff --git a/.travis.yml b/.travis.yml index 7a01d998dd..fe5d526213 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,10 +4,6 @@ language: php matrix: include: - - php: 5.4 # lowest versions of all dependencies - env: SYMFONY=2.7.19 SYMFONY_DEPRECATIONS_HELPER=weak # latest version of 2.7.* - - php: 5.5 - env: SYMFONY=2.7.19 SYMFONY_DEPRECATIONS_HELPER=weak #latest version of 2.7.* - php: 5.6 env: SYMFONY=2.8.12 SYMFONY_DEPRECATIONS_HELPER=weak # latest version of 2.8.* - php: 7.0 @@ -39,12 +35,12 @@ services: install: - export SF_VERSION=$(echo $SYMFONY | head -c 1) - - '[[ "$TRAVIS_PHP_VERSION" == "5.4" ]] || pecl install -f mongodb' + - 'pecl install -f mongodb' - yes '' | pecl install imagick #- echo "extension = mongodb.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini - composer self-update && composer --version - if [ -n "$CI_USER_TOKEN" ]; then composer config github-oauth.github.com ${CI_USER_TOKEN}; echo "Configured Github token"; fi; - - '[[ "$TRAVIS_PHP_VERSION" == "5.4" ]] || composer require mongodb/mongodb --no-update' + - 'composer require mongodb/mongodb --no-update' - '[[ "$TRAVIS_PHP_VERSION" == "7.2" ]] || composer global require "fxp/composer-asset-plugin:~1.3.1"' - '[[ -z "$SYMFONY" ]] || composer require symfony/finder=~$SYMFONY --no-update --ignore-platform-reqs' - '[[ -z "$SYMFONY" ]] || composer require symfony/yaml=~$SYMFONY --no-update --ignore-platform-reqs' @@ -60,32 +56,32 @@ install: # Yii2 - '[[ "$TRAVIS_PHP_VERSION" == "7.2" ]] || composer create-project "yiisoft/yii2-app-basic" frameworks-yii-basic --no-dev' # Phalcon - - '[[ "$TRAVIS_PHP_VERSION" == "5.4" ]] || git clone -q --depth=1 https://github.com/phalcon/cphalcon.git' - - '[[ "$TRAVIS_PHP_VERSION" == "5.4" ]] || (cd cphalcon/build; bash ./install --phpize $(phpenv which phpize) --php-config $(phpenv which php-config) &>/dev/null && phpenv config-add ../tests/_ci/phalcon.ini &> /dev/null)' - - '[[ "$TRAVIS_PHP_VERSION" == "5.4" ]] || git clone -q --depth=1 https://github.com/Codeception/phalcon-demo.git frameworks-phalcon' - - '[[ "$TRAVIS_PHP_VERSION" == "5.4" ]] || composer update -d frameworks-phalcon $composer_parameters' + - 'git clone -q --depth=1 https://github.com/phalcon/cphalcon.git' + - '(cd cphalcon/build; bash ./install --phpize $(phpenv which phpize) --php-config $(phpenv which php-config) &>/dev/null && phpenv config-add ../tests/_ci/phalcon.ini &> /dev/null)' + - 'git clone -q --depth=1 https://github.com/Codeception/phalcon-demo.git frameworks-phalcon' + - 'composer update -d frameworks-phalcon $composer_parameters' # Laravel 5 - - '[[ "$TRAVIS_PHP_VERSION" == "5.4" ]] || [[ "$TRAVIS_PHP_VERSION" == "5.5" ]] || git clone -q --depth=1 -b codeception-2.3 https://github.com/codeception/codeception-laravel5-sample.git frameworks-l5' - - '[[ "$TRAVIS_PHP_VERSION" == "5.4" ]] || [[ "$TRAVIS_PHP_VERSION" == "5.5" ]] || composer update -d frameworks-l5 $composer_parameters' + - 'git clone -q --depth=1 -b codeception-2.3 https://github.com/codeception/codeception-laravel5-sample.git frameworks-l5' + - 'composer update -d frameworks-l5 $composer_parameters --no-dev' # Lumen - - '[[ "$TRAVIS_PHP_VERSION" == "5.4" ]] || [[ "$TRAVIS_PHP_VERSION" == "5.5" ]] || git clone -q --depth=1 -b codeception-2.2 https://github.com/codeception/codeception-lumen-sample.git frameworks-lumen' - - '[[ "$TRAVIS_PHP_VERSION" == "5.4" ]] || [[ "$TRAVIS_PHP_VERSION" == "5.5" ]] || composer update -d frameworks-lumen $composer_parameters' + - 'git clone -q --depth=1 -b codeception-2.2 https://github.com/codeception/codeception-lumen-sample.git frameworks-lumen' + - 'composer update -d frameworks-lumen $composer_parameters --no-dev' # Symfony - '[[ "$SF_VERSION" != "2" ]] || (git clone -q --depth=1 -b 2.1 https://github.com/Codeception/symfony-demo.git frameworks-symfony && echo "Cloned Symfony 2 site")' - '[[ "$SF_VERSION" != "3" ]] || (git clone -q --depth=1 -b master --recursive https://github.com/Naktibalda/codeception-symfony-tests frameworks-symfony && echo "Cloned Symfony 3 site")' - '[[ "$SF_VERSION" != "4" ]] || (git clone -q --depth=1 -b master https://github.com/Codeception/symfony-demo.git frameworks-symfony && echo "Cloned Symfony 4 site")' - '[[ "$SF_VERSION" == "4" ]] || composer require -d frameworks-symfony symfony/symfony=~$SYMFONY --no-update' - "mysql -e 'create database symfony_test;'" - - 'composer update -d frameworks-symfony $composer_parameters' + - 'composer update -d frameworks-symfony $composer_parameters --no-dev' # ZF1 - git clone -q -b 2.2 --recursive https://github.com/Naktibalda/codeception-zf1-tests frameworks-zf1 - - composer update -d frameworks-zf1 $composer_parameters + - composer update -d frameworks-zf1 $composer_parameters --no-dev # ZF2 - git clone -q -b 2.2 --recursive https://github.com/Naktibalda/codeception-zf2-tests frameworks-zf2 - - composer update -d frameworks-zf2 $composer_parameters + - composer update -d frameworks-zf2 $composer_parameters --no-dev # Zend Expressive - - '[[ "$TRAVIS_PHP_VERSION" == "5.4" ]] || [[ "$TRAVIS_PHP_VERSION" == "5.5" ]] || git clone -q -b 2.2 --recursive https://github.com/Naktibalda/codeception-zend-expressive-tests frameworks-zend-expressive' - - '[[ "$TRAVIS_PHP_VERSION" == "5.4" ]] || [[ "$TRAVIS_PHP_VERSION" == "5.5" ]] || composer update -d frameworks-zend-expressive $composer_parameters' + - 'git clone -q -b 2.2 --recursive https://github.com/Naktibalda/codeception-zend-expressive-tests frameworks-zend-expressive' + - 'composer update -d frameworks-zend-expressive $composer_parameters' before_script: - '[[ "$TRAVIS_PHP_VERSION" == 7.* ]] || echo "extension = mongo.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini' @@ -97,14 +93,14 @@ before_script: - 'php -S 127.0.0.1:8010 -t tests/data >/dev/null 2>&1 &' # Phalcon - mysql -e 'CREATE DATABASE phalcon_demo CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;' - - '[[ "$TRAVIS_PHP_VERSION" == "5.4" ]] || cat frameworks-phalcon/schemas/phalcon_demo.sql | mysql phalcon_demo' + - 'cat frameworks-phalcon/schemas/phalcon_demo.sql | mysql phalcon_demo' # Laravel 5 - - '[[ "$TRAVIS_PHP_VERSION" == "5.4" ]] || [[ "$TRAVIS_PHP_VERSION" == "5.5" ]] || touch frameworks-l5/storage/testing.sqlite' - - '[[ "$TRAVIS_PHP_VERSION" == "5.4" ]] || [[ "$TRAVIS_PHP_VERSION" == "5.5" ]] || php frameworks-l5/artisan migrate --env=testing --database=sqlite_testing --force' + - 'touch frameworks-l5/storage/testing.sqlite' + - 'php frameworks-l5/artisan migrate --env=testing --database=sqlite_testing --force' # Lumen - - '[[ "$TRAVIS_PHP_VERSION" == "5.4" ]] || [[ "$TRAVIS_PHP_VERSION" == "5.5" ]] || cp frameworks-lumen/.env.testing frameworks-lumen/.env' - - '[[ "$TRAVIS_PHP_VERSION" == "5.4" ]] || [[ "$TRAVIS_PHP_VERSION" == "5.5" ]] || touch frameworks-lumen/storage/testing.sqlite' - - '[[ "$TRAVIS_PHP_VERSION" == "5.4" ]] || [[ "$TRAVIS_PHP_VERSION" == "5.5" ]] || php frameworks-lumen/artisan migrate --database=testing --force' + - 'cp frameworks-lumen/.env.testing frameworks-lumen/.env' + - 'touch frameworks-lumen/storage/testing.sqlite' + - 'php frameworks-lumen/artisan migrate --database=testing --force' # Symfony - '[[ "$SF_VERSION" != "2" ]] || php frameworks-symfony/app/console doctrine:schema:create -n --env test' - '[[ "$SF_VERSION" != "2" ]] || php frameworks-symfony/app/console doctrine:fixtures:load -n --env test' @@ -114,27 +110,25 @@ before_script: - php frameworks-zf2/vendor/bin/doctrine-module orm:schema-tool:create # Build - '[[ "$TRAVIS_PHP_VERSION" == "7.2" ]] || php codecept build -c frameworks-yii-basic' - - '[[ "$TRAVIS_PHP_VERSION" == "5.4" ]] || php codecept build -c frameworks-phalcon' + - 'php codecept build -c frameworks-phalcon' - '[[ "$SF_VERSION" != "2" ]] || php codecept build -c frameworks-symfony/src/AppBundle' - '[[ "$SF_VERSION" == "2" ]] || php codecept build -c frameworks-symfony' - - '[[ "$TRAVIS_PHP_VERSION" == "5.4" ]] || [[ "$TRAVIS_PHP_VERSION" == "5.5" ]] || php codecept build -c frameworks-l5' - - '[[ "$TRAVIS_PHP_VERSION" == "5.4" ]] || [[ "$TRAVIS_PHP_VERSION" == "5.5" ]] || php codecept build -c frameworks-lumen' + - 'php codecept build -c frameworks-l5' + - 'php codecept build -c frameworks-lumen' - php codecept build -c frameworks-zf1 - php codecept build -c frameworks-zf2 - - '[[ "$TRAVIS_PHP_VERSION" == "5.4" ]] || [[ "$TRAVIS_PHP_VERSION" == "5.5" ]] || php codecept build -c frameworks-zend-expressive' + - 'php codecept build -c frameworks-zend-expressive' script: - php codecept run cli,unit # self tests - '[[ "$TRAVIS_PHP_VERSION" == "7.0" ]] || php codecept run coverage' # run coverage tests on php only - '[[ "$TRAVIS_PHP_VERSION" == "7.2" ]] || php codecept run functional -c frameworks-yii-basic' # Yii2 tests - - '[[ "$TRAVIS_PHP_VERSION" == "5.4" ]] || [[ "$TRAVIS_PHP_VERSION" == "5.5" ]] || php codecept run -c frameworks-l5 --skip=seeder' # Laravel5 Tests - - '[[ "$TRAVIS_PHP_VERSION" == "5.4" ]] || [[ "$TRAVIS_PHP_VERSION" == "5.5" ]] || php codecept run -c frameworks-lumen' # Lumen Tests - - '[[ "$TRAVIS_PHP_VERSION" == "5.4" ]] || php codecept run functional -c frameworks-phalcon' # Phalcon Tests + - 'php codecept run -c frameworks-l5 --skip=seeder' # Laravel5 Tests + - 'php codecept run -c frameworks-lumen' # Lumen Tests + - 'php codecept run functional -c frameworks-phalcon' # Phalcon Tests - '[[ "$SF_VERSION" != "2" ]] || php codecept run functional -c frameworks-symfony/src/AppBundle' # Symfony 2 Tests - '[[ "$SF_VERSION" != "3" ]] || php codecept run -c frameworks-symfony' # Symfony 3 Tests - '[[ "$SF_VERSION" != "4" ]] || php codecept run -c frameworks-symfony functional,unit' # Symfony 4 Tests - php codecept run functional -c frameworks-zf1 # ZF1 Tests - #ZF2 run doctrine tests on PHP 5.4 and 5.5 only - - '[[ "$TRAVIS_PHP_VERSION" > "5.5" ]] || php codecept run -c frameworks-zf2 functional,doctrine' - - '[[ "$TRAVIS_PHP_VERSION" < "5.6" ]] || php codecept run -c frameworks-zf2 functional' - - '[[ "$TRAVIS_PHP_VERSION" == "5.4" ]] || [[ "$TRAVIS_PHP_VERSION" == "5.5" ]] || php codecept run functional -c frameworks-zend-expressive' # Zend Expressive Tests + - 'php codecept run -c frameworks-zf2 functional' + - 'php codecept run functional -c frameworks-zend-expressive' # Zend Expressive Tests diff --git a/autoload.php b/autoload.php index 05b92f925d..61b67589d9 100644 --- a/autoload.php +++ b/autoload.php @@ -21,26 +21,6 @@ unset($autoloadFile); // @codingStandardsIgnoreStart -// loading WebDriver aliases -if (!class_exists('RemoteWebDriver') and class_exists('Facebook\WebDriver\Remote\RemoteWebDriver')) { - class RemoteWebDriver extends \Facebook\WebDriver\Remote\RemoteWebDriver {}; - class InvalidSelectorException extends Facebook\WebDriver\Exception\InvalidSelectorException {}; - class NoSuchElementException extends Facebook\WebDriver\Exception\NoSuchElementException {}; - class WebDriverCurlException extends Facebook\WebDriver\Exception\WebDriverCurlException {}; - class WebDriverActions extends Facebook\WebDriver\Interactions\WebDriverActions {}; - class LocalFileDetector extends Facebook\WebDriver\Remote\LocalFileDetector {}; - class WebDriverCapabilityType extends Facebook\WebDriver\Remote\WebDriverCapabilityType {}; - class WebDriverAlert extends Facebook\WebDriver\WebDriverAlert {}; - class WebDriverBy extends Facebook\WebDriver\WebDriverBy {}; - class WebDriverDimension extends Facebook\WebDriver\WebDriverDimension {}; - class RemoteWebElement extends Facebook\WebDriver\Remote\RemoteWebElement {}; - class WebDriverExpectedCondition extends Facebook\WebDriver\WebDriverExpectedCondition {}; - class WebDriverKeys extends Facebook\WebDriver\WebDriverKeys {}; - class WebDriverSelect extends Facebook\WebDriver\WebDriverSelect {}; - class WebDriverTimeouts extends Facebook\WebDriver\WebDriverTimeouts {}; - class WebDriverWindow extends Facebook\WebDriver\WebDriverWindow {}; - interface WebDriverElement extends Facebook\WebDriver\WebDriverElement {}; -} include_once __DIR__ . DIRECTORY_SEPARATOR . 'shim.php'; // compat diff --git a/composer.json b/composer.json index a6358b3c28..aff71e1210 100644 --- a/composer.json +++ b/composer.json @@ -18,8 +18,6 @@ "php": ">=5.4.0 <8.0", "ext-json": "*", "ext-mbstring": "*", - "phpunit/phpunit": ">=4.8.28 <5.0.0 || >=5.6.3 <8.0", - "phpunit/php-code-coverage": ">=2.2.4 <6.0", "facebook/webdriver": ">=1.1.3 <2.0", "guzzlehttp/guzzle": ">=4.1.4 <7.0", "guzzlehttp/psr7": "~1.0", @@ -31,9 +29,9 @@ "symfony/css-selector": ">=2.7 <5.0", "symfony/dom-crawler": ">=2.7 <5.0", "behat/gherkin": "~4.4.0", - "sebastian/comparator": ">1.1 <3.0", - "sebastian/diff": ">=1.4 <3.0", + "codeception/phpunit-wrapper": "^6.0|^7.0", "codeception/stub": "^1.0" + }, "require-dev": { "monolog/monolog": "~1.8", diff --git a/phpunit5-loggers.php b/phpunit5-loggers.php deleted file mode 100644 index 30bbcd1e48..0000000000 --- a/phpunit5-loggers.php +++ /dev/null @@ -1,589 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - - if (!class_exists('PHPUnit_Util_String')) { - /** - * String helpers. - */ - class PHPUnit_Util_String - { - /** - * Converts a string to UTF-8 encoding. - * - * @param string $string - * - * @return string - */ - public static function convertToUtf8($string) - { - return mb_convert_encoding($string, 'UTF-8'); - } - - /** - * Checks a string for UTF-8 encoding. - * - * @param string $string - * - * @return bool - */ - protected static function isUtf8($string) - { - $length = strlen($string); - - for ($i = 0; $i < $length; $i++) { - if (ord($string[$i]) < 0x80) { - $n = 0; - } elseif ((ord($string[$i]) & 0xE0) == 0xC0) { - $n = 1; - } elseif ((ord($string[$i]) & 0xF0) == 0xE0) { - $n = 2; - } elseif ((ord($string[$i]) & 0xF0) == 0xF0) { - $n = 3; - } else { - return false; - } - - for ($j = 0; $j < $n; $j++) { - if ((++$i == $length) || ((ord($string[$i]) & 0xC0) != 0x80)) { - return false; - } - } - } - - return true; - } - } - } - - /* - * This file is part of PHPUnit. - * - * (c) Sebastian Bergmann - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - - /** - * A TestListener that generates JSON messages. - */ - if (!class_exists('PHPUnit_Util_Log_JSON')) { - class PHPUnit_Util_Log_JSON extends PHPUnit_Util_Printer implements PHPUnit_Framework_TestListener - { - /** - * @var string - */ - protected $currentTestSuiteName = ''; - - /** - * @var string - */ - protected $currentTestName = ''; - - /** - * @var bool - */ - protected $currentTestPass = true; - - /** - * An error occurred. - * - * @param PHPUnit_Framework_Test $test - * @param Exception $e - * @param float $time - */ - public function addError(PHPUnit_Framework_Test $test, Exception $e, $time) - { - $this->writeCase( - 'error', - $time, - PHPUnit_Util_Filter::getFilteredStacktrace($e, false), - PHPUnit_Framework_TestFailure::exceptionToString($e), - $test - ); - - $this->currentTestPass = false; - } - - /** - * A warning occurred. - * - * @param PHPUnit_Framework_Test $test - * @param PHPUnit_Framework_Warning $e - * @param float $time - */ - public function addWarning(PHPUnit_Framework_Test $test, PHPUnit_Framework_Warning $e, $time) - { - $this->writeCase( - 'warning', - $time, - PHPUnit_Util_Filter::getFilteredStacktrace($e, false), - PHPUnit_Framework_TestFailure::exceptionToString($e), - $test - ); - - $this->currentTestPass = false; - } - - /** - * A failure occurred. - * - * @param PHPUnit_Framework_Test $test - * @param PHPUnit_Framework_AssertionFailedError $e - * @param float $time - */ - public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time) - { - $this->writeCase( - 'fail', - $time, - PHPUnit_Util_Filter::getFilteredStacktrace($e, false), - PHPUnit_Framework_TestFailure::exceptionToString($e), - $test - ); - - $this->currentTestPass = false; - } - - /** - * Incomplete test. - * - * @param PHPUnit_Framework_Test $test - * @param Exception $e - * @param float $time - */ - public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time) - { - $this->writeCase( - 'error', - $time, - PHPUnit_Util_Filter::getFilteredStacktrace($e, false), - 'Incomplete Test: ' . $e->getMessage(), - $test - ); - - $this->currentTestPass = false; - } - - /** - * Risky test. - * - * @param PHPUnit_Framework_Test $test - * @param Exception $e - * @param float $time - */ - public function addRiskyTest(PHPUnit_Framework_Test $test, Exception $e, $time) - { - $this->writeCase( - 'error', - $time, - PHPUnit_Util_Filter::getFilteredStacktrace($e, false), - 'Risky Test: ' . $e->getMessage(), - $test - ); - - $this->currentTestPass = false; - } - - /** - * Skipped test. - * - * @param PHPUnit_Framework_Test $test - * @param Exception $e - * @param float $time - */ - public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time) - { - $this->writeCase( - 'error', - $time, - PHPUnit_Util_Filter::getFilteredStacktrace($e, false), - 'Skipped Test: ' . $e->getMessage(), - $test - ); - - $this->currentTestPass = false; - } - - /** - * A testsuite started. - * - * @param PHPUnit_Framework_TestSuite $suite - */ - public function startTestSuite(PHPUnit_Framework_TestSuite $suite) - { - $this->currentTestSuiteName = $suite->getName(); - $this->currentTestName = ''; - - $this->write( - [ - 'event' => 'suiteStart', - 'suite' => $this->currentTestSuiteName, - 'tests' => count($suite) - ] - ); - } - - /** - * A testsuite ended. - * - * @param PHPUnit_Framework_TestSuite $suite - */ - public function endTestSuite(PHPUnit_Framework_TestSuite $suite) - { - $this->currentTestSuiteName = ''; - $this->currentTestName = ''; - } - - /** - * A test started. - * - * @param PHPUnit_Framework_Test $test - */ - public function startTest(PHPUnit_Framework_Test $test) - { - $this->currentTestName = PHPUnit_Util_Test::describe($test); - $this->currentTestPass = true; - - $this->write( - [ - 'event' => 'testStart', - 'suite' => $this->currentTestSuiteName, - 'test' => $this->currentTestName - ] - ); - } - - /** - * A test ended. - * - * @param PHPUnit_Framework_Test $test - * @param float $time - */ - public function endTest(PHPUnit_Framework_Test $test, $time) - { - if ($this->currentTestPass) { - $this->writeCase('pass', $time, [], '', $test); - } - } - - /** - * @param string $status - * @param float $time - * @param array $trace - * @param string $message - * @param PHPUnit_Framework_TestCase|null $test - */ - protected function writeCase($status, $time, array $trace = [], $message = '', $test = null) - { - $output = ''; - // take care of TestSuite producing error (e.g. by running into exception) as TestSuite doesn't have hasOutput - if ($test !== null && method_exists($test, 'hasOutput') && $test->hasOutput()) { - $output = $test->getActualOutput(); - } - $this->write( - [ - 'event' => 'test', - 'suite' => $this->currentTestSuiteName, - 'test' => $this->currentTestName, - 'status' => $status, - 'time' => $time, - 'trace' => $trace, - 'message' => PHPUnit_Util_String::convertToUtf8($message), - 'output' => $output, - ] - ); - } - - /** - * @param string $buffer - */ - public function write($buffer) - { - array_walk_recursive( - $buffer, function (&$input) { - if (is_string($input)) { - $input = PHPUnit_Util_String::convertToUtf8($input); - } - } - ); - - parent::write(json_encode($buffer, JSON_PRETTY_PRINT)); - } - } - } - - /* - * This file is part of PHPUnit. - * - * (c) Sebastian Bergmann - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - - if (!class_exists('PHPUnit_Util_Log_TAP')) { - - /** - * A TestListener that generates a logfile of the - * test execution using the Test Anything Protocol (TAP). - */ - class PHPUnit_Util_Log_TAP extends PHPUnit_Util_Printer implements PHPUnit_Framework_TestListener - { - /** - * @var int - */ - protected $testNumber = 0; - - /** - * @var int - */ - protected $testSuiteLevel = 0; - - /** - * @var bool - */ - protected $testSuccessful = true; - - /** - * Constructor. - * - * @param mixed $out - * - * @throws PHPUnit_Framework_Exception - */ - public function __construct($out = null) - { - parent::__construct($out); - $this->write("TAP version 13\n"); - } - - /** - * An error occurred. - * - * @param PHPUnit_Framework_Test $test - * @param Exception $e - * @param float $time - */ - public function addError(PHPUnit_Framework_Test $test, Exception $e, $time) - { - $this->writeNotOk($test, 'Error'); - } - - /** - * A warning occurred. - * - * @param PHPUnit_Framework_Test $test - * @param PHPUnit_Framework_Warning $e - * @param float $time - */ - public function addWarning(PHPUnit_Framework_Test $test, PHPUnit_Framework_Warning $e, $time) - { - $this->writeNotOk($test, 'Warning'); - } - - /** - * A failure occurred. - * - * @param PHPUnit_Framework_Test $test - * @param PHPUnit_Framework_AssertionFailedError $e - * @param float $time - */ - public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time) - { - $this->writeNotOk($test, 'Failure'); - - $message = explode( - "\n", - PHPUnit_Framework_TestFailure::exceptionToString($e) - ); - - $diagnostic = [ - 'message' => $message[0], - 'severity' => 'fail' - ]; - - if ($e instanceof PHPUnit_Framework_ExpectationFailedException) { - $cf = $e->getComparisonFailure(); - - if ($cf !== null) { - $diagnostic['data'] = [ - 'got' => $cf->getActual(), - 'expected' => $cf->getExpected() - ]; - } - } - - $yaml = new Symfony\Component\Yaml\Dumper; - - $this->write( - sprintf( - " ---\n%s ...\n", - $yaml->dump($diagnostic, 2, 2) - ) - ); - } - - /** - * Incomplete test. - * - * @param PHPUnit_Framework_Test $test - * @param Exception $e - * @param float $time - */ - public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time) - { - $this->writeNotOk($test, '', 'TODO Incomplete Test'); - } - - /** - * Risky test. - * - * @param PHPUnit_Framework_Test $test - * @param Exception $e - * @param float $time - */ - public function addRiskyTest(PHPUnit_Framework_Test $test, Exception $e, $time) - { - $this->write( - sprintf( - "ok %d - # RISKY%s\n", - $this->testNumber, - $e->getMessage() != '' ? ' ' . $e->getMessage() : '' - ) - ); - - $this->testSuccessful = false; - } - - /** - * Skipped test. - * - * @param PHPUnit_Framework_Test $test - * @param Exception $e - * @param float $time - */ - public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time) - { - $this->write( - sprintf( - "ok %d - # SKIP%s\n", - $this->testNumber, - $e->getMessage() != '' ? ' ' . $e->getMessage() : '' - ) - ); - - $this->testSuccessful = false; - } - - /** - * A testsuite started. - * - * @param PHPUnit_Framework_TestSuite $suite - */ - public function startTestSuite(PHPUnit_Framework_TestSuite $suite) - { - $this->testSuiteLevel++; - } - - /** - * A testsuite ended. - * - * @param PHPUnit_Framework_TestSuite $suite - */ - public function endTestSuite(PHPUnit_Framework_TestSuite $suite) - { - $this->testSuiteLevel--; - - if ($this->testSuiteLevel == 0) { - $this->write(sprintf("1..%d\n", $this->testNumber)); - } - } - - /** - * A test started. - * - * @param PHPUnit_Framework_Test $test - */ - public function startTest(PHPUnit_Framework_Test $test) - { - $this->testNumber++; - $this->testSuccessful = true; - } - - /** - * A test ended. - * - * @param PHPUnit_Framework_Test $test - * @param float $time - */ - public function endTest(PHPUnit_Framework_Test $test, $time) - { - if ($this->testSuccessful === true) { - $this->write( - sprintf( - "ok %d - %s\n", - $this->testNumber, - PHPUnit_Util_Test::describe($test) - ) - ); - } - - $this->writeDiagnostics($test); - } - - /** - * @param PHPUnit_Framework_Test $test - * @param string $prefix - * @param string $directive - */ - protected function writeNotOk(PHPUnit_Framework_Test $test, $prefix = '', $directive = '') - { - $this->write( - sprintf( - "not ok %d - %s%s%s\n", - $this->testNumber, - $prefix != '' ? $prefix . ': ' : '', - PHPUnit_Util_Test::describe($test), - $directive != '' ? ' # ' . $directive : '' - ) - ); - - $this->testSuccessful = false; - } - - /** - * @param PHPUnit_Framework_Test $test - */ - private function writeDiagnostics(PHPUnit_Framework_Test $test) - { - if (!$test instanceof PHPUnit_Framework_TestCase) { - return; - } - - if (!$test->hasOutput()) { - return; - } - - foreach (explode("\n", trim($test->getActualOutput())) as $line) { - $this->write( - sprintf( - "# %s\n", - $line - ) - ); - } - } - } - } -} -// @codingStandardsIgnoreEnd diff --git a/shim.php b/shim.php index 5f85345437..edc3efe727 100644 --- a/shim.php +++ b/shim.php @@ -1,5 +1,10 @@ result = new \PHPUnit_Framework_TestResult; + $this->result = new \PHPUnit\Framework\TestResult; $this->dispatcher = new EventDispatcher(); $this->extensionLoader = new ExtensionLoader($this->dispatcher); @@ -207,7 +207,7 @@ public function printResult() } /** - * @return \PHPUnit_Framework_TestResult + * @return \PHPUnit\Framework\TestResult */ public function getResult() { diff --git a/src/Codeception/Command/Console.php b/src/Codeception/Command/Console.php index de284e0fcc..e4828e3b11 100644 --- a/src/Codeception/Command/Console.php +++ b/src/Codeception/Command/Console.php @@ -140,7 +140,7 @@ protected function executeCommands(InputInterface $input, OutputInterface $outpu if ($value && !is_object($value)) { codecept_debug($value); } - } catch (\PHPUnit_Framework_AssertionFailedError $fail) { + } catch (\PHPUnit\Framework\AssertionFailedError $fail) { $output->writeln("fail " . $fail->getMessage()); } catch (\Exception $e) { $output->writeln("error " . $e->getMessage()); diff --git a/src/Codeception/Command/DryRun.php b/src/Codeception/Command/DryRun.php index e23cfbb3b9..ce5cfc0e60 100644 --- a/src/Codeception/Command/DryRun.php +++ b/src/Codeception/Command/DryRun.php @@ -79,7 +79,7 @@ public function execute(InputInterface $input, OutputInterface $output) $dispatcher->dispatch(Events::SUITE_INIT, new SuiteEvent($suiteManager->getSuite(), null, $settings)); $dispatcher->dispatch(Events::SUITE_BEFORE, new SuiteEvent($suiteManager->getSuite(), null, $settings)); foreach ($tests as $test) { - if ($test instanceof \PHPUnit_Framework_TestSuite_DataProvider) { + if ($test instanceof \PHPUnit\Framework\TestSuite\DataProvider) { foreach ($test as $t) { if ($t instanceof Test) { $this->dryRunTest($output, $dispatcher, $t); diff --git a/src/Codeception/Command/Run.php b/src/Codeception/Command/Run.php index b208096afe..1ef490ba80 100644 --- a/src/Codeception/Command/Run.php +++ b/src/Codeception/Command/Run.php @@ -241,7 +241,7 @@ public function execute(InputInterface $input, OutputInterface $output) } if (!$this->options['silent']) { $this->output->writeln( - Codecept::versionString() . "\nPowered by " . \PHPUnit_Runner_Version::getVersionString() + Codecept::versionString() . "\nPowered by " . \PHPUnit\Runner\Version::getVersionString() ); } if ($this->options['debug']) { diff --git a/src/Codeception/Configuration.php b/src/Codeception/Configuration.php index c29ea7307a..a0f0b21dd8 100644 --- a/src/Codeception/Configuration.php +++ b/src/Codeception/Configuration.php @@ -79,9 +79,9 @@ class Configuration 'reporters' => [ 'xml' => 'Codeception\PHPUnit\Log\JUnit', 'html' => 'Codeception\PHPUnit\ResultPrinter\HTML', - 'tap' => 'PHPUnit_Util_Log_TAP', - 'json' => 'PHPUnit_Util_Log_JSON', 'report' => 'Codeception\PHPUnit\ResultPrinter\Report', + 'tap' => 'PHPUnit\Util\Log\TAP', + 'json' => 'PHPUnit\Util\Log\JSON', ], 'groups' => [], 'settings' => [ diff --git a/src/Codeception/Coverage/DummyCodeCoverage.php b/src/Codeception/Coverage/DummyCodeCoverage.php deleted file mode 100644 index 27579e6cad..0000000000 --- a/src/Codeception/Coverage/DummyCodeCoverage.php +++ /dev/null @@ -1,13 +0,0 @@ -phpCodeCoverage = $phpCoverage ? $phpCoverage - : new \PHP_CodeCoverage; + : new \SebastianBergmann\CodeCoverage\CodeCoverage; $this->filter = $this->phpCodeCoverage->filter(); } /** - * @param \PHP_CodeCoverage $phpCoverage + * @param \SebastianBergmann\CodeCoverage\CodeCoverage $phpCoverage * @return Filter */ - public static function setup(\PHP_CodeCoverage $phpCoverage) + public static function setup(\SebastianBergmann\CodeCoverage\CodeCoverage $phpCoverage) { self::$c3 = new self($phpCoverage); return self::$c3; } /** - * @return null|\PHP_CodeCoverage + * @return null|\SebastianBergmann\CodeCoverage\CodeCoverage */ public function getPhpCodeCoverage() { @@ -166,7 +166,7 @@ protected function matchWildcardPattern($pattern) } /** - * @return \PHP_CodeCoverage_Filter + * @return \SebastianBergmann\CodeCoverage\Filter */ public function getFilter() { diff --git a/src/Codeception/Coverage/Subscriber/Printer.php b/src/Codeception/Coverage/Subscriber/Printer.php index 065239dc21..2314ed038f 100644 --- a/src/Codeception/Coverage/Subscriber/Printer.php +++ b/src/Codeception/Coverage/Subscriber/Printer.php @@ -33,7 +33,7 @@ public function __construct($options) $this->options = $options; $this->logDir = Configuration::outputDir(); $this->settings = array_merge($this->settings, Configuration::config()['coverage']); - self::$coverage = new \PHP_CodeCoverage(); + self::$coverage = new \SebastianBergmann\CodeCoverage\CodeCoverage(); // Apply filter $filter = new Filter(self::$coverage); @@ -86,9 +86,9 @@ public function printResult(PrintResultEvent $e) } } - protected function printConsole(\PHPUnit_Util_Printer $printer) + protected function printConsole(\PHPUnit\Util\Printer $printer) { - $writer = new \PHP_CodeCoverage_Report_Text( + $writer = new \SebastianBergmann\CodeCoverage\Report\Text( $this->settings['low_limit'], $this->settings['high_limit'], $this->settings['show_uncovered'], @@ -99,12 +99,12 @@ protected function printConsole(\PHPUnit_Util_Printer $printer) protected function printHtml() { - $writer = new \PHP_CodeCoverage_Report_HTML( + $writer = new \SebastianBergmann\CodeCoverage\Report\Html\Facade( $this->settings['low_limit'], $this->settings['high_limit'], sprintf( ', Codeception and PHPUnit %s', - \PHPUnit_Runner_Version::id() + \PHPUnit\Runner\Version::id() ) ); @@ -113,19 +113,19 @@ protected function printHtml() protected function printXml() { - $writer = new \PHP_CodeCoverage_Report_Clover; + $writer = new \SebastianBergmann\CodeCoverage\Report\Clover(); $writer->process(self::$coverage, $this->absolutePath($this->options['coverage-xml'])); } protected function printPHP() { - $writer = new \PHP_CodeCoverage_Report_PHP; + $writer = new \SebastianBergmann\CodeCoverage\Report\PHP; $writer->process(self::$coverage, $this->absolutePath($this->options['coverage'])); } protected function printText() { - $writer = new \PHP_CodeCoverage_Report_Text( + $writer = new \SebastianBergmann\CodeCoverage\Report\Text( $this->settings['low_limit'], $this->settings['high_limit'], $this->settings['show_uncovered'], @@ -139,13 +139,13 @@ protected function printText() protected function printCrap4j() { - $writer = new \PHP_CodeCoverage_Report_Crap4j; + $writer = new \SebastianBergmann\CodeCoverage\Report\Crap4j; $writer->process(self::$coverage, $this->absolutePath($this->options['coverage-crap4j'])); } protected function printPHPUnit() { - $writer = new \PHP_CodeCoverage_Report_XML(\PHPUnit_Runner_Version::id()); + $writer = new \SebastianBergmann\CodeCoverage\Report\Xml\Facade(\PHPUnit\Runner\Version::id()); $writer->process(self::$coverage, $this->absolutePath($this->options['coverage-phpunit'])); } } diff --git a/src/Codeception/Coverage/SuiteSubscriber.php b/src/Codeception/Coverage/SuiteSubscriber.php index a0b6ef6ca4..f7bba990b5 100644 --- a/src/Codeception/Coverage/SuiteSubscriber.php +++ b/src/Codeception/Coverage/SuiteSubscriber.php @@ -4,7 +4,10 @@ use Codeception\Configuration; use Codeception\Coverage\Subscriber\Printer; use Codeception\Lib\Interfaces\Remote; +use Codeception\Stub; use Codeception\Subscriber\Shared\StaticEvents; +use PHPUnit\Framework\CodeCoverageException; +use SebastianBergmann\CodeCoverage\CodeCoverage; use Symfony\Component\EventDispatcher\EventSubscriberInterface; abstract class SuiteSubscriber implements EventSubscriberInterface @@ -41,8 +44,8 @@ public function __construct($options = []) protected function applySettings($settings) { try { - $this->coverage = new \PHP_CodeCoverage(); - } catch (\PHP_CodeCoverage_Exception $e) { + $this->coverage = new \SebastianBergmann\CodeCoverage\CodeCoverage(); + } catch (CodeCoverageException $e) { throw new \Exception( 'XDebug is required to collect CodeCoverage. Please install xdebug extension and enable it in php.ini' ); @@ -73,9 +76,10 @@ protected function getServerConnectionModule(array $modules) return null; } - public function applyFilter(\PHPUnit_Framework_TestResult $result) + public function applyFilter(\PHPUnit\Framework\TestResult $result) { - $result->setCodeCoverage(new DummyCodeCoverage()); + $driver = Stub::makeEmpty('SebastianBergmann\CodeCoverage\Driver\Driver'); + $result->setCodeCoverage(new CodeCoverage($driver)); Filter::setup($this->coverage) ->whiteList($this->filters) diff --git a/src/Codeception/Event/FailEvent.php b/src/Codeception/Event/FailEvent.php index f38231c538..372411ce43 100644 --- a/src/Codeception/Event/FailEvent.php +++ b/src/Codeception/Event/FailEvent.php @@ -13,7 +13,7 @@ class FailEvent extends TestEvent */ protected $count; - public function __construct(\PHPUnit_Framework_Test $test, $time, \Exception $e, $count = 0) + public function __construct(\PHPUnit\Framework\Test $test, $time, \Exception $e, $count = 0) { parent::__construct($test, $time); $this->fail = $e; diff --git a/src/Codeception/Event/PrintResultEvent.php b/src/Codeception/Event/PrintResultEvent.php index 24c792f04b..bc5c36257f 100644 --- a/src/Codeception/Event/PrintResultEvent.php +++ b/src/Codeception/Event/PrintResultEvent.php @@ -6,23 +6,23 @@ class PrintResultEvent extends Event { /** - * @var \PHPUnit_Framework_TestResult + * @var \PHPUnit\Framework\TestResult */ protected $result; /** - * @var \PHPUnit_Util_Printer + * @var \PHPUnit\Util\Printer */ protected $printer; - public function __construct(\PHPUnit_Framework_TestResult $result, \PHPUnit_Util_Printer $printer) + public function __construct(\PHPUnit\Framework\TestResult $result, \PHPUnit\Util\Printer $printer) { $this->result = $result; $this->printer = $printer; } /** - * @return \PHPUnit_Util_Printer + * @return \PHPUnit\Util\Printer */ public function getPrinter() { @@ -30,7 +30,7 @@ public function getPrinter() } /** - * @return \PHPUnit_Framework_TestResult + * @return \PHPUnit\Framework\TestResult */ public function getResult() { diff --git a/src/Codeception/Event/SuiteEvent.php b/src/Codeception/Event/SuiteEvent.php index 9a7c64dd2d..bcf99c8f4b 100644 --- a/src/Codeception/Event/SuiteEvent.php +++ b/src/Codeception/Event/SuiteEvent.php @@ -7,12 +7,12 @@ class SuiteEvent extends Event { /** - * @var \PHPUnit_Framework_TestSuite + * @var \PHPUnit\Framework\TestSuite */ protected $suite; /** - * @var \PHPUnit_Framework_TestResult + * @var \PHPUnit\Framework\TestResult */ protected $result; @@ -22,8 +22,8 @@ class SuiteEvent extends Event protected $settings; public function __construct( - \PHPUnit_Framework_TestSuite $suite, - \PHPUnit_Framework_TestResult $result = null, + \PHPUnit\Framework\TestSuite $suite, + \PHPUnit\Framework\TestResult $result = null, $settings = [] ) { $this->suite = $suite; @@ -40,7 +40,7 @@ public function getSuite() } /** - * @return \PHPUnit_Framework_TestResult + * @return \PHPUnit\Framework\TestResult */ public function getResult() { diff --git a/src/Codeception/Event/TestEvent.php b/src/Codeception/Event/TestEvent.php index dc6801ccda..59c25bda97 100644 --- a/src/Codeception/Event/TestEvent.php +++ b/src/Codeception/Event/TestEvent.php @@ -6,7 +6,7 @@ class TestEvent extends Event { /** - * @var \PHPUnit_Framework_Test + * @var \PHPUnit\Framework\Test */ protected $test; @@ -15,7 +15,7 @@ class TestEvent extends Event */ protected $time; - public function __construct(\PHPUnit_Framework_Test $test, $time = 0) + public function __construct(\PHPUnit\Framework\Test $test, $time = 0) { $this->test = $test; $this->time = $time; diff --git a/src/Codeception/Example.php b/src/Codeception/Example.php index 3651c69808..e322c1f73d 100644 --- a/src/Codeception/Example.php +++ b/src/Codeception/Example.php @@ -41,7 +41,7 @@ public function offsetExists($offset) public function offsetGet($offset) { if (!$this->offsetExists($offset)) { - throw new \PHPUnit_Framework_AssertionFailedError("Example $offset doesn't exist"); + throw new \PHPUnit\Framework\AssertionFailedError("Example $offset doesn't exist"); }; return $this->data[$offset]; } diff --git a/src/Codeception/Exception/ConditionalAssertionFailed.php b/src/Codeception/Exception/ConditionalAssertionFailed.php index 7bc105335e..a063917c10 100644 --- a/src/Codeception/Exception/ConditionalAssertionFailed.php +++ b/src/Codeception/Exception/ConditionalAssertionFailed.php @@ -1,6 +1,6 @@ getMock('Illuminate\Contracts\Events\Dispatcher'); - // Even if events are disabled we still want to record the triggered events. // But by mocking the event dispatcher the wildcard listener registered in the initialize method is removed. // So to record the triggered events we have to catch the calls to the fire method of the event dispatcher mock. @@ -257,9 +255,9 @@ private function mockEventDispatcher() // the 'fire' method was renamed to 'dispatch'. This code determines the correct method to mock. $method = method_exists($this->app['events'], 'dispatch') ? 'dispatch' : 'fire'; - $mock->expects(new \PHPUnit_Framework_MockObject_Matcher_AnyInvokedCount) - ->method($method) - ->will(new \PHPUnit_Framework_MockObject_Stub_ReturnCallback($callback)); + $mock = Stub::makeEmpty('Illuminate\Contracts\Events\Dispatcher', [ + $method => $callback + ]); $this->app->instance('events', $mock); } diff --git a/src/Codeception/Lib/Connector/ZF2.php b/src/Codeception/Lib/Connector/ZF2.php index 5b7fa75bd9..0c91bee89e 100644 --- a/src/Codeception/Lib/Connector/ZF2.php +++ b/src/Codeception/Lib/Connector/ZF2.php @@ -142,7 +142,7 @@ public function grabServiceFromContainer($service) $serviceManager = $this->application->getServiceManager(); if (!$serviceManager->has($service)) { - throw new \PHPUnit_Framework_AssertionFailedError("Service $service is not available in container"); + throw new \PHPUnit\Framework\AssertionFailedError("Service $service is not available in container"); } if ($service === 'Doctrine\ORM\EntityManager' && !isset($this->persistentServiceManager)) { diff --git a/src/Codeception/Lib/Driver/Beanstalk.php b/src/Codeception/Lib/Driver/Beanstalk.php index 5c6b1f9756..8215ddbc32 100644 --- a/src/Codeception/Lib/Driver/Beanstalk.php +++ b/src/Codeception/Lib/Driver/Beanstalk.php @@ -41,7 +41,7 @@ public function getMessagesTotalCountOnQueue($queue) try { return $this->queue->statsTube($queue)['total-jobs']; } catch (ConnectionException $ex) { - \PHPUnit_Framework_Assert::fail("queue [$queue] not found"); + \PHPUnit\Framework\Assert::fail("queue [$queue] not found"); } } @@ -74,7 +74,7 @@ public function getMessagesCurrentCountOnQueue($queue) try { return $this->queue->statsTube($queue)['current-jobs-ready']; } catch (ConnectionException $e) { - \PHPUnit_Framework_Assert::fail("queue [$queue] not found"); + \PHPUnit\Framework\Assert::fail("queue [$queue] not found"); } } diff --git a/src/Codeception/Lib/Driver/Iron.php b/src/Codeception/Lib/Driver/Iron.php index 18a76947a4..d7cd0cbb4a 100644 --- a/src/Codeception/Lib/Driver/Iron.php +++ b/src/Codeception/Lib/Driver/Iron.php @@ -23,7 +23,7 @@ public function openConnection($config) "host" => $config['host'] ]); if (!$this->queue) { - \PHPUnit_Framework_Assert::fail('connection failed or timed-out.'); + \PHPUnit\Framework\Assert::fail('connection failed or timed-out.'); } } @@ -65,7 +65,7 @@ public function getMessagesCurrentCountOnQueue($queue) try { return $this->queue->getQueue($queue)->size; } catch (\Http_Exception $ex) { - \PHPUnit_Framework_Assert::fail("queue [$queue] not found"); + \PHPUnit\Framework\Assert::fail("queue [$queue] not found"); } } @@ -81,7 +81,7 @@ public function getMessagesTotalCountOnQueue($queue) try { return $this->queue->getQueue($queue)->total_messages; } catch (\Http_Exception $e) { - \PHPUnit_Framework_Assert::fail("queue [$queue] not found"); + \PHPUnit\Framework\Assert::fail("queue [$queue] not found"); } } @@ -90,7 +90,7 @@ public function clearQueue($queue) try { $this->queue->clearQueue($queue); } catch (\Http_Exception $ex) { - \PHPUnit_Framework_Assert::fail("queue [$queue] not found"); + \PHPUnit\Framework\Assert::fail("queue [$queue] not found"); } } diff --git a/src/Codeception/Lib/GroupManager.php b/src/Codeception/Lib/GroupManager.php index 1c8af166cb..c796033bac 100644 --- a/src/Codeception/Lib/GroupManager.php +++ b/src/Codeception/Lib/GroupManager.php @@ -85,7 +85,7 @@ protected function loadConfiguredGroupSettings() } } - public function groupsForTest(\PHPUnit_Framework_Test $test) + public function groupsForTest(\PHPUnit\Framework\Test $test) { $groups = []; $filename = Descriptor::getTestFileName($test); @@ -95,14 +95,14 @@ public function groupsForTest(\PHPUnit_Framework_Test $test) if ($test instanceof Reported) { $info = $test->getReportFields(); if (isset($info['class'])) { - $groups = array_merge($groups, \PHPUnit_Util_Test::getGroups($info['class'], $info['name'])); + $groups = array_merge($groups, \PHPUnit\Util\Test::getGroups($info['class'], $info['name'])); } $filename = str_replace(['\\\\', '//'], ['\\', '/'], $info['file']); } - if ($test instanceof \PHPUnit_Framework_TestCase) { - $groups = array_merge($groups, \PHPUnit_Util_Test::getGroups(get_class($test), $test->getName(false))); + if ($test instanceof \PHPUnit\Framework\TestCase) { + $groups = array_merge($groups, \PHPUnit\Util\Test::getGroups(get_class($test), $test->getName(false))); } - if ($test instanceof \PHPUnit_Framework_TestSuite_DataProvider) { + if ($test instanceof \PHPUnit\Framework\TestSuite\DataProvider) { $firstTest = $test->testAt(0); if ($firstTest != false && $firstTest instanceof TestInterface) { $groups = array_merge($groups, $firstTest->getMetadata()->getGroups()); @@ -118,7 +118,7 @@ public function groupsForTest(\PHPUnit_Framework_Test $test) if (strpos($filename . ':' . $test->getName(false), $testPattern) === 0) { $groups[] = $group; } - if ($test instanceof \PHPUnit_Framework_TestSuite_DataProvider) { + if ($test instanceof \PHPUnit\Framework\TestSuite\DataProvider) { $firstTest = $test->testAt(0); if ($firstTest != false && $firstTest instanceof TestInterface) { if (strpos($filename . ':' . $firstTest->getName(false), $testPattern) === 0) { diff --git a/src/Codeception/Lib/InnerBrowser.php b/src/Codeception/Lib/InnerBrowser.php index c30fe3f069..1aefbc4399 100644 --- a/src/Codeception/Lib/InnerBrowser.php +++ b/src/Codeception/Lib/InnerBrowser.php @@ -557,12 +557,12 @@ public function dontSeeCurrentUrlEquals($uri) public function seeCurrentUrlMatches($uri) { - \PHPUnit_Framework_Assert::assertRegExp($uri, $this->_getCurrentUri()); + \PHPUnit\Framework\Assert::assertRegExp($uri, $this->_getCurrentUri()); } public function dontSeeCurrentUrlMatches($uri) { - \PHPUnit_Framework_Assert::assertNotRegExp($uri, $this->_getCurrentUri()); + \PHPUnit\Framework\Assert::assertNotRegExp($uri, $this->_getCurrentUri()); } public function grabFromCurrentUrl($uri = null) diff --git a/src/Codeception/Module/Cli.php b/src/Codeception/Module/Cli.php index 896d43bf65..8362cbcc8e 100644 --- a/src/Codeception/Module/Cli.php +++ b/src/Codeception/Module/Cli.php @@ -47,10 +47,10 @@ public function runShellCommand($command, $failNonZero = true) $this->result = $resultCode; $this->output = implode("\n", $data); if ($this->output === null) { - \PHPUnit_Framework_Assert::fail("$command can't be executed"); + \PHPUnit\Framework\Assert::fail("$command can't be executed"); } if ($resultCode !== 0 && $failNonZero) { - \PHPUnit_Framework_Assert::fail("Result code was $resultCode.\n\n" . $this->output); + \PHPUnit\Framework\Assert::fail("Result code was $resultCode.\n\n" . $this->output); } $this->debug(preg_replace('~s/\e\[\d+(?>(;\d+)*)m//g~', '', $this->output)); } @@ -62,7 +62,7 @@ public function runShellCommand($command, $failNonZero = true) */ public function seeInShellOutput($text) { - \PHPUnit_Framework_Assert::assertContains($text, $this->output); + \PHPUnit\Framework\Assert::assertContains($text, $this->output); } /** @@ -74,7 +74,7 @@ public function seeInShellOutput($text) public function dontSeeInShellOutput($text) { $this->debug($this->output); - \PHPUnit_Framework_Assert::assertNotContains($text, $this->output); + \PHPUnit\Framework\Assert::assertNotContains($text, $this->output); } /** @@ -82,7 +82,7 @@ public function dontSeeInShellOutput($text) */ public function seeShellOutputMatches($regex) { - \PHPUnit_Framework_Assert::assertRegExp($regex, $this->output); + \PHPUnit\Framework\Assert::assertRegExp($regex, $this->output); } /** diff --git a/src/Codeception/Module/Filesystem.php b/src/Codeception/Module/Filesystem.php index 03f3adee5f..ad5e886f2e 100644 --- a/src/Codeception/Module/Filesystem.php +++ b/src/Codeception/Module/Filesystem.php @@ -95,7 +95,7 @@ public function openFile($filename) public function deleteFile($filename) { if (!file_exists($this->absolutizePath($filename))) { - \PHPUnit_Framework_Assert::fail('file not found'); + \PHPUnit\Framework\Assert::fail('file not found'); } unlink($this->absolutizePath($filename)); } @@ -204,7 +204,7 @@ public function seeThisFileMatches($regex) public function seeFileContentsEqual($text) { $file = str_replace("\r", '', $this->file); - \PHPUnit_Framework_Assert::assertEquals($text, $file); + \PHPUnit\Framework\Assert::assertEquals($text, $file); } /** @@ -249,7 +249,7 @@ public function seeFileFound($filename, $path = '') { if ($path === '' && file_exists($filename)) { $this->openFile($filename); - \PHPUnit_Framework_Assert::assertFileExists($filename); + \PHPUnit\Framework\Assert::assertFileExists($filename); return; } @@ -260,7 +260,7 @@ public function seeFileFound($filename, $path = '') } $this->openFile($found); - \PHPUnit_Framework_Assert::assertFileExists($found); + \PHPUnit\Framework\Assert::assertFileExists($found); } /** @@ -272,7 +272,7 @@ public function seeFileFound($filename, $path = '') public function dontSeeFileFound($filename, $path = '') { if ($path === '') { - \PHPUnit_Framework_Assert::assertFileNotExists($filename); + \PHPUnit\Framework\Assert::assertFileNotExists($filename); return; } @@ -280,11 +280,11 @@ public function dontSeeFileFound($filename, $path = '') if ($found === false) { //this line keeps a count of assertions correct - \PHPUnit_Framework_Assert::assertTrue(true); + \PHPUnit\Framework\Assert::assertTrue(true); return; } - \PHPUnit_Framework_Assert::assertFileNotExists($found); + \PHPUnit\Framework\Assert::assertFileNotExists($found); } /** @@ -292,7 +292,7 @@ public function dontSeeFileFound($filename, $path = '') * * @param string $filename * @param string $path - * @throws \PHPUnit_Framework_AssertionFailedError When path does not exist + * @throws \PHPUnit\Framework\AssertionFailedError When path does not exist * @return string|false Path to the first matching file */ private function findFileInPath($filename, $path) diff --git a/src/Codeception/Module/MongoDb.php b/src/Codeception/Module/MongoDb.php index 9b98338be2..0109d3d1a9 100644 --- a/src/Codeception/Module/MongoDb.php +++ b/src/Codeception/Module/MongoDb.php @@ -286,7 +286,7 @@ public function seeInCollection($collection, $criteria = []) { $collection = $this->driver->getDbh()->selectCollection($collection); $res = $collection->count($criteria); - \PHPUnit_Framework_Assert::assertGreaterThan(0, $res); + \PHPUnit\Framework\Assert::assertGreaterThan(0, $res); } /** @@ -304,7 +304,7 @@ public function dontSeeInCollection($collection, $criteria = []) { $collection = $this->driver->getDbh()->selectCollection($collection); $res = $collection->count($criteria); - \PHPUnit_Framework_Assert::assertLessThan(1, $res); + \PHPUnit\Framework\Assert::assertLessThan(1, $res); } /** @@ -371,11 +371,11 @@ public function seeElementIsArray($collection, $criteria = [], $elementToCheck = ) ); if ($res > 1) { - throw new \PHPUnit_Framework_ExpectationFailedException( + throw new \PHPUnit\Framework\ExpectationFailedException( 'Error: you should test against a single element criteria when asserting that elementIsArray' ); } - \PHPUnit_Framework_Assert::assertEquals(1, $res, 'Specified element is not a Mongo Object'); + \PHPUnit\Framework\Assert::assertEquals(1, $res, 'Specified element is not a Mongo Object'); } /** @@ -404,11 +404,11 @@ public function seeElementIsObject($collection, $criteria = [], $elementToCheck ) ); if ($res > 1) { - throw new \PHPUnit_Framework_ExpectationFailedException( + throw new \PHPUnit\Framework\ExpectationFailedException( 'Error: you should test against a single element criteria when asserting that elementIsObject' ); } - \PHPUnit_Framework_Assert::assertEquals(1, $res, 'Specified element is not a Mongo Object'); + \PHPUnit\Framework\Assert::assertEquals(1, $res, 'Specified element is not a Mongo Object'); } /** @@ -428,7 +428,7 @@ public function seeNumElementsInCollection($collection, $expected, $criteria = [ { $collection = $this->driver->getDbh()->selectCollection($collection); $res = $collection->count($criteria); - \PHPUnit_Framework_Assert::assertSame($expected, $res); + \PHPUnit\Framework\Assert::assertSame($expected, $res); } /** diff --git a/src/Codeception/Module/REST.php b/src/Codeception/Module/REST.php index a33ca93d4d..aff9d2b5a0 100644 --- a/src/Codeception/Module/REST.php +++ b/src/Codeception/Module/REST.php @@ -514,12 +514,12 @@ private function setHeaderLink(array $linkEntries) { $values = []; foreach ($linkEntries as $linkEntry) { - \PHPUnit_Framework_Assert::assertArrayHasKey( + \PHPUnit\Framework\Assert::assertArrayHasKey( 'uri', $linkEntry, 'linkEntry should contain property "uri"' ); - \PHPUnit_Framework_Assert::assertArrayHasKey( + \PHPUnit\Framework\Assert::assertArrayHasKey( 'link-param', $linkEntry, 'linkEntry should contain property "link-param"' @@ -725,11 +725,11 @@ private function checkFileBeforeUpload($file) public function seeResponseIsJson() { $responseContent = $this->connectionModule->_getResponseContent(); - \PHPUnit_Framework_Assert::assertNotEquals('', $responseContent, 'response is empty'); + \PHPUnit\Framework\Assert::assertNotEquals('', $responseContent, 'response is empty'); json_decode($responseContent); $errorCode = json_last_error(); $errorMessage = json_last_error_msg(); - \PHPUnit_Framework_Assert::assertEquals( + \PHPUnit\Framework\Assert::assertEquals( JSON_ERROR_NONE, $errorCode, sprintf( @@ -790,7 +790,7 @@ public function dontSeeResponseContains($text) */ public function seeResponseContainsJson($json = []) { - \PHPUnit_Framework_Assert::assertThat( + \PHPUnit\Framework\Assert::assertThat( $this->connectionModule->_getResponseContent(), new JsonContains($json) ); @@ -1087,7 +1087,7 @@ public function seeResponseMatchesJsonType(array $jsonType, $jsonPath = null) $jsonArray = $jsonArray->filterByJsonPath($jsonPath); } - \PHPUnit_Framework_Assert::assertThat($jsonArray, new JsonTypeConstraint($jsonType)); + \PHPUnit\Framework\Assert::assertThat($jsonArray, new JsonTypeConstraint($jsonType)); } /** @@ -1106,7 +1106,7 @@ public function dontSeeResponseMatchesJsonType($jsonType, $jsonPath = null) $jsonArray = $jsonArray->filterByJsonPath($jsonPath); } - \PHPUnit_Framework_Assert::assertThat($jsonArray, new JsonTypeConstraint($jsonType, false)); + \PHPUnit\Framework\Assert::assertThat($jsonArray, new JsonTypeConstraint($jsonType, false)); } /** @@ -1180,7 +1180,7 @@ public function seeResponseIsXml() libxml_clear_errors(); } libxml_use_internal_errors(false); - \PHPUnit_Framework_Assert::assertNotSame( + \PHPUnit\Framework\Assert::assertNotSame( false, $doc, "xml decoding error #$num with message \"$title\", see http://www.xmlsoft.org/html/libxml-xmlerror.html" @@ -1262,7 +1262,7 @@ public function grabAttributeFromXmlElement($cssOrXPath, $attribute) */ public function seeXmlResponseEquals($xml) { - \PHPUnit_Framework_Assert::assertXmlStringEqualsXmlString($this->connectionModule->_getResponseContent(), $xml); + \PHPUnit\Framework\Assert::assertXmlStringEqualsXmlString($this->connectionModule->getResponseContent(), $xml); } @@ -1277,7 +1277,7 @@ public function seeXmlResponseEquals($xml) */ public function dontSeeXmlResponseEquals($xml) { - \PHPUnit_Framework_Assert::assertXmlStringNotEqualsXmlString( + \PHPUnit\Framework\Assert::assertXmlStringNotEqualsXmlString( $this->connectionModule->_getResponseContent(), $xml ); diff --git a/src/Codeception/Module/SOAP.php b/src/Codeception/Module/SOAP.php index 00b4b64647..35bc76b5ba 100644 --- a/src/Codeception/Module/SOAP.php +++ b/src/Codeception/Module/SOAP.php @@ -298,7 +298,7 @@ public function seeSoapResponseIncludes($xml) public function dontSeeSoapResponseEquals($xml) { $xml = SoapUtils::toXml($xml); - \PHPUnit_Framework_Assert::assertXmlStringNotEqualsXmlString($xml->C14N(), $this->getXmlResponse()->C14N()); + \PHPUnit\Framework\Assert::assertXmlStringNotEqualsXmlString($xml->C14N(), $this->getXmlResponse()->C14N()); } diff --git a/src/Codeception/Module/WebDriver.php b/src/Codeception/Module/WebDriver.php index 910f5afd78..1f976b5b95 100644 --- a/src/Codeception/Module/WebDriver.php +++ b/src/Codeception/Module/WebDriver.php @@ -1900,7 +1900,7 @@ public function seeInPopup($text) $alert = $this->webDriver->switchTo()->alert(); try { $this->assertContains($text, $alert->getText()); - } catch (\PHPUnit_Framework_AssertionFailedError $e) { + } catch (\PHPUnit\Framework\AssertionFailedError $e) { $alert->dismiss(); throw $e; } @@ -1922,7 +1922,7 @@ public function dontSeeInPopup($text) $alert = $this->webDriver->switchTo()->alert(); try { $this->assertNotContains($text, $alert->getText()); - } catch (\PHPUnit_Framework_AssertionFailedError $e) { + } catch (\PHPUnit\Framework\AssertionFailedError $e) { $alert->dismiss(); throw $e; } diff --git a/src/Codeception/Module/XMLRPC.php b/src/Codeception/Module/XMLRPC.php index 16a70c39ad..6cf3c98dac 100644 --- a/src/Codeception/Module/XMLRPC.php +++ b/src/Codeception/Module/XMLRPC.php @@ -118,7 +118,7 @@ public function haveHttpHeader($name, $value) */ public function seeResponseCodeIs($num) { - \PHPUnit_Framework_Assert::assertEquals($num, $this->client->getInternalResponse()->getStatus()); + \PHPUnit\Framework\Assert::assertEquals($num, $this->client->getInternalResponse()->getStatus()); } /** @@ -129,7 +129,7 @@ public function seeResponseCodeIs($num) public function seeResponseIsXMLRPC() { $result = xmlrpc_decode($this->response); - \PHPUnit_Framework_Assert::assertNotNull($result, 'Invalid response document returned from XmlRpc server'); + \PHPUnit\Framework\Assert::assertNotNull($result, 'Invalid response document returned from XmlRpc server'); } /** diff --git a/src/Codeception/Module/ZendExpressive.php b/src/Codeception/Module/ZendExpressive.php index e94e388713..78c32411ed 100644 --- a/src/Codeception/Module/ZendExpressive.php +++ b/src/Codeception/Module/ZendExpressive.php @@ -108,7 +108,7 @@ public function _getEntityManager() { $service = 'Doctrine\ORM\EntityManager'; if (!$this->container->has($service)) { - throw new \PHPUnit_Framework_AssertionFailedError("Service $service is not available in container"); + throw new \PHPUnit\Framework\AssertionFailedError("Service $service is not available in container"); } return $this->container->get('Doctrine\ORM\EntityManager'); diff --git a/src/Codeception/PHPUnit/ConsolePrinter.php b/src/Codeception/PHPUnit/ConsolePrinter.php deleted file mode 100644 index 42262f17fa..0000000000 --- a/src/Codeception/PHPUnit/ConsolePrinter.php +++ /dev/null @@ -1,15 +0,0 @@ -count()) { - return false; - } - if ($this->string === '') { - return true; - } - - foreach ($nodes as $node) { - if (parent::matches($node->nodeValue)) { - return true; - } - } - return false; - } - - protected function fail($nodes, $selector, ComparisonFailure $comparisonFailure = null) - { - /** @var $nodes DomCrawler * */ - if (!$nodes->count()) { - throw new ElementNotFound($selector, 'Element located either by name, CSS or XPath'); - } - - $output = "Failed asserting that any element by '$selector'"; - $output .= $this->uriMessage('on page'); - $output .= " "; - - if ($nodes->count() < 10) { - $output .= $this->nodesList($nodes); - } else { - $message = new Message("[total %s elements]"); - $output .= $message->with($nodes->count())->getMessage(); - } - $output .= "\ncontains text '{$this->string}'"; - - throw new \PHPUnit_Framework_ExpectationFailedException( - $output, - $comparisonFailure - ); - } - - protected function failureDescription($other) - { - $desc = ''; - foreach ($other as $o) { - $desc .= parent::failureDescription($o->textContent); - } - return $desc; - } - - protected function nodesList(DomCrawler $nodes, $contains = null) - { - $output = ""; - foreach ($nodes as $node) { - if ($contains && strpos($node->nodeValue, $contains) === false) { - continue; - } - $output .= "\n+ " . $node->C14N(); - } - return $output; - } -} diff --git a/src/Codeception/PHPUnit/Constraint/CrawlerNot.php b/src/Codeception/PHPUnit/Constraint/CrawlerNot.php deleted file mode 100644 index b3baf64f25..0000000000 --- a/src/Codeception/PHPUnit/Constraint/CrawlerNot.php +++ /dev/null @@ -1,40 +0,0 @@ -string) { - throw new \PHPUnit_Framework_ExpectationFailedException( - "Element '$selector' was found", - $comparisonFailure - ); - } - /** @var $nodes DomCrawler * */ - - $output = "There was '$selector' element"; - $output .= $this->uriMessage('on page'); - $output .= $this->nodesList($nodes, $this->string); - $output .= "\ncontaining '{$this->string}'"; - - throw new \PHPUnit_Framework_ExpectationFailedException( - $output, - $comparisonFailure - ); - } - - public function toString() - { - if ($this->string) { - return 'that contains text "' . $this->string . '"'; - } - } -} diff --git a/src/Codeception/PHPUnit/Constraint/JsonContains.php b/src/Codeception/PHPUnit/Constraint/JsonContains.php deleted file mode 100644 index 777fe8749f..0000000000 --- a/src/Codeception/PHPUnit/Constraint/JsonContains.php +++ /dev/null @@ -1,70 +0,0 @@ -expected = $expected; - } - - /** - * Evaluates the constraint for parameter $other. Returns true if the - * constraint is met, false otherwise. - * - * @param mixed $other Value or object to evaluate. - * - * @return bool - */ - protected function matches($other) - { - $jsonResponseArray = new JsonArray($other); - if (!is_array($jsonResponseArray->toArray())) { - throw new \PHPUnit_Framework_AssertionFailedError('JSON response is not an array: ' . $other); - } - - if ($jsonResponseArray->containsArray($this->expected)) { - return true; - } - - $comparator = new ArrayComparator(); - $comparator->setFactory(new Factory); - try { - $comparator->assertEquals($this->expected, $jsonResponseArray->toArray()); - } catch (ComparisonFailure $failure) { - throw new \PHPUnit_Framework_ExpectationFailedException( - "Response JSON does not contain the provided JSON\n", - $failure - ); - } - } - - /** - * Returns a string representation of the constraint. - * - * @return string - */ - public function toString() - { - //unused - return ''; - } - - protected function failureDescription($other) - { - //unused - return ''; - } -} diff --git a/src/Codeception/PHPUnit/Constraint/JsonType.php b/src/Codeception/PHPUnit/Constraint/JsonType.php deleted file mode 100644 index 9815db336c..0000000000 --- a/src/Codeception/PHPUnit/Constraint/JsonType.php +++ /dev/null @@ -1,64 +0,0 @@ -jsonType = $jsonType; - $this->match = $match; - } - - /** - * Evaluates the constraint for parameter $other. Returns true if the - * constraint is met, false otherwise. - * - * @param mixed $jsonArray Value or object to evaluate. - * - * @return bool - */ - protected function matches($jsonArray) - { - if ($jsonArray instanceof JsonArray) { - $jsonArray = $jsonArray->toArray(); - } - - $matched = (new JsonTypeUtil($jsonArray))->matches($this->jsonType); - - if ($this->match) { - if ($matched !== true) { - throw new \PHPUnit_Framework_ExpectationFailedException($matched); - } - } else { - if ($matched === true) { - throw new \PHPUnit_Framework_ExpectationFailedException('Unexpectedly response matched: ' . json_encode($jsonArray)); - } - } - return true; - } - - /** - * Returns a string representation of the constraint. - * - * @return string - */ - public function toString() - { - //unused - return ''; - } - - protected function failureDescription($other) - { - //unused - return ''; - } -} diff --git a/src/Codeception/PHPUnit/Constraint/Page.php b/src/Codeception/PHPUnit/Constraint/Page.php deleted file mode 100644 index 84cd48405f..0000000000 --- a/src/Codeception/PHPUnit/Constraint/Page.php +++ /dev/null @@ -1,80 +0,0 @@ -string = $this->normalizeText((string)$string); - $this->uri = $uri; - } - - /** - * Evaluates the constraint for parameter $other. Returns true if the - * constraint is met, false otherwise. - * - * @param mixed $other Value or object to evaluate. - * - * @return bool - */ - protected function matches($other) - { - $other = $this->normalizeText($other); - return mb_stripos($other, $this->string, null, 'UTF-8') !== false; - } - - /** - * @param $text - * @return string - */ - private function normalizeText($text) - { - $text = strtr($text, "\r\n", " "); - return trim(preg_replace('/\\s{2,}/', ' ', $text)); - } - - /** - * Returns a string representation of the constraint. - * - * @return string - */ - public function toString() - { - $string = mb_strtolower($this->string, 'UTF-8'); - - return sprintf( - 'contains "%s"', - $string - ); - } - - protected function failureDescription($pageContent) - { - $message = $this->uriMessage('on page'); - $message->append("\n--> "); - $message->append(substr($pageContent, 0, 300)); - if (strlen($pageContent) > 300) { - $debugMessage = new Message( - "[Content too long to display. See complete response in '" . codecept_output_dir() . "' directory]" - ); - $message->append("\n")->append($debugMessage); - } - $message->append("\n--> "); - return $message->getMessage() . $this->toString(); - } - - protected function uriMessage($onPage = "") - { - if (!$this->uri) { - return new Message(''); - } - $message = new Message($this->uri); - $message->prepend(" $onPage "); - return $message; - } -} diff --git a/src/Codeception/PHPUnit/Constraint/WebDriver.php b/src/Codeception/PHPUnit/Constraint/WebDriver.php deleted file mode 100644 index 8385979121..0000000000 --- a/src/Codeception/PHPUnit/Constraint/WebDriver.php +++ /dev/null @@ -1,79 +0,0 @@ -string === '') { - return true; - } - - foreach ($nodes as $node) { - /** @var $node \WebDriverElement * */ - if (!$node->isDisplayed()) { - continue; - } - if (parent::matches(htmlspecialchars_decode($node->getText()))) { - return true; - } - } - return false; - } - - protected function fail($nodes, $selector, ComparisonFailure $comparisonFailure = null) - { - if (!count($nodes)) { - throw new ElementNotFound($selector, 'Element located either by name, CSS or XPath'); - } - - $output = "Failed asserting that any element by " . Locator::humanReadableString($selector); - $output .= $this->uriMessage('on page'); - - if (count($nodes) < 5) { - $output .= "\nElements: "; - $output .= $this->nodesList($nodes); - } else { - $message = new Message("[total %s elements]"); - $output .= $message->with(count($nodes)); - } - $output .= "\ncontains text '" . $this->string . "'"; - - throw new \PHPUnit_Framework_ExpectationFailedException( - $output, - $comparisonFailure - ); - } - - protected function failureDescription($nodes) - { - $desc = ''; - foreach ($nodes as $node) { - $desc .= parent::failureDescription($node->getText()); - } - return $desc; - } - - protected function nodesList($nodes, $contains = null) - { - $output = ""; - foreach ($nodes as $node) { - if ($contains && strpos($node->getText(), $contains) === false) { - continue; - } - /** @var $node \WebDriverElement * */ - $message = new Message("\n+ <%s> %s"); - $output .= $message->with($node->getTagName(), $node->getText()); - } - return $output; - } -} diff --git a/src/Codeception/PHPUnit/Constraint/WebDriverNot.php b/src/Codeception/PHPUnit/Constraint/WebDriverNot.php deleted file mode 100644 index fe0612fcfa..0000000000 --- a/src/Codeception/PHPUnit/Constraint/WebDriverNot.php +++ /dev/null @@ -1,41 +0,0 @@ -string) { - throw new \PHPUnit_Framework_ExpectationFailedException( - "Element $selectorString was found", - $comparisonFailure - ); - } - - $output = "There was $selectorString element"; - $output .= $this->uriMessage("on page"); - $output .= $this->nodesList($nodes, $this->string); - $output .= "\ncontaining '{$this->string}'"; - - throw new \PHPUnit_Framework_ExpectationFailedException( - $output, - $comparisonFailure - ); - } - - public function toString() - { - if ($this->string) { - return 'that contains text "' . $this->string . '"'; - } - } -} diff --git a/src/Codeception/PHPUnit/FilterTest.php b/src/Codeception/PHPUnit/FilterTest.php deleted file mode 100644 index cdf8fcf68b..0000000000 --- a/src/Codeception/PHPUnit/FilterTest.php +++ /dev/null @@ -1,31 +0,0 @@ -getInnerIterator()->current(); - - if ($test instanceof \PHPUnit_Framework_TestSuite) { - return true; - } - - $name = Descriptor::getTestSignature($test); - $accepted = preg_match($this->filter, $name, $matches); - - if ($accepted && isset($this->filterMax)) { - $set = end($matches); - $accepted = $set >= $this->filterMin && $set <= $this->filterMax; - } - return $accepted; - } -} diff --git a/src/Codeception/PHPUnit/Listener.php b/src/Codeception/PHPUnit/Listener.php deleted file mode 100644 index 16a6315329..0000000000 --- a/src/Codeception/PHPUnit/Listener.php +++ /dev/null @@ -1,133 +0,0 @@ -dispatcher = $dispatcher; - } - - /** - * Risky test. - * - * @param PHPUnit_Framework_Test $test - * @param Exception $e - * @param float $time - * @since Method available since Release 4.0.0 - */ - public function addRiskyTest(PHPUnit_Framework_Test $test, Exception $e, $time) - { - } - - public function addFailure(\PHPUnit_Framework_Test $test, \PHPUnit_Framework_AssertionFailedError $e, $time) - { - $this->unsuccessfulTests[] = spl_object_hash($test); - $this->fire(Events::TEST_FAIL, new FailEvent($test, $time, $e)); - } - - public function addError(\PHPUnit_Framework_Test $test, \Exception $e, $time) - { - $this->unsuccessfulTests[] = spl_object_hash($test); - $this->fire(Events::TEST_ERROR, new FailEvent($test, $time, $e)); - } - - // This method was added in PHPUnit 6 - public function addWarning(\PhpUnit_Framework_Test $test, \PHPUnit_Framework_Warning $e, $time) - { - } - - public function addIncompleteTest(\PHPUnit_Framework_Test $test, \Exception $e, $time) - { - if (in_array(spl_object_hash($test), $this->skippedTests)) { - return; - } - $this->unsuccessfulTests[] = spl_object_hash($test); - $this->fire(Events::TEST_INCOMPLETE, new FailEvent($test, $time, $e)); - $this->skippedTests[] = spl_object_hash($test); - } - - public function addSkippedTest(\PHPUnit_Framework_Test $test, \Exception $e, $time) - { - if (in_array(spl_object_hash($test), $this->skippedTests)) { - return; - } - $this->unsuccessfulTests[] = spl_object_hash($test); - $this->fire(Events::TEST_SKIPPED, new FailEvent($test, $time, $e)); - $this->skippedTests[] = spl_object_hash($test); - } - - public function startTestSuite(\PHPUnit_Framework_TestSuite $suite) - { - $this->dispatcher->dispatch('suite.start', new SuiteEvent($suite)); - } - - public function endTestSuite(\PHPUnit_Framework_TestSuite $suite) - { - $this->dispatcher->dispatch('suite.end', new SuiteEvent($suite)); - } - - public function startTest(\PHPUnit_Framework_Test $test) - { - $this->dispatcher->dispatch(Events::TEST_START, new TestEvent($test)); - if (!$test instanceof TestInterface) { - return; - } - if ($test->getMetadata()->isBlocked()) { - return; - } - - try { - $this->startedTests[] = spl_object_hash($test); - $this->fire(Events::TEST_BEFORE, new TestEvent($test)); - } catch (\PHPUnit_Framework_IncompleteTestError $e) { - $test->getTestResultObject()->addFailure($test, $e, 0); - } catch (\PHPUnit_Framework_SkippedTestError $e) { - $test->getTestResultObject()->addFailure($test, $e, 0); - } catch (\Exception $e) { - $test->getTestResultObject()->addError($test, $e, 0); - } - } - - public function endTest(\PHPUnit_Framework_Test $test, $time) - { - $hash = spl_object_hash($test); - if (!in_array($hash, $this->unsuccessfulTests)) { - $this->fire(Events::TEST_SUCCESS, new TestEvent($test, $time)); - } - if (in_array($hash, $this->startedTests)) { - $this->fire(Events::TEST_AFTER, new TestEvent($test, $time)); - } - - $this->dispatcher->dispatch(Events::TEST_END, new TestEvent($test, $time)); - } - - protected function fire($event, TestEvent $eventType) - { - $test = $eventType->getTest(); - if ($test instanceof TestInterface) { - foreach ($test->getMetadata()->getGroups() as $group) { - $this->dispatcher->dispatch($event . '.' . $group, $eventType); - } - } - $this->dispatcher->dispatch($event, $eventType); - } -} diff --git a/src/Codeception/PHPUnit/Log/JUnit.php b/src/Codeception/PHPUnit/Log/JUnit.php deleted file mode 100644 index aab1e65244..0000000000 --- a/src/Codeception/PHPUnit/Log/JUnit.php +++ /dev/null @@ -1,43 +0,0 @@ -currentTestCase = $this->document->createElement('testcase'); - - $isStrict = Configuration::config()['settings']['strict_xml']; - - foreach ($test->getReportFields() as $attr => $value) { - if ($isStrict and !in_array($attr, $this->strictAttributes)) { - continue; - } - $this->currentTestCase->setAttribute($attr, $value); - } - } - - public function endTest(\PHPUnit_Framework_Test $test, $time) - { - if ($this->currentTestCase !== null and $test instanceof Test) { - $numAssertions = $test->getNumAssertions(); - $this->testSuiteAssertions[$this->testSuiteLevel] += $numAssertions; - - $this->currentTestCase->setAttribute( - 'assertions', - $numAssertions - ); - } - parent::endTest($test, $time); - } -} diff --git a/src/Codeception/PHPUnit/Overrides/Filter.php b/src/Codeception/PHPUnit/Overrides/Filter.php deleted file mode 100644 index ca425ba02c..0000000000 --- a/src/Codeception/PHPUnit/Overrides/Filter.php +++ /dev/null @@ -1,117 +0,0 @@ -getPrevious() ? $e->getPrevious()->getTrace() : $e->getTrace(); - if ($e instanceof \PHPUnit_Framework_ExceptionWrapper) { - $trace = $e->getSerializableTrace(); - } - - $eFile = $e->getFile(); - $eLine = $e->getLine(); - - if (!self::frameExists($trace, $eFile, $eLine)) { - array_unshift( - $trace, - ['file' => $eFile, 'line' => $eLine] - ); - } - - foreach ($trace as $step) { - if (self::classIsFiltered($step) and $filter) { - continue; - } - if (self::fileIsFiltered($step) and $filter) { - continue; - } - - if (!$asString) { - $stackTrace[] = $step; - continue; - } - if (!isset($step['file'])) { - continue; - } - - $stackTrace .= $step['file'] . ':' . $step['line'] . "\n"; - } - - return $stackTrace; - } - - protected static function classIsFiltered($step) - { - if (!isset($step['class'])) { - return false; - } - $className = $step['class']; - - foreach (self::$filteredClassesPattern as $filteredClassName) { - if (strpos($className, $filteredClassName) === 0) { - return true; - } - } - return false; - } - - protected static function fileIsFiltered($step) - { - if (!isset($step['file'])) { - return false; - } - - if (strpos($step['file'], 'codecept.phar/') !== false) { - return true; - } - - if (strpos($step['file'], 'vendor' . DIRECTORY_SEPARATOR . 'phpunit') !== false) { - return true; - } - - if (strpos($step['file'], 'vendor' . DIRECTORY_SEPARATOR . 'codeception') !== false) { - return true; - } - - $modulePath = 'src' . DIRECTORY_SEPARATOR . 'Codeception' . DIRECTORY_SEPARATOR . 'Module'; - if (strpos($step['file'], $modulePath) !== false) { - return false; // don`t filter modules - } - - if (strpos($step['file'], 'src' . DIRECTORY_SEPARATOR . 'Codeception' . DIRECTORY_SEPARATOR) !== false) { - return true; - } - - return false; - } - - /** - * @param array $trace - * @param string $file - * @param int $line - * - * @return bool - */ - private static function frameExists(array $trace, $file, $line) - { - foreach ($trace as $frame) { - if (isset($frame['file']) && $frame['file'] == $file && - isset($frame['line']) && $frame['line'] == $line) { - return true; - } - } - - return false; - } -} diff --git a/src/Codeception/PHPUnit/README.md b/src/Codeception/PHPUnit/README.md deleted file mode 100644 index 726a02cac5..0000000000 --- a/src/Codeception/PHPUnit/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# PHPUnit Overrides - -Codeception heavily relies on PHPUnit for running and managing tests. -Not all PHPUnit classes fit the needs of Codeception, that's why they were extended or redefined. \ No newline at end of file diff --git a/src/Codeception/PHPUnit/ResultPrinter.php b/src/Codeception/PHPUnit/ResultPrinter.php deleted file mode 100644 index 38cca9549f..0000000000 --- a/src/Codeception/PHPUnit/ResultPrinter.php +++ /dev/null @@ -1,83 +0,0 @@ -testStatus = PHPUnit_Runner_BaseTestRunner::STATUS_ERROR; - $this->failed++; - } - - /** - * A failure occurred. - * - * @param PHPUnit_Framework_Test $test - * @param PHPUnit_Framework_AssertionFailedError $e - * @param float $time - */ - public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time) - { - $this->testStatus = PHPUnit_Runner_BaseTestRunner::STATUS_FAILURE; - $this->failed++; - } - - /** - * Incomplete test. - * - * @param PHPUnit_Framework_Test $test - * @param \Exception $e - * @param float $time - */ - public function addIncompleteTest(PHPUnit_Framework_Test $test, \Exception $e, $time) - { - $this->testStatus = PHPUnit_Runner_BaseTestRunner::STATUS_INCOMPLETE; - $this->incomplete++; - } - - /** - * Risky test. - * - * @param PHPUnit_Framework_Test $test - * @param \Exception $e - * @param float $time - * - * @since Method available since Release 4.0.0 - */ - public function addRiskyTest(PHPUnit_Framework_Test $test, \Exception $e, $time) - { - $this->testStatus = PHPUnit_Runner_BaseTestRunner::STATUS_RISKY; - $this->risky++; - } - - /** - * Skipped test. - * - * @param PHPUnit_Framework_Test $test - * @param \Exception $e - * @param float $time - * - * @since Method available since Release 3.0.0 - */ - public function addSkippedTest(PHPUnit_Framework_Test $test, \Exception $e, $time) - { - $this->testStatus = PHPUnit_Runner_BaseTestRunner::STATUS_SKIPPED; - $this->skipped++; - } - - public function startTest(PHPUnit_Framework_Test $test) - { - $this->testStatus = PHPUnit_Runner_BaseTestRunner::STATUS_PASSED; - } -} diff --git a/src/Codeception/PHPUnit/ResultPrinter/HTML.php b/src/Codeception/PHPUnit/ResultPrinter/HTML.php deleted file mode 100644 index 43038e4a7a..0000000000 --- a/src/Codeception/PHPUnit/ResultPrinter/HTML.php +++ /dev/null @@ -1,303 +0,0 @@ -templatePath = sprintf( - '%s%stemplate%s', - __DIR__, - DIRECTORY_SEPARATOR, - DIRECTORY_SEPARATOR - ); - } - - /** - * Handler for 'start class' event. - * - * @param string $name - */ - protected function startClass($name) - { - } - - public function endTest(\PHPUnit_Framework_Test $test, $time) - { - $steps = []; - $success = ($this->testStatus == \PHPUnit_Runner_BaseTestRunner::STATUS_PASSED); - if ($success) { - $this->successful++; - } - - if ($test instanceof ScenarioDriven) { - $steps = $test->getScenario()->getSteps(); - } - $this->timeTaken += $time; - - switch ($this->testStatus) { - case \PHPUnit_Runner_BaseTestRunner::STATUS_FAILURE: - $scenarioStatus = 'scenarioFailed'; - break; - case \PHPUnit_Runner_BaseTestRunner::STATUS_SKIPPED: - $scenarioStatus = 'scenarioSkipped'; - break; - case \PHPUnit_Runner_BaseTestRunner::STATUS_INCOMPLETE: - $scenarioStatus = 'scenarioIncomplete'; - break; - case \PHPUnit_Runner_BaseTestRunner::STATUS_ERROR: - $scenarioStatus = 'scenarioFailed'; - break; - default: - $scenarioStatus = 'scenarioSuccess'; - } - - $stepsBuffer = ''; - $subStepsBuffer = ''; - $subStepsRendered = []; - - foreach ($steps as $step) { - if ($step->getMetaStep()) { - $subStepsRendered[$step->getMetaStep()->getAction()][] = $this->renderStep($step); - } - } - - foreach ($steps as $step) { - if ($step->getMetaStep()) { - if (! empty($subStepsRendered[$step->getMetaStep()->getAction()])) { - $subStepsBuffer = implode('', $subStepsRendered[$step->getMetaStep()->getAction()]); - unset($subStepsRendered[$step->getMetaStep()->getAction()]); - - $stepsBuffer .= $this->renderSubsteps($step->getMetaStep(), $subStepsBuffer); - } - } else { - $stepsBuffer .= $this->renderStep($step); - } - } - - $scenarioTemplate = new \Text_Template( - $this->templatePath . 'scenario.html' - ); - - $failures = ''; - $name = Descriptor::getTestSignature($test); - if (isset($this->failures[$name])) { - $failTemplate = new \Text_Template( - $this->templatePath . 'fail.html' - ); - foreach ($this->failures[$name] as $failure) { - $failTemplate->setVar(['fail' => nl2br($failure)]); - $failures .= $failTemplate->render() . PHP_EOL; - } - $this->failures[$name] = []; - } - - $png = ''; - $html = ''; - if ($test instanceof TestInterface) { - $reports = $test->getMetadata()->getReports(); - if (isset($reports['png'])) { - $localPath = PathResolver::getRelativeDir($reports['png'], codecept_output_dir()); - $png = "
failure screenshot
"; - } - if (isset($reports['html'])) { - $localPath = PathResolver::getRelativeDir($reports['html'], codecept_output_dir()); - $html = "See HTML snapshot of a failed page"; - } - } - - $toggle = $stepsBuffer ? '+' : ''; - - $testString = htmlspecialchars(ucfirst(Descriptor::getTestAsString($test))); - $testString = preg_replace('~^([\s\w\\\]+):\s~', '$1 » ', $testString); - - $scenarioTemplate->setVar( - [ - 'id' => ++$this->id, - 'name' => $testString, - 'scenarioStatus' => $scenarioStatus, - 'steps' => $stepsBuffer, - 'toggle' => $toggle, - 'failure' => $failures, - 'png' => $png, - 'html' => $html, - 'time' => round($time, 2) - ] - ); - - $this->scenarios .= $scenarioTemplate->render(); - } - - public function startTestSuite(\PHPUnit_Framework_TestSuite $suite) - { - $suiteTemplate = new \Text_Template( - $this->templatePath . 'suite.html' - ); - if (!$suite->getName()) { - return; - } - - $suiteTemplate->setVar(['suite' => ucfirst($suite->getName())]); - - $this->scenarios .= $suiteTemplate->render(); - } - - /** - * Handler for 'end run' event. - */ - protected function endRun() - { - $scenarioHeaderTemplate = new \Text_Template( - $this->templatePath . 'scenario_header.html' - ); - - $status = !$this->failed - ? 'OK' - : 'FAILED'; - - - $scenarioHeaderTemplate->setVar( - [ - 'name' => 'Codeception Results', - 'status' => $status, - 'time' => round($this->timeTaken, 1) - ] - ); - - $header = $scenarioHeaderTemplate->render(); - - $scenariosTemplate = new \Text_Template( - $this->templatePath . 'scenarios.html' - ); - - $scenariosTemplate->setVar( - [ - 'header' => $header, - 'scenarios' => $this->scenarios, - 'successfulScenarios' => $this->successful, - 'failedScenarios' => $this->failed, - 'skippedScenarios' => $this->skipped, - 'incompleteScenarios' => $this->incomplete - ] - ); - - $this->write($scenariosTemplate->render()); - } - - /** - * An error occurred. - * - * @param \PHPUnit_Framework_Test $test - * @param \Exception $e - * @param float $time - */ - public function addError(\PHPUnit_Framework_Test $test, \Exception $e, $time) - { - $this->failures[Descriptor::getTestSignature($test)][] = $this->cleanMessage($e); - parent::addError($test, $e, $time); - } - - /** - * A failure occurred. - * - * @param \PHPUnit_Framework_Test $test - * @param \PHPUnit_Framework_AssertionFailedError $e - * @param float $time - */ - public function addFailure(\PHPUnit_Framework_Test $test, \PHPUnit_Framework_AssertionFailedError $e, $time) - { - $this->failures[Descriptor::getTestSignature($test)][] = $this->cleanMessage($e); - parent::addFailure($test, $e, $time); - } - - /** - * Starts test. - * - * @param \PHPUnit_Framework_Test $test - */ - public function startTest(\PHPUnit_Framework_Test $test) - { - $name = Descriptor::getTestSignature($test); - if (isset($this->failures[$name])) { - // test failed in before hook - return; - } - - // start test and mark initialize as passed - parent::startTest($test); - } - - - /** - * @param $step - * @return string - */ - protected function renderStep(Step $step) - { - $stepTemplate = new \Text_Template($this->templatePath . 'step.html'); - $stepTemplate->setVar(['action' => $step->getHtml(), 'error' => $step->hasFailed() ? 'failedStep' : '']); - return $stepTemplate->render(); - } - - /** - * @param $metaStep - * @param $substepsBuffer - * @return string - */ - protected function renderSubsteps(Meta $metaStep, $substepsBuffer) - { - $metaTemplate = new \Text_Template($this->templatePath . 'substeps.html'); - $metaTemplate->setVar(['metaStep' => $metaStep->getHtml(), 'error' => $metaStep->hasFailed() ? 'failedStep' : '', 'steps' => $substepsBuffer, 'id' => uniqid()]); - return $metaTemplate->render(); - } - - private function cleanMessage($exception) - { - $msg = $exception->getMessage(); - $msg = str_replace(['','','',''], ['','','',''], $msg); - return htmlentities($msg); - } -} diff --git a/src/Codeception/PHPUnit/ResultPrinter/Report.php b/src/Codeception/PHPUnit/ResultPrinter/Report.php deleted file mode 100644 index 018f39fcc3..0000000000 --- a/src/Codeception/PHPUnit/ResultPrinter/Report.php +++ /dev/null @@ -1,58 +0,0 @@ -testStatus == \PHPUnit_Runner_BaseTestRunner::STATUS_PASSED); - if ($success) { - $this->successful++; - } - - if ($this->testStatus == \PHPUnit_Runner_BaseTestRunner::STATUS_FAILURE) { - $status = "\033[41;37mFAIL\033[0m"; - } elseif ($this->testStatus == \PHPUnit_Runner_BaseTestRunner::STATUS_SKIPPED) { - $status = 'Skipped'; - } elseif ($this->testStatus == \PHPUnit_Runner_BaseTestRunner::STATUS_INCOMPLETE) { - $status = 'Incomplete'; - } elseif ($this->testStatus == \PHPUnit_Runner_BaseTestRunner::STATUS_ERROR) { - $status = 'ERROR'; - } else { - $status = 'Ok'; - } - - if (strlen($name) > 75) { - $name = substr($name, 0, 70); - } - $line = $name . str_repeat('.', 75 - strlen($name)); - $line .= $status; - - $this->write($line . "\n"); - } - - protected function endRun() - { - $this->write("\nCodeception Results\n"); - $this->write(sprintf( - "Successful: %s. Failed: %s. Incomplete: %s. Skipped: %s", - $this->successful, - $this->failed, - $this->skipped, - $this->incomplete - ) . "\n"); - } - - public function printResult(\PHPUnit_Framework_TestResult $result) - { - } -} diff --git a/src/Codeception/PHPUnit/ResultPrinter/UI.php b/src/Codeception/PHPUnit/ResultPrinter/UI.php deleted file mode 100644 index 9200eaca8a..0000000000 --- a/src/Codeception/PHPUnit/ResultPrinter/UI.php +++ /dev/null @@ -1,95 +0,0 @@ - OutputInterface::VERBOSITY_NORMAL, $options['colors'] ? 'always' : 'never'); - $this->dispatcher = $dispatcher; - } - - protected function printDefect(\PHPUnit_Framework_TestFailure $defect, $count) - { - $this->write("\n---------\n"); - $this->dispatcher->dispatch( - Events::TEST_FAIL_PRINT, - new FailEvent($defect->failedTest(), null, $defect->thrownException(), $count) - ); - } - - /** - * @param \PHPUnit_Framework_TestFailure $defect - */ - protected function printDefectTrace(\PHPUnit_Framework_TestFailure $defect) - { - $this->write($defect->getExceptionAsString()); - $this->writeNewLine(); - - $stackTrace = \PHPUnit_Util_Filter::getFilteredStacktrace($defect->thrownException(), false); - - foreach ($stackTrace as $i => $frame) { - if (!isset($frame['file'])) { - continue; - } - - $this->write( - sprintf( - "#%d %s(%s)", - $i + 1, - $frame['file'], - isset($frame['line']) ? $frame['line'] : '?' - ) - ); - - $this->writeNewLine(); - } - } - - public function startTest(\PHPUnit_Framework_Test $test) - { - if ($test instanceof Unit) { - parent::startTest($test); - } - } - - public function endTest(\PHPUnit_Framework_Test $test, $time) - { - if ($test instanceof \PHPUnit_Framework_TestCase or $test instanceof \Codeception\Test\Test) { - $this->numAssertions += $test->getNumAssertions(); - } - - $this->lastTestFailed = false; - } - - public function addError(\PHPUnit_Framework_Test $test, \Exception $e, $time) - { - $this->lastTestFailed = true; - } - - public function addFailure(\PHPUnit_Framework_Test $test, \PHPUnit_Framework_AssertionFailedError $e, $time) - { - $this->lastTestFailed = true; - } - - public function addIncompleteTest(\PHPUnit_Framework_Test $test, \Exception $e, $time) - { - $this->lastTestFailed = true; - } - - public function addSkippedTest(\PHPUnit_Framework_Test $test, \Exception $e, $time) - { - $this->lastTestFailed = true; - } -} diff --git a/src/Codeception/PHPUnit/ResultPrinter/template/fail.html.dist b/src/Codeception/PHPUnit/ResultPrinter/template/fail.html.dist deleted file mode 100644 index b4a4f235bd..0000000000 --- a/src/Codeception/PHPUnit/ResultPrinter/template/fail.html.dist +++ /dev/null @@ -1,5 +0,0 @@ - - - {fail} - - \ No newline at end of file diff --git a/src/Codeception/PHPUnit/ResultPrinter/template/scenario.html.dist b/src/Codeception/PHPUnit/ResultPrinter/template/scenario.html.dist deleted file mode 100644 index d0b8c7a375..0000000000 --- a/src/Codeception/PHPUnit/ResultPrinter/template/scenario.html.dist +++ /dev/null @@ -1,22 +0,0 @@ - - -

{toggle} - {name} {time}s

- - - - - - - -{steps} - {failure} - {png} - {html} -
- - - - - - diff --git a/src/Codeception/PHPUnit/ResultPrinter/template/scenario_header.html.dist b/src/Codeception/PHPUnit/ResultPrinter/template/scenario_header.html.dist deleted file mode 100644 index 92f2a26108..0000000000 --- a/src/Codeception/PHPUnit/ResultPrinter/template/scenario_header.html.dist +++ /dev/null @@ -1,2 +0,0 @@ -

{name} {status} ({time}s)

- diff --git a/src/Codeception/PHPUnit/ResultPrinter/template/scenarios.html.dist b/src/Codeception/PHPUnit/ResultPrinter/template/scenarios.html.dist deleted file mode 100644 index 2179c76d3c..0000000000 --- a/src/Codeception/PHPUnit/ResultPrinter/template/scenarios.html.dist +++ /dev/null @@ -1,250 +0,0 @@ - - - Test results - - - - - - - - - - -
- {header} - - - {scenarios} - - - -
-

Summary

-
- - - - - - - - - - - - - - - - - -
Successful scenarios:{successfulScenarios}
Failed scenarios:{failedScenarios}
Skipped scenarios:{skippedScenarios}
Incomplete scenarios:{incompleteScenarios}
-
-
-
- - diff --git a/src/Codeception/PHPUnit/ResultPrinter/template/step.html.dist b/src/Codeception/PHPUnit/ResultPrinter/template/step.html.dist deleted file mode 100644 index 0b67a55efb..0000000000 --- a/src/Codeception/PHPUnit/ResultPrinter/template/step.html.dist +++ /dev/null @@ -1,4 +0,0 @@ - -     {action} - - diff --git a/src/Codeception/PHPUnit/ResultPrinter/template/substeps.html.dist b/src/Codeception/PHPUnit/ResultPrinter/template/substeps.html.dist deleted file mode 100644 index 38f60eeac6..0000000000 --- a/src/Codeception/PHPUnit/ResultPrinter/template/substeps.html.dist +++ /dev/null @@ -1,12 +0,0 @@ - -

+ {metaStep}

- - - - - - - {steps} -
- - diff --git a/src/Codeception/PHPUnit/ResultPrinter/template/suite.html.dist b/src/Codeception/PHPUnit/ResultPrinter/template/suite.html.dist deleted file mode 100644 index acedfb8510..0000000000 --- a/src/Codeception/PHPUnit/ResultPrinter/template/suite.html.dist +++ /dev/null @@ -1,5 +0,0 @@ - - -

{suite} Tests

- - \ No newline at end of file diff --git a/src/Codeception/PHPUnit/Runner.php b/src/Codeception/PHPUnit/Runner.php deleted file mode 100644 index 2b36a3914c..0000000000 --- a/src/Codeception/PHPUnit/Runner.php +++ /dev/null @@ -1,184 +0,0 @@ - false, - 'html' => false, - 'tap' => false, - 'json' => false, - 'report' => false - ]; - - protected $config = []; - - protected $logDir = null; - - public function __construct() - { - $this->config = Configuration::config(); - $this->logDir = Configuration::outputDir(); // prepare log dir - $this->phpUnitOverriders(); - parent::__construct(); - } - - public function phpUnitOverriders() - { - require_once __DIR__ . DIRECTORY_SEPARATOR . 'Overrides/Filter.php'; - } - - /** - * @return null|\PHPUnit_TextUI_ResultPrinter - */ - public function getPrinter() - { - return $this->printer; - } - - public function prepareSuite(\PHPUnit_Framework_Test $suite, array &$arguments) - { - $this->handleConfiguration($arguments); - - $filterFactory = new \PHPUnit_Runner_Filter_Factory(); - if ($arguments['groups']) { - $filterFactory->addFilter( - new \ReflectionClass('PHPUnit_Runner_Filter_Group_Include'), - $arguments['groups'] - ); - } - - if ($arguments['excludeGroups']) { - $filterFactory->addFilter( - new \ReflectionClass('PHPUnit_Runner_Filter_Group_Exclude'), - $arguments['excludeGroups'] - ); - } - - if ($arguments['filter']) { - $filterFactory->addFilter( - new \ReflectionClass('Codeception\PHPUnit\FilterTest'), - $arguments['filter'] - ); - } - - $suite->injectFilter($filterFactory); - } - - public function doEnhancedRun( - \PHPUnit_Framework_Test $suite, - \PHPUnit_Framework_TestResult $result, - array $arguments = [] - ) { - unset($GLOBALS['app']); // hook for not to serialize globals - - $result->convertErrorsToExceptions(false); - - if (isset($arguments['report_useless_tests'])) { - $result->beStrictAboutTestsThatDoNotTestAnything((bool)$arguments['report_useless_tests']); - } - - if (isset($arguments['disallow_test_output'])) { - $result->beStrictAboutOutputDuringTests((bool)$arguments['disallow_test_output']); - } - - if (empty(self::$persistentListeners)) { - $this->applyReporters($result, $arguments); - } - - if (class_exists('\Symfony\Bridge\PhpUnit\SymfonyTestsListener')) { - $arguments['listeners'] = isset($arguments['listeners']) ? $arguments['listeners'] : []; - $arguments['listeners'][] = new \Symfony\Bridge\PhpUnit\SymfonyTestsListener(); - } - - $arguments['listeners'][] = $this->printer; - - // clean up listeners between suites - foreach ($arguments['listeners'] as $listener) { - $result->addListener($listener); - } - - $suite->run($result); - unset($suite); - - foreach ($arguments['listeners'] as $listener) { - $result->removeListener($listener); - } - - return $result; - } - - /** - * @param \PHPUnit_Framework_TestResult $result - * @param array $arguments - * - * @return array - */ - protected function applyReporters(\PHPUnit_Framework_TestResult $result, array $arguments) - { - foreach ($this->defaultListeners as $listener => $value) { - if (!isset($arguments[$listener])) { - $arguments[$listener] = $value; - } - } - - if ($arguments['report']) { - self::$persistentListeners[] = $this->instantiateReporter('report'); - } - - if ($arguments['html']) { - codecept_debug('Printing HTML report into ' . $arguments['html']); - self::$persistentListeners[] = $this->instantiateReporter( - 'html', - [$this->absolutePath($arguments['html'])] - ); - } - if ($arguments['xml']) { - codecept_debug('Printing JUNIT report into ' . $arguments['xml']); - self::$persistentListeners[] = $this->instantiateReporter( - 'xml', - [$this->absolutePath($arguments['xml']), (bool)$arguments['log_incomplete_skipped']] - ); - } - if ($arguments['tap']) { - codecept_debug('Printing TAP report into ' . $arguments['tap']); - self::$persistentListeners[] = $this->instantiateReporter('tap', [$this->absolutePath($arguments['tap'])]); - } - if ($arguments['json']) { - codecept_debug('Printing JSON report into ' . $arguments['json']); - self::$persistentListeners[] = $this->instantiateReporter( - 'json', - [$this->absolutePath($arguments['json'])] - ); - } - - foreach (self::$persistentListeners as $listener) { - if ($listener instanceof ConsolePrinter) { - $this->printer = $listener; - continue; - } - $result->addListener($listener); - } - } - - protected function instantiateReporter($name, $args = []) - { - if (!isset($this->config['reporters'][$name])) { - throw new ConfigurationException("Reporter $name not defined"); - } - return (new \ReflectionClass($this->config['reporters'][$name]))->newInstanceArgs($args); - } - - private function absolutePath($path) - { - if ((strpos($path, '/') === 0) or (strpos($path, ':') === 1)) { // absolute path - return $path; - } - return $this->logDir . $path; - } -} diff --git a/src/Codeception/README.md b/src/Codeception/README.md index a6cc8828f6..db54b5072a 100644 --- a/src/Codeception/README.md +++ b/src/Codeception/README.md @@ -7,4 +7,4 @@ The most important classes are defined in root of Codeception. * `TestLoader` - loads tests from files * `Configuration` - loads YAML configuration * `Events` - defines all Codeception events -* `TestCase` - applies Codeception feature to `PHPUnit_Framework_TestCase` class. \ No newline at end of file +* `TestCase` - applies Codeception feature to `PHPUnit\Framework\TestCase` class. \ No newline at end of file diff --git a/src/Codeception/Scenario.php b/src/Codeception/Scenario.php index 60fb72596f..22535020f7 100644 --- a/src/Codeception/Scenario.php +++ b/src/Codeception/Scenario.php @@ -136,12 +136,12 @@ public function comment($comment) public function skip($message = '') { - throw new \PHPUnit_Framework_SkippedTestError($message); + throw new \PHPUnit\Framework\SkippedTestError($message); } public function incomplete($message = '') { - throw new \PHPUnit_Framework_IncompleteTestError($message); + throw new \PHPUnit\Framework\IncompleteTestError($message); } public function __call($method, $args) diff --git a/src/Codeception/Step/ConditionalAssertion.php b/src/Codeception/Step/ConditionalAssertion.php index 2940e61c92..574af549b9 100644 --- a/src/Codeception/Step/ConditionalAssertion.php +++ b/src/Codeception/Step/ConditionalAssertion.php @@ -10,7 +10,7 @@ public function run(ModuleContainer $container = null) { try { parent::run($container); - } catch (\PHPUnit_Framework_AssertionFailedError $e) { + } catch (\PHPUnit\Framework\AssertionFailedError $e) { throw new ConditionalAssertionFailed($e->getMessage(), $e->getCode(), $e); } } diff --git a/src/Codeception/Step/Incomplete.php b/src/Codeception/Step/Incomplete.php index f3c11c78ad..3db8d949e4 100644 --- a/src/Codeception/Step/Incomplete.php +++ b/src/Codeception/Step/Incomplete.php @@ -8,7 +8,7 @@ class Incomplete extends CodeceptionStep { public function run(ModuleContainer $container = null) { - throw new \PHPUnit_Framework_IncompleteTestError($this->getAction()); + throw new \PHPUnit\Framework\IncompleteTestError($this->getAction()); } public function __toString() diff --git a/src/Codeception/Step/Skip.php b/src/Codeception/Step/Skip.php index 10b84c0dd8..558f31080e 100644 --- a/src/Codeception/Step/Skip.php +++ b/src/Codeception/Step/Skip.php @@ -8,7 +8,7 @@ class Skip extends CodeceptionStep { public function run(ModuleContainer $container = null) { - throw new \PHPUnit_Framework_SkippedTestError($this->getAction()); + throw new \PHPUnit\Framework\SkippedTestError($this->getAction()); } public function __toString() diff --git a/src/Codeception/Subscriber/BeforeAfterTest.php b/src/Codeception/Subscriber/BeforeAfterTest.php index c5d8466ea2..414b1aa2a7 100644 --- a/src/Codeception/Subscriber/BeforeAfterTest.php +++ b/src/Codeception/Subscriber/BeforeAfterTest.php @@ -21,14 +21,14 @@ class BeforeAfterTest implements EventSubscriberInterface public function beforeClass(SuiteEvent $e) { foreach ($e->getSuite()->tests() as $test) { - /** @var $test \PHPUnit_Framework_Test * */ - if ($test instanceof \PHPUnit_Framework_TestSuite_DataProvider) { + /** @var $test \PHPUnit\Framework\Test * */ + if ($test instanceof \PHPUnit\Framework\TestSuite\DataProvider) { $potentialTestClass = strstr($test->getName(), '::', true); - $this->hooks[$potentialTestClass] = \PHPUnit_Util_Test::getHookMethods($potentialTestClass); + $this->hooks[$potentialTestClass] = \PHPUnit\Util\Test::getHookMethods($potentialTestClass); } $testClass = get_class($test); - $this->hooks[$testClass] = \PHPUnit_Util_Test::getHookMethods($testClass); + $this->hooks[$testClass] = \PHPUnit\Util\Test::getHookMethods($testClass); } $this->runHooks('beforeClass'); } diff --git a/src/Codeception/Subscriber/Console.php b/src/Codeception/Subscriber/Console.php index ddf9f99d99..707f3ddd87 100644 --- a/src/Codeception/Subscriber/Console.php +++ b/src/Codeception/Subscriber/Console.php @@ -362,7 +362,7 @@ public function printFail(FailEvent $e) public function printException($e, $cause = null) { - if ($e instanceof \PHPUnit_Framework_SkippedTestError or $e instanceof \PHPUnit_Framework_IncompleteTestError) { + if ($e instanceof \PHPUnit\Framework\SkippedTestError or $e instanceof \PHPUnit\Framework_IncompleteTestError) { if ($e->getMessage()) { $this->message(OutputFormatter::escape($e->getMessage()))->prepend("\n")->writeln(); } @@ -370,7 +370,7 @@ public function printException($e, $cause = null) return; } - $class = $e instanceof \PHPUnit_Framework_ExceptionWrapper + $class = $e instanceof \PHPUnit\Framework\ExceptionWrapper ? $e->getClassname() : get_class($e); @@ -381,16 +381,16 @@ public function printException($e, $cause = null) $this->output->writeln(''); $message = $this->message(OutputFormatter::escape($e->getMessage())); - if ($e instanceof \PHPUnit_Framework_ExpectationFailedException) { + if ($e instanceof \PHPUnit\Framework\ExpectationFailedException) { $comparisonFailure = $e->getComparisonFailure(); if ($comparisonFailure) { $message->append($this->messageFactory->prepareComparisonFailureMessage($comparisonFailure)); } } - $isFailure = $e instanceof \PHPUnit_Framework_AssertionFailedError - || $class === 'PHPUnit_Framework_ExpectationFailedException' - || $class === 'PHPUnit_Framework_AssertionFailedError'; + $isFailure = $e instanceof \PHPUnit\Framework\AssertionFailedError + || $class === 'PHPUnit\Framework\ExpectationFailedException' + || $class === 'PHPUnit\Framework\AssertionFailedError'; if (!$isFailure) { $message->prepend("[$class] ")->block('error'); @@ -423,7 +423,7 @@ public function printScenarioFail(ScenarioDriven $failedTest, $fail) return; } - if (!$fail instanceof \PHPUnit_Framework_AssertionFailedError) { + if (!$fail instanceof \PHPUnit\Framework\AssertionFailedError) { $this->printExceptionTrace($fail); return; @@ -434,17 +434,17 @@ public function printExceptionTrace(\Exception $e) { static $limit = 10; - if ($e instanceof \PHPUnit_Framework_SkippedTestError or $e instanceof \PHPUnit_Framework_IncompleteTestError) { + if ($e instanceof \PHPUnit\Framework\SkippedTestError or $e instanceof \PHPUnit\Framework_IncompleteTestError) { return; } if ($this->rawStackTrace) { - $this->message(OutputFormatter::escape(\PHPUnit_Util_Filter::getFilteredStacktrace($e, true, false)))->writeln(); + $this->message(OutputFormatter::escape(\PHPUnit\Util\Filter::getFilteredStacktrace($e, true, false)))->writeln(); return; } - $trace = \PHPUnit_Util_Filter::getFilteredStacktrace($e, false); + $trace = \PHPUnit\Util\Filter::getFilteredStacktrace($e, false); $i = 0; foreach ($trace as $step) { @@ -555,10 +555,10 @@ private function isWin() } /** - * @param \PHPUnit_Framework_SelfDescribing $test + * @param \PHPUnit\Framework\SelfDescribing $test * @param bool $inProgress */ - protected function writeCurrentTest(\PHPUnit_Framework_SelfDescribing $test, $inProgress = true) + protected function writeCurrentTest(\PHPUnit\Framework\SelfDescribing $test, $inProgress = true) { $prefix = ($this->output->isInteractive() and !$this->isDetailed($test) and $inProgress) ? '- ' : ''; diff --git a/src/Codeception/Subscriber/ErrorHandler.php b/src/Codeception/Subscriber/ErrorHandler.php index e8b380201d..9d1f3d7e59 100644 --- a/src/Codeception/Subscriber/ErrorHandler.php +++ b/src/Codeception/Subscriber/ErrorHandler.php @@ -80,7 +80,7 @@ public function errorHandler($errno, $errstr, $errfile, $errline, $context = arr return false; } - throw new \PHPUnit_Framework_Exception($errstr, $errno); + throw new \PHPUnit\Framework\Exception($errstr, $errno); } public function shutdownHandler() @@ -117,7 +117,7 @@ public function shutdownHandler() private function registerDeprecationErrorHandler() { if (class_exists('\Symfony\Bridge\PhpUnit\DeprecationErrorHandler') && 'disabled' !== getenv('SYMFONY_DEPRECATIONS_HELPER')) { - // DeprecationErrorHandler only will be installed if array('PHPUnit_Util_ErrorHandler', 'handleError') + // DeprecationErrorHandler only will be installed if array('PHPUnit\Util\ErrorHandler', 'handleError') // is installed or no other error handlers are installed. // So we will remove Symfony\Component\Debug\ErrorHandler if it's installed. $old = set_error_handler('var_dump'); diff --git a/src/Codeception/Suite.php b/src/Codeception/Suite.php index e1acf80e30..509e66627c 100644 --- a/src/Codeception/Suite.php +++ b/src/Codeception/Suite.php @@ -4,7 +4,7 @@ use Codeception\Test\Descriptor; use Codeception\Test\Interfaces\Dependent; -class Suite extends \PHPUnit_Framework_TestSuite +class Suite extends \PHPUnit\Framework\TestSuite { protected $modules; protected $baseName; diff --git a/src/Codeception/SuiteManager.php b/src/Codeception/SuiteManager.php index deaa1dd610..748ca8f114 100644 --- a/src/Codeception/SuiteManager.php +++ b/src/Codeception/SuiteManager.php @@ -16,7 +16,7 @@ class SuiteManager public static $name; /** - * @var \PHPUnit_Framework_TestSuite + * @var \PHPUnit\Framework\TestSuite */ protected $suite = null; @@ -108,7 +108,7 @@ protected function addToSuite($test) { $this->configureTest($test); - if ($test instanceof \PHPUnit_Framework_TestSuite_DataProvider) { + if ($test instanceof \PHPUnit\Framework\DataProviderTestSuite) { foreach ($test->tests() as $t) { $this->addToSuite($t); } @@ -150,7 +150,7 @@ protected function createSuite($name) } - public function run(PHPUnit\Runner $runner, \PHPUnit_Framework_TestResult $result, $options) + public function run(PHPUnit\Runner $runner, \PHPUnit\Framework\TestResult $result, $options) { $runner->prepareSuite($this->suite, $options); $this->dispatcher->dispatch(Events::SUITE_BEFORE, new Event\SuiteEvent($this->suite, $result, $this->settings)); diff --git a/src/Codeception/Test/Cest.php b/src/Codeception/Test/Cest.php index 85028ebd9c..cb2a130f83 100644 --- a/src/Codeception/Test/Cest.php +++ b/src/Codeception/Test/Cest.php @@ -98,7 +98,7 @@ protected function executeHook($I, $hook) protected function executeBeforeMethods($testMethod, $I) { - $annotations = \PHPUnit_Util_Test::parseTestMethodAnnotations(get_class($this->testClassInstance), $testMethod); + $annotations = \PHPUnit\Util\Test::parseTestMethodAnnotations(get_class($this->testClassInstance), $testMethod); if (!empty($annotations['method']['before'])) { foreach ($annotations['method']['before'] as $m) { $this->executeContextMethod(trim($m), $I); @@ -107,7 +107,7 @@ protected function executeBeforeMethods($testMethod, $I) } protected function executeAfterMethods($testMethod, $I) { - $annotations = \PHPUnit_Util_Test::parseTestMethodAnnotations(get_class($this->testClassInstance), $testMethod); + $annotations = \PHPUnit\Util\Test::parseTestMethodAnnotations(get_class($this->testClassInstance), $testMethod); if (!empty($annotations['method']['after'])) { foreach ($annotations['method']['after'] as $m) { $this->executeContextMethod(trim($m), $I); @@ -203,7 +203,7 @@ public function getLinesToBeCovered() $class = get_class($this->getTestClass()); $method = $this->getTestMethod(); - return \PHPUnit_Util_Test::getLinesToBeCovered($class, $method); + return \PHPUnit\Util\Test::getLinesToBeCovered($class, $method); } public function getLinesToBeUsed() @@ -211,6 +211,6 @@ public function getLinesToBeUsed() $class = get_class($this->getTestClass()); $method = $this->getTestMethod(); - return \PHPUnit_Util_Test::getLinesToBeUsed($class, $method); + return \PHPUnit\Util\Test::getLinesToBeUsed($class, $method); } } diff --git a/src/Codeception/Test/Descriptor.php b/src/Codeception/Test/Descriptor.php index 9050e76682..c68a6e0ef3 100644 --- a/src/Codeception/Test/Descriptor.php +++ b/src/Codeception/Test/Descriptor.php @@ -10,15 +10,15 @@ class Descriptor /** * Provides a test name which can be located by * - * @param \PHPUnit_Framework_SelfDescribing $testCase + * @param \PHPUnit\Framework\SelfDescribing $testCase * @return string */ - public static function getTestSignature(\PHPUnit_Framework_SelfDescribing $testCase) + public static function getTestSignature(\PHPUnit\Framework\SelfDescribing $testCase) { if ($testCase instanceof Descriptive) { return $testCase->getSignature(); } - if ($testCase instanceof \PHPUnit_Framework_TestCase) { + if ($testCase instanceof \PHPUnit\Framework\TestCase) { return get_class($testCase) . ':' . $testCase->getName(false); } return $testCase->toString(); @@ -27,10 +27,10 @@ public static function getTestSignature(\PHPUnit_Framework_SelfDescribing $testC /** * Provides a test name which is unique for individual iterations of tests using examples * - * @param \PHPUnit_Framework_SelfDescribing $testCase + * @param \PHPUnit\Framework\SelfDescribing $testCase * @return string */ - public static function getTestSignatureUnique(\PHPUnit_Framework_SelfDescribing $testCase) + public static function getTestSignatureUnique(\PHPUnit\Framework\SelfDescribing $testCase) { $example = null; @@ -43,9 +43,9 @@ public static function getTestSignatureUnique(\PHPUnit_Framework_SelfDescribing return self::getTestSignature($testCase) . $example; } - public static function getTestAsString(\PHPUnit_Framework_SelfDescribing $testCase) + public static function getTestAsString(\PHPUnit\Framework\SelfDescribing $testCase) { - if ($testCase instanceof \PHPUnit_Framework_TestCase) { + if ($testCase instanceof \PHPUnit\Framework\TestCase) { $text = $testCase->getName(); $text = preg_replace('/([A-Z]+)([A-Z][a-z])/', '\\1 \\2', $text); $text = preg_replace('/([a-z\d])([A-Z])/', '\\1 \\2', $text); @@ -61,10 +61,10 @@ public static function getTestAsString(\PHPUnit_Framework_SelfDescribing $testCa /** * Provides a test file name relative to Codeception root * - * @param \PHPUnit_Framework_SelfDescribing $testCase + * @param \PHPUnit\Framework\SelfDescribing $testCase * @return mixed */ - public static function getTestFileName(\PHPUnit_Framework_SelfDescribing $testCase) + public static function getTestFileName(\PHPUnit\Framework\SelfDescribing $testCase) { if ($testCase instanceof Descriptive) { return codecept_relative_path(realpath($testCase->getFileName())); @@ -73,10 +73,10 @@ public static function getTestFileName(\PHPUnit_Framework_SelfDescribing $testCa } /** - * @param \PHPUnit_Framework_SelfDescribing $testCase + * @param \PHPUnit\Framework\SelfDescribing $testCase * @return mixed|string */ - public static function getTestFullName(\PHPUnit_Framework_SelfDescribing $testCase) + public static function getTestFullName(\PHPUnit\Framework\SelfDescribing $testCase) { if ($testCase instanceof Plain) { return self::getTestFileName($testCase); @@ -85,7 +85,7 @@ public static function getTestFullName(\PHPUnit_Framework_SelfDescribing $testCa $signature = $testCase->getSignature(); // cut everything before ":" from signature return self::getTestFileName($testCase) . ':' . preg_replace('~^(.*?):~', '', $signature); } - if ($testCase instanceof \PHPUnit_Framework_TestCase) { + if ($testCase instanceof \PHPUnit\Framework\TestCase) { return self::getTestFileName($testCase) . ':' . $testCase->getName(false); } return self::getTestFileName($testCase) . ':' . $testCase->toString(); diff --git a/src/Codeception/Test/Feature/AssertionCounter.php b/src/Codeception/Test/Feature/AssertionCounter.php index 22d1f6c607..ad7c292893 100644 --- a/src/Codeception/Test/Feature/AssertionCounter.php +++ b/src/Codeception/Test/Feature/AssertionCounter.php @@ -12,11 +12,11 @@ public function getNumAssertions() protected function assertionCounterStart() { - \PHPUnit_Framework_Assert::resetCount(); + \PHPUnit\Framework\Assert::resetCount(); } protected function assertionCounterEnd() { - $this->numAssertions = \PHPUnit_Framework_Assert::getCount(); + $this->numAssertions = \PHPUnit\Framework\Assert::getCount(); } } diff --git a/src/Codeception/Test/Feature/CodeCoverage.php b/src/Codeception/Test/Feature/CodeCoverage.php index 4c5d4a2202..4357068b77 100644 --- a/src/Codeception/Test/Feature/CodeCoverage.php +++ b/src/Codeception/Test/Feature/CodeCoverage.php @@ -7,7 +7,7 @@ trait CodeCoverage { /** - * @return \PHPUnit_Framework_TestResult + * @return \PHPUnit\Framework\TestResult */ abstract public function getTestResultObject(); diff --git a/src/Codeception/Test/Feature/ErrorLogger.php b/src/Codeception/Test/Feature/ErrorLogger.php index 7400d13e09..7b1b846c9c 100644 --- a/src/Codeception/Test/Feature/ErrorLogger.php +++ b/src/Codeception/Test/Feature/ErrorLogger.php @@ -6,7 +6,7 @@ trait ErrorLogger { /** - * @return \PHPUnit_Framework_TestResult + * @return \PHPUnit\Framework\TestResult */ abstract public function getTestResultObject(); diff --git a/src/Codeception/Test/Feature/IgnoreIfMetadataBlocked.php b/src/Codeception/Test/Feature/IgnoreIfMetadataBlocked.php index eebdb04f4c..63ce3a04c0 100644 --- a/src/Codeception/Test/Feature/IgnoreIfMetadataBlocked.php +++ b/src/Codeception/Test/Feature/IgnoreIfMetadataBlocked.php @@ -13,7 +13,7 @@ abstract protected function getMetadata(); abstract protected function ignore($ignored); /** - * @return \PHPUnit_Framework_TestResult + * @return \PHPUnit\Framework\TestResult */ abstract protected function getTestResultObject(); @@ -26,11 +26,11 @@ protected function ignoreIfMetadataBlockedStart() $this->ignore(true); if ($this->getMetadata()->getSkip() !== null) { - $this->getTestResultObject()->addFailure($this, new \PHPUnit_Framework_SkippedTestError((string)$this->getMetadata()->getSkip()), 0); + $this->getTestResultObject()->addFailure($this, new \PHPUnit\Framework\SkippedTestError((string)$this->getMetadata()->getSkip()), 0); return; } if ($this->getMetadata()->getIncomplete() !== null) { - $this->getTestResultObject()->addFailure($this, new \PHPUnit_Framework_IncompleteTestError((string)$this->getMetadata()->getIncomplete()), 0); + $this->getTestResultObject()->addFailure($this, new \PHPUnit\Framework\IncompleteTestError((string)$this->getMetadata()->getIncomplete()), 0); return; } } diff --git a/src/Codeception/Test/Interfaces/Descriptive.php b/src/Codeception/Test/Interfaces/Descriptive.php index 015748d836..fa1b2e0454 100644 --- a/src/Codeception/Test/Interfaces/Descriptive.php +++ b/src/Codeception/Test/Interfaces/Descriptive.php @@ -1,7 +1,7 @@ $example) { if ($example === null) { throw new TestParseException( diff --git a/src/Codeception/Test/Loader/Unit.php b/src/Codeception/Test/Loader/Unit.php index d72984e177..3e1235a5d5 100644 --- a/src/Codeception/Test/Loader/Unit.php +++ b/src/Codeception/Test/Loader/Unit.php @@ -43,12 +43,12 @@ public function getTests() protected function createTestFromPhpUnitMethod(\ReflectionClass $class, \ReflectionMethod $method) { - if (!\PHPUnit_Framework_TestSuite::isTestMethod($method)) { + if (!\PHPUnit\Framework\TestSuite::isTestMethod($method)) { return; } - $test = \PHPUnit_Framework_TestSuite::createTest($class, $method->name); + $test = \PHPUnit\Framework\TestSuite::createTest($class, $method->name); - if ($test instanceof \PHPUnit_Framework_TestSuite_DataProvider) { + if ($test instanceof \PHPUnit\Framework\DataProviderTestSuite) { foreach ($test->tests() as $t) { $this->enhancePhpunitTest($t); } @@ -59,11 +59,11 @@ protected function createTestFromPhpUnitMethod(\ReflectionClass $class, \Reflect return $test; } - protected function enhancePhpunitTest(\PHPUnit_Framework_TestCase $test) + protected function enhancePhpunitTest(\PHPUnit\Framework\Test $test) { $className = get_class($test); $methodName = $test->getName(false); - $dependencies = \PHPUnit_Util_Test::getDependencies($className, $methodName); + $dependencies = \PHPUnit\Util\Test::getDependencies($className, $methodName); $test->setDependencies($dependencies); if ($test instanceof UnitFormat) { $test->getMetadata()->setParamsFromAnnotations(Annotation::forMethod($test, $methodName)->raw()); diff --git a/src/Codeception/Test/Test.php b/src/Codeception/Test/Test.php index 49490480a1..773f7a3aa8 100644 --- a/src/Codeception/Test/Test.php +++ b/src/Codeception/Test/Test.php @@ -3,6 +3,7 @@ use Codeception\TestInterface; use Codeception\Util\ReflectionHelper; +use SebastianBergmann\Timer\Timer; /** * The most simple testcase (with only one test in it) which can be executed by PHPUnit/Codeception. @@ -60,10 +61,10 @@ abstract public function toString(); * Runs a test and collects its result in a TestResult instance. * Executes before/after hooks coming from traits. * - * @param \PHPUnit_Framework_TestResult $result - * @return \PHPUnit_Framework_TestResult + * @param \PHPUnit\Framework\TestResult $result + * @return \PHPUnit\Framework\TestResult */ - final public function run(\PHPUnit_Framework_TestResult $result = null) + final public function run(\PHPUnit\Framework\TestResult $result = null) { $this->testResult = $result; @@ -82,22 +83,23 @@ final public function run(\PHPUnit_Framework_TestResult $result = null) $failedToStart = ReflectionHelper::readPrivateProperty($result, 'lastTestFailed'); if (!$this->ignored && !$failedToStart) { - \PHP_Timer::start(); + + Timer::start(); try { $this->test(); $status = self::STATUS_OK; - } catch (\PHPUnit_Framework_AssertionFailedError $e) { + } catch (\PHPUnit\Framework\AssertionFailedError $e) { $status = self::STATUS_FAIL; - } catch (\PHPUnit_Framework_Exception $e) { + } catch (\PHPUnit\Framework\Exception $e) { $status = self::STATUS_ERROR; } catch (\Throwable $e) { - $e = new \PHPUnit_Framework_ExceptionWrapper($e); + $e = new \PHPUnit\Framework\ExceptionWrapper($e); $status = self::STATUS_ERROR; } catch (\Exception $e) { - $e = new \PHPUnit_Framework_ExceptionWrapper($e); + $e = new \PHPUnit\Framework\ExceptionWrapper($e); $status = self::STATUS_ERROR; } - $time = \PHP_Timer::stop(); + $time = Timer::stop(); } foreach (array_reverse($this->hooks) as $hook) { diff --git a/src/Codeception/Test/Unit.php b/src/Codeception/Test/Unit.php index ab64e69eb5..c85acbfa8c 100644 --- a/src/Codeception/Test/Unit.php +++ b/src/Codeception/Test/Unit.php @@ -11,7 +11,7 @@ /** * Represents tests from PHPUnit compatible format. */ -class Unit extends \PHPUnit_Framework_TestCase implements +class Unit extends \PHPUnit\Framework\TestCase implements Interfaces\Reported, Interfaces\Dependent, TestInterface diff --git a/src/Codeception/TestInterface.php b/src/Codeception/TestInterface.php index 1974e97cf5..c8f7c09c5f 100644 --- a/src/Codeception/TestInterface.php +++ b/src/Codeception/TestInterface.php @@ -4,7 +4,7 @@ use Codeception\Test\Metadata; -interface TestInterface extends \PHPUnit_Framework_Test +interface TestInterface extends \PHPUnit\Framework\Test { /** * @return Metadata diff --git a/src/Codeception/Util/Shared/Asserts.php b/src/Codeception/Util/Shared/Asserts.php index 2b199b8e99..2c4958bed7 100644 --- a/src/Codeception/Util/Shared/Asserts.php +++ b/src/Codeception/Util/Shared/Asserts.php @@ -16,7 +16,7 @@ protected function assert($arguments, $not = false) $not = ''; } - call_user_func_array(['\PHPUnit_Framework_Assert', 'assert' . $not . $method], $arguments); + call_user_func_array(['\PHPUnit\Framework\Assert', 'assert' . $not . $method], $arguments); } protected function assertNot($arguments) @@ -34,7 +34,7 @@ protected function assertNot($arguments) */ protected function assertEquals($expected, $actual, $message = '', $delta = 0.0) { - \PHPUnit_Framework_Assert::assertEquals($expected, $actual, $message, $delta); + \PHPUnit\Framework\Assert::assertEquals($expected, $actual, $message, $delta); } /** @@ -47,7 +47,7 @@ protected function assertEquals($expected, $actual, $message = '', $delta = 0.0) */ protected function assertNotEquals($expected, $actual, $message = '', $delta = 0.0) { - \PHPUnit_Framework_Assert::assertNotEquals($expected, $actual, $message, $delta); + \PHPUnit\Framework\Assert::assertNotEquals($expected, $actual, $message, $delta); } /** @@ -59,7 +59,7 @@ protected function assertNotEquals($expected, $actual, $message = '', $delta = 0 */ protected function assertSame($expected, $actual, $message = '') { - \PHPUnit_Framework_Assert::assertSame($expected, $actual, $message); + \PHPUnit\Framework\Assert::assertSame($expected, $actual, $message); } /** @@ -71,7 +71,7 @@ protected function assertSame($expected, $actual, $message = '') */ protected function assertNotSame($expected, $actual, $message = '') { - \PHPUnit_Framework_Assert::assertNotSame($expected, $actual, $message); + \PHPUnit\Framework\Assert::assertNotSame($expected, $actual, $message); } /** @@ -83,7 +83,7 @@ protected function assertNotSame($expected, $actual, $message = '') */ protected function assertGreaterThan($expected, $actual, $message = '') { - \PHPUnit_Framework_Assert::assertGreaterThan($expected, $actual, $message); + \PHPUnit\Framework\Assert::assertGreaterThan($expected, $actual, $message); } /** @@ -91,7 +91,7 @@ protected function assertGreaterThan($expected, $actual, $message = '') */ protected function assertGreaterThen($expected, $actual, $message = '') { - \PHPUnit_Framework_Assert::assertGreaterThan($expected, $actual, $message); + \PHPUnit\Framework\Assert::assertGreaterThan($expected, $actual, $message); } /** @@ -103,7 +103,7 @@ protected function assertGreaterThen($expected, $actual, $message = '') */ protected function assertGreaterThanOrEqual($expected, $actual, $message = '') { - \PHPUnit_Framework_Assert::assertGreaterThanOrEqual($expected, $actual, $message); + \PHPUnit\Framework\Assert::assertGreaterThanOrEqual($expected, $actual, $message); } /** @@ -111,7 +111,7 @@ protected function assertGreaterThanOrEqual($expected, $actual, $message = '') */ protected function assertGreaterThenOrEqual($expected, $actual, $message = '') { - \PHPUnit_Framework_Assert::assertGreaterThanOrEqual($expected, $actual, $message); + \PHPUnit\Framework\Assert::assertGreaterThanOrEqual($expected, $actual, $message); } /** @@ -123,7 +123,7 @@ protected function assertGreaterThenOrEqual($expected, $actual, $message = '') */ protected function assertLessThan($expected, $actual, $message = '') { - \PHPUnit_Framework_Assert::assertLessThan($expected, $actual, $message); + \PHPUnit\Framework\Assert::assertLessThan($expected, $actual, $message); } /** @@ -135,7 +135,7 @@ protected function assertLessThan($expected, $actual, $message = '') */ protected function assertLessThanOrEqual($expected, $actual, $message = '') { - \PHPUnit_Framework_Assert::assertLessThanOrEqual($expected, $actual, $message); + \PHPUnit\Framework\Assert::assertLessThanOrEqual($expected, $actual, $message); } @@ -148,7 +148,7 @@ protected function assertLessThanOrEqual($expected, $actual, $message = '') */ protected function assertContains($needle, $haystack, $message = '') { - \PHPUnit_Framework_Assert::assertContains($needle, $haystack, $message); + \PHPUnit\Framework\Assert::assertContains($needle, $haystack, $message); } /** @@ -160,7 +160,7 @@ protected function assertContains($needle, $haystack, $message = '') */ protected function assertNotContains($needle, $haystack, $message = '') { - \PHPUnit_Framework_Assert::assertNotContains($needle, $haystack, $message); + \PHPUnit\Framework\Assert::assertNotContains($needle, $haystack, $message); } /** @@ -172,7 +172,7 @@ protected function assertNotContains($needle, $haystack, $message = '') */ protected function assertRegExp($pattern, $string, $message = '') { - \PHPUnit_Framework_Assert::assertRegExp($pattern, $string, $message); + \PHPUnit\Framework\Assert::assertRegExp($pattern, $string, $message); } /** @@ -184,7 +184,7 @@ protected function assertRegExp($pattern, $string, $message = '') */ protected function assertNotRegExp($pattern, $string, $message = '') { - \PHPUnit_Framework_Assert::assertNotRegExp($pattern, $string, $message); + \PHPUnit\Framework\Assert::assertNotRegExp($pattern, $string, $message); } /** @@ -196,7 +196,7 @@ protected function assertNotRegExp($pattern, $string, $message = '') */ protected function assertStringStartsWith($prefix, $string, $message = '') { - \PHPUnit_Framework_Assert::assertStringStartsWith($prefix, $string, $message); + \PHPUnit\Framework\Assert::assertStringStartsWith($prefix, $string, $message); } /** @@ -208,7 +208,7 @@ protected function assertStringStartsWith($prefix, $string, $message = '') */ protected function assertStringStartsNotWith($prefix, $string, $message = '') { - \PHPUnit_Framework_Assert::assertStringStartsNotWith($prefix, $string, $message); + \PHPUnit\Framework\Assert::assertStringStartsNotWith($prefix, $string, $message); } @@ -220,7 +220,7 @@ protected function assertStringStartsNotWith($prefix, $string, $message = '') */ protected function assertEmpty($actual, $message = '') { - \PHPUnit_Framework_Assert::assertEmpty($actual, $message); + \PHPUnit\Framework\Assert::assertEmpty($actual, $message); } /** @@ -231,7 +231,7 @@ protected function assertEmpty($actual, $message = '') */ protected function assertNotEmpty($actual, $message = '') { - \PHPUnit_Framework_Assert::assertNotEmpty($actual, $message); + \PHPUnit\Framework\Assert::assertNotEmpty($actual, $message); } /** @@ -242,7 +242,7 @@ protected function assertNotEmpty($actual, $message = '') */ protected function assertNull($actual, $message = '') { - \PHPUnit_Framework_Assert::assertNull($actual, $message); + \PHPUnit\Framework\Assert::assertNull($actual, $message); } /** @@ -253,7 +253,7 @@ protected function assertNull($actual, $message = '') */ protected function assertNotNull($actual, $message = '') { - \PHPUnit_Framework_Assert::assertNotNull($actual, $message); + \PHPUnit\Framework\Assert::assertNotNull($actual, $message); } /** @@ -264,7 +264,7 @@ protected function assertNotNull($actual, $message = '') */ protected function assertTrue($condition, $message = '') { - \PHPUnit_Framework_Assert::assertTrue($condition, $message); + \PHPUnit\Framework\Assert::assertTrue($condition, $message); } /** @@ -275,7 +275,7 @@ protected function assertTrue($condition, $message = '') */ protected function assertFalse($condition, $message = '') { - \PHPUnit_Framework_Assert::assertFalse($condition, $message); + \PHPUnit\Framework\Assert::assertFalse($condition, $message); } /** @@ -286,7 +286,7 @@ protected function assertFalse($condition, $message = '') */ protected function assertThat($haystack, $constraint, $message = '') { - \PHPUnit_Framework_Assert::assertThat($haystack, $constraint, $message); + \PHPUnit\Framework\Assert::assertThat($haystack, $constraint, $message); } /** @@ -298,8 +298,8 @@ protected function assertThat($haystack, $constraint, $message = '') */ protected function assertThatItsNot($haystack, $constraint, $message = '') { - $constraint = new \PHPUnit_Framework_Constraint_Not($constraint); - \PHPUnit_Framework_Assert::assertThat($haystack, $constraint, $message); + $constraint = new \PHPUnit\Framework\Constraint\LogicalNot($constraint); + \PHPUnit\Framework\Assert::assertThat($haystack, $constraint, $message); } @@ -311,7 +311,7 @@ protected function assertThatItsNot($haystack, $constraint, $message = '') */ protected function assertFileExists($filename, $message = '') { - \PHPUnit_Framework_Assert::assertFileExists($filename, $message); + \PHPUnit\Framework\Assert::assertFileExists($filename, $message); } @@ -323,7 +323,7 @@ protected function assertFileExists($filename, $message = '') */ protected function assertFileNotExists($filename, $message = '') { - \PHPUnit_Framework_Assert::assertFileNotExists($filename, $message); + \PHPUnit\Framework\Assert::assertFileNotExists($filename, $message); } /** @@ -333,7 +333,7 @@ protected function assertFileNotExists($filename, $message = '') */ protected function assertGreaterOrEquals($expected, $actual, $description = '') { - \PHPUnit_Framework_Assert::assertGreaterThanOrEqual($expected, $actual, $description); + \PHPUnit\Framework\Assert::assertGreaterThanOrEqual($expected, $actual, $description); } /** @@ -343,7 +343,7 @@ protected function assertGreaterOrEquals($expected, $actual, $description = '') */ protected function assertLessOrEquals($expected, $actual, $description = '') { - \PHPUnit_Framework_Assert::assertLessThanOrEqual($expected, $actual, $description); + \PHPUnit\Framework\Assert::assertLessThanOrEqual($expected, $actual, $description); } /** @@ -352,7 +352,7 @@ protected function assertLessOrEquals($expected, $actual, $description = '') */ protected function assertIsEmpty($actual, $description = '') { - \PHPUnit_Framework_Assert::assertEmpty($actual, $description); + \PHPUnit\Framework\Assert::assertEmpty($actual, $description); } /** @@ -362,7 +362,7 @@ protected function assertIsEmpty($actual, $description = '') */ protected function assertArrayHasKey($key, $actual, $description = '') { - \PHPUnit_Framework_Assert::assertArrayHasKey($key, $actual, $description); + \PHPUnit\Framework\Assert::assertArrayHasKey($key, $actual, $description); } /** @@ -372,7 +372,7 @@ protected function assertArrayHasKey($key, $actual, $description = '') */ protected function assertArrayNotHasKey($key, $actual, $description = '') { - \PHPUnit_Framework_Assert::assertArrayNotHasKey($key, $actual, $description); + \PHPUnit\Framework\Assert::assertArrayNotHasKey($key, $actual, $description); } /** @@ -385,7 +385,7 @@ protected function assertArrayNotHasKey($key, $actual, $description = '') */ protected function assertArraySubset($subset, $array, $strict = false, $message = '') { - \PHPUnit_Framework_Assert::assertArraySubset($subset, $array, $strict, $message); + \PHPUnit\Framework\Assert::assertArraySubset($subset, $array, $strict, $message); } /** @@ -395,7 +395,7 @@ protected function assertArraySubset($subset, $array, $strict = false, $message */ protected function assertCount($expectedCount, $actual, $description = '') { - \PHPUnit_Framework_Assert::assertCount($expectedCount, $actual, $description); + \PHPUnit\Framework\Assert::assertCount($expectedCount, $actual, $description); } /** @@ -405,7 +405,7 @@ protected function assertCount($expectedCount, $actual, $description = '') */ protected function assertInstanceOf($class, $actual, $description = '') { - \PHPUnit_Framework_Assert::assertInstanceOf($class, $actual, $description); + \PHPUnit\Framework\Assert::assertInstanceOf($class, $actual, $description); } /** @@ -415,7 +415,7 @@ protected function assertInstanceOf($class, $actual, $description = '') */ protected function assertNotInstanceOf($class, $actual, $description = '') { - \PHPUnit_Framework_Assert::assertNotInstanceOf($class, $actual, $description); + \PHPUnit\Framework\Assert::assertNotInstanceOf($class, $actual, $description); } /** @@ -425,7 +425,7 @@ protected function assertNotInstanceOf($class, $actual, $description = '') */ protected function assertInternalType($type, $actual, $description = '') { - \PHPUnit_Framework_Assert::assertInternalType($type, $actual, $description); + \PHPUnit\Framework\Assert::assertInternalType($type, $actual, $description); } /** @@ -435,6 +435,6 @@ protected function assertInternalType($type, $actual, $description = '') */ protected function fail($message) { - \PHPUnit_Framework_Assert::fail($message); + \PHPUnit\Framework\Assert::fail($message); } } diff --git a/tests/cli/RunCest.php b/tests/cli/RunCest.php index 9f29c477cc..2115a1ebdb 100644 --- a/tests/cli/RunCest.php +++ b/tests/cli/RunCest.php @@ -92,19 +92,6 @@ public function runXmlReportsInStrictMode(\CliGuy $I) $I->dontSeeInThisFile('feature="'); } - /** - * @group reports - * - * @param CliGuy $I - */ - public function runReportMode(\CliGuy $I) - { - $I->wantTo('try the reporting mode'); - $I->executeCommand('run dummy --report'); - $I->seeInShellOutput('FileExistsCept'); - $I->seeInShellOutput('........Ok'); - } - /** * @group reports * @@ -112,7 +99,9 @@ public function runReportMode(\CliGuy $I) */ public function runCustomReport(\CliGuy $I) { - $I->wantTo('try the reporting mode'); + if (\PHPUnit\Runner\Version::series() >= 7) { + throw new \Codeception\Exception\Skip('Not for PHPUnit 7'); + } $I->executeCommand('run dummy --report -c codeception_custom_report.yml'); $I->seeInShellOutput('FileExistsCept: Check config exists'); $I->dontSeeInShellOutput('Ok'); diff --git a/tests/cli/SecondTestIsExecutedWhenTheFirstTestFailsCest.php b/tests/cli/SecondTestIsExecutedWhenTheFirstTestFailsCest.php index 8f47dc2322..846e8f48d3 100644 --- a/tests/cli/SecondTestIsExecutedWhenTheFirstTestFailsCest.php +++ b/tests/cli/SecondTestIsExecutedWhenTheFirstTestFailsCest.php @@ -14,6 +14,9 @@ public function testIsExecuted(CliGuy $I) public function endTestEventIsEmitted(CliGuy $I) { + if (\PHPUnit\Runner\Version::series() >= 7) { + throw new \Codeception\Exception\Skip('Not for PHPUnit 7'); + } $I->wantTo('see that all start and end events are emitted'); $I->amInPath('tests/data/first_test_fails'); $I->executeFailCommand('run --xml --no-ansi --report -o "reporters: report: CustomReporter"'); diff --git a/tests/cli/UnitCept.php b/tests/cli/UnitCept.php index b7f67db005..02bd136769 100644 --- a/tests/cli/UnitCept.php +++ b/tests/cli/UnitCept.php @@ -12,7 +12,7 @@ $I->seeInThisFile('seeInThisFile('seeInThisFile('FailingTest::testMe'); } else { $I->seeInThisFile('FailingTest::testMe'); diff --git a/tests/data/SimpleTest.php b/tests/data/SimpleTest.php index 9dfbe781f0..74ef65cbe8 100755 --- a/tests/data/SimpleTest.php +++ b/tests/data/SimpleTest.php @@ -1,5 +1,5 @@ assertTrue(true); diff --git a/tests/data/app/db b/tests/data/app/db index c856afcf97..609cdc8eb1 100644 --- a/tests/data/app/db +++ b/tests/data/app/db @@ -1 +1 @@ -a:0:{} \ No newline at end of file +a:1:{s:6:"params";a:0:{}} \ No newline at end of file diff --git a/tests/data/claypit/c3.php b/tests/data/claypit/c3.php index 9eedd0b471..80330a1ccd 100644 --- a/tests/data/claypit/c3.php +++ b/tests/data/claypit/c3.php @@ -19,7 +19,7 @@ $cookie = json_decode($cookie, true); } - if ($cookie) { + if ($cookie) { foreach ($cookie as $key => $value) { $_SERVER["HTTP_X_CODECEPTION_" . strtoupper($key)] = $value; } @@ -49,16 +49,20 @@ function __c3_error($message) } // phpunit codecoverage shimming -if (class_exists('SebastianBergmann\CodeCoverage\CodeCoverage') and !class_exists('PHP_CodeCoverage')) { - class_alias('SebastianBergmann\CodeCoverage\CodeCoverage', 'PHP_CodeCoverage'); - class_alias('SebastianBergmann\CodeCoverage\Report\Text', 'PHP_CodeCoverage_Report_Text'); - class_alias('SebastianBergmann\CodeCoverage\Report\PHP', 'PHP_CodeCoverage_Report_PHP'); - class_alias('SebastianBergmann\CodeCoverage\Report\Clover', 'PHP_CodeCoverage_Report_Clover'); - class_alias('SebastianBergmann\CodeCoverage\Report\Crap4j', 'PHP_CodeCoverage_Report_Crap4j'); - class_alias('SebastianBergmann\CodeCoverage\Report\Html\Facade', 'PHP_CodeCoverage_Report_HTML'); - class_alias('SebastianBergmann\CodeCoverage\Report\Xml\Facade', 'PHP_CodeCoverage_Report_XML'); - class_alias('SebastianBergmann\CodeCoverage\Exception', 'PHP_CodeCoverage_Exception'); +if (!class_exists('PHP_CodeCoverage') and class_exists('SebastianBergmann\CodeCoverage\CodeCoverage')) { + class_alias('SebastianBergmann\CodeCoverage\CodeCoverage', 'PHP_CodeCoverage'); + class_alias('SebastianBergmann\CodeCoverage\Report\Text', 'PHP_CodeCoverage_Report_Text'); + class_alias('SebastianBergmann\CodeCoverage\Report\PHP', 'PHP_CodeCoverage_Report_PHP'); + class_alias('SebastianBergmann\CodeCoverage\Report\Clover', 'PHP_CodeCoverage_Report_Clover'); + class_alias('SebastianBergmann\CodeCoverage\Report\Crap4j', 'PHP_CodeCoverage_Report_Crap4j'); + class_alias('SebastianBergmann\CodeCoverage\Report\Html\Facade', 'PHP_CodeCoverage_Report_HTML'); + class_alias('SebastianBergmann\CodeCoverage\Report\Xml\Facade', 'PHP_CodeCoverage_Report_XML'); + class_alias('SebastianBergmann\CodeCoverage\Exception', 'PHP_CodeCoverage_Exception'); } +// phpunit version +if (!class_exists('PHPUnit_Runner_Version') && class_exists('PHPUnit\Runner\Version')) { + class_alias('PHPUnit\Runner\Version', 'PHPUnit_Runner_Version'); +} // Autoload Codeception classes if (!class_exists('\\Codeception\\Codecept')) { @@ -205,14 +209,28 @@ function __c3_send_file($filename) /** * @param $filename - * @return null|PHP_CodeCoverage + * @param bool $lock Lock the file for writing? + * @return [null|PHP_CodeCoverage|\SebastianBergmann\CodeCoverage\CodeCoverage, resource] */ - function __c3_factory($filename) + function __c3_factory($filename, $lock=false) { - $phpCoverage = is_readable($filename) - ? unserialize(file_get_contents($filename)) - : new PHP_CodeCoverage(); - + $file = null; + if ($filename !== null && is_readable($filename)) { + if ($lock) { + $file = fopen($filename, 'r+'); + if (flock($file, LOCK_EX)) { + $phpCoverage = unserialize(stream_get_contents($file)); + } else { + __c3_error("Failed to acquire write-lock for $filename"); + } + } else { + $phpCoverage = unserialize(file_get_contents($filename)); + } + + return array($phpCoverage, $file); + } else { + $phpCoverage = new PHP_CodeCoverage(); + } if (isset($_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE_SUITE'])) { $suite = $_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE_SUITE']; @@ -233,7 +251,7 @@ function __c3_factory($filename) __c3_error($e->getMessage()); } - return $phpCoverage; + return array($phpCoverage, $file); } function __c3_exit() @@ -267,12 +285,12 @@ function __c3_clear() $route = ltrim(strrchr($_SERVER['REQUEST_URI'], '/'), '/'); - if ($route == 'clear') { + if ($route === 'clear') { __c3_clear(); return __c3_exit(); } - $codeCoverage = __c3_factory($complete_report); + list($codeCoverage, ) = __c3_factory($complete_report); switch ($route) { case 'html': @@ -313,9 +331,9 @@ function __c3_clear() } } else { - $codeCoverage = __c3_factory($current_report); + list($codeCoverage, ) = __c3_factory(null); $codeCoverage->start(C3_CODECOVERAGE_TESTNAME); - if (!array_key_exists('HTTP_X_CODECEPTION_CODECOVERAGE_DEBUG', $_SERVER)) { + if (!array_key_exists('HTTP_X_CODECEPTION_CODECOVERAGE_DEBUG', $_SERVER)) { register_shutdown_function( function () use ($codeCoverage, $current_report) { @@ -326,7 +344,31 @@ function () use ($codeCoverage, $current_report) { } } - file_put_contents($current_report, serialize($codeCoverage)); + // This will either lock the existing report for writing and return it along with a file pointer, + // or return a fresh PHP_CodeCoverage object without a file pointer. We'll merge the current request + // into that coverage object, write it to disk, and release the lock. By doing this in the end of + // the request, we avoid this scenario, where Request 2 overwrites the changes from Request 1: + // + // Time -> + // Request 1 [ ] + // Request 2 [ ] + // + // In addition, by locking the file for exclusive writing, we make sure no other request try to + // read/write to the file at the same time as this request (leading to a corrupt file). flock() is a + // blocking call, so it waits until an exclusive lock can be acquired before continuing. + + list($existingCodeCoverage, $file) = __c3_factory($current_report, true); + $existingCodeCoverage->merge($codeCoverage); + + if ($file === null) { + file_put_contents($current_report, serialize($existingCodeCoverage), LOCK_EX); + } else { + fseek($file, 0); + fwrite($file, serialize($existingCodeCoverage)); + fflush($file); + flock($file, LOCK_UN); + fclose($file); + } } ); } diff --git a/tests/data/claypit/composer.json b/tests/data/claypit/composer.json index 7943da330b..cbd6aa6713 100644 --- a/tests/data/claypit/composer.json +++ b/tests/data/claypit/composer.json @@ -1,5 +1,5 @@ { "require-dev": { - "codeception/c3": "@dev" + "codeception/c3": "2.0.x-dev" } } \ No newline at end of file diff --git a/tests/data/claypit/composer.lock b/tests/data/claypit/composer.lock index 58142e547d..8d03452074 100644 --- a/tests/data/claypit/composer.lock +++ b/tests/data/claypit/composer.lock @@ -4,28 +4,32 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "2b7a5d38446cbc8d5d27c7192506b3bd", - "content-hash": "6a872dd1556c4dbb351b2c49717ada75", + "hash": "eef34880c17415a11aaa8fa92231b4fc", + "content-hash": "1dcee5d81a786ce03ba3dcd9e47b7251", "packages": [], "packages-dev": [ { "name": "codeception/c3", - "version": "dev-master", + "version": "2.0.x-dev", "source": { "type": "git", "url": "https://github.com/Codeception/c3.git", - "reference": "0b67a51b109a0748aa76a7d71fe1b409903ecf54" + "reference": "c7348bbc82da82834fe237c5fb754003ac0fe782" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Codeception/c3/zipball/0b67a51b109a0748aa76a7d71fe1b409903ecf54", - "reference": "0b67a51b109a0748aa76a7d71fe1b409903ecf54", + "url": "https://api.github.com/repos/Codeception/c3/zipball/c7348bbc82da82834fe237c5fb754003ac0fe782", + "reference": "c7348bbc82da82834fe237c5fb754003ac0fe782", "shasum": "" }, "require": { + "composer-plugin-api": "^1.0", "php": ">=5.4.0" }, - "type": "library", + "type": "composer-plugin", + "extra": { + "class": "Codeception\\c3\\Installer" + }, "autoload": { "psr-4": { "Codeception\\c3\\": "." @@ -36,9 +40,13 @@ "MIT" ], "authors": [ + { + "name": "Tiger Seo", + "email": "tiger.seo@gmail.com" + }, { "name": "Michael Bodnarchuk", - "email": "davert.php@resend.cc", + "email": "davert.php@codegyre.com", "homepage": "http://codegyre.com" } ], @@ -48,7 +56,7 @@ "code coverage", "codecoverage" ], - "time": "2014-10-02 23:18:47" + "time": "2018-02-19 11:27:45" } ], "aliases": [], diff --git a/tests/data/claypit/tests/_bootstrap.php b/tests/data/claypit/tests/_bootstrap.php index 72f5b3a351..6ce6debfa1 100644 --- a/tests/data/claypit/tests/_bootstrap.php +++ b/tests/data/claypit/tests/_bootstrap.php @@ -1,7 +1,10 @@ testStatus == \PHPUnit_Runner_BaseTestRunner::STATUS_FAILURE) { + if ($this->testStatus == \PHPUnit\Runner\BaseTestRunner::STATUS_FAILURE) { $this->write('×'); } else { - if ($this->testStatus == \PHPUnit_Runner_BaseTestRunner::STATUS_SKIPPED) { + if ($this->testStatus == \PHPUnit\Runner\BaseTestRunner::STATUS_SKIPPED) { $this->write('S'); } else { - if ($this->testStatus == \PHPUnit_Runner_BaseTestRunner::STATUS_INCOMPLETE) { + if ($this->testStatus == \PHPUnit\Runner\BaseTestRunner::STATUS_INCOMPLETE) { $this->write('I'); } else { - if ($this->testStatus == \PHPUnit_Runner_BaseTestRunner::STATUS_ERROR) { + if ($this->testStatus == \PHPUnit\Runner\BaseTestRunner::STATUS_ERROR) { $this->write('E'); } else { $this->write('✔'); @@ -31,7 +31,7 @@ public function endTest(PHPUnit_Framework_Test $test, $time) $this->write(" $name \n"); } - public function printResult(\PHPUnit_Framework_TestResult $result) + public function printResult(\PHPUnit\Framework\TestResult $result) { } diff --git a/tests/data/claypit/tests/dummy/AnotherTest.php b/tests/data/claypit/tests/dummy/AnotherTest.php index b721615544..48491a8c78 100755 --- a/tests/data/claypit/tests/dummy/AnotherTest.php +++ b/tests/data/claypit/tests/dummy/AnotherTest.php @@ -1,5 +1,5 @@ assertTrue(true); diff --git a/tests/data/claypit/tests/order/ParsedLoadedTest.php b/tests/data/claypit/tests/order/ParsedLoadedTest.php index 24c47f2e9f..44c699b98d 100644 --- a/tests/data/claypit/tests/order/ParsedLoadedTest.php +++ b/tests/data/claypit/tests/order/ParsedLoadedTest.php @@ -1,7 +1,7 @@ write("\nSTARTED: $testName\n"); } - public function endTest(PHPUnit_Framework_Test $test, $time) + public function endTest(PHPUnit\Framework\Test $test, $time) { $testName = \Codeception\Test\Descriptor::getTestAsString($test); $this->write("\nENDED: $testName\n"); diff --git a/tests/data/included/jazz/pianist/tests/_helpers/TestHelper.php b/tests/data/included/jazz/pianist/tests/_helpers/TestHelper.php index e9125517f5..6514a23997 100644 --- a/tests/data/included/jazz/pianist/tests/_helpers/TestHelper.php +++ b/tests/data/included/jazz/pianist/tests/_helpers/TestHelper.php @@ -6,6 +6,6 @@ class TestHelper extends \Codeception\Module { public function seeEquals($expected, $actual) { - \PHPUnit_Framework_Assert::assertEquals($expected, $actual); + $this->assertEquals($expected, $actual); } } diff --git a/tests/data/included/jazz/tests/_helpers/TestHelper.php b/tests/data/included/jazz/tests/_helpers/TestHelper.php index 44c5968051..3ab1b26daf 100644 --- a/tests/data/included/jazz/tests/_helpers/TestHelper.php +++ b/tests/data/included/jazz/tests/_helpers/TestHelper.php @@ -6,6 +6,6 @@ class TestHelper extends \Codeception\Module { public function seeEquals($expected, $actual) { - \PHPUnit_Framework_Assert::assertEquals($expected, $actual); + $this->assertEquals($expected, $actual); } } diff --git a/tests/data/included_mix/tests/unit/SimpleTest.php b/tests/data/included_mix/tests/unit/SimpleTest.php index 720ac2b98d..cec69fdfcb 100644 --- a/tests/data/included_mix/tests/unit/SimpleTest.php +++ b/tests/data/included_mix/tests/unit/SimpleTest.php @@ -1,6 +1,6 @@ assertEquals('PHPUnit_Framework_TestCase', PHPUnit_Framework_TestCase::class); diff --git a/tests/data/php70Test b/tests/data/php70Test index f16447a376..b25bca5cb3 100644 --- a/tests/data/php70Test +++ b/tests/data/php70Test @@ -1,6 +1,6 @@ nzWsQ(1-$6LWGf z=J}2ll8W$&Ad12+A%Y;>W3McGU2ZbVNS8b8w;0RM%H9(;|2to1wTpLt7nH|$-`qW1 ze!0At`#D!+1=t_}0SG_<0uX=z1R(Hn3yicySyff>;?vMN?NiV1QJ*K-{g$Dd1~K)$ znnCisEKk;#2+7;MJgGKJ<7=Zu8cmZl+O--vYE|oc>x6u3oNPn~xt2ro9soxi4lxnoak+{S#7X$>qf&Q*Q3iqd1li-8~DkH z7JifXycvDZuRIK>AMhlTyf80|E}57QtU2mfcK@n5R?zjS71CbE3iITE%{;SOH^_nU zSZ~)%vfpmCSVWzu@YvMrM}<)#%@r;*9>9S5jvWNH=LWH?lnf?T^Pvh+f8wLh0>2us z%Qpop^S%D{>@OUp7Sv)=r=~qjXovVG}vo4Ylhx<|8a}f<|*Y*LHUOz*dPD_2tWV= z5P$##AOHafKmY;|m`8yxQW@d1#maN*#S6!Bw@T%$%@X@5ldbYj`O(gU(&u7E(6W`T z$NrEQOw~W!*)EOO|E~n)jq++9JBXMd009U<00Izz00bZa0SG_<0uXp70VS1Q6=U~W z$V*~c6DM~kMC*S^c_}Ebm4B7LSq2*fAOHafKmY;|fB*y_009U<00MI>kdrg)KlfEB zW%V4}UCu;%S~}%W=al+6c9(#d)h2s)*ewCstTwJ1um2l@@|W_5@~hIA+YTZy2tWV= z5P$##AOHafKmY;|fWX`cY)aBfxpHdzz3z{e-?!=R!1B+if1f?M;>OMQm9L6vNi9|! zyH5k2?Dnjm?BJ~jZ*6~>l2+C#uH8M0Uc1rr8txCR8?BbNi=w0zDy%8$hvRhS!KDY$ z`ky`Y4;us^009U<00Izz00bZa0SG_<0=HOTDe4>6|F?LA(KQG_00Izz00bZa0SG_< z0uX?JAmICd%mN5N00Izz00bZa0SG_<0uX?}?H7o?{}+|l?D>DUzpv;a1Rwwb2tWV= c5P$##AOHafK;R=1$Vu6i754Z5*Bemxe=^p*-2eap diff --git a/tests/facebook/FacebookTest.php b/tests/facebook/FacebookTest.php index 23c636244b..001e39e450 100644 --- a/tests/facebook/FacebookTest.php +++ b/tests/facebook/FacebookTest.php @@ -8,7 +8,7 @@ use Codeception\Lib\Driver\Facebook as FacebookDriver; use Codeception\Util\Stub; -class FacebookTest extends \PHPUnit_Framework_TestCase +class FacebookTest extends \PHPUnit\Framework\TestCase { protected $config = array( 'app_id' => '460287924057084', diff --git a/tests/unit/C3Test.php b/tests/unit/C3Test.php index 69b3bd0f3b..7bef8086d6 100644 --- a/tests/unit/C3Test.php +++ b/tests/unit/C3Test.php @@ -2,7 +2,7 @@ use Codeception\Configuration; -class C3Test extends PHPUnit_Framework_TestCase +class C3Test extends \PHPUnit\Framework\TestCase { /** * @var string diff --git a/tests/unit/Codeception/ApplicationTest.php b/tests/unit/Codeception/ApplicationTest.php index f3b1d76997..5dc8c1b9cf 100644 --- a/tests/unit/Codeception/ApplicationTest.php +++ b/tests/unit/Codeception/ApplicationTest.php @@ -2,7 +2,7 @@ namespace Codeception; -class ApplicationTest extends \PHPUnit_Framework_TestCase +class ApplicationTest extends \PHPUnit\Framework\TestCase { public static function setUpBeforeClass() diff --git a/tests/unit/Codeception/Command/BaseCommandRunner.php b/tests/unit/Codeception/Command/BaseCommandRunner.php index 710e96b185..84c18dcd18 100644 --- a/tests/unit/Codeception/Command/BaseCommandRunner.php +++ b/tests/unit/Codeception/Command/BaseCommandRunner.php @@ -3,7 +3,7 @@ use Codeception\Application; use Symfony\Component\Console\Tester\CommandTester; -class BaseCommandRunner extends \PHPUnit_Framework_TestCase +class BaseCommandRunner extends \PHPUnit\Framework\TestCase { /** diff --git a/tests/unit/Codeception/Command/MyCustomCommandTest.php b/tests/unit/Codeception/Command/MyCustomCommandTest.php index d4288e4471..0dd8a4fc0e 100644 --- a/tests/unit/Codeception/Command/MyCustomCommandTest.php +++ b/tests/unit/Codeception/Command/MyCustomCommandTest.php @@ -1,7 +1,7 @@ Bye world

Bye warcraft

'); try { $this->constraint->evaluate($nodes->filter('p'), 'selector'); - } catch (PHPUnit_Framework_AssertionFailedError $fail) { + } catch (\PHPUnit\Framework\AssertionFailedError $fail) { $this->assertContains( "Failed asserting that any element by 'selector' on page /user", $fail->getMessage() @@ -44,7 +44,7 @@ public function testFailMessageResponseWhenMoreNodes() $nodes = new Symfony\Component\DomCrawler\Crawler($html); try { $this->constraint->evaluate($nodes->filter('p'), 'selector'); - } catch (PHPUnit_Framework_AssertionFailedError $fail) { + } catch (\PHPUnit\Framework\AssertionFailedError $fail) { $this->assertContains( "Failed asserting that any element by 'selector' on page /user", $fail->getMessage() @@ -63,7 +63,7 @@ public function testFailMessageResponseWithoutUrl() $nodes = new Symfony\Component\DomCrawler\Crawler('

Bye world

Bye warcraft

'); try { $this->constraint->evaluate($nodes->filter('p'), 'selector'); - } catch (PHPUnit_Framework_AssertionFailedError $fail) { + } catch (\PHPUnit\Framework\AssertionFailedError $fail) { $this->assertContains("Failed asserting that any element by 'selector'", $fail->getMessage()); $this->assertNotContains("Failed asserting that any element by 'selector' on page", $fail->getMessage()); return; diff --git a/tests/unit/Codeception/Constraints/CrawlerNotConstraintTest.php b/tests/unit/Codeception/Constraints/CrawlerNotConstraintTest.php index 21e90a7b84..17302e01ed 100644 --- a/tests/unit/Codeception/Constraints/CrawlerNotConstraintTest.php +++ b/tests/unit/Codeception/Constraints/CrawlerNotConstraintTest.php @@ -1,5 +1,5 @@ Bye world

Bye warcraft

'); try { $this->constraint->evaluate($nodes->filter('p'), 'selector'); - } catch (PHPUnit_Framework_AssertionFailedError $fail) { + } catch (\PHPUnit\Framework\AssertionFailedError $fail) { $this->assertContains("There was 'selector' element on page /user", $fail->getMessage()); $this->assertNotContains('+

Bye world

', $fail->getMessage()); $this->assertContains('+

Bye warcraft

', $fail->getMessage()); @@ -41,7 +41,7 @@ public function testFailMessageResponseWhenMoreNodes() $nodes = new Symfony\Component\DomCrawler\Crawler($html); try { $this->constraint->evaluate($nodes->filter('p'), 'selector'); - } catch (PHPUnit_Framework_AssertionFailedError $fail) { + } catch (\PHPUnit\Framework\AssertionFailedError $fail) { $this->assertContains("There was 'selector' element on page /user", $fail->getMessage()); $this->assertContains('+

warcraft 0

', $fail->getMessage()); $this->assertContains('+

warcraft 14

', $fail->getMessage()); @@ -56,7 +56,7 @@ public function testFailMessageResponseWithoutUrl() $nodes = new Symfony\Component\DomCrawler\Crawler('

Bye world

Bye warcraft

'); try { $this->constraint->evaluate($nodes->filter('p'), 'selector'); - } catch (PHPUnit_Framework_AssertionFailedError $fail) { + } catch (\PHPUnit\Framework\AssertionFailedError $fail) { $this->assertContains("There was 'selector' element", $fail->getMessage()); $this->assertNotContains("There was 'selector' element on page /user", $fail->getMessage()); return; diff --git a/tests/unit/Codeception/Constraints/WebDriverConstraintTest.php b/tests/unit/Codeception/Constraints/WebDriverConstraintTest.php index 52da852d86..0560630c6b 100644 --- a/tests/unit/Codeception/Constraints/WebDriverConstraintTest.php +++ b/tests/unit/Codeception/Constraints/WebDriverConstraintTest.php @@ -1,7 +1,7 @@ constraint->evaluate($nodes, 'selector'); - } catch (PHPUnit_Framework_AssertionFailedError $fail) { + } catch (\PHPUnit\Framework\AssertionFailedError $fail) { $this->assertContains( "Failed asserting that any element by 'selector' on page /user", $fail->getMessage() @@ -42,7 +42,7 @@ public function testFailMessageResponseWithArraySelector() $nodes = array(new TestedWebElement('Bye warcraft')); try { $this->constraint->evaluate($nodes, ['css' => 'p.mocked']); - } catch (PHPUnit_Framework_AssertionFailedError $fail) { + } catch (\PHPUnit\Framework\AssertionFailedError $fail) { $this->assertContains( "Failed asserting that any element by css 'p.mocked' on page /user", $fail->getMessage() @@ -61,7 +61,7 @@ public function testFailMessageResponseWhenMoreNodes() } try { $this->constraint->evaluate($nodes, 'selector'); - } catch (PHPUnit_Framework_AssertionFailedError $fail) { + } catch (\PHPUnit\Framework\AssertionFailedError $fail) { $this->assertContains( "Failed asserting that any element by 'selector' on page /user", $fail->getMessage() @@ -80,7 +80,7 @@ public function testFailMessageResponseWithoutUrl() $nodes = array(new TestedWebElement('Bye warcraft'), new TestedWebElement('Bye world')); try { $this->constraint->evaluate($nodes, 'selector'); - } catch (PHPUnit_Framework_AssertionFailedError $fail) { + } catch (\PHPUnit\Framework\AssertionFailedError $fail) { $this->assertContains("Failed asserting that any element by 'selector'", $fail->getMessage()); $this->assertNotContains("Failed asserting that any element by 'selector' on page", $fail->getMessage()); return; diff --git a/tests/unit/Codeception/Constraints/WebDriverNotConstraintTest.php b/tests/unit/Codeception/Constraints/WebDriverNotConstraintTest.php index 51f1d2d94f..6e8bbe95ed 100644 --- a/tests/unit/Codeception/Constraints/WebDriverNotConstraintTest.php +++ b/tests/unit/Codeception/Constraints/WebDriverNotConstraintTest.php @@ -1,7 +1,7 @@ constraint->evaluate($nodes, 'selector'); - } catch (PHPUnit_Framework_AssertionFailedError $fail) { + } catch (\PHPUnit\Framework\AssertionFailedError $fail) { $this->assertContains("There was 'selector' element on page /user", $fail->getMessage()); $this->assertNotContains('+

Bye world', $fail->getMessage()); $this->assertContains('+

Bye warcraft', $fail->getMessage()); @@ -39,7 +39,7 @@ public function testFailMessageResponseWithArraySelector() $nodes = array(new TestedWebElement('Bye warcraft')); try { $this->constraint->evaluate($nodes, ['css' => 'p.mocked']); - } catch (PHPUnit_Framework_AssertionFailedError $fail) { + } catch (\PHPUnit\Framework\AssertionFailedError $fail) { $this->assertContains("There was css 'p.mocked' element on page /user", $fail->getMessage()); $this->assertContains('+

Bye warcraft', $fail->getMessage()); return; @@ -55,7 +55,7 @@ public function testFailMessageResponseWhenMoreNodes() } try { $this->constraint->evaluate($nodes, 'selector'); - } catch (PHPUnit_Framework_AssertionFailedError $fail) { + } catch (\PHPUnit\Framework\AssertionFailedError $fail) { $this->assertContains("There was 'selector' element on page /user", $fail->getMessage()); $this->assertContains('+

warcraft 0', $fail->getMessage()); $this->assertContains('+

warcraft 14', $fail->getMessage()); @@ -70,7 +70,7 @@ public function testFailMessageResponseWithoutUrl() $nodes = array(new TestedWebElement('Bye warcraft'), new TestedWebElement('Bye world')); try { $this->constraint->evaluate($nodes, 'selector'); - } catch (PHPUnit_Framework_AssertionFailedError $fail) { + } catch (\PHPUnit\Framework\AssertionFailedError $fail) { $this->assertContains("There was 'selector' element", $fail->getMessage()); $this->assertNotContains("There was 'selector' element on page", $fail->getMessage()); return; diff --git a/tests/unit/Codeception/Coverage/FilterTest.php b/tests/unit/Codeception/Coverage/FilterTest.php index f37157c572..428229db31 100644 --- a/tests/unit/Codeception/Coverage/FilterTest.php +++ b/tests/unit/Codeception/Coverage/FilterTest.php @@ -1,6 +1,10 @@ filter = new Filter(new DummyCodeCoverage()); - } - - // tests - public function testBacklistFiltersApplied() - { - if (!method_exists($this->filter->getFilter(), 'addFileToBlacklist')) { - $this->markTestSkipped('The blacklist functionality has been removed from PHPUnit 5'); - } - $config = [ - 'coverage' => [ - 'blacklist' => [ - 'include' => [ - 'tests/*', - 'vendor/*/*Test.php', - 'src/Codeception/Codecept.php' - ], - 'exclude' => [ - 'tests/support/CodeGuy.php' - ] - ] - ] - ]; - $this->filter->blackList($config); - $fileFilter = $this->filter->getFilter(); - $this->assertTrue($fileFilter->isFiltered(codecept_root_dir('tests/unit/C3Test.php'))); - $this->assertTrue($fileFilter->isFiltered(codecept_root_dir('src/Codeception/Codecept.php'))); - $this->assertTrue( - $fileFilter->isFiltered(codecept_root_dir('vendor/phpunit/phpunit/tests/Framework/AssertTest.php')) - ); - $this->assertFalse($fileFilter->isFiltered(codecept_root_dir('vendor/guzzlehttp/guzzle/src/Client.php'))); - $this->assertFalse($fileFilter->isFiltered(codecept_root_dir('tests/support/CodeGuy.php'))); + $driver = Stub::makeEmpty('SebastianBergmann\CodeCoverage\Driver\Driver'); + $this->filter = new Filter(new CodeCoverage($driver)); } public function testWhitelistFilterApplied() @@ -64,9 +38,6 @@ public function testWhitelistFilterApplied() $fileFilter = $this->filter->getFilter(); $this->assertFalse($fileFilter->isFiltered(codecept_root_dir('tests/unit/C3Test.php'))); $this->assertFalse($fileFilter->isFiltered(codecept_root_dir('src/Codeception/Codecept.php'))); - $this->assertFalse( - $fileFilter->isFiltered(codecept_root_dir('vendor/phpunit/phpunit/tests/Framework/AssertTest.php')) - ); $this->assertTrue($fileFilter->isFiltered(codecept_root_dir('vendor/guzzlehttp/guzzle/src/Client.php'))); $this->assertTrue($fileFilter->isFiltered(codecept_root_dir('tests/unit/CodeGuy.php'))); } diff --git a/tests/unit/Codeception/Exception/ModuleConfigTest.php b/tests/unit/Codeception/Exception/ModuleConfigTest.php index 1eacd8dabd..642761f222 100644 --- a/tests/unit/Codeception/Exception/ModuleConfigTest.php +++ b/tests/unit/Codeception/Exception/ModuleConfigTest.php @@ -1,6 +1,6 @@ 'localhost', diff --git a/tests/unit/Codeception/Module/AssertsTest.php b/tests/unit/Codeception/Module/AssertsTest.php index 91114755b9..cba9cd9c48 100644 --- a/tests/unit/Codeception/Module/AssertsTest.php +++ b/tests/unit/Codeception/Module/AssertsTest.php @@ -1,5 +1,5 @@ 'beanstalkq', diff --git a/tests/unit/Codeception/Module/FTPTest.php b/tests/unit/Codeception/Module/FTPTest.php index 73cfe85b60..c2dc790947 100644 --- a/tests/unit/Codeception/Module/FTPTest.php +++ b/tests/unit/Codeception/Module/FTPTest.php @@ -12,7 +12,7 @@ * Contact: nathan.macnamara@outlook.com * */ -class FTPTest extends \PHPUnit_Framework_TestCase +class FTPTest extends \PHPUnit\Framework\TestCase { protected $config = array( 'host' => '127.0.0.1', diff --git a/tests/unit/Codeception/Module/FilesystemTest.php b/tests/unit/Codeception/Module/FilesystemTest.php index 9a2d38642b..a123dbbeeb 100644 --- a/tests/unit/Codeception/Module/FilesystemTest.php +++ b/tests/unit/Codeception/Module/FilesystemTest.php @@ -3,7 +3,7 @@ use Codeception\Module\Filesystem; use Codeception\Util\Stub; -class FilesystemTest extends \PHPUnit_Framework_TestCase +class FilesystemTest extends \PHPUnit\Framework\TestCase { /** @@ -34,7 +34,7 @@ public function testSeeFileFoundPassesWhenFileExistsInSubdirectoryOfPath() } /** - * @expectedException PHPUnit_Framework_AssertionFailedError + * @expectedException PHPUnit\Framework\AssertionFailedError * @expectedExceptionMessage File "does-not-exist" not found at */ public function testSeeFileFoundFailsWhenFileDoesNotExist() @@ -43,7 +43,7 @@ public function testSeeFileFoundFailsWhenFileDoesNotExist() } /** - * @expectedException PHPUnit_Framework_AssertionFailedError + * @expectedException PHPUnit\Framework\AssertionFailedError * @expectedExceptionMessageRegExp /Directory does not exist: .*does-not-exist/ */ public function testSeeFileFoundFailsWhenPathDoesNotExist() @@ -62,7 +62,7 @@ public function testDontSeeFileFoundPassesWhenFileDoesNotExistsInPath() } /** - * @expectedException PHPUnit_Framework_AssertionFailedError + * @expectedException PHPUnit\Framework\AssertionFailedError * @expectedExceptionMessage Failed asserting that file "tests/data/dumps/mysql.sql" does not exist. */ public function testDontSeeFileFoundFailsWhenFileExists() @@ -71,7 +71,7 @@ public function testDontSeeFileFoundFailsWhenFileExists() } /** - * @expectedException PHPUnit_Framework_AssertionFailedError + * @expectedException PHPUnit\Framework\AssertionFailedError * @expectedExceptionMessageRegExp /Directory does not exist: .*does-not-exist/ */ public function testDontSeeFileFoundFailsWhenPathDoesNotExist() @@ -80,7 +80,7 @@ public function testDontSeeFileFoundFailsWhenPathDoesNotExist() } /** - * @expectedException PHPUnit_Framework_AssertionFailedError + * @expectedException PHPUnit\Framework\AssertionFailedError * @expectedExceptionMessageRegExp /Failed asserting that file ".*tests\/data\/dumps\/mysql.sql" does not exist/ */ public function testDontSeeFileFoundFailsWhenFileExistsInSubdirectoryOfPath() diff --git a/tests/unit/Codeception/Module/FrameworksTest.php b/tests/unit/Codeception/Module/FrameworksTest.php index 4852cf79ca..7511c35a22 100644 --- a/tests/unit/Codeception/Module/FrameworksTest.php +++ b/tests/unit/Codeception/Module/FrameworksTest.php @@ -84,12 +84,12 @@ public function testMoveBackThrowsExceptionIfNumberOfStepsIsInvalid() public function testCreateSnapshotOnFail() { $module = Stub::construct(get_class($this->module), [make_container()], [ - '_savePageSource' => Stub::once(function ($filename) { + '_savePageSource' => \Codeception\Stub\Expected::once(function ($filename) { $this->assertEquals(codecept_log_dir('Codeception.Module.UniversalFramework.looks.like..test.fail.html'), $filename); }), ]); $module->amOnPage('/'); $cest = new \Codeception\Test\Cest($this->module, 'looks:like::test', 'demo1Cest.php'); - $module->_failed($cest, new PHPUnit_Framework_AssertionFailedError()); + $module->_failed($cest, new \PHPUnit\Framework\AssertionFailedError()); } } diff --git a/tests/unit/Codeception/Module/MongoDbLegacyTest.php b/tests/unit/Codeception/Module/MongoDbLegacyTest.php index fbc543496e..a8caa42ac5 100644 --- a/tests/unit/Codeception/Module/MongoDbLegacyTest.php +++ b/tests/unit/Codeception/Module/MongoDbLegacyTest.php @@ -2,7 +2,7 @@ use Codeception\Module\MongoDb; -class MongoDbLegacyTest extends \PHPUnit_Framework_TestCase +class MongoDbLegacyTest extends \PHPUnit\Framework\TestCase { /** * @var array @@ -102,7 +102,7 @@ public function testSeeElementIsArray() public function testSeeElementIsArrayThrowsError() { - $this->setExpectedException('PHPUnit_Framework_ExpectationFailedException'); + $this->setExpectedException('PHPUnit\Framework\ExpectationFailedException'); $this->userCollection->insert(array('id' => 5, 'trumpets' => array('piccolo', 'bass', 'slide'))); $this->userCollection->insert(array('id' => 6, 'trumpets' => array('piccolo', 'bass', 'slide'))); @@ -130,7 +130,7 @@ public function testSeeElementIsObjectThrowsError() $trumpet->pitch = 'B♭'; $trumpet->price = array('min' => 458, 'max' => 891); - $this->setExpectedException('PHPUnit_Framework_ExpectationFailedException'); + $this->setExpectedException('PHPUnit\Framework\ExpectationFailedException'); $this->userCollection->insert(array('id' => 5, 'trumpet' => $trumpet)); $this->userCollection->insert(array('id' => 6, 'trumpet' => $trumpet)); diff --git a/tests/unit/Codeception/Module/MongoDbTest.php b/tests/unit/Codeception/Module/MongoDbTest.php index 4ea7135b95..7baa4e9cde 100644 --- a/tests/unit/Codeception/Module/MongoDbTest.php +++ b/tests/unit/Codeception/Module/MongoDbTest.php @@ -107,7 +107,7 @@ public function testSeeElementIsArray() public function testSeeElementIsArrayThrowsError() { - $this->setExpectedException('PHPUnit_Framework_ExpectationFailedException'); + $this->setExpectedException('PHPUnit\Framework\ExpectationFailedException'); $this->userCollection->insertOne(array('id' => 5, 'trumpets' => array('piccolo', 'bass', 'slide'))); $this->userCollection->insertOne(array('id' => 6, 'trumpets' => array('piccolo', 'bass', 'slide'))); @@ -135,7 +135,7 @@ public function testSeeElementIsObjectThrowsError() $trumpet->pitch = 'B♭'; $trumpet->price = array('min' => 458, 'max' => 891); - $this->setExpectedException('PHPUnit_Framework_ExpectationFailedException'); + $this->setExpectedException('PHPUnit\Framework\ExpectationFailedException'); $this->userCollection->insertOne(array('id' => 5, 'trumpet' => $trumpet)); $this->userCollection->insertOne(array('id' => 6, 'trumpet' => $trumpet)); diff --git a/tests/unit/Codeception/Module/PhpBrowserRestTest.php b/tests/unit/Codeception/Module/PhpBrowserRestTest.php index df605009ee..0d6f5b6c3c 100644 --- a/tests/unit/Codeception/Module/PhpBrowserRestTest.php +++ b/tests/unit/Codeception/Module/PhpBrowserRestTest.php @@ -71,7 +71,7 @@ public function testValidJson() public function testInvalidJson() { - $this->setExpectedException('PHPUnit_Framework_ExpectationFailedException'); + $this->setExpectedException('PHPUnit\Framework\ExpectationFailedException'); $this->setStubResponse('{xxx = yyy}'); $this->module->seeResponseIsJson(); } @@ -87,7 +87,7 @@ public function testValidXml() public function testInvalidXml() { - $this->setExpectedException('PHPUnit_Framework_ExpectationFailedException'); + $this->setExpectedException('PHPUnit\Framework\ExpectationFailedException'); $this->setStubResponse('John'); $this->module->seeResponseIsXml(); } @@ -315,7 +315,7 @@ public function testSessionHeaderBackup() protected function shouldFail() { - $this->setExpectedException('PHPUnit_Framework_AssertionFailedError'); + $this->setExpectedException('PHPUnit\Framework\AssertionFailedError'); } public function testGrabFromCurrentUrl() diff --git a/tests/unit/Codeception/Module/PhpBrowserTest.php b/tests/unit/Codeception/Module/PhpBrowserTest.php index f2a41cd561..9c911f4414 100644 --- a/tests/unit/Codeception/Module/PhpBrowserTest.php +++ b/tests/unit/Codeception/Module/PhpBrowserTest.php @@ -608,7 +608,7 @@ public function testClickSelectsClickableElementFromMatchesUsingCssLocator() } /** - * @expectedException PHPUnit_Framework_AssertionFailedError + * @expectedException PHPUnit\Framework\AssertionFailedError */ public function testClickingOnButtonOutsideFormDoesNotCauseFatalError() { diff --git a/tests/unit/Codeception/Module/RedisTest.php b/tests/unit/Codeception/Module/RedisTest.php index 2507f37268..414851f5ef 100644 --- a/tests/unit/Codeception/Module/RedisTest.php +++ b/tests/unit/Codeception/Module/RedisTest.php @@ -94,7 +94,7 @@ protected function setUp() protected function shouldFail($exceptionClass = null) { if (!$exceptionClass) { - $exceptionClass = 'PHPUnit_Framework_AssertionFailedError'; + $exceptionClass = 'PHPUnit\Framework\AssertionFailedError'; } $this->setExpectedException($exceptionClass); diff --git a/tests/unit/Codeception/Module/RestTest.php b/tests/unit/Codeception/Module/RestTest.php index c09fd0a25c..a823e5c13f 100644 --- a/tests/unit/Codeception/Module/RestTest.php +++ b/tests/unit/Codeception/Module/RestTest.php @@ -109,7 +109,7 @@ public function testValidJson() public function testInvalidJson() { - $this->setExpectedException('PHPUnit_Framework_ExpectationFailedException'); + $this->setExpectedException('PHPUnit\Framework\ExpectationFailedException'); $this->setStubResponse('{xxx = yyy}'); $this->module->seeResponseIsJson(); } @@ -124,7 +124,7 @@ public function testValidXml() public function testInvalidXml() { - $this->setExpectedException('PHPUnit_Framework_ExpectationFailedException'); + $this->setExpectedException('PHPUnit\Framework\ExpectationFailedException'); $this->setStubResponse('John'); $this->module->seeResponseIsXml(); } @@ -366,7 +366,7 @@ public function testMatchJsonTypeFailsWithNiceMessage() try { $this->module->seeResponseMatchesJsonType(['zzz' => 'string']); $this->fail('it had to throw exception'); - } catch (PHPUnit_Framework_AssertionFailedError $e) { + } catch (PHPUnit\Framework\AssertionFailedError $e) { $this->assertEquals('Key `zzz` doesn\'t exist in {"xxx":"yyy","user_id":1}', $e->getMessage()); } } @@ -377,7 +377,7 @@ public function testDontMatchJsonTypeFailsWithNiceMessage() try { $this->module->dontSeeResponseMatchesJsonType(['xxx' => 'string']); $this->fail('it had to throw exception'); - } catch (PHPUnit_Framework_AssertionFailedError $e) { + } catch (PHPUnit\Framework\AssertionFailedError $e) { $this->assertEquals('Unexpectedly response matched: {"xxx":"yyy","user_id":1}', $e->getMessage()); } } @@ -436,7 +436,7 @@ public function testAmDigestAuthenticatedThrowsExceptionWithFunctionalModules() protected function shouldFail() { - $this->setExpectedException('PHPUnit_Framework_AssertionFailedError'); + $this->setExpectedException('PHPUnit\Framework\AssertionFailedError'); } } diff --git a/tests/unit/Codeception/Module/SFTPTest.php b/tests/unit/Codeception/Module/SFTPTest.php index 3912f2bf18..7944c98537 100644 --- a/tests/unit/Codeception/Module/SFTPTest.php +++ b/tests/unit/Codeception/Module/SFTPTest.php @@ -12,7 +12,7 @@ * Contact: nathan.macnamara@outlook.com * */ -class SFTPTest extends \PHPUnit_Framework_TestCase +class SFTPTest extends \PHPUnit\Framework\TestCase { protected $config = array( 'host' => '127.0.0.1', diff --git a/tests/unit/Codeception/Module/SoapTest.php b/tests/unit/Codeception/Module/SoapTest.php index 5dbb25fd60..9ba0a8e462 100644 --- a/tests/unit/Codeception/Module/SoapTest.php +++ b/tests/unit/Codeception/Module/SoapTest.php @@ -7,7 +7,7 @@ * Class SoapTest * @group appveyor */ -class SoapTest extends \PHPUnit_Framework_TestCase +class SoapTest extends \PHPUnit\Framework\TestCase { /** diff --git a/tests/unit/Codeception/Module/TestsForWeb.php b/tests/unit/Codeception/Module/TestsForWeb.php index 9c62ea707a..e636ea7110 100644 --- a/tests/unit/Codeception/Module/TestsForWeb.php +++ b/tests/unit/Codeception/Module/TestsForWeb.php @@ -8,7 +8,7 @@ * */ -abstract class TestsForWeb extends \Codeception\TestCase\Test +abstract class TestsForWeb extends \Codeception\Test\Unit { /** * @var \Codeception\Module\PhpBrowser @@ -92,7 +92,7 @@ public function testSeeIsCaseInsensitiveForUnicodeText() public function testDontSeeIsCaseInsensitiveForUnicodeText() { - $this->setExpectedException("PHPUnit_Framework_AssertionFailedError"); + $this->setExpectedException("PHPUnit\Framework\AssertionFailedError"); $this->module->amOnPage('/info'); $this->module->dontSee('ссылочка'); } @@ -128,7 +128,7 @@ public function testDontSeeLink() public function testSeeLinkFailsIfTextDoesNotMatch() { $this->setExpectedException( - 'PHPUnit_Framework_AssertionFailedError', + 'PHPUnit\Framework\AssertionFailedError', "No links containing text 'Codeception' were found in page /external_url" ); $this->module->amOnPage('/external_url'); @@ -138,7 +138,7 @@ public function testSeeLinkFailsIfTextDoesNotMatch() public function testSeeLinkFailsIfHrefDoesNotMatch() { $this->setExpectedException( - 'PHPUnit_Framework_AssertionFailedError', + 'PHPUnit\Framework\AssertionFailedError', "No links containing text 'Next' and URL '/fsdfsdf/' were found in page /external_url" ); $this->module->amOnPage('/external_url'); @@ -148,7 +148,7 @@ public function testSeeLinkFailsIfHrefDoesNotMatch() public function testDontSeeLinkFailsIfTextMatches() { $this->setExpectedException( - 'PHPUnit_Framework_AssertionFailedError', + 'PHPUnit\Framework\AssertionFailedError', "Link containing text 'Next' was found in page /external_url" ); $this->module->amOnPage('/external_url'); @@ -158,7 +158,7 @@ public function testDontSeeLinkFailsIfTextMatches() public function testDontSeeLinkFailsIfTextAndUrlMatches() { $this->setExpectedException( - 'PHPUnit_Framework_AssertionFailedError', + 'PHPUnit\Framework\AssertionFailedError', "Link containing text 'Next' and URL 'http://codeception.com/' was found in page /external_url" ); $this->module->amOnPage('/external_url'); @@ -174,7 +174,7 @@ public function testSeeLinkMatchesRelativeLink() public function testDontSeeLinkMatchesRelativeLink() { $this->setExpectedException( - 'PHPUnit_Framework_AssertionFailedError', + 'PHPUnit\Framework\AssertionFailedError', "Link containing text 'Sign in!' and URL '/login' was found in page /info" ); $this->module->amOnPage('/info'); @@ -611,7 +611,7 @@ public function testSeeInFormFields() public function testSeeInFormFieldsFails() { $this->module->amOnPage('/form/field_values'); - $this->setExpectedException("PHPUnit_Framework_AssertionFailedError"); + $this->setExpectedException("PHPUnit\Framework\AssertionFailedError"); $params = [ 'radio1' => 'something I should not see', 'checkbox1' => true, @@ -649,7 +649,7 @@ public function testDontSeeInFormFields() public function testDontSeeInFormFieldsFails() { $this->module->amOnPage('/form/field_values'); - $this->setExpectedException("PHPUnit_Framework_AssertionFailedError"); + $this->setExpectedException("PHPUnit\Framework\AssertionFailedError"); $params = [ 'checkbox[]' => [ 'wont see this anyway', @@ -777,7 +777,7 @@ public function testSeeElementOnPage() // regression test. https://github.com/Codeception/Codeception/issues/587 public function testSeeElementOnPageFails() { - $this->setExpectedException("PHPUnit_Framework_AssertionFailedError"); + $this->setExpectedException("PHPUnit\Framework\AssertionFailedError"); $this->module->amOnPage('/form/field'); $this->module->dontSeeElement('input[name=name]'); } @@ -1197,7 +1197,7 @@ public function testSelectTwoSubmitsByCSS() protected function shouldFail() { - $this->setExpectedException('PHPUnit_Framework_AssertionFailedError'); + $this->setExpectedException('PHPUnit\Framework\AssertionFailedError'); } /** diff --git a/tests/unit/Codeception/ModuleTest.php b/tests/unit/Codeception/ModuleTest.php index 017460b66d..3a9a52c2ab 100644 --- a/tests/unit/Codeception/ModuleTest.php +++ b/tests/unit/Codeception/ModuleTest.php @@ -2,7 +2,7 @@ use Codeception\Util\Stub; -class ModuleTest extends \PHPUnit_Framework_TestCase +class ModuleTest extends \PHPUnit\Framework\TestCase { public function testRequirements() { diff --git a/tests/unit/Codeception/ScenarioTest.php b/tests/unit/Codeception/ScenarioTest.php index 3a9a552399..8410707f30 100644 --- a/tests/unit/Codeception/ScenarioTest.php +++ b/tests/unit/Codeception/ScenarioTest.php @@ -1,6 +1,6 @@ suiteman = new \Codeception\SuiteManager($this->dispatcher, 'suite', $settings); - $printer = \Codeception\Util\Stub::makeEmpty('PHPUnit_TextUI_ResultPrinter'); + $printer = \Codeception\Util\Stub::makeEmpty('PHPUnit\TextUI\ResultPrinter'); $this->runner = new \Codeception\PHPUnit\Runner; $this->runner->setPrinter($printer); } @@ -49,7 +49,7 @@ public function testRun() $this->dispatcher->addListener('suite.after', $eventListener); $this->suiteman->run( $this->runner, - new \PHPUnit_Framework_TestResult, + new \PHPUnit\Framework\TestResult, ['colors' => false, 'steps' => true, 'debug' => false, 'report_useless_tests' => false, 'disallow_test_output' => false] ); $this->assertEquals($events, ['suite.before', 'suite.after']); @@ -109,7 +109,7 @@ public function testGroupEventsAreFired() $this->dispatcher->addListener('test.after.admin', $eventListener); $this->suiteman->loadTests(codecept_data_dir().'SimpleAdminGroupCest.php'); - $result = new \PHPUnit_Framework_TestResult; + $result = new \PHPUnit\Framework\TestResult; $listener = new \Codeception\PHPUnit\Listener($this->dispatcher); $result->addListener($listener); $this->suiteman->run( diff --git a/tests/unit/Codeception/TestLoaderTest.php b/tests/unit/Codeception/TestLoaderTest.php index 9d0044ed31..607a7a4fa8 100644 --- a/tests/unit/Codeception/TestLoaderTest.php +++ b/tests/unit/Codeception/TestLoaderTest.php @@ -4,7 +4,7 @@ * Class TestLoaderTest * @group load */ -class TestLoaderTest extends \PHPUnit_Framework_TestCase +class TestLoaderTest extends \PHPUnit\Framework\TestCase { /** * @var \Codeception\Test\Loader diff --git a/tests/unit/Codeception/Util/AnnotationTest.php b/tests/unit/Codeception/Util/AnnotationTest.php index 7b35503bc3..63d7b4a6d6 100644 --- a/tests/unit/Codeception/Util/AnnotationTest.php +++ b/tests/unit/Codeception/Util/AnnotationTest.php @@ -8,7 +8,7 @@ * @tag codeception * @tag tdd */ -class AnnotationTest extends PHPUnit_Framework_TestCase +class AnnotationTest extends \PHPUnit\Framework\TestCase { public function testClassAnnotation() diff --git a/tests/unit/Codeception/Util/AutoloadTest.php b/tests/unit/Codeception/Util/AutoloadTest.php index 829c3e9552..66963ff669 100644 --- a/tests/unit/Codeception/Util/AutoloadTest.php +++ b/tests/unit/Codeception/Util/AutoloadTest.php @@ -4,7 +4,7 @@ use Codeception\Util\MockAutoload as Autoload; -class AutoloadTest extends PHPUnit_Framework_TestCase +class AutoloadTest extends \PHPUnit\Framework\TestCase { protected function setUp() diff --git a/tests/unit/Codeception/Util/LocatorTest.php b/tests/unit/Codeception/Util/LocatorTest.php index 00fe335681..021dcd376e 100644 --- a/tests/unit/Codeception/Util/LocatorTest.php +++ b/tests/unit/Codeception/Util/LocatorTest.php @@ -3,7 +3,7 @@ use Codeception\Util\Locator; use Facebook\WebDriver\WebDriverBy; -class LocatorTest extends PHPUnit_Framework_TestCase +class LocatorTest extends \PHPUnit\Framework\TestCase { public function testCombine() diff --git a/tests/unit/Codeception/Util/StubTest.php b/tests/unit/Codeception/Util/StubTest.php index 647a1ad736..2750529d7d 100644 --- a/tests/unit/Codeception/Util/StubTest.php +++ b/tests/unit/Codeception/Util/StubTest.php @@ -1,7 +1,7 @@ thenWeDontCallAnyMethodForExceptionJustVerify($mock); } - } catch (PHPUnit_Framework_ExpectationFailedException $e) { + } catch (PHPUnit\Framework\ExpectationFailedException $e) { $this->assertSame($failMessage, $e->getMessage()); } diff --git a/tests/unit/Codeception/Util/TemplateTest.php b/tests/unit/Codeception/Util/TemplateTest.php index 7f0b3744cb..f17e841d5f 100644 --- a/tests/unit/Codeception/Util/TemplateTest.php +++ b/tests/unit/Codeception/Util/TemplateTest.php @@ -1,7 +1,7 @@ Date: Mon, 26 Feb 2018 20:53:14 +0200 Subject: [PATCH 002/395] call after hook for Cest after every test (PASSED or FAILED) (#4813) * call after hook for Cest after every test (PASSED or FAILED) * call after in finally block to prevent multiple calls --- src/Codeception/Test/Cest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Codeception/Test/Cest.php b/src/Codeception/Test/Cest.php index cb2a130f83..ea5beea4b2 100644 --- a/src/Codeception/Test/Cest.php +++ b/src/Codeception/Test/Cest.php @@ -81,11 +81,12 @@ public function test() $this->executeBeforeMethods($this->testMethod, $I); $this->executeTestMethod($I); $this->executeAfterMethods($this->testMethod, $I); - $this->executeHook($I, 'after'); } catch (\Exception $e) { $this->executeHook($I, 'failed'); // fails and errors are now handled by Codeception\PHPUnit\Listener throw $e; + } finally { + $this->executeHook($I, 'after'); } } From 1cd7980d6ce044ec38da2040912f186cbfc244a0 Mon Sep 17 00:00:00 2001 From: Gintautas Miselis Date: Mon, 26 Feb 2018 20:03:49 +0000 Subject: [PATCH 003/395] Support behat/gherkin 4.5 (#4830) --- composer.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/composer.json b/composer.json index aff71e1210..80fda783a2 100644 --- a/composer.json +++ b/composer.json @@ -28,10 +28,9 @@ "symfony/browser-kit": ">=2.7 <5.0", "symfony/css-selector": ">=2.7 <5.0", "symfony/dom-crawler": ">=2.7 <5.0", - "behat/gherkin": "~4.4.0", + "behat/gherkin": "^4.4.0", "codeception/phpunit-wrapper": "^6.0|^7.0", "codeception/stub": "^1.0" - }, "require-dev": { "monolog/monolog": "~1.8", From 75f59f3a035513ffaf2d94e0a86de57b03901d29 Mon Sep 17 00:00:00 2001 From: Davert Date: Tue, 27 Feb 2018 00:19:28 +0200 Subject: [PATCH 004/395] updated Cest format, added _passed hook --- docs/07-AdvancedUsage.md | 24 ++++++++++++++++++------ src/Codeception/Test/Cest.php | 1 + 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/docs/07-AdvancedUsage.md b/docs/07-AdvancedUsage.md index 7bc966f030..637d0afca2 100644 --- a/docs/07-AdvancedUsage.md +++ b/docs/07-AdvancedUsage.md @@ -40,7 +40,6 @@ class BasicCest and will receive an instance of the Actor class as the first parameter and the `$scenario` variable as the second one. In `_before` and `_after` methods you can use common setups and teardowns for the tests in the class. -This actually makes Cest tests more flexible than Cepts, which rely only on similar methods in Helper classes. As you see, we are passing the Actor object into `tryToTest` method. This allows us to write scenarios the way we did before: @@ -51,7 +50,6 @@ class BasicCest // test public function tryToTest(\AcceptanceTester $I) { - $I->wantTo('log in to site'); $I->amOnPage('/'); $I->click('Login'); $I->fillField('username', 'john'); @@ -63,11 +61,27 @@ class BasicCest } ``` -As you see, Cest classes have no parents like `\Codeception\Test\Unit` or `PHPUnit_Framework_TestCase`. +As you see, Cest classes have no parents. This is done intentionally. It allows you to extend your classes with common behaviors and workarounds that may be used in child classes. But don't forget to make these methods `protected` so they won't be executed as tests. -You can also define a `_failed` method in Cest classes which will be called if test finishes with `error` or fails. +Cest format also can contain hooks based on test results: + +* `_failed` will be executed on failed test +* `_passed` will be executed on passed test + +```php +wantTo('sign up'); - $this->navBar->click('Sign up'); $this->signUp->register([ 'first_name' => 'Joe', diff --git a/src/Codeception/Test/Cest.php b/src/Codeception/Test/Cest.php index ea5beea4b2..20f51f5ffd 100644 --- a/src/Codeception/Test/Cest.php +++ b/src/Codeception/Test/Cest.php @@ -81,6 +81,7 @@ public function test() $this->executeBeforeMethods($this->testMethod, $I); $this->executeTestMethod($I); $this->executeAfterMethods($this->testMethod, $I); + $this->executeHook($I, 'passed'); } catch (\Exception $e) { $this->executeHook($I, 'failed'); // fails and errors are now handled by Codeception\PHPUnit\Listener From 612af75585bd454b8f2585bf2f89c606c8cc039b Mon Sep 17 00:00:00 2001 From: Davert Date: Tue, 27 Feb 2018 01:28:27 +0200 Subject: [PATCH 005/395] release --- CHANGELOG-2.4.md | 12 ++++++++++++ RoboFile.php | 21 +++++++++++++-------- docs/05-UnitTests.md | 4 ++-- 3 files changed, 27 insertions(+), 10 deletions(-) create mode 100644 CHANGELOG-2.4.md diff --git a/CHANGELOG-2.4.md b/CHANGELOG-2.4.md new file mode 100644 index 0000000000..7c2f5ac802 --- /dev/null +++ b/CHANGELOG-2.4.md @@ -0,0 +1,12 @@ +#### 2.4.0 + +* PHPUnit 7.x compatibility +* Internal API refactored: + * Modern PHP class names used internally + * Moved PHPUnit related classes to [codeception/phpunit-wrapper](https://github.com/Codeception/phpunit-wrapper) package. +* Dropped PHP 5.4 and PHP 5.5 support (PHP 5.5 still may work) +* Cest hooks behavior changed (by @fffilimonov): + * `_failed` called when test fails + * `_passed` called when tests is successful + * `_after` is called for failing and successful tests + \ No newline at end of file diff --git a/RoboFile.php b/RoboFile.php index f4c8c22b5f..5811e50b86 100644 --- a/RoboFile.php +++ b/RoboFile.php @@ -6,7 +6,7 @@ class RoboFile extends \Robo\Tasks { - const STABLE_BRANCH = '2.3'; + const STABLE_BRANCH = '2.4'; const REPO_BLOB_URL = 'https://github.com/Codeception/Codeception/blob'; public function release() @@ -144,11 +144,11 @@ public function testCli() ->run(); } - private function installDependenciesForPhp54() + private function installDependenciesForPhp5() { $this->taskReplaceInFile('composer.json') ->regex('/"platform": \{.*?\}/') - ->to('"platform": {"php": "5.4.0"}') + ->to('"platform": {"php": "5.6.0"}') ->run(); $this->taskComposerUpdate()->run(); @@ -197,7 +197,7 @@ public function buildPhar5() if (!file_exists('package/php54')) { mkdir('package/php54'); } - $this->installDependenciesForPhp54(); + $this->installDependenciesForPhp5(); $this->packPhar('package/codecept5.phar'); $this->_copy('package/codecept5.phar', 'package/php54/codecept.phar'); $code = $this->taskExec('php codecept.phar')->dir('package/php54')->run()->getExitCode(); @@ -270,10 +270,13 @@ private function packPhar($pharFileName) $pharTask->addFile('autoload.php', 'autoload.php') ->addFile('codecept', 'package/bin') - ->addFile('shim.php', 'shim.php') - ->addFile('phpunit5-loggers.php', 'phpunit5-loggers.php') - ->run(); + ->addFile('shim.php', 'shim.php'); + + if (file_exists(__DIR__ .'phpunit5-loggers.php')) { + $pharTask->addFile('phpunit5-loggers.php', 'phpunit5-loggers.php'); + } + $pharTask->run(); } /** @@ -538,7 +541,9 @@ public function publishPhar() if (file_exists("releases/$releaseName/php54/codecept.phar")) { $downloadUrl = "http://codeception.com/releases/$releaseName/php54/codecept.phar"; - if (version_compare($releaseName, '2.3.0', '>=')) { + if (version_compare($releaseName, '2.4.0', '>=')) { + $versionLine .= ", [for PHP 5.6]($downloadUrl)"; + } elseif (version_compare($releaseName, '2.3.0', '>=')) { $versionLine .= ", [for PHP 5.4 - 5.6]($downloadUrl)"; } else { $versionLine .= ", [for PHP 5.4 or 5.5]($downloadUrl)"; diff --git a/docs/05-UnitTests.md b/docs/05-UnitTests.md index cf42a962cd..0aa9400710 100644 --- a/docs/05-UnitTests.md +++ b/docs/05-UnitTests.md @@ -156,7 +156,7 @@ In this \Codeception\Stub::make(UserRepository::class, ['find' => new User]); ``` -See a reference for static Stub API +See a reference for [static Stub API](http://codeception.com/docs/reference/Stub) #### Mocks @@ -468,6 +468,6 @@ public function testSingleton() ## Conclusion PHPUnit tests are first-class citizens in test suites. Whenever you need to write and execute unit tests, -you don't need to install PHPUnit seperately, but use Codeception directly to execute them. +you don't need to install PHPUnit separately, but use Codeception directly to execute them. Some nice features can be added to common unit tests by integrating Codeception modules. For most unit and integration testing, PHPUnit tests are enough. They run fast, and are easy to maintain. From 881b517797b4852684b3893cdf2091260fe1825c Mon Sep 17 00:00:00 2001 From: Davert Date: Tue, 27 Feb 2018 01:51:49 +0200 Subject: [PATCH 006/395] added PasswordArgument to docs --- docs/03-AcceptanceTests.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/docs/03-AcceptanceTests.md b/docs/03-AcceptanceTests.md index 171b1cb755..bab9320268 100644 --- a/docs/03-AcceptanceTests.md +++ b/docs/03-AcceptanceTests.md @@ -196,6 +196,22 @@ $I->submitForm('#update_form', array('user' => array( ))); ``` +##### Hiding Sensitive Data + +If you need to fill in sensitive data (like passwords) and hide it in logs, +you can pass instance `\Codeception\Step\Argument\PasswordArgument` with the data which needs to be hidden. + +```php +amOnPage('/form/password_argument'); +$I->fillField('password', new PasswordArgument('thisissecret')); +``` + +`thisissecret` will be filled into a form but it won't be shown in output and logs. + #### Assertions In the `PhpBrowser` you can test the page contents. From c50789a9a62cc0eefc0252e88a5f04f8c47b55f4 Mon Sep 17 00:00:00 2001 From: Davert Date: Tue, 27 Feb 2018 02:09:12 +0200 Subject: [PATCH 007/395] preparing 2.4.0 release --- CHANGELOG-2.4.md | 4 ++-- src/Codeception/Codecept.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG-2.4.md b/CHANGELOG-2.4.md index 7c2f5ac802..43e22a5a34 100644 --- a/CHANGELOG-2.4.md +++ b/CHANGELOG-2.4.md @@ -1,10 +1,10 @@ #### 2.4.0 -* PHPUnit 7.x compatibility +* **PHPUnit 7.x compatibility** +* **Dropped PHP 5.4 and PHP 5.5** support (PHP 5.5 still may work) * Internal API refactored: * Modern PHP class names used internally * Moved PHPUnit related classes to [codeception/phpunit-wrapper](https://github.com/Codeception/phpunit-wrapper) package. -* Dropped PHP 5.4 and PHP 5.5 support (PHP 5.5 still may work) * Cest hooks behavior changed (by @fffilimonov): * `_failed` called when test fails * `_passed` called when tests is successful diff --git a/src/Codeception/Codecept.php b/src/Codeception/Codecept.php index 4530848ebe..95b0235b6c 100644 --- a/src/Codeception/Codecept.php +++ b/src/Codeception/Codecept.php @@ -7,7 +7,7 @@ class Codecept { - const VERSION = "2.3.9"; + const VERSION = "2.4.0"; /** * @var \Codeception\PHPUnit\Runner From dc739be18b4e84ef8c7620a127ca51ae56564e44 Mon Sep 17 00:00:00 2001 From: Davert Date: Tue, 27 Feb 2018 14:14:39 +0200 Subject: [PATCH 008/395] updated docs, updated statuses for readme --- CHANGELOG-2.4.md | 4 +- RoboFile.php | 2 +- docs/modules/AMQP.md | 29 ++- docs/modules/AngularJS.md | 369 +++++++++++++++++++-------- docs/modules/Apc.md | 18 +- docs/modules/Asserts.md | 104 +++++--- docs/modules/Cli.md | 21 +- docs/modules/DataFactory.md | 38 ++- docs/modules/Db.md | 31 ++- docs/modules/Doctrine2.md | 29 ++- docs/modules/FTP.md | 82 ++++-- docs/modules/Facebook.md | 29 ++- docs/modules/Filesystem.md | 47 ++-- docs/modules/Laravel5.md | 309 ++++++++++++++-------- docs/modules/Lumen.md | 249 ++++++++++++------ docs/modules/Memcache.md | 18 +- docs/modules/MongoDb.md | 30 ++- docs/modules/Phalcon.md | 232 +++++++++++------ docs/modules/PhpBrowser.md | 207 ++++++++++----- docs/modules/Queue.md | 43 +++- docs/modules/REST.md | 153 +++++++---- docs/modules/Redis.md | 27 +- docs/modules/SOAP.md | 45 ++-- docs/modules/Sequence.md | 3 +- docs/modules/Silex.md | 196 +++++++++----- docs/modules/Symfony.md | 224 ++++++++++------ docs/modules/WebDriver.md | 364 ++++++++++++++++++-------- docs/modules/XMLRPC.md | 15 +- docs/modules/Yii1.md | 193 +++++++++----- docs/modules/Yii2.md | 259 ++++++++++++------- docs/modules/ZF1.md | 197 +++++++++----- docs/modules/ZF2.md | 202 ++++++++++----- docs/modules/ZendExpressive.md | 191 +++++++++----- docs/reference/Autoload.md | 33 +-- docs/reference/Commands.md | 65 ++++- docs/reference/Fixtures.md | 22 +- docs/reference/HttpCode.md | 11 +- docs/reference/InitTemplate.md | 98 +++---- docs/reference/JsonType.md | 30 ++- docs/reference/Locator.md | 78 +++--- docs/reference/Mock.md | 51 +--- docs/reference/Module.md | 262 ++++++++++--------- docs/reference/XmlBuilder.md | 38 +-- ext/README.md | 28 +- readme.md | 6 +- src/Codeception/Codecept.php | 2 +- src/Codeception/Module/WebDriver.php | 62 ++--- 47 files changed, 3125 insertions(+), 1621 deletions(-) diff --git a/CHANGELOG-2.4.md b/CHANGELOG-2.4.md index 43e22a5a34..f925fc89bf 100644 --- a/CHANGELOG-2.4.md +++ b/CHANGELOG-2.4.md @@ -8,5 +8,5 @@ * Cest hooks behavior changed (by @fffilimonov): * `_failed` called when test fails * `_passed` called when tests is successful - * `_after` is called for failing and successful tests - \ No newline at end of file + * `_after` is called for failing and successful tests + diff --git a/RoboFile.php b/RoboFile.php index 5811e50b86..e06510c685 100644 --- a/RoboFile.php +++ b/RoboFile.php @@ -612,7 +612,7 @@ public function publishDocs() 'source' => self::REPO_BLOB_URL."/".self::STABLE_BRANCH."/src/Codeception/Module/$name.php" ]; // building version switcher - foreach (['master', '2.2', '2.1', '2.0', '1.8'] as $branch) { + foreach (['master', '2.3', '2.2', '2.1', '2.0', '1.8'] as $branch) { $buttons[$branch] = self::REPO_BLOB_URL."/$branch/docs/modules/$name.md"; } $buttonHtml = "\n\n".'

'; diff --git a/docs/modules/AMQP.md b/docs/modules/AMQP.md index c7e332eea4..737054dfb1 100644 --- a/docs/modules/AMQP.md +++ b/docs/modules/AMQP.md @@ -1,5 +1,6 @@ # AMQP + This module interacts with message broker software that implements the Advanced Message Queuing Protocol (AMQP) standard. For example, RabbitMQ (tested). @@ -37,7 +38,7 @@ To use this module with Composer you need "php-amqplib/php-amqplib": "~2.4"< ## Actions ### bindQueueToExchange - + Binds a queue to an exchange This is an alias of method `queue_bind` of `PhpAmqpLib\Channel\AMQPChannel`. @@ -59,8 +60,9 @@ $I->bindQueueToExchange( * `param int` $ticket * `return` mixed|null -### declareExchange +### declareExchange + Declares an exchange This is an alias of method `exchange_declare` of `PhpAmqpLib\Channel\AMQPChannel`. @@ -84,8 +86,9 @@ $I->declareExchange( * `param int` $ticket * `return` mixed|null -### declareQueue +### declareQueue + Declares queue, creates if needed This is an alias of method `queue_declare` of `PhpAmqpLib\Channel\AMQPChannel`. @@ -107,8 +110,9 @@ $I->declareQueue( * `param int` $ticket * `return` mixed|null -### grabMessageFromQueue +### grabMessageFromQueue + Takes last message from queue. ``` php @@ -120,8 +124,9 @@ $message = $I->grabMessageFromQueue('queue.emails'); * `param string` $queue * `return` \PhpAmqpLib\Message\AMQPMessage -### purgeAllQueues +### purgeAllQueues + Purge all queues defined in config. ``` php @@ -130,8 +135,9 @@ $I->purgeAllQueues(); ?> ``` -### purgeQueue +### purgeQueue + Purge a specific queue defined in config. ``` php @@ -142,8 +148,9 @@ $I->purgeQueue('queue.emails'); * `param string` $queueName -### pushToExchange +### pushToExchange + Sends message to exchange by sending exchange name, message and (optionally) a routing key @@ -159,8 +166,9 @@ $I->pushToExchange('exchange.emails', new AMQPMessage('Thanks!'), 'severity'); * `param string|\PhpAmqpLib\Message\AMQPMessage` $message * `param string` $routing_key -### pushToQueue +### pushToQueue + Sends message to queue ``` php @@ -173,8 +181,9 @@ $I->pushToQueue('queue.jobs', new AMQPMessage('create')); * `param string` $queue * `param string|\PhpAmqpLib\Message\AMQPMessage` $message -### seeMessageInQueueContainsText +### seeMessageInQueueContainsText + Checks if message containing text received. **This method drops message from queue** @@ -190,4 +199,4 @@ $I->seeMessageInQueueContainsText('queue.emails','davert'); * `param string` $queue * `param string` $text -

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
+

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
diff --git a/docs/modules/AngularJS.md b/docs/modules/AngularJS.md index e8396ce3de..e929cc721e 100644 --- a/docs/modules/AngularJS.md +++ b/docs/modules/AngularJS.md @@ -1,5 +1,6 @@ # AngularJS + Module for AngularJS testing, based on [WebDriver module](http://codeception.com/docs/modules/WebDriver) and [Protractor](http://angular.github.io/protractor/). Performs **synchronization to ensure that page content is fully rendered**. @@ -21,6 +22,7 @@ The same as for [WebDriver](http://codeception.com/docs/modules/WebDriver#Config browser: firefox script_timeout: 10 + ### Additional Features Can perform matching elements by model. In this case you should provide a strict locator with `model` set. @@ -36,15 +38,16 @@ $I->selectOption(['model' => 'customerId'], '3'); ### _backupSession *hidden API method, expected to be used from Helper classes* - + Returns current WebDriver session for saving * `return` RemoteWebDriver + ### _capabilities *hidden API method, expected to be used from Helper classes* - + Change capabilities of WebDriver. Should be executed before starting a new browser session. This method expects a function to be passed which returns array or [WebDriver Desired Capabilities](https://github.com/facebook/php-webdriver/blob/community/lib/Remote/DesiredCapabilities.php) object. Additional [Chrome options](https://github.com/facebook/php-webdriver/wiki/ChromeOptions) (like adding extensions) can be passed as well. @@ -87,10 +90,11 @@ In this case, please ensure that `\Helper\Acceptance` is loaded before WebDriver * `param \Closure` $capabilityFunction + ### _closeSession *hidden API method, expected to be used from Helper classes* - + Manually closes current WebDriver session. ```php @@ -104,10 +108,11 @@ $this->getModule('WebDriver')->_closeSession($webDriver); * `param` $webDriver (optional) a specific webdriver session instance + ### _findClickable *hidden API method, expected to be used from Helper classes* - + Locates a clickable element. Use it in Helpers or GroupObject or Extension classes: @@ -129,10 +134,11 @@ $el = $module->_findClickable($topBar, 'Click Me'); * `param` $link a link text or locator to click * `return` WebDriverElement + ### _findElements *hidden API method, expected to be used from Helper classes* - + Locates element using available Codeception locator types: * XPath @@ -156,26 +162,29 @@ PhpBrowser and Framework modules return `Symfony\Component\DomCrawler\Crawler` i * `param` $locator * `return` array of interactive elements + ### _getCurrentUri *hidden API method, expected to be used from Helper classes* - + Uri of currently opened page. * `return` string @throws ModuleException + ### _getUrl *hidden API method, expected to be used from Helper classes* - + Returns URL of a host. @throws ModuleConfigException + ### _initializeSession *hidden API method, expected to be used from Helper classes* - + Manually starts a new browser session. ```php @@ -183,18 +192,21 @@ Manually starts a new browser session. $this->getModule('WebDriver')->_initializeSession(); ``` + + ### _loadSession *hidden API method, expected to be used from Helper classes* - + Loads current RemoteWebDriver instance as a session * `param RemoteWebDriver` $session + ### _restart *hidden API method, expected to be used from Helper classes* - + Restarts a web browser. Can be used with `_reconfigure` to open browser with different configuration @@ -207,17 +219,19 @@ $this->getModule('WebDriver')->_restart(['browser' => $browser]); // reconfigure * `param array` $config + ### _savePageSource *hidden API method, expected to be used from Helper classes* - + Saves HTML source of a page to a file * `param` $filename + ### _saveScreenshot *hidden API method, expected to be used from Helper classes* - + Saves screenshot of current page to a file ```php @@ -225,19 +239,22 @@ $this->getModule('AngularJS')->_saveScreenshot(codecept_output_dir().'screenshot ``` * `param` $filename -### acceptPopup +### acceptPopup + Accepts the active JavaScript native popup window, as created by `window.alert`|`window.confirm`|`window.prompt`. Don't confuse popups with modal windows, as created by [various libraries](http://jster.net/category/windows-modals-popups). -### amInsideAngularApp +### amInsideAngularApp + Enables Angular mode (enabled by default). Waits for Angular to finish rendering after each action. -### amOnPage +### amOnPage + Opens the page for the given relative URI. ``` php @@ -250,8 +267,9 @@ $I->amOnPage('/register'); * `param string` $page -### amOnSubdomain +### amOnSubdomain + Changes the subdomain for the 'url' configuration parameter. Does not open a page; use `amOnPage` for that. @@ -269,8 +287,10 @@ $I->amOnPage('/'); * `param` $subdomain -### amOnUrl + +### amOnUrl + Open web page at the given absolute URL and sets its hostname as the base host. ``` php @@ -280,14 +300,16 @@ $I->amOnPage('/quickstart'); // moves to http://codeception.com/quickstart ?> ``` -### amOutsideAngularApp +### amOutsideAngularApp + Disabled Angular mode. Falls back to original WebDriver, in case web page does not contain Angular app. -### appendField +### appendField + Append the given text to the given element. Can also add a selection to a select box. @@ -302,8 +324,9 @@ $I->appendField('#myTextField', 'appended'); * `param string` $value @throws \Codeception\Exception\ElementNotFound -### attachFile +### attachFile + Attaches a file relative to the Codeception `_data` directory to the given file upload field. ``` php @@ -316,12 +339,14 @@ $I->attachFile('input[@type="file"]', 'prices.xls'); * `param` $field * `param` $filename -### cancelPopup +### cancelPopup + Dismisses the active JavaScript popup, as created by `window.alert`, `window.confirm`, or `window.prompt`. -### checkOption +### checkOption + Ticks a checkbox. For radio buttons, use the `selectOption` method instead. ``` php @@ -332,8 +357,21 @@ $I->checkOption('#agree'); * `param` $option -### click +### clearField + +Clears given field which isn't empty. + +``` php +clearField('#username'); +``` + + * `param` $field + + +### click + Perform a click on a link or a button, given by a locator. If a fuzzy locator is given, the page will be searched for a button, link, or image matching the locator string. For buttons, the "value" attribute, "name" attribute, and inner text are searched. @@ -364,8 +402,9 @@ $I->click(['link' => 'Login']); * `param` $link * `param` $context -### clickWithLeftButton +### clickWithLeftButton + Performs click with the left mouse button on an element. If the first parameter `null` then the offset is relative to the actual mouse position. If the second and third parameters are given, @@ -386,8 +425,9 @@ $I->clickWithLeftButton(['css' => '.checkout'], 20, 50); @throws \Codeception\Exception\ElementNotFound -### clickWithRightButton +### clickWithRightButton + Performs contextual click with the right mouse button on an element. If the first parameter `null` then the offset is relative to the actual mouse position. If the second and third parameters are given, @@ -403,13 +443,14 @@ $I->clickWithRightButton(['css' => '.checkout'], 20, 50); ``` * `param string` $cssOrXPath css or xpath of the web element (body by default). - * `param int` $offsetX - * `param int` $offsetY + * `param int` $offsetX + * `param int` $offsetY @throws \Codeception\Exception\ElementNotFound -### closeTab +### closeTab + Closes current browser tab and switches to previous active tab. ```php @@ -419,14 +460,16 @@ $I->closeTab(); Can't be used with PhantomJS -### debugWebDriverLogs +### debugWebDriverLogs + Print out latest Selenium Logs in debug mode * `param TestInterface` $test -### dontSee +### dontSee + Checks that the current page doesn't contain the text specified (case insensitive). Give a locator as the second parameter to match a specific region. @@ -455,8 +498,9 @@ For checking the raw source code, use `seeInSource()`. * `param string` $text * `param string` $selector optional -### dontSeeCheckboxIsChecked +### dontSeeCheckboxIsChecked + Check that the specified checkbox is unchecked. ``` php @@ -468,8 +512,9 @@ $I->seeCheckboxIsChecked('#signup_form input[type=checkbox]'); // I suppose user * `param` $checkbox -### dontSeeCookie +### dontSeeCookie + Checks that there isn't a cookie with the given name. You can set additional cookie params like `domain`, `path` as array passed in last argument. @@ -477,8 +522,9 @@ You can set additional cookie params like `domain`, `path` as array passed in la * `param array` $params -### dontSeeCurrentUrlEquals +### dontSeeCurrentUrlEquals + Checks that the current URL doesn't equal the given string. Unlike `dontSeeInCurrentUrl`, this only matches the full URL. @@ -491,8 +537,9 @@ $I->dontSeeCurrentUrlEquals('/'); * `param string` $uri -### dontSeeCurrentUrlMatches +### dontSeeCurrentUrlMatches + Checks that current url doesn't match the given regular expression. ``` php @@ -504,8 +551,9 @@ $I->dontSeeCurrentUrlMatches('~$/users/(\d+)~'); * `param string` $uri -### dontSeeElement +### dontSeeElement + Checks that the given element is invisible or not present on the page. You can also specify expected attributes of this element. @@ -521,15 +569,17 @@ $I->dontSeeElement('input', ['value' => '123456']); * `param` $selector * `param array` $attributes -### dontSeeElementInDOM +### dontSeeElementInDOM + Opposite of `seeElementInDOM`. * `param` $selector * `param array` $attributes -### dontSeeInCurrentUrl +### dontSeeInCurrentUrl + Checks that the current URI doesn't contain the given string. ``` php @@ -540,8 +590,9 @@ $I->dontSeeInCurrentUrl('/users/'); * `param string` $uri -### dontSeeInField +### dontSeeInField + Checks that an input field or textarea doesn't contain the given value. For fuzzy locators, the field is matched by label text, CSS and XPath. @@ -559,8 +610,9 @@ $I->dontSeeInField(['name' => 'search'], 'Search'); * `param` $field * `param` $value -### dontSeeInFormFields +### dontSeeInFormFields + Checks if the array of form parameters (name => value) are not set on the form matched with the passed selector. @@ -601,14 +653,16 @@ $I->dontSeeInFormFields('#form-id', [ * `param` $formSelector * `param` $params -### dontSeeInPageSource +### dontSeeInPageSource + Checks that the page source doesn't contain the given string. * `param` $text -### dontSeeInPopup +### dontSeeInPopup + Checks that the active JavaScript popup, as created by `window.alert`|`window.confirm`|`window.prompt`, does NOT contain the given string. @@ -616,8 +670,9 @@ as created by `window.alert`|`window.confirm`|`window.prompt`, does NOT contain @throws \Codeception\Exception\ModuleException -### dontSeeInSource +### dontSeeInSource + Checks that the current page contains the given string in its raw source code. @@ -628,14 +683,17 @@ $I->dontSeeInSource('

Green eggs & ham

'); * `param` $raw -### dontSeeInTitle +### dontSeeInTitle + Checks that the page title does not contain the given string. * `param` $title -### dontSeeLink + +### dontSeeLink + Checks that the page doesn't contain a link with the given string. If the second parameter is given, only links with a matching "href" attribute will be checked. @@ -649,8 +707,9 @@ $I->dontSeeLink('Checkout now', '/store/cart.php'); * `param string` $text * `param string` $url optional -### dontSeeOptionIsSelected +### dontSeeOptionIsSelected + Checks that the given option is not selected. ``` php @@ -662,15 +721,18 @@ $I->dontSeeOptionIsSelected('#form input[name=payment]', 'Visa'); * `param` $selector * `param` $optionText -### doubleClick + +### doubleClick + Performs a double-click on an element matched by CSS or XPath. * `param` $cssOrXPath @throws \Codeception\Exception\ElementNotFound -### dragAndDrop +### dragAndDrop + Performs a simple mouse drag-and-drop operation. ``` php @@ -682,8 +744,28 @@ $I->dragAndDrop('#drag', '#drop'); * `param string` $source (CSS ID or XPath) * `param string` $target (CSS ID or XPath) -### executeInSelenium +### executeAsyncJS + +Executes asynchronous JavaScript. +A callback should be executed by JavaScript to exit from a script. +Callback is passed as a last element in `arguments` array. +Additional arguments can be passed as array in second parameter. + +```js +// wait for 1200 milliseconds my running `setTimeout` +* $I->executeAsyncJS('setTimeout(arguments[0], 1200)'); + +$seconds = 1200; // or seconds are passed as argument +$I->executeAsyncJS('setTimeout(arguments[1], arguments[0])', [$seconds]); +``` + + * `param` $script + * `param array` $arguments + + +### executeInSelenium + Low-level API method. If Codeception commands are not enough, this allows you to use Selenium WebDriver methods directly: @@ -700,8 +782,9 @@ If Codeception lacks a feature you need, please implement it and submit a patch. * `param callable` $function -### executeJS +### executeJS + Executes custom JavaScript. This example uses jQuery to get a value and assigns that value to a PHP variable: @@ -709,13 +792,18 @@ This example uses jQuery to get a value and assigns that value to a PHP variable ```php executeJS('return $("#myField").val()'); -?> + +// additional arguments can be passed as array +// Example shows `Hello World` alert: +$I->executeJS("window.alert(arguments[0])", ['Hello world']); ``` * `param` $script + * `param array` $arguments -### fillField +### fillField + Fills a text field or textarea with the given string. ``` php @@ -728,8 +816,9 @@ $I->fillField(['name' => 'email'], 'jon@mail.com'); * `param` $field * `param` $value -### grabAttributeFrom +### grabAttributeFrom + Grabs the value of the given attribute value from the given element. Fails if element is not found. @@ -742,8 +831,10 @@ $I->grabAttributeFrom('#tooltip', 'title'); * `param` $cssOrXpath * `param` $attribute -### grabCookie + +### grabCookie + Grabs a cookie value. You can set additional cookie params like `domain`, `path` in array passed as last argument. @@ -751,8 +842,9 @@ You can set additional cookie params like `domain`, `path` in array passed as la * `param array` $params -### grabFromCurrentUrl +### grabFromCurrentUrl + Executes the given regular expression against the current URI and returns the first capturing group. If no parameters are provided, the full URI is returned. @@ -765,8 +857,10 @@ $uri = $I->grabFromCurrentUrl(); * `param string` $uri optional -### grabMultiple + +### grabMultiple + Grabs either the text content, or attribute values, of nodes matched by $cssOrXpath and returns them as an array. @@ -790,16 +884,18 @@ $aLinks = $I->grabMultiple('a', 'href'); * `param` $attribute * `return` string[] -### grabPageSource +### grabPageSource + Grabs current page source code. @throws ModuleException if no page was opened. * `return` string Current page source code. -### grabTextFrom +### grabTextFrom + Finds and returns the text contents of the given element. If a fuzzy locator is used, the element is found using CSS, XPath, and by matching the full page source by regular expression. @@ -814,8 +910,10 @@ $value = $I->grabTextFrom('~grabValueFrom(['name' => 'username']); * `param` $field -### loadSessionSnapshot + +### loadSessionSnapshot + * `param string` $name * `return` bool -### makeScreenshot +### makeScreenshot + Takes a screenshot of the current window and saves it to `tests/_output/debug`. ``` php @@ -850,20 +951,24 @@ $I->makeScreenshot(); * `param` $name -### maximizeWindow +### maximizeWindow + Maximizes the current window. -### moveBack +### moveBack + Moves back in history. -### moveForward +### moveForward + Moves forward in history. -### moveMouseOver +### moveMouseOver + Move mouse over the first element matched by the given locator. If the first parameter null then the page is used. If the second and third parameters are given, @@ -884,8 +989,9 @@ $I->moveMouseOver(['css' => '.checkout'], 20, 50); @throws \Codeception\Exception\ElementNotFound -### openNewTab +### openNewTab + Opens a new browser tab (wherever it is possible) and switches to it. ```php @@ -897,16 +1003,19 @@ Please note, that adblock can restrict creating such tabs. Can't be used with PhantomJS -### pauseExecution + +### pauseExecution + Pauses test execution in debug mode. To proceed test press "ENTER" in console. This method is useful while writing tests, since it allows you to inspect the current page in the middle of a test case. -### performOn +### performOn + Waits for element and runs a sequence of actions inside its context. Actions can be defined with array, callback, or `Codeception\Util\ActionSequence` instance. @@ -949,8 +1058,9 @@ In 3rd argument you can set number a seconds to wait for element to appear * `param` $actions * `param int` $timeout -### pressKey +### pressKey + Presses the given key on the given element. To specify a character and modifier (e.g. ctrl, alt, shift, meta), pass an array for $char with the modifier as the first element and the character as the second. @@ -971,12 +1081,14 @@ $I->pressKey('#name', array('ctrl', 'a'), \Facebook\WebDriver\WebDriverKeys::DEL * `param` $char string|array Can be char or array with modifier. You can provide several chars. @throws \Codeception\Exception\ElementNotFound -### reloadPage +### reloadPage + Reloads the current page. -### resetCookie +### resetCookie + Unsets cookie with the given name. You can set additional cookie params like `domain`, `path` in array passed as last argument. @@ -984,8 +1096,9 @@ You can set additional cookie params like `domain`, `path` in array passed as la * `param array` $params -### resizeWindow +### resizeWindow + Resize the current window. ``` php @@ -997,12 +1110,14 @@ $I->resizeWindow(800, 600); * `param int` $width * `param int` $height -### saveSessionSnapshot +### saveSessionSnapshot + * `param string` $name -### scrollTo +### scrollTo + Move to the middle of the given element matched by the given locator. Extra shift, calculated from the top-left corner of the element, can be set by passing $offsetX and $offsetY parameters. @@ -1017,8 +1132,9 @@ $I->scrollTo(['css' => '.checkout'], 20, 50); * `param int` $offsetX * `param int` $offsetY -### see +### see + Checks that the current page contains the given string (case insensitive). You can specify a specific HTML element (via CSS or XPath) as the second @@ -1049,8 +1165,9 @@ For checking the raw source code, use `seeInSource()`. * `param string` $text * `param string` $selector optional -### seeCheckboxIsChecked +### seeCheckboxIsChecked + Checks that the specified checkbox is checked. ``` php @@ -1063,8 +1180,9 @@ $I->seeCheckboxIsChecked('//form/input[@type=checkbox and @name=agree]'); * `param` $checkbox -### seeCookie +### seeCookie + Checks that a cookie with the given name is set. You can set additional cookie params like `domain`, `path` as array passed in last argument. @@ -1077,8 +1195,9 @@ $I->seeCookie('PHPSESSID'); * `param` $cookie * `param array` $params -### seeCurrentUrlEquals +### seeCurrentUrlEquals + Checks that the current URL is equal to the given string. Unlike `seeInCurrentUrl`, this only matches the full URL. @@ -1091,8 +1210,9 @@ $I->seeCurrentUrlEquals('/'); * `param string` $uri -### seeCurrentUrlMatches +### seeCurrentUrlMatches + Checks that the current URL matches the given regular expression. ``` php @@ -1104,8 +1224,9 @@ $I->seeCurrentUrlMatches('~$/users/(\d+)~'); * `param string` $uri -### seeElement +### seeElement + Checks that the given element exists on the page and is visible. You can also specify expected attributes of this element. @@ -1125,8 +1246,9 @@ $I->seeElement(['css' => 'form input'], ['name' => 'login']); * `param array` $attributes @return -### seeElementInDOM +### seeElementInDOM + Checks that the given element exists on the page, even it is invisible. ``` php @@ -1138,8 +1260,9 @@ $I->seeElementInDOM('//form/input[type=hidden]'); * `param` $selector * `param array` $attributes -### seeInCurrentUrl +### seeInCurrentUrl + Checks that current URI contains the given string. ``` php @@ -1153,8 +1276,9 @@ $I->seeInCurrentUrl('/users/'); * `param string` $uri -### seeInField +### seeInField + Checks that the given input field or textarea *equals* (i.e. not just contains) the given value. Fields are matched by label text, the "name" attribute, CSS, or XPath. @@ -1172,8 +1296,9 @@ $I->seeInField(['name' => 'search'], 'Search'); * `param` $field * `param` $value -### seeInFormFields +### seeInFormFields + Checks if the array of form parameters (name => value) are set on the form matched with the passed selector. @@ -1234,8 +1359,9 @@ $I->seeInFormFields('//form[@id=my-form]', $form); * `param` $formSelector * `param` $params -### seeInPageSource +### seeInPageSource + Checks that the page source contains the given string. ```php @@ -1245,8 +1371,9 @@ $I->seeInPageSource('seeInSource('

Green eggs & ham

'); * `param` $raw -### seeInTitle +### seeInTitle + Checks that the page title contains the given string. ``` php @@ -1278,8 +1407,10 @@ $I->seeInTitle('Blog - Post #1'); * `param` $title -### seeLink + +### seeLink + Checks that there's a link with the specified text. Give a full URL as the second parameter to match links with that exact URL. @@ -1293,8 +1424,9 @@ $I->seeLink('Logout','/logout'); // matches Logout * `param string` $text * `param string` $url optional -### seeNumberOfElements +### seeNumberOfElements + Checks that there are a certain number of elements matched by the given locator on the page. ``` php @@ -1306,11 +1438,13 @@ $I->seeNumberOfElements('tr', [0,10]); // between 0 and 10 elements * `param` $selector * `param mixed` $expected int or int[] + ### seeNumberOfElementsInDOM __not documented__ -### seeOptionIsSelected +### seeOptionIsSelected + Checks that the given option is selected. ``` php @@ -1322,8 +1456,10 @@ $I->seeOptionIsSelected('#form input[name=payment]', 'Visa'); * `param` $selector * `param` $optionText -### selectOption + +### selectOption + Selects an option in a select tag or in radio button group. ``` php @@ -1354,8 +1490,9 @@ $I->selectOption('Which OS do you use?', array('value' => 'windows')); // Only s * `param` $select * `param` $option -### setCookie +### setCookie + Sets a cookie with the given name and value. You can set additional cookie params like `domain`, `path`, `expires`, `secure` in array passed as last argument. @@ -1369,8 +1506,10 @@ $I->setCookie('PHPSESSID', 'el4ukv0kqbvoirg7nkp4dncpk3'); * `param` $val * `param array` $params -### submitForm + +### submitForm + Submits the given form on the page, optionally with the given form values. Give the form fields values as an array. Note that hidden fields can't be accessed. @@ -1529,8 +1668,9 @@ For example, given the following HTML: * `param` $params * `param` $button -### switchToIFrame +### switchToIFrame + Switch to another frame on the page. Example: @@ -1550,8 +1690,9 @@ $I->switchToIFrame(); * `param string|null` $name -### switchToNextTab +### switchToNextTab + Switches to next browser tab. An offset can be specified. @@ -1567,8 +1708,9 @@ Can't be used with PhantomJS * `param int` $offset 1 -### switchToPreviousTab +### switchToPreviousTab + Switches to previous browser tab. An offset can be specified. @@ -1584,8 +1726,9 @@ Can't be used with PhantomJS * `param int` $offset 1 -### switchToWindow +### switchToWindow + Switch to another window identified by name. The window can only be identified by name. If the $name parameter is blank, the parent window will be used. @@ -1621,16 +1764,18 @@ $I->executeInSelenium(function (\Facebook\WebDriver\Remote\RemoteWebDriver $webd * `param string|null` $name -### typeInPopup +### typeInPopup + Enters text into a native JavaScript prompt popup, as created by `window.prompt`. * `param` $keys @throws \Codeception\Exception\ModuleException -### uncheckOption +### uncheckOption + Unticks a checkbox. ``` php @@ -1641,22 +1786,25 @@ $I->uncheckOption('#notify'); * `param` $option -### unselectOption +### unselectOption + Unselect an option in the given select box. * `param` $select * `param` $option -### wait +### wait + Wait for $timeout seconds. * `param int|float` $timeout secs @throws \Codeception\Exception\TestRuntimeException -### waitForElement +### waitForElement + Waits up to $timeout seconds for an element to appear on the page. If the element doesn't appear, a timeout exception is thrown. @@ -1671,8 +1819,9 @@ $I->click('#agree_button'); * `param int` $timeout seconds @throws \Exception -### waitForElementChange +### waitForElementChange + Waits up to $timeout seconds for the given element to change. Element "change" is determined by a callback function which is called repeatedly until the return value evaluates to true. @@ -1691,8 +1840,9 @@ $I->waitForElementChange('#menu', function(WebDriverElement $el) { * `param int` $timeout seconds @throws \Codeception\Exception\ElementNotFound -### waitForElementNotVisible +### waitForElementNotVisible + Waits up to $timeout seconds for the given element to become invisible. If element stays visible, a timeout exception is thrown. @@ -1706,8 +1856,9 @@ $I->waitForElementNotVisible('#agree_button', 30); // secs * `param int` $timeout seconds @throws \Exception -### waitForElementVisible +### waitForElementVisible + Waits up to $timeout seconds for the given element to be visible on the page. If element doesn't appear, a timeout exception is thrown. @@ -1722,8 +1873,9 @@ $I->click('#agree_button'); * `param int` $timeout seconds @throws \Exception -### waitForJS +### waitForJS + Executes JavaScript and waits up to $timeout seconds for it to return true. In this example we will wait up to 60 seconds for all jQuery AJAX requests to finish. @@ -1737,8 +1889,9 @@ $I->waitForJS("return $.active == 0;", 60); * `param string` $script * `param int` $timeout seconds -### waitForText +### waitForText + Waits up to $timeout seconds for the given string to appear on the page. Can also be passed a selector to search in, be as specific as possible when using selectors. @@ -1757,4 +1910,4 @@ $I->waitForText('foo', 30, '.title'); // secs * `param string` $selector optional @throws \Exception -

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
+

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
diff --git a/docs/modules/Apc.md b/docs/modules/Apc.md index 56bf326cf7..f0e08816f2 100644 --- a/docs/modules/Apc.md +++ b/docs/modules/Apc.md @@ -1,5 +1,6 @@ # Apc + This module interacts with the [Alternative PHP Cache (APC)](http://php.net/manual/en/intro.apcu.php) using either _APCu_ or _APC_ extension. @@ -20,10 +21,11 @@ Performs a cleanup by flushing all values after each test run. Be sure you don't use the production server to connect. + ## Actions ### dontSeeInApc - + Checks item in APC(u) doesn't exist or is the same as expected. Examples: @@ -41,12 +43,14 @@ $I->dontSeeInApc('users_count', 200); * `param string|string[]` $key * `param mixed` $value -### flushApc +### flushApc + Clears the APC(u) cache -### grabValueFromApc +### grabValueFromApc + Grabs value from APC(u) by key. Example: @@ -59,8 +63,9 @@ $users_count = $I->grabValueFromApc('users_count'); * `param string|string[]` $key -### haveInApc +### haveInApc + Stores an item `$value` with `$key` on the APC(u). Examples: @@ -87,8 +92,9 @@ $I->haveInApc($entries, null); * `param mixed` $value * `param int` $expiration -### seeInApc +### seeInApc + Checks item in APC(u) exists and the same as expected. Examples: @@ -106,4 +112,4 @@ $I->seeInApc('users_count', 200); * `param string|string[]` $key * `param mixed` $value -

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
+

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
diff --git a/docs/modules/Asserts.md b/docs/modules/Asserts.md index f634bddfac..924852ebf3 100644 --- a/docs/modules/Asserts.md +++ b/docs/modules/Asserts.md @@ -1,23 +1,26 @@ # Asserts + Special module for using asserts in your tests. ## Actions ### assertArrayHasKey - + * `param` $key * `param` $actual * `param` $description -### assertArrayNotHasKey +### assertArrayNotHasKey + * `param` $key * `param` $actual * `param` $description -### assertArraySubset +### assertArraySubset + Checks that array contains subset. * `param array` $subset @@ -25,29 +28,33 @@ Checks that array contains subset. * `param bool` $strict * `param string` $message -### assertContains +### assertContains + Checks that haystack contains needle * `param` $needle * `param` $haystack * `param string` $message -### assertCount +### assertCount + * `param` $expectedCount * `param` $actual * `param` $description -### assertEmpty +### assertEmpty + Checks that variable is empty. * `param` $actual * `param string` $message -### assertEquals +### assertEquals + Checks that two variables are equal. If you're comparing floating-point values, you can specify the optional "delta" parameter which dictates how great of a precision error are you willing to tolerate in order to consider the two values equal. @@ -69,105 +76,120 @@ $I->assertEquals($calculator->add(0.1, 0.2), 0.3, 'Calculator should add the two * `param string` $message * `param float` $delta -### assertFalse +### assertFalse + Checks that condition is negative. * `param` $condition * `param string` $message -### assertFileExists +### assertFileExists + Checks if file exists * `param string` $filename * `param string` $message -### assertFileNotExists +### assertFileNotExists + Checks if file doesn't exist * `param string` $filename * `param string` $message -### assertGreaterOrEquals +### assertGreaterOrEquals + * `param` $expected * `param` $actual * `param` $description -### assertGreaterThan +### assertGreaterThan + Checks that actual is greater than expected * `param` $expected * `param` $actual * `param string` $message -### assertGreaterThanOrEqual +### assertGreaterThanOrEqual + Checks that actual is greater or equal than expected * `param` $expected * `param` $actual * `param string` $message -### assertInstanceOf +### assertInstanceOf + * `param` $class * `param` $actual * `param` $description -### assertInternalType +### assertInternalType + * `param` $type * `param` $actual * `param` $description -### assertIsEmpty +### assertIsEmpty + * `param` $actual * `param` $description -### assertLessOrEquals +### assertLessOrEquals + * `param` $expected * `param` $actual * `param` $description -### assertLessThan +### assertLessThan + Checks that actual is less than expected * `param` $expected * `param` $actual * `param string` $message -### assertLessThanOrEqual +### assertLessThanOrEqual + Checks that actual is less or equal than expected * `param` $expected * `param` $actual * `param string` $message -### assertNotContains +### assertNotContains + Checks that haystack doesn't contain needle. * `param` $needle * `param` $haystack * `param string` $message -### assertNotEmpty +### assertNotEmpty + Checks that variable is not empty. * `param` $actual * `param string` $message -### assertNotEquals +### assertNotEquals + Checks that two variables are not equal. If you're comparing floating-point values, you can specify the optional "delta" parameter which dictates how great of a precision error are you willing to tolerate in order to consider the two values not equal. @@ -189,83 +211,94 @@ $I->assertNotEquals($calculator->add(0.1, 0.2), 0.4, 'Calculator should add the * `param string` $message * `param float` $delta -### assertNotInstanceOf +### assertNotInstanceOf + * `param` $class * `param` $actual * `param` $description -### assertNotNull +### assertNotNull + Checks that variable is not NULL * `param` $actual * `param string` $message -### assertNotRegExp +### assertNotRegExp + Checks that string not match with pattern * `param string` $pattern * `param string` $string * `param string` $message -### assertNotSame +### assertNotSame + Checks that two variables are not same * `param` $expected * `param` $actual * `param string` $message -### assertNull +### assertNull + Checks that variable is NULL * `param` $actual * `param string` $message -### assertRegExp +### assertRegExp + Checks that string match with pattern * `param string` $pattern * `param string` $string * `param string` $message -### assertSame +### assertSame + Checks that two variables are same * `param` $expected * `param` $actual * `param string` $message -### assertStringStartsNotWith +### assertStringStartsNotWith + Checks that a string doesn't start with the given prefix. * `param string` $prefix * `param string` $string * `param string` $message -### assertStringStartsWith +### assertStringStartsWith + Checks that a string starts with the given prefix. * `param string` $prefix * `param string` $string * `param string` $message -### assertTrue +### assertTrue + Checks that condition is positive. * `param` $condition * `param string` $message -### expectException +### expectException + Handles and checks exception called inside callback function. Either exception class name or exception instance should be provided. @@ -291,10 +324,11 @@ $I->expectException(new MyException("Don't do bad things"), function() { * `param` $exception string or \Exception * `param` $callback -### fail +### fail + Fails the test with message. * `param` $message -

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
+

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
diff --git a/docs/modules/Cli.md b/docs/modules/Cli.md index cf6e85bb0c..d736a59420 100644 --- a/docs/modules/Cli.md +++ b/docs/modules/Cli.md @@ -1,5 +1,6 @@ # Cli + Wrapper for basic shell commands and shell output ## Responsibility @@ -12,13 +13,15 @@ Wrapper for basic shell commands and shell output ## Actions ### dontSeeInShellOutput - + Checks that output from latest command doesn't contain text * `param` $text -### runShellCommand + +### runShellCommand + Executes a shell command. Fails If exit code is > 0. You can disable this by setting second parameter to false @@ -33,14 +36,16 @@ $I->runShellCommand('phpunit', false); * `param` $command * `param bool` $failNonZero -### seeInShellOutput +### seeInShellOutput + Checks that output from last executed command contains text * `param` $text -### seeResultCodeIs +### seeResultCodeIs + Checks result code ```php @@ -50,8 +55,9 @@ $I->seeResultCodeIs(0); * `param` $code -### seeResultCodeIsNot +### seeResultCodeIsNot + Checks result code ```php @@ -61,8 +67,9 @@ $I->seeResultCodeIsNot(0); * `param` $code -### seeShellOutputMatches +### seeShellOutputMatches + * `param` $regex -

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
+

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
diff --git a/docs/modules/DataFactory.md b/docs/modules/DataFactory.md index c6b6908d6a..a1ac2161b6 100644 --- a/docs/modules/DataFactory.md +++ b/docs/modules/DataFactory.md @@ -1,5 +1,6 @@ # DataFactory + DataFactory allows you to easily generate and create test data using [**FactoryMuffin**](https://github.com/thephpleague/factory-muffin). DataFactory uses an ORM of your application to define, save and cleanup data. Thus, should be used with ORM or Framework modules. @@ -8,7 +9,6 @@ This module requires packages installed: ```json { "league/factory-muffin": "^3.0", - "league/factory-muffin-faker": "^1.0" } ``` @@ -29,7 +29,7 @@ $fm->define(User::class)->setDefinitions([ // generate a profile and return its Id 'profile_id' => 'factory|Profile' -); +]); ``` Configure this module to load factory definitions from a directory. @@ -48,7 +48,7 @@ modules: (you can also use Laravel5 and Phalcon). In this example factories are loaded from `tests/_support/factories` directory. Please note that this directory is relative from the codeception.yml file (so for Yii2 it would be codeception/_support/factories). - * You should create this directory manually and create PHP files in it with factories definitions following [official documentation](https://github.com/thephpleague/factory-muffin#usage). +You should create this directory manually and create PHP files in it with factories definitions following [official documentation](https://github.com/thephpleague/factory-muffin#usage). In cases you want to use data from database inside your factory definitions you can define them in Helper. For instance, if you use Doctrine, this allows you to access `EntityManager` inside a definition. @@ -113,7 +113,7 @@ In case your ORM expects a related record itself (Doctrine) then you should use ## Actions ### have - + Generates and saves a record,. ```php @@ -123,13 +123,14 @@ $I->have('User', ['is_active' => true]); // creates active user Returns an instance of created user. - * `param` $name + * `param string` $name * `param array` $extraAttrs * `return` object -### haveMultiple +### haveMultiple + Generates and saves a record multiple times. ```php @@ -137,10 +138,29 @@ $I->haveMultiple('User', 10); // create 10 users $I->haveMultiple('User', 10, ['is_active' => true]); // create 10 active users ``` - * `param` $name - * `param` $times + * `param string` $name + * `param int` $times * `param array` $extraAttrs * `return` \object[] -

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
+ +### make + +Generates a record instance. + +This does not save it in the database. Use `have` for that. + +```php +$user = $I->make('User'); // return User instance +$activeUser = $I->make('User', ['is_active' => true]); // return active user instance +``` + +Returns an instance of created user without creating a record in database. + + * `param string` $name + * `param array` $extraAttrs + + * `return` object + +

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
diff --git a/docs/modules/Db.md b/docs/modules/Db.md index 73af2a0217..38015e04c4 100644 --- a/docs/modules/Db.md +++ b/docs/modules/Db.md @@ -1,5 +1,6 @@ # Db + Access a database. The most important function of this module is to clean a database before each test. @@ -169,10 +170,11 @@ SELECT COUNT(*) FROM `users` WHERE `name` = 'Davert' AND `email` LIKE 'davert%' * dbh - contains the PDO connection * driver - contains the Connection Driver + ## Actions ### dontSeeInDatabase - + Effect is opposite to ->seeInDatabase Asserts that there is no record with the given column values in a database. @@ -197,8 +199,9 @@ Supported operators: `<`, `>`, `>=`, `<=`, `!=`, `like`. * `param string` $table * `param array` $criteria -### grabColumnFromDatabase +### grabColumnFromDatabase + Fetches all values from the column in database. Provide table name, desired column and criteria. @@ -213,8 +216,9 @@ $mails = $I->grabColumnFromDatabase('users', 'email', array('name' => 'RebOOter' * `return` array -### grabFromDatabase +### grabFromDatabase + Fetches a single column value from a database. Provide table name, desired column and criteria. @@ -226,7 +230,7 @@ Comparison expressions can be used as well: ```php grabFromDatabase('posts', ['num_comments >=' => 100']); +$post = $I->grabFromDatabase('posts', ['num_comments >=' => 100]); $user = $I->grabFromDatabase('users', ['email like' => 'miles%']); ``` @@ -236,8 +240,10 @@ Supported operators: `<`, `>`, `>=`, `<=`, `!=`, `like`. * `param string` $column * `param array` $criteria -### grabNumRecords + +### grabNumRecords + Returns the number of rows in a database * `param string` $table Table name @@ -245,8 +251,9 @@ Returns the number of rows in a database * `return` int -### haveInDatabase +### haveInDatabase + Inserts an SQL record into a database. This record will be erased after the test. ```php @@ -260,11 +267,13 @@ $I->haveInDatabase('users', array('name' => 'miles', 'email' => 'miles@davis.com * `return integer` $id + ### isPopulated __not documented__ -### seeInDatabase +### seeInDatabase + Asserts that a row with the given column values exists. Provide table name and column values. @@ -287,8 +296,9 @@ Supported operators: `<`, `>`, `>=`, `<=`, `!=`, `like`. * `param string` $table * `param array` $criteria -### seeNumRecords +### seeNumRecords + Asserts that the given number of records were found in the database. ```php @@ -301,8 +311,9 @@ $I->seeNumRecords(1, 'users', ['name' => 'davert']) * `param string` $table Table name * `param array` $criteria Search criteria [Optional] -### updateInDatabase +### updateInDatabase + Update an SQL record into a database. ```php @@ -315,4 +326,4 @@ $I->updateInDatabase('users', array('isAdmin' => true), array('email' => 'miles@ * `param array` $data * `param array` $criteria -

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
+

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
diff --git a/docs/modules/Doctrine2.md b/docs/modules/Doctrine2.md index ad96027ae1..0defeecd03 100644 --- a/docs/modules/Doctrine2.md +++ b/docs/modules/Doctrine2.md @@ -1,5 +1,6 @@ # Doctrine2 + Access the database using [Doctrine2 ORM](http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/). When used with Zend Framework 2 or Symfony2, Doctrine's Entity Manager is automatically retrieved from Service Locator. @@ -45,18 +46,20 @@ tests will run much faster and will be isolated from each other. ## Actions ### dontSeeInRepository - + Flushes changes to database and performs `findOneBy()` call for current repository. * `param` $entity * `param array` $params -### flushToDatabase +### flushToDatabase + Performs $em->flush(); -### grabEntitiesFromRepository +### grabEntitiesFromRepository + Selects entities from repository. It builds query based on array of parameters. You can use entity associations to build complex queries. @@ -74,8 +77,9 @@ $users = $I->grabEntitiesFromRepository('AppBundle:User', array('name' => 'daver * `param array` $params * `return` array -### grabEntityFromRepository +### grabEntityFromRepository + Selects a single entity from repository. It builds query based on array of parameters. You can use entity associations to build complex queries. @@ -93,8 +97,9 @@ $user = $I->grabEntityFromRepository('User', array('id' => '1234')); * `param array` $params * `return` object -### grabFromRepository +### grabFromRepository + Selects field value from repository. It builds query based on array of parameters. You can use entity associations to build complex queries. @@ -113,8 +118,9 @@ $email = $I->grabFromRepository('User', 'email', array('name' => 'davert')); * `param array` $params * `return` array -### haveFakeRepository +### haveFakeRepository + Mocks the repository. With this action you can redefine any method of any repository. @@ -135,8 +141,9 @@ which will always return the NULL value. * `param` $classname * `param array` $methods -### haveInRepository +### haveInRepository + Persists record into repository. This method crates an entity, and sets its properties directly (via reflection). Setters of entity won't be executed, but you can create almost any entity and save it to database. @@ -146,8 +153,9 @@ Returns id using `getId` of newly created entity. $I->haveInRepository('Entity\User', array('name' => 'davert')); ``` -### persistEntity +### persistEntity + Adds entity to repository and flushes. You can redefine it's properties with the second parameter. Example: @@ -161,8 +169,9 @@ $I->persistEntity($user, array('name' => 'Miles')); * `param` $obj * `param array` $values -### seeInRepository +### seeInRepository + Flushes changes to database, and executes a query with parameters defined in an array. You can use entity associations to build complex queries. @@ -181,4 +190,4 @@ Fails if record for given criteria can\'t be found, * `param` $entity * `param array` $params -

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
+

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
diff --git a/docs/modules/FTP.md b/docs/modules/FTP.md index 9a5c164300..f6558008da 100644 --- a/docs/modules/FTP.md +++ b/docs/modules/FTP.md @@ -1,5 +1,7 @@ # FTP + + Works with SFTP/FTP servers. In order to test the contents of a specific file stored on any remote FTP/SFTP system @@ -79,18 +81,20 @@ For SFTP, add [phpseclib](http://phpseclib.sourceforge.net/) to require list. tmp: 'tests/_data/ftp' cleanup: false + This module extends the Filesystem module, file contents methods are inherited from this module. ## Actions ### amInPath - + Enters a directory on the ftp system - FTP root directory is used by default * `param` $path -### cleanDir +### cleanDir + Erases directory contents on the FTP/SFTP server ``` php @@ -101,15 +105,17 @@ $I->cleanDir('logs'); * `param` $dirname -### copyDir +### copyDir + Currently not supported in this module, overwrite inherited method * `param` $src * `param` $dst -### deleteDir +### deleteDir + Deletes directory with all subdirectories on the remote FTP/SFTP server ``` php @@ -120,8 +126,9 @@ $I->deleteDir('vendor'); * `param` $dirname -### deleteFile +### deleteFile + Deletes a file on the remote FTP/SFTP system ``` php @@ -132,27 +139,31 @@ $I->deleteFile('composer.lock'); * `param` $filename -### deleteThisFile +### deleteThisFile + Deletes a file -### dontSeeFileFound +### dontSeeFileFound + Checks if file does not exist in path on the remote FTP/SFTP system * `param` $filename * `param string` $path -### dontSeeFileFoundMatches +### dontSeeFileFoundMatches + Checks if file does not exist in path on the remote FTP/SFTP system, using regular expression as filename. DOES NOT OPEN the file when it's exists * `param` $regex * `param string` $path -### dontSeeInThisFile +### dontSeeInThisFile + Checks If opened file doesn't contain `text` in it ``` php @@ -164,8 +175,9 @@ $I->dontSeeInThisFile('codeception/codeception'); * `param string` $text -### grabDirectory +### grabDirectory + Grabber method to return current working directory ```php @@ -176,8 +188,9 @@ $pwd = $I->grabDirectory(); * `return` string -### grabFileCount +### grabFileCount + Grabber method for returning file/folders count in directory ```php @@ -191,8 +204,9 @@ $count = $I->grabFileCount('TEST', false); // Include . .. .thumbs.db * `param bool` $ignore - suppress '.', '..' and '.thumbs.db' * `return` int -### grabFileList +### grabFileList + Grabber method for returning file/folders listing in an array ```php @@ -206,8 +220,9 @@ $count = $I->grabFileList('TEST', false); // Include . .. .thumbs.db * `param bool` $ignore - suppress '.', '..' and '.thumbs.db' * `return` array -### grabFileModified +### grabFileModified + Grabber method to return last modified timestamp ```php @@ -219,8 +234,9 @@ $time = $I->grabFileModified('test.txt'); * `param` $filename * `return` bool -### grabFileSize +### grabFileSize + Grabber method to return file size ```php @@ -232,8 +248,9 @@ $size = $I->grabFileSize('test.txt'); * `param` $filename * `return` bool -### loginAs +### loginAs + Change the logged in user mid-way through your test, this closes the current connection to the server and initialises and new connection. @@ -250,8 +267,9 @@ $I->loginAs('user','password'); * `param String` $user * `param String` $password -### makeDir +### makeDir + Create a directory on the server ``` php @@ -262,8 +280,9 @@ $I->makeDir('vendor'); * `param` $dirname -### openFile +### openFile + Opens a file (downloads from the remote FTP/SFTP system to a tmp directory for processing) and stores it's content. @@ -278,8 +297,9 @@ $I->seeInThisFile('codeception/codeception'); * `param` $filename -### renameDir +### renameDir + Rename/Move directory on the FTP/SFTP server ``` php @@ -291,8 +311,9 @@ $I->renameDir('vendor', 'vendor_old'); * `param` $dirname * `param` $rename -### renameFile +### renameFile + Rename/Move file on the FTP/SFTP server ``` php @@ -304,8 +325,9 @@ $I->renameFile('composer.lock', 'composer_old.lock'); * `param` $filename * `param` $rename -### seeFileContentsEqual +### seeFileContentsEqual + Checks the strict matching of file contents. Unlike `seeInThisFile` will fail if file has something more than expected lines. Better to use with HEREDOC strings. @@ -320,8 +342,9 @@ $I->seeFileContentsEqual('3192'); * `param string` $text -### seeFileFound +### seeFileFound + Checks if file exists in path on the remote FTP/SFTP system. DOES NOT OPEN the file when it's exists @@ -334,8 +357,9 @@ $I->seeFileFound('UserModel.php','app/models'); * `param` $filename * `param string` $path -### seeFileFoundMatches +### seeFileFoundMatches + Checks if file exists in path on the remote FTP/SFTP system, using regular expression as filename. DOES NOT OPEN the file when it's exists @@ -348,8 +372,9 @@ $I->seeFileFoundMatches('/^UserModel_([0-9]{6}).php$/','app/models'); * `param` $regex * `param string` $path -### seeInThisFile +### seeInThisFile + Checks If opened file has `text` in it. Usage: @@ -363,8 +388,9 @@ $I->seeInThisFile('codeception/codeception'); * `param string` $text -### seeNumberNewLines +### seeNumberNewLines + Checks If opened file has the `number` of new lines. Usage: @@ -378,14 +404,16 @@ $I->seeNumberNewLines(5); * `param int` $number New lines -### seeThisFileMatches +### seeThisFileMatches + Checks that contents of currently opened file matches $regex * `param string` $regex -### writeToFile +### writeToFile + Saves contents to tmp file and uploads the FTP/SFTP system. Overwrites current file on server if exists. @@ -398,4 +426,4 @@ $I->writeToFile('composer.json', 'some data here'); * `param` $filename * `param` $contents -

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
+

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
diff --git a/docs/modules/Facebook.md b/docs/modules/Facebook.md index 0b60d0ccb7..76a61b8dc5 100644 --- a/docs/modules/Facebook.md +++ b/docs/modules/Facebook.md @@ -1,5 +1,6 @@ # Facebook + Provides testing for projects integrated with Facebook API. Relies on Facebook's tool Test User API. @@ -74,69 +75,79 @@ $I->see('Welcome, ' . $fbUserFirstName); ## Actions ### grabFacebookTestUserAccessToken - + Returns the test user access token. * `return` string -### grabFacebookTestUserEmail +### grabFacebookTestUserEmail + Returns the test user email. * `return` string -### grabFacebookTestUserId +### grabFacebookTestUserId + Returns the test user id. * `return` string -### grabFacebookTestUserLoginUrl +### grabFacebookTestUserLoginUrl + Returns URL for test user auto-login. * `return` string -### grabFacebookTestUserName +### grabFacebookTestUserName + Returns the test user name. * `return` string + ### grabFacebookTestUserPassword __not documented__ -### haveFacebookTestUserAccount +### haveFacebookTestUserAccount + Get facebook test user be created. *Please, note that the test user is created only at first invoke, unless $renew arguments is true.* * `param bool` $renew true if the test user should be recreated -### haveTestUserLoggedInOnFacebook +### haveTestUserLoggedInOnFacebook + Get facebook test user be logged in on facebook. This is done by going to facebook.com @throws ModuleConfigException -### postToFacebookAsTestUser +### postToFacebookAsTestUser + Please, note that you must have publish_actions permission to be able to publish to user's feed. * `param array` $params + ### seePostOnFacebookWithAttachedPlace Please, note that you must have publish_actions permission to be able to publish to user's feed. * `param string` $placeId Place identifier to be verified against user published posts + ### seePostOnFacebookWithMessage Please, note that you must have publish_actions permission to be able to publish to user's feed. * `param string` $message published post to be verified against the actual post on facebook -

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
+

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
diff --git a/docs/modules/Filesystem.md b/docs/modules/Filesystem.md index 6cc73b0735..c38486a621 100644 --- a/docs/modules/Filesystem.md +++ b/docs/modules/Filesystem.md @@ -1,5 +1,6 @@ # Filesystem + Module for testing local filesystem. Fork it to extend the module for FTP, Amazon S3, others. @@ -14,14 +15,15 @@ Module was developed to test Codeception itself. ## Actions ### amInPath - + Enters a directory In local filesystem. Project root directory is used by default * `param string` $path -### cleanDir +### cleanDir + Erases directory contents ``` php @@ -32,8 +34,9 @@ $I->cleanDir('logs'); * `param string` $dirname -### copyDir +### copyDir + Copies directory with all contents ``` php @@ -45,8 +48,9 @@ $I->copyDir('vendor','old_vendor'); * `param string` $src * `param string` $dst -### deleteDir +### deleteDir + Deletes directory with all subdirectories ``` php @@ -57,8 +61,9 @@ $I->deleteDir('vendor'); * `param string` $dirname -### deleteFile +### deleteFile + Deletes a file ``` php @@ -69,19 +74,22 @@ $I->deleteFile('composer.lock'); * `param string` $filename -### deleteThisFile +### deleteThisFile + Deletes a file -### dontSeeFileFound +### dontSeeFileFound + Checks if file does not exist in path * `param string` $filename * `param string` $path -### dontSeeInThisFile +### dontSeeInThisFile + Checks If opened file doesn't contain `text` in it ``` php @@ -93,8 +101,9 @@ $I->dontSeeInThisFile('codeception/codeception'); * `param string` $text -### openFile +### openFile + Opens a file and stores it's content. Usage: @@ -108,8 +117,9 @@ $I->seeInThisFile('codeception/codeception'); * `param string` $filename -### seeFileContentsEqual +### seeFileContentsEqual + Checks the strict matching of file contents. Unlike `seeInThisFile` will fail if file has something more than expected lines. Better to use with HEREDOC strings. @@ -124,8 +134,9 @@ $I->seeFileContentsEqual('3192'); * `param string` $text -### seeFileFound +### seeFileFound + Checks if file exists in path. Opens a file when it's exists @@ -138,8 +149,9 @@ $I->seeFileFound('UserModel.php','app/models'); * `param string` $filename * `param string` $path -### seeInThisFile +### seeInThisFile + Checks If opened file has `text` in it. Usage: @@ -153,8 +165,9 @@ $I->seeInThisFile('codeception/codeception'); * `param string` $text -### seeNumberNewLines +### seeNumberNewLines + Checks If opened file has the `number` of new lines. Usage: @@ -168,17 +181,19 @@ $I->seeNumberNewLines(5); * `param int` $number New lines -### seeThisFileMatches +### seeThisFileMatches + Checks that contents of currently opened file matches $regex * `param string` $regex -### writeToFile +### writeToFile + Saves contents to file * `param string` $filename * `param string` $contents -

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
+

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
diff --git a/docs/modules/Laravel5.md b/docs/modules/Laravel5.md index 21cb6566da..3275146e2c 100644 --- a/docs/modules/Laravel5.md +++ b/docs/modules/Laravel5.md @@ -1,5 +1,7 @@ # Laravel5 + + This module allows you to run functional tests for Laravel 5.1+ It should **not** be used for acceptance tests. See the Acceptance tests section below for more details. @@ -86,7 +88,7 @@ modules: ### _findElements *hidden API method, expected to be used from Helper classes* - + Locates element using available Codeception locator types: * XPath @@ -110,10 +112,11 @@ PhpBrowser and Framework modules return `Symfony\Component\DomCrawler\Crawler` i * `param` $locator * `return` array of interactive elements + ### _getResponseContent *hidden API method, expected to be used from Helper classes* - + Returns content of the last response Use it in Helpers when you want to retrieve response of request performed by another module. @@ -130,10 +133,11 @@ public function seeResponseContains($text) * `return` string @throws ModuleException + ### _loadPage *hidden API method, expected to be used from Helper classes* - + Opens a page with arbitrary request parameters. Useful for testing multi-step forms on a specific step. @@ -153,10 +157,11 @@ public function openCheckoutFormStep2($orderId) { * `param array` $server * `param null` $content + ### _request *hidden API method, expected to be used from Helper classes* - + Send custom request to a backend using method, uri, parameters, etc. Use it in Helpers to create special request actions, like accessing API Returns a string with response body. @@ -184,10 +189,11 @@ To load arbitrary page for interaction, use `_loadPage` method. @throws ExternalUrlException @see `_loadPage` + ### _savePageSource *hidden API method, expected to be used from Helper classes* - + Saves page source of to a file ```php @@ -195,15 +201,17 @@ $this->getModule('Laravel5')->_savePageSource(codecept_output_dir().'page.html') ``` * `param` $filename -### amHttpAuthenticated +### amHttpAuthenticated + Authenticates user for HTTP_AUTH * `param` $username * `param` $password -### amLoggedAs +### amLoggedAs + Set the currently logged in user for the application. Takes either an object that implements the User interface or an array of credentials. @@ -223,8 +231,9 @@ $I->amLoggedAs( new User ); * `param` string|null $driver The authentication driver for Laravel <= 5.1.*, guard name for Laravel >= 5.2 * `return` void -### amOnAction +### amOnAction + Opens web page by action name ``` php @@ -236,8 +245,9 @@ $I->amOnAction('PostsController@index'); * `param` $action * `param array` $params -### amOnPage +### amOnPage + Opens the page for the given relative URI. ``` php @@ -250,8 +260,9 @@ $I->amOnPage('/register'); * `param string` $page -### amOnRoute +### amOnRoute + Opens web page using route name and parameters. ``` php @@ -263,8 +274,9 @@ $I->amOnRoute('posts.create'); * `param` $routeName * `param array` $params -### attachFile +### attachFile + Attaches a file relative to the Codeception `_data` directory to the given file upload field. ``` php @@ -277,8 +289,9 @@ $I->attachFile('input[@type="file"]', 'prices.xls'); * `param` $field * `param` $filename -### callArtisan +### callArtisan + Call an Artisan command. ``` php @@ -291,8 +304,9 @@ $I->callArtisan('command:name', ['parameter' => 'value']); * `param string` $command * `param array` $parameters -### checkOption +### checkOption + Ticks a checkbox. For radio buttons, use the `selectOption` method instead. ``` php @@ -303,8 +317,9 @@ $I->checkOption('#agree'); * `param` $option -### clearApplicationHandlers +### clearApplicationHandlers + Clear the registered application handlers. ``` php @@ -313,8 +328,10 @@ $I->clearApplicationHandlers(); ?> ``` -### click + +### click + Perform a click on a link or a button, given by a locator. If a fuzzy locator is given, the page will be searched for a button, link, or image matching the locator string. For buttons, the "value" attribute, "name" attribute, and inner text are searched. @@ -345,8 +362,9 @@ $I->click(['link' => 'Login']); * `param` $link * `param` $context -### deleteHeader +### deleteHeader + Deletes the header with the passed name. Subsequent requests will not have the deleted header in its request. @@ -363,8 +381,9 @@ $I->amOnPage('some-other-page.php'); * `param string` $name the name of the header to delete. -### disableEvents +### disableEvents + Disable events for the next requests. This method does not disable model events. To disable model events you have to use the disableModelEvents() method. @@ -375,8 +394,9 @@ $I->disableEvents(); ?> ``` -### disableExceptionHandling +### disableExceptionHandling + Disable Laravel exception handling. ``` php @@ -385,8 +405,9 @@ $I->disableExceptionHandling(); ?> ``` -### disableMiddleware +### disableMiddleware + Disable middleware for the next requests. ``` php @@ -395,8 +416,9 @@ $I->disableMiddleware(); ?> ``` -### disableModelEvents +### disableModelEvents + Disable model events for the next requests. ``` php @@ -405,8 +427,9 @@ $I->disableModelEvents(); ?> ``` -### dontSee +### dontSee + Checks that the current page doesn't contain the text specified (case insensitive). Give a locator as the second parameter to match a specific region. @@ -435,14 +458,16 @@ For checking the raw source code, use `seeInSource()`. * `param string` $text * `param string` $selector optional -### dontSeeAuthentication +### dontSeeAuthentication + Check that user is not authenticated. You can specify the guard that should be use for Laravel >= 5.2. * `param string|null` $guard -### dontSeeCheckboxIsChecked +### dontSeeCheckboxIsChecked + Check that the specified checkbox is unchecked. ``` php @@ -454,8 +479,9 @@ $I->seeCheckboxIsChecked('#signup_form input[type=checkbox]'); // I suppose user * `param` $checkbox -### dontSeeCookie +### dontSeeCookie + Checks that there isn't a cookie with the given name. You can set additional cookie params like `domain`, `path` as array passed in last argument. @@ -463,8 +489,9 @@ You can set additional cookie params like `domain`, `path` as array passed in la * `param array` $params -### dontSeeCurrentUrlEquals +### dontSeeCurrentUrlEquals + Checks that the current URL doesn't equal the given string. Unlike `dontSeeInCurrentUrl`, this only matches the full URL. @@ -477,8 +504,9 @@ $I->dontSeeCurrentUrlEquals('/'); * `param string` $uri -### dontSeeCurrentUrlMatches +### dontSeeCurrentUrlMatches + Checks that current url doesn't match the given regular expression. ``` php @@ -490,8 +518,9 @@ $I->dontSeeCurrentUrlMatches('~$/users/(\d+)~'); * `param string` $uri -### dontSeeElement +### dontSeeElement + Checks that the given element is invisible or not present on the page. You can also specify expected attributes of this element. @@ -507,8 +536,9 @@ $I->dontSeeElement('input', ['value' => '123456']); * `param` $selector * `param array` $attributes -### dontSeeEventTriggered +### dontSeeEventTriggered + Make sure events did not fire during the test. ``` php @@ -521,8 +551,9 @@ $I->dontSeeEventTriggered(['App\MyEvent', 'App\MyOtherEvent']); ``` * `param` $events -### dontSeeFormErrors +### dontSeeFormErrors + Assert that there are no form errors bound to the View. ``` php @@ -533,8 +564,9 @@ $I->dontSeeFormErrors(); * `return` bool -### dontSeeInCurrentUrl +### dontSeeInCurrentUrl + Checks that the current URI doesn't contain the given string. ``` php @@ -545,8 +577,9 @@ $I->dontSeeInCurrentUrl('/users/'); * `param string` $uri -### dontSeeInField +### dontSeeInField + Checks that an input field or textarea doesn't contain the given value. For fuzzy locators, the field is matched by label text, CSS and XPath. @@ -564,8 +597,9 @@ $I->dontSeeInField(['name' => 'search'], 'Search'); * `param` $field * `param` $value -### dontSeeInFormFields +### dontSeeInFormFields + Checks if the array of form parameters (name => value) are not set on the form matched with the passed selector. @@ -606,8 +640,9 @@ $I->dontSeeInFormFields('#form-id', [ * `param` $formSelector * `param` $params -### dontSeeInSource +### dontSeeInSource + Checks that the current page contains the given string in its raw source code. @@ -618,14 +653,17 @@ $I->dontSeeInSource('

Green eggs & ham

'); * `param` $raw -### dontSeeInTitle +### dontSeeInTitle + Checks that the page title does not contain the given string. * `param` $title -### dontSeeLink + +### dontSeeLink + Checks that the page doesn't contain a link with the given string. If the second parameter is given, only links with a matching "href" attribute will be checked. @@ -639,8 +677,9 @@ $I->dontSeeLink('Checkout now', '/store/cart.php'); * `param string` $text * `param string` $url optional -### dontSeeOptionIsSelected +### dontSeeOptionIsSelected + Checks that the given option is not selected. ``` php @@ -652,8 +691,10 @@ $I->dontSeeOptionIsSelected('#form input[name=payment]', 'Visa'); * `param` $selector * `param` $optionText -### dontSeeRecord + +### dontSeeRecord + Checks that record does not exist in database. You can pass the name of a database table or the class name of an Eloquent model as the first argument. @@ -668,8 +709,9 @@ $I->dontSeeRecord('App\User', array('name' => 'davert')); * `param array` $attributes * `[Part]` orm -### dontSeeResponseCodeIs +### dontSeeResponseCodeIs + Checks that response code is equal to value provided. ```php @@ -681,8 +723,9 @@ $I->dontSeeResponseCodeIs(\Codeception\Util\HttpCode::OK); ``` * `param` $code -### enableExceptionHandling +### enableExceptionHandling + Enable Laravel exception handling. ``` php @@ -691,8 +734,9 @@ $I->enableExceptionHandling(); ?> ``` -### fillField +### fillField + Fills a text field or textarea with the given string. ``` php @@ -705,14 +749,16 @@ $I->fillField(['name' => 'email'], 'jon@mail.com'); * `param` $field * `param` $value -### getApplication +### getApplication + Provides access the Laravel application object. * `return` \Illuminate\Foundation\Application -### grabAttributeFrom +### grabAttributeFrom + Grabs the value of the given attribute value from the given element. Fails if element is not found. @@ -725,8 +771,10 @@ $I->grabAttributeFrom('#tooltip', 'title'); * `param` $cssOrXpath * `param` $attribute -### grabCookie + +### grabCookie + Grabs a cookie value. You can set additional cookie params like `domain`, `path` in array passed as last argument. @@ -734,8 +782,9 @@ You can set additional cookie params like `domain`, `path` in array passed as la * `param array` $params -### grabFromCurrentUrl +### grabFromCurrentUrl + Executes the given regular expression against the current URI and returns the first capturing group. If no parameters are provided, the full URI is returned. @@ -748,8 +797,10 @@ $uri = $I->grabFromCurrentUrl(); * `param string` $uri optional -### grabMultiple + +### grabMultiple + Grabs either the text content, or attribute values, of nodes matched by $cssOrXpath and returns them as an array. @@ -773,8 +824,9 @@ $aLinks = $I->grabMultiple('a', 'href'); * `param` $attribute * `return` string[] -### grabNumRecords +### grabNumRecords + Retrieves number of records from database You can pass the name of a database table or the class name of an Eloquent model as the first argument. @@ -790,16 +842,18 @@ $I->grabNumRecords('App\User', array('name' => 'davert')); * `return` integer * `[Part]` orm -### grabPageSource +### grabPageSource + Grabs current page source code. @throws ModuleException if no page was opened. * `return` string Current page source code. -### grabRecord +### grabRecord + Retrieves record from database If you pass the name of a database table as the first argument, this method returns an array. You can also pass the class name of an Eloquent model, in that case this method returns an Eloquent model. @@ -816,8 +870,9 @@ $record = $I->grabRecord('App\User', array('name' => 'davert')); // returns Eloq * `return` array|EloquentModel * `[Part]` orm -### grabService +### grabService + Return an instance of a class from the Laravel service container. (https://laravel.com/docs/master/container) @@ -838,8 +893,9 @@ $service = $I->grabService('foo'); * `param` string $class -### grabTextFrom +### grabTextFrom + Finds and returns the text contents of the given element. If a fuzzy locator is used, the element is found using CSS, XPath, and by matching the full page source by regular expression. @@ -854,14 +910,17 @@ $value = $I->grabTextFrom('~have('App\User', [], 'admin'); * `param string` $name * `[Part]` orm -### haveApplicationHandler +### haveApplicationHandler + Register a handler than can be used to modify the Laravel application object after it is initialized. The Laravel application object will be passed as an argument to the handler. @@ -894,8 +954,9 @@ $I->haveApplicationHandler(function($app) { * `param` $handler -### haveBinding +### haveBinding + Add a binding to the Laravel service container. (https://laravel.com/docs/master/container) @@ -908,8 +969,9 @@ $I->haveBinding('My\Interface', 'My\Implementation'); * `param` $abstract * `param` $concrete -### haveContextualBinding +### haveContextualBinding + Add a contextual binding to the Laravel service container. (https://laravel.com/docs/master/container) @@ -928,8 +990,9 @@ $app->when('My\Class') * `param` $abstract * `param` $implementation -### haveHttpHeader +### haveHttpHeader + Sets the HTTP header to the passed value - which is used on subsequent HTTP requests through PhpBrowser. @@ -956,8 +1019,9 @@ $I->haveHttpHeader('Client_Id', 'Codeception'); * `param string` $value the value to set it to for subsequent requests -### haveInstance +### haveInstance + Add an instance binding to the Laravel service container. (https://laravel.com/docs/master/container) @@ -970,8 +1034,9 @@ $I->haveInstance('My\Class', new My\Class()); * `param` $abstract * `param` $instance -### haveMultiple +### haveMultiple + Use Laravel's model factory to create multiple models. Can only be used with Laravel 5.1 and later. @@ -990,8 +1055,9 @@ $I->haveMultiple('App\User', 10, [], 'admin'); * `param string` $name * `[Part]` orm -### haveRecord +### haveRecord + Inserts record into the database. If you pass the name of a database table as the first argument, this method returns an integer ID. You can also pass the class name of an Eloquent model, in that case this method returns an Eloquent model. @@ -1008,8 +1074,9 @@ $user = $I->haveRecord('App\User', array('name' => 'Davert')); // returns Eloque * `return` integer|EloquentModel * `[Part]` orm -### haveSingleton +### haveSingleton + Add a singleton binding to the Laravel service container. (https://laravel.com/docs/master/container) @@ -1022,18 +1089,21 @@ $I->haveSingleton('My\Interface', 'My\Singleton'); * `param` $abstract * `param` $concrete -### logout +### logout + Logout user. -### moveBack +### moveBack + Moves back in history. * `param int` $numberOfSteps (default value 1) -### resetCookie +### resetCookie + Unsets cookie with the given name. You can set additional cookie params like `domain`, `path` in array passed as last argument. @@ -1041,8 +1111,9 @@ You can set additional cookie params like `domain`, `path` in array passed as la * `param array` $params -### see +### see + Checks that the current page contains the given string (case insensitive). You can specify a specific HTML element (via CSS or XPath) as the second @@ -1073,14 +1144,16 @@ For checking the raw source code, use `seeInSource()`. * `param string` $text * `param string` $selector optional -### seeAuthentication +### seeAuthentication + Checks that a user is authenticated. You can specify the guard that should be use for Laravel >= 5.2. * `param string|null` $guard -### seeCheckboxIsChecked +### seeCheckboxIsChecked + Checks that the specified checkbox is checked. ``` php @@ -1093,8 +1166,9 @@ $I->seeCheckboxIsChecked('//form/input[@type=checkbox and @name=agree]'); * `param` $checkbox -### seeCookie +### seeCookie + Checks that a cookie with the given name is set. You can set additional cookie params like `domain`, `path` as array passed in last argument. @@ -1107,8 +1181,9 @@ $I->seeCookie('PHPSESSID'); * `param` $cookie * `param array` $params -### seeCurrentActionIs +### seeCurrentActionIs + Checks that current url matches action ``` php @@ -1119,8 +1194,9 @@ $I->seeCurrentActionIs('PostsController@index'); * `param` $action -### seeCurrentRouteIs +### seeCurrentRouteIs + Checks that current url matches route ``` php @@ -1130,8 +1206,9 @@ $I->seeCurrentRouteIs('posts.index'); ``` * `param` $routeName -### seeCurrentUrlEquals +### seeCurrentUrlEquals + Checks that the current URL is equal to the given string. Unlike `seeInCurrentUrl`, this only matches the full URL. @@ -1144,8 +1221,9 @@ $I->seeCurrentUrlEquals('/'); * `param string` $uri -### seeCurrentUrlMatches +### seeCurrentUrlMatches + Checks that the current URL matches the given regular expression. ``` php @@ -1157,8 +1235,9 @@ $I->seeCurrentUrlMatches('~$/users/(\d+)~'); * `param string` $uri -### seeElement +### seeElement + Checks that the given element exists on the page and is visible. You can also specify expected attributes of this element. @@ -1178,8 +1257,9 @@ $I->seeElement(['css' => 'form input'], ['name' => 'login']); * `param array` $attributes @return -### seeEventTriggered +### seeEventTriggered + Make sure events fired during the test. ``` php @@ -1192,8 +1272,9 @@ $I->seeEventTriggered(['App\MyEvent', 'App\MyOtherEvent']); ``` * `param` $events -### seeFormErrorMessage +### seeFormErrorMessage + Assert that a specific form error message is set in the view. If you want to assert that there is a form error message for a specific key @@ -1211,8 +1292,9 @@ $I->seeFormErrorMessage('username', 'Invalid Username'); * `param string` $key * `param string|null` $expectedErrorMessage -### seeFormErrorMessages +### seeFormErrorMessages + Assert that specific form error messages are set in the view. This method calls `seeFormErrorMessage` for each entry in the `$bindings` array. @@ -1227,8 +1309,9 @@ $I->seeFormErrorMessages([ ``` * `param array` $bindings -### seeFormHasErrors +### seeFormHasErrors + Assert that form errors are bound to the View. ``` php @@ -1239,8 +1322,9 @@ $I->seeFormHasErrors(); * `return` bool -### seeInCurrentUrl +### seeInCurrentUrl + Checks that current URI contains the given string. ``` php @@ -1254,8 +1338,9 @@ $I->seeInCurrentUrl('/users/'); * `param string` $uri -### seeInField +### seeInField + Checks that the given input field or textarea *equals* (i.e. not just contains) the given value. Fields are matched by label text, the "name" attribute, CSS, or XPath. @@ -1273,8 +1358,9 @@ $I->seeInField(['name' => 'search'], 'Search'); * `param` $field * `param` $value -### seeInFormFields +### seeInFormFields + Checks if the array of form parameters (name => value) are set on the form matched with the passed selector. @@ -1335,8 +1421,9 @@ $I->seeInFormFields('//form[@id=my-form]', $form); * `param` $formSelector * `param` $params -### seeInSession +### seeInSession + Assert that a session variable exists. ``` php @@ -1350,8 +1437,9 @@ $I->seeInSession('key', 'value'); * `param` mixed|null $value * `return` void -### seeInSource +### seeInSource + Checks that the current page contains the given string in its raw source code. @@ -1362,8 +1450,9 @@ $I->seeInSource('

Green eggs & ham

'); * `param` $raw -### seeInTitle +### seeInTitle + Checks that the page title contains the given string. ``` php @@ -1374,8 +1463,10 @@ $I->seeInTitle('Blog - Post #1'); * `param` $title -### seeLink + +### seeLink + Checks that there's a link with the specified text. Give a full URL as the second parameter to match links with that exact URL. @@ -1389,8 +1480,9 @@ $I->seeLink('Logout','/logout'); // matches Logout * `param string` $text * `param string` $url optional -### seeNumRecords +### seeNumRecords + Checks that number of given records were found in database. You can pass the name of a database table or the class name of an Eloquent model as the first argument. @@ -1406,8 +1498,9 @@ $I->seeNumRecords(1, 'App\User', array('name' => 'davert')); * `param array` $attributes * `[Part]` orm -### seeNumberOfElements +### seeNumberOfElements + Checks that there are a certain number of elements matched by the given locator on the page. ``` php @@ -1419,8 +1512,9 @@ $I->seeNumberOfElements('tr', [0,10]); // between 0 and 10 elements * `param` $selector * `param mixed` $expected int or int[] -### seeOptionIsSelected +### seeOptionIsSelected + Checks that the given option is selected. ``` php @@ -1432,12 +1526,15 @@ $I->seeOptionIsSelected('#form input[name=payment]', 'Visa'); * `param` $selector * `param` $optionText -### seePageNotFound + +### seePageNotFound + Asserts that current page has 404 response status code. -### seeRecord +### seeRecord + Checks that record exists in database. You can pass the name of a database table or the class name of an Eloquent model as the first argument. @@ -1452,8 +1549,9 @@ $I->seeRecord('App\User', array('name' => 'davert')); * `param array` $attributes * `[Part]` orm -### seeResponseCodeIs +### seeResponseCodeIs + Checks that response code is equal to value provided. ```php @@ -1466,8 +1564,9 @@ $I->seeResponseCodeIs(\Codeception\Util\HttpCode::OK); * `param` $code -### seeSessionHasValues +### seeSessionHasValues + Assert that the session has a given list of values. ``` php @@ -1480,8 +1579,9 @@ $I->seeSessionHasValues(['key1' => 'value1', 'key2' => 'value2']); * `param` array $bindings * `return` void -### selectOption +### selectOption + Selects an option in a select tag or in radio button group. ``` php @@ -1512,8 +1612,9 @@ $I->selectOption('Which OS do you use?', array('value' => 'windows')); // Only s * `param` $select * `param` $option -### sendAjaxGetRequest +### sendAjaxGetRequest + If your page triggers an ajax request, you can perform it manually. This action sends a GET ajax request with specified params. @@ -1522,8 +1623,9 @@ See ->sendAjaxPostRequest for examples. * `param` $uri * `param` $params -### sendAjaxPostRequest +### sendAjaxPostRequest + If your page triggers an ajax request, you can perform it manually. This action sends a POST ajax request with specified params. Additional params can be passed as array. @@ -1543,8 +1645,9 @@ $I->sendAjaxGetRequest('/updateSettings', array('notifications' => true)); // GE * `param` $uri * `param` $params -### sendAjaxRequest +### sendAjaxRequest + If your page triggers an ajax request, you can perform it manually. This action sends an ajax request with specified method and params. @@ -1562,12 +1665,14 @@ $I->sendAjaxRequest('PUT', '/posts/7', array('title' => 'new title')); * `param` $uri * `param` $params -### setApplication +### setApplication + * `param` $app -### setCookie +### setCookie + Sets a cookie with the given name and value. You can set additional cookie params like `domain`, `path`, `expires`, `secure` in array passed as last argument. @@ -1581,8 +1686,10 @@ $I->setCookie('PHPSESSID', 'el4ukv0kqbvoirg7nkp4dncpk3'); * `param` $val * `param array` $params -### submitForm + +### submitForm + Submits the given form on the page, with the given form values. Pass the form field's values as an array in the second parameter. @@ -1753,8 +1860,9 @@ $I->submitForm('#my-form', [ * `param` $params * `param` $button -### switchToIframe +### switchToIframe + Switch to iframe or frame on the page. Example: @@ -1770,8 +1878,9 @@ $I->switchToIframe("another_frame"); * `param string` $name -### uncheckOption +### uncheckOption + Unticks a checkbox. ``` php @@ -1782,4 +1891,4 @@ $I->uncheckOption('#notify'); * `param` $option -

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
+

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
diff --git a/docs/modules/Lumen.md b/docs/modules/Lumen.md index ba4f8cd863..9b463ec1aa 100644 --- a/docs/modules/Lumen.md +++ b/docs/modules/Lumen.md @@ -1,5 +1,7 @@ # Lumen + + This module allows you to run functional tests for Lumen. Please try it and leave your feedback. @@ -41,7 +43,7 @@ Please try it and leave your feedback. ### _findElements *hidden API method, expected to be used from Helper classes* - + Locates element using available Codeception locator types: * XPath @@ -65,10 +67,11 @@ PhpBrowser and Framework modules return `Symfony\Component\DomCrawler\Crawler` i * `param` $locator * `return` array of interactive elements + ### _getResponseContent *hidden API method, expected to be used from Helper classes* - + Returns content of the last response Use it in Helpers when you want to retrieve response of request performed by another module. @@ -85,10 +88,11 @@ public function seeResponseContains($text) * `return` string @throws ModuleException + ### _loadPage *hidden API method, expected to be used from Helper classes* - + Opens a page with arbitrary request parameters. Useful for testing multi-step forms on a specific step. @@ -108,10 +112,11 @@ public function openCheckoutFormStep2($orderId) { * `param array` $server * `param null` $content + ### _request *hidden API method, expected to be used from Helper classes* - + Send custom request to a backend using method, uri, parameters, etc. Use it in Helpers to create special request actions, like accessing API Returns a string with response body. @@ -139,10 +144,11 @@ To load arbitrary page for interaction, use `_loadPage` method. @throws ExternalUrlException @see `_loadPage` + ### _savePageSource *hidden API method, expected to be used from Helper classes* - + Saves page source of to a file ```php @@ -150,15 +156,17 @@ $this->getModule('Lumen')->_savePageSource(codecept_output_dir().'page.html'); ``` * `param` $filename -### amHttpAuthenticated +### amHttpAuthenticated + Authenticates user for HTTP_AUTH * `param` $username * `param` $password -### amLoggedAs +### amLoggedAs + Set the authenticated user for the next request. This will not persist between multiple requests. @@ -166,8 +174,9 @@ This will not persist between multiple requests. * `param` string|null $driver The authentication driver for Lumen <= 5.1.*, guard name for Lumen >= 5.2 * `return` void -### amOnPage +### amOnPage + Opens the page for the given relative URI. ``` php @@ -180,8 +189,9 @@ $I->amOnPage('/register'); * `param string` $page -### amOnRoute +### amOnRoute + Opens web page using route name and parameters. ```php @@ -193,8 +203,9 @@ $I->amOnRoute('homepage'); * `param` $routeName * `param array` $params -### attachFile +### attachFile + Attaches a file relative to the Codeception `_data` directory to the given file upload field. ``` php @@ -207,8 +218,9 @@ $I->attachFile('input[@type="file"]', 'prices.xls'); * `param` $field * `param` $filename -### checkOption +### checkOption + Ticks a checkbox. For radio buttons, use the `selectOption` method instead. ``` php @@ -219,8 +231,9 @@ $I->checkOption('#agree'); * `param` $option -### clearApplicationHandlers +### clearApplicationHandlers + Clear the registered application handlers. ``` php @@ -229,8 +242,10 @@ $I->clearApplicationHandlers(); ?> ``` -### click + +### click + Perform a click on a link or a button, given by a locator. If a fuzzy locator is given, the page will be searched for a button, link, or image matching the locator string. For buttons, the "value" attribute, "name" attribute, and inner text are searched. @@ -261,8 +276,9 @@ $I->click(['link' => 'Login']); * `param` $link * `param` $context -### deleteHeader +### deleteHeader + Deletes the header with the passed name. Subsequent requests will not have the deleted header in its request. @@ -279,8 +295,9 @@ $I->amOnPage('some-other-page.php'); * `param string` $name the name of the header to delete. -### dontSee +### dontSee + Checks that the current page doesn't contain the text specified (case insensitive). Give a locator as the second parameter to match a specific region. @@ -309,12 +326,14 @@ For checking the raw source code, use `seeInSource()`. * `param string` $text * `param string` $selector optional -### dontSeeAuthentication +### dontSeeAuthentication + Check that user is not authenticated. -### dontSeeCheckboxIsChecked +### dontSeeCheckboxIsChecked + Check that the specified checkbox is unchecked. ``` php @@ -326,8 +345,9 @@ $I->seeCheckboxIsChecked('#signup_form input[type=checkbox]'); // I suppose user * `param` $checkbox -### dontSeeCookie +### dontSeeCookie + Checks that there isn't a cookie with the given name. You can set additional cookie params like `domain`, `path` as array passed in last argument. @@ -335,8 +355,9 @@ You can set additional cookie params like `domain`, `path` as array passed in la * `param array` $params -### dontSeeCurrentUrlEquals +### dontSeeCurrentUrlEquals + Checks that the current URL doesn't equal the given string. Unlike `dontSeeInCurrentUrl`, this only matches the full URL. @@ -349,8 +370,9 @@ $I->dontSeeCurrentUrlEquals('/'); * `param string` $uri -### dontSeeCurrentUrlMatches +### dontSeeCurrentUrlMatches + Checks that current url doesn't match the given regular expression. ``` php @@ -362,8 +384,9 @@ $I->dontSeeCurrentUrlMatches('~$/users/(\d+)~'); * `param string` $uri -### dontSeeElement +### dontSeeElement + Checks that the given element is invisible or not present on the page. You can also specify expected attributes of this element. @@ -379,8 +402,9 @@ $I->dontSeeElement('input', ['value' => '123456']); * `param` $selector * `param array` $attributes -### dontSeeInCurrentUrl +### dontSeeInCurrentUrl + Checks that the current URI doesn't contain the given string. ``` php @@ -391,8 +415,9 @@ $I->dontSeeInCurrentUrl('/users/'); * `param string` $uri -### dontSeeInField +### dontSeeInField + Checks that an input field or textarea doesn't contain the given value. For fuzzy locators, the field is matched by label text, CSS and XPath. @@ -410,8 +435,9 @@ $I->dontSeeInField(['name' => 'search'], 'Search'); * `param` $field * `param` $value -### dontSeeInFormFields +### dontSeeInFormFields + Checks if the array of form parameters (name => value) are not set on the form matched with the passed selector. @@ -452,8 +478,9 @@ $I->dontSeeInFormFields('#form-id', [ * `param` $formSelector * `param` $params -### dontSeeInSource +### dontSeeInSource + Checks that the current page contains the given string in its raw source code. @@ -464,14 +491,17 @@ $I->dontSeeInSource('

Green eggs & ham

'); * `param` $raw -### dontSeeInTitle +### dontSeeInTitle + Checks that the page title does not contain the given string. * `param` $title -### dontSeeLink + +### dontSeeLink + Checks that the page doesn't contain a link with the given string. If the second parameter is given, only links with a matching "href" attribute will be checked. @@ -485,8 +515,9 @@ $I->dontSeeLink('Checkout now', '/store/cart.php'); * `param string` $text * `param string` $url optional -### dontSeeOptionIsSelected +### dontSeeOptionIsSelected + Checks that the given option is not selected. ``` php @@ -498,8 +529,10 @@ $I->dontSeeOptionIsSelected('#form input[name=payment]', 'Visa'); * `param` $selector * `param` $optionText -### dontSeeRecord + +### dontSeeRecord + Checks that record does not exist in database. You can pass the name of a database table or the class name of an Eloquent model as the first argument. @@ -514,8 +547,9 @@ $I->dontSeeRecord('App\User', array('name' => 'davert')); * `param array` $attributes * `[Part]` orm -### dontSeeResponseCodeIs +### dontSeeResponseCodeIs + Checks that response code is equal to value provided. ```php @@ -527,8 +561,9 @@ $I->dontSeeResponseCodeIs(\Codeception\Util\HttpCode::OK); ``` * `param` $code -### fillField +### fillField + Fills a text field or textarea with the given string. ``` php @@ -541,14 +576,16 @@ $I->fillField(['name' => 'email'], 'jon@mail.com'); * `param` $field * `param` $value -### getApplication +### getApplication + Provides access the Lumen application object. * `return` \Laravel\Lumen\Application -### grabAttributeFrom +### grabAttributeFrom + Grabs the value of the given attribute value from the given element. Fails if element is not found. @@ -561,8 +598,10 @@ $I->grabAttributeFrom('#tooltip', 'title'); * `param` $cssOrXpath * `param` $attribute -### grabCookie + +### grabCookie + Grabs a cookie value. You can set additional cookie params like `domain`, `path` in array passed as last argument. @@ -570,8 +609,9 @@ You can set additional cookie params like `domain`, `path` in array passed as la * `param array` $params -### grabFromCurrentUrl +### grabFromCurrentUrl + Executes the given regular expression against the current URI and returns the first capturing group. If no parameters are provided, the full URI is returned. @@ -584,8 +624,10 @@ $uri = $I->grabFromCurrentUrl(); * `param string` $uri optional -### grabMultiple + +### grabMultiple + Grabs either the text content, or attribute values, of nodes matched by $cssOrXpath and returns them as an array. @@ -609,16 +651,18 @@ $aLinks = $I->grabMultiple('a', 'href'); * `param` $attribute * `return` string[] -### grabPageSource +### grabPageSource + Grabs current page source code. @throws ModuleException if no page was opened. * `return` string Current page source code. -### grabRecord +### grabRecord + Retrieves record from database If you pass the name of a database table as the first argument, this method returns an array. You can also pass the class name of an Eloquent model, in that case this method returns an Eloquent model. @@ -635,8 +679,9 @@ $record = $I->grabRecord('App\User', array('name' => 'davert')); // returns Eloq * `return` array|EloquentModel * `[Part]` orm -### grabService +### grabService + Return an instance of a class from the IoC Container. Example @@ -657,8 +702,9 @@ $service = $I->grabService('foo'); * `param` string $class -### grabTextFrom +### grabTextFrom + Finds and returns the text contents of the given element. If a fuzzy locator is used, the element is found using CSS, XPath, and by matching the full page source by regular expression. @@ -673,14 +719,17 @@ $value = $I->grabTextFrom('~have('App\User', [], 'admin'); * `param string` $name * `[Part]` orm -### haveApplicationHandler +### haveApplicationHandler + Register a handler than can be used to modify the Laravel application object after it is initialized. The Laravel application object will be passed as an argument to the handler. @@ -713,8 +763,9 @@ $I->haveApplicationHandler(function($app) { * `param` $handler -### haveBinding +### haveBinding + Add a binding to the Laravel service container. (https://laravel.com/docs/master/container) @@ -727,8 +778,9 @@ $I->haveBinding('My\Interface', 'My\Implementation'); * `param` $abstract * `param` $concrete -### haveContextualBinding +### haveContextualBinding + Add a contextual binding to the Laravel service container. (https://laravel.com/docs/master/container) @@ -747,8 +799,9 @@ $app->when('My\Class') * `param` $abstract * `param` $implementation -### haveHttpHeader +### haveHttpHeader + Sets the HTTP header to the passed value - which is used on subsequent HTTP requests through PhpBrowser. @@ -775,8 +828,9 @@ $I->haveHttpHeader('Client_Id', 'Codeception'); * `param string` $value the value to set it to for subsequent requests -### haveInstance +### haveInstance + Add an instance binding to the Laravel service container. (https://laravel.com/docs/master/container) @@ -789,8 +843,9 @@ $I->haveInstance('My\Class', new My\Class()); * `param` $abstract * `param` $instance -### haveMultiple +### haveMultiple + Use Laravel's model factory to create multiple models. Can only be used with Lumen 5.1 and later. @@ -809,8 +864,9 @@ $I->haveMultiple('App\User', 10, [], 'admin'); * `param string` $name * `[Part]` orm -### haveRecord +### haveRecord + Inserts record into the database. If you pass the name of a database table as the first argument, this method returns an integer ID. You can also pass the class name of an Eloquent model, in that case this method returns an Eloquent model. @@ -827,8 +883,9 @@ $user = $I->haveRecord('App\User', array('name' => 'Davert')); // returns Eloque * `return` integer|EloquentModel * `[Part]` orm -### haveSingleton +### haveSingleton + Add a singleton binding to the Laravel service container. (https://laravel.com/docs/master/container) @@ -841,14 +898,16 @@ $I->haveSingleton('My\Interface', 'My\Singleton'); * `param` $abstract * `param` $concrete -### moveBack +### moveBack + Moves back in history. * `param int` $numberOfSteps (default value 1) -### resetCookie +### resetCookie + Unsets cookie with the given name. You can set additional cookie params like `domain`, `path` in array passed as last argument. @@ -856,8 +915,9 @@ You can set additional cookie params like `domain`, `path` in array passed as la * `param array` $params -### see +### see + Checks that the current page contains the given string (case insensitive). You can specify a specific HTML element (via CSS or XPath) as the second @@ -888,12 +948,14 @@ For checking the raw source code, use `seeInSource()`. * `param string` $text * `param string` $selector optional -### seeAuthentication +### seeAuthentication + Checks that user is authenticated. -### seeCheckboxIsChecked +### seeCheckboxIsChecked + Checks that the specified checkbox is checked. ``` php @@ -906,8 +968,9 @@ $I->seeCheckboxIsChecked('//form/input[@type=checkbox and @name=agree]'); * `param` $checkbox -### seeCookie +### seeCookie + Checks that a cookie with the given name is set. You can set additional cookie params like `domain`, `path` as array passed in last argument. @@ -920,8 +983,9 @@ $I->seeCookie('PHPSESSID'); * `param` $cookie * `param array` $params -### seeCurrentUrlEquals +### seeCurrentUrlEquals + Checks that the current URL is equal to the given string. Unlike `seeInCurrentUrl`, this only matches the full URL. @@ -934,8 +998,9 @@ $I->seeCurrentUrlEquals('/'); * `param string` $uri -### seeCurrentUrlMatches +### seeCurrentUrlMatches + Checks that the current URL matches the given regular expression. ``` php @@ -947,8 +1012,9 @@ $I->seeCurrentUrlMatches('~$/users/(\d+)~'); * `param string` $uri -### seeElement +### seeElement + Checks that the given element exists on the page and is visible. You can also specify expected attributes of this element. @@ -968,8 +1034,9 @@ $I->seeElement(['css' => 'form input'], ['name' => 'login']); * `param array` $attributes @return -### seeInCurrentUrl +### seeInCurrentUrl + Checks that current URI contains the given string. ``` php @@ -983,8 +1050,9 @@ $I->seeInCurrentUrl('/users/'); * `param string` $uri -### seeInField +### seeInField + Checks that the given input field or textarea *equals* (i.e. not just contains) the given value. Fields are matched by label text, the "name" attribute, CSS, or XPath. @@ -1002,8 +1070,9 @@ $I->seeInField(['name' => 'search'], 'Search'); * `param` $field * `param` $value -### seeInFormFields +### seeInFormFields + Checks if the array of form parameters (name => value) are set on the form matched with the passed selector. @@ -1064,8 +1133,9 @@ $I->seeInFormFields('//form[@id=my-form]', $form); * `param` $formSelector * `param` $params -### seeInSource +### seeInSource + Checks that the current page contains the given string in its raw source code. @@ -1076,8 +1146,9 @@ $I->seeInSource('

Green eggs & ham

'); * `param` $raw -### seeInTitle +### seeInTitle + Checks that the page title contains the given string. ``` php @@ -1088,8 +1159,10 @@ $I->seeInTitle('Blog - Post #1'); * `param` $title -### seeLink + +### seeLink + Checks that there's a link with the specified text. Give a full URL as the second parameter to match links with that exact URL. @@ -1103,8 +1176,9 @@ $I->seeLink('Logout','/logout'); // matches Logout * `param string` $text * `param string` $url optional -### seeNumberOfElements +### seeNumberOfElements + Checks that there are a certain number of elements matched by the given locator on the page. ``` php @@ -1116,8 +1190,9 @@ $I->seeNumberOfElements('tr', [0,10]); // between 0 and 10 elements * `param` $selector * `param mixed` $expected int or int[] -### seeOptionIsSelected +### seeOptionIsSelected + Checks that the given option is selected. ``` php @@ -1129,12 +1204,15 @@ $I->seeOptionIsSelected('#form input[name=payment]', 'Visa'); * `param` $selector * `param` $optionText -### seePageNotFound + +### seePageNotFound + Asserts that current page has 404 response status code. -### seeRecord +### seeRecord + Checks that record exists in database. You can pass the name of a database table or the class name of an Eloquent model as the first argument. @@ -1149,8 +1227,9 @@ $I->seeRecord('App\User', array('name' => 'davert')); * `param array` $attributes * `[Part]` orm -### seeResponseCodeIs +### seeResponseCodeIs + Checks that response code is equal to value provided. ```php @@ -1163,8 +1242,9 @@ $I->seeResponseCodeIs(\Codeception\Util\HttpCode::OK); * `param` $code -### selectOption +### selectOption + Selects an option in a select tag or in radio button group. ``` php @@ -1195,8 +1275,9 @@ $I->selectOption('Which OS do you use?', array('value' => 'windows')); // Only s * `param` $select * `param` $option -### sendAjaxGetRequest +### sendAjaxGetRequest + If your page triggers an ajax request, you can perform it manually. This action sends a GET ajax request with specified params. @@ -1205,8 +1286,9 @@ See ->sendAjaxPostRequest for examples. * `param` $uri * `param` $params -### sendAjaxPostRequest +### sendAjaxPostRequest + If your page triggers an ajax request, you can perform it manually. This action sends a POST ajax request with specified params. Additional params can be passed as array. @@ -1226,8 +1308,9 @@ $I->sendAjaxGetRequest('/updateSettings', array('notifications' => true)); // GE * `param` $uri * `param` $params -### sendAjaxRequest +### sendAjaxRequest + If your page triggers an ajax request, you can perform it manually. This action sends an ajax request with specified method and params. @@ -1245,12 +1328,14 @@ $I->sendAjaxRequest('PUT', '/posts/7', array('title' => 'new title')); * `param` $uri * `param` $params -### setApplication +### setApplication + * `param \Laravel\Lumen\Application` $app -### setCookie +### setCookie + Sets a cookie with the given name and value. You can set additional cookie params like `domain`, `path`, `expires`, `secure` in array passed as last argument. @@ -1264,8 +1349,10 @@ $I->setCookie('PHPSESSID', 'el4ukv0kqbvoirg7nkp4dncpk3'); * `param` $val * `param array` $params -### submitForm + +### submitForm + Submits the given form on the page, with the given form values. Pass the form field's values as an array in the second parameter. @@ -1436,8 +1523,9 @@ $I->submitForm('#my-form', [ * `param` $params * `param` $button -### switchToIframe +### switchToIframe + Switch to iframe or frame on the page. Example: @@ -1453,8 +1541,9 @@ $I->switchToIframe("another_frame"); * `param string` $name -### uncheckOption +### uncheckOption + Unticks a checkbox. ``` php @@ -1465,4 +1554,4 @@ $I->uncheckOption('#notify'); * `param` $option -

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
+

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
diff --git a/docs/modules/Memcache.md b/docs/modules/Memcache.md index cef10c55c7..94b0665620 100644 --- a/docs/modules/Memcache.md +++ b/docs/modules/Memcache.md @@ -1,5 +1,6 @@ # Memcache + Connects to [memcached](http://www.memcached.org/) using either _Memcache_ or _Memcached_ extension. Performs a cleanup by flushing all values after each test run. @@ -30,14 +31,16 @@ Be sure you don't use the production server to connect. * **memcache** - instance of _Memcache_ or _Memcached_ object + ## Actions ### clearMemcache - + Flushes all Memcached data. -### dontSeeInMemcached +### dontSeeInMemcached + Checks item in Memcached doesn't exist or is the same as expected. Examples: @@ -55,8 +58,9 @@ $I->dontSeeInMemcached('users_count', 200); * `param` $key * `param` $value -### grabValueFromMemcached +### grabValueFromMemcached + Grabs value from memcached by key. Example: @@ -70,16 +74,18 @@ $users_count = $I->grabValueFromMemcached('users_count'); * `param` $key * `return` array|string -### haveInMemcached +### haveInMemcached + Stores an item `$value` with `$key` on the Memcached server. * `param string` $key * `param mixed` $value * `param int` $expiration -### seeInMemcached +### seeInMemcached + Checks item in Memcached exists and the same as expected. Examples: @@ -97,4 +103,4 @@ $I->seeInMemcached('users_count', 200); * `param` $key * `param` $value -

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
+

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
diff --git a/docs/modules/MongoDb.md b/docs/modules/MongoDb.md index 312b63b2b1..33092110ae 100644 --- a/docs/modules/MongoDb.md +++ b/docs/modules/MongoDb.md @@ -1,5 +1,6 @@ # MongoDb + Works with MongoDb database. The most important function of this module is cleaning database before each test. @@ -39,10 +40,11 @@ HINT: This module can be used with [Mongofill](https://github.com/mongofill/mong * populate: true - should the dump be loaded before test suite is started. * cleanup: true - should the dump be reloaded after each test + ## Actions ### dontSeeInCollection - + Checks if collection doesn't contain an item. ``` php @@ -53,8 +55,9 @@ $I->dontSeeInCollection('users', array('name' => 'miles')); * `param` $collection * `param array` $criteria -### grabCollectionCount +### grabCollectionCount + Grabs the documents count from a collection ``` php @@ -68,8 +71,9 @@ $count = $I->grabCollectionCount('users', array('isAdmin' => true)); * `param array` $criteria * `return` integer -### grabFromCollection +### grabFromCollection + Grabs a data from collection ``` php @@ -81,8 +85,9 @@ $user = $I->grabFromCollection('users', array('name' => 'miles')); * `param array` $criteria * `return` array -### haveInCollection +### haveInCollection + Inserts data into collection ``` php @@ -94,8 +99,9 @@ $user_id = $I->haveInCollection('users', array('email' => 'john@coltrane.com')); * `param` $collection * `param array` $data -### seeElementIsArray +### seeElementIsArray + Asserts that an element in a collection exists and is an Array ``` php @@ -107,8 +113,9 @@ $I->seeElementIsArray('users', array('name' => 'John Doe') , 'data.skills'); * `param Array` $criteria * `param String` $elementToCheck -### seeElementIsObject +### seeElementIsObject + Asserts that an element in a collection exists and is an Object ``` php @@ -120,8 +127,9 @@ $I->seeElementIsObject('users', array('name' => 'John Doe') , 'data'); * `param Array` $criteria * `param String` $elementToCheck -### seeInCollection +### seeInCollection + Checks if collection contains an item. ``` php @@ -132,8 +140,9 @@ $I->seeInCollection('users', array('name' => 'miles')); * `param` $collection * `param array` $criteria -### seeNumElementsInCollection +### seeNumElementsInCollection + Count number of records in a collection ``` php @@ -146,8 +155,9 @@ $I->seeNumElementsInCollection('users', 1, array('name' => 'miles')); * `param integer` $expected * `param array` $criteria -### useDatabase +### useDatabase + Specify the database to use ``` php @@ -157,4 +167,4 @@ $I->useDatabase('db_1'); * `param` $dbName -

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
+

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
diff --git a/docs/modules/Phalcon.md b/docs/modules/Phalcon.md index c4da09e670..7106ebf920 100644 --- a/docs/modules/Phalcon.md +++ b/docs/modules/Phalcon.md @@ -1,5 +1,6 @@ # Phalcon + This module provides integration with [Phalcon framework](http://www.phalconphp.com/) (3.x). Please try it and leave your feedback. @@ -70,7 +71,7 @@ modules: ### _findElements *hidden API method, expected to be used from Helper classes* - + Locates element using available Codeception locator types: * XPath @@ -94,10 +95,11 @@ PhpBrowser and Framework modules return `Symfony\Component\DomCrawler\Crawler` i * `param` $locator * `return` array of interactive elements + ### _getResponseContent *hidden API method, expected to be used from Helper classes* - + Returns content of the last response Use it in Helpers when you want to retrieve response of request performed by another module. @@ -114,10 +116,11 @@ public function seeResponseContains($text) * `return` string @throws ModuleException + ### _loadPage *hidden API method, expected to be used from Helper classes* - + Opens a page with arbitrary request parameters. Useful for testing multi-step forms on a specific step. @@ -137,10 +140,11 @@ public function openCheckoutFormStep2($orderId) { * `param array` $server * `param null` $content + ### _request *hidden API method, expected to be used from Helper classes* - + Send custom request to a backend using method, uri, parameters, etc. Use it in Helpers to create special request actions, like accessing API Returns a string with response body. @@ -168,10 +172,11 @@ To load arbitrary page for interaction, use `_loadPage` method. @throws ExternalUrlException @see `_loadPage` + ### _savePageSource *hidden API method, expected to be used from Helper classes* - + Saves page source of to a file ```php @@ -179,8 +184,9 @@ $this->getModule('Phalcon')->_savePageSource(codecept_output_dir().'page.html'); ``` * `param` $filename -### addServiceToContainer +### addServiceToContainer + Registers a service in the services container and resolve it. This record will be erased after the test. Recommended to use for unit testing. @@ -199,15 +205,17 @@ $filter = $I->addServiceToContainer('answer', function () { * `return` mixed|null * `[Part]` services -### amHttpAuthenticated +### amHttpAuthenticated + Authenticates user for HTTP_AUTH * `param` $username * `param` $password -### amOnPage +### amOnPage + Opens the page for the given relative URI. ``` php @@ -220,8 +228,9 @@ $I->amOnPage('/register'); * `param string` $page -### amOnRoute +### amOnRoute + Opens web page using route name and parameters. ``` php @@ -233,8 +242,9 @@ $I->amOnRoute('posts.create'); * `param string` $routeName * `param array` $params -### attachFile +### attachFile + Attaches a file relative to the Codeception `_data` directory to the given file upload field. ``` php @@ -247,8 +257,9 @@ $I->attachFile('input[@type="file"]', 'prices.xls'); * `param` $field * `param` $filename -### checkOption +### checkOption + Ticks a checkbox. For radio buttons, use the `selectOption` method instead. ``` php @@ -259,8 +270,9 @@ $I->checkOption('#agree'); * `param` $option -### click +### click + Perform a click on a link or a button, given by a locator. If a fuzzy locator is given, the page will be searched for a button, link, or image matching the locator string. For buttons, the "value" attribute, "name" attribute, and inner text are searched. @@ -291,8 +303,9 @@ $I->click(['link' => 'Login']); * `param` $link * `param` $context -### deleteHeader +### deleteHeader + Deletes the header with the passed name. Subsequent requests will not have the deleted header in its request. @@ -309,8 +322,9 @@ $I->amOnPage('some-other-page.php'); * `param string` $name the name of the header to delete. -### dontSee +### dontSee + Checks that the current page doesn't contain the text specified (case insensitive). Give a locator as the second parameter to match a specific region. @@ -339,8 +353,9 @@ For checking the raw source code, use `seeInSource()`. * `param string` $text * `param string` $selector optional -### dontSeeCheckboxIsChecked +### dontSeeCheckboxIsChecked + Check that the specified checkbox is unchecked. ``` php @@ -352,8 +367,9 @@ $I->seeCheckboxIsChecked('#signup_form input[type=checkbox]'); // I suppose user * `param` $checkbox -### dontSeeCookie +### dontSeeCookie + Checks that there isn't a cookie with the given name. You can set additional cookie params like `domain`, `path` as array passed in last argument. @@ -361,8 +377,9 @@ You can set additional cookie params like `domain`, `path` as array passed in la * `param array` $params -### dontSeeCurrentUrlEquals +### dontSeeCurrentUrlEquals + Checks that the current URL doesn't equal the given string. Unlike `dontSeeInCurrentUrl`, this only matches the full URL. @@ -375,8 +392,9 @@ $I->dontSeeCurrentUrlEquals('/'); * `param string` $uri -### dontSeeCurrentUrlMatches +### dontSeeCurrentUrlMatches + Checks that current url doesn't match the given regular expression. ``` php @@ -388,8 +406,9 @@ $I->dontSeeCurrentUrlMatches('~$/users/(\d+)~'); * `param string` $uri -### dontSeeElement +### dontSeeElement + Checks that the given element is invisible or not present on the page. You can also specify expected attributes of this element. @@ -405,8 +424,9 @@ $I->dontSeeElement('input', ['value' => '123456']); * `param` $selector * `param array` $attributes -### dontSeeInCurrentUrl +### dontSeeInCurrentUrl + Checks that the current URI doesn't contain the given string. ``` php @@ -417,8 +437,9 @@ $I->dontSeeInCurrentUrl('/users/'); * `param string` $uri -### dontSeeInField +### dontSeeInField + Checks that an input field or textarea doesn't contain the given value. For fuzzy locators, the field is matched by label text, CSS and XPath. @@ -436,8 +457,9 @@ $I->dontSeeInField(['name' => 'search'], 'Search'); * `param` $field * `param` $value -### dontSeeInFormFields +### dontSeeInFormFields + Checks if the array of form parameters (name => value) are not set on the form matched with the passed selector. @@ -478,8 +500,9 @@ $I->dontSeeInFormFields('#form-id', [ * `param` $formSelector * `param` $params -### dontSeeInSource +### dontSeeInSource + Checks that the current page contains the given string in its raw source code. @@ -490,14 +513,17 @@ $I->dontSeeInSource('

Green eggs & ham

'); * `param` $raw -### dontSeeInTitle +### dontSeeInTitle + Checks that the page title does not contain the given string. * `param` $title -### dontSeeLink + +### dontSeeLink + Checks that the page doesn't contain a link with the given string. If the second parameter is given, only links with a matching "href" attribute will be checked. @@ -511,8 +537,9 @@ $I->dontSeeLink('Checkout now', '/store/cart.php'); * `param string` $text * `param string` $url optional -### dontSeeOptionIsSelected +### dontSeeOptionIsSelected + Checks that the given option is not selected. ``` php @@ -524,8 +551,10 @@ $I->dontSeeOptionIsSelected('#form input[name=payment]', 'Visa'); * `param` $selector * `param` $optionText -### dontSeeRecord + +### dontSeeRecord + Checks that record does not exist in database. ``` php @@ -538,8 +567,9 @@ $I->dontSeeRecord('App\Models\Categories', ['name' => 'Testing']); * `param array` $attributes Model attributes * `[Part]` orm -### dontSeeResponseCodeIs +### dontSeeResponseCodeIs + Checks that response code is equal to value provided. ```php @@ -551,8 +581,9 @@ $I->dontSeeResponseCodeIs(\Codeception\Util\HttpCode::OK); ``` * `param` $code -### fillField +### fillField + Fills a text field or textarea with the given string. ``` php @@ -565,15 +596,17 @@ $I->fillField(['name' => 'email'], 'jon@mail.com'); * `param` $field * `param` $value -### getApplication +### getApplication + Provides access the Phalcon application object. @see \Codeception\Lib\Connector\Phalcon::getApplication * `return` \Phalcon\Application|\Phalcon\Mvc\Micro -### grabAttributeFrom +### grabAttributeFrom + Grabs the value of the given attribute value from the given element. Fails if element is not found. @@ -586,8 +619,10 @@ $I->grabAttributeFrom('#tooltip', 'title'); * `param` $cssOrXpath * `param` $attribute -### grabCookie + +### grabCookie + Grabs a cookie value. You can set additional cookie params like `domain`, `path` in array passed as last argument. @@ -595,8 +630,9 @@ You can set additional cookie params like `domain`, `path` in array passed as la * `param array` $params -### grabFromCurrentUrl +### grabFromCurrentUrl + Executes the given regular expression against the current URI and returns the first capturing group. If no parameters are provided, the full URI is returned. @@ -609,8 +645,10 @@ $uri = $I->grabFromCurrentUrl(); * `param string` $uri optional -### grabMultiple + +### grabMultiple + Grabs either the text content, or attribute values, of nodes matched by $cssOrXpath and returns them as an array. @@ -634,16 +672,18 @@ $aLinks = $I->grabMultiple('a', 'href'); * `param` $attribute * `return` string[] -### grabPageSource +### grabPageSource + Grabs current page source code. @throws ModuleException if no page was opened. * `return` string Current page source code. -### grabRecord +### grabRecord + Retrieves record from database ``` php @@ -656,8 +696,9 @@ $category = $I->grabRecord('App\Models\Categories', ['name' => 'Testing']); * `param array` $attributes Model attributes * `[Part]` orm -### grabServiceFromContainer +### grabServiceFromContainer + Resolves the service based on its configuration from Phalcon's DI container Recommended to use for unit testing. @@ -665,8 +706,9 @@ Recommended to use for unit testing. * `param array` $parameters Parameters [Optional] * `[Part]` services -### grabServiceFromDi +### grabServiceFromDi + Alias for `grabServiceFromContainer`. Note: Deprecated. Will be removed in Codeception 2.3. @@ -675,8 +717,9 @@ Note: Deprecated. Will be removed in Codeception 2.3. * `param array` $parameters Parameters [Optional] * `[Part]` services -### grabTextFrom +### grabTextFrom + Finds and returns the text contents of the given element. If a fuzzy locator is used, the element is found using CSS, XPath, and by matching the full page source by regular expression. @@ -691,14 +734,17 @@ $value = $I->grabTextFrom('~haveHttpHeader('Client_Id', 'Codeception'); * `param string` $value the value to set it to for subsequent requests -### haveInSession +### haveInSession + Sets value to session. Use for authorization. * `param string` $key * `param mixed` $val -### haveRecord +### haveRecord + Inserts record into the database. ``` php @@ -747,8 +795,9 @@ $I->haveRecord('App\Models\Categories', ['name' => 'Testing']'); * `param array` $attributes Model attributes * `[Part]` orm -### haveServiceInDi +### haveServiceInDi + Alias for `addServiceToContainer`. Note: Deprecated. Will be removed in Codeception 2.3. @@ -759,14 +808,16 @@ Note: Deprecated. Will be removed in Codeception 2.3. * `return` mixed|null * `[Part]` services -### moveBack +### moveBack + Moves back in history. * `param int` $numberOfSteps (default value 1) -### resetCookie +### resetCookie + Unsets cookie with the given name. You can set additional cookie params like `domain`, `path` in array passed as last argument. @@ -774,8 +825,9 @@ You can set additional cookie params like `domain`, `path` in array passed as la * `param array` $params -### see +### see + Checks that the current page contains the given string (case insensitive). You can specify a specific HTML element (via CSS or XPath) as the second @@ -806,8 +858,9 @@ For checking the raw source code, use `seeInSource()`. * `param string` $text * `param string` $selector optional -### seeCheckboxIsChecked +### seeCheckboxIsChecked + Checks that the specified checkbox is checked. ``` php @@ -820,8 +873,9 @@ $I->seeCheckboxIsChecked('//form/input[@type=checkbox and @name=agree]'); * `param` $checkbox -### seeCookie +### seeCookie + Checks that a cookie with the given name is set. You can set additional cookie params like `domain`, `path` as array passed in last argument. @@ -834,8 +888,9 @@ $I->seeCookie('PHPSESSID'); * `param` $cookie * `param array` $params -### seeCurrentRouteIs +### seeCurrentRouteIs + Checks that current url matches route ``` php @@ -845,8 +900,9 @@ $I->seeCurrentRouteIs('posts.index'); ``` * `param string` $routeName -### seeCurrentUrlEquals +### seeCurrentUrlEquals + Checks that the current URL is equal to the given string. Unlike `seeInCurrentUrl`, this only matches the full URL. @@ -859,8 +915,9 @@ $I->seeCurrentUrlEquals('/'); * `param string` $uri -### seeCurrentUrlMatches +### seeCurrentUrlMatches + Checks that the current URL matches the given regular expression. ``` php @@ -872,8 +929,9 @@ $I->seeCurrentUrlMatches('~$/users/(\d+)~'); * `param string` $uri -### seeElement +### seeElement + Checks that the given element exists on the page and is visible. You can also specify expected attributes of this element. @@ -893,8 +951,9 @@ $I->seeElement(['css' => 'form input'], ['name' => 'login']); * `param array` $attributes @return -### seeInCurrentUrl +### seeInCurrentUrl + Checks that current URI contains the given string. ``` php @@ -908,8 +967,9 @@ $I->seeInCurrentUrl('/users/'); * `param string` $uri -### seeInField +### seeInField + Checks that the given input field or textarea *equals* (i.e. not just contains) the given value. Fields are matched by label text, the "name" attribute, CSS, or XPath. @@ -927,8 +987,9 @@ $I->seeInField(['name' => 'search'], 'Search'); * `param` $field * `param` $value -### seeInFormFields +### seeInFormFields + Checks if the array of form parameters (name => value) are set on the form matched with the passed selector. @@ -989,8 +1050,9 @@ $I->seeInFormFields('//form[@id=my-form]', $form); * `param` $formSelector * `param` $params -### seeInSession +### seeInSession + Checks that session contains value. If value is `null` checks that session has key. @@ -1004,8 +1066,9 @@ $I->seeInSession('key', 'value'); * `param string` $key * `param mixed` $value -### seeInSource +### seeInSource + Checks that the current page contains the given string in its raw source code. @@ -1016,8 +1079,9 @@ $I->seeInSource('

Green eggs & ham

'); * `param` $raw -### seeInTitle +### seeInTitle + Checks that the page title contains the given string. ``` php @@ -1028,8 +1092,10 @@ $I->seeInTitle('Blog - Post #1'); * `param` $title -### seeLink + +### seeLink + Checks that there's a link with the specified text. Give a full URL as the second parameter to match links with that exact URL. @@ -1043,8 +1109,9 @@ $I->seeLink('Logout','/logout'); // matches Logout * `param string` $text * `param string` $url optional -### seeNumberOfElements +### seeNumberOfElements + Checks that there are a certain number of elements matched by the given locator on the page. ``` php @@ -1056,8 +1123,9 @@ $I->seeNumberOfElements('tr', [0,10]); // between 0 and 10 elements * `param` $selector * `param mixed` $expected int or int[] -### seeOptionIsSelected +### seeOptionIsSelected + Checks that the given option is selected. ``` php @@ -1069,12 +1137,15 @@ $I->seeOptionIsSelected('#form input[name=payment]', 'Visa'); * `param` $selector * `param` $optionText -### seePageNotFound + +### seePageNotFound + Asserts that current page has 404 response status code. -### seeRecord +### seeRecord + Checks that record exists in database. ``` php @@ -1087,8 +1158,9 @@ $I->seeRecord('App\Models\Categories', ['name' => 'Testing']); * `param array` $attributes Model attributes * `[Part]` orm -### seeResponseCodeIs +### seeResponseCodeIs + Checks that response code is equal to value provided. ```php @@ -1101,8 +1173,9 @@ $I->seeResponseCodeIs(\Codeception\Util\HttpCode::OK); * `param` $code -### seeSessionHasValues +### seeSessionHasValues + Assert that the session has a given list of values. ``` php @@ -1115,8 +1188,9 @@ $I->seeSessionHasValues(['key1' => 'value1', 'key2' => 'value2']); * `param` array $bindings * `return` void -### selectOption +### selectOption + Selects an option in a select tag or in radio button group. ``` php @@ -1147,8 +1221,9 @@ $I->selectOption('Which OS do you use?', array('value' => 'windows')); // Only s * `param` $select * `param` $option -### sendAjaxGetRequest +### sendAjaxGetRequest + If your page triggers an ajax request, you can perform it manually. This action sends a GET ajax request with specified params. @@ -1157,8 +1232,9 @@ See ->sendAjaxPostRequest for examples. * `param` $uri * `param` $params -### sendAjaxPostRequest +### sendAjaxPostRequest + If your page triggers an ajax request, you can perform it manually. This action sends a POST ajax request with specified params. Additional params can be passed as array. @@ -1178,8 +1254,9 @@ $I->sendAjaxGetRequest('/updateSettings', array('notifications' => true)); // GE * `param` $uri * `param` $params -### sendAjaxRequest +### sendAjaxRequest + If your page triggers an ajax request, you can perform it manually. This action sends an ajax request with specified method and params. @@ -1197,8 +1274,9 @@ $I->sendAjaxRequest('PUT', '/posts/7', array('title' => 'new title')); * `param` $uri * `param` $params -### setCookie +### setCookie + Sets a cookie with the given name and value. You can set additional cookie params like `domain`, `path`, `expires`, `secure` in array passed as last argument. @@ -1212,8 +1290,10 @@ $I->setCookie('PHPSESSID', 'el4ukv0kqbvoirg7nkp4dncpk3'); * `param` $val * `param array` $params -### submitForm + +### submitForm + Submits the given form on the page, with the given form values. Pass the form field's values as an array in the second parameter. @@ -1384,8 +1464,9 @@ $I->submitForm('#my-form', [ * `param` $params * `param` $button -### switchToIframe +### switchToIframe + Switch to iframe or frame on the page. Example: @@ -1401,8 +1482,9 @@ $I->switchToIframe("another_frame"); * `param string` $name -### uncheckOption +### uncheckOption + Unticks a checkbox. ``` php @@ -1413,4 +1495,4 @@ $I->uncheckOption('#notify'); * `param` $option -

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
+

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
diff --git a/docs/modules/PhpBrowser.md b/docs/modules/PhpBrowser.md index 37a5317e9a..fad0a6a363 100644 --- a/docs/modules/PhpBrowser.md +++ b/docs/modules/PhpBrowser.md @@ -1,5 +1,6 @@ # PhpBrowser + Uses [Guzzle](http://guzzlephp.org/) to interact with your application over CURL. Module works over CURL and requires **PHP CURL extension** to be enabled. @@ -13,6 +14,7 @@ If test fails stores last shown page in 'output' dir. * Stability: **stable** * Contact: codeception@codeception.com + ## Configuration * url *required* - start url of your app @@ -25,6 +27,7 @@ If test fails stores last shown page in 'output' dir. * verify - ... * .. those and other [Guzzle Request options](http://docs.guzzlephp.org/en/latest/request-options.html) + ### Example (`acceptance.suite.yml`) modules: @@ -47,6 +50,7 @@ If test fails stores last shown page in 'output' dir. Secure: true HttpOnly: false + All SSL certification checks are disabled by default. Use Guzzle request options to configure certifications and others. @@ -59,12 +63,13 @@ Properties: * `guzzle` - contains [Guzzle](http://guzzlephp.org/) client instance: `\GuzzleHttp\Client` * `client` - Symfony BrowserKit instance. + ## Actions ### _findElements *hidden API method, expected to be used from Helper classes* - + Locates element using available Codeception locator types: * XPath @@ -88,10 +93,11 @@ PhpBrowser and Framework modules return `Symfony\Component\DomCrawler\Crawler` i * `param` $locator * `return` array of interactive elements + ### _getResponseContent *hidden API method, expected to be used from Helper classes* - + Returns content of the last response Use it in Helpers when you want to retrieve response of request performed by another module. @@ -108,10 +114,11 @@ public function seeResponseContains($text) * `return` string @throws ModuleException + ### _loadPage *hidden API method, expected to be used from Helper classes* - + Opens a page with arbitrary request parameters. Useful for testing multi-step forms on a specific step. @@ -131,10 +138,11 @@ public function openCheckoutFormStep2($orderId) { * `param array` $server * `param null` $content + ### _request *hidden API method, expected to be used from Helper classes* - + Send custom request to a backend using method, uri, parameters, etc. Use it in Helpers to create special request actions, like accessing API Returns a string with response body. @@ -162,10 +170,11 @@ To load arbitrary page for interaction, use `_loadPage` method. @throws ExternalUrlException @see `_loadPage` + ### _savePageSource *hidden API method, expected to be used from Helper classes* - + Saves page source of to a file ```php @@ -173,15 +182,17 @@ $this->getModule('PhpBrowser')->_savePageSource(codecept_output_dir().'page.html ``` * `param` $filename -### amHttpAuthenticated +### amHttpAuthenticated + Authenticates user for HTTP_AUTH * `param` $username * `param` $password -### amOnPage +### amOnPage + Opens the page for the given relative URI. ``` php @@ -194,8 +205,9 @@ $I->amOnPage('/register'); * `param string` $page -### amOnSubdomain +### amOnSubdomain + Changes the subdomain for the 'url' configuration parameter. Does not open a page; use `amOnPage` for that. @@ -213,8 +225,10 @@ $I->amOnPage('/'); * `param` $subdomain -### amOnUrl + +### amOnUrl + Open web page at the given absolute URL and sets its hostname as the base host. ``` php @@ -224,8 +238,9 @@ $I->amOnPage('/quickstart'); // moves to http://codeception.com/quickstart ?> ``` -### attachFile +### attachFile + Attaches a file relative to the Codeception `_data` directory to the given file upload field. ``` php @@ -238,8 +253,9 @@ $I->attachFile('input[@type="file"]', 'prices.xls'); * `param` $field * `param` $filename -### checkOption +### checkOption + Ticks a checkbox. For radio buttons, use the `selectOption` method instead. ``` php @@ -250,8 +266,9 @@ $I->checkOption('#agree'); * `param` $option -### click +### click + Perform a click on a link or a button, given by a locator. If a fuzzy locator is given, the page will be searched for a button, link, or image matching the locator string. For buttons, the "value" attribute, "name" attribute, and inner text are searched. @@ -282,8 +299,9 @@ $I->click(['link' => 'Login']); * `param` $link * `param` $context -### deleteHeader +### deleteHeader + Deletes the header with the passed name. Subsequent requests will not have the deleted header in its request. @@ -300,8 +318,9 @@ $I->amOnPage('some-other-page.php'); * `param string` $name the name of the header to delete. -### dontSee +### dontSee + Checks that the current page doesn't contain the text specified (case insensitive). Give a locator as the second parameter to match a specific region. @@ -330,8 +349,9 @@ For checking the raw source code, use `seeInSource()`. * `param string` $text * `param string` $selector optional -### dontSeeCheckboxIsChecked +### dontSeeCheckboxIsChecked + Check that the specified checkbox is unchecked. ``` php @@ -343,8 +363,9 @@ $I->seeCheckboxIsChecked('#signup_form input[type=checkbox]'); // I suppose user * `param` $checkbox -### dontSeeCookie +### dontSeeCookie + Checks that there isn't a cookie with the given name. You can set additional cookie params like `domain`, `path` as array passed in last argument. @@ -352,8 +373,9 @@ You can set additional cookie params like `domain`, `path` as array passed in la * `param array` $params -### dontSeeCurrentUrlEquals +### dontSeeCurrentUrlEquals + Checks that the current URL doesn't equal the given string. Unlike `dontSeeInCurrentUrl`, this only matches the full URL. @@ -366,8 +388,9 @@ $I->dontSeeCurrentUrlEquals('/'); * `param string` $uri -### dontSeeCurrentUrlMatches +### dontSeeCurrentUrlMatches + Checks that current url doesn't match the given regular expression. ``` php @@ -379,8 +402,9 @@ $I->dontSeeCurrentUrlMatches('~$/users/(\d+)~'); * `param string` $uri -### dontSeeElement +### dontSeeElement + Checks that the given element is invisible or not present on the page. You can also specify expected attributes of this element. @@ -396,8 +420,9 @@ $I->dontSeeElement('input', ['value' => '123456']); * `param` $selector * `param array` $attributes -### dontSeeInCurrentUrl +### dontSeeInCurrentUrl + Checks that the current URI doesn't contain the given string. ``` php @@ -408,8 +433,9 @@ $I->dontSeeInCurrentUrl('/users/'); * `param string` $uri -### dontSeeInField +### dontSeeInField + Checks that an input field or textarea doesn't contain the given value. For fuzzy locators, the field is matched by label text, CSS and XPath. @@ -427,8 +453,9 @@ $I->dontSeeInField(['name' => 'search'], 'Search'); * `param` $field * `param` $value -### dontSeeInFormFields +### dontSeeInFormFields + Checks if the array of form parameters (name => value) are not set on the form matched with the passed selector. @@ -469,8 +496,9 @@ $I->dontSeeInFormFields('#form-id', [ * `param` $formSelector * `param` $params -### dontSeeInSource +### dontSeeInSource + Checks that the current page contains the given string in its raw source code. @@ -481,14 +509,17 @@ $I->dontSeeInSource('

Green eggs & ham

'); * `param` $raw -### dontSeeInTitle +### dontSeeInTitle + Checks that the page title does not contain the given string. * `param` $title -### dontSeeLink + +### dontSeeLink + Checks that the page doesn't contain a link with the given string. If the second parameter is given, only links with a matching "href" attribute will be checked. @@ -502,8 +533,9 @@ $I->dontSeeLink('Checkout now', '/store/cart.php'); * `param string` $text * `param string` $url optional -### dontSeeOptionIsSelected +### dontSeeOptionIsSelected + Checks that the given option is not selected. ``` php @@ -515,8 +547,10 @@ $I->dontSeeOptionIsSelected('#form input[name=payment]', 'Visa'); * `param` $selector * `param` $optionText -### dontSeeResponseCodeIs + +### dontSeeResponseCodeIs + Checks that response code is equal to value provided. ```php @@ -528,8 +562,9 @@ $I->dontSeeResponseCodeIs(\Codeception\Util\HttpCode::OK); ``` * `param` $code -### executeInGuzzle +### executeInGuzzle + Low-level API method. If Codeception commands are not enough, use [Guzzle HTTP Client](http://guzzlephp.org/) methods directly @@ -548,8 +583,9 @@ If Codeception lacks important Guzzle Client methods, implement them and submit * `param callable` $function -### fillField +### fillField + Fills a text field or textarea with the given string. ``` php @@ -562,8 +598,9 @@ $I->fillField(['name' => 'email'], 'jon@mail.com'); * `param` $field * `param` $value -### grabAttributeFrom +### grabAttributeFrom + Grabs the value of the given attribute value from the given element. Fails if element is not found. @@ -576,8 +613,10 @@ $I->grabAttributeFrom('#tooltip', 'title'); * `param` $cssOrXpath * `param` $attribute -### grabCookie + +### grabCookie + Grabs a cookie value. You can set additional cookie params like `domain`, `path` in array passed as last argument. @@ -585,8 +624,9 @@ You can set additional cookie params like `domain`, `path` in array passed as la * `param array` $params -### grabFromCurrentUrl +### grabFromCurrentUrl + Executes the given regular expression against the current URI and returns the first capturing group. If no parameters are provided, the full URI is returned. @@ -599,8 +639,10 @@ $uri = $I->grabFromCurrentUrl(); * `param string` $uri optional -### grabMultiple + +### grabMultiple + Grabs either the text content, or attribute values, of nodes matched by $cssOrXpath and returns them as an array. @@ -624,16 +666,18 @@ $aLinks = $I->grabMultiple('a', 'href'); * `param` $attribute * `return` string[] -### grabPageSource +### grabPageSource + Grabs current page source code. @throws ModuleException if no page was opened. * `return` string Current page source code. -### grabTextFrom +### grabTextFrom + Finds and returns the text contents of the given element. If a fuzzy locator is used, the element is found using CSS, XPath, and by matching the full page source by regular expression. @@ -648,14 +692,17 @@ $value = $I->grabTextFrom('~haveHttpHeader('Client_Id', 'Codeception'); * `param string` $value the value to set it to for subsequent requests -### moveBack +### moveBack + Moves back in history. * `param int` $numberOfSteps (default value 1) -### resetCookie +### resetCookie + Unsets cookie with the given name. You can set additional cookie params like `domain`, `path` in array passed as last argument. @@ -697,8 +746,9 @@ You can set additional cookie params like `domain`, `path` in array passed as la * `param array` $params -### see +### see + Checks that the current page contains the given string (case insensitive). You can specify a specific HTML element (via CSS or XPath) as the second @@ -729,8 +779,9 @@ For checking the raw source code, use `seeInSource()`. * `param string` $text * `param string` $selector optional -### seeCheckboxIsChecked +### seeCheckboxIsChecked + Checks that the specified checkbox is checked. ``` php @@ -743,8 +794,9 @@ $I->seeCheckboxIsChecked('//form/input[@type=checkbox and @name=agree]'); * `param` $checkbox -### seeCookie +### seeCookie + Checks that a cookie with the given name is set. You can set additional cookie params like `domain`, `path` as array passed in last argument. @@ -757,8 +809,9 @@ $I->seeCookie('PHPSESSID'); * `param` $cookie * `param array` $params -### seeCurrentUrlEquals +### seeCurrentUrlEquals + Checks that the current URL is equal to the given string. Unlike `seeInCurrentUrl`, this only matches the full URL. @@ -771,8 +824,9 @@ $I->seeCurrentUrlEquals('/'); * `param string` $uri -### seeCurrentUrlMatches +### seeCurrentUrlMatches + Checks that the current URL matches the given regular expression. ``` php @@ -784,8 +838,9 @@ $I->seeCurrentUrlMatches('~$/users/(\d+)~'); * `param string` $uri -### seeElement +### seeElement + Checks that the given element exists on the page and is visible. You can also specify expected attributes of this element. @@ -805,8 +860,9 @@ $I->seeElement(['css' => 'form input'], ['name' => 'login']); * `param array` $attributes @return -### seeInCurrentUrl +### seeInCurrentUrl + Checks that current URI contains the given string. ``` php @@ -820,8 +876,9 @@ $I->seeInCurrentUrl('/users/'); * `param string` $uri -### seeInField +### seeInField + Checks that the given input field or textarea *equals* (i.e. not just contains) the given value. Fields are matched by label text, the "name" attribute, CSS, or XPath. @@ -839,8 +896,9 @@ $I->seeInField(['name' => 'search'], 'Search'); * `param` $field * `param` $value -### seeInFormFields +### seeInFormFields + Checks if the array of form parameters (name => value) are set on the form matched with the passed selector. @@ -901,8 +959,9 @@ $I->seeInFormFields('//form[@id=my-form]', $form); * `param` $formSelector * `param` $params -### seeInSource +### seeInSource + Checks that the current page contains the given string in its raw source code. @@ -913,8 +972,9 @@ $I->seeInSource('

Green eggs & ham

'); * `param` $raw -### seeInTitle +### seeInTitle + Checks that the page title contains the given string. ``` php @@ -925,8 +985,10 @@ $I->seeInTitle('Blog - Post #1'); * `param` $title -### seeLink + +### seeLink + Checks that there's a link with the specified text. Give a full URL as the second parameter to match links with that exact URL. @@ -940,8 +1002,9 @@ $I->seeLink('Logout','/logout'); // matches Logout * `param string` $text * `param string` $url optional -### seeNumberOfElements +### seeNumberOfElements + Checks that there are a certain number of elements matched by the given locator on the page. ``` php @@ -953,8 +1016,9 @@ $I->seeNumberOfElements('tr', [0,10]); // between 0 and 10 elements * `param` $selector * `param mixed` $expected int or int[] -### seeOptionIsSelected +### seeOptionIsSelected + Checks that the given option is selected. ``` php @@ -966,12 +1030,15 @@ $I->seeOptionIsSelected('#form input[name=payment]', 'Visa'); * `param` $selector * `param` $optionText -### seePageNotFound + +### seePageNotFound + Asserts that current page has 404 response status code. -### seeResponseCodeIs +### seeResponseCodeIs + Checks that response code is equal to value provided. ```php @@ -984,8 +1051,9 @@ $I->seeResponseCodeIs(\Codeception\Util\HttpCode::OK); * `param` $code -### selectOption +### selectOption + Selects an option in a select tag or in radio button group. ``` php @@ -1016,8 +1084,9 @@ $I->selectOption('Which OS do you use?', array('value' => 'windows')); // Only s * `param` $select * `param` $option -### sendAjaxGetRequest +### sendAjaxGetRequest + If your page triggers an ajax request, you can perform it manually. This action sends a GET ajax request with specified params. @@ -1026,8 +1095,9 @@ See ->sendAjaxPostRequest for examples. * `param` $uri * `param` $params -### sendAjaxPostRequest +### sendAjaxPostRequest + If your page triggers an ajax request, you can perform it manually. This action sends a POST ajax request with specified params. Additional params can be passed as array. @@ -1047,8 +1117,9 @@ $I->sendAjaxGetRequest('/updateSettings', array('notifications' => true)); // GE * `param` $uri * `param` $params -### sendAjaxRequest +### sendAjaxRequest + If your page triggers an ajax request, you can perform it manually. This action sends an ajax request with specified method and params. @@ -1066,8 +1137,9 @@ $I->sendAjaxRequest('PUT', '/posts/7', array('title' => 'new title')); * `param` $uri * `param` $params -### setCookie +### setCookie + Sets a cookie with the given name and value. You can set additional cookie params like `domain`, `path`, `expires`, `secure` in array passed as last argument. @@ -1081,15 +1153,18 @@ $I->setCookie('PHPSESSID', 'el4ukv0kqbvoirg7nkp4dncpk3'); * `param` $val * `param array` $params -### setHeader + +### setHeader + Alias to `haveHttpHeader` * `param` $name * `param` $value -### submitForm +### submitForm + Submits the given form on the page, with the given form values. Pass the form field's values as an array in the second parameter. @@ -1260,8 +1335,9 @@ $I->submitForm('#my-form', [ * `param` $params * `param` $button -### switchToIframe +### switchToIframe + Switch to iframe or frame on the page. Example: @@ -1277,8 +1353,9 @@ $I->switchToIframe("another_frame"); * `param string` $name -### uncheckOption +### uncheckOption + Unticks a checkbox. ``` php @@ -1289,4 +1366,4 @@ $I->uncheckOption('#notify'); * `param` $option -

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
+

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
diff --git a/docs/modules/Queue.md b/docs/modules/Queue.md index 391a5bce87..3a97a89fdc 100644 --- a/docs/modules/Queue.md +++ b/docs/modules/Queue.md @@ -1,5 +1,7 @@ # Queue + + Works with Queue servers. Testing with a selection of remote/local queueing services, including Amazon's SQS service @@ -113,10 +115,11 @@ service. 'type': 'aws', 'region': 'us-west-2' + ## Actions ### addMessageToQueue - + Add a message to a queue/tube ```php @@ -128,8 +131,9 @@ $I->addMessageToQueue('this is a messages', 'default'); * `param string` $message Message Body * `param string` $queue Queue Name -### clearQueue +### clearQueue + Clear all messages of the queue/tube ```php @@ -140,8 +144,9 @@ $I->clearQueue('default'); * `param string` $queue Queue Name -### dontSeeEmptyQueue +### dontSeeEmptyQueue + Check if a queue/tube is NOT empty of all messages ```php @@ -152,8 +157,9 @@ $I->dontSeeEmptyQueue('default'); * `param string` $queue Queue Name -### dontSeeQueueExists +### dontSeeQueueExists + Check if a queue/tube does NOT exist on the queueing server. ```php @@ -164,8 +170,9 @@ $I->dontSeeQueueExists('default'); * `param string` $queue Queue Name -### dontSeeQueueHasCurrentCount +### dontSeeQueueHasCurrentCount + Check if a queue/tube does NOT have a given current number of messages ```php @@ -177,8 +184,9 @@ $I->dontSeeQueueHasCurrentCount('default', 10); * `param string` $queue Queue Name * `param int` $expected Number of messages expected -### dontSeeQueueHasTotalCount +### dontSeeQueueHasTotalCount + Check if a queue/tube does NOT have a given total number of messages ```php @@ -190,8 +198,9 @@ $I->dontSeeQueueHasTotalCount('default', 10); * `param string` $queue Queue Name * `param int` $expected Number of messages expected -### grabQueueCurrentCount +### grabQueueCurrentCount + Grabber method to get the current number of messages on the queue/tube (pending/ready) ```php @@ -203,8 +212,9 @@ Grabber method to get the current number of messages on the queue/tube (pending/ * `return` int Count -### grabQueueTotalCount +### grabQueueTotalCount + Grabber method to get the total number of messages on the queue/tube ```php @@ -217,8 +227,9 @@ Grabber method to get the total number of messages on the queue/tube * `return` int Count -### grabQueues +### grabQueues + Grabber method to get the list of queues/tubes on the server ```php @@ -229,8 +240,9 @@ $queues = $I->grabQueues(); * `return` array List of Queues/Tubes -### seeEmptyQueue +### seeEmptyQueue + Check if a queue/tube is empty of all messages ```php @@ -241,8 +253,9 @@ $I->seeEmptyQueue('default'); * `param string` $queue Queue Name -### seeQueueExists +### seeQueueExists + Check if a queue/tube exists on the queueing server. ```php @@ -253,8 +266,9 @@ $I->seeQueueExists('default'); * `param string` $queue Queue Name -### seeQueueHasCurrentCount +### seeQueueHasCurrentCount + Check if a queue/tube has a given current number of messages ```php @@ -266,8 +280,9 @@ $I->seeQueueHasCurrentCount('default', 10); * `param string` $queue Queue Name * `param int` $expected Number of messages expected -### seeQueueHasTotalCount +### seeQueueHasTotalCount + Check if a queue/tube has a given total number of messages ```php @@ -279,4 +294,4 @@ $I->seeQueueHasTotalCount('default', 10); * `param string` $queue Queue Name * `param int` $expected Number of messages expected -

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
+

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
diff --git a/docs/modules/REST.md b/docs/modules/REST.md index a3468404bc..6798cf5831 100644 --- a/docs/modules/REST.md +++ b/docs/modules/REST.md @@ -1,5 +1,6 @@ # REST + Module for testing REST WebService. This module can be used either with frameworks or PHPBrowser. @@ -35,10 +36,11 @@ This module requires PHPBrowser or any of Framework modules enabled. Conflicts with SOAP module + ## Actions ### amAWSAuthenticated - + Allows to send REST request using AWS Authorization Only works with PhpBrowser Example @@ -61,16 +63,18 @@ $I->amAWSAuthenticated(); * `param array` $additionalAWSConfig @throws ModuleException -### amBearerAuthenticated +### amBearerAuthenticated + Adds Bearer authentication via access token. * `param` $accessToken * `[Part]` json * `[Part]` xml -### amDigestAuthenticated +### amDigestAuthenticated + Adds Digest authentication via username/password. * `param` $username @@ -78,8 +82,9 @@ Adds Digest authentication via username/password. * `[Part]` json * `[Part]` xml -### amHttpAuthenticated +### amHttpAuthenticated + Adds HTTP authentication via username/password. * `param` $username @@ -87,8 +92,9 @@ Adds HTTP authentication via username/password. * `[Part]` json * `[Part]` xml -### amNTLMAuthenticated +### amNTLMAuthenticated + Adds NTLM authentication via username/password. Requires client to be Guzzle >=6.3.0 Out of scope for functional modules. @@ -106,8 +112,9 @@ $I->amNTLMAuthenticated('jon_snow', 'targaryen'); * `[Part]` json * `[Part]` xml -### deleteHeader +### deleteHeader + Deletes the header with the passed name. Subsequent requests will not have the deleted header in its request. @@ -126,8 +133,9 @@ $I->sendPOST('some-other-page.php'); * `[Part]` json * `[Part]` xml -### dontSeeBinaryResponseEquals +### dontSeeBinaryResponseEquals + Checks if the hash of a binary response is not the same as provided. ```php @@ -142,8 +150,9 @@ Opposite to `seeBinaryResponseEquals` * `[Part]` json * `[Part]` xml -### dontSeeHttpHeader +### dontSeeHttpHeader + Checks over the given HTTP header and (optionally) its value, asserting that are not there @@ -152,8 +161,9 @@ its value, asserting that are not there * `[Part]` json * `[Part]` xml -### dontSeeResponseCodeIs +### dontSeeResponseCodeIs + Checks that response code is not equal to provided value. ```php @@ -168,37 +178,42 @@ $I->dontSeeResponseCodeIs(\Codeception\Util\HttpCode::OK); * `[Part]` xml * `param` $code -### dontSeeResponseContains +### dontSeeResponseContains + Checks whether last response do not contain text. * `param` $text * `[Part]` json * `[Part]` xml -### dontSeeResponseContainsJson +### dontSeeResponseContainsJson + Opposite to seeResponseContainsJson * `[Part]` json * `param array` $json -### dontSeeResponseJsonMatchesJsonPath +### dontSeeResponseJsonMatchesJsonPath + Opposite to seeResponseJsonMatchesJsonPath * `param string` $jsonPath * `[Part]` json -### dontSeeResponseJsonMatchesXpath +### dontSeeResponseJsonMatchesXpath + Opposite to seeResponseJsonMatchesXpath * `param string` $xpath * `[Part]` json -### dontSeeResponseMatchesJsonType +### dontSeeResponseMatchesJsonType + Opposite to `seeResponseMatchesJsonType`. * `[Part]` json @@ -207,8 +222,9 @@ Opposite to `seeResponseMatchesJsonType`. * `param null` $jsonPath optionally set specific path to structure with JsonPath * `Available since` 2.1.3 -### dontSeeXmlResponseEquals +### dontSeeXmlResponseEquals + Checks XML response does not equal to provided XML. Comparison is done by canonicalizing both xml`s. @@ -217,8 +233,9 @@ Parameter can be passed either as XmlBuilder, DOMDocument, DOMNode, XML string, * `param` $xml * `[Part]` xml -### dontSeeXmlResponseIncludes +### dontSeeXmlResponseIncludes + Checks XML response does not include provided XML. Comparison is done by canonicalizing both xml`s. Parameter can be passed either as XmlBuilder, DOMDocument, DOMNode, XML string, or array (if no attributes). @@ -226,8 +243,9 @@ Parameter can be passed either as XmlBuilder, DOMDocument, DOMNode, XML string, * `param` $xml * `[Part]` xml -### dontSeeXmlResponseMatchesXpath +### dontSeeXmlResponseMatchesXpath + Checks whether XML response does not match XPath ```php @@ -237,8 +255,9 @@ $I->dontSeeXmlResponseMatchesXpath('//root/user[@id=1]'); * `[Part]` xml * `param` $xpath -### grabAttributeFromXmlElement +### grabAttributeFromXmlElement + Finds and returns attribute of element. Element is matched by either CSS or XPath @@ -247,16 +266,18 @@ Element is matched by either CSS or XPath * `return` string * `[Part]` xml -### grabDataFromJsonResponse +### grabDataFromJsonResponse + Deprecated since 2.0.9 and removed since 2.1.0 * `param` $path @throws ModuleException @deprecated -### grabDataFromResponseByJsonPath +### grabDataFromResponseByJsonPath + Returns data from the current JSON response using [JSONPath](http://goessner.net/articles/JsonPath/) as selector. JsonPath is XPath equivalent for querying Json structures. Try your JsonPath expressions [online](http://jsonpath.curiousconcept.com/). @@ -280,8 +301,9 @@ $I->sendPUT('/user', array('id' => $firstUserId[0], 'name' => 'davert')); @throws \Exception * `[Part]` json -### grabHttpHeader +### grabHttpHeader + Returns the value of the specified header name * `param` $name @@ -291,8 +313,9 @@ Returns the value of the specified header name * `[Part]` json * `[Part]` xml -### grabResponse +### grabResponse + Returns current response so that it can be used in next scenario steps. Example: @@ -309,8 +332,9 @@ $I->sendPUT('/user', array('id' => $user_id, 'name' => 'davert')); * `[Part]` json * `[Part]` xml -### grabTextContentFromXmlElement +### grabTextContentFromXmlElement + Finds and returns text contents of element. Element is matched by either CSS or XPath @@ -318,8 +342,9 @@ Element is matched by either CSS or XPath * `return` string * `[Part]` xml -### haveHttpHeader +### haveHttpHeader + Sets HTTP header valid for all next requests. Use `deleteHeader` to unset it ```php @@ -334,8 +359,9 @@ $I->haveHttpHeader('Content-Type', 'application/json'); * `[Part]` json * `[Part]` xml -### seeBinaryResponseEquals +### seeBinaryResponseEquals + Checks if the hash of a binary response is exactly the same as provided. Parameter can be passed as any hash string supported by hash(), with an optional second parameter to specify the hash type, which defaults to md5. @@ -370,8 +396,9 @@ $I->seeBinaryResponseEquals(hash("sha256", base64_decode($fileData)), 'sha256'); * `[Part]` json * `[Part]` xml -### seeHttpHeader +### seeHttpHeader + Checks over the given HTTP header and (optionally) its value, asserting that are there @@ -380,8 +407,9 @@ its value, asserting that are there * `[Part]` json * `[Part]` xml -### seeHttpHeaderOnce +### seeHttpHeaderOnce + Checks that http response header is received only once. HTTP RFC2616 allows multiple response headers with the same name. You can check that you didn't accidentally sent the same header twice. @@ -396,8 +424,9 @@ $I->seeHttpHeaderOnce('Cache-Control'); * `[Part]` json * `[Part]` xml -### seeResponseCodeIs +### seeResponseCodeIs + Checks response code equals to provided value. ```php @@ -412,16 +441,18 @@ $I->seeResponseCodeIs(\Codeception\Util\HttpCode::OK); * `[Part]` xml * `param` $code -### seeResponseContains +### seeResponseContains + Checks whether the last response contains text. * `param` $text * `[Part]` json * `[Part]` xml -### seeResponseContainsJson +### seeResponseContainsJson + Checks whether the last JSON response contains provided array. The response is converted to array with json_decode($response, true) Thus, JSON is represented by associative array. @@ -445,30 +476,34 @@ This method recursively checks if one array can be found inside of another. * `param array` $json * `[Part]` json -### seeResponseEquals +### seeResponseEquals + Checks if response is exactly the same as provided. * `[Part]` json * `[Part]` xml * `param` $response -### seeResponseIsJson +### seeResponseIsJson + Checks whether last response was valid JSON. This is done with json_last_error function. * `[Part]` json -### seeResponseIsXml +### seeResponseIsXml + Checks whether last response was valid XML. This is done with libxml_get_last_error function. * `[Part]` xml -### seeResponseJsonMatchesJsonPath +### seeResponseJsonMatchesJsonPath + Checks if json structure in response matches [JsonPath](http://goessner.net/articles/JsonPath/). JsonPath is XPath equivalent for querying Json structures. Try your JsonPath expressions [online](http://jsonpath.curiousconcept.com/). @@ -513,8 +548,9 @@ $I->seeResponseJsonMatchesJsonPath('$.store..price'); * `[Part]` json * `Available since` 2.0.9 -### seeResponseJsonMatchesXpath +### seeResponseJsonMatchesXpath + Checks if json structure in response matches the xpath provided. JSON is not supposed to be checked against XPath, yet it can be converted to xml and used with XPath. This assertion allows you to check the structure of response json. @@ -555,8 +591,9 @@ $I->seeResponseJsonMatchesXpath('/store//price'); * `[Part]` json * `Available since` 2.0.9 -### seeResponseMatchesJsonType +### seeResponseMatchesJsonType + Checks that Json matches provided types. In case you don't know the actual values of JSON data returned you can match them by type. Starts check with a root element. If JSON data is array it will check the first element of an array. @@ -636,8 +673,9 @@ See [JsonType reference](http://codeception.com/docs/reference/JsonType). * `param array` $jsonType * `param string` $jsonPath -### seeXmlResponseEquals +### seeXmlResponseEquals + Checks XML response equals provided XML. Comparison is done by canonicalizing both xml`s. @@ -646,8 +684,9 @@ Parameters can be passed either as DOMDocument, DOMNode, XML string, or array (i * `param` $xml * `[Part]` xml -### seeXmlResponseIncludes +### seeXmlResponseIncludes + Checks XML response includes provided XML. Comparison is done by canonicalizing both xml`s. Parameter can be passed either as XmlBuilder, DOMDocument, DOMNode, XML string, or array (if no attributes). @@ -663,8 +702,9 @@ $I->seeXmlResponseIncludes("1"); * `param` $xml * `[Part]` xml -### seeXmlResponseMatchesXpath +### seeXmlResponseMatchesXpath + Checks whether XML response matches XPath ```php @@ -674,8 +714,9 @@ $I->seeXmlResponseMatchesXpath('//root/user[@id=1]'); * `[Part]` xml * `param` $xpath -### sendDELETE +### sendDELETE + Sends DELETE request to given uri. * `param` $url @@ -684,8 +725,9 @@ Sends DELETE request to given uri. * `[Part]` json * `[Part]` xml -### sendGET +### sendGET + Sends a GET request to given uri. * `param` $url @@ -693,8 +735,9 @@ Sends a GET request to given uri. * `[Part]` json * `[Part]` xml -### sendHEAD +### sendHEAD + Sends a HEAD request to given uri. * `param` $url @@ -702,8 +745,9 @@ Sends a HEAD request to given uri. * `[Part]` json * `[Part]` xml -### sendLINK +### sendLINK + Sends LINK request to given uri. * `param` $url @@ -715,8 +759,9 @@ Sends LINK request to given uri. * `[Part]` json * `[Part]` xml -### sendOPTIONS +### sendOPTIONS + Sends an OPTIONS request to given uri. * `param` $url @@ -724,8 +769,9 @@ Sends an OPTIONS request to given uri. * `[Part]` json * `[Part]` xml -### sendPATCH +### sendPATCH + Sends PATCH request to given uri. * `param` $url @@ -734,8 +780,9 @@ Sends PATCH request to given uri. * `[Part]` json * `[Part]` xml -### sendPOST +### sendPOST + Sends a POST request to given uri. Parameters and files can be provided separately. Example: @@ -768,8 +815,9 @@ $I->sendPOST('/message/24', ['inline' => 0], [ * `[Part]` json * `[Part]` xml -### sendPUT +### sendPUT + Sends PUT request to given uri. * `param` $url @@ -778,8 +826,9 @@ Sends PUT request to given uri. * `[Part]` json * `[Part]` xml -### sendUNLINK +### sendUNLINK + Sends UNLINK request to given uri. * `param` $url @@ -789,8 +838,9 @@ Sends UNLINK request to given uri. * `[Part]` json * `[Part]` xml -### startFollowingRedirects +### startFollowingRedirects + Enables automatic redirects to be followed by the client ```php @@ -801,8 +851,9 @@ $I->startFollowingRedirects(); * `[Part]` xml * `[Part]` json -### stopFollowingRedirects +### stopFollowingRedirects + Prevents automatic redirects to be followed by the client ```php @@ -813,4 +864,4 @@ $I->stopFollowingRedirects(); * `[Part]` xml * `[Part]` json -

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
+

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
diff --git a/docs/modules/Redis.md b/docs/modules/Redis.md index 0495236030..459145e7cb 100644 --- a/docs/modules/Redis.md +++ b/docs/modules/Redis.md @@ -1,5 +1,6 @@ # Redis + This module uses the [Predis](https://github.com/nrk/predis) library to interact with a Redis server. @@ -37,13 +38,14 @@ to interact with a Redis server. ## Actions ### cleanup - + Delete all the keys in the Redis database @throws ModuleException -### dontSeeInRedis +### dontSeeInRedis + Asserts that a key does not exist or, optionally, that it doesn't have the provided $value @@ -74,8 +76,9 @@ $I->dontSeeInRedis('example:hash', ['riri' => true, 'fifi' => 'Dewey', 'loulou' * `param mixed` $value Optional. If specified, also checks the key has this value. Booleans will be converted to 1 and 0 (even inside arrays) -### dontSeeRedisKeyContains +### dontSeeRedisKeyContains + Asserts that a given key does not contain a given item Examples: @@ -111,8 +114,9 @@ specified, the method will also check that the $item has this value/score * `return` bool -### grabFromRedis +### grabFromRedis + Returns the value of a given key Examples: @@ -151,8 +155,9 @@ $I->grabFromRedis('example:hash', 'foo'); @throws ModuleException if the key does not exist -### haveInRedis +### haveInRedis + Creates or modifies keys If $key already exists: @@ -186,8 +191,9 @@ $I->haveInRedis('hash', ['obladi' => 'oblada']); @throws ModuleException -### seeInRedis +### seeInRedis + Asserts that a key exists, and optionally that it has the provided $value Examples: @@ -217,8 +223,9 @@ $I->seeInRedis('example:hash', ['riri' => true, 'fifi' => 'Dewey', 'loulou' => 2 * `param mixed` $value Optional. If specified, also checks the key has this value. Booleans will be converted to 1 and 0 (even inside arrays) -### seeRedisKeyContains +### seeRedisKeyContains + Asserts that a given key contains a given item Examples: @@ -254,8 +261,9 @@ specified, the method will also check that the $item has this value/score * `return` bool -### sendCommandToRedis +### sendCommandToRedis + Sends a command directly to the Redis driver. See documentation at https://github.com/nrk/predis Every argument that follows the $command name will be passed to it. @@ -273,4 +281,5 @@ $I->sendCommandToRedis('flushdb'); * `param string` $command The command name -

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
+ +

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
diff --git a/docs/modules/SOAP.md b/docs/modules/SOAP.md index 126e68a961..806fecb366 100644 --- a/docs/modules/SOAP.md +++ b/docs/modules/SOAP.md @@ -1,5 +1,6 @@ # SOAP + Module for testing SOAP WSDL web services. Send requests and check if response matches the pattern. @@ -29,15 +30,17 @@ If you use PHP SoapServer with framework, try to block call to this method in te * xmlRequest - last SOAP request (DOMDocument) * xmlResponse - last SOAP response (DOMDocument) + ## Actions ### dontSeeSoapResponseContainsStructure - + Opposite to `seeSoapResponseContainsStructure` * `param` $xml -### dontSeeSoapResponseContainsXPath +### dontSeeSoapResponseContainsXPath + Checks XML response doesn't contain XPath locator ``` php @@ -48,8 +51,9 @@ $I->dontSeeSoapResponseContainsXPath('//root/user[@id=1]'); * `param` $xpath -### dontSeeSoapResponseEquals +### dontSeeSoapResponseEquals + Checks XML response equals provided XML. Comparison is done by canonicalizing both xml`s. @@ -57,16 +61,18 @@ Parameter can be passed either as XmlBuilder, DOMDocument, DOMNode, XML string, * `param` $xml -### dontSeeSoapResponseIncludes +### dontSeeSoapResponseIncludes + Checks XML response does not include provided XML. Comparison is done by canonicalizing both xml`s. Parameter can be passed either as XmlBuilder, DOMDocument, DOMNode, XML string, or array (if no attributes). * `param` $xml -### grabAttributeFrom +### grabAttributeFrom + Finds and returns attribute of element. Element is matched by either CSS or XPath @@ -75,8 +81,9 @@ Element is matched by either CSS or XPath * `param` $attribute * `return` string -### grabTextContentFrom +### grabTextContentFrom + Finds and returns text contents of element. Element is matched by either CSS or XPath @@ -84,8 +91,9 @@ Element is matched by either CSS or XPath * `param` $cssOrXPath * `return` string -### haveSoapHeader +### haveSoapHeader + Prepare SOAP header. Receives header name and parameters as array. @@ -111,18 +119,21 @@ Will produce header: * `param` $header * `param array` $params -### seeResponseCodeIs +### seeResponseCodeIs + @deprecated use seeSoapResponseCodeIs instead -### seeSoapResponseCodeIs +### seeSoapResponseCodeIs + Checks response code from server. * `param` $code -### seeSoapResponseContainsStructure +### seeSoapResponseContainsStructure + Checks XML response contains provided structure. Response elements will be compared with XML provided. Only nodeNames are checked to see elements match. @@ -142,8 +153,9 @@ This method does not require path from root to match the structure. * `param` $xml -### seeSoapResponseContainsXPath +### seeSoapResponseContainsXPath + Checks XML response with XPath locator ``` php @@ -154,8 +166,9 @@ $I->seeSoapResponseContainsXPath('//root/user[@id=1]'); * `param` $xpath -### seeSoapResponseEquals +### seeSoapResponseEquals + Checks XML response equals provided XML. Comparison is done by canonicalizing both xml`s. @@ -175,8 +188,9 @@ $I->seeSoapRequestIncludes($dom); * `param` $xml -### seeSoapResponseIncludes +### seeSoapResponseIncludes + Checks XML response includes provided XML. Comparison is done by canonicalizing both xml`s. Parameter can be passed either as XmlBuilder, DOMDocument, DOMNode, XML string, or array (if no attributes). @@ -196,8 +210,9 @@ $I->seeSoapRequestIncludes($dom); * `param` $xml -### sendSoapRequest +### sendSoapRequest + Submits request to endpoint. Requires of api function name and parameters. @@ -217,4 +232,4 @@ $I->sendSoapRequest('UpdateUser', \Codeception\Utils\Soap::request()->user * `param` $request * `param` $body -

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
+

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
diff --git a/docs/modules/Sequence.md b/docs/modules/Sequence.md index 38d1249d93..0e7b08dd19 100644 --- a/docs/modules/Sequence.md +++ b/docs/modules/Sequence.md @@ -1,5 +1,6 @@ # Sequence + Sequence solves data cleanup issue in alternative way. Instead cleaning up the database between tests, you can use generated unique names, that should not conflict. @@ -93,4 +94,4 @@ Sequence: ## Actions -

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
+

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
diff --git a/docs/modules/Silex.md b/docs/modules/Silex.md index 9978810734..55684b8796 100644 --- a/docs/modules/Silex.md +++ b/docs/modules/Silex.md @@ -1,5 +1,6 @@ # Silex + Module for testing Silex applications like you would regularly do with Silex\WebTestCase. This module uses Symfony2 Crawler and HttpKernel to emulate requests and get response. @@ -49,7 +50,7 @@ Class Silex ### _findElements *hidden API method, expected to be used from Helper classes* - + Locates element using available Codeception locator types: * XPath @@ -73,10 +74,11 @@ PhpBrowser and Framework modules return `Symfony\Component\DomCrawler\Crawler` i * `param` $locator * `return` array of interactive elements + ### _getResponseContent *hidden API method, expected to be used from Helper classes* - + Returns content of the last response Use it in Helpers when you want to retrieve response of request performed by another module. @@ -93,10 +95,11 @@ public function seeResponseContains($text) * `return` string @throws ModuleException + ### _loadPage *hidden API method, expected to be used from Helper classes* - + Opens a page with arbitrary request parameters. Useful for testing multi-step forms on a specific step. @@ -116,10 +119,11 @@ public function openCheckoutFormStep2($orderId) { * `param array` $server * `param null` $content + ### _request *hidden API method, expected to be used from Helper classes* - + Send custom request to a backend using method, uri, parameters, etc. Use it in Helpers to create special request actions, like accessing API Returns a string with response body. @@ -147,10 +151,11 @@ To load arbitrary page for interaction, use `_loadPage` method. @throws ExternalUrlException @see `_loadPage` + ### _savePageSource *hidden API method, expected to be used from Helper classes* - + Saves page source of to a file ```php @@ -158,15 +163,17 @@ $this->getModule('Silex')->_savePageSource(codecept_output_dir().'page.html'); ``` * `param` $filename -### amHttpAuthenticated +### amHttpAuthenticated + Authenticates user for HTTP_AUTH * `param` $username * `param` $password -### amOnPage +### amOnPage + Opens the page for the given relative URI. ``` php @@ -179,8 +186,9 @@ $I->amOnPage('/register'); * `param string` $page -### attachFile +### attachFile + Attaches a file relative to the Codeception `_data` directory to the given file upload field. ``` php @@ -193,8 +201,9 @@ $I->attachFile('input[@type="file"]', 'prices.xls'); * `param` $field * `param` $filename -### checkOption +### checkOption + Ticks a checkbox. For radio buttons, use the `selectOption` method instead. ``` php @@ -205,8 +214,9 @@ $I->checkOption('#agree'); * `param` $option -### click +### click + Perform a click on a link or a button, given by a locator. If a fuzzy locator is given, the page will be searched for a button, link, or image matching the locator string. For buttons, the "value" attribute, "name" attribute, and inner text are searched. @@ -237,8 +247,9 @@ $I->click(['link' => 'Login']); * `param` $link * `param` $context -### deleteHeader +### deleteHeader + Deletes the header with the passed name. Subsequent requests will not have the deleted header in its request. @@ -255,8 +266,9 @@ $I->amOnPage('some-other-page.php'); * `param string` $name the name of the header to delete. -### dontSee +### dontSee + Checks that the current page doesn't contain the text specified (case insensitive). Give a locator as the second parameter to match a specific region. @@ -285,8 +297,9 @@ For checking the raw source code, use `seeInSource()`. * `param string` $text * `param string` $selector optional -### dontSeeCheckboxIsChecked +### dontSeeCheckboxIsChecked + Check that the specified checkbox is unchecked. ``` php @@ -298,8 +311,9 @@ $I->seeCheckboxIsChecked('#signup_form input[type=checkbox]'); // I suppose user * `param` $checkbox -### dontSeeCookie +### dontSeeCookie + Checks that there isn't a cookie with the given name. You can set additional cookie params like `domain`, `path` as array passed in last argument. @@ -307,8 +321,9 @@ You can set additional cookie params like `domain`, `path` as array passed in la * `param array` $params -### dontSeeCurrentUrlEquals +### dontSeeCurrentUrlEquals + Checks that the current URL doesn't equal the given string. Unlike `dontSeeInCurrentUrl`, this only matches the full URL. @@ -321,8 +336,9 @@ $I->dontSeeCurrentUrlEquals('/'); * `param string` $uri -### dontSeeCurrentUrlMatches +### dontSeeCurrentUrlMatches + Checks that current url doesn't match the given regular expression. ``` php @@ -334,8 +350,9 @@ $I->dontSeeCurrentUrlMatches('~$/users/(\d+)~'); * `param string` $uri -### dontSeeElement +### dontSeeElement + Checks that the given element is invisible or not present on the page. You can also specify expected attributes of this element. @@ -351,8 +368,9 @@ $I->dontSeeElement('input', ['value' => '123456']); * `param` $selector * `param array` $attributes -### dontSeeInCurrentUrl +### dontSeeInCurrentUrl + Checks that the current URI doesn't contain the given string. ``` php @@ -363,8 +381,9 @@ $I->dontSeeInCurrentUrl('/users/'); * `param string` $uri -### dontSeeInField +### dontSeeInField + Checks that an input field or textarea doesn't contain the given value. For fuzzy locators, the field is matched by label text, CSS and XPath. @@ -382,8 +401,9 @@ $I->dontSeeInField(['name' => 'search'], 'Search'); * `param` $field * `param` $value -### dontSeeInFormFields +### dontSeeInFormFields + Checks if the array of form parameters (name => value) are not set on the form matched with the passed selector. @@ -424,8 +444,9 @@ $I->dontSeeInFormFields('#form-id', [ * `param` $formSelector * `param` $params -### dontSeeInSource +### dontSeeInSource + Checks that the current page contains the given string in its raw source code. @@ -436,14 +457,17 @@ $I->dontSeeInSource('

Green eggs & ham

'); * `param` $raw -### dontSeeInTitle +### dontSeeInTitle + Checks that the page title does not contain the given string. * `param` $title -### dontSeeLink + +### dontSeeLink + Checks that the page doesn't contain a link with the given string. If the second parameter is given, only links with a matching "href" attribute will be checked. @@ -457,8 +481,9 @@ $I->dontSeeLink('Checkout now', '/store/cart.php'); * `param string` $text * `param string` $url optional -### dontSeeOptionIsSelected +### dontSeeOptionIsSelected + Checks that the given option is not selected. ``` php @@ -470,8 +495,10 @@ $I->dontSeeOptionIsSelected('#form input[name=payment]', 'Visa'); * `param` $selector * `param` $optionText -### dontSeeResponseCodeIs + +### dontSeeResponseCodeIs + Checks that response code is equal to value provided. ```php @@ -483,8 +510,9 @@ $I->dontSeeResponseCodeIs(\Codeception\Util\HttpCode::OK); ``` * `param` $code -### fillField +### fillField + Fills a text field or textarea with the given string. ``` php @@ -497,14 +525,16 @@ $I->fillField(['name' => 'email'], 'jon@mail.com'); * `param` $field * `param` $value -### getInternalDomains +### getInternalDomains + Returns a list of recognized domain names * `return` array -### grabAttributeFrom +### grabAttributeFrom + Grabs the value of the given attribute value from the given element. Fails if element is not found. @@ -517,8 +547,10 @@ $I->grabAttributeFrom('#tooltip', 'title'); * `param` $cssOrXpath * `param` $attribute -### grabCookie + +### grabCookie + Grabs a cookie value. You can set additional cookie params like `domain`, `path` in array passed as last argument. @@ -526,8 +558,9 @@ You can set additional cookie params like `domain`, `path` in array passed as la * `param array` $params -### grabFromCurrentUrl +### grabFromCurrentUrl + Executes the given regular expression against the current URI and returns the first capturing group. If no parameters are provided, the full URI is returned. @@ -540,8 +573,10 @@ $uri = $I->grabFromCurrentUrl(); * `param string` $uri optional -### grabMultiple + +### grabMultiple + Grabs either the text content, or attribute values, of nodes matched by $cssOrXpath and returns them as an array. @@ -565,16 +600,18 @@ $aLinks = $I->grabMultiple('a', 'href'); * `param` $attribute * `return` string[] -### grabPageSource +### grabPageSource + Grabs current page source code. @throws ModuleException if no page was opened. * `return` string Current page source code. -### grabService +### grabService + Return an instance of a class from the Container. Example @@ -586,8 +623,9 @@ $I->grabService('session'); * `param` string $service -### grabTextFrom +### grabTextFrom + Finds and returns the text contents of the given element. If a fuzzy locator is used, the element is found using CSS, XPath, and by matching the full page source by regular expression. @@ -602,14 +640,17 @@ $value = $I->grabTextFrom('~haveHttpHeader('Client_Id', 'Codeception'); * `param string` $value the value to set it to for subsequent requests -### moveBack +### moveBack + Moves back in history. * `param int` $numberOfSteps (default value 1) -### resetCookie +### resetCookie + Unsets cookie with the given name. You can set additional cookie params like `domain`, `path` in array passed as last argument. @@ -651,8 +694,9 @@ You can set additional cookie params like `domain`, `path` in array passed as la * `param array` $params -### see +### see + Checks that the current page contains the given string (case insensitive). You can specify a specific HTML element (via CSS or XPath) as the second @@ -683,8 +727,9 @@ For checking the raw source code, use `seeInSource()`. * `param string` $text * `param string` $selector optional -### seeCheckboxIsChecked +### seeCheckboxIsChecked + Checks that the specified checkbox is checked. ``` php @@ -697,8 +742,9 @@ $I->seeCheckboxIsChecked('//form/input[@type=checkbox and @name=agree]'); * `param` $checkbox -### seeCookie +### seeCookie + Checks that a cookie with the given name is set. You can set additional cookie params like `domain`, `path` as array passed in last argument. @@ -711,8 +757,9 @@ $I->seeCookie('PHPSESSID'); * `param` $cookie * `param array` $params -### seeCurrentUrlEquals +### seeCurrentUrlEquals + Checks that the current URL is equal to the given string. Unlike `seeInCurrentUrl`, this only matches the full URL. @@ -725,8 +772,9 @@ $I->seeCurrentUrlEquals('/'); * `param string` $uri -### seeCurrentUrlMatches +### seeCurrentUrlMatches + Checks that the current URL matches the given regular expression. ``` php @@ -738,8 +786,9 @@ $I->seeCurrentUrlMatches('~$/users/(\d+)~'); * `param string` $uri -### seeElement +### seeElement + Checks that the given element exists on the page and is visible. You can also specify expected attributes of this element. @@ -759,8 +808,9 @@ $I->seeElement(['css' => 'form input'], ['name' => 'login']); * `param array` $attributes @return -### seeInCurrentUrl +### seeInCurrentUrl + Checks that current URI contains the given string. ``` php @@ -774,8 +824,9 @@ $I->seeInCurrentUrl('/users/'); * `param string` $uri -### seeInField +### seeInField + Checks that the given input field or textarea *equals* (i.e. not just contains) the given value. Fields are matched by label text, the "name" attribute, CSS, or XPath. @@ -793,8 +844,9 @@ $I->seeInField(['name' => 'search'], 'Search'); * `param` $field * `param` $value -### seeInFormFields +### seeInFormFields + Checks if the array of form parameters (name => value) are set on the form matched with the passed selector. @@ -855,8 +907,9 @@ $I->seeInFormFields('//form[@id=my-form]', $form); * `param` $formSelector * `param` $params -### seeInSource +### seeInSource + Checks that the current page contains the given string in its raw source code. @@ -867,8 +920,9 @@ $I->seeInSource('

Green eggs & ham

'); * `param` $raw -### seeInTitle +### seeInTitle + Checks that the page title contains the given string. ``` php @@ -879,8 +933,10 @@ $I->seeInTitle('Blog - Post #1'); * `param` $title -### seeLink + +### seeLink + Checks that there's a link with the specified text. Give a full URL as the second parameter to match links with that exact URL. @@ -894,8 +950,9 @@ $I->seeLink('Logout','/logout'); // matches Logout * `param string` $text * `param string` $url optional -### seeNumberOfElements +### seeNumberOfElements + Checks that there are a certain number of elements matched by the given locator on the page. ``` php @@ -907,8 +964,9 @@ $I->seeNumberOfElements('tr', [0,10]); // between 0 and 10 elements * `param` $selector * `param mixed` $expected int or int[] -### seeOptionIsSelected +### seeOptionIsSelected + Checks that the given option is selected. ``` php @@ -920,12 +978,15 @@ $I->seeOptionIsSelected('#form input[name=payment]', 'Visa'); * `param` $selector * `param` $optionText -### seePageNotFound + +### seePageNotFound + Asserts that current page has 404 response status code. -### seeResponseCodeIs +### seeResponseCodeIs + Checks that response code is equal to value provided. ```php @@ -938,8 +999,9 @@ $I->seeResponseCodeIs(\Codeception\Util\HttpCode::OK); * `param` $code -### selectOption +### selectOption + Selects an option in a select tag or in radio button group. ``` php @@ -970,8 +1032,9 @@ $I->selectOption('Which OS do you use?', array('value' => 'windows')); // Only s * `param` $select * `param` $option -### sendAjaxGetRequest +### sendAjaxGetRequest + If your page triggers an ajax request, you can perform it manually. This action sends a GET ajax request with specified params. @@ -980,8 +1043,9 @@ See ->sendAjaxPostRequest for examples. * `param` $uri * `param` $params -### sendAjaxPostRequest +### sendAjaxPostRequest + If your page triggers an ajax request, you can perform it manually. This action sends a POST ajax request with specified params. Additional params can be passed as array. @@ -1001,8 +1065,9 @@ $I->sendAjaxGetRequest('/updateSettings', array('notifications' => true)); // GE * `param` $uri * `param` $params -### sendAjaxRequest +### sendAjaxRequest + If your page triggers an ajax request, you can perform it manually. This action sends an ajax request with specified method and params. @@ -1020,8 +1085,9 @@ $I->sendAjaxRequest('PUT', '/posts/7', array('title' => 'new title')); * `param` $uri * `param` $params -### setCookie +### setCookie + Sets a cookie with the given name and value. You can set additional cookie params like `domain`, `path`, `expires`, `secure` in array passed as last argument. @@ -1035,8 +1101,10 @@ $I->setCookie('PHPSESSID', 'el4ukv0kqbvoirg7nkp4dncpk3'); * `param` $val * `param array` $params -### submitForm + +### submitForm + Submits the given form on the page, with the given form values. Pass the form field's values as an array in the second parameter. @@ -1207,8 +1275,9 @@ $I->submitForm('#my-form', [ * `param` $params * `param` $button -### switchToIframe +### switchToIframe + Switch to iframe or frame on the page. Example: @@ -1224,8 +1293,9 @@ $I->switchToIframe("another_frame"); * `param string` $name -### uncheckOption +### uncheckOption + Unticks a checkbox. ``` php @@ -1236,4 +1306,4 @@ $I->uncheckOption('#notify'); * `param` $option -

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
+

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
diff --git a/docs/modules/Symfony.md b/docs/modules/Symfony.md index cee9cf5998..607fe2677b 100644 --- a/docs/modules/Symfony.md +++ b/docs/modules/Symfony.md @@ -1,5 +1,6 @@ # Symfony + This module uses Symfony Crawler and HttpKernel to emulate requests and test response. ## Demo Project @@ -25,6 +26,7 @@ This module uses Symfony Crawler and HttpKernel to emulate requests and test res app_path: 'src' environment: 'test' + ### Symfony 3.x * app_path: 'app' - specify custom path to your app dir, where the kernel interface is located. @@ -44,6 +46,7 @@ This module uses Symfony Crawler and HttpKernel to emulate requests and test res var_path: 'var' environment: 'local_test' + ### Symfony 2.x * app_path: 'app' - specify custom path to your app dir, where bootstrap cache and kernel interface is located. @@ -86,12 +89,13 @@ modules: browser: phantomjs ``` + ## Actions ### _findElements *hidden API method, expected to be used from Helper classes* - + Locates element using available Codeception locator types: * XPath @@ -115,10 +119,11 @@ PhpBrowser and Framework modules return `Symfony\Component\DomCrawler\Crawler` i * `param` $locator * `return` array of interactive elements + ### _getResponseContent *hidden API method, expected to be used from Helper classes* - + Returns content of the last response Use it in Helpers when you want to retrieve response of request performed by another module. @@ -135,10 +140,11 @@ public function seeResponseContains($text) * `return` string @throws ModuleException + ### _loadPage *hidden API method, expected to be used from Helper classes* - + Opens a page with arbitrary request parameters. Useful for testing multi-step forms on a specific step. @@ -158,10 +164,11 @@ public function openCheckoutFormStep2($orderId) { * `param array` $server * `param null` $content + ### _request *hidden API method, expected to be used from Helper classes* - + Send custom request to a backend using method, uri, parameters, etc. Use it in Helpers to create special request actions, like accessing API Returns a string with response body. @@ -189,10 +196,11 @@ To load arbitrary page for interaction, use `_loadPage` method. @throws ExternalUrlException @see `_loadPage` + ### _savePageSource *hidden API method, expected to be used from Helper classes* - + Saves page source of to a file ```php @@ -200,15 +208,17 @@ $this->getModule('Symfony')->_savePageSource(codecept_output_dir().'page.html'); ``` * `param` $filename -### amHttpAuthenticated +### amHttpAuthenticated + Authenticates user for HTTP_AUTH * `param` $username * `param` $password -### amOnPage +### amOnPage + Opens the page for the given relative URI. ``` php @@ -221,8 +231,9 @@ $I->amOnPage('/register'); * `param string` $page -### amOnRoute +### amOnRoute + Opens web page using route name and parameters. ``` php @@ -235,8 +246,9 @@ $I->amOnRoute('posts.show', array('id' => 34)); * `param` $routeName * `param array` $params -### attachFile +### attachFile + Attaches a file relative to the Codeception `_data` directory to the given file upload field. ``` php @@ -249,8 +261,9 @@ $I->attachFile('input[@type="file"]', 'prices.xls'); * `param` $field * `param` $filename -### checkOption +### checkOption + Ticks a checkbox. For radio buttons, use the `selectOption` method instead. ``` php @@ -261,8 +274,9 @@ $I->checkOption('#agree'); * `param` $option -### click +### click + Perform a click on a link or a button, given by a locator. If a fuzzy locator is given, the page will be searched for a button, link, or image matching the locator string. For buttons, the "value" attribute, "name" attribute, and inner text are searched. @@ -293,8 +307,9 @@ $I->click(['link' => 'Login']); * `param` $link * `param` $context -### deleteHeader +### deleteHeader + Deletes the header with the passed name. Subsequent requests will not have the deleted header in its request. @@ -311,8 +326,9 @@ $I->amOnPage('some-other-page.php'); * `param string` $name the name of the header to delete. -### dontSee +### dontSee + Checks that the current page doesn't contain the text specified (case insensitive). Give a locator as the second parameter to match a specific region. @@ -341,8 +357,9 @@ For checking the raw source code, use `seeInSource()`. * `param string` $text * `param string` $selector optional -### dontSeeCheckboxIsChecked +### dontSeeCheckboxIsChecked + Check that the specified checkbox is unchecked. ``` php @@ -354,8 +371,9 @@ $I->seeCheckboxIsChecked('#signup_form input[type=checkbox]'); // I suppose user * `param` $checkbox -### dontSeeCookie +### dontSeeCookie + Checks that there isn't a cookie with the given name. You can set additional cookie params like `domain`, `path` as array passed in last argument. @@ -363,8 +381,9 @@ You can set additional cookie params like `domain`, `path` as array passed in la * `param array` $params -### dontSeeCurrentUrlEquals +### dontSeeCurrentUrlEquals + Checks that the current URL doesn't equal the given string. Unlike `dontSeeInCurrentUrl`, this only matches the full URL. @@ -377,8 +396,9 @@ $I->dontSeeCurrentUrlEquals('/'); * `param string` $uri -### dontSeeCurrentUrlMatches +### dontSeeCurrentUrlMatches + Checks that current url doesn't match the given regular expression. ``` php @@ -390,8 +410,9 @@ $I->dontSeeCurrentUrlMatches('~$/users/(\d+)~'); * `param string` $uri -### dontSeeElement +### dontSeeElement + Checks that the given element is invisible or not present on the page. You can also specify expected attributes of this element. @@ -407,8 +428,9 @@ $I->dontSeeElement('input', ['value' => '123456']); * `param` $selector * `param array` $attributes -### dontSeeInCurrentUrl +### dontSeeInCurrentUrl + Checks that the current URI doesn't contain the given string. ``` php @@ -419,8 +441,9 @@ $I->dontSeeInCurrentUrl('/users/'); * `param string` $uri -### dontSeeInField +### dontSeeInField + Checks that an input field or textarea doesn't contain the given value. For fuzzy locators, the field is matched by label text, CSS and XPath. @@ -438,8 +461,9 @@ $I->dontSeeInField(['name' => 'search'], 'Search'); * `param` $field * `param` $value -### dontSeeInFormFields +### dontSeeInFormFields + Checks if the array of form parameters (name => value) are not set on the form matched with the passed selector. @@ -480,8 +504,9 @@ $I->dontSeeInFormFields('#form-id', [ * `param` $formSelector * `param` $params -### dontSeeInSource +### dontSeeInSource + Checks that the current page contains the given string in its raw source code. @@ -492,14 +517,17 @@ $I->dontSeeInSource('

Green eggs & ham

'); * `param` $raw -### dontSeeInTitle +### dontSeeInTitle + Checks that the page title does not contain the given string. * `param` $title -### dontSeeLink + +### dontSeeLink + Checks that the page doesn't contain a link with the given string. If the second parameter is given, only links with a matching "href" attribute will be checked. @@ -513,8 +541,9 @@ $I->dontSeeLink('Checkout now', '/store/cart.php'); * `param string` $text * `param string` $url optional -### dontSeeOptionIsSelected +### dontSeeOptionIsSelected + Checks that the given option is not selected. ``` php @@ -526,8 +555,10 @@ $I->dontSeeOptionIsSelected('#form input[name=payment]', 'Visa'); * `param` $selector * `param` $optionText -### dontSeeResponseCodeIs + +### dontSeeResponseCodeIs + Checks that response code is equal to value provided. ```php @@ -539,8 +570,9 @@ $I->dontSeeResponseCodeIs(\Codeception\Util\HttpCode::OK); ``` * `param` $code -### fillField +### fillField + Fills a text field or textarea with the given string. ``` php @@ -553,8 +585,9 @@ $I->fillField(['name' => 'email'], 'jon@mail.com'); * `param` $field * `param` $value -### grabAttributeFrom +### grabAttributeFrom + Grabs the value of the given attribute value from the given element. Fails if element is not found. @@ -567,8 +600,10 @@ $I->grabAttributeFrom('#tooltip', 'title'); * `param` $cssOrXpath * `param` $attribute -### grabCookie + +### grabCookie + Grabs a cookie value. You can set additional cookie params like `domain`, `path` in array passed as last argument. @@ -576,8 +611,9 @@ You can set additional cookie params like `domain`, `path` in array passed as la * `param array` $params -### grabFromCurrentUrl +### grabFromCurrentUrl + Executes the given regular expression against the current URI and returns the first capturing group. If no parameters are provided, the full URI is returned. @@ -590,8 +626,10 @@ $uri = $I->grabFromCurrentUrl(); * `param string` $uri optional -### grabMultiple + +### grabMultiple + Grabs either the text content, or attribute values, of nodes matched by $cssOrXpath and returns them as an array. @@ -615,16 +653,18 @@ $aLinks = $I->grabMultiple('a', 'href'); * `param` $attribute * `return` string[] -### grabPageSource +### grabPageSource + Grabs current page source code. @throws ModuleException if no page was opened. * `return` string Current page source code. -### grabService +### grabService + Grabs a service from Symfony DIC container. Recommended to use for unit testing. @@ -637,8 +677,9 @@ $em = $I->grabService('doctrine'); * `param` $service * `[Part]` services -### grabServiceFromContainer +### grabServiceFromContainer + Grabs a service from Symfony DIC container. Recommended to use for unit testing. @@ -652,8 +693,9 @@ $em = $I->grabServiceFromContainer('doctrine'); * `[Part]` services @deprecated Use grabService instead -### grabTextFrom +### grabTextFrom + Finds and returns the text contents of the given element. If a fuzzy locator is used, the element is found using CSS, XPath, and by matching the full page source by regular expression. @@ -668,14 +710,17 @@ $value = $I->grabTextFrom('~haveHttpHeader('Client_Id', 'Codeception'); * `param string` $value the value to set it to for subsequent requests -### invalidateCachedRouter +### invalidateCachedRouter + Invalidate previously cached routes. -### moveBack +### moveBack + Moves back in history. * `param int` $numberOfSteps (default value 1) -### persistService +### persistService + Get service $serviceName and add it to the lists of persistent services. If $isPermanent then service becomes persistent between tests * `param string` $serviceName * `param boolean` $isPermanent -### rebootClientKernel +### rebootClientKernel + Reboot client's kernel. Can be used to manually reboot kernel when 'rebootable_client' => false @@ -738,8 +787,10 @@ perform other requests ?> ``` -### resetCookie + +### resetCookie + Unsets cookie with the given name. You can set additional cookie params like `domain`, `path` in array passed as last argument. @@ -747,8 +798,9 @@ You can set additional cookie params like `domain`, `path` in array passed as la * `param array` $params -### see +### see + Checks that the current page contains the given string (case insensitive). You can specify a specific HTML element (via CSS or XPath) as the second @@ -779,8 +831,9 @@ For checking the raw source code, use `seeInSource()`. * `param string` $text * `param string` $selector optional -### seeCheckboxIsChecked +### seeCheckboxIsChecked + Checks that the specified checkbox is checked. ``` php @@ -793,8 +846,9 @@ $I->seeCheckboxIsChecked('//form/input[@type=checkbox and @name=agree]'); * `param` $checkbox -### seeCookie +### seeCookie + Checks that a cookie with the given name is set. You can set additional cookie params like `domain`, `path` as array passed in last argument. @@ -807,8 +861,9 @@ $I->seeCookie('PHPSESSID'); * `param` $cookie * `param array` $params -### seeCurrentRouteIs +### seeCurrentRouteIs + Checks that current url matches route. ``` php @@ -821,8 +876,9 @@ $I->seeCurrentRouteIs('posts.show', array('id' => 8)); * `param` $routeName * `param array` $params -### seeCurrentUrlEquals +### seeCurrentUrlEquals + Checks that the current URL is equal to the given string. Unlike `seeInCurrentUrl`, this only matches the full URL. @@ -835,8 +891,9 @@ $I->seeCurrentUrlEquals('/'); * `param string` $uri -### seeCurrentUrlMatches +### seeCurrentUrlMatches + Checks that the current URL matches the given regular expression. ``` php @@ -848,8 +905,9 @@ $I->seeCurrentUrlMatches('~$/users/(\d+)~'); * `param string` $uri -### seeElement +### seeElement + Checks that the given element exists on the page and is visible. You can also specify expected attributes of this element. @@ -869,14 +927,16 @@ $I->seeElement(['css' => 'form input'], ['name' => 'login']); * `param array` $attributes @return -### seeEmailIsSent +### seeEmailIsSent + Checks if any email were sent by last request @throws \LogicException -### seeInCurrentRoute +### seeInCurrentRoute + Checks that current url matches route. Unlike seeCurrentRouteIs, this can matches without exact route parameters @@ -888,8 +948,9 @@ $I->seeCurrentRouteMatches('my_blog_pages'); * `param` $routeName -### seeInCurrentUrl +### seeInCurrentUrl + Checks that current URI contains the given string. ``` php @@ -903,8 +964,9 @@ $I->seeInCurrentUrl('/users/'); * `param string` $uri -### seeInField +### seeInField + Checks that the given input field or textarea *equals* (i.e. not just contains) the given value. Fields are matched by label text, the "name" attribute, CSS, or XPath. @@ -922,8 +984,9 @@ $I->seeInField(['name' => 'search'], 'Search'); * `param` $field * `param` $value -### seeInFormFields +### seeInFormFields + Checks if the array of form parameters (name => value) are set on the form matched with the passed selector. @@ -984,8 +1047,9 @@ $I->seeInFormFields('//form[@id=my-form]', $form); * `param` $formSelector * `param` $params -### seeInSource +### seeInSource + Checks that the current page contains the given string in its raw source code. @@ -996,8 +1060,9 @@ $I->seeInSource('

Green eggs & ham

'); * `param` $raw -### seeInTitle +### seeInTitle + Checks that the page title contains the given string. ``` php @@ -1008,8 +1073,10 @@ $I->seeInTitle('Blog - Post #1'); * `param` $title -### seeLink + +### seeLink + Checks that there's a link with the specified text. Give a full URL as the second parameter to match links with that exact URL. @@ -1023,8 +1090,9 @@ $I->seeLink('Logout','/logout'); // matches Logout * `param string` $text * `param string` $url optional -### seeNumberOfElements +### seeNumberOfElements + Checks that there are a certain number of elements matched by the given locator on the page. ``` php @@ -1036,8 +1104,9 @@ $I->seeNumberOfElements('tr', [0,10]); // between 0 and 10 elements * `param` $selector * `param mixed` $expected int or int[] -### seeOptionIsSelected +### seeOptionIsSelected + Checks that the given option is selected. ``` php @@ -1049,12 +1118,15 @@ $I->seeOptionIsSelected('#form input[name=payment]', 'Visa'); * `param` $selector * `param` $optionText -### seePageNotFound + +### seePageNotFound + Asserts that current page has 404 response status code. -### seeResponseCodeIs +### seeResponseCodeIs + Checks that response code is equal to value provided. ```php @@ -1067,8 +1139,9 @@ $I->seeResponseCodeIs(\Codeception\Util\HttpCode::OK); * `param` $code -### selectOption +### selectOption + Selects an option in a select tag or in radio button group. ``` php @@ -1099,8 +1172,9 @@ $I->selectOption('Which OS do you use?', array('value' => 'windows')); // Only s * `param` $select * `param` $option -### sendAjaxGetRequest +### sendAjaxGetRequest + If your page triggers an ajax request, you can perform it manually. This action sends a GET ajax request with specified params. @@ -1109,8 +1183,9 @@ See ->sendAjaxPostRequest for examples. * `param` $uri * `param` $params -### sendAjaxPostRequest +### sendAjaxPostRequest + If your page triggers an ajax request, you can perform it manually. This action sends a POST ajax request with specified params. Additional params can be passed as array. @@ -1130,8 +1205,9 @@ $I->sendAjaxGetRequest('/updateSettings', array('notifications' => true)); // GE * `param` $uri * `param` $params -### sendAjaxRequest +### sendAjaxRequest + If your page triggers an ajax request, you can perform it manually. This action sends an ajax request with specified method and params. @@ -1149,8 +1225,9 @@ $I->sendAjaxRequest('PUT', '/posts/7', array('title' => 'new title')); * `param` $uri * `param` $params -### setCookie +### setCookie + Sets a cookie with the given name and value. You can set additional cookie params like `domain`, `path`, `expires`, `secure` in array passed as last argument. @@ -1164,8 +1241,10 @@ $I->setCookie('PHPSESSID', 'el4ukv0kqbvoirg7nkp4dncpk3'); * `param` $val * `param array` $params -### submitForm + +### submitForm + Submits the given form on the page, with the given form values. Pass the form field's values as an array in the second parameter. @@ -1336,8 +1415,9 @@ $I->submitForm('#my-form', [ * `param` $params * `param` $button -### switchToIframe +### switchToIframe + Switch to iframe or frame on the page. Example: @@ -1353,8 +1433,9 @@ $I->switchToIframe("another_frame"); * `param string` $name -### uncheckOption +### uncheckOption + Unticks a checkbox. ``` php @@ -1365,10 +1446,11 @@ $I->uncheckOption('#notify'); * `param` $option -### unpersistService +### unpersistService + Remove service $serviceName from the lists of persistent services. * `param string` $serviceName -

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
+

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
diff --git a/docs/modules/WebDriver.md b/docs/modules/WebDriver.md index 1bb791cb27..7faf738973 100644 --- a/docs/modules/WebDriver.md +++ b/docs/modules/WebDriver.md @@ -1,5 +1,6 @@ # WebDriver + New generation Selenium WebDriver module. ## Local Testing @@ -49,6 +50,7 @@ To run tests in Chrome browser you may connect to ChromeDriver directly, without Additional [Chrome options](https://sites.google.com/a/chromium.org/chromedriver/capabilities) can be set in `chromeOptions` capabilities. + ### PhantomJS PhantomJS is a [headless browser](https://en.wikipedia.org/wiki/Headless_browser) alternative to Selenium Server that implements @@ -227,20 +229,22 @@ If speed is a concern, it's recommended you stick with explicitly specifying the $this->getModule('WebDriver')->webDriver->getKeyboard()->sendKeys('hello, webdriver'); ``` + ## Actions ### _backupSession *hidden API method, expected to be used from Helper classes* - + Returns current WebDriver session for saving * `return` RemoteWebDriver + ### _capabilities *hidden API method, expected to be used from Helper classes* - + Change capabilities of WebDriver. Should be executed before starting a new browser session. This method expects a function to be passed which returns array or [WebDriver Desired Capabilities](https://github.com/facebook/php-webdriver/blob/community/lib/Remote/DesiredCapabilities.php) object. Additional [Chrome options](https://github.com/facebook/php-webdriver/wiki/ChromeOptions) (like adding extensions) can be passed as well. @@ -283,10 +287,11 @@ In this case, please ensure that `\Helper\Acceptance` is loaded before WebDriver * `param \Closure` $capabilityFunction + ### _closeSession *hidden API method, expected to be used from Helper classes* - + Manually closes current WebDriver session. ```php @@ -300,10 +305,11 @@ $this->getModule('WebDriver')->_closeSession($webDriver); * `param` $webDriver (optional) a specific webdriver session instance + ### _findClickable *hidden API method, expected to be used from Helper classes* - + Locates a clickable element. Use it in Helpers or GroupObject or Extension classes: @@ -325,10 +331,11 @@ $el = $module->_findClickable($topBar, 'Click Me'); * `param` $link a link text or locator to click * `return` WebDriverElement + ### _findElements *hidden API method, expected to be used from Helper classes* - + Locates element using available Codeception locator types: * XPath @@ -352,26 +359,29 @@ PhpBrowser and Framework modules return `Symfony\Component\DomCrawler\Crawler` i * `param` $locator * `return` array of interactive elements + ### _getCurrentUri *hidden API method, expected to be used from Helper classes* - + Uri of currently opened page. * `return` string @throws ModuleException + ### _getUrl *hidden API method, expected to be used from Helper classes* - + Returns URL of a host. @throws ModuleConfigException + ### _initializeSession *hidden API method, expected to be used from Helper classes* - + Manually starts a new browser session. ```php @@ -379,18 +389,21 @@ Manually starts a new browser session. $this->getModule('WebDriver')->_initializeSession(); ``` + + ### _loadSession *hidden API method, expected to be used from Helper classes* - + Loads current RemoteWebDriver instance as a session * `param RemoteWebDriver` $session + ### _restart *hidden API method, expected to be used from Helper classes* - + Restarts a web browser. Can be used with `_reconfigure` to open browser with different configuration @@ -403,17 +416,19 @@ $this->getModule('WebDriver')->_restart(['browser' => $browser]); // reconfigure * `param array` $config + ### _savePageSource *hidden API method, expected to be used from Helper classes* - + Saves HTML source of a page to a file * `param` $filename + ### _saveScreenshot *hidden API method, expected to be used from Helper classes* - + Saves screenshot of current page to a file ```php @@ -421,14 +436,16 @@ $this->getModule('WebDriver')->_saveScreenshot(codecept_output_dir().'screenshot ``` * `param` $filename -### acceptPopup +### acceptPopup + Accepts the active JavaScript native popup window, as created by `window.alert`|`window.confirm`|`window.prompt`. Don't confuse popups with modal windows, as created by [various libraries](http://jster.net/category/windows-modals-popups). -### amOnPage +### amOnPage + Opens the page for the given relative URI. ``` php @@ -441,8 +458,9 @@ $I->amOnPage('/register'); * `param string` $page -### amOnSubdomain +### amOnSubdomain + Changes the subdomain for the 'url' configuration parameter. Does not open a page; use `amOnPage` for that. @@ -460,8 +478,10 @@ $I->amOnPage('/'); * `param` $subdomain -### amOnUrl + +### amOnUrl + Open web page at the given absolute URL and sets its hostname as the base host. ``` php @@ -471,8 +491,9 @@ $I->amOnPage('/quickstart'); // moves to http://codeception.com/quickstart ?> ``` -### appendField +### appendField + Append the given text to the given element. Can also add a selection to a select box. @@ -487,8 +508,9 @@ $I->appendField('#myTextField', 'appended'); * `param string` $value @throws \Codeception\Exception\ElementNotFound -### attachFile +### attachFile + Attaches a file relative to the Codeception `_data` directory to the given file upload field. ``` php @@ -501,12 +523,14 @@ $I->attachFile('input[@type="file"]', 'prices.xls'); * `param` $field * `param` $filename -### cancelPopup +### cancelPopup + Dismisses the active JavaScript popup, as created by `window.alert`, `window.confirm`, or `window.prompt`. -### checkOption +### checkOption + Ticks a checkbox. For radio buttons, use the `selectOption` method instead. ``` php @@ -517,8 +541,21 @@ $I->checkOption('#agree'); * `param` $option -### click +### clearField + +Clears given field which isn't empty. + +``` php +clearField('#username'); +``` + + * `param` $field + + +### click + Perform a click on a link or a button, given by a locator. If a fuzzy locator is given, the page will be searched for a button, link, or image matching the locator string. For buttons, the "value" attribute, "name" attribute, and inner text are searched. @@ -549,8 +586,9 @@ $I->click(['link' => 'Login']); * `param` $link * `param` $context -### clickWithLeftButton +### clickWithLeftButton + Performs click with the left mouse button on an element. If the first parameter `null` then the offset is relative to the actual mouse position. If the second and third parameters are given, @@ -571,8 +609,9 @@ $I->clickWithLeftButton(['css' => '.checkout'], 20, 50); @throws \Codeception\Exception\ElementNotFound -### clickWithRightButton +### clickWithRightButton + Performs contextual click with the right mouse button on an element. If the first parameter `null` then the offset is relative to the actual mouse position. If the second and third parameters are given, @@ -588,13 +627,14 @@ $I->clickWithRightButton(['css' => '.checkout'], 20, 50); ``` * `param string` $cssOrXPath css or xpath of the web element (body by default). - * `param int` $offsetX - * `param int` $offsetY + * `param int` $offsetX + * `param int` $offsetY @throws \Codeception\Exception\ElementNotFound -### closeTab +### closeTab + Closes current browser tab and switches to previous active tab. ```php @@ -604,14 +644,16 @@ $I->closeTab(); Can't be used with PhantomJS -### debugWebDriverLogs +### debugWebDriverLogs + Print out latest Selenium Logs in debug mode * `param TestInterface` $test -### dontSee +### dontSee + Checks that the current page doesn't contain the text specified (case insensitive). Give a locator as the second parameter to match a specific region. @@ -640,8 +682,9 @@ For checking the raw source code, use `seeInSource()`. * `param string` $text * `param string` $selector optional -### dontSeeCheckboxIsChecked +### dontSeeCheckboxIsChecked + Check that the specified checkbox is unchecked. ``` php @@ -653,8 +696,9 @@ $I->seeCheckboxIsChecked('#signup_form input[type=checkbox]'); // I suppose user * `param` $checkbox -### dontSeeCookie +### dontSeeCookie + Checks that there isn't a cookie with the given name. You can set additional cookie params like `domain`, `path` as array passed in last argument. @@ -662,8 +706,9 @@ You can set additional cookie params like `domain`, `path` as array passed in la * `param array` $params -### dontSeeCurrentUrlEquals +### dontSeeCurrentUrlEquals + Checks that the current URL doesn't equal the given string. Unlike `dontSeeInCurrentUrl`, this only matches the full URL. @@ -676,8 +721,9 @@ $I->dontSeeCurrentUrlEquals('/'); * `param string` $uri -### dontSeeCurrentUrlMatches +### dontSeeCurrentUrlMatches + Checks that current url doesn't match the given regular expression. ``` php @@ -689,8 +735,9 @@ $I->dontSeeCurrentUrlMatches('~$/users/(\d+)~'); * `param string` $uri -### dontSeeElement +### dontSeeElement + Checks that the given element is invisible or not present on the page. You can also specify expected attributes of this element. @@ -706,15 +753,17 @@ $I->dontSeeElement('input', ['value' => '123456']); * `param` $selector * `param array` $attributes -### dontSeeElementInDOM +### dontSeeElementInDOM + Opposite of `seeElementInDOM`. * `param` $selector * `param array` $attributes -### dontSeeInCurrentUrl +### dontSeeInCurrentUrl + Checks that the current URI doesn't contain the given string. ``` php @@ -725,8 +774,9 @@ $I->dontSeeInCurrentUrl('/users/'); * `param string` $uri -### dontSeeInField +### dontSeeInField + Checks that an input field or textarea doesn't contain the given value. For fuzzy locators, the field is matched by label text, CSS and XPath. @@ -744,8 +794,9 @@ $I->dontSeeInField(['name' => 'search'], 'Search'); * `param` $field * `param` $value -### dontSeeInFormFields +### dontSeeInFormFields + Checks if the array of form parameters (name => value) are not set on the form matched with the passed selector. @@ -786,14 +837,16 @@ $I->dontSeeInFormFields('#form-id', [ * `param` $formSelector * `param` $params -### dontSeeInPageSource +### dontSeeInPageSource + Checks that the page source doesn't contain the given string. * `param` $text -### dontSeeInPopup +### dontSeeInPopup + Checks that the active JavaScript popup, as created by `window.alert`|`window.confirm`|`window.prompt`, does NOT contain the given string. @@ -801,8 +854,9 @@ as created by `window.alert`|`window.confirm`|`window.prompt`, does NOT contain @throws \Codeception\Exception\ModuleException -### dontSeeInSource +### dontSeeInSource + Checks that the current page contains the given string in its raw source code. @@ -813,14 +867,17 @@ $I->dontSeeInSource('

Green eggs & ham

'); * `param` $raw -### dontSeeInTitle +### dontSeeInTitle + Checks that the page title does not contain the given string. * `param` $title -### dontSeeLink + +### dontSeeLink + Checks that the page doesn't contain a link with the given string. If the second parameter is given, only links with a matching "href" attribute will be checked. @@ -834,8 +891,9 @@ $I->dontSeeLink('Checkout now', '/store/cart.php'); * `param string` $text * `param string` $url optional -### dontSeeOptionIsSelected +### dontSeeOptionIsSelected + Checks that the given option is not selected. ``` php @@ -847,15 +905,18 @@ $I->dontSeeOptionIsSelected('#form input[name=payment]', 'Visa'); * `param` $selector * `param` $optionText -### doubleClick + +### doubleClick + Performs a double-click on an element matched by CSS or XPath. * `param` $cssOrXPath @throws \Codeception\Exception\ElementNotFound -### dragAndDrop +### dragAndDrop + Performs a simple mouse drag-and-drop operation. ``` php @@ -867,8 +928,28 @@ $I->dragAndDrop('#drag', '#drop'); * `param string` $source (CSS ID or XPath) * `param string` $target (CSS ID or XPath) -### executeInSelenium +### executeAsyncJS + +Executes asynchronous JavaScript. +A callback should be executed by JavaScript to exit from a script. +Callback is passed as a last element in `arguments` array. +Additional arguments can be passed as array in second parameter. + +```js +// wait for 1200 milliseconds my running `setTimeout` +* $I->executeAsyncJS('setTimeout(arguments[0], 1200)'); + +$seconds = 1200; // or seconds are passed as argument +$I->executeAsyncJS('setTimeout(arguments[1], arguments[0])', [$seconds]); +``` + + * `param` $script + * `param array` $arguments + + +### executeInSelenium + Low-level API method. If Codeception commands are not enough, this allows you to use Selenium WebDriver methods directly: @@ -885,8 +966,9 @@ If Codeception lacks a feature you need, please implement it and submit a patch. * `param callable` $function -### executeJS +### executeJS + Executes custom JavaScript. This example uses jQuery to get a value and assigns that value to a PHP variable: @@ -894,13 +976,18 @@ This example uses jQuery to get a value and assigns that value to a PHP variable ```php executeJS('return $("#myField").val()'); -?> + +// additional arguments can be passed as array +// Example shows `Hello World` alert: +$I->executeJS("window.alert(arguments[0])", ['Hello world']); ``` * `param` $script + * `param array` $arguments -### fillField +### fillField + Fills a text field or textarea with the given string. ``` php @@ -913,8 +1000,9 @@ $I->fillField(['name' => 'email'], 'jon@mail.com'); * `param` $field * `param` $value -### grabAttributeFrom +### grabAttributeFrom + Grabs the value of the given attribute value from the given element. Fails if element is not found. @@ -927,8 +1015,10 @@ $I->grabAttributeFrom('#tooltip', 'title'); * `param` $cssOrXpath * `param` $attribute -### grabCookie + +### grabCookie + Grabs a cookie value. You can set additional cookie params like `domain`, `path` in array passed as last argument. @@ -936,8 +1026,9 @@ You can set additional cookie params like `domain`, `path` in array passed as la * `param array` $params -### grabFromCurrentUrl +### grabFromCurrentUrl + Executes the given regular expression against the current URI and returns the first capturing group. If no parameters are provided, the full URI is returned. @@ -950,8 +1041,10 @@ $uri = $I->grabFromCurrentUrl(); * `param string` $uri optional -### grabMultiple + +### grabMultiple + Grabs either the text content, or attribute values, of nodes matched by $cssOrXpath and returns them as an array. @@ -975,16 +1068,18 @@ $aLinks = $I->grabMultiple('a', 'href'); * `param` $attribute * `return` string[] -### grabPageSource +### grabPageSource + Grabs current page source code. @throws ModuleException if no page was opened. * `return` string Current page source code. -### grabTextFrom +### grabTextFrom + Finds and returns the text contents of the given element. If a fuzzy locator is used, the element is found using CSS, XPath, and by matching the full page source by regular expression. @@ -999,8 +1094,10 @@ $value = $I->grabTextFrom('~grabValueFrom(['name' => 'username']); * `param` $field -### loadSessionSnapshot + +### loadSessionSnapshot + * `param string` $name * `return` bool -### makeScreenshot +### makeScreenshot + Takes a screenshot of the current window and saves it to `tests/_output/debug`. ``` php @@ -1035,20 +1135,24 @@ $I->makeScreenshot(); * `param` $name -### maximizeWindow +### maximizeWindow + Maximizes the current window. -### moveBack +### moveBack + Moves back in history. -### moveForward +### moveForward + Moves forward in history. -### moveMouseOver +### moveMouseOver + Move mouse over the first element matched by the given locator. If the first parameter null then the page is used. If the second and third parameters are given, @@ -1069,8 +1173,9 @@ $I->moveMouseOver(['css' => '.checkout'], 20, 50); @throws \Codeception\Exception\ElementNotFound -### openNewTab +### openNewTab + Opens a new browser tab (wherever it is possible) and switches to it. ```php @@ -1082,16 +1187,19 @@ Please note, that adblock can restrict creating such tabs. Can't be used with PhantomJS -### pauseExecution + +### pauseExecution + Pauses test execution in debug mode. To proceed test press "ENTER" in console. This method is useful while writing tests, since it allows you to inspect the current page in the middle of a test case. -### performOn +### performOn + Waits for element and runs a sequence of actions inside its context. Actions can be defined with array, callback, or `Codeception\Util\ActionSequence` instance. @@ -1134,8 +1242,9 @@ In 3rd argument you can set number a seconds to wait for element to appear * `param` $actions * `param int` $timeout -### pressKey +### pressKey + Presses the given key on the given element. To specify a character and modifier (e.g. ctrl, alt, shift, meta), pass an array for $char with the modifier as the first element and the character as the second. @@ -1156,12 +1265,14 @@ $I->pressKey('#name', array('ctrl', 'a'), \Facebook\WebDriver\WebDriverKeys::DEL * `param` $char string|array Can be char or array with modifier. You can provide several chars. @throws \Codeception\Exception\ElementNotFound -### reloadPage +### reloadPage + Reloads the current page. -### resetCookie +### resetCookie + Unsets cookie with the given name. You can set additional cookie params like `domain`, `path` in array passed as last argument. @@ -1169,8 +1280,9 @@ You can set additional cookie params like `domain`, `path` in array passed as la * `param array` $params -### resizeWindow +### resizeWindow + Resize the current window. ``` php @@ -1182,12 +1294,14 @@ $I->resizeWindow(800, 600); * `param int` $width * `param int` $height -### saveSessionSnapshot +### saveSessionSnapshot + * `param string` $name -### scrollTo +### scrollTo + Move to the middle of the given element matched by the given locator. Extra shift, calculated from the top-left corner of the element, can be set by passing $offsetX and $offsetY parameters. @@ -1202,8 +1316,9 @@ $I->scrollTo(['css' => '.checkout'], 20, 50); * `param int` $offsetX * `param int` $offsetY -### see +### see + Checks that the current page contains the given string (case insensitive). You can specify a specific HTML element (via CSS or XPath) as the second @@ -1234,8 +1349,9 @@ For checking the raw source code, use `seeInSource()`. * `param string` $text * `param string` $selector optional -### seeCheckboxIsChecked +### seeCheckboxIsChecked + Checks that the specified checkbox is checked. ``` php @@ -1248,8 +1364,9 @@ $I->seeCheckboxIsChecked('//form/input[@type=checkbox and @name=agree]'); * `param` $checkbox -### seeCookie +### seeCookie + Checks that a cookie with the given name is set. You can set additional cookie params like `domain`, `path` as array passed in last argument. @@ -1262,8 +1379,9 @@ $I->seeCookie('PHPSESSID'); * `param` $cookie * `param array` $params -### seeCurrentUrlEquals +### seeCurrentUrlEquals + Checks that the current URL is equal to the given string. Unlike `seeInCurrentUrl`, this only matches the full URL. @@ -1276,8 +1394,9 @@ $I->seeCurrentUrlEquals('/'); * `param string` $uri -### seeCurrentUrlMatches +### seeCurrentUrlMatches + Checks that the current URL matches the given regular expression. ``` php @@ -1289,8 +1408,9 @@ $I->seeCurrentUrlMatches('~$/users/(\d+)~'); * `param string` $uri -### seeElement +### seeElement + Checks that the given element exists on the page and is visible. You can also specify expected attributes of this element. @@ -1310,8 +1430,9 @@ $I->seeElement(['css' => 'form input'], ['name' => 'login']); * `param array` $attributes @return -### seeElementInDOM +### seeElementInDOM + Checks that the given element exists on the page, even it is invisible. ``` php @@ -1323,8 +1444,9 @@ $I->seeElementInDOM('//form/input[type=hidden]'); * `param` $selector * `param array` $attributes -### seeInCurrentUrl +### seeInCurrentUrl + Checks that current URI contains the given string. ``` php @@ -1338,8 +1460,9 @@ $I->seeInCurrentUrl('/users/'); * `param string` $uri -### seeInField +### seeInField + Checks that the given input field or textarea *equals* (i.e. not just contains) the given value. Fields are matched by label text, the "name" attribute, CSS, or XPath. @@ -1357,8 +1480,9 @@ $I->seeInField(['name' => 'search'], 'Search'); * `param` $field * `param` $value -### seeInFormFields +### seeInFormFields + Checks if the array of form parameters (name => value) are set on the form matched with the passed selector. @@ -1419,8 +1543,9 @@ $I->seeInFormFields('//form[@id=my-form]', $form); * `param` $formSelector * `param` $params -### seeInPageSource +### seeInPageSource + Checks that the page source contains the given string. ```php @@ -1430,8 +1555,9 @@ $I->seeInPageSource('seeInSource('

Green eggs & ham

'); * `param` $raw -### seeInTitle +### seeInTitle + Checks that the page title contains the given string. ``` php @@ -1463,8 +1591,10 @@ $I->seeInTitle('Blog - Post #1'); * `param` $title -### seeLink + +### seeLink + Checks that there's a link with the specified text. Give a full URL as the second parameter to match links with that exact URL. @@ -1478,8 +1608,9 @@ $I->seeLink('Logout','/logout'); // matches Logout * `param string` $text * `param string` $url optional -### seeNumberOfElements +### seeNumberOfElements + Checks that there are a certain number of elements matched by the given locator on the page. ``` php @@ -1491,11 +1622,13 @@ $I->seeNumberOfElements('tr', [0,10]); // between 0 and 10 elements * `param` $selector * `param mixed` $expected int or int[] + ### seeNumberOfElementsInDOM __not documented__ -### seeOptionIsSelected +### seeOptionIsSelected + Checks that the given option is selected. ``` php @@ -1507,8 +1640,10 @@ $I->seeOptionIsSelected('#form input[name=payment]', 'Visa'); * `param` $selector * `param` $optionText -### selectOption + +### selectOption + Selects an option in a select tag or in radio button group. ``` php @@ -1539,8 +1674,9 @@ $I->selectOption('Which OS do you use?', array('value' => 'windows')); // Only s * `param` $select * `param` $option -### setCookie +### setCookie + Sets a cookie with the given name and value. You can set additional cookie params like `domain`, `path`, `expires`, `secure` in array passed as last argument. @@ -1554,8 +1690,10 @@ $I->setCookie('PHPSESSID', 'el4ukv0kqbvoirg7nkp4dncpk3'); * `param` $val * `param array` $params -### submitForm + +### submitForm + Submits the given form on the page, optionally with the given form values. Give the form fields values as an array. Note that hidden fields can't be accessed. @@ -1714,8 +1852,9 @@ For example, given the following HTML: * `param` $params * `param` $button -### switchToIFrame +### switchToIFrame + Switch to another frame on the page. Example: @@ -1735,8 +1874,9 @@ $I->switchToIFrame(); * `param string|null` $name -### switchToNextTab +### switchToNextTab + Switches to next browser tab. An offset can be specified. @@ -1752,8 +1892,9 @@ Can't be used with PhantomJS * `param int` $offset 1 -### switchToPreviousTab +### switchToPreviousTab + Switches to previous browser tab. An offset can be specified. @@ -1769,8 +1910,9 @@ Can't be used with PhantomJS * `param int` $offset 1 -### switchToWindow +### switchToWindow + Switch to another window identified by name. The window can only be identified by name. If the $name parameter is blank, the parent window will be used. @@ -1806,16 +1948,18 @@ $I->executeInSelenium(function (\Facebook\WebDriver\Remote\RemoteWebDriver $webd * `param string|null` $name -### typeInPopup +### typeInPopup + Enters text into a native JavaScript prompt popup, as created by `window.prompt`. * `param` $keys @throws \Codeception\Exception\ModuleException -### uncheckOption +### uncheckOption + Unticks a checkbox. ``` php @@ -1826,22 +1970,25 @@ $I->uncheckOption('#notify'); * `param` $option -### unselectOption +### unselectOption + Unselect an option in the given select box. * `param` $select * `param` $option -### wait +### wait + Wait for $timeout seconds. * `param int|float` $timeout secs @throws \Codeception\Exception\TestRuntimeException -### waitForElement +### waitForElement + Waits up to $timeout seconds for an element to appear on the page. If the element doesn't appear, a timeout exception is thrown. @@ -1856,8 +2003,9 @@ $I->click('#agree_button'); * `param int` $timeout seconds @throws \Exception -### waitForElementChange +### waitForElementChange + Waits up to $timeout seconds for the given element to change. Element "change" is determined by a callback function which is called repeatedly until the return value evaluates to true. @@ -1876,8 +2024,9 @@ $I->waitForElementChange('#menu', function(WebDriverElement $el) { * `param int` $timeout seconds @throws \Codeception\Exception\ElementNotFound -### waitForElementNotVisible +### waitForElementNotVisible + Waits up to $timeout seconds for the given element to become invisible. If element stays visible, a timeout exception is thrown. @@ -1891,8 +2040,9 @@ $I->waitForElementNotVisible('#agree_button', 30); // secs * `param int` $timeout seconds @throws \Exception -### waitForElementVisible +### waitForElementVisible + Waits up to $timeout seconds for the given element to be visible on the page. If element doesn't appear, a timeout exception is thrown. @@ -1907,8 +2057,9 @@ $I->click('#agree_button'); * `param int` $timeout seconds @throws \Exception -### waitForJS +### waitForJS + Executes JavaScript and waits up to $timeout seconds for it to return true. In this example we will wait up to 60 seconds for all jQuery AJAX requests to finish. @@ -1922,8 +2073,9 @@ $I->waitForJS("return $.active == 0;", 60); * `param string` $script * `param int` $timeout seconds -### waitForText +### waitForText + Waits up to $timeout seconds for the given string to appear on the page. Can also be passed a selector to search in, be as specific as possible when using selectors. @@ -1942,4 +2094,4 @@ $I->waitForText('foo', 30, '.title'); // secs * `param string` $selector optional @throws \Exception -

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
+

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
diff --git a/docs/modules/XMLRPC.md b/docs/modules/XMLRPC.md index f152dcdc39..d21f7a8635 100644 --- a/docs/modules/XMLRPC.md +++ b/docs/modules/XMLRPC.md @@ -1,5 +1,6 @@ # XMLRPC + Module for testing XMLRPC WebService. This module can be used either with frameworks or PHPBrowser. @@ -34,28 +35,32 @@ Otherwise sends raw HTTP requests to url via PHPBrowser. ## Actions ### haveHttpHeader - + Sets HTTP header * `param string` $name * `param string` $value -### seeResponseCodeIs +### seeResponseCodeIs + Checks response code. * `param` $num -### seeResponseIsXMLRPC +### seeResponseIsXMLRPC + Checks weather last response was valid XMLRPC. This is done with xmlrpc_decode function. -### sendXMLRPCMethodCall + +### sendXMLRPCMethodCall + Sends a XMLRPC method call to remote XMLRPC-server. * `param string` $methodName * `param array` $parameters -

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
+

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
diff --git a/docs/modules/Yii1.md b/docs/modules/Yii1.md index 74eee61ade..dae9e37d11 100644 --- a/docs/modules/Yii1.md +++ b/docs/modules/Yii1.md @@ -1,5 +1,6 @@ # Yii1 + This module provides integration with [Yii Framework 1.1](http://www.yiiframework.com/doc/guide/). The following configurations are available for this module: @@ -111,7 +112,7 @@ modules: ### _findElements *hidden API method, expected to be used from Helper classes* - + Locates element using available Codeception locator types: * XPath @@ -135,10 +136,11 @@ PhpBrowser and Framework modules return `Symfony\Component\DomCrawler\Crawler` i * `param` $locator * `return` array of interactive elements + ### _getResponseContent *hidden API method, expected to be used from Helper classes* - + Returns content of the last response Use it in Helpers when you want to retrieve response of request performed by another module. @@ -155,10 +157,11 @@ public function seeResponseContains($text) * `return` string @throws ModuleException + ### _loadPage *hidden API method, expected to be used from Helper classes* - + Opens a page with arbitrary request parameters. Useful for testing multi-step forms on a specific step. @@ -178,10 +181,11 @@ public function openCheckoutFormStep2($orderId) { * `param array` $server * `param null` $content + ### _request *hidden API method, expected to be used from Helper classes* - + Send custom request to a backend using method, uri, parameters, etc. Use it in Helpers to create special request actions, like accessing API Returns a string with response body. @@ -209,10 +213,11 @@ To load arbitrary page for interaction, use `_loadPage` method. @throws ExternalUrlException @see `_loadPage` + ### _savePageSource *hidden API method, expected to be used from Helper classes* - + Saves page source of to a file ```php @@ -220,15 +225,17 @@ $this->getModule('Yii1')->_savePageSource(codecept_output_dir().'page.html'); ``` * `param` $filename -### amHttpAuthenticated +### amHttpAuthenticated + Authenticates user for HTTP_AUTH * `param` $username * `param` $password -### amOnPage +### amOnPage + Opens the page for the given relative URI. ``` php @@ -241,8 +248,9 @@ $I->amOnPage('/register'); * `param string` $page -### attachFile +### attachFile + Attaches a file relative to the Codeception `_data` directory to the given file upload field. ``` php @@ -255,8 +263,9 @@ $I->attachFile('input[@type="file"]', 'prices.xls'); * `param` $field * `param` $filename -### checkOption +### checkOption + Ticks a checkbox. For radio buttons, use the `selectOption` method instead. ``` php @@ -267,8 +276,9 @@ $I->checkOption('#agree'); * `param` $option -### click +### click + Perform a click on a link or a button, given by a locator. If a fuzzy locator is given, the page will be searched for a button, link, or image matching the locator string. For buttons, the "value" attribute, "name" attribute, and inner text are searched. @@ -299,8 +309,9 @@ $I->click(['link' => 'Login']); * `param` $link * `param` $context -### deleteHeader +### deleteHeader + Deletes the header with the passed name. Subsequent requests will not have the deleted header in its request. @@ -317,8 +328,9 @@ $I->amOnPage('some-other-page.php'); * `param string` $name the name of the header to delete. -### dontSee +### dontSee + Checks that the current page doesn't contain the text specified (case insensitive). Give a locator as the second parameter to match a specific region. @@ -347,8 +359,9 @@ For checking the raw source code, use `seeInSource()`. * `param string` $text * `param string` $selector optional -### dontSeeCheckboxIsChecked +### dontSeeCheckboxIsChecked + Check that the specified checkbox is unchecked. ``` php @@ -360,8 +373,9 @@ $I->seeCheckboxIsChecked('#signup_form input[type=checkbox]'); // I suppose user * `param` $checkbox -### dontSeeCookie +### dontSeeCookie + Checks that there isn't a cookie with the given name. You can set additional cookie params like `domain`, `path` as array passed in last argument. @@ -369,8 +383,9 @@ You can set additional cookie params like `domain`, `path` as array passed in la * `param array` $params -### dontSeeCurrentUrlEquals +### dontSeeCurrentUrlEquals + Checks that the current URL doesn't equal the given string. Unlike `dontSeeInCurrentUrl`, this only matches the full URL. @@ -383,8 +398,9 @@ $I->dontSeeCurrentUrlEquals('/'); * `param string` $uri -### dontSeeCurrentUrlMatches +### dontSeeCurrentUrlMatches + Checks that current url doesn't match the given regular expression. ``` php @@ -396,8 +412,9 @@ $I->dontSeeCurrentUrlMatches('~$/users/(\d+)~'); * `param string` $uri -### dontSeeElement +### dontSeeElement + Checks that the given element is invisible or not present on the page. You can also specify expected attributes of this element. @@ -413,8 +430,9 @@ $I->dontSeeElement('input', ['value' => '123456']); * `param` $selector * `param array` $attributes -### dontSeeInCurrentUrl +### dontSeeInCurrentUrl + Checks that the current URI doesn't contain the given string. ``` php @@ -425,8 +443,9 @@ $I->dontSeeInCurrentUrl('/users/'); * `param string` $uri -### dontSeeInField +### dontSeeInField + Checks that an input field or textarea doesn't contain the given value. For fuzzy locators, the field is matched by label text, CSS and XPath. @@ -444,8 +463,9 @@ $I->dontSeeInField(['name' => 'search'], 'Search'); * `param` $field * `param` $value -### dontSeeInFormFields +### dontSeeInFormFields + Checks if the array of form parameters (name => value) are not set on the form matched with the passed selector. @@ -486,8 +506,9 @@ $I->dontSeeInFormFields('#form-id', [ * `param` $formSelector * `param` $params -### dontSeeInSource +### dontSeeInSource + Checks that the current page contains the given string in its raw source code. @@ -498,14 +519,17 @@ $I->dontSeeInSource('

Green eggs & ham

'); * `param` $raw -### dontSeeInTitle +### dontSeeInTitle + Checks that the page title does not contain the given string. * `param` $title -### dontSeeLink + +### dontSeeLink + Checks that the page doesn't contain a link with the given string. If the second parameter is given, only links with a matching "href" attribute will be checked. @@ -519,8 +543,9 @@ $I->dontSeeLink('Checkout now', '/store/cart.php'); * `param string` $text * `param string` $url optional -### dontSeeOptionIsSelected +### dontSeeOptionIsSelected + Checks that the given option is not selected. ``` php @@ -532,8 +557,10 @@ $I->dontSeeOptionIsSelected('#form input[name=payment]', 'Visa'); * `param` $selector * `param` $optionText -### dontSeeResponseCodeIs + +### dontSeeResponseCodeIs + Checks that response code is equal to value provided. ```php @@ -545,8 +572,9 @@ $I->dontSeeResponseCodeIs(\Codeception\Util\HttpCode::OK); ``` * `param` $code -### fillField +### fillField + Fills a text field or textarea with the given string. ``` php @@ -559,14 +587,16 @@ $I->fillField(['name' => 'email'], 'jon@mail.com'); * `param` $field * `param` $value -### getInternalDomains +### getInternalDomains + Returns a list of regex patterns for recognized domain names * `return` array -### grabAttributeFrom +### grabAttributeFrom + Grabs the value of the given attribute value from the given element. Fails if element is not found. @@ -579,8 +609,10 @@ $I->grabAttributeFrom('#tooltip', 'title'); * `param` $cssOrXpath * `param` $attribute -### grabCookie + +### grabCookie + Grabs a cookie value. You can set additional cookie params like `domain`, `path` in array passed as last argument. @@ -588,8 +620,9 @@ You can set additional cookie params like `domain`, `path` in array passed as la * `param array` $params -### grabFromCurrentUrl +### grabFromCurrentUrl + Executes the given regular expression against the current URI and returns the first capturing group. If no parameters are provided, the full URI is returned. @@ -602,8 +635,10 @@ $uri = $I->grabFromCurrentUrl(); * `param string` $uri optional -### grabMultiple + +### grabMultiple + Grabs either the text content, or attribute values, of nodes matched by $cssOrXpath and returns them as an array. @@ -627,16 +662,18 @@ $aLinks = $I->grabMultiple('a', 'href'); * `param` $attribute * `return` string[] -### grabPageSource +### grabPageSource + Grabs current page source code. @throws ModuleException if no page was opened. * `return` string Current page source code. -### grabTextFrom +### grabTextFrom + Finds and returns the text contents of the given element. If a fuzzy locator is used, the element is found using CSS, XPath, and by matching the full page source by regular expression. @@ -651,14 +688,17 @@ $value = $I->grabTextFrom('~haveHttpHeader('Client_Id', 'Codeception'); * `param string` $value the value to set it to for subsequent requests -### moveBack +### moveBack + Moves back in history. * `param int` $numberOfSteps (default value 1) -### resetCookie +### resetCookie + Unsets cookie with the given name. You can set additional cookie params like `domain`, `path` in array passed as last argument. @@ -700,8 +742,9 @@ You can set additional cookie params like `domain`, `path` in array passed as la * `param array` $params -### see +### see + Checks that the current page contains the given string (case insensitive). You can specify a specific HTML element (via CSS or XPath) as the second @@ -732,8 +775,9 @@ For checking the raw source code, use `seeInSource()`. * `param string` $text * `param string` $selector optional -### seeCheckboxIsChecked +### seeCheckboxIsChecked + Checks that the specified checkbox is checked. ``` php @@ -746,8 +790,9 @@ $I->seeCheckboxIsChecked('//form/input[@type=checkbox and @name=agree]'); * `param` $checkbox -### seeCookie +### seeCookie + Checks that a cookie with the given name is set. You can set additional cookie params like `domain`, `path` as array passed in last argument. @@ -760,8 +805,9 @@ $I->seeCookie('PHPSESSID'); * `param` $cookie * `param array` $params -### seeCurrentUrlEquals +### seeCurrentUrlEquals + Checks that the current URL is equal to the given string. Unlike `seeInCurrentUrl`, this only matches the full URL. @@ -774,8 +820,9 @@ $I->seeCurrentUrlEquals('/'); * `param string` $uri -### seeCurrentUrlMatches +### seeCurrentUrlMatches + Checks that the current URL matches the given regular expression. ``` php @@ -787,8 +834,9 @@ $I->seeCurrentUrlMatches('~$/users/(\d+)~'); * `param string` $uri -### seeElement +### seeElement + Checks that the given element exists on the page and is visible. You can also specify expected attributes of this element. @@ -808,8 +856,9 @@ $I->seeElement(['css' => 'form input'], ['name' => 'login']); * `param array` $attributes @return -### seeInCurrentUrl +### seeInCurrentUrl + Checks that current URI contains the given string. ``` php @@ -823,8 +872,9 @@ $I->seeInCurrentUrl('/users/'); * `param string` $uri -### seeInField +### seeInField + Checks that the given input field or textarea *equals* (i.e. not just contains) the given value. Fields are matched by label text, the "name" attribute, CSS, or XPath. @@ -842,8 +892,9 @@ $I->seeInField(['name' => 'search'], 'Search'); * `param` $field * `param` $value -### seeInFormFields +### seeInFormFields + Checks if the array of form parameters (name => value) are set on the form matched with the passed selector. @@ -904,8 +955,9 @@ $I->seeInFormFields('//form[@id=my-form]', $form); * `param` $formSelector * `param` $params -### seeInSource +### seeInSource + Checks that the current page contains the given string in its raw source code. @@ -916,8 +968,9 @@ $I->seeInSource('

Green eggs & ham

'); * `param` $raw -### seeInTitle +### seeInTitle + Checks that the page title contains the given string. ``` php @@ -928,8 +981,10 @@ $I->seeInTitle('Blog - Post #1'); * `param` $title -### seeLink + +### seeLink + Checks that there's a link with the specified text. Give a full URL as the second parameter to match links with that exact URL. @@ -943,8 +998,9 @@ $I->seeLink('Logout','/logout'); // matches Logout * `param string` $text * `param string` $url optional -### seeNumberOfElements +### seeNumberOfElements + Checks that there are a certain number of elements matched by the given locator on the page. ``` php @@ -956,8 +1012,9 @@ $I->seeNumberOfElements('tr', [0,10]); // between 0 and 10 elements * `param` $selector * `param mixed` $expected int or int[] -### seeOptionIsSelected +### seeOptionIsSelected + Checks that the given option is selected. ``` php @@ -969,12 +1026,15 @@ $I->seeOptionIsSelected('#form input[name=payment]', 'Visa'); * `param` $selector * `param` $optionText -### seePageNotFound + +### seePageNotFound + Asserts that current page has 404 response status code. -### seeResponseCodeIs +### seeResponseCodeIs + Checks that response code is equal to value provided. ```php @@ -987,8 +1047,9 @@ $I->seeResponseCodeIs(\Codeception\Util\HttpCode::OK); * `param` $code -### selectOption +### selectOption + Selects an option in a select tag or in radio button group. ``` php @@ -1019,8 +1080,9 @@ $I->selectOption('Which OS do you use?', array('value' => 'windows')); // Only s * `param` $select * `param` $option -### sendAjaxGetRequest +### sendAjaxGetRequest + If your page triggers an ajax request, you can perform it manually. This action sends a GET ajax request with specified params. @@ -1029,8 +1091,9 @@ See ->sendAjaxPostRequest for examples. * `param` $uri * `param` $params -### sendAjaxPostRequest +### sendAjaxPostRequest + If your page triggers an ajax request, you can perform it manually. This action sends a POST ajax request with specified params. Additional params can be passed as array. @@ -1050,8 +1113,9 @@ $I->sendAjaxGetRequest('/updateSettings', array('notifications' => true)); // GE * `param` $uri * `param` $params -### sendAjaxRequest +### sendAjaxRequest + If your page triggers an ajax request, you can perform it manually. This action sends an ajax request with specified method and params. @@ -1069,8 +1133,9 @@ $I->sendAjaxRequest('PUT', '/posts/7', array('title' => 'new title')); * `param` $uri * `param` $params -### setCookie +### setCookie + Sets a cookie with the given name and value. You can set additional cookie params like `domain`, `path`, `expires`, `secure` in array passed as last argument. @@ -1084,8 +1149,10 @@ $I->setCookie('PHPSESSID', 'el4ukv0kqbvoirg7nkp4dncpk3'); * `param` $val * `param array` $params -### submitForm + +### submitForm + Submits the given form on the page, with the given form values. Pass the form field's values as an array in the second parameter. @@ -1256,8 +1323,9 @@ $I->submitForm('#my-form', [ * `param` $params * `param` $button -### switchToIframe +### switchToIframe + Switch to iframe or frame on the page. Example: @@ -1273,8 +1341,9 @@ $I->switchToIframe("another_frame"); * `param string` $name -### uncheckOption +### uncheckOption + Unticks a checkbox. ``` php @@ -1285,4 +1354,4 @@ $I->uncheckOption('#notify'); * `param` $option -

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
+

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
diff --git a/docs/modules/Yii2.md b/docs/modules/Yii2.md index 52a28cb26e..ed6bb2c955 100644 --- a/docs/modules/Yii2.md +++ b/docs/modules/Yii2.md @@ -1,5 +1,6 @@ # Yii2 + This module provides integration with [Yii framework](http://www.yiiframework.com/) (2.0). It initializes Yii framework in test environment and provides actions for functional testing. @@ -108,12 +109,13 @@ $I->sendAjaxPostRequest(['/user/update', 'id' => 1], ['UserForm[name]' => 'G.Hop Maintainer: **samdark** Stability: **stable** + ## Actions ### _findElements *hidden API method, expected to be used from Helper classes* - + Locates element using available Codeception locator types: * XPath @@ -137,10 +139,11 @@ PhpBrowser and Framework modules return `Symfony\Component\DomCrawler\Crawler` i * `param` $locator * `return` array of interactive elements + ### _getResponseContent *hidden API method, expected to be used from Helper classes* - + Returns content of the last response Use it in Helpers when you want to retrieve response of request performed by another module. @@ -157,10 +160,11 @@ public function seeResponseContains($text) * `return` string @throws ModuleException + ### _loadPage *hidden API method, expected to be used from Helper classes* - + Opens a page with arbitrary request parameters. Useful for testing multi-step forms on a specific step. @@ -180,10 +184,11 @@ public function openCheckoutFormStep2($orderId) { * `param array` $server * `param null` $content + ### _request *hidden API method, expected to be used from Helper classes* - + Send custom request to a backend using method, uri, parameters, etc. Use it in Helpers to create special request actions, like accessing API Returns a string with response body. @@ -211,10 +216,11 @@ To load arbitrary page for interaction, use `_loadPage` method. @throws ExternalUrlException @see `_loadPage` + ### _savePageSource *hidden API method, expected to be used from Helper classes* - + Saves page source of to a file ```php @@ -222,15 +228,17 @@ $this->getModule('Yii2')->_savePageSource(codecept_output_dir().'page.html'); ``` * `param` $filename -### amHttpAuthenticated +### amHttpAuthenticated + Authenticates user for HTTP_AUTH * `param` $username * `param` $password -### amLoggedInAs +### amLoggedInAs + Authorizes user on a site without submitting login form. Use it for fast pragmatic authorization in functional tests. @@ -248,8 +256,9 @@ Requires `user` component to be enabled and configured. * `param` $user @throws ModuleException -### amOnPage +### amOnPage + Opens the page for the given relative URI. ``` php @@ -262,16 +271,19 @@ $I->amOnPage('/register'); * `param string` $page -### amOnRoute +### amOnRoute + Similar to amOnPage but accepts route as first argument and params as second ``` $I->amOnRoute('site/view', ['page' => 'about']); ``` -### attachFile + +### attachFile + Attaches a file relative to the Codeception `_data` directory to the given file upload field. ``` php @@ -284,8 +296,9 @@ $I->attachFile('input[@type="file"]', 'prices.xls'); * `param` $field * `param` $filename -### checkOption +### checkOption + Ticks a checkbox. For radio buttons, use the `selectOption` method instead. ``` php @@ -296,8 +309,9 @@ $I->checkOption('#agree'); * `param` $option -### click +### click + Perform a click on a link or a button, given by a locator. If a fuzzy locator is given, the page will be searched for a button, link, or image matching the locator string. For buttons, the "value" attribute, "name" attribute, and inner text are searched. @@ -328,8 +342,16 @@ $I->click(['link' => 'Login']); * `param` $link * `param` $context -### deleteHeader +### createAndSetCsrfCookie + +This function creates the CSRF Cookie. + * `param string` $val The value of the CSRF token + * `return` string[] Returns an array containing the name of the CSRF param and the masked CSRF token. + + +### deleteHeader + Deletes the header with the passed name. Subsequent requests will not have the deleted header in its request. @@ -346,8 +368,9 @@ $I->amOnPage('some-other-page.php'); * `param string` $name the name of the header to delete. -### dontSee +### dontSee + Checks that the current page doesn't contain the text specified (case insensitive). Give a locator as the second parameter to match a specific region. @@ -376,8 +399,9 @@ For checking the raw source code, use `seeInSource()`. * `param string` $text * `param string` $selector optional -### dontSeeCheckboxIsChecked +### dontSeeCheckboxIsChecked + Check that the specified checkbox is unchecked. ``` php @@ -389,8 +413,9 @@ $I->seeCheckboxIsChecked('#signup_form input[type=checkbox]'); // I suppose user * `param` $checkbox -### dontSeeCookie +### dontSeeCookie + Checks that there isn't a cookie with the given name. You can set additional cookie params like `domain`, `path` as array passed in last argument. @@ -398,8 +423,9 @@ You can set additional cookie params like `domain`, `path` as array passed in la * `param array` $params -### dontSeeCurrentUrlEquals +### dontSeeCurrentUrlEquals + Checks that the current URL doesn't equal the given string. Unlike `dontSeeInCurrentUrl`, this only matches the full URL. @@ -412,8 +438,9 @@ $I->dontSeeCurrentUrlEquals('/'); * `param string` $uri -### dontSeeCurrentUrlMatches +### dontSeeCurrentUrlMatches + Checks that current url doesn't match the given regular expression. ``` php @@ -425,8 +452,9 @@ $I->dontSeeCurrentUrlMatches('~$/users/(\d+)~'); * `param string` $uri -### dontSeeElement +### dontSeeElement + Checks that the given element is invisible or not present on the page. You can also specify expected attributes of this element. @@ -442,14 +470,16 @@ $I->dontSeeElement('input', ['value' => '123456']); * `param` $selector * `param array` $attributes -### dontSeeEmailIsSent +### dontSeeEmailIsSent + Checks that no email was sent * `[Part]` email -### dontSeeInCurrentUrl +### dontSeeInCurrentUrl + Checks that the current URI doesn't contain the given string. ``` php @@ -460,8 +490,9 @@ $I->dontSeeInCurrentUrl('/users/'); * `param string` $uri -### dontSeeInField +### dontSeeInField + Checks that an input field or textarea doesn't contain the given value. For fuzzy locators, the field is matched by label text, CSS and XPath. @@ -479,8 +510,9 @@ $I->dontSeeInField(['name' => 'search'], 'Search'); * `param` $field * `param` $value -### dontSeeInFormFields +### dontSeeInFormFields + Checks if the array of form parameters (name => value) are not set on the form matched with the passed selector. @@ -521,8 +553,9 @@ $I->dontSeeInFormFields('#form-id', [ * `param` $formSelector * `param` $params -### dontSeeInSource +### dontSeeInSource + Checks that the current page contains the given string in its raw source code. @@ -533,14 +566,17 @@ $I->dontSeeInSource('

Green eggs & ham

'); * `param` $raw -### dontSeeInTitle +### dontSeeInTitle + Checks that the page title does not contain the given string. * `param` $title -### dontSeeLink + +### dontSeeLink + Checks that the page doesn't contain a link with the given string. If the second parameter is given, only links with a matching "href" attribute will be checked. @@ -554,8 +590,9 @@ $I->dontSeeLink('Checkout now', '/store/cart.php'); * `param string` $text * `param string` $url optional -### dontSeeOptionIsSelected +### dontSeeOptionIsSelected + Checks that the given option is not selected. ``` php @@ -567,8 +604,10 @@ $I->dontSeeOptionIsSelected('#form input[name=payment]', 'Visa'); * `param` $selector * `param` $optionText -### dontSeeRecord + +### dontSeeRecord + Checks that record does not exist in database. ``` php @@ -579,8 +618,9 @@ $I->dontSeeRecord('app\models\User', array('name' => 'davert')); * `param array` $attributes * `[Part]` orm -### dontSeeResponseCodeIs +### dontSeeResponseCodeIs + Checks that response code is equal to value provided. ```php @@ -592,8 +632,9 @@ $I->dontSeeResponseCodeIs(\Codeception\Util\HttpCode::OK); ``` * `param` $code -### fillField +### fillField + Fills a text field or textarea with the given string. ``` php @@ -606,14 +647,16 @@ $I->fillField(['name' => 'email'], 'jon@mail.com'); * `param` $field * `param` $value -### getInternalDomains +### getInternalDomains + Returns a list of regex patterns for recognized domain names * `return` array -### grabAttributeFrom +### grabAttributeFrom + Grabs the value of the given attribute value from the given element. Fails if element is not found. @@ -626,8 +669,10 @@ $I->grabAttributeFrom('#tooltip', 'title'); * `param` $cssOrXpath * `param` $attribute -### grabComponent + +### grabComponent + Gets a component from Yii container. Throws exception if component is not available ```php @@ -638,8 +683,9 @@ $mailer = $I->grabComponent('mailer'); * `param` $component @throws ModuleException -### grabCookie +### grabCookie + Grabs a cookie value. You can set additional cookie params like `domain`, `path` in array passed as last argument. @@ -647,8 +693,9 @@ You can set additional cookie params like `domain`, `path` in array passed as la * `param array` $params -### grabFixture +### grabFixture + Gets a fixture by name. Returns a Fixture instance. If a fixture is an instance of `\yii\test\BaseActiveFixture` a second parameter can be used to return a specific model: @@ -667,16 +714,18 @@ $user = $I->grabFixture('users', 'user1'); @throws ModuleException if a fixture is not found * `[Part]` fixtures -### grabFixtures +### grabFixtures + Returns all loaded fixtures. Array of fixture instances * `[Part]` fixtures * `return` array -### grabFromCurrentUrl +### grabFromCurrentUrl + Executes the given regular expression against the current URI and returns the first capturing group. If no parameters are provided, the full URI is returned. @@ -689,8 +738,10 @@ $uri = $I->grabFromCurrentUrl(); * `param string` $uri optional -### grabLastSentEmail + +### grabLastSentEmail + Returns last sent email: ```php @@ -701,8 +752,9 @@ $I->assertEquals('admin@site,com', $message->getTo()); ``` * `[Part]` email -### grabMultiple +### grabMultiple + Grabs either the text content, or attribute values, of nodes matched by $cssOrXpath and returns them as an array. @@ -726,16 +778,18 @@ $aLinks = $I->grabMultiple('a', 'href'); * `param` $attribute * `return` string[] -### grabPageSource +### grabPageSource + Grabs current page source code. @throws ModuleException if no page was opened. * `return` string Current page source code. -### grabRecord +### grabRecord + Retrieves record from database ``` php @@ -746,10 +800,11 @@ $category = $I->grabRecord('app\models\User', array('name' => 'davert')); * `param array` $attributes * `[Part]` orm -### grabSentEmails +### grabSentEmails + Returns array of all sent email messages. -Each message implements `yii\mail\Message` interface. +Each message implements `yii\mail\MessageInterface` interface. Useful to perform additional checks using `Asserts` module: ```php @@ -763,8 +818,9 @@ $I->assertEquals('admin@site,com', $messages[0]->getTo()); * `return` array @throws ModuleException -### grabTextFrom +### grabTextFrom + Finds and returns the text contents of the given element. If a fuzzy locator is used, the element is found using CSS, XPath, and by matching the full page source by regular expression. @@ -779,14 +835,17 @@ $value = $I->grabTextFrom('~haveHttpHeader('Client_Id', 'Codeception'); * `param string` $value the value to set it to for subsequent requests -### haveRecord +### haveRecord + Inserts record into the database. ``` php @@ -862,14 +923,16 @@ $user_id = $I->haveRecord('app\models\User', array('name' => 'Davert')); * `param array` $attributes * `[Part]` orm -### moveBack +### moveBack + Moves back in history. * `param int` $numberOfSteps (default value 1) -### resetCookie +### resetCookie + Unsets cookie with the given name. You can set additional cookie params like `domain`, `path` in array passed as last argument. @@ -877,8 +940,9 @@ You can set additional cookie params like `domain`, `path` in array passed as la * `param array` $params -### see +### see + Checks that the current page contains the given string (case insensitive). You can specify a specific HTML element (via CSS or XPath) as the second @@ -909,8 +973,9 @@ For checking the raw source code, use `seeInSource()`. * `param string` $text * `param string` $selector optional -### seeCheckboxIsChecked +### seeCheckboxIsChecked + Checks that the specified checkbox is checked. ``` php @@ -923,8 +988,9 @@ $I->seeCheckboxIsChecked('//form/input[@type=checkbox and @name=agree]'); * `param` $checkbox -### seeCookie +### seeCookie + Checks that a cookie with the given name is set. You can set additional cookie params like `domain`, `path` as array passed in last argument. @@ -937,8 +1003,9 @@ $I->seeCookie('PHPSESSID'); * `param` $cookie * `param array` $params -### seeCurrentUrlEquals +### seeCurrentUrlEquals + Checks that the current URL is equal to the given string. Unlike `seeInCurrentUrl`, this only matches the full URL. @@ -951,8 +1018,9 @@ $I->seeCurrentUrlEquals('/'); * `param string` $uri -### seeCurrentUrlMatches +### seeCurrentUrlMatches + Checks that the current URL matches the given regular expression. ``` php @@ -964,8 +1032,9 @@ $I->seeCurrentUrlMatches('~$/users/(\d+)~'); * `param string` $uri -### seeElement +### seeElement + Checks that the given element exists on the page and is visible. You can also specify expected attributes of this element. @@ -985,8 +1054,9 @@ $I->seeElement(['css' => 'form input'], ['name' => 'login']); * `param array` $attributes @return -### seeEmailIsSent +### seeEmailIsSent + Checks that email is sent. ```php @@ -1002,8 +1072,9 @@ $I->seeEmailIsSent(3); @throws ModuleException * `[Part]` email -### seeInCurrentUrl +### seeInCurrentUrl + Checks that current URI contains the given string. ``` php @@ -1017,8 +1088,9 @@ $I->seeInCurrentUrl('/users/'); * `param string` $uri -### seeInField +### seeInField + Checks that the given input field or textarea *equals* (i.e. not just contains) the given value. Fields are matched by label text, the "name" attribute, CSS, or XPath. @@ -1036,8 +1108,9 @@ $I->seeInField(['name' => 'search'], 'Search'); * `param` $field * `param` $value -### seeInFormFields +### seeInFormFields + Checks if the array of form parameters (name => value) are set on the form matched with the passed selector. @@ -1098,8 +1171,9 @@ $I->seeInFormFields('//form[@id=my-form]', $form); * `param` $formSelector * `param` $params -### seeInSource +### seeInSource + Checks that the current page contains the given string in its raw source code. @@ -1110,8 +1184,9 @@ $I->seeInSource('

Green eggs & ham

'); * `param` $raw -### seeInTitle +### seeInTitle + Checks that the page title contains the given string. ``` php @@ -1122,8 +1197,10 @@ $I->seeInTitle('Blog - Post #1'); * `param` $title -### seeLink + +### seeLink + Checks that there's a link with the specified text. Give a full URL as the second parameter to match links with that exact URL. @@ -1137,8 +1214,9 @@ $I->seeLink('Logout','/logout'); // matches Logout * `param string` $text * `param string` $url optional -### seeNumberOfElements +### seeNumberOfElements + Checks that there are a certain number of elements matched by the given locator on the page. ``` php @@ -1150,8 +1228,9 @@ $I->seeNumberOfElements('tr', [0,10]); // between 0 and 10 elements * `param` $selector * `param mixed` $expected int or int[] -### seeOptionIsSelected +### seeOptionIsSelected + Checks that the given option is selected. ``` php @@ -1163,12 +1242,15 @@ $I->seeOptionIsSelected('#form input[name=payment]', 'Visa'); * `param` $selector * `param` $optionText -### seePageNotFound + +### seePageNotFound + Asserts that current page has 404 response status code. -### seeRecord +### seeRecord + Checks that record exists in database. ``` php @@ -1179,8 +1261,9 @@ $I->seeRecord('app\models\User', array('name' => 'davert')); * `param array` $attributes * `[Part]` orm -### seeResponseCodeIs +### seeResponseCodeIs + Checks that response code is equal to value provided. ```php @@ -1193,8 +1276,9 @@ $I->seeResponseCodeIs(\Codeception\Util\HttpCode::OK); * `param` $code -### selectOption +### selectOption + Selects an option in a select tag or in radio button group. ``` php @@ -1225,8 +1309,9 @@ $I->selectOption('Which OS do you use?', array('value' => 'windows')); // Only s * `param` $select * `param` $option -### sendAjaxGetRequest +### sendAjaxGetRequest + If your page triggers an ajax request, you can perform it manually. This action sends a GET ajax request with specified params. @@ -1235,8 +1320,9 @@ See ->sendAjaxPostRequest for examples. * `param` $uri * `param` $params -### sendAjaxPostRequest +### sendAjaxPostRequest + If your page triggers an ajax request, you can perform it manually. This action sends a POST ajax request with specified params. Additional params can be passed as array. @@ -1256,8 +1342,9 @@ $I->sendAjaxGetRequest('/updateSettings', array('notifications' => true)); // GE * `param` $uri * `param` $params -### sendAjaxRequest +### sendAjaxRequest + If your page triggers an ajax request, you can perform it manually. This action sends an ajax request with specified method and params. @@ -1275,23 +1362,17 @@ $I->sendAjaxRequest('PUT', '/posts/7', array('title' => 'new title')); * `param` $uri * `param` $params -### setCookie - -Sets a cookie with the given name and value. -You can set additional cookie params like `domain`, `path`, `expires`, `secure` in array passed as last argument. -``` php -setCookie('PHPSESSID', 'el4ukv0kqbvoirg7nkp4dncpk3'); -?> -``` +### setCookie + +Sets a cookie and, if validation is enabled, signs it. + * `param string` $name The name of the cookie + * `param string` $value The value of the cookie + * `param array` $params Additional cookie params like `domain`, `path`, `expires` and `secure`. - * `param` $name - * `param` $val - * `param array` $params ### submitForm - + Submits the given form on the page, with the given form values. Pass the form field's values as an array in the second parameter. @@ -1462,8 +1543,9 @@ $I->submitForm('#my-form', [ * `param` $params * `param` $button -### switchToIframe +### switchToIframe + Switch to iframe or frame on the page. Example: @@ -1479,8 +1561,9 @@ $I->switchToIframe("another_frame"); * `param string` $name -### uncheckOption +### uncheckOption + Unticks a checkbox. ``` php @@ -1491,4 +1574,4 @@ $I->uncheckOption('#notify'); * `param` $option -

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
+

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
diff --git a/docs/modules/ZF1.md b/docs/modules/ZF1.md index 8a44607c70..6a901dfabd 100644 --- a/docs/modules/ZF1.md +++ b/docs/modules/ZF1.md @@ -1,5 +1,6 @@ # ZF1 + This module allows you to run tests inside Zend Framework. It acts just like ControllerTestCase, but with usage of Codeception syntax. @@ -54,12 +55,13 @@ class TestHelper extends \Codeception\Module { This will make your functional tests run super-fast. + ## Actions ### _findElements *hidden API method, expected to be used from Helper classes* - + Locates element using available Codeception locator types: * XPath @@ -83,10 +85,11 @@ PhpBrowser and Framework modules return `Symfony\Component\DomCrawler\Crawler` i * `param` $locator * `return` array of interactive elements + ### _getResponseContent *hidden API method, expected to be used from Helper classes* - + Returns content of the last response Use it in Helpers when you want to retrieve response of request performed by another module. @@ -103,10 +106,11 @@ public function seeResponseContains($text) * `return` string @throws ModuleException + ### _loadPage *hidden API method, expected to be used from Helper classes* - + Opens a page with arbitrary request parameters. Useful for testing multi-step forms on a specific step. @@ -126,10 +130,11 @@ public function openCheckoutFormStep2($orderId) { * `param array` $server * `param null` $content + ### _request *hidden API method, expected to be used from Helper classes* - + Send custom request to a backend using method, uri, parameters, etc. Use it in Helpers to create special request actions, like accessing API Returns a string with response body. @@ -157,10 +162,11 @@ To load arbitrary page for interaction, use `_loadPage` method. @throws ExternalUrlException @see `_loadPage` + ### _savePageSource *hidden API method, expected to be used from Helper classes* - + Saves page source of to a file ```php @@ -168,15 +174,17 @@ $this->getModule('ZF1')->_savePageSource(codecept_output_dir().'page.html'); ``` * `param` $filename -### amHttpAuthenticated +### amHttpAuthenticated + Authenticates user for HTTP_AUTH * `param` $username * `param` $password -### amOnPage +### amOnPage + Opens the page for the given relative URI. ``` php @@ -189,8 +197,9 @@ $I->amOnPage('/register'); * `param string` $page -### amOnRoute +### amOnRoute + Opens web page using route name and parameters. ``` php @@ -203,8 +212,9 @@ $I->amOnRoute('posts.show', array('id' => 34)); * `param` $routeName * `param array` $params -### attachFile +### attachFile + Attaches a file relative to the Codeception `_data` directory to the given file upload field. ``` php @@ -217,8 +227,9 @@ $I->attachFile('input[@type="file"]', 'prices.xls'); * `param` $field * `param` $filename -### checkOption +### checkOption + Ticks a checkbox. For radio buttons, use the `selectOption` method instead. ``` php @@ -229,8 +240,9 @@ $I->checkOption('#agree'); * `param` $option -### click +### click + Perform a click on a link or a button, given by a locator. If a fuzzy locator is given, the page will be searched for a button, link, or image matching the locator string. For buttons, the "value" attribute, "name" attribute, and inner text are searched. @@ -261,8 +273,9 @@ $I->click(['link' => 'Login']); * `param` $link * `param` $context -### deleteHeader +### deleteHeader + Deletes the header with the passed name. Subsequent requests will not have the deleted header in its request. @@ -279,8 +292,9 @@ $I->amOnPage('some-other-page.php'); * `param string` $name the name of the header to delete. -### dontSee +### dontSee + Checks that the current page doesn't contain the text specified (case insensitive). Give a locator as the second parameter to match a specific region. @@ -309,8 +323,9 @@ For checking the raw source code, use `seeInSource()`. * `param string` $text * `param string` $selector optional -### dontSeeCheckboxIsChecked +### dontSeeCheckboxIsChecked + Check that the specified checkbox is unchecked. ``` php @@ -322,8 +337,9 @@ $I->seeCheckboxIsChecked('#signup_form input[type=checkbox]'); // I suppose user * `param` $checkbox -### dontSeeCookie +### dontSeeCookie + Checks that there isn't a cookie with the given name. You can set additional cookie params like `domain`, `path` as array passed in last argument. @@ -331,8 +347,9 @@ You can set additional cookie params like `domain`, `path` as array passed in la * `param array` $params -### dontSeeCurrentUrlEquals +### dontSeeCurrentUrlEquals + Checks that the current URL doesn't equal the given string. Unlike `dontSeeInCurrentUrl`, this only matches the full URL. @@ -345,8 +362,9 @@ $I->dontSeeCurrentUrlEquals('/'); * `param string` $uri -### dontSeeCurrentUrlMatches +### dontSeeCurrentUrlMatches + Checks that current url doesn't match the given regular expression. ``` php @@ -358,8 +376,9 @@ $I->dontSeeCurrentUrlMatches('~$/users/(\d+)~'); * `param string` $uri -### dontSeeElement +### dontSeeElement + Checks that the given element is invisible or not present on the page. You can also specify expected attributes of this element. @@ -375,8 +394,9 @@ $I->dontSeeElement('input', ['value' => '123456']); * `param` $selector * `param array` $attributes -### dontSeeInCurrentUrl +### dontSeeInCurrentUrl + Checks that the current URI doesn't contain the given string. ``` php @@ -387,8 +407,9 @@ $I->dontSeeInCurrentUrl('/users/'); * `param string` $uri -### dontSeeInField +### dontSeeInField + Checks that an input field or textarea doesn't contain the given value. For fuzzy locators, the field is matched by label text, CSS and XPath. @@ -406,8 +427,9 @@ $I->dontSeeInField(['name' => 'search'], 'Search'); * `param` $field * `param` $value -### dontSeeInFormFields +### dontSeeInFormFields + Checks if the array of form parameters (name => value) are not set on the form matched with the passed selector. @@ -448,8 +470,9 @@ $I->dontSeeInFormFields('#form-id', [ * `param` $formSelector * `param` $params -### dontSeeInSource +### dontSeeInSource + Checks that the current page contains the given string in its raw source code. @@ -460,14 +483,17 @@ $I->dontSeeInSource('

Green eggs & ham

'); * `param` $raw -### dontSeeInTitle +### dontSeeInTitle + Checks that the page title does not contain the given string. * `param` $title -### dontSeeLink + +### dontSeeLink + Checks that the page doesn't contain a link with the given string. If the second parameter is given, only links with a matching "href" attribute will be checked. @@ -481,8 +507,9 @@ $I->dontSeeLink('Checkout now', '/store/cart.php'); * `param string` $text * `param string` $url optional -### dontSeeOptionIsSelected +### dontSeeOptionIsSelected + Checks that the given option is not selected. ``` php @@ -494,8 +521,10 @@ $I->dontSeeOptionIsSelected('#form input[name=payment]', 'Visa'); * `param` $selector * `param` $optionText -### dontSeeResponseCodeIs + +### dontSeeResponseCodeIs + Checks that response code is equal to value provided. ```php @@ -507,8 +536,9 @@ $I->dontSeeResponseCodeIs(\Codeception\Util\HttpCode::OK); ``` * `param` $code -### fillField +### fillField + Fills a text field or textarea with the given string. ``` php @@ -521,8 +551,9 @@ $I->fillField(['name' => 'email'], 'jon@mail.com'); * `param` $field * `param` $value -### grabAttributeFrom +### grabAttributeFrom + Grabs the value of the given attribute value from the given element. Fails if element is not found. @@ -535,8 +566,10 @@ $I->grabAttributeFrom('#tooltip', 'title'); * `param` $cssOrXpath * `param` $attribute -### grabCookie + +### grabCookie + Grabs a cookie value. You can set additional cookie params like `domain`, `path` in array passed as last argument. @@ -544,8 +577,9 @@ You can set additional cookie params like `domain`, `path` in array passed as la * `param array` $params -### grabFromCurrentUrl +### grabFromCurrentUrl + Executes the given regular expression against the current URI and returns the first capturing group. If no parameters are provided, the full URI is returned. @@ -558,8 +592,10 @@ $uri = $I->grabFromCurrentUrl(); * `param string` $uri optional -### grabMultiple + +### grabMultiple + Grabs either the text content, or attribute values, of nodes matched by $cssOrXpath and returns them as an array. @@ -583,16 +619,18 @@ $aLinks = $I->grabMultiple('a', 'href'); * `param` $attribute * `return` string[] -### grabPageSource +### grabPageSource + Grabs current page source code. @throws ModuleException if no page was opened. * `return` string Current page source code. -### grabTextFrom +### grabTextFrom + Finds and returns the text contents of the given element. If a fuzzy locator is used, the element is found using CSS, XPath, and by matching the full page source by regular expression. @@ -607,14 +645,17 @@ $value = $I->grabTextFrom('~haveHttpHeader('Client_Id', 'Codeception'); * `param string` $value the value to set it to for subsequent requests -### moveBack +### moveBack + Moves back in history. * `param int` $numberOfSteps (default value 1) -### resetCookie +### resetCookie + Unsets cookie with the given name. You can set additional cookie params like `domain`, `path` in array passed as last argument. @@ -656,8 +699,9 @@ You can set additional cookie params like `domain`, `path` in array passed as la * `param array` $params -### see +### see + Checks that the current page contains the given string (case insensitive). You can specify a specific HTML element (via CSS or XPath) as the second @@ -688,8 +732,9 @@ For checking the raw source code, use `seeInSource()`. * `param string` $text * `param string` $selector optional -### seeCheckboxIsChecked +### seeCheckboxIsChecked + Checks that the specified checkbox is checked. ``` php @@ -702,8 +747,9 @@ $I->seeCheckboxIsChecked('//form/input[@type=checkbox and @name=agree]'); * `param` $checkbox -### seeCookie +### seeCookie + Checks that a cookie with the given name is set. You can set additional cookie params like `domain`, `path` as array passed in last argument. @@ -716,8 +762,9 @@ $I->seeCookie('PHPSESSID'); * `param` $cookie * `param array` $params -### seeCurrentRouteIs +### seeCurrentRouteIs + Checks that current url matches route. ``` php @@ -730,8 +777,9 @@ $I->seeCurrentRouteIs('posts.show', ['id' => 8])); * `param` $routeName * `param array` $params -### seeCurrentUrlEquals +### seeCurrentUrlEquals + Checks that the current URL is equal to the given string. Unlike `seeInCurrentUrl`, this only matches the full URL. @@ -744,8 +792,9 @@ $I->seeCurrentUrlEquals('/'); * `param string` $uri -### seeCurrentUrlMatches +### seeCurrentUrlMatches + Checks that the current URL matches the given regular expression. ``` php @@ -757,8 +806,9 @@ $I->seeCurrentUrlMatches('~$/users/(\d+)~'); * `param string` $uri -### seeElement +### seeElement + Checks that the given element exists on the page and is visible. You can also specify expected attributes of this element. @@ -778,8 +828,9 @@ $I->seeElement(['css' => 'form input'], ['name' => 'login']); * `param array` $attributes @return -### seeInCurrentUrl +### seeInCurrentUrl + Checks that current URI contains the given string. ``` php @@ -793,8 +844,9 @@ $I->seeInCurrentUrl('/users/'); * `param string` $uri -### seeInField +### seeInField + Checks that the given input field or textarea *equals* (i.e. not just contains) the given value. Fields are matched by label text, the "name" attribute, CSS, or XPath. @@ -812,8 +864,9 @@ $I->seeInField(['name' => 'search'], 'Search'); * `param` $field * `param` $value -### seeInFormFields +### seeInFormFields + Checks if the array of form parameters (name => value) are set on the form matched with the passed selector. @@ -874,8 +927,9 @@ $I->seeInFormFields('//form[@id=my-form]', $form); * `param` $formSelector * `param` $params -### seeInSource +### seeInSource + Checks that the current page contains the given string in its raw source code. @@ -886,8 +940,9 @@ $I->seeInSource('

Green eggs & ham

'); * `param` $raw -### seeInTitle +### seeInTitle + Checks that the page title contains the given string. ``` php @@ -898,8 +953,10 @@ $I->seeInTitle('Blog - Post #1'); * `param` $title -### seeLink + +### seeLink + Checks that there's a link with the specified text. Give a full URL as the second parameter to match links with that exact URL. @@ -913,8 +970,9 @@ $I->seeLink('Logout','/logout'); // matches Logout * `param string` $text * `param string` $url optional -### seeNumberOfElements +### seeNumberOfElements + Checks that there are a certain number of elements matched by the given locator on the page. ``` php @@ -926,8 +984,9 @@ $I->seeNumberOfElements('tr', [0,10]); // between 0 and 10 elements * `param` $selector * `param mixed` $expected int or int[] -### seeOptionIsSelected +### seeOptionIsSelected + Checks that the given option is selected. ``` php @@ -939,12 +998,15 @@ $I->seeOptionIsSelected('#form input[name=payment]', 'Visa'); * `param` $selector * `param` $optionText -### seePageNotFound + +### seePageNotFound + Asserts that current page has 404 response status code. -### seeResponseCodeIs +### seeResponseCodeIs + Checks that response code is equal to value provided. ```php @@ -957,8 +1019,9 @@ $I->seeResponseCodeIs(\Codeception\Util\HttpCode::OK); * `param` $code -### selectOption +### selectOption + Selects an option in a select tag or in radio button group. ``` php @@ -989,8 +1052,9 @@ $I->selectOption('Which OS do you use?', array('value' => 'windows')); // Only s * `param` $select * `param` $option -### sendAjaxGetRequest +### sendAjaxGetRequest + If your page triggers an ajax request, you can perform it manually. This action sends a GET ajax request with specified params. @@ -999,8 +1063,9 @@ See ->sendAjaxPostRequest for examples. * `param` $uri * `param` $params -### sendAjaxPostRequest +### sendAjaxPostRequest + If your page triggers an ajax request, you can perform it manually. This action sends a POST ajax request with specified params. Additional params can be passed as array. @@ -1020,8 +1085,9 @@ $I->sendAjaxGetRequest('/updateSettings', array('notifications' => true)); // GE * `param` $uri * `param` $params -### sendAjaxRequest +### sendAjaxRequest + If your page triggers an ajax request, you can perform it manually. This action sends an ajax request with specified method and params. @@ -1039,8 +1105,9 @@ $I->sendAjaxRequest('PUT', '/posts/7', array('title' => 'new title')); * `param` $uri * `param` $params -### setCookie +### setCookie + Sets a cookie with the given name and value. You can set additional cookie params like `domain`, `path`, `expires`, `secure` in array passed as last argument. @@ -1054,8 +1121,10 @@ $I->setCookie('PHPSESSID', 'el4ukv0kqbvoirg7nkp4dncpk3'); * `param` $val * `param array` $params -### submitForm + +### submitForm + Submits the given form on the page, with the given form values. Pass the form field's values as an array in the second parameter. @@ -1226,8 +1295,9 @@ $I->submitForm('#my-form', [ * `param` $params * `param` $button -### switchToIframe +### switchToIframe + Switch to iframe or frame on the page. Example: @@ -1243,8 +1313,9 @@ $I->switchToIframe("another_frame"); * `param string` $name -### uncheckOption +### uncheckOption + Unticks a checkbox. ``` php @@ -1255,4 +1326,4 @@ $I->uncheckOption('#notify'); * `param` $option -

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
+

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
diff --git a/docs/modules/ZF2.md b/docs/modules/ZF2.md index 3018081c34..263c422a75 100644 --- a/docs/modules/ZF2.md +++ b/docs/modules/ZF2.md @@ -1,5 +1,6 @@ # ZF2 + This module allows you to run tests inside Zend Framework 2 and Zend Framework 3. File `init_autoloader` in project's root is required by Zend Framework 2. @@ -46,7 +47,7 @@ modules: ### _findElements *hidden API method, expected to be used from Helper classes* - + Locates element using available Codeception locator types: * XPath @@ -70,10 +71,11 @@ PhpBrowser and Framework modules return `Symfony\Component\DomCrawler\Crawler` i * `param` $locator * `return` array of interactive elements + ### _getResponseContent *hidden API method, expected to be used from Helper classes* - + Returns content of the last response Use it in Helpers when you want to retrieve response of request performed by another module. @@ -90,10 +92,11 @@ public function seeResponseContains($text) * `return` string @throws ModuleException + ### _loadPage *hidden API method, expected to be used from Helper classes* - + Opens a page with arbitrary request parameters. Useful for testing multi-step forms on a specific step. @@ -113,10 +116,11 @@ public function openCheckoutFormStep2($orderId) { * `param array` $server * `param null` $content + ### _request *hidden API method, expected to be used from Helper classes* - + Send custom request to a backend using method, uri, parameters, etc. Use it in Helpers to create special request actions, like accessing API Returns a string with response body. @@ -144,10 +148,11 @@ To load arbitrary page for interaction, use `_loadPage` method. @throws ExternalUrlException @see `_loadPage` + ### _savePageSource *hidden API method, expected to be used from Helper classes* - + Saves page source of to a file ```php @@ -155,22 +160,25 @@ $this->getModule('ZF2')->_savePageSource(codecept_output_dir().'page.html'); ``` * `param` $filename -### addServiceToContainer +### addServiceToContainer + Adds service to ZF2 container * `param string` $name * `param object` $service * `[Part]` services -### amHttpAuthenticated +### amHttpAuthenticated + Authenticates user for HTTP_AUTH * `param` $username * `param` $password -### amOnPage +### amOnPage + Opens the page for the given relative URI. ``` php @@ -183,8 +191,9 @@ $I->amOnPage('/register'); * `param string` $page -### amOnRoute +### amOnRoute + Opens web page using route name and parameters. ``` php @@ -197,8 +206,9 @@ $I->amOnRoute('posts.show', array('id' => 34)); * `param` $routeName * `param array` $params -### attachFile +### attachFile + Attaches a file relative to the Codeception `_data` directory to the given file upload field. ``` php @@ -211,8 +221,9 @@ $I->attachFile('input[@type="file"]', 'prices.xls'); * `param` $field * `param` $filename -### checkOption +### checkOption + Ticks a checkbox. For radio buttons, use the `selectOption` method instead. ``` php @@ -223,8 +234,9 @@ $I->checkOption('#agree'); * `param` $option -### click +### click + Perform a click on a link or a button, given by a locator. If a fuzzy locator is given, the page will be searched for a button, link, or image matching the locator string. For buttons, the "value" attribute, "name" attribute, and inner text are searched. @@ -255,8 +267,9 @@ $I->click(['link' => 'Login']); * `param` $link * `param` $context -### deleteHeader +### deleteHeader + Deletes the header with the passed name. Subsequent requests will not have the deleted header in its request. @@ -273,8 +286,9 @@ $I->amOnPage('some-other-page.php'); * `param string` $name the name of the header to delete. -### dontSee +### dontSee + Checks that the current page doesn't contain the text specified (case insensitive). Give a locator as the second parameter to match a specific region. @@ -303,8 +317,9 @@ For checking the raw source code, use `seeInSource()`. * `param string` $text * `param string` $selector optional -### dontSeeCheckboxIsChecked +### dontSeeCheckboxIsChecked + Check that the specified checkbox is unchecked. ``` php @@ -316,8 +331,9 @@ $I->seeCheckboxIsChecked('#signup_form input[type=checkbox]'); // I suppose user * `param` $checkbox -### dontSeeCookie +### dontSeeCookie + Checks that there isn't a cookie with the given name. You can set additional cookie params like `domain`, `path` as array passed in last argument. @@ -325,8 +341,9 @@ You can set additional cookie params like `domain`, `path` as array passed in la * `param array` $params -### dontSeeCurrentUrlEquals +### dontSeeCurrentUrlEquals + Checks that the current URL doesn't equal the given string. Unlike `dontSeeInCurrentUrl`, this only matches the full URL. @@ -339,8 +356,9 @@ $I->dontSeeCurrentUrlEquals('/'); * `param string` $uri -### dontSeeCurrentUrlMatches +### dontSeeCurrentUrlMatches + Checks that current url doesn't match the given regular expression. ``` php @@ -352,8 +370,9 @@ $I->dontSeeCurrentUrlMatches('~$/users/(\d+)~'); * `param string` $uri -### dontSeeElement +### dontSeeElement + Checks that the given element is invisible or not present on the page. You can also specify expected attributes of this element. @@ -369,8 +388,9 @@ $I->dontSeeElement('input', ['value' => '123456']); * `param` $selector * `param array` $attributes -### dontSeeInCurrentUrl +### dontSeeInCurrentUrl + Checks that the current URI doesn't contain the given string. ``` php @@ -381,8 +401,9 @@ $I->dontSeeInCurrentUrl('/users/'); * `param string` $uri -### dontSeeInField +### dontSeeInField + Checks that an input field or textarea doesn't contain the given value. For fuzzy locators, the field is matched by label text, CSS and XPath. @@ -400,8 +421,9 @@ $I->dontSeeInField(['name' => 'search'], 'Search'); * `param` $field * `param` $value -### dontSeeInFormFields +### dontSeeInFormFields + Checks if the array of form parameters (name => value) are not set on the form matched with the passed selector. @@ -442,8 +464,9 @@ $I->dontSeeInFormFields('#form-id', [ * `param` $formSelector * `param` $params -### dontSeeInSource +### dontSeeInSource + Checks that the current page contains the given string in its raw source code. @@ -454,14 +477,17 @@ $I->dontSeeInSource('

Green eggs & ham

'); * `param` $raw -### dontSeeInTitle +### dontSeeInTitle + Checks that the page title does not contain the given string. * `param` $title -### dontSeeLink + +### dontSeeLink + Checks that the page doesn't contain a link with the given string. If the second parameter is given, only links with a matching "href" attribute will be checked. @@ -475,8 +501,9 @@ $I->dontSeeLink('Checkout now', '/store/cart.php'); * `param string` $text * `param string` $url optional -### dontSeeOptionIsSelected +### dontSeeOptionIsSelected + Checks that the given option is not selected. ``` php @@ -488,8 +515,10 @@ $I->dontSeeOptionIsSelected('#form input[name=payment]', 'Visa'); * `param` $selector * `param` $optionText -### dontSeeResponseCodeIs + +### dontSeeResponseCodeIs + Checks that response code is equal to value provided. ```php @@ -501,8 +530,9 @@ $I->dontSeeResponseCodeIs(\Codeception\Util\HttpCode::OK); ``` * `param` $code -### fillField +### fillField + Fills a text field or textarea with the given string. ``` php @@ -515,8 +545,9 @@ $I->fillField(['name' => 'email'], 'jon@mail.com'); * `param` $field * `param` $value -### grabAttributeFrom +### grabAttributeFrom + Grabs the value of the given attribute value from the given element. Fails if element is not found. @@ -529,8 +560,10 @@ $I->grabAttributeFrom('#tooltip', 'title'); * `param` $cssOrXpath * `param` $attribute -### grabCookie + +### grabCookie + Grabs a cookie value. You can set additional cookie params like `domain`, `path` in array passed as last argument. @@ -538,8 +571,9 @@ You can set additional cookie params like `domain`, `path` in array passed as la * `param array` $params -### grabFromCurrentUrl +### grabFromCurrentUrl + Executes the given regular expression against the current URI and returns the first capturing group. If no parameters are provided, the full URI is returned. @@ -552,8 +586,10 @@ $uri = $I->grabFromCurrentUrl(); * `param string` $uri optional -### grabMultiple + +### grabMultiple + Grabs either the text content, or attribute values, of nodes matched by $cssOrXpath and returns them as an array. @@ -577,16 +613,18 @@ $aLinks = $I->grabMultiple('a', 'href'); * `param` $attribute * `return` string[] -### grabPageSource +### grabPageSource + Grabs current page source code. @throws ModuleException if no page was opened. * `return` string Current page source code. -### grabServiceFromContainer +### grabServiceFromContainer + Grabs a service from ZF2 container. Recommended to use for unit testing. @@ -599,8 +637,9 @@ $em = $I->grabServiceFromContainer('Doctrine\ORM\EntityManager'); * `param` $service * `[Part]` services -### grabTextFrom +### grabTextFrom + Finds and returns the text contents of the given element. If a fuzzy locator is used, the element is found using CSS, XPath, and by matching the full page source by regular expression. @@ -615,14 +654,17 @@ $value = $I->grabTextFrom('~haveHttpHeader('Client_Id', 'Codeception'); * `param string` $value the value to set it to for subsequent requests -### moveBack +### moveBack + Moves back in history. * `param int` $numberOfSteps (default value 1) -### resetCookie +### resetCookie + Unsets cookie with the given name. You can set additional cookie params like `domain`, `path` in array passed as last argument. @@ -664,8 +708,9 @@ You can set additional cookie params like `domain`, `path` in array passed as la * `param array` $params -### see +### see + Checks that the current page contains the given string (case insensitive). You can specify a specific HTML element (via CSS or XPath) as the second @@ -696,8 +741,9 @@ For checking the raw source code, use `seeInSource()`. * `param string` $text * `param string` $selector optional -### seeCheckboxIsChecked +### seeCheckboxIsChecked + Checks that the specified checkbox is checked. ``` php @@ -710,8 +756,9 @@ $I->seeCheckboxIsChecked('//form/input[@type=checkbox and @name=agree]'); * `param` $checkbox -### seeCookie +### seeCookie + Checks that a cookie with the given name is set. You can set additional cookie params like `domain`, `path` as array passed in last argument. @@ -724,8 +771,9 @@ $I->seeCookie('PHPSESSID'); * `param` $cookie * `param array` $params -### seeCurrentRouteIs +### seeCurrentRouteIs + Checks that current url matches route. ``` php @@ -738,8 +786,9 @@ $I->seeCurrentRouteIs('posts.show', ['id' => 8])); * `param` $routeName * `param array` $params -### seeCurrentUrlEquals +### seeCurrentUrlEquals + Checks that the current URL is equal to the given string. Unlike `seeInCurrentUrl`, this only matches the full URL. @@ -752,8 +801,9 @@ $I->seeCurrentUrlEquals('/'); * `param string` $uri -### seeCurrentUrlMatches +### seeCurrentUrlMatches + Checks that the current URL matches the given regular expression. ``` php @@ -765,8 +815,9 @@ $I->seeCurrentUrlMatches('~$/users/(\d+)~'); * `param string` $uri -### seeElement +### seeElement + Checks that the given element exists on the page and is visible. You can also specify expected attributes of this element. @@ -786,8 +837,9 @@ $I->seeElement(['css' => 'form input'], ['name' => 'login']); * `param array` $attributes @return -### seeInCurrentUrl +### seeInCurrentUrl + Checks that current URI contains the given string. ``` php @@ -801,8 +853,9 @@ $I->seeInCurrentUrl('/users/'); * `param string` $uri -### seeInField +### seeInField + Checks that the given input field or textarea *equals* (i.e. not just contains) the given value. Fields are matched by label text, the "name" attribute, CSS, or XPath. @@ -820,8 +873,9 @@ $I->seeInField(['name' => 'search'], 'Search'); * `param` $field * `param` $value -### seeInFormFields +### seeInFormFields + Checks if the array of form parameters (name => value) are set on the form matched with the passed selector. @@ -882,8 +936,9 @@ $I->seeInFormFields('//form[@id=my-form]', $form); * `param` $formSelector * `param` $params -### seeInSource +### seeInSource + Checks that the current page contains the given string in its raw source code. @@ -894,8 +949,9 @@ $I->seeInSource('

Green eggs & ham

'); * `param` $raw -### seeInTitle +### seeInTitle + Checks that the page title contains the given string. ``` php @@ -906,8 +962,10 @@ $I->seeInTitle('Blog - Post #1'); * `param` $title -### seeLink + +### seeLink + Checks that there's a link with the specified text. Give a full URL as the second parameter to match links with that exact URL. @@ -921,8 +979,9 @@ $I->seeLink('Logout','/logout'); // matches Logout * `param string` $text * `param string` $url optional -### seeNumberOfElements +### seeNumberOfElements + Checks that there are a certain number of elements matched by the given locator on the page. ``` php @@ -934,8 +993,9 @@ $I->seeNumberOfElements('tr', [0,10]); // between 0 and 10 elements * `param` $selector * `param mixed` $expected int or int[] -### seeOptionIsSelected +### seeOptionIsSelected + Checks that the given option is selected. ``` php @@ -947,12 +1007,15 @@ $I->seeOptionIsSelected('#form input[name=payment]', 'Visa'); * `param` $selector * `param` $optionText -### seePageNotFound + +### seePageNotFound + Asserts that current page has 404 response status code. -### seeResponseCodeIs +### seeResponseCodeIs + Checks that response code is equal to value provided. ```php @@ -965,8 +1028,9 @@ $I->seeResponseCodeIs(\Codeception\Util\HttpCode::OK); * `param` $code -### selectOption +### selectOption + Selects an option in a select tag or in radio button group. ``` php @@ -997,8 +1061,9 @@ $I->selectOption('Which OS do you use?', array('value' => 'windows')); // Only s * `param` $select * `param` $option -### sendAjaxGetRequest +### sendAjaxGetRequest + If your page triggers an ajax request, you can perform it manually. This action sends a GET ajax request with specified params. @@ -1007,8 +1072,9 @@ See ->sendAjaxPostRequest for examples. * `param` $uri * `param` $params -### sendAjaxPostRequest +### sendAjaxPostRequest + If your page triggers an ajax request, you can perform it manually. This action sends a POST ajax request with specified params. Additional params can be passed as array. @@ -1028,8 +1094,9 @@ $I->sendAjaxGetRequest('/updateSettings', array('notifications' => true)); // GE * `param` $uri * `param` $params -### sendAjaxRequest +### sendAjaxRequest + If your page triggers an ajax request, you can perform it manually. This action sends an ajax request with specified method and params. @@ -1047,8 +1114,9 @@ $I->sendAjaxRequest('PUT', '/posts/7', array('title' => 'new title')); * `param` $uri * `param` $params -### setCookie +### setCookie + Sets a cookie with the given name and value. You can set additional cookie params like `domain`, `path`, `expires`, `secure` in array passed as last argument. @@ -1062,8 +1130,10 @@ $I->setCookie('PHPSESSID', 'el4ukv0kqbvoirg7nkp4dncpk3'); * `param` $val * `param array` $params -### submitForm + +### submitForm + Submits the given form on the page, with the given form values. Pass the form field's values as an array in the second parameter. @@ -1234,8 +1304,9 @@ $I->submitForm('#my-form', [ * `param` $params * `param` $button -### switchToIframe +### switchToIframe + Switch to iframe or frame on the page. Example: @@ -1251,8 +1322,9 @@ $I->switchToIframe("another_frame"); * `param string` $name -### uncheckOption +### uncheckOption + Unticks a checkbox. ``` php @@ -1263,4 +1335,4 @@ $I->uncheckOption('#notify'); * `param` $option -

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
+

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
diff --git a/docs/modules/ZendExpressive.md b/docs/modules/ZendExpressive.md index 57a2acfe73..f0e265a9a8 100644 --- a/docs/modules/ZendExpressive.md +++ b/docs/modules/ZendExpressive.md @@ -1,5 +1,6 @@ # ZendExpressive + This module allows you to run tests inside Zend Expressive. Uses `config/container.php` file by default. @@ -19,12 +20,13 @@ Uses `config/container.php` file by default. * container - instance of `\Interop\Container\ContainerInterface` * client - BrowserKit client + ## Actions ### _findElements *hidden API method, expected to be used from Helper classes* - + Locates element using available Codeception locator types: * XPath @@ -48,10 +50,11 @@ PhpBrowser and Framework modules return `Symfony\Component\DomCrawler\Crawler` i * `param` $locator * `return` array of interactive elements + ### _getResponseContent *hidden API method, expected to be used from Helper classes* - + Returns content of the last response Use it in Helpers when you want to retrieve response of request performed by another module. @@ -68,10 +71,11 @@ public function seeResponseContains($text) * `return` string @throws ModuleException + ### _loadPage *hidden API method, expected to be used from Helper classes* - + Opens a page with arbitrary request parameters. Useful for testing multi-step forms on a specific step. @@ -91,10 +95,11 @@ public function openCheckoutFormStep2($orderId) { * `param array` $server * `param null` $content + ### _request *hidden API method, expected to be used from Helper classes* - + Send custom request to a backend using method, uri, parameters, etc. Use it in Helpers to create special request actions, like accessing API Returns a string with response body. @@ -122,10 +127,11 @@ To load arbitrary page for interaction, use `_loadPage` method. @throws ExternalUrlException @see `_loadPage` + ### _savePageSource *hidden API method, expected to be used from Helper classes* - + Saves page source of to a file ```php @@ -133,15 +139,17 @@ $this->getModule('ZendExpressive')->_savePageSource(codecept_output_dir().'page. ``` * `param` $filename -### amHttpAuthenticated +### amHttpAuthenticated + Authenticates user for HTTP_AUTH * `param` $username * `param` $password -### amOnPage +### amOnPage + Opens the page for the given relative URI. ``` php @@ -154,8 +162,9 @@ $I->amOnPage('/register'); * `param string` $page -### attachFile +### attachFile + Attaches a file relative to the Codeception `_data` directory to the given file upload field. ``` php @@ -168,8 +177,9 @@ $I->attachFile('input[@type="file"]', 'prices.xls'); * `param` $field * `param` $filename -### checkOption +### checkOption + Ticks a checkbox. For radio buttons, use the `selectOption` method instead. ``` php @@ -180,8 +190,9 @@ $I->checkOption('#agree'); * `param` $option -### click +### click + Perform a click on a link or a button, given by a locator. If a fuzzy locator is given, the page will be searched for a button, link, or image matching the locator string. For buttons, the "value" attribute, "name" attribute, and inner text are searched. @@ -212,8 +223,9 @@ $I->click(['link' => 'Login']); * `param` $link * `param` $context -### deleteHeader +### deleteHeader + Deletes the header with the passed name. Subsequent requests will not have the deleted header in its request. @@ -230,8 +242,9 @@ $I->amOnPage('some-other-page.php'); * `param string` $name the name of the header to delete. -### dontSee +### dontSee + Checks that the current page doesn't contain the text specified (case insensitive). Give a locator as the second parameter to match a specific region. @@ -260,8 +273,9 @@ For checking the raw source code, use `seeInSource()`. * `param string` $text * `param string` $selector optional -### dontSeeCheckboxIsChecked +### dontSeeCheckboxIsChecked + Check that the specified checkbox is unchecked. ``` php @@ -273,8 +287,9 @@ $I->seeCheckboxIsChecked('#signup_form input[type=checkbox]'); // I suppose user * `param` $checkbox -### dontSeeCookie +### dontSeeCookie + Checks that there isn't a cookie with the given name. You can set additional cookie params like `domain`, `path` as array passed in last argument. @@ -282,8 +297,9 @@ You can set additional cookie params like `domain`, `path` as array passed in la * `param array` $params -### dontSeeCurrentUrlEquals +### dontSeeCurrentUrlEquals + Checks that the current URL doesn't equal the given string. Unlike `dontSeeInCurrentUrl`, this only matches the full URL. @@ -296,8 +312,9 @@ $I->dontSeeCurrentUrlEquals('/'); * `param string` $uri -### dontSeeCurrentUrlMatches +### dontSeeCurrentUrlMatches + Checks that current url doesn't match the given regular expression. ``` php @@ -309,8 +326,9 @@ $I->dontSeeCurrentUrlMatches('~$/users/(\d+)~'); * `param string` $uri -### dontSeeElement +### dontSeeElement + Checks that the given element is invisible or not present on the page. You can also specify expected attributes of this element. @@ -326,8 +344,9 @@ $I->dontSeeElement('input', ['value' => '123456']); * `param` $selector * `param array` $attributes -### dontSeeInCurrentUrl +### dontSeeInCurrentUrl + Checks that the current URI doesn't contain the given string. ``` php @@ -338,8 +357,9 @@ $I->dontSeeInCurrentUrl('/users/'); * `param string` $uri -### dontSeeInField +### dontSeeInField + Checks that an input field or textarea doesn't contain the given value. For fuzzy locators, the field is matched by label text, CSS and XPath. @@ -357,8 +377,9 @@ $I->dontSeeInField(['name' => 'search'], 'Search'); * `param` $field * `param` $value -### dontSeeInFormFields +### dontSeeInFormFields + Checks if the array of form parameters (name => value) are not set on the form matched with the passed selector. @@ -399,8 +420,9 @@ $I->dontSeeInFormFields('#form-id', [ * `param` $formSelector * `param` $params -### dontSeeInSource +### dontSeeInSource + Checks that the current page contains the given string in its raw source code. @@ -411,14 +433,17 @@ $I->dontSeeInSource('

Green eggs & ham

'); * `param` $raw -### dontSeeInTitle +### dontSeeInTitle + Checks that the page title does not contain the given string. * `param` $title -### dontSeeLink + +### dontSeeLink + Checks that the page doesn't contain a link with the given string. If the second parameter is given, only links with a matching "href" attribute will be checked. @@ -432,8 +457,9 @@ $I->dontSeeLink('Checkout now', '/store/cart.php'); * `param string` $text * `param string` $url optional -### dontSeeOptionIsSelected +### dontSeeOptionIsSelected + Checks that the given option is not selected. ``` php @@ -445,8 +471,10 @@ $I->dontSeeOptionIsSelected('#form input[name=payment]', 'Visa'); * `param` $selector * `param` $optionText -### dontSeeResponseCodeIs + +### dontSeeResponseCodeIs + Checks that response code is equal to value provided. ```php @@ -458,8 +486,9 @@ $I->dontSeeResponseCodeIs(\Codeception\Util\HttpCode::OK); ``` * `param` $code -### fillField +### fillField + Fills a text field or textarea with the given string. ``` php @@ -472,8 +501,9 @@ $I->fillField(['name' => 'email'], 'jon@mail.com'); * `param` $field * `param` $value -### grabAttributeFrom +### grabAttributeFrom + Grabs the value of the given attribute value from the given element. Fails if element is not found. @@ -486,8 +516,10 @@ $I->grabAttributeFrom('#tooltip', 'title'); * `param` $cssOrXpath * `param` $attribute -### grabCookie + +### grabCookie + Grabs a cookie value. You can set additional cookie params like `domain`, `path` in array passed as last argument. @@ -495,8 +527,9 @@ You can set additional cookie params like `domain`, `path` in array passed as la * `param array` $params -### grabFromCurrentUrl +### grabFromCurrentUrl + Executes the given regular expression against the current URI and returns the first capturing group. If no parameters are provided, the full URI is returned. @@ -509,8 +542,10 @@ $uri = $I->grabFromCurrentUrl(); * `param string` $uri optional -### grabMultiple + +### grabMultiple + Grabs either the text content, or attribute values, of nodes matched by $cssOrXpath and returns them as an array. @@ -534,16 +569,18 @@ $aLinks = $I->grabMultiple('a', 'href'); * `param` $attribute * `return` string[] -### grabPageSource +### grabPageSource + Grabs current page source code. @throws ModuleException if no page was opened. * `return` string Current page source code. -### grabTextFrom +### grabTextFrom + Finds and returns the text contents of the given element. If a fuzzy locator is used, the element is found using CSS, XPath, and by matching the full page source by regular expression. @@ -558,14 +595,17 @@ $value = $I->grabTextFrom('~haveHttpHeader('Client_Id', 'Codeception'); * `param string` $value the value to set it to for subsequent requests -### moveBack +### moveBack + Moves back in history. * `param int` $numberOfSteps (default value 1) -### resetCookie +### resetCookie + Unsets cookie with the given name. You can set additional cookie params like `domain`, `path` in array passed as last argument. @@ -607,8 +649,9 @@ You can set additional cookie params like `domain`, `path` in array passed as la * `param array` $params -### see +### see + Checks that the current page contains the given string (case insensitive). You can specify a specific HTML element (via CSS or XPath) as the second @@ -639,8 +682,9 @@ For checking the raw source code, use `seeInSource()`. * `param string` $text * `param string` $selector optional -### seeCheckboxIsChecked +### seeCheckboxIsChecked + Checks that the specified checkbox is checked. ``` php @@ -653,8 +697,9 @@ $I->seeCheckboxIsChecked('//form/input[@type=checkbox and @name=agree]'); * `param` $checkbox -### seeCookie +### seeCookie + Checks that a cookie with the given name is set. You can set additional cookie params like `domain`, `path` as array passed in last argument. @@ -667,8 +712,9 @@ $I->seeCookie('PHPSESSID'); * `param` $cookie * `param array` $params -### seeCurrentUrlEquals +### seeCurrentUrlEquals + Checks that the current URL is equal to the given string. Unlike `seeInCurrentUrl`, this only matches the full URL. @@ -681,8 +727,9 @@ $I->seeCurrentUrlEquals('/'); * `param string` $uri -### seeCurrentUrlMatches +### seeCurrentUrlMatches + Checks that the current URL matches the given regular expression. ``` php @@ -694,8 +741,9 @@ $I->seeCurrentUrlMatches('~$/users/(\d+)~'); * `param string` $uri -### seeElement +### seeElement + Checks that the given element exists on the page and is visible. You can also specify expected attributes of this element. @@ -715,8 +763,9 @@ $I->seeElement(['css' => 'form input'], ['name' => 'login']); * `param array` $attributes @return -### seeInCurrentUrl +### seeInCurrentUrl + Checks that current URI contains the given string. ``` php @@ -730,8 +779,9 @@ $I->seeInCurrentUrl('/users/'); * `param string` $uri -### seeInField +### seeInField + Checks that the given input field or textarea *equals* (i.e. not just contains) the given value. Fields are matched by label text, the "name" attribute, CSS, or XPath. @@ -749,8 +799,9 @@ $I->seeInField(['name' => 'search'], 'Search'); * `param` $field * `param` $value -### seeInFormFields +### seeInFormFields + Checks if the array of form parameters (name => value) are set on the form matched with the passed selector. @@ -811,8 +862,9 @@ $I->seeInFormFields('//form[@id=my-form]', $form); * `param` $formSelector * `param` $params -### seeInSource +### seeInSource + Checks that the current page contains the given string in its raw source code. @@ -823,8 +875,9 @@ $I->seeInSource('

Green eggs & ham

'); * `param` $raw -### seeInTitle +### seeInTitle + Checks that the page title contains the given string. ``` php @@ -835,8 +888,10 @@ $I->seeInTitle('Blog - Post #1'); * `param` $title -### seeLink + +### seeLink + Checks that there's a link with the specified text. Give a full URL as the second parameter to match links with that exact URL. @@ -850,8 +905,9 @@ $I->seeLink('Logout','/logout'); // matches Logout * `param string` $text * `param string` $url optional -### seeNumberOfElements +### seeNumberOfElements + Checks that there are a certain number of elements matched by the given locator on the page. ``` php @@ -863,8 +919,9 @@ $I->seeNumberOfElements('tr', [0,10]); // between 0 and 10 elements * `param` $selector * `param mixed` $expected int or int[] -### seeOptionIsSelected +### seeOptionIsSelected + Checks that the given option is selected. ``` php @@ -876,12 +933,15 @@ $I->seeOptionIsSelected('#form input[name=payment]', 'Visa'); * `param` $selector * `param` $optionText -### seePageNotFound + +### seePageNotFound + Asserts that current page has 404 response status code. -### seeResponseCodeIs +### seeResponseCodeIs + Checks that response code is equal to value provided. ```php @@ -894,8 +954,9 @@ $I->seeResponseCodeIs(\Codeception\Util\HttpCode::OK); * `param` $code -### selectOption +### selectOption + Selects an option in a select tag or in radio button group. ``` php @@ -926,8 +987,9 @@ $I->selectOption('Which OS do you use?', array('value' => 'windows')); // Only s * `param` $select * `param` $option -### sendAjaxGetRequest +### sendAjaxGetRequest + If your page triggers an ajax request, you can perform it manually. This action sends a GET ajax request with specified params. @@ -936,8 +998,9 @@ See ->sendAjaxPostRequest for examples. * `param` $uri * `param` $params -### sendAjaxPostRequest +### sendAjaxPostRequest + If your page triggers an ajax request, you can perform it manually. This action sends a POST ajax request with specified params. Additional params can be passed as array. @@ -957,8 +1020,9 @@ $I->sendAjaxGetRequest('/updateSettings', array('notifications' => true)); // GE * `param` $uri * `param` $params -### sendAjaxRequest +### sendAjaxRequest + If your page triggers an ajax request, you can perform it manually. This action sends an ajax request with specified method and params. @@ -976,8 +1040,9 @@ $I->sendAjaxRequest('PUT', '/posts/7', array('title' => 'new title')); * `param` $uri * `param` $params -### setCookie +### setCookie + Sets a cookie with the given name and value. You can set additional cookie params like `domain`, `path`, `expires`, `secure` in array passed as last argument. @@ -991,8 +1056,10 @@ $I->setCookie('PHPSESSID', 'el4ukv0kqbvoirg7nkp4dncpk3'); * `param` $val * `param array` $params -### submitForm + +### submitForm + Submits the given form on the page, with the given form values. Pass the form field's values as an array in the second parameter. @@ -1163,8 +1230,9 @@ $I->submitForm('#my-form', [ * `param` $params * `param` $button -### switchToIframe +### switchToIframe + Switch to iframe or frame on the page. Example: @@ -1180,8 +1248,9 @@ $I->switchToIframe("another_frame"); * `param string` $name -### uncheckOption +### uncheckOption + Unticks a checkbox. ``` php @@ -1192,4 +1261,4 @@ $I->uncheckOption('#notify'); * `param` $option -

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
+

 

Module reference is taken from the source code. Help us to improve documentation. Edit module reference
diff --git a/docs/reference/Autoload.md b/docs/reference/Autoload.md index 2b91db95f5..62aea34703 100644 --- a/docs/reference/Autoload.md +++ b/docs/reference/Autoload.md @@ -1,18 +1,21 @@ ## Codeception\Util\Autoload + + Autoloader, which is fully compatible with PSR-4, and can be used to autoload your `Helper`, `Page`, and `Step` classes. + #### __construct() - *private* __construct() + *private* __construct() -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Autoload.php#L18) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Autoload.php#L18) #### addNamespace() - *public static* addNamespace($prefix, $base_dir, $prepend = null) + *public static* addNamespace($prefix, $base_dir, $prepend = null) Adds a base directory for a namespace prefix. @@ -36,17 +39,17 @@ Autoload::addNamespace('app\Codeception', '/path/to/controllers'); this causes it to be searched first rather than last. * `return` void -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Autoload.php#L45) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Autoload.php#L45) #### load() - *public static* load($class) + *public static* load($class) -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Autoload.php#L88) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Autoload.php#L88) #### loadMappedFile() - *protected static* loadMappedFile($prefix, $relative_class) + *protected static* loadMappedFile($prefix, $relative_class) Load the mapped file for a namespace prefix and relative class. @@ -54,26 +57,26 @@ Load the mapped file for a namespace prefix and relative class. * `param string` $relative_class The relative class name. * `return` mixed Boolean false if no mapped file can be loaded, or the name of the mapped file that was loaded. -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Autoload.php#L136) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Autoload.php#L136) #### register() - *public static* register($namespace, $suffix, $path) + *public static* register($namespace, $suffix, $path) * `deprecated` Use self::addNamespace() instead. -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Autoload.php#L75) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Autoload.php#L75) #### registerSuffix() - *public static* registerSuffix($suffix, $path) + *public static* registerSuffix($suffix, $path) * `deprecated` Use self::addNamespace() instead. -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Autoload.php#L83) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Autoload.php#L83) #### requireFile() - *protected static* requireFile($file) + *protected static* requireFile($file) -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Autoload.php#L156) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Autoload.php#L156) -

 

Reference is taken from the source code. Help us to improve documentation. Edit module reference
+

 

Reference is taken from the source code. Help us to improve documentation. Edit module reference
diff --git a/docs/reference/Commands.md b/docs/reference/Commands.md index 097d861e17..d94e112203 100644 --- a/docs/reference/Commands.md +++ b/docs/reference/Commands.md @@ -9,6 +9,9 @@ Shows step by step execution process for scenario driven tests without actually * `codecept dry-run acceptance checkout.feature` * `codecept dry-run tests/acceptance/MyCest.php` + + + ## GenerateSuite Create new test suite. Requires suite name and actor name @@ -18,6 +21,9 @@ Create new test suite. Requires suite name and actor name * `codecept g:suite integration Code` -> integration + CodeTester * `codecept g:suite frontend Front` -> frontend + FrontTester + + + ## GherkinSnippets Generates code snippets for matched feature files in a suite. @@ -30,14 +36,20 @@ Usage: * `codecept gherkin:snippets acceptance user_account.feature` - snippets from a single feature file * `codecept gherkin:snippets acceptance/feature/users/user_accout.feature` - snippets from feature file in a dir + + ## Init + + ## Console Try to execute test commands in run-time. You may try commands before writing the test. * `codecept console acceptance` - starts acceptance suite environment. If you use WebDriver you can manipulate browser with Codeception commands. + + ## ConfigValidate Validates and prints Codeception config. @@ -59,12 +71,17 @@ Check overriding config values (like in `run` command) * `codecept config:validate -o "settings: lint: false"`: disable linting * `codecept config:validate -o "reporters: report: \Custom\Reporter" --report`: use custom reporter + + + ## GenerateGroup Creates empty GroupObject - extension which handles all group events. * `codecept g:group Admin` + + ## GenerateCept Generates Cept (scenario-driven test) file: @@ -73,6 +90,9 @@ Generates Cept (scenario-driven test) file: * `codecept g:cept suite subdir/subdir/testnameCept.php` * `codecept g:cept suite LoginCept -c path/to/project` + + + ## Run Executes tests. @@ -135,7 +155,7 @@ Options: --coverage-html Generate CodeCoverage HTML report in path (default: "coverage") --coverage-xml Generate CodeCoverage XML report in file (default: "coverage.xml") --coverage-text Generate CodeCoverage text report in file (default: "coverage.txt") - --coverage-phpunit Generate CodeCoverage PHPUnit report in path (default: "coverage-phpunit") + --coverage-phpunit Generate CodeCoverage PHPUnit report in file (default: "coverage-phpunit") --no-exit Don't finish with exit code --group (-g) Groups of tests to be executed (multiple values allowed) --skip (-s) Skip selected suites (multiple values allowed) @@ -151,6 +171,9 @@ Options: --no-interaction (-n) Do not ask any interactive question. ``` + + + ## SelfUpdate Auto-updates phar archive from official site: 'http://codeception.com/codecept.phar' . @@ -159,8 +182,12 @@ Auto-updates phar archive from official site: 'http://codeception.com/codecept.p @author Franck Cassedanne + + ## CompletionFallback + + ## GenerateTest Generates skeleton for Unit Test that extends `Codeception\TestCase\Test`. @@ -168,6 +195,8 @@ Generates skeleton for Unit Test that extends `Codeception\TestCase\Test`. * `codecept g:test unit User` * `codecept g:test unit "App\User"` + + ## Build Generates Actor classes (initially Guy classes) from suite configs. @@ -176,6 +205,9 @@ Starting from Codeception 2.0 actor classes are auto-generated. Use this command * `codecept build` * `codecept build path/to/project` + + + ## GenerateHelper Creates empty Helper class. @@ -183,6 +215,9 @@ Creates empty Helper class. * `codecept g:helper MyHelper` * `codecept g:helper "My\Helper"` + + + ## Bootstrap Creates default config, tests directory and sample suites for current project. @@ -196,6 +231,9 @@ By default it will create 3 suites **acceptance**, **functional**, and **unit**. * `codecept bootstrap --actor Wizard` - sets actor as Wizard, to have `TestWizard` actor in tests. * `codecept bootstrap path/to/the/project` - provide different path to a project, where tests should be placed + + + ## GenerateEnvironment Generates empty environment configuration file into envs dir: @@ -204,6 +242,8 @@ Generates empty environment configuration file into envs dir: Required to have `envs` path to be specified in `codeception.yml` + + ## GenerateFeature Generates Feature file (in Gherkin): @@ -212,6 +252,9 @@ Generates Feature file (in Gherkin): * `codecept g:feature suite subdir/subdir/login.feature` * `codecept g:feature suite login.feature -c path/to/project` + + + ## GenerateScenarios Generates user-friendly text scenarios from scenario-driven tests (Cest, Cept). @@ -220,6 +263,8 @@ Generates user-friendly text scenarios from scenario-driven tests (Cest, Cept). * `codecept g:scenarios acceptance --format html` - in html format * `codecept g:scenarios acceptance --path doc` - generate scenarios to `doc` dir + + ## GenerateStepObject Generates StepObject class. You will be asked for steps you want to implement. @@ -227,12 +272,17 @@ Generates StepObject class. You will be asked for steps you want to implement. * `codecept g:stepobject acceptance AdminSteps` * `codecept g:stepobject acceptance UserSteps --silent` - skip action questions + + + ## Clean -Cleans `output` directory +Recursively cleans `output` directory and generated code. * `codecept clean` -* `codecept clean -c path/to/project` + + + ## GherkinSteps @@ -242,6 +292,10 @@ Prints all steps from all Gherkin contexts for a specific suite codecept gherkin:steps acceptance ``` + + + + ## GenerateCest Generates Cest (scenario-driven object-oriented test) file: @@ -251,6 +305,9 @@ Generates Cest (scenario-driven object-oriented test) file: * `codecept g:cest suite LoginCest -c path/to/project` * `codecept g:cest "App\Login"` + + + ## GeneratePageObject Generates PageObject. Can be generated either globally, or just for one suite. @@ -260,3 +317,5 @@ If PageObject is generated globally it will act as UIMap, without any logic in i * `codecept g:page Registration` * `codecept g:page acceptance Login` + + diff --git a/docs/reference/Fixtures.md b/docs/reference/Fixtures.md index d6055fa68d..ac7a1257da 100644 --- a/docs/reference/Fixtures.md +++ b/docs/reference/Fixtures.md @@ -1,6 +1,8 @@ ## Codeception\Util\Fixtures + + Really basic class to store data in global array and use it in Cests/Tests. ```php @@ -12,28 +14,30 @@ Fixtures::exists('user1'); ?> ``` + + #### add() - *public static* add($name, $data) + *public static* add($name, $data) -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Fixtures.php#L21) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Fixtures.php#L21) #### cleanup() - *public static* cleanup() + *public static* cleanup() -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Fixtures.php#L35) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Fixtures.php#L35) #### exists() - *public static* exists($name) + *public static* exists($name) -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Fixtures.php#L40) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Fixtures.php#L40) #### get() - *public static* get($name) + *public static* get($name) -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Fixtures.php#L26) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Fixtures.php#L26) -

 

Reference is taken from the source code. Help us to improve documentation. Edit module reference
+

 

Reference is taken from the source code. Help us to improve documentation. Edit module reference
diff --git a/docs/reference/HttpCode.md b/docs/reference/HttpCode.md index 15381af26d..5add442112 100644 --- a/docs/reference/HttpCode.md +++ b/docs/reference/HttpCode.md @@ -1,6 +1,8 @@ ## Codeception\Util\HttpCode + + Class containing constants of HTTP Status Codes and method to print HTTP code with its description. @@ -15,9 +17,12 @@ $I->seeResponseCodeIs(HttpCode::OK); $I->dontSeeResponseCodeIs(HttpCode::NOT_FOUND); ``` + + + #### getDescription() - *public static* getDescription($code) + *public static* getDescription($code) Returns string with HTTP code and its description @@ -30,6 +35,6 @@ HttpCode::getDescription(401); // '401 (Unauthorized)' * `param` $code * `return` mixed -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/HttpCode.php#L155) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/HttpCode.php#L155) -

 

Reference is taken from the source code. Help us to improve documentation. Edit module reference
+

 

Reference is taken from the source code. Help us to improve documentation. Edit module reference
diff --git a/docs/reference/InitTemplate.md b/docs/reference/InitTemplate.md index d6eb2a0a37..d4179730fc 100644 --- a/docs/reference/InitTemplate.md +++ b/docs/reference/InitTemplate.md @@ -1,12 +1,14 @@ ## Codeception\InitTemplate + * *Uses* `Codeception\Command\Shared\FileSystem`, `Codeception\Command\Shared\Style` Codeception templates allow creating a customized setup and configuration for your project. An abstract class for installation template. Each init template should extend it and implement a `setup` method. Use it to build a custom setup class which can be started with `codecept init` command. + ```php ask('do you want to proceed (y/n)', true); * `param null` $answer * `return` mixed|string -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/InitTemplate.php#L107) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/InitTemplate.php#L107) #### breakParts() - *protected* breakParts($class) + *protected* breakParts($class) -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Shared/Namespaces.php#L6) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Shared/Namespaces.php#L6) #### checkInstalled() - *protected* checkInstalled($dir = null) + *protected* checkInstalled($dir = null) -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/InitTemplate.php#L208) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/InitTemplate.php#L208) #### completeSuffix() - *protected* completeSuffix($filename, $suffix) + *protected* completeSuffix($filename, $suffix) -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Command/Shared/FileSystem.php#L25) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Command/Shared/FileSystem.php#L25) #### createActor() - *protected* createActor($name, $directory, $suiteConfig) + *protected* createActor($name, $directory, $suiteConfig) Create an Actor class and generate actions for it. Requires a suite config as array in 3rd parameter. @@ -83,87 +86,87 @@ Requires a suite config as array in 3rd parameter. * `param` $directory * `param` $suiteConfig -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/InitTemplate.php#L223) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/InitTemplate.php#L223) #### createDirectoryFor() - *protected* createDirectoryFor($basePath, $className = null) + *protected* createDirectoryFor($basePath, $className = null) -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Command/Shared/FileSystem.php#L10) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Command/Shared/FileSystem.php#L10) #### createEmptyDirectory() - *protected* createEmptyDirectory($dir) + *protected* createEmptyDirectory($dir) Create an empty directory and add a placeholder file into it * `param` $dir -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/InitTemplate.php#L195) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/InitTemplate.php#L195) #### createFile() - *protected* createFile($filename, $contents, $force = null, $flags = null) + *protected* createFile($filename, $contents, $force = null, $flags = null) -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Command/Shared/FileSystem.php#L46) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Command/Shared/FileSystem.php#L46) #### createHelper() - *protected* createHelper($name, $directory) + *protected* createHelper($name, $directory) Create a helper class inside a directory * `param` $name * `param` $directory -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/InitTemplate.php#L174) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/InitTemplate.php#L174) #### getNamespaceHeader() - *protected* getNamespaceHeader($class) + *protected* getNamespaceHeader($class) -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Shared/Namespaces.php#L31) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Shared/Namespaces.php#L31) #### getNamespaceString() - *protected* getNamespaceString($class) + *protected* getNamespaceString($class) -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Shared/Namespaces.php#L25) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Shared/Namespaces.php#L25) #### getNamespaces() - *protected* getNamespaces($class) + *protected* getNamespaces($class) -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Shared/Namespaces.php#L40) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Shared/Namespaces.php#L40) #### getShortClassName() - *protected* getShortClassName($class) + *protected* getShortClassName($class) -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Shared/Namespaces.php#L19) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Shared/Namespaces.php#L19) #### gitIgnore() - *protected* gitIgnore($path) + *protected* gitIgnore($path) -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/InitTemplate.php#L201) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/InitTemplate.php#L201) #### initDir() - *public* initDir($workDir) + *public* initDir($workDir) Change the directory where Codeception should be installed. -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/InitTemplate.php#L75) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/InitTemplate.php#L75) #### removeSuffix() - *protected* removeSuffix($classname, $suffix) + *protected* removeSuffix($classname, $suffix) -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Command/Shared/FileSystem.php#L40) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Command/Shared/FileSystem.php#L40) #### say() - *protected* say($message = null) + *protected* say($message = null) Print a message to console. @@ -172,44 +175,45 @@ Print a message to console. $this->say('Welcome to Setup'); ``` + * `param string` $message -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/InitTemplate.php#L136) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/InitTemplate.php#L136) #### sayInfo() - *protected* sayInfo($message) + *protected* sayInfo($message) Print info message * `param` $message -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/InitTemplate.php#L163) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/InitTemplate.php#L163) #### saySuccess() - *protected* saySuccess($message) + *protected* saySuccess($message) Print a successful message * `param` $message -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/InitTemplate.php#L145) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/InitTemplate.php#L145) #### sayWarning() - *protected* sayWarning($message) + *protected* sayWarning($message) Print warning message * `param` $message -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/InitTemplate.php#L154) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/InitTemplate.php#L154) #### setup() - *abstract public* setup() + *abstract public* setup() Override this class to create customized setup. * `return` mixed -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/InitTemplate.php#L88) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/InitTemplate.php#L88) -

 

Reference is taken from the source code. Help us to improve documentation. Edit module reference
+

 

Reference is taken from the source code. Help us to improve documentation. Edit module reference
diff --git a/docs/reference/JsonType.md b/docs/reference/JsonType.md index beff957777..4cab25cfe5 100644 --- a/docs/reference/JsonType.md +++ b/docs/reference/JsonType.md @@ -1,6 +1,8 @@ ## Codeception\Util\JsonType + + JsonType matches JSON structures against templates. You can specify the type of fields in JSON or add additional validation rules. @@ -25,9 +27,10 @@ $jsonType->matches([ Class JsonType @package Codeception\Util + #### __construct() - *public* __construct($jsonArray) + *public* __construct($jsonArray) Creates instance of JsonType Pass an array or `\Codeception\Util\JsonArray` with data. @@ -35,11 +38,11 @@ If non-associative array is passed - the very first element of it will be used f * `param` $jsonArray array|\Codeception\Util\JsonArray -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/JsonType.php#L42) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/JsonType.php#L42) #### addCustomFilter() - *public static* addCustomFilter($name, callable $callable) + *public static* addCustomFilter($name, callable $callable) Adds custom filter to JsonType list. You should specify a name and parameters of a filter. @@ -53,6 +56,7 @@ JsonType::addCustomFilter('slug', function($value) { }); // => use it as 'string:slug' + // add custom function to matcher with `len($val)` syntax // parameter matching patterns should be valid regex and start with `/` char JsonType::addCustomFilter('/len\((.*?)\)/', function($value, $len) { @@ -65,25 +69,25 @@ JsonType::addCustomFilter('/len\((.*?)\)/', function($value, $len) { * `param` $name * `param callable` $callable -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/JsonType.php#L76) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/JsonType.php#L76) #### cleanCustomFilters() - *public static* cleanCustomFilters() + *public static* cleanCustomFilters() Removes all custom filters -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/JsonType.php#L84) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/JsonType.php#L84) #### matchFilter() - *protected* matchFilter($filter, $value) + *protected* matchFilter($filter, $value) -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/JsonType.php#L158) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/JsonType.php#L158) #### matches() - *public* matches(array $jsonType) + *public* matches(array $jsonType) Checks data against passed JsonType. If matching fails function returns a string with a message describing failure. @@ -92,12 +96,12 @@ On success returns `true`. * `param array` $jsonType * `return` bool|string -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/JsonType.php#L97) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/JsonType.php#L97) #### typeComparison() - *protected* typeComparison($data, $jsonType) + *protected* typeComparison($data, $jsonType) -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/JsonType.php#L116) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/JsonType.php#L116) -

 

Reference is taken from the source code. Help us to improve documentation. Edit module reference
+

 

Reference is taken from the source code. Help us to improve documentation. Edit module reference
diff --git a/docs/reference/Locator.md b/docs/reference/Locator.md index 734c8bdbeb..ae78463fa6 100644 --- a/docs/reference/Locator.md +++ b/docs/reference/Locator.md @@ -1,12 +1,16 @@ ## Codeception\Util\Locator + + Set of useful functions for using CSS and XPath locators. Please check them before writing complex functional or acceptance tests. + + #### combine() - *public static* combine($selector1, $selector2) + *public static* combine($selector1, $selector2) Applies OR operator to any number of CSS or XPath selectors. You can mix up CSS and XPath selectors here. @@ -31,17 +35,17 @@ $I->fillField(Locator::combine('form input[type=text]','//form/textarea[2]'), 'q ``` As a result the Locator will produce a mixed XPath value that will be used in fillField action. - * `static` + * `static` * `param` $selector1 * `param` $selector2 * `throws` \Exception * `return` string -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Locator.php#L50) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Locator.php#L50) #### contains() - *public static* contains($element, $text) + *public static* contains($element, $text) Locates an element containing a text inside. Either CSS or XPath locator can be passed, however they will be converted to XPath. @@ -58,11 +62,11 @@ Locator::contains('div[@contenteditable=true]', 'hello world'); * `param` $text * `return` string -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Locator.php#L292) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Locator.php#L292) #### elementAt() - *public static* elementAt($element, $position) + *public static* elementAt($element, $position) Locates element at position. Either CSS or XPath locator can be passed as locator, @@ -82,11 +86,11 @@ Locator::elementAt('table#grind>tr', -2); // previous than last row * `param int` $position xpath index * `return` mixed -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Locator.php#L318) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Locator.php#L318) #### find() - *public static* find($element, array $attributes) + *public static* find($element, array $attributes) Finds element by it's attribute(s) @@ -96,16 +100,16 @@ use \Codeception\Util\Locator; $I->seeElement(Locator::find('img', ['title' => 'diagram'])); ``` - * `static` + * `static` * `param` $element * `param` $attributes * `return` string -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Locator.php#L159) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Locator.php#L159) #### firstElement() - *public static* firstElement($element) + *public static* firstElement($element) Locates first element of group elements. Either CSS or XPath locator can be passed as locator, @@ -121,11 +125,11 @@ Locator::firstElement('//table/tr'); * `param` $element * `return` mixed -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Locator.php#L348) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Locator.php#L348) #### href() - *public static* href($url) + *public static* href($url) Matches the *a* element with given URL @@ -136,26 +140,26 @@ use \Codeception\Util\Locator; $I->see('Log In', Locator::href('/login.php')); ?> ``` - * `static` + * `static` * `param` $url * `return` string -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Locator.php#L79) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Locator.php#L79) #### humanReadableString() - *public static* humanReadableString($selector) + *public static* humanReadableString($selector) Transforms strict locator, \Facebook\WebDriver\WebDriverBy into a string represenation * `param` $selector * `return` string -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Locator.php#L381) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Locator.php#L381) #### isCSS() - *public static* isCSS($selector) + *public static* isCSS($selector) Checks that provided string is CSS selector @@ -169,11 +173,11 @@ Locator::isCSS('//body/p/user') => false * `param` $selector * `return` bool -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Locator.php#L186) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Locator.php#L186) #### isClass() - *public static* isClass($class) + *public static* isClass($class) Checks that a string is valid CSS class @@ -187,11 +191,11 @@ Locator::isClass('//body/p/user') => false * `param` $class * `return` bool -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Locator.php#L270) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Locator.php#L270) #### isID() - *public static* isID($id) + *public static* isID($id) Checks that a string is valid CSS ID @@ -205,20 +209,20 @@ Locator::isID('//body/p/user') => false * `param` $id * `return` bool -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Locator.php#L252) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Locator.php#L252) #### isPrecise() - *public static* isPrecise($locator) + *public static* isPrecise($locator) * `param` $locator * `return` bool -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Locator.php#L221) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Locator.php#L221) #### isXPath() - *public static* isXPath($locator) + *public static* isXPath($locator) Checks that locator is an XPath @@ -232,11 +236,11 @@ Locator::isXPath('//body/p/user') => true * `param` $locator * `return` bool -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Locator.php#L210) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Locator.php#L210) #### lastElement() - *public static* lastElement($element) + *public static* lastElement($element) Locates last element of group elements. Either CSS or XPath locator can be passed as locator, @@ -252,11 +256,11 @@ Locator::lastElement('//table/tr'); * `param` $element * `return` mixed -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Locator.php#L369) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Locator.php#L369) #### option() - *public static* option($value) + *public static* option($value) Matches option by text: @@ -270,11 +274,11 @@ $I->seeElement(Locator::option('Male'), '#select-gender'); * `param` $value * `return` string -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Locator.php#L124) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Locator.php#L124) #### tabIndex() - *public static* tabIndex($index) + *public static* tabIndex($index) Matches the element with given tab index @@ -289,16 +293,16 @@ $I->fillField(Locator::tabIndex(2) , 'qwerty'); $I->click('Login'); ?> ``` - * `static` + * `static` * `param` $index * `return` string -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Locator.php#L105) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Locator.php#L105) #### toXPath() - *protected static* toXPath($selector) + *protected static* toXPath($selector) -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Locator.php#L129) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Locator.php#L129) -

 

Reference is taken from the source code. Help us to improve documentation. Edit module reference
+

 

Reference is taken from the source code. Help us to improve documentation. Edit module reference
diff --git a/docs/reference/Mock.md b/docs/reference/Mock.md index e5db211b8f..20b859e31f 100644 --- a/docs/reference/Mock.md +++ b/docs/reference/Mock.md @@ -1,9 +1,7 @@ # Mocks Declare mocks inside `Codeception\Test\Unit` class. -If you want to use mocks outside it, check the reference for [Codeception/Stub](https://github.com/Codeception/Stub) library. - - +If you want to use mocks outside it, check the reference for [Codeception/Stub](https://github.com/Codeception/Stub) library. #### *public* make($class, $params = null) @@ -33,16 +31,6 @@ and it's return value or callback function as parameter make('User', ['save' => function () { return true; }]); $this->make('User', ['save' => true]); -?> -``` - -**To create a mock, pass current testcase name as last argument:** - -```php -make('User', [ - 'save' => \Codeception\Stub\Expected::once() -]); ``` * `param mixed` $class - A class to be mocked @@ -78,15 +66,6 @@ and it's return value or callback function as parameter makeEmpty('User', ['save' => function () { return true; }]); $this->makeEmpty('User', ['save' => true)); -``` - -**To create a mock, pass current testcase name as last argument:** - -```php -makeEmpty('User', [ - 'save' => \Codeception\Stub\Expected::once() -]); ``` * `param mixed` $class @@ -124,16 +103,6 @@ and it's return value or callback function as parameter makeEmptyExcept('User', 'save', ['isValid' => function () { return true; }]); $this->makeEmptyExcept('User', 'save', ['isValid' => true]); -?> -``` - -**To create a mock, pass current testcase name as last argument:** - -```php -makeEmptyExcept('User', 'validate', [ - 'save' => \Codeception\Stub\Expected::once() -]); ``` * `param mixed` $class @@ -172,15 +141,6 @@ and it's return value or callback function as parameter $this->construct('User', [], ['save' => function () { return true; }]); $this->construct('User', [], ['save' => true]); ?> -``` - -**To create a mock, pass current testcase name as last argument:** - -```php -construct('User', [], [ - 'save' => \Codeception\Stub\Expected::once() -]); ``` * `param mixed` $class @@ -263,15 +223,6 @@ and it's return value or callback function as parameter $this->constructEmptyExcept('User', 'save', [], ['save' => function () { return true; }]); $this->constructEmptyExcept('User', 'save', [], ['save' => true]); ?> -``` - -**To create a mock, pass current testcase name as last argument:** - -```php -constructEmptyExcept('User', 'save', [], [ - 'save' => \Codeception\Stub\Expected::once() -]); ``` * `param mixed` $class diff --git a/docs/reference/Module.md b/docs/reference/Module.md index dc3d3d81bb..7697eff883 100644 --- a/docs/reference/Module.md +++ b/docs/reference/Module.md @@ -1,6 +1,7 @@ ## Codeception\Module + * *Uses* `Codeception\Util\Shared\Asserts` Basic class for Modules and Helpers. @@ -9,6 +10,9 @@ You must extend from it while implementing own helpers. Public methods of this class start with `_` prefix in order to ignore them in actor classes. Module contains **HOOKS** which allow to handle test execution routine. + + + #### $includeInheritedActions *public static* **$includeInheritedActions** @@ -17,6 +21,7 @@ By setting it to false module wan't inherit methods of parent class. type `bool` + #### $onlyActions *public static* **$onlyActions** @@ -25,6 +30,7 @@ Allows to explicitly set what methods have this class. type `array` + #### $excludeActions *public static* **$excludeActions** @@ -33,6 +39,7 @@ Allows to explicitly exclude actions from module. type `array` + #### $aliases *public static* **$aliases** @@ -42,7 +49,7 @@ Allows to rename actions type `array` #### __construct() - *public* __construct($moduleContainer, $config = null) + *public* __construct($moduleContainer, $config = null) Module constructor. @@ -51,117 +58,117 @@ Requires module container (to provide access between modules of suite) and confi * `param ModuleContainer` $moduleContainer * `param null` $config -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Module.php#L70) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Module.php#L70) #### _after() - *public* _after($test) + *public* _after($test) **HOOK** executed after test * `param TestInterface` $test -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Module.php#L253) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Module.php#L253) #### _afterStep() - *public* _afterStep($step) + *public* _afterStep($step) **HOOK** executed after step * `param Step` $step -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Module.php#L235) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Module.php#L235) #### _afterSuite() - *public* _afterSuite() + *public* _afterSuite() **HOOK** executed after suite -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Module.php#L217) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Module.php#L217) #### _before() - *public* _before($test) + *public* _before($test) **HOOK** executed before test * `param TestInterface` $test -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Module.php#L244) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Module.php#L244) #### _beforeStep() - *public* _beforeStep($step) + *public* _beforeStep($step) **HOOK** executed before step * `param Step` $step -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Module.php#L226) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Module.php#L226) #### _beforeSuite() - *public* _beforeSuite($settings = null) + *public* _beforeSuite($settings = null) **HOOK** executed before suite * `param array` $settings -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Module.php#L210) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Module.php#L210) #### _failed() - *public* _failed($test, $fail) + *public* _failed($test, $fail) **HOOK** executed when test fails but before `_after` * `param TestInterface` $test * `param \Exception` $fail -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Module.php#L263) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Module.php#L263) #### _getConfig() - *public* _getConfig($key = null) + *public* _getConfig($key = null) Get config values or specific config item. * `param null` $key * `return` array|mixed|null -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Module.php#L338) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Module.php#L338) #### _getName() - *public* _getName() + *public* _getName() Returns a module name for a Module, a class name for Helper * `return` string -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Module.php#L177) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Module.php#L177) #### _hasRequiredFields() - *public* _hasRequiredFields() + *public* _hasRequiredFields() Checks if a module has required fields * `return` bool -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Module.php#L193) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Module.php#L193) #### _initialize() - *public* _initialize() + *public* _initialize() **HOOK** triggered after module is created and configuration is loaded -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Module.php#L201) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Module.php#L201) #### _reconfigure() - *public* _reconfigure($config) + *public* _reconfigure($config) Allows to redefine config for a specific test. Config is restored at the end of a test. @@ -180,19 +187,19 @@ public function _before(Test $test) { * `throws` Exception\ModuleConfigException * `throws` ModuleException -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Module.php#L119) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Module.php#L119) #### _resetConfig() - *public* _resetConfig() + *public* _resetConfig() Reverts config changed by `_reconfigure` -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Module.php#L137) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Module.php#L137) #### _setConfig() - *public* _setConfig($config) + *public* _setConfig($config) Allows to define initial module config. Can be used in `_beforeSuite` hook of Helpers or Extensions @@ -208,37 +215,37 @@ public function _beforeSuite($settings = []) { * `throws` Exception\ModuleConfigException * `throws` ModuleException -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Module.php#L95) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Module.php#L95) #### assert() - *protected* assert($arguments, $not = null) + *protected* assert($arguments, $not = null) -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Shared/Asserts.php#L6) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Shared/Asserts.php#L6) #### assertArrayHasKey() - *protected* assertArrayHasKey($key, $actual, $description = null) + *protected* assertArrayHasKey($key, $actual, $description = null) * `param` $key * `param` $actual * `param` $description -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Shared/Asserts.php#L363) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Shared/Asserts.php#L363) #### assertArrayNotHasKey() - *protected* assertArrayNotHasKey($key, $actual, $description = null) + *protected* assertArrayNotHasKey($key, $actual, $description = null) * `param` $key * `param` $actual * `param` $description -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Shared/Asserts.php#L373) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Shared/Asserts.php#L373) #### assertArraySubset() - *protected* assertArraySubset($subset, $array, $strict = null, $message = null) + *protected* assertArraySubset($subset, $array, $strict = null, $message = null) Checks that array contains subset. @@ -247,11 +254,11 @@ Checks that array contains subset. * `param bool` $strict * `param string` $message -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Shared/Asserts.php#L386) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Shared/Asserts.php#L386) #### assertContains() - *protected* assertContains($needle, $haystack, $message = null) + *protected* assertContains($needle, $haystack, $message = null) Checks that haystack contains needle @@ -259,32 +266,32 @@ Checks that haystack contains needle * `param` $haystack * `param string` $message -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Shared/Asserts.php#L149) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Shared/Asserts.php#L149) #### assertCount() - *protected* assertCount($expectedCount, $actual, $description = null) + *protected* assertCount($expectedCount, $actual, $description = null) * `param` $expectedCount * `param` $actual * `param` $description -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Shared/Asserts.php#L396) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Shared/Asserts.php#L396) #### assertEmpty() - *protected* assertEmpty($actual, $message = null) + *protected* assertEmpty($actual, $message = null) Checks that variable is empty. * `param` $actual * `param string` $message -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Shared/Asserts.php#L221) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Shared/Asserts.php#L221) #### assertEquals() - *protected* assertEquals($expected, $actual, $message = null, $delta = null) + *protected* assertEquals($expected, $actual, $message = null, $delta = null) Checks that two variables are equal. @@ -293,54 +300,54 @@ Checks that two variables are equal. * `param string` $message * `param float` $delta -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Shared/Asserts.php#L35) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Shared/Asserts.php#L35) #### assertFalse() - *protected* assertFalse($condition, $message = null) + *protected* assertFalse($condition, $message = null) Checks that condition is negative. * `param` $condition * `param string` $message -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Shared/Asserts.php#L276) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Shared/Asserts.php#L276) #### assertFileExists() - *protected* assertFileExists($filename, $message = null) + *protected* assertFileExists($filename, $message = null) Checks if file exists * `param string` $filename * `param string` $message -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Shared/Asserts.php#L312) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Shared/Asserts.php#L312) #### assertFileNotExists() - *protected* assertFileNotExists($filename, $message = null) + *protected* assertFileNotExists($filename, $message = null) Checks if file doesn't exist * `param string` $filename * `param string` $message -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Shared/Asserts.php#L324) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Shared/Asserts.php#L324) #### assertGreaterOrEquals() - *protected* assertGreaterOrEquals($expected, $actual, $description = null) + *protected* assertGreaterOrEquals($expected, $actual, $description = null) * `param` $expected * `param` $actual * `param` $description -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Shared/Asserts.php#L334) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Shared/Asserts.php#L334) #### assertGreaterThan() - *protected* assertGreaterThan($expected, $actual, $message = null) + *protected* assertGreaterThan($expected, $actual, $message = null) Checks that actual is greater than expected @@ -348,11 +355,11 @@ Checks that actual is greater than expected * `param` $actual * `param string` $message -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Shared/Asserts.php#L84) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Shared/Asserts.php#L84) #### assertGreaterThanOrEqual() - *protected* assertGreaterThanOrEqual($expected, $actual, $message = null) + *protected* assertGreaterThanOrEqual($expected, $actual, $message = null) Checks that actual is greater or equal than expected @@ -360,62 +367,62 @@ Checks that actual is greater or equal than expected * `param` $actual * `param string` $message -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Shared/Asserts.php#L104) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Shared/Asserts.php#L104) #### assertGreaterThen() - *protected* assertGreaterThen($expected, $actual, $message = null) - * `deprecated` -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Shared/Asserts.php#L92) + *protected* assertGreaterThen($expected, $actual, $message = null) + * `deprecated` +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Shared/Asserts.php#L92) #### assertGreaterThenOrEqual() - *protected* assertGreaterThenOrEqual($expected, $actual, $message = null) - * `deprecated` -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Shared/Asserts.php#L112) + *protected* assertGreaterThenOrEqual($expected, $actual, $message = null) + * `deprecated` +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Shared/Asserts.php#L112) #### assertInstanceOf() - *protected* assertInstanceOf($class, $actual, $description = null) + *protected* assertInstanceOf($class, $actual, $description = null) * `param` $class * `param` $actual * `param` $description -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Shared/Asserts.php#L406) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Shared/Asserts.php#L406) #### assertInternalType() - *protected* assertInternalType($type, $actual, $description = null) + *protected* assertInternalType($type, $actual, $description = null) * `param` $type * `param` $actual * `param` $description -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Shared/Asserts.php#L426) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Shared/Asserts.php#L426) #### assertIsEmpty() - *protected* assertIsEmpty($actual, $description = null) + *protected* assertIsEmpty($actual, $description = null) * `param` $actual * `param` $description -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Shared/Asserts.php#L353) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Shared/Asserts.php#L353) #### assertLessOrEquals() - *protected* assertLessOrEquals($expected, $actual, $description = null) + *protected* assertLessOrEquals($expected, $actual, $description = null) * `param` $expected * `param` $actual * `param` $description -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Shared/Asserts.php#L344) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Shared/Asserts.php#L344) #### assertLessThan() - *protected* assertLessThan($expected, $actual, $message = null) + *protected* assertLessThan($expected, $actual, $message = null) Checks that actual is less than expected @@ -423,11 +430,11 @@ Checks that actual is less than expected * `param` $actual * `param string` $message -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Shared/Asserts.php#L124) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Shared/Asserts.php#L124) #### assertLessThanOrEqual() - *protected* assertLessThanOrEqual($expected, $actual, $message = null) + *protected* assertLessThanOrEqual($expected, $actual, $message = null) Checks that actual is less or equal than expected @@ -435,17 +442,17 @@ Checks that actual is less or equal than expected * `param` $actual * `param string` $message -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Shared/Asserts.php#L136) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Shared/Asserts.php#L136) #### assertNot() - *protected* assertNot($arguments) + *protected* assertNot($arguments) -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Shared/Asserts.php#L22) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Shared/Asserts.php#L22) #### assertNotContains() - *protected* assertNotContains($needle, $haystack, $message = null) + *protected* assertNotContains($needle, $haystack, $message = null) Checks that haystack doesn't contain needle. @@ -453,22 +460,22 @@ Checks that haystack doesn't contain needle. * `param` $haystack * `param string` $message -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Shared/Asserts.php#L161) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Shared/Asserts.php#L161) #### assertNotEmpty() - *protected* assertNotEmpty($actual, $message = null) + *protected* assertNotEmpty($actual, $message = null) Checks that variable is not empty. * `param` $actual * `param string` $message -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Shared/Asserts.php#L232) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Shared/Asserts.php#L232) #### assertNotEquals() - *protected* assertNotEquals($expected, $actual, $message = null, $delta = null) + *protected* assertNotEquals($expected, $actual, $message = null, $delta = null) Checks that two variables are not equal @@ -477,32 +484,32 @@ Checks that two variables are not equal * `param string` $message * `param float` $delta -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Shared/Asserts.php#L48) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Shared/Asserts.php#L48) #### assertNotInstanceOf() - *protected* assertNotInstanceOf($class, $actual, $description = null) + *protected* assertNotInstanceOf($class, $actual, $description = null) * `param` $class * `param` $actual * `param` $description -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Shared/Asserts.php#L416) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Shared/Asserts.php#L416) #### assertNotNull() - *protected* assertNotNull($actual, $message = null) + *protected* assertNotNull($actual, $message = null) Checks that variable is not NULL * `param` $actual * `param string` $message -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Shared/Asserts.php#L254) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Shared/Asserts.php#L254) #### assertNotRegExp() - *protected* assertNotRegExp($pattern, $string, $message = null) + *protected* assertNotRegExp($pattern, $string, $message = null) Checks that string not match with pattern @@ -510,11 +517,11 @@ Checks that string not match with pattern * `param string` $string * `param string` $message -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Shared/Asserts.php#L185) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Shared/Asserts.php#L185) #### assertNotSame() - *protected* assertNotSame($expected, $actual, $message = null) + *protected* assertNotSame($expected, $actual, $message = null) Checks that two variables are not same @@ -522,22 +529,22 @@ Checks that two variables are not same * `param` $actual * `param string` $message -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Shared/Asserts.php#L72) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Shared/Asserts.php#L72) #### assertNull() - *protected* assertNull($actual, $message = null) + *protected* assertNull($actual, $message = null) Checks that variable is NULL * `param` $actual * `param string` $message -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Shared/Asserts.php#L243) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Shared/Asserts.php#L243) #### assertRegExp() - *protected* assertRegExp($pattern, $string, $message = null) + *protected* assertRegExp($pattern, $string, $message = null) Checks that string match with pattern @@ -545,11 +552,11 @@ Checks that string match with pattern * `param string` $string * `param string` $message -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Shared/Asserts.php#L173) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Shared/Asserts.php#L173) #### assertSame() - *protected* assertSame($expected, $actual, $message = null) + *protected* assertSame($expected, $actual, $message = null) Checks that two variables are same @@ -557,11 +564,11 @@ Checks that two variables are same * `param` $actual * `param string` $message -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Shared/Asserts.php#L60) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Shared/Asserts.php#L60) #### assertStringStartsNotWith() - *protected* assertStringStartsNotWith($prefix, $string, $message = null) + *protected* assertStringStartsNotWith($prefix, $string, $message = null) Checks that a string doesn't start with the given prefix. @@ -569,11 +576,11 @@ Checks that a string doesn't start with the given prefix. * `param string` $string * `param string` $message -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Shared/Asserts.php#L209) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Shared/Asserts.php#L209) #### assertStringStartsWith() - *protected* assertStringStartsWith($prefix, $string, $message = null) + *protected* assertStringStartsWith($prefix, $string, $message = null) Checks that a string starts with the given prefix. @@ -581,21 +588,22 @@ Checks that a string starts with the given prefix. * `param string` $string * `param string` $message -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Shared/Asserts.php#L197) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Shared/Asserts.php#L197) #### assertThat() - *protected* assertThat($haystack, $constraint, $message = null) + *protected* assertThat($haystack, $constraint, $message = null) + * `param` $haystack * `param` $constraint * `param string` $message -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Shared/Asserts.php#L287) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Shared/Asserts.php#L287) #### assertThatItsNot() - *protected* assertThatItsNot($haystack, $constraint, $message = null) + *protected* assertThatItsNot($haystack, $constraint, $message = null) Checks that haystack doesn't attend @@ -603,53 +611,53 @@ Checks that haystack doesn't attend * `param` $constraint * `param string` $message -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Shared/Asserts.php#L299) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Shared/Asserts.php#L299) #### assertTrue() - *protected* assertTrue($condition, $message = null) + *protected* assertTrue($condition, $message = null) Checks that condition is positive. * `param` $condition * `param string` $message -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Shared/Asserts.php#L265) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Shared/Asserts.php#L265) #### debug() - *protected* debug($message) + *protected* debug($message) Print debug message to the screen. * `param` $message -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Module.php#L272) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Module.php#L272) #### debugSection() - *protected* debugSection($title, $message) + *protected* debugSection($title, $message) Print debug message with a title * `param` $title * `param` $message -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Module.php#L283) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Module.php#L283) #### fail() - *protected* fail($message) + *protected* fail($message) Fails the test with message. * `param` $message -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Util/Shared/Asserts.php#L436) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Util/Shared/Asserts.php#L436) #### getModule() - *protected* getModule($name) + *protected* getModule($name) Get another module by its name: @@ -662,50 +670,50 @@ $this->getModule('WebDriver')->_findElements('.items'); * `return` Module * `throws` ModuleException -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Module.php#L324) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Module.php#L324) #### getModules() - *protected* getModules() + *protected* getModules() Get all enabled modules * `return` array -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Module.php#L307) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Module.php#L307) #### hasModule() - *protected* hasModule($name) + *protected* hasModule($name) Checks that module is enabled. * `param` $name * `return` bool -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Module.php#L297) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Module.php#L297) #### onReconfigure() - *protected* onReconfigure() + *protected* onReconfigure() HOOK to be executed when config changes with `_reconfigure`. -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Module.php#L129) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Module.php#L129) #### scalarizeArray() - *protected* scalarizeArray($array) + *protected* scalarizeArray($array) -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Module.php#L349) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Module.php#L349) #### validateConfig() - *protected* validateConfig() + *protected* validateConfig() Validates current config for required fields and required packages. * `throws` Exception\ModuleConfigException * `throws` ModuleException -[See source](https://github.com/Codeception/Codeception/blob/2.3/src/Codeception/Module.php#L148) +[See source](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Module.php#L148) -

 

Reference is taken from the source code. Help us to improve documentation. Edit module reference
+

 

Reference is taken from the source code. Help us to improve documentation. Edit module reference
diff --git a/docs/reference/XmlBuilder.md b/docs/reference/XmlBuilder.md index a92855156a..05191c2590 100644 --- a/docs/reference/XmlBuilder.md +++ b/docs/reference/XmlBuilder.md @@ -1,10 +1,13 @@ ## Codeception\Util\XmlBuilder + + That's a pretty simple yet powerful class to build XML structures in jQuery-like style. With no XML line actually written! Uses DOM extension to manipulate XML data. + ```php  

Reference is taken from the source code. Help us to improve documentation. Edit module reference
+

 

Reference is taken from the source code. Help us to improve documentation. Edit module reference
diff --git a/ext/README.md b/ext/README.md index fde3094b17..a6748b32ff 100644 --- a/ext/README.md +++ b/ext/README.md @@ -2,7 +2,7 @@ ## DotReporter -[See Source](https://github.com/Codeception/Codeception/blob/2.3/ext/DotReporter.php) +[See Source](https://github.com/Codeception/Codeception/blob/2.4/ext/DotReporter.php) DotReporter provides less verbose output for test execution. Like PHPUnit printer it prints dots "." for successful testes and "F" for failures. @@ -24,6 +24,7 @@ Time: 2.07 seconds, Memory: 20.00MB OK (80 tests, 124 assertions) ``` + Enable this reporter with `--ext option` ``` @@ -33,9 +34,11 @@ codecept run --ext DotReporter Failures and Errors are printed by a standard Codeception reporter. Use this extension as an example for building custom reporters. + + ## Logger -[See Source](https://github.com/Codeception/Codeception/blob/2.3/ext/Logger.php) +[See Source](https://github.com/Codeception/Codeception/blob/2.4/ext/Logger.php) Log suites/tests/steps using Monolog library. Monolog should be installed additionally by Composer. @@ -57,9 +60,12 @@ extensions: * `max_files` (default: 3) - how many log files to keep + + + ## Recorder -[See Source](https://github.com/Codeception/Codeception/blob/2.3/ext/Recorder.php) +[See Source](https://github.com/Codeception/Codeception/blob/2.4/ext/Recorder.php) Saves a screenshot of each step in acceptance tests and shows them as a slideshow on one HTML page (here's an [example](http://codeception.com/images/recorder.gif)) Activated only for suites with WebDriver module enabled. @@ -81,6 +87,7 @@ extensions: * `delete_successful` (default: true) - delete screenshots for successfully passed tests (i.e. log only failed and errored tests). * `module` (default: WebDriver) - which module for screenshots to use. Set `AngularJS` if you want to use it with AngularJS module. Generally, the module should implement `Codeception\Lib\Interfaces\ScreenshotSaver` interface. + #### Examples: ``` yaml @@ -91,9 +98,12 @@ extensions: delete_successful: false # keep screenshots of successful tests ``` + + + ## RunFailed -[See Source](https://github.com/Codeception/Codeception/blob/2.3/ext/RunFailed.php) +[See Source](https://github.com/Codeception/Codeception/blob/2.4/ext/RunFailed.php) Saves failed tests into tests/log/failed in order to rerun failed tests. @@ -118,9 +128,11 @@ extensions: On each execution failed tests are logged and saved into `tests/_output/failed` file. + + ## RunProcess -[See Source](https://github.com/Codeception/Codeception/blob/2.3/ext/RunProcess.php) +[See Source](https://github.com/Codeception/Codeception/blob/2.4/ext/RunProcess.php) Extension to start and stop processes per suite. Can be used to start/stop selenium server, chromedriver, phantomjs, mailcatcher, etc. @@ -163,10 +175,14 @@ extensions: HINT: you can use different configurations per environment. + + ## SimpleReporter -[See Source](https://github.com/Codeception/Codeception/blob/2.3/ext/SimpleReporter.php) +[See Source](https://github.com/Codeception/Codeception/blob/2.4/ext/SimpleReporter.php) This extension demonstrates how you can implement console output of your own. Recommended to be used for development purposes only. + + diff --git a/readme.md b/readme.md index 49633e4a37..12451b2293 100644 --- a/readme.md +++ b/readme.md @@ -5,7 +5,7 @@ [![Daily Downloads](https://img.shields.io/packagist/dd/codeception/codeception.svg)](https://packagist.org/packages/codeception/codeception) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Codeception/Codeception?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![PHP 7 ready](http://php7ready.timesplinter.ch/Codeception/Codeception/badge.svg)](https://travis-ci.org/Codeception/Codeception) -[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/Codeception/Codeception/badges/quality-score.png?b=2.3)](https://scrutinizer-ci.com/g/Codeception/Codeception/?branch=2.3) +[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/Codeception/Codeception/badges/quality-score.png?b=2.4)](https://scrutinizer-ci.com/g/Codeception/Codeception/?branch=2.4) **Modern PHP Testing for everyone** @@ -15,11 +15,11 @@ Powered by PHPUnit. | General | Windows | Webdriver | HHVM | | ------- | -------- | -------- | -------- | -| [![Build Status](https://secure.travis-ci.org/Codeception/Codeception.png?branch=2.3)](http://travis-ci.org/Codeception/Codeception) | [![Build status](https://ci.appveyor.com/api/projects/status/ntjj9i4y67d1rb7y?svg=true)](https://ci.appveyor.com/project/DavertMik/codeception/branch/2.3) | [![Build Status](https://semaphoreci.com/api/v1/codeception/codeception/branches/master/shields_badge.svg)](https://semaphoreci.com/codeception/codeception) | [![wercker status](https://app.wercker.com/status/b4eecd0596bedb65333ff7ab7836bc7f/s/ "wercker status")](https://app.wercker.com/project/byKey/b4eecd0596bedb65333ff7ab7836bc7f) | +| [![Build Status](https://secure.travis-ci.org/Codeception/Codeception.png?branch=2.4)](http://travis-ci.org/Codeception/Codeception) | [![Build status](https://ci.appveyor.com/api/projects/status/ntjj9i4y67d1rb7y?svg=true)](https://ci.appveyor.com/project/DavertMik/codeception/branch/2.4) | [![Build Status](https://semaphoreci.com/api/v1/codeception/codeception/branches/master/shields_badge.svg)](https://semaphoreci.com/codeception/codeception) | [![wercker status](https://app.wercker.com/status/b4eecd0596bedb65333ff7ab7836bc7f/s/ "wercker status")](https://app.wercker.com/project/byKey/b4eecd0596bedb65333ff7ab7836bc7f) | #### Contributions -At Codeception we are glad to receive contributions from the community. If you want to send additions or fixes to the code or the documentation please check the [Contributing guide](https://github.com/Codeception/Codeception/blob/2.3/CONTRIBUTING.md). +At Codeception we are glad to receive contributions from the community. If you want to send additions or fixes to the code or the documentation please check the [Contributing guide](https://github.com/Codeception/Codeception/blob/2.4/CONTRIBUTING.md). ### At a Glance diff --git a/src/Codeception/Codecept.php b/src/Codeception/Codecept.php index 95b0235b6c..8e1626d6bf 100644 --- a/src/Codeception/Codecept.php +++ b/src/Codeception/Codecept.php @@ -7,7 +7,7 @@ class Codecept { - const VERSION = "2.4.0"; + const VERSION = "2.4.1"; /** * @var \Codeception\PHPUnit\Runner diff --git a/src/Codeception/Module/WebDriver.php b/src/Codeception/Module/WebDriver.php index a5fec31f9a..942eaae15d 100644 --- a/src/Codeception/Module/WebDriver.php +++ b/src/Codeception/Module/WebDriver.php @@ -1,4 +1,5 @@ config['browser']; $capabilities = $this->config['capabilities']; } - $test->getMetadata()->setCurrent([ - 'browser' => $browser, - 'capabilities' => $capabilities, - ]); + $test->getMetadata()->setCurrent( + [ + 'browser' => $browser, + 'capabilities' => $capabilities, + ] + ); } /** @@ -600,11 +603,11 @@ protected function logJSErrors(ScenarioDriven $test, array $browserLogEntries) protected function isJSError($logEntryLevel, $message) { return - ( - ($this->isPhantom() && $logEntryLevel != 'INFO') // phantomjs logs errors as "WARNING" - || $logEntryLevel === 'SEVERE' // other browsers log errors as "SEVERE" - ) - && strpos($message, 'ERR_PROXY_CONNECTION_FAILED') === false; // ignore blackhole proxy + ( + ($this->isPhantom() && $logEntryLevel != 'INFO') // phantomjs logs errors as "WARNING" + || $logEntryLevel === 'SEVERE' // other browsers log errors as "SEVERE" + ) + && strpos($message, 'ERR_PROXY_CONNECTION_FAILED') === false; // ignore blackhole proxy } public function _afterSuite() @@ -1044,10 +1047,10 @@ protected function findFields($selector) $locator = Crawler::xpathLiteral(trim($selector)); // by text or label $xpath = Locator::combine( - // @codingStandardsIgnoreStart + // @codingStandardsIgnoreStart ".//*[self::input | self::textarea | self::select][not(./@type = 'submit' or ./@type = 'image' or ./@type = 'hidden')][(((./@name = $locator) or ./@id = //label[contains(normalize-space(string(.)), $locator)]/@for) or ./@placeholder = $locator)]", ".//label[contains(normalize-space(string(.)), $locator)]//.//*[self::input | self::textarea | self::select][not(./@type = 'submit' or ./@type = 'image' or ./@type = 'hidden')]" - // @codingStandardsIgnoreEnd + // @codingStandardsIgnoreEnd ); $fields = $this->webDriver->findElements(WebDriverBy::xpath($xpath)); if (!empty($fields)) { @@ -1550,7 +1553,7 @@ protected function findCheckable($context, $radioOrCheckbox, $byValue = false) $typeLiteral = Crawler::xPathLiteral($contextType); $inputLocatorFragment = "input[@type = $typeLiteral][@name = $nameLiteral]"; $xpath = Locator::combine( - // @codingStandardsIgnoreStart + // @codingStandardsIgnoreStart "ancestor::form//{$inputLocatorFragment}[(@id = ancestor::form//label[contains(normalize-space(string(.)), $locator)]/@for) or @placeholder = $locator]", // @codingStandardsIgnoreEnd "ancestor::form//label[contains(normalize-space(string(.)), $locator)]//{$inputLocatorFragment}" @@ -1560,7 +1563,7 @@ protected function findCheckable($context, $radioOrCheckbox, $byValue = false) } } else { $xpath = Locator::combine( - // @codingStandardsIgnoreStart + // @codingStandardsIgnoreStart "//input[@type = 'checkbox' or @type = 'radio'][(@id = //label[contains(normalize-space(string(.)), $locator)]/@for) or @placeholder = $locator or @name = $locator]", // @codingStandardsIgnoreEnd "//label[contains(normalize-space(string(.)), $locator)]//input[@type = 'radio' or @type = 'checkbox']" @@ -1621,26 +1624,25 @@ public function fillField($field, $value) { $el = $this->findField($field); $el->clear(); - $el->sendKeys((string) $value); + $el->sendKeys((string)$value); } /** - * Clears given field which isn't empty. - * - * ``` php - * clearField('#username'); - * ?> - * ``` - * - * @param $field - */ + * Clears given field which isn't empty. + * + * ``` php + * clearField('#username'); + * ``` + * + * @param $field + */ public function clearField($field) { $el = $this->findField($field); $el->clear(); } - + public function attachFile($field, $filename) { $el = $this->findField($field); @@ -2645,8 +2647,8 @@ public function clickWithLeftButton($cssOrXPath = null, $offsetX = null, $offset * ``` * * @param string $cssOrXPath css or xpath of the web element (body by default). - * @param int $offsetX - * @param int $offsetY + * @param int $offsetX + * @param int $offsetY * * @throws \Codeception\Exception\ElementNotFound */ @@ -2697,7 +2699,7 @@ protected function match($page, $selector, $throwMalformed = true) if ($this->isPhantom() and $e->getResults()['status'] == 12) { throw new MalformedLocatorException( key($selector) . ' => ' . reset($selector), - "Strict locator ".$e->getCode() + "Strict locator " . $e->getCode() ); } } From 7b3ac33e0b05a64c4ac1c8524b8ca9e4fcde8425 Mon Sep 17 00:00:00 2001 From: MilesChou Date: Wed, 28 Feb 2018 22:22:01 +0800 Subject: [PATCH 009/395] Fix clean command bug when output dir is not exist (#4834) Fix the bug when output dir is not exist and run Clean command. --- src/Codeception/Command/Clean.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Codeception/Command/Clean.php b/src/Codeception/Command/Clean.php index cf4d5bf05b..05704613fc 100644 --- a/src/Codeception/Command/Clean.php +++ b/src/Codeception/Command/Clean.php @@ -31,12 +31,11 @@ protected function execute(InputInterface $input, OutputInterface $output) private function cleanProjectsRecursively(OutputInterface $output, $projectDir) { - $config = Configuration::config($projectDir); - - $logDir = $projectDir . DIRECTORY_SEPARATOR . $config['paths']['output']; + $logDir = Configuration::logDir(); $output->writeln("Cleaning up output " . $logDir . "..."); FileSystem::doEmptyDir($logDir); + $config = Configuration::config($projectDir); $subProjects = $config['include']; foreach ($subProjects as $subProject) { $subProjectDir = $projectDir . $subProject; From f719c7bb987ca75a937e663816f14b9a03669c4a Mon Sep 17 00:00:00 2001 From: Davert Date: Wed, 28 Feb 2018 16:23:04 +0200 Subject: [PATCH 010/395] updated release notes --- CHANGELOG-2.4.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG-2.4.md b/CHANGELOG-2.4.md index f925fc89bf..2cc68994fa 100644 --- a/CHANGELOG-2.4.md +++ b/CHANGELOG-2.4.md @@ -5,8 +5,13 @@ * Internal API refactored: * Modern PHP class names used internally * Moved PHPUnit related classes to [codeception/phpunit-wrapper](https://github.com/Codeception/phpunit-wrapper) package. + * Removed `shims` for underscore PHPUnit classes > namespaced PHP classes * Cest hooks behavior changed (by @fffilimonov): * `_failed` called when test fails * `_passed` called when tests is successful * `_after` is called for failing and successful tests +**Upgrade Notice**: If you face issues with underscore PHPUnit class names (like PHPUnit_Framework_Assert) you have two options: + +* Lock version for PHPUnit in composer.json: "phpunit/phpunit":"^5.0.0" +* Update your codebase and replace underscore PHPUnit class names to namespaced (PHPUnit 6+ API) \ No newline at end of file From ef419075e8c669564deb5f4051803e0dd517130c Mon Sep 17 00:00:00 2001 From: Michael Bodnarchuk Date: Tue, 6 Mar 2018 23:50:06 +0200 Subject: [PATCH 011/395] Fixed RunCest to be compatible with all PHPUnits --- tests/cli/RunCest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cli/RunCest.php b/tests/cli/RunCest.php index 2115a1ebdb..6aee7c5fde 100644 --- a/tests/cli/RunCest.php +++ b/tests/cli/RunCest.php @@ -228,7 +228,7 @@ public function runErrorTest(\CliGuy $I) $I->executeCommand('run unit ErrorTest --no-exit'); $I->seeInShellOutput('There was 1 error'); $I->seeInShellOutput('Array to string conversion'); - $I->seeInShellOutput('ErrorTest.php:9'); + $I->seeInShellOutput('ErrorTest.php'); } public function runTestWithException(\CliGuy $I) From e76fb09644bcada40d79bee162de46422b198930 Mon Sep 17 00:00:00 2001 From: Vadim Date: Wed, 7 Mar 2018 01:44:00 +0200 Subject: [PATCH 012/395] Running tests with particular data set index (#4835) * Make working running test with particular data set by index Example: codecept run tests/acceptance/FirstCest.php:frontpageWorks#0 * return null if not descriptive --- src/Codeception/Test/Descriptor.php | 14 ++++++++++++++ src/Codeception/Test/Loader/Cest.php | 3 +++ src/Codeception/Test/Metadata.php | 17 +++++++++++++++++ 3 files changed, 34 insertions(+) diff --git a/src/Codeception/Test/Descriptor.php b/src/Codeception/Test/Descriptor.php index c68a6e0ef3..7e42dfc7b5 100644 --- a/src/Codeception/Test/Descriptor.php +++ b/src/Codeception/Test/Descriptor.php @@ -90,4 +90,18 @@ public static function getTestFullName(\PHPUnit\Framework\SelfDescribing $testCa } return self::getTestFileName($testCase) . ':' . $testCase->toString(); } + + /** + * Provides a test data set index + * + * @param \PHPUnit\Framework\SelfDescribing $testCase + * @return int|null + */ + public static function getTestDataSetIndex(\PHPUnit\Framework\SelfDescribing $testCase) + { + if ($testCase instanceof Descriptive) { + return $testCase->getMetadata()->getIndex(); + } + return null; + } } diff --git a/src/Codeception/Test/Loader/Cest.php b/src/Codeception/Test/Loader/Cest.php index ba69af0d40..a1cbc584fb 100644 --- a/src/Codeception/Test/Loader/Cest.php +++ b/src/Codeception/Test/Loader/Cest.php @@ -76,6 +76,7 @@ function ($v) { if (count($examples)) { $dataProvider = new \PHPUnit\Framework\DataProviderTestSuite(); + $index = 0; foreach ($examples as $k => $example) { if ($example === null) { throw new TestParseException( @@ -87,7 +88,9 @@ function ($v) { } $test = new CestFormat($unit, $method, $file); $test->getMetadata()->setCurrent(['example' => $example]); + $test->getMetadata()->setIndex($index); $dataProvider->addTest($test); + $index++; } $this->tests[] = $dataProvider; continue; diff --git a/src/Codeception/Test/Metadata.php b/src/Codeception/Test/Metadata.php index 2159c01286..71459cdb7d 100644 --- a/src/Codeception/Test/Metadata.php +++ b/src/Codeception/Test/Metadata.php @@ -9,6 +9,7 @@ class Metadata protected $name; protected $filename; protected $feature; + protected $index; protected $params = [ 'env' => [], @@ -126,6 +127,22 @@ public function getFilename() return $this->filename; } + /** + * @param mixed $index + */ + public function setIndex($index) + { + $this->index = $index; + } + + /** + * @return mixed + */ + public function getIndex() + { + return $this->index; + } + /** * @param mixed $filename */ From 72caa1400e735e90a0c0bbe0e1dc2862eef7b251 Mon Sep 17 00:00:00 2001 From: Michael Bodnarchuk Date: Wed, 7 Mar 2018 14:36:40 +0200 Subject: [PATCH 013/395] Fixing windows builds (#4849) * Fixing windows builds * Skip mongodb tests * Update appveyor.yml * Update appveyor.yml * Update .travis.yml Nor memory limit for composer * Update .travis.yml * Update .travis.yml * Update .travis.yml --- .travis.yml | 5 +++++ appveyor.yml | 7 +------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index fe5d526213..a78018cefe 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,6 +33,11 @@ services: - postgresql - redis + +before_install: + - export INI=~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini + - echo memory_limit = -1 >> $INI + install: - export SF_VERSION=$(echo $SYMFONY | head -c 1) - 'pecl install -f mongodb' diff --git a/appveyor.yml b/appveyor.yml index aa810db8ed..70955c10c8 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -35,11 +35,7 @@ install: - net start wuauserv - IF %PHP%==1 cinst -y php --version 7.1.14 - IF %PHP%==1 cd c:\tools\php71 - - IF %PHP%==1 cd ext - - IF %PHP%==1 appveyor DownloadFile http://windows.php.net/downloads/pecl/releases/mongodb/1.2.0/php_mongodb-1.2.0-7.1-nts-vc14-x64.zip - - IF %PHP%==1 7z x php_mongodb-1.2.0-7.1-nts-vc14-x64.zip -y >nul - - IF %PHP%==1 cd .. - - IF %PHP%==1 copy php.ini-production php.ini + - IF %PHP%==1 copy php.ini-production php.ini - IF %PHP%==1 echo extension_dir=ext >> php.ini - IF %PHP%==1 echo extension=php_openssl.dll >> php.ini - IF %PHP%==1 echo date.timezone="UTC" >> php.ini @@ -49,7 +45,6 @@ install: - IF %PHP%==1 echo extension=php_pdo_pgsql.dll >> php.ini - IF %PHP%==1 echo extension=php_pdo_sqlite.dll >> php.ini - IF %PHP%==1 echo extension=php_pgsql.dll >> php.ini - - IF %PHP%==1 echo extension=php_mongodb.dll >> php.ini - SET PATH=C:\tools\php71;%PATH% - cd %APPVEYOR_BUILD_FOLDER% - appveyor DownloadFile https://getcomposer.org/composer.phar From bfff25a16e0a81d51f070c7c03e825f48d2ba1ea Mon Sep 17 00:00:00 2001 From: Mohamed Aiman Date: Sun, 11 Mar 2018 23:44:37 +0500 Subject: [PATCH 014/395] Laravel 5.4+ (5.1+ backward compatible) support for callArtisan method in Laravel5 module. (#4860) Added Laravel 5.4+ backward compatible support for callArtisan method in Laravel5 module. Laravel 5.4 Laravel enables a third parameter can be passed to the call method (https://laravel.com/api/5.4/Illuminate/Foundation/Console/Kernel.html#method_call) of console Kernel. Which enables the developer to control the output while using commands within commands etc. For example here is a sample command. What does it do? When the command is executed it calls an Artisan command which from inside calls to other Artisan commands. If the proposed change is made the output interface (OutputInterface $output) that is being by default by Codeception execute method can be passed on to the Laravel artisan commands, which then will let the outputs be printed to the console as one would expect, else it won't be displayed. ```php config['modules']['config'][$moduleName]) ? $this->config['modules']['config'][$moduleName] : []; if (!isset($this->config['modules']['enabled'])) { return $config; } if (!is_array($this->config['modules']['enabled'])) { return $config; } foreach ($this->config['modules']['enabled'] as $enabledModuleConfig) { if (!is_array($enabledModuleConfig)) { continue; } $enabledModuleName = key($enabledModuleConfig); if ($enabledModuleName === $moduleName) { return Configuration::mergeConfigs(reset($enabledModuleConfig), $config); } } return $config; } public function getDescription() { return "As the database is huge, this command does the initial migrations, seeding, create initial users and attach roles, permissions "; } protected function execute(InputInterface $input, OutputInterface $output) { //just for example $this->config = Configuration::suiteSettings('acceptance', Configuration::config()); $mc = $this->moduleContainer = new ModuleContainer(new Di(), $this->config); $laravel = new \Helper\Laravel($mc, $this->getModuleConfig('Helper\Laravel')); new \Codeception\Lib\Connector\Laravel5($laravel); $laravel->callArtisan('multipleartisan:commandThatHasOtherCommandsInside', [], $output); } } ```php --- src/Codeception/Module/Laravel5.php | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/Codeception/Module/Laravel5.php b/src/Codeception/Module/Laravel5.php index a1633a0838..2c537b3681 100644 --- a/src/Codeception/Module/Laravel5.php +++ b/src/Codeception/Module/Laravel5.php @@ -14,6 +14,7 @@ use Illuminate\Contracts\Auth\Authenticatable; use Illuminate\Database\Eloquent\Model as EloquentModel; use Illuminate\Support\Collection; +use Symfony\Component\Console\Output\OutputInterface; /** * @@ -423,13 +424,18 @@ public function dontSeeEventTriggered($events) * @param string $command * @param array $parameters + * @param OutputInterface $output */ - public function callArtisan($command, $parameters = []) + public function callArtisan($command, $parameters = [], OutputInterface $output = null) { $console = $this->app->make('Illuminate\Contracts\Console\Kernel'); - $console->call($command, $parameters); - - return trim($console->output()); + if (!$output) { + $console->call($command, $parameters); + return trim($console->output()); + } + + $console->call($command, $parameters, $output); + } /** From 58104f1c8bdfe08e46f4315cecd7b366e99ca8f7 Mon Sep 17 00:00:00 2001 From: Nikolay Geo Date: Tue, 13 Mar 2018 09:59:01 +1100 Subject: [PATCH 015/395] cleanup of unnecessary escaping in operation arguments logging (#4856) --- src/Codeception/Step.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Codeception/Step.php b/src/Codeception/Step.php index 3c0bdd4364..ad90235e90 100644 --- a/src/Codeception/Step.php +++ b/src/Codeception/Step.php @@ -164,8 +164,9 @@ protected function stringifyArgument($argument) $argument = $this->getClassName($argument); } } - - return json_encode($argument, JSON_UNESCAPED_UNICODE); + $arg_str = json_encode($argument, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); + $arg_str = str_replace('\"', '"', $arg_str); + return $arg_str; } protected function getClassName($argument) From 5089d2990094e0a50684a2e42f1b01aa4c3c19b8 Mon Sep 17 00:00:00 2001 From: Nikolay Geo Date: Tue, 13 Mar 2018 10:00:45 +1100 Subject: [PATCH 016/395] Fixed humanize for utf8 strings (#4850) * Fixed humanize for utf8 strings * added encoding to case convertion and updated conversion to always be mb_ --- src/Codeception/Step.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Codeception/Step.php b/src/Codeception/Step.php index ad90235e90..b5b9eb78a4 100644 --- a/src/Codeception/Step.php +++ b/src/Codeception/Step.php @@ -245,7 +245,7 @@ protected function humanize($text) $text = preg_replace('/([A-Z]+)([A-Z][a-z])/', '\\1 \\2', $text); $text = preg_replace('/([a-z\d])([A-Z])/', '\\1 \\2', $text); $text = preg_replace('~\bdont\b~', 'don\'t', $text); - return strtolower($text); + return mb_strtolower($text, 'UTF-8'); } public function run(ModuleContainer $container = null) From 50f4edd284a0f0a9871ccc4c5fe44465b05d3fd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9E=D0=BB=D0=B5=D0=B3=20=D0=9C=D0=B0=D0=BA=D1=81=D0=B8?= =?UTF-8?q?=D0=BC=D0=B5=D0=BD=D0=BA=D0=BE?= Date: Tue, 13 Mar 2018 01:27:40 +0200 Subject: [PATCH 017/395] Fixed making for $settings['path'] in Codeception\Configuration::suiteSettings() on Windows (#4843) --- src/Codeception/Configuration.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Codeception/Configuration.php b/src/Codeception/Configuration.php index a0f0b21dd8..e5ebe96402 100644 --- a/src/Codeception/Configuration.php +++ b/src/Codeception/Configuration.php @@ -320,6 +320,8 @@ public static function suiteSettings($suite, $config) $settings['path'] = $suite; } + $config['paths']['tests'] = str_replace('/', DIRECTORY_SEPARATOR, $config['paths']['tests']); + $settings['path'] = self::$dir . DIRECTORY_SEPARATOR . $config['paths']['tests'] . DIRECTORY_SEPARATOR . $settings['path'] . DIRECTORY_SEPARATOR; From 93936b706cd3013264cda0af3258b1734be91563 Mon Sep 17 00:00:00 2001 From: quantum-x Date: Tue, 13 Mar 2018 00:28:46 +0100 Subject: [PATCH 018/395] 2.4 bug 4847 (#4853) * Update Uri.php PHP's parse_url fails on specific relative URLs. If the absolute URL is passed, it parses as expected. PHP Known bug: https://bugs.php.net/bug.php?id=70942 Discussion thread: https://github.com/Codeception/Codeception/issues/4847 * Update UriTest.php * Cleaning code - Removing ternary - Splitting $baseUri to $base.$uri (both work) --- src/Codeception/Util/Uri.php | 7 +++++++ tests/unit/Codeception/Util/UriTest.php | 8 ++++++++ 2 files changed, 15 insertions(+) diff --git a/src/Codeception/Util/Uri.php b/src/Codeception/Util/Uri.php index 3322488453..3719596e06 100644 --- a/src/Codeception/Util/Uri.php +++ b/src/Codeception/Util/Uri.php @@ -20,6 +20,13 @@ public static function mergeUrls($baseUri, $uri) { $base = new Psr7Uri($baseUri); $parts = parse_url($uri); + + //If the relative URL does not parse, attempt to parse the entire URL. + //PHP Known bug ( https://bugs.php.net/bug.php?id=70942 ) + if ($parts === false) { + $parts = parse_url($base.$uri); + } + if ($parts === false) { throw new \InvalidArgumentException("Invalid URI $uri"); } diff --git a/tests/unit/Codeception/Util/UriTest.php b/tests/unit/Codeception/Util/UriTest.php index 02117b97c7..2f44ec0218 100644 --- a/tests/unit/Codeception/Util/UriTest.php +++ b/tests/unit/Codeception/Util/UriTest.php @@ -50,6 +50,14 @@ public function testMergingPath() $this->assertEquals('/form/?param=1#anchor2', Uri::mergeUrls('/form/?param=1#anchor1', '#anchor2')); $this->assertEquals('/form/?param=2', Uri::mergeUrls('/form/?param=1#anchor', '?param=2')); $this->assertEquals('/page/', Uri::mergeUrls('/form/?param=1#anchor', '/page/')); + } + + /** + * @Issue https://github.com/Codeception/Codeception/pull/4847 + */ + public function testMergingNonParsingPath() + { + $this->assertEquals('/3.0/en/index/page:5', Uri::mergeUrls('https://cakephp.org/', '/3.0/en/index/page:5')); } /** From 69150097f19bb408b79cda0c1364e1a18316276b Mon Sep 17 00:00:00 2001 From: Nick Denry Date: Tue, 20 Mar 2018 22:55:28 +0300 Subject: [PATCH 019/395] Fix typo (#4882) [skip ci] Fix typo at line 104, missing close square bracket --- docs/modules/Yii2.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/modules/Yii2.md b/docs/modules/Yii2.md index ed6bb2c955..ab0e376330 100644 --- a/docs/modules/Yii2.md +++ b/docs/modules/Yii2.md @@ -101,7 +101,7 @@ This commands allows input like: $I->amOnPage(['site/view','page'=>'about']); $I->amOnPage('index-test.php?site/index'); $I->amOnPage('http://localhost/index-test.php?site/index'); -$I->sendAjaxPostRequest(['/user/update', 'id' => 1], ['UserForm[name]' => 'G.Hopper'); +$I->sendAjaxPostRequest(['/user/update', 'id' => 1], ['UserForm[name]' => 'G.Hopper']); ``` ## Status From f88f50bcf79542731ddc9117b2c1e74c91956944 Mon Sep 17 00:00:00 2001 From: Sam Date: Thu, 29 Mar 2018 11:30:56 +0200 Subject: [PATCH 020/395] Reorganized travis jobs (#4893) * Reorganized travis jobs * Disabled Yii2 tests --- .travis.yml | 191 +++++++++++++++++++++++++--------------------------- 1 file changed, 92 insertions(+), 99 deletions(-) diff --git a/.travis.yml b/.travis.yml index a78018cefe..e55226708f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,20 +1,58 @@ sudo: false language: php - +matrix: + fast_finish: true +php: + - 5.6 + - 7.0 + - 7.1 + - 7.2 +env: + global: + - XDEBUG= + - SUITES= + - FXP= + - PECL= + - TEST_PATH='framework-tests' + - SYMFONY_DEPRECATIONS_HELPER=weak + matrix: + - FRAMEWORK=Codeception SUITES=cli,unit TEST_PATH=. XDEBUG=1 PECL=mongodb + #- FRAMEWORK=Yii2 TEST_REPO="https://github.com/Codeception/yii2-tests" + - FRAMEWORK=Symfony VERSION=2.8 TEST_REPO='-b 2.1 https://github.com/Codeception/symfony-demo.git' SUITES=functional TEST_PATH=framework-tests/src/AppBundle + - FRAMEWORK=Symfony VERSION=3.4 TEST_REPO='--recurse-submodules https://github.com/Naktibalda/codeception-symfony-tests' + - FRAMEWORK=Symfony VERSION=4 TEST_REPO='https://github.com/Codeception/symfony-demo.git' SUITES=functional,unit + - FRAMEWORK=Lumen TEST_REPO='-b codeception-2.2 https://github.com/codeception/codeception-lumen-sample.git' + - FRAMEWORK=Laravel TEST_REPO='-b codeception-2.3 https://github.com/codeception/codeception-laravel5-sample.git' + - FRAMEWORK=Phalcon TEST_REPO=https://github.com/Codeception/phalcon-demo.git + - FRAMEWORK=Zend1 TEST_REPO='-b 2.2 --recurse-submodules https://github.com/Naktibalda/codeception-zf1-tests' + - FRAMEWORK=Zend2 TEST_REPO='-b 2.2 --recurse-submodules https://github.com/Naktibalda/codeception-zf2-tests' SUITES=functional + - FRAMEWORK=ZendExpressive TEST_REPO='-b 2.2 --recurse-submodules https://github.com/Naktibalda/codeception-zend-expressive-tests' SUITES=functional matrix: include: - - php: 5.6 - env: SYMFONY=2.8.12 SYMFONY_DEPRECATIONS_HELPER=weak # latest version of 2.8.* - - php: 7.0 - env: SYMFONY=3.2.9 SYMFONY_DEPRECATIONS_HELPER=weak # latest version of 3.2.* - - php: 7.1 - env: SYMFONY=3.3.2 SYMFONY_DEPRECATIONS_HELPER=weak # latest version of 3.3.* - - php: 7.1 - env: SYMFONY=4.0.1 SYMFONY_DEPRECATIONS_HELPER=weak # latest version of 4.0.* - - php: 7.2 - env: SYMFONY=4.0.1 SYMFONY_DEPRECATIONS_HELPER=weak # latest version of 4.0.* - + - php: 7.1 + env: FRAMEWORK=Codeception SUITES=cli,unit,coverage TEST_PATH=. XDEBUG=1 PECL=mongodb + exclude: + - php: 7.1 + env: FRAMEWORK=Codeception SUITES=cli,unit TEST_PATH=. XDEBUG=1 PECL=mongodb + - php: 7.0 + env: FRAMEWORK=Symfony VERSION=2.8 TEST_REPO='-b 2.1 https://github.com/Codeception/symfony-demo.git' SUITES=functional TEST_PATH=framework-tests/src/AppBundle + - php: 7.1 + env: FRAMEWORK=Symfony VERSION=2.8 TEST_REPO='-b 2.1 https://github.com/Codeception/symfony-demo.git' SUITES=functional TEST_PATH=framework-tests/src/AppBundle + - php: 7.2 + env: FRAMEWORK=Symfony VERSION=2.8 TEST_REPO='-b 2.1 https://github.com/Codeception/symfony-demo.git' SUITES=functional TEST_PATH=framework-tests/src/AppBundle + - php: 5.6 + env: FRAMEWORK=Symfony VERSION=3.4 TEST_REPO='--recurse-submodules https://github.com/Naktibalda/codeception-symfony-tests' + - php: 7.0 + env: FRAMEWORK=Symfony VERSION=3.4 TEST_REPO='--recurse-submodules https://github.com/Naktibalda/codeception-symfony-tests' + - php: 5.6 + env: FRAMEWORK=Symfony VERSION=4 TEST_REPO='https://github.com/Codeception/symfony-demo.git' SUITES=functional,unit + - php: 7.0 + env: FRAMEWORK=Symfony VERSION=4 TEST_REPO='https://github.com/Codeception/symfony-demo.git' SUITES=functional,unit +# - php: 7.1 +# env: FRAMEWORK=ZendExpressive TEST_REPO='-b 2.2 --recurse-submodules https://github.com/Naktibalda/codeception-zend-expressive-tests' functional +# - php: 7.2 +# env: FRAMEWORK=ZendExpressive TEST_REPO='-b 2.2 --recurse-submodules https://github.com/Naktibalda/codeception-zend-expressive-tests' functional addons: postgresql: "9.2" @@ -33,107 +71,62 @@ services: - postgresql - redis - before_install: + - '[[ !(-z "$XDEBUG") ]] || phpenv config-rm xdebug.ini' - export INI=~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini - echo memory_limit = -1 >> $INI - install: - - export SF_VERSION=$(echo $SYMFONY | head -c 1) - - 'pecl install -f mongodb' - - yes '' | pecl install imagick - #- echo "extension = mongodb.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini - - composer self-update && composer --version - - if [ -n "$CI_USER_TOKEN" ]; then composer config github-oauth.github.com ${CI_USER_TOKEN}; echo "Configured Github token"; fi; - - 'composer require mongodb/mongodb --no-update' - - '[[ "$TRAVIS_PHP_VERSION" == "7.2" ]] || composer global require "fxp/composer-asset-plugin:~1.3.1"' - - '[[ -z "$SYMFONY" ]] || composer require symfony/finder=~$SYMFONY --no-update --ignore-platform-reqs' - - '[[ -z "$SYMFONY" ]] || composer require symfony/yaml=~$SYMFONY --no-update --ignore-platform-reqs' - - '[[ -z "$SYMFONY" ]] || composer require symfony/console=~$SYMFONY --no-update --ignore-platform-reqs' - - '[[ -z "$SYMFONY" ]] || composer require symfony/event-dispatcher=~$SYMFONY --no-update --ignore-platform-reqs' - - '[[ -z "$SYMFONY" ]] || composer require symfony/css-selector=~$SYMFONY --no-update --ignore-platform-reqs' - - '[[ -z "$SYMFONY" ]] || composer require symfony/dom-crawler=~$SYMFONY --no-update --ignore-platform-reqs' - - '[[ -z "$SYMFONY" ]] || composer require symfony/browser-kit=~$SYMFONY --no-update --ignore-platform-reqs' - - composer_parameters="-n --prefer-dist" # this variable will be used in all composer install commands - - '[[ "$dependencies" != "lowest" ]] || composer_parameters="$composer_parameters --prefer-lowest"' - - composer update $composer_parameters - - composer_parameters="$composer_parameters --no-dev" # Codeception needs dev dependencies, but frameworks don't - # Yii2 - - '[[ "$TRAVIS_PHP_VERSION" == "7.2" ]] || composer create-project "yiisoft/yii2-app-basic" frameworks-yii-basic --no-dev' + - '[[ -z "$CI_USER_TOKEN" ]] || composer config github-oauth.github.com ${CI_USER_TOKEN};' + # Add extensions + - '[[ -z "$PECL" ]] || (yes "" | pecl install $PECL)' + # Clone test repository + - '[[ "$FRAMEWORK" == "Codeception" ]] || git clone -q --depth=1 $TEST_REPO framework-tests' + - '[[ "$FRAMEWORK" == "Codeception" ]] || git --git-dir framework-tests/.git log -n 1' + - '[[ "$FRAMEWORK" != "Codeception" ]] || composer require mongodb/mongodb --no-update' + - '[[ -z "$FXP" ]] || composer global require "fxp/composer-asset-plugin:~1.3.1"' + - '[[ "$FRAMEWORK" != "Symfony" ]] || composer require symfony/finder=~$VERSION --no-update --ignore-platform-reqs' + - '[[ "$FRAMEWORK" != "Symfony" ]] || composer require symfony/yaml=~$VERSION --no-update --ignore-platform-reqs' + - '[[ "$FRAMEWORK" != "Symfony" ]] || composer require symfony/console=~$VERSION --no-update --ignore-platform-reqs' + - '[[ "$FRAMEWORK" != "Symfony" ]] || composer require symfony/event-dispatcher=~$VERSION --no-update --ignore-platform-reqs' + - '[[ "$FRAMEWORK" != "Symfony" ]] || composer require symfony/css-selector=~$VERSION --no-update --ignore-platform-reqs' + - '[[ "$FRAMEWORK" != "Symfony" ]] || composer require symfony/dom-crawler=~$VERSION --no-update --ignore-platform-reqs' + - '[[ "$FRAMEWORK" != "Symfony" ]] || composer require symfony/browser-kit=~$VERSION --no-update --ignore-platform-reqs' + - '[[ "$FRAMEWORK" != "Symfony" ]] || composer require symfony/browser-kit=~$VERSION --no-update --ignore-platform-reqs' # Phalcon - - 'git clone -q --depth=1 https://github.com/phalcon/cphalcon.git' - - '(cd cphalcon/build; bash ./install --phpize $(phpenv which phpize) --php-config $(phpenv which php-config) &>/dev/null && phpenv config-add ../tests/_ci/phalcon.ini &> /dev/null)' - - 'git clone -q --depth=1 https://github.com/Codeception/phalcon-demo.git frameworks-phalcon' - - 'composer update -d frameworks-phalcon $composer_parameters' - # Laravel 5 - - 'git clone -q --depth=1 -b codeception-2.3 https://github.com/codeception/codeception-laravel5-sample.git frameworks-l5' - - 'composer update -d frameworks-l5 $composer_parameters --no-dev' - # Lumen - - 'git clone -q --depth=1 -b codeception-2.2 https://github.com/codeception/codeception-lumen-sample.git frameworks-lumen' - - 'composer update -d frameworks-lumen $composer_parameters --no-dev' + - '[[ "$FRAMEWORK" != "Phalcon" ]] || git clone -q --depth=1 https://github.com/phalcon/cphalcon.git' + - '[[ "$FRAMEWORK" != "Phalcon" ]] || (cd cphalcon/build; bash ./install --phpize $(phpenv which phpize) --php-config $(phpenv which php-config) &>/dev/null && phpenv config-add ../tests/_ci/phalcon.ini &> /dev/null)' # Symfony - - '[[ "$SF_VERSION" != "2" ]] || (git clone -q --depth=1 -b 2.1 https://github.com/Codeception/symfony-demo.git frameworks-symfony && echo "Cloned Symfony 2 site")' - - '[[ "$SF_VERSION" != "3" ]] || (git clone -q --depth=1 -b master --recursive https://github.com/Naktibalda/codeception-symfony-tests frameworks-symfony && echo "Cloned Symfony 3 site")' - - '[[ "$SF_VERSION" != "4" ]] || (git clone -q --depth=1 -b master https://github.com/Codeception/symfony-demo.git frameworks-symfony && echo "Cloned Symfony 4 site")' - - '[[ "$SF_VERSION" == "4" ]] || composer require -d frameworks-symfony symfony/symfony=~$SYMFONY --no-update' - - "mysql -e 'create database symfony_test;'" - - 'composer update -d frameworks-symfony $composer_parameters --no-dev' - # ZF1 - - git clone -q -b 2.2 --recursive https://github.com/Naktibalda/codeception-zf1-tests frameworks-zf1 - - composer update -d frameworks-zf1 $composer_parameters --no-dev - # ZF2 - - git clone -q -b 2.2 --recursive https://github.com/Naktibalda/codeception-zf2-tests frameworks-zf2 - - composer update -d frameworks-zf2 $composer_parameters --no-dev - # Zend Expressive - - 'git clone -q -b 2.2 --recursive https://github.com/Naktibalda/codeception-zend-expressive-tests frameworks-zend-expressive' - - 'composer update -d frameworks-zend-expressive $composer_parameters' - + #- '[[ "$FRAMEWORK$VERSION" != "Symfony3" ]] || composer require -d framework-tests symfony/symfony=~$VERSION --no-update' + - composer install + - '[[ "$FRAMEWORK" == "Codeception" ]] || composer update -d framework-tests --no-dev --prefer-dist' before_script: - '[[ "$TRAVIS_PHP_VERSION" == 7.* ]] || echo "extension = mongo.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini' # preparing databases - - "mysql -e 'create database codeception_test;'" - - psql -c 'create database codeception_test;' -U postgres + - '[[ "$FRAMEWORK" != "Codeception" ]] || mysql -e "create database codeception_test;"' + - '[[ "$FRAMEWORK" != "Codeception" ]] || psql -c "create database codeception_test;" -U postgres' + - '[[ "$FRAMEWORK" != "Symfony" ]] || mysql -e "create database symfony_test;"' # starting demo servers - - 'php -S 127.0.0.1:8000 -t tests/data/app >/dev/null 2>&1 &' - - 'php -S 127.0.0.1:8010 -t tests/data >/dev/null 2>&1 &' + - '[[ "$FRAMEWORK" != "Codeception" ]] || php -S 127.0.0.1:8000 -t tests/data/app >/dev/null 2>&1 &' + - '[[ "$FRAMEWORK" != "Codeception" ]] || php -S 127.0.0.1:8010 -t tests/data >/dev/null 2>&1 &' # Phalcon - - mysql -e 'CREATE DATABASE phalcon_demo CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;' - - 'cat frameworks-phalcon/schemas/phalcon_demo.sql | mysql phalcon_demo' + - '[[ "$FRAMEWORK" != "Phalcon" ]] || mysql -e "CREATE DATABASE phalcon_demo CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;"' + - '[[ "$FRAMEWORK" != "Phalcon" ]] || cat framework-tests/schemas/phalcon_demo.sql | mysql phalcon_demo' # Laravel 5 - - 'touch frameworks-l5/storage/testing.sqlite' - - 'php frameworks-l5/artisan migrate --env=testing --database=sqlite_testing --force' + - '[[ "$FRAMEWORK" != "Laravel" ]] || touch framework-tests/storage/testing.sqlite' + - '[[ "$FRAMEWORK" != "Laravel" ]] || php framework-tests/artisan migrate --env=testing --database=sqlite_testing --force' # Lumen - - 'cp frameworks-lumen/.env.testing frameworks-lumen/.env' - - 'touch frameworks-lumen/storage/testing.sqlite' - - 'php frameworks-lumen/artisan migrate --database=testing --force' + - '[[ "$FRAMEWORK" != "Lumen" ]] || cp framework-tests/.env.testing framework-tests/.env' + - '[[ "$FRAMEWORK" != "Lumen" ]] || touch framework-tests/storage/testing.sqlite' + - '[[ "$FRAMEWORK" != "Lumen" ]] || php framework-tests/artisan migrate --database=testing --force' # Symfony - - '[[ "$SF_VERSION" != "2" ]] || php frameworks-symfony/app/console doctrine:schema:create -n --env test' - - '[[ "$SF_VERSION" != "2" ]] || php frameworks-symfony/app/console doctrine:fixtures:load -n --env test' - - '[[ "$SF_VERSION" != "3" ]] || php frameworks-symfony/bin/console doctrine:schema:update --force -n' + - '[[ "$FRAMEWORK$VERSION" != "Symfony2.8" ]] || php framework-tests/app/console doctrine:schema:create -n --env test' + - '[[ "$FRAMEWORK$VERSION" != "Symfony2.8" ]] || php framework-tests/app/console doctrine:fixtures:load -n --env test' + - '[[ "$FRAMEWORK$VERSION" != "Symfony3.4" ]] || php framework-tests/bin/console doctrine:schema:update --force -n' # ZF2 - - "mysql -e 'create database zf2_test;'" - - php frameworks-zf2/vendor/bin/doctrine-module orm:schema-tool:create + - '[[ "$FRAMEWORK" != "Zend2" ]] || mysql -e "create database zf2_test;"' + - '[[ "$FRAMEWORK" != "Zend2" ]] || php framework-tests/vendor/bin/doctrine-module orm:schema-tool:create' # Build - - '[[ "$TRAVIS_PHP_VERSION" == "7.2" ]] || php codecept build -c frameworks-yii-basic' - - 'php codecept build -c frameworks-phalcon' - - '[[ "$SF_VERSION" != "2" ]] || php codecept build -c frameworks-symfony/src/AppBundle' - - '[[ "$SF_VERSION" == "2" ]] || php codecept build -c frameworks-symfony' - - 'php codecept build -c frameworks-l5' - - 'php codecept build -c frameworks-lumen' - - php codecept build -c frameworks-zf1 - - php codecept build -c frameworks-zf2 - - 'php codecept build -c frameworks-zend-expressive' - + - php codecept build -c $TEST_PATH script: - - php codecept run cli,unit # self tests - - '[[ "$TRAVIS_PHP_VERSION" == "7.0" ]] || php codecept run coverage' # run coverage tests on php only - - '[[ "$TRAVIS_PHP_VERSION" == "7.2" ]] || php codecept run functional -c frameworks-yii-basic' # Yii2 tests - - 'php codecept run -c frameworks-l5 --skip=seeder' # Laravel5 Tests - - 'php codecept run -c frameworks-lumen' # Lumen Tests - - 'php codecept run functional -c frameworks-phalcon' # Phalcon Tests - - '[[ "$SF_VERSION" != "2" ]] || php codecept run functional -c frameworks-symfony/src/AppBundle' # Symfony 2 Tests - - '[[ "$SF_VERSION" != "3" ]] || php codecept run -c frameworks-symfony' # Symfony 3 Tests - - '[[ "$SF_VERSION" != "4" ]] || php codecept run -c frameworks-symfony functional,unit' # Symfony 4 Tests - - php codecept run functional -c frameworks-zf1 # ZF1 Tests - - 'php codecept run -c frameworks-zf2 functional' - - 'php codecept run functional -c frameworks-zend-expressive' # Zend Expressive Tests + #- '[[ !("$FRAMEWORK" == "Codeception" && "$TRAVIS_PHP_VERSION" == "7.1") ]] || php codecept run coverage' # run coverage tests on php only + - php codecept run $SUITES -c $TEST_PATH \ No newline at end of file From 7da268034b406c593d71c32abc7f1e7b5e3996fc Mon Sep 17 00:00:00 2001 From: Greg Heitz Date: Sat, 31 Mar 2018 21:43:58 +0200 Subject: [PATCH 021/395] Improve support of PHPUnit warning status (#4901) --- src/Codeception/Events.php | 7 +++++++ src/Codeception/Subscriber/Console.php | 11 +++++++++++ tests/cli/RunCest.php | 13 ++++++++++++- tests/data/claypit/tests/unit/WarningTest.php | 15 +++++++++++++++ 4 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 tests/data/claypit/tests/unit/WarningTest.php diff --git a/src/Codeception/Events.php b/src/Codeception/Events.php index 6150b36db1..6769200f66 100644 --- a/src/Codeception/Events.php +++ b/src/Codeception/Events.php @@ -93,6 +93,13 @@ private function __construct() */ const TEST_SKIPPED = 'test.skipped'; + + /** + * The event listener method receives a {@link Codeception\Event\FailEvent} instance. + */ + const TEST_WARNING = 'test.warning'; + + /** * The event listener method receives a {@link Codeception\Event\TestEvent} instance. */ diff --git a/src/Codeception/Subscriber/Console.php b/src/Codeception/Subscriber/Console.php index 707f3ddd87..22b38b8d63 100644 --- a/src/Codeception/Subscriber/Console.php +++ b/src/Codeception/Subscriber/Console.php @@ -40,6 +40,7 @@ class Console implements EventSubscriberInterface Events::TEST_ERROR => 'testError', Events::TEST_INCOMPLETE => 'testIncomplete', Events::TEST_SKIPPED => 'testSkipped', + Events::TEST_WARNING => 'testWarning', Events::TEST_FAIL_PRINT => 'printFail', Events::RESULT_PRINT_AFTER => 'afterResult', ]; @@ -236,6 +237,16 @@ public function endTest(TestEvent $e) $this->printedTest = null; } + public function testWarning(TestEvent $e) + { + if ($this->isDetailed($e->getTest())) { + $this->message('WARNING')->center(' ')->style('pending')->append("\n")->writeln(); + + return; + } + $this->writelnFinishedTest($e, $this->message('W')->style('pending')); + } + public function testFail(FailEvent $e) { if ($this->isDetailed($e->getTest())) { diff --git a/tests/cli/RunCest.php b/tests/cli/RunCest.php index 6aee7c5fde..51e5ef6e9d 100644 --- a/tests/cli/RunCest.php +++ b/tests/cli/RunCest.php @@ -474,7 +474,7 @@ public function runTestWithCustomSetupMethod(CliGuy $I) $I->executeCommand('run powers PowerUpCest'); $I->dontSeeInShellOutput('FAILURES'); } - + public function runCestWithTwoFailedTest(CliGuy $I) { $I->executeCommand('run scenario PartialFailedCest', false); @@ -483,4 +483,15 @@ public function runCestWithTwoFailedTest(CliGuy $I) $I->seeInShellOutput('Tests: 3,'); $I->seeInShellOutput('Failures: 2.'); } + + + public function runWarningTests(CliGuy $I) + { + $I->executeCommand('run unit WarningTest.php:testWarningInvalidDataProvider', false); + $I->seeInShellOutput('There was 1 warning'); + $I->seeInShellOutput('WarningTest::testWarningInvalidDataProvider'); + $I->seeInShellOutput('Tests: 1,'); + $I->seeInShellOutput('Warnings: 1.'); + } + } diff --git a/tests/data/claypit/tests/unit/WarningTest.php b/tests/data/claypit/tests/unit/WarningTest.php new file mode 100644 index 0000000000..b2d46b2368 --- /dev/null +++ b/tests/data/claypit/tests/unit/WarningTest.php @@ -0,0 +1,15 @@ +assertTrue(true); + } + public function dependentProvider() + { + throw new Exception; + } +} From 53d7af85a51324e8a256d87b09770a46c94cdd62 Mon Sep 17 00:00:00 2001 From: Greg Heitz Date: Sat, 31 Mar 2018 21:44:45 +0200 Subject: [PATCH 022/395] Update Advanced Usage documentation for dataprovider (#4900) --- docs/07-AdvancedUsage.md | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/docs/07-AdvancedUsage.md b/docs/07-AdvancedUsage.md index 637d0afca2..9d8377cc41 100644 --- a/docs/07-AdvancedUsage.md +++ b/docs/07-AdvancedUsage.md @@ -61,18 +61,18 @@ class BasicCest } ``` -As you see, Cest classes have no parents. +As you see, Cest classes have no parents. This is done intentionally. It allows you to extend your classes with common behaviors and workarounds that may be used in child classes. But don't forget to make these methods `protected` so they won't be executed as tests. -Cest format also can contain hooks based on test results: +Cest format also can contain hooks based on test results: * `_failed` will be executed on failed test * `_passed` will be executed on passed test ```php sendGET($example[0]); $I->seeResponseCodeIs($example[1]); } +} ``` JSON: ```php see($example['title'], 'h1'); $I->seeInTitle($example['title']); } +} ```
@@ -230,6 +236,8 @@ Key-value data in Doctrine-style annotation syntax: ```php see($example['title'], 'h1'); $I->seeInTitle($example['title']); } +} ``` -You can also use the `@dataprovider` annotation for creating dynamic examples, using a protected method for providing example data: +## DataProvider Annotations + +You can also use the `@dataProvider` annotation for creating dynamic examples for [Cest classes](#Cest-Classes), using a **protected method** for providing example data: ```php "/contact", 'title'=>"Contact Us"] ]; } +} ``` -### Before/After Annotations +`@dataprovider` annotation is also available for [unit tests](https://codeception.com/docs/05-UnitTests), in this case the data provider **method must be public**. +For more details about how to use data provider for unit tests, please refer to [PHPUnit documentation](https://phpunit.de/manual/current/en/writing-tests-for-phpunit.html#writing-tests-for-phpunit.data-providers). + +## Before/After Annotations You can control execution flow with `@before` and `@after` annotations. You may move common actions into protected (non-test) methods and invoke them before or after the test method by putting them into annotations. From 08e487b0854bcc1f8a8478a5d5b7cf9713cbbc76 Mon Sep 17 00:00:00 2001 From: Sam Date: Sat, 31 Mar 2018 22:33:03 +0200 Subject: [PATCH 023/395] Yii2 rework, new PR same changes. (#4894) * Reorganized travis jobs * Improved Yii2 module * Fixed issue and updated docs * Added notice about absence of $app. * Fixed weird sentence --- .travis.yml | 2 +- CHANGELOG-2.4.md | 10 +- src/Codeception/Lib/Connector/Yii2.php | 173 +++++++-------- src/Codeception/Module/Yii2.php | 282 +++++++++++++++++++------ 4 files changed, 300 insertions(+), 167 deletions(-) diff --git a/.travis.yml b/.travis.yml index e55226708f..ebf56b4572 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,7 +18,7 @@ env: - SYMFONY_DEPRECATIONS_HELPER=weak matrix: - FRAMEWORK=Codeception SUITES=cli,unit TEST_PATH=. XDEBUG=1 PECL=mongodb - #- FRAMEWORK=Yii2 TEST_REPO="https://github.com/Codeception/yii2-tests" + - FRAMEWORK=Yii2 TEST_REPO="https://github.com/Codeception/yii2-tests" - FRAMEWORK=Symfony VERSION=2.8 TEST_REPO='-b 2.1 https://github.com/Codeception/symfony-demo.git' SUITES=functional TEST_PATH=framework-tests/src/AppBundle - FRAMEWORK=Symfony VERSION=3.4 TEST_REPO='--recurse-submodules https://github.com/Naktibalda/codeception-symfony-tests' - FRAMEWORK=Symfony VERSION=4 TEST_REPO='https://github.com/Codeception/symfony-demo.git' SUITES=functional,unit diff --git a/CHANGELOG-2.4.md b/CHANGELOG-2.4.md index 2cc68994fa..70b806a390 100644 --- a/CHANGELOG-2.4.md +++ b/CHANGELOG-2.4.md @@ -10,8 +10,14 @@ * `_failed` called when test fails * `_passed` called when tests is successful * `_after` is called for failing and successful tests - +* Yii2 Module request flow and database transactions refactored (by @sammousa): + * Multiple databases are now supported + * More reliable application state before and during test execution + * Fixtures method is now configurable + * Subset of misconfigurations are now detected and create informative messages + * Application is no longer available via the `$module->app`, now you must use `\Yii::$app` everywhere **Upgrade Notice**: If you face issues with underscore PHPUnit class names (like PHPUnit_Framework_Assert) you have two options: * Lock version for PHPUnit in composer.json: "phpunit/phpunit":"^5.0.0" -* Update your codebase and replace underscore PHPUnit class names to namespaced (PHPUnit 6+ API) \ No newline at end of file +* Update your codebase and replace underscore PHPUnit class names to namespaced (PHPUnit 6+ API) + diff --git a/src/Codeception/Lib/Connector/Yii2.php b/src/Codeception/Lib/Connector/Yii2.php index 667ee20a37..9624f05713 100644 --- a/src/Codeception/Lib/Connector/Yii2.php +++ b/src/Codeception/Lib/Connector/Yii2.php @@ -2,14 +2,16 @@ namespace Codeception\Lib\Connector; use Codeception\Lib\Connector\Yii2\Logger; -use Codeception\Lib\Connector\Yii2\TestMailer; +use Codeception\Lib\InnerBrowser; use Codeception\Util\Debug; use Symfony\Component\BrowserKit\Client; use Symfony\Component\BrowserKit\Cookie; use Symfony\Component\BrowserKit\Response; use Yii; use yii\base\ExitException; +use yii\base\Security; use yii\web\HttpException; +use yii\web\Request; use yii\web\Response as YiiResponse; class Yii2 extends Client @@ -21,71 +23,41 @@ class Yii2 extends Client */ public $configFile; - public $defaultServerVars = []; - - /** - * @var array - */ - public $headers; - public $statusCode; - - /** - * @var \yii\web\Application - */ - private $app; - - /** - * @var \yii\db\Connection - */ - public static $db; // remember the db instance - - /** - * @var TestMailer - */ - public static $mailer; - /** * @return \yii\web\Application */ public function getApplication() { - if (!isset($this->app)) { + if (!isset(Yii::$app)) { $this->startApp(); } - return $this->app; + return Yii::$app; } public function resetApplication() { - $this->app = null; + codecept_debug('Destroying application'); + Yii::$app = null; + \yii\web\UploadedFile::reset(); + if (method_exists(\yii\base\Event::className(), 'offAll')) { + \yii\base\Event::offAll(); + } + Yii::setLogger(null); } public function startApp() { + codecept_debug('Starting application'); $config = require($this->configFile); if (!isset($config['class'])) { $config['class'] = 'yii\web\Application'; } - if (static::$db) { - // If the DB conection already exists, make sure to pass it as early as possible - // to prevent application from new connection creating during bootstrap - $config['components']['db'] = static::$db; - } + + $config = $this->mockMailer($config); /** @var \yii\web\Application $app */ - $this->app = Yii::createObject($config); - $this->persistDb(); - $this->mockMailer($config); - \Yii::setLogger(new Logger()); - } + Yii::$app = Yii::createObject($config); - public function resetPersistentVars() - { - static::$db = null; - static::$mailer = null; - \yii\web\UploadedFile::reset(); - if (method_exists(\yii\base\Event::className(), 'offAll')) { - \yii\base\Event::offAll(); - } + Yii::setLogger(new Logger()); } /** @@ -98,7 +70,6 @@ public function doRequest($request) { $_COOKIE = $request->getCookies(); $_SERVER = $request->getServer(); - $this->restoreServerVars(); $_FILES = $this->remapFiles($request->getFiles()); $_REQUEST = $this->remapRequestParameters($request->getParameters()); $_POST = $_GET = []; @@ -123,20 +94,28 @@ public function doRequest($request) $app = $this->getApplication(); - $app->getResponse()->on(YiiResponse::EVENT_AFTER_PREPARE, [$this, 'processResponse']); + /** + * Just before the request we set the response object so it is always fresh. + * @todo Implement some kind of check to see if someone tried to change the objects' properties and expects + * those changes to be reflected in the reponse. + */ + $app->set('response', $app->getComponents()['response']); // disabling logging. Logs are slowing test execution down foreach ($app->log->targets as $target) { $target->enabled = false; } - $this->headers = []; - $this->statusCode = null; - ob_start(); // recreating request object to reset headers and cookies collections + /** + * Just before the request we set the request object so it is always fresh. + * @todo Implement some kind of check to see if someone tried to change the objects' properties and expects + * those changes to be reflected in the reponse. + */ $app->set('request', $app->getComponents()['request']); + $yiiRequest = $app->getRequest(); if ($request->getContent() !== null) { $yiiRequest->setRawBody($request->getContent()); @@ -148,17 +127,23 @@ public function doRequest($request) $yiiRequest->setQueryParams($_GET); try { + /* + * This is basically equivalent to $app->run() without sending the response. + * Sending the response is problematic because it tries to send headers. + */ $app->trigger($app::EVENT_BEFORE_REQUEST); - - $app->handleRequest($yiiRequest)->send(); - + $response = $app->handleRequest($yiiRequest); $app->trigger($app::EVENT_AFTER_REQUEST); + codecept_debug($response->isSent); + $response->send(); } catch (\Exception $e) { if ($e instanceof HttpException) { // Don't discard output and pass exception handling to Yii to be able // to expect error response codes in tests. $app->errorHandler->discardExistingOutput = false; $app->errorHandler->handleException($e); + $response = $app->response; + } elseif (!$e instanceof ExitException) { // for exceptions not related to Http, we pass them to Codeception $this->resetApplication(); @@ -166,17 +151,18 @@ public function doRequest($request) } } - $content = ob_get_clean(); + $this->encodeCookies($response, $yiiRequest, $app->security); - // catch "location" header and display it in debug, otherwise it would be handled - // by symfony browser-kit and not displayed. - if (isset($this->headers['location'])) { - Debug::debug("[Headers] " . json_encode($this->headers)); + if ($response->isRedirection) { + Debug::debug("[Redirect with headers]" . print_r($response->getHeaders()->toArray(), true)); } - $this->resetApplication(); + $content = ob_get_clean(); + if (empty($content) && !empty($response->content)) { + throw new \Exception('No content was sent from Yii application'); + } - return new Response($content, $this->statusCode, $this->headers); + return new Response($content, $response->statusCode, $response->getHeaders()->toArray()); } protected function revertErrorHandler() @@ -186,36 +172,28 @@ protected function revertErrorHandler() } - public function restoreServerVars() - { - $this->server = $this->defaultServerVars; - foreach ($this->server as $key => $value) { - $_SERVER[$key] = $value; - } - } - - public function processResponse($event) - { - /** @var \yii\web\Response $response */ - $response = $event->sender; - $request = Yii::$app->getRequest(); - $this->headers = $response->getHeaders()->toArray(); - $response->getHeaders()->removeAll(); - $this->statusCode = $response->getStatusCode(); - $cookies = $response->getCookies(); - + /** + * Encodes the cookies and adds them to the headers. + * @param \yii\web\Response $response + * @throws \yii\base\InvalidConfigException + */ + protected function encodeCookies( + YiiResponse $response, + Request $request, + Security $security + ) { if ($request->enableCookieValidation) { $validationKey = $request->cookieValidationKey; } - foreach ($cookies as $cookie) { + foreach ($response->getCookies() as $cookie) { /** @var \yii\web\Cookie $cookie */ $value = $cookie->value; if ($cookie->expire != 1 && isset($validationKey)) { $data = version_compare(Yii::getVersion(), '2.0.2', '>') ? [$cookie->name, $cookie->value] : $cookie->value; - $value = Yii::$app->security->hashData(serialize($data), $validationKey); + $value = $security->hashData(serialize($data), $validationKey); } $c = new Cookie( $cookie->name, @@ -228,21 +206,15 @@ public function processResponse($event) ); $this->getCookieJar()->set($c); } - $cookies->removeAll(); } /** * Replace mailer with in memory mailer - * @param $config - * @param $app + * @param array $config Original configuration + * @return array New configuration */ - protected function mockMailer($config) + protected function mockMailer(array $config) { - if (static::$mailer) { - $this->app->set('mailer', static::$mailer); - return; - } - // options that make sense for mailer mock $allowedOptions = [ 'htmlLayout', @@ -267,21 +239,24 @@ protected function mockMailer($config) } } } + $config['components']['mailer'] = $mailerConfig; - $this->app->set('mailer', $mailerConfig); - static::$mailer = $this->app->get('mailer'); + return $config; } /** - * @param $app + * A new client is created for every test, it is destroyed after every test. + * @see InnerBrowser::_after() + * */ - protected function persistDb() + public function __destruct() { - // always use the same DB connection - if (static::$db) { - $this->app->set('db', static::$db); - } elseif ($this->app->has('db')) { - static::$db = $this->app->get('db'); - } + $this->resetApplication(); + } + + public function restart() + { + parent::restart(); + $this->resetApplication(); } } diff --git a/src/Codeception/Module/Yii2.php b/src/Codeception/Module/Yii2.php index 76cfde3858..9d679ff896 100644 --- a/src/Codeception/Module/Yii2.php +++ b/src/Codeception/Module/Yii2.php @@ -8,14 +8,25 @@ use Codeception\Lib\Framework; use Codeception\Lib\Interfaces\ActiveRecord; use Codeception\Lib\Interfaces\PartedModule; -use Codeception\Lib\Notification; use Codeception\TestInterface; +use Codeception\Util\Debug; use Yii; +use yii\base\Event; use yii\db\ActiveRecordInterface; +use yii\db\Connection; +use yii\db\QueryInterface; +use yii\db\Transaction; /** * This module provides integration with [Yii framework](http://www.yiiframework.com/) (2.0). * It initializes Yii framework in test environment and provides actions for functional testing. + * ## Application state during testing + * This section details what you can expect when using this module. + * * You will get a fresh application in `\Yii::$app` at the start of each test (available in the test and in `_before()`). + * * When executing a request via one of the request functions the `request` and `response` component are both recreated. + * * After a request the whole application is available for inspection / interaction. + * * You may use multiple database connections, each will use a separate transaction; to prevent accidental mistakes we + * will warn you if you try to connect to the same database twice but we cannot reuse the same connection. * * ## Config * @@ -24,6 +35,8 @@ * * `entryScript` - front script title (like: index-test.php). If not set - taken from entryUrl. * * `transaction` - (default: true) wrap all database connection inside a transaction and roll it back after the test. Should be disabled for acceptance testing.. * * `cleanup` - (default: true) cleanup fixtures after the test + * * `ignoreCollidingDSN` - (default: false) When 2 database connections use the same DSN but different settings an exception will be thrown, set this to true to disable this behavior. + * * `fixturesMethod` - (default: _fixtures) Name of the method used for creating fixtures. * * You can use this module by setting params in your functional.suite.yml: * @@ -122,67 +135,124 @@ * Maintainer: **samdark** * Stability: **stable** * + * @property \Codeception\Lib\Connector\Yii2 $client */ class Yii2 extends Framework implements ActiveRecord, PartedModule { - const TEST_FIXTURES_METHOD = '_fixtures'; - /** * Application config file must be set. * @var array */ protected $config = [ + 'fixturesMethod' => '_fixtures', 'cleanup' => true, + 'ignoreCollidingDSN' => false, 'transaction' => null, 'entryScript' => '', 'entryUrl' => 'http://localhost/index-test.php', ]; protected $requiredFields = ['configFile']; - protected $transaction; /** - * @var \yii\base\Application + * @var array Array of Transaction objects indexed by a string key + */ + private $transactions = []; + /** + * @var \PDO[] Array of PDO objects indexed by a string key + */ + private $pdoCache = []; + /** + * @var string[] Array of cache keys indexes by their DSN */ - public $app; + private $dsnCache = []; /** * @var Yii2Connector\FixturesStore[] */ public $loadedFixtures = []; + /** + * @var array The contents of $_SERVER upon initialization of this object. + * This is only used to restore it upon object destruction. + * It MUST not be used anywhere else. + */ + private $server; public function _initialize() { if ($this->config['transaction'] === null) { $this->config['transaction'] = $this->backupConfig['transaction'] = $this->config['cleanup']; } + $this->defineConstants(); + $this->server = $_SERVER; + $this->initServerGlobal(); + } + + + /** + * Module configuration changed inside a test. + * We might need to re-create the application. + */ + protected function onReconfigure() + { + parent::onReconfigure(); + if (isset(\Yii::$app)) { + $this->client->restart(); + } + } + + + /** + * Adds the required server params. + * Note this is done separately from the request cycle since someone might call + * `Url::to` before doing a request, which would instantiate the request component with incorrect server params. + */ + private function initServerGlobal() + { + + $entryUrl = $this->config['entryUrl']; + $entryFile = $this->config['entryScript'] ?: basename($entryUrl); + $entryScript = $this->config['entryScript'] ?: parse_url($entryUrl, PHP_URL_PATH); + $_SERVER = array_merge($_SERVER, [ + 'SCRIPT_FILENAME' => $entryFile, + 'SCRIPT_NAME' => $entryScript, + 'SERVER_NAME' => parse_url($entryUrl, PHP_URL_HOST), + 'SERVER_PORT' => parse_url($entryUrl, PHP_URL_PORT) ?: '80', + 'HTTPS' => parse_url($entryUrl, PHP_URL_SCHEME) === 'https' + ]); + } + + protected function validateConfig() + { + parent::validateConfig(); if (!is_file(Configuration::projectDir() . $this->config['configFile'])) { throw new ModuleConfigException( __CLASS__, "The application config file does not exist: " . Configuration::projectDir() . $this->config['configFile'] ); } - $this->defineConstants(); } + public function _before(TestInterface $test) { $entryUrl = $this->config['entryUrl']; $entryFile = $this->config['entryScript'] ?: basename($entryUrl); $entryScript = $this->config['entryScript'] ?: parse_url($entryUrl, PHP_URL_PATH); - $this->client = new Yii2Connector(); - $this->client->defaultServerVars = [ + $this->client = new Yii2Connector([ 'SCRIPT_FILENAME' => $entryFile, - 'SCRIPT_NAME' => $entryScript, - 'SERVER_NAME' => parse_url($entryUrl, PHP_URL_HOST), - 'SERVER_PORT' => parse_url($entryUrl, PHP_URL_PORT) ?: '80', - ]; - $this->client->defaultServerVars['HTTPS'] = parse_url($entryUrl, PHP_URL_SCHEME) === 'https'; - $this->client->restoreServerVars(); + 'SCRIPT_NAME' => $entryScript, + 'SERVER_NAME' => parse_url($entryUrl, PHP_URL_HOST), + 'SERVER_PORT' => parse_url($entryUrl, PHP_URL_PORT) ?: '80', + 'HTTPS' => parse_url($entryUrl, PHP_URL_SCHEME) === 'https' + ]); + $this->client->configFile = Configuration::projectDir() . $this->config['configFile']; - $this->app = $this->client->getApplication(); + + $this->client->resetApplication(); + $app = $this->client->getApplication(); // load fixtures before db transaction if ($test instanceof \Codeception\Test\Cest) { @@ -191,13 +261,7 @@ public function _before(TestInterface $test) $this->loadFixtures($test); } - if ($this->config['transaction'] - && $this->app->has('db') - && $this->app->db instanceof \yii\db\Connection - ) { - $this->transaction = $this->app->db->beginTransaction(); - $this->debugSection('Database', 'Transaction started'); - } + $this->startTransactions(); } /** @@ -207,11 +271,27 @@ public function _before(TestInterface $test) */ private function loadFixtures($test) { + $this->debugSection('Fixtures', 'Loading fixtures'); + /** @var Connection[] $connections */ + $connections = []; + // Register event handler. + Event::on(Connection::class, Connection::EVENT_AFTER_OPEN, function (Event $event) use (&$connections) { + $this->debugSection('Fixtures', 'Opened database connection: ' . $event->sender->dsn); + $connections[] = $event->sender; + }); if (empty($this->loadedFixtures) - && method_exists($test, self::TEST_FIXTURES_METHOD) + && method_exists($test, $this->_getConfig('fixturesMethod')) ) { - $this->haveFixtures(call_user_func([$test, self::TEST_FIXTURES_METHOD])); + $this->haveFixtures(call_user_func([$test, $this->_getConfig('fixturesMethod')])); + } + + Event::offAll(); + // Close all connections so they get properly reopened after the transaction handler has been attached. + foreach ($connections as $connection) { + $this->debugSection('Fixtures', 'Closing database connection: ' . $connection->dsn); + $connection->close(); } + $this->debugSection('Fixtures', 'Done'); } public function _after(TestInterface $test) @@ -223,10 +303,7 @@ public function _after(TestInterface $test) $_COOKIE = []; $_REQUEST = []; - if ($this->config['transaction'] && $this->transaction) { - $this->transaction->rollBack(); - $this->debugSection('Database', 'Transaction cancelled; all changes reverted.'); - } + $this->rollbackTransactions(); if ($this->config['cleanup']) { foreach ($this->loadedFixtures as $fixture) { @@ -235,20 +312,78 @@ public function _after(TestInterface $test) $this->loadedFixtures = []; } - if ($this->client) { - $this->client->resetPersistentVars(); + if ($this->client->getApplication()->has('session', true)) { + $this->client->getApplication()->session->close(); } - if (isset(\Yii::$app) && \Yii::$app->has('session', true)) { - \Yii::$app->session->close(); - } + parent::_after($test); + } - // Close connections if exists - if (isset(\Yii::$app) && \Yii::$app->has('db', true)) { - \Yii::$app->db->close(); + protected function startTransactions() + { + if ($this->config['transaction']) { + // This should register handlers that start a transaction whenever a connection opens and add it to the transactions array. + Event::on(Connection::class, Connection::EVENT_AFTER_OPEN, function (Event $event) { + if ($event->sender instanceof Connection) { + $connection = $event->sender; + /* + * We should check if the known PDO objects are the same, in which case we should reuse the PDO + * object so only 1 transaction is started and multiple connections to the same database see the + * same data (due to writes inside a transaction not being visible from the outside). + * + */ + $key = md5(json_encode([ + 'dsn' => $connection->dsn, + 'user' => $connection->username, + 'pass' => $connection->password, + 'attributes' => $connection->attributes, + 'emulatePrepare' => $connection->emulatePrepare, + 'charset' => $connection->charset + ])); + + /* + * If keys match we assume connections are "similar enough". + */ + if (isset($this->pdoCache[$key])) { + $connection->pdo = $this->pdoCache[$key]; + } + + if (isset($this->dsnCache[$connection->dsn]) + && $this->dsnCache[$connection->dsn] !== $key + && !$this->config['ignoreCollidingDSN'] + ) { + $this->debugSection('WARNING', <<dsn}) with different configuration. +These connections will not see the same database state since we cannot share a transaction between different PDO +instances. +You can remove this message by adding 'ignoreCollidingDSN = true' in the module configuration. +TEXT + ); + Debug::pause(); + } + + if (isset($this->transactions[$key])) { + $this->debugSection('Database', 'Reusing PDO, so no need for a new transaction'); + return; + } + + $this->debugSection('Database', 'Transaction started for: ' . $connection->dsn); + $this->transactions[$key] = $connection->beginTransaction(); + } + }); } + } - parent::_after($test); + protected function rollbackTransactions() + { + /** @var Transaction $transaction */ + foreach ($this->transactions as $transaction) { + $transaction->rollBack(); + $this->debugSection('Database', 'Transaction cancelled; all changes reverted.'); + } + $this->transactions = []; + $this->pdoCache = []; + $this->dsnCache = []; } public function _parts() @@ -276,17 +411,17 @@ public function _parts() */ public function amLoggedInAs($user) { - if (!Yii::$app->has('user')) { + if (!$this->client->getApplication()->has('user')) { throw new ModuleException($this, 'User component is not loaded'); } if ($user instanceof \yii\web\IdentityInterface) { $identity = $user; } else { // class name implementing IdentityInterface - $identityClass = Yii::$app->user->identityClass; + $identityClass = $this->client->getApplication()->user->identityClass; $identity = call_user_func([$identityClass, 'findIdentity'], $user); } - Yii::$app->user->login($identity); + $this->client->getApplication()->user->login($identity); } /** @@ -407,7 +542,7 @@ public function grabFixture($name, $index = null) public function haveRecord($model, $attributes = []) { /** @var $record \yii\db\ActiveRecord * */ - $record = $this->getModelRecord($model); + $record = \Yii::createObject($model); $record->setAttributes($attributes, false); $res = $record->save(false); if (!$res) { @@ -473,24 +608,32 @@ public function grabRecord($model, $attributes = []) return $this->findRecord($model, $attributes); } + /** + * @param string $model Class name + * @param array $attributes + * @return mixed + */ protected function findRecord($model, $attributes = []) - { - $this->getModelRecord($model); - return call_user_func([$model, 'find']) - ->andWhere($attributes) - ->one(); - } - - protected function getModelRecord($model) { if (!class_exists($model)) { - throw new \RuntimeException("Model $model does not exist"); + throw new \RuntimeException("Class $model does not exist"); } - $record = Yii::createObject($model); - if (!$record instanceof ActiveRecordInterface) { - throw new \RuntimeException("Model $model is not implement interface \\yii\\db\\ActiveRecordInterface"); + $rc = new \ReflectionClass($model); + if ($rc->hasMethod('find') + && ($findMethod = $rc->getMethod('find')) + && $findMethod->isStatic() + && $findMethod->isPublic() + && $findMethod->getNumberOfRequiredParameters() === 0 + ) { + $activeQuery = $findMethod->invoke(null); + if ($activeQuery instanceof QueryInterface) { + return $activeQuery->andWhere($attributes)->one(); + } + + throw new \RuntimeException("$model::find() must return an instance of yii\db\QueryInterface"); + } - return $record; + throw new \RuntimeException("Class $model does not have a public static find() method without required parameters"); } /** @@ -522,7 +665,7 @@ public function amOnRoute($route, array $params = []) protected function clientRequest($method, $uri, array $parameters = [], array $files = [], array $server = [], $content = null, $changeHistory = true) { if (is_array($uri)) { - $uri = Yii::$app->getUrlManager()->createUrl($uri); + $uri = $this->client->getApplication()->getUrlManager()->createUrl($uri); } return parent::clientRequest($method, $uri, $parameters, $files, $server, $content, $changeHistory); } @@ -541,10 +684,10 @@ protected function clientRequest($method, $uri, array $parameters = [], array $f */ public function grabComponent($component) { - if (!Yii::$app->has($component)) { + if (!$this->client->getApplication()->has($component)) { throw new ModuleException($this, "Component $component is not available in current application"); } - return Yii::$app->get($component); + return $this->client->getApplication()->get($component); } /** @@ -660,10 +803,10 @@ function ($matches) use (&$parameters) { */ public function getInternalDomains() { - $domains = [$this->getDomainRegex(Yii::$app->urlManager->hostInfo)]; + $domains = [$this->getDomainRegex($this->client->getApplication()->urlManager->hostInfo)]; - if (Yii::$app->urlManager->enablePrettyUrl) { - foreach (Yii::$app->urlManager->rules as $rule) { + if ($this->client->getApplication()->urlManager->enablePrettyUrl) { + foreach ($this->client->getApplication()->urlManager->rules as $rule) { /** @var \yii\web\UrlRule $rule */ if (isset($rule->host)) { $domains[] = $this->getDomainRegex($rule->host); @@ -689,8 +832,8 @@ private function defineConstants() public function setCookie($name, $val, array $params = []) { // Sign the cookie. - if ($this->app->request->enableCookieValidation) { - $val = $this->app->security->hashData(serialize([$name, $val]), $this->app->request->cookieValidationKey); + if ($this->client->getApplication()->request->enableCookieValidation) { + $val = $this->client->getApplication()->security->hashData(serialize([$name, $val]), $this->client->getApplication()->request->cookieValidationKey); } parent::setCookie($name, $val, $params); } @@ -702,9 +845,18 @@ public function setCookie($name, $val, array $params = []) */ public function createAndSetCsrfCookie($val) { - $masked = $this->app->security->maskToken($val); - $name = $this->app->request->csrfParam; + $masked = $this->client->getApplication()->security->maskToken($val); + $name = $this->client->getApplication()->request->csrfParam; $this->setCookie($name, $val); return [$name, $masked]; } + + public function _afterSuite() + { + parent::_afterSuite(); + codecept_debug('Suite done, restoring $_SERVER to original'); + + $_SERVER = $this->server; + } + } From 59afc7c9c0dd1a653ab20842894528356426bca9 Mon Sep 17 00:00:00 2001 From: Michael Bodnarchuk Date: Sun, 1 Apr 2018 01:30:08 +0300 Subject: [PATCH 024/395] Prepare 241 (#4904) * updates to composer * updated changelog * fixed installing pecl modules * * Added documentation for `callArtisan` * Fixed warning tests for PHPUnit 5.6 * fixed travis builds * fixed WebDriver tests --- .travis.yml | 3 +- CHANGELOG-2.4.md | 26 ++++++++--- RoboFile.php | 17 +------- composer.json | 2 +- src/Codeception/Module/Laravel5.php | 9 ++-- src/Codeception/Module/WebDriver.php | 64 +++++++++++++++++----------- tests/cli/RunCest.php | 2 +- tests/data/app/db | 2 +- tests/web.suite.yml | 3 +- tests/web/WebDriverTest.php | 10 ++--- 10 files changed, 77 insertions(+), 61 deletions(-) diff --git a/.travis.yml b/.travis.yml index ebf56b4572..febacbc628 100644 --- a/.travis.yml +++ b/.travis.yml @@ -78,7 +78,7 @@ before_install: install: - '[[ -z "$CI_USER_TOKEN" ]] || composer config github-oauth.github.com ${CI_USER_TOKEN};' # Add extensions - - '[[ -z "$PECL" ]] || (yes "" | pecl install $PECL)' + - '[[ -z "$PECL" ]] || (yes "" | pecl install -f $PECL)' # Clone test repository - '[[ "$FRAMEWORK" == "Codeception" ]] || git clone -q --depth=1 $TEST_REPO framework-tests' - '[[ "$FRAMEWORK" == "Codeception" ]] || git --git-dir framework-tests/.git log -n 1' @@ -128,5 +128,4 @@ before_script: # Build - php codecept build -c $TEST_PATH script: - #- '[[ !("$FRAMEWORK" == "Codeception" && "$TRAVIS_PHP_VERSION" == "7.1") ]] || php codecept run coverage' # run coverage tests on php only - php codecept run $SUITES -c $TEST_PATH \ No newline at end of file diff --git a/CHANGELOG-2.4.md b/CHANGELOG-2.4.md index 70b806a390..0b17e0faab 100644 --- a/CHANGELOG-2.4.md +++ b/CHANGELOG-2.4.md @@ -1,3 +1,22 @@ +#### 2.4.1 + +* Fixed `PHP Fatal error: Uncaught Error: Call to undefined method Codeception\Test\Descriptor::getTestDataSetIndex()` when filtering tests +* Better support of PHPUnit warning status by @edno: + * support PHPUnit addWarning() + * display 'W' instead of success for warning test cases +* Fixed Running test with invalid dataprovider by @okneloper. Fixed #4888 by @edno +* [Yii2] **Request flow and database transactions refactored** (by @sammousa): + * **Breaking** Application is no longer available in helpers via `$this->getModule('Yii2'')->app`, now you must use `\Yii::$app` everywhere + * Multiple databases are now supported + * More reliable application state before and during test execution + * Fixtures method is now configurable + * Subset of misconfigurations are now detected and informative messages created +* Fixed using `$settings['path']` in `Codeception\Configuration::suiteSettings()` on Windows by @olegpro +* [Laravel5] Added Laravel 5.4+ (5.1+ backward compatible) support for `callArtisan` method in Laravel5 module. See #4860 by @mohamed-aiman +* Fixed #4854: unnecessary escaping in operation arguments logging by @nicholascus +* Fixed humanizing steps for utf8 strings by @nicholascus. See #4850 +* Fixed parsing relative urls in `parse_url`. See #4853 by @quantum-x + #### 2.4.0 * **PHPUnit 7.x compatibility** @@ -10,12 +29,7 @@ * `_failed` called when test fails * `_passed` called when tests is successful * `_after` is called for failing and successful tests -* Yii2 Module request flow and database transactions refactored (by @sammousa): - * Multiple databases are now supported - * More reliable application state before and during test execution - * Fixtures method is now configurable - * Subset of misconfigurations are now detected and create informative messages - * Application is no longer available via the `$module->app`, now you must use `\Yii::$app` everywhere + **Upgrade Notice**: If you face issues with underscore PHPUnit class names (like PHPUnit_Framework_Assert) you have two options: * Lock version for PHPUnit in composer.json: "phpunit/phpunit":"^5.0.0" diff --git a/RoboFile.php b/RoboFile.php index e06510c685..8e8e913a62 100644 --- a/RoboFile.php +++ b/RoboFile.php @@ -96,11 +96,6 @@ public function testCoverage() public function testWebdriver($args = '', $opt = ['test|t' => null]) { $test = $opt['test'] ? ':'.$opt['test'] : ''; - $container = $this->taskDockerRun('davert/selenium-env') - ->detached() - ->publish(4444, 4444) - ->env('APP_PORT', 8000) - ->run(); $this->taskServer(8000) ->dir('tests/data/app') @@ -108,22 +103,14 @@ public function testWebdriver($args = '', $opt = ['test|t' => null]) ->host('0.0.0.0') ->run(); - sleep(3); // wait for selenium to launch - $this->taskCodecept('./codecept') - ->test('tests/web/WebDriverTest.php'.$test) + ->suite('web') ->args($args) ->run(); - - $this->taskDockerStop($container)->run(); } - public function testLaunchServer($pathToSelenium = '~/selenium-server.jar ') + public function testLaunchServer() { - $this->taskExec('java -jar '.$pathToSelenium) - ->background() - ->run(); - $this->taskServer(8010) ->background() ->dir('tests/data/rest') diff --git a/composer.json b/composer.json index 80fda783a2..d707d4e5e8 100644 --- a/composer.json +++ b/composer.json @@ -29,7 +29,7 @@ "symfony/css-selector": ">=2.7 <5.0", "symfony/dom-crawler": ">=2.7 <5.0", "behat/gherkin": "^4.4.0", - "codeception/phpunit-wrapper": "^6.0|^7.0", + "codeception/phpunit-wrapper": "^6.0.9|^7.0.6", "codeception/stub": "^1.0" }, "require-dev": { diff --git a/src/Codeception/Module/Laravel5.php b/src/Codeception/Module/Laravel5.php index 2c537b3681..e97f536b95 100644 --- a/src/Codeception/Module/Laravel5.php +++ b/src/Codeception/Module/Laravel5.php @@ -419,19 +419,22 @@ public function dontSeeEventTriggered($events) * callArtisan('command:name'); * $I->callArtisan('command:name', ['parameter' => 'value']); - * ?> * ``` - + * Use 3rd parameter to pass in custom `OutputInterface` + * * @param string $command * @param array $parameters * @param OutputInterface $output + * @return string */ public function callArtisan($command, $parameters = [], OutputInterface $output = null) { $console = $this->app->make('Illuminate\Contracts\Console\Kernel'); if (!$output) { $console->call($command, $parameters); - return trim($console->output()); + $output = trim($console->output()); + $this->debug($output); + return $output; } $console->call($command, $parameters, $output); diff --git a/src/Codeception/Module/WebDriver.php b/src/Codeception/Module/WebDriver.php index 942eaae15d..1b575f03f6 100644 --- a/src/Codeception/Module/WebDriver.php +++ b/src/Codeception/Module/WebDriver.php @@ -341,6 +341,18 @@ public function _requires() return ['Facebook\WebDriver\Remote\RemoteWebDriver' => '"facebook/webdriver": "^1.0.1"']; } + /** + * @return RemoteWebElement + * @throws ModuleException + */ + protected function getBaseElement() + { + if (!$this->baseElement) { + throw new ModuleException($this, "Page not loaded. Use `\$I->amOnPage` (or hidden API methods `_request` and `_loadPage`) to open it"); + } + return $this->baseElement; + } + public function _initialize() { $this->wdHost = sprintf('%s://%s:%s%s', $this->config['protocol'], $this->config['host'], $this->config['port'], $this->config['path']); @@ -682,7 +694,7 @@ protected function getProxy() public function _getCurrentUri() { $url = $this->webDriver->getCurrentURL(); - if ($url == 'about:blank') { + if ($url == 'about:blank' || strpos($url, 'data:') === 0) { throw new ModuleException($this, 'Current url is blank, no page was opened'); } return Uri::retrieveUri($url); @@ -1087,7 +1099,7 @@ protected function findField($selector) public function seeLink($text, $url = null) { $this->enableImplicitWait(); - $nodes = $this->baseElement->findElements(WebDriverBy::partialLinkText($text)); + $nodes = $this->getBaseElement()->findElements(WebDriverBy::partialLinkText($text)); $this->disableImplicitWait(); $currentUri = $this->_getCurrentUri(); @@ -1102,7 +1114,7 @@ public function seeLink($text, $url = null) public function dontSeeLink($text, $url = null) { - $nodes = $this->baseElement->findElements(WebDriverBy::partialLinkText($text)); + $nodes = $this->getBaseElement()->findElements(WebDriverBy::partialLinkText($text)); $currentUri = $this->_getCurrentUri(); if (!$url) { $this->assertEmpty($nodes, "Link containing text '$text' was found in page $currentUri"); @@ -1213,7 +1225,7 @@ public function dontSeeInFormFields($formSelector, array $params) protected function proceedSeeInFormFields($formSelector, array $params, $assertNot) { - $form = $this->match($this->baseElement, $formSelector); + $form = $this->match($this->getBaseElement(), $formSelector); if (empty($form)) { throw new ElementNotFound($formSelector, "Form via CSS or XPath"); } @@ -1540,7 +1552,7 @@ protected function findCheckable($context, $radioOrCheckbox, $byValue = false) } if (is_array($radioOrCheckbox) or ($radioOrCheckbox instanceof WebDriverBy)) { - return $this->matchFirstOrFail($this->baseElement, $radioOrCheckbox); + return $this->matchFirstOrFail($this->getBaseElement(), $radioOrCheckbox); } $locator = Crawler::xpathLiteral($radioOrCheckbox); @@ -1610,7 +1622,7 @@ public function checkOption($option) public function uncheckOption($option) { - $field = $this->findCheckable($this->baseElement, $option); + $field = $this->findCheckable($this->getBaseElement(), $option); if (!$field) { throw new ElementNotFound($option, "Checkbox by Label or CSS or XPath"); } @@ -1671,10 +1683,10 @@ public function attachFile($field, $filename) */ protected function getVisibleText() { - if ($this->baseElement instanceof RemoteWebElement) { - return $this->baseElement->getText(); + if ($this->getBaseElement() instanceof RemoteWebElement) { + return $this->getBaseElement()->getText(); } - $els = $this->baseElement->findElements(WebDriverBy::cssSelector('body')); + $els = $this->getBaseElement()->findElements(WebDriverBy::cssSelector('body')); if (isset($els[0])) { return $els[0]->getText(); } @@ -1683,7 +1695,7 @@ protected function getVisibleText() public function grabTextFrom($cssOrXPathOrRegex) { - $els = $this->match($this->baseElement, $cssOrXPathOrRegex, false); + $els = $this->match($this->getBaseElement(), $cssOrXPathOrRegex, false); if (count($els)) { return $els[0]->getText(); } @@ -1695,7 +1707,7 @@ public function grabTextFrom($cssOrXPathOrRegex) public function grabAttributeFrom($cssOrXpath, $attribute) { - $el = $this->matchFirstOrFail($this->baseElement, $cssOrXpath); + $el = $this->matchFirstOrFail($this->getBaseElement(), $cssOrXpath); return $el->getAttribute($attribute); } @@ -1712,7 +1724,7 @@ public function grabValueFrom($field) public function grabMultiple($cssOrXpath, $attribute = null) { - $els = $this->match($this->baseElement, $cssOrXpath); + $els = $this->match($this->getBaseElement(), $cssOrXpath); return array_map( function (WebDriverElement $e) use ($attribute) { if ($attribute) { @@ -1769,7 +1781,7 @@ public function dontSeeElement($selector, $attributes = []) public function seeElementInDOM($selector, $attributes = []) { $this->enableImplicitWait(); - $els = $this->match($this->baseElement, $selector); + $els = $this->match($this->getBaseElement(), $selector); $els = $this->filterByAttributes($els, $attributes); $this->disableImplicitWait(); $this->assertNotEmpty($els); @@ -1784,7 +1796,7 @@ public function seeElementInDOM($selector, $attributes = []) */ public function dontSeeElementInDOM($selector, $attributes = []) { - $els = $this->match($this->baseElement, $selector); + $els = $this->match($this->getBaseElement(), $selector); $els = $this->filterByAttributes($els, $attributes); $this->assertEmpty($els); } @@ -1809,7 +1821,7 @@ public function seeNumberOfElements($selector, $expected) public function seeNumberOfElementsInDOM($selector, $expected) { - $counted = count($this->match($this->baseElement, $selector)); + $counted = count($this->match($this->getBaseElement(), $selector)); if (is_array($expected)) { list($floor, $ceil) = $expected; $this->assertTrue( @@ -2157,7 +2169,7 @@ protected function getSubmissionFormFieldName($name) */ public function submitForm($selector, array $params, $button = null) { - $form = $this->matchFirstOrFail($this->baseElement, $selector); + $form = $this->matchFirstOrFail($this->getBaseElement(), $selector); $fields = $form->findElements( WebDriverBy::cssSelector('input:enabled,textarea:enabled,select:enabled,input[type=hidden]') @@ -2255,7 +2267,7 @@ public function submitForm($selector, array $params, $button = null) */ public function waitForElementChange($element, \Closure $callback, $timeout = 30) { - $el = $this->matchFirstOrFail($this->baseElement, $element); + $el = $this->matchFirstOrFail($this->getBaseElement(), $element); $checker = function () use ($el, $callback) { return $callback($el); }; @@ -2565,8 +2577,8 @@ public function maximizeWindow() */ public function dragAndDrop($source, $target) { - $snodes = $this->matchFirstOrFail($this->baseElement, $source); - $tnodes = $this->matchFirstOrFail($this->baseElement, $target); + $snodes = $this->matchFirstOrFail($this->getBaseElement(), $source); + $tnodes = $this->matchFirstOrFail($this->getBaseElement(), $target); $action = new WebDriverActions($this->webDriver); $action->dragAndDrop($snodes, $tnodes)->perform(); @@ -2597,7 +2609,7 @@ public function moveMouseOver($cssOrXPath = null, $offsetX = null, $offsetY = nu { $where = null; if (null !== $cssOrXPath) { - $el = $this->matchFirstOrFail($this->baseElement, $cssOrXPath); + $el = $this->matchFirstOrFail($this->getBaseElement(), $cssOrXPath); $where = $el->getCoordinates(); } @@ -2678,7 +2690,7 @@ public function pauseExecution() */ public function doubleClick($cssOrXPath) { - $el = $this->matchFirstOrFail($this->baseElement, $cssOrXPath); + $el = $this->matchFirstOrFail($this->getBaseElement(), $cssOrXPath); $this->webDriver->getMouse()->doubleClick($el->getCoordinates()); } @@ -2819,7 +2831,7 @@ protected function matchFirstOrFail($page, $selector) */ public function pressKey($element, $char) { - $el = $this->matchFirstOrFail($this->baseElement, $element); + $el = $this->matchFirstOrFail($this->getBaseElement(), $element); $args = func_get_args(); array_shift($args); $keys = []; @@ -2954,7 +2966,7 @@ public function appendField($field, $value) if ($type == 'checkbox') { //Find by value or css,id,xpath - $field = $this->findCheckable($this->baseElement, $value, true); + $field = $this->findCheckable($this->getBaseElement(), $value, true); if (!$field) { throw new ElementNotFound($value, "Checkbox or Radio by Label or CSS or XPath"); } @@ -2981,7 +2993,7 @@ public function appendField($field, $value) */ protected function matchVisible($selector) { - $els = $this->match($this->baseElement, $selector); + $els = $this->match($this->getBaseElement(), $selector); $nodes = array_filter( $els, function (WebDriverElement $el) { @@ -3096,7 +3108,7 @@ protected function isPhantom() */ public function scrollTo($selector, $offsetX = null, $offsetY = null) { - $el = $this->matchFirstOrFail($this->baseElement, $selector); + $el = $this->matchFirstOrFail($this->getBaseElement(), $selector); $x = $el->getLocation()->getX() + $offsetX; $y = $el->getLocation()->getY() + $offsetY; $this->webDriver->executeScript("window.scrollTo($x, $y)"); @@ -3239,7 +3251,7 @@ public function performOn($element, $actions, $timeout = 10) { $this->waitForElement($element, $timeout); $this->setBaseElement($element); - $this->debugSection('InnerText', $this->baseElement->getText()); + $this->debugSection('InnerText', $this->getBaseElement()->getText()); if (is_callable($actions)) { $actions($this); diff --git a/tests/cli/RunCest.php b/tests/cli/RunCest.php index 51e5ef6e9d..1e01d040dc 100644 --- a/tests/cli/RunCest.php +++ b/tests/cli/RunCest.php @@ -487,7 +487,7 @@ public function runCestWithTwoFailedTest(CliGuy $I) public function runWarningTests(CliGuy $I) { - $I->executeCommand('run unit WarningTest.php:testWarningInvalidDataProvider', false); + $I->executeCommand('run unit WarningTest.php', false); $I->seeInShellOutput('There was 1 warning'); $I->seeInShellOutput('WarningTest::testWarningInvalidDataProvider'); $I->seeInShellOutput('Tests: 1,'); diff --git a/tests/data/app/db b/tests/data/app/db index 609cdc8eb1..c856afcf97 100644 --- a/tests/data/app/db +++ b/tests/data/app/db @@ -1 +1 @@ -a:1:{s:6:"params";a:0:{}} \ No newline at end of file +a:0:{} \ No newline at end of file diff --git a/tests/web.suite.yml b/tests/web.suite.yml index fb9e581807..4a9b562556 100644 --- a/tests/web.suite.yml +++ b/tests/web.suite.yml @@ -4,7 +4,7 @@ modules: config: WebDriver: url: http://localhost:8000 - browser: firefox + browser: chrome window_size: 1200x768 restart: true # Use a new browser window for each test (to isolate test cases from each other) env: @@ -30,6 +30,7 @@ env: WebDriver: browser: chrome window_size: false + restart: false capabilities: chromeOptions: args: ["--headless", "--disable-gpu", "--disable-extensions"] diff --git a/tests/web/WebDriverTest.php b/tests/web/WebDriverTest.php index 4d07285015..26ac63e4ae 100644 --- a/tests/web/WebDriverTest.php +++ b/tests/web/WebDriverTest.php @@ -92,7 +92,7 @@ public function testFailedSeeInPopup() { $this->notForPhantomJS(); $this->setExpectedException( - 'PHPUnit_Framework_AssertionFailedError', + '\PHPUnit\Framework\AssertionFailedError', 'Failed asserting that \'Really?\' contains "Different text"' ); $this->module->amOnPage('/form/popup'); @@ -114,7 +114,7 @@ public function testFailedDontSeeInPopup() { $this->notForPhantomJS(); $this->setExpectedException( - 'PHPUnit_Framework_AssertionFailedError', + '\PHPUnit\Framework\AssertionFailedError', 'Failed asserting that \'Really?\' does not contain "Really?"' ); $this->module->amOnPage('/form/popup'); @@ -508,7 +508,7 @@ public function testCreateCeptScreenshotFail() ]); $module = Stub::make(self::MODULE_CLASS, ['webDriver' => $fakeWd]); $cept = (new \Codeception\Test\Cept('loginCept', 'loginCept.php')); - $module->_failed($cept, new PHPUnit_Framework_AssertionFailedError()); + $module->_failed($cept, new \PHPUnit\Framework\AssertionFailedError()); } public function testCreateCestScreenshotOnFail() @@ -527,7 +527,7 @@ public function testCreateCestScreenshotOnFail() ]); $module = Stub::make(self::MODULE_CLASS, ['webDriver' => $fakeWd]); $cest = new \Codeception\Test\Cest(new stdClass(), 'login', 'someCest.php'); - $module->_failed($cest, new PHPUnit_Framework_AssertionFailedError()); + $module->_failed($cest, new \PHPUnit\Framework\AssertionFailedError()); } public function testCreateTestScreenshotOnFail() @@ -549,7 +549,7 @@ public function testCreateTestScreenshotOnFail() ]), ]); $module = Stub::make(self::MODULE_CLASS, ['webDriver' => $fakeWd]); - $module->_failed($test, new PHPUnit_Framework_AssertionFailedError()); + $module->_failed($test, new \PHPUnit\Framework\AssertionFailedError()); } public function testWebDriverWaits() From bca3547632556875f1cdd567d6057cc14fe472b8 Mon Sep 17 00:00:00 2001 From: Davert Date: Sun, 1 Apr 2018 01:30:43 +0300 Subject: [PATCH 025/395] documentation updated --- docs/modules/Laravel5.md | 4 +++- docs/modules/Yii2.md | 12 +++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/docs/modules/Laravel5.md b/docs/modules/Laravel5.md index 3275146e2c..b30b0b2907 100644 --- a/docs/modules/Laravel5.md +++ b/docs/modules/Laravel5.md @@ -298,11 +298,13 @@ Call an Artisan command. callArtisan('command:name'); $I->callArtisan('command:name', ['parameter' => 'value']); -?> ``` +Use 3rd parameter to pass in custom `OutputInterface` * `param string` $command * `param array` $parameters + * `param OutputInterface` $output + * `return` string ### checkOption diff --git a/docs/modules/Yii2.md b/docs/modules/Yii2.md index ab0e376330..e95817f354 100644 --- a/docs/modules/Yii2.md +++ b/docs/modules/Yii2.md @@ -3,6 +3,13 @@ This module provides integration with [Yii framework](http://www.yiiframework.com/) (2.0). It initializes Yii framework in test environment and provides actions for functional testing. +## Application state during testing +This section details what you can expect when using this module. +* You will get a fresh application in `\Yii::$app` at the start of each test (available in the test and in `_before()`). +* When executing a request via one of the request functions the `request` and `response` component are both recreated. +* After a request the whole application is available for inspection / interaction. +* You may use multiple database connections, each will use a separate transaction; to prevent accidental mistakes we +will warn you if you try to connect to the same database twice but we cannot reuse the same connection. ## Config @@ -11,6 +18,8 @@ It initializes Yii framework in test environment and provides actions for functi * `entryScript` - front script title (like: index-test.php). If not set - taken from entryUrl. * `transaction` - (default: true) wrap all database connection inside a transaction and roll it back after the test. Should be disabled for acceptance testing.. * `cleanup` - (default: true) cleanup fixtures after the test +* `ignoreCollidingDSN` - (default: false) When 2 database connections use the same DSN but different settings an exception will be thrown, set this to true to disable this behavior. +* `fixturesMethod` - (default: _fixtures) Name of the method used for creating fixtures. You can use this module by setting params in your functional.suite.yml: @@ -101,7 +110,7 @@ This commands allows input like: $I->amOnPage(['site/view','page'=>'about']); $I->amOnPage('index-test.php?site/index'); $I->amOnPage('http://localhost/index-test.php?site/index'); -$I->sendAjaxPostRequest(['/user/update', 'id' => 1], ['UserForm[name]' => 'G.Hopper']); +$I->sendAjaxPostRequest(['/user/update', 'id' => 1], ['UserForm[name]' => 'G.Hopper'); ``` ## Status @@ -109,6 +118,7 @@ $I->sendAjaxPostRequest(['/user/update', 'id' => 1], ['UserForm[name]' => 'G.Hop Maintainer: **samdark** Stability: **stable** +@property \Codeception\Lib\Connector\Yii2 $client ## Actions From 853683f3a802166d0786670a80340f9775377da0 Mon Sep 17 00:00:00 2001 From: Davert Date: Sun, 1 Apr 2018 01:42:13 +0300 Subject: [PATCH 026/395] version bump, fixed changelog formatting --- CHANGELOG-2.4.md | 2 +- src/Codeception/Codecept.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG-2.4.md b/CHANGELOG-2.4.md index 0b17e0faab..4a6bec80a9 100644 --- a/CHANGELOG-2.4.md +++ b/CHANGELOG-2.4.md @@ -1,6 +1,6 @@ #### 2.4.1 -* Fixed `PHP Fatal error: Uncaught Error: Call to undefined method Codeception\Test\Descriptor::getTestDataSetIndex()` when filtering tests +* Fixed "Uncaught Error: Call to undefined method Codeception\Test\Descriptor::getTestDataSetIndex()" error when filtering tests. * Better support of PHPUnit warning status by @edno: * support PHPUnit addWarning() * display 'W' instead of success for warning test cases diff --git a/src/Codeception/Codecept.php b/src/Codeception/Codecept.php index 8e1626d6bf..c144ddb1de 100644 --- a/src/Codeception/Codecept.php +++ b/src/Codeception/Codecept.php @@ -7,7 +7,7 @@ class Codecept { - const VERSION = "2.4.1"; + const VERSION = "2.4.2"; /** * @var \Codeception\PHPUnit\Runner From 543839658a2ffd360ec10efc873f5d615b313116 Mon Sep 17 00:00:00 2001 From: Davert Date: Sun, 1 Apr 2018 02:23:08 +0300 Subject: [PATCH 027/395] updated docs, removed mentions of Cept format --- docs/01-Introduction.md | 4 +- docs/02-GettingStarted.md | 134 ++++++++++++++----------------- docs/03-AcceptanceTests.md | 19 +++-- docs/05-UnitTests.md | 14 ++-- docs/06-ReusingTestCode.md | 7 +- docs/07-AdvancedUsage.md | 24 +++--- docs/07-BDD.md | 2 +- docs/08-Customization.md | 10 +-- docs/10-WebServices.md | 57 ++++++------- docs/12-ContinuousIntegration.md | 10 +-- 10 files changed, 137 insertions(+), 144 deletions(-) diff --git a/docs/01-Introduction.md b/docs/01-Introduction.md index ff97b24663..5d365b7d5f 100644 --- a/docs/01-Introduction.md +++ b/docs/01-Introduction.md @@ -48,7 +48,6 @@ With acceptance tests, you can be confident that users, following all the define ```php amOnPage('/'); $I->click('Sign Up'); $I->submitForm('#signup', ['username' => 'MilesDavis', 'email' => 'miles@davis.com']); @@ -72,7 +71,6 @@ Codeception provides connectors to several popular PHP frameworks. You can also ```php amOnPage('/'); $I->click('Sign Up'); $I->submitForm('#signup', ['username' => 'MilesDavis', 'email' => 'miles@davis.com']); @@ -106,7 +104,7 @@ function testSavingUser() $user->setSurname('Davis'); $user->save(); $this->assertEquals('Miles Davis', $user->getFullName()); - $this->unitTester->seeInDatabase('users', ['name' => 'Miles', 'surname' => 'Davis']); + $this->tester->seeInDatabase('users', ['name' => 'Miles', 'surname' => 'Davis']); } ``` diff --git a/docs/02-GettingStarted.md b/docs/02-GettingStarted.md index 058b13193c..bc3fb3174e 100644 --- a/docs/02-GettingStarted.md +++ b/docs/02-GettingStarted.md @@ -59,66 +59,64 @@ When you change the configuration, the actor classes are rebuilt automatically. try to generate them manually with the `build` command: ```bash -php codecept build +php vendor/bin/codecept build ``` -## Writing a Sample Scenario +## Writing a Sample Test -By default tests are written as narrative scenarios. To make a PHP file a valid scenario, its name should have a `Cept` suffix. - -Let's say we have created a file `tests/acceptance/SigninCept.php` - -We can do that by running the following command: +Codeception has its own testing format called Cest (Codecept + Test). +To start writing a test we need to create a new Cest file. We can do that by running the following command: ```bash -php codecept generate:cept acceptance Signin +php vendor/bin/codecept generate:cest acceptance Signin ``` -A scenario always starts with actor class initialization. After that, writing a scenario is just like typing `$I->` -and choosing a proper action from the auto-completion list. Let's log in to our website: +This will generate `SigninCest.php` file inside `tests/acceptance` directory. Let's open it: ```php wantTo('login to website'); - -``` - -The `wantTo` section describes your scenario in brief. There are additional comment methods that are useful to describe the context of a scenario: +class SigninCest +{ + function _before(AcceptanceTester $I) + { + } + + public function _after(AcceptanceTester $I) + { + } -```php -am('user'); // actor's role -$I->wantTo('login to website'); // feature to test -$I->lookForwardTo('access website features for logged-in users'); // result to achieve + public function tryToTest(AcceptanceTester $I) + { + // todo: write test + } +} ``` -After we have described the story background, let's start writing a scenario. +We have `_before` and `_after` methods to run some common actions before and after a test. And we have a placeholder action `tryToTest` which we need to implement. +If we try to test a signin process it's a good start to test a successful signin. Let's rename this method to `signInSuccessfully`. -We'll assume that we have a 'login' page where we get authenticated by providing a username and password. +We'll assume that we have a 'login' page where we get authenticated by providing a username and password. Then we are sent to a user page, where we see the text `Hello, %username%`. Let's look at how this scenario is written in Codeception: ```php am('user'); -$I->wantTo('login to website'); -$I->lookForwardTo('access website features for logged-in users'); -$I->amOnPage('/login'); -$I->fillField('Username','davert'); -$I->fillField('Password','qwerty'); -$I->click('Login'); -$I->see('Hello, davert'); +class SigninCest +{ + public function loginSuccessfully(AcceptanceTester $I) + { + $I->amOnPage('/login'); + $I->fillField('Username','davert'); + $I->fillField('Password','qwerty'); + $I->click('Login'); + $I->see('Hello, davert'); + } +} ``` This scenario can probably be read by non-technical people. If you just remove all special chars like braces, arrows and `$`, this test transforms into plain English text: ``` -I am user -I wantTo login to website -I lookForwardTo access website features for logged-in users I amOnPage '/login' I fillField 'Username','davert' I fillField 'Password','qwerty' @@ -129,7 +127,7 @@ I see 'Hello, davert' Codeception generates this text representation from PHP code by executing: ```bash -php codecept generate:scenarios +php vendor/bin/codecept generate:scenarios ``` These generated scenarios will be stored in your `_data` directory in text files. @@ -149,14 +147,14 @@ modules: After configuring the URL we can run this test with the `run` command: ```bash -php codecept run +php vendor/bin/codecept run ``` This is the output we should see: ```bash Acceptance Tests (1) ------------------------------- -✔ SigninCept: Login to website +✔ SigninCest: sign in successfully ---------------------------------------------------- Time: 1 second, Memory: 21.00Mb @@ -167,19 +165,17 @@ OK (1 test, 1 assertions) Let's get some detailed output: ```bash -php codecept run acceptance --steps +php vendor/bin/codecept run acceptance --steps ``` We should see a step-by-step report on the performed actions: ```bash Acceptance Tests (1) ------------------------------- -SigninCept: Login to website -Signature: SigninCept.php -Test: tests/acceptance/SigninCept.php +SigninCest: Login to website +Signature: SigninCest.php:signInSuccessfully +Test: tests/acceptance/SigninCest.php:signInSuccessfully Scenario -- - I am user - I look forward to access website features for logged-in users I am on page "/login" I fill field "Username" "davert" I fill field "Password" "qwerty" @@ -196,54 +192,43 @@ OK (1 test, 1 assertions) This simple test can be extended to a complete scenario of site usage, therefore, by emulating the user's actions, you can test any of your websites. -Give it a try! +To run more tests create a public method for each of them. Include `AcceptanceTester` object as `$I` as a method parameter and use the same `$I->` API you've seen before. +If your tests share common setup actions put them into `_before` method. -## Cept, Cest and Test Formats - -Codeception supports three test formats. Beside the previously described scenario-based Cept format, -Codeception can also execute [PHPUnit test files for unit testing](http://codeception.com/docs/05-UnitTests), and Cest format. - -**Cest** combines scenario-driven test approach with OOP design. In case you want to group a few testing scenarios into one, you should consider using Cest format. -In the example below we are testing CRUD actions within a single file but with several tests (one per operation): +For instance, to test CRUD we want 4 methods to be implemented and all next tests should start at `/task` page: ```php amOnPage('/'); + $I->amOnPage('/task'); } - function createPage(AcceptanceTester $I) + function createTask(AcceptanceTester $I) { // todo: write test } - function viewPage(AcceptanceTester $I) + function viewTask(AcceptanceTester $I) { // todo: write test } - function updatePage(AcceptanceTester $I) + function updateTask(AcceptanceTester $I) { // todo: write test } - function deletePage(AcceptanceTester $I) + function deleteTask(AcceptanceTester $I) { // todo: write test } } ``` -Cest files such as this can be created by running a generator: - -```bash -php codecept generate:cest acceptance PageCrud -``` - Learn more about the [Cest format](http://codeception.com/docs/07-AdvancedUsage#Cest-Classes) in the Advanced Testing section. ## BDD @@ -262,44 +247,44 @@ The same goes for suite configs. For example, the `unit.suite.yml` will be merge Tests can be started with the `run` command: ```bash -php codecept run +php vendor/bin/codecept run ``` With the first argument you can run all tests from one suite: ```bash -php codecept run acceptance +php vendor/bin/codecept run acceptance ``` To limit tests run to a single class, add a second argument. Provide a local path to the test class, from the suite directory: ```bash -php codecept run acceptance SigninCept.php +php vendor/bin/codecept run acceptance SigninCest.php ``` Alternatively you can provide the full path to test file: ```bash -php codecept run tests/acceptance/SigninCept.php +php vendor/bin/codecept run tests/acceptance/SigninCest.php ``` You can further filter which tests are run by appending a method name to the class, separated by a colon (for Cest or Test formats): ```bash -php codecept run tests/acceptance/SignInCest.php:^anonymousLogin$ +php vendor/bin/codecept run tests/acceptance/SigninCest.php:^anonymousLogin$ ``` You can provide a directory path as well. This will execute all acceptance tests from the `backend` dir: ```bash -php codecept run tests/acceptance/backend +php vendor/bin/codecept run tests/acceptance/backend ``` Using regular expressions, you can even run many different test methods from the same directory or class. For example, this will execute all acceptance tests from the `backend` dir beginning with the word "login": ```bash -php codecept run tests/acceptance/backend:^login +php vendor/bin/codecept run tests/acceptance/backend:^login ``` To execute a group of tests that are not stored in the same directory, you can organize them in [groups](http://codeception.com/docs/07-AdvancedUsage#Groups). @@ -309,7 +294,7 @@ To execute a group of tests that are not stored in the same directory, you can o To generate JUnit XML output, you can provide the `--xml` option, and `--html` for HTML report. ```bash -php codecept run --steps --xml --html +php vendor/bin/codecept run --steps --xml --html ``` This command will run all tests for all suites, displaying the steps, and building HTML and XML reports. Reports will be stored in the `tests/_output/` directory. @@ -317,7 +302,7 @@ This command will run all tests for all suites, displaying the steps, and buildi To see all the available options, run the following command: ```bash -php codecept help run +php vendor/bin/codecept help run ``` ## Debugging @@ -329,7 +314,6 @@ You may print any information inside a test using the `codecept_debug` function. There are plenty of useful Codeception commands: -* `generate:cept` *suite* *filename* - Generates a sample Cept scenario * `generate:cest` *suite* *filename* - Generates a sample Cest test * `generate:test` *suite* *filename* - Generates a sample PHPUnit Test with Codeception hooks * `generate:feature` *suite* *filename* - Generates Gherkin feature file diff --git a/docs/03-AcceptanceTests.md b/docs/03-AcceptanceTests.md index bab9320268..a091298d02 100644 --- a/docs/03-AcceptanceTests.md +++ b/docs/03-AcceptanceTests.md @@ -60,13 +60,23 @@ modules: - \Helper\Acceptance ``` -We should start by creating a 'Cept' file: +We should start by creating a test with the next command: + +``` +php vendor/bin/codecept g:cest acceptance Signin +``` + +It will be placed into `tests/acceptance` directory. ```php wantTo('sign in'); +class SigninCest +{ + public function tryToTest(AcceptanceTester $I) + { + $I->wantTo('test my page'); + } +} ``` The `$I` object is used to write all interactions. @@ -203,7 +213,6 @@ you can pass instance `\Codeception\Step\Argument\PasswordArgument` with the dat ```php amOnPage('/form/password_argument'); diff --git a/docs/05-UnitTests.md b/docs/05-UnitTests.md index 0aa9400710..60b538bab5 100644 --- a/docs/05-UnitTests.md +++ b/docs/05-UnitTests.md @@ -9,7 +9,7 @@ Codeception adds some nice helpers to simplify common tasks. Create a test using `generate:test` command with a suite and test names as parameters: ```bash -php codecept generate:test unit Example +php vendor/bin/codecept generate:test unit Example ``` It creates a new `ExampleTest` file located in the `tests/unit` directory. @@ -17,13 +17,13 @@ It creates a new `ExampleTest` file located in the `tests/unit` directory. As always, you can run the newly created test with this command: ```bash -php codecept run unit ExampleTest +php vendor/bin/codecept run unit ExampleTest ``` Or simply run the whole set of unit tests with: ```bash -php codecept run unit +php vendor/bin/codecept run unit ``` A test created by the `generate:test` command will look like this: @@ -73,15 +73,15 @@ class UserTest extends \Codeception\Test\Unit { public function testValidation() { - $user = User::create(); + $user = new User(); - $user->username = null; + $user->setName(null); $this->assertFalse($user->validate(['username'])); - $user->username = 'toolooooongnaaaaaaameeee'; + $user->setName('toolooooongnaaaaaaameeee'); $this->assertFalse($user->validate(['username'])); - $user->username = 'davert'; + $user->setName('davert'); $this->assertTrue($user->validate(['username'])); } } diff --git a/docs/06-ReusingTestCode.md b/docs/06-ReusingTestCode.md index ba076e333c..5ac61a6398 100644 --- a/docs/06-ReusingTestCode.md +++ b/docs/06-ReusingTestCode.md @@ -12,7 +12,6 @@ We will get back to this later in this chapter, but for now let's look at the fo ```php amOnPage('/'); $I->see('Hello'); $I->seeInDatabase('users', ['id' => 1]); @@ -150,14 +149,14 @@ We call such a classes StepObjects. Lets create an Admin StepObject with the generator: ```bash -php codecept generate:stepobject acceptance Admin +php vendor/bin/codecept generate:stepobject acceptance Admin ``` You can supply optional action names. Enter one at a time, followed by a newline. End with an empty line to continue to StepObject creation. ```bash -php codecept generate:stepobject acceptance Admin +php vendor/bin/codecept generate:stepobject acceptance Admin Add action to StepObject class (ENTER to exit): loginAsAdmin Add action to StepObject class (ENTER to exit): StepObject was created in /tests/acceptance/_support/Step/Acceptance/Admin.php @@ -243,7 +242,7 @@ Do not hardcode complex CSS or XPath locators in your tests but rather move them Codeception can generate a PageObject class for you with command: ```bash -php codecept generate:pageobject Login +php vendor/bin/codecept generate:pageobject Login ``` This will create a `Login` class in `tests/_support/Page`. diff --git a/docs/07-AdvancedUsage.md b/docs/07-AdvancedUsage.md index 9d8377cc41..dba333b58b 100644 --- a/docs/07-AdvancedUsage.md +++ b/docs/07-AdvancedUsage.md @@ -12,7 +12,7 @@ and you want to split it, you can easily move it into classes. You can create a Cest file by running the command: ```bash -$ php codecept generate:cest suitename CestName +$ php vendor/bin/codecept generate:cest suitename CestName ``` The generated file will look like this: @@ -387,7 +387,7 @@ The names of these files are used as environments names You can generate a new file with this environment configuration by using the `generate:environment` command: ```bash -$ php codecept g:env chrome +$ php vendor/bin/codecept g:env chrome ``` In that file you can specify just the options you wish to override: @@ -405,13 +405,13 @@ You can easily switch between those configs by running tests with `--env` option To run the tests only for PhantomJS you just need to pass `--env phantom` as an option: ```bash -$ php codecept run acceptance --env phantom +$ php vendor/bin/codecept run acceptance --env phantom ``` To run the tests in all 3 browsers, list all the environments: ```bash -$ php codecept run acceptance --env phantom --env chrome --env firefox +$ php vendor/bin/codecept run acceptance --env phantom --env chrome --env firefox ``` The tests will be executed 3 times, each time in a different browser. @@ -419,7 +419,7 @@ The tests will be executed 3 times, each time in a different browser. It's also possible to merge multiple environments into a single configuration by separating them with a comma: ```bash -$ php codecept run acceptance --env dev,phantom --env dev,chrome --env dev,firefox +$ php vendor/bin/codecept run acceptance --env dev,phantom --env dev,chrome --env dev,firefox ``` The configuration is merged in the order given. @@ -543,7 +543,7 @@ The interactive console was added to try Codeception commands before executing t You can run the console with the following command: ``` bash -$ php codecept console suitename +$ php vendor/bin/codecept console suitename ``` Now you can execute all the commands of an appropriate Actor class and see the results immediately. @@ -560,15 +560,15 @@ If you have several projects with Codeception tests, you can use a single `codec You can pass the `-c` option to any Codeception command (except `bootstrap`), to execute Codeception in another directory: ```bash -$ php codecept run -c ~/projects/ecommerce/ -$ php codecept run -c ~/projects/drupal/ -$ php codecept generate:cept acceptance CreateArticle -c ~/projects/drupal/ +$ php vendor/bin/codecept run -c ~/projects/ecommerce/ +$ php vendor/bin/codecept run -c ~/projects/drupal/ +$ php vendor/bin/codecept generate:cept acceptance CreateArticle -c ~/projects/drupal/ ``` To create a project in directory different from the current one, just provide its path as a parameter: ```bash -$ php codecept bootstrap ~/projects/drupal/ +$ php vendor/bin/codecept bootstrap ~/projects/drupal/ ``` Also, the `-c` option allows you to specify another config file to be used. @@ -580,13 +580,13 @@ and settings). Just pass the `.yml` filename as the `-c` parameter to execute te There are several ways to execute a bunch of tests. You can run tests from a specific directory: ```bash -$ php codecept run tests/acceptance/admin +$ php vendor/bin/codecept run tests/acceptance/admin ``` You can execute one (or several) specific groups of tests: ```bash -$ php codecept run -g admin -g editor +$ php vendor/bin/codecept run -g admin -g editor ``` The concept of groups was taken from PHPUnit and behave in the same way. diff --git a/docs/07-BDD.md b/docs/07-BDD.md index 1c05986f37..c4e7bfcd1a 100644 --- a/docs/07-BDD.md +++ b/docs/07-BDD.md @@ -81,7 +81,7 @@ Feature file is written in Gherkin format. Codeception can generate a feature fi We will assume that we will use scenarios in feature files for acceptance tests, so feature files to be placed in `acceptance` suite directory: ```bash -php codecept g:feature acceptance checkout +php vendor/bin/codecept g:feature acceptance checkout ``` Generated template will look like this: diff --git a/docs/08-Customization.md b/docs/08-Customization.md index dde87bfbd1..22e1d2f021 100644 --- a/docs/08-Customization.md +++ b/docs/08-Customization.md @@ -34,7 +34,7 @@ To avoid naming conflicts between Actor classes and Helper classes, they should To create test suites with namespaces you can add `--namespace` option to the bootstrap command: ```bash -php codecept bootstrap --namespace frontend +php vendor/bin/codecept bootstrap --namespace frontend ``` This will bootstrap a new project with the `namespace: frontend` parameter in the `codeception.yml` file. @@ -44,7 +44,7 @@ Once each of your applications (bundles) has its own namespace and different Hel you can execute all the tests in a single runner. Run the Codeception tests as usual, using the meta-config we created earlier: ```bash -php codecept run +php vendor/bin/codecept run ``` This will launch the test suites for all three applications and merge the reports from all of them. @@ -54,7 +54,7 @@ and you want to get a single report in JUnit and HTML format. The code coverage If you want to run a specific suite from the application you can execute: ``` -php codecept run unit -c frontend +php vendor/bin/codecept run unit -c frontend ``` Where `unit` is the name of suite and the `-c` option specifies the path to the `codeception.yml` configuration file to use. @@ -71,7 +71,7 @@ By default, one `RunFailed` Extension is already enabled in your global `codecep It allows you to rerun failed tests by using the `-g failed` option: ``` -php codecept run -g failed +php vendor/bin/codecept run -g failed ``` Codeception comes with bundled extensions located in `ext` directory. @@ -293,7 +293,7 @@ For instance, for `nocleanup` group we prevent Doctrine2 module from wrapping te } ``` -A group class can be created with `php codecept generate:group groupname` command. +A group class can be created with `php vendor/bin/codecept generate:group groupname` command. Group classes will be stored in the `tests/_support/Group` directory. A group class can be enabled just like you enable an extension class. In the file `codeception.yml`: diff --git a/docs/10-WebServices.md b/docs/10-WebServices.md index 7c5556294d..79a907bf7d 100644 --- a/docs/10-WebServices.md +++ b/docs/10-WebServices.md @@ -5,7 +5,7 @@ The same way we tested a web site, Codeception allows you to test web services. You should start by creating a new test suite, (which was not provided by the `bootstrap` command). We recommend calling it **api** and using the `ApiTester` class for it. ```bash -$ php codecept generate:suite api +$ php vendor/bin/codecept generate:suite api ``` We will put all the api tests there. @@ -51,22 +51,36 @@ modules: Once we have configured our new testing suite, we can create the first sample test: ```bash -$ php codecept generate:cept api CreateUser +$ codecept generate:cest api CreateUser ``` -It will be called `CreateUserCept.php`. We can use it to test the creation of a user via the REST API. +It will be called `CreateUserCest.php`. +We need to implement a public method for each test. Let's make `createUserViaAPI` to test creation of a user via the REST API. ```php wantTo('create a user via API'); -$I->amHttpAuthenticated('service_user', '123456'); -$I->haveHttpHeader('Content-Type', 'application/x-www-form-urlencoded'); -$I->sendPOST('/users', ['name' => 'davert', 'email' => 'davert@codeception.com']); -$I->seeResponseCodeIs(\Codeception\Util\HttpCode::OK); // 200 -$I->seeResponseIsJson(); -$I->seeResponseContains('{"result":"ok"}'); - +class CreateUserCest +{ + public function _before(\ApiTester $I) + { + } + + public function _after(\ApiTester $I) + { + } + + // tests + public function createUserViaAPI(\ApiTester $I) + { + $I->amHttpAuthenticated('service_user', '123456'); + $I->haveHttpHeader('Content-Type', 'application/x-www-form-urlencoded'); + $I->sendPOST('/users', ['name' => 'davert', 'email' => 'davert@codeception.com']); + $I->seeResponseCodeIs(\Codeception\Util\HttpCode::OK); // 200 + $I->seeResponseIsJson(); + $I->seeResponseContains('{"result":"ok"}'); + + } +} ``` We can use HTTP code constants from `Codeception\Util\HttpCode` instead of numeric values to check response code in `seeResponseCodeIs` and `dontSeeResponseCodeIs` methods. @@ -117,14 +131,11 @@ If we expect a JSON response to be received we can check its structure with [JSO ```php wantTo('validate structure of GitHub api responses'); $I->sendGET('/users'); $I->seeResponseCodeIs(HttpCode::OK); // 200 $I->seeResponseIsJson(); $I->seeResponseJsonMatchesJsonPath('$[0].user.login'); $I->seeResponseJsonMatchesXpath('//user/login'); - ``` More detailed check can be applied if you need to validate the type of fields in a response. @@ -155,25 +166,21 @@ There is `seeXmlResponseIncludes` method to match inclusion of XML parts in resp ```php wantTo('validate structure of GitHub api responses'); $I->sendGET('/users.xml'); $I->seeResponseCodeIs(\Codeception\Util\HttpCode::OK); // 200 $I->seeResponseIsXml(); $I->seeXmlResponseMatchesXpath('//user/login'); -$I->seeXmlResponseIncludes(XmlUtils::toXml( +$I->seeXmlResponseIncludes(\Codeception\Util\Xml::toXml([ 'user' => [ 'name' => 'davert', 'email' => 'davert@codeception.com', 'status' => 'inactive' ] -)); +])); ``` -We are using XmlUtils class which allows us to build XML structures in a clean manner. The `toXml` method may accept a string or array and returns \DOMDocument instance. If your XML contains attributes and so can't be represented as a PHP array you can create XML using the [XmlBuilder](http://codeception.com/docs/reference/XmlBuilder) class. We will take a look at it a bit more in next section. +We are using `Codeception\Util\Xml` class which allows us to build XML structures in a clean manner. The `toXml` method may accept a string or array and returns \DOMDocument instance. If your XML contains attributes and so can't be represented as a PHP array you can create XML using the [XmlBuilder](http://codeception.com/docs/reference/XmlBuilder) class. We will take a look at it a bit more in next section.
Use `\Codeception\Util\Xml::build()` to create XmlBuilder instance. @@ -247,14 +254,10 @@ In the next example we will use `XmlBuilder` instead of regular XML. ```php wantTo('create user'); $I->haveSoapHeader('Session', array('token' => '123456')); $I->sendSoapRequest('CreateUser', Xml::build() ->user->email->val('miles@davis.com')); -$I->seeSoapResponseIncludes(Xml::build() +$I->seeSoapResponseIncludes(\Codeception\Util\Xml::build() ->result->val('Ok') ->user->attr('id', 1) ); diff --git a/docs/12-ContinuousIntegration.md b/docs/12-ContinuousIntegration.md index bf077354af..ae89177be1 100644 --- a/docs/12-ContinuousIntegration.md +++ b/docs/12-ContinuousIntegration.md @@ -31,7 +31,7 @@ At first we need to create build project. Depending on your needs you can set up We need to define build steps. The most simple setup may look like this: ``` -php codecept run +php vendor/bin/codecept run ``` ![Jenkins Codeception Build Step](http://codeception.com/images/jenkins/Jenk5.png) @@ -47,7 +47,7 @@ But we don't want to analyze console output for each failing build. Especially I Now let's update our build step to generate xml: ``` -php codecept run --xml +php vendor/bin/codecept run --xml ``` and ask Jenkins to collect resulted XML. This can be done as part of Post-build actions. Let's add *Publish xUnit test result report* action and configure it to use with PHPUnit reports. @@ -65,7 +65,7 @@ Now for all builds we will see results trend graph that shows us percentage of p To get more details on steps executed you can generate HTML report and use Jenkins to display them. ``` -php codecept run --html +php vendor/bin/codecept run --html ``` Now we need HTML Publisher plugin configured to display generated HTML files. It should be added as post-build action similar way we did it for XML reports. @@ -93,7 +93,7 @@ As an alternative you can use 3rd-party [TeamCity extension](https://github.com/ After you create build project you should define build step with Codeception which is ``` -php codecept run --report +php vendor/bin/codecept run --report ``` ![build step](http://codeception.com/images/teamcity/build.png) @@ -109,7 +109,7 @@ Once you execute your first build you should see detailed report inside TeamCity Travis CI is popular service CI with good GitHub integration. Codeception is self-tested with Travis CI. There nothing special about configuration. Just add to the bottom line of travis configuration: ```yaml -php codecept run +php vendor/bin/codecept run ``` More details on configuration can be learned from Codeception's [`.travis.yml`](https://github.com/Codeception/Codeception/blob/master/.travis.yml). From 20aedae166684dacde4cfffb5cdefac06a4c6ddb Mon Sep 17 00:00:00 2001 From: Greg Heitz Date: Sun, 1 Apr 2018 18:06:28 +0200 Subject: [PATCH 028/395] Goodbye PHP 5.4 (fix #4836 and #4837) (#4905) --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index d707d4e5e8..fbb47559f5 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ "minimum-stability": "RC", "require": { - "php": ">=5.4.0 <8.0", + "php": ">=5.6.0 <8.0", "ext-json": "*", "ext-mbstring": "*", "facebook/webdriver": ">=1.1.3 <2.0", From 37d60db1822af1b17d9fadbea0b89a55c6cede05 Mon Sep 17 00:00:00 2001 From: edno Date: Sun, 1 Apr 2018 20:25:20 +0200 Subject: [PATCH 029/395] Fix #4846 --- src/Codeception/Module/WebDriver.php | 13 +++++++++++-- tests/web/WebDriverTest.php | 25 ++++++++++++++++++++++--- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/src/Codeception/Module/WebDriver.php b/src/Codeception/Module/WebDriver.php index 1b575f03f6..3afca58de9 100644 --- a/src/Codeception/Module/WebDriver.php +++ b/src/Codeception/Module/WebDriver.php @@ -2867,12 +2867,21 @@ protected function convertKeyModifier($keys) protected function assertNodesContain($text, $nodes, $selector = null) { - $this->assertThat($nodes, new WebDriverConstraint($text, $this->_getCurrentUri()), $selector); + $this->assertNodeConstraint($nodes, new WebDriverConstraint($text, $this->_getCurrentUri()), $selector); } protected function assertNodesNotContain($text, $nodes, $selector = null) { - $this->assertThat($nodes, new WebDriverConstraintNot($text, $this->_getCurrentUri()), $selector); + $this->assertNodeConstraint($nodes, new WebDriverConstraintNot($text, $this->_getCurrentUri()), $selector); + } + + protected function assertNodeConstraint($nodes, WebDriverConstraint $constraint, $selector = null) + { + $message = $selector; + if (is_array($selector)) { + $message = implode(array_keys($selector)) . ':' . implode($selector); + } + $this->assertThat($nodes, $constraint, $message); } protected function assertPageContains($needle, $message = '') diff --git a/tests/web/WebDriverTest.php b/tests/web/WebDriverTest.php index 26ac63e4ae..f14d35c547 100644 --- a/tests/web/WebDriverTest.php +++ b/tests/web/WebDriverTest.php @@ -802,7 +802,7 @@ public function testSeeInFieldForTextarea() $this->module->amOnPage('/form/bug2921'); $this->module->seeInField('foo', 'bar baz'); } - + /** * @Issue 4726 */ @@ -811,8 +811,8 @@ public function testClearField() $this->module->amOnPage('/form/textarea'); $this->module->fillField('#description', 'description'); $this->module->clearField('#description'); - $this->module->dontSeeInField('#description', 'description'); - } + $this->module->dontSeeInField('#description', 'description'); + } public function testClickHashLink() { @@ -1106,4 +1106,23 @@ public function testChangingCapabilities() $this->module->_initializeSession(); $this->assertTrue(true, $this->module->webDriver->getCapabilities()->getCapability('acceptInsecureCerts')); } + + /** + * @dataProvider strictBug4846Provider + **/ + public function testBug4846($selector) + { + $this->module->amOnPage('/'); + $this->module->see('Welcome to test app!', $selector); + $this->module->dontSee('You cannot see that', $selector); + } + + public function strictBug4846Provider() + { + return [ + 'by id' => ['h1'], + 'by css' => [['css' => 'body h1']], + 'by xpath' => ['//body/h1'], + ]; + } } From 9345d946800b18fcff5df387712ebf3fa62b4016 Mon Sep 17 00:00:00 2001 From: Sam Date: Wed, 4 Apr 2018 15:26:20 +0200 Subject: [PATCH 030/395] Implemented alternate strategies for clearing response / request objects (#4915) * Implemented alternate strategies for clearing response / request objects * Fixed nitpick CS * Removed constant visibility, which is not supported in older PHP versions --- src/Codeception/Lib/Connector/Yii2.php | 127 ++++++++++++++++++++++++- src/Codeception/Module/Yii2.php | 24 ++++- 2 files changed, 147 insertions(+), 4 deletions(-) diff --git a/src/Codeception/Lib/Connector/Yii2.php b/src/Codeception/Lib/Connector/Yii2.php index 9624f05713..ac219362d1 100644 --- a/src/Codeception/Lib/Connector/Yii2.php +++ b/src/Codeception/Lib/Connector/Yii2.php @@ -10,6 +10,8 @@ use Yii; use yii\base\ExitException; use yii\base\Security; +use yii\web\Application; +use yii\web\ErrorHandler; use yii\web\HttpException; use yii\web\Request; use yii\web\Response as YiiResponse; @@ -18,11 +20,50 @@ class Yii2 extends Client { use Shared\PhpSuperGlobalsConverter; + const CLEAN_METHODS = [ + self::CLEAN_RECREATE, + self::CLEAN_CLEAR, + self::CLEAN_FORCE_RECREATE, + self::CLEAN_MANUAL + ]; + /** + * Clean the response object by recreating it. + * This might lose behaviors / event handlers / other changes that are done in the application bootstrap phase. + */ + const CLEAN_RECREATE = 'recreate'; + /** + * Same as recreate but will not warn when behaviors / event handlers are lost. + */ + const CLEAN_FORCE_RECREATE = 'force_recreate'; + /** + * Clean the response object by resetting specific properties via its' `clear()` method. + * This will keep behaviors / event handlers, but could inadvertently leave some changes intact. + * @see \Yii\web\Response::clear() + */ + const CLEAN_CLEAR = 'clear'; + + /** + * Do not clean the response, instead the test writer will be responsible for manually resetting the response in + * between requests during one test + */ + const CLEAN_MANUAL = 'manual'; + + /** * @var string application config file */ public $configFile; + /** + * @var string method for cleaning the response object before each request + */ + public $responseCleanMethod; + + /** + * @var string method for cleaning the request object before each request + */ + public $requestCleanMethod; + /** * @return \yii\web\Application */ @@ -99,7 +140,9 @@ public function doRequest($request) * @todo Implement some kind of check to see if someone tried to change the objects' properties and expects * those changes to be reflected in the reponse. */ - $app->set('response', $app->getComponents()['response']); + $this->resetResponse($app); + + // disabling logging. Logs are slowing test execution down foreach ($app->log->targets as $target) { @@ -114,7 +157,7 @@ public function doRequest($request) * @todo Implement some kind of check to see if someone tried to change the objects' properties and expects * those changes to be reflected in the reponse. */ - $app->set('request', $app->getComponents()['request']); + $this->resetRequest($app); $yiiRequest = $app->getRequest(); if ($request->getContent() !== null) { @@ -134,7 +177,6 @@ public function doRequest($request) $app->trigger($app::EVENT_BEFORE_REQUEST); $response = $app->handleRequest($yiiRequest); $app->trigger($app::EVENT_AFTER_REQUEST); - codecept_debug($response->isSent); $response->send(); } catch (\Exception $e) { if ($e instanceof HttpException) { @@ -259,4 +301,83 @@ public function restart() parent::restart(); $this->resetApplication(); } + + /** + * Resets the applications' response object. + * The method used depends on the module configuration. + */ + protected function resetResponse(Application $app) + { + $method = $this->responseCleanMethod; + // First check the current response object. + if (($app->response->hasEventHandlers(\yii\web\Response::EVENT_BEFORE_SEND) + || $app->response->hasEventHandlers(\yii\web\Response::EVENT_AFTER_SEND) + || $app->response->hasEventHandlers(\yii\web\Response::EVENT_AFTER_PREPARE) + || count($app->response->getBehaviors()) > 0 + ) && $method === self::CLEAN_RECREATE + ) { + Debug::debug(<<set('response', $app->getComponents()['response']); + break; + case self::CLEAN_CLEAR: + $app->response->clear(); + break; + case self::CLEAN_MANUAL: + break; + } + } + + protected function resetRequest(Application $app) + { + $method = $this->requestCleanMethod; + $request = $app->request; + + // First check the current request object. + if (count($request->getBehaviors()) > 0 && $method === self::CLEAN_RECREATE) { + Debug::debug(<<set('request', $app->getComponents()['request']); + break; + case self::CLEAN_CLEAR: + $request->getHeaders()->removeAll(); + $request->getCookies()->removeAll(); + $request->setBaseUrl(null); + $request->setHostInfo(null); + $request->setPathInfo(null); + $request->setScriptFile(null); + $request->setScriptUrl(null); + $request->setUrl(null); + $request->setPort(null); + $request->setSecurePort(null); + $request->setAcceptableContentTypes(null); + $request->setAcceptableLanguages(null); + + break; + case self::CLEAN_MANUAL: + break; + } + } } diff --git a/src/Codeception/Module/Yii2.php b/src/Codeception/Module/Yii2.php index 9d679ff896..15b8eb48de 100644 --- a/src/Codeception/Module/Yii2.php +++ b/src/Codeception/Module/Yii2.php @@ -37,7 +37,10 @@ * * `cleanup` - (default: true) cleanup fixtures after the test * * `ignoreCollidingDSN` - (default: false) When 2 database connections use the same DSN but different settings an exception will be thrown, set this to true to disable this behavior. * * `fixturesMethod` - (default: _fixtures) Name of the method used for creating fixtures. - * + * * `responseCleanMethod` - (default: clear) Method for cleaning the response object. Note that this is only for multiple requests inside a single test case. + * Between test casesthe whole application is always recreated + * * `requestCleanMethod` - (default: clear) Method for cleaning the request object. Note that this is only for multiple requests inside a single test case. + * Between test cases the whole application is always recreated * You can use this module by setting params in your functional.suite.yml: * * ```yaml @@ -150,6 +153,8 @@ class Yii2 extends Framework implements ActiveRecord, PartedModule 'transaction' => null, 'entryScript' => '', 'entryUrl' => 'http://localhost/index-test.php', + 'responseCleanMethod' => Yii2Connector::CLEAN_CLEAR, + 'requestCleanMethod' => Yii2Connector::CLEAN_RECREATE ]; protected $requiredFields = ['configFile']; @@ -178,6 +183,7 @@ class Yii2 extends Framework implements ActiveRecord, PartedModule * It MUST not be used anywhere else. */ private $server; + public function _initialize() { if ($this->config['transaction'] === null) { @@ -232,6 +238,20 @@ protected function validateConfig() "The application config file does not exist: " . Configuration::projectDir() . $this->config['configFile'] ); } + + if (!in_array($this->config['responseCleanMethod'], Yii2Connector::CLEAN_METHODS)) { + throw new ModuleConfigException( + __CLASS__, + "The response clean method must be one of: " . implode(", ", Yii2Connector::CLEAN_METHODS) + ); + } + + if (!in_array($this->config['requestCleanMethod'], Yii2Connector::CLEAN_METHODS)) { + throw new ModuleConfigException( + __CLASS__, + "The response clean method must be one of: " . implode(", ", Yii2Connector::CLEAN_METHODS) + ); + } } @@ -250,6 +270,7 @@ public function _before(TestInterface $test) ]); $this->client->configFile = Configuration::projectDir() . $this->config['configFile']; + $this->client->responseCleanMethod = $this->config['responseCleanMethod']; $this->client->resetApplication(); $app = $this->client->getApplication(); @@ -352,6 +373,7 @@ protected function startTransactions() && $this->dsnCache[$connection->dsn] !== $key && !$this->config['ignoreCollidingDSN'] ) { + $this->debugSection('WARNING', <<dsn}) with different configuration. These connections will not see the same database state since we cannot share a transaction between different PDO From 30ec967a18bd866369df77c776c363c225eea656 Mon Sep 17 00:00:00 2001 From: Sam Date: Thu, 5 Apr 2018 11:53:20 +0200 Subject: [PATCH 031/395] Support reconfiguration (#4918) * Add support for reconfiguration during tests and fix issue with sqlite transactions * Fixed nitpick CS * Fixed docs, don't attempt to clear cookies since they won't get reloaded. --- src/Codeception/Lib/Connector/Yii2.php | 1 - src/Codeception/Module/Yii2.php | 136 ++++++++++++++----------- 2 files changed, 78 insertions(+), 59 deletions(-) diff --git a/src/Codeception/Lib/Connector/Yii2.php b/src/Codeception/Lib/Connector/Yii2.php index ac219362d1..5a485ef132 100644 --- a/src/Codeception/Lib/Connector/Yii2.php +++ b/src/Codeception/Lib/Connector/Yii2.php @@ -363,7 +363,6 @@ protected function resetRequest(Application $app) break; case self::CLEAN_CLEAR: $request->getHeaders()->removeAll(); - $request->getCookies()->removeAll(); $request->setBaseUrl(null); $request->setHostInfo(null); $request->setPathInfo(null); diff --git a/src/Codeception/Module/Yii2.php b/src/Codeception/Module/Yii2.php index 15b8eb48de..958b6202a8 100644 --- a/src/Codeception/Module/Yii2.php +++ b/src/Codeception/Module/Yii2.php @@ -39,7 +39,7 @@ * * `fixturesMethod` - (default: _fixtures) Name of the method used for creating fixtures. * * `responseCleanMethod` - (default: clear) Method for cleaning the response object. Note that this is only for multiple requests inside a single test case. * Between test casesthe whole application is always recreated - * * `requestCleanMethod` - (default: clear) Method for cleaning the request object. Note that this is only for multiple requests inside a single test case. + * * `requestCleanMethod` - (default: recreate) Method for cleaning the request object. Note that this is only for multiple requests inside a single test case. * Between test cases the whole application is always recreated * You can use this module by setting params in your functional.suite.yml: * @@ -198,17 +198,16 @@ public function _initialize() /** * Module configuration changed inside a test. - * We might need to re-create the application. + * We always re-create the application. */ protected function onReconfigure() { parent::onReconfigure(); - if (isset(\Yii::$app)) { - $this->client->restart(); - } + $this->client->resetApplication(); + $this->configureClient($this->config); + $this->client->startApp(); } - /** * Adds the required server params. * Note this is done separately from the request cycle since someone might call @@ -254,8 +253,22 @@ protected function validateConfig() } } + protected function configureClient(array $settings) + { + $settings['configFile'] = Configuration::projectDir() . $settings['configFile']; - public function _before(TestInterface $test) + foreach ($settings as $key => $value) { + if (property_exists($this->client, $key)) { + $this->client->$key = $value; + } + } + $this->client->resetApplication(); + } + + /** + * Instantiates the client based on module configuration + */ + protected function recreateClient() { $entryUrl = $this->config['entryUrl']; $entryFile = $this->config['entryScript'] ?: basename($entryUrl); @@ -269,11 +282,13 @@ public function _before(TestInterface $test) 'HTTPS' => parse_url($entryUrl, PHP_URL_SCHEME) === 'https' ]); - $this->client->configFile = Configuration::projectDir() . $this->config['configFile']; - $this->client->responseCleanMethod = $this->config['responseCleanMethod']; + $this->configureClient($this->config); + } - $this->client->resetApplication(); - $app = $this->client->getApplication(); + public function _before(TestInterface $test) + { + $this->recreateClient(); + $this->client->startApp(); // load fixtures before db transaction if ($test instanceof \Codeception\Test\Cest) { @@ -336,68 +351,73 @@ public function _after(TestInterface $test) if ($this->client->getApplication()->has('session', true)) { $this->client->getApplication()->session->close(); } - parent::_after($test); } - protected function startTransactions() - { - if ($this->config['transaction']) { - // This should register handlers that start a transaction whenever a connection opens and add it to the transactions array. - Event::on(Connection::class, Connection::EVENT_AFTER_OPEN, function (Event $event) { - if ($event->sender instanceof Connection) { - $connection = $event->sender; - /* - * We should check if the known PDO objects are the same, in which case we should reuse the PDO - * object so only 1 transaction is started and multiple connections to the same database see the - * same data (due to writes inside a transaction not being visible from the outside). - * - */ - $key = md5(json_encode([ - 'dsn' => $connection->dsn, - 'user' => $connection->username, - 'pass' => $connection->password, - 'attributes' => $connection->attributes, - 'emulatePrepare' => $connection->emulatePrepare, - 'charset' => $connection->charset - ])); - - /* - * If keys match we assume connections are "similar enough". - */ - if (isset($this->pdoCache[$key])) { - $connection->pdo = $this->pdoCache[$key]; - } - - if (isset($this->dsnCache[$connection->dsn]) - && $this->dsnCache[$connection->dsn] !== $key - && !$this->config['ignoreCollidingDSN'] - ) { - - $this->debugSection('WARNING', <<sender instanceof Connection) { + $connection = $event->sender; + /* + * We should check if the known PDO objects are the same, in which case we should reuse the PDO + * object so only 1 transaction is started and multiple connections to the same database see the + * same data (due to writes inside a transaction not being visible from the outside). + * + */ + $key = md5(json_encode([ + 'dsn' => $connection->dsn, + 'user' => $connection->username, + 'pass' => $connection->password, + 'attributes' => $connection->attributes, + 'emulatePrepare' => $connection->emulatePrepare, + 'charset' => $connection->charset + ])); + + /* + * If keys match we assume connections are "similar enough". + */ + if (isset($this->pdoCache[$key])) { + $connection->pdo = $this->pdoCache[$key]; + } + + if (isset($this->dsnCache[$connection->dsn]) + && $this->dsnCache[$connection->dsn] !== $key + && !$this->config['ignoreCollidingDSN'] + ) { + $this->debugSection('WARNING', <<dsn}) with different configuration. These connections will not see the same database state since we cannot share a transaction between different PDO instances. You can remove this message by adding 'ignoreCollidingDSN = true' in the module configuration. TEXT - ); - Debug::pause(); - } + ); + Debug::pause(); + } - if (isset($this->transactions[$key])) { - $this->debugSection('Database', 'Reusing PDO, so no need for a new transaction'); - return; - } + if (isset($this->transactions[$key])) { + $this->debugSection('Database', 'Reusing PDO, so no need for a new transaction'); + return; + } - $this->debugSection('Database', 'Transaction started for: ' . $connection->dsn); - $this->transactions[$key] = $connection->beginTransaction(); - } - }); + $this->debugSection('Database', 'Transaction started for: ' . $connection->dsn); + $this->transactions[$key] = $connection->beginTransaction(); + } + + } + + protected function startTransactions() + { + if ($this->config['transaction']) { + // This should register handlers that start a transaction whenever a connection opens and add it to the transactions array. + $this->debug('Transaction', 'Registering connection event handler'); + Event::on(Connection::class, Connection::EVENT_AFTER_OPEN, [$this, 'connectionOpenHandler']); } } protected function rollbackTransactions() { + $this->debugSection('Transaction', 'Rolling back ' . count($this->transactions) . ' transactions'); + Event::off(Connection::class, Connection::EVENT_AFTER_OPEN, [$this, 'connectionOpenHandler']); /** @var Transaction $transaction */ foreach ($this->transactions as $transaction) { $transaction->rollBack(); From 8794a9a501f0e9ad0f411e05789e15719c1dab8d Mon Sep 17 00:00:00 2001 From: Sam Date: Thu, 5 Apr 2018 16:16:55 +0200 Subject: [PATCH 032/395] Improved test speed (#4921) * This PR improves test speed by skipping framework tests if we're certain that changes don't impact them * Fixed NitPick CS * Fix typo * Only skip frameworks if code changes actually limited to framework code. * Fix NitPick CS * Stop nitpicking! --- .travis.yml | 5 +++-- PruneTest.php | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 PruneTest.php diff --git a/.travis.yml b/.travis.yml index febacbc628..c1665990c2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -72,6 +72,7 @@ services: - redis before_install: + - '$(php PruneTest.php)' - '[[ !(-z "$XDEBUG") ]] || phpenv config-rm xdebug.ini' - export INI=~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini - echo memory_limit = -1 >> $INI @@ -126,6 +127,6 @@ before_script: - '[[ "$FRAMEWORK" != "Zend2" ]] || mysql -e "create database zf2_test;"' - '[[ "$FRAMEWORK" != "Zend2" ]] || php framework-tests/vendor/bin/doctrine-module orm:schema-tool:create' # Build - - php codecept build -c $TEST_PATH + - '[[ -z "$FRAMEWORK" ]] || php codecept build -c $TEST_PATH' script: - - php codecept run $SUITES -c $TEST_PATH \ No newline at end of file + - '[[ -z "$FRAMEWORK" ]] || php codecept run $SUITES -c $TEST_PATH' \ No newline at end of file diff --git a/PruneTest.php b/PruneTest.php new file mode 100644 index 0000000000..f2145f51ef --- /dev/null +++ b/PruneTest.php @@ -0,0 +1,61 @@ + '/.*Yii2.*/', + 'Lumen' => '/.*(Lumen|LaravelCommon).*/', + 'Laravel' => '/.*Laravel.*/', + 'Phalcon' => '/.*Phalcon.*/', + 'Symfony' => '/.*Symfony.*/', + 'Yii1' => '/.*Yii1.*/', + 'ZendExpressive' => '/.*ZendExpressive.*/', + 'Zend1' => '/.*ZF1.*/', + 'Zend2' => '/.*ZF2.*/', +]; + +// First check if changes include files that are not framework files. +$frameworkOnly = true; +$frameworks = []; +foreach ($files as $file) { + $match = false; + foreach ($regexes as $framework => $regex) { + if (preg_match($regex, $file)) { + $match = true; + $frameworks[$framework] = $framework; + break; + } + } + if (!$match) { + $frameworkOnly = false; + break; + } +} + +if ($frameworkOnly) { + stderr('Changes limited to frameworks: ' . implode(', ', $frameworks)); + if (!isset($frameworks[$currentFramework])) { + stderr("Skipping test for framework: $currentFramework"); + echo "export FRAMEWORK=\n"; + echo "export PECL=\n"; + echo "export FXP=\n"; + echo "export CI_USER_TOKEN=\n"; + } +} From 8316c9f8695e719b025639ed04619467b0fbb1db Mon Sep 17 00:00:00 2001 From: Sam Date: Thu, 5 Apr 2018 20:56:57 +0200 Subject: [PATCH 033/395] Fixed an issue with exit exceptions (#4923) * Fixed an issue where exceptions in the Yii app resulted in exceptions in the Yii module * Fix test skipping * Fix syntax error * Update comments --- .travis.yml | 7 ++++--- src/Codeception/Lib/Connector/Yii2.php | 3 +-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index c1665990c2..d57db9e6df 100644 --- a/.travis.yml +++ b/.travis.yml @@ -98,8 +98,8 @@ install: - '[[ "$FRAMEWORK" != "Phalcon" ]] || (cd cphalcon/build; bash ./install --phpize $(phpenv which phpize) --php-config $(phpenv which php-config) &>/dev/null && phpenv config-add ../tests/_ci/phalcon.ini &> /dev/null)' # Symfony #- '[[ "$FRAMEWORK$VERSION" != "Symfony3" ]] || composer require -d framework-tests symfony/symfony=~$VERSION --no-update' - - composer install - - '[[ "$FRAMEWORK" == "Codeception" ]] || composer update -d framework-tests --no-dev --prefer-dist' + - '[[ -z "$FRAMEWORK" ]] || composer install' + - '[[ "$FRAMEWORK" == "Codeception" ]] || [[ -z "$FRAMEWORK" ]] || composer update -d framework-tests --no-dev --prefer-dist' before_script: - '[[ "$TRAVIS_PHP_VERSION" == 7.* ]] || echo "extension = mongo.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini' # preparing databases @@ -129,4 +129,5 @@ before_script: # Build - '[[ -z "$FRAMEWORK" ]] || php codecept build -c $TEST_PATH' script: - - '[[ -z "$FRAMEWORK" ]] || php codecept run $SUITES -c $TEST_PATH' \ No newline at end of file + # Run tests if $FRAMEWORK is not empty + - '[[ -z "$FRAMEWORK" ]] || php codecept run $SUITES -c $TEST_PATH' diff --git a/src/Codeception/Lib/Connector/Yii2.php b/src/Codeception/Lib/Connector/Yii2.php index 5a485ef132..a99214ef30 100644 --- a/src/Codeception/Lib/Connector/Yii2.php +++ b/src/Codeception/Lib/Connector/Yii2.php @@ -184,13 +184,12 @@ public function doRequest($request) // to expect error response codes in tests. $app->errorHandler->discardExistingOutput = false; $app->errorHandler->handleException($e); - $response = $app->response; - } elseif (!$e instanceof ExitException) { // for exceptions not related to Http, we pass them to Codeception $this->resetApplication(); throw $e; } + $response = $app->response; } $this->encodeCookies($response, $yiiRequest, $app->security); From 5c4872bebc9c9dbe0cae8072f6fc3ff702173c68 Mon Sep 17 00:00:00 2001 From: Sam Date: Fri, 6 Apr 2018 15:27:14 +0200 Subject: [PATCH 034/395] =?UTF-8?q?This=20adds=20support=20for=20component?= =?UTF-8?q?s=20that=20keep=20state=20that=20must=20be=20cleared=E2=80=A6?= =?UTF-8?q?=20(#4924)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * This adds support for components that keep state that must be cleared between requests * Fixed issue in test skip logic + nitpick CS * Fix application reset after exception * Add configuration option to recreate the whole application before each request * Add default configuration --- PruneTest.php | 5 +++ src/Codeception/Lib/Connector/Yii2.php | 57 ++++++++++++++++++-------- src/Codeception/Module/Yii2.php | 11 ++++- 3 files changed, 54 insertions(+), 19 deletions(-) diff --git a/PruneTest.php b/PruneTest.php index f2145f51ef..308be87bbd 100644 --- a/PruneTest.php +++ b/PruneTest.php @@ -15,6 +15,11 @@ function stderr($message) } $currentFramework = getenv('FRAMEWORK'); + +if ($currentFramework === 'Codeception') { + stderr('Codeception tests are always executed'); + die(); +} $files = []; exec("git diff --name-only $branch", $files); diff --git a/src/Codeception/Lib/Connector/Yii2.php b/src/Codeception/Lib/Connector/Yii2.php index a99214ef30..b7c750d006 100644 --- a/src/Codeception/Lib/Connector/Yii2.php +++ b/src/Codeception/Lib/Connector/Yii2.php @@ -64,6 +64,18 @@ class Yii2 extends Client */ public $requestCleanMethod; + /** + * @var string[] List of component names that must be recreated before each request + */ + public $recreateComponents = []; + + /** + * This option is there primarily for backwards compatibility. + * It means you cannot make any modification to application state inside your app, since they will get discarded. + * @var bool whether to recreate the whole application before each request + */ + public $recreateApplication = false; + /** * @return \yii\web\Application */ @@ -133,31 +145,19 @@ public function doRequest($request) $_GET[$k] = $v; } - $app = $this->getApplication(); - - /** - * Just before the request we set the response object so it is always fresh. - * @todo Implement some kind of check to see if someone tried to change the objects' properties and expects - * those changes to be reflected in the reponse. - */ - $this->resetResponse($app); + ob_start(); + $this->beforeRequest(); + $app = $this->getApplication(); // disabling logging. Logs are slowing test execution down foreach ($app->log->targets as $target) { $target->enabled = false; } - ob_start(); - // recreating request object to reset headers and cookies collections - /** - * Just before the request we set the request object so it is always fresh. - * @todo Implement some kind of check to see if someone tried to change the objects' properties and expects - * those changes to be reflected in the reponse. - */ - $this->resetRequest($app); + $yiiRequest = $app->getRequest(); if ($request->getContent() !== null) { @@ -186,7 +186,6 @@ public function doRequest($request) $app->errorHandler->handleException($e); } elseif (!$e instanceof ExitException) { // for exceptions not related to Http, we pass them to Codeception - $this->resetApplication(); throw $e; } $response = $app->response; @@ -378,4 +377,28 @@ protected function resetRequest(Application $app) break; } } + + /** + * Called before each request, preparation happens here. + */ + protected function beforeRequest() + { + if ($this->recreateApplication) { + $this->resetApplication(); + return; + } + + $application = $this->getApplication(); + + $this->resetResponse($application); + $this->resetRequest($application); + + $definitions = $application->getComponents(true); + foreach ($this->recreateComponents as $component) { + // Only recreate if it has actually been instantiated. + if ($application->has($component, true)) { + $application->set($component, $definitions[$component]); + } + } + } } diff --git a/src/Codeception/Module/Yii2.php b/src/Codeception/Module/Yii2.php index 958b6202a8..2a240a80b7 100644 --- a/src/Codeception/Module/Yii2.php +++ b/src/Codeception/Module/Yii2.php @@ -23,6 +23,7 @@ * ## Application state during testing * This section details what you can expect when using this module. * * You will get a fresh application in `\Yii::$app` at the start of each test (available in the test and in `_before()`). + * * Inside your test you may change application state; however these changes will be lost when doing a request if you have enabled `recreateApplication`. * * When executing a request via one of the request functions the `request` and `response` component are both recreated. * * After a request the whole application is available for inspection / interaction. * * You may use multiple database connections, each will use a separate transaction; to prevent accidental mistakes we @@ -41,8 +42,12 @@ * Between test casesthe whole application is always recreated * * `requestCleanMethod` - (default: recreate) Method for cleaning the request object. Note that this is only for multiple requests inside a single test case. * Between test cases the whole application is always recreated + * * `recreateComponents` - (default: []) Some components change their state making them unsuitable for processing multiple requests. In production this is usually + * not a problem since web apps tend to die and start over after each request. This allows you to list application components that need to be recreated before each request. + * As a consequence, any components specified here should not be changed inside a test since those changes will get regarded. + * You can use this module by setting params in your functional.suite.yml: + * * `recreateApplication` - (default: false) whether to recreate the whole application before each request * You can use this module by setting params in your functional.suite.yml: - * * ```yaml * actor: FunctionalTester * modules: @@ -154,7 +159,9 @@ class Yii2 extends Framework implements ActiveRecord, PartedModule 'entryScript' => '', 'entryUrl' => 'http://localhost/index-test.php', 'responseCleanMethod' => Yii2Connector::CLEAN_CLEAR, - 'requestCleanMethod' => Yii2Connector::CLEAN_RECREATE + 'requestCleanMethod' => Yii2Connector::CLEAN_RECREATE, + 'recreateComponents' => [], + 'recreateApplication' => false ]; protected $requiredFields = ['configFile']; From 6f0f6db334930aba49481e61a34824e6c2b0f588 Mon Sep 17 00:00:00 2001 From: Etki Date: Tue, 10 Apr 2018 21:49:05 +0300 Subject: [PATCH 035/395] Added safety check for runtimes emulating php 7.1+ but not supporting pcntl_async_signals() (#4912) --- src/Codeception/Subscriber/GracefulTermination.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Codeception/Subscriber/GracefulTermination.php b/src/Codeception/Subscriber/GracefulTermination.php index 0d9650534b..687b3b1fed 100644 --- a/src/Codeception/Subscriber/GracefulTermination.php +++ b/src/Codeception/Subscriber/GracefulTermination.php @@ -9,6 +9,7 @@ class GracefulTermination implements EventSubscriberInterface { const SIGNAL_FUNC = 'pcntl_signal'; + const ASYNC_SIGNAL_HANDLING_FUNC = 'pcntl_async_signals'; /** * @var SuiteEvent @@ -17,10 +18,11 @@ class GracefulTermination implements EventSubscriberInterface public function handleSuite(SuiteEvent $event) { - if (PHP_MAJOR_VERSION === 7) { - if (PHP_MINOR_VERSION === 0) { - return; // skip for PHP 7.0: https://github.com/Codeception/Codeception/issues/3607 - } + if (PHP_MAJOR_VERSION === 7 && PHP_MINOR_VERSION === 0) { + // skip for PHP 7.0: https://github.com/Codeception/Codeception/issues/3607 + return; + } + if (function_exists(self::ASYNC_SIGNAL_HANDLING_FUNC)) { pcntl_async_signals(true); } if (function_exists(self::SIGNAL_FUNC)) { From 36ae1350a8cf4e0fa244dbb2932df9cf33a021c2 Mon Sep 17 00:00:00 2001 From: Viktor Robev Date: Wed, 11 Apr 2018 03:30:09 +0300 Subject: [PATCH 036/395] Add session snapshot deletion (#4909) * Fix typo in split documentation (#4455) [skip ci] * Added new method seeOptionValueIsSelected (#4075) * Added test for expected functionality * Added new method seeOptionValueIsSelected This method checks only into the value attribute of the specified selector * Revert "Added new method seeOptionValueIsSelected (#4075)" (#4831) This reverts commit 8881d642baf93bd8c41a19ca571602e6d680422e. * Add session snapshot deletion * Fix codestyle --- src/Codeception/Module/WebDriver.php | 11 +++++++++++ tests/web/WebDriverTest.php | 12 ++++++++++++ 2 files changed, 23 insertions(+) diff --git a/src/Codeception/Module/WebDriver.php b/src/Codeception/Module/WebDriver.php index 1b575f03f6..740e3b12ab 100644 --- a/src/Codeception/Module/WebDriver.php +++ b/src/Codeception/Module/WebDriver.php @@ -3065,6 +3065,17 @@ public function loadSessionSnapshot($name) return true; } + /** + * @param string $name + */ + public function deleteSessionSnapshot($name) + { + if (isset($this->sessionSnapshots[$name])) { + unset($this->sessionSnapshots[$name]); + } + $this->debugSection('Snapshot', "Deleted \"$name\" session snapshot"); + } + /** * Check if the cookie domain matches the config URL. * diff --git a/tests/web/WebDriverTest.php b/tests/web/WebDriverTest.php index 26ac63e4ae..85e9f6a48d 100644 --- a/tests/web/WebDriverTest.php +++ b/tests/web/WebDriverTest.php @@ -652,6 +652,18 @@ public function testSessionSnapshots() $this->module->seeCookie('PHPSESSID'); } + public function testSessionSnapshotsAreDeleted() + { + $this->notForPhantomJS(); + $this->module->amOnPage('/'); + $this->module->setCookie('PHPSESSID', '123456', ['path' => '/']); + $this->module->saveSessionSnapshot('login'); + $this->webDriver->manage()->deleteAllCookies(); + $this->module->deleteSessionSnapshot('login'); + $this->assertFalse($this->module->loadSessionSnapshot('login')); + $this->module->dontSeeCookie('PHPSESSID'); + } + public function testSaveSessionSnapshotsExcludeInvalidCookieDomains() { $this->notForPhantomJS(); From 10d57842753b281b7f2dd84908de4396c58a5de9 Mon Sep 17 00:00:00 2001 From: Pavel Date: Mon, 16 Apr 2018 01:03:59 +0300 Subject: [PATCH 037/395] Fixed compatibility with ZF2 ServiceManager (#4934) --- .../Lib/Connector/ZF2/PersistentServiceManager.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Codeception/Lib/Connector/ZF2/PersistentServiceManager.php b/src/Codeception/Lib/Connector/ZF2/PersistentServiceManager.php index fe1f1b1e3b..a8952dcd0d 100644 --- a/src/Codeception/Lib/Connector/ZF2/PersistentServiceManager.php +++ b/src/Codeception/Lib/Connector/ZF2/PersistentServiceManager.php @@ -17,17 +17,17 @@ public function __construct(ServiceLocatorInterface $serviceManager) $this->serviceManager = $serviceManager; } - public function get($name) + public function get($name, $usePeeringServiceManagers = true) { if (parent::has($name)) { - return parent::get($name); + return parent::get($name, $usePeeringServiceManagers); } return $this->serviceManager->get($name); } - public function has($name) + public function has($name, $checkAbstractFactories = true, $usePeeringServiceManagers = true) { - if (parent::has($name)) { + if (parent::has($name, $checkAbstractFactories, $usePeeringServiceManagers)) { return true; } if (preg_match('/doctrine/i', $name)) { From 5e3530a665ef74519c9c6f8663356d48c9da3d54 Mon Sep 17 00:00:00 2001 From: Wolfgang Kritzinger Date: Tue, 17 Apr 2018 00:45:55 +1000 Subject: [PATCH 038/395] Restore null check for client in Yii2 (fix #4929) (#4940) --- src/Codeception/Module/Yii2.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Codeception/Module/Yii2.php b/src/Codeception/Module/Yii2.php index 2a240a80b7..c162894a39 100644 --- a/src/Codeception/Module/Yii2.php +++ b/src/Codeception/Module/Yii2.php @@ -355,7 +355,7 @@ public function _after(TestInterface $test) $this->loadedFixtures = []; } - if ($this->client->getApplication()->has('session', true)) { + if ($this->client !== null && $this->client->getApplication()->has('session', true)) { $this->client->getApplication()->session->close(); } parent::_after($test); From b574ef21a011621dd57b6446a770255566204853 Mon Sep 17 00:00:00 2001 From: Sam Date: Tue, 17 Apr 2018 11:53:31 +0200 Subject: [PATCH 039/395] Manual app reset (#4928) * Due to modules keeping references to the client, destructor is not a good place for clean up. Instead manually reset application in _after * Fix pdoCache never being filled * Improved garbage collection, fixes #4926 --- src/Codeception/Lib/Connector/Yii2.php | 12 ++---------- src/Codeception/Module/Yii2.php | 4 ++++ 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/Codeception/Lib/Connector/Yii2.php b/src/Codeception/Lib/Connector/Yii2.php index b7c750d006..67e44caf49 100644 --- a/src/Codeception/Lib/Connector/Yii2.php +++ b/src/Codeception/Lib/Connector/Yii2.php @@ -96,6 +96,8 @@ public function resetApplication() \yii\base\Event::offAll(); } Yii::setLogger(null); + // This resolves an issue with database connections not closing properly. + gc_collect_cycles(); } public function startApp() @@ -284,16 +286,6 @@ protected function mockMailer(array $config) return $config; } - /** - * A new client is created for every test, it is destroyed after every test. - * @see InnerBrowser::_after() - * - */ - public function __destruct() - { - $this->resetApplication(); - } - public function restart() { parent::restart(); diff --git a/src/Codeception/Module/Yii2.php b/src/Codeception/Module/Yii2.php index c162894a39..d714b18ad0 100644 --- a/src/Codeception/Module/Yii2.php +++ b/src/Codeception/Module/Yii2.php @@ -358,6 +358,8 @@ public function _after(TestInterface $test) if ($this->client !== null && $this->client->getApplication()->has('session', true)) { $this->client->getApplication()->session->close(); } + + $this->client->resetApplication(); parent::_after($test); } @@ -385,6 +387,8 @@ public function connectionOpenHandler(Event $event) */ if (isset($this->pdoCache[$key])) { $connection->pdo = $this->pdoCache[$key]; + } else { + $this->pdoCache[$key] = $connection->pdo; } if (isset($this->dsnCache[$connection->dsn]) From 0e91291e22b1dd4ac526f05fda7c5a91e5462e2c Mon Sep 17 00:00:00 2001 From: bscheshirwork Date: Fri, 20 Apr 2018 12:53:56 +0300 Subject: [PATCH 040/395] remove typehint for php7 compability (#4937) --- src/Codeception/Event/FailEvent.php | 2 +- src/Codeception/Subscriber/Console.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Codeception/Event/FailEvent.php b/src/Codeception/Event/FailEvent.php index 372411ce43..0f64570b74 100644 --- a/src/Codeception/Event/FailEvent.php +++ b/src/Codeception/Event/FailEvent.php @@ -13,7 +13,7 @@ class FailEvent extends TestEvent */ protected $count; - public function __construct(\PHPUnit\Framework\Test $test, $time, \Exception $e, $count = 0) + public function __construct(\PHPUnit\Framework\Test $test, $time, $e, $count = 0) { parent::__construct($test, $time); $this->fail = $e; diff --git a/src/Codeception/Subscriber/Console.php b/src/Codeception/Subscriber/Console.php index 22b38b8d63..081d7ac0cb 100644 --- a/src/Codeception/Subscriber/Console.php +++ b/src/Codeception/Subscriber/Console.php @@ -441,7 +441,7 @@ public function printScenarioFail(ScenarioDriven $failedTest, $fail) } } - public function printExceptionTrace(\Exception $e) + public function printExceptionTrace($e) { static $limit = 10; From b23e8be85e50919d898d3f7d669445ed33273e0d Mon Sep 17 00:00:00 2001 From: Filippo Tessarotto Date: Fri, 20 Apr 2018 11:54:57 +0200 Subject: [PATCH 041/395] Verbose fail message when no Exception caught (#4933) --- src/Codeception/Module/Asserts.php | 4 ++-- tests/unit/Codeception/Module/AssertsTest.php | 11 +++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/Codeception/Module/Asserts.php b/src/Codeception/Module/Asserts.php index 69fb64a82c..6bb7927ebc 100644 --- a/src/Codeception/Module/Asserts.php +++ b/src/Codeception/Module/Asserts.php @@ -465,8 +465,8 @@ public function expectException($exception, $callback) )); } $this->assertTrue(true); // increment assertion counter - return; + return; } - $this->fail("Expected exception to be thrown, but nothing was caught"); + $this->fail("Expected exception of $class to be thrown, but nothing was caught"); } } diff --git a/tests/unit/Codeception/Module/AssertsTest.php b/tests/unit/Codeception/Module/AssertsTest.php index cba9cd9c48..5d71f3b152 100644 --- a/tests/unit/Codeception/Module/AssertsTest.php +++ b/tests/unit/Codeception/Module/AssertsTest.php @@ -53,4 +53,15 @@ public function testExceptionFails() throw new Exception('here', 2); }); } + + /** + * @expectedException PHPUnit\Framework\AssertionFailedError + * @expectedExceptionMessageRegExp /RuntimeException/ + */ + public function testOutputExceptionTimeWhenNothingCaught() + { + $module = new \Codeception\Module\Asserts(make_container()); + $module->expectException(RuntimeException::class, function () { + }); + } } From db8a3bbc389fb85375100f2bcd38aa4798d13ee7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Barou=C5=A1?= Date: Fri, 20 Apr 2018 12:44:31 +0200 Subject: [PATCH 042/395] Makes JsonArray convert all decoded non-arrays to array (#4946) Also adds test covering this case. Issue on GitHub: Codeception/Codeception#4944 --- src/Codeception/Util/JsonArray.php | 8 +++++++- tests/unit/Codeception/Util/JsonArrayTest.php | 9 +++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/Codeception/Util/JsonArray.php b/src/Codeception/Util/JsonArray.php index 279f257487..6b2d553271 100644 --- a/src/Codeception/Util/JsonArray.php +++ b/src/Codeception/Util/JsonArray.php @@ -23,7 +23,13 @@ public function __construct($jsonString) throw new InvalidArgumentException('$jsonString param must be a string.'); } - $this->jsonArray = json_decode($jsonString, true); + $jsonDecode = json_decode($jsonString, true); + + if (!is_array($jsonDecode)) { + $jsonDecode = [$jsonDecode]; + } + + $this->jsonArray = $jsonDecode; if (JSON_ERROR_NONE !== json_last_error()) { throw new InvalidArgumentException( diff --git a/tests/unit/Codeception/Util/JsonArrayTest.php b/tests/unit/Codeception/Util/JsonArrayTest.php index 5907bc7359..6e0dfcf774 100644 --- a/tests/unit/Codeception/Util/JsonArrayTest.php +++ b/tests/unit/Codeception/Util/JsonArrayTest.php @@ -59,6 +59,15 @@ public function testThrowsInvalidArgumentExceptionIfJsonIsInvalid() new JsonArray('{"test":'); } + /** + * @issue https://github.com/Codeception/Codeception/issues/4944 + */ + public function testConvertsBareJson() + { + $jsonArray = new JsonArray('"I am a {string}."'); + $this->assertEquals(['I am a {string}.'], $jsonArray->toArray()); + } + /** * @Issue https://github.com/Codeception/Codeception/issues/2899 */ From f29f457f3bc3cd7a6a2b9fc2153f34dc8c3fbcf1 Mon Sep 17 00:00:00 2001 From: Gabriel Caruso Date: Mon, 23 Apr 2018 15:00:44 -0300 Subject: [PATCH 043/395] Use dedicated PHPUnit assertions (#4950) --- src/Codeception/Module/Memcache.php | 4 +- src/Codeception/Module/REST.php | 2 +- tests/unit/Codeception/Module/TestsForWeb.php | 40 +++++++++---------- tests/unit/Codeception/Util/JsonArrayTest.php | 6 +-- 4 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/Codeception/Module/Memcache.php b/src/Codeception/Module/Memcache.php index f46ba0517b..69ce2e01ac 100644 --- a/src/Codeception/Module/Memcache.php +++ b/src/Codeception/Module/Memcache.php @@ -139,7 +139,7 @@ public function seeInMemcached($key, $value = null) $this->debugSection("Value", $actual); if (null === $value) { - $this->assertTrue(false !== $actual, "Cannot find key '$key' in Memcached"); + $this->assertNotFalse($actual, "Cannot find key '$key' in Memcached"); } else { $this->assertEquals($value, $actual, "Cannot find key '$key' in Memcached with the provided value"); } @@ -169,7 +169,7 @@ public function dontSeeInMemcached($key, $value = null) $this->debugSection("Value", $actual); if (null === $value) { - $this->assertTrue(false === $actual, "The key '$key' exists in Memcached"); + $this->assertFalse($actual, "The key '$key' exists in Memcached"); } else { if (false !== $actual) { $this->assertEquals($value, $actual, "The key '$key' exists in Memcached with the provided value"); diff --git a/src/Codeception/Module/REST.php b/src/Codeception/Module/REST.php index aff9d2b5a0..3f1db8c6b5 100644 --- a/src/Codeception/Module/REST.php +++ b/src/Codeception/Module/REST.php @@ -241,7 +241,7 @@ public function dontSeeHttpHeader($name, $value = null) public function seeHttpHeaderOnce($name) { $headers = $this->getRunningClient()->getInternalResponse()->getHeader($name, false); - $this->assertEquals(1, count($headers)); + $this->assertCount(1, $headers); } /** diff --git a/tests/unit/Codeception/Module/TestsForWeb.php b/tests/unit/Codeception/Module/TestsForWeb.php index 02ede2d14a..a37976582e 100644 --- a/tests/unit/Codeception/Module/TestsForWeb.php +++ b/tests/unit/Codeception/Module/TestsForWeb.php @@ -1042,10 +1042,10 @@ public function testSubmitForm() $form = data::get('form'); $this->assertEquals('Davert', $form['name']); $this->assertEquals('Is Codeception maintainer', $form['description']); - $this->assertFalse(isset($form['disabled_fieldset'])); - $this->assertFalse(isset($form['disabled_fieldset_textarea'])); - $this->assertFalse(isset($form['disabled_fieldset_select'])); - $this->assertFalse(isset($form['disabled_field'])); + $this->assertArrayNotHasKey('disabled_fieldset', $form); + $this->assertArrayNotHasKey('disabled_fieldset_textarea', $form); + $this->assertArrayNotHasKey('disabled_fieldset_select', $form); + $this->assertArrayNotHasKey('disabled_field', $form); $this->assertEquals('kill_all', $form['action']); } @@ -1209,8 +1209,8 @@ public function testSubmitFormWithTwoSubmitButtonsSubmitsCorrectValue() $this->module->seeElement("#button2"); $this->module->click("#button2"); $form = data::get('form'); - $this->assertTrue(isset($form['button2'])); - $this->assertTrue(isset($form['username'])); + $this->assertArrayHasKey('button2', $form); + $this->assertArrayHasKey('username', $form); $this->assertEquals('value2', $form['button2']); $this->assertEquals('fred', $form['username']); } @@ -1224,8 +1224,8 @@ public function testSubmitFormWithTwoSubmitButtonsSubmitsCorrectValueAfterFillFi $this->module->fillField("username", "bob"); $this->module->click("#button2"); $form = data::get('form'); - $this->assertTrue(isset($form['button2'])); - $this->assertTrue(isset($form['username'])); + $this->assertArrayHasKey('button2', $form); + $this->assertArrayHasKey('username', $form); $this->assertEquals('value2', $form['button2']); $this->assertEquals('bob', $form['username']); } @@ -1268,8 +1268,8 @@ public function testSubmitFormWithDefaultRadioAndCheckboxValues() 'test' => 'value' )); $form = data::get('form'); - $this->assertTrue(isset($form['checkbox1']), 'Checkbox value not sent'); - $this->assertTrue(isset($form['radio1']), 'Radio button value not sent'); + $this->assertArrayHasKey('checkbox1', $form, 'Checkbox value not sent'); + $this->assertArrayHasKey('radio1', $form, 'Radio button value not sent'); $this->assertEquals('testing', $form['checkbox1']); $this->assertEquals('to be sent', $form['radio1']); } @@ -1281,7 +1281,7 @@ public function testSubmitFormCheckboxWithBoolean() 'checkbox1' => true )); $form = data::get('form'); - $this->assertTrue(isset($form['checkbox1']), 'Checkbox value not sent'); + $this->assertArrayHasKey('checkbox1', $form, 'Checkbox value not sent'); $this->assertEquals('testing', $form['checkbox1']); $this->module->amOnPage('/form/example16'); @@ -1289,7 +1289,7 @@ public function testSubmitFormCheckboxWithBoolean() 'checkbox1' => false )); $form = data::get('form'); - $this->assertFalse(isset($form['checkbox1']), 'Checkbox value sent'); + $this->assertArrayNotHasKey('checkbox1', $form, 'Checkbox value sent'); } public function testSubmitFormWithCheckboxesWithoutValue() @@ -1320,7 +1320,7 @@ public function testSubmitFormWithButtons() isset($form['button1']) || isset($form['button2']) || isset($form['button4']), 'Button values for buttons 1, 2 and 4 should not be set' ); - $this->assertTrue(isset($form['button3']), 'Button value for button3 should be set'); + $this->assertArrayHasKey('button3', $form, 'Button value for button3 should be set'); $this->assertEquals($form['button3'], 'third', 'Button value for button3 should equal third'); $this->module->amOnPage('/form/form_with_buttons'); @@ -1332,7 +1332,7 @@ public function testSubmitFormWithButtons() isset($form['button1']) || isset($form['button2']) || isset($form['button3']), 'Button values for buttons 1, 2 and 3 should not be set' ); - $this->assertTrue(isset($form['button4']), 'Button value for button4 should be set'); + $this->assertArrayHasKey('button4', $form, 'Button value for button4 should be set'); $this->assertEquals($form['button4'], 'fourth', 'Button value for button4 should equal fourth'); } @@ -1441,8 +1441,8 @@ public function testSubmitAdjacentForms() $this->module->amOnPage('/form/submit_adjacentforms'); $this->module->submitForm('#form-2', []); $data = data::get('form'); - $this->assertTrue(isset($data['second-field'])); - $this->assertFalse(isset($data['first-field'])); + $this->assertArrayHasKey('second-field', $data); + $this->assertArrayNotHasKey('first-field', $data); $this->assertEquals('Killgore Trout', $data['second-field']); } @@ -1453,8 +1453,8 @@ public function testSubmitAdjacentFormsByButton() $this->module->fillField('second-field', 'Second'); $this->module->click('#submit1'); $data = data::get('form'); - $this->assertTrue(isset($data['first-field'])); - $this->assertFalse(isset($data['second-field'])); + $this->assertArrayHasKey('first-field', $data); + $this->assertArrayNotHasKey('second-field', $data); $this->assertEquals('First', $data['first-field']); $this->module->amOnPage('/form/submit_adjacentforms'); @@ -1462,8 +1462,8 @@ public function testSubmitAdjacentFormsByButton() $this->module->fillField('second-field', 'Second'); $this->module->click('#submit2'); $data = data::get('form'); - $this->assertFalse(isset($data['first-field'])); - $this->assertTrue(isset($data['second-field'])); + $this->assertArrayNotHasKey('first-field', $data); + $this->assertArrayHasKey('second-field', $data); $this->assertEquals('Second', $data['second-field']); } diff --git a/tests/unit/Codeception/Util/JsonArrayTest.php b/tests/unit/Codeception/Util/JsonArrayTest.php index 6e0dfcf774..a2dbcedd24 100644 --- a/tests/unit/Codeception/Util/JsonArrayTest.php +++ b/tests/unit/Codeception/Util/JsonArrayTest.php @@ -36,9 +36,9 @@ public function testXmlArrayConversion2() public function testXPathLocation() { - $this->assertTrue($this->jsonArray->filterByXPath('//ticket/title')->length > 0); - $this->assertTrue($this->jsonArray->filterByXPath('//ticket/user/name')->length > 0); - $this->assertTrue($this->jsonArray->filterByXPath('//user/name')->length > 0); + $this->assertGreaterThan(0, $this->jsonArray->filterByXPath('//ticket/title')->length); + $this->assertGreaterThan(0, $this->jsonArray->filterByXPath('//ticket/user/name')->length); + $this->assertGreaterThan(0, $this->jsonArray->filterByXPath('//user/name')->length); } public function testJsonPathLocation() From 39a510f9646f5d0d54228a11ec3f7a0f2a9a7b61 Mon Sep 17 00:00:00 2001 From: Gintautas Miselis Date: Mon, 30 Apr 2018 19:17:19 +0100 Subject: [PATCH 044/395] WebDriverTest: fixed incorrect assertion (#4957) --- tests/web/WebDriverTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/web/WebDriverTest.php b/tests/web/WebDriverTest.php index 85e9f6a48d..f220463a2e 100644 --- a/tests/web/WebDriverTest.php +++ b/tests/web/WebDriverTest.php @@ -1116,6 +1116,6 @@ public function testChangingCapabilities() }); $this->assertNotTrue($this->module->webDriver->getCapabilities()->getCapability('acceptInsecureCerts')); $this->module->_initializeSession(); - $this->assertTrue(true, $this->module->webDriver->getCapabilities()->getCapability('acceptInsecureCerts')); + $this->assertTrue($this->module->webDriver->getCapabilities()->getCapability('acceptInsecureCerts')); } } From d29f0e1e77ad709e07b42d1b6be6d3c65d8fbbd0 Mon Sep 17 00:00:00 2001 From: Jack Robbers <31850261+JackRobbers@users.noreply.github.com> Date: Tue, 1 May 2018 05:36:19 +1000 Subject: [PATCH 045/395] Fix broken links to code in customisation docs (#4951) --- docs/08-Customization.md | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/docs/08-Customization.md b/docs/08-Customization.md index 22e1d2f021..2abd32b29a 100644 --- a/docs/08-Customization.md +++ b/docs/08-Customization.md @@ -95,29 +95,29 @@ All listed events are available as constants in `Codeception\Events` class. | Event | When? | Triggered by |:--------------------:| --------------------------------------- | --------------------------: -| `suite.before` | Before suite is executed | [Suite, Settings](https://github.com/Codeception/Codeception/blob/master/src/Codeception/Event/SuiteEvent.php) -| `test.start` | Before test is executed | [Test](https://github.com/Codeception/Codeception/blob/master/src/Codeception/Event/TestEvent.php) -| `test.before` | At the very beginning of test execution | [Codeception Test](https://github.com/Codeception/Codeception/blob/master/src/Codeception/Event/TestEvent.php) -| `step.before` | Before step | [Step](https://github.com/Codeception/Codeception/blob/master/src/Codeception/Event/StepEvent.php) -| `step.after` | After step | [Step](https://github.com/Codeception/Codeception/blob/master/src/Codeception/Event/StepEvent.php) -| `step.fail` | After failed step | [Step](https://github.com/Codeception/Codeception/blob/master/src/Codeception/Event/StepEvent.php) -| `test.fail` | After failed test | [Test, Fail](https://github.com/Codeception/Codeception/blob/master/src/Codeception/Event/FailEvent.php) -| `test.error` | After test ended with error | [Test, Fail](https://github.com/Codeception/Codeception/blob/master/src/Codeception/Event/FailEvent.php) -| `test.incomplete` | After executing incomplete test | [Test, Fail](https://github.com/Codeception/Codeception/blob/master/src/Codeception/Event/FailEvent.php) -| `test.skipped` | After executing skipped test | [Test, Fail](https://github.com/Codeception/Codeception/blob/master/src/Codeception/Event/FailEvent.php) -| `test.success` | After executing successful test | [Test](https://github.com/Codeception/Codeception/blob/master/src/Codeception/Event/TestEvent.php) -| `test.after` | At the end of test execution | [Codeception Test](https://github.com/Codeception/Codeception/blob/master/src/Codeception/Event/TestEvent.php) -| `test.end` | After test execution | [Test](https://github.com/Codeception/Codeception/blob/master/src/Codeception/Event/TestEvent.php) -| `suite.after` | After suite was executed | [Suite, Result, Settings](https://github.com/Codeception/Codeception/blob/master/src/Codeception/Event/SuiteEvent.php) -| `test.fail.print` | When test fails are printed | [Test, Fail](https://github.com/Codeception/Codeception/blob/master/src/Codeception/Event/FailEvent.php) -| `result.print.after` | After result was printed | [Result, Printer](https://github.com/Codeception/Codeception/blob/master/src/Codeception/Event/PrintResultEvent.php) +| `suite.before` | Before suite is executed | [Suite, Settings](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Event/SuiteEvent.php) +| `test.start` | Before test is executed | [Test](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Event/TestEvent.php) +| `test.before` | At the very beginning of test execution | [Codeception Test](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Event/TestEvent.php) +| `step.before` | Before step | [Step](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Event/StepEvent.php) +| `step.after` | After step | [Step](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Event/StepEvent.php) +| `step.fail` | After failed step | [Step](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Event/StepEvent.php) +| `test.fail` | After failed test | [Test, Fail](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Event/FailEvent.php) +| `test.error` | After test ended with error | [Test, Fail](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Event/FailEvent.php) +| `test.incomplete` | After executing incomplete test | [Test, Fail](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Event/FailEvent.php) +| `test.skipped` | After executing skipped test | [Test, Fail](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Event/FailEvent.php) +| `test.success` | After executing successful test | [Test](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Event/TestEvent.php) +| `test.after` | At the end of test execution | [Codeception Test](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Event/TestEvent.php) +| `test.end` | After test execution | [Test](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Event/TestEvent.php) +| `suite.after` | After suite was executed | [Suite, Result, Settings](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Event/SuiteEvent.php) +| `test.fail.print` | When test fails are printed | [Test, Fail](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Event/FailEvent.php) +| `result.print.after` | After result was printed | [Result, Printer](https://github.com/Codeception/Codeception/blob/2.4/src/Codeception/Event/PrintResultEvent.php) There may be some confusion between `test.start`/`test.before` and `test.after`/`test.end`. The start and end events are triggered by PHPUnit, but the before and after events are triggered by Codeception. Thus, when you are using classical PHPUnit tests (extended from `PHPUnit\Framework\TestCase`), the before/after events won't be triggered for them. During the `test.before` event you can mark a test as skipped or incomplete, which is not possible in `test.start`. You can learn more from -[Codeception internal event listeners](https://github.com/Codeception/Codeception/tree/master/src/Codeception/Subscriber). +[Codeception internal event listeners](https://github.com/Codeception/Codeception/tree/2.4/src/Codeception/Subscriber). The extension class itself is inherited from `Codeception\Extension`: From df7f10a35f8223f1e92c73e3409dc8b82faa4900 Mon Sep 17 00:00:00 2001 From: Pavel Date: Mon, 30 Apr 2018 22:48:45 +0300 Subject: [PATCH 046/395] Added support for custom kernel names for Symfony (#4949) --- src/Codeception/Module/Symfony.php | 38 ++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/src/Codeception/Module/Symfony.php b/src/Codeception/Module/Symfony.php index 3009434a6c..2ceab3dbcc 100644 --- a/src/Codeception/Module/Symfony.php +++ b/src/Codeception/Module/Symfony.php @@ -1,7 +1,9 @@ 'app', 'var_path' => 'app', + 'kernel_class' => null, 'environment' => 'test', 'debug' => true, 'cache_router' => false, @@ -284,10 +295,8 @@ protected function getKernelClass() require_once $file; - $possibleKernelClasses = [ - 'AppKernel', // Symfony Standard - 'App\Kernel', // Symfony Flex - ]; + $possibleKernelClasses = $this->getPossibleKernelClasses(); + foreach ($possibleKernelClasses as $class) { if (class_exists($class)) { $refClass = new \ReflectionClass($class); @@ -624,4 +633,25 @@ private function dataRevealsValue(Data $data) { return method_exists($data, 'getValue'); } + + /** + * Returns list of the possible kernel classes based on the module configuration + * + * @return array + */ + private function getPossibleKernelClasses() + { + if (empty($this->config['kernel_class'])) { + return self::$possibleKernelClasses; + } + + if (!is_string($this->config['kernel_class'])) { + throw new ModuleException( + __CLASS__, + "Parameter 'kernel_class' must have 'string' type.\n" + ); + } + + return [$this->config['kernel_class']]; + } } From 604e62c191f51363c69246b8082767ca60364ac5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9?= Date: Mon, 30 Apr 2018 21:51:12 +0200 Subject: [PATCH 047/395] Added dochead for grabFromDatabase (#4945) Added dochead for proceedSeeInDatabase --- src/Codeception/Module/Db.php | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/Codeception/Module/Db.php b/src/Codeception/Module/Db.php index e48ff7156f..2e372a8f44 100644 --- a/src/Codeception/Module/Db.php +++ b/src/Codeception/Module/Db.php @@ -534,6 +534,16 @@ protected function countInDatabase($table, array $criteria = []) return (int) $this->proceedSeeInDatabase($table, 'count(*)', $criteria); } + /** + * Fetches all values from the column in database. + * Provide table name, desired column and criteria. + * + * @param string $table + * @param string $column + * @param array $criteria + * + * @return array + */ protected function proceedSeeInDatabase($table, $column, $criteria) { $query = $this->driver->select($column, $table, $criteria); @@ -573,6 +583,21 @@ public function grabColumnFromDatabase($table, $column, array $criteria = []) return $sth->fetchAll(\PDO::FETCH_COLUMN, 0); } + /** + * Fetches all values from the column in database. + * Provide table name, desired column and criteria. + * + * ``` php + * grabFromDatabase('users', 'email', array('name' => 'RebOOter')); + * ``` + * + * @param string $table + * @param string $column + * @param array $criteria + * + * @return array + */ public function grabFromDatabase($table, $column, $criteria = []) { return $this->proceedSeeInDatabase($table, $column, $criteria); From c498dcb30f8c884a4b487b960297901640c7f7ea Mon Sep 17 00:00:00 2001 From: Dmitry Naumenko Date: Thu, 3 May 2018 16:09:26 +0300 Subject: [PATCH 048/395] Handle absolute paths in ParamsLoader properly (#4960) --- src/Codeception/Lib/ParamsLoader.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Codeception/Lib/ParamsLoader.php b/src/Codeception/Lib/ParamsLoader.php index 309334ad8e..ce60a4d147 100644 --- a/src/Codeception/Lib/ParamsLoader.php +++ b/src/Codeception/Lib/ParamsLoader.php @@ -22,7 +22,7 @@ public function load($paramStorage) return $this->loadEnvironmentVars(); } - $this->paramsFile = codecept_root_dir($paramStorage); + $this->paramsFile = $paramStorage[0] === '/' ? $paramStorage : codecept_root_dir($paramStorage); if (!file_exists($this->paramsFile)) { throw new ConfigurationException("Params file {$this->paramsFile} not found"); } From fd45d579f0f50ba2d664b23438ed44947fe67751 Mon Sep 17 00:00:00 2001 From: Adrian Skierniewski Date: Wed, 16 May 2018 23:19:15 +0200 Subject: [PATCH 049/395] Fix memory leak when using Laravel factories inside Codeception (#4971) --- src/Codeception/Module/Laravel5.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Codeception/Module/Laravel5.php b/src/Codeception/Module/Laravel5.php index e97f536b95..54357d3cb8 100644 --- a/src/Codeception/Module/Laravel5.php +++ b/src/Codeception/Module/Laravel5.php @@ -217,6 +217,10 @@ public function _after(\Codeception\TestInterface $test) $connection->disconnect(); } } + + // Remove references to Faker in factories to prevent memory leak + unset($this->app[\Faker\Generator::class]); + unset($this->app[\Illuminate\Database\Eloquent\Factory::class]); } } From 889a32ff7b57cb3881d906e87ab189a0a25fafd5 Mon Sep 17 00:00:00 2001 From: philek Date: Sat, 26 May 2018 02:26:44 +0200 Subject: [PATCH 050/395] added support for null (#4987) --- src/Codeception/Lib/Driver/SqlSrv.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Codeception/Lib/Driver/SqlSrv.php b/src/Codeception/Lib/Driver/SqlSrv.php index b0858d5530..5d4fbbc89e 100644 --- a/src/Codeception/Lib/Driver/SqlSrv.php +++ b/src/Codeception/Lib/Driver/SqlSrv.php @@ -56,6 +56,12 @@ protected function generateWhereClause(array &$criteria) $params = []; foreach ($criteria as $k => $v) { + if ($v === null) { + $params[] = $this->getQuotedName($k) . " IS NULL "; + unset($criteria[$k]); + continue; + } + if (strpos(strtolower($k), ' like') > 0) { $k = str_replace(' like', '', strtolower($k)); $params[] = $this->getQuotedName($k) . " LIKE ? "; From 4364068d81b9d44dc56849d3812335a88de5d454 Mon Sep 17 00:00:00 2001 From: Dmytro Naumenko Date: Sat, 26 May 2018 03:31:53 +0300 Subject: [PATCH 051/395] Respect absolute paths in Yii2 module (#4961) * Respect absoulte paths in Yii2 module * Added codecept_absolute_path function * Added CHANGELOG * Use codecept_absolute_path() in ParamsLoader --- CHANGELOG-2.4.md | 2 ++ autoload.php | 15 +++++++++++++++ src/Codeception/Lib/ParamsLoader.php | 2 +- src/Codeception/Module/Yii2.php | 10 ++++++---- 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/CHANGELOG-2.4.md b/CHANGELOG-2.4.md index 4a6bec80a9..4ddcba25cd 100644 --- a/CHANGELOG-2.4.md +++ b/CHANGELOG-2.4.md @@ -12,6 +12,8 @@ * Fixtures method is now configurable * Subset of misconfigurations are now detected and informative messages created * Fixed using `$settings['path']` in `Codeception\Configuration::suiteSettings()` on Windows by @olegpro +* **Breaking** `$settings['configFile']` now supports absolute paths. In you have defined relative path to config in absolute manner +(starting with `/`), you must change it. @silverfire * [Laravel5] Added Laravel 5.4+ (5.1+ backward compatible) support for `callArtisan` method in Laravel5 module. See #4860 by @mohamed-aiman * Fixed #4854: unnecessary escaping in operation arguments logging by @nicholascus * Fixed humanizing steps for utf8 strings by @nicholascus. See #4850 diff --git a/autoload.php b/autoload.php index 61b67589d9..ee043a39b6 100644 --- a/autoload.php +++ b/autoload.php @@ -101,3 +101,18 @@ function codecept_relative_path($path) ); } } + +if (!function_exists('codecept_absolute_path')) { + /** + * If $path is absolute, it will be returned without changes. + * If $path is relative, it will be passed to `codecept_root_dir()` function + * to make it absolute. + * + * @param string $path + * @return string the absolute path + */ + function codecept_absolute_path($path) + { + return mb_substr($path, 0, 1) === DIRECTORY_SEPARATOR ? $path : codecept_root_dir($path); + } +} diff --git a/src/Codeception/Lib/ParamsLoader.php b/src/Codeception/Lib/ParamsLoader.php index ce60a4d147..b863c6dd5a 100644 --- a/src/Codeception/Lib/ParamsLoader.php +++ b/src/Codeception/Lib/ParamsLoader.php @@ -22,7 +22,7 @@ public function load($paramStorage) return $this->loadEnvironmentVars(); } - $this->paramsFile = $paramStorage[0] === '/' ? $paramStorage : codecept_root_dir($paramStorage); + $this->paramsFile = codecept_absolute_path($paramStorage); if (!file_exists($this->paramsFile)) { throw new ConfigurationException("Params file {$this->paramsFile} not found"); } diff --git a/src/Codeception/Module/Yii2.php b/src/Codeception/Module/Yii2.php index d714b18ad0..213e2b8983 100644 --- a/src/Codeception/Module/Yii2.php +++ b/src/Codeception/Module/Yii2.php @@ -53,7 +53,7 @@ * modules: * enabled: * - Yii2: - * configFile: '/path/to/config.php' + * configFile: 'path/to/config.php' * ``` * * ### Parts @@ -238,10 +238,12 @@ private function initServerGlobal() protected function validateConfig() { parent::validateConfig(); - if (!is_file(Configuration::projectDir() . $this->config['configFile'])) { + + $pathToConfig = codecept_absolute_path($this->config['configFile']); + if (!is_file($pathToConfig)) { throw new ModuleConfigException( __CLASS__, - "The application config file does not exist: " . Configuration::projectDir() . $this->config['configFile'] + "The application config file does not exist: " . $pathToConfig ); } @@ -262,7 +264,7 @@ protected function validateConfig() protected function configureClient(array $settings) { - $settings['configFile'] = Configuration::projectDir() . $settings['configFile']; + $settings['configFile'] = codecept_absolute_path($settings['configFile']); foreach ($settings as $key => $value) { if (property_exists($this->client, $key)) { From 8b3e3b4e03217bb11e3a1af87aa2005e5e3d2c19 Mon Sep 17 00:00:00 2001 From: Gintautas Miselis Date: Sat, 26 May 2018 01:45:55 +0100 Subject: [PATCH 052/395] Stub 2.0 (#4981) I released Stub 2.0, because the change is incompatible with Codeception 2.3 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index fbb47559f5..03397bf643 100644 --- a/composer.json +++ b/composer.json @@ -30,7 +30,7 @@ "symfony/dom-crawler": ">=2.7 <5.0", "behat/gherkin": "^4.4.0", "codeception/phpunit-wrapper": "^6.0.9|^7.0.6", - "codeception/stub": "^1.0" + "codeception/stub": "^2.0" }, "require-dev": { "monolog/monolog": "~1.8", From e7ef7a2d99f0d62dc282d4d12250b9eb0e177e14 Mon Sep 17 00:00:00 2001 From: Michail Date: Sat, 26 May 2018 22:27:24 +0300 Subject: [PATCH 053/395] Fix error on single file test: headers already sent (#4986) Notice: Undefined index: tests in Codeception\Command\Run.php on line 389 --- src/Codeception/Command/Run.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Codeception/Command/Run.php b/src/Codeception/Command/Run.php index 1ef490ba80..a6686f641b 100644 --- a/src/Codeception/Command/Run.php +++ b/src/Codeception/Command/Run.php @@ -386,7 +386,7 @@ protected function matchSingleTest($suite, $config) { // Workaround when codeception.yml is inside tests directory and tests path is set to "." // @see https://github.com/Codeception/Codeception/issues/4432 - if ($config['paths']['tests'] === '.' && !preg_match('~^\.[/\\\]~', $suite)) { + if (isset($config['paths']['tests']) && $config['paths']['tests'] === '.' && !preg_match('~^\.[/\\\]~', $suite)) { $suite = './' . $suite; } From 8fa27b72a3d3ad75f0dd456c24730c15cae07dff Mon Sep 17 00:00:00 2001 From: Johannes Schobel Date: Sat, 26 May 2018 21:48:01 +0200 Subject: [PATCH 054/395] Features: Allow PRESETs for codeception and suite config files (#4984) * feature to load presetfile in main codeception file * same for the suites * add tests * changelog and docs * change presetfile to extends --- CHANGELOG-2.4.md | 3 ++ docs/reference/Configuration.md | 3 +- src/Codeception/Configuration.php | 32 +++++++++++++++---- tests/cli/ConfigWithPresetsCest.php | 12 +++++++ .../presets/_presets/preset.codeception.yml | 10 ++++++ .../presets/_presets/preset.unit.suite.yml | 3 ++ tests/data/presets/codeception.yml | 1 + tests/data/presets/codeception_2.yml | 1 + .../presets/tests/_support/DummyTester.php | 26 +++++++++++++++ .../presets/tests/_support/Helper/Dummy.php | 27 ++++++++++++++++ .../tests/_support/_generated/.gitignore | 1 + tests/data/presets/tests/unit.suite.yml | 2 ++ tests/data/presets/tests/unit/PresetTest.php | 11 +++++++ 13 files changed, 125 insertions(+), 7 deletions(-) create mode 100644 tests/cli/ConfigWithPresetsCest.php create mode 100644 tests/data/presets/_presets/preset.codeception.yml create mode 100644 tests/data/presets/_presets/preset.unit.suite.yml create mode 100644 tests/data/presets/codeception.yml create mode 100644 tests/data/presets/codeception_2.yml create mode 100644 tests/data/presets/tests/_support/DummyTester.php create mode 100644 tests/data/presets/tests/_support/Helper/Dummy.php create mode 100644 tests/data/presets/tests/_support/_generated/.gitignore create mode 100644 tests/data/presets/tests/unit.suite.yml create mode 100644 tests/data/presets/tests/unit/PresetTest.php diff --git a/CHANGELOG-2.4.md b/CHANGELOG-2.4.md index 4ddcba25cd..46eca2907a 100644 --- a/CHANGELOG-2.4.md +++ b/CHANGELOG-2.4.md @@ -1,3 +1,6 @@ +#### 2.4.2 +* Added support for `extends` in the `codeception.yml` and `*.suite.yml` files; by @johannesschobel + #### 2.4.1 * Fixed "Uncaught Error: Call to undefined method Codeception\Test\Descriptor::getTestDataSetIndex()" error when filtering tests. diff --git a/docs/reference/Configuration.md b/docs/reference/Configuration.md index c00ecb8ace..41c068a1f1 100644 --- a/docs/reference/Configuration.md +++ b/docs/reference/Configuration.md @@ -93,7 +93,7 @@ modules: password: '' dump: tests/_data/dump.sql ``` - +* `extends`: allows you to specify a file (relative to the `codeception.yml` file) that holds some already pre-defined values. This can be used to always use the same configuration for modules or whatever. * `extensions`: allows to enable and configure [Codeception extensions](http://codeception.com/docs/08-Customization#Extension), [Group Objects](http://codeception.com/docs/08-Customization#Group-Objects), and [Custom Commands](http://codeception.com/docs/08-Customization#Custom-Commands). * `reporters`: allows to [change default reporters](http://codeception.com/docs/08-Customization#Custom-Reporters) of Codeception * `coverage`: [CodeCoverage](http://codeception.com/docs/11-Codecoverage#Configuration) settings. @@ -134,6 +134,7 @@ modules: ``` +* `extends`: allows you to specify a file (relative to the `*.suite.yml` file) that holds some already pre-defined values. This can be used to always use the same configuration for modules or whatever. * `namespace`: default namespace of actor, support classes and tests. * `suite_namespace`: default namespace for new tests of this suite (ignores `namespace` option) * `env`: override any configuration per [environment](http://codeception.com/docs/07-AdvancedUsage#Environments). diff --git a/src/Codeception/Configuration.php b/src/Codeception/Configuration.php index e5ebe96402..8914191403 100644 --- a/src/Codeception/Configuration.php +++ b/src/Codeception/Configuration.php @@ -69,6 +69,7 @@ class Configuration 'namespace' => '', 'include' => [], 'paths' => [], + 'extends' => null, 'suites' => [], 'modules' => [], 'extensions' => [ @@ -109,6 +110,7 @@ class Configuration 'depends' => [] ], 'path' => null, + 'extends' => null, 'namespace' => null, 'groups' => [], 'shuffle' => false, @@ -180,6 +182,16 @@ public static function config($configFile = null) throw new ConfigurationException("Configuration file is invalid"); } + // we check for the "extends" key in the yml file + if (isset($config['extends'])) { + // and now we search for the file + $presetFilePath = realpath(self::$dir . DIRECTORY_SEPARATOR . $config['extends']); + if (file_exists($presetFilePath)) { + // and merge it with our configuration file + $config = self::mergeConfigs(self::getConfFromFile($presetFilePath), $config); + } + } + self::$config = $config; // compatibility with suites created by Codeception < 2.3.0 @@ -670,14 +682,22 @@ protected static function loadSuiteConfig($suite, $path, $settings) return self::mergeConfigs($settings, self::$config['suites'][$suite]); } - $suiteDistConf = self::getConfFromFile( - self::$dir . DIRECTORY_SEPARATOR . $path . DIRECTORY_SEPARATOR . "$suite.suite.dist.yml" - ); - $suiteConf = self::getConfFromFile( - self::$dir . DIRECTORY_SEPARATOR . $path . DIRECTORY_SEPARATOR . "$suite.suite.yml" - ); + $suiteDir = self::$dir . DIRECTORY_SEPARATOR . $path; + + $suiteDistConf = self::getConfFromFile($suiteDir . DIRECTORY_SEPARATOR . "$suite.suite.dist.yml"); + $suiteConf = self::getConfFromFile($suiteDir . DIRECTORY_SEPARATOR . "$suite.suite.yml"); + + // now we check the suite config file, if a extends key is defined + if (isset($suiteConf['extends'])) { + $presetFilePath = realpath($suiteDir . DIRECTORY_SEPARATOR . $suiteConf['extends']); + if (file_exists($presetFilePath)) { + $settings = self::mergeConfigs(self::getConfFromFile($presetFilePath), $settings); + } + } + $settings = self::mergeConfigs($settings, $suiteDistConf); $settings = self::mergeConfigs($settings, $suiteConf); + return $settings; } diff --git a/tests/cli/ConfigWithPresetsCest.php b/tests/cli/ConfigWithPresetsCest.php new file mode 100644 index 0000000000..5e79a113aa --- /dev/null +++ b/tests/cli/ConfigWithPresetsCest.php @@ -0,0 +1,12 @@ +amInPath('tests/data/presets'); + $I->executeCommand('run -c codeception.yml'); + $I->seeInShellOutput('OK (1 test'); + } + +} diff --git a/tests/data/presets/_presets/preset.codeception.yml b/tests/data/presets/_presets/preset.codeception.yml new file mode 100644 index 0000000000..f0446cc8a1 --- /dev/null +++ b/tests/data/presets/_presets/preset.codeception.yml @@ -0,0 +1,10 @@ +paths: + tests: tests + output: tests/_output + data: tests/_data + support: tests/_support + envs: tests/_envs +actor_suffix: Tester +extensions: + enabled: + - Codeception\Extension\RunFailed diff --git a/tests/data/presets/_presets/preset.unit.suite.yml b/tests/data/presets/_presets/preset.unit.suite.yml new file mode 100644 index 0000000000..6e8aea8013 --- /dev/null +++ b/tests/data/presets/_presets/preset.unit.suite.yml @@ -0,0 +1,3 @@ +modules: + enabled: + - \Helper\Dummy \ No newline at end of file diff --git a/tests/data/presets/codeception.yml b/tests/data/presets/codeception.yml new file mode 100644 index 0000000000..1fd32bd717 --- /dev/null +++ b/tests/data/presets/codeception.yml @@ -0,0 +1 @@ +extends: ./_presets/preset.codeception.yml diff --git a/tests/data/presets/codeception_2.yml b/tests/data/presets/codeception_2.yml new file mode 100644 index 0000000000..bbbc1a614b --- /dev/null +++ b/tests/data/presets/codeception_2.yml @@ -0,0 +1 @@ +extends: ./_presets/missing.preset.codeception.yml diff --git a/tests/data/presets/tests/_support/DummyTester.php b/tests/data/presets/tests/_support/DummyTester.php new file mode 100644 index 0000000000..3f333003bc --- /dev/null +++ b/tests/data/presets/tests/_support/DummyTester.php @@ -0,0 +1,26 @@ +debug($this->config); + } + + public function seePathIsSet() + { + $this->assertNotEmpty($this->config['path']); + } + + public function seeVarsAreSet() + { + $vars = $this->config['vars']; + $this->assertContains('val1', $vars); + $this->assertContains('val2', $vars); + } +} diff --git a/tests/data/presets/tests/_support/_generated/.gitignore b/tests/data/presets/tests/_support/_generated/.gitignore new file mode 100644 index 0000000000..cde8069e12 --- /dev/null +++ b/tests/data/presets/tests/_support/_generated/.gitignore @@ -0,0 +1 @@ +*.php diff --git a/tests/data/presets/tests/unit.suite.yml b/tests/data/presets/tests/unit.suite.yml new file mode 100644 index 0000000000..2d0b4bf877 --- /dev/null +++ b/tests/data/presets/tests/unit.suite.yml @@ -0,0 +1,2 @@ +presetfile: ./../_presets/preset.unit.suite.yml +class_name: DummyTester \ No newline at end of file diff --git a/tests/data/presets/tests/unit/PresetTest.php b/tests/data/presets/tests/unit/PresetTest.php new file mode 100644 index 0000000000..5b345378eb --- /dev/null +++ b/tests/data/presets/tests/unit/PresetTest.php @@ -0,0 +1,11 @@ +assertEquals(true, true); + $this->assertNotEquals(true, false); + } + +} \ No newline at end of file From f280db96c06291e0d33e89b01f4bbfd84d22eab2 Mon Sep 17 00:00:00 2001 From: Davert Date: Sun, 27 May 2018 01:16:48 +0300 Subject: [PATCH 055/395] removed incorrect coverage tests --- tests/coverage/RemoteServerWithCrap4jCept.php | 7 ------- tests/coverage/RemoteServerWithPHPUnitCept.php | 7 ------- 2 files changed, 14 deletions(-) delete mode 100644 tests/coverage/RemoteServerWithCrap4jCept.php delete mode 100644 tests/coverage/RemoteServerWithPHPUnitCept.php diff --git a/tests/coverage/RemoteServerWithCrap4jCept.php b/tests/coverage/RemoteServerWithCrap4jCept.php deleted file mode 100644 index e333fc27b4..0000000000 --- a/tests/coverage/RemoteServerWithCrap4jCept.php +++ /dev/null @@ -1,7 +0,0 @@ -wantTo('try generate remote codecoverage crap4j report'); -$I->amInPath('tests/data/sandbox'); -$I->executeCommand('run remote_server --coverage-crap4j remote_crap.xml'); -$I->seeFileFound('remote_crap.xml', 'tests/_output'); -$I->seeInThisFile('Method Crap Stats'); \ No newline at end of file diff --git a/tests/coverage/RemoteServerWithPHPUnitCept.php b/tests/coverage/RemoteServerWithPHPUnitCept.php deleted file mode 100644 index 63dadcb7db..0000000000 --- a/tests/coverage/RemoteServerWithPHPUnitCept.php +++ /dev/null @@ -1,7 +0,0 @@ -wantTo('try generate remote codecoverage phpunit report'); -$I->amInPath('tests/data/sandbox'); -$I->executeCommand('run remote_server --coverage-phpunit remote_server'); -$I->seeFileFound('index.xml', 'tests/_output/remote_server'); From 356c286aaf77e89cf280ac17d835af9e667474ec Mon Sep 17 00:00:00 2001 From: Michael Bodnarchuk Date: Sun, 27 May 2018 01:17:36 +0300 Subject: [PATCH 056/395] Preparing 2.4.2 release; Updated changelog (#4990) --- CHANGELOG-2.4.md | 31 +++++++++++++++++-- docs/12-ParallelExecution.md | 19 ++++-------- .../Lib/Interfaces/SessionSnapshot.php | 16 ++++++++-- src/Codeception/Module/WebDriver.php | 10 ------ 4 files changed, 48 insertions(+), 28 deletions(-) diff --git a/CHANGELOG-2.4.md b/CHANGELOG-2.4.md index 46eca2907a..02a7f56ce2 100644 --- a/CHANGELOG-2.4.md +++ b/CHANGELOG-2.4.md @@ -1,5 +1,31 @@ #### 2.4.2 -* Added support for `extends` in the `codeception.yml` and `*.suite.yml` files; by @johannesschobel + +* Added support for `extends` in the `codeception.yml` and `*.suite.yml` files; by @johannesschobel. + Allows to inherit current config from a provided file. See example for `functional.suite.yml`: + + +```yml +actor: FunctionalTester +extends: shared.functional.suite.yml +modules: + enabled: + - \App\Modules\X\Tests\Helper\Functional +``` + +* [Yii2] Restore null check for client in Yii2 by @wkritzinger. See #4940 +* [Yii2] Resetting Yii application in `_after`. By @SamMousa. See #4928 +* [Yii2] **Breaking** `$settings['configFile']` now supports absolute paths. In you have defined relative path to config in absolute manner +* [WebDriverIO] Added `deleteSessionSnapshot` by @vi4o +* [Symfony] Added support for custom kernel names with `kernel_class` config option. By @omnilight. +* [Asserts] Better exception message for `expectException` by @Slamdunk +* [REST] Decode all non-arrays to array. See #4946 by @Amunak, fixes #4944. +* [ZF2] Fixed compatibility with ZF2 ServiceManager by @omnilight. +* [Laravel5] Fixed memory leak when using Laravel factories inside Codeception. See #4971 by @AdrianSkierniewski +* [Db] Added support for `null` values in MSSQL driver by @philek +* Handle absolute paths in ParamsLoader by @SilverFire +* Fix error on single file test. See #4986 by @mikbox74 +* Upgraded to Codeception/Stub 2.0 by @Naktibalda, fixed compatibility. + #### 2.4.1 @@ -14,8 +40,7 @@ * More reliable application state before and during test execution * Fixtures method is now configurable * Subset of misconfigurations are now detected and informative messages created -* Fixed using `$settings['path']` in `Codeception\Configuration::suiteSettings()` on Windows by @olegpro -* **Breaking** `$settings['configFile']` now supports absolute paths. In you have defined relative path to config in absolute manner +* Fixed using `$settings['path']` in `Codeception\Configuration::suiteSettings()` on Windows by @olegpro (starting with `/`), you must change it. @silverfire * [Laravel5] Added Laravel 5.4+ (5.1+ backward compatible) support for `callArtisan` method in Laravel5 module. See #4860 by @mohamed-aiman * Fixed #4854: unnecessary escaping in operation arguments logging by @nicholascus diff --git a/docs/12-ParallelExecution.md b/docs/12-ParallelExecution.md index fce0be60c9..a7c18e0549 100644 --- a/docs/12-ParallelExecution.md +++ b/docs/12-ParallelExecution.md @@ -28,7 +28,7 @@ Run official Codeception image from DockerHub: docker run codeception/codeception Running tests from a project, by mounting the current path as a host-volume into the container. -The default working directory in the container is `/project`. +The **default working directory in the container is `/project`**. docker run -v ${PWD}:/project codeception/codeception run @@ -39,17 +39,15 @@ Define all required services in `docker-compose.yml` file. Make sure to follow D We prepared a sample config with codeception, web server, database, and selenium with firefox to be executed together. ```yaml -version: '2' +version: '3' services: codecept: image: codeception/codeception depends_on: - - firefox + - chrome - web volumes: - - ./src:/src - - ./tests:/tests - - ./codeception.yml:/codeception.yml + - .:/project web: image: php:7-apache depends_on: @@ -58,13 +56,8 @@ services: - .:/var/www/html db: image: percona:5.6 - ports: - - '3306' - firefox: - image: selenium/standalone-firefox-debug:2.53.0 - ports: - - '4444' - - '5900' + chrome: + image: selenium/standalone-chrome ``` Codeception service will execute command `codecept run` but only after all services are started. This is defined using `depends_on` parameter. diff --git a/src/Codeception/Lib/Interfaces/SessionSnapshot.php b/src/Codeception/Lib/Interfaces/SessionSnapshot.php index 84074b391e..00ee66a892 100644 --- a/src/Codeception/Lib/Interfaces/SessionSnapshot.php +++ b/src/Codeception/Lib/Interfaces/SessionSnapshot.php @@ -36,11 +36,23 @@ interface SessionSnapshot public function saveSessionSnapshot($name); /** - * Loads cookies from saved snapshot. + * Loads cookies from a saved snapshot. + * Allows to reuse same session across tests without additional login. + * + * See [saveSessionSnapshot](#saveSessionSnapshot) * * @param $name - * @see saveSessionSnapshot * @return mixed */ public function loadSessionSnapshot($name); + + /** + * Deletes session snapshot. + * + * See [saveSessionSnapshot](#saveSessionSnapshot) + * + * @param $name + * @return mixed + */ + public function deleteSessionSnapshot($name); } diff --git a/src/Codeception/Module/WebDriver.php b/src/Codeception/Module/WebDriver.php index 740e3b12ab..0848e1755e 100644 --- a/src/Codeception/Module/WebDriver.php +++ b/src/Codeception/Module/WebDriver.php @@ -3028,9 +3028,6 @@ protected function getLocator($selector) throw new \InvalidArgumentException("Only CSS or XPath allowed"); } - /** - * @param string $name - */ public function saveSessionSnapshot($name) { $this->sessionSnapshots[$name] = []; @@ -3048,10 +3045,6 @@ public function saveSessionSnapshot($name) $this->debugSection('Snapshot', "Saved \"$name\" session snapshot"); } - /** - * @param string $name - * @return bool - */ public function loadSessionSnapshot($name) { if (!isset($this->sessionSnapshots[$name])) { @@ -3065,9 +3058,6 @@ public function loadSessionSnapshot($name) return true; } - /** - * @param string $name - */ public function deleteSessionSnapshot($name) { if (isset($this->sessionSnapshots[$name])) { From 0c4ad4feae6e0681d5675976e9208c7f3b516ab6 Mon Sep 17 00:00:00 2001 From: Cladis Date: Thu, 7 Jun 2018 09:53:44 +0300 Subject: [PATCH 057/395] =?UTF-8?q?it's=20=E2=86=92=20its=20(#5003)=20[ski?= =?UTF-8?q?p=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/reference/Mock.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/reference/Mock.md b/docs/reference/Mock.md index 20b859e31f..2d53316572 100644 --- a/docs/reference/Mock.md +++ b/docs/reference/Mock.md @@ -24,8 +24,8 @@ $this->make(new User, ['name' => 'davert']); ?> ``` -To replace method provide it's name as a key in second parameter -and it's return value or callback function as parameter +To replace method provide its name as a key in second parameter +and its return value or callback function as parameter ``` php Date: Wed, 20 Jun 2018 16:49:10 -0300 Subject: [PATCH 058/395] Bug fix with multiple kernels (#5022) * Bug fix with multiple kernels It's not possible to set a Kernel different of the AppKernel, and I have two kernels an Admin and an Api, and I need use ApiKernel to run tests This commit makes a checking if kernel defined exists in the path. Because the previous version he gets the first kernel in my case it gets AdminKernel and always returns Kernel not found * Remove 1 space after closing parenthesis --- src/Codeception/Module/Symfony.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Codeception/Module/Symfony.php b/src/Codeception/Module/Symfony.php index 2ceab3dbcc..d9674fbee7 100644 --- a/src/Codeception/Module/Symfony.php +++ b/src/Codeception/Module/Symfony.php @@ -286,21 +286,23 @@ protected function getKernelClass() . "Specify directory where file with Kernel class for your application is located with `app_path` parameter." ); } - $file = current($results); if (file_exists(codecept_root_dir() . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php')) { // ensure autoloader from this dir is loaded require_once codecept_root_dir() . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php'; } - require_once $file; + $filesRealPath = array_map(function ($file) { + require_once $file; + return $file->getRealPath(); + }, $results); $possibleKernelClasses = $this->getPossibleKernelClasses(); foreach ($possibleKernelClasses as $class) { if (class_exists($class)) { $refClass = new \ReflectionClass($class); - if ($refClass->getFileName() === $file->getRealpath()) { + if ($file = array_search($refClass->getFileName(), $filesRealPath)) { return $class; } } From 534dc68c4ac79a251733f04547dcd963c76429a1 Mon Sep 17 00:00:00 2001 From: Joseph Zidell Date: Wed, 20 Jun 2018 15:50:10 -0400 Subject: [PATCH 059/395] Update shim.php (#5013) Fix indentation [skip ci] --- shim.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shim.php b/shim.php index edc3efe727..7ba3df6e31 100644 --- a/shim.php +++ b/shim.php @@ -6,7 +6,7 @@ } namespace Symfony\Component\CssSelector { -if (!class_exists('Symfony\Component\CssSelector\CssSelectorConverter')) { + if (!class_exists('Symfony\Component\CssSelector\CssSelectorConverter')) { class CssSelectorConverter { function toXPath($cssExpr, $prefix = 'descendant-or-self::') { return CssSelector::toXPath($cssExpr, $prefix); @@ -69,4 +69,4 @@ class WebDriverTimeouts extends Facebook\WebDriver\WebDriverTimeouts {}; class WebDriverWindow extends Facebook\WebDriver\WebDriverWindow {}; interface WebDriverElement extends Facebook\WebDriver\WebDriverElement {}; } -} \ No newline at end of file +} From b903a8220ac5dbca8580ec8dd9baabafd995b7a7 Mon Sep 17 00:00:00 2001 From: Mark Lambley Date: Thu, 21 Jun 2018 06:01:01 +1000 Subject: [PATCH 060/395] Add your own test format classes to the loader (#5009) --- docs/07-AdvancedUsage.md | 44 +++++++++++++++++++++++++++++++ docs/reference/Configuration.md | 1 + src/Codeception/Configuration.php | 1 + src/Codeception/Test/Loader.php | 5 ++++ 4 files changed, 51 insertions(+) diff --git a/docs/07-AdvancedUsage.md b/docs/07-AdvancedUsage.md index dba333b58b..616c706168 100644 --- a/docs/07-AdvancedUsage.md +++ b/docs/07-AdvancedUsage.md @@ -661,6 +661,50 @@ groups: This will load all found `p*` files in `tests/_data` as groups. Group names will be as follows p1,p2,...,pN. +## Formats + +In addition to the standard test formats (Cept, Cest, Unit, Gherkin) you can implement your own format classes to customise your test execution. +Specify these in your suite configuration: + +```yaml +formats: + - \My\Namespace\MyFormat +``` + +Then define a class which implements the LoaderInterface + +```php +namespace My\Namespace; + +class MyFormat implements \Codeception\Test\Loader\LoaderInterface +{ + protected $tests; + + protected $settings; + + public function __construct($settings = []) + { + //These are the suite settings + $this->settings = $settings; + } + + public function loadTests($filename) + { + //Load file and create tests + } + + public function getTests() + { + return $this->tests; + } + + public function getPattern() + { + return '~Myformat\.php$~'; + } +} +``` + ## Shell autocompletion For bash and zsh shells, you can use autocompletion for your Codeception projects by executing the following in your shell (or add it to your .bashrc/.zshrc): diff --git a/docs/reference/Configuration.md b/docs/reference/Configuration.md index 41c068a1f1..234d6b77d0 100644 --- a/docs/reference/Configuration.md +++ b/docs/reference/Configuration.md @@ -139,6 +139,7 @@ modules: * `suite_namespace`: default namespace for new tests of this suite (ignores `namespace` option) * `env`: override any configuration per [environment](http://codeception.com/docs/07-AdvancedUsage#Environments). * `groups`: [groups](http://codeception.com/docs/07-AdvancedUsage#Groups) with the list of tests of for corresponding group. +* `formats`: [formats](http://codeception.com/docs/07-AdvancedUsage#Formats) with the list of extra test format classes. * `coverage`: pre suite [CodeCoverage](http://codeception.com/docs/11-Codecoverage#Configuration) settings. * `gherkin`: per suite [BDD Gherkin](http://codeception.com/docs/07-BDD#Configuration) settings. * `error_level`: [error level](http://codeception.com/docs/04-FunctionalTests#Error-Reporting) for runner in current suite. Should be specified for unit, integration, functional tests. Passes value to `error_reporting` function. diff --git a/src/Codeception/Configuration.php b/src/Codeception/Configuration.php index 8914191403..2732d82cf7 100644 --- a/src/Codeception/Configuration.php +++ b/src/Codeception/Configuration.php @@ -113,6 +113,7 @@ class Configuration 'extends' => null, 'namespace' => null, 'groups' => [], + 'formats' => [], 'shuffle' => false, 'extensions' => [ // suite extensions 'enabled' => [], diff --git a/src/Codeception/Test/Loader.php b/src/Codeception/Test/Loader.php index 0cdd72a7d5..bb12cc9995 100644 --- a/src/Codeception/Test/Loader.php +++ b/src/Codeception/Test/Loader.php @@ -53,6 +53,11 @@ public function __construct(array $suiteSettings) new UnitLoader(), new GherkinLoader($suiteSettings) ]; + if (isset($suiteSettings['formats'])) { + foreach ($suiteSettings['formats'] as $format) { + $this->formats[] = new $format($suiteSettings); + } + } } public function getTests() From d8aaf00515d0cd5f2c8df4721bc956c2007c5f1a Mon Sep 17 00:00:00 2001 From: Johannes Schobel Date: Wed, 20 Jun 2018 22:05:07 +0200 Subject: [PATCH 061/395] adding new assert methods (#5029) --- src/Codeception/Module/Asserts.php | 22 +++++++++++++++++++ src/Codeception/Util/Shared/Asserts.php | 22 +++++++++++++++++++ tests/unit/Codeception/Module/AssertsTest.php | 6 +++++ 3 files changed, 50 insertions(+) diff --git a/src/Codeception/Module/Asserts.php b/src/Codeception/Module/Asserts.php index 6bb7927ebc..314d284d4c 100644 --- a/src/Codeception/Module/Asserts.php +++ b/src/Codeception/Module/Asserts.php @@ -263,6 +263,17 @@ public function assertTrue($condition, $message = '') parent::assertTrue($condition, $message); } + /** + * Checks that the condition is NOT true (everything but true) + * + * @param $condition + * @param string $message + */ + public function assertNotTrue($condition, $message = '') + { + parent::assertNotTrue($condition, $message); + } + /** * Checks that condition is negative. * @@ -274,6 +285,17 @@ public function assertFalse($condition, $message = '') parent::assertFalse($condition, $message); } + /** + * Checks that the condition is NOT false (everything but false) + * + * @param $condition + * @param string $message + */ + public function assertNotFalse($condition, $message = '') + { + parent::assertNotFalse($condition, $message); + } + /** * Checks if file exists * diff --git a/src/Codeception/Util/Shared/Asserts.php b/src/Codeception/Util/Shared/Asserts.php index 2c4958bed7..c50211ce19 100644 --- a/src/Codeception/Util/Shared/Asserts.php +++ b/src/Codeception/Util/Shared/Asserts.php @@ -267,6 +267,17 @@ protected function assertTrue($condition, $message = '') \PHPUnit\Framework\Assert::assertTrue($condition, $message); } + /** + * Checks that the condition is NOT true (everything but true) + * + * @param $condition + * @param string $message + */ + protected function assertNotTrue($condition, $message = '') + { + \PHPUnit\Framework\Assert::assertNotTrue($condition, $message); + } + /** * Checks that condition is negative. * @@ -278,6 +289,17 @@ protected function assertFalse($condition, $message = '') \PHPUnit\Framework\Assert::assertFalse($condition, $message); } + /** + * Checks that the condition is NOT false (everything but false) + * + * @param $condition + * @param string $message + */ + protected function assertNotFalse($condition, $message = '') + { + \PHPUnit\Framework\Assert::assertNotFalse($condition, $message); + } + /** * * @param $haystack diff --git a/tests/unit/Codeception/Module/AssertsTest.php b/tests/unit/Codeception/Module/AssertsTest.php index 5d71f3b152..e237175049 100644 --- a/tests/unit/Codeception/Module/AssertsTest.php +++ b/tests/unit/Codeception/Module/AssertsTest.php @@ -19,7 +19,13 @@ public function testAsserts() $module->assertNotNull(false); $module->assertNotNull(0); $module->assertTrue(true); + $module->assertNotTrue(false); + $module->assertNotTrue(null); + $module->assertNotTrue('foo'); $module->assertFalse(false); + $module->assertNotFalse(true); + $module->assertNotFalse(null); + $module->assertNotFalse('foo'); $module->assertFileExists(__FILE__); $module->assertFileNotExists(__FILE__ . '.notExist'); $module->assertInstanceOf('Exception', new Exception()); From 3174f5fa5ab22f39ec0a49391cef3b02b8c1f370 Mon Sep 17 00:00:00 2001 From: Mike Harrison Date: Wed, 20 Jun 2018 17:06:52 -0400 Subject: [PATCH 062/395] Issue #5023 (#5024) * Created failing test RunCest::runJsonReport * PSR2 Formatting * Removed double parentheses --- tests/cli.suite.yml | 3 ++- tests/cli/RunCest.php | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/cli.suite.yml b/tests/cli.suite.yml index 8176cf742a..9824f57c17 100644 --- a/tests/cli.suite.yml +++ b/tests/cli.suite.yml @@ -4,4 +4,5 @@ modules: - Filesystem - Cli - CliHelper - - CodeHelper \ No newline at end of file + - CodeHelper + - Asserts \ No newline at end of file diff --git a/tests/cli/RunCest.php b/tests/cli/RunCest.php index 1e01d040dc..ddab45ea0c 100644 --- a/tests/cli/RunCest.php +++ b/tests/cli/RunCest.php @@ -47,6 +47,7 @@ public function runJsonReport(\CliGuy $I) $I->seeFileFound('report.json', 'tests/_output'); $I->seeInThisFile('"suite":'); $I->seeInThisFile('"dummy"'); + $I->assertNotNull(json_decode(file_get_contents('tests/_output/report.json'))); } /** @@ -292,7 +293,7 @@ public function runTestWithSubSteps(\CliGuy $I, $scenario) $scenario->skip("Xdebug not loaded"); } - $file = "codeception".DIRECTORY_SEPARATOR."c3"; + $file = "codeception" . DIRECTORY_SEPARATOR . "c3"; $I->executeCommand('run scenario SubStepsCept --steps'); $I->seeInShellOutput(<< Date: Thu, 21 Jun 2018 14:15:29 +0200 Subject: [PATCH 063/395] new REST / InnerBrowser Asserts (#5030) * new assertions to assert "ranges" of status-codes (e.g., if it is a client-error --> 4xx) * add missing test --- src/Codeception/Lib/InnerBrowser.php | 50 +++++++++++++++++++ src/Codeception/Module/REST.php | 33 ++++++++++++ .../Codeception/Module/PhpBrowserTest.php | 36 +++++++++++++ 3 files changed, 119 insertions(+) diff --git a/src/Codeception/Lib/InnerBrowser.php b/src/Codeception/Lib/InnerBrowser.php index 1aefbc4399..fa41755b04 100644 --- a/src/Codeception/Lib/InnerBrowser.php +++ b/src/Codeception/Lib/InnerBrowser.php @@ -1576,6 +1576,24 @@ public function seeResponseCodeIs($code) $this->assertEquals($code, $this->getResponseStatusCode(), $failureMessage); } + /** + * Checks that response code is between a certain range. Between actually means [from <= CODE <= to] + * + * @param $from + * @param $to + */ + public function seeResponseCodeIsBetween($from, $to) + { + $failureMessage = sprintf( + 'Expected HTTP Status Code between %s and %s. Actual Status Code: %s', + HttpCode::getDescription($from), + HttpCode::getDescription($to), + HttpCode::getDescription($this->getResponseStatusCode()) + ); + $this->assertGreaterThanOrEqual($from, $this->getResponseStatusCode(), $failureMessage); + $this->assertLessThanOrEqual($to, $this->getResponseStatusCode(), $failureMessage); + } + /** * Checks that response code is equal to value provided. * @@ -1597,6 +1615,38 @@ public function dontSeeResponseCodeIs($code) $this->assertNotEquals($code, $this->getResponseStatusCode(), $failureMessage); } + /** + * Checks that the response code 2xx + */ + public function seeResponseCodeIsSuccessful() + { + $this->seeResponseCodeIsBetween(200, 299); + } + + /** + * Checks that the response code 3xx + */ + public function seeResponseCodeIsRedirection() + { + $this->seeResponseCodeIsBetween(300, 399); + } + + /** + * Checks that the response code is 4xx + */ + public function seeResponseCodeIsClientError() + { + $this->seeResponseCodeIsBetween(400, 499); + } + + /** + * Checks that the response code is 5xx + */ + public function seeResponseCodeIsServerError() + { + $this->seeResponseCodeIsBetween(500, 599); + } + public function seeInTitle($title) { $nodes = $this->getCrawler()->filter('title'); diff --git a/src/Codeception/Module/REST.php b/src/Codeception/Module/REST.php index 3f1db8c6b5..dd3b808b2b 100644 --- a/src/Codeception/Module/REST.php +++ b/src/Codeception/Module/REST.php @@ -1161,6 +1161,39 @@ public function dontSeeResponseCodeIs($code) $this->connectionModule->dontSeeResponseCodeIs($code); } + /** + * Checks that the response code is 2xx + */ + public function seeResponseCodeIsSuccessful() + { + $this->connectionModule->seeResponseCodeIsSuccessful(); + } + + /** + * Checks that the response code 3xx + */ + public function seeResponseCodeIsRedirection() + { + $this->connectionModule->seeResponseCodeIsRedirection(); + } + + /** + * Checks that the response code is 4xx + */ + public function seeResponseCodeIsClientError() + { + $this->connectionModule->seeResponseCodeIsClientError(); + } + + /** + * Checks that the response code is 5xx + */ + public function seeResponseCodeIsServerError() + { + $this->connectionModule->seeResponseCodeIsServerError(); + } + + /** * Checks whether last response was valid XML. * This is done with libxml_get_last_error function. diff --git a/tests/unit/Codeception/Module/PhpBrowserTest.php b/tests/unit/Codeception/Module/PhpBrowserTest.php index 9c911f4414..86a92de7d4 100644 --- a/tests/unit/Codeception/Module/PhpBrowserTest.php +++ b/tests/unit/Codeception/Module/PhpBrowserTest.php @@ -691,4 +691,40 @@ public function testSetUserAgentUsingConfig() $response = $this->module->grabPageSource(); $this->assertEquals('Codeception User Agent Test 1.0', $response, 'Incorrect user agent'); } + + public function testIfStatusCodeIsWithin2xxRange() + { + $this->module->amOnPage('https://httpstat.us/200'); + $this->module->seeResponseCodeIsSuccessful(); + + $this->module->amOnPage('https://httpstat.us/299'); + $this->module->seeResponseCodeIsSuccessful(); + } + + public function testIfStatusCodeIsWithin3xxRange() + { + $this->module->amOnPage('https://httpstat.us/300'); + $this->module->seeResponseCodeIsRedirection(); + + $this->module->amOnPage('https://httpstat.us/399'); + $this->module->seeResponseCodeIsRedirection(); + } + + public function testIfStatusCodeIsWithin4xxRange() + { + $this->module->amOnPage('https://httpstat.us/400'); + $this->module->seeResponseCodeIsClientError(); + + $this->module->amOnPage('https://httpstat.us/499'); + $this->module->seeResponseCodeIsClientError(); + } + + public function testIfStatusCodeIsWithin5xxRange() + { + $this->module->amOnPage('https://httpstat.us/500'); + $this->module->seeResponseCodeIsServerError(); + + $this->module->amOnPage('https://httpstat.us/599'); + $this->module->seeResponseCodeIsServerError(); + } } From 01973880f3c3aa7fcc534aa16a51d4352bf7518a Mon Sep 17 00:00:00 2001 From: Johannes Schobel Date: Thu, 21 Jun 2018 23:13:41 +0200 Subject: [PATCH 064/395] minor doc updates (#5035) --- docs/03-AcceptanceTests.md | 2 +- docs/06-ModulesAndHelpers.md | 4 ++++ docs/06-ReusingTestCode.md | 4 ++-- docs/07-AdvancedUsage.md | 6 +++--- docs/12-ParallelExecution.md | 2 +- docs/modules/AMQP.md | 8 ++++---- docs/modules/AngularJS.md | 4 ++-- docs/modules/REST.md | 1 + docs/modules/WebDriver.md | 4 ++-- docs/reference/Locator.md | 24 ++++++++++++------------ docs/reference/Mock.md | 4 ++-- docs/reference/XmlBuilder.md | 2 +- 12 files changed, 35 insertions(+), 30 deletions(-) diff --git a/docs/03-AcceptanceTests.md b/docs/03-AcceptanceTests.md index a091298d02..fb7d600a34 100644 --- a/docs/03-AcceptanceTests.md +++ b/docs/03-AcceptanceTests.md @@ -295,7 +295,7 @@ and you want to check that the user can log into the site using this password: ```php fillField('email', 'miles@davis.com') +$I->fillField('email', 'miles@davis.com'); $I->click('Generate Password'); $password = $I->grabTextFrom('#password'); $I->click('Login'); diff --git a/docs/06-ModulesAndHelpers.md b/docs/06-ModulesAndHelpers.md index 052a244034..2c8c2bd9a0 100644 --- a/docs/06-ModulesAndHelpers.md +++ b/docs/06-ModulesAndHelpers.md @@ -357,6 +357,8 @@ Here is how it is done in the Db module: class Db extends \Codeception\Module { protected $requiredFields = ['dsn', 'user', 'password']; + // ... +} ``` The next time you start the suite without setting one of these values, an exception will be thrown. @@ -370,6 +372,8 @@ class WebDriver extends \Codeception\Module { protected $requiredFields = ['browser', 'url']; protected $config = ['host' => '127.0.0.1', 'port' => '4444']; + // ... +} ``` The host and port parameter can be redefined in the suite configuration. diff --git a/docs/06-ReusingTestCode.md b/docs/06-ReusingTestCode.md index 5ac61a6398..9d921d6697 100644 --- a/docs/06-ReusingTestCode.md +++ b/docs/06-ReusingTestCode.md @@ -106,7 +106,7 @@ breaking the [Single Responsibility Principle](http://en.wikipedia.org/wiki/Sing ### Session Snapshot -If you need to authorize a user for each test, you can do so by submiting the login form at the beginning of every test. +If you need to authorize a user for each test, you can do so by submitting the login form at the beginning of every test. Running those steps takes time, and in the case of Selenium tests (which are slow by themselves) that time loss can become significant. @@ -237,7 +237,7 @@ the [PageObject pattern](http://docs.seleniumhq.org/docs/06_test_design_consider which is widely used by test automation engineers. The PageObject pattern represents a web page as a class and the DOM elements on that page as its properties, and some basic interactions as its methods. PageObjects are very important when you are developing a flexible architecture of your tests. -Do not hardcode complex CSS or XPath locators in your tests but rather move them into PageObject classes. +Do not hard-code complex CSS or XPath locators in your tests but rather move them into PageObject classes. Codeception can generate a PageObject class for you with command: diff --git a/docs/07-AdvancedUsage.md b/docs/07-AdvancedUsage.md index 616c706168..df4fc85e92 100644 --- a/docs/07-AdvancedUsage.md +++ b/docs/07-AdvancedUsage.md @@ -497,7 +497,7 @@ public function myTest(\AcceptanceTester $I, \Codeception\Scenario $scenario) } ``` -`Codeception\Scenario` is also availble in Actor classes and StepObjects. You can access it with `$this->getScenario()`. +`Codeception\Scenario` is also available in Actor classes and StepObjects. You can access it with `$this->getScenario()`. ### Dependencies @@ -705,9 +705,9 @@ class MyFormat implements \Codeception\Test\Loader\LoaderInterface } ``` -## Shell autocompletion +## Shell auto-completion -For bash and zsh shells, you can use autocompletion for your Codeception projects by executing the following in your shell (or add it to your .bashrc/.zshrc): +For bash and zsh shells, you can use auto-completion for your Codeception projects by executing the following in your shell (or add it to your .bashrc/.zshrc): ```bash # BASH ~4.x, ZSH source <([codecept location] _completion --generate-hook --program codecept --use-vendor-bin) diff --git a/docs/12-ParallelExecution.md b/docs/12-ParallelExecution.md index a7c18e0549..9ca83e8607 100644 --- a/docs/12-ParallelExecution.md +++ b/docs/12-ParallelExecution.md @@ -138,7 +138,7 @@ $ composer require codeception/codeception ### Preparing Robo -Intitalizes basic RoboFile in the root of your project +Initializes basic RoboFile in the root of your project ```bash $ robo init diff --git a/docs/modules/AMQP.md b/docs/modules/AMQP.md index 737054dfb1..3b01152a42 100644 --- a/docs/modules/AMQP.md +++ b/docs/modules/AMQP.md @@ -49,7 +49,7 @@ $I->bindQueueToExchange( 'nameOfMyQueueToBind', // name of the queue 'transactionTracking.transaction', // exchange name to bind to 'your.routing.key' // Optionally, provide a binding key -) +); ``` * `param string` $queue @@ -72,7 +72,7 @@ This is an alias of method `exchange_declare` of `PhpAmqpLib\Channel\AMQPChannel $I->declareExchange( 'nameOfMyExchange', // exchange name 'topic' // exchange type -) +); ``` * `param string` $exchange @@ -96,8 +96,8 @@ This is an alias of method `queue_declare` of `PhpAmqpLib\Channel\AMQPChannel`. ```php declareQueue( - 'nameOfMyQueue', // exchange name -) + 'nameOfMyQueue' // exchange name +); ``` * `param string` $queue diff --git a/docs/modules/AngularJS.md b/docs/modules/AngularJS.md index e929cc721e..51270a1ca2 100644 --- a/docs/modules/AngularJS.md +++ b/docs/modules/AngularJS.md @@ -752,9 +752,9 @@ A callback should be executed by JavaScript to exit from a script. Callback is passed as a last element in `arguments` array. Additional arguments can be passed as array in second parameter. -```js +``` php // wait for 1200 milliseconds my running `setTimeout` -* $I->executeAsyncJS('setTimeout(arguments[0], 1200)'); +$I->executeAsyncJS('setTimeout(arguments[0], 1200)'); $seconds = 1200; // or seconds are passed as argument $I->executeAsyncJS('setTimeout(arguments[1], arguments[0])', [$seconds]); diff --git a/docs/modules/REST.md b/docs/modules/REST.md index 6798cf5831..c9eaf2221f 100644 --- a/docs/modules/REST.md +++ b/docs/modules/REST.md @@ -661,6 +661,7 @@ $I->seeResponseMatchesJsonType([ // {'user_id': '1'} $I->seeResponseMatchesJsonType([ 'user_id' => 'string:>0', // works with strings as well + ]); } ?> ``` diff --git a/docs/modules/WebDriver.md b/docs/modules/WebDriver.md index 7faf738973..3cc1cd8279 100644 --- a/docs/modules/WebDriver.md +++ b/docs/modules/WebDriver.md @@ -936,9 +936,9 @@ A callback should be executed by JavaScript to exit from a script. Callback is passed as a last element in `arguments` array. Additional arguments can be passed as array in second parameter. -```js +``` php // wait for 1200 milliseconds my running `setTimeout` -* $I->executeAsyncJS('setTimeout(arguments[0], 1200)'); +$I->executeAsyncJS('setTimeout(arguments[0], 1200)'); $seconds = 1200; // or seconds are passed as argument $I->executeAsyncJS('setTimeout(arguments[1], arguments[0])', [$seconds]); diff --git a/docs/reference/Locator.md b/docs/reference/Locator.md index ae78463fa6..239dc8697a 100644 --- a/docs/reference/Locator.md +++ b/docs/reference/Locator.md @@ -165,9 +165,9 @@ Checks that provided string is CSS selector ```php true -Locator::isCSS('body') => true -Locator::isCSS('//body/p/user') => false +Locator::isCSS('#user .hello'); // => true +Locator::isCSS('body'); // => true +Locator::isCSS('//body/p/user'); // => false ``` * `param` $selector @@ -183,9 +183,9 @@ Checks that a string is valid CSS class ```php true -Locator::isClass('body') => false -Locator::isClass('//body/p/user') => false +Locator::isClass('.hello'); // => true +Locator::isClass('body'); // => false +Locator::isClass('//body/p/user'); // => false ``` * `param` $class @@ -201,9 +201,9 @@ Checks that a string is valid CSS ID ```php true -Locator::isID('body') => false -Locator::isID('//body/p/user') => false +Locator::isID('#user'); // => true +Locator::isID('body'); // => false +Locator::isID('//body/p/user'); // => false ``` * `param` $id @@ -228,9 +228,9 @@ Checks that locator is an XPath ```php false -Locator::isXPath('body') => false -Locator::isXPath('//body/p/user') => true +Locator::isXPath('#user .hello'); // => false +Locator::isXPath('body'); // => false +Locator::isXPath('//body/p/user'); // => true ``` * `param` $locator diff --git a/docs/reference/Mock.md b/docs/reference/Mock.md index 2d53316572..8066190e98 100644 --- a/docs/reference/Mock.md +++ b/docs/reference/Mock.md @@ -301,7 +301,7 @@ use \Codeception\Stub\Expected; $user = $this->make( 'User', - array( + array ( 'getName' => Expected::atLeastOnce('Davert')), 'someMethod' => function() {} ) @@ -353,7 +353,7 @@ Alternatively, a function can be passed as parameter: ```php users ->attr('empty','false') ->items ->item - ->val('useful item'); + ->val('useful item') ->parents('user') ->active ->val(1); From 9aa56242cb107c79b5a2960ad9231f739bb6623e Mon Sep 17 00:00:00 2001 From: Johannes Schobel Date: Tue, 26 Jun 2018 03:14:39 +0200 Subject: [PATCH 065/395] bump changelog (#5041) --- CHANGELOG-2.4.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG-2.4.md b/CHANGELOG-2.4.md index 02a7f56ce2..eec398b49e 100644 --- a/CHANGELOG-2.4.md +++ b/CHANGELOG-2.4.md @@ -1,9 +1,17 @@ +#### 2.4.3 + +* Fixed a bug in order to use multiple Kernels; by @alefcastelo +* Added feature to specify your own test formats (e.g., Cept, Cest, ...); by @mlambley +* [Asserts] Added new methods `assertNotTrue` and `assertNotFalse` methods; by @johannesschobel +* [REST / InnerBrowser] Added new methods to check for `Http Status Ranges` with nice "wrappers" (e.g., `seeHttpStatusCodeIsSuccessful()` checks the code between 200 and 299); by @johannesschobel +* [REST / InnerBrowser] Added new method to load a stub file from the `data` folder of the suite and replace placeholder with real values; by @johannesschobel +* Improved the docs; by community + #### 2.4.2 * Added support for `extends` in the `codeception.yml` and `*.suite.yml` files; by @johannesschobel. Allows to inherit current config from a provided file. See example for `functional.suite.yml`: - ```yml actor: FunctionalTester extends: shared.functional.suite.yml From 13b2db0d54068afaabf3ca8ac8b6591d69018f46 Mon Sep 17 00:00:00 2001 From: Davert Date: Tue, 26 Jun 2018 17:09:28 +0300 Subject: [PATCH 066/395] updated changelog, updated docs --- CHANGELOG-2.4.md | 7 ++--- docs/modules/AMQP.md | 8 ++--- docs/modules/AngularJS.md | 49 ++++++++++++++++++++++++++--- docs/modules/Asserts.md | 16 ++++++++++ docs/modules/Db.md | 16 +++------- docs/modules/Laravel5.md | 28 +++++++++++++++++ docs/modules/Lumen.md | 28 +++++++++++++++++ docs/modules/Phalcon.md | 28 +++++++++++++++++ docs/modules/PhpBrowser.md | 28 +++++++++++++++++ docs/modules/REST.md | 21 ++++++++++++- docs/modules/Silex.md | 28 +++++++++++++++++ docs/modules/Symfony.md | 31 ++++++++++++++++++ docs/modules/WebDriver.md | 49 ++++++++++++++++++++++++++--- docs/modules/Yii1.md | 28 +++++++++++++++++ docs/modules/Yii2.md | 46 +++++++++++++++++++++++++-- docs/modules/ZF1.md | 28 +++++++++++++++++ docs/modules/ZF2.md | 28 +++++++++++++++++ docs/modules/ZendExpressive.md | 28 +++++++++++++++++ docs/reference/Locator.md | 24 +++++++------- docs/reference/Mock.md | 8 ++--- docs/reference/Module.md | 54 ++++++++++++++++++++++---------- docs/reference/XmlBuilder.md | 2 +- src/Codeception/Codecept.php | 2 +- tests/data/claypit/composer.lock | 8 ++--- 24 files changed, 521 insertions(+), 72 deletions(-) diff --git a/CHANGELOG-2.4.md b/CHANGELOG-2.4.md index eec398b49e..cde1c9fe25 100644 --- a/CHANGELOG-2.4.md +++ b/CHANGELOG-2.4.md @@ -1,10 +1,9 @@ #### 2.4.3 -* Fixed a bug in order to use multiple Kernels; by @alefcastelo -* Added feature to specify your own test formats (e.g., Cept, Cest, ...); by @mlambley +* [Create your own test formats](https://codeception.com/docs/07-AdvancedUsage#Formats) (e.g., Cept, Cest, ...); by @mlambley +* [Symfony] Fixed a bug in order to use multiple Kernels; by @alefcastelo * [Asserts] Added new methods `assertNotTrue` and `assertNotFalse` methods; by @johannesschobel -* [REST / InnerBrowser] Added new methods to check for `Http Status Ranges` with nice "wrappers" (e.g., `seeHttpStatusCodeIsSuccessful()` checks the code between 200 and 299); by @johannesschobel -* [REST / InnerBrowser] Added new method to load a stub file from the `data` folder of the suite and replace placeholder with real values; by @johannesschobel +* [REST][PhpBrowser][Frameworks] Added new methods to check for `Http Status Ranges` with nice "wrappers" (e.g., `seeHttpStatusCodeIsSuccessful()` checks the code between 200 and 299); by @johannesschobel * Improved the docs; by community #### 2.4.2 diff --git a/docs/modules/AMQP.md b/docs/modules/AMQP.md index 3b01152a42..737054dfb1 100644 --- a/docs/modules/AMQP.md +++ b/docs/modules/AMQP.md @@ -49,7 +49,7 @@ $I->bindQueueToExchange( 'nameOfMyQueueToBind', // name of the queue 'transactionTracking.transaction', // exchange name to bind to 'your.routing.key' // Optionally, provide a binding key -); +) ``` * `param string` $queue @@ -72,7 +72,7 @@ This is an alias of method `exchange_declare` of `PhpAmqpLib\Channel\AMQPChannel $I->declareExchange( 'nameOfMyExchange', // exchange name 'topic' // exchange type -); +) ``` * `param string` $exchange @@ -96,8 +96,8 @@ This is an alias of method `queue_declare` of `PhpAmqpLib\Channel\AMQPChannel`. ```php declareQueue( - 'nameOfMyQueue' // exchange name -); + 'nameOfMyQueue', // exchange name +) ``` * `param string` $queue diff --git a/docs/modules/AngularJS.md b/docs/modules/AngularJS.md index 51270a1ca2..5fa69b66a5 100644 --- a/docs/modules/AngularJS.md +++ b/docs/modules/AngularJS.md @@ -468,6 +468,15 @@ Print out latest Selenium Logs in debug mode * `param TestInterface` $test +### deleteSessionSnapshot + +Deletes session snapshot. + +See [saveSessionSnapshot](#saveSessionSnapshot) + + * `param` $name + + ### dontSee Checks that the current page doesn't contain the text specified (case insensitive). @@ -752,9 +761,9 @@ A callback should be executed by JavaScript to exit from a script. Callback is passed as a last element in `arguments` array. Additional arguments can be passed as array in second parameter. -``` php +```js // wait for 1200 milliseconds my running `setTimeout` -$I->executeAsyncJS('setTimeout(arguments[0], 1200)'); +* $I->executeAsyncJS('setTimeout(arguments[0], 1200)'); $seconds = 1200; // or seconds are passed as argument $I->executeAsyncJS('setTimeout(arguments[1], arguments[0])', [$seconds]); @@ -932,8 +941,12 @@ $name = $I->grabValueFrom(['name' => 'username']); ### loadSessionSnapshot - * `param string` $name - * `return` bool +Loads cookies from a saved snapshot. +Allows to reuse same session across tests without additional login. + +See [saveSessionSnapshot](#saveSessionSnapshot) + + * `param` $name ### makeScreenshot @@ -1113,7 +1126,33 @@ $I->resizeWindow(800, 600); ### saveSessionSnapshot - * `param string` $name +Saves current cookies into named snapshot in order to restore them in other tests +This is useful to save session state between tests. +For example, if user needs log in to site for each test this scenario can be executed once +while other tests can just restore saved cookies. + +``` php +loadSessionSnapshot('login')) return; + + // logging in + $I->amOnPage('/login'); + $I->fillField('name', 'jon'); + $I->fillField('password', '123345'); + $I->click('Login'); + + // saving snapshot + $I->saveSessionSnapshot('login'); +} +?> +``` + + * `param` $name ### scrollTo diff --git a/docs/modules/Asserts.md b/docs/modules/Asserts.md index 924852ebf3..7ae38dc8ab 100644 --- a/docs/modules/Asserts.md +++ b/docs/modules/Asserts.md @@ -212,6 +212,14 @@ $I->assertNotEquals($calculator->add(0.1, 0.2), 0.4, 'Calculator should add the * `param float` $delta +### assertNotFalse + +Checks that the condition is NOT false (everything but false) + + * `param` $condition + * `param string` $message + + ### assertNotInstanceOf * `param` $class @@ -245,6 +253,14 @@ Checks that two variables are not same * `param string` $message +### assertNotTrue + +Checks that the condition is NOT true (everything but true) + + * `param` $condition + * `param string` $message + + ### assertNull Checks that variable is NULL diff --git a/docs/modules/Db.md b/docs/modules/Db.md index 38015e04c4..73d9356274 100644 --- a/docs/modules/Db.md +++ b/docs/modules/Db.md @@ -219,27 +219,19 @@ $mails = $I->grabColumnFromDatabase('users', 'email', array('name' => 'RebOOter' ### grabFromDatabase -Fetches a single column value from a database. +Fetches all values from the column in database. Provide table name, desired column and criteria. ``` php grabFromDatabase('users', 'email', array('name' => 'Davert')); -``` -Comparison expressions can be used as well: - -```php -grabFromDatabase('posts', ['num_comments >=' => 100]); -$user = $I->grabFromDatabase('users', ['email like' => 'miles%']); +$mails = $I->grabFromDatabase('users', 'email', array('name' => 'RebOOter')); ``` -Supported operators: `<`, `>`, `>=`, `<=`, `!=`, `like`. - * `param string` $table * `param string` $column - * `param array` $criteria + * `param array` $criteria + * `return` array ### grabNumRecords diff --git a/docs/modules/Laravel5.md b/docs/modules/Laravel5.md index b30b0b2907..78547ccb4d 100644 --- a/docs/modules/Laravel5.md +++ b/docs/modules/Laravel5.md @@ -1567,6 +1567,34 @@ $I->seeResponseCodeIs(\Codeception\Util\HttpCode::OK); * `param` $code +### seeResponseCodeIsBetween + +Checks that response code is between a certain range. Between actually means [from <= CODE <= to] + + * `param` $from + * `param` $to + + +### seeResponseCodeIsClientError + +Checks that the response code is 4xx + + +### seeResponseCodeIsRedirection + +Checks that the response code 3xx + + +### seeResponseCodeIsServerError + +Checks that the response code is 5xx + + +### seeResponseCodeIsSuccessful + +Checks that the response code 2xx + + ### seeSessionHasValues Assert that the session has a given list of values. diff --git a/docs/modules/Lumen.md b/docs/modules/Lumen.md index 9b463ec1aa..e6a49f9f54 100644 --- a/docs/modules/Lumen.md +++ b/docs/modules/Lumen.md @@ -1243,6 +1243,34 @@ $I->seeResponseCodeIs(\Codeception\Util\HttpCode::OK); * `param` $code +### seeResponseCodeIsBetween + +Checks that response code is between a certain range. Between actually means [from <= CODE <= to] + + * `param` $from + * `param` $to + + +### seeResponseCodeIsClientError + +Checks that the response code is 4xx + + +### seeResponseCodeIsRedirection + +Checks that the response code 3xx + + +### seeResponseCodeIsServerError + +Checks that the response code is 5xx + + +### seeResponseCodeIsSuccessful + +Checks that the response code 2xx + + ### selectOption Selects an option in a select tag or in radio button group. diff --git a/docs/modules/Phalcon.md b/docs/modules/Phalcon.md index 7106ebf920..b454e2c911 100644 --- a/docs/modules/Phalcon.md +++ b/docs/modules/Phalcon.md @@ -1174,6 +1174,34 @@ $I->seeResponseCodeIs(\Codeception\Util\HttpCode::OK); * `param` $code +### seeResponseCodeIsBetween + +Checks that response code is between a certain range. Between actually means [from <= CODE <= to] + + * `param` $from + * `param` $to + + +### seeResponseCodeIsClientError + +Checks that the response code is 4xx + + +### seeResponseCodeIsRedirection + +Checks that the response code 3xx + + +### seeResponseCodeIsServerError + +Checks that the response code is 5xx + + +### seeResponseCodeIsSuccessful + +Checks that the response code 2xx + + ### seeSessionHasValues Assert that the session has a given list of values. diff --git a/docs/modules/PhpBrowser.md b/docs/modules/PhpBrowser.md index fad0a6a363..b0b658fae4 100644 --- a/docs/modules/PhpBrowser.md +++ b/docs/modules/PhpBrowser.md @@ -1052,6 +1052,34 @@ $I->seeResponseCodeIs(\Codeception\Util\HttpCode::OK); * `param` $code +### seeResponseCodeIsBetween + +Checks that response code is between a certain range. Between actually means [from <= CODE <= to] + + * `param` $from + * `param` $to + + +### seeResponseCodeIsClientError + +Checks that the response code is 4xx + + +### seeResponseCodeIsRedirection + +Checks that the response code 3xx + + +### seeResponseCodeIsServerError + +Checks that the response code is 5xx + + +### seeResponseCodeIsSuccessful + +Checks that the response code 2xx + + ### selectOption Selects an option in a select tag or in radio button group. diff --git a/docs/modules/REST.md b/docs/modules/REST.md index c9eaf2221f..c5f6cb42a6 100644 --- a/docs/modules/REST.md +++ b/docs/modules/REST.md @@ -442,6 +442,26 @@ $I->seeResponseCodeIs(\Codeception\Util\HttpCode::OK); * `param` $code +### seeResponseCodeIsClientError + +Checks that the response code is 4xx + + +### seeResponseCodeIsRedirection + +Checks that the response code 3xx + + +### seeResponseCodeIsServerError + +Checks that the response code is 5xx + + +### seeResponseCodeIsSuccessful + +Checks that the response code is 2xx + + ### seeResponseContains Checks whether the last response contains text. @@ -661,7 +681,6 @@ $I->seeResponseMatchesJsonType([ // {'user_id': '1'} $I->seeResponseMatchesJsonType([ 'user_id' => 'string:>0', // works with strings as well - ]); } ?> ``` diff --git a/docs/modules/Silex.md b/docs/modules/Silex.md index 55684b8796..1e1b7f7e1f 100644 --- a/docs/modules/Silex.md +++ b/docs/modules/Silex.md @@ -1000,6 +1000,34 @@ $I->seeResponseCodeIs(\Codeception\Util\HttpCode::OK); * `param` $code +### seeResponseCodeIsBetween + +Checks that response code is between a certain range. Between actually means [from <= CODE <= to] + + * `param` $from + * `param` $to + + +### seeResponseCodeIsClientError + +Checks that the response code is 4xx + + +### seeResponseCodeIsRedirection + +Checks that the response code 3xx + + +### seeResponseCodeIsServerError + +Checks that the response code is 5xx + + +### seeResponseCodeIsSuccessful + +Checks that the response code 2xx + + ### selectOption Selects an option in a select tag or in radio button group. diff --git a/docs/modules/Symfony.md b/docs/modules/Symfony.md index 607fe2677b..50645edbf5 100644 --- a/docs/modules/Symfony.md +++ b/docs/modules/Symfony.md @@ -13,6 +13,7 @@ This module uses Symfony Crawler and HttpKernel to emulate requests and test res * app_path: 'src' - in Symfony 4 Kernel is located inside `src` * environment: 'local' - environment used for load kernel +* kernel_class: 'App\Kernel' - kernel class name * em_service: 'doctrine.orm.entity_manager' - use the stated EntityManager to pair with Doctrine Module. * debug: true - turn on/off debug mode * cache_router: 'false' - enable router caching between tests in order to [increase performance](http://lakion.com/blog/how-did-we-speed-up-sylius-behat-suite-with-blackfire) @@ -32,6 +33,7 @@ This module uses Symfony Crawler and HttpKernel to emulate requests and test res * app_path: 'app' - specify custom path to your app dir, where the kernel interface is located. * var_path: 'var' - specify custom path to your var dir, where bootstrap cache is located. * environment: 'local' - environment used for load kernel +* kernel_class: 'AppKernel' - kernel class name * em_service: 'doctrine.orm.entity_manager' - use the stated EntityManager to pair with Doctrine Module. * debug: true - turn on/off debug mode * cache_router: 'false' - enable router caching between tests in order to [increase performance](http://lakion.com/blog/how-did-we-speed-up-sylius-behat-suite-with-blackfire) @@ -51,6 +53,7 @@ This module uses Symfony Crawler and HttpKernel to emulate requests and test res * app_path: 'app' - specify custom path to your app dir, where bootstrap cache and kernel interface is located. * environment: 'local' - environment used for load kernel +* kernel_class: 'AppKernel' - kernel class name * debug: true - turn on/off debug mode * em_service: 'doctrine.orm.entity_manager' - use the stated EntityManager to pair with Doctrine Module. * cache_router: 'false' - enable router caching between tests in order to [increase performance](http://lakion.com/blog/how-did-we-speed-up-sylius-behat-suite-with-blackfire) @@ -1140,6 +1143,34 @@ $I->seeResponseCodeIs(\Codeception\Util\HttpCode::OK); * `param` $code +### seeResponseCodeIsBetween + +Checks that response code is between a certain range. Between actually means [from <= CODE <= to] + + * `param` $from + * `param` $to + + +### seeResponseCodeIsClientError + +Checks that the response code is 4xx + + +### seeResponseCodeIsRedirection + +Checks that the response code 3xx + + +### seeResponseCodeIsServerError + +Checks that the response code is 5xx + + +### seeResponseCodeIsSuccessful + +Checks that the response code 2xx + + ### selectOption Selects an option in a select tag or in radio button group. diff --git a/docs/modules/WebDriver.md b/docs/modules/WebDriver.md index 3cc1cd8279..de64f181df 100644 --- a/docs/modules/WebDriver.md +++ b/docs/modules/WebDriver.md @@ -652,6 +652,15 @@ Print out latest Selenium Logs in debug mode * `param TestInterface` $test +### deleteSessionSnapshot + +Deletes session snapshot. + +See [saveSessionSnapshot](#saveSessionSnapshot) + + * `param` $name + + ### dontSee Checks that the current page doesn't contain the text specified (case insensitive). @@ -936,9 +945,9 @@ A callback should be executed by JavaScript to exit from a script. Callback is passed as a last element in `arguments` array. Additional arguments can be passed as array in second parameter. -``` php +```js // wait for 1200 milliseconds my running `setTimeout` -$I->executeAsyncJS('setTimeout(arguments[0], 1200)'); +* $I->executeAsyncJS('setTimeout(arguments[0], 1200)'); $seconds = 1200; // or seconds are passed as argument $I->executeAsyncJS('setTimeout(arguments[1], arguments[0])', [$seconds]); @@ -1116,8 +1125,12 @@ $name = $I->grabValueFrom(['name' => 'username']); ### loadSessionSnapshot - * `param string` $name - * `return` bool +Loads cookies from a saved snapshot. +Allows to reuse same session across tests without additional login. + +See [saveSessionSnapshot](#saveSessionSnapshot) + + * `param` $name ### makeScreenshot @@ -1297,7 +1310,33 @@ $I->resizeWindow(800, 600); ### saveSessionSnapshot - * `param string` $name +Saves current cookies into named snapshot in order to restore them in other tests +This is useful to save session state between tests. +For example, if user needs log in to site for each test this scenario can be executed once +while other tests can just restore saved cookies. + +``` php +loadSessionSnapshot('login')) return; + + // logging in + $I->amOnPage('/login'); + $I->fillField('name', 'jon'); + $I->fillField('password', '123345'); + $I->click('Login'); + + // saving snapshot + $I->saveSessionSnapshot('login'); +} +?> +``` + + * `param` $name ### scrollTo diff --git a/docs/modules/Yii1.md b/docs/modules/Yii1.md index dae9e37d11..3112f39876 100644 --- a/docs/modules/Yii1.md +++ b/docs/modules/Yii1.md @@ -1048,6 +1048,34 @@ $I->seeResponseCodeIs(\Codeception\Util\HttpCode::OK); * `param` $code +### seeResponseCodeIsBetween + +Checks that response code is between a certain range. Between actually means [from <= CODE <= to] + + * `param` $from + * `param` $to + + +### seeResponseCodeIsClientError + +Checks that the response code is 4xx + + +### seeResponseCodeIsRedirection + +Checks that the response code 3xx + + +### seeResponseCodeIsServerError + +Checks that the response code is 5xx + + +### seeResponseCodeIsSuccessful + +Checks that the response code 2xx + + ### selectOption Selects an option in a select tag or in radio button group. diff --git a/docs/modules/Yii2.md b/docs/modules/Yii2.md index e95817f354..de4a150a18 100644 --- a/docs/modules/Yii2.md +++ b/docs/modules/Yii2.md @@ -6,6 +6,7 @@ It initializes Yii framework in test environment and provides actions for functi ## Application state during testing This section details what you can expect when using this module. * You will get a fresh application in `\Yii::$app` at the start of each test (available in the test and in `_before()`). +* Inside your test you may change application state; however these changes will be lost when doing a request if you have enabled `recreateApplication`. * When executing a request via one of the request functions the `request` and `response` component are both recreated. * After a request the whole application is available for inspection / interaction. * You may use multiple database connections, each will use a separate transaction; to prevent accidental mistakes we @@ -20,15 +21,22 @@ will warn you if you try to connect to the same database twice but we cannot reu * `cleanup` - (default: true) cleanup fixtures after the test * `ignoreCollidingDSN` - (default: false) When 2 database connections use the same DSN but different settings an exception will be thrown, set this to true to disable this behavior. * `fixturesMethod` - (default: _fixtures) Name of the method used for creating fixtures. - +* `responseCleanMethod` - (default: clear) Method for cleaning the response object. Note that this is only for multiple requests inside a single test case. +Between test casesthe whole application is always recreated +* `requestCleanMethod` - (default: recreate) Method for cleaning the request object. Note that this is only for multiple requests inside a single test case. +Between test cases the whole application is always recreated +* `recreateComponents` - (default: []) Some components change their state making them unsuitable for processing multiple requests. In production this is usually +not a problem since web apps tend to die and start over after each request. This allows you to list application components that need to be recreated before each request. +As a consequence, any components specified here should not be changed inside a test since those changes will get regarded. +You can use this module by setting params in your functional.suite.yml: +* `recreateApplication` - (default: false) whether to recreate the whole application before each request You can use this module by setting params in your functional.suite.yml: - ```yaml actor: FunctionalTester modules: enabled: - Yii2: - configFile: '/path/to/config.php' + configFile: 'path/to/config.php' ``` ### Parts @@ -353,6 +361,10 @@ $I->click(['link' => 'Login']); * `param` $context +### connectionOpenHandler +__not documented__ + + ### createAndSetCsrfCookie This function creates the CSRF Cookie. @@ -1287,6 +1299,34 @@ $I->seeResponseCodeIs(\Codeception\Util\HttpCode::OK); * `param` $code +### seeResponseCodeIsBetween + +Checks that response code is between a certain range. Between actually means [from <= CODE <= to] + + * `param` $from + * `param` $to + + +### seeResponseCodeIsClientError + +Checks that the response code is 4xx + + +### seeResponseCodeIsRedirection + +Checks that the response code 3xx + + +### seeResponseCodeIsServerError + +Checks that the response code is 5xx + + +### seeResponseCodeIsSuccessful + +Checks that the response code 2xx + + ### selectOption Selects an option in a select tag or in radio button group. diff --git a/docs/modules/ZF1.md b/docs/modules/ZF1.md index 6a901dfabd..cefb62e2df 100644 --- a/docs/modules/ZF1.md +++ b/docs/modules/ZF1.md @@ -1020,6 +1020,34 @@ $I->seeResponseCodeIs(\Codeception\Util\HttpCode::OK); * `param` $code +### seeResponseCodeIsBetween + +Checks that response code is between a certain range. Between actually means [from <= CODE <= to] + + * `param` $from + * `param` $to + + +### seeResponseCodeIsClientError + +Checks that the response code is 4xx + + +### seeResponseCodeIsRedirection + +Checks that the response code 3xx + + +### seeResponseCodeIsServerError + +Checks that the response code is 5xx + + +### seeResponseCodeIsSuccessful + +Checks that the response code 2xx + + ### selectOption Selects an option in a select tag or in radio button group. diff --git a/docs/modules/ZF2.md b/docs/modules/ZF2.md index 263c422a75..edc01c6a4b 100644 --- a/docs/modules/ZF2.md +++ b/docs/modules/ZF2.md @@ -1029,6 +1029,34 @@ $I->seeResponseCodeIs(\Codeception\Util\HttpCode::OK); * `param` $code +### seeResponseCodeIsBetween + +Checks that response code is between a certain range. Between actually means [from <= CODE <= to] + + * `param` $from + * `param` $to + + +### seeResponseCodeIsClientError + +Checks that the response code is 4xx + + +### seeResponseCodeIsRedirection + +Checks that the response code 3xx + + +### seeResponseCodeIsServerError + +Checks that the response code is 5xx + + +### seeResponseCodeIsSuccessful + +Checks that the response code 2xx + + ### selectOption Selects an option in a select tag or in radio button group. diff --git a/docs/modules/ZendExpressive.md b/docs/modules/ZendExpressive.md index f0e265a9a8..04b032af71 100644 --- a/docs/modules/ZendExpressive.md +++ b/docs/modules/ZendExpressive.md @@ -955,6 +955,34 @@ $I->seeResponseCodeIs(\Codeception\Util\HttpCode::OK); * `param` $code +### seeResponseCodeIsBetween + +Checks that response code is between a certain range. Between actually means [from <= CODE <= to] + + * `param` $from + * `param` $to + + +### seeResponseCodeIsClientError + +Checks that the response code is 4xx + + +### seeResponseCodeIsRedirection + +Checks that the response code 3xx + + +### seeResponseCodeIsServerError + +Checks that the response code is 5xx + + +### seeResponseCodeIsSuccessful + +Checks that the response code 2xx + + ### selectOption Selects an option in a select tag or in radio button group. diff --git a/docs/reference/Locator.md b/docs/reference/Locator.md index 239dc8697a..ae78463fa6 100644 --- a/docs/reference/Locator.md +++ b/docs/reference/Locator.md @@ -165,9 +165,9 @@ Checks that provided string is CSS selector ```php true -Locator::isCSS('body'); // => true -Locator::isCSS('//body/p/user'); // => false +Locator::isCSS('#user .hello') => true +Locator::isCSS('body') => true +Locator::isCSS('//body/p/user') => false ``` * `param` $selector @@ -183,9 +183,9 @@ Checks that a string is valid CSS class ```php true -Locator::isClass('body'); // => false -Locator::isClass('//body/p/user'); // => false +Locator::isClass('.hello') => true +Locator::isClass('body') => false +Locator::isClass('//body/p/user') => false ``` * `param` $class @@ -201,9 +201,9 @@ Checks that a string is valid CSS ID ```php true -Locator::isID('body'); // => false -Locator::isID('//body/p/user'); // => false +Locator::isID('#user') => true +Locator::isID('body') => false +Locator::isID('//body/p/user') => false ``` * `param` $id @@ -228,9 +228,9 @@ Checks that locator is an XPath ```php false -Locator::isXPath('body'); // => false -Locator::isXPath('//body/p/user'); // => true +Locator::isXPath('#user .hello') => false +Locator::isXPath('body') => false +Locator::isXPath('//body/p/user') => true ``` * `param` $locator diff --git a/docs/reference/Mock.md b/docs/reference/Mock.md index 8066190e98..20b859e31f 100644 --- a/docs/reference/Mock.md +++ b/docs/reference/Mock.md @@ -24,8 +24,8 @@ $this->make(new User, ['name' => 'davert']); ?> ``` -To replace method provide its name as a key in second parameter -and its return value or callback function as parameter +To replace method provide it's name as a key in second parameter +and it's return value or callback function as parameter ``` php make( 'User', - array ( + array( 'getName' => Expected::atLeastOnce('Davert')), 'someMethod' => function() {} ) @@ -353,7 +353,7 @@ Alternatively, a function can be passed as parameter: ```php users ->attr('empty','false') ->items ->item - ->val('useful item') + ->val('useful item'); ->parents('user') ->active ->val(1); diff --git a/src/Codeception/Codecept.php b/src/Codeception/Codecept.php index c144ddb1de..158096ed0b 100644 --- a/src/Codeception/Codecept.php +++ b/src/Codeception/Codecept.php @@ -7,7 +7,7 @@ class Codecept { - const VERSION = "2.4.2"; + const VERSION = "2.4.3"; /** * @var \Codeception\PHPUnit\Runner diff --git a/tests/data/claypit/composer.lock b/tests/data/claypit/composer.lock index 8d03452074..c1bef1de0a 100644 --- a/tests/data/claypit/composer.lock +++ b/tests/data/claypit/composer.lock @@ -14,12 +14,12 @@ "source": { "type": "git", "url": "https://github.com/Codeception/c3.git", - "reference": "c7348bbc82da82834fe237c5fb754003ac0fe782" + "reference": "f7e31fce8a9abf1021990b4e31a7ed01689f4295" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Codeception/c3/zipball/c7348bbc82da82834fe237c5fb754003ac0fe782", - "reference": "c7348bbc82da82834fe237c5fb754003ac0fe782", + "url": "https://api.github.com/repos/Codeception/c3/zipball/f7e31fce8a9abf1021990b4e31a7ed01689f4295", + "reference": "f7e31fce8a9abf1021990b4e31a7ed01689f4295", "shasum": "" }, "require": { @@ -56,7 +56,7 @@ "code coverage", "codecoverage" ], - "time": "2018-02-19 11:27:45" + "time": "2018-05-26 21:53:33" } ], "aliases": [], From c04934dff6ffdf718a1bebe3345c3170cbe1b841 Mon Sep 17 00:00:00 2001 From: Sam Date: Thu, 28 Jun 2018 17:04:49 +0200 Subject: [PATCH 067/395] =?UTF-8?q?Unbind=20specific=20event=20handler=20i?= =?UTF-8?q?nstead=20of=20all=20class=20level=20events=20when=20=E2=80=A6?= =?UTF-8?q?=20(#5045)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Unbind specific event handler instead of all class level events when loading fixtures * Refactored connecition / transaction watching to separate classes. * Fixed Nitpick-CI * Use the connection watcher for closing fixture connections as well. * Prevent crash in case database connection for a transaction is closed --- .../Lib/Connector/Yii2/ConnectionWatcher.php | 67 ++++++++++ .../Lib/Connector/Yii2/TransactionForcer.php | 97 +++++++++++++++ src/Codeception/Module/Yii2.php | 116 ++++-------------- 3 files changed, 191 insertions(+), 89 deletions(-) create mode 100644 src/Codeception/Lib/Connector/Yii2/ConnectionWatcher.php create mode 100644 src/Codeception/Lib/Connector/Yii2/TransactionForcer.php diff --git a/src/Codeception/Lib/Connector/Yii2/ConnectionWatcher.php b/src/Codeception/Lib/Connector/Yii2/ConnectionWatcher.php new file mode 100644 index 0000000000..eae5382bc1 --- /dev/null +++ b/src/Codeception/Lib/Connector/Yii2/ConnectionWatcher.php @@ -0,0 +1,67 @@ +handler = function (Event $event) { + if ($event->sender instanceof Connection) { + $this->connectionOpened($event->sender); + } + }; + } + + protected function connectionOpened(Connection $connection) + { + $this->debug('Connection opened!'); + if ($connection instanceof Connection) { + $this->connections[] = $connection; + } + } + + public function start() + { + Event::on(Connection::class, Connection::EVENT_AFTER_OPEN, $this->handler); + $this->debug('watching new connections'); + } + + public function stop() + { + Event::off(Connection::class, Connection::EVENT_AFTER_OPEN, $this->handler); + $this->debug('no longer watching new connections'); + } + + public function closeAll() + { + $count = count($this->connections); + $this->debug("closing all ($count) connections"); + foreach ($this->connections as $connection) { + $connection->close(); + } + } + + protected function debug($message) + { + $title = (new \ReflectionClass($this))->getShortName(); + if (is_array($message) or is_object($message)) { + $message = stripslashes(json_encode($message)); + } + codecept_debug("[$title] $message"); + } +} diff --git a/src/Codeception/Lib/Connector/Yii2/TransactionForcer.php b/src/Codeception/Lib/Connector/Yii2/TransactionForcer.php new file mode 100644 index 0000000000..060b8a13f2 --- /dev/null +++ b/src/Codeception/Lib/Connector/Yii2/TransactionForcer.php @@ -0,0 +1,97 @@ +ignoreCollidingDSN = $ignoreCollidingDSN; + } + + + protected function connectionOpened(Connection $connection) + { + parent::connectionOpened($connection); + /** + * We should check if the known PDO objects are the same, in which case we should reuse the PDO + * object so only 1 transaction is started and multiple connections to the same database see the + * same data (due to writes inside a transaction not being visible from the outside). + * + */ + $key = md5(json_encode([ + 'dsn' => $connection->dsn, + 'user' => $connection->username, + 'pass' => $connection->password, + 'attributes' => $connection->attributes, + 'emulatePrepare' => $connection->emulatePrepare, + 'charset' => $connection->charset + ])); + + /* + * If keys match we assume connections are "similar enough". + */ + if (isset($this->pdoCache[$key])) { + $connection->pdo = $this->pdoCache[$key]; + } else { + $this->pdoCache[$key] = $connection->pdo; + } + + if (isset($this->dsnCache[$connection->dsn]) + && $this->dsnCache[$connection->dsn] !== $key + && !$this->ignoreCollidingDSN + ) { + $this->debug(<<dsn}) with different configuration. +These connections will not see the same database state since we cannot share a transaction between different PDO +instances. +You can remove this message by adding 'ignoreCollidingDSN = true' in the module configuration. +TEXT + ); + Debug::pause(); + } + + if (isset($this->transactions[$key])) { + $this->debug('Reusing PDO, so no need for a new transaction'); + return; + } + + $this->debug('Transaction started for: ' . $connection->dsn); + $this->transactions[$key] = $connection->beginTransaction(); + } + + public function rollbackAll() + { + /** @var Transaction $transaction */ + foreach ($this->transactions as $transaction) { + if ($transaction->db->isActive) { + $transaction->rollBack(); + $this->debug('Transaction cancelled; all changes reverted.'); + } + } + + $this->transactions = []; + $this->pdoCache = []; + $this->dsnCache = []; + } +} diff --git a/src/Codeception/Module/Yii2.php b/src/Codeception/Module/Yii2.php index 213e2b8983..b4826cc435 100644 --- a/src/Codeception/Module/Yii2.php +++ b/src/Codeception/Module/Yii2.php @@ -167,22 +167,21 @@ class Yii2 extends Framework implements ActiveRecord, PartedModule protected $requiredFields = ['configFile']; /** - * @var array Array of Transaction objects indexed by a string key - */ - private $transactions = []; - /** - * @var \PDO[] Array of PDO objects indexed by a string key + * @var Yii2Connector\FixturesStore[] */ - private $pdoCache = []; + public $loadedFixtures = []; + /** - * @var string[] Array of cache keys indexes by their DSN + * Helper to manage database connections + * @var Yii2Connector\ConnectionWatcher */ - private $dsnCache = []; + private $connectionWatcher; /** - * @var Yii2Connector\FixturesStore[] + * Helper to force database transaction + * @var Yii2Connector\TransactionForcer */ - public $loadedFixtures = []; + private $transactionForcer; /** * @var array The contents of $_SERVER upon initialization of this object. @@ -299,6 +298,9 @@ public function _before(TestInterface $test) $this->recreateClient(); $this->client->startApp(); + $this->connectionWatcher = new Yii2Connector\ConnectionWatcher(); + $this->connectionWatcher->start(); + // load fixtures before db transaction if ($test instanceof \Codeception\Test\Cest) { $this->loadFixtures($test->getTestClass()); @@ -306,6 +308,7 @@ public function _before(TestInterface $test) $this->loadFixtures($test); } + $this->startTransactions(); } @@ -317,24 +320,14 @@ public function _before(TestInterface $test) private function loadFixtures($test) { $this->debugSection('Fixtures', 'Loading fixtures'); - /** @var Connection[] $connections */ - $connections = []; - // Register event handler. - Event::on(Connection::class, Connection::EVENT_AFTER_OPEN, function (Event $event) use (&$connections) { - $this->debugSection('Fixtures', 'Opened database connection: ' . $event->sender->dsn); - $connections[] = $event->sender; - }); if (empty($this->loadedFixtures) && method_exists($test, $this->_getConfig('fixturesMethod')) ) { + $connectionWatcher = new Yii2Connector\ConnectionWatcher(); + $connectionWatcher->start(); $this->haveFixtures(call_user_func([$test, $this->_getConfig('fixturesMethod')])); - } - - Event::offAll(); - // Close all connections so they get properly reopened after the transaction handler has been attached. - foreach ($connections as $connection) { - $this->debugSection('Fixtures', 'Closing database connection: ' . $connection->dsn); - $connection->close(); + $connectionWatcher->stop(); + $connectionWatcher->closeAll(); } $this->debugSection('Fixtures', 'Done'); } @@ -350,6 +343,10 @@ public function _after(TestInterface $test) $this->rollbackTransactions(); + $this->connectionWatcher->stop(); + $this->connectionWatcher->closeAll(); + unset($this->connectionWatcher); + if ($this->config['cleanup']) { foreach ($this->loadedFixtures as $fixture) { $fixture->unloadFixtures(); @@ -365,80 +362,21 @@ public function _after(TestInterface $test) parent::_after($test); } - public function connectionOpenHandler(Event $event) - { - if ($event->sender instanceof Connection) { - $connection = $event->sender; - /* - * We should check if the known PDO objects are the same, in which case we should reuse the PDO - * object so only 1 transaction is started and multiple connections to the same database see the - * same data (due to writes inside a transaction not being visible from the outside). - * - */ - $key = md5(json_encode([ - 'dsn' => $connection->dsn, - 'user' => $connection->username, - 'pass' => $connection->password, - 'attributes' => $connection->attributes, - 'emulatePrepare' => $connection->emulatePrepare, - 'charset' => $connection->charset - ])); - - /* - * If keys match we assume connections are "similar enough". - */ - if (isset($this->pdoCache[$key])) { - $connection->pdo = $this->pdoCache[$key]; - } else { - $this->pdoCache[$key] = $connection->pdo; - } - - if (isset($this->dsnCache[$connection->dsn]) - && $this->dsnCache[$connection->dsn] !== $key - && !$this->config['ignoreCollidingDSN'] - ) { - $this->debugSection('WARNING', <<dsn}) with different configuration. -These connections will not see the same database state since we cannot share a transaction between different PDO -instances. -You can remove this message by adding 'ignoreCollidingDSN = true' in the module configuration. -TEXT - ); - Debug::pause(); - } - - if (isset($this->transactions[$key])) { - $this->debugSection('Database', 'Reusing PDO, so no need for a new transaction'); - return; - } - - $this->debugSection('Database', 'Transaction started for: ' . $connection->dsn); - $this->transactions[$key] = $connection->beginTransaction(); - } - - } - protected function startTransactions() { if ($this->config['transaction']) { - // This should register handlers that start a transaction whenever a connection opens and add it to the transactions array. - $this->debug('Transaction', 'Registering connection event handler'); - Event::on(Connection::class, Connection::EVENT_AFTER_OPEN, [$this, 'connectionOpenHandler']); + $this->transactionForcer = new Yii2Connector\TransactionForcer($this->config['ignoreCollidingDSN']); + $this->transactionForcer->start(); } } protected function rollbackTransactions() { - $this->debugSection('Transaction', 'Rolling back ' . count($this->transactions) . ' transactions'); - Event::off(Connection::class, Connection::EVENT_AFTER_OPEN, [$this, 'connectionOpenHandler']); - /** @var Transaction $transaction */ - foreach ($this->transactions as $transaction) { - $transaction->rollBack(); - $this->debugSection('Database', 'Transaction cancelled; all changes reverted.'); + if (isset($this->transactionForcer)) { + $this->transactionForcer->rollbackAll(); + $this->transactionForcer->stop(); + unset($this->transactionForcer); } - $this->transactions = []; - $this->pdoCache = []; - $this->dsnCache = []; } public function _parts() From 7b9d40c3b5c4197dd64db451f7bf8dcb17db8e2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=9Erw=E1=B4=A7n=20Rich=E1=B4=A7rd?= Date: Mon, 2 Jul 2018 11:44:08 +0000 Subject: [PATCH 068/395] Fix typo (#5052) --- src/Codeception/Module/Doctrine2.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Codeception/Module/Doctrine2.php b/src/Codeception/Module/Doctrine2.php index b60293d13e..479ba625e8 100644 --- a/src/Codeception/Module/Doctrine2.php +++ b/src/Codeception/Module/Doctrine2.php @@ -305,7 +305,7 @@ public function haveFakeRepository($classname, $methods = []) /** * Persists record into repository. - * This method crates an entity, and sets its properties directly (via reflection). + * This method creates an entity, and sets its properties directly (via reflection). * Setters of entity won't be executed, but you can create almost any entity and save it to database. * Returns id using `getId` of newly created entity. * From ce7d225b2df3569d312a7cd248dbefedd99c9003 Mon Sep 17 00:00:00 2001 From: Aleksandr Date: Thu, 5 Jul 2018 11:19:26 +0300 Subject: [PATCH 069/395] Typo fix (#5057) [skip ci] --- docs/02-GettingStarted.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/02-GettingStarted.md b/docs/02-GettingStarted.md index bc3fb3174e..e007d484f7 100644 --- a/docs/02-GettingStarted.md +++ b/docs/02-GettingStarted.md @@ -14,16 +14,16 @@ Codeception follows simple naming rules to make it easy to remember (as well as click('Login'); $I->fillField('#input-username', 'John Dough'); - $i->pressKey('#input-remarks', 'foo'); + $I->pressKey('#input-remarks', 'foo'); ``` * **Assertions** always start with "see" or "dontSee". Examples: ```php see('Welcome'); $I->seeInTitle('My Company'); - $i->seeElement('nav'); - $i->dontSeeElement('#error-message'); - $i->dontSeeInPageSource('
'); + $I->seeElement('nav'); + $I->dontSeeElement('#error-message'); + $I->dontSeeInPageSource('
'); ``` * **Grabbers** just *read* something from the page, but don't process it. The return value of those are meant to be saved as variables and used later. Example: ```php From f942fc6ce0f6516e97f80023db76cbbe0053659c Mon Sep 17 00:00:00 2001 From: Aleksandr Date: Fri, 6 Jul 2018 01:44:46 +0300 Subject: [PATCH 070/395] Typo fix in phpdoc (#5060) --- ext/Recorder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/Recorder.php b/ext/Recorder.php index e02945e853..6059bdf630 100644 --- a/ext/Recorder.php +++ b/ext/Recorder.php @@ -39,7 +39,7 @@ * ``` yaml * extensions: * enabled: - * Codeception\Extension\Recorder: + * - Codeception\Extension\Recorder: * module: AngularJS # enable for Angular * delete_successful: false # keep screenshots of successful tests * ``` From 85342fd574660c649ece8a7a54aadfe38d01c880 Mon Sep 17 00:00:00 2001 From: Martin Bohal Date: Fri, 6 Jul 2018 00:50:18 +0200 Subject: [PATCH 071/395] Symfony test email count (#5059) * Improve testing sent emails in Symfony * fixup! Improve testing sent emails in Symfony * fixup! fixup! Improve testing sent emails in Symfony --- src/Codeception/Module/Symfony.php | 46 +++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/src/Codeception/Module/Symfony.php b/src/Codeception/Module/Symfony.php index d9674fbee7..6de5947c73 100644 --- a/src/Codeception/Module/Symfony.php +++ b/src/Codeception/Module/Symfony.php @@ -445,11 +445,18 @@ public function seeInCurrentRoute($routeName) } /** - * Checks if any email were sent by last request + * Checks if the desired number of emails was sent. + * If no argument is provided then at least one email must be sent to satisfy the check. * - * @throws \LogicException + * ``` php + * seeEmailIsSent(2); + * ?> + * ``` + * + * @param null|int $expectedCount */ - public function seeEmailIsSent() + public function seeEmailIsSent($expectedCount = null) { $profile = $this->getProfile(); if (!$profile) { @@ -459,7 +466,38 @@ public function seeEmailIsSent() $this->fail('Emails can\'t be tested without SwiftMailer connector'); } - $this->assertGreaterThan(0, $profile->getCollector('swiftmailer')->getMessageCount()); + if (!is_int($expectedCount) && !is_null($expectedCount)) { + $this->fail(sprintf( + 'The required number of emails must be either an integer or null. "%s" was provided.', + print_r($expectedCount, true) + )); + } + + $realCount = $profile->getCollector('swiftmailer')->getMessageCount(); + if ($expectedCount === null) { + $this->assertGreaterThan(0, $realCount); + } else { + $this->assertEquals( + $expectedCount, + $realCount, + sprintf( + 'Expected number of sent emails was %d, but in reality %d %s sent.', + $expectedCount, + $realCount, + $realCount === 2 ? 'was' : 'were' + ) + ); + } + } + + /** + * Checks that no email was sent. This is an alias for seeEmailIsSent(0). + * + * @part email + */ + public function dontSeeEmailIsSent() + { + $this->seeEmailIsSent(0); } /** From 21fb2ffd1148cd0f761ecd3fe53ad80c361a8999 Mon Sep 17 00:00:00 2001 From: Dmytro Naumenko Date: Tue, 10 Jul 2018 13:20:10 +0300 Subject: [PATCH 072/395] Allow absolute paths in `extends` property of configs (#5061) * Updated Configuration::loadSuiteConfig() to respect absolute paths in `extends` parameter * Allow abspath for `extends` property in Configuration::config() * Added unit tests to confirm config extending works * Updated CHANGELOG * Removed excess changes ConfigurationTest * Fixed comments to PR * minor --- CHANGELOG-2.4.md | 5 ++++ autoload.php | 20 +++++++++++++- src/Codeception/Configuration.php | 7 +++-- tests/cli/ConfigExtendsCest.php | 17 ++++++++++++ .../config_extends/codeception.common.yml | 13 ++++++++++ tests/data/config_extends/codeception.yml | 2 ++ .../config_extends/tests/_output/.gitignore | 2 ++ .../tests/_support/UnitTester.php | 26 +++++++++++++++++++ .../tests/_support/_generated/.gitignore | 2 ++ .../tests/unit.suite.common.yml | 3 +++ .../data/config_extends/tests/unit.suite.yml | 6 +++++ .../config_extends/tests/unit/UnitCest.php | 9 +++++++ tests/unit/Codeception/ConfigurationTest.php | 3 +++ 13 files changed, 112 insertions(+), 3 deletions(-) create mode 100644 tests/cli/ConfigExtendsCest.php create mode 100644 tests/data/config_extends/codeception.common.yml create mode 100644 tests/data/config_extends/codeception.yml create mode 100644 tests/data/config_extends/tests/_output/.gitignore create mode 100644 tests/data/config_extends/tests/_support/UnitTester.php create mode 100644 tests/data/config_extends/tests/_support/_generated/.gitignore create mode 100644 tests/data/config_extends/tests/unit.suite.common.yml create mode 100644 tests/data/config_extends/tests/unit.suite.yml create mode 100644 tests/data/config_extends/tests/unit/UnitCest.php diff --git a/CHANGELOG-2.4.md b/CHANGELOG-2.4.md index cde1c9fe25..60e71a711f 100644 --- a/CHANGELOG-2.4.md +++ b/CHANGELOG-2.4.md @@ -1,3 +1,8 @@ +#### 2.4.4 + +* Recently added `extends` property in the `codeception.yml` and `*.suite.yml` files now support absolute paths; by @silverfire +* Fixed absolute paths handling on Windows in ParamLoader; by @silverfire + #### 2.4.3 * [Create your own test formats](https://codeception.com/docs/07-AdvancedUsage#Formats) (e.g., Cept, Cest, ...); by @mlambley diff --git a/autoload.php b/autoload.php index ee043a39b6..e15b1413c0 100644 --- a/autoload.php +++ b/autoload.php @@ -113,6 +113,24 @@ function codecept_relative_path($path) */ function codecept_absolute_path($path) { - return mb_substr($path, 0, 1) === DIRECTORY_SEPARATOR ? $path : codecept_root_dir($path); + return codecept_is_path_absolute($path) ? $path : codecept_root_dir($path); + } +} + +if (!function_exists('codecept_is_path_absolute')) { + /** + * Check whether the given $path is absolute. + * + * @param string $path + * @return bool + * @since 2.4.4 + */ + function codecept_is_path_absolute($path) + { + if (DIRECTORY_SEPARATOR === '/') { + return mb_substr($path, 0, 1) === DIRECTORY_SEPARATOR; + } + + return preg_match('#^[A-Z]:(?![^/\\])#i', $path) === 1; } } diff --git a/src/Codeception/Configuration.php b/src/Codeception/Configuration.php index 2732d82cf7..92e8061490 100644 --- a/src/Codeception/Configuration.php +++ b/src/Codeception/Configuration.php @@ -186,7 +186,7 @@ public static function config($configFile = null) // we check for the "extends" key in the yml file if (isset($config['extends'])) { // and now we search for the file - $presetFilePath = realpath(self::$dir . DIRECTORY_SEPARATOR . $config['extends']); + $presetFilePath = codecept_absolute_path($config['extends']); if (file_exists($presetFilePath)) { // and merge it with our configuration file $config = self::mergeConfigs(self::getConfFromFile($presetFilePath), $config); @@ -690,7 +690,10 @@ protected static function loadSuiteConfig($suite, $path, $settings) // now we check the suite config file, if a extends key is defined if (isset($suiteConf['extends'])) { - $presetFilePath = realpath($suiteDir . DIRECTORY_SEPARATOR . $suiteConf['extends']); + $presetFilePath = codecept_is_path_absolute($suiteConf['extends']) + ? $suiteConf['extends'] // If path is absolute – use it + : realpath($suiteDir . DIRECTORY_SEPARATOR . $suiteConf['extends']); // Otherwise try to locate it in the suite dir + if (file_exists($presetFilePath)) { $settings = self::mergeConfigs(self::getConfFromFile($presetFilePath), $settings); } diff --git a/tests/cli/ConfigExtendsCest.php b/tests/cli/ConfigExtendsCest.php new file mode 100644 index 0000000000..eef07ce7c3 --- /dev/null +++ b/tests/cli/ConfigExtendsCest.php @@ -0,0 +1,17 @@ +amInPath('tests/data/config_extends'); + $I->executeCommand('run'); + + $I->seeInShellOutput('UnitCest'); + $I->seeInShellOutput('OK (1 test, 1 assertion)'); + $I->dontSeeInShellOutput('Exception'); + } +} diff --git a/tests/data/config_extends/codeception.common.yml b/tests/data/config_extends/codeception.common.yml new file mode 100644 index 0000000000..018c7db57e --- /dev/null +++ b/tests/data/config_extends/codeception.common.yml @@ -0,0 +1,13 @@ +paths: + tests: tests + log: tests/_output + data: tests/_data + support: tests/_support + envs: tests/_envs +settings: + bootstrap: _bootstrap.php + colors: true + memory_limit: 2048M +extensions: + enabled: + - Codeception\Extension\RunFailed diff --git a/tests/data/config_extends/codeception.yml b/tests/data/config_extends/codeception.yml new file mode 100644 index 0000000000..073df879c5 --- /dev/null +++ b/tests/data/config_extends/codeception.yml @@ -0,0 +1,2 @@ +actor: Tester +extends: codeception.common.yml diff --git a/tests/data/config_extends/tests/_output/.gitignore b/tests/data/config_extends/tests/_output/.gitignore new file mode 100644 index 0000000000..c96a04f008 --- /dev/null +++ b/tests/data/config_extends/tests/_output/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore \ No newline at end of file diff --git a/tests/data/config_extends/tests/_support/UnitTester.php b/tests/data/config_extends/tests/_support/UnitTester.php new file mode 100644 index 0000000000..28353572c1 --- /dev/null +++ b/tests/data/config_extends/tests/_support/UnitTester.php @@ -0,0 +1,26 @@ +assertTrue(true); + } +} diff --git a/tests/unit/Codeception/ConfigurationTest.php b/tests/unit/Codeception/ConfigurationTest.php index 45422539a2..a263b6bca1 100644 --- a/tests/unit/Codeception/ConfigurationTest.php +++ b/tests/unit/Codeception/ConfigurationTest.php @@ -65,5 +65,8 @@ public function testDefaultCustomCommandConfig() $commandsConfig = $defaultConfig['extensions']; $this->assertArrayHasKey('commands', $commandsConfig); + + $this->assertArrayHasKey('extends', $defaultConfig); + $this->assertNull($defaultConfig['extends']); } } From 37fb9c6a6a2215f2826933f92bd9b42d7c7f0ac8 Mon Sep 17 00:00:00 2001 From: Johannes Schobel Date: Tue, 10 Jul 2018 14:02:20 +0200 Subject: [PATCH 073/395] [WIP] Start using assert() and not fail() (#5063) * start using assert() and not fail() * style --- src/Codeception/Module/Laravel5.php | 55 +++++++++++++++-------------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/src/Codeception/Module/Laravel5.php b/src/Codeception/Module/Laravel5.php index 54357d3cb8..ab3663a6c1 100644 --- a/src/Codeception/Module/Laravel5.php +++ b/src/Codeception/Module/Laravel5.php @@ -247,7 +247,7 @@ protected function checkBootstrapFileExists() throw new ModuleConfigException( $this, "Laravel bootstrap file not found in $bootstrapFile.\n" - . "Please provide a valid path to it using 'bootstrap' config param. " + . "Please provide a valid path by using the 'bootstrap' config param. " ); } } @@ -442,7 +442,6 @@ public function callArtisan($command, $parameters = [], OutputInterface $output } $console->call($command, $parameters, $output); - } /** @@ -659,14 +658,13 @@ public function seeSessionHasValues(array $bindings) * ?> * ``` * - * @return bool + * @return void */ public function seeFormHasErrors() { $viewErrorBag = $this->app->make('view')->shared('errors'); - if (count($viewErrorBag) == 0) { - $this->fail("There are no form errors"); - } + + $this->assertGreaterThan(0, count($viewErrorBag), 'Expecting that the form has errors, but there were none!'); } /** @@ -678,14 +676,13 @@ public function seeFormHasErrors() * ?> * ``` * - * @return bool + * @return void */ public function dontSeeFormErrors() { $viewErrorBag = $this->app->make('view')->shared('errors'); - if (count($viewErrorBag) > 0) { - $this->fail("Found the following form errors: \n\n" . $viewErrorBag->toJson(JSON_PRETTY_PRINT)); - } + + $this->assertEquals(0, count($viewErrorBag), 'Expecting that the form does not have errors, but there were!'); } /** @@ -778,9 +775,7 @@ public function amLoggedAs($user, $driver = null) return; } - if (! $guard->attempt($user)) { - $this->fail("Failed to login with credentials " . json_encode($user)); - } + $this->assertTrue($guard->attempt($user), 'Failed to login with credentials ' . json_encode($user)); } /** @@ -804,9 +799,7 @@ public function seeAuthentication($guard = null) $auth = $auth->guard($guard); } - if (! $auth->check()) { - $this->fail("There is no authenticated user"); - } + $this->assertTrue($auth->check(), 'There is no authenticated user'); } /** @@ -822,9 +815,7 @@ public function dontSeeAuthentication($guard = null) $auth = $auth->guard($guard); } - if ($auth->check()) { - $this->fail("There is an authenticated user"); - } + $this->assertNotTrue($auth->check(), 'There is an user authenticated'); } /** @@ -868,8 +859,9 @@ public function grabService($class) * ``` * * @param string $table - * @param array $attributes - * @return integer|EloquentModel + * @param array $attributes + * @return EloquentModel|int + * @throws \RuntimeException * @part orm */ public function haveRecord($table, $attributes = []) @@ -917,6 +909,8 @@ public function seeRecord($table, $attributes = []) } elseif (! $this->findRecord($table, $attributes)) { $this->fail("Could not find matching record in table '$table'"); } + + $this->assertTrue(true); } /** @@ -943,6 +937,8 @@ public function dontSeeRecord($table, $attributes = []) } elseif ($this->findRecord($table, $attributes)) { $this->fail("Unexpectedly found matching record in table '$table'"); } + + $this->assertTrue(true); } /** @@ -999,14 +995,18 @@ public function seeNumRecords($expectedNum, $table, $attributes = []) { if (class_exists($table)) { $currentNum = $this->countModels($table, $attributes); - if ($currentNum != $expectedNum) { - $this->fail("The number of found $table ($currentNum) does not match expected number $expectedNum with " . json_encode($attributes)); - } + $this->assertEquals( + $expectedNum, + $currentNum, + "The number of found {$table} ({$currentNum}) does not match expected number {$expectedNum} with " . json_encode($attributes) + ); } else { $currentNum = $this->countRecords($table, $attributes); - if ($currentNum != $expectedNum) { - $this->fail("The number of found records ($currentNum) does not match expected number $expectedNum in table $table with " . json_encode($attributes)); - } + $this->assertEquals( + $expectedNum, + $currentNum, + "The number of found records in table {$table} ({$currentNum}) does not match expected number $expectedNum with " . json_encode($attributes) + ); } } @@ -1096,6 +1096,7 @@ protected function countRecords($table, $attributes = []) * @param string $modelClass * * @return EloquentModel + * @throws \RuntimeException */ protected function getQueryBuilderFromModel($modelClass) { From 51b8cba4be0589e632aaf3ea01d7e1e9a4594858 Mon Sep 17 00:00:00 2001 From: Patrik Foldes Date: Tue, 10 Jul 2018 15:02:53 +0300 Subject: [PATCH 074/395] Added new option to Recorder extension to disable recording of specified steps (#5015) * Added new option to Recorder extension to disable recording of specified steps * Added wildcard support to ignore_steps configuration option of the Recorder extension --- ext/Recorder.php | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/ext/Recorder.php b/ext/Recorder.php index 6059bdf630..e87f81a942 100644 --- a/ext/Recorder.php +++ b/ext/Recorder.php @@ -7,6 +7,7 @@ use Codeception\Exception\ExtensionException; use Codeception\Lib\Interfaces\ScreenshotSaver; use Codeception\Module\WebDriver; +use Codeception\Step; use Codeception\Step\Comment as CommentStep; use Codeception\Test\Descriptor; use Codeception\Util\FileSystem; @@ -32,6 +33,7 @@ * * * `delete_successful` (default: true) - delete screenshots for successfully passed tests (i.e. log only failed and errored tests). * * `module` (default: WebDriver) - which module for screenshots to use. Set `AngularJS` if you want to use it with AngularJS module. Generally, the module should implement `Codeception\Lib\Interfaces\ScreenshotSaver` interface. + * * `ignore_steps` (default: []) - array of step names that should not be recorded, * wildcards supported * * * #### Examples: @@ -42,6 +44,7 @@ * - Codeception\Extension\Recorder: * module: AngularJS # enable for Angular * delete_successful: false # keep screenshots of successful tests + * ignore_steps: [have, grab*] * ``` * */ @@ -51,7 +54,8 @@ class Recorder extends \Codeception\Extension 'delete_successful' => true, 'module' => 'WebDriver', 'template' => null, - 'animate_slides' => true + 'animate_slides' => true, + 'ignore_steps' => [] ]; protected $template = <<getStep() instanceof CommentStep) { return; } + if ($this->isStepIgnored($e->getStep())) { + return; + } $filename = str_pad($this->stepNum, 3, "0", STR_PAD_LEFT) . '.png'; $this->webDriverModule->_saveScreenshot($this->dir . DIRECTORY_SEPARATOR . $filename); $this->stepNum++; $this->slides[$filename] = $e->getStep(); } + + /** + * @param Step $step + * @return bool + */ + protected function isStepIgnored($step) + { + foreach ($this->config['ignore_steps'] as $stepPattern) { + $stepRegexp = '/^' . str_replace('*', '.*?', $stepPattern) . '$/i'; + if (preg_match($stepRegexp, $step->getAction())) { + return true; + } + } + + return false; + } } From 392b7e4528a805ca4591bd98936b311527c495f2 Mon Sep 17 00:00:00 2001 From: Michael Bodnarchuk Date: Wed, 11 Jul 2018 17:49:10 +0300 Subject: [PATCH 075/395] Fixed "No Session Timeout" fatal error in WebDriver (#5070) --- src/Codeception/Module/WebDriver.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Codeception/Module/WebDriver.php b/src/Codeception/Module/WebDriver.php index 0848e1755e..0bb4274899 100644 --- a/src/Codeception/Module/WebDriver.php +++ b/src/Codeception/Module/WebDriver.php @@ -507,7 +507,12 @@ public function _after(TestInterface $test) return; } if ($this->config['clear_cookies'] && isset($this->webDriver)) { - $this->webDriver->manage()->deleteAllCookies(); + try { + $this->webDriver->manage()->deleteAllCookies(); + } catch (\Exception $e) { + // may cause fatal errors when not handled + $this->debug("Error, can't clean cookies after a test: " . $e->getMessage()); + } } } From 888b6a6d6ef37a4433849a1e60bc70efcfc1cd74 Mon Sep 17 00:00:00 2001 From: Chuck Burgess Date: Wed, 11 Jul 2018 09:49:29 -0500 Subject: [PATCH 076/395] add config option for session lock wait setting (and Oracle implementation); (#5069) --- docs/modules/Db.md | 2 ++ src/Codeception/Lib/Driver/Db.php | 11 ++++++++++- src/Codeception/Lib/Driver/Oci.php | 4 ++++ src/Codeception/Module/Db.php | 18 +++++++++++++----- 4 files changed, 29 insertions(+), 6 deletions(-) diff --git a/docs/modules/Db.md b/docs/modules/Db.md index 73d9356274..611f920a77 100644 --- a/docs/modules/Db.md +++ b/docs/modules/Db.md @@ -35,6 +35,7 @@ if you run into problems loading dumps and cleaning databases. * populate: false - whether the the dump should be loaded before the test suite is started * cleanup: false - whether the dump should be reloaded before each test * reconnect: false - whether the module should reconnect to the database before each test +* waitlock: 0 - wait lock (in seconds) that the database session should use for DDL statements * ssl_key - path to the SSL key (MySQL specific, @see http://php.net/manual/de/ref.pdo-mysql.php#pdo.constants.mysql-attr-key) * ssl_cert - path to the SSL certificate (MySQL specific, @see http://php.net/manual/de/ref.pdo-mysql.php#pdo.constants.mysql-attr-ssl-cert) * ssl_ca - path to the SSL certificate authority (MySQL specific, @see http://php.net/manual/de/ref.pdo-mysql.php#pdo.constants.mysql-attr-ssl-ca) @@ -51,6 +52,7 @@ if you run into problems loading dumps and cleaning databases. populate: true cleanup: true reconnect: true + waitlock: 10 ssl_key: '/path/to/client-key.pem' ssl_cert: '/path/to/client-cert.pem' ssl_ca: '/path/to/ca-cert.pem' diff --git a/src/Codeception/Lib/Driver/Db.php b/src/Codeception/Lib/Driver/Db.php index 601b81bbf1..2c3fd1a2ab 100755 --- a/src/Codeception/Lib/Driver/Db.php +++ b/src/Codeception/Lib/Driver/Db.php @@ -121,6 +121,15 @@ public function cleanup() { } + /** + * Set the lock waiting interval for the database session + * @param int $seconds + * @return void + */ + public function setWaitLock($seconds) + { + } + public function load($sql) { $query = ''; @@ -224,7 +233,7 @@ protected function generateWhereClause(array &$criteria) return 'WHERE ' . implode('AND ', $params); } - + /** * @deprecated use deleteQueryByCriteria instead */ diff --git a/src/Codeception/Lib/Driver/Oci.php b/src/Codeception/Lib/Driver/Oci.php index 07b638e943..d75f8d497c 100644 --- a/src/Codeception/Lib/Driver/Oci.php +++ b/src/Codeception/Lib/Driver/Oci.php @@ -3,6 +3,10 @@ class Oci extends Db { + public function setWaitLock($seconds) + { + $this->dbh->exec('ALTER SESSION SET ddl_lock_timeout = ' . (int) $seconds); + } public function cleanup() { diff --git a/src/Codeception/Module/Db.php b/src/Codeception/Module/Db.php index 2e372a8f44..3f7150e61a 100644 --- a/src/Codeception/Module/Db.php +++ b/src/Codeception/Module/Db.php @@ -45,6 +45,7 @@ * * populate: false - whether the the dump should be loaded before the test suite is started * * cleanup: false - whether the dump should be reloaded before each test * * reconnect: false - whether the module should reconnect to the database before each test + * * waitlock: 0 - wait lock (in seconds) that the database session should use for DDL statements * * ssl_key - path to the SSL key (MySQL specific, @see http://php.net/manual/de/ref.pdo-mysql.php#pdo.constants.mysql-attr-key) * * ssl_cert - path to the SSL certificate (MySQL specific, @see http://php.net/manual/de/ref.pdo-mysql.php#pdo.constants.mysql-attr-ssl-cert) * * ssl_ca - path to the SSL certificate authority (MySQL specific, @see http://php.net/manual/de/ref.pdo-mysql.php#pdo.constants.mysql-attr-ssl-ca) @@ -61,6 +62,7 @@ * populate: true * cleanup: true * reconnect: true + * waitlock: 10 * ssl_key: '/path/to/client-key.pem' * ssl_cert: '/path/to/client-cert.pem' * ssl_ca: '/path/to/ca-cert.pem' @@ -201,6 +203,7 @@ class Db extends CodeceptionModule implements DbInterface 'populate' => false, 'cleanup' => false, 'reconnect' => false, + 'waitlock' => 0, 'dump' => null, 'populator' => null, ]; @@ -279,7 +282,7 @@ private function readSql() private function connect() { $options = []; - + /** * @see http://php.net/manual/en/pdo.construct.php * @see http://php.net/manual/de/ref.pdo-mysql.php#pdo-mysql.constants @@ -287,11 +290,11 @@ private function connect() if (array_key_exists('ssl_key', $this->config) && !empty($this->config['ssl_key'])) { $options[\PDO::MYSQL_ATTR_SSL_KEY] = $this->config['ssl_key']; } - + if (array_key_exists('ssl_cert', $this->config) && !empty($this->config['ssl_cert'])) { $options[\PDO::MYSQL_ATTR_SSL_CERT] = $this->config['ssl_cert']; } - + if (array_key_exists('ssl_ca', $this->config) && !empty($this->config['ssl_ca'])) { $options[\PDO::MYSQL_ATTR_SSL_CA] = $this->config['ssl_ca']; } @@ -307,6 +310,11 @@ private function connect() throw new ModuleException(__CLASS__, $message . ' while creating PDO connection'); } + + if ($this->config['waitlock']) { + $this->driver->setWaitLock($this->config['waitlock']); + } + $this->debugSection('Db', 'Connected to ' . $this->driver->getDb()); $this->dbh = $this->driver->getDbh(); } @@ -425,7 +433,7 @@ public function haveInDatabase($table, array $data) return $lastInsertId; } - + public function _insertInDatabase($table, array $data) { $query = $this->driver->insert($table, $data); @@ -579,7 +587,7 @@ public function grabColumnFromDatabase($table, $column, array $criteria = []) $this->debugSection('Query', $query); $this->debugSection('Parameters', $parameters); $sth = $this->driver->executeQuery($query, $parameters); - + return $sth->fetchAll(\PDO::FETCH_COLUMN, 0); } From 88d572c2a44c28085df8fe2221cf3d66b0966060 Mon Sep 17 00:00:00 2001 From: Gordon Franke Date: Thu, 12 Jul 2018 11:17:06 +0200 Subject: [PATCH 077/395] match title in input fields (#5065) --- src/Codeception/Module/WebDriver.php | 4 ++-- tests/data/app/view/form/anchor.php | 2 +- tests/web/WebDriverTest.php | 7 +++++++ 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/Codeception/Module/WebDriver.php b/src/Codeception/Module/WebDriver.php index 0bb4274899..16b4663629 100644 --- a/src/Codeception/Module/WebDriver.php +++ b/src/Codeception/Module/WebDriver.php @@ -994,7 +994,7 @@ public function click($link, $context = null) * * ``` * @api - * @param $page WebDriver instance or an element to search within + * @param RemoteWebDriver $page WebDriver instance or an element to search within * @param $link a link text or locator to click * @return WebDriverElement */ @@ -1030,7 +1030,7 @@ public function _findClickable($page, $link) ".//input[./@type = 'submit' or ./@type = 'image' or ./@type = 'button'][contains(./@value, $locator)]", ".//input[./@type = 'image'][contains(./@alt, $locator)]", ".//button[contains(normalize-space(string(.)), $locator)]", - ".//input[./@type = 'submit' or ./@type = 'image' or ./@type = 'button'][./@name = $locator]", + ".//input[./@type = 'submit' or ./@type = 'image' or ./@type = 'button'][./@name = $locator or ./@title = $locator]", ".//button[./@name = $locator or ./@title = $locator]" ); diff --git a/tests/data/app/view/form/anchor.php b/tests/data/app/view/form/anchor.php index de1bf9ee99..d213041793 100644 --- a/tests/data/app/view/form/anchor.php +++ b/tests/data/app/view/form/anchor.php @@ -6,7 +6,7 @@
- +
diff --git a/tests/web/WebDriverTest.php b/tests/web/WebDriverTest.php index f220463a2e..6ada29c2b7 100644 --- a/tests/web/WebDriverTest.php +++ b/tests/web/WebDriverTest.php @@ -857,6 +857,13 @@ public function testSubmitHashForm() $this->module->seeCurrentUrlEquals('/form/anchor#a'); } + public function testSubmitHashFormTitle() + { + $this->module->amOnPage('/form/anchor'); + $this->module->click('Hash Form Title'); + $this->module->seeCurrentUrlEquals('/form/anchor#a'); + } + public function testSubmitHashButtonForm() { $this->module->amOnPage('/form/anchor'); From e03f4049bc878acaad0b6b01793ff711d762bdf4 Mon Sep 17 00:00:00 2001 From: Lee Robert Date: Sat, 14 Jul 2018 18:28:54 -0400 Subject: [PATCH 078/395] Fixes a missing _ for _getResponseContent() in seeXmlResponseEquals (#5074) * Fixes a missing _ for _getResponseContent() in seeXmlResponseEquals * Added test --- src/Codeception/Module/REST.php | 2 +- tests/unit/Codeception/Module/RestTest.php | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Codeception/Module/REST.php b/src/Codeception/Module/REST.php index dd3b808b2b..759c98a3b5 100644 --- a/src/Codeception/Module/REST.php +++ b/src/Codeception/Module/REST.php @@ -1295,7 +1295,7 @@ public function grabAttributeFromXmlElement($cssOrXPath, $attribute) */ public function seeXmlResponseEquals($xml) { - \PHPUnit\Framework\Assert::assertXmlStringEqualsXmlString($this->connectionModule->getResponseContent(), $xml); + \PHPUnit\Framework\Assert::assertXmlStringEqualsXmlString($this->connectionModule->_getResponseContent(), $xml); } diff --git a/tests/unit/Codeception/Module/RestTest.php b/tests/unit/Codeception/Module/RestTest.php index a823e5c13f..3af75d9b77 100644 --- a/tests/unit/Codeception/Module/RestTest.php +++ b/tests/unit/Codeception/Module/RestTest.php @@ -122,6 +122,13 @@ public function testValidXml() $this->module->seeResponseEquals('John'); } + public function testXmlResponseEquals() + { + $this->setStubResponse(''); + $this->module->seeResponseIsXml(); + $this->module->seeXmlResponseEquals(''); + } + public function testInvalidXml() { $this->setExpectedException('PHPUnit\Framework\ExpectationFailedException'); From 2060fc1fe8ac2823ff3b8ece04616fc12aca968a Mon Sep 17 00:00:00 2001 From: Michael Bodnarchuk Date: Mon, 16 Jul 2018 11:14:50 +0300 Subject: [PATCH 079/395] Version bump and changelog (#5077) --- CHANGELOG-2.4.md | 9 +++++++++ src/Codeception/Codecept.php | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG-2.4.md b/CHANGELOG-2.4.md index 60e71a711f..b85b698018 100644 --- a/CHANGELOG-2.4.md +++ b/CHANGELOG-2.4.md @@ -2,6 +2,15 @@ * Recently added `extends` property in the `codeception.yml` and `*.suite.yml` files now support absolute paths; by @silverfire * Fixed absolute paths handling on Windows in ParamLoader; by @silverfire +* [Yii2] Refactored database connection handling by @SamMousa. Database connections should now always be closed after tests no matter how you have opened them or who is holding references to them. See #5045 +* [Symfony] Email handling improved by @mbohal. Fixes #5058. + * Added optional argument `$expectedCount` to `seeEmailIsSent` + * Added `dontSeeEmailIsSent` +* [Recorder Extension] Added `ignore_steps` option to disable recording of specific steps. By @sspat. +* [WebDriver] Fixed "No Session Timeout" fatal error by @davertmik. +* [WebDriver] Added ability to locate clickable element by its title. See #5065 by @gimler +* [Db] Add `waitlock` config option for the database session to wait for lock in Oracle. By @ashnazg. See #5069 +* [REST] Fixed `seeXmlResponseEquals` by @Voziv #### 2.4.3 diff --git a/src/Codeception/Codecept.php b/src/Codeception/Codecept.php index 158096ed0b..831944a7b0 100644 --- a/src/Codeception/Codecept.php +++ b/src/Codeception/Codecept.php @@ -7,7 +7,7 @@ class Codecept { - const VERSION = "2.4.3"; + const VERSION = "2.4.4"; /** * @var \Codeception\PHPUnit\Runner From 6ca7696e00f0d18bfad549f7c0ba9dee1427ce57 Mon Sep 17 00:00:00 2001 From: jonny7 Date: Tue, 17 Jul 2018 09:43:52 -0300 Subject: [PATCH 080/395] Update autoload.php Fixes Compilation error: >Warning: preg_match(): Compilation failed: missing terminating ] for character class at offset 16 in C:\xampp-7\htdocs\www\vendor\codeception\codeception\autoload.php on line 134 --- autoload.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload.php b/autoload.php index e15b1413c0..132c109e4f 100644 --- a/autoload.php +++ b/autoload.php @@ -131,6 +131,6 @@ function codecept_is_path_absolute($path) return mb_substr($path, 0, 1) === DIRECTORY_SEPARATOR; } - return preg_match('#^[A-Z]:(?![^/\\])#i', $path) === 1; + return preg_match('#^[A-Z]:(?![^/\\\])#i', $path) === 1; } } From 5960d64ded678561b4bda4af37ed09f4c775ff4d Mon Sep 17 00:00:00 2001 From: Chuck Burgess Date: Sat, 21 Jul 2018 04:00:17 -0500 Subject: [PATCH 081/395] update stale github/tree URLs in docs; (#5084) --- docs/08-Customization.md | 2 +- docs/modules/Db.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/08-Customization.md b/docs/08-Customization.md index 2abd32b29a..e9bc2e57cd 100644 --- a/docs/08-Customization.md +++ b/docs/08-Customization.md @@ -366,7 +366,7 @@ Learn from the examples above to build a custom Installation Template. Here are * Use methods like `say`, `saySuccess`, `sayWarning`, `sayError`, `ask`, to interact with a user. * Use `createDirectoryFor`, `createEmptyDirectory` methods to create directories * Use `createHelper`, `createActor` methods to create helpers and actors. -* Use [Codeception generators](https://github.com/Codeception/Codeception/tree/2.3/src/Codeception/Lib/Generator) to create other support classes. +* Use [Codeception generators](https://github.com/Codeception/Codeception/tree/2.4/src/Codeception/Lib/Generator) to create other support classes. ## Conclusion diff --git a/docs/modules/Db.md b/docs/modules/Db.md index 611f920a77..0b843c2486 100644 --- a/docs/modules/Db.md +++ b/docs/modules/Db.md @@ -23,7 +23,7 @@ Also available: * Oracle Connection is done by database Drivers, which are stored in the `Codeception\Lib\Driver` namespace. -[Check out the drivers](https://github.com/Codeception/Codeception/tree/2.3/src/Codeception/Lib/Driver) +[Check out the drivers](https://github.com/Codeception/Codeception/tree/2.4/src/Codeception/Lib/Driver) if you run into problems loading dumps and cleaning databases. ## Config From 26cdd4913ca54c67ddb6e8469599f5438a8dfae4 Mon Sep 17 00:00:00 2001 From: Gintautas Miselis Date: Sun, 29 Jul 2018 13:49:00 +0300 Subject: [PATCH 082/395] [Docs] updated PHP requirements for 2..4 version (#5098) --- RoboFile.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/RoboFile.php b/RoboFile.php index 8e8e913a62..71c4e48543 100644 --- a/RoboFile.php +++ b/RoboFile.php @@ -519,8 +519,10 @@ public function publishPhar() $releaseFile->line("\n## $branch"); if ($major < 2) { $releaseFile->line("*Requires: PHP 5.3 and higher + CURL*\n"); - } else { + } elseif ($major == 2 && $minor < 4) { $releaseFile->line("*Requires: PHP 5.4 and higher + CURL*\n"); + } else { + $releaseFile->line("*Requires: PHP 5.6 and higher + CURL*\n"); } $releaseFile->line("* **[Download Latest $branch Release]($downloadUrl)**"); } From 8a4bb3d12e4aed2755f0d063fea9fd94bc603eb8 Mon Sep 17 00:00:00 2001 From: bangertz Date: Sun, 29 Jul 2018 22:46:20 +0200 Subject: [PATCH 083/395] [DB][Mysql] Two new options: "ssl_cipher" and "ssl_verify_server_cert" (#5095) * Two new options: "ssl_cipher" and "ssl_verify_server_cert" Added two options: "ssl_cipher" (list of one or more permissible ciphers to use for SSL encryption) and "ssl_verify_server_cert" (disables certificate CN verification) * Spaces removed --- src/Codeception/Module/Db.php | 38 +++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/src/Codeception/Module/Db.php b/src/Codeception/Module/Db.php index 3f7150e61a..ac674a8576 100644 --- a/src/Codeception/Module/Db.php +++ b/src/Codeception/Module/Db.php @@ -49,6 +49,8 @@ * * ssl_key - path to the SSL key (MySQL specific, @see http://php.net/manual/de/ref.pdo-mysql.php#pdo.constants.mysql-attr-key) * * ssl_cert - path to the SSL certificate (MySQL specific, @see http://php.net/manual/de/ref.pdo-mysql.php#pdo.constants.mysql-attr-ssl-cert) * * ssl_ca - path to the SSL certificate authority (MySQL specific, @see http://php.net/manual/de/ref.pdo-mysql.php#pdo.constants.mysql-attr-ssl-ca) + * * ssl_verify_server_cert - disables certificate CN verification (MySQL specific, @see http://php.net/manual/de/ref.pdo-mysql.php) + * * ssl_cipher - list of one or more permissible ciphers to use for SSL encryption (MySQL specific, @see http://php.net/manual/de/ref.pdo-mysql.php#pdo.constants.mysql-attr-cipher) * * ## Example * @@ -66,6 +68,8 @@ * ssl_key: '/path/to/client-key.pem' * ssl_cert: '/path/to/client-cert.pem' * ssl_ca: '/path/to/ca-cert.pem' + * ssl_verify_server_cert: false + * ssl_cipher: 'AES256-SHA' * * ## SQL data dump * @@ -287,16 +291,38 @@ private function connect() * @see http://php.net/manual/en/pdo.construct.php * @see http://php.net/manual/de/ref.pdo-mysql.php#pdo-mysql.constants */ - if (array_key_exists('ssl_key', $this->config) && !empty($this->config['ssl_key'])) { - $options[\PDO::MYSQL_ATTR_SSL_KEY] = $this->config['ssl_key']; + if (array_key_exists('ssl_key', $this->config) + && !empty($this->config['ssl_key']) + && defined('\PDO::MYSQL_ATTR_SSL_KEY') + ) { + $options[\PDO::MYSQL_ATTR_SSL_KEY] = (string) $this->config['ssl_key']; } - if (array_key_exists('ssl_cert', $this->config) && !empty($this->config['ssl_cert'])) { - $options[\PDO::MYSQL_ATTR_SSL_CERT] = $this->config['ssl_cert']; + if (array_key_exists('ssl_cert', $this->config) + && !empty($this->config['ssl_cert']) + && defined('\PDO::MYSQL_ATTR_SSL_CERT') + ) { + $options[\PDO::MYSQL_ATTR_SSL_CERT] = (string) $this->config['ssl_cert']; + } + + if (array_key_exists('ssl_ca', $this->config) + && !empty($this->config['ssl_ca']) + && defined('\PDO::MYSQL_ATTR_SSL_CA') + ) { + $options[\PDO::MYSQL_ATTR_SSL_CA] = (string) $this->config['ssl_ca']; } - if (array_key_exists('ssl_ca', $this->config) && !empty($this->config['ssl_ca'])) { - $options[\PDO::MYSQL_ATTR_SSL_CA] = $this->config['ssl_ca']; + if (array_key_exists('ssl_cipher', $this->config) + && !empty($this->config['ssl_cipher']) + && defined('\PDO::MYSQL_ATTR_SSL_CIPHER') + ) { + $options[\PDO::MYSQL_ATTR_SSL_CIPHER] = (string) $this->config['ssl_cipher']; + } + + if (array_key_exists('ssl_verify_server_cert', $this->config) + && defined('\PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT') + ) { + $options[\PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT] = (boolean) $this->config[ 'ssl_verify_server_cert' ]; } try { From e864e787b7374376057a01cefd1788b709841830 Mon Sep 17 00:00:00 2001 From: Michael Bodnarchuk Date: Wed, 1 Aug 2018 00:29:14 +0300 Subject: [PATCH 084/395] fixed compat with phpunit 7.2 (#5104) --- src/Codeception/Codecept.php | 2 +- src/Codeception/Subscriber/Dependencies.php | 2 +- src/Codeception/Suite.php | 2 +- src/Codeception/Test/Cept.php | 2 +- src/Codeception/Test/Cest.php | 2 +- src/Codeception/Test/Interfaces/Dependent.php | 2 +- src/Codeception/Test/Unit.php | 4 ++-- tests/data/claypit/composer.lock | 8 ++++---- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Codeception/Codecept.php b/src/Codeception/Codecept.php index 831944a7b0..7ab393de3e 100644 --- a/src/Codeception/Codecept.php +++ b/src/Codeception/Codecept.php @@ -7,7 +7,7 @@ class Codecept { - const VERSION = "2.4.4"; + const VERSION = "2.4.5"; /** * @var \Codeception\PHPUnit\Runner diff --git a/src/Codeception/Subscriber/Dependencies.php b/src/Codeception/Subscriber/Dependencies.php index ca97490b1d..1e52feb532 100644 --- a/src/Codeception/Subscriber/Dependencies.php +++ b/src/Codeception/Subscriber/Dependencies.php @@ -26,7 +26,7 @@ public function testStart(TestEvent $event) return; } - $testSignatures = $test->getDependencies(); + $testSignatures = $test->fetchDependencies(); foreach ($testSignatures as $signature) { if (!in_array($signature, $this->successfulTests)) { $test->getMetadata()->setSkip("This test depends on $signature to pass"); diff --git a/src/Codeception/Suite.php b/src/Codeception/Suite.php index 509e66627c..53c19415d5 100644 --- a/src/Codeception/Suite.php +++ b/src/Codeception/Suite.php @@ -34,7 +34,7 @@ protected function getDependencies($test) return [$test]; } $tests = []; - foreach ($test->getDependencies() as $requiredTestName) { + foreach ($test->fetchDependencies() as $requiredTestName) { $required = $this->findMatchedTest($requiredTestName); if (!$required) { continue; diff --git a/src/Codeception/Test/Cept.php b/src/Codeception/Test/Cept.php index bdbcefea49..c82a936926 100644 --- a/src/Codeception/Test/Cept.php +++ b/src/Codeception/Test/Cept.php @@ -77,7 +77,7 @@ protected function getParser() return $this->parser; } - public function getDependencies() + public function fetchDependencies() { return $this->getMetadata()->getDependencies(); } diff --git a/src/Codeception/Test/Cest.php b/src/Codeception/Test/Cest.php index 20f51f5ffd..c644ed2ea5 100644 --- a/src/Codeception/Test/Cest.php +++ b/src/Codeception/Test/Cest.php @@ -188,7 +188,7 @@ protected function getParser() return $this->parser; } - public function getDependencies() + public function fetchDependencies() { $names = []; foreach ($this->getMetadata()->getDependencies() as $required) { diff --git a/src/Codeception/Test/Interfaces/Dependent.php b/src/Codeception/Test/Interfaces/Dependent.php index 245d3bb153..c32e00d9b0 100644 --- a/src/Codeception/Test/Interfaces/Dependent.php +++ b/src/Codeception/Test/Interfaces/Dependent.php @@ -3,5 +3,5 @@ interface Dependent { - public function getDependencies(); + public function fetchDependencies(); } diff --git a/src/Codeception/Test/Unit.php b/src/Codeception/Test/Unit.php index c85acbfa8c..061072f526 100644 --- a/src/Codeception/Test/Unit.php +++ b/src/Codeception/Test/Unit.php @@ -130,7 +130,7 @@ public function getReportFields() ]; } - public function getDependencies() + public function fetchDependencies() { $names = []; foreach ($this->getMetadata()->getDependencies() as $required) { @@ -148,7 +148,7 @@ public function getDependencies() */ public function handleDependencies() { - $dependencies = $this->getDependencies(); + $dependencies = $this->fetchDependencies(); if (empty($dependencies)) { return true; } diff --git a/tests/data/claypit/composer.lock b/tests/data/claypit/composer.lock index c1bef1de0a..128b162bff 100644 --- a/tests/data/claypit/composer.lock +++ b/tests/data/claypit/composer.lock @@ -14,12 +14,12 @@ "source": { "type": "git", "url": "https://github.com/Codeception/c3.git", - "reference": "f7e31fce8a9abf1021990b4e31a7ed01689f4295" + "reference": "d841be32a6785e2f565b9f88f5ff36c905931a9a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Codeception/c3/zipball/f7e31fce8a9abf1021990b4e31a7ed01689f4295", - "reference": "f7e31fce8a9abf1021990b4e31a7ed01689f4295", + "url": "https://api.github.com/repos/Codeception/c3/zipball/d841be32a6785e2f565b9f88f5ff36c905931a9a", + "reference": "d841be32a6785e2f565b9f88f5ff36c905931a9a", "shasum": "" }, "require": { @@ -56,7 +56,7 @@ "code coverage", "codecoverage" ], - "time": "2018-05-26 21:53:33" + "time": "2018-05-26 22:34:28" } ], "aliases": [], From 11d32cf5387ca355464d45c1bb4515739f5dbb58 Mon Sep 17 00:00:00 2001 From: OneEyedSpaceFish Date: Tue, 31 Jul 2018 22:59:19 +0100 Subject: [PATCH 085/395] Fixing edge-case issues with the recording extension (#5101) Fixes #5093 --- ext/Recorder.php | 135 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 101 insertions(+), 34 deletions(-) diff --git a/ext/Recorder.php b/ext/Recorder.php index e87f81a942..67a63d23ad 100644 --- a/ext/Recorder.php +++ b/ext/Recorder.php @@ -1,4 +1,5 @@ 'WebDriver', 'template' => null, 'animate_slides' => true, - 'ignore_steps' => [] + 'ignore_steps' => [], ]; protected $template = <<recordedTests as $link => $url) { - $links .= "
  • $link
  • \n"; + + if (count($this->slides)) { + foreach ($this->recordedTests as $link => $url) { + $links .= "
  • $link
  • \n"; + } + $indexHTML = (new Template($this->indexTemplate)) + ->place('seed', $this->seed) + ->place('records', $links) + ->produce(); + + file_put_contents(codecept_output_dir() . 'records.html', $indexHTML); + $this->writeln("⏺ Records saved into: file://" . codecept_output_dir() . 'records.html'); } - $indexHTML = (new Template($this->indexTemplate)) - ->place('seed', $this->seed) - ->place('records', $links) - ->produce(); - file_put_contents(codecept_output_dir().'records.html', $indexHTML); - $this->writeln("⏺ Records saved into: file://" . codecept_output_dir().'records.html'); + foreach ($this->errors as $testPath => $screenshotPath) { + while (count($this->errorMessages[$testPath])) { + $this->writeln(array_pop($this->errorMessages[$testPath])); + } + + if ($screenshotPath !== null) { + $this->writeln("⏺ Screenshot saved into: file://{$screenshotPath}"); + } + } } public function before(TestEvent $e) @@ -281,6 +297,9 @@ public function before(TestEvent $e) $this->dir = null; $this->stepNum = 0; $this->slides = []; + $this->errors = []; + $this->errorMessages = []; + $testName = preg_replace('~\W~', '_', Descriptor::getTestAsString($e->getTest())); $this->dir = codecept_output_dir() . "record_{$this->seed}_$testName"; @mkdir($this->dir); @@ -302,37 +321,65 @@ public function cleanup(TestEvent $e) public function persist(TestEvent $e) { - if (!$this->webDriverModule or !$this->dir) { + if (!$this->webDriverModule) { return; } $indicatorHtml = ''; $slideHtml = ''; - foreach ($this->slides as $i => $step) { - $indicatorHtml .= (new Template($this->indicatorTemplate)) - ->place('step', (int)$i) - ->place('isActive', (int)$i ? '' : 'class="active"') - ->produce(); - $slideHtml .= (new Template($this->slidesTemplate)) - ->place('image', $i) - ->place('caption', $step->getHtml('#3498db')) - ->place('isActive', (int)$i ? '' : 'active') - ->place('isError', $step->hasFailed() ? 'error' : '') - ->produce(); + $testName = preg_replace('~\W~', '_', Descriptor::getTestAsString($e->getTest())); + $testPath = codecept_relative_path(Descriptor::getTestFullName($e->getTest())); + $dir = codecept_output_dir() . "record_{$this->seed}_$testName"; + + if ($this->dir !== $dir) { + $screenshotPath = "{$dir}/error.png"; + @mkdir($dir); + $this->errors = []; + $this->recordedTests = []; + $this->slides = []; + $this->errorMessages[$testPath] = [ + "⏺ An error has occurred in {$testName} before any steps could've executed", + ]; + + try { + $this->webDriverModule->webDriver->takeScreenshot($screenshotPath); + $this->errors[$testPath] = $screenshotPath; + } catch (\Exception $exception) { + $this->errors[$testPath] = null; + FileSystem::deleteDir($dir); + } + + return; } - $html = (new Template($this->template)) - ->place('indicators', $indicatorHtml) - ->place('slides', $slideHtml) - ->place('feature', ucfirst($e->getTest()->getFeature())) - ->place('test', Descriptor::getTestSignature($e->getTest())) - ->place('carousel_class', $this->config['animate_slides'] ? ' slide' : '') - ->produce(); - - $indexFile = $this->dir . DIRECTORY_SEPARATOR . 'index.html'; - file_put_contents($indexFile, $html); - $testName = Descriptor::getTestSignature($e->getTest()). ' - '.ucfirst($e->getTest()->getFeature()); - $this->recordedTests[$testName] = substr($indexFile, strlen(codecept_output_dir())); + if (!array_key_exists($testPath, $this->errors)) { + foreach ($this->slides as $i => $step) { + $indicatorHtml .= (new Template($this->indicatorTemplate)) + ->place('step', (int)$i) + ->place('isActive', (int)$i ? '' : 'class="active"') + ->produce(); + + $slideHtml .= (new Template($this->slidesTemplate)) + ->place('image', $i) + ->place('caption', $step->getHtml('#3498db')) + ->place('isActive', (int)$i ? '' : 'active') + ->place('isError', $step->hasFailed() ? 'error' : '') + ->produce(); + } + + $html = (new Template($this->template)) + ->place('indicators', $indicatorHtml) + ->place('slides', $slideHtml) + ->place('feature', ucfirst($e->getTest()->getFeature())) + ->place('test', Descriptor::getTestSignature($e->getTest())) + ->place('carousel_class', $this->config['animate_slides'] ? ' slide' : '') + ->produce(); + + $indexFile = $this->dir . DIRECTORY_SEPARATOR . 'index.html'; + file_put_contents($indexFile, $html); + $testName = Descriptor::getTestSignature($e->getTest()). ' - '.ucfirst($e->getTest()->getFeature()); + $this->recordedTests[$testName] = substr($indexFile, strlen(codecept_output_dir())); + } } public function afterStep(StepEvent $e) @@ -348,7 +395,27 @@ public function afterStep(StepEvent $e) } $filename = str_pad($this->stepNum, 3, "0", STR_PAD_LEFT) . '.png'; - $this->webDriverModule->_saveScreenshot($this->dir . DIRECTORY_SEPARATOR . $filename); + + try { + $this->webDriverModule->webDriver->takeScreenshot($this->dir . DIRECTORY_SEPARATOR . $filename); + } catch (\Exception $exception) { + $testPath = codecept_relative_path(Descriptor::getTestFullName($e->getTest())); + $this->errors[$testPath] = null; + + if (array_key_exists($testPath, $this->errorMessages)) { + $this->errorMessages[$testPath] = array_merge( + $this->errorMessages[$testPath], + ["⏺ Unable to capture a screenshot for {$testPath}/{$e->getStep()->getAction()}"] + ); + } else { + $this->errorMessages[$testPath] = [ + "⏺ Unable to capture a screenshot for {$testPath}/{$e->getStep()->getAction()}", + ]; + } + + return; + } + $this->stepNum++; $this->slides[$filename] = $e->getStep(); } From 04879c2d3c811228faa94656135fe295cb3bde45 Mon Sep 17 00:00:00 2001 From: Aleksey Shmelev Date: Wed, 1 Aug 2018 01:00:41 +0300 Subject: [PATCH 086/395] Adding an extension to run processes before tests (#5089) --- ext/RunBefore.php | 145 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 ext/RunBefore.php diff --git a/ext/RunBefore.php b/ext/RunBefore.php new file mode 100644 index 0000000000..e369069020 --- /dev/null +++ b/ext/RunBefore.php @@ -0,0 +1,145 @@ + 'runBefore' + ]; + + /** @var array[] */ + private $processes = []; + + public function _initialize() + { + if (!class_exists('Symfony\Component\Process\Process')) { + throw new ExtensionException($this, 'symfony/process package is required'); + } + } + + public function runBefore() + { + $this->runProcesses(); + $this->processMonitoring(); + } + + private function runProcesses() + { + foreach ($this->config as $item) { + if (is_array($item)) { + $currentCommand = array_shift($item); + $followingCommands = $item; + } else { + $currentCommand = $item; + $followingCommands = []; + } + + $process = $this->runProcess($currentCommand); + $this->addProcessToMonitoring($process, $followingCommands); + } + } + + /** + * @param string $command + * @return Process + */ + private function runProcess($command) + { + $this->output->debug('[RunBefore] Starting ' . $command); + $process = new Process($command, $this->getRootDir()); + $process->start(); + + return $process; + } + + /** + * @param string[] $followingCommands + */ + private function addProcessToMonitoring(Process $process, array $followingCommands) + { + $this->processes[] = [ + 'instance' => $process, + 'following' => $followingCommands + ]; + } + + /** + * @param int $index + */ + private function removeProcessFromMonitoring($index) + { + unset($this->processes[$index]); + } + + private function processMonitoring() + { + while (count($this->processes) !== 0) { + $this->checkProcesses(); + sleep(1); + } + } + + private function checkProcesses() + { + foreach ($this->processes as $index => $process) { + if (!$this->isRunning($process['instance'])) { + $this->output->debug('[RunBefore] Completing ' . $process['instance']->getCommandLine()); + $this->runFollowingCommand($process['following']); + $this->removeProcessFromMonitoring($index); + } + } + } + + /** + * @param string[] $followingCommands + */ + private function runFollowingCommand(array $followingCommands) + { + if (count($followingCommands) > 0) { + $process = $this->runProcess(array_shift($followingCommands)); + $this->addProcessToMonitoring($process, $followingCommands); + } + } + + private function isRunning(Process $process) + { + if ($process->isRunning()) { + return true; + } + return false; + } +} From 23a1f926c7652b939d65582903566133b13156e2 Mon Sep 17 00:00:00 2001 From: Marco van 't Wout Date: Wed, 1 Aug 2018 00:02:08 +0200 Subject: [PATCH 087/395] Fixes https://github.com/Codeception/Codeception/issues/4913 (#5086) * Improve check before calling getMetaData() is_callable() cannot be used if $testCase implements __call(). instanceof TestInterface should be the correct check, * Update Descriptor.php Switch to solution https://github.com/Codeception/Codeception/issues/4913#issuecomment-407014807 --- src/Codeception/Test/Descriptor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Codeception/Test/Descriptor.php b/src/Codeception/Test/Descriptor.php index 7e42dfc7b5..81ca09b770 100644 --- a/src/Codeception/Test/Descriptor.php +++ b/src/Codeception/Test/Descriptor.php @@ -34,7 +34,7 @@ public static function getTestSignatureUnique(\PHPUnit\Framework\SelfDescribing { $example = null; - if (is_callable([$testCase, 'getMetadata']) + if (method_exists($testCase, 'getMetaData') && $example = $testCase->getMetadata()->getCurrent('example') ) { $example = ':' . substr(sha1(json_encode($example)), 0, 7); From c86a69137dab521f67e34fc0b7934a84065266d3 Mon Sep 17 00:00:00 2001 From: Istvan Katona Date: Wed, 1 Aug 2018 00:03:36 +0200 Subject: [PATCH 088/395] fix Lumen file upload via REST module (#5082) * fix Lumen file upload via REST module * missing dependency --- src/Codeception/Lib/Connector/Lumen.php | 40 +++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/Codeception/Lib/Connector/Lumen.php b/src/Codeception/Lib/Connector/Lumen.php index 3ff004559d..d79b159e15 100644 --- a/src/Codeception/Lib/Connector/Lumen.php +++ b/src/Codeception/Lib/Connector/Lumen.php @@ -9,6 +9,7 @@ use Symfony\Component\HttpFoundation\Request as SymfonyRequest; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Client; +use Illuminate\Http\UploadedFile; class Lumen extends Client { @@ -124,4 +125,43 @@ private function initialize($request = null) $this->module->setApplication($this->app); } + + /** + * Make sure files are \Illuminate\Http\UploadedFile instances with the private $test property set to true. + * Fixes issue https://github.com/Codeception/Codeception/pull/3417. + * + * @param array $files + * @return array + */ + protected function filterFiles(array $files) + { + $files = parent::filterFiles($files); + + if (! class_exists('Illuminate\Http\UploadedFile')) { + // The \Illuminate\Http\UploadedFile class was introduced in Laravel 5.2.15, + // so don't change the $files array if it does not exist. + return $files; + } + + return $this->convertToTestFiles($files); + } + + /** + * @param array $files + * @return array + */ + private function convertToTestFiles(array $files) + { + $filtered = []; + + foreach ($files as $key => $value) { + if (is_array($value)) { + $filtered[$key] = $this->convertToTestFiles($value); + } else { + $filtered[$key] = UploadedFile::createFromBase($value, true); + } + } + + return $filtered; + } } From be408d0c519016fbc48073d376a202f06e6f352b Mon Sep 17 00:00:00 2001 From: Chuck Burgess Date: Tue, 31 Jul 2018 17:07:02 -0500 Subject: [PATCH 089/395] More explicit PDO closing upon destruction (#5072) * do explicit rollback if destructing while transaction is open; * do explicit disconnect on destruct; * destruct driver first, where the PDO instance gets destructed more cleanly; --- src/Codeception/Lib/Driver/Db.php | 8 ++++++++ src/Codeception/Module/Db.php | 9 +++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/Codeception/Lib/Driver/Db.php b/src/Codeception/Lib/Driver/Db.php index 2c3fd1a2ab..6a01b2554c 100755 --- a/src/Codeception/Lib/Driver/Db.php +++ b/src/Codeception/Lib/Driver/Db.php @@ -101,6 +101,14 @@ public function __construct($dsn, $user, $password, $options = null) $this->options = $options; } + public function __destruct() + { + if ($this->dbh->inTransaction()) { + $this->dbh->rollBack(); + } + $this->dbh = null; + } + public function getDbh() { return $this->dbh; diff --git a/src/Codeception/Module/Db.php b/src/Codeception/Module/Db.php index ac674a8576..19c7550d6f 100644 --- a/src/Codeception/Module/Db.php +++ b/src/Codeception/Module/Db.php @@ -237,6 +237,11 @@ public function _initialize() $this->connect(); } + public function __destruct() + { + $this->disconnect(); + } + public function _beforeSuite($settings = []) { if (!$this->config['populator'] @@ -347,9 +352,9 @@ private function connect() private function disconnect() { - $this->debugSection('Db', 'Disconnected'); - $this->dbh = null; $this->driver = null; + $this->dbh = null; + $this->debugSection('Db', 'Disconnected'); } public function _before(TestInterface $test) From 8c7c171d60f96f5399f99b0ae355d3eb8ae02615 Mon Sep 17 00:00:00 2001 From: Chuck Burgess Date: Tue, 31 Jul 2018 17:35:25 -0500 Subject: [PATCH 090/395] always disconnect before connect when reconnect is set (#5068) * if $dbh is already PDO instance, no need to connect again; * always disconnect before connect when reconnect is set; * let it connect every time... --- src/Codeception/Module/Db.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Codeception/Module/Db.php b/src/Codeception/Module/Db.php index 19c7550d6f..12d2f42a4c 100644 --- a/src/Codeception/Module/Db.php +++ b/src/Codeception/Module/Db.php @@ -360,6 +360,7 @@ private function disconnect() public function _before(TestInterface $test) { if ($this->config['reconnect']) { + $this->disconnect(); $this->connect(); } if ($this->config['cleanup'] && !$this->populated) { From 5fee32d5c82791548931cbc34806b4de6aa1abfc Mon Sep 17 00:00:00 2001 From: Davert Date: Wed, 1 Aug 2018 10:21:49 +0300 Subject: [PATCH 091/395] version bump and changelog --- CHANGELOG-2.4.md | 13 +++++++++++++ docs/modules/AngularJS.md | 2 +- docs/modules/Db.md | 6 +++++- docs/modules/Doctrine2.md | 2 +- docs/modules/Laravel5.md | 9 +++++---- docs/modules/Symfony.md | 18 ++++++++++++++++-- docs/modules/WebDriver.md | 2 +- docs/modules/Yii2.md | 4 ---- ext/README.md | 35 ++++++++++++++++++++++++++++++++++- 9 files changed, 76 insertions(+), 15 deletions(-) diff --git a/CHANGELOG-2.4.md b/CHANGELOG-2.4.md index b85b698018..8683fbd02a 100644 --- a/CHANGELOG-2.4.md +++ b/CHANGELOG-2.4.md @@ -1,3 +1,16 @@ +#### 2.4.5 + +* Fixed PHPUnit 7.2 compatibility. +* Introduced **RunBefore** extension to execute scripts before running tests. See #5049 by @aashmelev. +* [Db] Added two options for MySQL by @bangertz + * `ssl_cipher` - list of one or more permissible ciphers to use for SSL encryption + * `ssl_verify_server_cert` - disables certificate CN verification +* [Db] Always disconnect before connect when `reconnect` is set. By @ashnazg +* [Db] More explicit PDO closing upon destruction and close opened transactions by @ashnazg. +* [Recorder Extension] Improved error logging by @OneEyedSpaceFish. See #5101 +* [Lumen] Fixed file uploads via REST module. By @retnek. +* Fixed: function getMetadata() may not exist, results in fatal error. See #4913 by @marcovtwout + #### 2.4.4 * Recently added `extends` property in the `codeception.yml` and `*.suite.yml` files now support absolute paths; by @silverfire diff --git a/docs/modules/AngularJS.md b/docs/modules/AngularJS.md index 5fa69b66a5..e20555c2e8 100644 --- a/docs/modules/AngularJS.md +++ b/docs/modules/AngularJS.md @@ -130,7 +130,7 @@ $topBar = $module->_findElements('.top-bar')[0]; $el = $module->_findClickable($topBar, 'Click Me'); ``` - * `param` $page WebDriver instance or an element to search within + * `param RemoteWebDriver` $page WebDriver instance or an element to search within * `param` $link a link text or locator to click * `return` WebDriverElement diff --git a/docs/modules/Db.md b/docs/modules/Db.md index 0b843c2486..208cc304e1 100644 --- a/docs/modules/Db.md +++ b/docs/modules/Db.md @@ -23,7 +23,7 @@ Also available: * Oracle Connection is done by database Drivers, which are stored in the `Codeception\Lib\Driver` namespace. -[Check out the drivers](https://github.com/Codeception/Codeception/tree/2.4/src/Codeception/Lib/Driver) +[Check out the drivers](https://github.com/Codeception/Codeception/tree/2.3/src/Codeception/Lib/Driver) if you run into problems loading dumps and cleaning databases. ## Config @@ -39,6 +39,8 @@ if you run into problems loading dumps and cleaning databases. * ssl_key - path to the SSL key (MySQL specific, @see http://php.net/manual/de/ref.pdo-mysql.php#pdo.constants.mysql-attr-key) * ssl_cert - path to the SSL certificate (MySQL specific, @see http://php.net/manual/de/ref.pdo-mysql.php#pdo.constants.mysql-attr-ssl-cert) * ssl_ca - path to the SSL certificate authority (MySQL specific, @see http://php.net/manual/de/ref.pdo-mysql.php#pdo.constants.mysql-attr-ssl-ca) +* ssl_verify_server_cert - disables certificate CN verification (MySQL specific, @see http://php.net/manual/de/ref.pdo-mysql.php) +* ssl_cipher - list of one or more permissible ciphers to use for SSL encryption (MySQL specific, @see http://php.net/manual/de/ref.pdo-mysql.php#pdo.constants.mysql-attr-cipher) ## Example @@ -56,6 +58,8 @@ if you run into problems loading dumps and cleaning databases. ssl_key: '/path/to/client-key.pem' ssl_cert: '/path/to/client-cert.pem' ssl_ca: '/path/to/ca-cert.pem' + ssl_verify_server_cert: false + ssl_cipher: 'AES256-SHA' ## SQL data dump diff --git a/docs/modules/Doctrine2.md b/docs/modules/Doctrine2.md index 0defeecd03..4660e83890 100644 --- a/docs/modules/Doctrine2.md +++ b/docs/modules/Doctrine2.md @@ -145,7 +145,7 @@ which will always return the NULL value. ### haveInRepository Persists record into repository. -This method crates an entity, and sets its properties directly (via reflection). +This method creates an entity, and sets its properties directly (via reflection). Setters of entity won't be executed, but you can create almost any entity and save it to database. Returns id using `getId` of newly created entity. diff --git a/docs/modules/Laravel5.md b/docs/modules/Laravel5.md index 78547ccb4d..3597158a4a 100644 --- a/docs/modules/Laravel5.md +++ b/docs/modules/Laravel5.md @@ -564,7 +564,7 @@ $I->dontSeeFormErrors(); ?> ``` - * `return` bool + * `return` void ### dontSeeInCurrentUrl @@ -1072,8 +1072,9 @@ $user = $I->haveRecord('App\User', array('name' => 'Davert')); // returns Eloque ``` * `param string` $table - * `param array` $attributes - * `return` integer|EloquentModel + * `param array` $attributes + * `return` EloquentModel|int +@throws \RuntimeException * `[Part]` orm @@ -1322,7 +1323,7 @@ $I->seeFormHasErrors(); ?> ``` - * `return` bool + * `return` void ### seeInCurrentUrl diff --git a/docs/modules/Symfony.md b/docs/modules/Symfony.md index 50645edbf5..b2c14f3b89 100644 --- a/docs/modules/Symfony.md +++ b/docs/modules/Symfony.md @@ -432,6 +432,13 @@ $I->dontSeeElement('input', ['value' => '123456']); * `param array` $attributes +### dontSeeEmailIsSent + +Checks that no email was sent. This is an alias for seeEmailIsSent(0). + + * `[Part]` email + + ### dontSeeInCurrentUrl Checks that the current URI doesn't contain the given string. @@ -933,9 +940,16 @@ $I->seeElement(['css' => 'form input'], ['name' => 'login']); ### seeEmailIsSent -Checks if any email were sent by last request +Checks if the desired number of emails was sent. +If no argument is provided then at least one email must be sent to satisfy the check. + +``` php +seeEmailIsSent(2); +?> +``` -@throws \LogicException + * `param null|int` $expectedCount ### seeInCurrentRoute diff --git a/docs/modules/WebDriver.md b/docs/modules/WebDriver.md index de64f181df..785dd84082 100644 --- a/docs/modules/WebDriver.md +++ b/docs/modules/WebDriver.md @@ -327,7 +327,7 @@ $topBar = $module->_findElements('.top-bar')[0]; $el = $module->_findClickable($topBar, 'Click Me'); ``` - * `param` $page WebDriver instance or an element to search within + * `param RemoteWebDriver` $page WebDriver instance or an element to search within * `param` $link a link text or locator to click * `return` WebDriverElement diff --git a/docs/modules/Yii2.md b/docs/modules/Yii2.md index de4a150a18..62adfebb6b 100644 --- a/docs/modules/Yii2.md +++ b/docs/modules/Yii2.md @@ -361,10 +361,6 @@ $I->click(['link' => 'Login']); * `param` $context -### connectionOpenHandler -__not documented__ - - ### createAndSetCsrfCookie This function creates the CSRF Cookie. diff --git a/ext/README.md b/ext/README.md index a6748b32ff..904a88b90e 100644 --- a/ext/README.md +++ b/ext/README.md @@ -86,6 +86,7 @@ extensions: * `delete_successful` (default: true) - delete screenshots for successfully passed tests (i.e. log only failed and errored tests). * `module` (default: WebDriver) - which module for screenshots to use. Set `AngularJS` if you want to use it with AngularJS module. Generally, the module should implement `Codeception\Lib\Interfaces\ScreenshotSaver` interface. +* `ignore_steps` (default: []) - array of step names that should not be recorded, * wildcards supported #### Examples: @@ -93,14 +94,46 @@ extensions: ``` yaml extensions: enabled: - Codeception\Extension\Recorder: + - Codeception\Extension\Recorder: module: AngularJS # enable for Angular delete_successful: false # keep screenshots of successful tests + ignore_steps: [have, grab*] ``` +## RunBefore + +[See Source](https://github.com/Codeception/Codeception/blob/2.4/ext/RunBefore.php) + +Extension for execution of some processes before running tests. + +Processes can be independent and dependent. +Independent processes run independently of each other. +Dependent processes run sequentially one by one. + +Can be configured in suite config: + +```yaml +# acceptance.suite.yml +extensions: + enabled: + - Codeception\Extension\RunBefore: + - independent_process_1 + - + - dependent_process_1_1 + - dependent_process_1_2 + - independent_process_2 + - + - dependent_process_2_1 + - dependent_process_2_2 +``` + +HINT: you can use different configurations per environment. + + + ## RunFailed [See Source](https://github.com/Codeception/Codeception/blob/2.4/ext/RunFailed.php) From 0af1030fa35299241812301683d00d86d4712def Mon Sep 17 00:00:00 2001 From: Davert Date: Wed, 1 Aug 2018 11:24:08 +0300 Subject: [PATCH 092/395] updated readme --- readme.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/readme.md b/readme.md index 12451b2293..a35235021b 100644 --- a/readme.md +++ b/readme.md @@ -2,9 +2,6 @@ [![Latest Stable](https://poser.pugx.org/Codeception/Codeception/version.png)](https://packagist.org/packages/Codeception/Codeception) [![Total Downloads](https://poser.pugx.org/codeception/codeception/downloads.png)](https://packagist.org/packages/codeception/codeception) -[![Daily Downloads](https://img.shields.io/packagist/dd/codeception/codeception.svg)](https://packagist.org/packages/codeception/codeception) -[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Codeception/Codeception?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -[![PHP 7 ready](http://php7ready.timesplinter.ch/Codeception/Codeception/badge.svg)](https://travis-ci.org/Codeception/Codeception) [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/Codeception/Codeception/badges/quality-score.png?b=2.4)](https://scrutinizer-ci.com/g/Codeception/Codeception/?branch=2.4) **Modern PHP Testing for everyone** From 928f4b9e6f19426d09baaf9deeb3634830625679 Mon Sep 17 00:00:00 2001 From: Gintautas Miselis Date: Thu, 2 Aug 2018 19:40:02 +0300 Subject: [PATCH 093/395] [WebDriver] report correct strict locator in error message Implemented my own suggestion, This message is more accurate because getStrictLocator uses only the first key and its' value: https://github.com/edno/Codeception/blob/37d60db1822af1b17d9fadbea0b89a55c6cede05/src/Codeception/Module/WebDriver.php#L2703-L2707 https://github.com/edno/Codeception/blob/37d60db1822af1b17d9fadbea0b89a55c6cede05/src/Codeception/Module/WebDriver.php#L2769-L2772 --- src/Codeception/Module/WebDriver.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Codeception/Module/WebDriver.php b/src/Codeception/Module/WebDriver.php index 3afca58de9..9bda9990a7 100644 --- a/src/Codeception/Module/WebDriver.php +++ b/src/Codeception/Module/WebDriver.php @@ -2879,7 +2879,9 @@ protected function assertNodeConstraint($nodes, WebDriverConstraint $constraint, { $message = $selector; if (is_array($selector)) { - $message = implode(array_keys($selector)) . ':' . implode($selector); + $type = key($selector); + $locator = $selector[$type]; + $message = $type . ':' . $locator; } $this->assertThat($nodes, $constraint, $message); } From d0522f769edd358cb8cf0360b8627ec1a807c619 Mon Sep 17 00:00:00 2001 From: OneEyedSpaceFish Date: Thu, 2 Aug 2018 22:47:48 +0100 Subject: [PATCH 094/395] Fixing recorder extension issues caused by phpunit 7.2.7 update (#5110) Fixes #5109 --- ext/Recorder.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/ext/Recorder.php b/ext/Recorder.php index 67a63d23ad..e62552ca79 100644 --- a/ext/Recorder.php +++ b/ext/Recorder.php @@ -245,6 +245,8 @@ public function beforeSuite() } $this->seed = uniqid(); $this->webDriverModule = $this->getModule($this->config['module']); + $this->errors = []; + $this->errorMessages = []; if (!$this->webDriverModule instanceof ScreenshotSaver) { throw new ExtensionException( $this, @@ -260,7 +262,7 @@ public function beforeSuite() public function afterSuite() { - if (!$this->webDriverModule or !$this->dir) { + if (!$this->webDriverModule) { return; } $links = ''; @@ -297,8 +299,6 @@ public function before(TestEvent $e) $this->dir = null; $this->stepNum = 0; $this->slides = []; - $this->errors = []; - $this->errorMessages = []; $testName = preg_replace('~\W~', '_', Descriptor::getTestAsString($e->getTest())); $this->dir = codecept_output_dir() . "record_{$this->seed}_$testName"; @@ -331,10 +331,9 @@ public function persist(TestEvent $e) $testPath = codecept_relative_path(Descriptor::getTestFullName($e->getTest())); $dir = codecept_output_dir() . "record_{$this->seed}_$testName"; - if ($this->dir !== $dir) { + if (strcasecmp($this->dir, $dir) != 0) { $screenshotPath = "{$dir}/error.png"; @mkdir($dir); - $this->errors = []; $this->recordedTests = []; $this->slides = []; $this->errorMessages[$testPath] = [ From 8be87c6f035c4bfd23166c5b8d5479b20d76637c Mon Sep 17 00:00:00 2001 From: Dmytro Naumenko Date: Mon, 27 Aug 2018 23:09:12 +0300 Subject: [PATCH 095/395] Prevent NPE in Yii2 module (#5136) --- src/Codeception/Module/Yii2.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Codeception/Module/Yii2.php b/src/Codeception/Module/Yii2.php index b4826cc435..bae48f0754 100644 --- a/src/Codeception/Module/Yii2.php +++ b/src/Codeception/Module/Yii2.php @@ -343,9 +343,11 @@ public function _after(TestInterface $test) $this->rollbackTransactions(); - $this->connectionWatcher->stop(); - $this->connectionWatcher->closeAll(); - unset($this->connectionWatcher); + if (isset($this->connectionWatcher)) { + $this->connectionWatcher->stop(); + $this->connectionWatcher->closeAll(); + unset($this->connectionWatcher); + } if ($this->config['cleanup']) { foreach ($this->loadedFixtures as $fixture) { From fe06a0dac706d7c8512d258ad086e596ff36515a Mon Sep 17 00:00:00 2001 From: rajras Date: Tue, 28 Aug 2018 19:09:10 -0300 Subject: [PATCH 096/395] Fix in LoadSessionSnapshot (#5137) As same in saveSessionSnapshot, at the moment of load the snapshot, I think we need to avoid the deletion of all cookies. we need to delete all of them except those related to COVERAGE. --- src/Codeception/Module/WebDriver.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Codeception/Module/WebDriver.php b/src/Codeception/Module/WebDriver.php index dac4c4a916..a64efc3b01 100644 --- a/src/Codeception/Module/WebDriver.php +++ b/src/Codeception/Module/WebDriver.php @@ -3066,7 +3066,14 @@ public function loadSessionSnapshot($name) if (!isset($this->sessionSnapshots[$name])) { return false; } - $this->webDriver->manage()->deleteAllCookies(); + + foreach ($this->webDriver->manage()->getCookies() as $cookie) { + if (in_array(trim($cookie['name']), [LocalServer::COVERAGE_COOKIE, LocalServer::COVERAGE_COOKIE_ERROR])) { + continue; + } + $this->webDriver->manage()->deleteCookieNamed($cookie['name']); + } + foreach ($this->sessionSnapshots[$name] as $cookie) { $this->webDriver->manage()->addCookie($cookie); } From 68400f97db33cbf33b2e2e555e338b77bf457d44 Mon Sep 17 00:00:00 2001 From: Bert Ramakers Date: Wed, 29 Aug 2018 00:11:42 +0200 Subject: [PATCH 097/395] Fix errors in parallelRun() codeblock (#5125) The opt() methods should be option(), and there was a syntax error (unexpected ; on line 290). --- docs/12-ParallelExecution.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/12-ParallelExecution.md b/docs/12-ParallelExecution.md index 9ca83e8607..8fedab10eb 100644 --- a/docs/12-ParallelExecution.md +++ b/docs/12-ParallelExecution.md @@ -286,8 +286,8 @@ public function parallelRun() for ($i = 1; $i <= 5; $i++) { $parallel->process( $this->taskExec('docker-compose run --rm codecept run') - ->opt('group', "paracept_$i") // run for groups paracept_* - ->opt('xml', "tests/_log/result_$i.xml"); // provide xml report + ->option('group', "paracept_$i") // run for groups paracept_* + ->option('xml', "tests/_log/result_$i.xml") // provide xml report ); } return $parallel->run(); From d29867ede029f24e0d2970a573a46af6638d7e7e Mon Sep 17 00:00:00 2001 From: Gintautas Miselis Date: Wed, 29 Aug 2018 01:12:14 +0300 Subject: [PATCH 098/395] [Docs] Documented no-rebuild option of run command (#5130) --- src/Codeception/Command/Run.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Codeception/Command/Run.php b/src/Codeception/Command/Run.php index a6686f641b..2e45d48abb 100644 --- a/src/Codeception/Command/Run.php +++ b/src/Codeception/Command/Run.php @@ -78,6 +78,7 @@ * --skip-group (-x) Skip selected groups (multiple values allowed) * --env Run tests in selected environments. (multiple values allowed, environments can be merged with ',') * --fail-fast (-f) Stop after first failure + * --no-rebuild Do not rebuild actor classes on start * --help (-h) Display this help message. * --quiet (-q) Do not output any message. * --verbose (-v|vv|vvv) Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug From 13bff515d18143e61e62346794857e81dec3a622 Mon Sep 17 00:00:00 2001 From: Siad Ardroumli Date: Wed, 29 Aug 2018 00:47:29 +0200 Subject: [PATCH 099/395] Added memory_limit to dryrun command (#5138) --- src/Codeception/Command/DryRun.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Codeception/Command/DryRun.php b/src/Codeception/Command/DryRun.php index ce5cfc0e60..5e9dc40562 100644 --- a/src/Codeception/Command/DryRun.php +++ b/src/Codeception/Command/DryRun.php @@ -55,6 +55,10 @@ public function execute(InputInterface $input, OutputInterface $output) $test = $input->getArgument('test'); $config = $this->getGlobalConfig(); + ini_set( + 'memory_limit', + isset($config['settings']['memory_limit']) ? $config['settings']['memory_limit'] : '1024M' + ); if (! Configuration::isEmpty() && ! $test && strpos($suite, $config['paths']['tests']) === 0) { list(, $suite, $test) = $this->matchTestFromFilename($suite, $config['paths']['tests']); } From b79c86cffbd716df6ea8db8698553a1c86511c53 Mon Sep 17 00:00:00 2001 From: siad007 Date: Sat, 1 Sep 2018 23:34:35 +0200 Subject: [PATCH 100/395] Ignore empty context and extra fields in logger module. --- ext/Logger.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ext/Logger.php b/ext/Logger.php index b945139b64..cdd0b466c7 100644 --- a/ext/Logger.php +++ b/ext/Logger.php @@ -9,6 +9,7 @@ use Codeception\Exception\ConfigurationException; use Codeception\Extension; use Codeception\Test\Descriptor; +use Monolog\Formatter\LineFormatter; use Monolog\Handler\RotatingFileHandler; /** @@ -67,6 +68,12 @@ public function _initialize() // internal log $logHandler = new RotatingFileHandler($this->path . 'codeception.log', $this->config['max_files']); + + $formatter = $logHandler->getFormatter(); + if ($formatter instanceof LineFormatter) { + $formatter->ignoreEmptyContextAndExtra(true); + } + $this->logger = new \Monolog\Logger('Codeception'); $this->logger->pushHandler($logHandler); } From f740ce4859b189596ade88757fa49580c47b6749 Mon Sep 17 00:00:00 2001 From: Hexoplon <32719220+Hexoplon@users.noreply.github.com> Date: Tue, 4 Sep 2018 15:57:02 +0200 Subject: [PATCH 101/395] [Asserts] Updated examples of assertEquals and assertNotEquals assertEquals and assertNotEquals had the arguments mixed up in the examples. It should be $expected, $actual. It was $actual, $expected --- src/Codeception/Module/Asserts.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Codeception/Module/Asserts.php b/src/Codeception/Module/Asserts.php index 314d284d4c..6e77930fdf 100644 --- a/src/Codeception/Module/Asserts.php +++ b/src/Codeception/Module/Asserts.php @@ -17,13 +17,13 @@ class Asserts extends CodeceptionModule * Regular example: * ```php * assertEquals($element->getChildrenCount(), 5); + * $I->assertEquals(5, $element->getChildrenCount()); * ``` * * Floating-point example: * ```php * assertEquals($calculator->add(0.1, 0.2), 0.3, 'Calculator should add the two numbers correctly.', 0.01); + * $I->assertEquals(0.3, $calculator->add(0.1, 0.2), 'Calculator should add the two numbers correctly.', 0.01); * ``` * * @param $expected @@ -44,13 +44,13 @@ public function assertEquals($expected, $actual, $message = '', $delta = 0.0) * Regular example: * ```php * assertNotEquals($element->getChildrenCount(), 0); + * $I->assertNotEquals(0, $element->getChildrenCount()); * ``` * * Floating-point example: * ```php * assertNotEquals($calculator->add(0.1, 0.2), 0.4, 'Calculator should add the two numbers correctly.', 0.01); + * $I->assertNotEquals(0.4, $calculator->add(0.1, 0.2), 'Calculator should add the two numbers correctly.', 0.01); * ``` * * @param $expected From 0e5d909b726aa8f8e590ca9bbb5b14233bc84cea Mon Sep 17 00:00:00 2001 From: Michael Bodnarchuk Date: Wed, 5 Sep 2018 11:47:54 +0300 Subject: [PATCH 102/395] Multi database merged and updated (#5140) * Update Db.php to manage multi database * Update Db.php * Update Db.php * Update SqliteDbTest.php * Update Db.php * Update Db.php * Update SqliteDbTest.php * Update Db.php * Update SqliteDbTest.php * Update Db.php * Update Db.php * Update SqliteDbTest.php * Update Db.php * Update public function to protected function * Add doc for amConnectedToDatabase * Add deprecate on magic get method * Add example for multi-databases * Removed deprecated driver * Update Db.php * Merge branch 'multi-db' of https://github.com/eXorus/Codeception into eXorus-multi-db # Conflicts: # src/Codeception/Module/Db.php * small docs patch --- src/Codeception/Module/Db.php | 433 +++++++++++++----- tests/data/sqlite.db | Bin 0 -> 36864 bytes .../Codeception/Module/Db/SqliteDbTest.php | 177 +++++++ 3 files changed, 489 insertions(+), 121 deletions(-) diff --git a/src/Codeception/Module/Db.php b/src/Codeception/Module/Db.php index 12d2f42a4c..1a6323bec4 100644 --- a/src/Codeception/Module/Db.php +++ b/src/Codeception/Module/Db.php @@ -9,6 +9,8 @@ use Codeception\Lib\Driver\Db as Driver; use Codeception\Lib\DbPopulator; use Codeception\TestInterface; +use Codeception\Lib\Notification; +use Codeception\Util\ActionSequence; /** * Access a database. @@ -33,7 +35,7 @@ * * Oracle * * Connection is done by database Drivers, which are stored in the `Codeception\Lib\Driver` namespace. - * [Check out the drivers](https://github.com/Codeception/Codeception/tree/2.3/src/Codeception/Lib/Driver) + * [Check out the drivers](https://github.com/Codeception/Codeception/tree/2.4/src/Codeception/Lib/Driver) * if you run into problems loading dumps and cleaning databases. * * ## Config @@ -51,6 +53,7 @@ * * ssl_ca - path to the SSL certificate authority (MySQL specific, @see http://php.net/manual/de/ref.pdo-mysql.php#pdo.constants.mysql-attr-ssl-ca) * * ssl_verify_server_cert - disables certificate CN verification (MySQL specific, @see http://php.net/manual/de/ref.pdo-mysql.php) * * ssl_cipher - list of one or more permissible ciphers to use for SSL encryption (MySQL specific, @see http://php.net/manual/de/ref.pdo-mysql.php#pdo.constants.mysql-attr-cipher) + * * databases - include more database configs and switch between them in tests. * * ## Example * @@ -71,6 +74,20 @@ * ssl_verify_server_cert: false * ssl_cipher: 'AES256-SHA' * + * ## Example with multi-databases + * + * modules: + * enabled: + * - Db: + * dsn: 'mysql:host=localhost;dbname=testdb' + * user: 'root' + * password: '' + * databases: + * db2: + * dsn: 'mysql:host=localhost;dbname=testdb2' + * user: 'userdb2' + * password: '' + * * ## SQL data dump * * There are two ways of loading the dump into your database: @@ -162,7 +179,7 @@ * Example: * ```php * seeInDatabase('users', array('name' => 'Davert', 'email' => 'davert@mail.com')); + * $I->seeInDatabase('users', ['name' => 'Davert', 'email' => 'davert@mail.com']); * * ``` * Will generate: @@ -174,7 +191,7 @@ * * ```php * seeInDatabase('users', array('name' => 'Davert', 'email like' => 'davert%')); + * $I->seeInDatabase('users', ['name' => 'Davert', 'email like' => 'davert%']); * * ``` * Will generate: @@ -189,17 +206,6 @@ */ class Db extends CodeceptionModule implements DbInterface { - /** - * @api - * @var - */ - public $dbh; - - /** - * @var array - */ - protected $sql = []; - /** * @var array */ @@ -213,188 +219,359 @@ class Db extends CodeceptionModule implements DbInterface ]; /** - * @var bool + * @var array */ - protected $populated = false; + protected $requiredFields = ['dsn', 'user', 'password']; + const DEFAULT_DATABASE = 'default'; - /** - * @var \Codeception\Lib\Driver\Db - */ - public $driver; + public $drivers = []; + public $dbhs = []; + public $databasesPopulated = []; + public $databasesSql = []; + protected $insertedRows = []; + public $currentDatabase = self::DEFAULT_DATABASE; + + protected function getDatabases() + { + $databases = [$this->currentDatabase => $this->config]; + + if (!empty($this->config['databases'])) { + foreach ($this->config['databases'] as $databaseKey => $databaseConfig) { + $databases[$databaseKey] = array_merge([ + 'populate' => false, + 'cleanup' => false, + 'reconnect' => false, + 'waitlock' => 0, + 'dump' => null, + 'populator' => null, + ], $databaseConfig); + } + } + return $databases; + } + protected function connectToDatabases() + { + foreach ($this->getDatabases() as $databaseKey => $databaseConfig) { + $this->connect($databaseKey, $databaseConfig); + } + } + protected function cleanUpDatabases() + { + foreach ($this->getDatabases() as $databaseKey => $databaseConfig) { + $this->_cleanup($databaseKey, $databaseConfig); + } + } + protected function populateDatabases($configKey) + { + foreach ($this->getDatabases() as $databaseKey => $databaseConfig) { + if ($databaseConfig[$configKey]) { + $this->_loadDump($databaseKey, $databaseConfig); + } + } + } + protected function readSqlForDatabases() + { + foreach ($this->getDatabases() as $databaseKey => $databaseConfig) { + $this->readSql($databaseKey, $databaseConfig); + } + } + protected function removeInsertedForDatabases() + { + foreach ($this->getDatabases() as $databaseKey => $databaseConfig) { + $this->amConnectedToDatabase($databaseKey); + $this->removeInserted($databaseKey, $databaseConfig); + } + } + protected function disconnectDatabases() + { + foreach ($this->getDatabases() as $databaseKey => $databaseConfig) { + $this->disconnect($databaseKey, $databaseConfig); + } + } + protected function reconnectDatabases() + { + foreach ($this->getDatabases() as $databaseKey => $databaseConfig) { + if ($databaseConfig['reconnect']) { + $this->disconnect($databaseKey, $databaseConfig); + $this->connect($databaseKey, $databaseConfig); + } + } + } + + public function __get($name) + { + Notification::deprecate("Properties dbh and driver are deprecated in favor of Db::_getDbh and Db::_getDriver", "Db module"); + + if ($name == 'driver') { + return $this->_getDriver(); + } + if ($name == 'dbh') { + return $this->_getDbh(); + } + } + + public function _getDriver() + { + return $this->drivers[$this->currentDatabase]; + } + public function _getDbh() + { + return $this->dbhs[$this->currentDatabase]; + } /** - * @var array + * Make sure you are connected to the right database. + * + * ```php + * seeNumRecords(2, 'users'); //executed on default database + * $I->amConnectedToDatabase('db_books'); + * $I->seeNumRecords(30, 'books'); //executed on db_books database + * //All the next queries will be on db_books + * ``` + * @param $databaseKey + * @throws ModuleConfigException */ - protected $insertedRows = []; + public function amConnectedToDatabase($databaseKey) + { + if (empty($this->getDatabases()[$databaseKey]) && $databaseKey != self::DEFAULT_DATABASE) { + throw new ModuleConfigException( + __CLASS__, + "\nNo database $databaseKey in the key databases.\n" + ); + } + $this->currentDatabase = $databaseKey; + } /** - * @var array + * Can be used with a callback if you don't want to change the current database in your test. + * + * ```php + * seeNumRecords(2, 'users'); //executed on default database + * $I->performInDatabase('db_books', function($I) { + * $I->seeNumRecords(30, 'books'); //executed on db_books database + * }); + * $I->seeNumRecords(2, 'users'); //executed on default database + * ``` + * List of actions can be pragmatically built using `Codeception\Util\ActionSequence`: + * + * ```php + * performInDatabase('db_books', ActionSequence::build() + * ->seeNumRecords(30, 'books') + * ); + * ``` + * Alternatively an array can be used: + * + * ```php + * $I->performInDatabase('db_books', ['seeNumRecords' => [30, 'books']]); + * ``` + * + * Choose the syntax you like the most and use it, + * + * Actions executed from array or ActionSequence will print debug output for actions, and adds an action name to + * exception on failure. + * + * @param $databaseKey + * @param actions $actions + * @throws ModuleConfigException */ - protected $requiredFields = ['dsn', 'user', 'password']; + public function performInDatabase($databaseKey, $actions) + { + $backupDatabase = $this->currentDatabase; + $this->amConnectedToDatabase($databaseKey); + + if (is_callable($actions)) { + $actions($this); + $this->amConnectedToDatabase($backupDatabase); + return; + } + if (is_array($actions)) { + $actions = ActionSequence::build()->fromArray($actions); + } + + if (!$actions instanceof ActionSequence) { + throw new \InvalidArgumentException("2nd parameter, actions should be callback, ActionSequence or array"); + } + + $actions->run($this); + $this->amConnectedToDatabase($backupDatabase); + } public function _initialize() { - $this->connect(); + $this->connectToDatabases(); } public function __destruct() { - $this->disconnect(); + $this->disconnectDatabases(); } public function _beforeSuite($settings = []) { - if (!$this->config['populator'] - && $this->config['dump'] - && ($this->config['cleanup'] || ($this->config['populate'])) - ) { - $this->readSql(); - } - - $this->connect(); + $this->readSqlForDatabases(); + $this->connectToDatabases(); + $this->cleanUpDatabases(); + $this->populateDatabases('populate'); + } - // starting with loading dump - if ($this->config['populate']) { - if ($this->config['cleanup']) { - $this->_cleanup(); - } - $this->_loadDump(); + private function readSql($databaseKey = null, $databaseConfig = null) + { + if ($databaseConfig['populator']) { + return; } - - if ($this->config['reconnect']) { - $this->disconnect(); + if (!$databaseConfig['cleanup'] && !$databaseConfig['populate']) { + return; + } + if (empty($databaseConfig['dump'])) { + return; } - } - private function readSql() - { - if (!file_exists(Configuration::projectDir() . $this->config['dump'])) { + if (!file_exists(Configuration::projectDir() . $databaseConfig['dump'])) { throw new ModuleConfigException( __CLASS__, "\nFile with dump doesn't exist.\n" . "Please, check path for sql file: " - . $this->config['dump'] + . $databaseConfig['dump'] ); } - $sql = file_get_contents(Configuration::projectDir() . $this->config['dump']); + $sql = file_get_contents(Configuration::projectDir() . $databaseConfig['dump']); // remove C-style comments (except MySQL directives) $sql = preg_replace('%/\*(?!!\d+).*?\*/%s', '', $sql); if (!empty($sql)) { // split SQL dump into lines - $this->sql = preg_split('/\r\n|\n|\r/', $sql, -1, PREG_SPLIT_NO_EMPTY); + $this->databasesSql[$databaseKey] = preg_split('/\r\n|\n|\r/', $sql, -1, PREG_SPLIT_NO_EMPTY); } } - private function connect() + private function connect($databaseKey, $databaseConfig) { + if (!empty($this->drivers[$databaseKey]) && !empty($this->dbhs[$databaseKey])) { + return; + } $options = []; /** * @see http://php.net/manual/en/pdo.construct.php * @see http://php.net/manual/de/ref.pdo-mysql.php#pdo-mysql.constants */ - if (array_key_exists('ssl_key', $this->config) - && !empty($this->config['ssl_key']) + if (array_key_exists('ssl_key', $databaseConfig) + && !empty($databaseConfig['ssl_key']) && defined('\PDO::MYSQL_ATTR_SSL_KEY') ) { - $options[\PDO::MYSQL_ATTR_SSL_KEY] = (string) $this->config['ssl_key']; + $options[\PDO::MYSQL_ATTR_SSL_KEY] = (string) $databaseConfig['ssl_key']; } - if (array_key_exists('ssl_cert', $this->config) - && !empty($this->config['ssl_cert']) + if (array_key_exists('ssl_cert', $databaseConfig) + && !empty($databaseConfig['ssl_cert']) && defined('\PDO::MYSQL_ATTR_SSL_CERT') ) { - $options[\PDO::MYSQL_ATTR_SSL_CERT] = (string) $this->config['ssl_cert']; + $options[\PDO::MYSQL_ATTR_SSL_CERT] = (string) $databaseConfig['ssl_cert']; } - if (array_key_exists('ssl_ca', $this->config) - && !empty($this->config['ssl_ca']) + if (array_key_exists('ssl_ca', $databaseConfig) + && !empty($databaseConfig['ssl_ca']) && defined('\PDO::MYSQL_ATTR_SSL_CA') ) { - $options[\PDO::MYSQL_ATTR_SSL_CA] = (string) $this->config['ssl_ca']; + $options[\PDO::MYSQL_ATTR_SSL_CA] = (string) $databaseConfig['ssl_ca']; } - if (array_key_exists('ssl_cipher', $this->config) - && !empty($this->config['ssl_cipher']) + if (array_key_exists('ssl_cipher', $databaseConfig) + && !empty($databaseConfig['ssl_cipher']) && defined('\PDO::MYSQL_ATTR_SSL_CIPHER') ) { - $options[\PDO::MYSQL_ATTR_SSL_CIPHER] = (string) $this->config['ssl_cipher']; + $options[\PDO::MYSQL_ATTR_SSL_CIPHER] = (string) $databaseConfig['ssl_cipher']; } - if (array_key_exists('ssl_verify_server_cert', $this->config) + if (array_key_exists('ssl_verify_server_cert', $databaseConfig) && defined('\PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT') ) { - $options[\PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT] = (boolean) $this->config[ 'ssl_verify_server_cert' ]; + $options[\PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT] = (boolean) $databaseConfig[ 'ssl_verify_server_cert' ]; } try { - $this->driver = Driver::create($this->config['dsn'], $this->config['user'], $this->config['password'], $options); + $this->drivers[$databaseKey] = Driver::create($databaseConfig['dsn'], $databaseConfig['user'], $databaseConfig['password'], $options); } catch (\PDOException $e) { $message = $e->getMessage(); if ($message === 'could not find driver') { - list ($missingDriver, ) = explode(':', $this->config['dsn'], 2); + list ($missingDriver, ) = explode(':', $databaseConfig['dsn'], 2); $message = "could not find $missingDriver driver"; } throw new ModuleException(__CLASS__, $message . ' while creating PDO connection'); } - if ($this->config['waitlock']) { - $this->driver->setWaitLock($this->config['waitlock']); + if ($databaseConfig['waitlock']) { + $this->__getDriver()->setWaitLock($databaseConfig['waitlock']); } - $this->debugSection('Db', 'Connected to ' . $this->driver->getDb()); - $this->dbh = $this->driver->getDbh(); + $this->debugSection('Db', 'Connected to ' . $databaseKey . ' ' . $this->drivers[$databaseKey]->getDb()); + $this->dbhs[$databaseKey] = $this->drivers[$databaseKey]->getDbh(); } - private function disconnect() + private function disconnect($databaseKey) { - $this->driver = null; - $this->dbh = null; - $this->debugSection('Db', 'Disconnected'); + $this->debugSection('Db', 'Disconnected from ' . $databaseKey); + $this->dbhs[$databaseKey] = null; + $this->drivers[$databaseKey] = null; } public function _before(TestInterface $test) { - if ($this->config['reconnect']) { - $this->disconnect(); - $this->connect(); - } - if ($this->config['cleanup'] && !$this->populated) { - $this->_cleanup(); - $this->_loadDump(); - } + $this->reconnectDatabases(); + $this->amConnectedToDatabase(self::DEFAULT_DATABASE); + + $this->cleanUpDatabases(); + + $this->populateDatabases('cleanup'); + parent::_before($test); } public function _after(TestInterface $test) { - $this->removeInserted(); - if ($this->config['reconnect']) { - $this->disconnect(); - } + $this->removeInsertedForDatabases(); parent::_after($test); } - protected function removeInserted() + protected function removeInserted($databaseKey = null) { - foreach (array_reverse($this->insertedRows) as $row) { + $databaseKey = empty($databaseKey) ? self::DEFAULT_DATABASE : $databaseKey; + + if (empty($this->insertedRows[$databaseKey])) { + return; + } + + foreach (array_reverse($this->insertedRows[$databaseKey]) as $row) { try { - $this->driver->deleteQueryByCriteria($row['table'], $row['primary']); + $this->_getDriver()->deleteQueryByCriteria($row['table'], $row['primary']); } catch (\Exception $e) { - $this->debug("couldn't delete record " . json_encode($row['primary']) ." from {$row['table']}"); + $this->debug("Couldn't delete record " . json_encode($row['primary']) ." from {$row['table']}"); } } - $this->insertedRows = []; - $this->populated = false; + $this->insertedRows[$databaseKey] = []; } - public function _cleanup() + public function _cleanup($databaseKey = null, $databaseConfig = null) { - $dbh = $this->driver->getDbh(); + $databaseKey = empty($databaseKey) ? self::DEFAULT_DATABASE : $databaseKey; + $databaseConfig = empty($databaseConfig) ? $this->config : $databaseConfig; + + if (!$databaseConfig['populate']) { + return; + } + if (!$databaseConfig['cleanup']) { + return; + } + if (isset($this->databasesPopulated[$databaseKey]) && !$this->databasesPopulated[$databaseKey]) { + return; + } + $dbh = $this->dbhs[$databaseKey]; if (!$dbh) { throw new ModuleConfigException( __CLASS__, @@ -403,11 +580,11 @@ public function _cleanup() } try { // don't clear database for empty dump - if (!count($this->sql)) { + if (isset($this->databasesSql[$databaseKey]) && !count($this->databasesSql[$databaseKey])) { return; } - $this->driver->cleanup(); - $this->populated = false; + $this->drivers[$databaseKey]->cleanup(); + $this->databasesPopulated[$databaseKey] = false; } catch (\Exception $e) { throw new ModuleException(__CLASS__, $e->getMessage()); } @@ -415,32 +592,46 @@ public function _cleanup() public function isPopulated() { - return $this->populated; + return $this->databasesPopulated[$this->currentDatabase]; } - public function _loadDump() + public function _loadDump($databaseKey = null, $databaseConfig = null) { - if ($this->config['populator']) { - $this->loadDumpUsingPopulator(); + $databaseKey = empty($databaseKey) ? self::DEFAULT_DATABASE : $databaseKey; + $databaseConfig = empty($databaseConfig) ? $this->config : $databaseConfig; + + if (!$databaseConfig['populate']) { return; } - $this->loadDumpUsingDriver(); + + if (isset($this->databasesPopulated[$databaseKey]) && $this->databasesPopulated[$databaseKey]) { + return; + } + + if ($databaseConfig['populator']) { + $this->loadDumpUsingPopulator($databaseKey, $databaseConfig); + return; + } + $this->loadDumpUsingDriver($databaseKey, $databaseConfig); } - protected function loadDumpUsingPopulator() + protected function loadDumpUsingPopulator($databaseKey, $databaseConfig) { - $populator = new DbPopulator($this->config); - $this->populated = $populator->run(); + $populator = new DbPopulator($databaseConfig); + $this->databasesPopulated[$databaseKey] = $populator->run(); } - protected function loadDumpUsingDriver() + protected function loadDumpUsingDriver($databaseKey) { - if (!$this->sql) { + if (!isset($this->databasesSql[$databaseKey])) { + return; + } + if (!$this->databasesSql[$databaseKey]) { $this->debugSection('Db', 'No SQL loaded, loading dump skipped'); return; } - $this->driver->load($this->sql); - $this->populated = true; + $this->drivers[$databaseKey]->load($this->databasesSql[$databaseKey]); + $this->databasesPopulated[$databaseKey] = true; } /** @@ -468,14 +659,14 @@ public function haveInDatabase($table, array $data) public function _insertInDatabase($table, array $data) { - $query = $this->driver->insert($table, $data); + $query = $this->_getDriver()->insert($table, $data); $parameters = array_values($data); $this->debugSection('Query', $query); $this->debugSection('Parameters', $parameters); - $this->driver->executeQuery($query, $parameters); + $this->_getDriver()->executeQuery($query, $parameters); try { - $lastInsertId = (int)$this->driver->lastInsertId($table); + $lastInsertId = (int)$this->_getDriver()->lastInsertId($table); } catch (\PDOException $e) { // ignore errors due to uncommon DB structure, // such as tables without _id_seq in PGSQL @@ -486,7 +677,7 @@ public function _insertInDatabase($table, array $data) private function addInsertedRow($table, array $row, $id) { - $primaryKey = $this->driver->getPrimaryKey($table); + $primaryKey = $this->_getDriver()->getPrimaryKey($table); $primary = []; if ($primaryKey) { if ($id && count($primaryKey) === 1) { @@ -506,7 +697,7 @@ private function addInsertedRow($table, array $row, $id) $primary = $row; } - $this->insertedRows[] = [ + $this->insertedRows[$this->currentDatabase][] = [ 'table' => $table, 'primary' => $primary, ]; @@ -586,13 +777,13 @@ protected function countInDatabase($table, array $criteria = []) */ protected function proceedSeeInDatabase($table, $column, $criteria) { - $query = $this->driver->select($column, $table, $criteria); + $query = $this->_getDriver()->select($column, $table, $criteria); $parameters = array_values($criteria); $this->debugSection('Query', $query); if (!empty($parameters)) { $this->debugSection('Parameters', $parameters); } - $sth = $this->driver->executeQuery($query, $parameters); + $sth = $this->_getDriver()->executeQuery($query, $parameters); return $sth->fetchColumn(); } @@ -614,11 +805,11 @@ protected function proceedSeeInDatabase($table, $column, $criteria) */ public function grabColumnFromDatabase($table, $column, array $criteria = []) { - $query = $this->driver->select($column, $table, $criteria); + $query = $this->_getDriver()->select($column, $table, $criteria); $parameters = array_values($criteria); $this->debugSection('Query', $query); $this->debugSection('Parameters', $parameters); - $sth = $this->driver->executeQuery($query, $parameters); + $sth = $this->_getDriver()->executeQuery($query, $parameters); return $sth->fetchAll(\PDO::FETCH_COLUMN, 0); } @@ -671,12 +862,12 @@ public function grabNumRecords($table, array $criteria = []) */ public function updateInDatabase($table, array $data, array $criteria = []) { - $query = $this->driver->update($table, $data, $criteria); + $query = $this->_getDriver()->update($table, $data, $criteria); $parameters = array_merge(array_values($data), array_values($criteria)); $this->debugSection('Query', $query); if (!empty($parameters)) { $this->debugSection('Parameters', $parameters); } - $this->driver->executeQuery($query, $parameters); + $this->_getDriver()->executeQuery($query, $parameters); } } diff --git a/tests/data/sqlite.db b/tests/data/sqlite.db index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..cd631d343ed58a2a8e18f95276182f07f95cbfb5 100755 GIT binary patch literal 36864 zcmeI)Z%^As90zbaaWJ8wUMnHX>a?AL(1=1&LW;Wa2m|iOmOm^wtI!@qCb_mQv7OpZ zr&Zdd@CNoi_Gs^5Py2k*9#5+F3fdR2^Cf^C8fojJh<+_{obT-O?>={lbj0}hyP6$R z^2GBUD$FcjzejzZWcOQ!ZW_eY z_i6^o^RhfyUm_%L_wuCLFpaN`7HKq1(rDLe#Y;=t#Psu9pqXL&6Dr-*8ZV> zbr`P-LMt2w*DIF_884eeHoN7~;exEL zt%>KyytS_947`9XL|CKoyqs)1UNyPIQ{Nj7I`1RkeVbV^E41jWm>pTqUtVE@Qx~RL zM(K>KuC9usI`0Z~2H{Vg>Fh$XBe8>6KN2Gtzc|s`X0zI0=hlseNv=khh4RFveKzou z5iR^8@p&`)fnRwTP(R>FCV63A7F{wiA6RqLvF!e3bF852Q!Avsjuqy~0h@VdwQi6D zW6I}tx#c2Q9m4~GY>93 zh}Qq?p?}yQ009U<00Izz00bZa0SG_<0uZ>t0!vZfu>QZnBaE&=00Izz00bZa0SG_< z0uX=z1Ox%!|6>+F00Izz00bZa0SG_<0uX=z1a7`S^!>l6yk*b-yZL=Z4assertEquals($connection1, $connection2); $this->assertNotEquals($connection3, $connection2); } + + public function testMultiDatabase() + { + $config = array_merge($this->getConfig(), [ + 'dsn' => 'sqlite:tests/data/sqlite1.db', + 'cleanup' => false + ]); + $this->module->_reconfigure( + [ + 'databases' => ['db2' => $config], + ] + ); + $this->module->_beforeSuite(); + + $testDataInDb1 = ['name' => 'userdb1', 'email' => 'userdb1@example.org']; + $testDataInDb2 = ['name' => 'userdb2', 'email' => 'userdb2@example.org']; + + $this->module->_insertInDatabase('users', $testDataInDb1); + $this->module->seeInDatabase('users', $testDataInDb1); + + $this->module->amConnectedToDatabase('db2'); + + $this->module->_insertInDatabase('users', $testDataInDb2); + $this->module->seeInDatabase('users', $testDataInDb2); + $this->module->dontSeeInDatabase('users', $testDataInDb1); + } + + public function testDatabaseIsAlwaysDefaultBeforeTest() + { + $config = array_merge($this->getConfig(), ['dsn' => 'sqlite:tests/data/sqlite1.db']); + $this->module->_reconfigure( + [ + 'cleanup' => false, + 'databases' => ['db2' => $config], + ] + ); + $this->module->_beforeSuite(); + + $testCase1 = \Codeception\Util\Stub::makeEmpty('\Codeception\TestInterface'); + $testCase2 = \Codeception\Util\Stub::makeEmpty('\Codeception\TestInterface'); + $testDataInDb1 = ['name' => 'userdb1', 'email' => 'userdb1@example.org']; + $testDataInDb2 = ['name' => 'userdb2', 'email' => 'userdb2@example.org']; + + // Simulate a test that runs + $this->module->_before($testCase1); + $this->module->_insertInDatabase('users', $testDataInDb1); + $this->module->seeInDatabase('users', $testDataInDb1); + $this->module->amConnectedToDatabase('db2'); + $this->module->_insertInDatabase('users', $testDataInDb2); + $this->module->seeInDatabase('users', $testDataInDb2); + $this->module->_after($testCase1); + + // Simulate a second test that runs + $this->module->_before($testCase2); + $this->module->dontSeeInDatabase('users', $testDataInDb2); + $this->module->seeInDatabase('users', $testDataInDb1); + $this->module->_after($testCase2); + $this->module->_afterSuite(); + } + + public function testMultiDatabaseWithArray() + { + $config = array_merge($this->getConfig(), [ + 'dsn' => 'sqlite:tests/data/sqlite1.db', + 'cleanup' => false + ]); + $this->module->_reconfigure( + [ + 'databases' => ['db2' => $config], + ] + ); + $this->module->_beforeSuite(); + + $testDataInDb1 = ['name' => 'userdb1', 'email' => 'userdb1@example.org']; + $testDataInDb2 = ['name' => 'userdb2', 'email' => 'userdb2@example.org']; + + $this->module->_insertInDatabase('users', $testDataInDb1); + $this->module->performInDatabase('db2', [ + 'haveInDatabase' => ['users', $testDataInDb2], + 'seeInDatabase' => ['users', $testDataInDb2], + ]); + $this->module->seeInDatabase('users', $testDataInDb1); + $this->module->dontSeeInDatabase('users', $testDataInDb2); + } + + public function testMultiDatabaseWithActionSequence() + { + $config = array_merge($this->getConfig(), [ + 'dsn' => 'sqlite:tests/data/sqlite1.db', + 'cleanup' => false + ]); + $this->module->_reconfigure( + [ + 'databases' => ['db2' => $config], + ] + ); + $this->module->_beforeSuite(); + + $testDataInDb1 = ['name' => 'userdb1', 'email' => 'userdb1@example.org']; + $testDataInDb2 = ['name' => 'userdb2', 'email' => 'userdb2@example.org']; + + $this->module->_insertInDatabase('users', $testDataInDb1); + $this->module->performInDatabase('db2', ActionSequence::build() + ->haveInDatabase('users', $testDataInDb2) + ->seeInDatabase('users', $testDataInDb2) + ); + $this->module->seeInDatabase('users', $testDataInDb1); + $this->module->dontSeeInDatabase('users', $testDataInDb2); + } + + public function testMultiDatabaseWithAnonymousFunction() + { + $config = array_merge($this->getConfig(), [ + 'dsn' => 'sqlite:tests/data/sqlite1.db', + 'cleanup' => false + ]); + $this->module->_reconfigure( + [ + 'databases' => ['db2' => $config], + ] + ); + $this->module->_beforeSuite(); + + $testDataInDb1 = ['name' => 'userdb1', 'email' => 'userdb1@example.org']; + $testDataInDb2 = ['name' => 'userdb2', 'email' => 'userdb2@example.org']; + + $this->module->_insertInDatabase('users', $testDataInDb1); + $this->module->performInDatabase('db2', function ($module) use ($testDataInDb2) { + $module->_insertInDatabase('users', $testDataInDb2); + $module->seeInDatabase('users', $testDataInDb2); + }); + $this->module->seeInDatabase('users', $testDataInDb1); + $this->module->dontSeeInDatabase('users', $testDataInDb2); + } + + public function testMultiDatabaseWithUnknowDatabase() + { + $this->expectException(Codeception\Exception\ModuleConfigException::class); + $this->module->amConnectedToDatabase('db2'); + } + + public function testMultiDatabaseWithRemoveInserted() + { + $testCase1 = \Codeception\Util\Stub::makeEmpty('\Codeception\TestInterface'); + $testCase2 = \Codeception\Util\Stub::makeEmpty('\Codeception\TestInterface'); + $config = array_merge($this->getConfig(), [ + 'dsn' => 'sqlite:tests/data/sqlite1.db', + 'cleanup' => false + ]); + $this->module->_reconfigure( + [ + 'databases' => ['db2' => $config], + ] + ); + $this->module->_beforeSuite(); + $this->module->_before($testCase1); + + $testDataInDb1 = ['name' => 'userdb1', 'email' => 'userdb1@example.org']; + $testDataInDb2 = ['name' => 'userdb2', 'email' => 'userdb2@example.org']; + + $this->module->haveInDatabase('users', $testDataInDb1); + $this->module->seeInDatabase('users', $testDataInDb1); + $this->module->amConnectedToDatabase('db2', function ($module) use ($testDataInDb2) { + $module->haveInDatabase('users', $testDataInDb2); + $module->seeInDatabase('users', $testDataInDb2); + }); + $this->module->_after($testCase1); + + $this->module->_before($testCase2); + $this->module->dontSeeInDatabase('users', $testDataInDb1); + $this->module->amConnectedToDatabase('db2', function ($module) use ($testDataInDb2) { + $module->dontSeeInDatabase('users', $testDataInDb2); + }); + $this->module->_after($testCase2); + } } From d46fbf93697fa1848ff94ed8451586d883da8daf Mon Sep 17 00:00:00 2001 From: Siad Ardroumli Date: Wed, 5 Sep 2018 10:50:06 +0200 Subject: [PATCH 103/395] Test name should be equal. (#5151) --- src/Codeception/Actor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Codeception/Actor.php b/src/Codeception/Actor.php index e9228ce697..d9dbbd649d 100644 --- a/src/Codeception/Actor.php +++ b/src/Codeception/Actor.php @@ -35,7 +35,7 @@ public function wantToTest($text) public function wantTo($text) { - $this->scenario->setFeature(mb_strtolower($text, 'utf-8')); + $this->scenario->setFeature($text); } public function __call($method, $arguments) From e94541b30b3603c36a1b4fc209fdcfcd7b4212f8 Mon Sep 17 00:00:00 2001 From: Siad Ardroumli Date: Wed, 5 Sep 2018 10:50:33 +0200 Subject: [PATCH 104/395] Ensure php extension mbstring is available. (#5147) --- src/Codeception/Command/Run.php | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/Codeception/Command/Run.php b/src/Codeception/Command/Run.php index 2e45d48abb..9f52aee220 100644 --- a/src/Codeception/Command/Run.php +++ b/src/Codeception/Command/Run.php @@ -222,7 +222,8 @@ public function getDescription() */ public function execute(InputInterface $input, OutputInterface $output) { - $this->ensureCurlIsAvailable(); + $this->ensurePhpExtIsAvailable('CURL'); + $this->ensurePhpExtIsAvailable('mbstring'); $this->options = $input->getOptions(); $this->output = $output; @@ -545,14 +546,18 @@ protected function booleanOptions(InputInterface $input, $options = []) return $values; } - private function ensureCurlIsAvailable() + /** + * @param string $ext + * @throws \Exception + */ + private function ensurePhpExtIsAvailable($ext) { - if (!extension_loaded('curl')) { + if (!extension_loaded(strtolower($ext))) { throw new \Exception( - "Codeception requires CURL extension installed to make tests run\n" - . "If you are not sure, how to install CURL, please refer to StackOverflow\n\n" + "Codeception requires \"{$ext}\" extension installed to make tests run\n" + . "If you are not sure, how to install \"{$ext}\", please refer to StackOverflow\n\n" . "Notice: PHP for Apache/Nginx and CLI can have different php.ini files.\n" - . "Please make sure that your PHP you run from console has CURL enabled." + . "Please make sure that your PHP you run from console has \"{$ext}\" enabled." ); } } From bc42c50a587354a4ba1fb70441377c134eaea6ee Mon Sep 17 00:00:00 2001 From: Siad Ardroumli Date: Wed, 5 Sep 2018 10:51:14 +0200 Subject: [PATCH 105/395] Added ext-curl to the composer require section. (#5148) --- composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/composer.json b/composer.json index 03397bf643..7dd90d5e49 100644 --- a/composer.json +++ b/composer.json @@ -16,6 +16,7 @@ "require": { "php": ">=5.6.0 <8.0", + "ext-curl": "*", "ext-json": "*", "ext-mbstring": "*", "facebook/webdriver": ">=1.1.3 <2.0", From ddd99ff5bb67a1521e8b876f8c34bbfc9f1ccc13 Mon Sep 17 00:00:00 2001 From: Joilson Rezende Date: Tue, 11 Sep 2018 12:41:24 -0300 Subject: [PATCH 106/395] Use bind for Phalcon module find record (#5158) --- src/Codeception/Module/Phalcon.php | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/Codeception/Module/Phalcon.php b/src/Codeception/Module/Phalcon.php index 1f45b5c56b..c67f5399a1 100644 --- a/src/Codeception/Module/Phalcon.php +++ b/src/Codeception/Module/Phalcon.php @@ -561,13 +561,18 @@ public function seeCurrentRouteIs($routeName) protected function findRecord($model, $attributes = []) { $this->getModelRecord($model); - $query = []; + $conditions = []; + $bind = []; foreach ($attributes as $key => $value) { - $query[] = "$key = '$value'"; + $conditions[] = "$key = :$key:"; + $bind[$key] = $value; } - $squery = implode(' AND ', $query); - $this->debugSection('Query', $squery); - return call_user_func_array([$model, 'findFirst'], [$squery]); + $query = implode(' AND ', $conditions); + $this->debugSection('Query', $query); + return call_user_func_array([$model, 'findFirst'], [ + 'conditions' => $query, + 'bind' => $bind, + ]); } /** From 62b1fb082c0652620c8ad591bd996e151f4ebda0 Mon Sep 17 00:00:00 2001 From: Siad Ardroumli Date: Tue, 11 Sep 2018 17:43:08 +0200 Subject: [PATCH 107/395] Added getLogger (#5152) * Added getLogger * Do autoload in extension directly. * typo --- ext/Logger.php | 45 ++++++++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/ext/Logger.php b/ext/Logger.php index b945139b64..9a56a1ffd3 100644 --- a/ext/Logger.php +++ b/ext/Logger.php @@ -7,6 +7,7 @@ use Codeception\Event\TestEvent; use Codeception\Events; use Codeception\Exception\ConfigurationException; +use Codeception\Exception\ExtensionException; use Codeception\Extension; use Codeception\Test\Descriptor; use Monolog\Handler\RotatingFileHandler; @@ -52,7 +53,7 @@ class Logger extends Extension /** * @var \Monolog\Logger */ - protected $logger; + protected static $logger; protected $path; @@ -67,8 +68,13 @@ public function _initialize() // internal log $logHandler = new RotatingFileHandler($this->path . 'codeception.log', $this->config['max_files']); - $this->logger = new \Monolog\Logger('Codeception'); - $this->logger->pushHandler($logHandler); + self::$logger = new \Monolog\Logger('Codeception'); + self::$logger->pushHandler($logHandler); + } + + public static function getLogger() + { + return self::$logger; } public function beforeSuite(SuiteEvent $e) @@ -79,10 +85,10 @@ public function beforeSuite(SuiteEvent $e) public function beforeTest(TestEvent $e) { - $this->logger = new \Monolog\Logger(Descriptor::getTestFileName($e->getTest())); - $this->logger->pushHandler($this->logHandler); - $this->logger->info('------------------------------------'); - $this->logger->info("STARTED: " . ucfirst(Descriptor::getTestAsString($e->getTest()))); + self::$logger = new \Monolog\Logger(Descriptor::getTestFileName($e->getTest())); + self::$logger->pushHandler($this->logHandler); + self::$logger->info('------------------------------------'); + self::$logger->info("STARTED: " . ucfirst(Descriptor::getTestAsString($e->getTest()))); } public function afterTest(TestEvent $e) @@ -91,33 +97,42 @@ public function afterTest(TestEvent $e) public function endTest(TestEvent $e) { - $this->logger->info("PASSED"); + self::$logger->info("PASSED"); } public function testFail(FailEvent $e) { - $this->logger->alert($e->getFail()->getMessage()); - $this->logger->info("# FAILED #"); + self::$logger->alert($e->getFail()->getMessage()); + self::$logger->info("# FAILED #"); } public function testError(FailEvent $e) { - $this->logger->alert($e->getFail()->getMessage()); - $this->logger->info("# ERROR #"); + self::$logger->alert($e->getFail()->getMessage()); + self::$logger->info("# ERROR #"); } public function testSkipped(FailEvent $e) { - $this->logger->info("# Skipped #"); + self::$logger->info("# Skipped #"); } public function testIncomplete(FailEvent $e) { - $this->logger->info("# Incomplete #"); + self::$logger->info("# Incomplete #"); } public function beforeStep(StepEvent $e) { - $this->logger->info((string) $e->getStep()); + self::$logger->info((string) $e->getStep()); + } +} + +if (!function_exists('codecept_log')) { + function codecept_log() + { + return Logger::getLogger(); } +} else { + throw new ExtensionException('Codeception\Extension\Logger', "function 'codecept_log' already defined"); } From 607d90fca065ba813cfc8627119fd680920d10aa Mon Sep 17 00:00:00 2001 From: Siad Ardroumli Date: Tue, 11 Sep 2018 17:44:48 +0200 Subject: [PATCH 108/395] Fixed psr4 autoload path. (#5145) --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 7dd90d5e49..5faf6279d7 100644 --- a/composer.json +++ b/composer.json @@ -60,7 +60,7 @@ "autoload":{ "psr-4":{ - "Codeception\\": "src\\Codeception", + "Codeception\\": "src/Codeception", "Codeception\\Extension\\": "ext" } }, From f957aa01003314bd44e5d85bd17e868d2b2bdf29 Mon Sep 17 00:00:00 2001 From: Gintautas Miselis Date: Tue, 11 Sep 2018 18:45:14 +0300 Subject: [PATCH 109/395] [Autoload] Removed json_last_error_msg declaration (#5144) because PHP 5.4 is no longer supported. PHP 5.5 and newer versions have native implementation. --- autoload.php | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/autoload.php b/autoload.php index 132c109e4f..e1514366f7 100644 --- a/autoload.php +++ b/autoload.php @@ -34,27 +34,6 @@ class ParseError extends \Exception {}; } // @codingStandardsIgnoreEnd -if (!function_exists('json_last_error_msg')) { - /** - * Copied from http://php.net/manual/en/function.json-last-error-msg.php#117393 - * @return string - */ - function json_last_error_msg() - { - static $errors = array( - JSON_ERROR_NONE => 'No error', - JSON_ERROR_DEPTH => 'Maximum stack depth exceeded', - JSON_ERROR_STATE_MISMATCH => 'State mismatch (invalid or malformed JSON)', - JSON_ERROR_CTRL_CHAR => 'Control character error, possibly incorrectly encoded', - JSON_ERROR_SYNTAX => 'Syntax error', - JSON_ERROR_UTF8 => 'Malformed UTF-8 characters, possibly incorrectly encoded' - ); - - $error = json_last_error(); - return isset($errors[$error]) ? $errors[$error] : 'Unknown error'; - } -} - // function not autoloaded in PHP, thus its a good place for them if (!function_exists('codecept_debug')) { function codecept_debug($data) From 7af63172e14c941613201172b2fa2f90740463bf Mon Sep 17 00:00:00 2001 From: Christopher Stebe Date: Tue, 11 Sep 2018 17:46:17 +0200 Subject: [PATCH 110/395] make coverage 'show_only_summary' configurable (#5142) * make 'show_only_summary' on init `\SebastianBergmann\CodeCoverage\Report\Text` configurable * updates codecoverage docs for new config option * updates codecoverage docs, phpunit configuration reference link --- docs/11-Codecoverage.md | 18 ++++++++++++++++++ .../Coverage/Subscriber/Printer.php | 13 +++++++------ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/docs/11-Codecoverage.md b/docs/11-Codecoverage.md index 97cf54ba25..e9864f81c9 100644 --- a/docs/11-Codecoverage.md +++ b/docs/11-Codecoverage.md @@ -47,6 +47,24 @@ coverage: high_limit: 60 ``` +By default, show all whitelisted files in `--coverage-text` output not just the ones with coverage information is set to false, config option: + +```yaml +coverage: + enabled: true + show_uncovered: false +``` + +By default, show only the coverage report summary in `--coverage-text` output is set to false, config option: + +```yaml +coverage: + enabled: true + show_only_summary: false +``` + +For further information please refer to the [PHPUnit configuration docs](https://phpunit.readthedocs.io/en/latest/configuration.html) + ## Local CodeCoverage The basic codecoverage can be collected for functional and unit tests. diff --git a/src/Codeception/Coverage/Subscriber/Printer.php b/src/Codeception/Coverage/Subscriber/Printer.php index 2314ed038f..64dc466bd5 100644 --- a/src/Codeception/Coverage/Subscriber/Printer.php +++ b/src/Codeception/Coverage/Subscriber/Printer.php @@ -17,10 +17,11 @@ class Printer implements EventSubscriberInterface ]; protected $settings = [ - 'enabled' => true, - 'low_limit' => '35', - 'high_limit' => '70', - 'show_uncovered' => false + 'enabled' => true, + 'low_limit' => '35', + 'high_limit' => '70', + 'show_uncovered' => false, + 'show_only_summary' => false ]; public static $coverage; @@ -92,7 +93,7 @@ protected function printConsole(\PHPUnit\Util\Printer $printer) $this->settings['low_limit'], $this->settings['high_limit'], $this->settings['show_uncovered'], - false + $this->settings['show_only_summary'] ); $printer->write($writer->process(self::$coverage, $this->options['colors'])); } @@ -129,7 +130,7 @@ protected function printText() $this->settings['low_limit'], $this->settings['high_limit'], $this->settings['show_uncovered'], - false + $this->settings['show_only_summary'] ); file_put_contents( $this->absolutePath($this->options['coverage-text']), From 005abfaa677e44908fa0a345b4cafeea97a92540 Mon Sep 17 00:00:00 2001 From: Sam Date: Tue, 18 Sep 2018 10:43:44 +0200 Subject: [PATCH 111/395] Yii2: Move implementations to connector (#5173) * Refactor functions from module to connector, keeping the module interface the same but moving implementations to the connector. * Fixed nitpick CS * Attempt to use Guzzle MockHandler instead of external service * Fixed issues with test & phpbrowser configurability --- src/Codeception/Lib/Connector/Guzzle6.php | 5 +- src/Codeception/Lib/Connector/Yii2.php | 153 +++++++++++++++++- src/Codeception/Module/PhpBrowser.php | 8 +- src/Codeception/Module/Yii2.php | 90 +++-------- .../Codeception/Module/PhpBrowserTest.php | 16 +- 5 files changed, 195 insertions(+), 77 deletions(-) diff --git a/src/Codeception/Lib/Connector/Guzzle6.php b/src/Codeception/Lib/Connector/Guzzle6.php index 6a6e80f3d2..34b69b16ca 100644 --- a/src/Codeception/Lib/Connector/Guzzle6.php +++ b/src/Codeception/Lib/Connector/Guzzle6.php @@ -333,13 +333,16 @@ protected function extractCookies($host) public static function createHandler($handler) { + if ($handler instanceof HandlerStack) { + return $handler; + } if ($handler === 'curl') { return HandlerStack::create(new CurlHandler()); } if ($handler === 'stream') { return HandlerStack::create(new StreamHandler()); } - if (class_exists($handler)) { + if (is_string($handler) && class_exists($handler)) { return HandlerStack::create(new $handler); } if (is_callable($handler)) { diff --git a/src/Codeception/Lib/Connector/Yii2.php b/src/Codeception/Lib/Connector/Yii2.php index 67e44caf49..881f424b0d 100644 --- a/src/Codeception/Lib/Connector/Yii2.php +++ b/src/Codeception/Lib/Connector/Yii2.php @@ -1,7 +1,9 @@ startApp(); @@ -90,6 +92,7 @@ public function getApplication() public function resetApplication() { codecept_debug('Destroying application'); + $this->closeSession(); Yii::$app = null; \yii\web\UploadedFile::reset(); if (method_exists(\yii\base\Event::className(), 'offAll')) { @@ -100,6 +103,144 @@ public function resetApplication() gc_collect_cycles(); } + /** + * Finds and logs in a user + * @param $user + * @throws ConfigurationException + */ + public function findAndLoginUser($user) + { + $app = $this->getApplication(); + if (!$app->has('user')) { + throw new ConfigurationException('The user component is not configured'); + } + + if ($user instanceof \yii\web\IdentityInterface) { + $identity = $user; + } else { + // class name implementing IdentityInterface + $identityClass = $app->user->identityClass; + $identity = call_user_func([$identityClass, 'findIdentity'], $user); + } + $app->user->login($identity); + } + + /** + * Masks a value + * @param string $val + * @return string + * @see \yii\base\Security::maskToken + */ + public function maskToken($val) + { + return $this->getApplication()->security->maskToken($val); + } + + /** + * @param string $name The name of the cookie + * @param string $value The value of the cookie + * @return string The value to send to the browser + */ + public function hashCookieData($name, $value) + { + $app = $this->getApplication(); + if (!$app->request->enableCookieValidation) { + return $value; + } + return $app->security->hashData(serialize([$name, $value]), $app->request->cookieValidationKey); + } + + /** + * @return array List of regex patterns for recognized domain names + */ + public function getInternalDomains() + { + /** @var \yii\web\UrlManager $urlManager */ + $urlManager = $this->getApplication()->urlManager; + $domains = [$this->getDomainRegex($urlManager->hostInfo)]; + if ($urlManager->enablePrettyUrl) { + foreach ($urlManager->rules as $rule) { + /** @var \yii\web\UrlRule $rule */ + if (isset($rule->host)) { + $domains[] = $this->getDomainRegex($rule->host); + } + } + } + return array_unique($domains); + } + + /** + * @return array List of sent emails + */ + public function getEmails() + { + $app = $this->getApplication(); + if ($app->has('mailer', true)) { + $mailer = $app->get('mailer'); + if ($mailer instanceof TestMailer) { + return $app->get('mailer')->getSentMessages(); + } else { + throw new ConfigurationException("Mailer module is not mocked, can't test emails"); + } + } + return []; + } + + public function getComponent($name) + { + $app = $this->getApplication(); + if (!$app->has($name)) { + throw new ConfigurationException("Component $name is not available in current application"); + } + return $app->get($name); + } + + /** + * Getting domain regex from rule host template + * + * @param string $template + * @return string + */ + private function getDomainRegex($template) + { + if (preg_match('#https?://(.*)#', $template, $matches)) { + $template = $matches[1]; + } + $parameters = []; + if (strpos($template, '<') !== false) { + $template = preg_replace_callback( + '/<(?:\w+):?([^>]+)?>/u', + function ($matches) use (&$parameters) { + $key = '#' . count($parameters) . '#'; + $parameters[$key] = isset($matches[1]) ? $matches[1] : '\w+'; + return $key; + }, + $template + ); + } + $template = preg_quote($template); + $template = strtr($template, $parameters); + return '/^' . $template . '$/u'; + } + + /** + * Gets the name of the CSRF param. + * @return string + */ + public function getCsrfParamName() + { + return $this->getApplication()->request->csrfParam; + } + + /** + * @param $params + * @return mixed + */ + public function createUrl($params) + { + return is_array($params) ?$this->getApplication()->getUrlManager()->createUrl($params) : $params; + } + public function startApp() { codecept_debug('Starting application'); @@ -292,6 +433,16 @@ public function restart() $this->resetApplication(); } + /** + * This functions closes the session of the application, if the application exists and has a session. + */ + public function closeSession() + { + if (isset(\Yii::$app) && \Yii::$app->has('session', true)) { + \Yii::$app->session->close(); + } + } + /** * Resets the applications' response object. * The method used depends on the module configuration. diff --git a/src/Codeception/Module/PhpBrowser.php b/src/Codeception/Module/PhpBrowser.php index b61efbc24b..652205b7d6 100644 --- a/src/Codeception/Module/PhpBrowser.php +++ b/src/Codeception/Module/PhpBrowser.php @@ -172,7 +172,9 @@ public function amHttpAuthenticated($username, $password) public function amOnUrl($url) { $host = Uri::retrieveHost($url); - $this->_reconfigure(['url' => $host]); + $config = $this->config; + $config['url'] = $host; + $this->_reconfigure($config); $page = substr($url, strlen($host)); if ($page === '') { $page = '/'; @@ -186,7 +188,9 @@ public function amOnSubdomain($subdomain) $url = $this->config['url']; $url = preg_replace('~(https?:\/\/)(.*\.)(.*\.)~', "$1$3", $url); // removing current subdomain $url = preg_replace('~(https?:\/\/)(.*)~', "$1$subdomain.$2", $url); // inserting new - $this->_reconfigure(['url' => $url]); + $config = $this->config; + $config['url'] = $url; + $this->_reconfigure($config); } protected function onReconfigure() diff --git a/src/Codeception/Module/Yii2.php b/src/Codeception/Module/Yii2.php index bae48f0754..b50e59b829 100644 --- a/src/Codeception/Module/Yii2.php +++ b/src/Codeception/Module/Yii2.php @@ -2,6 +2,7 @@ namespace Codeception\Module; use Codeception\Configuration; +use Codeception\Exception\ConfigurationException; use Codeception\Exception\ModuleConfigException; use Codeception\Exception\ModuleException; use Codeception\Lib\Connector\Yii2 as Yii2Connector; @@ -356,10 +357,6 @@ public function _after(TestInterface $test) $this->loadedFixtures = []; } - if ($this->client !== null && $this->client->getApplication()->has('session', true)) { - $this->client->getApplication()->session->close(); - } - $this->client->resetApplication(); parent::_after($test); } @@ -406,17 +403,11 @@ public function _parts() */ public function amLoggedInAs($user) { - if (!$this->client->getApplication()->has('user')) { - throw new ModuleException($this, 'User component is not loaded'); + try { + $this->client->findAndLoginUser($user); + } catch (ConfigurationException $e) { + throw new ModuleException($this, $e->getMessage()); } - if ($user instanceof \yii\web\IdentityInterface) { - $identity = $user; - } else { - // class name implementing IdentityInterface - $identityClass = $this->client->getApplication()->user->identityClass; - $identity = call_user_func([$identityClass, 'findIdentity'], $user); - } - $this->client->getApplication()->user->login($identity); } /** @@ -659,10 +650,7 @@ public function amOnRoute($route, array $params = []) */ protected function clientRequest($method, $uri, array $parameters = [], array $files = [], array $server = [], $content = null, $changeHistory = true) { - if (is_array($uri)) { - $uri = $this->client->getApplication()->getUrlManager()->createUrl($uri); - } - return parent::clientRequest($method, $uri, $parameters, $files, $server, $content, $changeHistory); + return parent::clientRequest($method, $this->client->createUrl($uri), $parameters, $files, $server, $content, $changeHistory); } /** @@ -676,13 +664,15 @@ protected function clientRequest($method, $uri, array $parameters = [], array $f * @param $component * @return mixed * @throws ModuleException + * @deprecated in your tests you can use \Yii::$app directly. */ public function grabComponent($component) { - if (!$this->client->getApplication()->has($component)) { - throw new ModuleException($this, "Component $component is not available in current application"); + try { + return $this->client->getComponent($component); + } catch (ConfigurationException $e) { + throw new ModuleException($this, $e->getMessage()); } - return $this->client->getApplication()->get($component); } /** @@ -738,11 +728,11 @@ public function dontSeeEmailIsSent() */ public function grabSentEmails() { - $mailer = $this->grabComponent('mailer'); - if (!$mailer instanceof Yii2Connector\TestMailer) { - throw new ModuleException($this, "Mailer module is not mocked, can't test emails"); + try { + return $this->client->getEmails(); + } catch (ConfigurationException $e) { + throw new ModuleException($this, $e->getMessage()); } - return $mailer->getSentMessages(); } /** @@ -763,33 +753,7 @@ public function grabLastSentEmail() return end($messages); } - /** - * Getting domain regex from rule host template - * - * @param string $template - * @return string - */ - private function getDomainRegex($template) - { - if (preg_match('#https?://(.*)#', $template, $matches)) { - $template = $matches[1]; - } - $parameters = []; - if (strpos($template, '<') !== false) { - $template = preg_replace_callback( - '/<(?:\w+):?([^>]+)?>/u', - function ($matches) use (&$parameters) { - $key = '#' . count($parameters) . '#'; - $parameters[$key] = isset($matches[1]) ? $matches[1] : '\w+'; - return $key; - }, - $template - ); - } - $template = preg_quote($template); - $template = strtr($template, $parameters); - return '/^' . $template . '$/u'; - } + /** * Returns a list of regex patterns for recognized domain names @@ -798,17 +762,7 @@ function ($matches) use (&$parameters) { */ public function getInternalDomains() { - $domains = [$this->getDomainRegex($this->client->getApplication()->urlManager->hostInfo)]; - - if ($this->client->getApplication()->urlManager->enablePrettyUrl) { - foreach ($this->client->getApplication()->urlManager->rules as $rule) { - /** @var \yii\web\UrlRule $rule */ - if (isset($rule->host)) { - $domains[] = $this->getDomainRegex($rule->host); - } - } - } - return array_unique($domains); + return $this->client->getInternalDomains(); } private function defineConstants() @@ -826,11 +780,7 @@ private function defineConstants() */ public function setCookie($name, $val, array $params = []) { - // Sign the cookie. - if ($this->client->getApplication()->request->enableCookieValidation) { - $val = $this->client->getApplication()->security->hashData(serialize([$name, $val]), $this->client->getApplication()->request->cookieValidationKey); - } - parent::setCookie($name, $val, $params); + parent::setCookie($name, $this->client->hashCookieData($name, $val), $params); } /** @@ -840,8 +790,8 @@ public function setCookie($name, $val, array $params = []) */ public function createAndSetCsrfCookie($val) { - $masked = $this->client->getApplication()->security->maskToken($val); - $name = $this->client->getApplication()->request->csrfParam; + $masked = $this->client->maskToken($val); + $name = $this->client->getCsrfParamName(); $this->setCookie($name, $val); return [$name, $masked]; } diff --git a/tests/unit/Codeception/Module/PhpBrowserTest.php b/tests/unit/Codeception/Module/PhpBrowserTest.php index 86a92de7d4..a7fa3315a4 100644 --- a/tests/unit/Codeception/Module/PhpBrowserTest.php +++ b/tests/unit/Codeception/Module/PhpBrowserTest.php @@ -4,6 +4,8 @@ require_once 'tests/data/app/data.php'; require_once __DIR__ . '/TestsForBrowsers.php'; + +use GuzzleHttp\Handler\MockHandler; use GuzzleHttp\Psr7\Response; class PhpBrowserTest extends TestsForBrowsers @@ -19,7 +21,7 @@ protected function setUp() { $this->module = new \Codeception\Module\PhpBrowser(make_container()); $url = 'http://localhost:8000'; - $this->module->_setConfig(array('url' => $url)); + $this->module->_setConfig(['url' => $url]); $this->module->_initialize(); $this->module->_before($this->makeTest()); if (class_exists('GuzzleHttp\Url')) { @@ -280,7 +282,15 @@ public function testLocationHeaderDoesNotRedirectWhenStatusCodeIs201() public function testRedirectToAnotherDomainUsingSchemalessUrl() { - $this->module->amOnUrl('http://httpbin.org/redirect-to?url=//example.org/'); + + $this->module->_reconfigure([ + 'handler' => new MockHandler([ + new Response(302, ['Location' => '//example.org/']), + new Response(200, [], 'Cool stuff') + ]) + ]); + /** @var \GuzzleHttp\HandlerStack $handlerStack */ + $this->module->amOnUrl('http://fictional.redirector/redirect-to?url=//example.org/'); $currentUrl = $this->module->client->getHistory()->current()->getUri(); $this->assertSame('http://example.org/', $currentUrl); } @@ -481,7 +491,7 @@ public function testCookiesForDomain() { $this->skipForOldGuzzle(); - $mock = new \GuzzleHttp\Handler\MockHandler([ + $mock = new MockHandler([ new Response(200, ['X-Foo' => 'Bar']), ]); $handler = \GuzzleHttp\HandlerStack::create($mock); From b8124f0abd462f3cec614094e5c9b7af1379e884 Mon Sep 17 00:00:00 2001 From: Sam Date: Thu, 20 Sep 2018 13:58:28 +0200 Subject: [PATCH 112/395] Fixed issue with empty response stream in Yii2 (#5180) --- src/Codeception/Lib/Connector/Yii2.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Codeception/Lib/Connector/Yii2.php b/src/Codeception/Lib/Connector/Yii2.php index 881f424b0d..3ac380dc2b 100644 --- a/src/Codeception/Lib/Connector/Yii2.php +++ b/src/Codeception/Lib/Connector/Yii2.php @@ -341,7 +341,7 @@ public function doRequest($request) } $content = ob_get_clean(); - if (empty($content) && !empty($response->content)) { + if (empty($content) && !empty($response->content) && !isset($response->stream)) { throw new \Exception('No content was sent from Yii application'); } From 67352bf5f554ea97c27c2aa6b405ca1970f9673c Mon Sep 17 00:00:00 2001 From: Arjan Westdorp Date: Thu, 20 Sep 2018 13:59:03 +0200 Subject: [PATCH 113/395] Phalcon find null support (#5179) * Add support for nullable fields in findRecord() * Wrap parameters in array for findFirst * Make usage of single value more visible --- src/Codeception/Module/Phalcon.php | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/Codeception/Module/Phalcon.php b/src/Codeception/Module/Phalcon.php index c67f5399a1..62935c6503 100644 --- a/src/Codeception/Module/Phalcon.php +++ b/src/Codeception/Module/Phalcon.php @@ -564,14 +564,20 @@ protected function findRecord($model, $attributes = []) $conditions = []; $bind = []; foreach ($attributes as $key => $value) { - $conditions[] = "$key = :$key:"; - $bind[$key] = $value; + if ($value === null) { + $conditions[] = "$key IS NULL"; + } else { + $conditions[] = "$key = :$key:"; + $bind[$key] = $value; + } } $query = implode(' AND ', $conditions); $this->debugSection('Query', $query); return call_user_func_array([$model, 'findFirst'], [ - 'conditions' => $query, - 'bind' => $bind, + [ + 'conditions' => $query, + 'bind' => $bind, + ] ]); } From 69add948a68298aa15c7a66c06b5511d74b6a720 Mon Sep 17 00:00:00 2001 From: Oleksandr Roslov Date: Thu, 20 Sep 2018 14:59:48 +0300 Subject: [PATCH 114/395] Yii2: Fix `Too many connections` issue (#5175) --- src/Codeception/Module/Yii2.php | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/Codeception/Module/Yii2.php b/src/Codeception/Module/Yii2.php index b50e59b829..b7ea870272 100644 --- a/src/Codeception/Module/Yii2.php +++ b/src/Codeception/Module/Yii2.php @@ -344,12 +344,6 @@ public function _after(TestInterface $test) $this->rollbackTransactions(); - if (isset($this->connectionWatcher)) { - $this->connectionWatcher->stop(); - $this->connectionWatcher->closeAll(); - unset($this->connectionWatcher); - } - if ($this->config['cleanup']) { foreach ($this->loadedFixtures as $fixture) { $fixture->unloadFixtures(); @@ -358,6 +352,13 @@ public function _after(TestInterface $test) } $this->client->resetApplication(); + + if (isset($this->connectionWatcher)) { + $this->connectionWatcher->stop(); + $this->connectionWatcher->closeAll(); + unset($this->connectionWatcher); + } + parent::_after($test); } From 6d607b391bc9d1dedc96439f9135df282028462b Mon Sep 17 00:00:00 2001 From: Sam Mousa Date: Thu, 20 Sep 2018 14:32:31 +0200 Subject: [PATCH 115/395] Implement command-line option for specifying shuffle seed value --- docs/reference/Commands.md | 1 + src/Codeception/Codecept.php | 2 ++ src/Codeception/Command/Run.php | 19 +++++++++++++++++++ 3 files changed, 22 insertions(+) diff --git a/docs/reference/Commands.md b/docs/reference/Commands.md index d94e112203..e7ae703394 100644 --- a/docs/reference/Commands.md +++ b/docs/reference/Commands.md @@ -169,6 +169,7 @@ Options: --ansi Force ANSI output. --no-ansi Disable ANSI output. --no-interaction (-n) Do not ask any interactive question. + --seed Use the given seed for shuffling tests ``` diff --git a/src/Codeception/Codecept.php b/src/Codeception/Codecept.php index 7ab393de3e..e47f90677e 100644 --- a/src/Codeception/Codecept.php +++ b/src/Codeception/Codecept.php @@ -185,7 +185,9 @@ public function runSuite($settings, $suite, $test = null) { $suiteManager = new SuiteManager($this->dispatcher, $suite, $settings); $suiteManager->initialize(); + srand($this->options['seed']); $suiteManager->loadTests($test); + srand(); $suiteManager->run($this->runner, $this->result, $this->options); return $this->result; } diff --git a/src/Codeception/Command/Run.php b/src/Codeception/Command/Run.php index 9f52aee220..e6e32d530d 100644 --- a/src/Codeception/Command/Run.php +++ b/src/Codeception/Command/Run.php @@ -86,6 +86,7 @@ * --ansi Force ANSI output. * --no-ansi Disable ANSI output. * --no-interaction (-n) Do not ask any interactive question. + * --seed Use the given seed for shuffling tests * ``` * */ @@ -202,6 +203,13 @@ protected function configure() ), new InputOption('fail-fast', 'f', InputOption::VALUE_NONE, 'Stop after first failure'), new InputOption('no-rebuild', '', InputOption::VALUE_NONE, 'Do not rebuild actor classes on start'), + new InputOption( + 'seed', + '', + InputOption::VALUE_REQUIRED, + 'Define random seed for shuffle setting' + ), + ]); parent::configure(); @@ -241,10 +249,21 @@ public function execute(InputInterface $input, OutputInterface $output) if (!$this->options['colors']) { $this->options['colors'] = $config['settings']['colors']; } + + if (!$this->options['seed']) { + $this->options['seed'] = rand(); + } else { + $this->options['seed'] = intval($this->options['seed']); + } + if (!$this->options['silent']) { $this->output->writeln( Codecept::versionString() . "\nPowered by " . \PHPUnit\Runner\Version::getVersionString() ); + $this->output->writeln( + "Running with seed: " . $this->options['seed'] . "\n" + ); + } if ($this->options['debug']) { $this->output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE); From d75ca6468aafb9bdbbaea42ca7ff1ffd530fe866 Mon Sep 17 00:00:00 2001 From: Sam Mousa Date: Thu, 20 Sep 2018 16:52:40 +0200 Subject: [PATCH 116/395] Pass seed via userOptions --- src/Codeception/Command/Run.php | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/Codeception/Command/Run.php b/src/Codeception/Command/Run.php index e6e32d530d..41167d00b8 100644 --- a/src/Codeception/Command/Run.php +++ b/src/Codeception/Command/Run.php @@ -250,12 +250,6 @@ public function execute(InputInterface $input, OutputInterface $output) $this->options['colors'] = $config['settings']['colors']; } - if (!$this->options['seed']) { - $this->options['seed'] = rand(); - } else { - $this->options['seed'] = intval($this->options['seed']); - } - if (!$this->options['silent']) { $this->output->writeln( Codecept::versionString() . "\nPowered by " . \PHPUnit\Runner\Version::getVersionString() @@ -288,6 +282,11 @@ public function execute(InputInterface $input, OutputInterface $output) $userOptions['interactive'] = !$input->hasParameterOption(['--no-interaction', '-n']); $userOptions['ansi'] = (!$input->hasParameterOption('--no-ansi') xor $input->hasParameterOption('ansi')); + if (!$this->options['seed']) { + $userOptions['seed'] = rand(); + } else { + $userOptions['seed'] = intval($this->options['seed']); + } if ($this->options['no-colors'] || !$userOptions['ansi']) { $userOptions['colors'] = false; } From 4ebdb92873efe2c3d3979292c8d54a1de9c4713c Mon Sep 17 00:00:00 2001 From: Sam Date: Thu, 20 Sep 2018 17:23:24 +0200 Subject: [PATCH 117/395] Fixed issue #4769 (#5182) --- src/Codeception/Lib/Connector/Yii2.php | 5 +++++ src/Codeception/Module/Yii2.php | 2 ++ 2 files changed, 7 insertions(+) diff --git a/src/Codeception/Lib/Connector/Yii2.php b/src/Codeception/Lib/Connector/Yii2.php index 3ac380dc2b..41e16a9b10 100644 --- a/src/Codeception/Lib/Connector/Yii2.php +++ b/src/Codeception/Lib/Connector/Yii2.php @@ -2,6 +2,7 @@ namespace Codeception\Lib\Connector; use Codeception\Exception\ConfigurationException; +use Codeception\Exception\ModuleException; use Codeception\Lib\Connector\Yii2\Logger; use Codeception\Lib\Connector\Yii2\TestMailer; use Codeception\Lib\InnerBrowser; @@ -107,6 +108,7 @@ public function resetApplication() * Finds and logs in a user * @param $user * @throws ConfigurationException + * @throws \RuntimeException */ public function findAndLoginUser($user) { @@ -121,6 +123,9 @@ public function findAndLoginUser($user) // class name implementing IdentityInterface $identityClass = $app->user->identityClass; $identity = call_user_func([$identityClass, 'findIdentity'], $user); + if (!isset($identity)) { + throw new \RuntimeException('User not found'); + } } $app->user->login($identity); } diff --git a/src/Codeception/Module/Yii2.php b/src/Codeception/Module/Yii2.php index b7ea870272..61224ec3d7 100644 --- a/src/Codeception/Module/Yii2.php +++ b/src/Codeception/Module/Yii2.php @@ -408,6 +408,8 @@ public function amLoggedInAs($user) $this->client->findAndLoginUser($user); } catch (ConfigurationException $e) { throw new ModuleException($this, $e->getMessage()); + } catch (\RuntimeException $e) { + throw new ModuleException($this, $e->getMessage()); } } From 1d4bb38d1a5ac852ddb8a35f7aa88c18180176df Mon Sep 17 00:00:00 2001 From: Michael Bodnarchuk Date: Fri, 21 Sep 2018 00:01:31 +0300 Subject: [PATCH 118/395] Snapshots (#5165) * Snapshots feature * fixed failing tests on Appveyor, Werker. Fixed linting * fix tests, updated docs * added snapshot data --- codecept | 1 + docs/09-Data.md | 60 ++ package/bin | 1 + src/Codeception/Command/GenerateSnapshot.php | 72 ++ src/Codeception/Lib/Generator/Cest.php | 7 +- src/Codeception/Lib/Generator/Snapshot.php | 76 ++ src/Codeception/Lib/Generator/Test.php | 3 +- src/Codeception/Snapshot.php | 130 +++ src/Codeception/Step.php | 6 + src/Codeception/Util/Debug.php | 19 + tests/cli/SnapshotCest.php | 91 ++ tests/data/snapshots/codeception.yml | 23 + .../data/snapshots/tests/SnapshotDataCest.php | 38 + .../data/snapshots/tests/SnapshotFailCest.php | 17 + tests/data/snapshots/tests/_data/.gitkeep | 0 .../tests/_data/Snapshot.UserSnapshot.json | 1 + .../_data/Snapshot.UserSnapshot.original.json | 1 + .../tests/_data/snapshot.test_db_snapshot | Bin 0 -> 36864 bytes tests/data/snapshots/tests/_output/.gitkeep | 0 .../snapshots/tests/_support/DataTester.php | 26 + .../tests/_support/Helper/RestoreData.php | 13 + .../tests/_support/Snapshot/UserSnapshot.php | 20 + .../_support/_generated/DataTesterActions.php | 858 ++++++++++++++++++ .../Codeception/Command/GenerateCestTest.php | 1 - 24 files changed, 1455 insertions(+), 9 deletions(-) create mode 100644 src/Codeception/Command/GenerateSnapshot.php create mode 100644 src/Codeception/Lib/Generator/Snapshot.php create mode 100644 src/Codeception/Snapshot.php create mode 100644 tests/cli/SnapshotCest.php create mode 100644 tests/data/snapshots/codeception.yml create mode 100644 tests/data/snapshots/tests/SnapshotDataCest.php create mode 100644 tests/data/snapshots/tests/SnapshotFailCest.php create mode 100644 tests/data/snapshots/tests/_data/.gitkeep create mode 100644 tests/data/snapshots/tests/_data/Snapshot.UserSnapshot.json create mode 100644 tests/data/snapshots/tests/_data/Snapshot.UserSnapshot.original.json create mode 100644 tests/data/snapshots/tests/_data/snapshot.test_db_snapshot create mode 100644 tests/data/snapshots/tests/_output/.gitkeep create mode 100644 tests/data/snapshots/tests/_support/DataTester.php create mode 100644 tests/data/snapshots/tests/_support/Helper/RestoreData.php create mode 100644 tests/data/snapshots/tests/_support/Snapshot/UserSnapshot.php create mode 100644 tests/data/snapshots/tests/_support/_generated/DataTesterActions.php diff --git a/codecept b/codecept index cb11444b7f..8047a92a46 100755 --- a/codecept +++ b/codecept @@ -23,6 +23,7 @@ $app->add(new Codeception\Command\GenerateScenarios('generate:scenarios')); $app->add(new Codeception\Command\Clean('clean')); $app->add(new Codeception\Command\GenerateGroup('generate:groupobject')); $app->add(new Codeception\Command\GeneratePageObject('generate:pageobject')); +$app->add(new Codeception\Command\GenerateSnapshot('generate:snapshot')); $app->add(new Codeception\Command\GenerateStepObject('generate:stepobject')); $app->add(new Codeception\Command\GenerateEnvironment('generate:environment')); $app->add(new Codeception\Command\GenerateFeature('generate:feature')); diff --git a/docs/09-Data.md b/docs/09-Data.md index 926d92a6d2..41cf03202f 100644 --- a/docs/09-Data.md +++ b/docs/09-Data.md @@ -272,6 +272,66 @@ modules: DataFactory provides a powerful solution for managing data in integration/functional/acceptance tests. Read the [full reference](http://codeception.com/docs/modules/DataFactory) to learn how to set this module up. +## Testing Dynamic Data with Snapshots + +What if you deal with data which you don't own? For instance, the page look depends on number of categories in database, +and categories are set by admin user. How would you test that the page is still valid? + +There is a way to get it tested as well. Codeception allows you take a snapshot of a data on first run and compare with on next executions. +This principle is so general that it can work for testing APIs, items on a web page, etc. + +Let's check that list of categories on a page is the same it was before. +Create a snapshot class: + +``` +php vendor/bin/codecept g:snapshot Categories +``` + +Inject an actor class via constructor and implement `fetchData` method which should return a data set from a test. + +```php +i = $I; + } + + protected function fetchData() + { + // fetch texts from all 'a.category' elements on a page + return $this->i->grabMultiple('a.category'); + } +} +``` + +Inside a test you can inject the snapshot class and call `assert` method on it: + +```php +amOnPage('/categories'); + // if previously saved array of users does not match current set, test will fail + // to update data in snapshot run test with --debug flag + $snapshot->assert(); +} +``` + +On the first run, data will be obtained via `fetchData` method and saved to `tests/_data` directory in json format. +On next execution the obtained data will be compared with previously saved snapshot. + +**To update a snapshot with a new data run tests in `--debug` mode.** + +By default Snapshot uses `assertEquals` assertion, however this can be customized by overriding `assertData` method. + + ## Conclusion Codeception also assists the developer when dealing with data. Tools for database population diff --git a/package/bin b/package/bin index 67866547bb..bea52d73b7 100644 --- a/package/bin +++ b/package/bin @@ -21,6 +21,7 @@ $app->add(new Codeception\Command\Clean('clean')); $app->add(new Codeception\Command\GenerateGroup('generate:groupobject')); $app->add(new Codeception\Command\GeneratePageObject('generate:pageobject')); $app->add(new Codeception\Command\GenerateStepObject('generate:stepobject')); +$app->add(new Codeception\Command\GenerateSnapshot('generate:snapshot')); $app->add(new Codeception\Command\GenerateEnvironment('generate:environment')); $app->add(new Codeception\Command\GenerateFeature('generate:feature')); $app->add(new Codeception\Command\GherkinSnippets('gherkin:snippets')); diff --git a/src/Codeception/Command/GenerateSnapshot.php b/src/Codeception/Command/GenerateSnapshot.php new file mode 100644 index 0000000000..c184584b64 --- /dev/null +++ b/src/Codeception/Command/GenerateSnapshot.php @@ -0,0 +1,72 @@ +setDefinition([ + new InputArgument('suite', InputArgument::REQUIRED, 'Suite name or snapshot name)'), + new InputArgument('snapshot', InputArgument::OPTIONAL, 'Name of snapshot'), + ]); + parent::configure(); + } + + public function getDescription() + { + return 'Generates empty Snapshot class'; + } + + public function execute(InputInterface $input, OutputInterface $output) + { + $suite = $input->getArgument('suite'); + $class = $input->getArgument('snapshot'); + + if (!$class) { + $class = $suite; + $suite = null; + } + + $conf = $suite + ? $this->getSuiteConfig($suite) + : $this->getGlobalConfig(); + + if ($suite) { + $suite = DIRECTORY_SEPARATOR . ucfirst($suite); + } + + $path = $this->createDirectoryFor(Configuration::supportDir() . 'Snapshot' . $suite, $class); + + $filename = $path . $this->getShortClassName($class) . '.php'; + + $output->writeln($filename); + + $gen = new SnapshotGenerator($conf, ucfirst($suite) . '\\' . $class); + $res = $this->createFile($filename, $gen->produce()); + + if (!$res) { + $output->writeln("Snapshot $filename already exists"); + exit; + } + $output->writeln("Snapshot was created in $filename"); + } +} diff --git a/src/Codeception/Lib/Generator/Cest.php b/src/Codeception/Lib/Generator/Cest.php index 5a116804f5..cae786987b 100644 --- a/src/Codeception/Lib/Generator/Cest.php +++ b/src/Codeception/Lib/Generator/Cest.php @@ -11,8 +11,7 @@ class Cest use Namespaces; protected $template = <<{{actor}} = \$I; + } +EOF; + + protected $namespace; + protected $name; + protected $settings; + + public function __construct($settings, $name) + { + $this->settings = $settings; + $this->name = $this->getShortClassName($name); + $this->namespace = $this->getNamespaceString($this->settings['namespace'] . '\\Snapshot\\' . $name); + } + + public function produce() + { + return (new Template($this->template)) + ->place('namespace', $this->namespace) + ->place('actions', $this->produceActions()) + ->place('name', $this->name) + ->produce(); + } + + protected function produceActions() + { + if (!isset($this->settings['actor'])) { + return ''; // no actor in suite + } + + $actor = lcfirst($this->settings['actor']); + $actorClass = $this->settings['actor']; + if (!empty($this->settings['namespace'])) { + $actorClass = rtrim($this->settings['namespace'], '\\') . '\\' . $actorClass; + } + + return (new Template($this->actionsTemplate)) + ->place('actorClass', $actorClass) + ->place('actor', $actor) + ->produce(); + } +} diff --git a/src/Codeception/Lib/Generator/Test.php b/src/Codeception/Lib/Generator/Test.php index 11102e6c68..8a6fb3bdcf 100644 --- a/src/Codeception/Lib/Generator/Test.php +++ b/src/Codeception/Lib/Generator/Test.php @@ -11,8 +11,7 @@ class Test use Shared\Classname; protected $template = <<assertEquals($this->dataSet, $data, 'Snapshot doesn\'t match real data'); + } + + /** + * Loads data set from file. + */ + protected function load() + { + if (!file_exists($this->getFileName())) { + return; + } + $this->dataSet = json_decode(file_get_contents($this->getFileName())); + if (!$this->dataSet) { + throw new ContentNotFound("Loaded snapshot is empty"); + } + } + + /** + * Saves data set to file + */ + protected function save() + { + file_put_contents($this->getFileName(), json_encode($this->dataSet)); + } + + /** + * If no filename is defined, generates one from class name + * + * @return string + */ + protected function getFileName() + { + if (!$this->fileName) { + $this->fileName = preg_replace('/\W/', '.', get_class($this)) . '.json'; + } + return codecept_data_dir() . $this->fileName; + } + + /** + * Performs assertion for data sets + */ + public function assert() + { + // fetch data + $data = $this->fetchData(); + if (!$data) { + throw new ContentNotFound("Fetched snapshot is empty."); + } + + $this->load(); + + if (!$this->dataSet) { + $this->printDebug('Snapshot is empty. Updating snapshot...'); + $this->dataSet = $data; + $this->save(); + return; + } + + try { + $this->assertData($data); + $this->printDebug('Data matches snapshot'); + } catch (AssertionFailedError $exception) { + $this->printDebug('Snapshot assertion failed'); + + if (!is_bool($this->refresh)) { + $confirm = Debug::confirm('Should we update snapshot with fresh data? (Y/n) '); + } else { + $confirm = $this->refresh; + } + + if ($confirm) { + $this->dataSet = $data; + $this->save(); + $this->printDebug('Snapshot data updated'); + return; + } + + $this->fail($exception->getMessage()); + } + } + + /** + * Force update snapshot data. + * + * @param bool $refresh + */ + public function shouldRefreshSnapshot($refresh = true) + { + $this->refresh = $refresh; + } + + private function printDebug($message) + { + Debug::debug(get_class($this) . ': ' . $message); + } +} diff --git a/src/Codeception/Step.php b/src/Codeception/Step.php index b5b9eb78a4..260bb24682 100644 --- a/src/Codeception/Step.php +++ b/src/Codeception/Step.php @@ -305,8 +305,14 @@ protected function addMetaStep($step, $stack) }, array_values($step['args']))); $this->metaStep->setTraceInfo($step['file'], $step['line']); + codecept_debug(get_class($step['object'])); // pageobjects or other classes should not be included with "I" if (!in_array('Codeception\Actor', class_parents($step['class']))) { + if (isset($step['object'])) { + $this->metaStep->setPrefix(get_class($step['object']) . ':'); + return; + } + $this->metaStep->setPrefix($step['class'] . ':'); } return; diff --git a/src/Codeception/Util/Debug.php b/src/Codeception/Util/Debug.php index 573af69ad9..f237e059d7 100644 --- a/src/Codeception/Util/Debug.php +++ b/src/Codeception/Util/Debug.php @@ -2,6 +2,10 @@ namespace Codeception\Util; use Codeception\Lib\Console\Output; +use Symfony\Component\Console\Helper\QuestionHelper; +use Symfony\Component\Console\Input\ArgvInput; +use Symfony\Component\Console\Question\ConfirmationQuestion; +use Symfony\Component\Console\Question\Question; /** * This class is used only when Codeception is executed in `--debug` mode. @@ -47,4 +51,19 @@ public static function pause() return; } } + + public static function isEnabled() + { + return (bool) self::$output; + } + + public static function confirm($question) + { + if (!self::$output) { + return; + } + + $questionHelper = new QuestionHelper(); + return $questionHelper->ask(new ArgvInput(), self::$output, new ConfirmationQuestion($question)); + } } diff --git a/tests/cli/SnapshotCest.php b/tests/cli/SnapshotCest.php new file mode 100644 index 0000000000..a10058681f --- /dev/null +++ b/tests/cli/SnapshotCest.php @@ -0,0 +1,91 @@ +amInPath('tests/data/snapshots'); + } + + /** + * @before _openSnapshotSuite + * @param CliGuy $I + */ + public function runAllSnapshotTests(CliGuy $I) + { + $I->executeCommand('run tests/SnapshotDataCest.php'); + $I->seeInShellOutput('OK (3 tests'); + $I->seeInShellOutput('Load snapshot and skip refresh'); + $I->seeInShellOutput('Load snapshot and refresh'); + } + + /** + * @before _openSnapshotSuite + * @param CliGuy $I + */ + public function runSnapshotRefresh(CliGuy $I) + { + $I->executeCommand('run tests/SnapshotDataCest.php:loadSnapshotAndRefresh --debug --no-colors'); + $I->seeInShellOutput('Snapshot\UserSnapshot: assert'); + $I->seeInShellOutput('I grab column from database'); + $I->seeInShellOutput('Snapshot assertion failed'); + $I->seeInShellOutput('Snapshot data updated'); + } + + /** + * @before _openSnapshotSuite + * @param CliGuy $I + */ + public function runSnapshotRefreshFail(CliGuy $I) + { + $I->executeCommand('run tests/SnapshotDataCest.php:loadSnapshotAndSkipRefresh --debug --no-colors'); + $I->seeInShellOutput('Snapshot\UserSnapshot: assert'); + $I->seeInShellOutput('I grab column from database'); + $I->seeInShellOutput('Snapshot assertion failed'); + $I->dontSeeInShellOutput('Snapshot data updated'); + } + + /** + * @before _openSnapshotSuite + * @param CliGuy $I + */ + public function loadSnapshotInDebugAndFailOnProd(CliGuy $I) + { + $I->executeCommand('run tests/SnapshotFailCest.php --debug'); + $I->seeInShellOutput('PASSED'); + $I->executeCommand('run tests/SnapshotFailCest.php --no-exit'); + $I->seeInShellOutput('FAILURES'); + $I->seeInShellOutput('Snapshot doesn\'t match real data'); + } + + public function generateGlobalSnapshot(CliGuy\GeneratorSteps $I) + { + $I->amInPath('tests/data/sandbox'); + $I->executeCommand('generate:snapshot Login'); + $I->seeFileWithGeneratedClass('Login', 'tests/_support/Snapshot'); + $I->dontSeeInThisFile('public function __construct(\DumbGuy $I)'); + $I->seeFileFound('tests/_bootstrap.php'); + } + + public function generateSuiteSnapshot(CliGuy\GeneratorSteps $I) + { + $I->amInPath('tests/data/sandbox'); + $I->executeCommand('generate:snapshot dummy Login'); + $I->seeFileWithGeneratedClass('Login', 'tests/_support/Snapshot/Dummy'); + $I->seeInThisFile('namespace Snapshot\\Dummy;'); + $I->seeInThisFile('class Login'); + $I->seeInThisFile('protected $dumbGuy;'); + $I->seeInThisFile('public function __construct(\DumbGuy $I)'); + } + + public function generateGlobalSnapshotInDifferentPath(CliGuy\GeneratorSteps $I) + { + $I->executeCommand('generate:snapshot Login -c tests/data/sandbox'); + $I->amInPath('tests/data/sandbox'); + $I->seeFileWithGeneratedClass('Login', 'tests/_support/Snapshot'); + $I->dontSeeInThisFile('public function __construct(\DumbGuy $I)'); + $I->seeFileFound('tests/_bootstrap.php'); + } + +} \ No newline at end of file diff --git a/tests/data/snapshots/codeception.yml b/tests/data/snapshots/codeception.yml new file mode 100644 index 0000000000..8eba8d25f0 --- /dev/null +++ b/tests/data/snapshots/codeception.yml @@ -0,0 +1,23 @@ +paths: + data: tests/_data + output: tests/_output + tests: tests + support: tests/_support + +suites: + basic: + actor: DataTester + path: . + modules: + enabled: + - \Helper\RestoreData + - Asserts + - Db: + dsn: sqlite:tests/_data/snapshot_test.db + user: + password: + +actor_suffix: Tester +extensions: + enabled: + - Codeception\Extension\RunFailed diff --git a/tests/data/snapshots/tests/SnapshotDataCest.php b/tests/data/snapshots/tests/SnapshotDataCest.php new file mode 100644 index 0000000000..ed99898562 --- /dev/null +++ b/tests/data/snapshots/tests/SnapshotDataCest.php @@ -0,0 +1,38 @@ +assert(); + } + + public function loadSnapshotAndSkipRefresh(DataTester $I, UserSnapshot $snapshot) + { + $snapshot->assert(); + $I->haveInDatabase('users', [ + 'name' => 'hobgoblin', + 'email' => 'hobgoblin@vasya.com' + ]); + + $snapshot->shouldRefreshSnapshot(false); + $I->expectException(\PHPUnit\Framework\AssertionFailedError::class, function() use ($snapshot) { + $snapshot->assert(); + }); + } + + public function loadSnapshotAndRefresh(DataTester $I, UserSnapshot $snapshot) + { + $snapshot->assert(); + $I->haveInDatabase('users', [ + 'name' => 'hobgoblin', + 'email' => 'hobgoblin@vasya.com' + ]); + + $snapshot->shouldRefreshSnapshot(true); + $snapshot->assert(); + } + +} diff --git a/tests/data/snapshots/tests/SnapshotFailCest.php b/tests/data/snapshots/tests/SnapshotFailCest.php new file mode 100644 index 0000000000..4a04257947 --- /dev/null +++ b/tests/data/snapshots/tests/SnapshotFailCest.php @@ -0,0 +1,17 @@ +shouldRefreshSnapshot(true); + } + $I->haveInDatabase('users', [ + 'name' => 'hobgoblin', + 'email' => 'hobgoblin@vasya.com' + ]); + $snapshot->assert(); + } +} diff --git a/tests/data/snapshots/tests/_data/.gitkeep b/tests/data/snapshots/tests/_data/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/data/snapshots/tests/_data/Snapshot.UserSnapshot.json b/tests/data/snapshots/tests/_data/Snapshot.UserSnapshot.json new file mode 100644 index 0000000000..6f9f799271 --- /dev/null +++ b/tests/data/snapshots/tests/_data/Snapshot.UserSnapshot.json @@ -0,0 +1 @@ +["davert@mail.ua","nick@mail.ua","miles@davis.com","charlie@parker.com","hobgoblin@vasya.com"] \ No newline at end of file diff --git a/tests/data/snapshots/tests/_data/Snapshot.UserSnapshot.original.json b/tests/data/snapshots/tests/_data/Snapshot.UserSnapshot.original.json new file mode 100644 index 0000000000..2b9da7b919 --- /dev/null +++ b/tests/data/snapshots/tests/_data/Snapshot.UserSnapshot.original.json @@ -0,0 +1 @@ +["davert@mail.ua","nick@mail.ua","miles@davis.com","charlie@parker.com"] \ No newline at end of file diff --git a/tests/data/snapshots/tests/_data/snapshot.test_db_snapshot b/tests/data/snapshots/tests/_data/snapshot.test_db_snapshot new file mode 100644 index 0000000000000000000000000000000000000000..e442e4dd5dc88e1c640803792e97068754fe8e91 GIT binary patch literal 36864 zcmeI)Z%^As90zbaaWJ8w-YOx>nzWsQ(1-$6LWGf z=J}2ll8W$&Ad12+A%Y;>W3McGU2ZbVNS8b8w;0RM%H9(;|2to1wTpLt7nH|$-`qW1 ze!0At`#D!+1=t_}0SG_<0uX=z1R(Hn3yicySyff>;?vMN?NiV1QJ*K-{g$Dd1~K)$ znnCisEKk;#2+7;MJgGKJ<7=Zu8cmZl+O--vYE|oc>x6u3oNPn~xt2ro9soxi4lxnoak+{S#7X$>qf&Q*Q3iqd1li-8~DkH z7JifXycvDZuRIK>AMhlTyf80|E}57QtU2mfcK@n5R?zjS71CbE3iITE%{;SOH^_nU zSZ~)%vfpmCSVWzu@YvMrM}<)#%@r;*9>9S5jvWNH=LWH?lnf?T^Pvh+f8wLh0>2us z%Qpop^S%D{>@OUp7Sv)=r=~qjXovVG}vo4Ylhx<|8a}f<|*Y*LHUOz*dPD_2tWV= z5P$##AOHafKmY;|m`8yxQW@d1#maN*#S6!Bw@T%$%@X@5ldbYj`O(gU(&u7E(6W`T z$NrEQOw~W!*)EOO|E~n)jq++9JBXMd009U<00Izz00bZa0SG_<0uXp70VS1Q6=U~W z$V*~c6DM~kMC*S^c_}Ebm4B7LSq2*fAOHafKmY;|fB*y_009U<00MI>kdrg)KlfEB zW%V4}UCu;%S~}%W=al+6c9(#d)h2s)*ewCstTwJ1um2l@@|W_5@~hIA+YTZy2tWV= z5P$##AOHafKmY;|fWX`cY)aBfxpHdzz3z{e-?!=R!1B+if1f?M;>OMQm9L6vNi9|! zyH5k2?Dnjm?BJ~jZ*6~>l2+C#uH8M0Uc1rr8txCR8?BbNi=w0zDy%8$hvRhS!KDY$ z`ky`Y4;us^009U<00Izz00bZa0SG_<0=HOTDe4>6|F?LA(KQG_00Izz00bZa0SG_< z0uX?JAmICd%mN5N00Izz00bZa0SG_<0uX?}?H7o?{}+|l?D>DUzpv;a1Rwwb2tWV= c5P$##AOHafK;R=1$Vu6i754Z5*Bemxe=^p*-2eap literal 0 HcmV?d00001 diff --git a/tests/data/snapshots/tests/_output/.gitkeep b/tests/data/snapshots/tests/_output/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/data/snapshots/tests/_support/DataTester.php b/tests/data/snapshots/tests/_support/DataTester.php new file mode 100644 index 0000000000..da363b34c2 --- /dev/null +++ b/tests/data/snapshots/tests/_support/DataTester.php @@ -0,0 +1,26 @@ +dataTester = $I; + } + + protected function fetchData() + { + return $this->dataTester->grabColumnFromDatabase('users', 'email'); + } +} \ No newline at end of file diff --git a/tests/data/snapshots/tests/_support/_generated/DataTesterActions.php b/tests/data/snapshots/tests/_support/_generated/DataTesterActions.php new file mode 100644 index 0000000000..ba7da188e4 --- /dev/null +++ b/tests/data/snapshots/tests/_support/_generated/DataTesterActions.php @@ -0,0 +1,858 @@ +assertEquals($element->getChildrenCount(), 5); + * ``` + * + * Floating-point example: + * ```php + * assertEquals($calculator->add(0.1, 0.2), 0.3, 'Calculator should add the two numbers correctly.', 0.01); + * ``` + * + * @param $expected + * @param $actual + * @param string $message + * @param float $delta + * @see \Codeception\Module\Asserts::assertEquals() + */ + public function assertEquals($expected, $actual, $message = null, $delta = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertEquals', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that two variables are not equal. If you're comparing floating-point values, + * you can specify the optional "delta" parameter which dictates how great of a precision + * error are you willing to tolerate in order to consider the two values not equal. + * + * Regular example: + * ```php + * assertNotEquals($element->getChildrenCount(), 0); + * ``` + * + * Floating-point example: + * ```php + * assertNotEquals($calculator->add(0.1, 0.2), 0.4, 'Calculator should add the two numbers correctly.', 0.01); + * ``` + * + * @param $expected + * @param $actual + * @param string $message + * @param float $delta + * @see \Codeception\Module\Asserts::assertNotEquals() + */ + public function assertNotEquals($expected, $actual, $message = null, $delta = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertNotEquals', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that two variables are same + * + * @param $expected + * @param $actual + * @param string $message + * @see \Codeception\Module\Asserts::assertSame() + */ + public function assertSame($expected, $actual, $message = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertSame', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that two variables are not same + * + * @param $expected + * @param $actual + * @param string $message + * @see \Codeception\Module\Asserts::assertNotSame() + */ + public function assertNotSame($expected, $actual, $message = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertNotSame', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that actual is greater than expected + * + * @param $expected + * @param $actual + * @param string $message + * @see \Codeception\Module\Asserts::assertGreaterThan() + */ + public function assertGreaterThan($expected, $actual, $message = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertGreaterThan', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that actual is greater or equal than expected + * + * @param $expected + * @param $actual + * @param string $message + * @see \Codeception\Module\Asserts::assertGreaterThanOrEqual() + */ + public function assertGreaterThanOrEqual($expected, $actual, $message = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertGreaterThanOrEqual', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that actual is less than expected + * + * @param $expected + * @param $actual + * @param string $message + * @see \Codeception\Module\Asserts::assertLessThan() + */ + public function assertLessThan($expected, $actual, $message = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertLessThan', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that actual is less or equal than expected + * + * @param $expected + * @param $actual + * @param string $message + * @see \Codeception\Module\Asserts::assertLessThanOrEqual() + */ + public function assertLessThanOrEqual($expected, $actual, $message = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertLessThanOrEqual', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that haystack contains needle + * + * @param $needle + * @param $haystack + * @param string $message + * @see \Codeception\Module\Asserts::assertContains() + */ + public function assertContains($needle, $haystack, $message = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertContains', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that haystack doesn't contain needle. + * + * @param $needle + * @param $haystack + * @param string $message + * @see \Codeception\Module\Asserts::assertNotContains() + */ + public function assertNotContains($needle, $haystack, $message = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertNotContains', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that string match with pattern + * + * @param string $pattern + * @param string $string + * @param string $message + * @see \Codeception\Module\Asserts::assertRegExp() + */ + public function assertRegExp($pattern, $string, $message = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertRegExp', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that string not match with pattern + * + * @param string $pattern + * @param string $string + * @param string $message + * @see \Codeception\Module\Asserts::assertNotRegExp() + */ + public function assertNotRegExp($pattern, $string, $message = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertNotRegExp', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that a string starts with the given prefix. + * + * @param string $prefix + * @param string $string + * @param string $message + * @see \Codeception\Module\Asserts::assertStringStartsWith() + */ + public function assertStringStartsWith($prefix, $string, $message = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertStringStartsWith', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that a string doesn't start with the given prefix. + * + * @param string $prefix + * @param string $string + * @param string $message + * @see \Codeception\Module\Asserts::assertStringStartsNotWith() + */ + public function assertStringStartsNotWith($prefix, $string, $message = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertStringStartsNotWith', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that variable is empty. + * + * @param $actual + * @param string $message + * @see \Codeception\Module\Asserts::assertEmpty() + */ + public function assertEmpty($actual, $message = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertEmpty', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that variable is not empty. + * + * @param $actual + * @param string $message + * @see \Codeception\Module\Asserts::assertNotEmpty() + */ + public function assertNotEmpty($actual, $message = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertNotEmpty', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that variable is NULL + * + * @param $actual + * @param string $message + * @see \Codeception\Module\Asserts::assertNull() + */ + public function assertNull($actual, $message = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertNull', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that variable is not NULL + * + * @param $actual + * @param string $message + * @see \Codeception\Module\Asserts::assertNotNull() + */ + public function assertNotNull($actual, $message = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertNotNull', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that condition is positive. + * + * @param $condition + * @param string $message + * @see \Codeception\Module\Asserts::assertTrue() + */ + public function assertTrue($condition, $message = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertTrue', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that the condition is NOT true (everything but true) + * + * @param $condition + * @param string $message + * @see \Codeception\Module\Asserts::assertNotTrue() + */ + public function assertNotTrue($condition, $message = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertNotTrue', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that condition is negative. + * + * @param $condition + * @param string $message + * @see \Codeception\Module\Asserts::assertFalse() + */ + public function assertFalse($condition, $message = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertFalse', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that the condition is NOT false (everything but false) + * + * @param $condition + * @param string $message + * @see \Codeception\Module\Asserts::assertNotFalse() + */ + public function assertNotFalse($condition, $message = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertNotFalse', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks if file exists + * + * @param string $filename + * @param string $message + * @see \Codeception\Module\Asserts::assertFileExists() + */ + public function assertFileExists($filename, $message = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertFileExists', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks if file doesn't exist + * + * @param string $filename + * @param string $message + * @see \Codeception\Module\Asserts::assertFileNotExists() + */ + public function assertFileNotExists($filename, $message = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertFileNotExists', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * @param $expected + * @param $actual + * @param $description + * @see \Codeception\Module\Asserts::assertGreaterOrEquals() + */ + public function assertGreaterOrEquals($expected, $actual, $description = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertGreaterOrEquals', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * @param $expected + * @param $actual + * @param $description + * @see \Codeception\Module\Asserts::assertLessOrEquals() + */ + public function assertLessOrEquals($expected, $actual, $description = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertLessOrEquals', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * @param $actual + * @param $description + * @see \Codeception\Module\Asserts::assertIsEmpty() + */ + public function assertIsEmpty($actual, $description = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertIsEmpty', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * @param $key + * @param $actual + * @param $description + * @see \Codeception\Module\Asserts::assertArrayHasKey() + */ + public function assertArrayHasKey($key, $actual, $description = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertArrayHasKey', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * @param $key + * @param $actual + * @param $description + * @see \Codeception\Module\Asserts::assertArrayNotHasKey() + */ + public function assertArrayNotHasKey($key, $actual, $description = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertArrayNotHasKey', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that array contains subset. + * + * @param array $subset + * @param array $array + * @param bool $strict + * @param string $message + * @see \Codeception\Module\Asserts::assertArraySubset() + */ + public function assertArraySubset($subset, $array, $strict = null, $message = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertArraySubset', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * @param $expectedCount + * @param $actual + * @param $description + * @see \Codeception\Module\Asserts::assertCount() + */ + public function assertCount($expectedCount, $actual, $description = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertCount', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * @param $class + * @param $actual + * @param $description + * @see \Codeception\Module\Asserts::assertInstanceOf() + */ + public function assertInstanceOf($class, $actual, $description = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertInstanceOf', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * @param $class + * @param $actual + * @param $description + * @see \Codeception\Module\Asserts::assertNotInstanceOf() + */ + public function assertNotInstanceOf($class, $actual, $description = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertNotInstanceOf', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * @param $type + * @param $actual + * @param $description + * @see \Codeception\Module\Asserts::assertInternalType() + */ + public function assertInternalType($type, $actual, $description = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('assertInternalType', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Fails the test with message. + * + * @param $message + * @see \Codeception\Module\Asserts::fail() + */ + public function fail($message) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('fail', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Handles and checks exception called inside callback function. + * Either exception class name or exception instance should be provided. + * + * ```php + * expectException(MyException::class, function() { + * $this->doSomethingBad(); + * }); + * + * $I->expectException(new MyException(), function() { + * $this->doSomethingBad(); + * }); + * ``` + * If you want to check message or exception code, you can pass them with exception instance: + * ```php + * expectException(new MyException("Don't do bad things"), function() { + * $this->doSomethingBad(); + * }); + * ``` + * + * @param $exception string or \Exception + * @param $callback + * @see \Codeception\Module\Asserts::expectException() + */ + public function expectException($exception, $callback) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('expectException', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * + * @see \Codeception\Module\Db::isPopulated() + */ + public function isPopulated() { + return $this->getScenario()->runStep(new \Codeception\Step\Action('isPopulated', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Inserts an SQL record into a database. This record will be erased after the test. + * + * ```php + * haveInDatabase('users', array('name' => 'miles', 'email' => 'miles@davis.com')); + * ?> + * ``` + * + * @param string $table + * @param array $data + * + * @return integer $id + * @see \Codeception\Module\Db::haveInDatabase() + */ + public function haveInDatabase($table, $data) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('haveInDatabase', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Asserts that a row with the given column values exists. + * Provide table name and column values. + * + * ```php + * seeInDatabase('users', ['name' => 'Davert', 'email' => 'davert@mail.com']); + * ``` + * Fails if no such user found. + * + * Comparison expressions can be used as well: + * + * ```php + * seeInDatabase('posts', ['num_comments >=' => '0']); + * $I->seeInDatabase('users', ['email like' => 'miles@davis.com']); + * ``` + * + * Supported operators: `<`, `>`, `>=`, `<=`, `!=`, `like`. + * + * + * @param string $table + * @param array $criteria + * Conditional Assertion: Test won't be stopped on fail + * @see \Codeception\Module\Db::seeInDatabase() + */ + public function canSeeInDatabase($table, $criteria = null) { + return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeInDatabase', func_get_args())); + } + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Asserts that a row with the given column values exists. + * Provide table name and column values. + * + * ```php + * seeInDatabase('users', ['name' => 'Davert', 'email' => 'davert@mail.com']); + * ``` + * Fails if no such user found. + * + * Comparison expressions can be used as well: + * + * ```php + * seeInDatabase('posts', ['num_comments >=' => '0']); + * $I->seeInDatabase('users', ['email like' => 'miles@davis.com']); + * ``` + * + * Supported operators: `<`, `>`, `>=`, `<=`, `!=`, `like`. + * + * + * @param string $table + * @param array $criteria + * @see \Codeception\Module\Db::seeInDatabase() + */ + public function seeInDatabase($table, $criteria = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeInDatabase', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Asserts that the given number of records were found in the database. + * + * ```php + * seeNumRecords(1, 'users', ['name' => 'davert']) + * ?> + * ``` + * + * @param int $expectedNumber Expected number + * @param string $table Table name + * @param array $criteria Search criteria [Optional] + * Conditional Assertion: Test won't be stopped on fail + * @see \Codeception\Module\Db::seeNumRecords() + */ + public function canSeeNumRecords($expectedNumber, $table, $criteria = null) { + return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeNumRecords', func_get_args())); + } + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Asserts that the given number of records were found in the database. + * + * ```php + * seeNumRecords(1, 'users', ['name' => 'davert']) + * ?> + * ``` + * + * @param int $expectedNumber Expected number + * @param string $table Table name + * @param array $criteria Search criteria [Optional] + * @see \Codeception\Module\Db::seeNumRecords() + */ + public function seeNumRecords($expectedNumber, $table, $criteria = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeNumRecords', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Effect is opposite to ->seeInDatabase + * + * Asserts that there is no record with the given column values in a database. + * Provide table name and column values. + * + * ``` php + * dontSeeInDatabase('users', ['name' => 'Davert', 'email' => 'davert@mail.com']); + * ``` + * Fails if such user was found. + * + * Comparison expressions can be used as well: + * + * ```php + * dontSeeInDatabase('posts', ['num_comments >=' => '0']); + * $I->dontSeeInDatabase('users', ['email like' => 'miles%']); + * ``` + * + * Supported operators: `<`, `>`, `>=`, `<=`, `!=`, `like`. + * + * @param string $table + * @param array $criteria + * Conditional Assertion: Test won't be stopped on fail + * @see \Codeception\Module\Db::dontSeeInDatabase() + */ + public function cantSeeInDatabase($table, $criteria = null) { + return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeInDatabase', func_get_args())); + } + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Effect is opposite to ->seeInDatabase + * + * Asserts that there is no record with the given column values in a database. + * Provide table name and column values. + * + * ``` php + * dontSeeInDatabase('users', ['name' => 'Davert', 'email' => 'davert@mail.com']); + * ``` + * Fails if such user was found. + * + * Comparison expressions can be used as well: + * + * ```php + * dontSeeInDatabase('posts', ['num_comments >=' => '0']); + * $I->dontSeeInDatabase('users', ['email like' => 'miles%']); + * ``` + * + * Supported operators: `<`, `>`, `>=`, `<=`, `!=`, `like`. + * + * @param string $table + * @param array $criteria + * @see \Codeception\Module\Db::dontSeeInDatabase() + */ + public function dontSeeInDatabase($table, $criteria = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeInDatabase', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Fetches all values from the column in database. + * Provide table name, desired column and criteria. + * + * ``` php + * grabColumnFromDatabase('users', 'email', array('name' => 'RebOOter')); + * ``` + * + * @param string $table + * @param string $column + * @param array $criteria + * + * @return array + * @see \Codeception\Module\Db::grabColumnFromDatabase() + */ + public function grabColumnFromDatabase($table, $column, $criteria = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('grabColumnFromDatabase', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Fetches all values from the column in database. + * Provide table name, desired column and criteria. + * + * ``` php + * grabFromDatabase('users', 'email', array('name' => 'RebOOter')); + * ``` + * + * @param string $table + * @param string $column + * @param array $criteria + * + * @return array + * @see \Codeception\Module\Db::grabFromDatabase() + */ + public function grabFromDatabase($table, $column, $criteria = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('grabFromDatabase', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Returns the number of rows in a database + * + * @param string $table Table name + * @param array $criteria Search criteria [Optional] + * + * @return int + * @see \Codeception\Module\Db::grabNumRecords() + */ + public function grabNumRecords($table, $criteria = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('grabNumRecords', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Update an SQL record into a database. + * + * ```php + * updateInDatabase('users', array('isAdmin' => true), array('email' => 'miles@davis.com')); + * ?> + * ``` + * + * @param string $table + * @param array $data + * @param array $criteria + * @see \Codeception\Module\Db::updateInDatabase() + */ + public function updateInDatabase($table, $data, $criteria = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('updateInDatabase', func_get_args())); + } +} diff --git a/tests/unit/Codeception/Command/GenerateCestTest.php b/tests/unit/Codeception/Command/GenerateCestTest.php index b786844666..74764d49e3 100644 --- a/tests/unit/Codeception/Command/GenerateCestTest.php +++ b/tests/unit/Codeception/Command/GenerateCestTest.php @@ -23,7 +23,6 @@ public function testBasic() $this->assertContains('class HallUnderTheHillCest', $this->content); $this->assertContains('public function _before(HobbitGuy $I)', $this->content); - $this->assertContains('public function _after(HobbitGuy $I)', $this->content); $this->assertContains('public function tryToTest(HobbitGuy $I)', $this->content); $this->assertContains('Test was created in tests/shire/HallUnderTheHillCest.php', $this->output); } From 0c5f1cab4b1dfe5961ef6941a31ff3ec148d25bb Mon Sep 17 00:00:00 2001 From: Sam Date: Fri, 21 Sep 2018 13:51:18 +0200 Subject: [PATCH 119/395] TestMailer now stores messages in the connector. (#5185) * TestMailer now stores messages in the connector. * NitPick CI --- src/Codeception/Lib/Connector/Yii2.php | 20 +++++++---------- .../Lib/Connector/Yii2/TestMailer.php | 22 +++++++------------ 2 files changed, 16 insertions(+), 26 deletions(-) diff --git a/src/Codeception/Lib/Connector/Yii2.php b/src/Codeception/Lib/Connector/Yii2.php index 41e16a9b10..7e5821424e 100644 --- a/src/Codeception/Lib/Connector/Yii2.php +++ b/src/Codeception/Lib/Connector/Yii2.php @@ -13,6 +13,7 @@ use Yii; use yii\base\ExitException; use yii\base\Security; +use yii\mail\MessageInterface; use yii\web\Application; use yii\web\ErrorHandler; use yii\web\HttpException; @@ -79,6 +80,8 @@ class Yii2 extends Client */ public $recreateApplication = false; + + private $emails = []; /** * @return \yii\web\Application */ @@ -179,16 +182,7 @@ public function getInternalDomains() */ public function getEmails() { - $app = $this->getApplication(); - if ($app->has('mailer', true)) { - $mailer = $app->get('mailer'); - if ($mailer instanceof TestMailer) { - return $app->get('mailer')->getSentMessages(); - } else { - throw new ConfigurationException("Mailer module is not mocked, can't test emails"); - } - } - return []; + return $this->emails; } public function getComponent($name) @@ -257,7 +251,6 @@ public function startApp() $config = $this->mockMailer($config); /** @var \yii\web\Application $app */ Yii::$app = Yii::createObject($config); - Yii::setLogger(new Logger()); } @@ -417,7 +410,10 @@ protected function mockMailer(array $config) ]; $mailerConfig = [ - 'class' => 'Codeception\Lib\Connector\Yii2\TestMailer', + 'class' => TestMailer::class, + 'callback' => function (MessageInterface $message) { + $this->emails[] = $message; + } ]; if (isset($config['components']['mailer']) && is_array($config['components']['mailer'])) { diff --git a/src/Codeception/Lib/Connector/Yii2/TestMailer.php b/src/Codeception/Lib/Connector/Yii2/TestMailer.php index 93a09abf6a..4401e1ec2e 100644 --- a/src/Codeception/Lib/Connector/Yii2/TestMailer.php +++ b/src/Codeception/Lib/Connector/Yii2/TestMailer.php @@ -5,28 +5,22 @@ class TestMailer extends BaseMailer { - public $messageClass = 'yii\swiftmailer\Message'; + public $messageClass = \yii\swiftmailer\Message::class; - private $sentMessages = []; + /** + * @var \Closure + */ + public $callback; protected function sendMessage($message) { - $this->sentMessages[] = $message; + call_user_func($this->callback, $message); return true; } protected function saveMessage($message) { - return $this->sendMessage($message); - } - - public function getSentMessages() - { - return $this->sentMessages; - } - - public function reset() - { - $this->sentMessages = []; + call_user_func($this->callback, $message); + return true; } } From 4c9e137e2bc39a85ca937316de078098ea6a6455 Mon Sep 17 00:00:00 2001 From: Gintautas Miselis Date: Fri, 21 Sep 2018 14:55:27 +0300 Subject: [PATCH 120/395] [REST] Add response code assertions to json and xml parts (#5184) --- src/Codeception/Module/REST.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/Codeception/Module/REST.php b/src/Codeception/Module/REST.php index 759c98a3b5..df5af15797 100644 --- a/src/Codeception/Module/REST.php +++ b/src/Codeception/Module/REST.php @@ -1163,6 +1163,9 @@ public function dontSeeResponseCodeIs($code) /** * Checks that the response code is 2xx + * + * @part json + * @part xml */ public function seeResponseCodeIsSuccessful() { @@ -1171,6 +1174,9 @@ public function seeResponseCodeIsSuccessful() /** * Checks that the response code 3xx + * + * @part json + * @part xml */ public function seeResponseCodeIsRedirection() { @@ -1179,6 +1185,9 @@ public function seeResponseCodeIsRedirection() /** * Checks that the response code is 4xx + * + * @part json + * @part xml */ public function seeResponseCodeIsClientError() { @@ -1187,6 +1196,9 @@ public function seeResponseCodeIsClientError() /** * Checks that the response code is 5xx + * + * @part json + * @part xml */ public function seeResponseCodeIsServerError() { From 2a7e9c60debddafa2c44e9b08787fb7ee0a4d0aa Mon Sep 17 00:00:00 2001 From: Davert Date: Mon, 24 Sep 2018 00:21:05 +0300 Subject: [PATCH 121/395] Updated changelog --- CHANGELOG-2.4.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/CHANGELOG-2.4.md b/CHANGELOG-2.4.md index 8683fbd02a..82ae61fa3a 100644 --- a/CHANGELOG-2.4.md +++ b/CHANGELOG-2.4.md @@ -1,3 +1,24 @@ +#### 2.5.0 + +* [**Snapshot testing**](https://codeception.com/docs/09-Data#Testing-Dynamic-Data-with-Snapshots) introduced. Test dynamic data sets by comparing current values with previously saved ones. +* [Db] **Multi database support**. See #4857 by @eXorus + * `amConnectedToDatabase` method added. + * `performInDatabase` method added. +* [WebDriver] Keep coverage cookies in `loadSessionSnapshot`. Fix by @rajras +* [Yii2] Prevent null pointer exception by @SilverFire. See #5136 +* [Yii2] Fixed issue with empty response stream by @SamMousa. +* [Yii2] Fixed `Too many connections` issue #4926. By @roslov +* [Yii2] Fixed #4769: `amLoggedInAs()` throws TypeError. By @SamMousa +* [Recorder Extension] Fixing recorder extension issues caused by phpunit 7.2.7 update by @OneEyedSpaceFish +* [Logger Extension] Added `codecept_log` function to write to logs from any place. Fixes #3551 by @siad007 +* [WebDriver] Report correct strict locator in error message. When `see()` and `dontSee()` are used with array selector. Fix by @Naktibalda. +* [Phalcon] Use bind for find record. See #5158 by @Joilson +* [Phalcon] Add support for nullable fields in `findRecord()` by @arjanwestdorp +* Added `memory_limit` to `dry-run` command by @siad007. Fixes #5090 +* Added ext-curl to the composer require section by @siad007 +* Make `coverage: show_only_summary` configurable. See #5142 by @Quexer69 +* Ensure php extension `mbstring` is available by @siad007. Fixes #4575 + #### 2.4.5 * Fixed PHPUnit 7.2 compatibility. From 6da56e912ef279377a947347d045b0cb50605525 Mon Sep 17 00:00:00 2001 From: Siad Ardroumli Date: Mon, 24 Sep 2018 11:12:33 +0200 Subject: [PATCH 122/395] Added symfony xml support for parameter files. (#5191) * Added symfony xml support for parameter files. * Fixed formatting --- src/Codeception/Lib/ParamsLoader.php | 38 +++++++++++++++++++++++++++ tests/cli/ConfigParamsCest.php | 7 +++++ tests/data/params/codeception_xml.yml | 9 +++++++ tests/data/params/params.xml | 4 +++ 4 files changed, 58 insertions(+) create mode 100644 tests/data/params/codeception_xml.yml create mode 100644 tests/data/params/params.xml diff --git a/src/Codeception/Lib/ParamsLoader.php b/src/Codeception/Lib/ParamsLoader.php index b863c6dd5a..16ba23f954 100644 --- a/src/Codeception/Lib/ParamsLoader.php +++ b/src/Codeception/Lib/ParamsLoader.php @@ -43,6 +43,10 @@ public function load($paramStorage) if (preg_match('~(\.env(\.|$))~', $paramStorage)) { return $this->loadDotEnvFile(); } + + if (preg_match('~\.xml$~', $paramStorage)) { + return $this->loadXmlFile(); + } } catch (\Exception $e) { throw new ConfigurationException("Failed loading params from $paramStorage\n" . $e->getMessage()); } @@ -74,6 +78,40 @@ protected function loadYamlFile() return $params; } + protected function loadXmlFile() + { + $paramsToArray = function (\SimpleXMLElement $params) use (&$paramsToArray) { + $a = []; + foreach ($params as $param) { + $key = isset($param['key']) ? (string) $param['key'] : $param->getName(); + $type = isset($param['type']) ? (string) $param['type'] : 'string'; + $value = (string) $param; + switch ($type) { + case 'bool': + case 'boolean': + case 'int': + case 'integer': + case 'float': + case 'double': + $a[$key] = settype($value, $type); + break; + case 'constant': + $a[$key] = constant($value); + break; + case 'collection': + $a[$key] = $paramsToArray($param); + break; + default: + $a[$key] = (string) $param; + } + } + + return $a; + }; + + return $paramsToArray(simplexml_load_file($this->paramsFile)); + } + protected function loadDotEnvFile() { if (class_exists('Dotenv\Dotenv')) { diff --git a/tests/cli/ConfigParamsCest.php b/tests/cli/ConfigParamsCest.php index 6afba0bdd0..f5bcd31f2b 100644 --- a/tests/cli/ConfigParamsCest.php +++ b/tests/cli/ConfigParamsCest.php @@ -37,4 +37,11 @@ public function checkParamsPassedInSelf(CliGuy $I) $I->executeCommand('run -c codeception_self.yml'); $I->seeInShellOutput('OK (1 test'); } + + public function checkXmlParamsPassed(CliGuy $I) + { + $I->amInPath('tests/data/params'); + $I->executeCommand('run -c codeception_xml.yml'); + $I->seeInShellOutput('OK (1 test'); + } } diff --git a/tests/data/params/codeception_xml.yml b/tests/data/params/codeception_xml.yml new file mode 100644 index 0000000000..0ced03809b --- /dev/null +++ b/tests/data/params/codeception_xml.yml @@ -0,0 +1,9 @@ +actor: Tester +paths: + tests: tests + log: . + data: . + support: tests/_support +params: + - env + - params.xml diff --git a/tests/data/params/params.xml b/tests/data/params/params.xml new file mode 100644 index 0000000000..5fc87b8475 --- /dev/null +++ b/tests/data/params/params.xml @@ -0,0 +1,4 @@ + + val1 + val2 + From 170d89ae753d333edb05812ceac49851b4513244 Mon Sep 17 00:00:00 2001 From: Filippo Tessarotto Date: Mon, 24 Sep 2018 11:16:36 +0200 Subject: [PATCH 123/395] seeLink: fix partial href matching (#5187) * seeLink: fix partial href matching * Add bad path case for seeLink * Emulate ends-with --- src/Codeception/Lib/InnerBrowser.php | 4 ++-- tests/unit/Codeception/Module/TestsForWeb.php | 13 +++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/Codeception/Lib/InnerBrowser.php b/src/Codeception/Lib/InnerBrowser.php index fa41755b04..abe9c06897 100644 --- a/src/Codeception/Lib/InnerBrowser.php +++ b/src/Codeception/Lib/InnerBrowser.php @@ -504,7 +504,7 @@ public function seeLink($text, $url = null) $this->fail("No links containing text '$text' were found in page " . $this->_getCurrentUri()); } if ($url) { - $crawler = $crawler->filterXPath(sprintf('.//a[contains(@href, %s)]', Crawler::xpathLiteral($url))); + $crawler = $crawler->filterXPath(sprintf('.//a[substring(@href, string-length(@href) - string-length(%1$s) + 1)=%1$s]', Crawler::xpathLiteral($url))); if ($crawler->count() === 0) { $this->fail("No links containing text '$text' and URL '$url' were found in page " . $this->_getCurrentUri()); } @@ -520,7 +520,7 @@ public function dontSeeLink($text, $url = null) $this->fail("Link containing text '$text' was found in page " . $this->_getCurrentUri()); } } - $crawler = $crawler->filterXPath(sprintf('.//a[contains(@href, %s)]', Crawler::xpathLiteral($url))); + $crawler = $crawler->filterXPath(sprintf('.//a[substring(@href, string-length(@href) - string-length(%1$s) + 1)=%1$s]', Crawler::xpathLiteral($url))); if ($crawler->count() > 0) { $this->fail("Link containing text '$text' and URL '$url' was found in page " . $this->_getCurrentUri()); } diff --git a/tests/unit/Codeception/Module/TestsForWeb.php b/tests/unit/Codeception/Module/TestsForWeb.php index a37976582e..dc8fb94de2 100644 --- a/tests/unit/Codeception/Module/TestsForWeb.php +++ b/tests/unit/Codeception/Module/TestsForWeb.php @@ -116,6 +116,8 @@ public function testSeeLink() $this->module->amOnPage('/external_url'); $this->module->seeLink('Next'); $this->module->seeLink('Next', 'http://codeception.com/'); + // Without TLD and trailing slash + $this->module->dontSeeLink('Next', 'http://codeception'); } public function testDontSeeLink() @@ -145,6 +147,16 @@ public function testSeeLinkFailsIfHrefDoesNotMatch() $this->module->seeLink('Next', '/fsdfsdf/'); } + public function testSeeLinkFailsIfHrefDoesNotMatchExactly() + { + $this->setExpectedException( + 'PHPUnit\Framework\AssertionFailedError', + "No links containing text 'Next' and URL 'http://codeception' were found in page /external_url" + ); + $this->module->amOnPage('/external_url'); + $this->module->seeLink('Next', 'http://codeception'); + } + public function testDontSeeLinkFailsIfTextMatches() { $this->setExpectedException( @@ -169,6 +181,7 @@ public function testSeeLinkMatchesRelativeLink() { $this->module->amOnPage('/info'); $this->module->seeLink('Sign in!', '/login'); + $this->module->dontSeeLink('Sign in!', '/log'); } public function testDontSeeLinkMatchesRelativeLink() From 895e7e6d24eac5c9ce0aca39106f96a67667acb1 Mon Sep 17 00:00:00 2001 From: Michael Bodnarchuk Date: Mon, 24 Sep 2018 12:18:57 +0300 Subject: [PATCH 124/395] Improvements to seed on shuffle (#5192) * Implement command-line option for specifying shuffle seed value * Pass seed via userOptions * Fixed shuffle tests, improved output, added tests for shuffle * Added docs for shuffle and seed * disabled shuffle tests on windows --- docs/07-AdvancedUsage.md | 36 +++++++++ docs/reference/Commands.md | 1 + src/Codeception/Codecept.php | 2 + src/Codeception/Command/Run.php | 20 +++++ src/Codeception/Configuration.php | 3 +- .../DataProviderFailuresAndExceptionsCest.php | 4 +- tests/cli/RunCest.php | 41 +++++++++++ .../tests/_data/Snapshot.UserSnapshot.json | 2 +- .../_support/_generated/DataTesterActions.php | 73 +++++++++++++++++-- tests/support/CliHelper.php | 10 +++ 10 files changed, 183 insertions(+), 9 deletions(-) diff --git a/docs/07-AdvancedUsage.md b/docs/07-AdvancedUsage.md index df4fc85e92..cca1b20991 100644 --- a/docs/07-AdvancedUsage.md +++ b/docs/07-AdvancedUsage.md @@ -534,6 +534,42 @@ Signature: ModeratorCest:login` Codeception reorders tests so dependent tests will always be executed before the tests that rely on them. +### Shuffle + +By default Codeception runs tests in alphabetic order. +To ensure that tests are not depending on each other (unless explicitly declared via `@depends`) you can enable `shuffle` option. + +```yaml +# inside codeception.yml +settings: + shuffle: true +``` + +Alternatively, you may run tests in shuffle without changing the config: + +``` +codecept run -o "settings: shuffle: true" +``` + + +Tests will be randomly reordered on each run. When tests executed in shuffle mode a seed value will be printed. +Copy this seed value from output to be able to rerun tests in the same order. + +``` +$ codecept run +Codeception PHP Testing Framework v2.4.5 +Powered by PHPUnit 5.7.27 by Sebastian Bergmann and contributors. +[Seed] 1872290562 +``` + +Pass the copied seed into `--seed` option: + +``` +codecept run --seed 1872290562 +``` + + + ## Interactive Console The interactive console was added to try Codeception commands before executing them inside a test. diff --git a/docs/reference/Commands.md b/docs/reference/Commands.md index d94e112203..e7ae703394 100644 --- a/docs/reference/Commands.md +++ b/docs/reference/Commands.md @@ -169,6 +169,7 @@ Options: --ansi Force ANSI output. --no-ansi Disable ANSI output. --no-interaction (-n) Do not ask any interactive question. + --seed Use the given seed for shuffling tests ``` diff --git a/src/Codeception/Codecept.php b/src/Codeception/Codecept.php index 7ab393de3e..e47f90677e 100644 --- a/src/Codeception/Codecept.php +++ b/src/Codeception/Codecept.php @@ -185,7 +185,9 @@ public function runSuite($settings, $suite, $test = null) { $suiteManager = new SuiteManager($this->dispatcher, $suite, $settings); $suiteManager->initialize(); + srand($this->options['seed']); $suiteManager->loadTests($test); + srand(); $suiteManager->run($this->runner, $this->result, $this->options); return $this->result; } diff --git a/src/Codeception/Command/Run.php b/src/Codeception/Command/Run.php index 9f52aee220..85f8096d43 100644 --- a/src/Codeception/Command/Run.php +++ b/src/Codeception/Command/Run.php @@ -86,6 +86,7 @@ * --ansi Force ANSI output. * --no-ansi Disable ANSI output. * --no-interaction (-n) Do not ask any interactive question. + * --seed Use the given seed for shuffling tests * ``` * */ @@ -202,6 +203,13 @@ protected function configure() ), new InputOption('fail-fast', 'f', InputOption::VALUE_NONE, 'Stop after first failure'), new InputOption('no-rebuild', '', InputOption::VALUE_NONE, 'Do not rebuild actor classes on start'), + new InputOption( + 'seed', + '', + InputOption::VALUE_REQUIRED, + 'Define random seed for shuffle setting' + ), + ]); parent::configure(); @@ -241,6 +249,7 @@ public function execute(InputInterface $input, OutputInterface $output) if (!$this->options['colors']) { $this->options['colors'] = $config['settings']['colors']; } + if (!$this->options['silent']) { $this->output->writeln( Codecept::versionString() . "\nPowered by " . \PHPUnit\Runner\Version::getVersionString() @@ -269,6 +278,11 @@ public function execute(InputInterface $input, OutputInterface $output) $userOptions['interactive'] = !$input->hasParameterOption(['--no-interaction', '-n']); $userOptions['ansi'] = (!$input->hasParameterOption('--no-ansi') xor $input->hasParameterOption('ansi')); + if (!$this->options['seed']) { + $userOptions['seed'] = rand(); + } else { + $userOptions['seed'] = intval($this->options['seed']); + } if ($this->options['no-colors'] || !$userOptions['ansi']) { $userOptions['colors'] = false; } @@ -351,6 +365,12 @@ public function execute(InputInterface $input, OutputInterface $output) $userOptions['filter'] = $filter; } + if (!$this->options['silent'] && $config['settings']['shuffle']) { + $this->output->writeln( + "[Seed] " . $userOptions['seed'] . "" + ); + } + $this->codecept = new Codecept($userOptions); if ($suite and $test) { diff --git a/src/Codeception/Configuration.php b/src/Codeception/Configuration.php index 92e8061490..80254fcce4 100644 --- a/src/Codeception/Configuration.php +++ b/src/Codeception/Configuration.php @@ -94,7 +94,8 @@ class Configuration 'log_incomplete_skipped' => false, 'report_useless_tests' => false, 'disallow_test_output' => false, - 'be_strict_about_changes_to_global_state' => false + 'be_strict_about_changes_to_global_state' => false, + 'shuffle' => false, ], 'coverage' => [], 'params' => [], diff --git a/tests/cli/DataProviderFailuresAndExceptionsCest.php b/tests/cli/DataProviderFailuresAndExceptionsCest.php index 6fdec1cc10..fdf62aab46 100644 --- a/tests/cli/DataProviderFailuresAndExceptionsCest.php +++ b/tests/cli/DataProviderFailuresAndExceptionsCest.php @@ -29,7 +29,7 @@ public function runTestWithDataProvidersFailureStdout(\CliGuy $I) $devNull = (DIRECTORY_SEPARATOR === '\\')?'NUL':'/dev/null'; $I->executeCommand('run -n -v unit DataProvidersFailureCest 2> '.$devNull,false); // We should only see the version headers in stdout when there is this kind of failure. - $I->canSeeShellOutputMatches('/^Codeception PHP Testing Framework v[0-9\.]+\nPowered by PHPUnit .+ by Sebastian Bergmann and contributors\.$/'); + $I->canSeeShellOutputMatches('/^Codeception PHP Testing Framework v[0-9\.]+\nPowered by PHPUnit .+ by Sebastian Bergmann and contributors\./'); $I->seeResultCodeIs(1); } @@ -105,7 +105,7 @@ public function runTestWithDataProvidersExceptionStdout(\CliGuy $I) $devNull = (DIRECTORY_SEPARATOR === '\\')?'NUL':'/dev/null'; $I->executeCommand('run -n unit DataProvidersExceptionCest -v 2> '.$devNull, false); // Depending on the test environment, we either see nothing or just the headers here. - $I->canSeeShellOutputMatches('/^Codeception PHP Testing Framework v[0-9\.]+\nPowered by PHPUnit .+ by Sebastian Bergmann and contributors\.$/'); + $I->canSeeShellOutputMatches('/^Codeception PHP Testing Framework v[0-9\.]+\nPowered by PHPUnit .+ by Sebastian Bergmann and contributors\./'); $I->seeResultCodeIs(1); } diff --git a/tests/cli/RunCest.php b/tests/cli/RunCest.php index ddab45ea0c..17fc4fe482 100644 --- a/tests/cli/RunCest.php +++ b/tests/cli/RunCest.php @@ -495,4 +495,45 @@ public function runWarningTests(CliGuy $I) $I->seeInShellOutput('Warnings: 1.'); } + /** + * @group shuffle + * @param CliGuy $I + */ + public function showSeedNumberOnShuffle(CliGuy $I) + { + $I->executeCommand('run unit -o "settings: shuffle: true"', false); + $I->seeInShellOutput('Seed'); + $I->executeCommand('run unit', false); + $I->dontSeeInShellOutput('Seed'); + } + + + /** + * @group shuffle + * @param CliGuy $I + */ + public function showSameOrderOfFilesOnSeed(CliGuy $I, \Codeception\Scenario $s) + { + if (DIRECTORY_SEPARATOR === '\\') { + $s->skip('Failing on Windows. Need to investigate'); + } + $I->executeCommand('run unit -o "settings: shuffle: true"', false); + $I->seeInShellOutput('Seed'); + $output = $I->grabFromOutput('/---\n((.|\n)*?)---/m'); + $output = preg_replace('~\(\d\.\d+s\)~m', '', $output); + $seed = $I->grabFromOutput('~\[Seed\] (.*)~'); + + $I->executeCommand('run unit -o "settings: shuffle: true" --seed ' . $seed, false); + $newOutput = $I->grabFromOutput('/---\n((.|\n)*?)---/m'); + $newOutput = preg_replace('~\(\d\.\d+s\)~m', '', $newOutput); + + $I->assertEquals($output, $newOutput, 'order of tests is the same'); + + $I->executeCommand('run unit -o "settings: shuffle: true"', false); + $newOutput = $I->grabFromOutput('/---\n((.|\n)*?)---/m'); + $newOutput = preg_replace('~\(\d\.\d+s\)~m', '', $newOutput); + + $I->assertNotEquals($output, $newOutput, 'order of tests is the same'); + } + } diff --git a/tests/data/snapshots/tests/_data/Snapshot.UserSnapshot.json b/tests/data/snapshots/tests/_data/Snapshot.UserSnapshot.json index 6f9f799271..2b9da7b919 100644 --- a/tests/data/snapshots/tests/_data/Snapshot.UserSnapshot.json +++ b/tests/data/snapshots/tests/_data/Snapshot.UserSnapshot.json @@ -1 +1 @@ -["davert@mail.ua","nick@mail.ua","miles@davis.com","charlie@parker.com","hobgoblin@vasya.com"] \ No newline at end of file +["davert@mail.ua","nick@mail.ua","miles@davis.com","charlie@parker.com"] \ No newline at end of file diff --git a/tests/data/snapshots/tests/_support/_generated/DataTesterActions.php b/tests/data/snapshots/tests/_support/_generated/DataTesterActions.php index ba7da188e4..2bb00d11cd 100644 --- a/tests/data/snapshots/tests/_support/_generated/DataTesterActions.php +++ b/tests/data/snapshots/tests/_support/_generated/DataTesterActions.php @@ -1,4 +1,4 @@ -assertEquals($element->getChildrenCount(), 5); + * $I->assertEquals(5, $element->getChildrenCount()); * ``` * * Floating-point example: * ```php * assertEquals($calculator->add(0.1, 0.2), 0.3, 'Calculator should add the two numbers correctly.', 0.01); + * $I->assertEquals(0.3, $calculator->add(0.1, 0.2), 'Calculator should add the two numbers correctly.', 0.01); * ``` * * @param $expected @@ -53,13 +53,13 @@ public function assertEquals($expected, $actual, $message = null, $delta = null) * Regular example: * ```php * assertNotEquals($element->getChildrenCount(), 0); + * $I->assertNotEquals(0, $element->getChildrenCount()); * ``` * * Floating-point example: * ```php * assertNotEquals($calculator->add(0.1, 0.2), 0.4, 'Calculator should add the two numbers correctly.', 0.01); + * $I->assertNotEquals(0.4, $calculator->add(0.1, 0.2), 'Calculator should add the two numbers correctly.', 0.01); * ``` * * @param $expected @@ -572,6 +572,69 @@ public function expectException($exception, $callback) { } + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Make sure you are connected to the right database. + * + * ```php + * seeNumRecords(2, 'users'); //executed on default database + * $I->amConnectedToDatabase('db_books'); + * $I->seeNumRecords(30, 'books'); //executed on db_books database + * //All the next queries will be on db_books + * ``` + * @param $databaseKey + * @throws ModuleConfigException + * @see \Codeception\Module\Db::amConnectedToDatabase() + */ + public function amConnectedToDatabase($databaseKey) { + return $this->getScenario()->runStep(new \Codeception\Step\Condition('amConnectedToDatabase', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Can be used with a callback if you don't want to change the current database in your test. + * + * ```php + * seeNumRecords(2, 'users'); //executed on default database + * $I->performInDatabase('db_books', function($I) { + * $I->seeNumRecords(30, 'books'); //executed on db_books database + * }); + * $I->seeNumRecords(2, 'users'); //executed on default database + * ``` + * List of actions can be pragmatically built using `Codeception\Util\ActionSequence`: + * + * ```php + * performInDatabase('db_books', ActionSequence::build() + * ->seeNumRecords(30, 'books') + * ); + * ``` + * Alternatively an array can be used: + * + * ```php + * $I->performInDatabase('db_books', ['seeNumRecords' => [30, 'books']]); + * ``` + * + * Choose the syntax you like the most and use it, + * + * Actions executed from array or ActionSequence will print debug output for actions, and adds an action name to + * exception on failure. + * + * @param $databaseKey + * @param actions $actions + * @throws ModuleConfigException + * @see \Codeception\Module\Db::performInDatabase() + */ + public function performInDatabase($databaseKey, $actions) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('performInDatabase', func_get_args())); + } + + /** * [!] Method is generated. Documentation taken from corresponding module. * diff --git a/tests/support/CliHelper.php b/tests/support/CliHelper.php index 8135ac08f5..448a22fd1f 100644 --- a/tests/support/CliHelper.php +++ b/tests/support/CliHelper.php @@ -34,6 +34,16 @@ public function executeFailCommand($command) $this->getModule('Cli')->runShellCommand('php '.\Codeception\Configuration::projectDir().'codecept '.$command.' -n', false); } + public function grabFromOutput($regex) + { + $match = []; + $found = preg_match($regex, $this->getModule('Cli')->output, $match); + if (!$found) { + return ''; + } + return $match[1]; + } + public function seeDirFound($dir) { $this->assertTrue(is_dir($dir) && file_exists($dir), "Directory does not exist"); From dee493561daf644134c95cf176fd2c25aff59ea9 Mon Sep 17 00:00:00 2001 From: Davert Date: Mon, 24 Sep 2018 12:33:01 +0300 Subject: [PATCH 125/395] updated changelog, version bump --- CHANGELOG-2.4.md | 21 --------------------- CHANGELOG-2.5.md | 21 +++++++++++++++++++++ RoboFile.php | 2 +- src/Codeception/Codecept.php | 2 +- 4 files changed, 23 insertions(+), 23 deletions(-) create mode 100644 CHANGELOG-2.5.md diff --git a/CHANGELOG-2.4.md b/CHANGELOG-2.4.md index 82ae61fa3a..8683fbd02a 100644 --- a/CHANGELOG-2.4.md +++ b/CHANGELOG-2.4.md @@ -1,24 +1,3 @@ -#### 2.5.0 - -* [**Snapshot testing**](https://codeception.com/docs/09-Data#Testing-Dynamic-Data-with-Snapshots) introduced. Test dynamic data sets by comparing current values with previously saved ones. -* [Db] **Multi database support**. See #4857 by @eXorus - * `amConnectedToDatabase` method added. - * `performInDatabase` method added. -* [WebDriver] Keep coverage cookies in `loadSessionSnapshot`. Fix by @rajras -* [Yii2] Prevent null pointer exception by @SilverFire. See #5136 -* [Yii2] Fixed issue with empty response stream by @SamMousa. -* [Yii2] Fixed `Too many connections` issue #4926. By @roslov -* [Yii2] Fixed #4769: `amLoggedInAs()` throws TypeError. By @SamMousa -* [Recorder Extension] Fixing recorder extension issues caused by phpunit 7.2.7 update by @OneEyedSpaceFish -* [Logger Extension] Added `codecept_log` function to write to logs from any place. Fixes #3551 by @siad007 -* [WebDriver] Report correct strict locator in error message. When `see()` and `dontSee()` are used with array selector. Fix by @Naktibalda. -* [Phalcon] Use bind for find record. See #5158 by @Joilson -* [Phalcon] Add support for nullable fields in `findRecord()` by @arjanwestdorp -* Added `memory_limit` to `dry-run` command by @siad007. Fixes #5090 -* Added ext-curl to the composer require section by @siad007 -* Make `coverage: show_only_summary` configurable. See #5142 by @Quexer69 -* Ensure php extension `mbstring` is available by @siad007. Fixes #4575 - #### 2.4.5 * Fixed PHPUnit 7.2 compatibility. diff --git a/CHANGELOG-2.5.md b/CHANGELOG-2.5.md new file mode 100644 index 0000000000..fc1eecfb89 --- /dev/null +++ b/CHANGELOG-2.5.md @@ -0,0 +1,21 @@ +#### 2.5.0 + +* [**Snapshot testing**](https://codeception.com/docs/09-Data#Testing-Dynamic-Data-with-Snapshots) introduced. Test dynamic data sets by comparing current values with previously saved ones. +* [Db] **Multi database support**. See #4857 by @eXorus + * `amConnectedToDatabase` method added. + * `performInDatabase` method added. +* Rerun tests in **[shuffle mode](https://codeception.com/docs/07-AdvancedUsage#Shuffle)** in the same order by setting seed value. By @SamMousa +* [WebDriver] Keep coverage cookies in `loadSessionSnapshot`. Fix by @rajras +* [Yii2] Prevent null pointer exception by @SilverFire. See #5136 +* [Yii2] Fixed issue with empty response stream by @SamMousa. +* [Yii2] Fixed `Too many connections` issue #4926. By @roslov +* [Yii2] Fixed #4769: `amLoggedInAs()` throws TypeError. By @SamMousa +* [Recorder Extension] Fixing recorder extension issues caused by phpunit 7.2.7 update by @OneEyedSpaceFish +* [Logger Extension] Added `codecept_log` function to write to logs from any place. Fixes #3551 by @siad007 +* [WebDriver] Report correct strict locator in error message. When `see()` and `dontSee()` are used with array selector. Fix by @Naktibalda. +* [Phalcon] Use bind for find record. See #5158 by @Joilson +* [Phalcon] Add support for nullable fields in `findRecord()` by @arjanwestdorp +* Added `memory_limit` to `dry-run` command by @siad007. Fixes #5090 +* Added ext-curl to the composer require section by @siad007 +* Make `coverage: show_only_summary` configurable. See #5142 by @Quexer69 +* Ensure php extension `mbstring` is available by @siad007. Fixes #4575 diff --git a/RoboFile.php b/RoboFile.php index 71c4e48543..8a62ae21e1 100644 --- a/RoboFile.php +++ b/RoboFile.php @@ -6,7 +6,7 @@ class RoboFile extends \Robo\Tasks { - const STABLE_BRANCH = '2.4'; + const STABLE_BRANCH = '2.5'; const REPO_BLOB_URL = 'https://github.com/Codeception/Codeception/blob'; public function release() diff --git a/src/Codeception/Codecept.php b/src/Codeception/Codecept.php index e47f90677e..d6934f09ad 100644 --- a/src/Codeception/Codecept.php +++ b/src/Codeception/Codecept.php @@ -7,7 +7,7 @@ class Codecept { - const VERSION = "2.4.5"; + const VERSION = "2.5.0"; /** * @var \Codeception\PHPUnit\Runner From cc739e8a049309842e88d8f5389f47826549ca7f Mon Sep 17 00:00:00 2001 From: Davert Date: Mon, 24 Sep 2018 15:50:43 +0300 Subject: [PATCH 126/395] updated changlog --- CHANGELOG-2.5.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG-2.5.md b/CHANGELOG-2.5.md index fc1eecfb89..20cdc6de62 100644 --- a/CHANGELOG-2.5.md +++ b/CHANGELOG-2.5.md @@ -5,6 +5,9 @@ * `amConnectedToDatabase` method added. * `performInDatabase` method added. * Rerun tests in **[shuffle mode](https://codeception.com/docs/07-AdvancedUsage#Shuffle)** in the same order by setting seed value. By @SamMousa +* [PhpBrowser][Frameworks] **Breaking Change** `seeLink` now matches the end of a URL, instead of partial matching. By @Slamdunk + * Previous: `$I->seeLink('Delete','/post/1');` matches `Delete` + * Now: `$I->seeLink('Delete','/post/1');` does NOT match `Delete` * [WebDriver] Keep coverage cookies in `loadSessionSnapshot`. Fix by @rajras * [Yii2] Prevent null pointer exception by @SilverFire. See #5136 * [Yii2] Fixed issue with empty response stream by @SamMousa. From 6d8935f388517afc9a6a43e384457e35207ab471 Mon Sep 17 00:00:00 2001 From: Joseph Zidell Date: Mon, 24 Sep 2018 09:31:48 -0400 Subject: [PATCH 127/395] Removes debug Removes debug in new code --- src/Codeception/Step.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Codeception/Step.php b/src/Codeception/Step.php index 260bb24682..06b0796f8c 100644 --- a/src/Codeception/Step.php +++ b/src/Codeception/Step.php @@ -305,7 +305,6 @@ protected function addMetaStep($step, $stack) }, array_values($step['args']))); $this->metaStep->setTraceInfo($step['file'], $step['line']); - codecept_debug(get_class($step['object'])); // pageobjects or other classes should not be included with "I" if (!in_array('Codeception\Actor', class_parents($step['class']))) { if (isset($step['object'])) { From e57a45e014405d690ecd7f17728dd9e968355142 Mon Sep 17 00:00:00 2001 From: Filippo Tessarotto Date: Wed, 26 Sep 2018 11:05:43 +0200 Subject: [PATCH 128/395] [Yii2] Restore getApplication() API --- src/Codeception/Lib/Connector/Yii2.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Codeception/Lib/Connector/Yii2.php b/src/Codeception/Lib/Connector/Yii2.php index 7e5821424e..1d18d601e8 100644 --- a/src/Codeception/Lib/Connector/Yii2.php +++ b/src/Codeception/Lib/Connector/Yii2.php @@ -85,7 +85,7 @@ class Yii2 extends Client /** * @return \yii\web\Application */ - protected function getApplication() + public function getApplication() { if (!isset(Yii::$app)) { $this->startApp(); From c961b1140550bd141501ae8e1c3ca1f570bab0c3 Mon Sep 17 00:00:00 2001 From: Filippo Tessarotto Date: Wed, 26 Sep 2018 13:56:26 +0200 Subject: [PATCH 129/395] Add deprecation doc to getApplication() --- src/Codeception/Lib/Connector/Yii2.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Codeception/Lib/Connector/Yii2.php b/src/Codeception/Lib/Connector/Yii2.php index 1d18d601e8..71bb8d895d 100644 --- a/src/Codeception/Lib/Connector/Yii2.php +++ b/src/Codeception/Lib/Connector/Yii2.php @@ -82,8 +82,11 @@ class Yii2 extends Client private $emails = []; + /** * @return \yii\web\Application + * + * @deprecated since 2.5, will become protected in 3.0. Use getComponent() or directly access to \Yii::$app. */ public function getApplication() { From 6fa428b54a8cf60a25d853102f008c19ac9efa48 Mon Sep 17 00:00:00 2001 From: Filippo Tessarotto Date: Wed, 26 Sep 2018 14:35:31 +0200 Subject: [PATCH 130/395] Mark new API as @internal --- src/Codeception/Lib/Connector/Yii2.php | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/Codeception/Lib/Connector/Yii2.php b/src/Codeception/Lib/Connector/Yii2.php index 71bb8d895d..68f2e3f620 100644 --- a/src/Codeception/Lib/Connector/Yii2.php +++ b/src/Codeception/Lib/Connector/Yii2.php @@ -86,7 +86,7 @@ class Yii2 extends Client /** * @return \yii\web\Application * - * @deprecated since 2.5, will become protected in 3.0. Use getComponent() or directly access to \Yii::$app. + * @deprecated since 2.5, will become protected in 3.0. Directly access to \Yii::$app if you need to interact with it. */ public function getApplication() { @@ -112,6 +112,7 @@ public function resetApplication() /** * Finds and logs in a user + * @internal * @param $user * @throws ConfigurationException * @throws \RuntimeException @@ -138,6 +139,7 @@ public function findAndLoginUser($user) /** * Masks a value + * @internal * @param string $val * @return string * @see \yii\base\Security::maskToken @@ -148,6 +150,7 @@ public function maskToken($val) } /** + * @internal * @param string $name The name of the cookie * @param string $value The value of the cookie * @return string The value to send to the browser @@ -162,6 +165,7 @@ public function hashCookieData($name, $value) } /** + * @internal * @return array List of regex patterns for recognized domain names */ public function getInternalDomains() @@ -181,6 +185,7 @@ public function getInternalDomains() } /** + * @internal * @return array List of sent emails */ public function getEmails() @@ -188,6 +193,9 @@ public function getEmails() return $this->emails; } + /** + * @internal + */ public function getComponent($name) { $app = $this->getApplication(); @@ -227,6 +235,7 @@ function ($matches) use (&$parameters) { /** * Gets the name of the CSRF param. + * @internal * @return string */ public function getCsrfParamName() @@ -235,6 +244,7 @@ public function getCsrfParamName() } /** + * @internal * @param $params * @return mixed */ @@ -439,6 +449,7 @@ public function restart() /** * This functions closes the session of the application, if the application exists and has a session. + * @internal */ public function closeSession() { From 72458d7298ab535160b48306f904f03955657707 Mon Sep 17 00:00:00 2001 From: Joseph Zidell Date: Thu, 4 Oct 2018 08:56:24 -0400 Subject: [PATCH 131/395] Fixes PHPStan issue (#5204) * Fixes PHPStan issue Uses full namespace for docblock, allowing PHPStan to find the class when using namespaces * Fixes docblock (#2) * Alphabetize types --- src/Codeception/Module/Db.php | 2 +- src/Codeception/Module/WebDriver.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Codeception/Module/Db.php b/src/Codeception/Module/Db.php index 1a6323bec4..6ee0c91321 100644 --- a/src/Codeception/Module/Db.php +++ b/src/Codeception/Module/Db.php @@ -374,7 +374,7 @@ public function amConnectedToDatabase($databaseKey) * exception on failure. * * @param $databaseKey - * @param actions $actions + * @param \Codeception\Util\ActionSequence|array|callable $actions * @throws ModuleConfigException */ public function performInDatabase($databaseKey, $actions) diff --git a/src/Codeception/Module/WebDriver.php b/src/Codeception/Module/WebDriver.php index a64efc3b01..d59a34621f 100644 --- a/src/Codeception/Module/WebDriver.php +++ b/src/Codeception/Module/WebDriver.php @@ -531,7 +531,7 @@ public function _failed(TestInterface $test, $fail) /** * Print out latest Selenium Logs in debug mode * - * @param TestInterface $test + * @param \Codeception\TestInterface $test */ public function debugWebDriverLogs(TestInterface $test = null) { From d1c9028776b11c30fa2bbdd6483852a01a5125d1 Mon Sep 17 00:00:00 2001 From: Gordon Franke Date: Thu, 4 Oct 2018 14:59:27 +0200 Subject: [PATCH 132/395] correct regex to root url (#5207) --- docs/03-AcceptanceTests.md | 4 ++-- docs/modules/AngularJS.md | 6 +++--- docs/modules/Laravel5.md | 6 +++--- docs/modules/Lumen.md | 6 +++--- docs/modules/Phalcon.md | 6 +++--- docs/modules/PhpBrowser.md | 6 +++--- docs/modules/Silex.md | 6 +++--- docs/modules/Symfony.md | 6 +++--- docs/modules/WebDriver.md | 6 +++--- docs/modules/Yii1.md | 6 +++--- docs/modules/Yii2.md | 6 +++--- docs/modules/ZF1.md | 6 +++--- docs/modules/ZF2.md | 6 +++--- docs/modules/ZendExpressive.md | 6 +++--- src/Codeception/Lib/Interfaces/Web.php | 6 +++--- 15 files changed, 44 insertions(+), 44 deletions(-) diff --git a/docs/03-AcceptanceTests.md b/docs/03-AcceptanceTests.md index fb7d600a34..b31f55d63f 100644 --- a/docs/03-AcceptanceTests.md +++ b/docs/03-AcceptanceTests.md @@ -337,9 +337,9 @@ Actions for URLs: ```php seeCurrentUrlEquals('/login'); -$I->seeCurrentUrlMatches('~$/users/(\d+)~'); +$I->seeCurrentUrlMatches('~^/users/(\d+)~'); $I->seeInCurrentUrl('user/1'); -$user_id = $I->grabFromCurrentUrl('~$/user/(\d+)/~'); +$user_id = $I->grabFromCurrentUrl('~^/user/(\d+)/~'); ``` ## WebDriver diff --git a/docs/modules/AngularJS.md b/docs/modules/AngularJS.md index e20555c2e8..f92163bb83 100644 --- a/docs/modules/AngularJS.md +++ b/docs/modules/AngularJS.md @@ -554,7 +554,7 @@ Checks that current url doesn't match the given regular expression. ``` php dontSeeCurrentUrlMatches('~$/users/(\d+)~'); +$I->dontSeeCurrentUrlMatches('~^/users/(\d+)~'); ?> ``` @@ -859,7 +859,7 @@ If no parameters are provided, the full URI is returned. ``` php grabFromCurrentUrl('~$/user/(\d+)/~'); +$user_id = $I->grabFromCurrentUrl('~^/user/(\d+)/~'); $uri = $I->grabFromCurrentUrl(); ?> ``` @@ -1257,7 +1257,7 @@ Checks that the current URL matches the given regular expression. ``` php seeCurrentUrlMatches('~$/users/(\d+)~'); +$I->seeCurrentUrlMatches('~^/users/(\d+)~'); ?> ``` diff --git a/docs/modules/Laravel5.md b/docs/modules/Laravel5.md index 3597158a4a..67f4bace9b 100644 --- a/docs/modules/Laravel5.md +++ b/docs/modules/Laravel5.md @@ -514,7 +514,7 @@ Checks that current url doesn't match the given regular expression. ``` php dontSeeCurrentUrlMatches('~$/users/(\d+)~'); +$I->dontSeeCurrentUrlMatches('~^/users/(\d+)~'); ?> ``` @@ -792,7 +792,7 @@ If no parameters are provided, the full URI is returned. ``` php grabFromCurrentUrl('~$/user/(\d+)/~'); +$user_id = $I->grabFromCurrentUrl('~^/user/(\d+)/~'); $uri = $I->grabFromCurrentUrl(); ?> ``` @@ -1232,7 +1232,7 @@ Checks that the current URL matches the given regular expression. ``` php seeCurrentUrlMatches('~$/users/(\d+)~'); +$I->seeCurrentUrlMatches('~^/users/(\d+)~'); ?> ``` diff --git a/docs/modules/Lumen.md b/docs/modules/Lumen.md index e6a49f9f54..2376139d07 100644 --- a/docs/modules/Lumen.md +++ b/docs/modules/Lumen.md @@ -378,7 +378,7 @@ Checks that current url doesn't match the given regular expression. ``` php dontSeeCurrentUrlMatches('~$/users/(\d+)~'); +$I->dontSeeCurrentUrlMatches('~^/users/(\d+)~'); ?> ``` @@ -617,7 +617,7 @@ If no parameters are provided, the full URI is returned. ``` php grabFromCurrentUrl('~$/user/(\d+)/~'); +$user_id = $I->grabFromCurrentUrl('~^/user/(\d+)/~'); $uri = $I->grabFromCurrentUrl(); ?> ``` @@ -1006,7 +1006,7 @@ Checks that the current URL matches the given regular expression. ``` php seeCurrentUrlMatches('~$/users/(\d+)~'); +$I->seeCurrentUrlMatches('~^/users/(\d+)~'); ?> ``` diff --git a/docs/modules/Phalcon.md b/docs/modules/Phalcon.md index b454e2c911..eeb41f6db1 100644 --- a/docs/modules/Phalcon.md +++ b/docs/modules/Phalcon.md @@ -400,7 +400,7 @@ Checks that current url doesn't match the given regular expression. ``` php dontSeeCurrentUrlMatches('~$/users/(\d+)~'); +$I->dontSeeCurrentUrlMatches('~^/users/(\d+)~'); ?> ``` @@ -638,7 +638,7 @@ If no parameters are provided, the full URI is returned. ``` php grabFromCurrentUrl('~$/user/(\d+)/~'); +$user_id = $I->grabFromCurrentUrl('~^/user/(\d+)/~'); $uri = $I->grabFromCurrentUrl(); ?> ``` @@ -923,7 +923,7 @@ Checks that the current URL matches the given regular expression. ``` php seeCurrentUrlMatches('~$/users/(\d+)~'); +$I->seeCurrentUrlMatches('~^/users/(\d+)~'); ?> ``` diff --git a/docs/modules/PhpBrowser.md b/docs/modules/PhpBrowser.md index b0b658fae4..f990ceab0e 100644 --- a/docs/modules/PhpBrowser.md +++ b/docs/modules/PhpBrowser.md @@ -396,7 +396,7 @@ Checks that current url doesn't match the given regular expression. ``` php dontSeeCurrentUrlMatches('~$/users/(\d+)~'); +$I->dontSeeCurrentUrlMatches('~^/users/(\d+)~'); ?> ``` @@ -632,7 +632,7 @@ If no parameters are provided, the full URI is returned. ``` php grabFromCurrentUrl('~$/user/(\d+)/~'); +$user_id = $I->grabFromCurrentUrl('~^/user/(\d+)/~'); $uri = $I->grabFromCurrentUrl(); ?> ``` @@ -832,7 +832,7 @@ Checks that the current URL matches the given regular expression. ``` php seeCurrentUrlMatches('~$/users/(\d+)~'); +$I->seeCurrentUrlMatches('~^/users/(\d+)~'); ?> ``` diff --git a/docs/modules/Silex.md b/docs/modules/Silex.md index 1e1b7f7e1f..d737f80af3 100644 --- a/docs/modules/Silex.md +++ b/docs/modules/Silex.md @@ -344,7 +344,7 @@ Checks that current url doesn't match the given regular expression. ``` php dontSeeCurrentUrlMatches('~$/users/(\d+)~'); +$I->dontSeeCurrentUrlMatches('~^/users/(\d+)~'); ?> ``` @@ -566,7 +566,7 @@ If no parameters are provided, the full URI is returned. ``` php grabFromCurrentUrl('~$/user/(\d+)/~'); +$user_id = $I->grabFromCurrentUrl('~^/user/(\d+)/~'); $uri = $I->grabFromCurrentUrl(); ?> ``` @@ -780,7 +780,7 @@ Checks that the current URL matches the given regular expression. ``` php seeCurrentUrlMatches('~$/users/(\d+)~'); +$I->seeCurrentUrlMatches('~^/users/(\d+)~'); ?> ``` diff --git a/docs/modules/Symfony.md b/docs/modules/Symfony.md index b2c14f3b89..4cfe4d2ec5 100644 --- a/docs/modules/Symfony.md +++ b/docs/modules/Symfony.md @@ -407,7 +407,7 @@ Checks that current url doesn't match the given regular expression. ``` php dontSeeCurrentUrlMatches('~$/users/(\d+)~'); +$I->dontSeeCurrentUrlMatches('~^/users/(\d+)~'); ?> ``` @@ -629,7 +629,7 @@ If no parameters are provided, the full URI is returned. ``` php grabFromCurrentUrl('~$/user/(\d+)/~'); +$user_id = $I->grabFromCurrentUrl('~^/user/(\d+)/~'); $uri = $I->grabFromCurrentUrl(); ?> ``` @@ -909,7 +909,7 @@ Checks that the current URL matches the given regular expression. ``` php seeCurrentUrlMatches('~$/users/(\d+)~'); +$I->seeCurrentUrlMatches('~^/users/(\d+)~'); ?> ``` diff --git a/docs/modules/WebDriver.md b/docs/modules/WebDriver.md index 785dd84082..6f7259b12f 100644 --- a/docs/modules/WebDriver.md +++ b/docs/modules/WebDriver.md @@ -738,7 +738,7 @@ Checks that current url doesn't match the given regular expression. ``` php dontSeeCurrentUrlMatches('~$/users/(\d+)~'); +$I->dontSeeCurrentUrlMatches('~^/users/(\d+)~'); ?> ``` @@ -1043,7 +1043,7 @@ If no parameters are provided, the full URI is returned. ``` php grabFromCurrentUrl('~$/user/(\d+)/~'); +$user_id = $I->grabFromCurrentUrl('~^/user/(\d+)/~'); $uri = $I->grabFromCurrentUrl(); ?> ``` @@ -1441,7 +1441,7 @@ Checks that the current URL matches the given regular expression. ``` php seeCurrentUrlMatches('~$/users/(\d+)~'); +$I->seeCurrentUrlMatches('~^/users/(\d+)~'); ?> ``` diff --git a/docs/modules/Yii1.md b/docs/modules/Yii1.md index 3112f39876..c3af2eadb6 100644 --- a/docs/modules/Yii1.md +++ b/docs/modules/Yii1.md @@ -406,7 +406,7 @@ Checks that current url doesn't match the given regular expression. ``` php dontSeeCurrentUrlMatches('~$/users/(\d+)~'); +$I->dontSeeCurrentUrlMatches('~^/users/(\d+)~'); ?> ``` @@ -628,7 +628,7 @@ If no parameters are provided, the full URI is returned. ``` php grabFromCurrentUrl('~$/user/(\d+)/~'); +$user_id = $I->grabFromCurrentUrl('~^/user/(\d+)/~'); $uri = $I->grabFromCurrentUrl(); ?> ``` @@ -828,7 +828,7 @@ Checks that the current URL matches the given regular expression. ``` php seeCurrentUrlMatches('~$/users/(\d+)~'); +$I->seeCurrentUrlMatches('~^/users/(\d+)~'); ?> ``` diff --git a/docs/modules/Yii2.md b/docs/modules/Yii2.md index 62adfebb6b..10fd81cde4 100644 --- a/docs/modules/Yii2.md +++ b/docs/modules/Yii2.md @@ -464,7 +464,7 @@ Checks that current url doesn't match the given regular expression. ``` php dontSeeCurrentUrlMatches('~$/users/(\d+)~'); +$I->dontSeeCurrentUrlMatches('~^/users/(\d+)~'); ?> ``` @@ -749,7 +749,7 @@ If no parameters are provided, the full URI is returned. ``` php grabFromCurrentUrl('~$/user/(\d+)/~'); +$user_id = $I->grabFromCurrentUrl('~^/user/(\d+)/~'); $uri = $I->grabFromCurrentUrl(); ?> ``` @@ -1044,7 +1044,7 @@ Checks that the current URL matches the given regular expression. ``` php seeCurrentUrlMatches('~$/users/(\d+)~'); +$I->seeCurrentUrlMatches('~^/users/(\d+)~'); ?> ``` diff --git a/docs/modules/ZF1.md b/docs/modules/ZF1.md index cefb62e2df..fbb0aa78fe 100644 --- a/docs/modules/ZF1.md +++ b/docs/modules/ZF1.md @@ -370,7 +370,7 @@ Checks that current url doesn't match the given regular expression. ``` php dontSeeCurrentUrlMatches('~$/users/(\d+)~'); +$I->dontSeeCurrentUrlMatches('~^/users/(\d+)~'); ?> ``` @@ -585,7 +585,7 @@ If no parameters are provided, the full URI is returned. ``` php grabFromCurrentUrl('~$/user/(\d+)/~'); +$user_id = $I->grabFromCurrentUrl('~^/user/(\d+)/~'); $uri = $I->grabFromCurrentUrl(); ?> ``` @@ -800,7 +800,7 @@ Checks that the current URL matches the given regular expression. ``` php seeCurrentUrlMatches('~$/users/(\d+)~'); +$I->seeCurrentUrlMatches('~^/users/(\d+)~'); ?> ``` diff --git a/docs/modules/ZF2.md b/docs/modules/ZF2.md index edc01c6a4b..a1f9f77122 100644 --- a/docs/modules/ZF2.md +++ b/docs/modules/ZF2.md @@ -364,7 +364,7 @@ Checks that current url doesn't match the given regular expression. ``` php dontSeeCurrentUrlMatches('~$/users/(\d+)~'); +$I->dontSeeCurrentUrlMatches('~^/users/(\d+)~'); ?> ``` @@ -579,7 +579,7 @@ If no parameters are provided, the full URI is returned. ``` php grabFromCurrentUrl('~$/user/(\d+)/~'); +$user_id = $I->grabFromCurrentUrl('~^/user/(\d+)/~'); $uri = $I->grabFromCurrentUrl(); ?> ``` @@ -809,7 +809,7 @@ Checks that the current URL matches the given regular expression. ``` php seeCurrentUrlMatches('~$/users/(\d+)~'); +$I->seeCurrentUrlMatches('~^/users/(\d+)~'); ?> ``` diff --git a/docs/modules/ZendExpressive.md b/docs/modules/ZendExpressive.md index 04b032af71..b84f8b2ad9 100644 --- a/docs/modules/ZendExpressive.md +++ b/docs/modules/ZendExpressive.md @@ -320,7 +320,7 @@ Checks that current url doesn't match the given regular expression. ``` php dontSeeCurrentUrlMatches('~$/users/(\d+)~'); +$I->dontSeeCurrentUrlMatches('~^/users/(\d+)~'); ?> ``` @@ -535,7 +535,7 @@ If no parameters are provided, the full URI is returned. ``` php grabFromCurrentUrl('~$/user/(\d+)/~'); +$user_id = $I->grabFromCurrentUrl('~^/user/(\d+)/~'); $uri = $I->grabFromCurrentUrl(); ?> ``` @@ -735,7 +735,7 @@ Checks that the current URL matches the given regular expression. ``` php seeCurrentUrlMatches('~$/users/(\d+)~'); +$I->seeCurrentUrlMatches('~^/users/(\d+)~'); ?> ``` diff --git a/src/Codeception/Lib/Interfaces/Web.php b/src/Codeception/Lib/Interfaces/Web.php index 805d88fdd4..fbcc776014 100644 --- a/src/Codeception/Lib/Interfaces/Web.php +++ b/src/Codeception/Lib/Interfaces/Web.php @@ -383,7 +383,7 @@ public function seeCurrentUrlEquals($uri); * ``` php * seeCurrentUrlMatches('~$/users/(\d+)~'); + * $I->seeCurrentUrlMatches('~^/users/(\d+)~'); * ?> * ``` * @@ -425,7 +425,7 @@ public function dontSeeCurrentUrlEquals($uri); * ``` php * dontSeeCurrentUrlMatches('~$/users/(\d+)~'); + * $I->dontSeeCurrentUrlMatches('~^/users/(\d+)~'); * ?> * ``` * @@ -439,7 +439,7 @@ public function dontSeeCurrentUrlMatches($uri); * * ``` php * grabFromCurrentUrl('~$/user/(\d+)/~'); + * $user_id = $I->grabFromCurrentUrl('~^/user/(\d+)/~'); * $uri = $I->grabFromCurrentUrl(); * ?> * ``` From eb8badf98b65d89407b6118e498259bc7f5548c6 Mon Sep 17 00:00:00 2001 From: James LaChance Date: Sun, 7 Oct 2018 09:54:12 -0400 Subject: [PATCH 133/395] Add waitForElementClickable (#5217) * Add waitForElementClickablea. Fixes #5216 * Change wait to 16 times to account for added waits --- src/Codeception/Module/WebDriver.php | 21 +++++++++++++++++++++ tests/web/WebDriverTest.php | 7 ++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/Codeception/Module/WebDriver.php b/src/Codeception/Module/WebDriver.php index d59a34621f..1e6f7636be 100644 --- a/src/Codeception/Module/WebDriver.php +++ b/src/Codeception/Module/WebDriver.php @@ -2341,6 +2341,27 @@ public function waitForElementNotVisible($element, $timeout = 10) $this->webDriver->wait($timeout)->until($condition); } + /** + * Waits up to $timeout seconds for the given element to be clickable. + * If element doesn't become clickable, a timeout exception is thrown. + * + * ``` php + * waitForElementClickable('#agree_button', 30); // secs + * $I->click('#agree_button'); + * ?> + * ``` + * + * @param $element + * @param int $timeout seconds + * @throws \Exception + */ + public function waitForElementClickable($element, $timeout = 10) + { + $condition = WebDriverExpectedCondition::elementToBeClickable($this->getLocator($element)); + $this->webDriver->wait($timeout)->until($condition); + } + /** * Waits up to $timeout seconds for the given string to appear on the page. * diff --git a/tests/web/WebDriverTest.php b/tests/web/WebDriverTest.php index 583a6187ca..d20bb7d4ca 100644 --- a/tests/web/WebDriverTest.php +++ b/tests/web/WebDriverTest.php @@ -554,7 +554,7 @@ public function testCreateTestScreenshotOnFail() public function testWebDriverWaits() { - $fakeWd = Stub::make(self::WEBDRIVER_CLASS, ['wait' => Stub::exactly(12, function () { + $fakeWd = Stub::make(self::WEBDRIVER_CLASS, ['wait' => Stub::exactly(16, function () { return new \Codeception\Util\Maybe(); })]); $module = Stub::make(self::MODULE_CLASS, ['webDriver' => $fakeWd]); @@ -572,6 +572,11 @@ public function testWebDriverWaits() $module->waitForElementNotVisible(['id' => 'user']); $module->waitForElementNotVisible(['css' => '.user']); $module->waitForElementNotVisible('//xpath'); + + $module->waitForElementClickable(WebDriverBy::partialLinkText('yeah')); + $module->waitForElementClickable(['id' => 'user']); + $module->waitForElementClickable(['css' => '.user']); + $module->waitForElementClickable('//xpath'); } public function testWaitForElement() From b2353e935d28ecf4f0b8f15d0c2093bc537f2fe6 Mon Sep 17 00:00:00 2001 From: Gintautas Miselis Date: Sun, 7 Oct 2018 20:09:48 +0300 Subject: [PATCH 134/395] Unconditional _loadDump in 2.5 (#5198) * [Db] _loadDump works unconditionally, like in 2.4 #5195 * [Db] some internal method take databaseKey parameter only * [Db] Added some docblocks * [Db] Call _getDriver instead of __getDriver * [DB] _insertInDatabase prints PDO exception to debug output --- src/Codeception/Module/Db.php | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/src/Codeception/Module/Db.php b/src/Codeception/Module/Db.php index 6ee0c91321..7f2cebb3e5 100644 --- a/src/Codeception/Module/Db.php +++ b/src/Codeception/Module/Db.php @@ -224,7 +224,13 @@ class Db extends CodeceptionModule implements DbInterface protected $requiredFields = ['dsn', 'user', 'password']; const DEFAULT_DATABASE = 'default'; + /** + * @var Driver[] + */ public $drivers = []; + /** + * @var \PDO[] + */ public $dbhs = []; public $databasesPopulated = []; public $databasesSql = []; @@ -265,6 +271,13 @@ protected function populateDatabases($configKey) { foreach ($this->getDatabases() as $databaseKey => $databaseConfig) { if ($databaseConfig[$configKey]) { + if (!$databaseConfig['populate']) { + return; + } + + if (isset($this->databasesPopulated[$databaseKey]) && $this->databasesPopulated[$databaseKey]) { + return; + } $this->_loadDump($databaseKey, $databaseConfig); } } @@ -279,20 +292,20 @@ protected function removeInsertedForDatabases() { foreach ($this->getDatabases() as $databaseKey => $databaseConfig) { $this->amConnectedToDatabase($databaseKey); - $this->removeInserted($databaseKey, $databaseConfig); + $this->removeInserted($databaseKey); } } protected function disconnectDatabases() { foreach ($this->getDatabases() as $databaseKey => $databaseConfig) { - $this->disconnect($databaseKey, $databaseConfig); + $this->disconnect($databaseKey); } } protected function reconnectDatabases() { foreach ($this->getDatabases() as $databaseKey => $databaseConfig) { if ($databaseConfig['reconnect']) { - $this->disconnect($databaseKey, $databaseConfig); + $this->disconnect($databaseKey); $this->connect($databaseKey, $databaseConfig); } } @@ -310,6 +323,9 @@ public function __get($name) } } + /** + * @return Driver + */ public function _getDriver() { return $this->drivers[$this->currentDatabase]; @@ -507,7 +523,7 @@ private function connect($databaseKey, $databaseConfig) } if ($databaseConfig['waitlock']) { - $this->__getDriver()->setWaitLock($databaseConfig['waitlock']); + $this->_getDriver()->setWaitLock($databaseConfig['waitlock']); } $this->debugSection('Db', 'Connected to ' . $databaseKey . ' ' . $this->drivers[$databaseKey]->getDb()); @@ -600,19 +616,11 @@ public function _loadDump($databaseKey = null, $databaseConfig = null) $databaseKey = empty($databaseKey) ? self::DEFAULT_DATABASE : $databaseKey; $databaseConfig = empty($databaseConfig) ? $this->config : $databaseConfig; - if (!$databaseConfig['populate']) { - return; - } - - if (isset($this->databasesPopulated[$databaseKey]) && $this->databasesPopulated[$databaseKey]) { - return; - } - if ($databaseConfig['populator']) { $this->loadDumpUsingPopulator($databaseKey, $databaseConfig); return; } - $this->loadDumpUsingDriver($databaseKey, $databaseConfig); + $this->loadDumpUsingDriver($databaseKey); } protected function loadDumpUsingPopulator($databaseKey, $databaseConfig) @@ -671,6 +679,7 @@ public function _insertInDatabase($table, array $data) // ignore errors due to uncommon DB structure, // such as tables without _id_seq in PGSQL $lastInsertId = 0; + $this->debugSection('DB error', $e->getMessage()); } return $lastInsertId; } From ce1434843e3f233953e0f0bc8bcfe3527bef6552 Mon Sep 17 00:00:00 2001 From: Gintautas Miselis Date: Mon, 8 Oct 2018 02:08:28 +0300 Subject: [PATCH 135/395] [REST] Updated docblock of amAWSAuthenticated (#5197) * [REST] Updated docblock of amAWSAuthenticated Because config example wasn't rendered correctly * Deleted whitespace at end of line --- src/Codeception/Module/REST.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Codeception/Module/REST.php b/src/Codeception/Module/REST.php index df5af15797..535e500614 100644 --- a/src/Codeception/Module/REST.php +++ b/src/Codeception/Module/REST.php @@ -339,10 +339,10 @@ public function amNTLMAuthenticated($username, $password) /** * Allows to send REST request using AWS Authorization - * Only works with PhpBrowser - * Example - * Config - * + * Only works with PhpBrowser + * Example Config: + * ```yml * modules: * enabled: * - REST: @@ -351,7 +351,8 @@ public function amNTLMAuthenticated($username, $password) * secret: accessSecret * service: awsService * region: awsRegion - * + * ``` + * Code: * ```php * amAWSAuthenticated(); From c13dc47dbaccaf91e4799ce2bcadb2b75aef901b Mon Sep 17 00:00:00 2001 From: Geoffrey Laurent Date: Mon, 8 Oct 2018 19:36:32 +0200 Subject: [PATCH 136/395] use param files .yaml like .yml (#5218) --- src/Codeception/Lib/ParamsLoader.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Codeception/Lib/ParamsLoader.php b/src/Codeception/Lib/ParamsLoader.php index 16ba23f954..ef956ee6a2 100644 --- a/src/Codeception/Lib/ParamsLoader.php +++ b/src/Codeception/Lib/ParamsLoader.php @@ -28,7 +28,7 @@ public function load($paramStorage) } try { - if (preg_match('~\.yml$~', $paramStorage)) { + if (preg_match('~\.ya?ml$~', $paramStorage)) { return $this->loadYamlFile(); } From 7d4c4eeb598474ba48a21b88fda1947bc3ff1ee4 Mon Sep 17 00:00:00 2001 From: Fenikkusu <5033618+Fenikkusu@users.noreply.github.com> Date: Thu, 11 Oct 2018 06:21:35 -0400 Subject: [PATCH 137/395] Accounting For Null Content In Response Object (IE: Redirect) (#5222) --- src/Codeception/Lib/Connector/Phalcon.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Codeception/Lib/Connector/Phalcon.php b/src/Codeception/Lib/Connector/Phalcon.php index 7d252c0bde..92cc877a05 100644 --- a/src/Codeception/Lib/Connector/Phalcon.php +++ b/src/Codeception/Lib/Connector/Phalcon.php @@ -151,7 +151,7 @@ public function doRequest($request) } return new Response( - $response->getContent(), + $response->getContent() ?: '', $status ? $status : 200, $headers ); From b572a2bc4a23eda53f00f2aefb89067b0c24aed7 Mon Sep 17 00:00:00 2001 From: Serhey Dolgushev Date: Tue, 16 Oct 2018 17:26:02 -0400 Subject: [PATCH 138/395] HTML Report: use HTTPS for fonts (#5229) --- tests/data/result.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/data/result.html b/tests/data/result.html index 532d8a4956..d7ca25e7aa 100755 --- a/tests/data/result.html +++ b/tests/data/result.html @@ -4,7 +4,7 @@ Test results - + From 96237711233ef5b66f0d91d61ba360fac76b733d Mon Sep 17 00:00:00 2001 From: OneEyedSpaceFish Date: Tue, 16 Oct 2018 22:31:54 +0100 Subject: [PATCH 139/395] Recorder extension improvements (#5221) * Fixing recorder extension issues caused by phpunit 7.2.7 update Fixes #5109 * Prototype of improved recorder extension #5177 * Adding configurable colors to recorder extension #5177 * Adding the availability to honour --no-color and --no-ascii options #5177 * Removing a superfluous quote from carousel in Recorder extension #5177 * Adding feature to record errors in Recorder extension #5177 * Adding extra handling for unexpected exceptions, and changing ignore_step so it will only ignore passed steps only #5177 * Adding delete_orphaned functionality to recorder extension #5177 * Fixing codestyle violation in recorer extension #5177 --- ext/Recorder.php | 364 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 262 insertions(+), 102 deletions(-) diff --git a/ext/Recorder.php b/ext/Recorder.php index e62552ca79..7363cc88e9 100644 --- a/ext/Recorder.php +++ b/ext/Recorder.php @@ -34,8 +34,11 @@ * * * `delete_successful` (default: true) - delete screenshots for successfully passed tests (i.e. log only failed and errored tests). * * `module` (default: WebDriver) - which module for screenshots to use. Set `AngularJS` if you want to use it with AngularJS module. Generally, the module should implement `Codeception\Lib\Interfaces\ScreenshotSaver` interface. - * * `ignore_steps` (default: []) - array of step names that should not be recorded, * wildcards supported - * + * * `ignore_steps` (default: []) - array of step names that should not be recorded (given the step passed), * wildcards supported. + * * `success_color` (default: success) - bootstrap values to be used for color representation for passed tests + * * `failure_color` (default: danger) - bootstrap values to be used for color representation for failed tests + * * `error_color` (default: dark) - bootstrap values to be used for color representation for scenarios where there's an issue occurred while generating a recording + * * `delete_orphaned` (default: false) - delete recording folders created via previous runs * * #### Examples: * @@ -51,14 +54,20 @@ */ class Recorder extends \Codeception\Extension { + /** @var array */ protected $config = [ 'delete_successful' => true, 'module' => 'WebDriver', 'template' => null, 'animate_slides' => true, 'ignore_steps' => [], + 'success_color' => 'success', + 'failure_color' => 'danger', + 'error_color' => 'dark', + 'delete_orphaned' => false, ]; + /** @var string */ protected $template = << @@ -68,33 +77,25 @@ class Recorder extends \Codeception\Extension Recorder Result - + -
    - - + + + Previous - - + + + Next - - - + + ` - -But will ignore strings like: - - - `Home` - - `
    Home` - - `` - -For checking the raw source code, use `seeInSource()`. - - * `param string` $text - * `param string` $selector optional - - -### dontSeeCheckboxIsChecked - -Check that the specified checkbox is unchecked. - -``` php -dontSeeCheckboxIsChecked('#agree'); // I suppose user didn't agree to terms -$I->seeCheckboxIsChecked('#signup_form input[type=checkbox]'); // I suppose user didn't check the first checkbox in form. -?> -``` - - * `param` $checkbox - - -### dontSeeCookie - -Checks that there isn't a cookie with the given name. -You can set additional cookie params like `domain`, `path` as array passed in last argument. - - * `param` $cookie - - * `param array` $params - - -### dontSeeCurrentUrlEquals - -Checks that the current URL doesn't equal the given string. -Unlike `dontSeeInCurrentUrl`, this only matches the full URL. - -``` php -dontSeeCurrentUrlEquals('/'); -?> -``` - - * `param string` $uri - - -### dontSeeCurrentUrlMatches - -Checks that current url doesn't match the given regular expression. - -``` php -dontSeeCurrentUrlMatches('~^/users/(\d+)~'); -?> -``` - - * `param string` $uri - - -### dontSeeElement - -Checks that the given element is invisible or not present on the page. -You can also specify expected attributes of this element. - -``` php -dontSeeElement('.error'); -$I->dontSeeElement('//form/input[1]'); -$I->dontSeeElement('input', ['name' => 'login']); -$I->dontSeeElement('input', ['value' => '123456']); -?> -``` - - * `param` $selector - * `param array` $attributes - - -### dontSeeElementInDOM - -Opposite of `seeElementInDOM`. - - * `param` $selector - * `param array` $attributes - - -### dontSeeInCurrentUrl - -Checks that the current URI doesn't contain the given string. - -``` php -dontSeeInCurrentUrl('/users/'); -?> -``` - - * `param string` $uri - - -### dontSeeInField - -Checks that an input field or textarea doesn't contain the given value. -For fuzzy locators, the field is matched by label text, CSS and XPath. - -``` php -dontSeeInField('Body','Type your comment here'); -$I->dontSeeInField('form textarea[name=body]','Type your comment here'); -$I->dontSeeInField('form input[type=hidden]','hidden_value'); -$I->dontSeeInField('#searchform input','Search'); -$I->dontSeeInField('//form/*[@name=search]','Search'); -$I->dontSeeInField(['name' => 'search'], 'Search'); -?> -``` - - * `param` $field - * `param` $value - - -### dontSeeInFormFields - -Checks if the array of form parameters (name => value) are not set on the form matched with -the passed selector. - -``` php -dontSeeInFormFields('form[name=myform]', [ - 'input1' => 'non-existent value', - 'input2' => 'other non-existent value', -]); -?> -``` - -To check that an element hasn't been assigned any one of many values, an array can be passed -as the value: - -``` php -dontSeeInFormFields('.form-class', [ - 'fieldName' => [ - 'This value shouldn\'t be set', - 'And this value shouldn\'t be set', - ], -]); -?> -``` - -Additionally, checkbox values can be checked with a boolean. - -``` php -dontSeeInFormFields('#form-id', [ - 'checkbox1' => true, // fails if checked - 'checkbox2' => false, // fails if unchecked -]); -?> -``` - - * `param` $formSelector - * `param` $params - - -### dontSeeInPageSource - -Checks that the page source doesn't contain the given string. - - * `param` $text - - -### dontSeeInPopup - -Checks that the active JavaScript popup, -as created by `window.alert`|`window.confirm`|`window.prompt`, does NOT contain the given string. - - * `param` $text - -@throws \Codeception\Exception\ModuleException - - -### dontSeeInSource - -Checks that the current page contains the given string in its -raw source code. - -```php -dontSeeInSource('

    Green eggs & ham

    '); -``` - - * `param` $raw - - -### dontSeeInTitle - -Checks that the page title does not contain the given string. - - * `param` $title - - - -### dontSeeLink - -Checks that the page doesn't contain a link with the given string. -If the second parameter is given, only links with a matching "href" attribute will be checked. - -``` php -dontSeeLink('Logout'); // I suppose user is not logged in -$I->dontSeeLink('Checkout now', '/store/cart.php'); -?> -``` - - * `param string` $text - * `param string` $url optional - - -### dontSeeOptionIsSelected - -Checks that the given option is not selected. - -``` php -dontSeeOptionIsSelected('#form input[name=payment]', 'Visa'); -?> -``` - - * `param` $selector - * `param` $optionText - - - -### doubleClick - -Performs a double-click on an element matched by CSS or XPath. - - * `param` $cssOrXPath -@throws \Codeception\Exception\ElementNotFound - - -### dragAndDrop - -Performs a simple mouse drag-and-drop operation. - -``` php -dragAndDrop('#drag', '#drop'); -?> -``` - - * `param string` $source (CSS ID or XPath) - * `param string` $target (CSS ID or XPath) - - -### executeAsyncJS - -Executes asynchronous JavaScript. -A callback should be executed by JavaScript to exit from a script. -Callback is passed as a last element in `arguments` array. -Additional arguments can be passed as array in second parameter. - -```js -// wait for 1200 milliseconds my running `setTimeout` -* $I->executeAsyncJS('setTimeout(arguments[0], 1200)'); - -$seconds = 1200; // or seconds are passed as argument -$I->executeAsyncJS('setTimeout(arguments[1], arguments[0])', [$seconds]); -``` - - * `param` $script - * `param array` $arguments - - -### executeInSelenium - -Low-level API method. -If Codeception commands are not enough, this allows you to use Selenium WebDriver methods directly: - -``` php -$I->executeInSelenium(function(\Facebook\WebDriver\Remote\RemoteWebDriver $webdriver) { - $webdriver->get('http://google.com'); -}); -``` - -This runs in the context of the -[RemoteWebDriver class](https://github.com/facebook/php-webdriver/blob/master/lib/remote/RemoteWebDriver.php). -Try not to use this command on a regular basis. -If Codeception lacks a feature you need, please implement it and submit a patch. - - * `param callable` $function - - -### executeJS - -Executes custom JavaScript. - -This example uses jQuery to get a value and assigns that value to a PHP variable: - -```php -executeJS('return $("#myField").val()'); - -// additional arguments can be passed as array -// Example shows `Hello World` alert: -$I->executeJS("window.alert(arguments[0])", ['Hello world']); -``` - - * `param` $script - * `param array` $arguments - - -### fillField - -Fills a text field or textarea with the given string. - -``` php -fillField("//input[@type='text']", "Hello World!"); -$I->fillField(['name' => 'email'], 'jon@mail.com'); -?> -``` - - * `param` $field - * `param` $value - - -### grabAttributeFrom - -Grabs the value of the given attribute value from the given element. -Fails if element is not found. - -``` php -grabAttributeFrom('#tooltip', 'title'); -?> -``` - - * `param` $cssOrXpath - * `param` $attribute - - - -### grabCookie - -Grabs a cookie value. -You can set additional cookie params like `domain`, `path` in array passed as last argument. - - * `param` $cookie - - * `param array` $params - - -### grabFromCurrentUrl - -Executes the given regular expression against the current URI and returns the first capturing group. -If no parameters are provided, the full URI is returned. - -``` php -grabFromCurrentUrl('~^/user/(\d+)/~'); -$uri = $I->grabFromCurrentUrl(); -?> -``` - - * `param string` $uri optional - - - -### grabMultiple - -Grabs either the text content, or attribute values, of nodes -matched by $cssOrXpath and returns them as an array. - -```html -First -Second -Third -``` - -```php -grabMultiple('a'); - -// would return ['#first', '#second', '#third'] -$aLinks = $I->grabMultiple('a', 'href'); -?> -``` - - * `param` $cssOrXpath - * `param` $attribute - * `return` string[] - - -### grabPageSource - -Grabs current page source code. - -@throws ModuleException if no page was opened. - - * `return` string Current page source code. - - -### grabTextFrom - -Finds and returns the text contents of the given element. -If a fuzzy locator is used, the element is found using CSS, XPath, -and by matching the full page source by regular expression. - -``` php -grabTextFrom('h1'); -$heading = $I->grabTextFrom('descendant-or-self::h1'); -$value = $I->grabTextFrom('~ -``` - - * `param` $cssOrXPathOrRegex - - - -### grabValueFrom - -Finds the value for the given form field. -If a fuzzy locator is used, the field is found by field name, CSS, and XPath. - -``` php -grabValueFrom('Name'); -$name = $I->grabValueFrom('input[name=username]'); -$name = $I->grabValueFrom('descendant-or-self::form/descendant::input[@name = 'username']'); -$name = $I->grabValueFrom(['name' => 'username']); -?> -``` - - * `param` $field - - - -### loadSessionSnapshot - -Loads cookies from a saved snapshot. -Allows to reuse same session across tests without additional login. - -See [saveSessionSnapshot](#saveSessionSnapshot) - - * `param` $name - - -### makeScreenshot - -Takes a screenshot of the current window and saves it to `tests/_output/debug`. - -``` php -amOnPage('/user/edit'); -$I->makeScreenshot('edit_page'); -// saved to: tests/_output/debug/edit_page.png -$I->makeScreenshot(); -// saved to: tests/_output/debug/2017-05-26_14-24-11_4b3403665fea6.png -``` - - * `param` $name - - -### maximizeWindow - -Maximizes the current window. - - -### moveBack - -Moves back in history. - - -### moveForward - -Moves forward in history. - - -### moveMouseOver - -Move mouse over the first element matched by the given locator. -If the first parameter null then the page is used. -If the second and third parameters are given, -then the mouse is moved to an offset of the element's top-left corner. -Otherwise, the mouse is moved to the center of the element. - -``` php -moveMouseOver(['css' => '.checkout']); -$I->moveMouseOver(null, 20, 50); -$I->moveMouseOver(['css' => '.checkout'], 20, 50); -?> -``` - - * `param string` $cssOrXPath css or xpath of the web element - * `param int` $offsetX - * `param int` $offsetY - -@throws \Codeception\Exception\ElementNotFound - - -### openNewTab - -Opens a new browser tab (wherever it is possible) and switches to it. - -```php -openNewTab(); -``` -Tab is opened by using `window.open` javascript in a browser. -Please note, that adblock can restrict creating such tabs. - -Can't be used with PhantomJS - - - -### pauseExecution - -Pauses test execution in debug mode. -To proceed test press "ENTER" in console. - -This method is useful while writing tests, -since it allows you to inspect the current page in the middle of a test case. - - -### performOn - -Waits for element and runs a sequence of actions inside its context. -Actions can be defined with array, callback, or `Codeception\Util\ActionSequence` instance. - -Actions as array are recommended for simple to combine "waitForElement" with assertions; -`waitForElement($el)` and `see('text', $el)` can be simplified to: - -```php -performOn($el, ['see' => 'text']); -``` - -List of actions can be pragmatically build using `Codeception\Util\ActionSequence`: - -```php -performOn('.model', ActionSequence::build() - ->see('Warning') - ->see('Are you sure you want to delete this?') - ->click('Yes') -); -``` - -Actions executed from array or ActionSequence will print debug output for actions, and adds an action name to -exception on failure. - -Whenever you need to define more actions a callback can be used. A WebDriver module is passed for argument: - -```php -performOn('.rememberMe', function (WebDriver $I) { - $I->see('Remember me next time'); - $I->seeElement('#LoginForm_rememberMe'); - $I->dontSee('Login'); -}); -``` - -In 3rd argument you can set number a seconds to wait for element to appear - - * `param` $element - * `param` $actions - * `param int` $timeout - - -### pressKey - -Presses the given key on the given element. -To specify a character and modifier (e.g. ctrl, alt, shift, meta), pass an array for $char with -the modifier as the first element and the character as the second. -For special keys use key constants from WebDriverKeys class. - -``` php - -$I->pressKey('#page','a'); // => olda -$I->pressKey('#page',array('ctrl','a'),'new'); //=> new -$I->pressKey('#page',array('shift','111'),'1','x'); //=> old!!!1x -$I->pressKey('descendant-or-self::*[@id='page']','u'); //=> oldu -$I->pressKey('#name', array('ctrl', 'a'), \Facebook\WebDriver\WebDriverKeys::DELETE); //=>'' -?> -``` - - * `param` $element - * `param` $char string|array Can be char or array with modifier. You can provide several chars. -@throws \Codeception\Exception\ElementNotFound - - -### reloadPage - -Reloads the current page. - - -### resetCookie - -Unsets cookie with the given name. -You can set additional cookie params like `domain`, `path` in array passed as last argument. - - * `param` $cookie - - * `param array` $params - - -### resizeWindow - -Resize the current window. - -``` php -resizeWindow(800, 600); - -``` - - * `param int` $width - * `param int` $height - - -### saveSessionSnapshot - -Saves current cookies into named snapshot in order to restore them in other tests -This is useful to save session state between tests. -For example, if user needs log in to site for each test this scenario can be executed once -while other tests can just restore saved cookies. - -``` php -loadSessionSnapshot('login')) return; - - // logging in - $I->amOnPage('/login'); - $I->fillField('name', 'jon'); - $I->fillField('password', '123345'); - $I->click('Login'); - - // saving snapshot - $I->saveSessionSnapshot('login'); -} -?> -``` - - * `param` $name - - -### scrollTo - -Move to the middle of the given element matched by the given locator. -Extra shift, calculated from the top-left corner of the element, -can be set by passing $offsetX and $offsetY parameters. - -``` php -scrollTo(['css' => '.checkout'], 20, 50); -?> -``` - - * `param` $selector - * `param int` $offsetX - * `param int` $offsetY - - -### see - -Checks that the current page contains the given string (case insensitive). - -You can specify a specific HTML element (via CSS or XPath) as the second -parameter to only search within that element. - -``` php -see('Logout'); // I can suppose user is logged in -$I->see('Sign Up', 'h1'); // I can suppose it's a signup page -$I->see('Sign Up', '//body/h1'); // with XPath -$I->see('Sign Up', ['css' => 'body h1']); // with strict CSS locator -``` - -Note that the search is done after stripping all HTML tags from the body, -so `$I->see('strong')` will return true for strings like: - - - `

    I am Stronger than thou

    ` - - `` - -But will *not* be true for strings like: - - - `Home` - - `
    Home` - - `` - -For checking the raw source code, use `seeInSource()`. - - * `param string` $text - * `param string` $selector optional - - -### seeCheckboxIsChecked - -Checks that the specified checkbox is checked. - -``` php -seeCheckboxIsChecked('#agree'); // I suppose user agreed to terms -$I->seeCheckboxIsChecked('#signup_form input[type=checkbox]'); // I suppose user agreed to terms, If there is only one checkbox in form. -$I->seeCheckboxIsChecked('//form/input[@type=checkbox and @name=agree]'); -?> -``` - - * `param` $checkbox - - -### seeCookie - -Checks that a cookie with the given name is set. -You can set additional cookie params like `domain`, `path` as array passed in last argument. - -``` php -seeCookie('PHPSESSID'); -?> -``` - - * `param` $cookie - * `param array` $params - - -### seeCurrentUrlEquals - -Checks that the current URL is equal to the given string. -Unlike `seeInCurrentUrl`, this only matches the full URL. - -``` php -seeCurrentUrlEquals('/'); -?> -``` - - * `param string` $uri - - -### seeCurrentUrlMatches - -Checks that the current URL matches the given regular expression. - -``` php -seeCurrentUrlMatches('~^/users/(\d+)~'); -?> -``` - - * `param string` $uri - - -### seeElement - -Checks that the given element exists on the page and is visible. -You can also specify expected attributes of this element. - -``` php -seeElement('.error'); -$I->seeElement('//form/input[1]'); -$I->seeElement('input', ['name' => 'login']); -$I->seeElement('input', ['value' => '123456']); - -// strict locator in first arg, attributes in second -$I->seeElement(['css' => 'form input'], ['name' => 'login']); -?> -``` - - * `param` $selector - * `param array` $attributes -@return - - -### seeElementInDOM - -Checks that the given element exists on the page, even it is invisible. - -``` php -seeElementInDOM('//form/input[type=hidden]'); -?> -``` - - * `param` $selector - * `param array` $attributes - - -### seeInCurrentUrl - -Checks that current URI contains the given string. - -``` php -seeInCurrentUrl('home'); -// to match: /users/1 -$I->seeInCurrentUrl('/users/'); -?> -``` - - * `param string` $uri - - -### seeInField - -Checks that the given input field or textarea *equals* (i.e. not just contains) the given value. -Fields are matched by label text, the "name" attribute, CSS, or XPath. - -``` php -seeInField('Body','Type your comment here'); -$I->seeInField('form textarea[name=body]','Type your comment here'); -$I->seeInField('form input[type=hidden]','hidden_value'); -$I->seeInField('#searchform input','Search'); -$I->seeInField('//form/*[@name=search]','Search'); -$I->seeInField(['name' => 'search'], 'Search'); -?> -``` - - * `param` $field - * `param` $value - - -### seeInFormFields - -Checks if the array of form parameters (name => value) are set on the form matched with the -passed selector. - -``` php -seeInFormFields('form[name=myform]', [ - 'input1' => 'value', - 'input2' => 'other value', -]); -?> -``` - -For multi-select elements, or to check values of multiple elements with the same name, an -array may be passed: - -``` php -seeInFormFields('.form-class', [ - 'multiselect' => [ - 'value1', - 'value2', - ], - 'checkbox[]' => [ - 'a checked value', - 'another checked value', - ], -]); -?> -``` - -Additionally, checkbox values can be checked with a boolean. - -``` php -seeInFormFields('#form-id', [ - 'checkbox1' => true, // passes if checked - 'checkbox2' => false, // passes if unchecked -]); -?> -``` - -Pair this with submitForm for quick testing magic. - -``` php - 'value', - 'field2' => 'another value', - 'checkbox1' => true, - // ... -]; -$I->submitForm('//form[@id=my-form]', $form, 'submitButton'); -// $I->amOnPage('/path/to/form-page') may be needed -$I->seeInFormFields('//form[@id=my-form]', $form); -?> -``` - - * `param` $formSelector - * `param` $params - - -### seeInPageSource - -Checks that the page source contains the given string. - -```php -seeInPageSource('seeInSource('

    Green eggs & ham

    '); -``` - - * `param` $raw - - -### seeInTitle - -Checks that the page title contains the given string. - -``` php -seeInTitle('Blog - Post #1'); -?> -``` - - * `param` $title - - - -### seeLink - -Checks that there's a link with the specified text. -Give a full URL as the second parameter to match links with that exact URL. - -``` php -seeLink('Logout'); // matches Logout -$I->seeLink('Logout','/logout'); // matches Logout -?> -``` - - * `param string` $text - * `param string` $url optional - - -### seeNumberOfElements - -Checks that there are a certain number of elements matched by the given locator on the page. - -``` php -seeNumberOfElements('tr', 10); -$I->seeNumberOfElements('tr', [0,10]); // between 0 and 10 elements -?> -``` - * `param` $selector - * `param mixed` $expected int or int[] - - -### seeNumberOfElementsInDOM -__not documented__ - - -### seeOptionIsSelected - -Checks that the given option is selected. - -``` php -seeOptionIsSelected('#form input[name=payment]', 'Visa'); -?> -``` - - * `param` $selector - * `param` $optionText - - - -### selectOption - -Selects an option in a select tag or in radio button group. - -``` php -selectOption('form select[name=account]', 'Premium'); -$I->selectOption('form input[name=payment]', 'Monthly'); -$I->selectOption('//form/select[@name=account]', 'Monthly'); -?> -``` - -Provide an array for the second argument to select multiple options: - -``` php -selectOption('Which OS do you use?', array('Windows','Linux')); -?> -``` - -Or provide an associative array for the second argument to specifically define which selection method should be used: - -``` php -selectOption('Which OS do you use?', array('text' => 'Windows')); // Only search by text 'Windows' -$I->selectOption('Which OS do you use?', array('value' => 'windows')); // Only search by value 'windows' -?> -``` - - * `param` $select - * `param` $option - - -### setCookie - -Sets a cookie with the given name and value. -You can set additional cookie params like `domain`, `path`, `expires`, `secure` in array passed as last argument. - -``` php -setCookie('PHPSESSID', 'el4ukv0kqbvoirg7nkp4dncpk3'); -?> -``` - - * `param` $name - * `param` $val - * `param array` $params - - - -### submitForm - -Submits the given form on the page, optionally with the given form -values. Give the form fields values as an array. Note that hidden fields -can't be accessed. - -Skipped fields will be filled by their values from the page. -You don't need to click the 'Submit' button afterwards. -This command itself triggers the request to form's action. - -You can optionally specify what button's value to include -in the request with the last parameter as an alternative to -explicitly setting its value in the second parameter, as -button values are not otherwise included in the request. - -Examples: - -``` php -submitForm('#login', [ - 'login' => 'davert', - 'password' => '123456' -]); -// or -$I->submitForm('#login', [ - 'login' => 'davert', - 'password' => '123456' -], 'submitButtonName'); - -``` - -For example, given this sample "Sign Up" form: - -``` html -
    - Login: -
    - Password: -
    - Do you agree to our terms? -
    - Select pricing plan: - - -
    -``` - -You could write the following to submit it: - -``` php -submitForm( - '#userForm', - [ - 'user[login]' => 'Davert', - 'user[password]' => '123456', - 'user[agree]' => true - ], - 'submitButton' -); -``` -Note that "2" will be the submitted value for the "plan" field, as it is -the selected option. - -Also note that this differs from PhpBrowser, in that -```'user' => [ 'login' => 'Davert' ]``` is not supported at the moment. -Named array keys *must* be included in the name as above. - -Pair this with seeInFormFields for quick testing magic. - -``` php - 'value', - 'field2' => 'another value', - 'checkbox1' => true, - // ... -]; -$I->submitForm('//form[@id=my-form]', $form, 'submitButton'); -// $I->amOnPage('/path/to/form-page') may be needed -$I->seeInFormFields('//form[@id=my-form]', $form); -?> -``` - -Parameter values must be set to arrays for multiple input fields -of the same name, or multi-select combo boxes. For checkboxes, -either the string value can be used, or boolean values which will -be replaced by the checkbox's value in the DOM. - -``` php -submitForm('#my-form', [ - 'field1' => 'value', - 'checkbox' => [ - 'value of first checkbox', - 'value of second checkbox, - ], - 'otherCheckboxes' => [ - true, - false, - false - ], - 'multiselect' => [ - 'first option value', - 'second option value' - ] -]); -?> -``` - -Mixing string and boolean values for a checkbox's value is not supported -and may produce unexpected results. - -Field names ending in "[]" must be passed without the trailing square -bracket characters, and must contain an array for its value. This allows -submitting multiple values with the same name, consider: - -```php -$I->submitForm('#my-form', [ - 'field[]' => 'value', - 'field[]' => 'another value', // 'field[]' is already a defined key -]); -``` - -The solution is to pass an array value: - -```php -// this way both values are submitted -$I->submitForm('#my-form', [ - 'field' => [ - 'value', - 'another value', - ] -]); -``` - -The `$button` parameter can be either a string, an array or an instance -of Facebook\WebDriver\WebDriverBy. When it is a string, the -button will be found by its "name" attribute. If $button is an -array then it will be treated as a strict selector and a WebDriverBy -will be used verbatim. - -For example, given the following HTML: - -``` html - -``` - -`$button` could be any one of the following: - - 'submitButton' - - ['name' => 'submitButton'] - - WebDriverBy::name('submitButton') - - * `param` $selector - * `param` $params - * `param` $button - - -### switchToIFrame - -Switch to another frame on the page. - -Example: -``` html -