You are here

CommentLinkBuilderTest.php in Zircon Profile 8

Same filename and directory in other branches
  1. 8.0 core/modules/comment/tests/src/Unit/CommentLinkBuilderTest.php

File

core/modules/comment/tests/src/Unit/CommentLinkBuilderTest.php
View source
<?php

/**
 * @file
 * Contains \Drupal\Tests\comment\Unit\CommentLinkBuilderTest.
 */
namespace Drupal\Tests\comment\Unit {
  use Drupal\comment\CommentLinkBuilder;
  use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface;
  use Drupal\Core\Url;
  use Drupal\node\NodeInterface;
  use Drupal\simpletest\TestBase;
  use Drupal\Tests\UnitTestCase;

  /**
   * @coversDefaultClass \Drupal\comment\CommentLinkBuilder
   * @group comment
   */
  class CommentLinkBuilderTest extends UnitTestCase {

    /**
     * Comment manager mock.
     *
     * @var \Drupal\comment\CommentManagerInterface|\PHPUnit_Framework_MockObject_MockObject
     */
    protected $commentManager;

    /**
     * String translation mock.
     *
     * @var \Drupal\Core\StringTranslation\TranslationInterface|\PHPUnit_Framework_MockObject_MockObject
     */
    protected $stringTranslation;

    /**
     * The entity manager service.
     *
     * @var \Drupal\Core\Entity\EntityManagerInterface
     */
    protected $entityManager;

    /**
     * Module handler mock.
     *
     * @var \Drupal\Core\Extension\ModuleHandlerInterface|\PHPUnit_Framework_MockObject_MockObject
     */
    protected $moduleHandler;

    /**
     * Current user proxy mock.
     *
     * @var \Drupal\Core\Session\AccountProxyInterface|\PHPUnit_Framework_MockObject_MockObject
     */
    protected $currentUser;

    /**
     * Timestamp used in test.
     *
     * @var int
     */
    protected $timestamp;

    /**
     * @var \Drupal\comment\CommentLinkBuilderInterface;
     */
    protected $commentLinkBuilder;

    /**
     * Prepares mocks for the test.
     */
    protected function setUp() {
      $this->commentManager = $this
        ->getMock('\\Drupal\\comment\\CommentManagerInterface');
      $this->stringTranslation = $this
        ->getStringTranslationStub();
      $this->entityManager = $this
        ->getMock('\\Drupal\\Core\\Entity\\EntityManagerInterface');
      $this->moduleHandler = $this
        ->getMock('\\Drupal\\Core\\Extension\\ModuleHandlerInterface');
      $this->currentUser = $this
        ->getMock('\\Drupal\\Core\\Session\\AccountProxyInterface');
      $this->commentLinkBuilder = new CommentLinkBuilder($this->currentUser, $this->commentManager, $this->moduleHandler, $this->stringTranslation, $this->entityManager);
      $this->commentManager
        ->expects($this
        ->any())
        ->method('getFields')
        ->with('node')
        ->willReturn(array(
        'comment' => array(),
      ));
      $this->commentManager
        ->expects($this
        ->any())
        ->method('forbiddenMessage')
        ->willReturn("Can't let you do that Dave.");
      $this->stringTranslation
        ->expects($this
        ->any())
        ->method('formatPlural')
        ->willReturnArgument(1);
    }

