Issues (216)

tests/TopPage/TopPageTest.php (6 issues)

1
<?php
2
3
namespace DNADesign\Elemental\Tests\TopPage;
4
5
use DNADesign\Elemental\Extensions\ElementalAreasExtension;
6
use DNADesign\Elemental\Extensions\ElementalPageExtension;
7
use DNADesign\Elemental\Models\BaseElement;
8
use DNADesign\Elemental\Models\ElementalArea;
9
use DNADesign\Elemental\TopPage;
10
use Page;
11
use SilverStripe\Dev\SapphireTest;
12
use SilverStripe\ORM\DataObject;
13
14
class TopPageTest extends SapphireTest
15
{
16
    /**
17
     * @var string
18
     */
19
    protected static $fixture_file = 'TopPageTest.yml';
20
21
    /**
22
     * @var array
23
     */
24
    protected static $required_extensions = [
25
        TestBlockPage::class => [
26
            ElementalPageExtension::class,
27
        ],
28
        TestChildPage::class => [
29
            ElementalPageExtension::class,
30
        ],
31
        Page::class => [
32
            TopPage\SiteTreeExtension::class,
33
        ],
34
        ElementalArea::class => [
35
            TopPage\DataExtension::class,
36
        ],
37
        BaseElement::class => [
38
            TopPage\DataExtension::class,
39
        ],
40
        TestList::class => [
41
            ElementalAreasExtension::class,
42
        ],
43
    ];
44
45
    /**
46
     * @var array
47
     */
48
    protected static $extra_dataobjects = [
49
        TestContent::class,
50
        TestList::class,
51
        TestBlockPage::class,
52
        TestChildPage::class,
53
    ];
54
55
    /**
56
     * @param string $pageIdentifier
57
     * @param string $pageClass
58
     * @param string $objectIdentifier
59
     * @param string $objectClass
60
     * @dataProvider objectsProvider
61
     */
62
    public function testTestGetTopPage(
63
        string $pageIdentifier,
64
        string $pageClass,
65
        string $objectIdentifier,
66
        string $objectClass
67
    ): void {
68
        /** @var Page|TopPage\SiteTreeExtension $content */
69
        $page = $this->objFromFixture($pageClass, $pageIdentifier);
70
71
        /** @var DataObject|TopPage\DataExtension $object */
72
        $object = $this->objFromFixture($objectClass, $objectIdentifier);
73
74
        $topPage = $object->getTopPage();
75
76
        $this->assertNotNull($topPage);
77
        $this->assertEquals((int) $page->ID, (int) $topPage->ID);
78
    }
79
80
    /**
81
     * @param string $pageIdentifier
82
     * @param string $pageClass
83
     * @param string $objectIdentifier
84
     * @param string $objectClass
85
     * @dataProvider objectsProvider
86
     */
87
    public function testTestUpdateTopPageEmptyCache(
88
        string $pageIdentifier,
89
        string $pageClass,
90
        string $objectIdentifier,
91
        string $objectClass
92
    ): void {
93
        /** @var TopPage\DataExtension $extension */
94
        $extension = singleton(TopPage\DataExtension::class);
95
        $extension->withTopPageUpdate(
96
            true,
97
            function () use ($pageIdentifier, $pageClass, $objectIdentifier, $objectClass): void {
98
                /** @var Page|TopPage\SiteTreeExtension $content */
99
                $page = $this->objFromFixture($pageClass, $pageIdentifier);
100
101
                /** @var DataObject|TopPage\DataExtension $object */
102
                $object = $this->objFromFixture($objectClass, $objectIdentifier);
103
104
                $this->assertEquals(0, (int) $object->TopPageID);
105
106
                $object->forceChange();
107
                $id = $object->write();
108
                $object = DataObject::get($object->ClassName)->byID($id);
109
110
                $this->assertEquals((int) $page->ID, (int) $object->TopPageID);
111
112
                // do a second write to make sure that we won't override existing top page
113
                $object->forceChange();
114
                $id = $object->write();
115
                $object = DataObject::get($object->ClassName)->byID($id);
116
117
                $this->assertEquals((int) $page->ID, (int) $object->TopPageID);
118
            }
119
        );
120
    }
121
122
    public function testNewPage(): void
123
    {
124
        /** @var TopPage\DataExtension $extension */
125
        $extension = singleton(TopPage\DataExtension::class);
126
        $extension->withTopPageUpdate(
127
            true,
128
            function (): void {
129
                $page = TestBlockPage::create();
130
                $page->Title = 'New page test';
131
                $page->write();
132
133
                /** @var ElementalArea|TopPage\DataExtension $area */
134
                $area = $page->ElementalArea();
135
                $this->assertEquals((int) $page->ID, (int) $area->TopPageID);
0 ignored issues
show
Bug Best Practice introduced by
The property TopPageID does not exist on DNADesign\Elemental\Models\ElementalArea. Since you implemented __get, consider adding a @property annotation.
Loading history...
136
            }
137
        );
138
    }
139
140
    /**
141
     * @param bool $populateTopPage
142
     * @dataProvider populateTopPageProvider
143
     */
144
    public function testNewBlock(bool $populateTopPage): void
145
    {
146
        /** @var TopPage\DataExtension $extension */
147
        $extension = singleton(TopPage\DataExtension::class);
148
        $extension->withTopPageUpdate(
149
            true,
150
            function () use ($populateTopPage): void {
151
                if ($populateTopPage) {
152
                    $this->populateTopPageForAllObjects();
153
                }
154
155
                /** @var TestBlockPage $page */
156
                $page = $this->objFromFixture(TestBlockPage::class, 'block-page1');
157
158
                /** @var ElementalArea $area */
159
                $area = $this->objFromFixture(ElementalArea::class, 'area3');
160
161
                /** @var TestContent|TopPage\DataExtension $content */
162
                $content = TestContent::create();
163
                $content->Title = 'Fresh block';
0 ignored issues
show
The property Title does not seem to exist on DNADesign\Elemental\TopPage\DataExtension.
Loading history...
164
165
                $area->Elements()->add($content);
0 ignored issues
show
It seems like $content can also be of type DNADesign\Elemental\TopPage\DataExtension; however, parameter $item of SilverStripe\ORM\HasManyList::add() does only seem to accept SilverStripe\ORM\DataObject|integer, maybe add an additional type check? ( Ignorable by Annotation )

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

165
                $area->Elements()->add(/** @scrutinizer ignore-type */ $content);
Loading history...
166
                $content = DataObject::get($content->ClassName)->byID($content->ID);
0 ignored issues
show
The property ClassName does not seem to exist on DNADesign\Elemental\TopPage\DataExtension.
Loading history...
The property ID does not seem to exist on DNADesign\Elemental\TopPage\DataExtension.
Loading history...
167
168
                $this->assertEquals((int) $page->ID, (int) $content->TopPageID);
169
            }
170
        );
171
    }
172
173
    /**
174
     * This test is checking for page duplication in two cases
175
     * Case 1: standard duplication
176
     * Case 2: duplication with a fixed page setting
177
     * The seconds case shows that it's possible to use the withFixedTopPage to set the top page to arbitrary value
178
     * and completely bypass page determination logic
179
     * This is needed in some edge cases were automatic determination is not possible due to the object not being
180
     * assigned to the parent object at the time of duplication but rather later
181
     *
182
     * @param int $fixedPageID
183
     * @dataProvider fixedPagesProvider
184
     */
185
    public function testPageDuplication(int $fixedPageID): void
186
    {
187
        /** @var TopPage\DataExtension $extension */
188
        $extension = singleton(TopPage\DataExtension::class);
189
        $extension->withFixedTopPage($fixedPageID, function () use ($extension, $fixedPageID) {
190
            $extension->withTopPageUpdate(
191
                true,
192
                function () use ($fixedPageID): void {
193
                    $this->populateTopPageForAllObjects();
194
195
                    /** @var TestBlockPage $page */
196
                    $page = $this->objFromFixture(TestBlockPage::class, 'block-page1');
197
198
                    /** @var TestChildPage $childPage */
199
                    $childPage = $this->objFromFixture(TestChildPage::class, 'child-page1');
200
201
                    $page->duplicate();
202
                    $pages = TestBlockPage::get()->filter(['Title' => 'BlockPage1'])->sort('ID', 'DESC');
203
204
                    $this->assertCount(2, $pages);
205
206
                    $pageClone = $pages->first();
207
                    $childPages = TestChildPage::get()->filter(['Title' => 'ChildPage1'])->sort('ID', 'DESC');
208
209
                    $this->assertCount(2, $childPages);
210
211
                    $childClone = $childPages->first();
212
213
                    $this->assertNotEquals((int) $childPage->ID, (int) $childClone->ID);
214
215
                    $objects = [
216
                        [TestList::class, 'List1', $pageClone],
217
                        [TestContent::class, 'Content1', $pageClone],
218
                        [TestList::class, 'List2', $childClone],
219
                        [TestContent::class, 'Content2', $childClone],
220
                    ];
221
222
                    foreach ($objects as $objectData) {
223
                        $class = array_shift($objectData);
224
                        $title = array_shift($objectData);
225
                        $page = array_shift($objectData);
226
227
                        $items = DataObject::get($class)->filter(['Title' => $title])->sort('ID', 'DESC');
228
229
                        $this->assertCount(2, $items);
230
231
                        /** @var DataObject|TopPage\DataExtension $objectClone */
232
                        $objectClone = $items->first();
233
234
                        $expected = $fixedPageID ?: (int) $page->ID;
235
                        $this->assertEquals($expected, (int) $objectClone->TopPageID);
236
237
                        /** @var ElementalArea|TopPage\DataExtension $area */
238
                        $area = $objectClone->Parent();
239
240
                        $this->assertEquals($expected, (int) $area->TopPageID);
0 ignored issues
show
Bug Best Practice introduced by
The property TopPageID does not exist on DNADesign\Elemental\Models\ElementalArea. Since you implemented __get, consider adding a @property annotation.
Loading history...
241
                    }
242
                }
243
            );
244
        });
245
    }
246
247
    public function objectsProvider(): array
248
    {
249
        return [
250
            [
251
                'block-page1',
252
                TestBlockPage::class,
253
                'content1',
254
                TestContent::class,
255
            ],
256
            [
257
                'block-page1',
258
                TestBlockPage::class,
259
                'list1',
260
                TestList::class,
261
            ],
262
            [
263
                'block-page1',
264
                TestBlockPage::class,
265
                'area1',
266
                ElementalArea::class,
267
            ],
268
            [
269
                'block-page1',
270
                TestBlockPage::class,
271
                'area3',
272
                ElementalArea::class,
273
            ],
274
            [
275
                'child-page1',
276
                TestChildPage::class,
277
                'content2',
278
                TestContent::class,
279
            ],
280
            [
281
                'child-page1',
282
                TestChildPage::class,
283
                'list2',
284
                TestList::class,
285
            ],
286
            [
287
                'child-page1',
288
                TestChildPage::class,
289
                'area2',
290
                ElementalArea::class,
291
            ],
292
            [
293
                'child-page1',
294
                TestChildPage::class,
295
                'area4',
296
                ElementalArea::class,
297
            ],
298
        ];
299
    }
300
301
    public function populateTopPageProvider(): array
302
    {
303
        return [
304
            [true],
305
            [false],
306
        ];
307
    }
308
309
    public function fixedPagesProvider(): array
310
    {
311
        return [
312
            [0], // feature is disabled
313
            [99], // obviously non-existent page
314
        ];
315
    }
316
317
    private function populateTopPageForAllObjects(): void
318
    {
319
        $list = $this->objectsProvider();
320
321
        foreach ($list as $objects) {
322
            array_shift($objects);
323
            array_shift($objects);
324
            $identifier = array_shift($objects);
325
            $class = array_shift($objects);
326
327
            $object = $this->objFromFixture($class, $identifier);
328
            $object->forceChange();
329
            $object->write();
330
        }
331
    }
332
}
333