Initial commit
This commit is contained in:
154
templates/AGENTS.md
Normal file
154
templates/AGENTS.md
Normal file
@@ -0,0 +1,154 @@
|
||||
# Testing Context for AI Assistants
|
||||
|
||||
This directory contains tests for the TYPO3 extension.
|
||||
|
||||
## Test Type
|
||||
|
||||
**[Unit|Functional|Acceptance]** tests
|
||||
|
||||
## Test Strategy
|
||||
|
||||
<!-- Describe what this directory tests and why -->
|
||||
<!-- Example: "Unit tests for domain models - validates business logic without database" -->
|
||||
<!-- Example: "Functional tests for repositories - verifies database queries and persistence" -->
|
||||
<!-- Example: "Acceptance tests for checkout workflow - validates complete user journey from cart to payment" -->
|
||||
|
||||
**Scope:**
|
||||
|
||||
**Key Scenarios:**
|
||||
|
||||
**Not Covered:** <!-- What is intentionally not tested here -->
|
||||
|
||||
## Testing Framework
|
||||
|
||||
- **TYPO3 Testing Framework** (typo3/testing-framework)
|
||||
- **PHPUnit** for assertions and test execution
|
||||
- **[Additional tools for this test type]:**
|
||||
- Unit: Prophecy for mocking
|
||||
- Functional: CSV fixtures for database data
|
||||
- Acceptance: Codeception + Selenium for browser automation
|
||||
|
||||
## Test Structure
|
||||
|
||||
### Base Class
|
||||
|
||||
Tests in this directory extend:
|
||||
- **Unit**: `TYPO3\TestingFramework\Core\Unit\UnitTestCase`
|
||||
- **Functional**: `TYPO3\TestingFramework\Core\Functional\FunctionalTestCase`
|
||||
- **Acceptance**: Codeception Cest classes
|
||||
|
||||
### Naming Convention
|
||||
|
||||
- **Unit/Functional**: `*Test.php` (e.g., `ProductTest.php`, `ProductRepositoryTest.php`)
|
||||
- **Acceptance**: `*Cest.php` (e.g., `LoginCest.php`, `CheckoutCest.php`)
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### setUp() and tearDown()
|
||||
|
||||
```php
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
// Initialize test dependencies
|
||||
}
|
||||
|
||||
protected function tearDown(): void
|
||||
{
|
||||
// Clean up resources
|
||||
parent::tearDown();
|
||||
}
|
||||
```
|
||||
|
||||
### Assertions
|
||||
|
||||
Use specific assertions over generic ones:
|
||||
- `self::assertTrue()`, `self::assertFalse()` for booleans
|
||||
- `self::assertSame()` for strict equality
|
||||
- `self::assertInstanceOf()` for type checks
|
||||
- `self::assertCount()` for arrays/collections
|
||||
|
||||
### Fixtures (Functional Tests Only)
|
||||
|
||||
```php
|
||||
$this->importCSVDataSet(__DIR__ . '/../Fixtures/MyFixture.csv');
|
||||
```
|
||||
|
||||
**Fixture Files:** `Tests/Functional/Fixtures/`
|
||||
|
||||
**Strategy:**
|
||||
- Keep fixtures minimal (only required data)
|
||||
- One fixture per test scenario
|
||||
- Document fixture contents in test or below
|
||||
|
||||
### Mocking (Unit Tests Only)
|
||||
|
||||
```php
|
||||
use Prophecy\PhpUnit\ProphecyTrait;
|
||||
|
||||
$repository = $this->prophesize(UserRepository::class);
|
||||
$repository->findByEmail('test@example.com')->willReturn($user);
|
||||
```
|
||||
|
||||
## Running Tests
|
||||
|
||||
```bash
|
||||
# All tests in this directory
|
||||
composer ci:test:php:[unit|functional|acceptance]
|
||||
|
||||
# Via runTests.sh
|
||||
Build/Scripts/runTests.sh -s [unit|functional|acceptance]
|
||||
|
||||
# Specific test file
|
||||
vendor/bin/phpunit Tests/[Unit|Functional]/Path/To/TestFile.php
|
||||
|
||||
# Specific test method
|
||||
vendor/bin/phpunit --filter testMethodName
|
||||
```
|
||||
|
||||
## Fixtures Documentation (Functional Tests)
|
||||
|
||||
<!-- Document what each fixture contains -->
|
||||
|
||||
### `Fixtures/BasicProducts.csv`
|
||||
- 3 products in category 1
|
||||
- 2 products in category 2
|
||||
- All products visible and published
|
||||
|
||||
### `Fixtures/PageTree.csv`
|
||||
- Root page (uid: 1)
|
||||
- Products page (uid: 2, pid: 1)
|
||||
- Services page (uid: 3, pid: 1)
|
||||
|
||||
## Test Dependencies
|
||||
|
||||
<!-- List any special dependencies or requirements -->
|
||||
|
||||
- [ ] Database (functional tests only)
|
||||
- [ ] Docker (acceptance tests only)
|
||||
- [ ] Specific TYPO3 extensions: <!-- list if any -->
|
||||
- [ ] External services: <!-- list if any -->
|
||||
|
||||
## Common Issues
|
||||
|
||||
<!-- Document common test failures and solutions -->
|
||||
|
||||
**Database connection errors:**
|
||||
- Verify database driver configuration in `FunctionalTests.xml`
|
||||
- Check Docker database service is running
|
||||
|
||||
**Fixture import errors:**
|
||||
- Verify CSV format (proper escaping, matching table structure)
|
||||
- Check file paths are correct relative to test class
|
||||
|
||||
**Flaky tests:**
|
||||
- Use proper waits in acceptance tests (`waitForElement`)
|
||||
- Avoid timing dependencies in unit/functional tests
|
||||
- Ensure test independence (no shared state)
|
||||
|
||||
## Resources
|
||||
|
||||
- [Unit Testing Guide](~/.claude/skills/typo3-testing/references/unit-testing.md)
|
||||
- [Functional Testing Guide](~/.claude/skills/typo3-testing/references/functional-testing.md)
|
||||
- [Acceptance Testing Guide](~/.claude/skills/typo3-testing/references/acceptance-testing.md)
|
||||
- [TYPO3 Testing Documentation](https://docs.typo3.org/m/typo3/reference-coreapi/main/en-us/Testing/)
|
||||
36
templates/FunctionalTests.xml
Normal file
36
templates/FunctionalTests.xml
Normal file
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="../../vendor/phpunit/phpunit.xsd"
|
||||
bootstrap="FunctionalTestsBootstrap.php"
|
||||
cacheResult="false"
|
||||
beStrictAboutTestsThatDoNotTestAnything="true"
|
||||
beStrictAboutOutputDuringTests="true"
|
||||
failOnDeprecation="true"
|
||||
failOnNotice="true"
|
||||
failOnWarning="true"
|
||||
failOnRisky="true"
|
||||
colors="true">
|
||||
<testsuites>
|
||||
<testsuite name="Functional tests">
|
||||
<directory>../../Tests/Functional/</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<php>
|
||||
<const name="TYPO3_TESTING_FUNCTIONAL_REMOVE_ERROR_HANDLER" value="true" />
|
||||
<env name="TYPO3_CONTEXT" value="Testing"/>
|
||||
<env name="typo3DatabaseDriver" value="mysqli" force="true"/>
|
||||
<env name="typo3DatabaseHost" value="localhost" force="true"/>
|
||||
<env name="typo3DatabasePort" value="3306" force="true"/>
|
||||
<env name="typo3DatabaseName" value="typo3_test" force="true"/>
|
||||
<env name="typo3DatabaseUsername" value="root" force="true"/>
|
||||
<env name="typo3DatabasePassword" value="" force="true"/>
|
||||
</php>
|
||||
<coverage>
|
||||
<report>
|
||||
<clover outputFile="../../var/log/coverage/clover.xml"/>
|
||||
<html outputDirectory="../../var/log/coverage/html"/>
|
||||
<text outputFile="php://stdout" showOnlySummary="true"/>
|
||||
</report>
|
||||
</coverage>
|
||||
</phpunit>
|
||||
21
templates/FunctionalTestsBootstrap.php
Normal file
21
templates/FunctionalTestsBootstrap.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Bootstrap file for TYPO3 functional tests
|
||||
*
|
||||
* This file initializes the testing environment for functional tests.
|
||||
* It sets up the necessary directory structure and prepares the TYPO3 instance.
|
||||
*/
|
||||
|
||||
call_user_func(static function () {
|
||||
$testbase = new \TYPO3\TestingFramework\Core\Testbase();
|
||||
|
||||
// Define original root path
|
||||
$testbase->defineOriginalRootPath();
|
||||
|
||||
// Create necessary directories for test execution
|
||||
$testbase->createDirectory(ORIGINAL_ROOT . 'typo3temp/var/tests');
|
||||
$testbase->createDirectory(ORIGINAL_ROOT . 'typo3temp/var/transient');
|
||||
});
|
||||
26
templates/UnitTests.xml
Normal file
26
templates/UnitTests.xml
Normal file
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="../../vendor/phpunit/phpunit/phpunit.xsd"
|
||||
bootstrap="../../vendor/autoload.php"
|
||||
cacheResult="false"
|
||||
beStrictAboutTestsThatDoNotTestAnything="true"
|
||||
beStrictAboutOutputDuringTests="true"
|
||||
failOnDeprecation="true"
|
||||
failOnNotice="true"
|
||||
failOnWarning="true"
|
||||
failOnRisky="true"
|
||||
colors="true">
|
||||
<testsuites>
|
||||
<testsuite name="Unit tests">
|
||||
<directory>../../Tests/Unit/</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<coverage>
|
||||
<report>
|
||||
<clover outputFile="../../var/log/coverage/clover.xml"/>
|
||||
<html outputDirectory="../../var/log/coverage/html"/>
|
||||
<text outputFile="php://stdout" showOnlySummary="true"/>
|
||||
</report>
|
||||
</coverage>
|
||||
</phpunit>
|
||||
39
templates/docker/codeception.yml
Normal file
39
templates/docker/codeception.yml
Normal file
@@ -0,0 +1,39 @@
|
||||
paths:
|
||||
tests: Tests/Acceptance
|
||||
output: var/log/acceptance
|
||||
data: Tests/Acceptance/_data
|
||||
support: Tests/Acceptance/_support
|
||||
envs: Tests/Acceptance/_envs
|
||||
|
||||
actor_suffix: Tester
|
||||
|
||||
extensions:
|
||||
enabled:
|
||||
- Codeception\Extension\RunFailed
|
||||
|
||||
suites:
|
||||
acceptance:
|
||||
actor: AcceptanceTester
|
||||
path: .
|
||||
modules:
|
||||
enabled:
|
||||
- WebDriver:
|
||||
url: http://web:8000
|
||||
browser: chrome
|
||||
host: selenium
|
||||
port: 4444
|
||||
wait: 2
|
||||
window_size: 1920x1080
|
||||
capabilities:
|
||||
chromeOptions:
|
||||
args: ["--no-sandbox", "--disable-dev-shm-usage"]
|
||||
- \\Helper\\Acceptance
|
||||
config:
|
||||
WebDriver:
|
||||
browser: '%BROWSER%'
|
||||
|
||||
settings:
|
||||
shuffle: false
|
||||
lint: true
|
||||
colors: true
|
||||
memory_limit: 1024M
|
||||
51
templates/docker/docker-compose.yml
Normal file
51
templates/docker/docker-compose.yml
Normal file
@@ -0,0 +1,51 @@
|
||||
services:
|
||||
web:
|
||||
image: php:8.4-apache
|
||||
container_name: typo3-test-web
|
||||
volumes:
|
||||
- ../../../:/var/www/html
|
||||
ports:
|
||||
- "8000:80"
|
||||
environment:
|
||||
- TYPO3_CONTEXT=Testing
|
||||
- typo3DatabaseDriver=mysqli
|
||||
- typo3DatabaseHost=db
|
||||
- typo3DatabaseName=typo3_test
|
||||
- typo3DatabaseUsername=typo3
|
||||
- typo3DatabasePassword=typo3
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
networks:
|
||||
- typo3-test
|
||||
|
||||
db:
|
||||
image: mysql:8.0
|
||||
container_name: typo3-test-db
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: root
|
||||
MYSQL_DATABASE: typo3_test
|
||||
MYSQL_USER: typo3
|
||||
MYSQL_PASSWORD: typo3
|
||||
ports:
|
||||
- "3306:3306"
|
||||
healthcheck:
|
||||
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
networks:
|
||||
- typo3-test
|
||||
|
||||
selenium:
|
||||
image: selenium/standalone-chrome:latest
|
||||
container_name: typo3-test-selenium
|
||||
ports:
|
||||
- "4444:4444"
|
||||
shm_size: 2gb
|
||||
networks:
|
||||
- typo3-test
|
||||
|
||||
networks:
|
||||
typo3-test:
|
||||
driver: bridge
|
||||
87
templates/example-tests/ExampleAcceptanceCest.php
Normal file
87
templates/example-tests/ExampleAcceptanceCest.php
Normal file
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Vendor\Extension\Tests\Acceptance;
|
||||
|
||||
use Vendor\Extension\Tests\Acceptance\AcceptanceTester;
|
||||
|
||||
/**
|
||||
* Example acceptance test demonstrating TYPO3 testing patterns
|
||||
*
|
||||
* Acceptance tests use a real browser to test complete user workflows.
|
||||
* They verify frontend functionality and user interactions.
|
||||
*/
|
||||
final class LoginCest
|
||||
{
|
||||
public function _before(AcceptanceTester $I): void
|
||||
{
|
||||
// Runs before each test method
|
||||
// Setup: Import fixtures, reset state, etc.
|
||||
}
|
||||
|
||||
public function loginAsBackendUser(AcceptanceTester $I): void
|
||||
{
|
||||
// Navigate to login page
|
||||
$I->amOnPage('/typo3');
|
||||
|
||||
// Fill login form
|
||||
$I->fillField('username', 'admin');
|
||||
$I->fillField('password', 'password');
|
||||
|
||||
// Submit form
|
||||
$I->click('Login');
|
||||
|
||||
// Verify successful login
|
||||
$I->see('Dashboard');
|
||||
$I->seeInCurrentUrl('/typo3/module/dashboard');
|
||||
}
|
||||
|
||||
public function loginFailsWithInvalidCredentials(AcceptanceTester $I): void
|
||||
{
|
||||
$I->amOnPage('/typo3');
|
||||
|
||||
$I->fillField('username', 'admin');
|
||||
$I->fillField('password', 'wrong_password');
|
||||
$I->click('Login');
|
||||
|
||||
// Verify login failed
|
||||
$I->see('Login error');
|
||||
$I->seeInCurrentUrl('/typo3');
|
||||
}
|
||||
|
||||
public function searchesForProducts(AcceptanceTester $I): void
|
||||
{
|
||||
// Navigate to product listing
|
||||
$I->amOnPage('/products');
|
||||
|
||||
// Wait for page to load
|
||||
$I->waitForElement('.product-list', 5);
|
||||
|
||||
// Use search
|
||||
$I->fillField('#search', 'laptop');
|
||||
$I->click('Search');
|
||||
|
||||
// Wait for results
|
||||
$I->waitForElement('.search-results', 5);
|
||||
|
||||
// Verify search results
|
||||
$I->see('laptop', '.product-title');
|
||||
$I->seeNumberOfElements('.product-item', [1, 10]);
|
||||
}
|
||||
|
||||
public function addsProductToCart(AcceptanceTester $I): void
|
||||
{
|
||||
$I->amOnPage('/products/1');
|
||||
|
||||
// Click add to cart button
|
||||
$I->click('#add-to-cart');
|
||||
|
||||
// Wait for AJAX response
|
||||
$I->waitForElement('.cart-badge', 3);
|
||||
|
||||
// Verify cart updated
|
||||
$I->see('1', '.cart-badge');
|
||||
$I->see('Product added to cart');
|
||||
}
|
||||
}
|
||||
91
templates/example-tests/ExampleFunctionalTest.php
Normal file
91
templates/example-tests/ExampleFunctionalTest.php
Normal file
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Vendor\Extension\Tests\Functional\Domain\Repository;
|
||||
|
||||
use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
|
||||
use Vendor\Extension\Domain\Model\Product;
|
||||
use Vendor\Extension\Domain\Repository\ProductRepository;
|
||||
|
||||
/**
|
||||
* Example functional test demonstrating TYPO3 testing patterns
|
||||
*
|
||||
* Functional tests use a real database and full TYPO3 instance.
|
||||
* They test repositories, controllers, and integration scenarios.
|
||||
*/
|
||||
final class ProductRepositoryTest extends FunctionalTestCase
|
||||
{
|
||||
protected ProductRepository $subject;
|
||||
|
||||
/**
|
||||
* Extensions to load for this test
|
||||
*/
|
||||
protected array $testExtensionsToLoad = [
|
||||
'typo3conf/ext/my_extension',
|
||||
];
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
// Get repository from dependency injection container
|
||||
$this->subject = $this->get(ProductRepository::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function findsProductsByCategory(): void
|
||||
{
|
||||
// Import test data from CSV fixture
|
||||
$this->importCSVDataSet(__DIR__ . '/../Fixtures/Products.csv');
|
||||
|
||||
// Execute repository method
|
||||
$products = $this->subject->findByCategory(1);
|
||||
|
||||
// Assert results
|
||||
self::assertCount(3, $products);
|
||||
self::assertInstanceOf(Product::class, $products[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function findsVisibleProductsOnly(): void
|
||||
{
|
||||
$this->importCSVDataSet(__DIR__ . '/../Fixtures/ProductsWithHidden.csv');
|
||||
|
||||
$products = $this->subject->findAll();
|
||||
|
||||
// Only visible products should be returned
|
||||
self::assertCount(2, $products);
|
||||
|
||||
foreach ($products as $product) {
|
||||
self::assertFalse($product->isHidden());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function persistsNewProduct(): void
|
||||
{
|
||||
$this->importCSVDataSet(__DIR__ . '/../Fixtures/Pages.csv');
|
||||
|
||||
$product = new Product();
|
||||
$product->setTitle('New Product');
|
||||
$product->setPrice(19.99);
|
||||
$product->setPid(1);
|
||||
|
||||
$this->subject->add($product);
|
||||
|
||||
// Persist to database
|
||||
$this->persistenceManager->persistAll();
|
||||
|
||||
// Verify product was saved
|
||||
$savedProducts = $this->subject->findAll();
|
||||
self::assertCount(1, $savedProducts);
|
||||
self::assertSame('New Product', $savedProducts[0]->getTitle());
|
||||
}
|
||||
}
|
||||
66
templates/example-tests/ExampleUnitTest.php
Normal file
66
templates/example-tests/ExampleUnitTest.php
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Vendor\Extension\Tests\Unit\Domain\Validator;
|
||||
|
||||
use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
|
||||
use Vendor\Extension\Domain\Validator\EmailValidator;
|
||||
|
||||
/**
|
||||
* Example unit test demonstrating TYPO3 testing patterns
|
||||
*
|
||||
* Unit tests are fast, isolated tests without external dependencies.
|
||||
* They test individual components (validators, utilities, domain logic).
|
||||
*/
|
||||
final class EmailValidatorTest extends UnitTestCase
|
||||
{
|
||||
protected EmailValidator $subject;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
$this->subject = new EmailValidator();
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function validEmailPassesValidation(): void
|
||||
{
|
||||
$result = $this->subject->validate('user@example.com');
|
||||
|
||||
self::assertFalse($result->hasErrors());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function invalidEmailFailsValidation(): void
|
||||
{
|
||||
$result = $this->subject->validate('invalid-email');
|
||||
|
||||
self::assertTrue($result->hasErrors());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @dataProvider invalidEmailProvider
|
||||
*/
|
||||
public function rejectsInvalidEmails(string $email): void
|
||||
{
|
||||
$result = $this->subject->validate($email);
|
||||
|
||||
self::assertTrue($result->hasErrors(), "Email '$email' should be invalid");
|
||||
}
|
||||
|
||||
public static function invalidEmailProvider(): array
|
||||
{
|
||||
return [
|
||||
'missing @' => ['userexample.com'],
|
||||
'missing domain' => ['user@'],
|
||||
'empty string' => [''],
|
||||
'spaces' => ['user @example.com'],
|
||||
];
|
||||
}
|
||||
}
|
||||
215
templates/github-actions-tests.yml
Normal file
215
templates/github-actions-tests.yml
Normal file
@@ -0,0 +1,215 @@
|
||||
name: Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main, develop]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
name: PHP Lint
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
php: ['8.1', '8.2', '8.3', '8.4']
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup PHP ${{ matrix.php }}
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
|
||||
- name: Get Composer Cache Directory
|
||||
id: composer-cache
|
||||
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Cache Composer dependencies
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{ steps.composer-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
|
||||
restore-keys: ${{ runner.os }}-composer-
|
||||
|
||||
- name: Install dependencies
|
||||
run: composer install --no-progress --prefer-dist
|
||||
|
||||
- name: Run PHP linting
|
||||
run: composer ci:test:php:lint
|
||||
|
||||
phpstan:
|
||||
name: PHPStan (Latest PHP)
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: '8.4'
|
||||
|
||||
- name: Cache Composer dependencies
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.composer/cache
|
||||
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
|
||||
|
||||
- name: Install dependencies
|
||||
run: composer install --no-progress
|
||||
|
||||
- name: Run PHPStan
|
||||
run: composer ci:test:php:phpstan
|
||||
|
||||
security:
|
||||
name: Security Audit
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: '8.4'
|
||||
|
||||
- name: Cache Composer dependencies
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.composer/cache
|
||||
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
|
||||
|
||||
- name: Install dependencies
|
||||
run: composer install --no-progress
|
||||
|
||||
- name: Run Composer audit
|
||||
run: composer audit
|
||||
|
||||
cgl:
|
||||
name: Code Style
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: '8.4'
|
||||
|
||||
- name: Cache Composer dependencies
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.composer/cache
|
||||
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
|
||||
|
||||
- name: Install dependencies
|
||||
run: composer install --no-progress
|
||||
|
||||
- name: Check code style
|
||||
run: composer ci:test:php:cgl
|
||||
|
||||
unit:
|
||||
name: Unit Tests (PHP ${{ matrix.php }})
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
php: ['8.1', '8.2', '8.3', '8.4']
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup PHP ${{ matrix.php }}
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
coverage: xdebug
|
||||
|
||||
- name: Cache Composer dependencies
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.composer/cache
|
||||
key: ${{ runner.os }}-php${{ matrix.php }}-composer-${{ hashFiles('**/composer.lock') }}
|
||||
|
||||
- name: Install dependencies
|
||||
run: composer install --no-progress
|
||||
|
||||
- name: Run unit tests
|
||||
run: composer ci:test:php:unit
|
||||
|
||||
- name: Upload coverage to Codecov
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
files: ./var/log/coverage/clover.xml
|
||||
flags: unittests
|
||||
name: unit-tests-php-${{ matrix.php }}
|
||||
|
||||
functional:
|
||||
name: Functional Tests (PHP ${{ matrix.php }}, ${{ matrix.database }})
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
php: ['8.1', '8.2', '8.3', '8.4']
|
||||
database: ['mysqli', 'pdo_mysql', 'postgres', 'sqlite']
|
||||
exclude:
|
||||
# Reduce matrix for faster execution
|
||||
- php: '8.2'
|
||||
database: 'pdo_mysql'
|
||||
- php: '8.3'
|
||||
database: 'postgres'
|
||||
- php: '8.4'
|
||||
database: 'pdo_mysql'
|
||||
|
||||
services:
|
||||
mysql:
|
||||
image: mysql:8.0
|
||||
env:
|
||||
MYSQL_ROOT_PASSWORD: root
|
||||
MYSQL_DATABASE: typo3_test
|
||||
ports:
|
||||
- 3306:3306
|
||||
options: >-
|
||||
--health-cmd="mysqladmin ping"
|
||||
--health-interval=10s
|
||||
--health-timeout=5s
|
||||
--health-retries=3
|
||||
|
||||
postgres:
|
||||
image: postgres:15
|
||||
env:
|
||||
POSTGRES_PASSWORD: postgres
|
||||
POSTGRES_DB: typo3_test
|
||||
ports:
|
||||
- 5432:5432
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup PHP ${{ matrix.php }}
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
extensions: ${{ matrix.database == 'postgres' && 'pdo_pgsql' || 'mysqli' }}
|
||||
|
||||
- name: Cache Composer dependencies
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.composer/cache
|
||||
key: ${{ runner.os }}-php${{ matrix.php }}-composer-${{ hashFiles('**/composer.lock') }}
|
||||
|
||||
- name: Install dependencies
|
||||
run: composer install --no-progress
|
||||
|
||||
- name: Run functional tests
|
||||
env:
|
||||
typo3DatabaseDriver: ${{ matrix.database }}
|
||||
typo3DatabaseHost: 127.0.0.1
|
||||
typo3DatabaseName: typo3_test
|
||||
typo3DatabaseUsername: ${{ matrix.database == 'postgres' && 'postgres' || 'root' }}
|
||||
typo3DatabasePassword: ${{ matrix.database == 'postgres' && 'postgres' || 'root' }}
|
||||
run: composer ci:test:php:functional
|
||||
Reference in New Issue
Block a user