Canvas AI: add layout fixture support so page builder and template builder agent tests can run against a realistic layout
## Goal Create automated tests for the Canvas AI agents, so the manual testing otherwise needed every time an agent's system prompt changes can be avoided. ## Related issues This issue is one step toward that coverage. It builds on: - [#3579681 (closed)](https://git.drupalcode.org/project/canvas/-/work_items/3579681) — Added the `canvas_ai_agents_test` module and a framework to validate the YAML output produced by the page builder and template builder agents. - [#3582390 (closed)](https://git.drupalcode.org/project/canvas/-/work_items/3582390) — Added tests for the Canvas AI orchestrator agent. - [#3591516 (closed)](https://git.drupalcode.org/project/canvas/-/work_items/3591516) — The page builder and template builder agents both reason from the list of available components. To keep that list identical for everyone running the tests, this restricts the catalog to components from `canvas_test_sdc` (a module shipping many SDCs already used across Canvas tests). ## Problem The page builder and template builder agents also need the page's **current layout** — the component-tree JSON — to decide what to place and where. In normal use the Canvas UI sends this layout from the client to the back end, which holds it in tempstore. Under test there is no client, so the layout is never populated, and these agents cannot be tested against realistic page states. ## What this issue does Adds the infrastructure to supply that layout in tests, as fixtures: - **New `LayoutFixtureSubscriber`** — for a test targeting the page builder or template builder agent, it reads a `canvas_layout_fixture` token from the test, loads the named JSON fixture, and writes it into tempstore under the key the `get_current_layout` tool reads. The key is cleared once the test response is built. The token is required for these agents: a missing, absent, or invalid-JSON fixture fails the test loudly rather than running against an undefined layout. - **Updated `SubAgentResponseMockSubscriber`** — this subscriber returns a canned success response for Canvas sub-agent AI calls. That is correct for orchestrator tests, which only verify routing, but it would prevent page builder and template builder tests from executing their real tool chains. Mocking is now opt-in: it is enabled only when the test targets the orchestrator. When a test targets a sub-agent directly, that agent runs normally so its tool output can be asserted. Both subscribers are registered in `canvas_ai_agents_test.services.yml` with autowiring and autoconfiguration. ## Testing steps 1. Enable the `canvas_ai_agents_test` module. 2. Create `modules/canvas_ai/tests/modules/canvas_ai_agents_test/fixtures/page_layout/page-with-hero.json` with: ```json { "regions": { "content": { "nodePathPrefix": [ 0 ], "components": [ { "name": "sdc.canvas_test_sdc.my-hero", "uuid": "0904de51-02cc-4cc1-9c50-8ec655191615", "nodePath": [ 0, 0 ] } ] } } } ``` 3. Go to `/admin/config/ai/agents-test/import` and import the attached [test_page_builder_agent_test.yaml](/uploads/8ee22600e2257ad9f90a7965c2f8a280/test_page_builder_agent_test.yaml) It already carries `canvas_layout_fixture: page-with-hero` under its tokens section. 4. Run the imported test. 5. Expected: the `get_current_layout` tool returns the fixture contents (visible under **Agent Data** in the result), and the test passes. ![image.png](/uploads/10c16f96f7dc0e6740c132ab72c83d16/image.png){width=759 height=600} --- _This issue description was written with AI assistance._
issue