You are here

PollTestBase.php in Poll 8

File

tests/src/Functional/PollTestBase.php
View source
<?php

namespace Drupal\Tests\poll\Functional;

use Drupal\poll\PollInterface;
use Drupal\Tests\BrowserTestBase;
use InvalidArgumentException;

/**
 * Defines a base class for testing the Poll module.
 */
abstract class PollTestBase extends BrowserTestBase {

  /**
   * @var \Drupal\user\UserInterface
   */
  protected $admin_user;

  /**
   * @var \Drupal\user\UserInterface
   */
  protected $web_user;

  /**
   * @var \Drupal\poll\PollInterface
   */
  protected $poll;

  /**
   * List of permissions used by admin_user.
   *
   * @var array
   */
  protected $adminPermissions = [];

  /**
   * List of permissions used by web_user.
   *
   * @var array
   */
  protected $webUserPermissions = [];

  /**
   * Modules to enable.
   *
   * @var array
   */
  public static $modules = array(
    'poll',
    'node',
    'block',
  );

  /**
   * {@inheritdoc}
   */
  protected $defaultTheme = 'classy';

  /**
   * {@inheritdoc}
   */
  protected function setUp() {
    parent::setUp();
    $this
      ->drupalPlaceBlock('local_tasks_block');
    $this
      ->drupalPlaceBlock('local_actions_block');
    $this
      ->drupalPlaceBlock('page_title_block');
    $this->admin_user = $this
      ->drupalCreateUser(array_merge([
      'administer polls',
      'access polls',
      'access poll overview',
      'view poll results',
    ], $this->adminPermissions));
    $this->web_user = $this
      ->drupalCreateUser(array_merge([
      'access polls',
      'cancel own vote',
    ], $this->webUserPermissions));
    $this->poll = $this
      ->pollCreate();
  }

  /**
   * Creates a poll.
   *
   * @param int $choice_count
   *   (optional) The number of choices to generate. Defaults to 7.
   * @param \Drupal\user\UserInterface $account
   *   (optional) Poll creator user. Defaults to NULL, then use $this->admin_user.
   * @param boolean $preview
   *   (optional) Whether to test if the preview is working or not. Defaults to
   *   TRUE.
   *
   * @return mixed
   *   The created poll entity, or FALSE on error.
   */
  function pollCreate($choice_count = 7, $account = NULL, $preview = TRUE) {
    if (!$account) {
      $this
        ->drupalLogin($this->admin_user);
    }
    else {
      $this
        ->drupalLogin($account);
    }

    // Get the form first to initialize the state of the internal browser.
    $this
      ->drupalGet('poll/add');
    $question = $this
      ->randomMachineName();
    $choices = $this
      ->generateChoices($choice_count);
    list($edit, $index) = $this
      ->pollGenerateEdit($question, $choices);

    // Re-submit the form until all choices are filled in.
    if (count($choices) > 0) {
      for ($delta = 0; $delta <= count($choices); $delta++) {
        $this
          ->drupalPostForm(NULL, $edit, t('Add another item'));
        list($edit, $index) = $this
          ->pollGenerateEdit($question, $choices, $index);
      }
    }

    //    if ($preview) {
    //      $this->drupalPostForm('poll/add', $edit, t('Preview'));
    //      $this->assertPollChoiceOrder($choices, $index, TRUE);
    //      list($edit, $index) = $this->pollGenerateEdit($title, $choices, $index);
    //    }
    $this
      ->drupalPostForm(NULL, $edit, t('Save'));

    // Load the first poll returned from the database.
    $polls = \Drupal::entityTypeManager()
      ->getStorage('poll')
      ->loadByProperties(array(
      'question' => $question,
    ));
    $poll = reset($polls);
    $this
      ->assertText(t('The poll @question has been added.', array(
      '@question' => $question,
    )));
    $this
      ->assertInstanceOf(PollInterface::class, $poll);
    return $poll instanceof PollInterface ? $poll : FALSE;
  }

