CommentLinkBuilderTest.php

Same filename in other branches
  1. 9 core/modules/comment/tests/src/Unit/CommentLinkBuilderTest.php
  2. 8.9.x core/modules/comment/tests/src/Unit/CommentLinkBuilderTest.php
  3. 11.x core/modules/comment/tests/src/Unit/CommentLinkBuilderTest.php

Namespace

Drupal\Tests\comment\Unit

File

core/modules/comment/tests/src/Unit/CommentLinkBuilderTest.php

View source
<?php

declare (strict_types=1);
namespace Drupal\Tests\comment\Unit;

use Drupal\comment\CommentLinkBuilder;
use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Url;
use Drupal\Tests\Traits\Core\GeneratePermutationsTrait;
use Drupal\Tests\UnitTestCase;

/**
 * @coversDefaultClass \Drupal\comment\CommentLinkBuilder
 * @group comment
 */
class CommentLinkBuilderTest extends UnitTestCase {
    use GeneratePermutationsTrait;
    
    /**
     * 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 type manager.
     *
     * @var \Drupal\Core\Entity\EntityTypeManagerInterface|\PHPUnit\Framework\MockObject\MockObject
     */
    protected $entityTypeManager;
    
    /**
     * 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() : void {
        parent::setUp();
        $this->commentManager = $this->createMock('\\Drupal\\comment\\CommentManagerInterface');
        $this->stringTranslation = $this->getStringTranslationStub();
        $this->entityTypeManager = $this->createMock(EntityTypeManagerInterface::class);
        $this->moduleHandler = $this->createMock('\\Drupal\\Core\\Extension\\ModuleHandlerInterface');
        $this->currentUser = $this->createMock('\\Drupal\\Core\\Session\\AccountProxyInterface');
        $this->commentLinkBuilder = new CommentLinkBuilder($this->currentUser, $this->commentManager, $this->moduleHandler, $this->stringTranslation, $this->entityTypeManager);
        $this->commentManager
            ->expects($this->any())
            ->method('getFields')
            ->with('node')
            ->willReturn([
            'comment' => [],
        ]);
        $this->commentManager
            ->expects($this->any())
            ->method('forbiddenMessage')
            ->willReturn("Can't let you do that Dave.");
        $this->stringTranslation
            ->expects($this->any())
            ->method('formatPlural')
            ->willReturnArgument(1);
    }
    
    /**
     * Tests the buildCommentedEntityLinks method.
     *
     * @param array $node_args
     *   Arguments for the 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(array $node_args, $context, $has_access_comments, $history_exists, $has_post_comments, $is_anonymous, $expected) : void {
        $node = $this->getMockNode(...$node_args);
        $this->moduleHandler
            ->expects($this->any())
            ->method('moduleExists')
            ->with('history')
            ->willReturn($history_exists);
        $this->currentUser
            ->expects($this->any())
            ->method('hasPermission')
            ->willReturnMap([
            [
                'access comments',
                $has_access_comments,
            ],
            [
                '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 static function getLinkCombinations() {
        $cases = [];
        // No links should be created if the entity doesn't have the field.
        $cases[] = [
            [
                FALSE,
                CommentItemInterface::OPEN,
                CommentItemInterface::FORM_BELOW,
                1,
            ],
            [
                'view_mode' => 'teaser',
            ],
            TRUE,
            TRUE,
            TRUE,
            TRUE,
            [],
        ];
        foreach ([
            'search_result',
            'search_index',
            'print',
        ] as $view_mode) {
            // Nothing should be output in these view modes.
            $cases[] = [
                [
                    TRUE,
                    CommentItemInterface::OPEN,
                    CommentItemInterface::FORM_BELOW,
                    1,
                ],
                [
                    'view_mode' => $view_mode,
                ],
                TRUE,
                TRUE,
                TRUE,
                TRUE,
                [],
            ];
        }
        // All other combinations.
        $combinations = [
            'is_anonymous' => [
                FALSE,
                TRUE,
            ],
            'comment_count' => [
                0,
                1,
            ],
            'has_access_comments' => [
                0,
                1,
            ],
            'history_exists' => [
                FALSE,
                TRUE,
            ],
            'has_post_comments' => [
                0,
                1,
            ],
            'form_location' => [
                CommentItemInterface::FORM_BELOW,
                CommentItemInterface::FORM_SEPARATE_PAGE,
            ],
            'comments' => [
                CommentItemInterface::OPEN,
                CommentItemInterface::CLOSED,
                CommentItemInterface::HIDDEN,
            ],
            'view_mode' => [
                'teaser',
                'rss',
                'full',
            ],
        ];
        $permutations = static::generatePermutations($combinations);
        foreach ($permutations as $combination) {
            $case = [
                [
                    TRUE,
                    $combination['comments'],
                    $combination['form_location'],
                    $combination['comment_count'],
                ],
                [
                    'view_mode' => $combination['view_mode'],
                ],
                $combination['has_access_comments'],
                $combination['history_exists'],
                $combination['has_post_comments'],
                $combination['is_anonymous'],
            ];
            $expected = [];
            // 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 an add comment link.
                            $expected['comment-add'] = [
                                '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->createMock('\\Drupal\\node\\NodeInterface');
        $node->expects($this->any())
            ->method('hasField')
            ->willReturn($has_field);
        if (empty($this->timestamp)) {
            $this->timestamp = time();
        }
        $field_item = (object) [
            '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->createMock('\\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('toUrl')
            ->willReturn($url);
        return $node;
    }

}
namespace Drupal\comment;

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

Classes

Title Deprecated Summary
CommentLinkBuilderTest @coversDefaultClass \Drupal\comment\CommentLinkBuilder @group comment

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.