diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 18560f03..f180f51d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -48,6 +48,18 @@ jobs: HOST_PROJECT_PATH: ${{ github.workspace }} steps: - uses: actions/checkout@v4 + - name: Restore Composer cache + uses: actions/cache@v4 + with: + path: vendor + key: composer-${{ hashFiles('composer.lock') }} + restore-keys: composer- + - name: Restore npm cache + uses: actions/cache@v4 + with: + path: node_modules + key: npm-${{ hashFiles('package-lock.json') }} + restore-keys: npm- - name: Login to GitHub Container Registry uses: docker/login-action@v3 with: @@ -78,6 +90,18 @@ jobs: HOST_PROJECT_PATH: ${{ github.workspace }} steps: - uses: actions/checkout@v4 + - name: Restore Composer cache + uses: actions/cache@v4 + with: + path: vendor + key: composer-${{ hashFiles('composer.lock') }} + restore-keys: composer- + - name: Restore npm cache + uses: actions/cache@v4 + with: + path: node_modules + key: npm-${{ hashFiles('package-lock.json') }} + restore-keys: npm- - name: Login to GitHub Container Registry uses: docker/login-action@v3 with: @@ -105,6 +129,18 @@ jobs: HOST_PROJECT_PATH: ${{ github.workspace }} steps: - uses: actions/checkout@v4 + - name: Restore Composer cache + uses: actions/cache@v4 + with: + path: vendor + key: composer-${{ hashFiles('composer.lock') }} + restore-keys: composer- + - name: Restore npm cache + uses: actions/cache@v4 + with: + path: node_modules + key: npm-${{ hashFiles('package-lock.json') }} + restore-keys: npm- - name: Login to GitHub Container Registry uses: docker/login-action@v3 with: @@ -162,6 +198,18 @@ jobs: HOST_PROJECT_PATH: ${{ github.workspace }} steps: - uses: actions/checkout@v4 + - name: Restore Composer cache + uses: actions/cache@v4 + with: + path: vendor + key: composer-${{ hashFiles('composer.lock') }} + restore-keys: composer- + - name: Restore npm cache + uses: actions/cache@v4 + with: + path: node_modules + key: npm-${{ hashFiles('package-lock.json') }} + restore-keys: npm- - name: Login to GitHub Container Registry uses: docker/login-action@v3 with: @@ -172,6 +220,13 @@ jobs: run: docker pull ${{ env.APP_IMAGE }} - name: Start Docker services run: docker compose -f docker-compose.yml -f docker-compose.ci.yml up -d app mariadb + - name: Wait for MariaDB + run: | + for i in {1..30}; do + docker compose exec -T mariadb mariadb -uroot -psecret -e "SELECT 1" && break + echo "Waiting for MariaDB... ($i/30)" + sleep 2 + done - name: Install dependencies run: | docker compose exec -T app mise trust @@ -201,6 +256,18 @@ jobs: COMPOSE_FILES: -f docker-compose.yml -f docker-compose.ci.yml -f docker-compose.e2e.yml steps: - uses: actions/checkout@v4 + - name: Restore Composer cache + uses: actions/cache@v4 + with: + path: vendor + key: composer-${{ hashFiles('composer.lock') }} + restore-keys: composer- + - name: Restore npm cache + uses: actions/cache@v4 + with: + path: node_modules + key: npm-${{ hashFiles('package-lock.json') }} + restore-keys: npm- - name: Login to GitHub Container Registry uses: docker/login-action@v3 with: @@ -210,7 +277,7 @@ jobs: - name: Pull app image run: docker pull ${{ env.APP_IMAGE }} - name: Start E2E stack - run: docker compose ${{ env.COMPOSE_FILES }} up -d app nginx mariadb + run: docker compose ${{ env.COMPOSE_FILES }} up -d app messenger nginx mariadb - name: Wait for MariaDB run: | for i in $(seq 1 30); do @@ -244,6 +311,18 @@ jobs: docker compose ${{ env.COMPOSE_FILES }} exec -T app php bin/console doctrine:database:create --env=test docker compose ${{ env.COMPOSE_FILES }} exec -T app php bin/console doctrine:migrations:migrate --no-interaction --env=test docker compose ${{ env.COMPOSE_FILES }} exec -T app php bin/console app:e2e:create-user e2e@example.com --password=e2e-secret + - name: Restore Playwright deps cache + uses: actions/cache@v4 + with: + path: tests/End2End/node_modules + key: playwright-deps-${{ hashFiles('tests/End2End/package-lock.json') }} + restore-keys: playwright-deps- + - name: Restore Playwright browsers cache + uses: actions/cache@v4 + with: + path: /home/runner/.cache/ms-playwright + key: playwright-browsers-${{ hashFiles('tests/End2End/package-lock.json') }} + restore-keys: playwright-browsers- - name: Install Playwright run: | cd tests/End2End diff --git a/.mise/tasks/tests/e2e.sh b/.mise/tasks/tests/e2e.sh index 61d99dd7..22cca48f 100755 --- a/.mise/tasks/tests/e2e.sh +++ b/.mise/tasks/tests/e2e.sh @@ -13,7 +13,14 @@ echo "End-to-end tests (Playwright)" echo "BASE_URL=${BASE_URL}" echo +restore_dev_stack() { + echo "" + echo "Restoring dev stack (docker compose up -d)..." + docker compose up -d +} + if [ "${NO_START}" != "true" ]; then + trap restore_dev_stack EXIT echo "Starting stack with e2e override..." docker compose $COMPOSE_FILES up -d echo "Waiting for MariaDB..." @@ -48,6 +55,15 @@ echo "Installing Playwright dependencies (if needed)..." (cd tests/End2End && npx playwright install chromium 2>/dev/null || true) echo "Running Playwright tests..." +set +e (cd tests/End2End && BASE_URL="$BASE_URL" npx playwright test) +PLAYWRIGHT_EXIT=$? +set -e + +if [ $PLAYWRIGHT_EXIT -eq 0 ]; then + echo "E2E tests completed!" +else + echo "E2E tests failed (exit code $PLAYWRIGHT_EXIT)." +fi -echo "E2E tests completed!" +exit $PLAYWRIGHT_EXIT diff --git a/config/services.yaml b/config/services.yaml index d060cc6f..956828f4 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -25,6 +25,9 @@ parameters: photo_builder.openai_timeout_seconds: 120 llm_content_editor.simulate: "%env(bool:LLM_CONTENT_EDITOR_SIMULATE)%" + # E2E workspace fixture (used by SimulatedGitAdapter when APP_ENV=test) + e2e.workspace_fixture_path: "%kernel.project_dir%/tests/fixtures/e2e-workspace-template" + services: # default configuration for services in *this* file _defaults: @@ -106,6 +109,9 @@ services: App\RemoteContentAssets\Infrastructure\RemoteManifestFetcherInterface: class: App\RemoteContentAssets\Infrastructure\RemoteManifestFetcher + App\RemoteContentAssets\Infrastructure\S3AssetUploaderInterface: + class: App\RemoteContentAssets\Infrastructure\S3AssetUploader + # Remote content assets facade - metadata for remote images (dimensions, size, mime type), # manifest validation and fetching App\RemoteContentAssets\Facade\RemoteContentAssetsFacadeInterface: @@ -114,6 +120,7 @@ services: - "@App\\RemoteContentAssets\\Infrastructure\\RemoteImageInfoFetcherInterface" - "@App\\RemoteContentAssets\\Infrastructure\\RemoteManifestValidatorInterface" - "@App\\RemoteContentAssets\\Infrastructure\\RemoteManifestFetcherInterface" + - "@App\\RemoteContentAssets\\Infrastructure\\S3AssetUploaderInterface" # Sitebuilder-specific workspace tooling facade App\WorkspaceTooling\Facade\WorkspaceToolingFacadeInterface: @@ -210,3 +217,25 @@ services: App\LlmContentEditor\Facade\LlmContentEditorFacadeInterface: alias: App\LlmContentEditor\Facade\SwitchableLlmContentEditorFacade + +when@test: + services: + # E2E/test doubles: no external HTTP or git/GitHub calls + App\RemoteContentAssets\Infrastructure\RemoteManifestValidatorInterface: + class: App\RemoteContentAssets\TestHarness\SimulatedRemoteManifestValidator + + App\RemoteContentAssets\Infrastructure\S3AssetUploaderInterface: + class: App\RemoteContentAssets\TestHarness\SimulatedS3AssetUploader + + App\WorkspaceMgmt\Infrastructure\Adapter\GitAdapterInterface: + class: App\WorkspaceMgmt\TestHarness\SimulatedGitAdapter + arguments: + $workspaceFixturePath: "%e2e.workspace_fixture_path%" + $realGitAdapter: "@App\\WorkspaceMgmt\\Infrastructure\\Adapter\\GitCliAdapter" + + App\WorkspaceMgmt\Infrastructure\Adapter\GitHubAdapterInterface: + class: App\WorkspaceMgmt\TestHarness\SimulatedGitHubAdapter + + # E2E: no-op setup steps (priority so it is used instead of DefaultProjectSetupStepsProvider) + App\WorkspaceMgmt\TestHarness\E2eNoOpProjectSetupStepsProvider: + tags: [{ name: workspace_mgmt.setup_steps_provider, priority: 100 }] diff --git a/docker-compose.e2e.yml b/docker-compose.e2e.yml index e7f3d2b0..293ffe45 100644 --- a/docker-compose.e2e.yml +++ b/docker-compose.e2e.yml @@ -1,10 +1,14 @@ -# E2E override: run app in test env, nginx with test env and fixed port for Playwright. +# E2E override: run app and messenger in test env, nginx with test env and fixed port for Playwright. # Use: docker compose -f docker-compose.yml -f docker-compose.e2e.yml up -d services: app: environment: APP_ENV: test + messenger: + environment: + APP_ENV: test + nginx: ports: - "127.0.0.1:8080:80" diff --git a/src/ChatBasedContentEditor/Presentation/Resources/templates/chat_based_content_editor.twig b/src/ChatBasedContentEditor/Presentation/Resources/templates/chat_based_content_editor.twig index daaba15b..dc4af916 100644 --- a/src/ChatBasedContentEditor/Presentation/Resources/templates/chat_based_content_editor.twig +++ b/src/ChatBasedContentEditor/Presentation/Resources/templates/chat_based_content_editor.twig @@ -12,6 +12,7 @@ {% endif %}
{{ 'editor.input_label'|trans }}