Completed
Push — master ( 9dab44...8bd79e )
by Robbie
02:00
created

tests/CommentsTest.php (18 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace SilverStripe\Comments\Tests;
4
5
use HTMLPurifier_Config;
6
use HTMLPurifier;
7
use ReflectionClass;
8
use SilverStripe\Comments\Extensions\CommentsExtension;
9
use SilverStripe\Comments\Model\Comment;
10
use SilverStripe\Comments\Tests\Stubs\CommentableItem;
11
use SilverStripe\Comments\Tests\Stubs\CommentableItemDisabled;
12
use SilverStripe\Comments\Tests\Stubs\CommentableItemEnabled;
13
use SilverStripe\Control\Controller;
14
use SilverStripe\Control\Director;
15
use SilverStripe\Core\Config\Config;
16
use SilverStripe\Core\Email\Email;
17
use SilverStripe\Dev\FunctionalTest;
18
use SilverStripe\Dev\TestOnly;
19
use SilverStripe\i18n\i18n;
20
use SilverStripe\ORM\DataObject;
21
use SilverStripe\Security\Member;
22
use SilverStripe\Security\Security;
23
use SilverStripe\Security\Permission;
24
25
class CommentsTest extends FunctionalTest
26
{
27
    protected static $fixture_file = 'CommentsTest.yml';
28
29
    protected static $extra_dataobjects = array(
30
        CommentableItem::class,
31
        CommentableItemEnabled::class,
32
        CommentableItemDisabled::class
33
    );
34
35
    public function setUp()
36
    {
37
        parent::setUp();
38
39
        // Set good default values
40
        Config::modify()->merge(CommentsExtension::class, 'comments', array(
41
            'enabled' => true,
42
            'comment_permalink_prefix' => 'comment-'
43
        ));
44
    }
45
46
    public function testCommentsList()
47
    {
48
        // comments don't require moderation so unmoderated comments can be
49
        // shown but not spam posts
50
        Config::modify()->merge(CommentableItem::class, 'comments', array(
51
            'require_moderation_nonmembers' => false,
52
            'require_moderation' => false,
53
            'require_moderation_cms' => false,
54
        ));
55
56
        $item = $this->objFromFixture(CommentableItem::class, 'spammed');
57
58
        $this->assertDOSEquals(array(
59
            array('Name' => 'Comment 1'),
60
            array('Name' => 'Comment 3')
61
        ), $item->Comments(), 'Only 2 non spam posts should be shown');
62
63
        // when moderated, only moderated, non spam posts should be shown.
64
        Config::modify()->merge(CommentableItem::class, 'comments', array('require_moderation_nonmembers' => true));
65
66
        // Check that require_moderation overrides this option
67
        Config::modify()->merge(CommentableItem::class, 'comments', array('require_moderation' => true));
68
69
        $this->assertDOSEquals(array(
70
            array('Name' => 'Comment 3')
71
        ), $item->Comments(), 'Only 1 non spam, moderated post should be shown');
72
        $this->assertEquals(1, $item->Comments()->Count());
73
74
        // require_moderation_nonmembers still filters out unmoderated comments
75
        Config::modify()->merge(CommentableItem::class, 'comments', array('require_moderation' => false));
76
        $this->assertEquals(1, $item->Comments()->Count());
77
78
        Config::modify()->merge(CommentableItem::class, 'comments', array('require_moderation_nonmembers' => false));
79
        $this->assertEquals(2, $item->Comments()->Count());
80
81
        // With unmoderated comments set to display in frontend
82
        Config::modify()->merge(CommentableItem::class, 'comments', array(
83
            'require_moderation' => true,
84
            'frontend_moderation' => true
85
        ));
86
        $this->assertEquals(1, $item->Comments()->Count());
87
88
        $this->logInWithPermission('ADMIN');
89
        $this->assertEquals(2, $item->Comments()->Count());
90
91
        // With spam comments set to display in frontend
92
        Config::modify()->merge(CommentableItem::class, 'comments', array(
93
            'require_moderation' => true,
94
            'frontend_moderation' => false,
95
            'frontend_spam' => true,
96
        ));
97
        if ($member = Member::currentUser()) {
0 ignored issues
show
Deprecated Code introduced by
The method SilverStripe\Security\Member::currentUser() has been deprecated with message: 5.0.0 use Security::getCurrentUser()

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
98
            $member->logOut();
0 ignored issues
show
Deprecated Code introduced by
The method SilverStripe\Security\Member::logOut() has been deprecated with message: Use Security::setCurrentUser(null) or an IdentityStore
Logs this member out.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
99
        }
100
        $this->assertEquals(1, $item->Comments()->Count());
101
102
        $this->logInWithPermission('ADMIN');
103
        $this->assertEquals(2, $item->Comments()->Count());
104
105
106
        // With spam and unmoderated comments set to display in frontend
107
        Config::modify()->merge(CommentableItem::class, 'comments', array(
108
            'require_moderation' => true,
109
            'frontend_moderation' => true,
110
            'frontend_spam' => true,
111
        ));
112
        if ($member = Member::currentUser()) {
0 ignored issues
show
Deprecated Code introduced by
The method SilverStripe\Security\Member::currentUser() has been deprecated with message: 5.0.0 use Security::getCurrentUser()

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
113
            $member->logOut();
0 ignored issues
show
Deprecated Code introduced by
The method SilverStripe\Security\Member::logOut() has been deprecated with message: Use Security::setCurrentUser(null) or an IdentityStore
Logs this member out.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
114
        }
115
        $this->assertEquals(1, $item->Comments()->Count());
116
117
        $this->logInWithPermission('ADMIN');
118
        $this->assertEquals(4, $item->Comments()->Count());
119
    }
120
121
    /**
122
     * Test moderation options configured via the CMS
123
     */
124
    public function testCommentCMSModerationList()
125
    {
126
        Config::modify()->merge(CommentableItem::class, 'comments', array(
127
            'require_moderation' => true,
128
            'require_moderation_cms' => true,
129
        ));
130
131
        $item = $this->objFromFixture(CommentableItem::class, 'spammed');
132
133
        $this->assertEquals('None', $item->getModerationRequired());
134
135
        $this->assertDOSEquals(array(
136
            array('Name' => 'Comment 1'),
137
            array('Name' => 'Comment 3')
138
        ), $item->Comments(), 'Only 2 non spam posts should be shown');
139
140
        // when moderated, only moderated, non spam posts should be shown.
141
        $item->ModerationRequired = 'NonMembersOnly';
142
        $item->write();
143
144
        $this->assertEquals('NonMembersOnly', $item->getModerationRequired());
145
146
        // Check that require_moderation overrides this option
147
        $item->ModerationRequired = 'Required';
148
        $item->write();
149
        $this->assertEquals('Required', $item->getModerationRequired());
150
151
        $this->assertDOSEquals(array(
152
            array('Name' => 'Comment 3')
153
        ), $item->Comments(), 'Only 1 non spam, moderated post should be shown');
154
        $this->assertEquals(1, $item->Comments()->Count());
155
156
        // require_moderation_nonmembers still filters out unmoderated comments
157
        $item->ModerationRequired = 'NonMembersOnly';
158
        $item->write();
159
        $this->assertEquals(1, $item->Comments()->Count());
160
161
        $item->ModerationRequired = 'None';
162
        $item->write();
163
        $this->assertEquals(2, $item->Comments()->Count());
164
    }
165
166
    public function testCanPostComment()
167
    {
168
        Config::modify()->merge(CommentableItem::class, 'comments', array(
169
            'require_login' => false,
170
            'require_login_cms' => false,
171
            'required_permission' => false,
172
        ));
173
        $item = $this->objFromFixture(CommentableItem::class, 'first');
174
        $item2 = $this->objFromFixture(CommentableItem::class, 'second');
175
176
        // Test restriction free commenting
177
        if ($member = Member::currentUser()) {
0 ignored issues
show
Deprecated Code introduced by
The method SilverStripe\Security\Member::currentUser() has been deprecated with message: 5.0.0 use Security::getCurrentUser()

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
178
            $member->logOut();
0 ignored issues
show
Deprecated Code introduced by
The method SilverStripe\Security\Member::logOut() has been deprecated with message: Use Security::setCurrentUser(null) or an IdentityStore
Logs this member out.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
179
        }
180
        $this->assertFalse($item->CommentsRequireLogin);
181
        $this->assertTrue($item->canPostComment());
182
183
        // Test permission required to post
184
        Config::modify()->merge(CommentableItem::class, 'comments', array(
185
            'require_login' => true,
186
            'required_permission' => 'POSTING_PERMISSION',
187
        ));
188
        $this->assertTrue($item->CommentsRequireLogin);
189
        $this->assertFalse($item->canPostComment());
190
        $this->logInWithPermission('WRONG_ONE');
191
        $this->assertFalse($item->canPostComment());
192
        $this->logInWithPermission('POSTING_PERMISSION');
193
        $this->assertTrue($item->canPostComment());
194
        $this->logInWithPermission('ADMIN');
195
        $this->assertTrue($item->canPostComment());
196
197
        // Test require login to post, but not any permissions
198
        Config::modify()->merge(CommentableItem::class, 'comments', array(
199
            'required_permission' => false,
200
        ));
201
        $this->assertTrue($item->CommentsRequireLogin);
202
        if ($member = Member::currentUser()) {
0 ignored issues
show
Deprecated Code introduced by
The method SilverStripe\Security\Member::currentUser() has been deprecated with message: 5.0.0 use Security::getCurrentUser()

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
203
            $member->logOut();
0 ignored issues
show
Deprecated Code introduced by
The method SilverStripe\Security\Member::logOut() has been deprecated with message: Use Security::setCurrentUser(null) or an IdentityStore
Logs this member out.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
204
        }
205
        $this->assertFalse($item->canPostComment());
206
        $this->logInWithPermission('ANY_PERMISSION');
207
        $this->assertTrue($item->canPostComment());
208
209
        // Test options set via CMS
210
        Config::modify()->merge(CommentableItem::class, 'comments', array(
211
            'require_login' => true,
212
            'require_login_cms' => true,
213
        ));
214
        $this->assertFalse($item->CommentsRequireLogin);
215
        $this->assertTrue($item2->CommentsRequireLogin);
216
        if ($member = Member::currentUser()) {
0 ignored issues
show
Deprecated Code introduced by
The method SilverStripe\Security\Member::currentUser() has been deprecated with message: 5.0.0 use Security::getCurrentUser()

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
217
            $member->logOut();
0 ignored issues
show
Deprecated Code introduced by
The method SilverStripe\Security\Member::logOut() has been deprecated with message: Use Security::setCurrentUser(null) or an IdentityStore
Logs this member out.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
218
        }
219
        $this->assertTrue($item->canPostComment());
220
        $this->assertFalse($item2->canPostComment());
221
222
        // Login grants permission to post
223
        $this->logInWithPermission('ANY_PERMISSION');
224
        $this->assertTrue($item->canPostComment());
225
        $this->assertTrue($item2->canPostComment());
226
    }
227
    public function testDeleteComment()
228
    {
229
        // Test anonymous user
230
        if ($member = Member::currentUser()) {
0 ignored issues
show
Deprecated Code introduced by
The method SilverStripe\Security\Member::currentUser() has been deprecated with message: 5.0.0 use Security::getCurrentUser()

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
231
            $member->logOut();
0 ignored issues
show
Deprecated Code introduced by
The method SilverStripe\Security\Member::logOut() has been deprecated with message: Use Security::setCurrentUser(null) or an IdentityStore
Logs this member out.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
232
        }
233
        $comment = $this->objFromFixture(Comment::class, 'firstComA');
234
        $commentID = $comment->ID;
235
        $this->assertNull($comment->DeleteLink(), 'No permission to see delete link');
236
        $delete = $this->get('comments/delete/' . $comment->ID . '?ajax=1');
237
        $this->assertEquals(403, $delete->getStatusCode());
238
        $check = DataObject::get_by_id(Comment::class, $commentID);
239
        $this->assertTrue($check && $check->exists());
240
241
        // Test non-authenticated user
242
        $this->logInAs('visitor');
243
        $this->assertNull($comment->DeleteLink(), 'No permission to see delete link');
244
245
        // Test authenticated user
246
        $this->logInAs('commentadmin');
247
        $comment = $this->objFromFixture(Comment::class, 'firstComA');
248
        $commentID = $comment->ID;
249
        $adminComment1Link = $comment->DeleteLink();
250
        $this->assertContains('comments/delete/' . $commentID . '?t=', $adminComment1Link);
251
252
        // Test that this link can't be shared / XSS exploited
253
        $this->logInAs('commentadmin2');
254
        $delete = $this->get($adminComment1Link);
255
        $this->assertEquals(400, $delete->getStatusCode());
256
        $check = DataObject::get_by_id(Comment::class, $commentID);
257
        $this->assertTrue($check && $check->exists());
258
259
        // Test that this other admin can delete the comment with their own link
260
        $adminComment2Link = $comment->DeleteLink();
261
        $this->assertNotEquals($adminComment2Link, $adminComment1Link);
262
        $this->autoFollowRedirection = false;
263
        $delete = $this->get($adminComment2Link);
264
        $this->assertEquals(302, $delete->getStatusCode());
265
        $check = DataObject::get_by_id(Comment::class, $commentID);
266
        $this->assertFalse($check && $check->exists());
267
    }
268
269 View Code Duplication
    public function testSpamComment()
270
    {
271
        // Test anonymous user
272
        if ($member = Member::currentUser()) {
0 ignored issues
show
Deprecated Code introduced by
The method SilverStripe\Security\Member::currentUser() has been deprecated with message: 5.0.0 use Security::getCurrentUser()

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
273
            $member->logOut();
0 ignored issues
show
Deprecated Code introduced by
The method SilverStripe\Security\Member::logOut() has been deprecated with message: Use Security::setCurrentUser(null) or an IdentityStore
Logs this member out.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
274
        }
275
        $comment = $this->objFromFixture(Comment::class, 'firstComA');
276
        $commentID = $comment->ID;
277
        $this->assertNull($comment->SpamLink(), 'No permission to see mark as spam link');
278
        $spam = $this->get('comments/spam/'.$comment->ID.'?ajax=1');
279
        $this->assertEquals(403, $spam->getStatusCode());
280
        $check = DataObject::get_by_id(Comment::class, $commentID);
281
        $this->assertEquals(0, $check->IsSpam, 'No permission to mark as spam');
282
283
        // Test non-authenticated user
284
        $this->logInAs('visitor');
285
        $this->assertNull($comment->SpamLink(), 'No permission to see mark as spam link');
286
287
        // Test authenticated user
288
        $this->logInAs('commentadmin');
289
        $comment = $this->objFromFixture(Comment::class, 'firstComA');
290
        $commentID = $comment->ID;
291
        $adminComment1Link = $comment->SpamLink();
292
        $this->assertContains('comments/spam/' . $commentID . '?t=', $adminComment1Link);
293
294
        // Test that this link can't be shared / XSS exploited
295
        $this->logInAs('commentadmin2');
296
        $spam = $this->get($adminComment1Link);
297
        $this->assertEquals(400, $spam->getStatusCode());
298
        $check = DataObject::get_by_id(Comment::class, $comment->ID);
299
        $this->assertEquals(0, $check->IsSpam, 'No permission to mark as spam');
300
301
        // Test that this other admin can spam the comment with their own link
302
        $adminComment2Link = $comment->SpamLink();
303
        $this->assertNotEquals($adminComment2Link, $adminComment1Link);
304
        $this->autoFollowRedirection = false;
305
        $spam = $this->get($adminComment2Link);
306
        $this->assertEquals(302, $spam->getStatusCode());
307
        $check = DataObject::get_by_id(Comment::class, $commentID);
308
        $this->assertEquals(1, $check->IsSpam);
309
310
        // Cannot re-spam spammed comment
311
        $this->assertNull($check->SpamLink());
312
    }
313
314 View Code Duplication
    public function testHamComment()
315
    {
316
        // Test anonymous user
317
        if ($member = Member::currentUser()) {
0 ignored issues
show
Deprecated Code introduced by
The method SilverStripe\Security\Member::currentUser() has been deprecated with message: 5.0.0 use Security::getCurrentUser()

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
318
            $member->logOut();
0 ignored issues
show
Deprecated Code introduced by
The method SilverStripe\Security\Member::logOut() has been deprecated with message: Use Security::setCurrentUser(null) or an IdentityStore
Logs this member out.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
319
        }
320
        $comment = $this->objFromFixture(Comment::class, 'secondComC');
321
        $commentID = $comment->ID;
322
        $this->assertNull($comment->HamLink(), 'No permission to see mark as ham link');
323
        $ham = $this->get('comments/ham/' . $comment->ID . '?ajax=1');
324
        $this->assertEquals(403, $ham->getStatusCode());
325
        $check = DataObject::get_by_id(Comment::class, $commentID);
326
        $this->assertEquals(1, $check->IsSpam, 'No permission to mark as ham');
327
328
        // Test non-authenticated user
329
        $this->logInAs('visitor');
330
        $this->assertNull($comment->HamLink(), 'No permission to see mark as ham link');
331
332
        // Test authenticated user
333
        $this->logInAs('commentadmin');
334
        $comment = $this->objFromFixture(Comment::class, 'secondComC');
335
        $commentID = $comment->ID;
336
        $adminComment1Link = $comment->HamLink();
337
        $this->assertContains('comments/ham/' . $commentID . '?t=', $adminComment1Link);
338
339
        // Test that this link can't be shared / XSS exploited
340
        $this->logInAs('commentadmin2');
341
        $ham = $this->get($adminComment1Link);
342
        $this->assertEquals(400, $ham->getStatusCode());
343
        $check = DataObject::get_by_id(Comment::class, $comment->ID);
344
        $this->assertEquals(1, $check->IsSpam, 'No permission to mark as ham');
345
346
        // Test that this other admin can ham the comment with their own link
347
        $adminComment2Link = $comment->HamLink();
348
        $this->assertNotEquals($adminComment2Link, $adminComment1Link);
349
        $this->autoFollowRedirection = false;
350
        $ham = $this->get($adminComment2Link);
351
        $this->assertEquals(302, $ham->getStatusCode());
352
        $check = DataObject::get_by_id(Comment::class, $commentID);
353
        $this->assertEquals(0, $check->IsSpam);
354
355
        // Cannot re-ham hammed comment
356
        $this->assertNull($check->HamLink());
357
    }
358
359 View Code Duplication
    public function testApproveComment()
360
    {
361
        // Test anonymous user
362
        if ($member = Member::currentUser()) {
0 ignored issues
show
Deprecated Code introduced by
The method SilverStripe\Security\Member::currentUser() has been deprecated with message: 5.0.0 use Security::getCurrentUser()

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
363
            $member->logOut();
0 ignored issues
show
Deprecated Code introduced by
The method SilverStripe\Security\Member::logOut() has been deprecated with message: Use Security::setCurrentUser(null) or an IdentityStore
Logs this member out.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
364
        }
365
        $comment = $this->objFromFixture(Comment::class, 'secondComB');
366
        $commentID = $comment->ID;
367
        $this->assertNull($comment->ApproveLink(), 'No permission to see approve link');
368
        $approve = $this->get('comments/approve/' . $comment->ID . '?ajax=1');
369
        $this->assertEquals(403, $approve->getStatusCode());
370
        $check = DataObject::get_by_id(Comment::class, $commentID);
371
        $this->assertEquals(0, $check->Moderated, 'No permission to approve');
372
373
        // Test non-authenticated user
374
        $this->logInAs('visitor');
375
        $this->assertNull($comment->ApproveLink(), 'No permission to see approve link');
376
377
        // Test authenticated user
378
        $this->logInAs('commentadmin');
379
        $comment = $this->objFromFixture(Comment::class, 'secondComB');
380
        $commentID = $comment->ID;
381
        $adminComment1Link = $comment->ApproveLink();
382
        $this->assertContains('comments/approve/' . $commentID . '?t=', $adminComment1Link);
383
384
        // Test that this link can't be shared / XSS exploited
385
        $this->logInAs('commentadmin2');
386
        $approve = $this->get($adminComment1Link);
387
        $this->assertEquals(400, $approve->getStatusCode());
388
        $check = DataObject::get_by_id(Comment::class, $comment->ID);
389
        $this->assertEquals(0, $check->Moderated, 'No permission to approve');
390
391
        // Test that this other admin can approve the comment with their own link
392
        $adminComment2Link = $comment->ApproveLink();
393
        $this->assertNotEquals($adminComment2Link, $adminComment1Link);
394
        $this->autoFollowRedirection = false;
395
        $approve = $this->get($adminComment2Link);
396
        $this->assertEquals(302, $approve->getStatusCode());
397
        $check = DataObject::get_by_id(Comment::class, $commentID);
398
        $this->assertEquals(1, $check->Moderated);
399
400
        // Cannot re-approve approved comment
401
        $this->assertNull($check->ApproveLink());
402
    }
403
404
    public function testCommenterURLWrite()
405
    {
406
        $comment = new Comment();
407
        // We only care about the CommenterURL, so only set that
408
        // Check a http and https URL. Add more test urls here as needed.
409
        $protocols = array(
410
            'Http',
411
            'Https',
412
        );
413
        $url = '://example.com';
414
415
        foreach ($protocols as $protocol) {
416
            $comment->CommenterURL = $protocol . $url;
417
            // The protocol should stay as if, assuming it is valid
418
            $comment->write();
419
            $this->assertEquals($comment->CommenterURL, $protocol . $url, $protocol . ':// is a valid protocol');
420
        }
421
    }
422
423
    public function testSanitizesWithAllowHtml()
424
    {
425
        if (!class_exists('\\HTMLPurifier')) {
426
            $this->markTestSkipped('HTMLPurifier class not found');
427
            return;
428
        }
429
430
        // Add p for paragraph
431
        // NOTE: The config method appears to append to the existing array
432
        Config::modify()->merge(CommentableItem::class, 'comments', array(
433
            'html_allowed_elements' => array('p'),
434
        ));
435
436
        // Without HTML allowed
437
        $comment1 = new Comment();
438
        $comment1->AllowHtml = false;
439
        $comment1->ParentClass = CommentableItem::class;
440
        $comment1->Comment = '<p><script>alert("w00t")</script>my comment</p>';
441
        $comment1->write();
442
        $this->assertEquals(
443
            '<p><script>alert("w00t")</script>my comment</p>',
444
            $comment1->Comment,
445
            'Does not remove HTML tags with html_allowed=false, ' .
446
            'which is correct behaviour because the HTML will be escaped'
447
        );
448
449
        // With HTML allowed
450
        $comment2 = new Comment();
451
        $comment2->AllowHtml = true;
452
        $comment2->ParentClass = CommentableItem::class;
453
        $comment2->Comment = '<p><script>alert("w00t")</script>my comment</p>';
454
        $comment2->write();
455
        $this->assertEquals(
456
            '<p>my comment</p>',
457
            $comment2->Comment,
458
            'Removes HTML tags which are not on the whitelist'
459
        );
460
    }
461
462
    public function testDefaultTemplateRendersHtmlWithAllowHtml()
463
    {
464
        if (!class_exists('\\HTMLPurifier')) {
465
            $this->markTestSkipped('HTMLPurifier class not found');
466
        }
467
468
        Config::modify()->merge(CommentableItem::class, 'comments', array(
469
            'html_allowed_elements' => array('p'),
470
        ));
471
472
        $item = new CommentableItem();
473
        $item->write();
474
475
        // Without HTML allowed
476
        $comment = new Comment();
477
        $comment->Comment = '<p>my comment</p>';
478
        $comment->AllowHtml = false;
479
        $comment->ParentID = $item->ID;
480
        $comment->ParentClass = CommentableItem::class;
481
        $comment->write();
482
483
        $html = $item->customise(array('CommentsEnabled' => true))->renderWith('CommentsInterface');
484
        $this->assertContains(
485
            '&lt;p&gt;my comment&lt;/p&gt;',
486
            $html
487
        );
488
489
        $comment->AllowHtml = true;
490
        $comment->write();
491
        $html = $item->customise(array('CommentsEnabled' => true))->renderWith('CommentsInterface');
492
        $this->assertContains(
493
            '<p>my comment</p>',
494
            $html
495
        );
496
    }
497
498
499
    /**
500
     * Tests whether comments are enabled or disabled by default
501
     */
502
    public function testDefaultEnabled()
503
    {
504
        Config::modify()->merge(CommentableItem::class, 'comments', array(
505
            'enabled_cms' => true,
506
            'require_moderation_cms' => true,
507
            'require_login_cms' => true
508
        ));
509
510
        // With default = true
511
        $obj = new CommentableItem();
512
        $this->assertTrue((bool)$obj->getCommentsOption('enabled'), "Default setting is enabled");
513
        $this->assertTrue((bool)$obj->ProvideComments);
514
        $this->assertEquals('None', $obj->ModerationRequired);
515
        $this->assertFalse((bool)$obj->CommentsRequireLogin);
516
517
        $obj = new CommentableItemEnabled();
518
        $this->assertTrue((bool)$obj->ProvideComments);
519
        $this->assertEquals('Required', $obj->ModerationRequired);
520
        $this->assertTrue((bool)$obj->CommentsRequireLogin);
521
522
        $obj = new CommentableItemDisabled();
523
        $this->assertFalse((bool)$obj->ProvideComments);
524
        $this->assertEquals('None', $obj->ModerationRequired);
525
        $this->assertFalse((bool)$obj->CommentsRequireLogin);
526
527
        // With default = false
528
        // Because of config rules about falsey values, apply config to object directly
529
        Config::modify()->merge(CommentableItem::class, 'comments', array(
530
            'enabled' => false,
531
            'require_login' => true,
532
            'require_moderation' => true
533
        ));
534
535
        $obj = new CommentableItem();
536
537
        $this->assertFalse((bool)$obj->getCommentsOption('enabled'), 'Default setting is disabled');
538
        $this->assertFalse((bool)$obj->ProvideComments);
539
        $this->assertEquals('Required', $obj->ModerationRequired);
540
        $this->assertTrue((bool)$obj->CommentsRequireLogin);
541
542
        $obj = new CommentableItemEnabled();
543
544
        $this->assertTrue((bool)$obj->ProvideComments);
545
        $this->assertEquals('Required', $obj->ModerationRequired);
546
        $this->assertTrue((bool)$obj->CommentsRequireLogin);
547
548
        $obj = new CommentableItemDisabled();
549
550
        $this->assertFalse((bool)$obj->ProvideComments);
551
        $this->assertEquals('None', $obj->ModerationRequired);
552
        $this->assertFalse((bool)$obj->CommentsRequireLogin);
553
    }
554
555
    public function testOnBeforeDelete()
556
    {
557
        $comment = $this->objFromFixture(Comment::class, 'firstComA');
558
559
        $child = new Comment();
560
        $child->Name = 'Fred Bloggs';
561
        $child->Comment = 'Child of firstComA';
562
        $child->write();
563
        $comment->ChildComments()->add($child);
564
        $this->assertEquals(4, $comment->ChildComments()->count());
565
566
        $commentID = $comment->ID;
567
        $childCommentID = $child->ID;
568
569
        $comment->delete();
570
571
        // assert that the new child been deleted
572
        $this->assertNull(DataObject::get_by_id(Comment::class, $commentID));
573
        $this->assertNull(DataObject::get_by_id(Comment::class, $childCommentID));
574
    }
575
576
    public function testRequireDefaultRecords()
577
    {
578
        $this->markTestSkipped('TODO');
579
    }
580
581
    public function testLink()
582
    {
583
        $comment = $this->objFromFixture(Comment::class, 'thirdComD');
584
        $this->assertEquals(
585
            'CommentableItemController#comment-' . $comment->ID,
586
            $comment->Link()
587
        );
588
        $this->assertEquals($comment->ID, $comment->ID);
589
590
        // An orphan comment has no link
591
        $comment->ParentID = 0;
592
        $comment->ParentClass = null;
593
        $comment->write();
594
        $this->assertEquals('', $comment->Link());
595
    }
596
597
    public function testPermalink()
598
    {
599
        $comment = $this->objFromFixture(Comment::class, 'thirdComD');
600
        $this->assertEquals('comment-' . $comment->ID, $comment->Permalink());
601
    }
602
603
    /**
604
     * Test field labels in 2 languages
605
     */
606
    public function testFieldLabels()
607
    {
608
        $locale = i18n::get_locale();
609
        i18n::set_locale('fr');
610
611
        /** @var Comment $comment */
612
        $comment = $this->objFromFixture(Comment::class, 'firstComA');
613
614
        $labels = $comment->FieldLabels();
615
        $expected = array(
616
            'Name' => 'Nom de l\'Auteur',
617
            'Comment' => 'Commentaire',
618
            'Email' => 'Email',
619
            'URL' => 'URL',
620
            'Moderated' => 'Modéré?',
621
            'IsSpam' => 'Spam?',
622
            'AllowHtml' => 'Allow Html',
623
            'SecretToken' => 'Secret Token',
624
            'Depth' => 'Depth',
625
            'Author' => 'Author Member',
626
            'ParentComment' => 'Parent Comment',
627
            'ChildComments' => 'Child Comments',
628
            'ParentTitle' => 'Parent',
629
            'Created' => 'Date de publication',
630
            'Parent' => 'Parent'
631
        );
632
        i18n::set_locale($locale);
633
        foreach ($expected as $key => $value) {
634
            $this->assertEquals($value, $labels[$key]);
635
        }
636
637
        $labels = $comment->FieldLabels();
638
        $expected = array(
639
            'Name' => 'Author Name',
640
            'Comment' => 'Comment',
641
            'Email' => 'Email',
642
            'URL' => 'URL',
643
            'Moderated' => 'Moderated?',
644
            'IsSpam' => 'Spam?',
645
            'AllowHtml' => 'Allow Html',
646
            'SecretToken' => 'Secret Token',
647
            'Depth' => 'Depth',
648
            'Author' => 'Author Member',
649
            'ParentComment' => 'Parent Comment',
650
            'ChildComments' => 'Child Comments',
651
            'ParentTitle' => 'Parent',
652
            'Created' => 'Date posted',
653
            'Parent' => 'Parent'
654
        );
655
        foreach ($expected as $key => $value) {
656
            $this->assertEquals($value, $labels[$key]);
657
        }
658
    }
659
660
    public function testGetParent()
661
    {
662
        $comment = $this->objFromFixture(Comment::class, 'firstComA');
663
        $item = $this->objFromFixture(CommentableItem::class, 'first');
664
        $parent = $comment->Parent();
665
        $this->assertSame($item->getClassName(), $parent->getClassName());
666
        $this->assertSame($item->ID, $parent->ID);
667
    }
668
669 View Code Duplication
    public function testGetParentTitle()
670
    {
671
        $comment = $this->objFromFixture(Comment::class, 'firstComA');
672
        $title = $comment->getParentTitle();
673
        $this->assertEquals('First', $title);
674
675
        // Title from a comment with no parent is blank
676
        $comment->ParentID = 0;
677
        $comment->ParentClass = null;
678
        $comment->write();
679
        $this->assertEquals('', $comment->getParentTitle());
680
    }
681
682
    public function testGetParentClassName()
683
    {
684
        $comment = $this->objFromFixture(Comment::class, 'firstComA');
685
        $className = $comment->getParentClassName();
686
        $this->assertEquals(CommentableItem::class, $className);
687
    }
688
689
    public function testCastingHelper()
690
    {
691
        $this->markTestSkipped('TODO');
692
    }
693
694
    public function testGetEscapedComment()
695
    {
696
        $this->markTestSkipped('TODO');
697
    }
698
699
    public function testIsPreview()
700
    {
701
        $comment = new Comment();
702
        $comment->Name = 'Fred Bloggs';
703
        $comment->Comment = 'this is a test comment';
704
        $this->assertTrue($comment->isPreview());
705
        $comment->write();
706
        $this->assertFalse($comment->isPreview());
707
    }
708
709
    public function testCanCreate()
710
    {
711
        $comment = $this->objFromFixture(Comment::class, 'firstComA');
712
713
        // admin can create - this is always false
714
        $this->logInAs('commentadmin');
715
        $this->assertFalse($comment->canCreate());
716
717
        // visitor can view
718
        $this->logInAs('visitor');
719
        $this->assertFalse($comment->canCreate());
720
    }
721
722 View Code Duplication
    public function testCanView()
723
    {
724
        $comment = $this->objFromFixture(Comment::class, 'firstComA');
725
726
        // admin can view
727
        $this->logInAs('commentadmin');
728
        $this->assertTrue($comment->canView());
729
730
        // visitor can view
731
        $this->logInAs('visitor');
732
        $this->assertTrue($comment->canView());
733
734
        $comment->ParentID = 0;
735
        $comment->write();
736
        $this->assertFalse($comment->canView());
737
    }
738
739 View Code Duplication
    public function testCanEdit()
740
    {
741
        $comment = $this->objFromFixture(Comment::class, 'firstComA');
742
743
        // admin can edit
744
        $this->logInAs('commentadmin');
745
        $this->assertTrue($comment->canEdit());
746
747
        // visitor cannot
748
        $this->logInAs('visitor');
749
        $this->assertFalse($comment->canEdit());
750
751
        $comment->ParentID = 0;
752
        $comment->write();
753
        $this->assertFalse($comment->canEdit());
754
    }
755
756 View Code Duplication
    public function testCanDelete()
757
    {
758
        $comment = $this->objFromFixture(Comment::class, 'firstComA');
759
760
        // admin can delete
761
        $this->logInAs('commentadmin');
762
        $this->assertTrue($comment->canDelete());
763
764
        // visitor cannot
765
        $this->logInAs('visitor');
766
        $this->assertFalse($comment->canDelete());
767
768
        $comment->ParentID = 0;
769
        $comment->write();
770
        $this->assertFalse($comment->canDelete());
771
    }
772
773
    public function testGetMember()
774
    {
775
        $this->logInAs('visitor');
776
        $current = Security::getCurrentUser();
777
        $comment = $this->objFromFixture(Comment::class, 'firstComA');
778
        $method = $this->getMethod('getMember');
779
780
        // null case
781
        $member = $method->invokeArgs($comment, array());
782
        $this->assertEquals($current->ID, $member->ID);
783
784
        // numeric ID case
785
        $member = $method->invokeArgs($comment, array($current->ID));
786
        $this->assertEquals($current->ID, $member->ID);
787
788
        // identity case
789
        $member = $method->invokeArgs($comment, array($current));
790
        $this->assertEquals($current->ID, $member->ID);
791
    }
792
793
    public function testGetAuthorName()
794
    {
795
        $comment = $this->objFromFixture(Comment::class, 'firstComA');
796
        $this->assertEquals(
797
            'FA',
798
            $comment->getAuthorName()
799
        );
800
801
        $comment->Name = '';
802
        $this->assertEquals(
803
            '',
804
            $comment->getAuthorName()
805
        );
806
807
        $author = $this->objFromFixture(Member::class, 'visitor');
808
        $comment->AuthorID = $author->ID;
809
        $comment->write();
810
        $this->assertEquals(
811
            'visitor',
812
            $comment->getAuthorName()
813
        );
814
815
        // null the names, expect null back
816
        $comment->Name = null;
817
        $comment->AuthorID = 0;
818
        $this->assertNull($comment->getAuthorName());
819
    }
820
821
822
    public function testLinks()
823
    {
824
        $comment = $this->objFromFixture(Comment::class, 'firstComA');
825
        $this->logInAs('commentadmin');
826
827
        $method = $this->getMethod('ActionLink');
828
829
        // test with starts of strings and tokens and salts change each time
830
        $this->assertContains(
831
            '/comments/theaction/' . $comment->ID,
832
            $method->invokeArgs($comment, array('theaction'))
833
        );
834
835
        $this->assertContains(
836
            '/comments/delete/' . $comment->ID,
837
            $comment->DeleteLink()
838
        );
839
840
        $this->assertContains(
841
            '/comments/spam/' . $comment->ID,
842
            $comment->SpamLink()
843
        );
844
845
        $comment->markSpam();
846
        $this->assertContains(
847
            '/comments/ham/' . $comment->ID,
848
            $comment->HamLink()
849
        );
850
851
        //markApproved
852
        $comment->markUnapproved();
853
        $this->assertContains(
854
            '/comments/approve/' . $comment->ID,
855
            $comment->ApproveLink()
856
        );
857
    }
858
859
    public function testMarkSpam()
860
    {
861
        $comment = $this->objFromFixture(Comment::class, 'firstComA');
862
        $comment->markSpam();
863
        $this->assertTrue($comment->Moderated);
864
        $this->assertTrue($comment->IsSpam);
865
    }
866
867
    public function testMarkApproved()
868
    {
869
        $comment = $this->objFromFixture(Comment::class, 'firstComA');
870
        $comment->markApproved();
871
        $this->assertTrue($comment->Moderated);
872
        $this->assertFalse($comment->IsSpam);
873
    }
874
875
    public function testMarkUnapproved()
876
    {
877
        $comment = $this->objFromFixture(Comment::class, 'firstComA');
878
        $comment->markApproved();
879
        $this->assertTrue($comment->Moderated);
880
    }
881
882 View Code Duplication
    public function testSpamClass()
883
    {
884
        $comment = $this->objFromFixture(Comment::class, 'firstComA');
885
        $this->assertEquals('notspam', $comment->spamClass());
886
        $comment->Moderated = false;
887
        $this->assertEquals('unmoderated', $comment->spamClass());
888
        $comment->IsSpam = true;
889
        $this->assertEquals('spam', $comment->spamClass());
890
    }
891
892
    public function testGetTitle()
893
    {
894
        $comment = $this->objFromFixture(Comment::class, 'firstComA');
895
        $this->assertEquals(
896
            'Comment by FA on First',
897
            $comment->getTitle()
898
        );
899
    }
900
901
    public function testGetCMSFields()
902
    {
903
        $comment = $this->objFromFixture(Comment::class, 'firstComA');
904
        $fields = $comment->getCMSFields();
905
        $names = array();
906
        foreach ($fields as $field) {
907
            $names[] = $field->getName();
908
        }
909
        $expected = array(
910
            'Created',
911
            'Name',
912
            'Comment',
913
            'Email',
914
            'URL',
915
            'Options'
916
        );
917
        $this->assertEquals($expected, $names);
918
    }
919
920
    public function testGetCMSFieldsCommentHasAuthor()
921
    {
922
        $member = Member::get()->filter('FirstName', 'visitor')->first();
923
        $comment = $this->objFromFixture(Comment::class, 'firstComA');
924
        $comment->AuthorID = $member->ID;
925
        $comment->write();
926
927
        $fields = $comment->getCMSFields();
928
        $names = array();
929
        foreach ($fields as $field) {
930
            $names[] = $field->getName();
931
        }
932
        $expected = array(
933
            'Created',
934
            'Name',
935
            'AuthorMember',
936
            'Comment',
937
            'Email',
938
            'URL',
939
            'Options'
940
        );
941
        $this->assertEquals($expected, $names);
942
    }
943
944
    public function testGetCMSFieldsWithParentComment()
945
    {
946
        $comment = $this->objFromFixture(Comment::class, 'firstComA');
947
948
        $child = new Comment();
949
        $child->Name = 'John Smith';
950
        $child->Comment = 'This is yet another test commnent';
951
        $child->ParentCommentID = $comment->ID;
952
        $child->write();
953
954
        $fields = $child->getCMSFields();
955
        $names = array();
956
        foreach ($fields as $field) {
957
            $names[] = $field->getName();
958
        }
959
        $expected = array(
960
            'Created',
961
            'Name',
962
            'Comment',
963
            'Email',
964
            'URL',
965
            'Options',
966
            'ParentComment_Title',
967
            'ParentComment_Created',
968
            'ParentComment_AuthorName',
969
            'ParentComment_EscapedComment'
970
        );
971
        $this->assertEquals($expected, $names);
972
    }
973
974
    public function testPurifyHtml()
975
    {
976
        if (!class_exists(HTMLPurifier_Config::class)) {
977
            $this->markTestSkipped('HTMLPurifier class not found');
978
            return;
979
        }
980
981
        $comment = $this->objFromFixture(Comment::class, 'firstComA');
982
983
        $dirtyHTML = '<p><script>alert("w00t")</script>my comment</p>';
984
        $this->assertEquals(
985
            'my comment',
986
            $comment->purifyHtml($dirtyHTML)
987
        );
988
    }
989
990
    public function testGravatar()
991
    {
992
        // Turn gravatars on
993
        Config::modify()->merge(CommentableItem::class, 'comments', array(
994
            'use_gravatar' => true,
995
            'gravatar_size' => 80,
996
            'gravatar_default' => 'identicon',
997
            'gravatar_rating' => 'g'
998
        ));
999
1000
        $comment = $this->objFromFixture(Comment::class, 'firstComA');
1001
1002
        $this->assertEquals(
1003
            'https://www.gravatar.com/avatar/d41d8cd98f00b204e9800998ecf8427e?s'
1004
            . '=80&d=identicon&r=g',
1005
            $comment->Gravatar()
1006
        );
1007
1008
        // Turn gravatars off
1009
        Config::modify()->merge(CommentableItem::class, 'comments', array(
1010
            'use_gravatar' => false
1011
        ));
1012
1013
        $comment = $this->objFromFixture(Comment::class, 'firstComA');
1014
1015
        $this->assertEquals(
1016
            '',
1017
            $comment->Gravatar()
1018
        );
1019
    }
1020
1021
    public function testGetRepliesEnabled()
1022
    {
1023
        Config::modify()->merge(CommentableItem::class, 'comments', array(
1024
            'nested_comments' => false
1025
        ));
1026
1027
        $comment = $this->objFromFixture(Comment::class, 'firstComA');
1028
        $this->assertFalse($comment->getRepliesEnabled());
1029
1030
        Config::modify()->merge(CommentableItem::class, 'comments', array(
1031
            'nested_comments' => true,
1032
            'nested_depth' => 4
1033
        ));
1034
1035
        $this->assertTrue($comment->getRepliesEnabled());
1036
1037
        $comment->Depth = 4;
1038
        $this->assertFalse($comment->getRepliesEnabled());
1039
1040
1041
        // 0 indicates no limit for nested_depth
1042
        Config::modify()->merge(CommentableItem::class, 'comments', array(
1043
            'nested_comments' => true,
1044
            'nested_depth' => 0
1045
        ));
1046
1047
        $comment = $this->objFromFixture(Comment::class, 'firstComA');
1048
        $comment->Depth = 234;
1049
1050
        $comment->markUnapproved();
1051
        $this->assertFalse($comment->getRepliesEnabled());
1052
1053
        $comment->markSpam();
1054
        $this->assertFalse($comment->getRepliesEnabled());
1055
1056
        $comment->markApproved();
1057
        $this->assertTrue($comment->getRepliesEnabled());
1058
    }
1059
1060
    public function testAllReplies()
1061
    {
1062
        Config::modify()->merge(CommentableItem::class, 'comments', array(
1063
            'nested_comments' => true,
1064
            'nested_depth' => 4
1065
        ));
1066
1067
        $comment = $this->objFromFixture(Comment::class, 'firstComA');
1068
1069
        $this->assertEquals(
1070
            3,
1071
            $comment->allReplies()->count()
1072
        );
1073
1074
        $child = new Comment();
1075
        $child->Name = 'Fred Smith';
1076
        $child->Comment = 'This is a child comment';
1077
        $child->ParentCommentID = $comment->ID;
1078
1079
        // spam should be returned by this method
1080
        $child->markSpam();
1081
        $child->write();
1082
        $replies = $comment->allReplies();
1083
        $this->assertEquals(
1084
            4,
1085
            $comment->allReplies()->count()
1086
        );
1087
1088
        Config::modify()->merge(CommentableItem::class, 'comments', array(
1089
            'nested_comments' => false
1090
        ));
1091
1092
        $this->assertEquals(0, $comment->allReplies()->count());
1093
    }
1094
1095
    public function testReplies()
1096
    {
1097
        CommentableItem::add_extension(CommentsExtension::class);
1098
        $this->logInWithPermission('ADMIN');
1099
        Config::modify()->merge(CommentableItem::class, 'comments', array(
1100
            'nested_comments' => true,
1101
            'nested_depth' => 4
1102
        ));
1103
        $comment = $this->objFromFixture(Comment::class, 'firstComA');
1104
        $this->assertEquals(
1105
            3,
1106
            $comment->Replies()->count()
1107
        );
1108
1109
        // Test that spam comments are not returned
1110
        $childComment = $comment->Replies()->first();
1111
        $childComment->IsSpam = 1;
1112
        $childComment->write();
1113
        $this->assertEquals(
1114
            2,
1115
            $comment->Replies()->count()
1116
        );
1117
1118
        // Test that unmoderated comments are not returned
1119
        //
1120
        $childComment = $comment->Replies()->first();
1121
1122
        // FIXME - moderation settings scenarios need checked here
1123
        $childComment->Moderated = 0;
1124
        $childComment->IsSpam = 0;
1125
        $childComment->write();
1126
        $this->assertEquals(
1127
            2,
1128
            $comment->Replies()->count()
1129
        );
1130
1131
1132
        // Test moderation required on the front end
1133
        $item = $this->objFromFixture(CommentableItem::class, 'first');
1134
        $item->ModerationRequired = 'Required';
1135
        $item->write();
1136
1137
        Config::modify()->merge(CommentableItemDisabled::class, 'comments', array(
1138
            'nested_comments' => true,
1139
            'nested_depth' => 4,
1140
            'frontend_moderation' => true
1141
        ));
1142
1143
        $comment = DataObject::get_by_id(Comment::class, $comment->ID);
1144
1145
        $this->assertEquals(
1146
            2,
1147
            $comment->Replies()->count()
1148
        );
1149
1150
        // Turn off nesting, empty array should be returned
1151
        Config::modify()->merge(CommentableItem::class, 'comments', array(
1152
            'nested_comments' => false
1153
        ));
1154
1155
        $this->assertEquals(
1156
            0,
1157
            $comment->Replies()->count()
1158
        );
1159
1160
        CommentableItem::remove_extension(CommentsExtension::class);
1161
    }
1162
1163
    public function testPagedReplies()
1164
    {
1165
        Config::modify()->merge(CommentableItem::class, 'comments', array(
1166
            'nested_comments' => true,
1167
            'nested_depth' => 4,
1168
            'comments_per_page' => 2
1169
        ));
1170
1171
        $comment = $this->objFromFixture(Comment::class, 'firstComA');
1172
        $pagedList = $comment->pagedReplies();
1173
1174
        $this->assertEquals(
1175
            2,
1176
            $pagedList->TotalPages()
1177
        );
1178
1179
        $this->assertEquals(
1180
            3,
1181
            $pagedList->getTotalItems()
1182
        );
1183
1184
        Config::modify()->merge(CommentableItem::class, 'comments', array(
1185
            'nested_comments' => false
1186
        ));
1187
1188
        $this->assertEquals(0, $comment->PagedReplies()->count());
1189
    }
1190
1191
    public function testReplyForm()
1192
    {
1193
        Config::modify()->merge(CommentableItem::class, 'comments', array(
1194
            'nested_comments' => false,
1195
            'nested_depth' => 4
1196
        ));
1197
1198
        $comment = $this->objFromFixture(Comment::class, 'firstComA');
1199
1200
        // No nesting, no reply form
1201
        $form = $comment->replyForm();
1202
        $this->assertNull($form);
1203
1204
        // parent item so show form
1205
        Config::modify()->merge(CommentableItem::class, 'comments', array(
1206
            'nested_comments' => true,
1207
            'nested_depth' => 4
1208
        ));
1209
        $form = $comment->ReplyForm();
1210
        $this->assertNotNull($form);
1211
        $names = array();
1212
1213
        foreach ($form->Fields() as $field) {
1214
            array_push($names, $field->getName());
1215
        }
1216
1217
        $this->assertContains('NameEmailURLComment', $names, 'The CompositeField name');
1218
        $this->assertContains('ParentID', $names);
1219
        $this->assertContains('ParentClassName', $names);
1220
        $this->assertContains('ReturnURL', $names);
1221
        $this->assertContains('ParentCommentID', $names);
1222
1223
        // no parent, no reply form
1224
1225
        $comment->ParentID = 0;
1226
        $comment->ParentClass = null;
1227
        $comment->write();
1228
        $form = $comment->replyForm();
1229
        $this->assertNull($form);
1230
    }
1231
1232
    public function testUpdateDepth()
1233
    {
1234
        Config::modify()->merge(CommentableItem::class, 'comments', array(
1235
            'nested_comments' => true,
1236
            'nested_depth' => 4
1237
        ));
1238
1239
        $comment = $this->objFromFixture(Comment::class, 'firstComA');
1240
        $children = $comment->allReplies()->toArray();
1241
        // Make the second child a child of the first
1242
        // Make the third child a child of the second
1243
        $reply1 = $children[0];
1244
        $reply2 = $children[1];
1245
        $reply3 = $children[2];
1246
        $reply2->ParentCommentID = $reply1->ID;
1247
        $reply2->write();
1248
        $this->assertEquals(3, $reply2->Depth);
1249
        $reply3->ParentCommentID = $reply2->ID;
1250
        $reply3->write();
1251
        $this->assertEquals(4, $reply3->Depth);
1252
    }
1253
1254
    public function testGetToken()
1255
    {
1256
        $this->markTestSkipped('TODO');
1257
    }
1258
1259
    public function testMemberSalt()
1260
    {
1261
        $this->markTestSkipped('TODO');
1262
    }
1263
1264
    public function testAddToUrl()
1265
    {
1266
        $this->markTestSkipped('TODO');
1267
    }
1268
1269
    public function testCheckRequest()
1270
    {
1271
        $this->markTestSkipped('TODO');
1272
    }
1273
1274
    public function testGenerate()
1275
    {
1276
        $this->markTestSkipped('TODO');
1277
    }
1278
1279
    protected static function getMethod($name)
1280
    {
1281
        $class = new ReflectionClass(Comment::class);
1282
        $method = $class->getMethod($name);
1283
        $method->setAccessible(true);
1284
        return $method;
1285
    }
1286
}
1287