Skip to content

Commit e7406a1

Browse files
committed
Complete CwaFixtureBuilder: fix route ordering and expand test coverage
- Add orderedRouteSpecs to track page/pageData specs in registration order so phaseThree() always processes parent routes before child routes - Explicitly persist auto-generated routes (don't rely solely on cascade) - Update CLAUDE.md status to reflect builder is implemented and tested - Expand unit tests to 17: cover named routes, template pages, template linking, component positions, pageDataProperty positions, and both parent-before-child ordering cases
1 parent 41002b6 commit e7406a1

3 files changed

Lines changed: 342 additions & 108 deletions

File tree

CLAUDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ Implementation: `RouteChildren` + `RouteChildrenNode` DTOs, `RouteChildrenStateP
246246

247247
## Feature: CwaFixtureBuilder
248248

249-
> **Status: Design agreed, not yet implemented.**
249+
> **Status: Implemented and tested (unit tests in `tests/Fixture/CwaFixtureBuilderTest.php`).**
250250
251251
A fluent builder API that lets developers scaffold CWA website structure (layouts, pages, component groups, components, routes) in Doctrine fixture code with minimal boilerplate. The Doctrine Fixtures Bundle handles execution; this feature adds the ergonomic PHP API on top.
252252

src/Fixture/CwaFixtureBuilder.php

Lines changed: 50 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -36,19 +36,27 @@ class CwaFixtureBuilder
3636
private array $layoutBuilders = [];
3737

3838
/**
39-
* Each entry: ['builder' => PageBuilder, 'layoutRef' => string, 'route' => ?string, 'routeName' => ?string, 'isTemplate' => bool].
39+
* Each entry: ['builder' => PageBuilder, 'layoutRef' => string, 'route' => ?string, 'routeName' => ?string, 'isTemplate' => bool, 'type' => 'page'].
4040
*
4141
* @var array<string, array>
4242
*/
4343
private array $pageSpecs = [];
4444

4545
/**
46-
* Each entry: ['builder' => PageDataBuilder, 'templateRef' => ?string, 'route' => ?string, 'routeName' => ?string].
46+
* Each entry: ['builder' => PageDataBuilder, 'templateRef' => ?string, 'route' => ?string, 'routeName' => ?string, 'type' => 'pageData'].
4747
*
4848
* @var array<array>
4949
*/
5050
private array $pageDataSpecs = [];
5151

52+
/**
53+
* All page and pageData specs in registration order (parents before children).
54+
* Used in phaseThree() to ensure parent routes are created before child routes.
55+
*
56+
* @var array<array>
57+
*/
58+
private array $orderedRouteSpecs = [];
59+
5260
/** @var array<string, Route> */
5361
private array $namedRoutes = [];
5462

@@ -104,13 +112,16 @@ public function page(
104112
if (null !== $configure) {
105113
$configure($builder);
106114
}
107-
$this->pageSpecs[$ref] = [
115+
$spec = [
108116
'builder' => $builder,
109117
'layoutRef' => $layout,
110118
'route' => $route,
111119
'routeName' => $routeName,
112120
'isTemplate' => $isTemplate,
121+
'type' => 'page',
113122
];
123+
$this->pageSpecs[$ref] = $spec;
124+
$this->orderedRouteSpecs[] = $spec;
114125
}
115126

116127
return $this->pageSpecs[$ref]['builder'];
@@ -133,12 +144,15 @@ public function pageData(
133144
if (null !== $configure) {
134145
$configure($builder);
135146
}
136-
$this->pageDataSpecs[] = [
147+
$spec = [
137148
'builder' => $builder,
138149
'templateRef' => $template,
139150
'route' => $route,
140151
'routeName' => $routeName,
152+
'type' => 'pageData',
141153
];
154+
$this->pageDataSpecs[] = $spec;
155+
$this->orderedRouteSpecs[] = $spec;
142156

143157
return $builder;
144158
}
@@ -288,38 +302,40 @@ private function phaseTwo(): void
288302

289303
private function phaseThree(): void
290304
{
291-
foreach ($this->pageSpecs as $spec) {
292-
$page = $spec['builder']->getPage();
293-
if (null !== $spec['route']) {
294-
$route = $this->createExplicitRoute($spec['route'], $spec['routeName']);
295-
$route->setPage($page);
296-
$this->timestampedPersister->persistTimestampedFields($route, true);
297-
$this->manager->persist($route);
298-
if (null !== $spec['routeName']) {
299-
$this->namedRoutes[$spec['routeName']] = $route;
300-
}
301-
} elseif (!$spec['isTemplate']) {
302-
$route = $this->routeGenerator->create($page);
303-
if (null !== $spec['routeName'] && null !== $page->getRoute()) {
304-
$this->namedRoutes[$spec['routeName']] = $page->getRoute();
305-
}
306-
}
307-
}
308-
309-
foreach ($this->pageDataSpecs as $spec) {
310-
$pageData = $spec['builder']->getPageData();
311-
if (null !== $spec['route']) {
312-
$route = $this->createExplicitRoute($spec['route'], $spec['routeName']);
313-
$route->setPageData($pageData);
314-
$this->timestampedPersister->persistTimestampedFields($route, true);
315-
$this->manager->persist($route);
316-
if (null !== $spec['routeName']) {
317-
$this->namedRoutes[$spec['routeName']] = $route;
305+
foreach ($this->orderedRouteSpecs as $spec) {
306+
if ('page' === $spec['type']) {
307+
$page = $spec['builder']->getPage();
308+
if (null !== $spec['route']) {
309+
$route = $this->createExplicitRoute($spec['route'], $spec['routeName']);
310+
$route->setPage($page);
311+
$this->timestampedPersister->persistTimestampedFields($route, true);
312+
$this->manager->persist($route);
313+
if (null !== $spec['routeName']) {
314+
$this->namedRoutes[$spec['routeName']] = $route;
315+
}
316+
} elseif (!$spec['isTemplate']) {
317+
$route = $this->routeGenerator->create($page);
318+
$this->manager->persist($route);
319+
if (null !== $spec['routeName'] && null !== $page->getRoute()) {
320+
$this->namedRoutes[$spec['routeName']] = $page->getRoute();
321+
}
318322
}
319323
} else {
320-
$route = $this->routeGenerator->create($pageData);
321-
if (null !== $spec['routeName'] && null !== $pageData->getRoute()) {
322-
$this->namedRoutes[$spec['routeName']] = $pageData->getRoute();
324+
$pageData = $spec['builder']->getPageData();
325+
if (null !== $spec['route']) {
326+
$route = $this->createExplicitRoute($spec['route'], $spec['routeName']);
327+
$route->setPageData($pageData);
328+
$this->timestampedPersister->persistTimestampedFields($route, true);
329+
$this->manager->persist($route);
330+
if (null !== $spec['routeName']) {
331+
$this->namedRoutes[$spec['routeName']] = $route;
332+
}
333+
} else {
334+
$route = $this->routeGenerator->create($pageData);
335+
$this->manager->persist($route);
336+
if (null !== $spec['routeName'] && null !== $pageData->getRoute()) {
337+
$this->namedRoutes[$spec['routeName']] = $pageData->getRoute();
338+
}
323339
}
324340
}
325341
}

0 commit comments

Comments
 (0)