diff --git a/.gitignore b/.gitignore index 15b433a..edaa150 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,6 @@ /vendor/ .vscode +.Build/ +.idea/ +Build/testing-docker/.env +composer.lock diff --git a/Build/Scripts/runTests.sh b/Build/Scripts/runTests.sh new file mode 100755 index 0000000..3c14dd6 --- /dev/null +++ b/Build/Scripts/runTests.sh @@ -0,0 +1,284 @@ +#!/usr/bin/env bash + +# +# TYPO3 core test runner based on docker and docker-compose. +# + +# Function to write a .env file in Build/testing-docker/local +# This is read by docker-compose and vars defined here are +# used in Build/testing-docker/local/docker-compose.yml +setUpDockerComposeDotEnv() { + # Delete possibly existing local .env file if exists + [ -e .env ] && rm .env + # Set up a new .env file for docker-compose + echo "COMPOSE_PROJECT_NAME=local" >> .env + # To prevent access rights of files created by the testing, the docker image later + # runs with the same user that is currently executing the script. docker-compose can't + # use $UID directly itself since it is a shell variable and not an env variable, so + # we have to set it explicitly here. + echo "HOST_UID=`id -u`" >> .env + # Your local home directory for composer and npm caching + echo "HOST_HOME=${HOME}" >> .env + # Your local user + echo "ROOT_DIR"=${ROOT_DIR} >> .env + echo "HOST_USER=${USER}" >> .env + echo "TEST_FILE=${TEST_FILE}" >> .env + echo "PHP_XDEBUG_ON=${PHP_XDEBUG_ON}" >> .env + echo "PHP_XDEBUG_PORT=${PHP_XDEBUG_PORT}" >> .env + echo "PHP_VERSION=${PHP_VERSION}" >> .env + echo "DOCKER_PHP_IMAGE=${DOCKER_PHP_IMAGE}" >> .env + echo "EXTRA_TEST_OPTIONS=${EXTRA_TEST_OPTIONS}" >> .env + echo "SCRIPT_VERBOSE=${SCRIPT_VERBOSE}" >> .env +} + +# Load help text into $HELP +read -r -d '' HELP < + Specifies which test suite to run + - composerInstall: "composer install" + - composerInstallMax: "composer update", with no platform.php config. + - composerInstallMin: "composer update --prefer-lowest", with platform.php set to PHP version x.x.0. + - composerValidate: "composer validate" + - lint: PHP linting + - unit (default): PHP unit tests + - functional: functional tests + + -d + Only with -s functional + Specifies on which DBMS tests are performed + - mariadb (default): use mariadb + - mssql: use mssql microsoft sql server + - postgres: use postgres + - sqlite: use sqlite + + -p <7.2|7.3|7.4> + Specifies the PHP minor version to be used + - 7.2 (default): use PHP 7.2 + - 7.3: use PHP 7.3 + + -e "" + Only with -s functional|unit + Additional options to send to phpunit tests. + For phpunit, options starting with "--" must be added after options starting with "-". + Example -e "-v --filter canRetrieveValueWithGP" to enable verbose output AND filter tests + named "canRetrieveValueWithGP" + + -x + Only with -s unit + Send information to host instance for test or system under test break points. This is especially + useful if a local PhpStorm instance is listening on default xdebug port 9000. A different port + can be selected with -y + + -y + Send xdebug information to a different port than default 9000 if an IDE like PhpStorm + is not listening on default port. + + -u + Update existing typo3gmbh/phpXY:latest docker images. Maintenance call to docker pull latest + versions of the main php images. The images are updated once in a while and only the youngest + ones are supported by core testing. Use this if weird test errors occur. Also removes obsolete + image versions of typo3gmbh/phpXY. + + -v + Enable verbose script output. Shows variables and docker commands. + + -h + Show this help. + +Examples: + # Run unit tests using PHP 7.2 + ./Build/Scripts/runTests.sh + + # Run unit tests using PHP 7.3 + ./Build/Scripts/runTests.sh -p 7.3 +EOF + +# Test if docker-compose exists, else exit out with error +if ! type "docker-compose" > /dev/null; then + echo "This script relies on docker and docker-compose. Please install" >&2 + exit 1 +fi + +# Go to the directory this script is located, so everything else is relative +# to this dir, no matter from where this script is called. +THIS_SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" +cd "$THIS_SCRIPT_DIR" || exit 1 + +# Go to directory that contains the local docker-compose.yml file +cd ../testing-docker || exit 1 + +# Option defaults +ROOT_DIR=`readlink -f ${PWD}/../../` +TEST_SUITE="unit" +DBMS="mariadb" +PHP_VERSION="7.2" +PHP_XDEBUG_ON=0 +PHP_XDEBUG_PORT=9000 +EXTRA_TEST_OPTIONS="" +SCRIPT_VERBOSE=0 + +# Option parsing +# Reset in case getopts has been used previously in the shell +OPTIND=1 +# Array for invalid options +INVALID_OPTIONS=(); +# Simple option parsing based on getopts (! not getopt) +while getopts ":s:d:p:e:xy:huv" OPT; do + case ${OPT} in + s) + TEST_SUITE=${OPTARG} + ;; + d) + DBMS=${OPTARG} + ;; + p) + PHP_VERSION=${OPTARG} + ;; + e) + EXTRA_TEST_OPTIONS=${OPTARG} + ;; + x) + PHP_XDEBUG_ON=1 + ;; + y) + PHP_XDEBUG_PORT=${OPTARG} + ;; + h) + echo "${HELP}" + exit 0 + ;; + u) + TEST_SUITE=update + ;; + v) + SCRIPT_VERBOSE=1 + ;; + \?) + INVALID_OPTIONS+=(${OPTARG}) + ;; + :) + INVALID_OPTIONS+=(${OPTARG}) + ;; + esac +done + +# Exit on invalid options +if [ ${#INVALID_OPTIONS[@]} -ne 0 ]; then + echo "Invalid option(s):" >&2 + for I in "${INVALID_OPTIONS[@]}"; do + echo "-"${I} >&2 + done + echo >&2 + echo "${HELP}" >&2 + exit 1 +fi + +# Move "7.2" to "php72", the latter is the docker container name +DOCKER_PHP_IMAGE=`echo "php${PHP_VERSION}" | sed -e 's/\.//'` + +# Set $1 to first mass argument, this is the optional test file or test directory to execute +shift $((OPTIND - 1)) +if [ -n "${1}" ]; then + TEST_FILE="Web/typo3conf/ext/publisher_db/${1}" +else + case ${TEST_SUITE} in + functional) + TEST_FILE="Web/typo3conf/ext/publisher_db/Tests/Functional" + ;; + unit) + TEST_FILE="Web/typo3conf/ext/publisher_db/Tests/Unit" + ;; + esac +fi + +if [ ${SCRIPT_VERBOSE} -eq 1 ]; then + set -x +fi + +# Suite execution +case ${TEST_SUITE} in + composerInstall) + setUpDockerComposeDotEnv + docker-compose run composer_install + SUITE_EXIT_CODE=$? + docker-compose down + ;; + composerInstallMax) + setUpDockerComposeDotEnv + docker-compose run composer_install_max + SUITE_EXIT_CODE=$? + docker-compose down + ;; + composerInstallMin) + setUpDockerComposeDotEnv + docker-compose run composer_install_min + SUITE_EXIT_CODE=$? + docker-compose down + ;; + composerValidate) + setUpDockerComposeDotEnv + docker-compose run composer_validate + SUITE_EXIT_CODE=$? + docker-compose down + ;; + functional) + setUpDockerComposeDotEnv + case ${DBMS} in + mariadb) + docker-compose run functional_mariadb10 + SUITE_EXIT_CODE=$? + ;; + mssql) + docker-compose run functional_mssql2019latest + SUITE_EXIT_CODE=$? + ;; + postgres) + docker-compose run functional_postgres10 + SUITE_EXIT_CODE=$? + ;; + sqlite) + docker-compose run functional_sqlite + SUITE_EXIT_CODE=$? + ;; + *) + echo "Invalid -d option argument ${DBMS}" >&2 + echo >&2 + echo "${HELP}" >&2 + exit 1 + esac + docker-compose down + ;; + lint) + setUpDockerComposeDotEnv + docker-compose run lint + SUITE_EXIT_CODE=$? + docker-compose down + ;; + unit) + setUpDockerComposeDotEnv + docker-compose run unit + SUITE_EXIT_CODE=$? + docker-compose down + ;; + update) + # pull typo3gmbh/phpXY:latest versions of those ones that exist locally + docker images typo3gmbh/php*:latest --format "{{.Repository}}:latest" | xargs -I {} docker pull {} + # remove "dangling" typo3gmbh/phpXY images (those tagged as ) + docker images typo3gmbh/php* --filter "dangling=true" --format "{{.ID}}" | xargs -I {} docker rmi {} + ;; + *) + echo "Invalid -s option argument ${TEST_SUITE}" >&2 + echo >&2 + echo "${HELP}" >&2 + exit 1 +esac + +exit $SUITE_EXIT_CODE diff --git a/README.md b/README.md index 7fcea93..6e0975d 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,14 @@ # slub_find_flexibleviews Flexible Views for the SLUB find catalog + +## Running the Unit Tests + +PHPUnit is required for running the unit tests. It comes with the DEV requirement `typo3/testing-framework` + +### Running outside a TYPO3 environment + +```.Build/bin/phpunit Tests/``` + +### Running within a TYPO3 environment + +```./vendor/bin/phpunit public/typo3conf/ext/slub_find_flexibleviews/Tests``` diff --git a/Tests/Unit/Controller/FlexibleviewsControllerTest.php b/Tests/Unit/Controller/FlexibleviewsControllerTest.php index ce7ce68..c07ec65 100644 --- a/Tests/Unit/Controller/FlexibleviewsControllerTest.php +++ b/Tests/Unit/Controller/FlexibleviewsControllerTest.php @@ -43,7 +43,7 @@ public function listActionFetchesAllFlexibleviewssFromRepositoryAndAssignsThemTo $this->inject($this->subject, 'flexibleviewsRepository', $flexibleviewsRepository); $view = $this->getMockBuilder(\TYPO3\CMS\Extbase\Mvc\View\ViewInterface::class)->getMock(); - $view->expects(self::once())->method('assign')->with('flexibleviewss', $allFlexibleviewss); + $view->expects(self::once())->method('assign')->with('flexibleviews', $allFlexibleviewss); $this->inject($this->subject, 'view', $view); $this->subject->listAction(); diff --git a/Tests/Unit/Slots/AdvancedQueryTest.php b/Tests/Unit/Slots/AdvancedQueryTest.php new file mode 100644 index 0000000..d6077e1 --- /dev/null +++ b/Tests/Unit/Slots/AdvancedQueryTest.php @@ -0,0 +1,98 @@ +advancedQuery = $this->getMockBuilder(AdvancedQuery::class) + ->setMethodsExcept(['build', 'injectFlexibleviewsRepository']) + ->disableOriginalConstructor() + ->getMock(); + + $this->flexibleviewsRepository = $this->getMockBuilder(FlexibleviewsRepository::class) + ->setMethods(['findByUid']) + ->disableOriginalConstructor() + ->getMock(); + + $flexibleviews = new Flexibleviews(); + $this->flexibleviewsRepository + ->method('findByUid') + ->will($this->returnValueMap([[1, $flexibleviews]])); + + $this->inject($this->advancedQuery, 'flexibleviewsRepository', $this->flexibleviewsRepository); + } + + /** + * @test + */ + public function nullArgumentsDontChangeQuery() { + $preparedQuery = new Query(); + $preparedQueryString = $preparedQuery->getQuery(); + + $this->advancedQuery->build($preparedQuery, null); + + $this->assertEquals($preparedQuery->getQuery(), $preparedQueryString); + $this->assertEquals(count($preparedQuery->getFilterQueries()), 0); + } + + /** + * @test + */ + public function emptyArgumentsDontChangeQuery() { + $preparedQuery = new Query(); + $preparedQueryString = $preparedQuery->getQuery(); + + $this->advancedQuery->build($preparedQuery, []); + + $this->assertEquals(count($preparedQuery->getFilterQueries()), 0); + $this->assertEquals($preparedQuery->getQuery(), $preparedQueryString); + } + + /** + * @test + */ + public function argumentIsAppendedToQuery() { + $preparedQuery = new Query(); + $arguments = array( + 'flexibleviews' => '1' + ); + $countFilterQueries = count($preparedQuery->getFilterQueries()); + + $this->advancedQuery->build($preparedQuery, $arguments); + + $this->assertEquals(count($preparedQuery->getFilterQueries()), $countFilterQueries + 1); + } + + /** + * @test + */ + public function invalidArgumentIsNotAppendedToQuery() { + $preparedQuery = new Query(); + $arguments = array( + 'flexibleviews' => '2' + ); + + $this->advancedQuery->build($preparedQuery, $arguments); + + $this->assertEquals(count($preparedQuery->getFilterQueries()), 0); + } + +} diff --git a/composer.json b/composer.json index fdb6da9..e04b442 100644 --- a/composer.json +++ b/composer.json @@ -34,5 +34,23 @@ "typo3/cms": { "extension-key": "slub_find_flexibleviews" } + }, + "config": { + "vendor-dir": ".Build/vendor", + "bin-dir": ".Build/bin" + }, + "require-dev": { + "typo3/testing-framework": "^4.11.1" + }, + "scripts": { + "post-autoload-dump": [ + "TYPO3\\TestingFramework\\Composer\\ExtensionTestEnvironment::prepare" + ] + }, + "extra": { + "typo3/cms": { + "extension-key": "enetcache", + "web-dir": ".Build/Web" + } } }