I have a custom menu profile-menu and have configured a block to display that menu. It has four menu items with 'expanded' => TRUE. However, during test runs these expanded menu items do not show as expanded. I've dug through the Drupal menu code and it looks like Drupal won't handle 'expanded' unless the variable 'menu_expanded' includes the menu name, which is odd because I've never had this problem outside of the test environment. I tried adding variable_set('menu_expanded', array('profile-menu')) to hook_install but for whatever reason when I call variable_get('menu_expanded') inside the test case that variable is an empty array.

If during the test case I call menu_cache_clear_all(); variable_set('menu_expanded', array('profile-menu')), everything does work as expected. The code that seems to be gated by this variable is in menu_tree_page_data.

What's the right way to make sure certain menu items (which I have defined myself in hook_menu) are always expanded? Because setting expanded => TRUE in hook_menu apparently doesn't cut it during test cases. Also, why am I only seeing this issue when running test cases?


I have investigated this a bit more and made a bug report on Drupal.org. It turns out the 'menu_expanded' variable is basically a redundant layer of caching which must be set by _menu_set_expanded_menus whenever the cache is cleared. However, if Drupal tries to call that function more than once in a single request, it will be registered as a shutdown callback instead of called immediately. This would work fine most of the time in normal use, but during test cases the shutdown function won't get called until after the tests are over.

Knowing that most of the time this operation will handle itself correctly, and that even if it doesn't it's just a cache clear away from being fixed, I've decided it is acceptable to add a direct call to _menu_set_expanded_menus in the setUp function like so:

function setUp() {
  // Call this function now to set up expanded menu item processing. Normally
  // we could wait for it to be called in a shutdown function added during
  // the menu rebuild in parent::setUp() above, but in this case it must be
  // handled before the tests are run.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.