Skip to content

Testing

Per-plugin kernel tests (tests/src/Kernel/Plugin/AiFunctionCall/)

Each plugin has its own kernel test, exercising it in isolation with hand-built context values - including permission checks, error handling, and every documented code path:

  • CreateViewTest
  • CreateViewDisplayTest
  • ListViewTest
  • CreateViewHandlerTest
  • RemoveViewHandlerTest
  • UpdateViewHandlerOptionsTest
  • UpdateViewPluginsTest

Integration tests (tests/src/Kernel/Integration/)

These load the real shipped views_agent config entity and drive it through realistic workflows, rather than hand-building context on one plugin at a time:

  • ViewsAgentTest: Asserts every tool the agent declares resolves to a real plugin, then drives the full declared tool set (create/configure/list/remove) through one workflow, finishing with a real Views::preview() execution against real content.
  • CreateNonAdminViewTest / CreateAdminViewTest: Build a frontpage-style (public, filtered, sorted) and a content-listing-style (admin, unfiltered) view respectively, modeled on core's own views.view.frontpage.yml and views.view.content.yml, directly invoking each ai_agents_views:* plugin.
  • AgentWrapperViewTest: Drives the views_agent through the agent wrapper's recorded-state replay (AiAgentEntityWrapper::fromArray() + getToolResultsByPluginId(), the same mechanism ai_agents's own AiAgentEntityWrapperTest uses), loading a create-then-update workflow fixture under tests/assets/agent_states/. This does not call execute() on either replayed tool - see the class doc comment for what it does and doesn't prove.
  • AgentEchoAiViewTest: Drives the agent's real determineSolvability() tool-calling loop against the ai_test module's echoai provider through a scripted create-then-update workflow (create_view then update_view_plugins), fixtured across three turns under tests/resources/ai_test/requests/chat/. Unlike the replay test above, execute() genuinely runs for both tool calls - this is the one test that proves the full multi-step path a real LLM-driven run would take, end to end.

Each test sets up the required modules and environment, and verifies the plugin's behavior, including permission checks, error handling, and correct output.

Static analysis

A module-local phpstan.neon (level 1 + bleedingEdge.neon) is provided, with a small, scoped ignoreErrors list documenting Drupal-architecture false positives (e.g. plugin create() methods and $modules test properties flagged as dead code by shipmonk/dead-code-detector, since both are read reflectively rather than through a traceable call):

vendor/bin/phpstan analyse --configuration=modules/contrib/ai_agents_views/phpstan.neon