Passed
Pull Request — master (#133)
by
unknown
02:23
created

PublishableSiteTreeTest   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 286
Duplicated Lines 0 %

Importance

Changes 4
Bugs 0 Features 1
Metric Value
wmc 13
eloc 158
c 4
b 0
f 1
dl 0
loc 286
rs 10

12 Methods

Rating   Name   Duplication   Size   Complexity  
A testObjectsToUpdateOnURLSegmentChangeWithParents() 0 26 1
A testObjectsToUpdateOnPublishIfVirtualExists() 0 20 1
A transformMapToCallback() 0 29 2
A testObjectsToUpdateOnUnpublish() 0 28 1
A testObjectsToUpdateOnPublish() 0 24 1
A testObjectsToDeleteOnPublish() 0 5 1
A setExpectedFlushChangesOutput() 0 16 1
A testObjectsToDeleteOnUnpublish() 0 7 1
A setUp() 0 5 1
A testObjectsToDeleteOnUnpublishIfVirtualExists() 0 22 1
A testObjectsToUpdateOnSiteTreeRearrange() 0 35 1
A testObjectsToUpdateOnURLSegmentChange() 0 19 1
1
<?php
2
3
namespace SilverStripe\StaticPublishQueue\Test;
4
5
use Psr\Log\LoggerInterface;
6
use SilverStripe\CMS\Model\SiteTree;
7
use SilverStripe\Core\Injector\Injector;
8
use SilverStripe\Dev\SapphireTest;
9
use SilverStripe\ORM\ArrayList;
10
use SilverStripe\StaticPublishQueue\Extension\Engine\SiteTreePublishingEngine;
11
use SilverStripe\StaticPublishQueue\Extension\Publishable\PublishableSiteTree;
12
use SilverStripe\StaticPublishQueue\Test\PublishableSiteTreeTest\Model\PublishablePage;
13
14
class PublishableSiteTreeTest extends SapphireTest
15
{
16
    protected $usesDatabase = true;
17
18
    protected static $required_extensions = [
19
        SiteTree::class => [
20
            PublishableSiteTree::class,
21
        ],
22
    ];
23
24
    protected static $extra_dataobjects = [
25
        PublishablePage::class,
26
    ];
27
28
    protected function setUp()
29
    {
30
        parent::setUp();
31
32
        Injector::inst()->registerService(@$this->createMock(LoggerInterface::class), LoggerInterface::class);
33
    }
34
35
    public function testObjectsToUpdateOnURLSegmentChange()
36
    {
37
        $this->setExpectedFlushChangesOutput([
38
            [[], ['stub/']],
39
            [['stub/'], []],
40
            [[], ['stub-a-lub-a-dub-dub/']],
41
        ]);
42
43
        $page = new PublishablePage;
44
        $page->URLSegment = 'stub';
45
46
        // publish the page
47
        $page->write();
48
        $page->publishRecursive();
0 ignored issues
show
Bug introduced by
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

48
        $page->/** @scrutinizer ignore-call */ 
49
               publishRecursive();
Loading history...
49
50
        // change the URL and go again
51
        $page->URLSegment = 'stub-a-lub-a-dub-dub';
52
        $page->write();
53
        $page->publishRecursive();
54
    }
55
56
    public function testObjectsToUpdateOnURLSegmentChangeWithParents()
57
    {
58
        $this->setExpectedFlushChangesOutput([
59
            [[], ['parent/']],
60
            [[], ['parent/stub/', 'parent/']],
61
            [['parent/stub/'], ['parent/']],
62
            [[], ['parent/stub-a-lub-a-dub-dub/', 'parent/']]
63
        ]);
64
65
        $parent = new PublishablePage;
66
        $parent->URLSegment = 'parent';
67
        $parent->write();
68
        $parent->publishRecursive();
69
70
        $page = new PublishablePage;
71
        $page->URLSegment = 'stub';
72
        $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...
73
74
        // publish the page
75
        $page->write();
76
        $page->publishRecursive();
77
78
        // change the URL and go again
79
        $page->URLSegment = 'stub-a-lub-a-dub-dub';
80
        $page->write();
81
        $page->publishRecursive();
82
    }
83
84
    public function testObjectsToUpdateOnSiteTreeRearrange()
85
    {
86
        $this->setExpectedFlushChangesOutput([
87
            [[], ['parent/']],
88
            [[], ['parent/stub/', 'parent/']],
89
            [['parent/stub/'], ['parent/']],
90
            [[], ['stub/']],
91
            [['stub/'], []],
92
            [[], ['parent/stub/', 'parent/']],
93
        ]);
94
95
        $parent = new PublishablePage;
96
97
        $parent->URLSegment = 'parent';
98
        $parent->write();
99
        $parent->publishRecursive();
100
101
        $page = new PublishablePage;
102
103
        $page->URLSegment = 'stub';
104
        $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...
105
106
        // publish the page
107
        $page->write();
108
        $page->publishRecursive();
109
110
        // move to root
111
        $page->ParentID = 0;
112
        $page->write();
113
        $page->publishRecursive();
114
115
        // move back
116
        $page->ParentID = $parent->ID;
117
        $page->write();
118
        $page->publishRecursive();
119
    }
120
121
    public function testObjectsToUpdateOnPublish()
122
    {
123
        $parent = new PublishablePage;
124
125
        $stub = $this->getMockBuilder(PublishablePage::class)
126
            ->setMethods(
127
                [
128
                    'getParentID',
129
                    'Parent',
130
                ]
131
            )->getMock();
132
133
        $stub->expects($this->once())
134
            ->method('getParentID')
135
            ->will($this->returnValue('2'));
136
137
        $stub->expects($this->once())
138
            ->method('Parent')
139
            ->will($this->returnValue($parent));
140
141
        $objects = $stub->objectsToUpdate(['action' => 'publish']);
142
        $this->assertContains($stub, $objects);
143
        $this->assertContains($parent, $objects);
144
        $this->assertCount(2, $objects);
145
    }
146
147
    public function testObjectsToUpdateOnUnpublish()
148
    {
149
        $parent = new PublishablePage;
150
151
        $stub = $this->getMockBuilder(PublishablePage::class)
152
            ->setMethods(
153
                [
154
                    'getParentID',
155
                    'Parent',
156
                ]
157
            )->getMock();
158
159
        $stub->expects($this->once())
160
            ->method('getParentID')
161
            ->will($this->returnValue('2'));
162
163
        $stub->expects($this->once())
164
            ->method('Parent')
165
            ->will($this->returnValue($parent));
166
167
        $updates = $stub->objectsToUpdate(['action' => 'unpublish']);
168
        $deletions = $stub->objectsToDelete(['action' => 'unpublish']);
169
        $this->assertContains($stub, $deletions);
170
        $this->assertNotContains($parent, $deletions);
171
        $this->assertContains($parent, $updates);
172
        $this->assertNotContains($stub, $updates);
173
        $this->assertCount(1, $deletions);
174
        $this->assertCount(1, $updates);
175
    }
176
177
    public function testObjectsToDeleteOnPublish()
178
    {
179
        $stub = new PublishablePage;
180
        $objects = $stub->objectsToDelete(['action' => 'publish']);
0 ignored issues
show
Bug introduced by
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

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