annotate core/modules/comment/tests/src/Unit/CommentLinkBuilderTest.php @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents af1871eacc83
children
rev   line source
Chris@0 1 <?php
Chris@0 2
Chris@0 3 namespace Drupal\Tests\comment\Unit;
Chris@0 4
Chris@0 5 use Drupal\comment\CommentLinkBuilder;
Chris@0 6 use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface;
Chris@18 7 use Drupal\Core\Entity\EntityTypeManagerInterface;
Chris@0 8 use Drupal\Core\Url;
Chris@0 9 use Drupal\node\NodeInterface;
Chris@0 10 use Drupal\Tests\Traits\Core\GeneratePermutationsTrait;
Chris@0 11 use Drupal\Tests\UnitTestCase;
Chris@0 12
Chris@0 13 /**
Chris@0 14 * @coversDefaultClass \Drupal\comment\CommentLinkBuilder
Chris@0 15 * @group comment
Chris@0 16 */
Chris@0 17 class CommentLinkBuilderTest extends UnitTestCase {
Chris@0 18
Chris@0 19 use GeneratePermutationsTrait;
Chris@0 20
Chris@0 21 /**
Chris@0 22 * Comment manager mock.
Chris@0 23 *
Chris@0 24 * @var \Drupal\comment\CommentManagerInterface|\PHPUnit_Framework_MockObject_MockObject
Chris@0 25 */
Chris@0 26 protected $commentManager;
Chris@0 27
Chris@0 28 /**
Chris@0 29 * String translation mock.
Chris@0 30 *
Chris@0 31 * @var \Drupal\Core\StringTranslation\TranslationInterface|\PHPUnit_Framework_MockObject_MockObject
Chris@0 32 */
Chris@0 33 protected $stringTranslation;
Chris@0 34
Chris@0 35 /**
Chris@18 36 * The entity type manager.
Chris@0 37 *
Chris@18 38 * @var \Drupal\Core\Entity\EntityTypeManagerInterface|\PHPUnit_Framework_MockObject_MockObject
Chris@0 39 */
Chris@18 40 protected $entityTypeManager;
Chris@0 41
Chris@0 42 /**
Chris@0 43 * Module handler mock.
Chris@0 44 *
Chris@0 45 * @var \Drupal\Core\Extension\ModuleHandlerInterface|\PHPUnit_Framework_MockObject_MockObject
Chris@0 46 */
Chris@0 47 protected $moduleHandler;
Chris@0 48
Chris@0 49 /**
Chris@0 50 * Current user proxy mock.
Chris@0 51 *
Chris@0 52 * @var \Drupal\Core\Session\AccountProxyInterface|\PHPUnit_Framework_MockObject_MockObject
Chris@0 53 */
Chris@0 54 protected $currentUser;
Chris@0 55
Chris@0 56 /**
Chris@0 57 * Timestamp used in test.
Chris@0 58 *
Chris@0 59 * @var int
Chris@0 60 */
Chris@0 61 protected $timestamp;
Chris@0 62
Chris@0 63 /**
Chris@17 64 * @var \Drupal\comment\CommentLinkBuilderInterface
Chris@0 65 */
Chris@0 66 protected $commentLinkBuilder;
Chris@0 67
Chris@0 68 /**
Chris@0 69 * Prepares mocks for the test.
Chris@0 70 */
Chris@0 71 protected function setUp() {
Chris@0 72 $this->commentManager = $this->getMock('\Drupal\comment\CommentManagerInterface');
Chris@0 73 $this->stringTranslation = $this->getStringTranslationStub();
Chris@18 74 $this->entityTypeManager = $this->createMock(EntityTypeManagerInterface::class);
Chris@0 75 $this->moduleHandler = $this->getMock('\Drupal\Core\Extension\ModuleHandlerInterface');
Chris@0 76 $this->currentUser = $this->getMock('\Drupal\Core\Session\AccountProxyInterface');
Chris@18 77 $this->commentLinkBuilder = new CommentLinkBuilder($this->currentUser, $this->commentManager, $this->moduleHandler, $this->stringTranslation, $this->entityTypeManager);
Chris@0 78 $this->commentManager->expects($this->any())
Chris@0 79 ->method('getFields')
Chris@0 80 ->with('node')
Chris@0 81 ->willReturn([
Chris@0 82 'comment' => [],
Chris@0 83 ]);
Chris@0 84 $this->commentManager->expects($this->any())
Chris@0 85 ->method('forbiddenMessage')
Chris@0 86 ->willReturn("Can't let you do that Dave.");
Chris@0 87 $this->stringTranslation->expects($this->any())
Chris@0 88 ->method('formatPlural')
Chris@0 89 ->willReturnArgument(1);
Chris@0 90 }
Chris@0 91
Chris@0 92 /**
Chris@0 93 * Test the buildCommentedEntityLinks method.
Chris@0 94 *
Chris@0 95 * @param \Drupal\node\NodeInterface|\PHPUnit_Framework_MockObject_MockObject $node
Chris@0 96 * Mock node.
Chris@0 97 * @param array $context
Chris@0 98 * Context for the links.
Chris@0 99 * @param bool $has_access_comments
Chris@0 100 * TRUE if the user has 'access comments' permission.
Chris@0 101 * @param bool $history_exists
Chris@0 102 * TRUE if the history module exists.
Chris@0 103 * @param bool $has_post_comments
Chris@0 104 * TRUE if the use has 'post comments' permission.
Chris@0 105 * @param bool $is_anonymous
Chris@0 106 * TRUE if the user is anonymous.
Chris@0 107 * @param array $expected
Chris@0 108 * Array of expected links keyed by link ID. Can be either string (link
Chris@0 109 * title) or array of link properties.
Chris@0 110 *
Chris@0 111 * @dataProvider getLinkCombinations
Chris@0 112 *
Chris@0 113 * @covers ::buildCommentedEntityLinks
Chris@0 114 */
Chris@0 115 public function testCommentLinkBuilder(NodeInterface $node, $context, $has_access_comments, $history_exists, $has_post_comments, $is_anonymous, $expected) {
Chris@0 116 $this->moduleHandler->expects($this->any())
Chris@0 117 ->method('moduleExists')
Chris@0 118 ->with('history')
Chris@0 119 ->willReturn($history_exists);
Chris@0 120 $this->currentUser->expects($this->any())
Chris@0 121 ->method('hasPermission')
Chris@0 122 ->willReturnMap([
Chris@0 123 ['access comments', $has_access_comments],
Chris@0 124 ['post comments', $has_post_comments],
Chris@0 125 ]);
Chris@0 126 $this->currentUser->expects($this->any())
Chris@0 127 ->method('isAuthenticated')
Chris@0 128 ->willReturn(!$is_anonymous);
Chris@0 129 $this->currentUser->expects($this->any())
Chris@0 130 ->method('isAnonymous')
Chris@0 131 ->willReturn($is_anonymous);
Chris@0 132 $links = $this->commentLinkBuilder->buildCommentedEntityLinks($node, $context);
Chris@0 133 if (!empty($expected)) {
Chris@0 134 if (!empty($links)) {
Chris@0 135 foreach ($expected as $link => $detail) {
Chris@0 136 if (is_array($detail)) {
Chris@0 137 // Array of link attributes.
Chris@0 138 foreach ($detail as $key => $value) {
Chris@0 139 $this->assertEquals($value, $links['comment__comment']['#links'][$link][$key]);
Chris@0 140 }
Chris@0 141 }
Chris@0 142 else {
Chris@0 143 // Just the title.
Chris@0 144 $this->assertEquals($detail, $links['comment__comment']['#links'][$link]['title']);
Chris@0 145 }
Chris@0 146 }
Chris@0 147 }
Chris@0 148 else {
Chris@0 149 $this->fail('Expected links but found none.');
Chris@0 150 }
Chris@0 151 }
Chris@0 152 else {
Chris@0 153 $this->assertSame($links, $expected);
Chris@0 154 }
Chris@0 155 }
Chris@0 156
Chris@0 157 /**
Chris@0 158 * Data provider for ::testCommentLinkBuilder.
Chris@0 159 */
Chris@0 160 public function getLinkCombinations() {
Chris@0 161 $cases = [];
Chris@0 162 // No links should be created if the entity doesn't have the field.
Chris@0 163 $cases[] = [
Chris@0 164 $this->getMockNode(FALSE, CommentItemInterface::OPEN, CommentItemInterface::FORM_BELOW, 1),
Chris@0 165 ['view_mode' => 'teaser'],
Chris@0 166 TRUE,
Chris@0 167 TRUE,
Chris@0 168 TRUE,
Chris@0 169 TRUE,
Chris@0 170 [],
Chris@0 171 ];
Chris@0 172 foreach (['search_result', 'search_index', 'print'] as $view_mode) {
Chris@0 173 // Nothing should be output in these view modes.
Chris@0 174 $cases[] = [
Chris@0 175 $this->getMockNode(TRUE, CommentItemInterface::OPEN, CommentItemInterface::FORM_BELOW, 1),
Chris@0 176 ['view_mode' => $view_mode],
Chris@0 177 TRUE,
Chris@0 178 TRUE,
Chris@0 179 TRUE,
Chris@0 180 TRUE,
Chris@0 181 [],
Chris@0 182 ];
Chris@0 183 }
Chris@0 184 // All other combinations.
Chris@0 185 $combinations = [
Chris@0 186 'is_anonymous' => [FALSE, TRUE],
Chris@0 187 'comment_count' => [0, 1],
Chris@0 188 'has_access_comments' => [0, 1],
Chris@0 189 'history_exists' => [FALSE, TRUE],
Chris@0 190 'has_post_comments' => [0, 1],
Chris@0 191 'form_location' => [CommentItemInterface::FORM_BELOW, CommentItemInterface::FORM_SEPARATE_PAGE],
Chris@0 192 'comments' => [
Chris@0 193 CommentItemInterface::OPEN,
Chris@0 194 CommentItemInterface::CLOSED,
Chris@0 195 CommentItemInterface::HIDDEN,
Chris@0 196 ],
Chris@0 197 'view_mode' => [
Chris@0 198 'teaser', 'rss', 'full',
Chris@0 199 ],
Chris@0 200 ];
Chris@0 201 $permutations = $this->generatePermutations($combinations);
Chris@0 202 foreach ($permutations as $combination) {
Chris@0 203 $case = [
Chris@0 204 $this->getMockNode(TRUE, $combination['comments'], $combination['form_location'], $combination['comment_count']),
Chris@0 205 ['view_mode' => $combination['view_mode']],
Chris@0 206 $combination['has_access_comments'],
Chris@0 207 $combination['history_exists'],
Chris@0 208 $combination['has_post_comments'],
Chris@0 209 $combination['is_anonymous'],
Chris@0 210 ];
Chris@0 211 $expected = [];
Chris@0 212 // When comments are enabled in teaser mode, and comments exist, and the
Chris@0 213 // user has access - we can output the comment count.
Chris@0 214 if ($combination['comments'] && $combination['view_mode'] == 'teaser' && $combination['comment_count'] && $combination['has_access_comments']) {
Chris@0 215 $expected['comment-comments'] = '1 comment';
Chris@0 216 // And if history module exists, we can show a 'new comments' link.
Chris@0 217 if ($combination['history_exists']) {
Chris@0 218 $expected['comment-new-comments'] = '';
Chris@0 219 }
Chris@0 220 }
Chris@0 221 // All view modes other than RSS.
Chris@0 222 if ($combination['view_mode'] != 'rss') {
Chris@0 223 // Where commenting is open.
Chris@0 224 if ($combination['comments'] == CommentItemInterface::OPEN) {
Chris@0 225 // And the user has post-comments permission.
Chris@0 226 if ($combination['has_post_comments']) {
Chris@0 227 // If the view mode is teaser, or the user can access comments and
Chris@0 228 // comments exist or the form is on a separate page.
Chris@0 229 if ($combination['view_mode'] == 'teaser' || ($combination['has_access_comments'] && $combination['comment_count']) || $combination['form_location'] == CommentItemInterface::FORM_SEPARATE_PAGE) {
Chris@0 230 // There should be a add comment link.
Chris@0 231 $expected['comment-add'] = ['title' => 'Add new comment'];
Chris@0 232 if ($combination['form_location'] == CommentItemInterface::FORM_BELOW) {
Chris@0 233 // On the same page.
Chris@0 234 $expected['comment-add']['url'] = Url::fromRoute('node.view');
Chris@0 235 }
Chris@0 236 else {
Chris@0 237 // On a separate page.
Chris@0 238 $expected['comment-add']['url'] = Url::fromRoute('comment.reply', ['entity_type' => 'node', 'entity' => 1, 'field_name' => 'comment']);
Chris@0 239 }
Chris@0 240 }
Chris@0 241 }
Chris@0 242 elseif ($combination['is_anonymous']) {
Chris@0 243 // Anonymous users get the forbidden message if the can't post
Chris@0 244 // comments.
Chris@0 245 $expected['comment-forbidden'] = "Can't let you do that Dave.";
Chris@0 246 }
Chris@0 247 }
Chris@0 248 }
Chris@0 249
Chris@0 250 $case[] = $expected;
Chris@0 251 $cases[] = $case;
Chris@0 252 }
Chris@0 253 return $cases;
Chris@0 254 }
Chris@0 255
Chris@0 256 /**
Chris@0 257 * Builds a mock node based on given scenario.
Chris@0 258 *
Chris@0 259 * @param bool $has_field
Chris@0 260 * TRUE if the node has the 'comment' field.
Chris@0 261 * @param int $comment_status
Chris@0 262 * One of CommentItemInterface::OPEN|HIDDEN|CLOSED
Chris@0 263 * @param int $form_location
Chris@0 264 * One of CommentItemInterface::FORM_BELOW|FORM_SEPARATE_PAGE
Chris@0 265 * @param int $comment_count
Chris@0 266 * Number of comments against the field.
Chris@0 267 *
Chris@0 268 * @return \Drupal\node\NodeInterface|\PHPUnit_Framework_MockObject_MockObject
Chris@0 269 * Mock node for testing.
Chris@0 270 */
Chris@0 271 protected function getMockNode($has_field, $comment_status, $form_location, $comment_count) {
Chris@0 272 $node = $this->getMock('\Drupal\node\NodeInterface');
Chris@14 273 $node->expects($this->any())
Chris@0 274 ->method('hasField')
Chris@0 275 ->willReturn($has_field);
Chris@0 276
Chris@0 277 if (empty($this->timestamp)) {
Chris@0 278 $this->timestamp = time();
Chris@0 279 }
Chris@0 280 $field_item = (object) [
Chris@0 281 'status' => $comment_status,
Chris@0 282 'comment_count' => $comment_count,
Chris@0 283 'last_comment_timestamp' => $this->timestamp,
Chris@0 284 ];
Chris@0 285 $node->expects($this->any())
Chris@0 286 ->method('get')
Chris@0 287 ->with('comment')
Chris@0 288 ->willReturn($field_item);
Chris@0 289
Chris@0 290 $field_definition = $this->getMock('\Drupal\Core\Field\FieldDefinitionInterface');
Chris@0 291 $field_definition->expects($this->any())
Chris@0 292 ->method('getSetting')
Chris@0 293 ->with('form_location')
Chris@0 294 ->willReturn($form_location);
Chris@0 295 $node->expects($this->any())
Chris@0 296 ->method('getFieldDefinition')
Chris@0 297 ->with('comment')
Chris@0 298 ->willReturn($field_definition);
Chris@0 299
Chris@0 300 $node->expects($this->any())
Chris@0 301 ->method('language')
Chris@0 302 ->willReturn('und');
Chris@0 303
Chris@0 304 $node->expects($this->any())
Chris@0 305 ->method('getEntityTypeId')
Chris@0 306 ->willReturn('node');
Chris@0 307
Chris@0 308 $node->expects($this->any())
Chris@0 309 ->method('id')
Chris@0 310 ->willReturn(1);
Chris@0 311
Chris@0 312 $url = Url::fromRoute('node.view');
Chris@0 313 $node->expects($this->any())
Chris@17 314 ->method('toUrl')
Chris@0 315 ->willReturn($url);
Chris@0 316 $node->expects($this->any())
Chris@0 317 ->method('url')
Chris@0 318 ->willReturn(['route_name' => 'node.view']);
Chris@0 319
Chris@0 320 return $node;
Chris@0 321 }
Chris@0 322
Chris@0 323 }
Chris@0 324
Chris@0 325 namespace Drupal\comment;
Chris@0 326
Chris@0 327 if (!function_exists('history_read')) {
Chris@17 328
Chris@0 329 function history_read() {
Chris@0 330 return 0;
Chris@0 331 }
Chris@17 332
Chris@0 333 }