    /**
     * Test the buildCommentedEntityLinks method.
     *
     * @param \Drupal\node\NodeInterface|\PHPUnit_Framework_MockObject_MockObject $node
     *   Mock node.
     * @param array $context
     *   Context for the links.
     * @param bool $has_access_comments
     *   TRUE if the user has 'access comments' permission.
     * @param bool $history_exists
     *   TRUE if the history module exists.
     * @param bool $has_post_comments
     *   TRUE if the use has 'post comments' permission.
     * @param bool $is_anonymous
     *   TRUE if the user is anonymous.
     * @param array $expected
     *   Array of expected links keyed by link ID. Can be either string (link
     *   title) or array of link properties.
     *
     * @dataProvider getLinkCombinations
     *
     * @covers ::buildCommentedEntityLinks
     */
    public function testCommentLinkBuilder(NodeInterface $node, $context, $has_access_comments, $history_exists, $has_post_comments, $is_anonymous, $expected) {
      $this->moduleHandler
        ->expects($this
        ->any())
        ->method('moduleExists')
        ->with('history')
        ->willReturn($history_exists);
      $this->currentUser
        ->expects($this
        ->any())
        ->method('hasPermission')
        ->willReturnMap(array(
        array(
          'access comments',
          $has_access_comments,
        ),
        array(
          'post comments',
          $has_post_comments,
        ),
      ));
      $this->currentUser
        ->expects($this
        ->any())
        ->method('isAuthenticated')
        ->willReturn(!$is_anonymous);
      $this->currentUser
        ->expects($this
        ->any())
        ->method('isAnonymous')
        ->willReturn($is_anonymous);
      $links = $this->commentLinkBuilder
        ->buildCommentedEntityLinks($node, $context);
      if (!empty($expected)) {
        if (!empty($links)) {
          foreach ($expected as $link => $detail) {
            if (is_array($detail)) {

              // Array of link attributes.
              foreach ($detail as $key => $value) {
                $this
                  ->assertEquals($value, $links['comment__comment']['#links'][$link][$key]);
              }
            }
            else {

              // Just the title.
              $this
                ->assertEquals($detail, $links['comment__comment']['#links'][$link]['title']);
            }
          }
        }
        else {
          $this
            ->fail('Expected links but found none.');
        }
      }
      else {
        $this
          ->assertSame($links, $expected);
      }
    }

    /**
     * Data provider for ::testCommentLinkBuilder.
     */
    public function getLinkCombinations() {
      $cases = array();

      // No links should be created if the entity doesn't have the field.
      $cases[] = array(
        $this
          ->getMockNode(FALSE, CommentItemInterface::OPEN, CommentItemInterface::FORM_BELOW, 1),
        array(
          'view_mode' => 'teaser',
        ),
        TRUE,
        TRUE,
        TRUE,
        TRUE,
        array(),
      );
      foreach (array(
        'search_result',
        'search_index',
        'print',
      ) as $view_mode) {

        // Nothing should be output in these view modes.
        $cases[] = array(
          $this
            ->getMockNode(TRUE, CommentItemInterface::OPEN, CommentItemInterface::FORM_BELOW, 1),
          array(
            'view_mode' => $view_mode,
          ),
          TRUE,
          TRUE,
          TRUE,
          TRUE,
          array(),
        );
      }

      // All other combinations.
      $combinations = array(
        'is_anonymous' => array(
          FALSE,
          TRUE,
        ),
        'comment_count' => array(
          0,
          1,
        ),
        'has_access_comments' => array(
          0,
          1,
        ),
        'history_exists' => array(
          FALSE,
          TRUE,
        ),
        'has_post_comments' => array(
          0,
          1,
        ),
        'form_location' => array(
          CommentItemInterface::FORM_BELOW,
          CommentItemInterface::FORM_SEPARATE_PAGE,
        ),
        'comments' => array(
          CommentItemInterface::OPEN,
          CommentItemInterface::CLOSED,
          CommentItemInterface::HIDDEN,
        ),
        'view_mode' => array(
          'teaser',
          'rss',
          'full',
        ),
      );
      $permutations = TestBase::generatePermutations($combinations);
      foreach ($permutations as $combination) {
        $case = array(
          $this
            ->getMockNode(TRUE, $combination['comments'], $combination['form_location'], $combination['comment_count']),
          array(
            'view_mode' => $combination['view_mode'],
          ),
          $combination['has_access_comments'],
          $combination['history_exists'],
          $combination['has_post_comments'],
          $combination['is_anonymous'],
        );
        $expected = array();

        // When comments are enabled in teaser mode, and comments exist, and the
        // user has access - we can output the comment count.
        if ($combination['comments'] && $combination['view_mode'] == 'teaser' && $combination['comment_count'] && $combination['has_access_comments']) {
          $expected['comment-comments'] = '1 comment';

          // And if history module exists, we can show a 'new comments' link.
          if ($combination['history_exists']) {
            $expected['comment-new-comments'] = '';
          }
        }

        // All view modes other than RSS.
        if ($combination['view_mode'] != 'rss') {

          // Where commenting is open.
          if ($combination['comments'] == CommentItemInterface::OPEN) {

            // And the user has post-comments permission.
            if ($combination['has_post_comments']) {

              // If the view mode is teaser, or the user can access comments and
              // comments exist or the form is on a separate page.
              if ($combination['view_mode'] == 'teaser' || $combination['has_access_comments'] && $combination['comment_count'] || $combination['form_location'] == CommentItemInterface::FORM_SEPARATE_PAGE) {

                // There should be a add comment link.
                $expected['comment-add'] = array(
                  'title' => 'Add new comment',
                );
                if ($combination['form_location'] == CommentItemInterface::FORM_BELOW) {

                  // On the same page.
                  $expected['comment-add']['url'] = Url::fromRoute('node.view');
                }
                else {

                  // On a separate page.
                  $expected['comment-add']['url'] = Url::fromRoute('comment.reply', [
                    'entity_type' => 'node',
                    'entity' => 1,
                    'field_name' => 'comment',
                  ]);
                }
              }
            }
            elseif ($combination['is_anonymous']) {

              // Anonymous users get the forbidden message if the can't post
              // comments.
              $expected['comment-forbidden'] = "Can't let you do that Dave.";
            }
          }
        }
        $case[] = $expected;
        $cases[] = $case;
      }
      return $cases;
    }

