Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,17 +61,17 @@ jobs:
working-directory: app/vendor/playwright-php/playwright/bin
run: npx --no-install playwright install-deps chromium

# Boots its own postgres in docker (tests/e2e/fixture.php), so there is no service to
# declare here. Linux only, and that is the whole story: the checks drive frankenphp
# and a headless chromium, never the native shell, so a second platform would re-run
# the same assertions — at 10x on macOS.
# Boots its own postgres and mysql in docker (tests/e2e/harness/fixture.php), so there is
# no service to declare here. Linux only, and that is the whole story: the scenarios drive
# frankenphp and a headless chromium, never the native shell, so a second platform would
# re-run the same assertions — at 10x on macOS.
- run: make e2e FRANKEN_ASSET=frankenphp-linux-x86_64

# A failed assertion names the check and the selector; the screenshot is the only way
# to see what the page actually looked like on a runner nobody was watching.
# A failed step names the scenario and the step; the picture and the HTML beside it are the
# only way to see what the page actually looked like on a runner nobody was watching.
- if: failure()
uses: actions/upload-artifact@v7
with:
name: e2e-screenshots
path: tests/e2e/screenshots
name: e2e-artifacts
path: tests/e2e/artifacts
if-no-files-found: ignore
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
# truth; the trees themselves are built by `mise run install`, not committed.
/node_modules
/app/vendor/
# e2e artifacts: screenshots the browser check writes.
/tests/e2e/screenshots/
# What a failed step left behind: the picture and the HTML of the page it failed on.
/tests/e2e/artifacts/
/app/adminer.php
/app/editor.php
/app/src/Settings/Plugins/available
Expand Down
43 changes: 26 additions & 17 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ else
EXE = .exe
endif

.PHONY: help install linux-deps fetch verify qa phpstan phpcs golangci biome security check check-app e2e i18n i18n-check build run dev editor debug demo down destroy bundle zip dist tarball windows deb logs serve clean checksums
.PHONY: help install linux-deps fetch verify qa phpstan phpcs golangci biome security check check-app e2e e2e-visual i18n i18n-check build run dev editor debug demo down destroy bundle zip dist tarball windows deb logs serve clean checksums

.DEFAULT_GOAL := help

Expand Down Expand Up @@ -305,13 +305,18 @@ qa: bin/frankenphp$(EXE) app/vendor i18n ## Run every static check (php, go, js
check: fetch app/vendor ## Boot the app, assert before-login behaviour (prefill, design, plugins)
./check.sh

# Browser end-to-end check: logs in, asserts the theme applies in light and dark, and
# writes screenshots to tests/e2e/screenshots/. Needs docker (a throwaway postgres) and
# the Playwright browser from `mise run install`. Kept out of `qa` because it is slow and
# needs docker; run it on its own.
e2e: fetch ## Browser check: login + theme in light and dark (needs docker)
# The end-to-end scenarios: Behat driving a real browser through the app, against a throwaway
# postgres and mysql in docker. app/vendor because behat and playwright live there. Kept out of
# `qa` because it is slow and needs docker; run it on its own. A failed step leaves the page it
# failed on in tests/e2e/artifacts/, which the workflow uploads.
e2e: fetch app/vendor ## Every scenario, against both drivers (needs docker)
mise run e2e

# The same, in a browser you can watch: this is how a scenario is written, and how a failing one
# is understood. `make e2e-visual SUITE=mysql` or `ARGS='--name "Sorting"'` narrows it down.
e2e-visual: fetch app/vendor ## The same, in a browser you can watch (needs docker)
mise run e2e-visual

##@ Build & run

# About reads these, so it can never disagree with what is actually bundled.
Expand Down Expand Up @@ -360,29 +365,33 @@ debug: build ## Run with Safari's Web Inspector attached
# a shipped build never auto-logs-in. `make down` kills the container when you are done.
# vendor/ because dev serves app/ and Latte renders from it. The seed drops and recreates,
# so re-running just refreshes the data.
# The postgres one is shared with the e2e (tests/e2e/harness/fixture.php names it), so `make demo`
# and a run reuse each other's database rather than each leaving one behind. DEMO_MYSQL is only
# ever started by the e2e; it is named here so `down` and `destroy` can clean up after it.
DEMO_PG = adminer-demo-pg
DEMO_MYSQL = adminer-demo-mysql

demo: build app/vendor ## Run against seeded demo data, opened logged in (needs docker)
@docker start $(DEMO_PG) >/dev/null 2>&1 || docker run -d --name $(DEMO_PG) \
-e POSTGRES_PASSWORD=demo -e POSTGRES_DB=demo -p 55432:5432 postgres:18-alpine >/dev/null
@echo "waiting for postgres ..." && until docker exec $(DEMO_PG) pg_isready -U postgres >/dev/null 2>&1; do sleep 1; done
@docker exec -i $(DEMO_PG) psql -U postgres -d demo -v ON_ERROR_STOP=1 < tests/e2e/seed.sql >/dev/null
@docker exec -i $(DEMO_PG) psql -U postgres -d demo -v ON_ERROR_STOP=1 < tests/e2e/seed/pgsql.sql >/dev/null
@echo "demo data ready on 127.0.0.1:55432 (postgres / demo / demo)"
ADMINER_DESKTOP_DEMO='pgsql 127.0.0.1:55432 postgres demo demo' ./build/adminer-desktop$(EXE) -dev

# Kill the demo database container `make demo` left running.
down: ## Stop the demo database container
-docker rm -f $(DEMO_PG)
# Kill the database containers `make demo` and the e2e left running.
down: ## Stop the demo database containers
-docker rm -f $(DEMO_PG) $(DEMO_MYSQL)

# The same, plus the anonymous volume postgres keeps its data in — which plain `rm -f` leaves
# behind, dangling and named after nothing. Reach for this when tests/e2e/seed.sql changed: the
# e2e fixture reuses a container that is already up and never reseeds, so a new table only
# reaches the database when one is created from scratch.
# The same, plus the anonymous volumes the databases keep their data in — which plain `rm -f`
# leaves behind, dangling and named after nothing. Rarely needed now that the fixture reseeds on
# every run: an edited seed reaches the database without this. Reach for it when a container is
# wedged, or to get the disk back.
#
# `rm -v` and not `volume prune`, which would take every other project's anonymous volumes on
# this machine with it — this removes the ones attached to our container and nothing else.
destroy: ## Remove the demo database container and its data volume
-docker rm -fv $(DEMO_PG)
# this machine with it — this removes the ones attached to our containers and nothing else.
destroy: ## Remove the demo database containers and their data volumes
-docker rm -fv $(DEMO_PG) $(DEMO_MYSQL)

# Same startup path as `run`, minus the window — so it works over ssh and in CI.
check-app: build
Expand Down
12 changes: 12 additions & 0 deletions app/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"license": "Apache-2.0",
"type": "project",
"require-dev": {
"behat/behat": "^3.32",
"dg/composer-cleaner": "^2.2",
"nette/tester": "^2.5",
"playwright-php/playwright": "^1.2",
Expand All @@ -25,5 +26,16 @@
"psr-4": {
"Desktop\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Desktop\\Tests\\": "../tests/e2e/bootstrap/"
}
},
"extra": {
"cleaner-ignore": {
"behat/behat": true,
"behat/gherkin": true
}
}
}
Loading