Issue #3586324: Replace hardcoded admin path assertions in tests with...

Route-path test hardening

Problem

Production code in ai_context builds every admin link with Url::fromRoute(), but many tests asserted hardcoded URL strings (e.g. '/admin/config/ai/agents/debug?agent_id=' . $agent_id). When an upstream module moves a route — as ai_agents did in 1.3.2 by relocating agent URLs under /admin/config/ai/tools-automation/ — those tests fail even though ai_context behaves correctly, producing false negatives in CI on dependency updates unrelated to ai_context changes. #3586323 (closed) fixed one such assertion; this MR addresses the rest, plus the optional follow-ups from the issue (internal ai_context paths and outdated docs).

What was done

New shared test helpertests/src/Traits/AiContextRoutePathTrait.php provides getRoutePath(string $route_name, array $route_parameters = [], array $options = []): string, a thin wrapper around Url::fromRoute(...)->toString(), now used by 22 test classes (Functional, FunctionalJavascript, and Kernel — all have a container).

High priority — external-route assertions (paths owned by other modules)

  • AiContextAgentSettingsTest: all debug/explore assertions derive from ai_agents_debugger.form / ai_agents_explorer.explorer with the same ['query' => ['agent_id' => ...]] option production uses (AiContextAgentsForm.php), including the occurrences embedded in elementsCount() CSS selectors (a[href*="..."]).
  • AiContextAdminSettingsTest: the modules-filter link derives from system.modules_list with ['query' => ['filter' => 'ai_context_document_loader']], mirroring AiContextExtensionsController.
  • AiContextScopeLanguageTest / AiContextScopeTagTest (Kernel): manage-link URLs derive from entity.configurable_language.collection and entity.taxonomy_vocabulary.overview_form (with the AiContextScopeTag::VOCABULARY_ID parameter).
  • AiContextDocumentLoaderIntegrationFunctionalTest (submodule): derives from document_loader.settings_form and document_loader_mdx.dialog (route names verified in document_loader 2.0.x).
  • AiContextLanguageDetectorTraitTest (Unit): no path changes — a class docblock now documents that the admin-style paths are intentional fixture data (see decisions below).

Medium priority — internal ai_context paths (~160 occurrences across 21 test files)

All drupalGet() / addressEquals() / linkByHrefExists() calls now derive from ai_context.routing.yml routes, ai_context_item entity link templates, the dynamic scope routes registered by AiContextScopeRouteSubscriber (ai_context.settings.scope.<plugin_id>), and the usage Views route (view.ai_context_usage.page_usage). Two kernel tests not listed in the issue (AiContextScopeSiteSectionTest, AiContextScopeTargetEntityTest) had the same manage-link pattern and were converted for consistency.

Low priority — docs

The four references to the pre-1.3.2 agents path /admin/config/ai/agents (README.md, docs/index.md, docs/developers/configuration.md, docs/features/agent_configuration.md) were updated to /admin/config/ai/tools-automation/agents, verified against the entity.ai_agent.collection route. Debug/explore doc paths were left untouched — those routes did not move. All other documented paths were audited against current routing and are correct.

Intentionally left hardcoded

  • AiContextScopeSettingsTest::testOldSiteSectionUrlNotFound() asserts a removed legacy path returns 404 — there is no route to derive it from. A comment now marks it as intentional.
  • AiContextUsageTrackerTest fake paths and AiContextScopeSiteSectionTest path-matching inputs — logic test data, out of scope per the issue.

