Issue #1479454 by Hugo Wetterberg, galooph, dawehner, andypost, marcingy, heyrocker...
[project/drupal.git] / core / modules / comment / lib / Drupal / comment / Tests / CommentLinksTest.php
1 <?php
2
3 /**
4 * @file
5 * Contains Drupal\comment\Tests\CommentLinksTest.
6 */
7
8 namespace Drupal\comment\Tests;
9
10 /**
11 * Tests comment links based on environment configurations.
12 */
13 class CommentLinksTest extends CommentTestBase {
14
15 public static function getInfo() {
16 return array(
17 'name' => 'Comment links',
18 'description' => 'Tests comment links based on environment configurations.',
19 'group' => 'Comment',
20 );
21 }
22
23 /**
24 * Tests comment links.
25 *
26 * The output of comment links depends on various environment conditions:
27 * - Various Comment module configuration settings, user registration
28 * settings, and user access permissions.
29 * - Whether the user is authenticated or not, and whether any comments exist.
30 *
31 * To account for all possible cases, this test creates permutations of all
32 * possible conditions and tests the expected appearance of comment links in
33 * each environment.
34 */
35 function testCommentLinks() {
36 // Bartik theme alters comment links, so use a different theme.
37 theme_enable(array('stark'));
38 variable_set('theme_default', 'stark');
39
40 // Remove additional user permissions from $this->web_user added by setUp(),
41 // since this test is limited to anonymous and authenticated roles only.
42 entity_delete_multiple('user_role', array(key($this->web_user->roles)));
43
44 // Matrix of possible environmental conditions and configuration settings.
45 // See setEnvironment() for details.
46 $conditions = array(
47 'authenticated' => array(FALSE, TRUE),
48 'comment count' => array(FALSE, TRUE),
49 'access comments' => array(0, 1),
50 'post comments' => array(0, 1),
51 'form' => array(COMMENT_FORM_BELOW, COMMENT_FORM_SEPARATE_PAGE),
52 // USER_REGISTER_VISITORS_ADMINISTRATIVE_APPROVAL is irrelevant for this
53 // test; there is only a difference between open and closed registration.
54 'user_register' => array(USER_REGISTER_VISITORS, USER_REGISTER_ADMINISTRATORS_ONLY),
55 // @todo Complete test coverage for:
56 //'comments' => array(COMMENT_NODE_OPEN, COMMENT_NODE_CLOSED, COMMENT_NODE_HIDDEN),
57 //// COMMENT_ANONYMOUS_MUST_CONTACT is irrelevant for this test.
58 //'contact ' => array(COMMENT_ANONYMOUS_MAY_CONTACT, COMMENT_ANONYMOUS_MAYNOT_CONTACT),
59 );
60
61 $environments = $this->generatePermutations($conditions);
62 foreach ($environments as $info) {
63 $this->assertCommentLinks($info);
64 }
65 }
66
67 /**
68 * Re-configures the environment, module settings, and user permissions.
69 *
70 * @param $info
71 * An associative array describing the environment to setup:
72 * - Environment conditions:
73 * - authenticated: Boolean whether to test with $this->web_user or
74 * anonymous.
75 * - comment count: Boolean whether to test with a new/unread comment on
76 * $this->node or no comments.
77 * - Configuration settings:
78 * - form: COMMENT_FORM_BELOW or COMMENT_FORM_SEPARATE_PAGE.
79 * - user_register: USER_REGISTER_ADMINISTRATORS_ONLY or
80 * USER_REGISTER_VISITORS.
81 * - contact: COMMENT_ANONYMOUS_MAY_CONTACT or
82 * COMMENT_ANONYMOUS_MAYNOT_CONTACT.
83 * - comments: COMMENT_NODE_OPEN, COMMENT_NODE_CLOSED, or
84 * COMMENT_NODE_HIDDEN.
85 * - User permissions:
86 * These are granted or revoked for the user, according to the
87 * 'authenticated' flag above. Pass 0 or 1 as parameter values. See
88 * user_role_change_permissions().
89 * - access comments
90 * - post comments
91 * - skip comment approval
92 * - edit own comments
93 */
94 function setEnvironment(array $info) {
95 static $current;
96
97 // Apply defaults to initial environment.
98 if (!isset($current)) {
99 $current = array(
100 'authenticated' => FALSE,
101 'comment count' => FALSE,
102 'form' => COMMENT_FORM_BELOW,
103 'user_register' => USER_REGISTER_VISITORS,
104 'contact' => COMMENT_ANONYMOUS_MAY_CONTACT,
105 'comments' => COMMENT_NODE_OPEN,
106 'access comments' => 0,
107 'post comments' => 0,
108 // Enabled by default, because it's irrelevant for this test.
109 'skip comment approval' => 1,
110 'edit own comments' => 0,
111 );
112 }
113 // Complete new environment with current environment.
114 $info = array_merge($current, $info);
115
116 // Change environment conditions.
117 if ($current['authenticated'] != $info['authenticated']) {
118 if ($this->loggedInUser) {
119 $this->drupalLogout();
120 }
121 else {
122 $this->drupalLogin($this->web_user);
123 }
124 }
125 if ($current['comment count'] != $info['comment count']) {
126 if ($info['comment count']) {
127 // Create a comment via CRUD API functionality, since
128 // $this->postComment() relies on actual user permissions.
129 $comment = entity_create('comment', array(
130 'cid' => NULL,
131 'nid' => $this->node->nid,
132 'node_type' => $this->node->type,
133 'pid' => 0,
134 'uid' => 0,
135 'status' => COMMENT_PUBLISHED,
136 'subject' => $this->randomName(),
137 'hostname' => ip_address(),
138 'langcode' => LANGUAGE_NOT_SPECIFIED,
139 'comment_body' => array(LANGUAGE_NOT_SPECIFIED => array($this->randomName())),
140 ));
141 comment_save($comment);
142 $this->comment = $comment;
143
144 // comment_num_new() relies on history_read(), so ensure that no one has
145 // seen the node of this comment.
146 db_delete('history')->condition('nid', $this->node->nid)->execute();
147 }
148 else {
149 $cids = db_query("SELECT cid FROM {comment}")->fetchCol();
150 comment_delete_multiple($cids);
151 unset($this->comment);
152 }
153 }
154
155 // Change comment settings.
156 variable_set('comment_form_location_' . $this->node->type, $info['form']);
157 variable_set('comment_anonymous_' . $this->node->type, $info['contact']);
158 if ($this->node->comment != $info['comments']) {
159 $this->node->comment = $info['comments'];
160 node_save($this->node);
161 }
162
163 // Change user settings.
164 config('user.settings')->set('register', $info['user_register'])->save();
165
166 // Change user permissions.
167 $rid = ($this->loggedInUser ? DRUPAL_AUTHENTICATED_RID : DRUPAL_ANONYMOUS_RID);
168 $perms = array_intersect_key($info, array('access comments' => 1, 'post comments' => 1, 'skip comment approval' => 1, 'edit own comments' => 1));
169 user_role_change_permissions($rid, $perms);
170
171 // Output verbose debugging information.
172 // @see Drupal\simpletest\TestBase::error()
173 $t_form = array(
174 COMMENT_FORM_BELOW => 'below',
175 COMMENT_FORM_SEPARATE_PAGE => 'separate page',
176 );
177 $t_contact = array(
178 COMMENT_ANONYMOUS_MAY_CONTACT => 'optional',
179 COMMENT_ANONYMOUS_MAYNOT_CONTACT => 'disabled',
180 COMMENT_ANONYMOUS_MUST_CONTACT => 'required',
181 );
182 $t_comments = array(
183 COMMENT_NODE_OPEN => 'open',
184 COMMENT_NODE_CLOSED => 'closed',
185 COMMENT_NODE_HIDDEN => 'hidden',
186 );
187 $verbose = $info;
188 $verbose['form'] = $t_form[$info['form']];
189 $verbose['contact'] = $t_contact[$info['contact']];
190 $verbose['comments'] = $t_comments[$info['comments']];
191 $message = t('Changed environment:<pre>@verbose</pre>', array(
192 '@verbose' => var_export($verbose, TRUE),
193 ));
194 $this->assert('debug', $message, 'Debug');
195
196 // Update current environment.
197 $current = $info;
198
199 return $info;
200 }
201
202 /**
203 * Asserts that comment links appear according to the passed environment.
204 *
205 * @param $info
206 * An associative array describing the environment to pass to
207 * setEnvironment().
208 */
209 function assertCommentLinks(array $info) {
210 $info = $this->setEnvironment($info);
211
212 $nid = $this->node->nid;
213
214 foreach (array('node', "node/$nid") as $path) {
215 $this->drupalGet($path);
216
217 // User is allowed to view comments.
218 if ($info['access comments']) {
219 if ($path == '') {
220 // In teaser view, a link containing the comment count is always
221 // expected.
222 if ($info['comment count']) {
223 $this->assertLink(t('1 comment'));
224
225 // For logged in users, a link containing the amount of new/unread
226 // comments is expected.
227 // See important note about comment_num_new() below.
228 if ($this->loggedInUser && isset($this->comment) && !isset($this->comment->seen)) {
229 $this->assertLink(t('1 new comment'));
230 $this->comment->seen = TRUE;
231 }
232 }
233 }
234 }
235 else {
236 $this->assertNoLink(t('1 comment'));
237 $this->assertNoLink(t('1 new comment'));
238 }
239 // comment_num_new() is based on node views, so comments are marked as
240 // read when a node is viewed, regardless of whether we have access to
241 // comments.
242 if ($path == "node/$nid" && $this->loggedInUser && isset($this->comment)) {
243 $this->comment->seen = TRUE;
244 }
245
246 // User is not allowed to post comments.
247 if (!$info['post comments']) {
248 $this->assertNoLink('Add new comment');
249
250 // Anonymous users should see a note to log in or register in case
251 // authenticated users are allowed to post comments.
252 // @see theme_comment_post_forbidden()
253 if (!$this->loggedInUser) {
254 if (user_access('post comments', $this->web_user)) {
255 // The note depends on whether users are actually able to register.
256 if ($info['user_register'] != USER_REGISTER_ADMINISTRATORS_ONLY) {
257 $this->assertText('Log in or register to post comments');
258 }
259 else {
260 $this->assertText('Log in to post comments');
261 }
262 }
263 else {
264 $this->assertNoText('Log in or register to post comments');
265 $this->assertNoText('Log in to post comments');
266 }
267 }
268 }
269 // User is allowed to post comments.
270 else {
271 $this->assertNoText('Log in or register to post comments');
272
273 // "Add new comment" is always expected, except when there are no
274 // comments or if the user cannot see them.
275 if ($path == "node/$nid" && $info['form'] == COMMENT_FORM_BELOW && (!$info['comment count'] || !$info['access comments'])) {
276 $this->assertNoLink('Add new comment');
277 }
278 else {
279 $this->assertLink('Add new comment');
280
281 // Verify that the "Add new comment" link points to the correct URL
282 // based on the comment form location configuration.
283 if ($info['form'] == COMMENT_FORM_SEPARATE_PAGE) {
284 $this->assertLinkByHref("comment/reply/$nid#comment-form", 0, 'Comment form link destination is on a separate page.');
285 $this->assertNoLinkByHref("node/$nid#comment-form");
286 }
287 else {
288 $this->assertLinkByHref("node/$nid#comment-form", 0, 'Comment form link destination is on node.');
289 $this->assertNoLinkByHref("comment/reply/$nid#comment-form");
290 }
291 }
292
293 // Also verify that the comment form appears according to the configured
294 // location.
295 if ($path == "node/$nid") {
296 $elements = $this->xpath('//form[@id=:id]', array(':id' => 'comment-form'));
297 if ($info['form'] == COMMENT_FORM_BELOW) {
298 $this->assertTrue(count($elements), 'Comment form found below.');
299 }
300 else {
301 $this->assertFalse(count($elements), 'Comment form not found below.');
302 }
303 }
304 }
305 }
306 }
307
308 }