$this->drupalPostAJAX does not work for ajax_command_replace() commands in my form that has several commands returned in ajax callback function.

To reproduce you need to:
1. Return ajax_command_replace() command in form callback.
2. Call $this->drupalPostAJAX() on a page with form in question.
3. Check that form or some other content on the page was not replaced.

At the same time if I just return $form in the callback, it's content is being rebuild as expected.

Expected
Content within selector of ajax_command_replace to be replaced when $this->drupalPostAJAX is called in tests.

The reason of this bug explained in the @todo comment within drupalPostAJAX() function:

   // @todo Ajax commands can target any jQuery selector, but these are
   //   hard to fully emulate with XPath. For now, just handle 'head'
   //   and 'body', since these are used by ajax_render().
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

bulat’s picture

Status: Active » Needs review
FileSize
876 bytes
bulat’s picture

Patch in #1 only fixes the issue for simple id selectors like #my-replacement-block.

I guess it should be said in comments for drupalPostAJAX function that complex jQuery selectors are not supported. It should be clear that there is no way to test what ajax_command_replace does for selectors that have more than a single element ID.

czigor’s picture

Issue summary: View changes

It's quite easy to use the symfony CssSelector component here which can convert css selectors into xpath. Just override drupalPostAJAX() in your test class and replace this part:

// @todo Ajax commands can target any jQuery selector, but these are
//   hard to fully emulate with XPath. For now, just handle 'head'
//   and 'body', since these are used by ajax_render().
elseif (in_array($command['selector'], array('head', 'body'))) {
  $wrapperNode = $xpath->query('//' . $command['selector'])->item(0);
}

with this:

// Use the CssSelector symfony component.
else  {
  $converter = new CssSelectorConverter();
  $query = $converter->toXPath($command['selector']);
  $wrapperNode = $xpath->query($query)->item(0);
}

and add

use Symfony\Component\CssSelector\CssSelectorConverter;

to the beginning of the class.

Look at https://symfony.com/doc/current/components/css_selector.html for unsupported css selectors.