  /**
   * Generates POST values for the poll node form, specifically poll choices.
   *
   * @param string $question
   *   The poll question.
   * @param array $choices
   *   An array containing poll choices, as generated by
   *   PollTestBase::generateChoices().
   * @param int $index
   *   (optional) The amount/number of already submitted poll choices. Defaults
   *   to 0.
   *
   * @return array
   *   An indexed array containing:
   *   - The generated POST values, suitable for
   *     Drupal\simpletest\WebTestBase::drupalPostForm().
   *   - The number of poll choices contained in 'edit', for potential re-usage
   *     in subsequent invocations of this function.
   */
  private function pollGenerateEdit($question, array $choices, $index = 0) {
    $max_new_choices = 1;
    $already_submitted_choices = array_slice($choices, 0, $index);
    $new_choices = array_values(array_slice($choices, $index, $max_new_choices));
    $edit = array(
      'question[0][value]' => $question,
    );
    foreach ($already_submitted_choices as $k => $text) {
      $edit['choice[' . $k . '][choice]'] = $text;
    }
    foreach ($new_choices as $k => $text) {
      $edit['choice[' . $k . '][choice]'] = $text;
    }
    return array(
      $edit,
      count($already_submitted_choices) + count($new_choices),
    );
  }

  /**
   * Generates random choices for the poll.
   *
   * @param int $count
   *   (optional) The number of choices to generate. Defaults to 7.
   *
   * @return array $choices
   *   An array of generated choices.
   */
  private function generateChoices($count = 7) {
    $choices = array();
    for ($i = 1; $i <= $count; $i++) {
      $choices[] = $this
        ->randomMachineName();
    }
    return $choices;
  }

  /**
   * Asserts correct poll choice order in the node form after submission.
   *
   * Verifies both the order in the DOM and in the 'weight' form elements.
   *
   * @param array $choices
   *   An array containing poll choices, as generated by
   *   PollTestBase::generateChoices().
   * @param int $index
   *   (optional) The amount/number of already submitted poll choices. Defaults
   *   to 0.
   * @param bool $preview
   *   (optional) Whether to also check the poll preview. Defaults to FALSE.
   *
   * @see PollTestBase::pollGenerateEdit()
   */
  function assertPollChoiceOrder(array $choices, $index = 0, $preview = FALSE) {
    $expected = array();
    $weight = 0;
    foreach ($choices as $id => $label) {
      if ($id < $index) {

        // Directly assert the weight form element value for this choice.
        $this
          ->assertFieldByName('choice[' . $id . '][_weight]', $weight);

        // The expected weight of each choice is higher than the previous one.
        $weight++;

        // Append to our (to be reversed) stack of labels.
        $expected[$weight] = $label;
      }
    }
    ksort($expected);

    // Verify DOM order of poll choices (i.e., #weight of form elements).
    $elements = $this
      ->xpath('//input[starts-with(@name, :prefix) and contains(@name, :suffix)]', array(
      ':prefix' => 'choice[chid:',
      ':suffix' => '][chtext]',
    ));
    $expected_order = $expected;
    foreach ($elements as $element) {
      $next_label = array_shift($expected_order);
      $this
        ->assertEqual((string) $element['value'], $next_label);
    }

    // If requested, also verify DOM order in preview.
    if ($preview) {
      $elements = $this
        ->xpath('//div[contains(@class, :teaser)]/descendant::div[@class=:text]', array(
        ':teaser' => 'node-teaser',
        ':text' => 'text',
      ));
      $expected_order = $expected;
      foreach ($elements as $element) {
        $next_label = array_shift($expected_order);
        $this
          ->assertEqual((string) $element, $next_label, "Found choice {$next_label} in preview.");
      }
    }
  }

  /**
   * Get the Choice ID of a poll.
   *
   * @param \Drupal\poll\PollInterface $poll
   *   The poll of the choice.
   * @param int $delta
   *   The number of the choice.
   *
   * @return int $key
   *   Returns the choice ID or an error.
   *
   * @throws InvalidArgumentException
   *   Throws it if the poll does not have the choice delta.
   */
  protected function getChoiceId(PollInterface $poll, $delta) {
    $options = $poll
      ->getOptions();
    $keys = array_keys($options);
    foreach ($keys as $id => $key) {
      if ($delta == $id + 1) {
        return $key;
      }
    }
    throw new InvalidArgumentException();
  }

  /**
   * Get the Choice ID of a poll from the label.
   *
   * @param \Drupal\poll\PollInterface $poll
   *   The poll of the choice.
   * @param string $label
   *   The label of the choice.
   *
   * @return int $id
   *   Returns the choice id or an error.
   *
   * @throws InvalidArgumentException
   *   Throws it if the poll does not have the choice label.
   */
  protected function getChoiceIdByLabel(PollInterface $poll, $label) {
    $options = $poll
      ->getOptions();
    foreach ($options as $id => $option) {
      if ($label == $option) {
        return $id;
      }
    }
    throw new InvalidArgumentException();
  }

}

Classes

Namesort descending Description
PollTestBase Defines a base class for testing the Poll module.