18 — Development and tests
For anyone working on yavi_core or a theme.
Repository layout
<distribution>/
├── config/sites/<id>/settings.yaml ← what the backend module writes
├── packages/
│ ├── yavi-core/ framework
│ └── yavi-lucerne/ theme
├── vendor/
└── init-yavi.sh local DDEV setupThe packages are wired in through a Composer path repository, so an edit in packages/ takes effect without reinstalling.
The everyday loop
# edit a template, SCSS file or PHP class
ddev exec vendor/bin/typo3 cache:flush
# reloadAlmost every "my change does nothing" is a missing cache flush: SCSS is compiled into a hashed file, Fluid templates are compiled, DI is compiled, and the importmap is only cache-busted per file change in Development context.
Tests
ddev composer test # everything
ddev exec php packages/yavi-core/Tests/run.php Unit # one suiteThe runner is dependency-free — no PHPUnit — and exits non-zero on failure, so it works as a pre-commit or CI gate. Tests/bootstrap.php attempts a full TYPO3 bootstrap and degrades to autoload-only when there is no database; tests that need the container report themselves as skipped instead of failing.
What the suites cover today:
| Area | Guards against |
|---|---|
| Licence | Cache trust, signature age, product scope |
| Settings | Every Layout field renders, maps to a CSS variable, survives the write path, and clears itself when set to the default |
| Tokens | Spacing -base inputs, radius factors vs lengths, the SCSS lists staying in sync across themes |
| Templates | No positive tabindex, every <iframe> has a title, every aria-labelledby points at an existing id |
| ViewHelpers | FormatText, InlineIcon, gradient seeds, corner radius parsing |
Note the assertion signature — the name comes first:
$this->assertSame('round trip: ' . $key, $expected, $actual);Adding a test
Put it in Tests/Unit/ or Tests/Integration/, name the class …Test, and name each test after the defect it protects against. A failure should tell the next person what broke, not merely that something did.
Build scripts
ddev exec php packages/yavi-core/Build/sync-theme-scss.php # regenerate every theme's SCSS lists
ddev exec php packages/yavi-core/Build/sync-theme-scss.php --check # fail on drift, used by the testsWhere things live
| You want to change | Look in |
|---|---|
| A content element's markup | yavi-core/Resources/Private/Templates/ContentElements/ |
| A shared building block | yavi-core/Resources/Private/Partials/ContentElements/ |
| Geometry of a component | yavi-core/Resources/Public/Scss/Structure/ |
| Colour and decoration | yavi-core/Resources/Public/Scss/Skin/ or the theme's Skin/ |
| A backend field | yavi-core/Configuration/TCA/Overrides/ |
| A site setting | yavi-core/Configuration/Sets/Full/settings.definitions.yaml |
| The backend module | yavi-core/Classes/Controller/Backend/ThemeSettingsController.php + Resources/Private/Templates/Backend/ThemeSettings.html |
| Its styling | yavi-core/Resources/Public/Vendor/Backend/Css/backend-module.css |
| Labels | yavi-core/Resources/Private/Language/ |
Adding a site setting
- Declare it in
settings.definitions.yamlwith a category, a label and a description. The description is not optional — a test enforces that every field explains itself and says more than its label. - Map it to a CSS custom property in
ThemeCssVariablesRenderer::CSS_VARIABLE_MAP— another test fails if a field cannot reach a variable. - Read the token in the SCSS with a fallback:
var(--my-token, <the theme's default>). - Flush the cache, run the tests.
Language files
| File | Contains |
|---|---|
Backend.xlf / de.Backend.xlf | TCA labels, backend module |
locallang.xlf / de.locallang.xlf | Frontend labels |
locallang_mod.xlf, locallang_be.xlf (+ de. variants) | Module and backend layout labels |
locallang_db.xlf / de.locallang_db.xlf | Form finisher labels |
Two rules that are easy to get wrong:
- A translation file is named
de.<file>.xlf.<file>.de.xlfis silently ignored. - A translation file needs
target-language="de"and a<target>per unit. A file with only<source>is not a translation.
Coding conventions in this codebase
- Comments explain why, not what. They are written in German in the source and read as prose, not as labels.
- No comments in Fluid templates or SCSS unless something genuinely surprising needs recording.
- One token, one meaning. Before adding a variable, check whether an existing one already owns that decision.
- Prefer deleting to deprecating. Dead preview templates, unused palettes and orphaned partials are removed, not kept "just in case".