chore(dev): DDEV setup so the test suite actually runs
CI / test (push) Has been cancelled

Mirrors aqua-iq's pattern but adapted for pictureFrame's stack:
postgres 16, php 8.4, node 22, imagick + pcov via apt extras,
Mercure hub at https://pictureframe.ddev.site/.well-known/mercure,
and four custom commands — `ddev tests`, `ddev coverage`,
`ddev frontend` (vite HMR), `ddev worker`.

Also restores dev deps (DAMA, Doctrine fixtures, symfony/uid) that
got dropped during earlier composer reshuffles, and adds a separate
`db_test` connection in .env.test so DAMA's transactional isolation
doesn't share state with whatever dev is mid-experiment with.

Two test fixes the new env exposed:
  - RotationServiceTest::test_prioritize_never_shown_falls_through_when_all_shown
    needed uniquenessWindow=2 so the recent-window filter wipes the
    set and the fallback restores the full pool — otherwise window=1
    excluded the most-recently-served image and the assertion drifted.
  - DeviceImageControllerTest::test_locked_image_served_without_rotation_advance
    was asserting currentImage stays null on a lock poll, but the
    controller intentionally sets currentImage on the lock path so
    Home reflects the live frame state. Now asserts both the
    currentImage update AND that no DeviceImageHistory row was
    written (the actual rotation-bypass guarantee).

Backend coverage (full suite via `ddev coverage`): 89.08% lines /
92.24% methods / 74.36% classes — the first real number we've had.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-08 13:56:36 -04:00
parent b48ed73b4e
commit 2a8bf3895f
14 changed files with 602 additions and 13 deletions
+33 -1
View File
@@ -645,7 +645,7 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param;
* }>,
* },
* uid?: bool|array{ // Uid configuration
* enabled?: bool|Param, // Default: false
* enabled?: bool|Param, // Default: true
* default_uuid_version?: 7|6|4|1|Param, // Default: 7
* name_based_uuid_version?: 5|3|Param, // Default: 5
* name_based_uuid_namespace?: scalar|Param|null,
@@ -1452,6 +1452,33 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param;
* generate_final_classes?: bool|Param, // Default: true
* generate_final_entities?: bool|Param, // Default: false
* }
* @psalm-type DamaDoctrineTestConfig = array{
* enable_static_connection?: mixed, // Default: true
* enable_static_meta_data_cache?: bool|Param, // Default: true
* enable_static_query_cache?: bool|Param, // Default: true
* connection_keys?: list<mixed>,
* }
* @psalm-type MercureConfig = array{
* hubs?: array<string, array{ // Default: []
* url?: scalar|Param|null, // URL of the hub's publish endpoint
* public_url?: scalar|Param|null, // URL of the hub's public endpoint // Default: null
* jwt?: string|array{ // JSON Web Token configuration.
* value?: scalar|Param|null, // JSON Web Token to use to publish to this hub.
* provider?: scalar|Param|null, // The ID of a service to call to provide the JSON Web Token.
* factory?: scalar|Param|null, // The ID of a service to call to create the JSON Web Token.
* publish?: list<scalar|Param|null>,
* subscribe?: list<scalar|Param|null>,
* secret?: scalar|Param|null, // The JWT Secret to use.
* passphrase?: scalar|Param|null, // The JWT secret passphrase. // Default: ""
* algorithm?: scalar|Param|null, // The algorithm to use to sign the JWT // Default: "hmac.sha256"
* },
* jwt_provider?: scalar|Param|null, // Deprecated: The child node "jwt_provider" at path "mercure.hubs..jwt_provider" is deprecated, use "jwt.provider" instead. // The ID of a service to call to generate the JSON Web Token.
* bus?: scalar|Param|null, // Name of the Messenger bus where the handler for this hub must be registered. Default to the default bus if Messenger is enabled.
* }>,
* default_hub?: scalar|Param|null,
* default_cookie_lifetime?: int|Param, // Default lifetime of the cookie containing the JWT, in seconds. Defaults to the value of "framework.session.cookie_lifetime". // Default: null
* enable_profiler?: bool|Param, // Deprecated: The child node "enable_profiler" at path "mercure.enable_profiler" is deprecated. // Enable Symfony Web Profiler integration.
* }
* @psalm-type ConfigType = array{
* imports?: ImportsConfig,
* parameters?: ParametersConfig,
@@ -1463,6 +1490,7 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param;
* twig_extra?: TwigExtraConfig,
* security?: SecurityConfig,
* monolog?: MonologConfig,
* mercure?: MercureConfig,
* "when@dev"?: array{
* imports?: ImportsConfig,
* parameters?: ParametersConfig,
@@ -1477,6 +1505,7 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param;
* security?: SecurityConfig,
* monolog?: MonologConfig,
* maker?: MakerConfig,
* mercure?: MercureConfig,
* },
* "when@prod"?: array{
* imports?: ImportsConfig,
@@ -1489,6 +1518,7 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param;
* twig_extra?: TwigExtraConfig,
* security?: SecurityConfig,
* monolog?: MonologConfig,
* mercure?: MercureConfig,
* },
* "when@test"?: array{
* imports?: ImportsConfig,
@@ -1502,6 +1532,8 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param;
* twig_extra?: TwigExtraConfig,
* security?: SecurityConfig,
* monolog?: MonologConfig,
* dama_doctrine_test?: DamaDoctrineTestConfig,
* mercure?: MercureConfig,
* },
* ...<string, ExtensionType|array{ // extra keys must follow the when@%env% pattern or match an extension alias
* imports?: ImportsConfig,