Add getRecipePath() helper method to RecipeTestTrait

Created on 16 October 2025, 9 days ago

Problem/Motivation

Recipe tests currently need to determine the path of the recipe under test manually using approaches like dirname($dir, 3); or dirname((new \ReflectionObject($this))->getFileName(), 4);. Both approaches fail when the recipe path is a symlink because the real path of the recipe gets resolved, and if the recipe has dependencies on external (contrib) recipes, they are not found by the Recipe system.

This issue was raised in the context of automated QA on GitLab CI ( Add recipes path handling Active ). While copying recipes instead of symlinking is a valid solution on GitLab CI where code under test should not be modified, it is a major problem in local development environments that leverage symlinks to reduce copy-pasting while developers work—environments such as DDEV Drupal Contrib creates.

Today at DrupalCon 2025 Vienna, /me, @alexpott and @phenaproxima talked about this problem and we thought that a realpath() is missing somewhere. We also agreed that there is still no need for flexibility like Expand Drupal\Core\Recipe\RecipeDiscovery to allow discovering available recipes, likely for use in Project Browser Active in recipe discovery. However it quickly turned out that we weren't right and the problem is not a missing realpath(). Moreover, the problem only impacts tests because ddev drush recipe /var/www/html/recipes/[recipe_name] works just fine, so we have to provide a solution for this at the tests level.

Steps to reproduce

  1. Create a local development environment using DDEV Drupal Contrib for a recipe which has dependencies on other contrib recipes.
  2. Set up a recipe test that extends a test class using RecipeTestTrait
  3. Use either dirname($dir, 3) or dirname((new \ReflectionObject($this))->getFileName(), 4) to retrieve the recipe path
  4. Observe that the symlink is resolved to its real path
  5. If the recipe has dependencies on external recipes, observe that they cannot be found

Proposed resolution

Add a getRecipePath() helper method to RecipeTestTrait that extracts the recipe name from the test class namespace and constructs the path relative to Drupal root without resolving symlinks:

protected function getRecipePath(): string {
  $rc = new \ReflectionObject($this);
  [, , $recipe_name] = explode('\\', $rc->getNamespaceName());
  return dirname(\Drupal::root()) . '/recipes/' . $recipe_name;
}

This approach avoids symlink resolution issues while maintaining consistency with Drupal's standard recipe directory structure.

Approaches that did not work

  • \Composer\InstalledVersions::getInstallPath('drupal/ai_recipe_llm_optimized_content') - Other than this would have also required knowing or guessing the recipe's name, composer also stores the resolved path of the symlink
  • debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS) - LLM suggested solution, but because tests run in a browser, this leads nowhere
  • Finding the symlink path on the reflection class - Reflection also always has the resolved symlink
  • Leveraging work from 🐛 Wrong DRUPAL_ROOT with non-standard code structure Needs work - The latest version of the patch there aims to kill app.root and @kingdutch just required in comment 262 to keep it, because it is still going to be needed after Use symfony/runtime for less bespoke bootstrap/compatibility with varied runtime environments Active . So that is also potential dead end

Remaining tasks

  • Add test coverage for the new method
  • Review and commit

User interface changes

None.

Introduced terminology

None.

API changes

A new protected method getRecipePath() will be added to Drupal\FunctionalTests\Core\Recipe\RecipeTestTrait:

Data model changes

None.

Release notes snippet

Recipe tests can now use the getRecipePath() helper method from RecipeTestTrait to retrieve the path of the recipe under test without resolving symlinks. This improves support for local development environments that use symlinked recipes, such as DDEV Drupal Contrib setups.

Feature request
Status

Active

Version

11.0 🔥

Component

recipe system

Created by

🇭🇺Hungary mxr576 Hungary

Live updates comments and jobs are added and updated live.
  • Needs tests

    The change is currently missing an automated test that fails when run with the original code, and succeeds when the bug has been fixed.

Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

No activities found.

Production build 0.71.5 2024