Issues (27)

tests/php/PublishableSiteTreeTest.php (5 issues)

1
<?php
2
3
namespace SilverStripe\StaticPublishQueue\Test;
4
5
use SilverStripe\CMS\Model\SiteTree;
6
use SilverStripe\Core\Injector\Injector;
7
use SilverStripe\Dev\SapphireTest;
8
use SilverStripe\ORM\ArrayList;
9
use SilverStripe\StaticPublishQueue\Extension\Engine\SiteTreePublishingEngine;
10
use SilverStripe\StaticPublishQueue\Extension\Publishable\PublishableSiteTree;
11
use SilverStripe\StaticPublishQueue\Test\PublishableSiteTreeTest\Model\PublishablePage;
12
13
class PublishableSiteTreeTest extends SapphireTest
14
{
15
    protected $usesDatabase = true;
16
17
    protected static $required_extensions = [
18
        SiteTree::class => [
19
            PublishableSiteTree::class,
20
        ],
21
    ];
22
23
    protected static $extra_dataobjects = [
24
        PublishablePage::class,
25
    ];
26
27
    public function testObjectsToUpdateOnURLSegmentChange()
28
    {
29
        $this->setExpectedFlushChangesOutput([
30
            [[], ['stub/']],
31
            [['stub/'], []],
32
            [[], ['stub-a-lub-a-dub-dub/']],
33
        ]);
34
35
        $page = new PublishablePage;
36
        $page->URLSegment = 'stub';
37
38
        // publish the page
39
        $page->write();
40
        $page->publishRecursive();
0 ignored issues
show
The method publishRecursive() does not exist on SilverStripe\StaticPubli...t\Model\PublishablePage. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

40
        $page->/** @scrutinizer ignore-call */ 
41
               publishRecursive();
Loading history...
41
42
        // change the URL and go again
43
        $page->URLSegment = 'stub-a-lub-a-dub-dub';
44
        $page->write();
45
        $page->publishRecursive();
46
    }
47
48
    public function testObjectsToUpdateOnURLSegmentChangeWithParents()
49
    {
50
        $this->setExpectedFlushChangesOutput([
51
            [[], ['parent/']],
52
            [[], ['parent/stub/', 'parent/']],
53
            [['parent/stub/'], ['parent/']],
54
            [[], ['parent/stub-a-lub-a-dub-dub/', 'parent/']]
55
        ]);
56
57
        $parent = new PublishablePage;
58
        $parent->URLSegment = 'parent';
59
        $parent->write();
60
        $parent->publishRecursive();
61
62
        $page = new PublishablePage;
63
        $page->URLSegment = 'stub';
64
        $page->ParentID = $parent->ID;
0 ignored issues
show
Bug Best Practice introduced by
The property ParentID does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
65
66
        // publish the page
67
        $page->write();
68
        $page->publishRecursive();
69
70
        // change the URL and go again
71
        $page->URLSegment = 'stub-a-lub-a-dub-dub';
72
        $page->write();
73
        $page->publishRecursive();
74
    }
75
76
    public function testObjectsToUpdateOnSiteTreeRearrange()
77
    {
78
        $this->setExpectedFlushChangesOutput([
79
            [[], ['parent/']],
80
            [[], ['parent/stub/', 'parent/']],
81
            [['parent/stub/'], ['parent/']],
82
            [[], ['stub/']],
83
            [['stub/'], []],
84
            [[], ['parent/stub/', 'parent/']],
85
        ]);
86
87
        $parent = new PublishablePage;
88
89
        $parent->URLSegment = 'parent';
90
        $parent->write();
91
        $parent->publishRecursive();
92
93
        $page = new PublishablePage;
94
95
        $page->URLSegment = 'stub';
96
        $page->ParentID = $parent->ID;
0 ignored issues
show
Bug Best Practice introduced by
The property ParentID does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
97
98
        // publish the page
99
        $page->write();
100
        $page->publishRecursive();
101
102
        // move to root
103
        $page->ParentID = 0;
104
        $page->write();
105
        $page->publishRecursive();
106
107
        // move back
108
        $page->ParentID = $parent->ID;
109
        $page->write();
110
        $page->publishRecursive();
111
    }
112
113
    public function testObjectsToUpdateOnPublish()
114
    {
115
        $parent = new PublishablePage;
116
117
        $stub = $this->getMockBuilder(PublishablePage::class)
118
            ->setMethods(
119
                [
120
                    'getParentID',
121
                    'Parent',
122
                ]
123
            )->getMock();
124
125
        $stub->expects($this->once())
126
            ->method('getParentID')
127
            ->will($this->returnValue('2'));
128
129
        $stub->expects($this->once())
130
            ->method('Parent')
131
            ->will($this->returnValue($parent));
132
133
        $objects = $stub->objectsToUpdate(['action' => 'publish']);
134
        $this->assertContains($stub, $objects);
135
        $this->assertContains($parent, $objects);
136
        $this->assertCount(2, $objects);
137
    }
138
139
    public function testObjectsToUpdateOnUnpublish()
140
    {
141
        $parent = new PublishablePage;
142
143
        $stub = $this->getMockBuilder(PublishablePage::class)
144
            ->setMethods(
145
                [
146
                    'getParentID',
147
                    'Parent',
148
                ]
149
            )->getMock();
150
151
        $stub->expects($this->once())
152
            ->method('getParentID')
153
            ->will($this->returnValue('2'));
154
155
        $stub->expects($this->once())
156
            ->method('Parent')
157
            ->will($this->returnValue($parent));
158
159
        $updates = $stub->objectsToUpdate(['action' => 'unpublish']);
160
        $deletions = $stub->objectsToDelete(['action' => 'unpublish']);
161
        $this->assertContains($stub, $deletions);
162
        $this->assertNotContains($parent, $deletions);
163
        $this->assertContains($parent, $updates);
164
        $this->assertNotContains($stub, $updates);
165
        $this->assertCount(1, $deletions);
166
        $this->assertCount(1, $updates);
167
    }
168
169
    public function testObjectsToDeleteOnPublish()
170
    {
171
        $stub = new PublishablePage;
172
        $objects = $stub->objectsToDelete(['action' => 'publish']);
0 ignored issues
show
The method objectsToDelete() does not exist on SilverStripe\StaticPubli...t\Model\PublishablePage. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

172
        /** @scrutinizer ignore-call */ 
173
        $objects = $stub->objectsToDelete(['action' => 'publish']);
Loading history...
173
        $this->assertEmpty($objects);
174
    }
175
176
    public function testObjectsToDeleteOnUnpublish()
177
    {
178
        $stub = new PublishablePage;
179
        $stub->Title = 'stub';
180
        $objects = $stub->objectsToDelete(['action' => 'unpublish']);
181
        $this->assertContains($stub, $objects);
182
        $this->assertCount(1, $objects);
183
    }
184
185
    public function testObjectsToUpdateOnPublishIfVirtualExists()
186
    {
187
        $redir = new PublishablePage;
188
189
        $stub = $this->getMockBuilder(PublishablePage::class)
190
            ->setMethods(['getMyVirtualPages'])
191
            ->getMock();
192
193
        $stub->expects($this->once())
194
            ->method('getMyVirtualPages')
195
            ->will(
196
                $this->returnValue(
197
                    new ArrayList([$redir])
198
                )
199
            );
200
201
        $objects = $stub->objectsToUpdate(['action' => 'publish']);
202
        $this->assertContains($stub, $objects);
203
        $this->assertContains($redir, $objects);
204
        $this->assertCount(2, $objects);
205
    }
206
207
    public function testObjectsToDeleteOnUnpublishIfVirtualExists()
208
    {
209
        $redir = new PublishablePage;
210
211
        $stub = $this->getMockBuilder(PublishablePage::class)
212
            ->setMethods(['getMyVirtualPages'])
213
            ->getMock();
214
215
        $stub->Title = 'stub';
0 ignored issues
show
Accessing Title on the interface PHPUnit_Framework_MockObject_MockObject suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
216
217
        $stub->expects($this->once())
218
            ->method('getMyVirtualPages')
219
            ->will(
220
                $this->returnValue(
221
                    new ArrayList([$redir])
222
                )
223
            );
224
225
        $objects = $stub->objectsToDelete(['action' => 'unpublish']);
226
        $this->assertContains($stub, $objects);
227
        $this->assertContains($redir, $objects);
228
        $this->assertCount(2, $objects);
229
    }
230
231
    /**
232
     * Takes in a map of urls we expect to be deleted and updated on each successive flushChanges call
233
     * [
234
     *   [['deleted'], ['updated']], // first time its called
235
     *   [['deleted'], ['updated']], // second time its called
236
     * ]
237
     * @param $map
238
     */
239
    protected function setExpectedFlushChangesOutput($map)
240
    {
241
        // build a mock of the extension overriding flushChanges to prevent writing to the queue
242
        $mockExtension = $this->getMockBuilder(SiteTreePublishingEngine::class)
243
            ->setMethods(['flushChanges'])
244
            ->getMock();
245
246
        // IF YOU'RE OF A NERVOUS DISPOSITION, LOOK AWAY NOW
247
        // stub the flushChanges method and make sure that each call is able to assert the correct items are in the
248
        $mockExtension
249
            ->expects($this->exactly(count($map)))
250
            ->method('flushChanges')
251
            ->willReturnOnConsecutiveCalls(...$this->transformMapToCallback($map, $mockExtension));
252
253
        // register our extension instance so it's applied to all SiteTree objects
254
        Injector::inst()->registerService($mockExtension, SiteTreePublishingEngine::class);
255
    }
256
257
    /**
258
     * Transforms the array [['deleted'], ['updated']] into callbacks with assertions
259
     * @param $map
260
     * @param $mockExtension
261
     * @return array
262
     */
263
    protected function transformMapToCallback($map, $mockExtension)
264
    {
265
        $getURL = function ($value) {
266
            return $value->RelativeLink();
267
        };
268
269
        $callbacks = [];
270
        $count = 0;
271
        foreach ($map as $urls) {
272
            ++$count;
273
            list($toDelete, $toUpdate) = $urls;
274
            $callbacks[] = new \PHPUnit_Framework_MockObject_Stub_ReturnCallback(
275
                function () use ($toDelete, $toUpdate, $mockExtension, $getURL, $count) {
276
                    $this->assertSame(
277
                        $toDelete,
278
                        array_map($getURL, $mockExtension->getToDelete()),
279
                        'Failed on delete, iteration ' . $count
280
                    );
281
                    $mockExtension->setToDelete([]);
282
                    $this->assertSame(
283
                        $toUpdate,
284
                        array_map($getURL, $mockExtension->getToUpdate()),
285
                        'Failed on update, iteration ' . $count
286
                    );
287
                    $mockExtension->setToUpdate([]);
288
                }
289
            );
290
        }
291
        return $callbacks;
292
    }
293
}
294