diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..a921123 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,23 @@ +root = true + +[*] +end_of_line = lf +indent_style = space +charset = utf-8 +insert_final_newline = true +trim_trailing_whitespace = true + +[*.{yml,twig,php}] +indent_size = 4 + +[*.{js,json,scss,css}] +indent_size = 2 + +[.travis.yml] +indent_size = 2 + +[composer.json] +indent_size = 4 + +[Makefile] +indent_style = tab diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..3edeb7c --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +.* export-ignore +*.md export-ignore +Tests/* export-ignore diff --git a/.github/Bug_report.md b/.github/Bug_report.md new file mode 100644 index 0000000..8b27ed7 --- /dev/null +++ b/.github/Bug_report.md @@ -0,0 +1,24 @@ +--- +name: Bug Report +about: Report errors and problems + +--- + + + +**Description** + + +**How to reproduce** + + +**Possible Solution** + + +**Additional context** + diff --git a/.github/Documentation_issue.md b/.github/Documentation_issue.md new file mode 100644 index 0000000..196478c --- /dev/null +++ b/.github/Documentation_issue.md @@ -0,0 +1,10 @@ +--- +name: Documentation Issue +about: Anything related to Symfony CMF Documentation + +--- + +Symfony CMF Documentation has its own dedicated repository. Please open your +documentation-related issue at https://github.com/symfony-cmf/symfony-cmf-docs/issues + +Thanks! diff --git a/.github/Feature_request.md b/.github/Feature_request.md new file mode 100644 index 0000000..db3e02c --- /dev/null +++ b/.github/Feature_request.md @@ -0,0 +1,12 @@ +--- +name: Feature Request +about: RFC and ideas for new features and improvements + +--- + +**Description** + + +**Example** + diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000..d04471f --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,43 @@ + + + + +### Environment + +#### Symfony packages + +``` +$ composer show --latest 'symfony/*' +``` + +#### Symfony CMF packages + +``` +$ composer show --latest 'symfony-cmf/*' +``` + +## Subject + + + +## Steps to reproduce + +## Expected results + +## Actual results + + diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..0d8f7f7 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,10 @@ +| Q | A +| ------------- | --- +| Branch? | "master" for new features / the branch of the current release for fixes +| Bug fix? | yes/no +| New feature? | yes/no +| BC breaks? | yes/no +| Deprecations? | yes/no +| Fixed tickets | comma-separated list of tickets fixed by the PR, if any +| License | MIT +| Doc PR | reference to the documentation PR, if any diff --git a/.github/Security_issue.md b/.github/Security_issue.md new file mode 100644 index 0000000..34be6e0 --- /dev/null +++ b/.github/Security_issue.md @@ -0,0 +1,9 @@ +--- +name: Security Issue +about: Report security-related errors + +--- + +If you have found a security issue in Symfony, please send the details to +[David](mailto:david@liip.ch) or [Maximilian](mailto:maximilian.berghoff@gmx.de) and don't disclose it publicly until we can provide a +fix for it. diff --git a/.github/Support_question.md b/.github/Support_question.md new file mode 100644 index 0000000..c128b56 --- /dev/null +++ b/.github/Support_question.md @@ -0,0 +1,15 @@ +--- +name: Support Question +about: Questions about using Symfony CMF and its components + +--- + +**Description** + + +**How to reproduce (optional)** + + +**Possible Solution** + + diff --git a/.github/workflows/test-application.yaml b/.github/workflows/test-application.yaml new file mode 100644 index 0000000..22ce986 --- /dev/null +++ b/.github/workflows/test-application.yaml @@ -0,0 +1,48 @@ +name: Test application + +on: + pull_request: + push: + branches: + - '[0-9]+.x' + - '[0-9]+.[0-9]+' + - '[0-9]+.[0-9]+.x' + +jobs: + test: + name: 'PHP ${{ matrix.php-version }}, Symfony ${{ matrix.symfony-version }} ${{ matrix.dependencies}}' + runs-on: ubuntu-20.04 + + env: + SYMFONY_DEPRECATIONS_HELPER: weak + SYMFONY_REQUIRE: ${{ matrix.symfony-version }} + + strategy: + fail-fast: false + matrix: + include: + - php-version: '8.1' + dependencies: 'lowest' + symfony-version: '^6.4' + - php-version: '8.1' + - php-version: '8.2' + - php-version: '8.3' + + steps: + - name: Checkout project + uses: actions/checkout@v4 + + - name: Install and configure PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-version }} + tools: composer:v2, flex + + - name: Install dependencies with Composer + uses: ramsey/composer-install@v2 + with: + dependency-versions: ${{ matrix.dependencies }} + composer-options: --prefer-dist + + - name: Execute test cases + run: make test diff --git a/.gitignore b/.gitignore index c55784d..aa17890 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ composer.lock /vendor/ +build/ diff --git a/.styleci.yml b/.styleci.yml new file mode 100644 index 0000000..3f52aa6 --- /dev/null +++ b/.styleci.yml @@ -0,0 +1,29 @@ +####################################################### +# DO NOT EDIT THIS FILE! # +# # +# It's auto-generated by symfony-cmf/dev-kit package. # +####################################################### + +############################################################################ +# This file is part of the Symfony CMF package. # +# # +# (c) 2011-2017 Symfony CMF # +# # +# For the full copyright and license information, please view the LICENSE # +# file that was distributed with this source code. # +############################################################################ + + +preset: symfony +risky: true + +enabled: + - combine_consecutive_unsets + - no_useless_else + - ordered_use + - strict + - php_unit_construct + +disabled: + - single_line_class_definition + - single_line_throw diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index b3cd945..0000000 --- a/.travis.yml +++ /dev/null @@ -1,25 +0,0 @@ -language: php - -php: - - 5.3 - - 5.4 - - 5.5 - -env: - - SYMFONY_VERSION=2.3.* - - SYMFONY_VERSION=2.4.* - - SYMFONY_VERSION=dev-master - -before_script: - - composer self-update - - composer require symfony/symfony:${SYMFONY_VERSION} --prefer-source - -script: phpunit --coverage-text - -notifications: - irc: "irc.freenode.org#symfony-cmf" - email: "symfony-cmf-devs@googlegroups.com" - -matrix: - allow_failures: - - env: SYMFONY_VERSION=dev-master diff --git a/CHANGELOG.md b/CHANGELOG.md index 129a8c5..742867f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,160 @@ Changelog ========= +5.x +=== + +5.0.2 +----- + +* Fixed regression in `TestKernel`. + +5.0.1 +----- + +* Cleanup PHP 8.1 language features. +* Simplify configuration code. +* Update with cleanups from symfony-cmf/testing 4.5.*. + +5.0.0 +----- + +* Drop support for Symfony < 6.4 +* Drop support for PHP < 8.1 +* The default framework configuration no longer enables validation attributes. +* The PHPCR-ODM additional namespace is expected to use attributes rather than annotations. + +4.x +=== + +4.5.1 +----- + +* Use regular fixture loader with Symfony 7 rather than the dropped `ContainerAwareLoader`. + For fixtures with services, instantiate the fixture and pass the instance to `PHPCR::loadFixture` + instead of passing the class string. + +4.5.0 +----- + +* Support phpcr-bundle 3. +* Support Symfony 7. +* Drop support for Symfony < 5.4. + +4.4.2 +----- + +* Only call `AnnotationRegistry::registerLoader` if it is available. + +4.4.1 +----- + +Should have been 4.1.1 but gave the wrong tag name. + +* Configuration fixes for Symfony 6. + +4.1.0 +----- + +* **2021-12-16**: Allow installation with Symfony 6. + Technically there is a BC break with BaseTestCase::bootKernel now having a return type declaration, but the CMF bundles to not overwrite that method further. + +4.0.0 +----- + +* **2021-08-30**: [BC-BREAK] Made bootstrap utility methods in BaseTestCase static to not conflict with recent versions of Symfony FrameworkBundle. + +3.3.0 +----- + +* **2021-01-22**: Support PHP 8 + +3.2.1 +----- + +* **2020-10-22**: Remove typehints to allow doctrine persistence in commons and stand alone + +3.2.0 +----- + +* **2020-04-28**: Support Symfony 5 + +3.1.0 +----- + +* **2020-02-24**: [BC-BREAK] Remove framework templating configuration from prepended config. + +3.0.0 +----- + +* **2020-01-08**: [BC-BREAK] Move feature packages to require-dev to make sure packages using the testing component declare their dependencies correctly. +* **2019-12-05**: [BC-BREAK] Support PHPUnit 6, 7 and 8, drop support for PHPUnit 5.7 +* **2019-07-26**: [BC-BREAK] Remove deprecated `BaseTestCase::getClient`, use `BaseTestCase::getFrameworkBundleClient` instead. +* **2019-02-28**: [BC-BREAK] Remove `DatabaseTestListener`, use scripts in `bin/make/` to ramp up your testing environment for several test suites + +2.1.12 +------ + +* **2019-07-26**: Work around name collision with Symfony 4.3. + `BaseTestCase::getClient` is deprecated, use `BaseTestCase::getFrameworkBundleClient` instead. + +2.1.0 +----- + +* **2017-01-18**: Introduce a `TestCompilePass` to make services public, which are needed +in i.e. a WebTest. + * **2017-11-08**: Removed php 5.6 and 7.0 support, removed Symfony 3.0.* and 3.1.* support + introduce KERNEL_CLASS handling to avoid deprecated KERNEL_DIR, removed usage of `ProcessBuilder` + +2.0.1 +----- + + * **2018-01-02**: Remove dependency on symfony/symfony in favor of more specific packages. Its a + bug of the package using testing if it does not declare its dependencies. + +2.0.0 +----- + +2.0.0-RC2 +--------- + + * **2017-01-25**: Added WebServerBundle support + * **2017-01-25**: Dropped PHP <5.6 support + +2.0.0-RC1 +--------- + + * **2016-06-21**: [BC BREAK] Deleted the `sonata_admin` bundle set + * **2016-06-21**: [BC BREAK] Deleted the `LoadBaseData` data fixtures + * **2016-06-21**: [BC BREAK] Deleted the `Content` document + * **2016-06-21**: [BC BREAK] Dropped PHP <5.5 support + * **2016-06-21**: [BC BREAK] Dropped Symfony <2.8 support + +1.3.0 +----- + +1.3.0-RC1 +--------- + +* **2015-10-17**: Symfony 3 is supported +* **2015-10-17**: [BC Break] `resources/config/dist/framework.yml` has been + renamed to `resources/config/dist/framework.php` +* **2015-04-26**: Added `BaseTestCase::assertResponseSuccess()` to provide + helpfull output in case the response errored +* **2015-04-19**: The package now requires `symfony/phpunit-bridge` +* **2015-01-18**: Added required `--force` for the `doctrine:phpcr:init:dbal` + command to support Jackalope 1.2 + +1.2.0-RC2 +--------- + +* **2014-10-06**: Added purgeDatabase method to ORM manager + +1.2.0-RC1 +--------- + +* **2014-07-27**: Added DataFixture support to the ORM DbManager +* **2014-06-16**: Initializer for phpcr fixture loading * **2014-06-06**: Updated to PSR-4 autoloading 1.1.0-RC2 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..521e2c2 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,12 @@ +Contributing +------------ + +Symfony CMF is an open source, community-driven project. We follow the same +guidelines as core Symfony. If you'd like to contribute, please read the +[Contributing Code][1] part of the documentation. If you're submitting a pull +request, please follow the guidelines in the [Submitting a Patch][2] section +and use the [Pull Request Template][3]. + +[1]: http://symfony.com/doc/current/contributing/code/index.html +[2]: http://symfony.com/doc/current/contributing/code/patches.html#check-list +[3]: http://symfony.com/doc/current/contributing/code/patches.html#make-a-pull-request diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..41bc937 --- /dev/null +++ b/LICENSE @@ -0,0 +1,23 @@ +Testing + + The MIT License + + Copyright (c) 2011-2017 Symfony CMF + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..89871e9 --- /dev/null +++ b/Makefile @@ -0,0 +1,58 @@ +####################################################### +# DO NOT EDIT THIS FILE! # +# # +# It's auto-generated by symfony-cmf/dev-kit package. # +####################################################### + +############################################################################ +# This file is part of the Symfony CMF package. # +# # +# (c) 2011-2017 Symfony CMF # +# # +# For the full copyright and license information, please view the LICENSE # +# file that was distributed with this source code. # +############################################################################ + +TESTING_SCRIPTS_DIR=bin +CONSOLE=${TESTING_SCRIPTS_DIR}/console +VERSION=dev-master +ifdef BRANCH + VERSION=dev-${BRANCH} +endif +PACKAGE=symfony-cmf/testing +HAS_XDEBUG=$(shell php --modules|grep --quiet xdebug;echo $$?) + +list: + @echo 'test: will run all tests' + @echo 'unit_tests: will run unit tests only' + + +include ${TESTING_SCRIPTS_DIR}/make/unit_tests.mk + +.PHONY: test +test: unit_tests +lint-php: + php-cs-fixer fix --ansi --verbose --diff --dry-run +.PHONY: lint-php + +int: lint-composer lint-php +.PHONY: lint + +lint-composer: + composer validate +.PHONY: lint-composer + +cs-fix: cs-fix-php +.PHONY: cs-fix + +cs-fix-php: + php-cs-fixer fix --verbose +.PHONY: cs-fix-php + +build: + mkdir $@ + +build/xdebug-filter.php: phpunit.xml.dist build +ifeq ($(HAS_XDEBUG), 0) + phpunit --dump-xdebug-filter $@ +endif diff --git a/README.md b/README.md index 1c08848..5a4f764 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,37 @@ -# Symfony CMF Testing Component +# Symfony CMF Testing -[![Build Status](https://travis-ci.org/symfony-cmf/Testing.png?branch=master)](https://travis-ci.org/symfony-cmf/Testing) +[![Tests](https://github.com/symfony-cmf/Testing/actions/workflows/test-application.yaml/badge.svg)](https://github.com/symfony-cmf/Testing/actions) +[![Latest Stable Version](https://poser.pugx.org/symfony-cmf/testing/v/stable)](https://packagist.org/packages/symfony-cmf/testing) +[![License](https://poser.pugx.org/symfony-cmf/testing/license)](https://packagist.org/packages/symfony-cmf/testing) + +[![Total Downloads](https://poser.pugx.org/symfony-cmf/testing/downloads)](https://packagist.org/packages/symfony-cmf/testing) +[![Monthly Downloads](https://poser.pugx.org/symfony-cmf/testing/d/monthly)](https://packagist.org/packages/symfony-cmf/testing) + +This package is part of the [Symfony Content Management Framework (CMF)](https://cmf.symfony.com/) and licensed +under the [MIT License](LICENSE). **NOTE**: This is an internal tool and is not intended to be used outside of the context of the CMF. -This is a testing library created to aid the development of functional tests -for the Symfony CMF. +## Documentation + +For the install guide and reference, see: + +* [symfony-cmf/testing Documentation](https://github.com/symfony-cmf/symfony-cmf-docs/blob/master/components/testing.rst) + +## Support + +For general support and questions, please use [StackOverflow](https://stackoverflow.com/questions/tagged/symfony-cmf). + +## Contributing + +Pull requests are welcome. Please see our +[CONTRIBUTING](https://github.com/symfony-cmf/testing/blob/5.x/CONTRIBUTING.md) +guide. + +Thanks to +[everyone who has contributed](contributors) already. -See the [official documentation](http://symfony.com/doc/master/cmf/components/testing.html) +## License +This package is available under the [MIT license](src/Resources/meta/LICENSE). diff --git a/UPGRADE-2.0.md b/UPGRADE-2.0.md new file mode 100644 index 0000000..b0e9f4f --- /dev/null +++ b/UPGRADE-2.0.md @@ -0,0 +1,14 @@ +# Upgrade from 1.x to 2.0 + +## Bundle sets + + * The `sonata_admin` bundle set was removed. Use the `sonata_admin_orm` or + `sonata_admin_phpcr` set instead. + +## Fixtures + + * The `LoadBaseData` fixture loader was removed. You have to initialize your + test nodes in your own fixtures now. + + * `Symfony\Cmf\Component\Testing\Document\Content` as a general test document + was removed, so you have to create own testing document classes now. diff --git a/bin/make/functional_tests_orm.mk b/bin/make/functional_tests_orm.mk new file mode 100644 index 0000000..4c22f40 --- /dev/null +++ b/bin/make/functional_tests_orm.mk @@ -0,0 +1,15 @@ + +functional_tests_orm: + @if [ "${CONSOLE}" = "" ]; then echo "Console executable missing"; exit 1; fi + @echo + @echo '+++ create ORM database +++' + @${CONSOLE} doctrine:schema:drop --env=orm --force + @${CONSOLE} doctrine:database:create --env=orm || echo "Failed to create database. If this is sqlite, this is normal. Otherwise there will be an error with schema creation" + @${CONSOLE} doctrine:schema:create --env=orm + @echo '+++ run ORM functional tests +++' +ifeq ($(HAS_XDEBUG), 0) + @vendor/bin/simple-phpunit --coverage-clover build/logs/clover.xml --testsuite "functional tests with orm" +else + @vendor/bin/simple-phpunit --testsuite "functional tests with orm" +endif + @${CONSOLE} doctrine:database:drop --force diff --git a/bin/make/functional_tests_phpcr.mk b/bin/make/functional_tests_phpcr.mk new file mode 100644 index 0000000..b75f6b7 --- /dev/null +++ b/bin/make/functional_tests_phpcr.mk @@ -0,0 +1,14 @@ + +functional_tests_phpcr: + @if [ "${CONSOLE}" = "" ]; then echo "Console executable missing"; exit 1; fi + @echo + @echo '+++ create PHPCR +++' + @${CONSOLE} doctrine:phpcr:init:dbal --drop --force + @${CONSOLE} doctrine:phpcr:repository:init + @echo '+++ run PHPCR functional tests +++' +ifeq ($(HAS_XDEBUG), 0) + @vendor/bin/simple-phpunit --coverage-clover build/logs/clover.xml --testsuite "functional tests with phpcr" +else + @vendor/bin/simple-phpunit --testsuite "functional tests with phpcr" +endif + @${CONSOLE} doctrine:database:drop --force diff --git a/bin/make/test_installation.mk b/bin/make/test_installation.mk new file mode 100644 index 0000000..ceb0b14 --- /dev/null +++ b/bin/make/test_installation.mk @@ -0,0 +1,6 @@ + +test_installation: + @if [ "${PACKAGE}" = "" ] || [ "${VERSION}" = "" ]; then echo "Package name or version missing"; exit 1; fi + @echo + @echo '+++ testing installation into a blank symfony application +++' + vendor/symfony-cmf/testing/bin/scripts/check_install.sh -p${PACKAGE} -v${VERSION} diff --git a/bin/make/unit_tests.mk b/bin/make/unit_tests.mk new file mode 100644 index 0000000..069f44f --- /dev/null +++ b/bin/make/unit_tests.mk @@ -0,0 +1,9 @@ + +unit_tests: + @echo + @echo '+++ run unit tests +++' +ifeq ($(HAS_XDEBUG), 0) + @vendor/bin/simple-phpunit --coverage-clover build/logs/clover.xml --testsuite "unit tests" +else + @vendor/bin/simple-phpunit --testsuite "unit tests" +endif diff --git a/bin/scripts/check_install.sh b/bin/scripts/check_install.sh new file mode 100755 index 0000000..5a287d9 --- /dev/null +++ b/bin/scripts/check_install.sh @@ -0,0 +1,64 @@ +#!/usr/bin/env bash + +usage="$(basename "$0") [-hl] [-t] -- Script to test a bundle installation with on a symfony application. + where: + -h show help text + -p The complete package name of the bundle + -s The Symfony version to use + -v The version/branch to install;" + +BASE_DIR=${PWD} +BUILD_DIR=${BASE_DIR}/build + +PACKAGE_NAME='' +VERSION='dev-master' +SYMFONY_VERSION="^3.3" +function installBundle() { + DIR=${BUILD_DIR}/${PACKAGE_NAME}/${VERSION} + if [ "${SYMFONY_VERSION}" = *"dev" ]; then STABILITY_FLAG=' -s dev'; else STABILITY_FLAG=''; fi + mkdir -p ${DIR} + echo "Create directory ${DIR}" + cd ${DIR} + echo "+++ Create Symfony skeleton app +++ " + composer create-project${STABILITY_FLAG} "symfony/skeleton:${SYMFONY_VERSION}" test-app + cd test-app/ + composer config extra.symfony.allow-contrib true + if [ "${VERSION}" = "dev"* ]; then perl -pi -e 's/^}$/,"minimum-stability":"dev"}/' composer.json; fi + REQUIRE=${PACKAGE_NAME}":"${VERSION} + echo "+++ Require bundle ${REQUIRE} +++" + composer req -n "${REQUIRE}" + OUT=$? + if [ ${OUT} -eq 0 ];then + echo "+++ Install is fine +++" + exit 0 + else + echo "+++ Problems to install package +++" + exit ${OUT} + fi + echo $? + echo "+++ We should fetch composer exit code here +++" +} + +while getopts :hv:p:s: option +do + case "${option}" + in + p) PACKAGE_NAME=${OPTARG};; + v) VERSION=${OPTARG};; + s) SYMFONY_VERSION=${OPTARG};; + h) echo "${usage}" + exit 1 + ;; + :) printf "missing argument for -%s\n" "$OPTARG" >&2 + echo "$usage" >&2 + exit 1 + ;; + \?) printf "illegal option: -%s\n" "$OPTARG" >&2 + echo "$usage" >&2 + exit 1 + ;; + esac +done + +installBundle + diff --git a/bin/travis/doctrine_orm.sh b/bin/travis/doctrine_orm.sh index 7abdacd..3a12f60 100755 --- a/bin/travis/doctrine_orm.sh +++ b/bin/travis/doctrine_orm.sh @@ -1,9 +1,7 @@ #!/bin/bash - DIR_NAME=`dirname $0` CONSOLE_DIR=$DIR_NAME"/.." # composer install --dev -php $CONSOLE_DIR"/console" doctrine:database:create --env=orm -php $CONSOLE_DIR"/console" doctrine:schema:create --env=orm -php $CONSOLE_DIR"/console" doctrine:phpcr:repository:init +$CONSOLE_DIR"/console" doctrine:database:create --env=orm +$CONSOLE_DIR"/console" doctrine:schema:create --env=orm diff --git a/bin/travis/phpcr_odm_doctrine_dbal.sh b/bin/travis/phpcr_odm_doctrine_dbal.sh index 38e25ed..f5aa4a2 100755 --- a/bin/travis/phpcr_odm_doctrine_dbal.sh +++ b/bin/travis/phpcr_odm_doctrine_dbal.sh @@ -1,8 +1,13 @@ #!/bin/bash +# make the script display the commands it runs to help debugging failures +set -x DIR_NAME=`dirname $0` CONSOLE_DIR=$DIR_NAME"/.." -# composer install --dev -php $CONSOLE_DIR"/console" doctrine:phpcr:init:dbal --drop -php $CONSOLE_DIR"/console" doctrine:phpcr:repository:init +if ! $CONSOLE_DIR"/console" doctrine:phpcr:init:dbal --drop --force; then + # To support Jackalope <1.2 + $CONSOLE_DIR"/console" doctrine:phpcr:init:dbal --drop +fi + +$CONSOLE_DIR"/console" doctrine:phpcr:repository:init diff --git a/bootstrap/bootstrap.php b/bootstrap/bootstrap.php index 38c7f83..100d0f9 100644 --- a/bootstrap/bootstrap.php +++ b/bootstrap/bootstrap.php @@ -1,34 +1,26 @@ '; - echo "$nl$nl"; - die('You must set up the project dependencies.'.$nl. - 'Run the following commands in '.dirname(__DIR__).':'.$nl.$nl. + $nl = 'cli' === substr(\PHP_SAPI, 0, 3) ? \PHP_EOL : '
'; + echo $nl.$nl. + 'You must set up the project dependencies.'.$nl. + 'Run the following commands in '.dirname($vendorDir).':'.$nl.$nl. 'curl -s http://getcomposer.org/installer | php'.$nl. - 'php composer.phar install'.$nl); + 'php composer.phar install'.$nl; + exit(1); } - -use Doctrine\Common\Annotations\AnnotationRegistry; -AnnotationRegistry::registerLoader(function($class) use ($loader) { - $loader->loadClass($class); - - // this was class_exists($class, false) i.e. do not autoload. - // this is required so that custom annotations (e.g. TreeUiBundle - // annotations) are autoloaded - but they should be found by the - // composer loader above. - // - // This probably slows things down. - // - // @todo: Fix me. - return class_exists($class); -}); - -AnnotationRegistry::registerFile($vendorDir.'/doctrine/phpcr-odm/lib/Doctrine/ODM/PHPCR/Mapping/Annotations/DoctrineAnnotations.php'); - if (!defined('CMF_TEST_ROOT_DIR')) { define('CMF_TEST_ROOT_DIR', realpath(__DIR__.'/..')); } diff --git a/bootstrap/kernel_bootstrap.php b/bootstrap/kernel_bootstrap.php index 221f060..5506341 100644 --- a/bootstrap/kernel_bootstrap.php +++ b/bootstrap/kernel_bootstrap.php @@ -1,5 +1,19 @@ php[0]->server[0]['value']; -$kernelFile = $rootDir.'/'.$kernelDir.'/AppKernel.php'; +$envClass = $xml->xpath("//php/env[@name='KERNEL_CLASS']"); +if (count($envClass)) { + $kernelClass = (string) $envClass[0]['value']; +} else { + $envDir = $xml->xpath("//php/server[@name='KERNEL_DIR']"); + if (!count($envDir)) { + throw new \Exception( + 'KERNEL_CLASS must be set via ' + ); + } + $kernelClass = 'AppKernel'; + $kernelFile = $rootDir.'/'.$envDir[0]['value'].'/'.$kernelClass.'.php'; -if (!file_exists($kernelFile)) { - throw new \Exception(sprintf( - 'Cannot find kernel file "%s"', - $kernelFile - )); -} + if (!file_exists($kernelFile)) { + throw new \Exception(sprintf( + 'Cannot find kernel file "%s"', + $kernelFile + )); + } -require_once $kernelFile; + require_once $kernelFile; +} -return new AppKernel($env, true); +return new $kernelClass($env, true); diff --git a/composer.json b/composer.json index 6cb63a5..07dd10e 100644 --- a/composer.json +++ b/composer.json @@ -1,24 +1,38 @@ { "name": "symfony-cmf/testing", "license": "MIT", - "description": "Component for bootstraping functional tests for CMF bundles only.", + "description": "Component providing tools for writing tests with Symfony.", "authors": [ { - "name": "dantleech", - "email": "daniel@dantleech.com" + "name": "Symfony CMF Community", + "homepage": "https://github.com/symfony-cmf/Routing/contributors" } ], - "minimum-stability": "dev", "require": { - "symfony/symfony": "~2.3", - "symfony/monolog-bundle": "~2.1", - "doctrine/common": "~2.4", - "doctrine/doctrine-bundle": "1.*", - "doctrine/phpcr-odm": "1.*", - "doctrine/phpcr-bundle": "1.*", - "doctrine/data-fixtures": "1.0.*", - "jackalope/jackalope": "1.*", - "jackalope/jackalope-doctrine-dbal": "1.*" + "php": "^8.1", + "doctrine/data-fixtures": "^1.2", + "symfony/browser-kit": "^6.4 || ^7.0" + }, + "require-dev": { + "ext-dom": "*", + "doctrine/doctrine-bundle": "^1.8 || ^2.0", + "doctrine/phpcr-odm": "^2.0", + "doctrine/phpcr-bundle": "^3.0", + "jackalope/jackalope-doctrine-dbal": "^2.0", + "symfony/console": "^6.4 || ^7.0", + "symfony/dependency-injection": "^6.4 || ^7.0", + "symfony/doctrine-bridge": "^6.4 || ^7.0", + "symfony/framework-bundle": "^6.4 || ^7.0", + "symfony/http-kernel": "^6.4 || ^7.0", + "symfony/monolog-bundle": "^3.5", + "symfony/security-bundle": "^6.4 || ^7.0", + "symfony/twig-bundle": "^6.4 || ^7.0", + "symfony/phpunit-bridge": "^7.0.3" + }, + "conflict": { + "doctrine/phpcr-odm": "<2.0", + "doctrine/phpcr-bundle": "<3.0", + "symfony/framework-bundle": "<6.4" }, "autoload": { "psr-4": { @@ -30,9 +44,10 @@ "Symfony\\Cmf\\Component\\Testing\\Tests\\": "tests/" } }, - "extra": { - "branch-alias": { - "dev-master": "1.1-dev" + "config": { + "sort-packages": true, + "allow-plugins": { + "composer/package-versions-deprecated": true } } } diff --git a/php_cs.dist b/php_cs.dist new file mode 100644 index 0000000..bc0747f --- /dev/null +++ b/php_cs.dist @@ -0,0 +1,67 @@ + true, + '@Symfony:risky' => true, + 'array_syntax' => [ + 'syntax' => 'short', + ], + 'combine_consecutive_issets' => true, + 'combine_consecutive_unsets' => true, + 'header_comment' => [ + 'header' => $header, + ], + 'no_extra_blank_lines' => true, + 'no_php4_constructor' => true, + 'no_useless_else' => true, + 'no_useless_return' => true, + 'ordered_class_elements' => true, + 'ordered_imports' => true, + 'phpdoc_order' => true, + '@PHP56Migration' => true, + '@PHP56Migration:risky' => true, + '@PHPUnit57Migration:risky' => true, + '@PHP70Migration' => true, + '@PHP70Migration:risky' => true, + '@PHPUnit60Migration:risky' => true, + '@PHP71Migration' => true, + '@PHP71Migration:risky' => true, + 'compact_nullable_typehint' => true, + 'void_return' => null, + 'strict_comparison' => true, + 'strict_param' => true, + 'php_unit_strict' => true, +]; + + +$finder = PhpCsFixer\Finder::create() + ->in(__DIR__) + ->exclude('Tests/Fixtures') + ->exclude('tests/Fixtures') + ->exclude('Resources/skeleton') + ->exclude('Resources/public/vendor') +; + +return PhpCsFixer\Config::create() + ->setFinder($finder) + ->setRiskyAllowed(true) + ->setRules($rules) + ->setUsingCache(true) +; diff --git a/phpunit.xml.dist b/phpunit.xml.dist index ebf4491..d1e9538 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,15 +1,18 @@ - - + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd" +> - + ./tests + + + diff --git a/resources/.travis.yml b/resources/.travis.yml deleted file mode 100644 index dd9412d..0000000 --- a/resources/.travis.yml +++ /dev/null @@ -1,23 +0,0 @@ -language: php - -php: - - 5.3 - - 5.4 - -env: - - SYMFONY_VERSION=2.3.* - - SYMFONY_VERSION=2.4.* - - SYMFONY_VERSION=dev-master - -before_script: - - ./vendor/symfony-cmf/testing/bin/init-travis/phpcr_odm_doctrine_dbal.sh - -script: phpunit --coverage-text - -notifications: - irc: "irc.freenode.org#symfony-cmf" - email: "symfony-cmf-devs@googlegroups.com" - -matrix: - allow_failures: - - env: SYMFONY_VERSION=dev-master diff --git a/resources/config/default.php b/resources/config/default.php index 6584474..40aa30b 100644 --- a/resources/config/default.php +++ b/resources/config/default.php @@ -1,6 +1,15 @@ getParameter('kernel.root_dir'); +/* + * This file is part of the Symfony CMF package. + * + * (c) 2011-2017 Symfony CMF + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +$kernelRootDir = $container->hasParameter('kernel.project_dir') ? $container->getParameter('kernel.project_dir') : $container->getParameter('kernel.root_dir'); $bundleName = null; if (preg_match('&/([a-zA-Z]+?)Bundle&', $kernelRootDir, $matches)) { @@ -14,10 +23,14 @@ } } -$loader->import('dist/parameters.yml'); -$loader->import('dist/framework.yml'); +if ($container->hasParameter('kernel.project_dir')) { + $loader->import(__DIR__.'/dist/parameters_sf5.yml'); +} else { + $loader->import(__DIR__.'/dist/parameters.yml'); +} if (class_exists('Symfony\Bundle\MonologBundle\MonologBundle')) { - $loader->import('dist/monolog.yml'); + $loader->import(__DIR__.'/dist/monolog.yml'); } -$loader->import('dist/doctrine.yml'); -$loader->import('dist/security.yml'); +$loader->import(__DIR__.'/dist/doctrine.yml'); +$loader->import(__DIR__.'/dist/framework.php'); +$loader->import(__DIR__.'/dist/security.php'); diff --git a/resources/config/dist/doctrine.yml b/resources/config/dist/doctrine.yml index 4ebffe6..0bac98d 100644 --- a/resources/config/dist/doctrine.yml +++ b/resources/config/dist/doctrine.yml @@ -1,5 +1,5 @@ doctrine: dbal: - driver: %database_driver% - path: %database_path% + driver: "%database_driver%" + path: "%database_path%" charset: UTF8 diff --git a/resources/config/dist/doctrine_orm.yml b/resources/config/dist/doctrine_orm.yml index 363512c..c616981 100644 --- a/resources/config/dist/doctrine_orm.yml +++ b/resources/config/dist/doctrine_orm.yml @@ -1,3 +1,5 @@ doctrine: orm: auto_mapping: true + controller_resolver: + auto_mapping: false diff --git a/resources/config/dist/framework.php b/resources/config/dist/framework.php new file mode 100644 index 0000000..bf9c84e --- /dev/null +++ b/resources/config/dist/framework.php @@ -0,0 +1,36 @@ + 'test', + 'test' => true, + 'form' => true, + 'validation' => [ + 'enabled' => true, + ], + 'router' => [ + 'resource' => '%kernel.project_dir%/config/routing.php', + ], + 'default_locale' => 'en', + 'translator' => [ + 'fallback' => 'en', + ], + 'session' => [ + 'storage_factory_id' => 'session.storage.factory.mock_file', + ], +]; + +$container->loadFromExtension('framework', $config); + +$container->loadFromExtension('twig', [ + 'debug' => '%kernel.debug%', + 'strict_variables' => '%kernel.debug%', +]); diff --git a/resources/config/dist/framework.yml b/resources/config/dist/framework.yml deleted file mode 100644 index 353e3e1..0000000 --- a/resources/config/dist/framework.yml +++ /dev/null @@ -1,19 +0,0 @@ -framework: - secret: test - test: ~ - session: - storage_id: session.storage.filesystem - form: true - csrf_protection: true - validation: - enabled: true - enable_annotations: true - router: - resource: %kernel.root_dir%/config/routing.php - default_locale: "en" - templating: { engines: ['twig'] } - translator: { fallback: en } - -twig: - debug: %kernel.debug% - strict_variables: %kernel.debug% diff --git a/resources/config/dist/monolog.yml b/resources/config/dist/monolog.yml index a87d5fc..9e21abc 100644 --- a/resources/config/dist/monolog.yml +++ b/resources/config/dist/monolog.yml @@ -2,5 +2,5 @@ monolog: handlers: main: type: stream - path: %kernel.logs_dir%/%kernel.environment%.log + path: "%kernel.logs_dir%/%kernel.environment%.log" level: debug diff --git a/resources/config/dist/parameters.yml b/resources/config/dist/parameters.yml index 068f115..80056e0 100644 --- a/resources/config/dist/parameters.yml +++ b/resources/config/dist/parameters.yml @@ -1,14 +1,5 @@ -parameters: - phpcr_backend: - #type: jackrabbit - #url: http://localhost:8080/server/ - type: doctrinedbal - # connection: default - phpcr_workspace: default - phpcr_user: admin - phpcr_pass: admin - - database_driver: pdo_sqlite - database_path: '%kernel.root_dir%/cache/app.sqlite' +imports: + - { resource: parameters.yml } - locale: en +parameters: + database_path: '%kernel.root_dir%/var/cache/app.sqlite' diff --git a/resources/config/dist/parameters_sf5.yml b/resources/config/dist/parameters_sf5.yml new file mode 100644 index 0000000..bbf8279 --- /dev/null +++ b/resources/config/dist/parameters_sf5.yml @@ -0,0 +1,16 @@ +parameters: + phpcr_backend: + #type: jackrabbit + #url: http://localhost:8080/server/ + type: doctrinedbal + # connection: default + parameters: + jackalope.check_login_on_server: false + phpcr_workspace: default + phpcr_user: admin + phpcr_pass: admin + + database_driver: pdo_sqlite + database_path: '%kernel.project_dir%/var/cache/app.sqlite' + + locale: en diff --git a/resources/config/dist/phpcr_odm.php b/resources/config/dist/phpcr_odm.php index bfb09d8..4933d35 100644 --- a/resources/config/dist/phpcr_odm.php +++ b/resources/config/dist/phpcr_odm.php @@ -1,44 +1,49 @@ array( - 'backend' => '%phpcr_backend%', +/* + * This file is part of the Symfony CMF package. + * + * (c) 2011-2017 Symfony CMF + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +$config = [ + 'session' => [ + 'backend' => '%phpcr_backend%', 'workspace' => '%phpcr_workspace%', 'username' => '%phpcr_user%', 'password' => '%phpcr_pass%', - ), - 'odm' => array( + ], + 'odm' => [ 'auto_mapping' => true, 'auto_generate_proxy_classes' => '%kernel.debug%', - 'locales' => array( - 'en' => array('de', 'fr'), - 'de' => array('en', 'fr'), - 'fr' => array('en', 'de'), - ), - 'mappings' => array( - 'test_default' => array( - 'type' => 'annotation', - 'prefix' => 'Symfony\Cmf\Component\Testing\Document', - 'dir' => CMF_TEST_ROOT_DIR.'/src/Document', - 'is_bundle' => false, - ), - ), - ), -); + 'locales' => [ + 'en' => ['de', 'fr'], + 'de' => ['en', 'fr'], + 'fr' => ['en', 'de'], + ], + ], +]; -$kernelRootDir = $container->getParameter('kernel.root_dir'); +$kernelRootDir = $container->hasParameter('kernel.project_dir') ? $container->getParameter('kernel.project_dir') : $container->getParameter('kernel.root_dir'); $bundleFQN = $container->getParameter('cmf_testing.bundle_fqn'); -$phpcrOdmDocDir = sprintf('%s/../Document', $kernelRootDir); -$phpcrOdmDocPrefix = sprintf('%s\Tests\Resources\Document', $bundleFQN); +if (getenv('KERNEL_CLASS')) { + $phpcrOdmDocDir = sprintf('%s/Document', $kernelRootDir); + $phpcrOdmDocPrefix = sprintf('%s\Tests\Fixtures\App\Document', $bundleFQN); +} else { + $phpcrOdmDocDir = sprintf('%s/../Document', $kernelRootDir); + $phpcrOdmDocPrefix = sprintf('%s\Tests\Resources\Document', $bundleFQN); +} if (file_exists($phpcrOdmDocDir)) { - - $config['odm']['mappings']['test_additional'] = array( - 'type' => 'annotation', + $config['odm']['mappings']['test_additional'] = [ + 'type' => 'attribute', 'prefix' => $phpcrOdmDocPrefix, 'dir' => $phpcrOdmDocDir, 'is_bundle' => false, - ); + ]; } $container->loadFromExtension('doctrine_phpcr', $config); diff --git a/resources/config/dist/security.php b/resources/config/dist/security.php new file mode 100644 index 0000000..57d1dc1 --- /dev/null +++ b/resources/config/dist/security.php @@ -0,0 +1,48 @@ + [ + 'ROLE_ADMIN' => 'ROLE_USER', + 'ROLE_SUPER_ADMIN' => ['ROLE_USER', 'ROLE_ADMIN', 'ROLE_ALLOWED_TO_SWITCH'], + ], + 'providers' => [ + 'in_memory' => [ + 'memory' => [ + 'users' => [ + 'admin' => ['password' => 'adminpass', 'roles' => ['ROLE_ADMIN']], + ], + ], + ], + ], + 'firewalls' => [ + 'dev' => [ + 'pattern' => '^/(_(profiler|wdt)|css|images|js)/', + 'security' => false, + ], + 'main' => [ + 'pattern' => '^/', + 'http_basic' => [ + 'realm' => 'Secured Demo Area', + ], + ], + ], + 'password_hashers' => [ + 'Symfony\Component\Security\Core\User\User' => 'plaintext', + ], +]; + +if (class_exists(\Symfony\Component\Security\Core\Security::class)) { + // Symfony 6 but not 7 + $config['enable_authenticator_manager'] = true; +} + +$container->loadFromExtension('security', $config); diff --git a/resources/config/dist/security.yml b/resources/config/dist/security.yml deleted file mode 100644 index e3b2db3..0000000 --- a/resources/config/dist/security.yml +++ /dev/null @@ -1,24 +0,0 @@ -security: - encoders: - Symfony\Component\Security\Core\User\User: plaintext - - role_hierarchy: - ROLE_ADMIN: ROLE_USER - ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH] - - providers: - in_memory: - memory: - users: - admin: { password: adminpass, roles: [ 'ROLE_ADMIN' ] } - - firewalls: - dev: - pattern: ^/(_(profiler|wdt)|css|images|js)/ - security: false - - main: - pattern: ^/ - anonymous: ~ - http_basic: - realm: "Secured Demo Area" diff --git a/resources/config/doctrine_orm.php b/resources/config/doctrine_orm.php index 9057b2d..1580261 100644 --- a/resources/config/doctrine_orm.php +++ b/resources/config/doctrine_orm.php @@ -1,3 +1,12 @@ import(CMF_TEST_CONFIG_DIR.'/dist/doctrine_orm.yml'); diff --git a/resources/config/phpcr_odm.php b/resources/config/phpcr_odm.php index 93fcd1d..3ad7bfb 100644 --- a/resources/config/phpcr_odm.php +++ b/resources/config/phpcr_odm.php @@ -1,3 +1,12 @@ import(CMF_TEST_CONFIG_DIR.'/dist/phpcr_odm.php'); diff --git a/resources/config/routing/sonata_routing.yml b/resources/config/routing/sonata_routing.yml index e438477..7b3e41e 100644 --- a/resources/config/routing/sonata_routing.yml +++ b/resources/config/routing/sonata_routing.yml @@ -1,5 +1,5 @@ admin: - resource: "@SonataAdminBundle/Resources/config/routing/sonata_admin.xml" + resource: '@SonataAdminBundle/Resources/config/routing/sonata_admin.xml' prefix: /admin sonata_admin: @@ -10,7 +10,7 @@ sonata_admin: id: .+ admin_dashboard: - pattern: /admin/ + path: /admin/ defaults: _controller: FrameworkBundle:Redirect:redirect route: sonata_admin_dashboard @@ -20,4 +20,4 @@ cmf_tree: type: 'cmf_tree' fos_js_routing: - resource: @FOSJsRoutingBundle/Resources/config/routing/routing.xml + resource: '@FOSJsRoutingBundle/Resources/config/routing/routing.xml' diff --git a/resources/config/sonata_admin.php b/resources/config/sonata_admin.php index 6d383bc..527efac 100644 --- a/resources/config/sonata_admin.php +++ b/resources/config/sonata_admin.php @@ -1,3 +1,12 @@ import(CMF_TEST_CONFIG_DIR.'/dist/sonata_admin.yml'); diff --git a/resources/web/app.php b/resources/web/app.php new file mode 100644 index 0000000..6174385 --- /dev/null +++ b/resources/web/app.php @@ -0,0 +1,32 @@ +query->get('env', 'phpcr'); +$request->query->remove('env'); + +$kernel = include __DIR__.'/../../bootstrap/kernel_bootstrap.php'; +$kernel->loadClassCache(); +$response = $kernel->handle($request); +$response->send(); +$kernel->terminate($request, $response); diff --git a/resources/web/app_test.php b/resources/web/app_test.php index 3c99048..2945383 100644 --- a/resources/web/app_test.php +++ b/resources/web/app_test.php @@ -1,18 +1,13 @@ query->get('env', 'phpcr'); -$request->query->remove('env'); - -$kernel = include __DIR__.'/../../bootstrap/kernel_bootstrap.php'; -$kernel->loadClassCache(); -$response = $kernel->handle($request); -$response->send(); -$kernel->terminate($request, $response); +/* + * This file is part of the Symfony CMF package. + * + * (c) 2011-2017 Symfony CMF + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +// This file exists for Symfony <3.3 support +require_once __DIR__.'/app.php'; diff --git a/resources/web/router.php b/resources/web/router.php index 9c60256..3728c02 100644 --- a/resources/web/router.php +++ b/resources/web/router.php @@ -1,16 +1,25 @@ find(null, '/'); - $base = new Generic; - $base->setNodename('test'); - $base->setParent($root); - $manager->persist($base); - $manager->flush(); - } -} - diff --git a/src/DependencyInjection/Compiler/TestContainerPass.php b/src/DependencyInjection/Compiler/TestContainerPass.php new file mode 100644 index 0000000..4514164 --- /dev/null +++ b/src/DependencyInjection/Compiler/TestContainerPass.php @@ -0,0 +1,40 @@ + + */ +class TestContainerPass implements CompilerPassInterface +{ + /** + * @var string[] Service id's which should be public in a test scenario + */ + private array $services; + + public function __construct(array $services = []) + { + $this->services = $services; + } + + public function process(ContainerBuilder $container): void + { + foreach ($container->getDefinitions() as $id => $definition) { + if (\in_array($id, $this->services, true)) { + $definition->setPublic(true); + } + } + } +} diff --git a/src/Document/Content.php b/src/Document/Content.php deleted file mode 100644 index e0dead2..0000000 --- a/src/Document/Content.php +++ /dev/null @@ -1,89 +0,0 @@ -id = $id; - } - - public function getId() - { - return $this->id; - } - - public function setParent($parent) - { - $this->parent = $parent; - } - - public function getParent() - { - return $this->parent; - } - - public function setName($name) - { - $this->name = $name; - } - - public function getName() - { - return $this->name; - } - - public function getTitle() - { - return $this->title; - } - - public function setTitle($title) - { - $this->title = $title; - } -} - diff --git a/src/Functional/BaseTestCase.php b/src/Functional/BaseTestCase.php index 9f19672..3a77b68 100644 --- a/src/Functional/BaseTestCase.php +++ b/src/Functional/BaseTestCase.php @@ -3,17 +3,22 @@ /* * This file is part of the Symfony CMF package. * - * (c) 2011-2014 Symfony CMF + * (c) 2011-2017 Symfony CMF * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ - namespace Symfony\Cmf\Component\Testing\Functional; +use Doctrine\Bundle\PHPCRBundle\Test\RepositoryManager; +use Symfony\Bundle\FrameworkBundle\KernelBrowser; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; -use Symfony\Component\DependencyInjection\Container; +use Symfony\Cmf\Component\Testing\Functional\DbManager\ORM; +use Symfony\Cmf\Component\Testing\Functional\DbManager\PHPCR; +use Symfony\Cmf\Component\Testing\Functional\DbManager\PhpcrDecorator; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\KernelInterface; /** * The base class for Functional and Web tests. @@ -24,16 +29,11 @@ abstract class BaseTestCase extends WebTestCase { /** - * Use this property to save the DbManager. + * Use this property to save the DbManagers. */ - protected $db; - - protected $dbManagers = array(); + protected array $dbManagers = []; - /** - * @var Container - */ - protected $container; + protected ?KernelBrowser $client = null; /** * Return the configuration to use when creating the Kernel. @@ -42,47 +42,83 @@ abstract class BaseTestCase extends WebTestCase * * * environment - The environment to use (defaults to 'phpcr') * * debug - If debug should be enabled/disabled (defaults to true) - * - * @return array */ - protected function getKernelConfiguration() + protected static function getKernelConfiguration(): array { - return array(); + return []; } /** - * Gets the container. + * {@inheritdoc} * - * @return Container + * Overwritten to set the default environment to 'phpcr'. */ - public function getContainer() + protected static function createKernel(array $options = []): KernelInterface { - if (null === $this->container) { - $client = $this->createClient($this->getKernelConfiguration()); - $this->container = $client->getContainer(); + // default environment is 'phpcr' + if (!isset($options['environment'])) { + $options['environment'] = 'phpcr'; } - return $this->container; + return parent::createKernel($options); } /** - * Gets the DbManager. + * {@inheritdoc} * - * @see self::getDbManager + * Overwritten to set the kernel configuration from getKernelConfiguration. */ - public function db($type) + protected static function bootKernel(array $options = []): KernelInterface { - return $this->getDbManager($type); + return parent::bootKernel(static::getKernelConfiguration()); + } + + protected static function getKernel(): KernelInterface + { + if (null === static::$kernel) { + static::bootKernel(); + } + + if (static::$kernel instanceof KernelInterface) { + $kernelEnvironment = static::$kernel->getEnvironment(); + $expectedEnvironment = static::getKernelConfiguration()['environment'] ?? 'phpcr'; + if ($kernelEnvironment !== $expectedEnvironment) { + var_dump($kernelEnvironment, $expectedEnvironment); + static::bootKernel(); + } + } + + if (!static::$kernel->getContainer()) { + static::$kernel->boot(); + } + + return static::$kernel; + } + + protected function getFrameworkBundleClient(): KernelBrowser + { + if (null === $this->client) { + // property does not exist in all symfony versions + if (property_exists(self::class, 'booted') && self::$booted) { + self::ensureKernelShutdown(); + } + $this->client = self::createClient(self::getKernelConfiguration()); + } + + return $this->client; } /** - * Gets the DbManager. + * Shortcut for getDbManager. * - * @param string $type The Db type - * - * @return object + * @see self::getDbManager */ - public function getDbManager($type) + protected function db(string $type): PhpcrDecorator|PHPCR|ORM + { + return $this->getDbManager($type); + } + + protected function getDbManager(string $type): PhpcrDecorator|PHPCR|ORM { if (isset($this->dbManagers[$type])) { return $this->dbManagers[$type]; @@ -93,6 +129,10 @@ public function getDbManager($type) $type ); + if ('phpcr' === strtolower($type) && class_exists(RepositoryManager::class)) { + $className = PhpcrDecorator::class; + } + if (!class_exists($className)) { throw new \InvalidArgumentException(sprintf( 'Test DBManager "%s" does not exist.', @@ -100,25 +140,27 @@ public function getDbManager($type) )); } - $dbManager = new $className($this->getContainer()); + $dbManager = new $className(self::getContainer()); $this->dbManagers[$type] = $dbManager; - return $this->getDbManager($type); + return $dbManager; } - /** - * {@inheritDoc} - * - * This is overriden to set the default environment to 'phpcr' - */ - protected static function createKernel(array $options = array()) + protected static function assertResponseSuccess(Response $response): void { - // default environment is 'phpcr' - if (!isset($options['environment'])) { - $options['environment'] = 'phpcr'; + libxml_use_internal_errors(true); + + $dom = new \DOMDocument(); + $dom->loadHTML($response->getContent()); + + $xpath = new \DOMXPath($dom); + $result = $xpath->query('//div[contains(@class,"text-exception")]/h1'); + $exception = null; + if ($result->length) { + $exception = $result->item(0)->nodeValue; } - return parent::createKernel($options); + self::assertEquals(200, $response->getStatusCode(), $exception ? 'Exception: "'.$exception.'"' : ''); } } diff --git a/src/Functional/DbManager/ORM.php b/src/Functional/DbManager/ORM.php index b3635ea..c72fd14 100644 --- a/src/Functional/DbManager/ORM.php +++ b/src/Functional/DbManager/ORM.php @@ -3,20 +3,24 @@ /* * This file is part of the Symfony CMF package. * - * (c) 2011-2014 Symfony CMF + * (c) 2011-2017 Symfony CMF * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ - namespace Symfony\Cmf\Component\Testing\Functional\DbManager; +use Doctrine\Common\DataFixtures\DependentFixtureInterface; +use Doctrine\Common\DataFixtures\Executor\ORMExecutor; +use Doctrine\Common\DataFixtures\Loader; +use Doctrine\Common\DataFixtures\ProxyReferenceRepository; +use Doctrine\Common\DataFixtures\Purger\ORMPurger; +use Doctrine\Persistence\ManagerRegistry; +use Doctrine\Persistence\ObjectManager; +use Symfony\Bridge\Doctrine\DataFixtures\ContainerAwareLoader; use Symfony\Component\DependencyInjection\ContainerInterface; -use Doctrine\Common\Persistence\ManagerRegistry; -use Doctrine\Common\Persistence\ObjectManager; - /** * The DbManager for the Doctrine2 ORM. * @@ -26,48 +30,86 @@ */ class ORM { - /** - * @var ContainerInterface - */ - protected $container; + private ORMExecutor $executor; + protected ContainerInterface $container; + protected ObjectManager $om; - /** - * @var ObjectManager - */ - protected $om; - - /** - * Constructor. - * - * @param ContainerInterface $container - */ public function __construct(ContainerInterface $container) { $this->container = $container; } - /** - * Gets the Doctrine ManagerRegistry - * - * @return ManagerRegistry - */ - public function getRegistry() + public function getRegistry(): ManagerRegistry { return $this->container->get('doctrine'); } - /** - * Gets the Doctrine ObjectManager - * - * @param null $managerName - * @return ObjectManager - */ - public function getOm($managerName = null) + public function getOm($managerName = null): ObjectManager { - if (!$this->om) { + if (!isset($this->om)) { $this->om = $this->getRegistry()->getManager($managerName); } return $this->om; } + + public function purgeDatabase(): void + { + $referenceRepository = new ProxyReferenceRepository($this->getOm()); + $this->getExecutor()->setReferenceRepository($referenceRepository); + $this->getExecutor()->purge(); + } + + /** + * @param string[] $classNames + */ + public function loadFixtures(array $classNames): void + { + $this->purgeDatabase(); + $loader = new ContainerAwareLoader($this->container); + + foreach ($classNames as $className) { + $this->loadFixtureClass($loader, $className); + } + + $this->getExecutor()->execute($loader->getFixtures(), true); + } + + protected function loadFixtureClass(Loader $loader, string $className): void + { + if (!class_exists($className)) { + throw new \InvalidArgumentException(sprintf( + 'Fixture class "%s" does not exist.', + $className + )); + } + + $fixture = new $className(); + + if ($loader->hasFixture($fixture)) { + unset($fixture); + + return; + } + + $loader->addFixture($fixture); + + if ($fixture instanceof DependentFixtureInterface) { + foreach ($fixture->getDependencies() as $dependency) { + $this->loadFixtureClass($loader, $dependency); + } + } + } + + private function getExecutor(): ORMExecutor + { + if (isset($this->executor)) { + return $this->executor; + } + + $purger = new ORMPurger(); + $this->executor = new ORMExecutor($this->getOm(), $purger); + + return $this->executor; + } } diff --git a/src/Functional/DbManager/PHPCR.php b/src/Functional/DbManager/PHPCR.php index 42d2759..4a86fab 100644 --- a/src/Functional/DbManager/PHPCR.php +++ b/src/Functional/DbManager/PHPCR.php @@ -3,43 +3,44 @@ /* * This file is part of the Symfony CMF package. * - * (c) 2011-2014 Symfony CMF + * (c) 2011-2017 Symfony CMF * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ - namespace Symfony\Cmf\Component\Testing\Functional\DbManager; -use Doctrine\Common\DataFixtures\Purger\PHPCRPurger; -use Doctrine\Common\DataFixtures\Executor\PHPCRExecutor; -use Symfony\Bridge\Doctrine\DataFixtures\ContainerAwareLoader; +use Doctrine\Bundle\PHPCRBundle\DataFixtures\PHPCRExecutor; use Doctrine\Common\DataFixtures\DependentFixtureInterface; +use Doctrine\Common\DataFixtures\FixtureInterface; +use Doctrine\Common\DataFixtures\Loader; +use Doctrine\Common\DataFixtures\ProxyReferenceRepository; +use Doctrine\Common\DataFixtures\Purger\PHPCRPurger; use Doctrine\ODM\PHPCR\DocumentManager; +use Doctrine\Persistence\ManagerRegistry; +use Symfony\Bridge\Doctrine\DataFixtures\ContainerAwareLoader; use Symfony\Component\DependencyInjection\ContainerInterface; -use Doctrine\Common\DataFixtures\ProxyReferenceRepository; class PHPCR { - protected $container; - protected $om; + protected ContainerInterface $container; + + protected ?DocumentManager $om = null; + + private ?PHPCRExecutor $executor = null; public function __construct(ContainerInterface $container) { $this->container = $container; } - public function getRegistry() + public function getRegistry(): ManagerRegistry { return $this->container->get('doctrine_phpcr'); } - /** - * @param null|string $managerName - * @return DocumentManager - */ - public function getOm($managerName = null) + public function getOm(?string $managerName = null): DocumentManager { if (!$this->om) { $this->om = $this->getRegistry()->getManager($managerName); @@ -48,37 +49,50 @@ public function getOm($managerName = null) return $this->om; } - public function loadFixtures(array $classNames) + public function purgeRepository(bool $initialize = false): void { - $loader = new ContainerAwareLoader($this->container);; - $purger = new PHPCRPurger(); - $executor = new PHPCRExecutor($this->getOm(), $purger); - - $referenceRepository = new ProxyReferenceRepository($this->getOm()); + $this->getExecutor($initialize)->purge(); + } - $executor->setReferenceRepository($referenceRepository); - $executor->purge(); + /** + * @param array $classes Fixture classes or class names to load + * @param bool $initialize Whether the ODM repository initializers should be executed + */ + public function loadFixtures(array $classes, bool $initialize = false): void + { + $loader = class_exists(ContainerAwareLoader::class) + ? new ContainerAwareLoader($this->container) + : new Loader() + ; - foreach ($classNames as $className) { + foreach ($classes as $className) { $this->loadFixtureClass($loader, $className); } - $executor->execute($loader->getFixtures(), true); + $this->getExecutor($initialize)->execute($loader->getFixtures(), false); } - public function loadFixtureClass($loader, $className) + /** + * @param class-string|FixtureInterface $class + */ + public function loadFixtureClass(Loader $loader, $class): void { - if (!class_exists($className)) { - throw new \InvalidArgumentException(sprintf( - 'Fixture class "%s" does not exist.', - $className - )); - } + if (\is_object($class)) { + $fixture = $class; + } else { + if (!class_exists($class)) { + throw new \InvalidArgumentException(sprintf( + 'Fixture class "%s" does not exist.', + $class + )); + } - $fixture = new $className(); + $fixture = new $class(); + } if ($loader->hasFixture($fixture)) { unset($fixture); + return; } @@ -91,7 +105,10 @@ public function loadFixtureClass($loader, $className) } } - public function createTestNode() + /** + * Create a test node, if the test node already exists, remove it. + */ + public function createTestNode(): void { $session = $this->container->get('doctrine_phpcr.session'); @@ -103,4 +120,24 @@ public function createTestNode() $session->save(); } + + private function getExecutor(bool $initialize = false): PHPCRExecutor + { + static $lastInitialize = null; + + if ($this->executor && $initialize === $lastInitialize) { + return $this->executor; + } + + $initializerManager = $initialize ? $this->container->get('doctrine_phpcr.initializer_manager') : null; + $purger = new PHPCRPurger(); + $executor = new PHPCRExecutor($this->getOm(), $purger, $initializerManager); + $referenceRepository = new ProxyReferenceRepository($this->getOm()); + $executor->setReferenceRepository($referenceRepository); + + $this->executor = $executor; + $lastInitialize = $initialize; + + return $executor; + } } diff --git a/src/Functional/DbManager/PhpcrDecorator.php b/src/Functional/DbManager/PhpcrDecorator.php new file mode 100644 index 0000000..c1ab08b --- /dev/null +++ b/src/Functional/DbManager/PhpcrDecorator.php @@ -0,0 +1,49 @@ +get('doctrine_phpcr'), $container->get('doctrine_phpcr.initializer_manager')); + } + + public function getOm(string $managerName = null): DocumentManagerInterface + { + return $this->getDocumentManager($managerName); + } + + /** + * Create a test node, if the test node already exists, remove it. + */ + public function createTestNode(): void + { + $session = $this->getDocumentManager()->getPhpcrSession(); + + if ($session->nodeExists('/test')) { + $session->getNode('/test')->remove(); + } + + $session->getRootNode()->addNode('test', 'nt:unstructured'); + + $session->save(); + } +} diff --git a/src/HttpKernel/TestKernel.php b/src/HttpKernel/TestKernel.php index e19b143..27b7b06 100644 --- a/src/HttpKernel/TestKernel.php +++ b/src/HttpKernel/TestKernel.php @@ -3,19 +3,26 @@ /* * This file is part of the Symfony CMF package. * - * (c) 2011-2014 Symfony CMF + * (c) 2011-2017 Symfony CMF * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ - namespace Symfony\Cmf\Component\Testing\HttpKernel; -use Symfony\Component\Filesystem\Filesystem; -use Symfony\Component\Config\Loader\LoaderInterface; -use Symfony\Component\HttpKernel\Kernel; +use Doctrine\Bundle\DoctrineBundle\DoctrineBundle; +use Doctrine\Bundle\PHPCRBundle\DoctrinePHPCRBundle; +use Symfony\Bundle\FrameworkBundle\FrameworkBundle; +use Symfony\Bundle\MonologBundle\MonologBundle; +use Symfony\Bundle\SecurityBundle\SecurityBundle; +use Symfony\Bundle\TwigBundle\TwigBundle; +use Symfony\Bundle\WebServerBundle\WebServerBundle; +use Symfony\Cmf\Component\Testing\DependencyInjection\Compiler\TestContainerPass; +use Symfony\Component\DependencyInjection\Compiler\PassConfig; +use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\HttpKernel\Bundle\BundleInterface; +use Symfony\Component\HttpKernel\Kernel; /** * TestKernel base class for Symfony CMF Bundle @@ -25,8 +32,9 @@ */ abstract class TestKernel extends Kernel { - protected $bundleSets = array(); - protected $requiredBundles = array(); + protected array $bundleSets = []; + + protected array $requiredBundles = []; /** * Register commonly needed bundle sets and then @@ -34,57 +42,25 @@ abstract class TestKernel extends Kernel * concrete kernel configure itself using the abstracvt * configure() command. */ - public function init() + public function __construct(string $env, bool $debug) { - $this->registerBundleSet('default', array( - 'Symfony\Bundle\FrameworkBundle\FrameworkBundle', - 'Symfony\Bundle\SecurityBundle\SecurityBundle', - 'Symfony\Bundle\TwigBundle\TwigBundle', - 'Symfony\Bundle\MonologBundle\MonologBundle', - )); - - $this->registerBundleSet('phpcr_odm', array( - 'Doctrine\Bundle\DoctrineBundle\DoctrineBundle', - 'Doctrine\Bundle\PHPCRBundle\DoctrinePHPCRBundle', - )); - - $this->registerBundleSet('doctrine_orm', array( - 'Doctrine\Bundle\DoctrineBundle\DoctrineBundle', - )); - - $this->registerBundleSet('sonata_admin', array( - 'Sonata\BlockBundle\SonataBlockBundle', - 'Sonata\CoreBundle\SonataCoreBundle', - 'Sonata\AdminBundle\SonataAdminBundle', - 'Sonata\jQueryBundle\SonatajQueryBundle', - 'Knp\Bundle\MenuBundle\KnpMenuBundle', - 'Sonata\DoctrinePHPCRAdminBundle\SonataDoctrinePHPCRAdminBundle', - 'Symfony\Cmf\Bundle\TreeBrowserBundle\CmfTreeBrowserBundle', - 'FOS\JsRoutingBundle\FOSJsRoutingBundle', - )); - - $this->registerBundleSet('sonata_admin_orm', array( - 'Sonata\BlockBundle\SonataBlockBundle', - 'Sonata\CoreBundle\SonataCoreBundle', - 'Sonata\AdminBundle\SonataAdminBundle', - 'Sonata\jQueryBundle\SonatajQueryBundle', - 'Knp\Bundle\MenuBundle\KnpMenuBundle', - 'FOS\JsRoutingBundle\FOSJsRoutingBundle', - 'Sonata\DoctrineORMAdminBundle\SonataDoctrineORMAdminBundle', - )); - - $this->registerBundleSet('sonata_admin_phpcr', array( - 'Sonata\BlockBundle\SonataBlockBundle', - 'Sonata\CoreBundle\SonataCoreBundle', - 'Sonata\AdminBundle\SonataAdminBundle', - 'Sonata\jQueryBundle\SonatajQueryBundle', - 'Knp\Bundle\MenuBundle\KnpMenuBundle', - 'Sonata\DoctrinePHPCRAdminBundle\SonataDoctrinePHPCRAdminBundle', - 'Symfony\Cmf\Bundle\TreeBrowserBundle\CmfTreeBrowserBundle', - 'FOS\JsRoutingBundle\FOSJsRoutingBundle', - )); - - parent::init(); + $defaultBundles = [ + FrameworkBundle::class, + SecurityBundle::class, + TwigBundle::class, + MonologBundle::class, + ]; + + if (class_exists(WebServerBundle::class)) { + $defaultBundles[] = WebServerBundle::class; + } + + $this->registerBundleSet('default', $defaultBundles); + + $this->registerBundleSet('phpcr_odm', [DoctrineBundle::class, DoctrinePHPCRBundle::class]); + $this->registerBundleSet('doctrine_orm', [DoctrineBundle::class]); + + parent::__construct($env, $debug); $this->configure(); } @@ -95,25 +71,26 @@ public function init() * $this->requireBundleSets('default', 'phpcr_odm'); * $this->addBundle(new MyBundle); * $this->addBundles(array(new Bundle1, new Bundle2)); - * */ - abstract protected function configure(); + abstract protected function configure(): void; /** - * Register a set of bundles with the given name + * Register a set of bundles with the given name. * * This method does not add the bundles to the kernel, * it just makes a set available. */ - public function registerBundleSet($name, $bundles) + public function registerBundleSet(string $name, array $bundles): void { $this->bundleSets[$name] = $bundles; } /** * The bundles in the named sets will be added to the Kernel. + * + * @param string[] $names */ - public function requireBundleSets(array $names) + public function requireBundleSets(array $names): void { foreach ($names as $name) { $this->requireBundleSet($name); @@ -127,7 +104,7 @@ public function requireBundleSets(array $names) * This enables us to declare pre-defined bundle sets without * worrying if the bundle is actually present or not. */ - public function requireBundleSet($name) + public function requireBundleSet(string $name): void { if (!isset($this->bundleSets[$name])) { throw new \InvalidArgumentException(sprintf( @@ -145,14 +122,14 @@ public function requireBundleSet($name) )); } - $this->requiredBundles[$bundle] = new $bundle; + $this->requiredBundles[$bundle] = new $bundle(); } } /** - * Add concrete bundles to the kernel + * Add concrete bundles to the kernel. */ - public function addBundles(array $bundles) + public function addBundles(array $bundles): void { foreach ($bundles as $bundle) { $this->addBundle($bundle); @@ -160,41 +137,85 @@ public function addBundles(array $bundles) } /** - * Add a concrete bundle to the kernel + * Add a concrete bundle to the kernel. */ - public function addBundle(BundleInterface $bundle) + public function addBundle(BundleInterface $bundle): void { $this->requiredBundles[] = $bundle; } /** - * {inheritDoc} + * {@inheritDoc}. * * Here we return our list of bundles */ - public function registerBundles() + public function registerBundles(): iterable { return $this->requiredBundles; } /** - * Returns the KernelDir of the CHILD class, + * Returns the project directory of the CHILD class, * i.e. the concrete implementation in the bundles * src/ directory (or wherever). */ - public function getKernelDir() + public function getProjectDir(): string { $refl = new \ReflectionClass($this); $fname = $refl->getFileName(); - $kernelDir = dirname($fname); - return $kernelDir; + + return \dirname($fname); + } + + public function getCacheDir(): string + { + return implode('/', [ + $this->getProjectDir(), + 'var', + 'cache', + ]); } - public function getCacheDir() + public function getLogDir(): string { - return implode('/', array( - $this->getKernelDir(), - 'cache' - )); + return implode('/', [ + $this->getProjectDir(), + 'var', + 'logs', + ]); + } + + /** + * Registers the bundles defined in config/bundles.php. + */ + protected function registerConfiguredBundles(): void + { + $bundleFilePath = $this->getProjectDir().'/config/bundles.php'; + if (!file_exists($bundleFilePath)) { + return; + } + + $bundles = require $bundleFilePath; + foreach ($bundles as $class => $environments) { + if (isset($environments['all']) || isset($environments[$this->environment])) { + if (!class_exists($class)) { + throw new \InvalidArgumentException(sprintf( + 'Bundle class "%s" does not exist.', + $class + )); + } + + $this->requiredBundles[$class] = new $class(); + } + } + } + + protected function build(ContainerBuilder $container): void + { + parent::build($container); + if (\in_array($this->getEnvironment(), ['test', 'phpcr']) && file_exists($this->getProjectDir().'/config/public_services.php')) { + $services = require $this->getProjectDir().'/config/public_services.php'; + $container->addCompilerPass(new TestContainerPass($services), PassConfig::TYPE_OPTIMIZE); + } } } diff --git a/src/Phpunit/DatabaseTestListener.php b/src/Phpunit/DatabaseTestListener.php deleted file mode 100644 index 458305d..0000000 --- a/src/Phpunit/DatabaseTestListener.php +++ /dev/null @@ -1,224 +0,0 @@ -processBuilder = new ProcessBuilder(); - $phpExecutableFinder = new PhpExecutableFinder(); - $phpExecutable = $phpExecutableFinder->find(); - if (false === $phpExecutable) { - throw new \RuntimeException('No PHP executable found on the current system.'); - } - - // Symfony 2.3 does not support array prefix, so we have to implement it ourselves - $this->prefix = array($phpExecutable, __DIR__.'/../../bin/console'); - } else { - $this->processBuilder = $processBuilder; - } - } - - public function addError(\PHPUnit_Framework_Test $test, \Exception $e, $time) - { - } - - public function addFailure(\PHPUnit_Framework_Test $test, \PHPUnit_Framework_AssertionFailedError $e, $time) - { - } - - public function addIncompleteTest(\PHPUnit_Framework_Test $test, \Exception $e, $time) - { - } - - public function addSkippedTest(\PHPUnit_Framework_Test $test, \Exception $e, $time) - { - } - - public function addRiskyTest(PHPUnit_Framework_Test $test, Exception $e, $time) - { - } - - public function startTest(\PHPUnit_Framework_Test $test) - { - switch (static::$currentSuite->getName()) { - case 'orm': - $db = $test->getDbManager('ORM'); - $purger = new Purger\ORMPurger($db->getOm()); - break; - - case 'phpcr': - $db = $test->getDbManager('PHPCR'); - $purger = new Purger\PHPCRPurger($db->getOm()); - break; - - default; - return; - } - - $purger->purge(); - } - - public function endTest(\PHPUnit_Framework_Test $test, $time) - { - } - - public function startTestSuite(\PHPUnit_Framework_TestSuite $suite) - { - static::$currentSuite = $suite; - - switch ($suite->getName()) { - case 'orm': - $this->setUpOrmDatabase($suite); - break; - - case 'phpcr': - $this->setUpPhpcrDatabase($suite); - break; - - default: - if (!class_exists($suite->getName()) && false === strpos($suite->getName(), '::')) { - echo PHP_EOL.PHP_EOL.'['.$suite->getName().']'.PHP_EOL; - } - } - } - - private function setUpPhpcrDatabase($suite) - { - echo PHP_EOL.PHP_EOL; - - $process = $this->processBuilder - ->setArguments(array_merge($this->prefix, array('doctrine:phpcr:init:dbal', '--drop'))) - ->getProcess(); - $process->run(); - - while (true) { - if ($process->isTerminated()) { - if (!$process->isSuccessful()) { - $output = null !== $process->getErrorOutput() ? $process->getErrorOutput() : $process->getOutput(); - $suite->markTestSuiteSkipped('[PHPCR] Error when initializing dbal: '.$output); - } else { - $process = $this->processBuilder - ->setArguments(array_merge($this->prefix, array('doctrine:phpcr:repository:init'))) - ->getProcess(); - $process->run(); - - while (true) { - if ($process->isTerminated()) { - if (!$process->isSuccessful()) { - $output = null !== $process->getErrorOutput() ? $process->getErrorOutput() : $process->getOutput(); - $suite->markTestSuiteSkipped('[PHPCR] Error when initializing repositories: '.$output); - } else { - echo '[PHPCR]'.PHP_EOL; - } - } - - break; - } - } - - break; - } - } - } - - private function setUpOrmDatabase($suite) - { - echo PHP_EOL.PHP_EOL; - - $process = $this->processBuilder - ->setArguments(array_merge($this->prefix, array('doctrine:schema:drop', '--env=orm', '--force'))) - ->getProcess(); - $process->run(); - - while (true) { - if ($process->isTerminated()) { - if (!$process->isSuccessful()) { - $output = null !== $process->getErrorOutput() ? $process->getErrorOutput() : $process->getOutput(); - $suite->markTestSuiteSkipped('[ORM] Error when dropping database: '.$output); - return; - } - break; - } - } - - $process = $this->processBuilder - ->setArguments(array_merge($this->prefix, array('doctrine:database:create', '--env=orm'))) - ->getProcess(); - $process->run(); - - while (true) { - if ($process->isTerminated()) { - if (!$process->isSuccessful()) { - $output = null !== $process->getErrorOutput() ? $process->getErrorOutput() : $process->getOutput(); - $suite->markTestSuiteSkipped('[ORM] Error when creating database: '.$output); - } else { - $process = $this->processBuilder - ->setArguments(array_merge($this->prefix, array('doctrine:schema:create', '--env=orm'))) - ->getProcess(); - $process->run(); - - while (true) { - if ($process->isTerminated()) { - if (!$process->isSuccessful()) { - $output = null !== $process->getErrorOutput() ? $process->getErrorOutput() : $process->getOutput(); - $suite->markTestSuiteSkipped('[ORM] Error when creating schema: '.$output); - } else { - echo '[ORM]'.PHP_EOL; - } - } - - break; - } - } - - break; - } - } - } - - public function endTestSuite(\PHPUnit_Framework_TestSuite $suite) - { - if (!in_array($suite->getName(), array('phpcr', 'orm'))) { - return; - } - - $process = $this->processBuilder - ->setArguments(array_merge($this->prefix, array('doctrine:database:drop', '--force'))) - ->getProcess(); - $process->run(); - - while (true) { - if ($process->isTerminated()) { - if (!$process->isSuccessful()) { - $output = null !== $process->getErrorOutput() ? $process->getErrorOutput() : $process->getOutput(); - $suite->markTestSuiteSkipped('Error when dropping database: '.$output); - } - } - break; - } - } -} diff --git a/src/Resources/meta/LICENSE b/src/Resources/meta/LICENSE new file mode 100644 index 0000000..be94b1b --- /dev/null +++ b/src/Resources/meta/LICENSE @@ -0,0 +1,23 @@ +Symfony CMF Testing + + The MIT License + + Copyright (c) 2011-2017 Symfony CMF + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. diff --git a/src/Unit/Constraint/SchemaAcceptsXml.php b/src/Unit/Constraint/SchemaAcceptsXml.php index 981ff9f..d3913ae 100644 --- a/src/Unit/Constraint/SchemaAcceptsXml.php +++ b/src/Unit/Constraint/SchemaAcceptsXml.php @@ -3,19 +3,22 @@ /* * This file is part of the Symfony CMF package. * - * (c) 2011-2014 Symfony CMF + * (c) 2011-2017 Symfony CMF * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ - namespace Symfony\Cmf\Component\Testing\Unit\Constraint; -class SchemaAcceptsXml extends \PHPUnit_Framework_Constraint +use PHPUnit\Framework\Constraint\Constraint; + +class SchemaAcceptsXml extends Constraint { protected $xml; + protected $failingElement; + protected $errors; public function __construct($xml) @@ -23,7 +26,7 @@ public function __construct($xml) $this->xml = $xml; } - public function matches($schemaFile) + public function matches($schemaFile): bool { foreach ($this->xml as $id => $dom) { $configElement = $dom->getElementsByTagName('config'); @@ -32,7 +35,7 @@ public function matches($schemaFile) throw new \InvalidArgumentException(sprintf('Can only test a file if it contains 1 element, %d given', $configElement->length)); } - $configDom = new \DomDocument(); + $configDom = new \DOMDocument(); $configDom->appendChild($configDom->importNode($configElement->item(0), true)); libxml_use_internal_errors(true); @@ -47,22 +50,24 @@ public function matches($schemaFile) return true; } - public function count() + public function count(): int { - return count($this->xml); + return \count($this->xml); } - public function toString() { } + public function toString(): string + { + } - protected function failureDescription($schemaFile) + protected function failureDescription($schemaFile): string { return sprintf( - "Xml is accepted by the XML schema \"%s\"", + 'Xml is accepted by the XML schema "%s"', $schemaFile ); } - protected function additionalFailureDescription($schema) + protected function additionalFailureDescription($schema): string { $str = "\n".$this->xml[$this->failingElement]->saveXml()."\n\n"; diff --git a/src/Unit/XmlSchemaTestCase.php b/src/Unit/XmlSchemaTestCase.php index 6e568a0..1c53e8a 100644 --- a/src/Unit/XmlSchemaTestCase.php +++ b/src/Unit/XmlSchemaTestCase.php @@ -3,16 +3,18 @@ /* * This file is part of the Symfony CMF package. * - * (c) 2011-2014 Symfony CMF + * (c) 2011-2017 Symfony CMF * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ - namespace Symfony\Cmf\Component\Testing\Unit; -abstract class XmlSchemaTestCase extends \PHPUnit_Framework_TestCase +use PHPUnit\Framework\Constraint\LogicalNot; +use PHPUnit\Framework\TestCase; + +abstract class XmlSchemaTestCase extends TestCase { public static function assertSchemaAcceptsXml($xmlDoms, $schemaPath, $message = '') { @@ -23,28 +25,28 @@ public static function assertSchemaRefusesXml($xmlDoms, $schemaPath, $message = { return self::assertThat( $schemaPath, - new \PHPUnit_Framework_Constraint_Not(self::getSchemaAcceptsXmlConstraint($xmlDoms)), + new LogicalNot(self::getSchemaAcceptsXmlConstraint($xmlDoms)), $message ); } private static function getSchemaAcceptsXmlConstraint($xmlDoms) { - if (!is_array($xmlDoms)) { - $xmlDoms = array($xmlDoms); + if (!\is_array($xmlDoms)) { + $xmlDoms = [$xmlDoms]; } $xmlDoms = array_map(function ($dom) { - if (is_string($dom)) { + if (\is_string($dom)) { $xml = $dom; $dom = new \DOMDocument(); $dom->load($xml); return $dom; } - + if (!$dom instanceof \DOMDocument) { - throw new \InvalidArgumentException(sprintf('The first argument of assertSchemaAcceptsXml should be instances of \DOMDocument, "%s" given', get_class($dom))); + throw new \InvalidArgumentException(sprintf('The first argument of assertSchemaAcceptsXml should be instances of \DOMDocument, "%s" given', \get_class($dom))); } return $dom; diff --git a/tests/Fixtures/TestTestCase.php b/tests/Fixtures/TestTestCase.php index 4df89a9..17b2b4c 100644 --- a/tests/Fixtures/TestTestCase.php +++ b/tests/Fixtures/TestTestCase.php @@ -1,5 +1,14 @@ testCase = new TestTestCase(); + private Container&MockObject $container; + private KernelInterface&MockObject $kernel; + private TestTestCase $testCase; + private KernelBrowser&MockObject $client; - $this->container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface'); - - $me = $this; - $this->container->expects($this->any()) + protected function setUp(): void + { + $managerRegistry = $this->createMock(ManagerRegistryInterface::class); + $initializerManager = $this->createMock(InitializerManager::class); + $this->container = $this->createMock(Container::class); + $this->container ->method('get') - ->will($this->returnCallback(function ($name) use ($me) { - $dic = array( - 'test.client' => $me->client, - ); + ->willReturnCallback(function ($name) use ($managerRegistry, $initializerManager) { + $dic = [ + 'test.client' => $this->client, + 'test.service_container' => $this->container, + 'doctrine_phpcr' => $managerRegistry, + 'doctrine_phpcr.initializer_manager' => $initializerManager, + ]; return $dic[$name]; - })); + }); - $this->kernel = $this->getMock('Symfony\Component\HttpKernel\KernelInterface'); + $this->kernel = $this->createMock(KernelInterface::class); + $this->kernel + ->method('getContainer') + ->willReturn($this->container) + ; + $this->kernel + ->method('getEnvironment') + ->willReturn('phpcr') + ; + $this->testCase = new TestTestCase(); $this->testCase->setKernel($this->kernel); - $this->kernel->expects($this->any()) - ->method('getContainer') - ->will($this->returnValue($this->container)); - - $this->client = $this->getMockBuilder('Symfony\Bundle\FrameworkBundle\Client') - ->disableOriginalConstructor() - ->getMock(); + $this->client = $this->createMock(KernelBrowser::class); - $this->client->expects($this->any()) + $this->client ->method('getContainer') - ->will($this->returnValue($this->container)); + ->willReturn($this->container); + } + + public function testGetKernel(): void + { + $class = new \ReflectionClass(BaseTestCase::class); + $method = $class->getMethod('getKernel'); + $this->assertInstanceOf(KernelInterface::class, $method->invoke(null)); } - public function testGetContainer() + public function testItCanProvideAFrameworkBundleClient(): void { - $this->assertEquals($this->container, $this->testCase->getContainer()); + $class = new \ReflectionClass(BaseTestCase::class); + $method = $class->getMethod('getFrameworkBundleClient'); + + $this->assertInstanceOf(KernelBrowser::class, $method->invoke($this->testCase)); } - public function provideTestDb() + public function provideTestDb(): array { - return array( - array('PHPCR', 'PHPCR'), - array('Phpcr', 'PHPCR'), - array('ORM', 'ORM'), - array('foobar', null), - ); + return [ + ['PHPCR', 'PHPCR'], + ['Phpcr', 'PHPCR'], + ['ORM', 'ORM'], + ['foobar', null], + ]; } /** * @dataProvider provideTestDb - * @depends testGetContainer */ - public function testDb($dbName, $expected) + public function testDb(string $dbName, string|null $expected): void { + $class = new \ReflectionClass(BaseTestCase::class); + $method = $class->getMethod('getDbManager'); + if (null === $expected) { - $this->setExpectedException('InvalidArgumentException', $dbName.'" does not exist'); + $this->expectException('InvalidArgumentException'); + $this->expectExceptionMessage($dbName.'" does not exist'); } - $res = $this->testCase->getDbManager($dbName); + $res = $method->invoke($this->testCase, $dbName); + if (null === $expected) { + // do not do assertions if the expected exception has not been thrown. + return; + } $className = sprintf( 'Symfony\Cmf\Component\Testing\Functional\DbManager\%s', $expected ); + if (PHPCR::class === $className && class_exists(RepositoryManager::class)) { + $className = RepositoryManager::class; + } $this->assertInstanceOf($className, $res); } diff --git a/tests/Functional/HttpKernel/TestKernelTest.php b/tests/Functional/HttpKernel/TestKernelTest.php new file mode 100644 index 0000000..4d67acc --- /dev/null +++ b/tests/Functional/HttpKernel/TestKernelTest.php @@ -0,0 +1,75 @@ +kernel = $this->getMockBuilder(TestKernel::class) + ->setConstructorArgs(['test', true]) + ->getMockForAbstractClass(); + + $this->mockBundle = $this->createMock(BundleInterface::class); + } + + /** + * @dataProvider bundleSetProvider + */ + public function testBundleSetRequire(array $bundleSets, array $expectedBundles): void + { + $this->kernel->requireBundleSets($bundleSets); + $bundles = array_keys($this->kernel->registerBundles()); + + foreach ($expectedBundles as $key => $value) { + $this->assertArrayHasKey($key, $bundles); + $this->assertSame($value, $bundles[$key]); + } + } + + public function bundleSetProvider(): array + { + return [ + [['default'], [FrameworkBundle::class, SecurityBundle::class, TwigBundle::class]], + [['phpcr_odm'], [DoctrineBundle::class, DoctrinePHPCRBundle::class]], + [['doctrine_orm'], [DoctrineBundle::class]], + ]; + } + + public function testBundleAdd(): void + { + $this->kernel->addBundle($this->mockBundle); + $this->kernel->addBundle($this->mockBundle); + + $this->assertCount(2, $this->kernel->registerBundles()); + } + + public function testRequireInvalidBundleSet(): void + { + $this->expectException(\InvalidArgumentException::class); + $this->kernel->requireBundleSet('foobar'); + } +} diff --git a/tests/HttpKernel/TestKernelTest.php b/tests/HttpKernel/TestKernelTest.php deleted file mode 100644 index 68b4594..0000000 --- a/tests/HttpKernel/TestKernelTest.php +++ /dev/null @@ -1,66 +0,0 @@ -kernel = $this->getMockBuilder( - 'Symfony\Cmf\Component\Testing\HttpKernel\TestKernel' - )->disableOriginalConstructor()->getMockForAbstractClass(); - $this->mockBundle = $this->getMock( - 'Symfony\Component\HttpKernel\Bundle\BundleInterface' - ); - } - - /** - * @dataProvider bundleSetProvider - */ - public function testBundleSetRequire(array $bundleSets, $count) - { - $this->kernel->init(); - $this->kernel->requireBundleSets($bundleSets); - $bundles = $this->kernel->registerBundles(); - $this->assertCount($count, $bundles); - } - - public function bundleSetProvider() - { - return array( - array(array('default', 'phpcr_odm'), 6), - array(array('default', 'doctrine_orm'), 5), - array(array('default', 'doctrine_orm', 'phpcr_odm'), 6), - ); - } - - public function testBundleAdd() - { - $this->kernel->addBundle($this->mockBundle); - $this->kernel->addBundle($this->mockBundle); - - $this->assertCount(2, $this->kernel->registerBundles()); - } - - /** - * @expectedException \InvalidArgumentException - */ - public function testRequireInvalidBundleSet() - { - $this->kernel->init(); - $this->kernel->requireBundleSet('foobar'); - } -} diff --git a/tests/Phpunit/DatabaseTestListenerTest.php b/tests/Phpunit/DatabaseTestListenerTest.php deleted file mode 100644 index 4a34f28..0000000 --- a/tests/Phpunit/DatabaseTestListenerTest.php +++ /dev/null @@ -1,116 +0,0 @@ -listener = new DatabaseTestListener($this->getProcessBuilder()); - self::$i = 0; - } - - public function testPhpcrTestSuite() - { - $suite = $this->getMock('PHPUnit_Framework_TestSuite'); - $suite->expects($this->any()) - ->method('getName') - ->will($this->returnValue('phpcr')); - - $this->assertProcessExecuted(array('doctrine:phpcr:init:dbal', '--drop')); - $this->assertProcessExecuted(array('doctrine:phpcr:repository:init')); - - ob_start(); - $this->listener->startTestSuite($suite); - - $this->assertEquals(PHP_EOL.PHP_EOL.'[PHPCR]'.PHP_EOL, ob_get_clean()); - } - - public function testOrmTestSuite() - { - $suite = $this->getMock('PHPUnit_Framework_TestSuite'); - $suite->expects($this->any()) - ->method('getName') - ->will($this->returnValue('orm')); - - $this->assertProcessExecuted(array('doctrine:schema:drop', '--env=orm', '--force')); - $this->assertProcessExecuted(array('doctrine:database:create', '--env=orm')); - $this->assertProcessExecuted(array('doctrine:schema:create', '--env=orm')); - - ob_start(); - $this->listener->startTestSuite($suite); - - $this->assertEquals(PHP_EOL.PHP_EOL.'[ORM]'.PHP_EOL, ob_get_clean()); - } - - public function testUnknownTestSuite() - { - $suite = $this->getMock('PHPUnit_Framework_TestSuite'); - $suite->expects($this->any()) - ->method('getName') - ->will($this->returnValue('not orm or phpcr tests')); - - $this->getProcessBuilder() - ->expects($this->never()) - ->method('setArguments'); - - ob_start(); - $this->listener->startTestSuite($suite); - - $this->assertEquals(PHP_EOL.PHP_EOL.'[not orm or phpcr tests]'.PHP_EOL, ob_get_clean()); - } - - protected function assertProcessExecuted(array $arguments, $successfull = true) - { - $process = $this->getMockBuilder('Symfony\Component\Process\Process') - ->disableOriginalConstructor() - ->getMock(); - - $process->expects($this->once()) - ->method('run'); - - $process->expects($this->once()) - ->method('isTerminated') - ->will($this->returnValue(true)); - - $process->expects($this->once()) - ->method('isSuccessful') - ->will($this->returnValue($successfull)); - - $processPlaceholder = $this->getMock('ProcessPlaceholder', array('getProcess')); - $processPlaceholder->expects($this->once()) - ->method('getProcess') - ->will($this->returnValue($process)); - - $this->getProcessBuilder() - ->expects($this->at(self::$i++)) - ->method('setArguments') - ->with($this->equalTo($arguments)) - ->will($this->returnValue($processPlaceholder)); - } - - protected function getProcessBuilder() - { - if (null === $this->processBuilder) { - $this->processBuilder = $this->getMock('Symfony\Component\Process\ProcessBuilder'); - } - - return $this->processBuilder; - } -} diff --git a/tests/Unit/Constraint/SchemaAcceptsXmlTest.php b/tests/Unit/Constraint/SchemaAcceptsXmlTest.php index 070f8a6..91b2b7b 100644 --- a/tests/Unit/Constraint/SchemaAcceptsXmlTest.php +++ b/tests/Unit/Constraint/SchemaAcceptsXmlTest.php @@ -3,22 +3,22 @@ /* * This file is part of the Symfony CMF package. * - * (c) 2011-2014 Symfony CMF + * (c) 2011-2017 Symfony CMF * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ - namespace Symfony\Cmf\Component\Testing\Tests\Unit\Constraint; +use PHPUnit\Framework\TestCase; use Symfony\Cmf\Component\Testing\Unit\Constraint\SchemaAcceptsXml; -class SchemaAcceptsXmlTest extends \PHPUnit_Framework_TestCase +class SchemaAcceptsXmlTest extends TestCase { - public function testCount() + public function testCount(): void { - $constraint = new SchemaAcceptsXml(array('config1', 'config2', 'config3')); + $constraint = new SchemaAcceptsXml(['config1', 'config2', 'config3']); try { $this->matches('schema_file.xsd'); @@ -31,7 +31,7 @@ public function testCount() /** * @dataProvider getAssertingData */ - public function testAsserting($input, $schemaFile, $result, $message = null) + public function testAsserting($input, $schemaFile, $result, $message = null): void { $constraint = new SchemaAcceptsXml($input); @@ -47,36 +47,34 @@ public function testAsserting($input, $schemaFile, $result, $message = null) } } - public function getAssertingData() + public function getAssertingData(): array { $schema1 = __DIR__.'/../../Fixtures/schema/schema1.xsd'; - $data = array(); + $data = []; - $dom1 = new \DomDocument(); + $dom1 = new \DOMDocument(); $dom1->loadXML(''); - $data[] = array(array($dom1), $schema1, true); + $data[] = [[$dom1], $schema1, true]; - $dom2 = new \DomDocument(); + $dom2 = new \DOMDocument(); $dom2->loadXML(''); - $data[] = array(array($dom2), $schema1, false); + $data[] = [[$dom2], $schema1, false]; - $data[] = array(array($dom1, $dom1), $schema1, true); - $data[] = array(array($dom1, $dom2), $schema1, false); - $data[] = array(array($dom2, $dom1), $schema1, false); + $data[] = [[$dom1, $dom1], $schema1, true]; + $data[] = [[$dom1, $dom2], $schema1, false]; + $data[] = [[$dom2, $dom1], $schema1, false]; return $data; } - /** - * @expectedException \InvalidArgumentException - */ - public function testFailsIfNoConfigElementIsAvailable() + public function testFailsIfNoConfigElementIsAvailable(): void { - $dom = new \DomDocument(); + $dom = new \DOMDocument(); $dom->loadXML(''); - $constraint = new SchemaAcceptsXml(array($dom)); + $constraint = new SchemaAcceptsXml([$dom]); + $this->expectException(\InvalidArgumentException::class); $constraint->matches(__DIR__.'/../Fixtures/schema/schema1.xsd'); } } diff --git a/tests/Unit/XmlSchemaTestCaseTest.php b/tests/Unit/XmlSchemaTestCaseTest.php index 80c1c85..ea13d7f 100644 --- a/tests/Unit/XmlSchemaTestCaseTest.php +++ b/tests/Unit/XmlSchemaTestCaseTest.php @@ -3,29 +3,28 @@ /* * This file is part of the Symfony CMF package. * - * (c) 2011-2014 Symfony CMF + * (c) 2011-2017 Symfony CMF * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ - namespace Symfony\Cmf\Component\Testing\Tests\Unit; use Symfony\Cmf\Component\Testing\Unit\XmlSchemaTestCase; class XmlSchemaTestCaseTest extends XmlSchemaTestCase { - public function testAcceptsSingleDomsWithoutArray() + public function testAcceptsSingleDomsWithoutArray(): void { - $dom = new \DomDocument(); + $dom = new \DOMDocument(); $dom->loadXML(''); $this->assertSchemaAcceptsXml($dom, __DIR__.'/../Fixtures/schema/schema1.xsd'); } - public function testNegativeAssertion() + public function testNegativeAssertion(): void { - $dom = new \DomDocument(); + $dom = new \DOMDocument(); $dom->loadXML(''); $this->assertSchemaRefusesXml($dom, __DIR__.'/../Fixtures/schema/schema1.xsd'); diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 47505b0..f1ac602 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -1,11 +1,20 @@ '; + $nl = \PHP_SAPI === 'cli' ? \PHP_EOL : '
'; echo "$nl$nl"; - die('You must set up the project dependencies.'.$nl. + exit('You must set up the project dependencies.'.$nl. 'Run the following commands in '.dirname(__DIR__).':'.$nl.$nl. 'curl -s http://getcomposer.org/installer | php'.$nl. 'php composer.phar install'.$nl);