Pull merge.
[yaffs-website] / web / core / modules / comment / tests / src / Functional / CommentNewIndicatorTest.php
1 <?php
2
3 namespace Drupal\Tests\comment\Functional;
4
5 use Drupal\Component\Serialization\Json;
6 use Drupal\Core\Language\LanguageInterface;
7 use Drupal\comment\CommentInterface;
8 use Drupal\Core\Url;
9 use Drupal\comment\Entity\Comment;
10
11 /**
12  * Tests the 'new' indicator posted on comments.
13  *
14  * @group comment
15  */
16 class CommentNewIndicatorTest extends CommentTestBase {
17
18   /**
19    * Use the main node listing to test rendering on teasers.
20    *
21    * @var array
22    *
23    * @todo Remove this dependency.
24    */
25   public static $modules = ['views'];
26
27   /**
28    * Get node "x new comments" metadata from the server for the current user.
29    *
30    * @param array $node_ids
31    *   An array of node IDs.
32    *
33    * @return \Psr\Http\Message\ResponseInterface
34    *   The HTTP response.
35    */
36   protected function renderNewCommentsNodeLinks(array $node_ids) {
37     $client = $this->getHttpClient();
38     $url = Url::fromRoute('comment.new_comments_node_links');
39
40     return $client->request('POST', $this->buildUrl($url), [
41       'cookies' => $this->getSessionCookies(),
42       'http_errors' => FALSE,
43       'form_params' => [
44         'node_ids' => $node_ids,
45         'field_name' => 'comment',
46       ],
47     ]);
48   }
49
50   /**
51    * Tests new comment marker.
52    */
53   public function testCommentNewCommentsIndicator() {
54     // Test if the right links are displayed when no comment is present for the
55     // node.
56     $this->drupalLogin($this->adminUser);
57     $this->drupalGet('node');
58     $this->assertNoLink(t('@count comments', ['@count' => 0]));
59     $this->assertLink(t('Read more'));
60     // Verify the data-history-node-last-comment-timestamp attribute, which is
61     // used by the drupal.node-new-comments-link library to determine whether
62     // a "x new comments" link might be necessary or not. We do this in
63     // JavaScript to prevent breaking the render cache.
64     $this->assertIdentical(0, count($this->xpath('//*[@data-history-node-last-comment-timestamp]')), 'data-history-node-last-comment-timestamp attribute is not set.');
65
66     // Create a new comment. This helper function may be run with different
67     // comment settings so use $comment->save() to avoid complex setup.
68     /** @var \Drupal\comment\CommentInterface $comment */
69     $comment = Comment::create([
70       'cid' => NULL,
71       'entity_id' => $this->node->id(),
72       'entity_type' => 'node',
73       'field_name' => 'comment',
74       'pid' => 0,
75       'uid' => $this->loggedInUser->id(),
76       'status' => CommentInterface::PUBLISHED,
77       'subject' => $this->randomMachineName(),
78       'hostname' => '127.0.0.1',
79       'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
80       'comment_body' => [LanguageInterface::LANGCODE_NOT_SPECIFIED => [$this->randomMachineName()]],
81     ]);
82     $comment->save();
83     $this->drupalLogout();
84
85     // Log in with 'web user' and check comment links.
86     $this->drupalLogin($this->webUser);
87     $this->drupalGet('node');
88     // Verify the data-history-node-last-comment-timestamp attribute. Given its
89     // value, the drupal.node-new-comments-link library would determine that the
90     // node received a comment after the user last viewed it, and hence it would
91     // perform an HTTP request to render the "new comments" node link.
92     $this->assertIdentical(1, count($this->xpath('//*[@data-history-node-last-comment-timestamp="' . $comment->getChangedTime() . '"]')), 'data-history-node-last-comment-timestamp attribute is set to the correct value.');
93     $this->assertIdentical(1, count($this->xpath('//*[@data-history-node-field-name="comment"]')), 'data-history-node-field-name attribute is set to the correct value.');
94     // The data will be pre-seeded on this particular page in drupalSettings, to
95     // avoid the need for the client to make a separate request to the server.
96     $settings = $this->getDrupalSettings();
97     $this->assertEqual($settings['history'], ['lastReadTimestamps' => [1 => 0]]);
98     $this->assertEqual($settings['comment'], [
99       'newCommentsLinks' => [
100         'node' => [
101           'comment' => [
102             1 => [
103               'new_comment_count' => 1,
104               'first_new_comment_link' => Url::fromRoute('entity.node.canonical', ['node' => 1])->setOptions([
105                 'fragment' => 'new',
106               ])->toString(),
107             ],
108           ],
109         ],
110       ],
111     ]);
112     // Pretend the data was not present in drupalSettings, i.e. test the
113     // separate request to the server.
114     $response = $this->renderNewCommentsNodeLinks([$this->node->id()]);
115     $this->assertSame(200, $response->getStatusCode());
116     $json = Json::decode($response->getBody());
117     $expected = [
118       $this->node->id() => [
119         'new_comment_count' => 1,
120         'first_new_comment_link' => $this->node->url('canonical', ['fragment' => 'new']),
121       ],
122     ];
123     $this->assertIdentical($expected, $json);
124
125     // Failing to specify node IDs for the endpoint should return a 404.
126     $response = $this->renderNewCommentsNodeLinks([]);
127     $this->assertSame(404, $response->getStatusCode());
128
129     // Accessing the endpoint as the anonymous user should return a 403.
130     $this->drupalLogout();
131     $response = $this->renderNewCommentsNodeLinks([$this->node->id()]);
132     $this->assertSame(403, $response->getStatusCode());
133     $response = $this->renderNewCommentsNodeLinks([]);
134     $this->assertSame(403, $response->getStatusCode());
135   }
136
137 }