    /**
     * Builds a mock node based on given scenario.
     *
     * @param bool $has_field
     *   TRUE if the node has the 'comment' field.
     * @param int $comment_status
     *   One of CommentItemInterface::OPEN|HIDDEN|CLOSED
     * @param int $form_location
     *   One of CommentItemInterface::FORM_BELOW|FORM_SEPARATE_PAGE
     * @param int $comment_count
     *   Number of comments against the field.
     *
     * @return \Drupal\node\NodeInterface|\PHPUnit_Framework_MockObject_MockObject
     *   Mock node for testing.
     */
    protected function getMockNode($has_field, $comment_status, $form_location, $comment_count) {
      $node = $this
        ->getMock('\\Drupal\\node\\NodeInterface');
      $node
        ->expects($this
        ->once())
        ->method('hasField')
        ->willReturn($has_field);
      if (empty($this->timestamp)) {
        $this->timestamp = time();
      }
      $field_item = (object) array(
        'status' => $comment_status,
        'comment_count' => $comment_count,
        'last_comment_timestamp' => $this->timestamp,
      );
      $node
        ->expects($this
        ->any())
        ->method('get')
        ->with('comment')
        ->willReturn($field_item);
      $field_definition = $this
        ->getMock('\\Drupal\\Core\\Field\\FieldDefinitionInterface');
      $field_definition
        ->expects($this
        ->any())
        ->method('getSetting')
        ->with('form_location')
        ->willReturn($form_location);
      $node
        ->expects($this
        ->any())
        ->method('getFieldDefinition')
        ->with('comment')
        ->willReturn($field_definition);
      $node
        ->expects($this
        ->any())
        ->method('language')
        ->willReturn('und');
      $node
        ->expects($this
        ->any())
        ->method('getEntityTypeId')
        ->willReturn('node');
      $node
        ->expects($this
        ->any())
        ->method('id')
        ->willReturn(1);
      $url = Url::fromRoute('node.view');
      $node
        ->expects($this
        ->any())
        ->method('urlInfo')
        ->willReturn($url);
      $node
        ->expects($this
        ->any())
        ->method('url')
        ->willReturn(array(
        'route_name' => 'node.view',
      ));
      return $node;
    }

  }
}
namespace {
  if (!function_exists('history_read')) {
    function history_read() {
      return 0;
    }
  }
}

Classes

Namesort descending Description
CommentLinkBuilderTest @coversDefaultClass \Drupal\comment\CommentLinkBuilder @group comment