Issues (124)

tests/CommentingControllerTest.php (1 issue)

1
<?php
2
3
namespace SilverStripe\Comments\Tests;
4
5
use SilverStripe\Akismet\AkismetSpamProtector;
0 ignored issues
show
The type SilverStripe\Akismet\AkismetSpamProtector was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
6
use SilverStripe\Comments\Controllers\CommentingController;
7
use SilverStripe\Comments\Model\Comment;
8
use SilverStripe\Comments\Model\Comment\SecurityToken as CommentSecurityToken;
9
use SilverStripe\Comments\Tests\Stubs\CommentableItem;
10
use SilverStripe\Control\Controller;
11
use SilverStripe\Core\Config\Config;
12
use SilverStripe\Core\Injector\Injector;
13
use SilverStripe\Dev\FunctionalTest;
14
use SilverStripe\ORM\DataObject;
15
use SilverStripe\Security\Member;
16
use SilverStripe\Security\SecurityToken;
17
18
class CommentingControllerTest extends FunctionalTest
19
{
20
    /**
21
     * {@inheritDoc}
22
     */
23
    protected static $fixture_file = 'CommentsTest.yml';
24
25
    /**
26
     * {@inheritDoc}
27
     */
28
    protected static $extra_dataobjects = [
29
        CommentableItem::class
30
    ];
31
32
    protected $securityEnabled;
33
34
    protected function tearDown()
35
    {
36
        if ($this->securityEnabled) {
37
            SecurityToken::inst()->enable();
38
        } else {
39
            SecurityToken::inst()->disable();
40
        }
41
        parent::tearDown();
42
    }
43
44
    protected function setUp()
45
    {
46
        parent::setUp();
47
        $this->securityEnabled = SecurityToken::inst()->is_enabled();
48
49
        // We will assert against explicit responses, unless handed otherwise in a test for redirects
50
        $this->autoFollowRedirection = false;
51
52
        // Mock Akismet if it's installed
53
        if (class_exists(AkismetSpamProtector::class)) {
54
            $akismetMock = $this->createMock(AkismetSpamProtector::class);
55
            Injector::inst()->registerService($akismetMock, AkismetSpamProtector::class);
56
        }
57
    }
58
59
    public function testCommentsFormUsePreview()
60
    {
61
        $parent = $this->objFromFixture(CommentableItem::class, 'first');
62
        $commController = new CommentingController();
63
        $commController->setOwnerRecord($parent);
64
        $form = $commController->CommentsForm();
65
66
        $commentsFields = $form->Fields()->first()->FieldList();
67
        $expected = array('Name', 'Email', 'URL', 'Comment');
68
        CommentTestHelper::assertFieldNames($this, $expected, $commentsFields);
69
70
        // test with preview on
71
        Config::modify()->merge(CommentableItem::class, 'comments', array(
72
            'use_preview' => true
73
        ));
74
75
        $parent = $this->objFromFixture(CommentableItem::class, 'first');
76
        $commController = new CommentingController();
77
        $commController->setOwnerRecord($parent);
78
79
        $this->objFromFixture(Comment::class, 'firstComAChild1')->delete();
80
        $this->objFromFixture(Comment::class, 'firstComAChild2')->delete();
81
        $this->objFromFixture(Comment::class, 'firstComAChild3')->delete();
82
83
        SecurityToken::inst()->disable();
84
        $this->autoFollowRedirection = false;
85
86
        $form = $commController->CommentsForm();
87
        $commentsFields = $form->Fields()->first()->FieldList();
88
        $expected = array('Name', 'Email', 'URL', 'Comment', 'PreviewComment');
89
        CommentTestHelper::assertFieldNames($this, $expected, $commentsFields);
90
    }
91
92
    public function testApproveUnmoderatedComment()
93
    {
94
        SecurityToken::inst()->disable();
95
96
        // mark a comment as spam then approve it
97
        $this->logInWithPermission('CMS_ACCESS_CommentAdmin');
98
        $comment = $this->objFromFixture(Comment::class, 'testModeratedComment1');
99
        $st = new CommentSecurityToken($comment);
100
        $url = 'comments/approve/' . $comment->ID;
101
        $url = $st->addToUrl($url, Member::currentUser());
102
        $response = $this->get($url, null, ['Referer' => '/']);
103
        $this->assertEquals(302, $response->getStatusCode());
104
        $comment = DataObject::get_by_id(Comment::class, $comment->ID);
105
106
        // Need to use 0,1 here instead of false, true for SQLite
107
        $this->assertEquals(0, $comment->IsSpam);
108
        $this->assertEquals(1, $comment->Moderated);
109
110
        // try and approve a non existent comment
111
        $response = $this->get('comments/approve/100000');
112
        $this->assertEquals(404, $response->getStatusCode());
113
    }
114
115
    public function testSetGetOwnerController()
116
    {
117
        $commController = new CommentingController();
118
        $commController->setOwnerController(Controller::curr());
119
        $this->assertEquals(Controller::curr(), $commController->getOwnerController());
120
        $commController->setOwnerController(null);
121
        $this->assertNull($commController->getOwnerController());
122
    }
123
124
    public function testHam()
125
    {
126
        SecurityToken::inst()->disable();
127
128
        // mark a comment as spam then ham it
129
        $this->logInWithPermission('CMS_ACCESS_CommentAdmin');
130
        $comment = $this->objFromFixture(Comment::class, 'firstComA');
131
        $comment->markSpam();
132
        $st = new CommentSecurityToken($comment);
133
        $url = 'comments/ham/' . $comment->ID;
134
        $url = $st->addToUrl($url, Member::currentUser());
135
        $response = $this->get($url);
136
        $this->assertEquals(302, $response->getStatusCode());
137
        $comment = DataObject::get_by_id(Comment::class, $comment->ID);
138
139
        // Need to use 0,1 here instead of false, true for SQLite
140
        $this->assertEquals(0, $comment->IsSpam);
141
        $this->assertEquals(1, $comment->Moderated);
142
143
        // try and ham a non existent comment
144
        $response = $this->get('comments/ham/100000');
145
        $this->assertEquals(404, $response->getStatusCode());
146
    }
147
148
    public function testSpam()
149
    {
150
        // mark a comment as approved then spam it
151
        $this->logInWithPermission('CMS_ACCESS_CommentAdmin');
152
        $comment = $this->objFromFixture(Comment::class, 'firstComA');
153
        $comment->markApproved();
154
        $st = new CommentSecurityToken($comment);
155
        $url = 'comments/spam/' . $comment->ID;
156
        $url = $st->addToUrl($url, Member::currentUser());
157
        $response = $this->get($url);
158
        $this->assertEquals(302, $response->getStatusCode());
159
        $comment = DataObject::get_by_id(Comment::class, $comment->ID);
160
161
        // Need to use 0,1 here instead of false, true for SQLite
162
        $this->assertEquals(1, $comment->IsSpam);
163
        $this->assertEquals(1, $comment->Moderated);
164
165
        // try and spam a non existent comment
166
        $response = $this->get('comments/spam/100000');
167
        $this->assertEquals(404, $response->getStatusCode());
168
    }
169
170
    public function testRSS()
171
    {
172
        // Delete the newly added children of firstComA so as not to have to recalculate values below
173
        $this->objFromFixture(Comment::class, 'firstComAChild1')->delete();
174
        $this->objFromFixture(Comment::class, 'firstComAChild2')->delete();
175
        $this->objFromFixture(Comment::class, 'firstComAChild3')->delete();
176
177
        $item = $this->objFromFixture(CommentableItem::class, 'first');
178
179
        // comments sitewide
180
        $response = $this->get('comments/rss');
181
        $comment = "10 approved, non spam comments on page 1";
182
        $this->assertEquals(10, substr_count($response->getBody(), "<item>"), $comment);
183
184
        $response = $this->get('comments/rss?start=10');
185
        $this->assertEquals(4, substr_count($response->getBody(), "<item>"), "3 approved, non spam comments on page 2");
186
187
        // all comments on a type
188
        $response = $this->get('comments/rss/SilverStripe-Comments-Tests-Stubs-CommentableItem');
189
        $this->assertEquals(10, substr_count($response->getBody(), "<item>"));
190
191
        $response = $this->get('comments/rss/SilverStripe-Comments-Tests-Stubs-CommentableItem?start=10');
192
        $this->assertEquals(4, substr_count($response->getBody(), "<item>"), "3 approved, non spam comments on page 2");
193
194
        // specific page
195
        $response = $this->get('comments/rss/SilverStripe-Comments-Tests-Stubs-CommentableItem/'.$item->ID);
196
        $this->assertEquals(1, substr_count($response->getBody(), "<item>"));
197
        $this->assertContains('<dc:creator>FA</dc:creator>', $response->getBody());
198
199
        // test accessing comments on a type that doesn't exist
200
        $response = $this->get('comments/rss/Fake');
201
        $this->assertEquals(404, $response->getStatusCode());
202
    }
203
204
    // This is returning a 404 which looks logical code wise but also a bit weird.
205
    // Test module on a clean install and check what the actual URL is first
206
/*    public function testReply() {
207
        $this->logInWithPermission('CMS_ACCESS_CommentAdmin');
208
        $comment = $this->objFromFixture('Comment', 'firstComA');
209
        $item = $this->objFromFixture('CommentableItem', 'first');
210
211
        $st = new CommentSecurityToken($comment);
212
        $url = 'comments/reply/' . $item->ID.'?ParentCommentID=' . $comment->ID;
213
        error_log($url);
214
        $response = $this->get($url);
215
        error_log(print_r($response,1));
216
217
        $this->assertEquals(200, $response->getStatusCode());
218
219
    }
220
*/
221
/*
222
    public function testCommentsFormLoadMemberData() {
223
        Config::modify()->set('CommentableItem', 'comments', array(
224
            'use_preview' => false
225
        ));
226
        $this->logInAs('visitor');
227
        SecurityToken::inst()->disable();
228
        $parent = $this->objFromFixture('CommentableItem', 'first');
229
        $parent->CommentsRequireLogin = true;
230
        $parent->PostingRequiredPermission = true;
231
        //$parent->write();
232
        $commController = new CommentingController();
233
        $commController->setOwnerRecord($parent);
234
235
        $form = $commController->CommentsForm();
236
        $commentsFields = $form->Fields()->first()->FieldList();
237
        $expected = array('Name', 'Email', 'URL', 'Comment', 'PreviewComment');
238
        CommentTestHelper::assertFieldNames($this, $expected, $commentsFields);
239
    }
240
*/
241
242
    public function testCommentsForm()
243
    {
244
        $this->autoFollowRedirection = true;
245
246
        // Delete the newly added children of firstComA so as not to change this test
247
        $this->objFromFixture(Comment::class, 'firstComAChild1')->delete();
248
        $this->objFromFixture(Comment::class, 'firstComAChild2')->delete();
249
        $this->objFromFixture(Comment::class, 'firstComAChild3')->delete();
250
251
        SecurityToken::inst()->disable();
252
        $this->autoFollowRedirection = false;
253
        $parent = $this->objFromFixture(CommentableItem::class, 'first');
254
255
        // Test posting to base comment
256
        $response = $this->post(
257
            'comments/CommentsForm',
258
            array(
259
                'Name' => 'Poster',
260
                'Email' => '[email protected]',
261
                'Comment' => 'My Comment',
262
                'ParentID' => $parent->ID,
263
                'ParentClassName' => CommentableItem::class,
264
                'action_doPostComment' => 'Post'
265
            )
266
        );
267
        $this->assertEquals(302, $response->getStatusCode());
268
        // $this->assertStringStartsWith('CommentableItemController#comment-', $response->getHeader('Location'));
269
        $this->assertDOSEquals(
270
            array(
271
                array(
272
                    'Name' => 'Poster',
273
                    'Email' => '[email protected]',
274
                    'Comment' => 'My Comment',
275
                    'ParentID' => $parent->ID,
276
                    'ParentClass' => CommentableItem::class,
277
                )
278
            ),
279
            Comment::get()->filter('Email', '[email protected]')
280
        );
281
282
        // Test posting to parent comment
283
        $parentComment = $this->objFromFixture(Comment::class, 'firstComA');
284
        $this->assertEquals(0, $parentComment->ChildComments()->count());
285
286
        $response = $this->post(
287
            'comments/reply/' . $parentComment->ID,
288
            array(
289
                'Name' => 'Test Author',
290
                'Email' => '[email protected]',
291
                'Comment' => 'Making a reply to firstComA',
292
                'ParentID' => $parent->ID,
293
                'ParentClassName' => CommentableItem::class,
294
                'ParentCommentID' => $parentComment->ID,
295
                'action_doPostComment' => 'Post'
296
            )
297
        );
298
        $this->assertEquals(302, $response->getStatusCode());
299
        // $this->assertStringStartsWith('CommentableItemController#comment-', $response->getHeader('Location'));
300
        $this->assertDOSEquals(
301
            array(
302
                array(
303
                    'Name' => 'Test Author',
304
                    'Email' => '[email protected]',
305
                    'Comment' => 'Making a reply to firstComA',
306
                    'ParentID' => $parent->ID,
307
                    'ParentClass' => CommentableItem::class,
308
                    'ParentCommentID' => $parentComment->ID
309
                )
310
            ),
311
            $parentComment->ChildComments()
312
        );
313
    }
314
315
    /**
316
     * SS4 introduces namespaces. They don't work in URLs, so we encode and decode them here.
317
     */
318
    public function testEncodeClassName()
319
    {
320
        $controller = new CommentingController;
321
        $this->assertSame('SilverStripe-Comments-Model-Comment', $controller->encodeClassName(Comment::class));
322
    }
323
324
    public function testDecodeClassName()
325
    {
326
        $controller = new CommentingController;
327
        $this->assertSame(Comment::class, $controller->decodeClassName('SilverStripe-Comments-Model-Comment'));
328
    }
329
}
330