php artisan boost:add-skill wm/wm-package
Save this content to: .cursor/rules/test.md
# Trappole: test
Si applica quando scrivi o modifichi un test del package.
- **Il database di test del package è `wm_package`**, dichiarato in `phpunit.xml.dist`. Un
`phpunit.xml` locale ha la precedenza sul `.dist`: se lo crei senza le righe `DB_*`, la suite
punta al database dell'`.env` e `RefreshDatabase` lo svuota — è già successo su `forestas`
(oc:8182).
- **Un test che crea un'App con `native_app_deep_link_enabled = true` scrive sul registro SFTP
condiviso**: è la regola in cima, non una sfumatura (oc:8251).
- **Un test che non dichiara il `TestCase` giusto fallisce in silenzio**: package e consumer hanno
due `TestCase` diversi, e i consumer non registrano l'autoload del package. Il dettaglio è in
[docs/knowledge/testare-il-package.md](docs/knowledge/testare-il-package.md).
- Nelle Action invocate direttamente nei test `request()->user()` è **sempre `null`** (si bypassa
il kernel HTTP): si usa `auth()->user()`, identico in produzione (oc:8486).
- `Bus::fake()` non impedisce l'acquisizione del lock di un job `ShouldBeUnique`: gira in
`PendingDispatch::shouldDispatch()`, prima che il Dispatcher fake sostituisca quello vero. Se il
job ha `uniqueVia()` su Redis (es. `UpdateAppConfigJob`, `BuildAppPoisGeojsonJob`), un test sotto
`Bus::fake()` dipende comunque da Redis reale. Il `TestCase` del package mette lo store `redis`
su `array` per tutta la suite (`tests/TestCase.php`, oc:8660), ma da un consumer vale il
`TestCase` del consumer, che non lo fa: lì serve nel `setUp()`
`config(['cache.stores.redis.driver' => 'array'])` (oc:8564, oc:8677).
- `Bus::fake()` non onora `afterCommit()`: sotto fake un job accodato dopo il commit parte subito,
anche se la transazione va in rollback. Si verifica `$job->afterCommit === true`, non lo scarto
(oc:8571).
- `EcTrackFactory` valorizza `osmid` a caso nel 70% dei casi: un test che crea tracce con la factory
e non fissa `osmid` ottiene a caso una traccia OSM, con precedenze e catene diverse — passa
`'osmid' => null` (oc:8543).
- I test del package non registrano `ScoutServiceProvider`: `EngineManager` non è un singleton e un
engine registrato con `extend()` si perde alla chiamata successiva — registra il singleton nel
`setUp()` del test (oc:8543).
- I test in `tests/Unit/Services/EcTrackService/` non si lanciano per file singolo:
`AbstractEcTrackServiceTest` è nello spazio dei nomi `Tests\…`, che `autoload-dev` non mappa — usa
`vendor/bin/pest tests/Unit/Services/EcTrackService --filter=<Classe>` (oc:8543).
- Su `ArrayStore` `flush()` non libera i lock di `ShouldBeUnique`, che vivono in `$locks` e non in
`$storage`: per ripartire da zero in un test usa `app('cache')->forgetDriver('redis')` (oc:8660).
- I test del package non girano in nessuna CI: le testsuite dei consumer includono solo i loro
`tests/`, e la CI di wm-package fallisce a «Install dependencies» (al 06/10/2026 tutti gli ultimi
100 run, dal 23/06/2026: ricontrolla prima di contarci). Si lanciano a mano da un
consumer (`vendor/bin/pest wm-package/tests/...`), e lì il DB dipende dallo shard: maphub e
osm2cai2 non impostano `DB_DATABASE` in `phpunit.xml` e usano il DB del `.env`, forestas e
camminiditalia usano `forestas_testing`/`camminiditalia_testing`. Un test che usa tassonomie senza
crearle passa dove ci sono e fallisce dove mancano: crea nel test ciò che usa, con identifier
`prefisso-`.`uniqid()` dentro `DatabaseTransactions`, perché un identifier fisso già presente fa
scattare il controllo dei doppioni di `TaxonomyObserver` (oc:8675).
- **Il test di caratterizzazione di `MapRenderService::render()` confronta l'md5 del PNG**: su
un'altra versione di GD o libpng può fallire senza che il disegno sia cambiato. Se succede,
verifica l'immagine a occhio prima di aggiornare l'hash (oc:8702).
- **Un `Bus::fake([...])` dentro un test sostituisce quello globale di `tests/Pest.php`**, che rende
finto `UpdateUgcTrackDemStatsJob`: se il test salva una UgcTrack con `locations` e la lista non
contiene quel job, il job gira davvero e chiama il servizio DEM esterno. Aggiungilo sempre alla
lista (oc:8742).
- In un test Pest **non usare `$this->app` né `$this->options` come proprietà tue**: sono
l'applicazione di Testbench e le opzioni di Pest, e sovrascriverle rompe il teardown o dà un
`TypeError` (oc:8911).
- **`wasRecentlyCreated` resta `true` sull'istanza creata nel test**, anche con
`createQuietly()`: un test che verifica cosa succede al salvataggio di un modello esistente deve
salvare `$model->fresh()`, come avviene in Nova (oc:8911).
Si applica quando scrivi o modifichi un test del package.
wm_package, dichiarato in phpunit.xml.dist. Un
phpunit.xml locale ha la precedenza sul .dist: se lo crei senza le righe DB_*, la suite
punta al database dell'.env e RefreshDatabase lo svuota — è già successo su forestas
(oc:8182).native_app_deep_link_enabled = true scrive sul registro SFTP
condiviso: è la regola in cima, non una sfumatura (oc:8251).TestCase giusto fallisce in silenzio: package e consumer hanno
due TestCase diversi, e i consumer non registrano l'autoload del package. Il dettaglio è in
docs/knowledge/testare-il-package.md.request()->user() è sempre null (si bypassa
il kernel HTTP): si usa auth()->user(), identico in produzione (oc:8486).Bus::fake() non impedisce l'acquisizione del lock di un job ShouldBeUnique: gira in
PendingDispatch::shouldDispatch(), prima che il Dispatcher fake sostituisca quello vero. Se il
job ha uniqueVia() su Redis (es. UpdateAppConfigJob, BuildAppPoisGeojsonJob), un test sotto
Bus::fake() dipende comunque da Redis reale. Il TestCase del package mette lo store redis
su array per tutta la suite (tests/TestCase.php, oc:8660), ma da un consumer vale il
TestCase del consumer, che non lo fa: lì serve nel setUp()
config(['cache.stores.redis.driver' => 'array']) (oc:8564, oc:8677).Bus::fake() non onora afterCommit(): sotto fake un job accodato dopo il commit parte subito,
anche se la transazione va in rollback. Si verifica $job->afterCommit === true, non lo scarto
(oc:8571).EcTrackFactory valorizza osmid a caso nel 70% dei casi: un test che crea tracce con la factory
e non fissa osmid ottiene a caso una traccia OSM, con precedenze e catene diverse — passa
'osmid' => null (oc:8543).ScoutServiceProvider: EngineManager non è un singleton e un
engine registrato con extend() si perde alla chiamata successiva — registra il singleton nel
setUp() del test (oc:8543).tests/Unit/Services/EcTrackService/ non si lanciano per file singolo:
AbstractEcTrackServiceTest è nello spazio dei nomi Tests\…, che autoload-dev non mappa — usa
vendor/bin/pest tests/Unit/Services/EcTrackService --filter=<Classe> (oc:8543).ArrayStore flush() non libera i lock di ShouldBeUnique, che vivono in $locks e non in
$storage: per ripartire da zero in un test usa app('cache')->forgetDriver('redis') (oc:8660).tests/, e la CI di wm-package fallisce a «Install dependencies» (al 06/10/2026 tutti gli ultimi
100 run, dal 23/06/2026: ricontrolla prima di contarci). Si lanciano a mano da un
consumer (vendor/bin/pest wm-package/tests/...), e lì il DB dipende dallo shard: maphub e
osm2cai2 non impostano DB_DATABASE in phpunit.xml e usano il DB del .env, forestas e
camminiditalia usano forestas_testing/camminiditalia_testing. Un test che usa tassonomie senza
crearle passa dove ci sono e fallisce dove mancano: crea nel test ciò che usa, con identifier
prefisso-.uniqid() dentro DatabaseTransactions, perché un identifier fisso già presente fa
scattare il controllo dei doppioni di TaxonomyObserver (oc:8675).MapRenderService::render() confronta l'md5 del PNG: su
un'altra versione di GD o libpng può fallire senza che il disegno sia cambiato. Se succede,
verifica l'immagine a occhio prima di aggiornare l'hash (oc:8702).Bus::fake([...]) dentro un test sostituisce quello globale di tests/Pest.php, che rende
finto UpdateUgcTrackDemStatsJob: se il test salva una UgcTrack con locations e la lista non
contiene quel job, il job gira davvero e chiama il servizio DEM esterno. Aggiungilo sempre alla
lista (oc:8742).$this->app né $this->options come proprietà tue: sono
l'applicazione di Testbench e le opzioni di Pest, e sovrascriverle rompe il teardown o dà un
TypeError (oc:8911).wasRecentlyCreated resta true sull'istanza creata nel test, anche con
createQuietly(): un test che verifica cosa succede al salvataggio di un modello esistente deve
salvare $model->fresh(), come avviene in Nova (oc:8911).How can I help you explore Laravel packages today?