diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index e286c8ab..cfec80b7 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -18,6 +18,7 @@ jobs: - 8.1 - 8.2 - 8.3 + - 8.4 steps: - name: Checkout uses: actions/checkout@v4 @@ -75,6 +76,8 @@ jobs: typo3-version: '^12.4' - php-version: '8.3' typo3-version: '^12.4' + - php-version: '8.4' + typo3-version: '^12.4' steps: - uses: actions/checkout@v4 @@ -88,10 +91,13 @@ jobs: run: |- composer require --no-interaction --prefer-dist --no-progress "typo3/cms-core:${{ matrix.typo3-version }}" "typo3/cms-extbase:${{ matrix.typo3-version }}" "typo3/cms-frontend:${{ matrix.typo3-version }}" + - name: Build codeception tester + run: vendor/bin/codecept build + - name: Code Quality (by PHPStan) run: vendor/bin/phpstan analyse -c Build/phpstan.neon - tests-acceptance: + test-php: runs-on: ubuntu-latest needs: - coding-guideline @@ -112,6 +118,9 @@ jobs: - name: Run Unit Tests PHP8.3 run: nix-shell --arg phpVersion \"php83\" --pure --run project-test-unit + - name: Run Unit Tests PHP8.4 + run: nix-shell --arg phpVersion \"php84\" --pure --run project-test-unit + - name: Run Functional Tests PHP8.1 run: nix-shell --arg phpVersion \"php81\" --pure --run project-test-functional @@ -121,6 +130,20 @@ jobs: - name: Run Functional Tests PHP8.3 run: nix-shell --arg phpVersion \"php83\" --pure --run project-test-functional + - name: Run Functional Tests PHP8.4 + run: nix-shell --arg phpVersion \"php84\" --pure --run project-test-functional + + test-acceptance: + runs-on: ubuntu-latest + needs: + - test-php + steps: + - uses: actions/checkout@v3 + + - uses: cachix/install-nix-action@v17 + with: + nix_path: nixpkgs=channel:nixos-unstable + - name: Run Acceptance Tests PHP8.1 run: nix-shell --arg phpVersion \"php81\" --pure --run project-test-acceptance @@ -129,3 +152,6 @@ jobs: - name: Run Acceptance Tests PHP8.3 run: nix-shell --arg phpVersion \"php83\" --pure --run project-test-acceptance + + - name: Run Acceptance Tests PHP8.4 + run: nix-shell --arg phpVersion \"php84\" --pure --run project-test-acceptance diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index acd4c95d..d169a475 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -5,14 +5,7 @@ cache: - .php_cs.cache variables: - COMPOSER_CACHE_DIR: ".composer" - TYPO3_PATH_WEB: "$CI_PROJECT_DIR/.build/public" - MYSQL_DATABASE: "typo3" - MYSQL_ROOT_PASSWORD: "joh316" - typo3DatabaseName: "typo3" - typo3DatabaseHost: "mysql" - typo3DatabaseUsername: "root" - typo3DatabasePassword: "joh316" + TYPO3_VERSION: ^12.4 before_script: - apk add git --update @@ -26,29 +19,10 @@ lint:cgl: image: $CI_REGISTRY/containers/phpunit-with-php-8.1:main stage: lint before_script: - - sed -i -e "s#ssh://git@code.extco.de:22722#https://gitlab-ci-token:$CI_JOB_TOKEN@code.extco.de#g" composer.json - - composer config platform.php 8.1 - composer remove typo3/cms-core --no-update - composer install --no-progress --no-ansi --no-interaction script: - vendor/bin/php-cs-fixer fix --config=Build/.php-cs-fixer.dist.php -v --dry-run --using-cache=no --path-mode=intersection ./ - -lint:typoscriptcgl: - image: php:8.1-alpine - stage: lint - before_script: - - apk add --no-cache bash curl git mercurial openssh openssl parallel subversion tini zlib-dev libzip-dev zip icu-dev g++ - - docker-php-ext-install mysqli && docker-php-ext-install zip && docker-php-ext-configure intl && docker-php-ext-install intl && docker-php-ext-enable intl - - wget https://composer.github.io/installer.sig -O - -q | tr -d '\n' > installer.sig - - php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" - - php -r "if (hash_file('SHA384', 'composer-setup.php') === trim(file_get_contents('installer.sig'))) { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" - - php composer-setup.php --no-ansi --install-dir=/usr/bin --filename=composer - - php -r "unlink('composer-setup.php'); unlink('installer.sig');" - - sed -i -e "s#ssh://git@code.extco.de:22722#https://gitlab-ci-token:$CI_JOB_TOKEN@code.extco.de#g" composer.json - - composer config platform.php 8.1 - - composer remove typo3/cms-core --no-update - - composer install --no-progress --no-ansi --no-interaction - script: - vendor/bin/typoscript-lint -c Build/typoscriptlint.yaml Configuration lint:yaml: @@ -81,6 +55,11 @@ lint:php83: variables: CONTAINER_IMAGE: php:8.3-alpine +lint:php84: + <<: *lint_php + variables: + CONTAINER_IMAGE: php:8.4-alpine + phpstan:analyse: image: $CI_REGISTRY/containers/phpunit-with-php-8.1:main stage: lint @@ -89,6 +68,7 @@ phpstan:analyse: - composer config platform.php 8.1 - composer install --no-progress --no-ansi --no-interaction script: + - vendor/bin/codecept build - vendor/bin/phpstan analyse -c Build/phpstan.neon --memory-limit 256M .test_php: &test_php @@ -106,26 +86,25 @@ phpstan:analyse: - vendor/bin/phpunit -c Build/UnitTests.xml - typo3DatabaseDriver=pdo_sqlite vendor/bin/phpunit -c Build/FunctionalTests.xml -# Build in PHP 8.1 and TYPO3 12.4 -test:php81:typo3_12: +test:php81: <<: *test_php variables: CONTAINER_IMAGE: $CI_REGISTRY/containers/phpunit-with-php-8.1:main - TYPO3_VERSION: ^12.4 -# Build in PHP 8.2 and TYPO3 12.4 -test:php82:typo3_12: +test:php82: <<: *test_php variables: CONTAINER_IMAGE: $CI_REGISTRY/containers/phpunit-with-php-8.2:main - TYPO3_VERSION: ^12.4 -# Build in PHP 8.3 and TYPO3 12.4 -test:php83:typo3_12: +test:php83: <<: *test_php variables: CONTAINER_IMAGE: $CI_REGISTRY/containers/phpunit-with-php-8.3:main - TYPO3_VERSION: ^12.4 + +test:php84: + <<: *test_php + variables: + CONTAINER_IMAGE: $CI_REGISTRY/containers/phpunit-with-php-8.4:main .test_codeception: &test_codeception stage: test @@ -151,33 +130,31 @@ test:php83:typo3_12: expire_in: 1 day when: always -# Build in PHP 8.1 and TYPO3 12.4 -test:codception:php81:typo3_12: +codeception:php81: <<: *test_codeception variables: CONTAINER_IMAGE: $CI_REGISTRY/containers/codeception-with-php-8.1:main - TYPO3_VERSION: ^12.4 - GECKODRIVER_VERSION: v0.34.0 -# Build in PHP 8.2 and TYPO3 12.4 -test:codception:php82:typo3_12: +codeception:php82: <<: *test_codeception needs: - - test:codception:php81:typo3_12 + - codeception:php81 variables: CONTAINER_IMAGE: $CI_REGISTRY/containers/codeception-with-php-8.2:main - TYPO3_VERSION: ^12.4 - GECKODRIVER_VERSION: v0.34.0 -# Build in PHP 8.3 and TYPO3 12.4 -test:codception:php83:typo3_12: +codeception:php83: <<: *test_codeception needs: - - test:codception:php82:typo3_12 + - codeception:php82 variables: CONTAINER_IMAGE: $CI_REGISTRY/containers/codeception-with-php-8.3:main - TYPO3_VERSION: ^12.4 - GECKODRIVER_VERSION: v0.34.0 + +codeception:php84: + <<: *test_codeception + needs: + - codeception:php83 + variables: + CONTAINER_IMAGE: $CI_REGISTRY/containers/codeception-with-php-8.4:main documentation: stage: documentation diff --git a/Build/phpstan.neon b/Build/phpstan.neon index c166ea3c..f9aa6f76 100644 --- a/Build/phpstan.neon +++ b/Build/phpstan.neon @@ -7,4 +7,4 @@ parameters: - ../ext_emconf.php - ../ext_localconf.php excludePaths: - - ../Tests/Acceptance + - ../Tests/Acceptance/Support/_generated diff --git a/Classes/Controller/ProductController.php b/Classes/Controller/ProductController.php index 55bf0c89..2b4c372a 100644 --- a/Classes/Controller/ProductController.php +++ b/Classes/Controller/ProductController.php @@ -181,7 +181,7 @@ public function listAction(int $currentPage = 1): ResponseInterface return $this->htmlResponse(); } - public function showAction(Product $product = null): ResponseInterface + public function showAction(?Product $product = null): ResponseInterface { if ((int)$GLOBALS['TSFE']->page['doktype'] === 183) { $productUid = (int)$GLOBALS['TSFE']->page['cart_products_product']; @@ -197,7 +197,7 @@ public function showAction(Product $product = null): ResponseInterface return $this->htmlResponse(); } - public function showFormAction(Product $product = null): ResponseInterface + public function showFormAction(?Product $product = null): ResponseInterface { if (!$product) { $product = $this->getProduct(); diff --git a/Classes/Domain/Repository/CategoryRepository.php b/Classes/Domain/Repository/CategoryRepository.php index a8ca332e..b4100a95 100644 --- a/Classes/Domain/Repository/CategoryRepository.php +++ b/Classes/Domain/Repository/CategoryRepository.php @@ -16,13 +16,13 @@ class CategoryRepository extends Repository { - public function findAllAsRecursiveTreeArray(Category $selectedCategory = null): array + public function findAllAsRecursiveTreeArray(?Category $selectedCategory = null): array { $categoriesArray = $this->findAllAsArray($selectedCategory); return $this->buildSubcategories($categoriesArray, null); } - public function findAllAsArray(Category $selectedCategory = null): array + public function findAllAsArray(?Category $selectedCategory = null): array { $localCategories = $this->findAll(); $categories = []; @@ -41,7 +41,7 @@ public function findAllAsArray(Category $selectedCategory = null): array return $categories; } - public function findSubcategoriesRecursiveAsArray(Category $parentCategory = null): array + public function findSubcategoriesRecursiveAsArray(?Category $parentCategory = null): array { $categories = []; $localCategories = $this->findAllAsArray(); diff --git a/Tests/Acceptance/AddConfigurableProductWithStockHandlingToCartCest.php b/Tests/Acceptance/AddConfigurableProductWithStockHandlingToCartCest.php index 4e9cb1b1..d2fa9aa3 100644 --- a/Tests/Acceptance/AddConfigurableProductWithStockHandlingToCartCest.php +++ b/Tests/Acceptance/AddConfigurableProductWithStockHandlingToCartCest.php @@ -32,10 +32,9 @@ public function testAddDifferentItemsWithinAvailableAmountToCart(Tester $I): voi $I->see('Item was added to cart.', '#product-6 .form-message .form-success'); $I->dontSeeElement('#product-6 .form-message .form-error'); - $I->wait(3); - $I->dontSeeElement('#product-6 .form-message .form-success'); - $I->dontSeeElement('#product-6 .form-message .form-error'); + $I->waitForElementNotVisible('#product-6 .form-message .form-success'); + $I->waitForElementNotVisible('#product-6 .form-message .form-error'); $I->fillField('tx_cart_cart[quantity]', 2); $I->selectOption('tx_cart_cart[beVariants][1]', 'M - green'); @@ -44,10 +43,9 @@ public function testAddDifferentItemsWithinAvailableAmountToCart(Tester $I): voi $I->see('2 Items were added to cart.', '#product-6 .form-message .form-success'); $I->dontSeeElement('#product-6 .form-message .form-error'); - $I->wait(3); - $I->dontSeeElement('#product-6 .form-message .form-success'); - $I->dontSeeElement('#product-6 .form-message .form-error'); + $I->waitForElementNotVisible('#product-6 .form-message .form-success'); + $I->waitForElementNotVisible('#product-6 .form-message .form-error'); $I->fillField('tx_cart_cart[quantity]', 4); $I->selectOption('tx_cart_cart[beVariants][1]', 'XL - red'); @@ -56,10 +54,9 @@ public function testAddDifferentItemsWithinAvailableAmountToCart(Tester $I): voi $I->see('4 Items were added to cart.', '#product-6 .form-message .form-success'); $I->dontSeeElement('#product-6 .form-message .form-error'); - $I->wait(3); - $I->dontSeeElement('#product-6 .form-message .form-success'); - $I->dontSeeElement('#product-6 .form-message .form-error'); + $I->waitForElementNotVisible('#product-6 .form-message .form-success'); + $I->waitForElementNotVisible('#product-6 .form-message .form-error'); } public function testAddMoreItemsThanInStockOfASimpleProductToCart(Tester $I): void @@ -80,10 +77,8 @@ public function testAddMoreItemsThanInStockOfASimpleProductToCart(Tester $I): vo $I->dontSeeElement('#product-6 .form-message .form-success'); $I->see('Desired number of this item not available.', '#product-6 .form-message .form-error'); - $I->wait(3); - - $I->dontSeeElement('#product-6 .form-message .form-success'); - $I->dontSeeElement('#product-6 .form-message .form-error'); + $I->waitForElementNotVisible('#product-6 .form-message .form-success'); + $I->waitForElementNotVisible('#product-6 .form-message .form-error'); } public function testAddOneAndThanMoreItemsThanInStockOfASimpleProductToCart(Tester $I): void @@ -103,10 +98,9 @@ public function testAddOneAndThanMoreItemsThanInStockOfASimpleProductToCart(Test $I->see('Item was added to cart.', '#product-6 .form-message .form-success'); $I->dontSeeElement('#product-6 .form-message .form-error'); - $I->wait(3); - $I->dontSeeElement('#product-6 .form-message .form-success'); - $I->dontSeeElement('#product-6 .form-message .form-error'); + $I->waitForElementNotVisible('#product-6 .form-message .form-success'); + $I->waitForElementNotVisible('#product-6 .form-message .form-error'); $I->fillField('tx_cart_cart[quantity]', 5); $I->selectOption('tx_cart_cart[beVariants][1]', 'XL - red'); @@ -116,9 +110,7 @@ public function testAddOneAndThanMoreItemsThanInStockOfASimpleProductToCart(Test $I->dontSeeElement('#product-6 .form-message .form-success'); $I->see('Desired number of this item not available.', '#product-6 .form-message .form-error'); - $I->wait(3); - - $I->dontSeeElement('#product-6 .form-message .form-success'); - $I->dontSeeElement('#product-6 .form-message .form-error'); + $I->waitForElementNotVisible('#product-6 .form-message .form-success'); + $I->waitForElementNotVisible('#product-6 .form-message .form-error'); } } diff --git a/Tests/Acceptance/AddConfigurableProductWithoutStockHandlingToCartCest.php b/Tests/Acceptance/AddConfigurableProductWithoutStockHandlingToCartCest.php index 9312d955..bb28676b 100644 --- a/Tests/Acceptance/AddConfigurableProductWithoutStockHandlingToCartCest.php +++ b/Tests/Acceptance/AddConfigurableProductWithoutStockHandlingToCartCest.php @@ -31,10 +31,9 @@ public function testAddDifferentItemsToCart(Tester $I): void $I->see('Item was added to cart.', '#product-5 .form-message .form-success'); $I->dontSeeElement('#product-5 .form-message .form-error'); - $I->wait(3); - $I->dontSeeElement('#product-5 .form-message .form-success'); - $I->dontSeeElement('#product-5 .form-message .form-error'); + $I->waitForElementNotVisible('#product-5 .form-message .form-success'); + $I->waitForElementNotVisible('#product-5 .form-message .form-error'); $I->fillField('tx_cart_cart[quantity]', 2); $I->selectOption('tx_cart_cart[beVariants][1]', 'green'); @@ -42,10 +41,9 @@ public function testAddDifferentItemsToCart(Tester $I): void $I->see('2 Items were added to cart.', '#product-5 .form-message .form-success'); $I->dontSeeElement('#product-5 .form-message .form-error'); - $I->wait(3); - $I->dontSeeElement('#product-5 .form-message .form-success'); - $I->dontSeeElement('#product-5 .form-message .form-error'); + $I->waitForElementNotVisible('#product-5 .form-message .form-success'); + $I->waitForElementNotVisible('#product-5 .form-message .form-error'); $I->fillField('tx_cart_cart[quantity]', 100); $I->selectOption('tx_cart_cart[beVariants][1]', 'red'); @@ -53,9 +51,8 @@ public function testAddDifferentItemsToCart(Tester $I): void $I->see('100 Items were added to cart.', '#product-5 .form-message .form-success'); $I->dontSeeElement('#product-5 .form-message .form-error'); - $I->wait(3); - $I->dontSeeElement('#product-5 .form-message .form-success'); - $I->dontSeeElement('#product-5 .form-message .form-error'); + $I->waitForElementNotVisible('#product-5 .form-message .form-success'); + $I->waitForElementNotVisible('#product-5 .form-message .form-error'); } } diff --git a/Tests/Acceptance/AddSimpleProductWithStockHandlingToCartCest.php b/Tests/Acceptance/AddSimpleProductWithStockHandlingToCartCest.php index d54be8ca..b0e2ae20 100644 --- a/Tests/Acceptance/AddSimpleProductWithStockHandlingToCartCest.php +++ b/Tests/Acceptance/AddSimpleProductWithStockHandlingToCartCest.php @@ -30,20 +30,18 @@ public function testAddDifferentItemsWithinAvailableAmountToCart(Tester $I): voi $I->see('Item was added to cart.', '#product-1 .form-message .form-success'); $I->dontSeeElement('#product-1 .form-message .form-error'); - $I->wait(3); - $I->dontSeeElement('#product-1 .form-message .form-success'); - $I->dontSeeElement('#product-1 .form-message .form-error'); + $I->waitForElementNotVisible('#product-1 .form-message .form-success'); + $I->waitForElementNotVisible('#product-1 .form-message .form-error'); $I->fillField('tx_cart_cart[quantity]', 2); $I->click('#product-1.add-to-cart-form input.btn[type="submit"]'); $I->see('2 Items were added to cart.', '#product-1 .form-message .form-success'); $I->dontSeeElement('#product-1 .form-message .form-error'); - $I->wait(3); - $I->dontSeeElement('#product-1 .form-message .form-success'); - $I->dontSeeElement('#product-1 .form-message .form-error'); + $I->waitForElementNotVisible('#product-1 .form-message .form-success'); + $I->waitForElementNotVisible('#product-1 .form-message .form-error'); } public function testAddMoreItemsThanInStockOfASimpleProductToCart(Tester $I): void @@ -62,10 +60,8 @@ public function testAddMoreItemsThanInStockOfASimpleProductToCart(Tester $I): vo $I->dontSeeElement('#product-1 .form-message .form-success'); $I->see('Desired number of this item not available.', '#product-1 .form-message .form-error'); - $I->wait(3); - - $I->dontSeeElement('#product-1 .form-message .form-success'); - $I->dontSeeElement('#product-1 .form-message .form-error'); + $I->waitForElementNotVisible('#product-1 .form-message .form-success'); + $I->waitForElementNotVisible('#product-1 .form-message .form-error'); } public function testAddOneAndThanMoreItemsThanInStockOfASimpleProductToCart(Tester $I): void @@ -83,10 +79,9 @@ public function testAddOneAndThanMoreItemsThanInStockOfASimpleProductToCart(Test $I->see('Item was added to cart.', '#product-1 .form-message .form-success'); $I->dontSeeElement('#product-1 .form-message .form-error'); - $I->wait(3); - $I->dontSeeElement('#product-1 .form-message .form-success'); - $I->dontSeeElement('#product-1 .form-message .form-error'); + $I->waitForElementNotVisible('#product-1 .form-message .form-success'); + $I->waitForElementNotVisible('#product-1 .form-message .form-error'); $I->fillField('tx_cart_cart[quantity]', 10); $I->click('#product-1.add-to-cart-form input.btn[type="submit"]'); @@ -94,9 +89,7 @@ public function testAddOneAndThanMoreItemsThanInStockOfASimpleProductToCart(Test $I->dontSeeElement('#product-1 .form-message .form-success'); $I->see('Desired number of this item not available.', '#product-1 .form-message .form-error'); - $I->wait(3); - - $I->dontSeeElement('#product-1 .form-message .form-success'); - $I->dontSeeElement('#product-1 .form-message .form-error'); + $I->waitForElementNotVisible('#product-1 .form-message .form-success'); + $I->waitForElementNotVisible('#product-1 .form-message .form-error'); } } diff --git a/Tests/Acceptance/AddSimpleProductWithoutStockHandlingToCartCest.php b/Tests/Acceptance/AddSimpleProductWithoutStockHandlingToCartCest.php index 8d4585cc..df2d2eb5 100644 --- a/Tests/Acceptance/AddSimpleProductWithoutStockHandlingToCartCest.php +++ b/Tests/Acceptance/AddSimpleProductWithoutStockHandlingToCartCest.php @@ -30,29 +30,26 @@ public function testAddDifferentItemsToCart(Tester $I): void $I->see('Item was added to cart.', '#product-2 .form-message .form-success'); $I->dontSeeElement('#product-2 .form-message .form-error'); - $I->wait(3); - $I->dontSeeElement('#product-2 .form-message .form-success'); - $I->dontSeeElement('#product-2 .form-message .form-error'); + $I->waitForElementNotVisible('#product-2 .form-message .form-success'); + $I->waitForElementNotVisible('#product-2 .form-message .form-error'); $I->fillField('tx_cart_cart[quantity]', 2); $I->click('#product-2.add-to-cart-form input.btn[type="submit"]'); $I->see('2 Items were added to cart.', '#product-2 .form-message .form-success'); $I->dontSeeElement('#product-2 .form-message .form-error'); - $I->wait(3); - $I->dontSeeElement('#product-2 .form-message .form-success'); - $I->dontSeeElement('#product-2 .form-message .form-error'); + $I->waitForElementNotVisible('#product-2 .form-message .form-success'); + $I->waitForElementNotVisible('#product-2 .form-message .form-error'); $I->fillField('tx_cart_cart[quantity]', 100); $I->click('#product-2.add-to-cart-form input.btn[type="submit"]'); $I->see('100 Items were added to cart.', '#product-2 .form-message .form-success'); $I->dontSeeElement('#product-2 .form-message .form-error'); - $I->wait(3); - $I->dontSeeElement('#product-2 .form-message .form-success'); - $I->dontSeeElement('#product-2 .form-message .form-error'); + $I->waitForElementNotVisible('#product-2 .form-message .form-success'); + $I->waitForElementNotVisible('#product-2 .form-message .form-error'); } } diff --git a/Tests/Fixtures/cart_products_test/Configuration/TypoScript/setup.typoscript b/Tests/Fixtures/cart_products_test/Configuration/TypoScript/setup.typoscript index 57404ed0..20801205 100644 --- a/Tests/Fixtures/cart_products_test/Configuration/TypoScript/setup.typoscript +++ b/Tests/Fixtures/cart_products_test/Configuration/TypoScript/setup.typoscript @@ -1,2 +1,6 @@ page = PAGE -page.10 < styles.content.get \ No newline at end of file +page.10 < styles.content.get + +plugin.tx_cartproducts { + view.partialRootPaths.1 = EXT:cart_products_test/Resources/Private/Partials/ +} diff --git a/Tests/Fixtures/cart_products_test/Resources/Private/Partials/Product/CartForm.html b/Tests/Fixtures/cart_products_test/Resources/Private/Partials/Product/CartForm.html new file mode 100644 index 00000000..292f6648 --- /dev/null +++ b/Tests/Fixtures/cart_products_test/Resources/Private/Partials/Product/CartForm.html @@ -0,0 +1,58 @@ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+
+
+ +