You are here

protected function WebTestBase::drupalPostAjaxForm in Drupal 8

Executes an Ajax form submission.

This executes a POST as ajax.js does. The returned JSON data is used to update $this->content via drupalProcessAjaxResponse(). It also returns the array of AJAX commands received.

Parameters

\Drupal\Core\Url|string $path: Location of the form containing the Ajax enabled element to test. Can be either a Drupal path or an absolute path or NULL to use the current page.

$edit: Field data in an associative array. Changes the current input fields (where possible) to the values indicated.

$triggering_element: The name of the form element that is responsible for triggering the Ajax functionality to test. May be a string or, if the triggering element is a button, an associative array where the key is the name of the button and the value is the button label. i.e.) array('op' => t('Refresh')).

$ajax_path: (optional) Override the path set by the Ajax settings of the triggering element.

$options: (optional) Options to be forwarded to the url generator.

$headers: (optional) An array containing additional HTTP request headers, each formatted as "name: value". Forwarded to drupalPostForm().

$form_html_id: (optional) HTML ID of the form to be submitted, use when there is more than one identical form on the same page and the value of the triggering element is not enough to identify the form. Note this is not the Drupal ID of the form but rather the HTML ID of the form.

$ajax_settings: (optional) An array of Ajax settings which if specified will be used in place of the Ajax settings of the triggering element.

Return value

An array of Ajax commands.

See also

drupalPostForm()

drupalProcessAjaxResponse()

ajax.js

File

core/modules/simpletest/src/WebTestBase.php, line 1117

Class

WebTestBase
Test case for typical Drupal tests.

Namespace

Drupal\simpletest

Code

protected function drupalPostAjaxForm($path, $edit, $triggering_element, $ajax_path = NULL, array $options = [], array $headers = [], $form_html_id = NULL, $ajax_settings = NULL) {

  // Get the content of the initial page prior to calling drupalPostForm(),
  // since drupalPostForm() replaces $this->content.
  if (isset($path)) {

    // Avoid sending the wrapper query argument to drupalGet so we can fetch
    // the form and populate the internal WebTest values.
    $get_options = $options;
    unset($get_options['query'][MainContentViewSubscriber::WRAPPER_FORMAT]);
    $this
      ->drupalGet($path, $get_options);
  }
  $content = $this->content;
  $drupal_settings = $this->drupalSettings;

  // Provide a default value for the wrapper envelope.
  $options['query'][MainContentViewSubscriber::WRAPPER_FORMAT] = isset($options['query'][MainContentViewSubscriber::WRAPPER_FORMAT]) ? $options['query'][MainContentViewSubscriber::WRAPPER_FORMAT] : 'drupal_ajax';

  // Get the Ajax settings bound to the triggering element.
  if (!isset($ajax_settings)) {
    if (is_array($triggering_element)) {
      $xpath = '//*[@name="' . key($triggering_element) . '" and @value="' . current($triggering_element) . '"]';
    }
    else {
      $xpath = '//*[@name="' . $triggering_element . '"]';
    }
    if (isset($form_html_id)) {
      $xpath = '//form[@id="' . $form_html_id . '"]' . $xpath;
    }
    $element = $this
      ->xpath($xpath);
    $element_id = (string) $element[0]['id'];
    $ajax_settings = $drupal_settings['ajax'][$element_id];
  }

  // Add extra information to the POST data as ajax.js does.
  $extra_post = [];
  if (isset($ajax_settings['submit'])) {
    foreach ($ajax_settings['submit'] as $key => $value) {
      $extra_post[$key] = $value;
    }
  }
  $extra_post[AjaxResponseSubscriber::AJAX_REQUEST_PARAMETER] = 1;
  $extra_post += $this
    ->getAjaxPageStatePostData();

  // Now serialize all the $extra_post values, and prepend it with an '&'.
  $extra_post = '&' . $this
    ->serializePostValues($extra_post);

  // Unless a particular path is specified, use the one specified by the
  // Ajax settings.
  if (!isset($ajax_path)) {
    if (isset($ajax_settings['url'])) {

      // In order to allow to set for example the wrapper envelope query
      // parameter we need to get the system path again.
      $parsed_url = UrlHelper::parse($ajax_settings['url']);
      $options['query'] = $parsed_url['query'] + $options['query'];
      $options += [
        'fragment' => $parsed_url['fragment'],
      ];

      // We know that $parsed_url['path'] is already with the base path
      // attached.
      $ajax_path = preg_replace('/^' . preg_quote(base_path(), '/') . '/', '', $parsed_url['path']);
    }
  }
  if (empty($ajax_path)) {
    throw new \Exception('No #ajax path specified.');
  }
  $ajax_path = $this->container
    ->get('unrouted_url_assembler')
    ->assemble('base://' . $ajax_path, $options);

  // Submit the POST request.
  $return = Json::decode($this
    ->drupalPostForm(NULL, $edit, [
    'path' => $ajax_path,
    'triggering_element' => $triggering_element,
  ], $options, $headers, $form_html_id, $extra_post));
  if ($this->assertAjaxHeader) {
    $this
      ->assertIdentical($this
      ->drupalGetHeader('X-Drupal-Ajax-Token'), '1', 'Ajax response header found.');
  }

  // Change the page content by applying the returned commands.
  if (!empty($ajax_settings) && !empty($return)) {
    $this
      ->drupalProcessAjaxResponse($content, $return, $ajax_settings, $drupal_settings);
  }
  $verbose = 'AJAX POST request to: ' . $path;
  $verbose .= '<br />AJAX controller path: ' . $ajax_path;
  $verbose .= '<hr />Ending URL: ' . $this
    ->getUrl();
  $verbose .= '<hr />' . $this->content;
  $this
    ->verbose($verbose);
  return $return;
}