feat(dev): migrate local development from Valet to DDEV
Production Caddy/FPM setup (build/Dockerfile, docker-compose.yml) is untouched -- this only swaps the local dev stack. - .ddev/config.yaml: PHP 8.4, Node 20, sqlite (db container omitted), libreoffice/ghostscript/poppler/sqlite3 packages, Vite port 5173 via Traefik, post-start hooks bootstrap the app on every `ddev start`. - .ddev/commands/web/dev: custom `ddev dev` runs queue + pail + vite (mirror of old `composer dev`). - start_dev.sh / stop_dev.sh: rewritten as DDEV wrappers so devs can onboard without DDEV knowledge; --keep-ddev keeps containers up. - vite.config.js: HMR over WSS to https://pp-planer.ddev.site:5173. - playwright + auth.setup.ts: baseURL switched to https://pp-planer.ddev.site. - .env.example: APP_URL and CHURCHTOOLS_REDIRECT_URI use ddev.site. - composer: drop laravel/sail (replaced by DDEV). - package.json: add explicit "name" so host/container lockfiles match (container WORKDIR is /var/www/html, npm would otherwise pick "html" as project name). - tests/fixtures/propresenter/Test.pro: inline reference fixture; tests no longer depend on a sibling host directory. - AGENTS.md: docs rewritten for DDEV workflow.
This commit is contained in:
parent
49d557a184
commit
599b8635c9
17
.ddev/commands/web/dev
Executable file
17
.ddev/commands/web/dev
Executable file
|
|
@ -0,0 +1,17 @@
|
||||||
|
#!/bin/bash
|
||||||
|
## Description: Run Laravel dev workers (queue, log tail, vite) inside the web container.
|
||||||
|
## Usage: dev
|
||||||
|
## Example: ddev dev
|
||||||
|
## ProjectTypes: laravel
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
cd /var/www/html
|
||||||
|
|
||||||
|
exec npx --yes concurrently \
|
||||||
|
-c "#c4b5fd,#fb7185,#fdba74" \
|
||||||
|
--names=queue,logs,vite \
|
||||||
|
--kill-others \
|
||||||
|
"php artisan queue:listen --tries=1 --timeout=0" \
|
||||||
|
"php artisan pail --timeout=0" \
|
||||||
|
"npm run dev"
|
||||||
312
.ddev/config.yaml
Normal file
312
.ddev/config.yaml
Normal file
|
|
@ -0,0 +1,312 @@
|
||||||
|
name: pp-planer
|
||||||
|
type: laravel
|
||||||
|
docroot: public
|
||||||
|
php_version: "8.4"
|
||||||
|
webserver_type: nginx-fpm
|
||||||
|
xdebug_enabled: false
|
||||||
|
additional_hostnames: []
|
||||||
|
additional_fqdns: []
|
||||||
|
database:
|
||||||
|
type: mariadb
|
||||||
|
version: "11.8"
|
||||||
|
hooks:
|
||||||
|
post-start:
|
||||||
|
- composer: install --no-interaction
|
||||||
|
- exec: test -f .env || cp .env.example .env
|
||||||
|
- exec: grep -q '^APP_KEY=base64:' .env || php artisan key:generate
|
||||||
|
- exec: test -f database/database.sqlite || (touch database/database.sqlite && chmod 664 database/database.sqlite)
|
||||||
|
- exec: php artisan migrate --force
|
||||||
|
# Drop node_modules+lock if they were installed for a different platform
|
||||||
|
# (e.g. host was macOS but container is Linux — rollup native binary mismatch).
|
||||||
|
- exec: '[ ! -d node_modules ] || node -e ''require("rollup/dist/native")'' >/dev/null 2>&1 || rm -rf node_modules package-lock.json'
|
||||||
|
- exec: test -d node_modules || npm install
|
||||||
|
- exec: npm run build
|
||||||
|
omit_containers: [db]
|
||||||
|
webimage_extra_packages: [libreoffice, libreoffice-l10n-de, ghostscript, poppler-utils, sqlite3]
|
||||||
|
use_dns_when_possible: true
|
||||||
|
composer_version: "2"
|
||||||
|
disable_settings_management: true
|
||||||
|
web_environment: []
|
||||||
|
nodejs_version: "20"
|
||||||
|
corepack_enable: false
|
||||||
|
web_extra_exposed_ports:
|
||||||
|
- name: vite
|
||||||
|
container_port: 5173
|
||||||
|
http_port: 5172
|
||||||
|
https_port: 5173
|
||||||
|
|
||||||
|
# Key features of DDEV's config.yaml:
|
||||||
|
|
||||||
|
# name: <projectname> # Name of the project, automatically provides
|
||||||
|
# http://projectname.ddev.site and https://projectname.ddev.site
|
||||||
|
# If the name is omitted, the project will take the name of the enclosing directory,
|
||||||
|
# which is useful if you want to have a copy of the project side by side with this one.
|
||||||
|
|
||||||
|
# type: <projecttype> # asterios, backdrop, cakephp, codeigniter, craftcms, drupal, drupal6, drupal7, drupal8, drupal9, drupal10, drupal11, drupal12, generic, joomla, laravel, magento, magento2, php, shopware6, silverstripe, symfony, typo3, wordpress, wp-bedrock
|
||||||
|
# See https://docs.ddev.com/en/stable/users/quickstart/ for more
|
||||||
|
# information on the different project types
|
||||||
|
|
||||||
|
# docroot: <relative_path> # Relative path to the directory containing index.php.
|
||||||
|
|
||||||
|
# php_version: "8.4" # PHP version to use, "5.6" through "8.5"
|
||||||
|
|
||||||
|
# You can explicitly specify the webimage but this
|
||||||
|
# is not recommended, as the images are often closely tied to DDEV's' behavior,
|
||||||
|
# so this can break upgrades.
|
||||||
|
|
||||||
|
# webimage: <docker_image>
|
||||||
|
# It’s unusual to change this option, and we don’t recommend it without Docker experience and a good reason.
|
||||||
|
# Typically, this means additions to the existing web image using a .ddev/web-build/Dockerfile.*
|
||||||
|
|
||||||
|
# database:
|
||||||
|
# type: <dbtype> # mysql, mariadb, postgres
|
||||||
|
# version: <version> # database version, like "10.11" or "8.0"
|
||||||
|
# MariaDB versions can be 5.5-10.8, 10.11, 11.4, 11.8
|
||||||
|
# MySQL versions can be 5.5-8.0, 8.4
|
||||||
|
# PostgreSQL versions can be 9-18
|
||||||
|
|
||||||
|
# router_http_port: <port> # Port to be used for http (defaults to global configuration, usually 80)
|
||||||
|
# router_https_port: <port> # Port for https (defaults to global configuration, usually 443)
|
||||||
|
|
||||||
|
# xdebug_enabled: false # Set to true to enable Xdebug and "ddev start" or "ddev restart"
|
||||||
|
# Note that for most people the commands
|
||||||
|
# "ddev xdebug" to enable Xdebug and "ddev xdebug off" to disable it work better,
|
||||||
|
# as leaving Xdebug enabled all the time is a big performance hit.
|
||||||
|
|
||||||
|
# xhgui_http_port: "8143"
|
||||||
|
# xhgui_https_port: "8142"
|
||||||
|
# The XHGui ports can be changed from the default 8143 and 8142
|
||||||
|
# Very rarely used
|
||||||
|
|
||||||
|
# host_xhgui_port: "8142"
|
||||||
|
# Can be used to change the host binding port of the XHGui
|
||||||
|
# application. Rarely used; only when port conflict and
|
||||||
|
# bind_all_ports is used (normally with router disabled)
|
||||||
|
|
||||||
|
# xhprof_mode: [prepend|xhgui|global]
|
||||||
|
# Default is "xhgui"
|
||||||
|
|
||||||
|
# webserver_type: nginx-fpm, apache-fpm, generic
|
||||||
|
|
||||||
|
# timezone: Europe/Berlin
|
||||||
|
# If timezone is unset, DDEV will attempt to derive it from the host system timezone
|
||||||
|
# using the $TZ environment variable or the /etc/localtime symlink.
|
||||||
|
# This is the timezone used in the containers and by PHP;
|
||||||
|
# it can be set to any valid timezone,
|
||||||
|
# see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
|
||||||
|
# For example Europe/Dublin or MST7MDT
|
||||||
|
|
||||||
|
# composer_root: <relative_path>
|
||||||
|
# Relative path to the Composer root directory from the project root. This is
|
||||||
|
# the directory which contains the composer.json and where all Composer related
|
||||||
|
# commands are executed.
|
||||||
|
|
||||||
|
# composer_version: "2"
|
||||||
|
# You can set it to "" or "2" (default) for Composer v2
|
||||||
|
# to use the latest major version available at the time your container is built.
|
||||||
|
# It is also possible to use each other Composer version channel. This includes:
|
||||||
|
# - 2.2 (latest Composer LTS version)
|
||||||
|
# - stable
|
||||||
|
# - preview
|
||||||
|
# - snapshot
|
||||||
|
# Alternatively, an explicit Composer version may be specified, for example "2.2.18".
|
||||||
|
# To reinstall Composer after the image was built, run "ddev utility rebuild".
|
||||||
|
|
||||||
|
# nodejs_version: "24"
|
||||||
|
# change from the default system Node.js version to any other version.
|
||||||
|
# See https://docs.ddev.com/en/stable/users/configuration/config/#nodejs_version for more information
|
||||||
|
# and https://www.npmjs.com/package/n#specifying-nodejs-versions for the full documentation.
|
||||||
|
|
||||||
|
# corepack_enable: false
|
||||||
|
# Change to 'true' to 'corepack enable' and gain access to latest versions of yarn/pnpm
|
||||||
|
|
||||||
|
# additional_hostnames:
|
||||||
|
# - somename
|
||||||
|
# - someothername
|
||||||
|
# would provide http and https URLs for "somename.ddev.site"
|
||||||
|
# and "someothername.ddev.site".
|
||||||
|
|
||||||
|
# additional_fqdns:
|
||||||
|
# - example.com
|
||||||
|
# - sub1.example.com
|
||||||
|
# would provide http and https URLs for "example.com" and "sub1.example.com"
|
||||||
|
# Please take care with this because it can cause great confusion.
|
||||||
|
|
||||||
|
# upload_dirs: "custom/upload/dir"
|
||||||
|
#
|
||||||
|
# upload_dirs:
|
||||||
|
# - custom/upload/dir
|
||||||
|
# - ../private
|
||||||
|
#
|
||||||
|
# would set the destination paths for ddev import-files to <docroot>/custom/upload/dir
|
||||||
|
# When Mutagen is enabled this path is bind-mounted so that all the files
|
||||||
|
# in the upload_dirs don't have to be synced into Mutagen.
|
||||||
|
|
||||||
|
# disable_upload_dirs_warning: false
|
||||||
|
# If true, turns off the normal warning that says
|
||||||
|
# "You have Mutagen enabled and your 'php' project type doesn't have upload_dirs set"
|
||||||
|
|
||||||
|
# ddev_version_constraint: ""
|
||||||
|
# Example:
|
||||||
|
# ddev_version_constraint: ">= 1.24.8"
|
||||||
|
# This will enforce that the running ddev version is within this constraint.
|
||||||
|
# See https://github.com/Masterminds/semver#checking-version-constraints for
|
||||||
|
# supported constraint formats
|
||||||
|
|
||||||
|
# working_dir:
|
||||||
|
# web: /var/www/html
|
||||||
|
# db: /home
|
||||||
|
# would set the default working directory for the web and db services.
|
||||||
|
# These values specify the destination directory for ddev ssh and the
|
||||||
|
# directory in which commands passed into ddev exec are run.
|
||||||
|
|
||||||
|
# omit_containers: [db, ddev-ssh-agent]
|
||||||
|
# Currently only these containers are supported. Some containers can also be
|
||||||
|
# omitted globally in the ~/.ddev/global_config.yaml. Note that if you omit
|
||||||
|
# the "db" container, several standard features of DDEV that access the
|
||||||
|
# database container will be unusable. In the global configuration it is also
|
||||||
|
# possible to omit ddev-router, but not here.
|
||||||
|
|
||||||
|
# performance_mode: "global"
|
||||||
|
# DDEV offers performance optimization strategies to improve the filesystem
|
||||||
|
# performance depending on your host system. Should be configured globally.
|
||||||
|
#
|
||||||
|
# If set, will override the global config. Possible values are:
|
||||||
|
# - "global": uses the value from the global config.
|
||||||
|
# - "none": disables performance optimization for this project.
|
||||||
|
# - "mutagen": enables Mutagen for this project.
|
||||||
|
#
|
||||||
|
# See https://docs.ddev.com/en/stable/users/install/performance/#mutagen
|
||||||
|
|
||||||
|
# fail_on_hook_fail: False
|
||||||
|
# Decide whether 'ddev start' should be interrupted by a failing hook
|
||||||
|
|
||||||
|
# host_https_port: "59002"
|
||||||
|
# The host port binding for https can be explicitly specified. It is
|
||||||
|
# dynamic unless otherwise specified.
|
||||||
|
# This is not used by most people, most people use the *router* instead
|
||||||
|
# of the localhost port.
|
||||||
|
|
||||||
|
# host_webserver_port: "59001"
|
||||||
|
# The host port binding for the ddev-webserver can be explicitly specified. It is
|
||||||
|
# dynamic unless otherwise specified.
|
||||||
|
# This is not used by most people, most people use the *router* instead
|
||||||
|
# of the localhost port.
|
||||||
|
|
||||||
|
# host_db_port: "59002"
|
||||||
|
# The host port binding for the ddev-dbserver can be explicitly specified. It is dynamic
|
||||||
|
# unless explicitly specified.
|
||||||
|
|
||||||
|
# mailpit_http_port: "8025"
|
||||||
|
# mailpit_https_port: "8026"
|
||||||
|
# The Mailpit ports can be changed from the default 8025 and 8026
|
||||||
|
|
||||||
|
# host_mailpit_port: "8025"
|
||||||
|
# The mailpit port is not normally bound on the host at all, instead being routed
|
||||||
|
# through ddev-router, but it can be bound directly to localhost if specified here.
|
||||||
|
|
||||||
|
# webimage_extra_packages: ['php${DDEV_PHP_VERSION}-tidy', 'php${DDEV_PHP_VERSION}-yac']
|
||||||
|
# Extra Debian packages that are needed in the webimage can be added here
|
||||||
|
|
||||||
|
# dbimage_extra_packages: [netcat, telnet, sudo]
|
||||||
|
# Extra Debian packages that are needed in the dbimage can be added here
|
||||||
|
|
||||||
|
# use_dns_when_possible: true
|
||||||
|
# If the host has internet access and the domain configured can
|
||||||
|
# successfully be looked up, DNS will be used for hostname resolution
|
||||||
|
# instead of editing /etc/hosts
|
||||||
|
# Defaults to true
|
||||||
|
|
||||||
|
# project_tld: ddev.site
|
||||||
|
# The top-level domain used for project URLs
|
||||||
|
# The default "ddev.site" allows DNS lookup via a wildcard
|
||||||
|
|
||||||
|
# share_default_provider: ngrok
|
||||||
|
# The default share provider to use for "ddev share"
|
||||||
|
# Defaults to global configuration, usually "ngrok"
|
||||||
|
# Can be "ngrok" or "cloudflared" or the name of a custom provider from .ddev/share-providers/
|
||||||
|
|
||||||
|
# share_provider_args: --basic-auth username:pass1234
|
||||||
|
# Provide extra flags to the share provider script
|
||||||
|
# See https://docs.ddev.com/en/stable/users/configuration/config/#share_provider_args
|
||||||
|
|
||||||
|
# disable_settings_management: false
|
||||||
|
# If true, DDEV will not create CMS-specific settings files like
|
||||||
|
# Drupal's settings.php/settings.ddev.php or TYPO3's additional.php
|
||||||
|
# In this case the user must provide all such settings.
|
||||||
|
|
||||||
|
# You can inject environment variables into the web container with:
|
||||||
|
# web_environment:
|
||||||
|
# - SOMEENV=somevalue
|
||||||
|
# - SOMEOTHERENV=someothervalue
|
||||||
|
|
||||||
|
# no_project_mount: false
|
||||||
|
# (Experimental) If true, DDEV will not mount the project into the web container;
|
||||||
|
# the user is responsible for mounting it manually or via a script.
|
||||||
|
# This is to enable experimentation with alternate file mounting strategies.
|
||||||
|
# For advanced users only!
|
||||||
|
|
||||||
|
# bind_all_interfaces: false
|
||||||
|
# If true, host ports will be bound on all network interfaces,
|
||||||
|
# not the localhost interface only. This means that ports
|
||||||
|
# will be available on the local network if the host firewall
|
||||||
|
# allows it.
|
||||||
|
|
||||||
|
# default_container_timeout: 120
|
||||||
|
# The default time that DDEV waits for all containers to become ready can be increased from
|
||||||
|
# the default 120. This helps in importing huge databases, for example.
|
||||||
|
|
||||||
|
#web_extra_exposed_ports:
|
||||||
|
#- name: nodejs
|
||||||
|
# container_port: 3000
|
||||||
|
# http_port: 2999
|
||||||
|
# https_port: 3000
|
||||||
|
#- name: something
|
||||||
|
# container_port: 4000
|
||||||
|
# https_port: 4000
|
||||||
|
# http_port: 3999
|
||||||
|
# Allows a set of extra ports to be exposed via ddev-router
|
||||||
|
# Fill in all three fields even if you don’t intend to use the https_port!
|
||||||
|
# If you don’t add https_port, then it defaults to 0 and ddev-router will fail to start.
|
||||||
|
#
|
||||||
|
# The port behavior on the ddev-webserver must be arranged separately, for example
|
||||||
|
# using web_extra_daemons.
|
||||||
|
# For example, with a web app on port 3000 inside the container, this config would
|
||||||
|
# expose that web app on https://<project>.ddev.site:9999 and http://<project>.ddev.site:9998
|
||||||
|
# web_extra_exposed_ports:
|
||||||
|
# - name: myapp
|
||||||
|
# container_port: 3000
|
||||||
|
# http_port: 9998
|
||||||
|
# https_port: 9999
|
||||||
|
|
||||||
|
#web_extra_daemons:
|
||||||
|
#- name: "http-1"
|
||||||
|
# command: "/var/www/html/node_modules/.bin/http-server -p 3000"
|
||||||
|
# directory: /var/www/html
|
||||||
|
#- name: "http-2"
|
||||||
|
# command: "/var/www/html/node_modules/.bin/http-server /var/www/html/sub -p 3000"
|
||||||
|
# directory: /var/www/html
|
||||||
|
|
||||||
|
# override_config: false
|
||||||
|
# By default, config.*.yaml files are *merged* into the configuration
|
||||||
|
# But this means that some things can't be overridden
|
||||||
|
# For example, if you have 'use_dns_when_possible: true'' you can't override it with a merge
|
||||||
|
# and you can't erase existing hooks or all environment variables.
|
||||||
|
# However, with "override_config: true" in a particular config.*.yaml file,
|
||||||
|
# 'use_dns_when_possible: false' can override the existing values, and
|
||||||
|
# hooks:
|
||||||
|
# post-start: []
|
||||||
|
# or
|
||||||
|
# web_environment: []
|
||||||
|
# or
|
||||||
|
# additional_hostnames: []
|
||||||
|
# can have their intended affect. 'override_config' affects only behavior of the
|
||||||
|
# config.*.yaml file it exists in.
|
||||||
|
|
||||||
|
# Many DDEV commands can be extended to run tasks before or after the
|
||||||
|
# DDEV command is executed, for example "post-start", "post-import-db",
|
||||||
|
# "pre-composer", "post-composer"
|
||||||
|
# See https://docs.ddev.com/en/stable/users/extend/custom-commands/ for more
|
||||||
|
# information on the commands that can be extended and the tasks you can define
|
||||||
|
# for them. Example:
|
||||||
|
#hooks:
|
||||||
|
|
@ -2,7 +2,7 @@ APP_NAME="CTS Presenter"
|
||||||
APP_ENV=local
|
APP_ENV=local
|
||||||
APP_KEY=
|
APP_KEY=
|
||||||
APP_DEBUG=true
|
APP_DEBUG=true
|
||||||
APP_URL=http://cts-work.test
|
APP_URL=https://pp-planer.ddev.site
|
||||||
|
|
||||||
# Application Locale (German)
|
# Application Locale (German)
|
||||||
APP_LOCALE=de
|
APP_LOCALE=de
|
||||||
|
|
@ -74,7 +74,7 @@ CTS_API_TOKEN=CHANGEME
|
||||||
CHURCHTOOLS_URL=https://CHANGEME.church.tools
|
CHURCHTOOLS_URL=https://CHANGEME.church.tools
|
||||||
CHURCHTOOLS_CLIENT_ID=CHANGEME
|
CHURCHTOOLS_CLIENT_ID=CHANGEME
|
||||||
CHURCHTOOLS_CLIENT_SECRET=CHANGEME
|
CHURCHTOOLS_CLIENT_SECRET=CHANGEME
|
||||||
CHURCHTOOLS_REDIRECT_URI=http://cts-work.test/auth/churchtools/callback
|
CHURCHTOOLS_REDIRECT_URI=https://pp-planer.ddev.site/auth/churchtools/callback
|
||||||
|
|
||||||
# File Upload Configuration
|
# File Upload Configuration
|
||||||
# Maximum file size in bytes (default: 100MB)
|
# Maximum file size in bytes (default: 100MB)
|
||||||
|
|
@ -85,6 +85,7 @@ UPLOAD_TEMP_DIR=/tmp
|
||||||
TEST_CTS_USERNAME=
|
TEST_CTS_USERNAME=
|
||||||
TEST_CTS_PASSWORD=
|
TEST_CTS_PASSWORD=
|
||||||
|
|
||||||
# Docker: map FPM worker to host user (run `id -u` and `id -g`)
|
# Production Docker only: map FPM worker to host user (run `id -u` and `id -g`).
|
||||||
|
# Not used by DDEV local dev.
|
||||||
WWWUSER=1000
|
WWWUSER=1000
|
||||||
WWWGROUP=1000
|
WWWGROUP=1000
|
||||||
|
|
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -27,3 +27,4 @@ Thumbs.db
|
||||||
tests/e2e/.auth/
|
tests/e2e/.auth/
|
||||||
test-results/
|
test-results/
|
||||||
.dev.pid
|
.dev.pid
|
||||||
|
.dev.log
|
||||||
|
|
|
||||||
45
AGENTS.md
45
AGENTS.md
|
|
@ -113,40 +113,49 @@ ## Build, Test, Lint Commands
|
||||||
|
|
||||||
### pp-planer (Laravel App)
|
### pp-planer (Laravel App)
|
||||||
|
|
||||||
|
Local dev runs in **DDEV** (Docker). Site URL: `https://pp-planer.ddev.site`.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# First-time setup
|
# Easy onboarding wrappers (no DDEV knowledge required):
|
||||||
composer setup # install, .env, key:generate, migrate, npm install, npm build
|
./start_dev.sh # ddev start + spawns dev workers in background
|
||||||
|
./stop_dev.sh # stops workers and DDEV (use --keep-ddev to leave DDEV running)
|
||||||
|
|
||||||
# Dev server (Laravel + Vite + Queue + Logs)
|
# Or use DDEV directly:
|
||||||
composer dev
|
ddev start # composer install, key:generate, migrate, npm install, npm run build
|
||||||
|
ddev dev # queue + log tail + vite HMR (foreground)
|
||||||
|
ddev stop # stop the project
|
||||||
|
|
||||||
# Build frontend
|
# Open a shell inside the web container
|
||||||
npm run build
|
ddev ssh
|
||||||
|
|
||||||
# Run ALL PHP tests (206 tests, clears config cache first)
|
# Frontend
|
||||||
composer test
|
ddev npm run build
|
||||||
php artisan test
|
ddev npm run dev
|
||||||
|
|
||||||
|
# Run ALL PHP tests (clears config cache first)
|
||||||
|
ddev composer test
|
||||||
|
ddev exec php artisan test
|
||||||
|
|
||||||
# Single test file
|
# Single test file
|
||||||
php artisan test tests/Feature/ServiceControllerTest.php
|
ddev exec php artisan test tests/Feature/ServiceControllerTest.php
|
||||||
|
|
||||||
# Single test method
|
# Single test method
|
||||||
php artisan test --filter=test_service_kann_abgeschlossen_werden
|
ddev exec php artisan test --filter=test_service_kann_abgeschlossen_werden
|
||||||
|
|
||||||
# Test suite
|
# Test suite
|
||||||
php artisan test --testsuite=Feature
|
ddev exec php artisan test --testsuite=Feature
|
||||||
php artisan test --testsuite=Unit
|
ddev exec php artisan test --testsuite=Unit
|
||||||
|
|
||||||
# PHP formatting (Laravel Pint, default preset — no pint.json)
|
# PHP formatting (Laravel Pint, default preset — no pint.json)
|
||||||
./vendor/bin/pint
|
ddev exec ./vendor/bin/pint
|
||||||
./vendor/bin/pint --test # check only
|
ddev exec ./vendor/bin/pint --test # check only
|
||||||
|
|
||||||
# E2E tests (requires dev server at http://pp-planer.test)
|
# E2E tests (requires `ddev start` running; baseURL is https://pp-planer.ddev.site)
|
||||||
npx playwright test
|
npx playwright test
|
||||||
npx playwright test tests/e2e/service-list.spec.ts
|
npx playwright test tests/e2e/service-list.spec.ts
|
||||||
|
|
||||||
# Migrations
|
# Migrations
|
||||||
php artisan migrate
|
ddev exec php artisan migrate
|
||||||
```
|
```
|
||||||
|
|
||||||
### propresenter-work (Parser Module)
|
### propresenter-work (Parser Module)
|
||||||
|
|
@ -241,7 +250,7 @@ ### ProPresenter Parser Tests (PHPUnit 11)
|
||||||
|
|
||||||
### E2E Tests (Playwright)
|
### E2E Tests (Playwright)
|
||||||
|
|
||||||
- TypeScript in `tests/e2e/`, baseURL `http://pp-planer.test`
|
- TypeScript in `tests/e2e/`, baseURL `https://pp-planer.ddev.site` (HTTPS, `ignoreHTTPSErrors: true` set in `playwright.config.ts`)
|
||||||
- Auth via `auth.setup.ts` (XSRF token + `/dev-login` endpoint, saves state to `.auth/user.json`)
|
- Auth via `auth.setup.ts` (XSRF token + `/dev-login` endpoint, saves state to `.auth/user.json`)
|
||||||
- Selectors: `page.getByTestId('...')`, `page.getByText('...')`, `page.getByRole('...')`
|
- Selectors: `page.getByTestId('...')`, `page.getByText('...')`, `page.getByRole('...')`
|
||||||
- German text assertions: `await expect(page.getByText('Mit ChurchTools anmelden')).toBeVisible()`
|
- German text assertions: `await expect(page.getByText('Mit ChurchTools anmelden')).toBeVisible()`
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,6 @@
|
||||||
"laravel/breeze": "^2.3",
|
"laravel/breeze": "^2.3",
|
||||||
"laravel/pail": "^1.2.2",
|
"laravel/pail": "^1.2.2",
|
||||||
"laravel/pint": "^1.24",
|
"laravel/pint": "^1.24",
|
||||||
"laravel/sail": "^1.41",
|
|
||||||
"mockery/mockery": "^1.6",
|
"mockery/mockery": "^1.6",
|
||||||
"nunomaduro/collision": "^8.6",
|
"nunomaduro/collision": "^8.6",
|
||||||
"pestphp/pest": "^4.4",
|
"pestphp/pest": "^4.4",
|
||||||
|
|
|
||||||
148
composer.lock
generated
148
composer.lock
generated
|
|
@ -4,7 +4,7 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "9dbae3f5dca103e9a9aab8a5291791dd",
|
"content-hash": "424677667864ca1fffd6f4af9632aa92",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "5pm-hdh/churchtools-api",
|
"name": "5pm-hdh/churchtools-api",
|
||||||
|
|
@ -893,12 +893,12 @@
|
||||||
"version": "v7.0.3",
|
"version": "v7.0.3",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/firebase/php-jwt.git",
|
"url": "https://github.com/googleapis/php-jwt.git",
|
||||||
"reference": "28aa0694bcfdfa5e2959c394d5a1ee7a5083629e"
|
"reference": "28aa0694bcfdfa5e2959c394d5a1ee7a5083629e"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/firebase/php-jwt/zipball/28aa0694bcfdfa5e2959c394d5a1ee7a5083629e",
|
"url": "https://api.github.com/repos/googleapis/php-jwt/zipball/28aa0694bcfdfa5e2959c394d5a1ee7a5083629e",
|
||||||
"reference": "28aa0694bcfdfa5e2959c394d5a1ee7a5083629e",
|
"reference": "28aa0694bcfdfa5e2959c394d5a1ee7a5083629e",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
|
|
@ -946,8 +946,8 @@
|
||||||
"php"
|
"php"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/firebase/php-jwt/issues",
|
"issues": "https://github.com/googleapis/php-jwt/issues",
|
||||||
"source": "https://github.com/firebase/php-jwt/tree/v7.0.3"
|
"source": "https://github.com/googleapis/php-jwt/tree/v7.0.3"
|
||||||
},
|
},
|
||||||
"time": "2026-02-25T22:16:40+00:00"
|
"time": "2026-02-25T22:16:40+00:00"
|
||||||
},
|
},
|
||||||
|
|
@ -8244,69 +8244,6 @@
|
||||||
},
|
},
|
||||||
"time": "2026-02-10T20:00:20+00:00"
|
"time": "2026-02-10T20:00:20+00:00"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "laravel/sail",
|
|
||||||
"version": "v1.53.0",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/laravel/sail.git",
|
|
||||||
"reference": "e340eaa2bea9b99192570c48ed837155dbf24fbb"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/laravel/sail/zipball/e340eaa2bea9b99192570c48ed837155dbf24fbb",
|
|
||||||
"reference": "e340eaa2bea9b99192570c48ed837155dbf24fbb",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"illuminate/console": "^9.52.16|^10.0|^11.0|^12.0|^13.0",
|
|
||||||
"illuminate/contracts": "^9.52.16|^10.0|^11.0|^12.0|^13.0",
|
|
||||||
"illuminate/support": "^9.52.16|^10.0|^11.0|^12.0|^13.0",
|
|
||||||
"php": "^8.0",
|
|
||||||
"symfony/console": "^6.0|^7.0|^8.0",
|
|
||||||
"symfony/yaml": "^6.0|^7.0|^8.0"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"orchestra/testbench": "^7.0|^8.0|^9.0|^10.0|^11.0",
|
|
||||||
"phpstan/phpstan": "^2.0"
|
|
||||||
},
|
|
||||||
"bin": [
|
|
||||||
"bin/sail"
|
|
||||||
],
|
|
||||||
"type": "library",
|
|
||||||
"extra": {
|
|
||||||
"laravel": {
|
|
||||||
"providers": [
|
|
||||||
"Laravel\\Sail\\SailServiceProvider"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"Laravel\\Sail\\": "src/"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Taylor Otwell",
|
|
||||||
"email": "taylor@laravel.com"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "Docker files for running a basic Laravel application.",
|
|
||||||
"keywords": [
|
|
||||||
"docker",
|
|
||||||
"laravel"
|
|
||||||
],
|
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/laravel/sail/issues",
|
|
||||||
"source": "https://github.com/laravel/sail"
|
|
||||||
},
|
|
||||||
"time": "2026-02-06T12:16:02+00:00"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "mockery/mockery",
|
"name": "mockery/mockery",
|
||||||
"version": "1.6.12",
|
"version": "1.6.12",
|
||||||
|
|
@ -10750,81 +10687,6 @@
|
||||||
],
|
],
|
||||||
"time": "2024-10-20T05:08:20+00:00"
|
"time": "2024-10-20T05:08:20+00:00"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "symfony/yaml",
|
|
||||||
"version": "v8.0.6",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/symfony/yaml.git",
|
|
||||||
"reference": "5f006c50a981e1630bbb70ad409c5d85f9a716e0"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/5f006c50a981e1630bbb70ad409c5d85f9a716e0",
|
|
||||||
"reference": "5f006c50a981e1630bbb70ad409c5d85f9a716e0",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"php": ">=8.4",
|
|
||||||
"symfony/polyfill-ctype": "^1.8"
|
|
||||||
},
|
|
||||||
"conflict": {
|
|
||||||
"symfony/console": "<7.4"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"symfony/console": "^7.4|^8.0"
|
|
||||||
},
|
|
||||||
"bin": [
|
|
||||||
"Resources/bin/yaml-lint"
|
|
||||||
],
|
|
||||||
"type": "library",
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"Symfony\\Component\\Yaml\\": ""
|
|
||||||
},
|
|
||||||
"exclude-from-classmap": [
|
|
||||||
"/Tests/"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Fabien Potencier",
|
|
||||||
"email": "fabien@symfony.com"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Symfony Community",
|
|
||||||
"homepage": "https://symfony.com/contributors"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "Loads and dumps YAML files",
|
|
||||||
"homepage": "https://symfony.com",
|
|
||||||
"support": {
|
|
||||||
"source": "https://github.com/symfony/yaml/tree/v8.0.6"
|
|
||||||
},
|
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"url": "https://symfony.com/sponsor",
|
|
||||||
"type": "custom"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "https://github.com/fabpot",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "https://github.com/nicolas-grekas",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
|
||||||
"type": "tidelift"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"time": "2026-02-09T10:14:57+00:00"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "ta-tikoma/phpunit-architecture-test",
|
"name": "ta-tikoma/phpunit-architecture-test",
|
||||||
"version": "0.8.7",
|
"version": "0.8.7",
|
||||||
|
|
|
||||||
1018
package-lock.json
generated
1018
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -1,5 +1,6 @@
|
||||||
{
|
{
|
||||||
"$schema": "https://www.schemastore.org/package.json",
|
"$schema": "https://www.schemastore.org/package.json",
|
||||||
|
"name": "pp-planer",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,8 @@ export default defineConfig({
|
||||||
timeout: 5000,
|
timeout: 5000,
|
||||||
},
|
},
|
||||||
use: {
|
use: {
|
||||||
baseURL: 'http://pp-planer.test',
|
baseURL: 'https://pp-planer.ddev.site',
|
||||||
|
ignoreHTTPSErrors: true,
|
||||||
trace: 'on-first-retry',
|
trace: 'on-first-retry',
|
||||||
},
|
},
|
||||||
projects: [
|
projects: [
|
||||||
|
|
|
||||||
109
start_dev.sh
109
start_dev.sh
|
|
@ -3,7 +3,8 @@ set -euo pipefail
|
||||||
|
|
||||||
PROJECT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
PROJECT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
PID_FILE="$PROJECT_DIR/.dev.pid"
|
PID_FILE="$PROJECT_DIR/.dev.pid"
|
||||||
SITE_NAME="pp-planer"
|
LOG_FILE="$PROJECT_DIR/.dev.log"
|
||||||
|
SITE_URL="https://pp-planer.ddev.site"
|
||||||
cd "$PROJECT_DIR"
|
cd "$PROJECT_DIR"
|
||||||
|
|
||||||
GREEN='\033[0;32m'
|
GREEN='\033[0;32m'
|
||||||
|
|
@ -12,95 +13,59 @@ RED='\033[0;31m'
|
||||||
CYAN='\033[0;36m'
|
CYAN='\033[0;36m'
|
||||||
NC='\033[0m'
|
NC='\033[0m'
|
||||||
|
|
||||||
# ── Stale PID cleanup ──────────────────────────────────────
|
if ! command -v ddev >/dev/null 2>&1; then
|
||||||
if [ -f "$PID_FILE" ]; then
|
echo -e "${RED}✗ DDEV ist nicht installiert.${NC}"
|
||||||
ALL_DEAD=true
|
echo ""
|
||||||
while read -r PID; do
|
echo -e " Installieren mit Homebrew:"
|
||||||
if kill -0 "$PID" 2>/dev/null; then
|
echo -e " ${CYAN}brew install ddev/ddev/ddev${NC}"
|
||||||
ALL_DEAD=false
|
echo ""
|
||||||
break
|
echo -e " Doku: ${CYAN}https://ddev.readthedocs.io/${NC}"
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
done < <(tr ' ' '\n' < "$PID_FILE")
|
|
||||||
|
|
||||||
if [ "$ALL_DEAD" = true ]; then
|
if ! docker info >/dev/null 2>&1; then
|
||||||
echo -e "${YELLOW}▸ Verwaiste PID-Datei entfernt${NC}"
|
echo -e "${RED}✗ Docker läuft nicht.${NC}"
|
||||||
rm -f "$PID_FILE"
|
echo -e " Starte zuerst Docker Desktop / Colima / OrbStack."
|
||||||
else
|
exit 1
|
||||||
echo -e "${RED}Dev-Umgebung läuft bereits.${NC}"
|
fi
|
||||||
|
|
||||||
|
if [ -f "$PID_FILE" ]; then
|
||||||
|
if kill -0 "$(cat "$PID_FILE")" 2>/dev/null; then
|
||||||
|
echo -e "${RED}Dev-Worker laufen bereits (PID $(cat "$PID_FILE")).${NC}"
|
||||||
echo -e "Stoppe zuerst mit: ${CYAN}./stop_dev.sh${NC}"
|
echo -e "Stoppe zuerst mit: ${CYAN}./stop_dev.sh${NC}"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
echo -e "${YELLOW}▸ Verwaiste PID-Datei entfernt${NC}"
|
||||||
|
rm -f "$PID_FILE"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# ── Valet link ──────────────────────────────────────────────
|
echo -e "${YELLOW}▸ DDEV starten (composer install, key:generate, migrate, npm build) …${NC}"
|
||||||
echo -e "${YELLOW}▸ Valet-Link prüfen …${NC}"
|
ddev start
|
||||||
if [ ! -L "$HOME/.config/valet/Sites/$SITE_NAME" ]; then
|
echo -e " ${GREEN}✓${NC} DDEV läuft"
|
||||||
valet link "$SITE_NAME" 2>/dev/null
|
|
||||||
echo -e " ${GREEN}✓${NC} Valet-Link erstellt: ${SITE_NAME}.test"
|
|
||||||
else
|
|
||||||
echo -e " ${GREEN}✓${NC} Valet-Link vorhanden"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# ── Dependencies check ──────────────────────────────────────
|
echo -e "${YELLOW}▸ Dev-Worker im Hintergrund starten (queue + logs + vite HMR) …${NC}"
|
||||||
if [ ! -d "node_modules" ]; then
|
nohup ddev dev > "$LOG_FILE" 2>&1 &
|
||||||
echo -e "${YELLOW}▸ npm install …${NC}"
|
DEV_PID=$!
|
||||||
npm install --silent
|
sleep 1.5
|
||||||
echo -e " ${GREEN}✓${NC} Node-Module installiert"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -d "vendor" ]; then
|
if ! kill -0 "$DEV_PID" 2>/dev/null; then
|
||||||
echo -e "${YELLOW}▸ composer install …${NC}"
|
echo -e " ${RED}✗${NC} Dev-Worker konnten nicht gestartet werden"
|
||||||
composer install --quiet
|
echo -e " Logs: ${CYAN}cat $LOG_FILE${NC}"
|
||||||
echo -e " ${GREEN}✓${NC} Composer-Pakete installiert"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# ── APP_KEY check ───────────────────────────────────────────
|
|
||||||
if ! grep -q '^APP_KEY=base64:' .env 2>/dev/null; then
|
|
||||||
echo -e "${YELLOW}▸ APP_KEY generieren …${NC}"
|
|
||||||
php artisan key:generate --quiet
|
|
||||||
echo -e " ${GREEN}✓${NC} APP_KEY generiert"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# ── Migrate ─────────────────────────────────────────────────
|
|
||||||
echo -e "${YELLOW}▸ Migrations ausführen …${NC}"
|
|
||||||
php artisan migrate --force --quiet
|
|
||||||
echo -e " ${GREEN}✓${NC} Datenbank aktuell"
|
|
||||||
|
|
||||||
# ── Queue worker ────────────────────────────────────────────
|
|
||||||
echo -e "${YELLOW}▸ Queue-Worker starten …${NC}"
|
|
||||||
php artisan queue:listen --tries=1 --timeout=0 > /dev/null 2>&1 &
|
|
||||||
QUEUE_PID=$!
|
|
||||||
sleep 0.3
|
|
||||||
if kill -0 "$QUEUE_PID" 2>/dev/null; then
|
|
||||||
echo -e " ${GREEN}✓${NC} Queue-Worker (PID $QUEUE_PID)"
|
|
||||||
else
|
|
||||||
echo -e " ${RED}✗${NC} Queue-Worker konnte nicht gestartet werden"
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# ── Vite dev server ─────────────────────────────────────────
|
echo "$DEV_PID" > "$PID_FILE"
|
||||||
echo -e "${YELLOW}▸ Vite starten …${NC}"
|
echo -e " ${GREEN}✓${NC} Dev-Worker (PID $DEV_PID)"
|
||||||
npx --yes vite --port 5173 > /dev/null 2>&1 &
|
|
||||||
VITE_PID=$!
|
|
||||||
sleep 0.5
|
|
||||||
if kill -0 "$VITE_PID" 2>/dev/null; then
|
|
||||||
echo -e " ${GREEN}✓${NC} Vite (PID $VITE_PID)"
|
|
||||||
else
|
|
||||||
echo -e " ${RED}✗${NC} Vite konnte nicht gestartet werden"
|
|
||||||
kill "$QUEUE_PID" 2>/dev/null || true
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# ── Save PIDs ───────────────────────────────────────────────
|
|
||||||
echo "$QUEUE_PID $VITE_PID" > "$PID_FILE"
|
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${GREEN}═══════════════════════════════════════════════${NC}"
|
echo -e "${GREEN}═══════════════════════════════════════════════${NC}"
|
||||||
echo -e "${GREEN} Dev-Umgebung läuft!${NC}"
|
echo -e "${GREEN} Dev-Umgebung läuft!${NC}"
|
||||||
echo -e "${GREEN}═══════════════════════════════════════════════${NC}"
|
echo -e "${GREEN}═══════════════════════════════════════════════${NC}"
|
||||||
echo ""
|
echo ""
|
||||||
echo -e " App: ${CYAN}http://${SITE_NAME}.test${NC}"
|
echo -e " App: ${CYAN}${SITE_URL}${NC}"
|
||||||
echo -e " Vite: ${CYAN}http://localhost:5173${NC}"
|
echo -e " Vite: ${CYAN}${SITE_URL}:5173${NC}"
|
||||||
|
echo -e " Mail: ${CYAN}${SITE_URL}:8026${NC} (Mailpit)"
|
||||||
|
echo -e " Logs: ${CYAN}tail -f .dev.log${NC}"
|
||||||
echo ""
|
echo ""
|
||||||
echo -e " Stop: ${YELLOW}./stop_dev.sh${NC}"
|
echo -e " Stop: ${YELLOW}./stop_dev.sh${NC}"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
|
||||||
57
stop_dev.sh
57
stop_dev.sh
|
|
@ -3,34 +3,55 @@ set -euo pipefail
|
||||||
|
|
||||||
PROJECT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
PROJECT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
PID_FILE="$PROJECT_DIR/.dev.pid"
|
PID_FILE="$PROJECT_DIR/.dev.pid"
|
||||||
|
LOG_FILE="$PROJECT_DIR/.dev.log"
|
||||||
|
cd "$PROJECT_DIR"
|
||||||
|
|
||||||
GREEN='\033[0;32m'
|
GREEN='\033[0;32m'
|
||||||
RED='\033[0;31m'
|
RED='\033[0;31m'
|
||||||
YELLOW='\033[1;33m'
|
YELLOW='\033[1;33m'
|
||||||
|
CYAN='\033[0;36m'
|
||||||
NC='\033[0m'
|
NC='\033[0m'
|
||||||
|
|
||||||
if [ ! -f "$PID_FILE" ]; then
|
KEEP_DDEV=false
|
||||||
echo -e "${RED}Dev-Umgebung läuft nicht (keine PID-Datei).${NC}"
|
if [ "${1:-}" = "--keep-ddev" ]; then
|
||||||
|
KEEP_DDEV=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "$PID_FILE" ]; then
|
||||||
|
DEV_PID="$(cat "$PID_FILE")"
|
||||||
|
if kill -0 "$DEV_PID" 2>/dev/null; then
|
||||||
|
kill -TERM "$DEV_PID" 2>/dev/null || true
|
||||||
|
for _ in 1 2 3 4 5; do
|
||||||
|
kill -0 "$DEV_PID" 2>/dev/null || break
|
||||||
|
sleep 0.5
|
||||||
|
done
|
||||||
|
kill -0 "$DEV_PID" 2>/dev/null && kill -KILL "$DEV_PID" 2>/dev/null || true
|
||||||
|
echo -e " ${YELLOW}▸${NC} Dev-Worker (PID $DEV_PID) gestoppt"
|
||||||
|
else
|
||||||
|
echo -e " ${YELLOW}▸${NC} Dev-Worker waren bereits beendet"
|
||||||
|
fi
|
||||||
|
rm -f "$PID_FILE"
|
||||||
|
else
|
||||||
|
echo -e " ${YELLOW}▸${NC} Keine PID-Datei – keine laufenden Dev-Worker"
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -f "$LOG_FILE"
|
||||||
|
|
||||||
|
if [ "$KEEP_DDEV" = true ]; then
|
||||||
|
echo ""
|
||||||
|
echo -e "${GREEN}Dev-Worker gestoppt. DDEV läuft weiter.${NC}"
|
||||||
|
echo -e " Komplett stoppen: ${CYAN}ddev stop${NC}"
|
||||||
|
echo ""
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
STOPPED=0
|
if command -v ddev >/dev/null 2>&1; then
|
||||||
ALREADY_DEAD=0
|
echo -e "${YELLOW}▸ DDEV stoppen …${NC}"
|
||||||
|
ddev stop >/dev/null 2>&1 || true
|
||||||
while read -r PID; do
|
echo -e " ${GREEN}✓${NC} DDEV gestoppt"
|
||||||
if kill "$PID" 2>/dev/null; then
|
|
||||||
STOPPED=$((STOPPED + 1))
|
|
||||||
echo -e " ${YELLOW}▸${NC} Prozess $PID gestoppt"
|
|
||||||
else
|
|
||||||
ALREADY_DEAD=$((ALREADY_DEAD + 1))
|
|
||||||
fi
|
fi
|
||||||
done < <(tr ' ' '\n' < "$PID_FILE")
|
|
||||||
|
|
||||||
rm -f "$PID_FILE"
|
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
if [ "$ALREADY_DEAD" -gt 0 ]; then
|
echo -e "${GREEN}Dev-Umgebung komplett gestoppt.${NC}"
|
||||||
echo -e "${YELLOW} $ALREADY_DEAD Prozess(e) waren bereits beendet.${NC}"
|
echo -e " Tipp: ${CYAN}./stop_dev.sh --keep-ddev${NC} stoppt nur die Worker (DDEV bleibt an)"
|
||||||
fi
|
|
||||||
echo -e "${GREEN}Dev-Umgebung gestoppt. ($STOPPED Prozess(e) beendet)${NC}"
|
|
||||||
echo ""
|
echo ""
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ public function test_download_pro_roundtrip_import_export(): void
|
||||||
{
|
{
|
||||||
$user = User::factory()->create();
|
$user = User::factory()->create();
|
||||||
|
|
||||||
$sourcePath = base_path('../propresenter/doc/reference_samples/Test.pro');
|
$sourcePath = base_path('tests/fixtures/propresenter/Test.pro');
|
||||||
$file = new \Illuminate\Http\UploadedFile($sourcePath, 'Test.pro', 'application/octet-stream', null, true);
|
$file = new \Illuminate\Http\UploadedFile($sourcePath, 'Test.pro', 'application/octet-stream', null, true);
|
||||||
|
|
||||||
$importResponse = $this->actingAs($user)->postJson(route('api.songs.import-pro'), ['file' => $file]);
|
$importResponse = $this->actingAs($user)->postJson(route('api.songs.import-pro'), ['file' => $file]);
|
||||||
|
|
@ -93,7 +93,7 @@ public function test_download_pro_roundtrip_preserves_content(): void
|
||||||
$user = User::factory()->create();
|
$user = User::factory()->create();
|
||||||
|
|
||||||
// 1. Import the reference .pro file
|
// 1. Import the reference .pro file
|
||||||
$sourcePath = base_path('../propresenter/doc/reference_samples/Test.pro');
|
$sourcePath = base_path('tests/fixtures/propresenter/Test.pro');
|
||||||
$file = new \Illuminate\Http\UploadedFile($sourcePath, 'Test.pro', 'application/octet-stream', null, true);
|
$file = new \Illuminate\Http\UploadedFile($sourcePath, 'Test.pro', 'application/octet-stream', null, true);
|
||||||
|
|
||||||
$importResponse = $this->actingAs($user)->postJson(route('api.songs.import-pro'), ['file' => $file]);
|
$importResponse = $this->actingAs($user)->postJson(route('api.songs.import-pro'), ['file' => $file]);
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ final class ProFileImportTest extends TestCase
|
||||||
|
|
||||||
private function test_pro_file(): UploadedFile
|
private function test_pro_file(): UploadedFile
|
||||||
{
|
{
|
||||||
$sourcePath = base_path('../propresenter/doc/reference_samples/Test.pro');
|
$sourcePath = base_path('tests/fixtures/propresenter/Test.pro');
|
||||||
|
|
||||||
return new UploadedFile($sourcePath, 'Test.pro', 'application/octet-stream', null, true);
|
return new UploadedFile($sourcePath, 'Test.pro', 'application/octet-stream', null, true);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,24 +2,26 @@ import { test as setup, expect } from '@playwright/test';
|
||||||
|
|
||||||
const authFile = 'tests/e2e/.auth/user.json';
|
const authFile = 'tests/e2e/.auth/user.json';
|
||||||
|
|
||||||
|
const baseUrl = 'https://pp-planer.ddev.site';
|
||||||
|
|
||||||
setup('authenticate', async ({ page }) => {
|
setup('authenticate', async ({ page }) => {
|
||||||
// Navigate to login page to establish session cookies (incl. XSRF-TOKEN)
|
// Navigate to login page to establish session cookies (incl. XSRF-TOKEN)
|
||||||
await page.goto('http://pp-planer.test/login');
|
await page.goto(`${baseUrl}/login`);
|
||||||
|
|
||||||
// Get XSRF token from cookies for CSRF protection
|
// Get XSRF token from cookies for CSRF protection
|
||||||
const cookies = await page.context().cookies('http://pp-planer.test');
|
const cookies = await page.context().cookies(baseUrl);
|
||||||
const xsrfCookie = cookies.find((c) => c.name === 'XSRF-TOKEN');
|
const xsrfCookie = cookies.find((c) => c.name === 'XSRF-TOKEN');
|
||||||
const xsrfToken = decodeURIComponent(xsrfCookie?.value || '');
|
const xsrfToken = decodeURIComponent(xsrfCookie?.value || '');
|
||||||
|
|
||||||
// POST to dev-login route directly (bypasses Vue rendering dependency)
|
// POST to dev-login route directly (bypasses Vue rendering dependency)
|
||||||
await page.request.post('http://pp-planer.test/dev-login', {
|
await page.request.post(`${baseUrl}/dev-login`, {
|
||||||
headers: {
|
headers: {
|
||||||
'X-XSRF-TOKEN': xsrfToken,
|
'X-XSRF-TOKEN': xsrfToken,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// Navigate to dashboard to confirm login and load session
|
// Navigate to dashboard to confirm login and load session
|
||||||
await page.goto('http://pp-planer.test/dashboard');
|
await page.goto(`${baseUrl}/dashboard`);
|
||||||
await page.waitForURL('**/dashboard');
|
await page.waitForURL('**/dashboard');
|
||||||
|
|
||||||
// Save signed-in state
|
// Save signed-in state
|
||||||
|
|
|
||||||
BIN
tests/fixtures/propresenter/Test.pro
vendored
Normal file
BIN
tests/fixtures/propresenter/Test.pro
vendored
Normal file
Binary file not shown.
|
|
@ -25,12 +25,14 @@ export default defineConfig({
|
||||||
},
|
},
|
||||||
host: '0.0.0.0',
|
host: '0.0.0.0',
|
||||||
port: 5173,
|
port: 5173,
|
||||||
|
strictPort: true,
|
||||||
|
cors: {
|
||||||
|
origin: /^https?:\/\/(.+\.ddev\.site|localhost)(:\d+)?$/,
|
||||||
|
},
|
||||||
hmr: {
|
hmr: {
|
||||||
host: 'localhost',
|
host: 'pp-planer.ddev.site',
|
||||||
port: 5173,
|
protocol: 'wss',
|
||||||
|
clientPort: 5173,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// HMR: When using Herd, run `npm run build` to use production assets.
|
|
||||||
// The ws://localhost:5173 error occurs when dev assets are loaded without `npm run dev`.
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue