From fa6c3fc4ea30193965ee260e58fd6d1e8780443a Mon Sep 17 00:00:00 2001 From: Benjamin Franzke Date: Sat, 17 Feb 2024 10:33:23 +0100 Subject: [PATCH] [TASK] Add composer-mode to our acceptance test matrix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All applicable acceptance tests are now also executed in composer mode. Tests that check classic-mode specific functions are excluded and are therefore now tagged as classic-mode test. The composer mode instance is generated with our CLI setup tools, allowing to mimic the realworld case where a instance is creating via our setup tools instead of from fixtures (which we still use for classic mode tests, but try to reducde/avoid for composer mode tests). The existing existing classic-mode test acceptance test execution will keep running as-is. Resolves: #103297 Releases: main, 12.4, 11.5 Change-Id: I64973f110931b51ed2ef7ef8f8cc3411834fcf37 Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/83027 Tested-by: Stefan Bürk Reviewed-by: Christian Kuhn Tested-by: Christian Kuhn Reviewed-by: Stefan Bürk Tested-by: core-ci Reviewed-by: Benjamin Franzke Tested-by: Benjamin Franzke --- Build/Scripts/runTests.sh | 82 ++++++++- Build/Scripts/setupAcceptanceComposer.sh | 50 ++++++ Build/composer/composer.dist.json | 6 +- Build/gitlab-ci.yml | 2 + .../acceptance-application-composer.yml | 163 ++++++++++++++++++ .../acceptance-application-composer.yml | 17 ++ .../Classes/Command/DatasetImportCommand.php | 50 ++++++ .../Configuration/Services.yaml | 8 + .../packages/dataset_import/composer.json | 20 +++ .../Tests/Acceptance/Application.suite.yml | 6 +- .../Application/BackendUser/ListUserCest.php | 100 ++++++++--- .../Extensionmanager/GetExtensionsCest.php | 5 + .../InstalledExtensionsCest.php | 3 + .../FormEngine/FalMetadataCest.php | 10 +- .../Application/FormEngine/Inline1nCest.php | 10 ++ .../Frontend/ContentElementsCest.php | 12 +- .../Frontend/FormFrameworkCest.php | 12 +- .../Frontend/FrontendLoginCest.php | 12 +- .../Frontend/IndexedSearchCest.php | 12 +- .../Application/Impexp/ImportCest.php | 9 +- .../Application/InstallTool/AbstractCest.php | 20 ++- .../InstallTool/MaintenanceCest.php | 2 + .../Application/InstallTool/SettingsCest.php | 10 +- .../Application/InstallTool/UpgradeCest.php | 2 + .../Redirect/RedirectModuleCest.php | 2 +- .../Application/Scheduler/TasksCest.php | 1 + .../Application/Template/TemplateCest.php | 4 + .../ApplicationComposerEnvironment.php | 49 ++++++ .../Extension/ApplicationEnvironment.php | 4 + 29 files changed, 617 insertions(+), 66 deletions(-) create mode 100755 Build/Scripts/setupAcceptanceComposer.sh create mode 100644 Build/gitlab-ci/nightly/acceptance-application-composer.yml create mode 100644 Build/gitlab-ci/pre-merge/acceptance-application-composer.yml create mode 100644 Build/tests/packages/dataset_import/Classes/Command/DatasetImportCommand.php create mode 100644 Build/tests/packages/dataset_import/Configuration/Services.yaml create mode 100644 Build/tests/packages/dataset_import/composer.json create mode 100644 typo3/sysext/core/Tests/Acceptance/Support/Extension/ApplicationComposerEnvironment.php diff --git a/Build/Scripts/runTests.sh b/Build/Scripts/runTests.sh index af4723c7f565..9d4f7ed7a420 100755 --- a/Build/Scripts/runTests.sh +++ b/Build/Scripts/runTests.sh @@ -174,6 +174,7 @@ Options: -s <...> Specifies the test suite to run - acceptance: main application acceptance tests + - acceptanceComposer: main application acceptance tests - acceptanceInstall: installation acceptance tests, only with -d mariadb|postgres|sqlite - buildCss: execute scss to css builder - buildJavascript: execute typescript to javascript builder @@ -236,7 +237,7 @@ Options: - pdo_mysql -d - Only with -s functional|functionalDeprecated|acceptance|acceptanceInstall + Only with -s functional|functionalDeprecated|acceptance|acceptanceComposer|acceptanceInstall Specifies on which DBMS tests are performed - sqlite: (default): use sqlite - mariadb: use mariadb @@ -293,12 +294,12 @@ Options: Build/Scripts/runTests.sh -s unit -- --filter filterByValueRecursiveCorrectlyFiltersArray -g - Only with -s acceptance|acceptanceInstall + Only with -s acceptance|acceptanceComposer|acceptanceInstall Activate selenium grid as local port to watch browser clicking around. Can be surfed using http://localhost:7900/. A browser tab is opened automatically if xdg-open is installed. -x - Only with -s functional|functionalDeprecated|unit|unitDeprecated|unitRandom|acceptance|acceptanceInstall + Only with -s functional|functionalDeprecated|unit|unitDeprecated|unitRandom|acceptance|acceptanceComposer|acceptanceInstall 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 9003. A different port can be selected with -y @@ -566,9 +567,9 @@ fi # Suite execution case ${TEST_SUITE} in acceptance) - CODECEPION_ENV="--env ci" + CODECEPION_ENV="--env ci,classic" if [ "${ACCEPTANCE_HEADLESS}" -eq 1 ]; then - CODECEPION_ENV="--env ci,headless" + CODECEPION_ENV="--env ci,classic,headless" fi if [ "${CHUNKS}" -gt 0 ]; then ${CONTAINER_BIN} run ${CONTAINER_COMMON_PARAMS} --name ac-splitter-${SUFFIX} ${IMAGE_PHP} php -dxdebug.mode=off Build/Scripts/splitAcceptanceTests.php -v ${CHUNKS} @@ -630,6 +631,75 @@ case ${TEST_SUITE} in ;; esac ;; + acceptanceComposer) + rm -rf "${CORE_ROOT}/typo3temp/var/tests/acceptance-composer" "${CORE_ROOT}/typo3temp/var/tests/AcceptanceReports" + + PREPAREPARAMS="" + TESTPARAMS="" + case ${DBMS} in + mariadb) + ${CONTAINER_BIN} run --rm ${CI_PARAMS} --name mariadb-ac-${SUFFIX} --network ${NETWORK} -d -e MYSQL_ROOT_PASSWORD=acp -e MYSQL_DATABASE=ac_test --tmpfs /var/lib/mysql/:rw,noexec,nosuid ${IMAGE_MARIADB} >/dev/null + waitFor mariadb-ac-${SUFFIX} 3306 + PREPAREPARAMS="-e TYPO3_DB_DRIVER=mysqli -e TYPO3_DB_DBNAME=ac_test -e TYPO3_DB_USERNAME=root -e TYPO3_DB_PASSWORD=acp -e TYPO3_DB_HOST=mariadb-ac-${SUFFIX} -e TYPO3_DB_PORT=3306" + TESTPARAMS="-e typo3DatabaseName=ac_test -e typo3DatabaseUsername=root -e typo3DatabasePassword=funcp -e typo3DatabaseHost=mariadb-ac-${SUFFIX}" + ;; + mysql) + ${CONTAINER_BIN} run --rm ${CI_PARAMS} --name mysql-ac-${SUFFIX} --network ${NETWORK} -d -e MYSQL_ROOT_PASSWORD=acp -e MYSQL_DATABASE=ac_test --tmpfs /var/lib/mysql/:rw,noexec,nosuid ${IMAGE_MYSQL} >/dev/null + waitFor mysql-ac-${SUFFIX} 3306 + PREPAREPARAMS="-e TYPO3_DB_DRIVER=mysqli -e TYPO3_DB_DBNAME=ac_test -e TYPO3_DB_USERNAME=root -e TYPO3_DB_PASSWORD=acp -e TYPO3_DB_HOST=mysql-ac-${SUFFIX} -e TYPO3_DB_PORT=3306" + TESTPARAMS="-e typo3DatabaseName=ac_test -e typo3DatabaseUsername=root -e typo3DatabasePassword=funcp -e typo3DatabaseHost=mysql-ac-${SUFFIX}" + ;; + postgres) + ${CONTAINER_BIN} run --rm ${CI_PARAMS} --name postgres-ac-${SUFFIX} --network ${NETWORK} -d -e POSTGRES_DB=ac_test -e POSTGRES_PASSWORD=acp -e POSTGRES_USER=ac_test --tmpfs /var/lib/postgresql/data:rw,noexec,nosuid ${IMAGE_POSTGRES} >/dev/null + waitFor postgres-ac-${SUFFIX} 5432 + PREPAREPARAMS="-e TYPO3_DB_DRIVER=postgres -e TYPO3_DB_DBNAME=ac_test -e TYPO3_DB_USERNAME=ac_test -e TYPO3_DB_PASSWORD=acp -e TYPO3_DB_HOST=postgres-ac-${SUFFIX} -e TYPO3_DB_PORT=5432" + TESTPARAMS="-e typo3DatabaseDriver=pdo_pgsql -e typo3DatabaseName=ac_test -e typo3DatabaseUsername=ac_test -e typo3DatabasePassword=acp -e typo3DatabaseHost=postgres-ac-${SUFFIX}" + ;; + sqlite) + PREPAREPARAMS="-e TYPO3_DB_DRIVER=sqlite" + TESTPARAMS="-e typo3DatabaseDriver=pdo_sqlite" + ;; + esac + + ${CONTAINER_BIN} run ${CONTAINER_COMMON_PARAMS} --name acceptance-prepare ${XDEBUG_MODE} -e COMPOSER_CACHE_DIR=${CORE_ROOT}/.cache/composer -e COMPOSER_ROOT_VERSION=${COMPOSER_ROOT_VERSION} -e XDEBUG_CONFIG="${XDEBUG_CONFIG}" ${PREPAREPARAMS} ${IMAGE_PHP} "${CORE_ROOT}/Build/Scripts/setupAcceptanceComposer.sh" "typo3temp/var/tests/acceptance-composer" + SUITE_EXIT_CODE=$? + if [[ ${SUITE_EXIT_CODE} -eq 0 ]]; then + CODECEPION_ENV="--env ci,composer" + if [ "${ACCEPTANCE_HEADLESS}" -eq 1 ]; then + CODECEPION_ENV="--env ci,composer,headless" + fi + if [ "${CHUNKS}" -gt 0 ]; then + ${CONTAINER_BIN} run ${CONTAINER_COMMON_PARAMS} --name ac-splitter-${SUFFIX} ${IMAGE_PHP} php -dxdebug.mode=off Build/Scripts/splitAcceptanceTests.php -v ${CHUNKS} + COMMAND=(bin/codecept run Application -d -g AcceptanceTests-Job-${THISCHUNK} -c typo3/sysext/core/Tests/codeception.yml ${EXTRA_TEST_OPTIONS} ${CODECEPION_ENV} "$@" --html reports.html) + else + COMMAND=(bin/codecept run Application -d -c typo3/sysext/core/Tests/codeception.yml ${EXTRA_TEST_OPTIONS} ${CODECEPION_ENV} "$@" --html reports.html) + fi + SELENIUM_GRID="" + if [ "${ACCEPTANCE_HEADLESS}" -eq 0 ]; then + SELENIUM_GRID="-p 7900:7900 -e SE_VNC_NO_PASSWORD=1 -e VNC_NO_PASSWORD=1" + fi + APACHE_OPTIONS="-e APACHE_RUN_USER=#${HOST_UID} -e APACHE_RUN_SERVERNAME=web -e APACHE_RUN_GROUP=#${HOST_PID} -e APACHE_RUN_DOCROOT=${CORE_ROOT}/typo3temp/var/tests/acceptance-composer/public -e PHPFPM_HOST=phpfpm -e PHPFPM_PORT=9000" + ${CONTAINER_BIN} run --rm ${CI_PARAMS} -d ${SELENIUM_GRID} --name ac-chrome-${SUFFIX} --network ${NETWORK} --network-alias chrome --tmpfs /dev/shm:rw,nosuid,nodev,noexec ${IMAGE_SELENIUM} >/dev/null + if [ ${CONTAINER_BIN} = "docker" ]; then + ${CONTAINER_BIN} run --rm -d --name ac-phpfpm-${SUFFIX} --network ${NETWORK} --network-alias phpfpm --add-host "${CONTAINER_HOST}:host-gateway" ${USERSET} -e PHPFPM_USER=${HOST_UID} -e PHPFPM_GROUP=${HOST_PID} -v ${CORE_ROOT}:${CORE_ROOT} ${IMAGE_PHP} php-fpm ${PHP_FPM_OPTIONS} >/dev/null + ${CONTAINER_BIN} run --rm -d --name ac-web-${SUFFIX} --network ${NETWORK} --network-alias web --add-host "${CONTAINER_HOST}:host-gateway" -v ${CORE_ROOT}:${CORE_ROOT} ${APACHE_OPTIONS} ${IMAGE_APACHE} >/dev/null + else + ${CONTAINER_BIN} run --rm ${CI_PARAMS} -d --name ac-phpfpm-${SUFFIX} --network ${NETWORK} --network-alias phpfpm ${USERSET} -e PHPFPM_USER=0 -e PHPFPM_GROUP=0 -v ${CORE_ROOT}:${CORE_ROOT} ${IMAGE_PHP} php-fpm -R ${PHP_FPM_OPTIONS} >/dev/null + ${CONTAINER_BIN} run --rm ${CI_PARAMS} -d --name ac-web-${SUFFIX} --network ${NETWORK} --network-alias web -v ${CORE_ROOT}:${CORE_ROOT} ${APACHE_OPTIONS} ${IMAGE_APACHE} >/dev/null + fi + waitFor chrome 4444 + waitFor chrome 7900 + waitFor web 80 + if [ "${ACCEPTANCE_HEADLESS}" -eq 0 ] && type "xdg-open" >/dev/null; then + xdg-open http://localhost:7900/?autoconnect=1 >/dev/null + elif [ "${ACCEPTANCE_HEADLESS}" -eq 0 ] && type "open" >/dev/null; then + open http://localhost:7900/?autoconnect=1 >/dev/null + fi + + ${CONTAINER_BIN} run ${CONTAINER_COMMON_PARAMS} --name ac-${DBMS}-composer ${XDEBUG_MODE} -e XDEBUG_CONFIG="${XDEBUG_CONFIG}" ${TESTPARAMS} ${IMAGE_PHP} "${COMMAND[@]}" + SUITE_EXIT_CODE=$? + fi + ;; acceptanceInstall) SELENIUM_GRID="" if [ "${ACCEPTANCE_HEADLESS}" -eq 0 ]; then @@ -1009,7 +1079,7 @@ echo "########################################################################## echo "Result of ${TEST_SUITE}" >&2 echo "Container runtime: ${CONTAINER_BIN}" >&2 echo "PHP: ${PHP_VERSION}" >&2 -if [[ ${TEST_SUITE} =~ ^(functional|functionalDeprecated|acceptance|acceptanceInstall)$ ]]; then +if [[ ${TEST_SUITE} =~ ^(functional|functionalDeprecated|acceptance|acceptanceComposer|acceptanceInstall)$ ]]; then case "${DBMS}" in mariadb|mysql|postgres) echo "DBMS: ${DBMS} version ${DBMS_VERSION} driver ${DATABASE_DRIVER}" >&2 diff --git a/Build/Scripts/setupAcceptanceComposer.sh b/Build/Scripts/setupAcceptanceComposer.sh new file mode 100755 index 000000000000..5e5f43b9375b --- /dev/null +++ b/Build/Scripts/setupAcceptanceComposer.sh @@ -0,0 +1,50 @@ +#!/bin/sh + +set -e + +cd "$(dirname $(realpath $0))/../../" + +PROJECT_PATH=${1:-typo3temp/var/tests/acceptance-composer/} +export TYPO3_DB_DRIVER=${2:-${TYPO3_DB_DRIVER:-sqlite}} +EXTRA_PACKAGES="${3}" + +mkdir -p "${PROJECT_PATH}" +ln -snf $(echo "${PROJECT_PATH}" | sed -e 's/[^\/][^\/]*/../g' -e 's/\/$//')/typo3/sysext "${PROJECT_PATH}/typo3-sysext" +ln -snf $(echo "${PROJECT_PATH}" | sed -e 's/[^\/][^\/]*/../g' -e 's/\/$//')/Build/tests/packages "${PROJECT_PATH}/packages" +sed 's/..\/..\/typo3\/sysext/typo3-sysext/' Build/composer/composer.dist.json > "${PROJECT_PATH}/composer.json" + +cd "${PROJECT_PATH}" +rm -rf composer.lock config/ public/ var/ vendor/ + +mkdir -p "config/system/" +cat > "config/system/additional.php" <<\EOF +addArgument('path', InputArgument::REQUIRED, 'Path to CSV dataset to import'); + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + if (!class_exists(DataSet::class)) { + $io = new SymfonyStyle($input, $output); + $io->getErrorStyle()->error('Missing typo3/testing-framework dependency.'); + return Command::FAILURE; + } + DataSet::import($input->getArgument('path')); + return Command::SUCCESS; + } + +} diff --git a/Build/tests/packages/dataset_import/Configuration/Services.yaml b/Build/tests/packages/dataset_import/Configuration/Services.yaml new file mode 100644 index 000000000000..adae8cd8e361 --- /dev/null +++ b/Build/tests/packages/dataset_import/Configuration/Services.yaml @@ -0,0 +1,8 @@ +services: + _defaults: + autowire: true + autoconfigure: true + public: false + + TYPO3Tests\DatasetImport\: + resource: '../Classes/*' diff --git a/Build/tests/packages/dataset_import/composer.json b/Build/tests/packages/dataset_import/composer.json new file mode 100644 index 000000000000..9f1d4b403404 --- /dev/null +++ b/Build/tests/packages/dataset_import/composer.json @@ -0,0 +1,20 @@ +{ + "name": "typo3tests/dataset-import", + "type": "typo3-cms-extension", + "description": "Support extension providing dataset:import command", + "license": "GPL-2.0-or-later", + "require": { + "typo3/cms-core": "13.1.*@dev", + "typo3/testing-framework": "dev-main" + }, + "extra": { + "typo3/cms": { + "extension-key": "dataset_import" + } + }, + "autoload": { + "psr-4": { + "TYPO3Tests\\DatasetImport\\": "Classes/" + } + } +} diff --git a/typo3/sysext/core/Tests/Acceptance/Application.suite.yml b/typo3/sysext/core/Tests/Acceptance/Application.suite.yml index 4ccfcfbef30e..d4e288724934 100644 --- a/typo3/sysext/core/Tests/Acceptance/Application.suite.yml +++ b/typo3/sysext/core/Tests/Acceptance/Application.suite.yml @@ -16,10 +16,14 @@ modules: editor: '%typo3TestingAcceptanceEditorPassword%' env: - ci: + classic: extensions: enabled: - TYPO3\CMS\Core\Tests\Acceptance\Support\Extension\ApplicationEnvironment + composer: + extensions: + enabled: + - TYPO3\CMS\Core\Tests\Acceptance\Support\Extension\ApplicationComposerEnvironment groups: AcceptanceTests-Job-*: AcceptanceTests-Job-* diff --git a/typo3/sysext/core/Tests/Acceptance/Application/BackendUser/ListUserCest.php b/typo3/sysext/core/Tests/Acceptance/Application/BackendUser/ListUserCest.php index 910bf40fd0cc..57b66fc726cb 100644 --- a/typo3/sysext/core/Tests/Acceptance/Application/BackendUser/ListUserCest.php +++ b/typo3/sysext/core/Tests/Acceptance/Application/BackendUser/ListUserCest.php @@ -17,6 +17,7 @@ namespace TYPO3\CMS\Core\Tests\Acceptance\Application\BackendUser; +use Codeception\Scenario; use TYPO3\CMS\Core\Tests\Acceptance\Support\ApplicationTester; /** @@ -34,23 +35,38 @@ public function _before(ApplicationTester $I): void $I->switchToContentFrame(); } - public function showsHeadingAndListsBackendUsers(ApplicationTester $I): void + public function showsHeadingAndListsBackendUsers(ApplicationTester $I, Scenario $scenario): void { $I->see('Backend users'); $I->wantTo('See the table of users'); $I->waitForElementVisible('#typo3-backend-user-list'); + $I->click('button[value="reset-filters"]'); + $I->waitForElementVisible('#typo3-backend-user-list'); - // We expect exact four Backend Users created from the Fixtures - $this->checkCountOfUsers($I, 4); + $isComposerMode = str_contains($scenario->current('env'), 'composer'); + // We expect exactly four Backend Users to have been created by the fixtures + $expectedUsers = 4; + if ($isComposerMode) { + // User _cli_ will additionally be available in composer mode, created + // by execution of `vendor/bin/typo3` CLI in setup script. + $expectedUsers++; + } + $this->checkCountOfUsers($I, $expectedUsers); } - public function filterUsersByUsername(ApplicationTester $I): void + public function filterUsersByUsername(ApplicationTester $I, Scenario $scenario): void { $I->wantTo('See the table of users'); $I->waitForElementVisible('#typo3-backend-user-list'); - // We expect exact four Backend Users created from the Fixtures - $I->canSeeNumberOfElements('#typo3-backend-user-list tbody tr', 4); + $I->click('button[value="reset-filters"]'); + $I->waitForElementVisible('#typo3-backend-user-list'); + $isComposerMode = str_contains($scenario->current('env'), 'composer'); + $expectedUsers = 4; + if ($isComposerMode) { + $expectedUsers++; + } + $I->canSeeNumberOfElements('#typo3-backend-user-list tbody tr', $expectedUsers); $I->wantTo('Filter the list of user by valid username admin'); $I->fillField('#tx_Beuser_username', 'admin'); @@ -71,12 +87,18 @@ public function filterUsersByUsername(ApplicationTester $I): void $this->checkCountOfUsers($I, 0); } - public function filterUsersByAdmin(ApplicationTester $I): void + public function filterUsersByAdmin(ApplicationTester $I, Scenario $scenario): void { $I->wantTo('See the table of users'); $I->waitForElementVisible('#typo3-backend-user-list'); - // We expect exact four Backend Users created from the Fixtures - $I->canSeeNumberOfElements('#typo3-backend-user-list tbody tr', 4); + $I->click('button[value="reset-filters"]'); + $I->waitForElementVisible('#typo3-backend-user-list'); + $isComposerMode = str_contains($scenario->current('env'), 'composer'); + $expectedUsers = 4; + if ($isComposerMode) { + $expectedUsers++; + } + $I->canSeeNumberOfElements('#typo3-backend-user-list tbody tr', $expectedUsers); $I->wantToTest('Filter BackendUser and see only admins'); $I->selectOption('#tx_Beuser_usertype', 'Admin only'); @@ -84,8 +106,8 @@ public function filterUsersByAdmin(ApplicationTester $I): void $I->waitForElementNotVisible('div#nprogess'); $I->waitForElementVisible('#typo3-backend-user-list'); - // We expect exact two fitting Backend Users created from the Fixtures - $this->checkCountOfUsers($I, 2); + // We expect exact two (composer-mode: three) fitting Backend Users created from the Fixtures + $this->checkCountOfUsers($I, 2 + ($isComposerMode ? 1 : 0)); $I->wantToTest('Filter BackendUser and see normal users'); $I->selectOption('#tx_Beuser_usertype', 'Normal users only'); @@ -97,12 +119,18 @@ public function filterUsersByAdmin(ApplicationTester $I): void $this->checkCountOfUsers($I, 2); } - public function filterUsersByStatus(ApplicationTester $I): void + public function filterUsersByStatus(ApplicationTester $I, Scenario $scenario): void { $I->wantTo('See the table of users'); $I->waitForElementVisible('#typo3-backend-user-list'); - // We expect exact four Backend Users created from the Fixtures - $I->canSeeNumberOfElements('#typo3-backend-user-list tbody tr', 4); + $I->click('button[value="reset-filters"]'); + $I->waitForElementVisible('#typo3-backend-user-list'); + $isComposerMode = str_contains($scenario->current('env'), 'composer'); + $expectedUsers = 4; + if ($isComposerMode) { + $expectedUsers++; + } + $I->canSeeNumberOfElements('#typo3-backend-user-list tbody tr', $expectedUsers); $I->wantToTest('Filter BackendUser and see only active users'); $I->selectOption('#tx_Beuser_status', 'Active only'); @@ -110,8 +138,8 @@ public function filterUsersByStatus(ApplicationTester $I): void $I->waitForElementNotVisible('div#nprogess'); $I->waitForElementVisible('#typo3-backend-user-list'); - // We expect exact two fitting Backend Users created from the Fixtures - $this->checkCountOfUsers($I, 2); + // We expect exact two (composer-mode three) fitting Backend Users created from the Fixtures + $this->checkCountOfUsers($I, 2 + ($isComposerMode ? 1 : 0)); $I->wantToTest('Filter BackendUser and see only inactive users'); $I->selectOption('#tx_Beuser_status', 'Inactive only'); @@ -123,12 +151,18 @@ public function filterUsersByStatus(ApplicationTester $I): void $this->checkCountOfUsers($I, 2); } - public function filterUsersByLogin(ApplicationTester $I): void + public function filterUsersByLogin(ApplicationTester $I, Scenario $scenario): void { $I->wantTo('See the table of users'); $I->waitForElementVisible('#typo3-backend-user-list'); - // We expect exact four Backend Users created from the Fixtures - $I->canSeeNumberOfElements('#typo3-backend-user-list tbody tr', 4); + $I->click('button[value="reset-filters"]'); + $I->waitForElementVisible('#typo3-backend-user-list'); + $isComposerMode = str_contains($scenario->current('env'), 'composer'); + $expectedUsers = 4; + if ($isComposerMode) { + $expectedUsers++; + } + $I->canSeeNumberOfElements('#typo3-backend-user-list tbody tr', $expectedUsers); $I->wantToTest('Filter BackendUser and see only users logged in before'); $I->selectOption('#tx_Beuser_logins', 'Logged in before'); @@ -145,16 +179,22 @@ public function filterUsersByLogin(ApplicationTester $I): void $I->waitForElementNotVisible('div#nprogess'); $I->waitForElementVisible('#typo3-backend-user-list'); - // We expect exact two fitting Backend Users created from the Fixtures - $this->checkCountOfUsers($I, 2); + // We expect exact two (composer-mode three) fitting Backend Users created from the Fixtures + $this->checkCountOfUsers($I, 2 + ($isComposerMode ? 1 : 0)); } - public function filterUsersByUserGroup(ApplicationTester $I): void + public function filterUsersByUserGroup(ApplicationTester $I, Scenario $scenario): void { $I->wantTo('See the table of users'); $I->waitForElementVisible('#typo3-backend-user-list'); - // We expect exact four Backend Users created from the Fixtures - $I->canSeeNumberOfElements('#typo3-backend-user-list tbody tr', 4); + $I->click('button[value="reset-filters"]'); + $I->waitForElementVisible('#typo3-backend-user-list'); + $isComposerMode = str_contains($scenario->current('env'), 'composer'); + $expectedUsers = 4; + if ($isComposerMode) { + $expectedUsers++; + } + $I->canSeeNumberOfElements('#typo3-backend-user-list tbody tr', $expectedUsers); // We expect exact one Backend Users created from the Fixtures has the usergroup named 'editor-group' $I->wantToTest('Filter BackendUser and see only users with given usergroup'); @@ -170,18 +210,22 @@ public function filterUsersByUserGroup(ApplicationTester $I): void public function canEditUsersFromIndexListView(ApplicationTester $I): void { $I->canSee('Backend users', 'h1'); - $username = $I->grabTextFrom('#typo3-backend-user-list > tbody > tr:nth-child(1) > td.col-title > a:nth-child(1) > b'); + $I->waitForElementVisible('#typo3-backend-user-list'); + $I->click('button[value="reset-filters"]'); + $I->waitForElementVisible('#typo3-backend-user-list'); + $username = 'admin'; + $adminRow = '//*[@id="typo3-backend-user-list"]//tr[contains(td[2]/a[1]/b[1], "' . $username . '")]'; $I->amGoingTo('test the edit button'); - $I->click('#typo3-backend-user-list > tbody > tr:nth-child(1) > td.col-control > div:nth-child(1) > a'); + $I->click($adminRow . '//div[@role="group"]/a[@title="Edit"]'); $this->openAndCloseTheEditForm($I, $username); $I->amGoingTo('test the edit link on username'); - $I->click('#typo3-backend-user-list > tbody > tr:nth-child(1) > td.col-title > a:nth-child(1)'); + $I->click($adminRow . '//td[@class="col-title"]/a[1]'); $this->openAndCloseTheEditForm($I, $username); $I->amGoingTo('test the edit link on real name'); - $I->click('#typo3-backend-user-list > tbody > tr:nth-child(1) > td.col-title > a:nth-child(4)'); + $I->click($adminRow . '//td[@class="col-title"]/a[2]'); $this->openAndCloseTheEditForm($I, $username); } diff --git a/typo3/sysext/core/Tests/Acceptance/Application/Extensionmanager/GetExtensionsCest.php b/typo3/sysext/core/Tests/Acceptance/Application/Extensionmanager/GetExtensionsCest.php index aec2d2505dc5..89dbbaa169fb 100644 --- a/typo3/sysext/core/Tests/Acceptance/Application/Extensionmanager/GetExtensionsCest.php +++ b/typo3/sysext/core/Tests/Acceptance/Application/Extensionmanager/GetExtensionsCest.php @@ -17,6 +17,7 @@ namespace TYPO3\CMS\Core\Tests\Acceptance\Application\Extensionmanager; +use Codeception\Attribute\Env; use Facebook\WebDriver\WebDriverKeys; use TYPO3\CMS\Core\Tests\Acceptance\Support\ApplicationTester; @@ -47,18 +48,21 @@ public function _before(ApplicationTester $I): void $I->seeNumberOfElements('#terTable tbody tr', 2); } + #[Env('classic')] public function checkRetrievedExtensionsFromTerAreDisplayed(ApplicationTester $I): void { $I->see('superext'); $I->see('neededext'); } + #[Env('classic')] public function checkPaginationIsNotDisplayedForTwoRecords(ApplicationTester $I): void { $I->dontSeeElement('.pagination-wrap'); $I->dontSee('Extensions 1 - 2'); } + #[Env('classic')] public function checkSearchFilterListFindsExtensionKey(ApplicationTester $I): void { $I->fillField('input[name="search"]', 'superext'); @@ -81,6 +85,7 @@ public function checkSearchFilterListFindsExtensionKey(ApplicationTester $I): vo $I->see('Needed Extension'); } + #[Env('classic')] public function checkSearchFilterListFindsPartOfExtensionKey(ApplicationTester $I): void { $I->fillField('input[name="search"]', 'ext'); diff --git a/typo3/sysext/core/Tests/Acceptance/Application/Extensionmanager/InstalledExtensionsCest.php b/typo3/sysext/core/Tests/Acceptance/Application/Extensionmanager/InstalledExtensionsCest.php index c3aee7e30146..915b3d47632d 100644 --- a/typo3/sysext/core/Tests/Acceptance/Application/Extensionmanager/InstalledExtensionsCest.php +++ b/typo3/sysext/core/Tests/Acceptance/Application/Extensionmanager/InstalledExtensionsCest.php @@ -17,6 +17,7 @@ namespace TYPO3\CMS\Core\Tests\Acceptance\Application\Extensionmanager; +use Codeception\Attribute\Env; use TYPO3\CMS\Core\Tests\Acceptance\Support\ApplicationTester; /** @@ -61,6 +62,7 @@ public function checkSearchFiltersList(ApplicationTester $I): void $I->seeNumberOfElements('#typo3-extension-list tbody tr[role="row"]', [10, 100]); } + #[Env('classic')] public function checkIfUploadFormAppears(ApplicationTester $I): void { $I->cantSeeElement('.module-body .extension-upload-form'); @@ -68,6 +70,7 @@ public function checkIfUploadFormAppears(ApplicationTester $I): void $I->seeElement('.module-body .extension-upload-form'); } + #[Env('classic')] public function checkUninstallingAndInstallingAnExtension(ApplicationTester $I): void { $I->wantTo('Check if uninstalling and installing an extension with backend module removes and adds the module from the module menu.'); diff --git a/typo3/sysext/core/Tests/Acceptance/Application/FormEngine/FalMetadataCest.php b/typo3/sysext/core/Tests/Acceptance/Application/FormEngine/FalMetadataCest.php index f541dcdf772e..a6b31ccb64cc 100644 --- a/typo3/sysext/core/Tests/Acceptance/Application/FormEngine/FalMetadataCest.php +++ b/typo3/sysext/core/Tests/Acceptance/Application/FormEngine/FalMetadataCest.php @@ -108,7 +108,10 @@ public function checkIfUpdatedFileMetadataIsUpdatedInContent(ApplicationTester $ $I->waitForElementNotVisible('#t3js-ui-block'); $I->waitForText('Edit Page Content "tt_content with image" on page "styleguide TCA demo"'); $I->click('Images'); - $I->click('.form-irre-header'); + if (count($I->grabMultiple('.panel-collapsed .form-irre-header')) > 0) { + $I->click('.panel-collapsed .form-irre-header'); + } + $I->waitForElement('.t3js-form-field-eval-null-placeholder-checkbox'); $I->see('(Default: "Test title")', '.t3js-form-field-eval-null-placeholder-checkbox'); $I->see('(Default: "Test alternative")', '.t3js-form-field-eval-null-placeholder-checkbox'); @@ -203,7 +206,10 @@ public function checkIfDeactivatingNullCheckboxesFocusesTextFields(ApplicationTe $I->waitForElementNotVisible('#t3js-ui-block'); $I->waitForText('Edit Page Content "tt_content with image" on page "styleguide TCA demo"'); $I->click('Images'); - $I->click('.form-irre-header'); + if (count($I->grabMultiple('.panel-collapsed .form-irre-header')) > 0) { + $I->click('.panel-collapsed .form-irre-header'); + } + $I->waitForElement('.t3js-form-field-eval-null-placeholder-checkbox'); $I->see('(Default: "Test title")', '.t3js-form-field-eval-null-placeholder-checkbox'); $I->see('(Default: "Test alternative")', '.t3js-form-field-eval-null-placeholder-checkbox'); diff --git a/typo3/sysext/core/Tests/Acceptance/Application/FormEngine/Inline1nCest.php b/typo3/sysext/core/Tests/Acceptance/Application/FormEngine/Inline1nCest.php index 8128e2e91203..92b92d22d9ce 100644 --- a/typo3/sysext/core/Tests/Acceptance/Application/FormEngine/Inline1nCest.php +++ b/typo3/sysext/core/Tests/Acceptance/Application/FormEngine/Inline1nCest.php @@ -89,6 +89,11 @@ public function createInline1nInlineElement(ApplicationTester $I): void $I->see('lipsum', '#recordlist-tx_styleguide_inline_1n_inline_1_child > div:nth-child(1) > table:nth-child(1) > tbody:nth-child(2) > tr:nth-child(1) > td:nth-child(3) > a'); $I->see('Fo Bar', '#recordlist-tx_styleguide_inline_1n_inline_1_child > div:nth-child(1) > table:nth-child(1) > tbody:nth-child(2) > tr:nth-child(4) > td:nth-child(3) > a'); + + $I->click('button[data-table="tx_styleguide_inline_1n"] .icon-actions-view-list-expand'); + $I->wait(1); + $I->click('button[data-table="pages_translated"] .icon-actions-view-list-expand'); + $I->wait(1); } /** @@ -111,6 +116,11 @@ public function checkIfCanSortingInlineElement(ApplicationTester $I): void $I->wantTo('Check new sorting'); $I->see('Fo Bar', '#recordlist-tx_styleguide_inline_1n_inline_1_child > div:nth-child(1) > table:nth-child(1) > tbody:nth-child(2) > tr:nth-child(1) > td:nth-child(3) > a'); $I->see('lipsum', '#recordlist-tx_styleguide_inline_1n_inline_1_child > div:nth-child(1) > table:nth-child(1) > tbody:nth-child(2) > tr:nth-child(2) > td:nth-child(3) > a'); + + $I->click('button[data-table="tx_styleguide_inline_1n"] .icon-actions-view-list-expand'); + $I->wait(1); + $I->click('button[data-table="pages_translated"] .icon-actions-view-list-expand'); + $I->wait(1); } public function changeInline1nInlineInput(ApplicationTester $I): void diff --git a/typo3/sysext/core/Tests/Acceptance/Application/Frontend/ContentElementsCest.php b/typo3/sysext/core/Tests/Acceptance/Application/Frontend/ContentElementsCest.php index 7e0fdf5552d9..43580c49874e 100644 --- a/typo3/sysext/core/Tests/Acceptance/Application/Frontend/ContentElementsCest.php +++ b/typo3/sysext/core/Tests/Acceptance/Application/Frontend/ContentElementsCest.php @@ -31,6 +31,8 @@ public function _before(ApplicationTester $I, PageTree $pageTree): void $I->click('Page'); $pageTree->openPath(['styleguide frontend demo']); $I->switchToContentFrame(); + $I->waitForElementVisible('select[name=actionMenu]'); + $I->selectOption('select[name=actionMenu]', 'Layout'); $I->waitForElementVisible('.t3js-module-docheader-bar a[title="View webpage"]'); $I->wait(1); $I->click('.t3js-module-docheader-bar a[title="View webpage"]'); @@ -49,9 +51,13 @@ public function _after(ApplicationTester $I): void // Close FE tab again and switch to BE to avoid side effects $I->executeInSelenium(static function (RemoteWebDriver $webdriver) { $handles = $webdriver->getWindowHandles(); - $webdriver->close(); - $firstWindow = current($handles); - $webdriver->switchTo()->window($firstWindow); + // Avoid closing the main backend tab (holds the webdriver session) if the test failed to open the frontend tab + // (All subsequent tests would fail with "[Facebook\WebDriver\Exception\InvalidSessionIdException] invalid session id" + if (count($handles) > 1) { + $webdriver->close(); + $firstWindow = current($handles); + $webdriver->switchTo()->window($firstWindow); + } }); } diff --git a/typo3/sysext/core/Tests/Acceptance/Application/Frontend/FormFrameworkCest.php b/typo3/sysext/core/Tests/Acceptance/Application/Frontend/FormFrameworkCest.php index 370fefff61cb..e04b2dfc765e 100644 --- a/typo3/sysext/core/Tests/Acceptance/Application/Frontend/FormFrameworkCest.php +++ b/typo3/sysext/core/Tests/Acceptance/Application/Frontend/FormFrameworkCest.php @@ -37,6 +37,8 @@ public function _before(ApplicationTester $I, PageTree $pageTree): void $I->click('Page'); $pageTree->openPath(['styleguide frontend demo']); $I->switchToContentFrame(); + $I->waitForElementVisible('select[name=actionMenu]'); + $I->selectOption('select[name=actionMenu]', 'Layout'); $I->waitForElementVisible('.t3js-module-docheader-bar a[title="View webpage"]'); $I->wait(1); $I->click('.t3js-module-docheader-bar a[title="View webpage"]'); @@ -57,9 +59,13 @@ public function _after(ApplicationTester $I): void // Close FE tab again and switch to BE to avoid side effects $I->executeInSelenium(static function (RemoteWebDriver $webdriver) { $handles = $webdriver->getWindowHandles(); - $webdriver->close(); - $firstWindow = current($handles); - $webdriver->switchTo()->window($firstWindow); + // Avoid closing the main backend tab (holds the webdriver session) if the test failed to open the frontend tab + // (All subsequent tests would fail with "[Facebook\WebDriver\Exception\InvalidSessionIdException] invalid session id" + if (count($handles) > 1) { + $webdriver->close(); + $firstWindow = current($handles); + $webdriver->switchTo()->window($firstWindow); + } }); } diff --git a/typo3/sysext/core/Tests/Acceptance/Application/Frontend/FrontendLoginCest.php b/typo3/sysext/core/Tests/Acceptance/Application/Frontend/FrontendLoginCest.php index 30f2e0f3a0a0..03597fa69921 100644 --- a/typo3/sysext/core/Tests/Acceptance/Application/Frontend/FrontendLoginCest.php +++ b/typo3/sysext/core/Tests/Acceptance/Application/Frontend/FrontendLoginCest.php @@ -35,6 +35,8 @@ public function _before(ApplicationTester $I, PageTree $pageTree): void $I->click('Page'); $pageTree->openPath(['styleguide frontend demo']); $I->switchToContentFrame(); + $I->waitForElementVisible('select[name=actionMenu]'); + $I->selectOption('select[name=actionMenu]', 'Layout'); $I->waitForElementVisible('.t3js-module-docheader-bar a[title="View webpage"]'); $I->wait(1); $I->click('.t3js-module-docheader-bar a[title="View webpage"]'); @@ -55,9 +57,13 @@ public function _after(ApplicationTester $I): void // Close FE tab again and switch to BE to avoid side effects $I->executeInSelenium(static function (RemoteWebDriver $webdriver) { $handles = $webdriver->getWindowHandles(); - $webdriver->close(); - $firstWindow = current($handles); - $webdriver->switchTo()->window($firstWindow); + // Avoid closing the main backend tab (holds the webdriver session) if the test failed to open the frontend tab + // (All subsequent tests would fail with "[Facebook\WebDriver\Exception\InvalidSessionIdException] invalid session id" + if (count($handles) > 1) { + $webdriver->close(); + $firstWindow = current($handles); + $webdriver->switchTo()->window($firstWindow); + } }); } diff --git a/typo3/sysext/core/Tests/Acceptance/Application/Frontend/IndexedSearchCest.php b/typo3/sysext/core/Tests/Acceptance/Application/Frontend/IndexedSearchCest.php index e61b74ec66e1..363a8878f2c3 100644 --- a/typo3/sysext/core/Tests/Acceptance/Application/Frontend/IndexedSearchCest.php +++ b/typo3/sysext/core/Tests/Acceptance/Application/Frontend/IndexedSearchCest.php @@ -36,6 +36,8 @@ public function _before(ApplicationTester $I, PageTree $pageTree): void $I->click('Page'); $pageTree->openPath(['styleguide frontend demo']); $I->switchToContentFrame(); + $I->waitForElementVisible('select[name=actionMenu]'); + $I->selectOption('select[name=actionMenu]', 'Layout'); $I->waitForElementVisible('.t3js-module-docheader-bar a[title="View webpage"]'); $I->wait(1); $I->click('.t3js-module-docheader-bar a[title="View webpage"]'); @@ -56,9 +58,13 @@ public function _after(ApplicationTester $I): void // Close FE tab again and switch to BE to avoid side effects $I->executeInSelenium(static function (RemoteWebDriver $webdriver) { $handles = $webdriver->getWindowHandles(); - $webdriver->close(); - $firstWindow = current($handles); - $webdriver->switchTo()->window($firstWindow); + // Avoid closing the main backend tab (holds the webdriver session) if the test failed to open the frontend tab + // (All subsequent tests would fail with "[Facebook\WebDriver\Exception\InvalidSessionIdException] invalid session id" + if (count($handles) > 1) { + $webdriver->close(); + $firstWindow = current($handles); + $webdriver->switchTo()->window($firstWindow); + } }); } diff --git a/typo3/sysext/core/Tests/Acceptance/Application/Impexp/ImportCest.php b/typo3/sysext/core/Tests/Acceptance/Application/Impexp/ImportCest.php index 7ec1bc16c6ef..c337096351c4 100644 --- a/typo3/sysext/core/Tests/Acceptance/Application/Impexp/ImportCest.php +++ b/typo3/sysext/core/Tests/Acceptance/Application/Impexp/ImportCest.php @@ -17,7 +17,6 @@ namespace TYPO3\CMS\Core\Tests\Acceptance\Application\Impexp; -use TYPO3\CMS\Core\Core\Environment; use TYPO3\CMS\Core\Tests\Acceptance\Support\ApplicationTester; use TYPO3\CMS\Core\Tests\Acceptance\Support\Helper\ModalDialog; use TYPO3\CMS\Core\Tests\Acceptance\Support\Helper\PageTree; @@ -143,7 +142,7 @@ public function rejectImportIfPrerequisitesNotMet(ApplicationTester $I, ModalDia $I->canSeeElement($this->inModuleTabs . ' ' . $this->tabMessages); $flashMessage = $I->grabTextFrom($this->inFlashMessages . ' .alert.alert-success .alert-message'); preg_match('/[^"]+"([^"]+)"[^"]+"([^"]+)"[^"]+/', $flashMessage, $flashMessageParts); - $loadFilePath = Environment::getProjectPath() . '/fileadmin' . $flashMessageParts[2] . $flashMessageParts[1]; + $loadFilePath = getenv('TYPO3_ACCEPTANCE_PATH_WEB') . '/fileadmin' . $flashMessageParts[2] . $flashMessageParts[1]; $I->assertFileExists($loadFilePath); $this->testFilesToDelete[] = $loadFilePath; @@ -180,7 +179,7 @@ public function importPageAndRecords(ApplicationTester $I, ModalDialog $modalDia $I->cantSeeElement($this->inModuleTabs . ' ' . $this->tabMessages); $flashMessage = $I->grabTextFrom($this->inFlashMessages . ' .alert.alert-success .alert-message'); preg_match('/[^"]+"([^"]+)"[^"]+"([^"]+)"[^"]+/', $flashMessage, $flashMessageParts); - $loadFilePath = Environment::getProjectPath() . '/fileadmin' . $flashMessageParts[2] . $flashMessageParts[1]; + $loadFilePath = getenv('TYPO3_ACCEPTANCE_PATH_WEB') . '/fileadmin' . $flashMessageParts[2] . $flashMessageParts[1]; $I->assertFileExists($loadFilePath); $this->testFilesToDelete[] = $loadFilePath; @@ -221,7 +220,7 @@ public function importTable(ApplicationTester $I, ModalDialog $modalDialog, Page $I->cantSeeElement($this->inModuleTabs . ' ' . $this->tabMessages); $flashMessage = $I->grabTextFrom($this->inFlashMessages . ' .alert.alert-success .alert-message'); preg_match('/[^"]+"([^"]+)"[^"]+"([^"]+)"[^"]+/', $flashMessage, $flashMessageParts); - $loadFilePath = Environment::getProjectPath() . '/fileadmin' . $flashMessageParts[2] . $flashMessageParts[1]; + $loadFilePath = getenv('TYPO3_ACCEPTANCE_PATH_WEB') . '/fileadmin' . $flashMessageParts[2] . $flashMessageParts[1]; $I->assertFileExists($loadFilePath); $this->testFilesToDelete[] = $loadFilePath; @@ -264,7 +263,7 @@ public function importRecord(ApplicationTester $I, ModalDialog $modalDialog, Pag $I->cantSeeElement($this->inModuleTabs . ' ' . $this->tabMessages); $flashMessage = $I->grabTextFrom($this->inFlashMessages . ' .alert.alert-success .alert-message'); preg_match('/[^"]+"([^"]+)"[^"]+"([^"]+)"[^"]+/', $flashMessage, $flashMessageParts); - $loadFilePath = Environment::getProjectPath() . '/fileadmin' . $flashMessageParts[2] . $flashMessageParts[1]; + $loadFilePath = getenv('TYPO3_ACCEPTANCE_PATH_WEB') . '/fileadmin' . $flashMessageParts[2] . $flashMessageParts[1]; $I->assertFileExists($loadFilePath); $this->testFilesToDelete[] = $loadFilePath; diff --git a/typo3/sysext/core/Tests/Acceptance/Application/InstallTool/AbstractCest.php b/typo3/sysext/core/Tests/Acceptance/Application/InstallTool/AbstractCest.php index bee44be2fb93..cf832d38256e 100644 --- a/typo3/sysext/core/Tests/Acceptance/Application/InstallTool/AbstractCest.php +++ b/typo3/sysext/core/Tests/Acceptance/Application/InstallTool/AbstractCest.php @@ -17,7 +17,6 @@ namespace TYPO3\CMS\Core\Tests\Acceptance\Application\InstallTool; -use TYPO3\CMS\Core\Core\Environment; use TYPO3\CMS\Core\Crypto\PasswordHashing\Argon2iPasswordHash; use TYPO3\CMS\Core\Tests\Acceptance\Support\ApplicationTester; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -25,7 +24,7 @@ class AbstractCest { - private const ADDITIONAL_CONFIGURATION_FILEPATH = 'typo3conf/system/additional.php'; + private const ADDITIONAL_CONFIGURATION_FILEPATH = '/system/additional.php'; protected const INSTALL_TOOL_PASSWORD = 'temporary password'; public function _before(ApplicationTester $I): void @@ -40,15 +39,19 @@ public function _after(ApplicationTester $I): void $I->waitForText('The Install Tool is locked', 20); $I->amGoingTo('clean up created files'); - unlink(Environment::getProjectPath() . '/' . self::ADDITIONAL_CONFIGURATION_FILEPATH); + if (getenv('TYPO3_ACCEPTANCE_INSTALLTOOL_PW_PRESET') !== '1') { + unlink(getenv('TYPO3_ACCEPTANCE_PATH_CONFIG') . self::ADDITIONAL_CONFIGURATION_FILEPATH); + } $I->dontSeeFileFound($this->getEnableInstallToolFilePath()); - $I->dontSeeFileFound(Environment::getProjectPath() . '/' . self::ADDITIONAL_CONFIGURATION_FILEPATH); + if (getenv('TYPO3_ACCEPTANCE_INSTALLTOOL_PW_PRESET') !== '1') { + $I->dontSeeFileFound(getenv('TYPO3_ACCEPTANCE_PATH_CONFIG') . self::ADDITIONAL_CONFIGURATION_FILEPATH); + } } protected function getEnableInstallToolFilePath(): string { - return Environment::getVarPath() . '/transient/' . EnableFileService::INSTALL_TOOL_ENABLE_FILE_PATH; + return getenv('TYPO3_ACCEPTANCE_PATH_VAR') . '/transient/' . EnableFileService::INSTALL_TOOL_ENABLE_FILE_PATH; } protected function logIntoInstallTool(ApplicationTester $I): void @@ -65,11 +68,14 @@ protected function logIntoInstallTool(ApplicationTester $I): void private function setInstallToolPassword(ApplicationTester $I): string { - $hashMethod = GeneralUtility::makeInstance(Argon2iPasswordHash::class); $password = self::INSTALL_TOOL_PASSWORD; + if (getenv('TYPO3_ACCEPTANCE_INSTALLTOOL_PW_PRESET') === '1') { + return $password; + } + $hashMethod = GeneralUtility::makeInstance(Argon2iPasswordHash::class); $hashedPassword = $hashMethod->getHashedPassword($password); $I->writeToFile( - self::ADDITIONAL_CONFIGURATION_FILEPATH, + getenv('TYPO3_ACCEPTANCE_PATH_CONFIG') . self::ADDITIONAL_CONFIGURATION_FILEPATH, 'waitForElementNotVisible('.modal-dialog'); } + #[Env('classic')] public function dumpAutoloadWorks(ApplicationTester $I): void { $I->click('Dump autoload'); diff --git a/typo3/sysext/core/Tests/Acceptance/Application/InstallTool/SettingsCest.php b/typo3/sysext/core/Tests/Acceptance/Application/InstallTool/SettingsCest.php index 882f1af6d1d3..50b30206d13f 100644 --- a/typo3/sysext/core/Tests/Acceptance/Application/InstallTool/SettingsCest.php +++ b/typo3/sysext/core/Tests/Acceptance/Application/InstallTool/SettingsCest.php @@ -17,6 +17,7 @@ namespace TYPO3\CMS\Core\Tests\Acceptance\Application\InstallTool; +use Codeception\Scenario; use TYPO3\CMS\Core\Tests\Acceptance\Support\ApplicationTester; use TYPO3\CMS\Core\Tests\Acceptance\Support\Helper\ModalDialog; @@ -151,7 +152,7 @@ public function seeConfigurationPresets(ApplicationTester $I, ModalDialog $modal $this->closeModalAndHideFlashMessage($I); } - public function seeFeatureToggles(ApplicationTester $I, ModalDialog $modalDialog): void + public function seeFeatureToggles(ApplicationTester $I, ModalDialog $modalDialog, Scenario $scenario): void { $button = 'Configure Features…'; $modalButton = 'Save'; @@ -169,7 +170,12 @@ public function seeFeatureToggles(ApplicationTester $I, ModalDialog $modalDialog // Switch back hit count feature toggle $I->click($button); $modalDialog->canSeeDialog(); - $I->cantSeeCheckboxIsChecked($featureToggle); + if (str_contains($scenario->current('env'), 'classic')) { + // ['features']['redirects.hitCount'] is enabled by default in classic mode (set by TF BackendEnvironment setup) + $I->cantSeeCheckboxIsChecked($featureToggle); + } else { + $I->canSeeCheckboxIsChecked($featureToggle); + } $I->amGoingTo('reset hit count feature toggle and save it'); $I->click($featureToggle); $I->click($modalButton, ModalDialog::$openedModalButtonContainerSelector); diff --git a/typo3/sysext/core/Tests/Acceptance/Application/InstallTool/UpgradeCest.php b/typo3/sysext/core/Tests/Acceptance/Application/InstallTool/UpgradeCest.php index 997c4107a82c..816a05b9a223 100644 --- a/typo3/sysext/core/Tests/Acceptance/Application/InstallTool/UpgradeCest.php +++ b/typo3/sysext/core/Tests/Acceptance/Application/InstallTool/UpgradeCest.php @@ -17,6 +17,7 @@ namespace TYPO3\CMS\Core\Tests\Acceptance\Application\InstallTool; +use Codeception\Attribute\Env; use TYPO3\CMS\Core\Tests\Acceptance\Support\ApplicationTester; use TYPO3\CMS\Core\Tests\Acceptance\Support\Helper\ModalDialog; @@ -30,6 +31,7 @@ public function _before(ApplicationTester $I): void $I->see('Upgrade', 'h1'); } + #[Env('classic')] public function seeUpgradeCore(ApplicationTester $I, ModalDialog $modalDialog): void { $I->click('Update Core…'); diff --git a/typo3/sysext/core/Tests/Acceptance/Application/Redirect/RedirectModuleCest.php b/typo3/sysext/core/Tests/Acceptance/Application/Redirect/RedirectModuleCest.php index b219db8a3dc7..6f48e185c9d6 100644 --- a/typo3/sysext/core/Tests/Acceptance/Application/Redirect/RedirectModuleCest.php +++ b/typo3/sysext/core/Tests/Acceptance/Application/Redirect/RedirectModuleCest.php @@ -71,7 +71,7 @@ public function canEditRecordFromListView(ApplicationTester $I): void $I->canSee('Redirect Management', 'h1'); $I->amGoingTo('test edit on edit button'); - $I->click('table.table-striped > tbody > tr > td:nth-child(8) > div > a:nth-child(2)'); + $I->click('table.table-striped > tbody > tr > td.col-control > div > a:nth-child(2)'); $I->waitForElementNotVisible('#t3js-ui-block'); $I->canSee('Edit Redirect "' . $sourceHost . ', ' . $sourcePath . '" on root level'); $I->click('div.module-docheader .btn.t3js-editform-close'); diff --git a/typo3/sysext/core/Tests/Acceptance/Application/Scheduler/TasksCest.php b/typo3/sysext/core/Tests/Acceptance/Application/Scheduler/TasksCest.php index f6ac098e002a..8be04e089a78 100644 --- a/typo3/sysext/core/Tests/Acceptance/Application/Scheduler/TasksCest.php +++ b/typo3/sysext/core/Tests/Acceptance/Application/Scheduler/TasksCest.php @@ -126,6 +126,7 @@ public function canSwitchToInformation(ApplicationTester $I): void $I->waitForElementVisible('[data-module-name="scheduler_availabletasks"]'); $I->see('Available scheduler commands & tasks'); $I->canSeeNumberOfElements('[data-module-name="scheduler_availabletasks"] table tbody tr', [1, 10000]); + $I->selectOption('select[name=moduleMenu]', 'Scheduled tasks'); } public function canCreateNewTaskGroupFromEditForm(ApplicationTester $I, ModalDialog $modalDialog): void diff --git a/typo3/sysext/core/Tests/Acceptance/Application/Template/TemplateCest.php b/typo3/sysext/core/Tests/Acceptance/Application/Template/TemplateCest.php index bc37fa0239c5..b33275258b89 100644 --- a/typo3/sysext/core/Tests/Acceptance/Application/Template/TemplateCest.php +++ b/typo3/sysext/core/Tests/Acceptance/Application/Template/TemplateCest.php @@ -166,6 +166,10 @@ public function checkClosestTemplateButton(ApplicationTester $I, PageTree $pageT $I->waitForText('Edit the whole TypoScript record'); $I->see('Edit the whole TypoScript record'); $I->click('Edit the whole TypoScript record'); + // Avoid race condition: + // SEVERE - http://web/typo3/sysext/backend/Resources/Public/JavaScript/code-editor/autocomplete/ts-ref.js?bust=[…] + // 12:613 Uncaught TypeError: Cannot convert undefined or null to object + $I->waitForElementNotVisible('#nprogress', 120); } public function createExtensionTemplate(ApplicationTester $I, PageTree $pageTree): void diff --git a/typo3/sysext/core/Tests/Acceptance/Support/Extension/ApplicationComposerEnvironment.php b/typo3/sysext/core/Tests/Acceptance/Support/Extension/ApplicationComposerEnvironment.php new file mode 100644 index 000000000000..2a19602a628d --- /dev/null +++ b/typo3/sysext/core/Tests/Acceptance/Support/Extension/ApplicationComposerEnvironment.php @@ -0,0 +1,49 @@ + 'typo3temp/var/tests/acceptance-composer', + ]; + + public static $events = [ + Events::SUITE_BEFORE => 'bootstrapTypo3Environment', + ]; + + public function bootstrapTypo3Environment() + { + // @todo: ugly workaround for InstallTool/AbstractCest.php + $root = realpath(__DIR__ . '/../../../../../../../' . $this->config['typo3InstancePath']); + chdir($root); + putenv('TYPO3_ACCEPTANCE_PATH_WEB=' . $root . '/public'); + putenv('TYPO3_ACCEPTANCE_PATH_VAR=' . $root . '/var'); + putenv('TYPO3_ACCEPTANCE_PATH_CONFIG=' . $root . '/config'); + putenv('TYPO3_ACCEPTANCE_INSTALLTOOL_PW_PRESET=1'); + } +} diff --git a/typo3/sysext/core/Tests/Acceptance/Support/Extension/ApplicationEnvironment.php b/typo3/sysext/core/Tests/Acceptance/Support/Extension/ApplicationEnvironment.php index dfd3c3330998..df19aa525cbe 100644 --- a/typo3/sysext/core/Tests/Acceptance/Support/Extension/ApplicationEnvironment.php +++ b/typo3/sysext/core/Tests/Acceptance/Support/Extension/ApplicationEnvironment.php @@ -152,6 +152,10 @@ public function bootstrapTypo3Environment(SuiteEvent $suiteEvent): void ); } } + // @todo: ugly workaround for InstallTool/AbstractCest.php + putenv('TYPO3_ACCEPTANCE_PATH_WEB=' . $instancePath); + putenv('TYPO3_ACCEPTANCE_PATH_VAR=' . $instancePath . '/typo3temp/var'); + putenv('TYPO3_ACCEPTANCE_PATH_CONFIG=' . $instancePath . '/typo3conf'); } // @todo Eventually move this up to TF::BackendEnvironment, but then as protected.