annotate core/modules/comment/tests/src/Unit/CommentLinkBuilderTest.php @ 17:129ea1e6d783

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