Files
XC_VM/docs/en/guides/dev-workflow.md
T
rootandClaude Opus 5 d0458a8eeb test(e2e): drive the admin panel the way an administrator does
The Playwright suite only checked that pages render. It now performs the
administrator's work against a live test panel and asserts the panel's own
data after each step:

- catalogue: a stream category, a bouquet and a reseller package — created,
  renamed / edited, reopened, deleted;
- subscribers: a line with a bouquet (search, edit in the modal, disable /
  enable, ban / unban, delete), a MAG and an Enigma2 device;
- bulk: two lines selected with the header checkbox, disabled and deleted;
- resellers: created with credits, topped up, edited, disabled, deleted;
- block lists: an IP (RFC 5737 address — blocking adds an iptables rule), a
  user agent and an ISP;
- streams: a live stream added with a source and a server, started, running
  with codecs and the Resources column filled in, stopped, renamed, deleted;
- sign-in: a second administrator refused with a wrong password, signing in
  and out — a separate account, because every admin login re-hashes the
  password and ends that account's other sessions.

Records are named `e2e-<run>-…`; a teardown project sweeps whatever a run
leaves behind and nothing else. tools/create-admin.php provisions the
dedicated test administrator on the panel host.

The first runs found three save paths that answered an empty page (fixed in
f7bba5cb, fd13c940, ee2f586a). Against the test panel: 82 passed, 1 skipped
(no series to select).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016WDhDajBPziJwjWZcXnh6R
2026-09-16 14:39:39 +00:00

6.3 KiB

Development Workflow

How to set up the project locally, run the quality checks, and deploy code to a development server.


Local Setup

Prerequisites: PHP 8.1 (the codebase pins php: 8.1.33; newer majors are not supported) and Composer available locally.

The committed src/vendor/ is production-only, so the dev tools (PHPStan, phpcs) are not in the tree. Install them once from the committed lock:

make dev-tools          # = cd src && composer install

This adds the require-dev packages into src/vendor/. Never commit them — the committed vendor must stay production-only (composer install --no-dev). .gitignore keeps the dev packages out of git add, and a CI gate (check-vendor-prod-only) fails the build if one is ever committed.

Quality Checks

Run these before pushing — CI runs the same set:

Command Checks
make phpstan Static analysis against the committed baseline (fails only on NEW issues)
make cs Code style — import/namespace hygiene (phpcs + Slevomat)
make cs-fix Apply the style fixes in place
make gates PSR-4 regression gates (below)
php tests/phpunit.phar -c tests/phpunit.xml.dist Unit tests — see PHPUnit Setup
make e2e Browser tests against a live test panel — see End-to-End Tests
make rector Dry-run automated refactoring — see Automated Refactoring (Rector)

make phpstan and make cs need the dev tools — run make dev-tools first.

The PHPStan baseline lives at build/phpstan-baseline.neon — it freezes all pre-existing issues so only new ones fail CI. If you intentionally change the level or accept a batch of findings, regenerate it with make phpstan-baseline and commit the result. Don't regenerate it just to silence a real new error — fix the code.

make gates bundles three guards:

  • check-procedural-use — procedural / view files import every migrated class they use (PHP imports are positional, so the use must precede the usage);
  • verify-lb-archive — the Load Balancer build excludes privileged code (admin/reseller controllers, user/device domain, install/root commands) — see Build System (MAIN vs LB) for the exclusion boundary;
  • check-vendor-prod-only — no require-dev package is committed under src/vendor/.

End-to-End Tests

tests/e2e is a Playwright suite that drives the admin panel the way an administrator does: it creates categories, bouquets, packages, lines, devices, resellers, block-list entries and a live stream, edits them, starts and stops the stream, and deletes everything again. It needs a test panel (never production) and an admin account used only by the tests — every admin login re-hashes the password and signs out that account's other sessions.

Set XC_E2E_BASE_URL (the admin URL including the access code), XC_E2E_USER and XC_E2E_PASS, then run make e2e-install once and make e2e. The suite's README.md (in tests/e2e/) lists what each spec covers, how to provision the test account with tests/e2e/tools/create-admin.php, and what the tests change on the panel host.

Deploying Code to VDS via SFTP

For daily development, we recommend the SFTP extension for VS Code — edit locally, auto-upload on save.

Setup

Create .vscode/sftp.json:

[
    {
        "name": "My Dev VDS",
        "host": "YOUR_VDS_IP",
        "protocol": "sftp",
        "port": 22,
        "username": "root",
        "remotePath": "/home/xc_vm",
        "useTempFile": false,
        "uploadOnSave": true,
        "openSsh": false,
        "watcher": {
            "files": "**/*",
            "autoUpload": false,
            "autoDelete": true
        },
        "ignore": [
            ".vscode",
            ".git",
            ".gitattributes",
            ".gitignore",
            "update",
            "*pycache/",
            "*.gitkeep",
            "bin/",
            "config/",
            "tmp/"
        ],
        "context": "./src/",
        "profiles": {}
    },
    {
        "name": "My Dev VDS Tests",
        "host": "YOUR_VDS_IP",
        "protocol": "sftp",
        "port": 22,
        "username": "root",
        "remotePath": "/home/xc_vm/tests",
        "useTempFile": false,
        "uploadOnSave": true,
        "openSsh": false,
        "watcher": {
            "files": "**/*",
            "autoUpload": false,
            "autoDelete": true
        },
        "ignore": [
            ".vscode",
            ".git",
            ".gitattributes",
            ".gitignore",
            "tmp/",
            ".cache/"
        ],
        "context": "./tests/",
        "profiles": {}
    }
]

Key Settings

  • context: "./src/" — maps local src/ to remote /home/xc_vm/
  • context: "./tests/" — maps local tests/ to remote /home/xc_vm/tests/
  • uploadOnSave: true — every Ctrl+S pushes the file to VDS instantly
  • ignore — protects server-specific files (bin/, config/, tmp/)

⚠️ watcher.autoDelete: true — deleting a file locally deletes it on the VDS too. Handy for keeping the tree in sync, but a mis-deleted local file (or a bad rename) will remove the remote copy. Keep the ignore list tight, or set it to false if you don't want the watcher to propagate deletions.

Security: Use SSH keys instead of password. The .vscode/ directory is in .gitignore, so credentials won't leak to git.

How to sync the tests folder

  1. Add a second SFTP entry with context: "./tests/" and remotePath: "/home/xc_vm/tests".
  2. Save files under tests/ locally.
  3. The extension will upload them separately from src/ into /home/xc_vm/tests.
  4. This is required because tests are stored outside src/ and will not be uploaded by the main entry.

Workflow

  1. Open project in VS Code
  2. Edit any file under src/
  3. If you add a test, edit the file under tests/
  4. Save — the matching SFTP entry uploads the file to VDS
  5. Run the relevant test on VDS
  6. Commit to git as usual
File Role
.vscode/sftp.json Local → VDS sync config (gitignored)
Makefile make dev-tools, make phpstan, make cs, make gates
src/composer.json Dependencies + PSR-4 autoload