# Testing Automated tests cover the PHP API (`api/`, `handlers/`), shared libraries, and the admin SPA in `website/`. Legacy root PHP scripts and duplicate `api/*.php` files are **not** tested. ## Requirements - **PHP 8.x** with extensions: `pdo_sqlite`, `openssl`, `json` - **Composer** - **Node.js 20+** and npm ### PHP: enable SQLite (Windows) If `composer test` fails with `PDOException: could not find driver`, PDO has no SQLite driver loaded. Check: ```powershell php -r "print_r(PDO::getAvailableDrivers());" ``` You should see `sqlite` in the list. If not, edit the `php.ini` shown by `php --ini` and uncomment: ```ini extension=pdo_sqlite extension=sqlite3 ``` Restart the terminal, then run the check again. Winget’s PHP package uses a path like: `%LOCALAPPDATA%\Microsoft\WinGet\Packages\PHP.PHP.8.4_*\php.ini` ## One-time setup ```bash composer install npm install cd website && npm install && cd .. npx playwright install ``` ## Test database key Tests use a fixed master key (not for production): ```text QDB_MASTER_KEY=dGVzdC1tYXN0ZXIta2V5LXRoaXQtMzJieXRzIQ== ``` PHPUnit writes to `tests/var/uploads/`. Playwright and manual E2E seed `uploads/` via: ```bash php tests/bin/seed-test-db.php ``` ### Seeded accounts | Username | Password | Role | |-----------------|---------------|-------------| | testadmin | testpass123 | admin | | testsuper1 | testpass123 | supervisor | | testcoach1 | testpass123 | coach | | testmustchange | testpass123 | coach (must change password on first login) | Sample questionnaire ID: `questionnaire_test_demo` (active, with question `q1`). ## Run tests ### All suites From the repository root (PHPUnit, Vitest, then Playwright): ```bash npm run test ``` Alias: `npm run test:all`. ### PHP (unit + integration) ```bash composer test ``` Integration tests reset the database before **each** test method (isolated state; slightly slower). ### Website unit (Vitest) ```bash cd website && npm run test:unit ``` ### End-to-end (Playwright) Starts `php -S 127.0.0.1:8080 dev-router.php`, seeds the DB, then runs HTTP smoke tests and website UI tests. Detailed API behaviour is covered by PHPUnit; Playwright API tests are smoke + password-change flow only. ```bash npm run test:e2e ``` ### Continuous integration (Gitea Actions) Workflow: [`.gitea/workflows/tests.yml`](.gitea/workflows/tests.yml) — same three steps on push and pull request (`CI=true` for E2E so the dev server is always started fresh). **Prerequisites on your Gitea instance:** 1. **Enable Actions** in `app.ini`: ```ini [actions] ENABLED = true ``` 2. **Register an [act_runner](https://gitea.com/gitea/act_runner)** on a Linux host (needs Docker or host tools for Playwright system deps). Use a label that matches the workflow, e.g. `ubuntu-latest`: ```bash act_runner register --instance https://your-gitea.example --token act_runner daemon ``` 3. **Enable Actions** on this repository (Settings → Actions). 4. **Third-party actions** (`actions/checkout`, `setup-php`, `setup-node`) are fetched from GitHub by default (`DEFAULT_ACTIONS_URL = github`). On air-gapped instances, mirror those actions or switch the workflow to shell `apt`/`composer` installs. Gitea also reads `.github/workflows/` for migrated repos; this project uses **`.gitea/workflows/`** only to avoid duplicate runs. Interactive UI: ```bash npm run test:e2e:ui ``` ## Manual development server ```bash # Optional: seed test data into uploads/ php tests/bin/seed-test-db.php $env:QDB_MASTER_KEY="dGVzdC1tYXN0ZXIta2V5LXRoaXQtMzJieXRzIQ==" php -S 127.0.0.1:8080 dev-router.php ``` Open [http://127.0.0.1:8080/website/](http://127.0.0.1:8080/website/). ## Layout ```text .gitea/workflows/ Gitea Actions CI (tests.yml) tests/ PHPUnit (Unit/, Integration/, Support/) tests/fixtures/ schema.sql copy for tests website/tests/ Vitest unit tests e2e/api/ Playwright HTTP smoke tests (Android API) e2e/website/ Playwright browser tests (hash routes) ```