Architectural decisions

  1. A trait rather than repeated inline Url::fromRoute() — the issue proposed a shared helper; with 20+ call sites across many files it keeps call sites short, gives one place to change URL-generation behavior, and follows the existing convention of traits in tests/src/Traits/.
  2. Derive debug/explore paths before the mid-test module uninstallstestDebugAndExploreLinkVisibility() uninstalls ai_agents_debugger and ai_agents_explorer partway through; Url::fromRoute() throws RouteNotFoundException once a route is gone. Paths are computed once at method start and stored in variables, with a code comment explaining why, so a future cleanup doesn't inline them back.
  3. $entity->toUrl('link-template') when an entity is in scope, getRoutePath() otherwisetoUrl() matches the existing exemplar (AiContextItemViewTest) and survives entity-type route changes automatically; getRoutePath() covers routing.yml-only routes (settings tabs, revision revert/delete confirm forms, dynamic scope routes). No entity is ever loaded solely to call toUrl().
  4. Local variables per test method by default; setUp() properties only where repetition is heavyAiContextItemListTest uses a $itemsListPath property for its 28 identical occurrences; everywhere else paths are derived where used, avoiding cross-test state.
  5. Kernel manage-link assertions tightened from assertStringContainsString to assertSame — both sides now come from the URL generator, so exact comparison is safe and stronger.
  6. Unit test fixtures documented, not convertedUnitTestCase has no container, so Url::fromRoute() is impossible there. The paths are Request/Referer parsing fixtures with no route dependency; keeping realistic paths preserves the docblock's documentation of the real AJAX scenario. The issue explicitly offered this option.
  7. Redirect tests derive both sides — e.g. drupalGet(getRoutePath('ai_context.context_redirect')) then addressEquals(getRoutePath('ai_context.overview')), so redirect source and destination both track route changes.

Testing instructions

Prerequisite for the submodule test only: the document_loader stack must be present or that test class self-skips (it is exercised in CI either way):

composer require drupal/document_loader:^2.0 drupal/ai_file_to_text

1. Run the changed test suites (from the Drupal project root; adjust -c to your phpunit config — SIMPLETEST_BASE_URL, SIMPLETEST_DB, and MINK_DRIVER_ARGS_WEBDRIVER must be set for Functional/FunctionalJavascript):

`# Unit + Kernel (fast): vendor/bin/phpunit -c web/core web/modules/contrib/ai_context/tests/src/Unit
web/modules/contrib/ai_context/tests/src/Kernel

Functional:

vendor/bin/phpunit -c web/core web/modules/contrib/ai_context/tests/src/Functional

FunctionalJavascript (needs webdriver):

vendor/bin/phpunit -c web/core web/modules/contrib/ai_context/tests/src/FunctionalJavascript

Submodule (requires document_loader installed, otherwise skips):

vendor/bin/phpunit -c web/core web/modules/contrib/ai_context/modules/ai_context_document_loader/tests `

All suites should be green. Deprecation notices are pre-existing and unrelated.

2. Verify no brittle paths remain:

grep -rn "'/admin/config/ai" web/modules/contrib/ai_context/tests/src \ web/modules/contrib/ai_context/modules/*/tests/src | grep -v "getRoutePath\|toUrl"

Expected hits — exactly four, all intentional: the legacy-404 assertion in AiContextScopeSettingsTest and three unit-test fixture strings in AiContextLanguageDetectorTraitTest.

3. Confirm the resilience this MR buys (the actual point): temporarily change a route path, e.g. edit ai_context.routing.yml and change /admin/config/ai/context/settings/general to something else, clear caches, and re-run AiContextDebugLoggingTest — it still passes, where the old hardcoded assertion would have failed. Revert afterward.

4. Manual/CLI spot-check on a live site (optional): log in as an admin and confirm (a) /admin/config/ai/tools-automation/agents renders while /admin/config/ai/agents 404s — the docs fix; (b) the agents listing at /admin/config/ai/context/settings/agents shows Debug/Explore links matching /admin/config/ai/agents/debug|explore?agent_id=... (requires ai_agents_debugger/ai_agents_explorer enabled); (c) the extensions page links to /admin/modules?filter=ai_context_document_loader.

5. Linting (CI-blocking gates):

vendor/bin/phpcs --standard=Drupal,DrupalPractice web/modules/contrib/ai_context/tests \ web/modules/contrib/ai_context/modules/ai_context_document_loader/tests npx cspell --config web/modules/contrib/ai_context/.cspell.json "web/modules/contrib/ai_context/**"

  • #3586323 (closed) — agent edit form path assertion (fixed separately; pattern followed here)
  • ai_agents #3586032 — upstream route move that exposed this failure class

Merge request reports

Loading