Completed
Push — 4 ( cd71f9...196752 )
by Ingo
28s queued 20s
created

testRedirectMissingRecords()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 28
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 17
nc 1
nop 0
dl 0
loc 28
rs 9.7
c 0
b 0
f 0
1
<?php
2
3
namespace SilverStripe\Forms\Tests\GridField;
4
5
use SilverStripe\Control\Controller;
6
use SilverStripe\Dev\CSSContentParser;
7
use SilverStripe\Dev\FunctionalTest;
8
use SilverStripe\Forms\GridField\GridField;
9
use SilverStripe\Forms\GridField\GridFieldDetailForm;
10
use SilverStripe\Forms\GridField\GridFieldDetailForm_ItemRequest;
11
use SilverStripe\Forms\HiddenField;
12
use SilverStripe\Forms\Tests\GridField\GridFieldDetailFormTest\Category;
13
use SilverStripe\Forms\Tests\GridField\GridFieldDetailFormTest\CategoryController;
14
use SilverStripe\Forms\Tests\GridField\GridFieldDetailFormTest\GroupController;
15
use SilverStripe\Forms\Tests\GridField\GridFieldDetailFormTest\PeopleGroup;
16
use SilverStripe\Forms\Tests\GridField\GridFieldDetailFormTest\Person;
17
use SilverStripe\Forms\Tests\GridField\GridFieldDetailFormTest\TestController;
18
19
/**
20
 * @skipUpgrade
21
 */
22
class GridFieldDetailFormTest extends FunctionalTest
23
{
24
    protected static $fixture_file = 'GridFieldDetailFormTest.yml';
25
26
    protected static $extra_dataobjects = [
27
        Person::class,
28
        PeopleGroup::class,
29
        Category::class,
30
    ];
31
32
    protected static $extra_controllers = [
33
        CategoryController::class,
34
        TestController::class,
35
        GroupController::class,
36
    ];
37
38
    protected static $disable_themes = true;
39
40
    public function testValidator()
41
    {
42
        $this->logInWithPermission('ADMIN');
43
44
        $response = $this->get('GridFieldDetailFormTest_Controller');
45
        $this->assertFalse($response->isError());
46
        $parser = new CSSContentParser($response->getBody());
47
        $addlinkitem = $parser->getBySelector('.grid-field .new-link');
48
        $addlink = (string) $addlinkitem[0]['href'];
49
50
        $response = $this->get($addlink);
51
        $this->assertFalse($response->isError());
52
53
        $parser = new CSSContentParser($response->getBody());
54
        $addform = $parser->getBySelector('#Form_ItemEditForm');
55
        $addformurl = (string) $addform[0]['action'];
56
57
        $response = $this->post(
58
            $addformurl,
59
            [
60
                'FirstName' => 'Jeremiah',
61
                'ajax' => 1,
62
                'action_doSave' => 1
63
            ]
64
        );
65
66
        $parser = new CSSContentParser($response->getBody());
67
        $errors = $parser->getBySelector('span.required');
68
        $this->assertEquals(1, count($errors));
69
70
        $response = $this->post(
71
            $addformurl,
72
            [
73
                'ajax' => 1,
74
                'action_doSave' => 1
75
            ]
76
        );
77
78
        $parser = new CSSContentParser($response->getBody());
79
        $errors = $parser->getBySelector('span.required');
80
        $this->assertEquals(2, count($errors));
81
    }
82
83
    public function testAddForm()
84
    {
85
        $this->logInWithPermission('ADMIN');
86
        $group = PeopleGroup::get()
87
            ->filter('Name', 'My Group')
88
            ->sort('Name')
89
            ->First();
90
        $count = $group->People()->Count();
0 ignored issues
show
Bug introduced by
The method People() does not exist on SilverStripe\ORM\DataObject. 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

90
        $count = $group->/** @scrutinizer ignore-call */ People()->Count();
Loading history...
91
92
        $response = $this->get('GridFieldDetailFormTest_Controller');
93
        $this->assertFalse($response->isError());
94
        $parser = new CSSContentParser($response->getBody());
95
        $addlinkitem = $parser->getBySelector('.grid-field .new-link');
96
        $addlink = (string) $addlinkitem[0]['href'];
97
98
        $response = $this->get($addlink);
99
        $this->assertFalse($response->isError());
100
101
        $parser = new CSSContentParser($response->getBody());
102
        $addform = $parser->getBySelector('#Form_ItemEditForm');
103
        $addformurl = (string) $addform[0]['action'];
104
105
        $response = $this->post(
106
            $addformurl,
107
            [
108
                'FirstName' => 'Jeremiah',
109
                'Surname' => 'BullFrog',
110
                'action_doSave' => 1
111
            ]
112
        );
113
        $this->assertFalse($response->isError());
114
115
        $group = PeopleGroup::get()
116
            ->filter('Name', 'My Group')
117
            ->sort('Name')
118
            ->First();
119
        $this->assertEquals($count + 1, $group->People()->Count());
120
    }
121
122
    public function testViewForm()
123
    {
124
        $this->logInWithPermission('ADMIN');
125
126
        $response = $this->get('GridFieldDetailFormTest_Controller');
127
        $parser   = new CSSContentParser($response->getBody());
128
129
        $viewLink = $parser->getBySelector('.ss-gridfield-items .first .view-link');
130
        $viewLink = (string) $viewLink[0]['href'];
131
132
        $response = $this->get($viewLink);
133
        $parser   = new CSSContentParser($response->getBody());
134
135
        $firstName = $parser->getBySelector('#Form_ItemEditForm_FirstName');
136
        $surname   = $parser->getBySelector('#Form_ItemEditForm_Surname');
137
138
        $this->assertFalse($response->isError());
139
        $this->assertEquals('Jane', (string) $firstName[0]);
140
        $this->assertEquals('Doe', (string) $surname[0]);
141
    }
142
143
    public function testEditForm()
144
    {
145
        $this->logInWithPermission('ADMIN');
146
        $group = PeopleGroup::get()
147
            ->filter('Name', 'My Group')
148
            ->sort('Name')
149
            ->First();
150
        $firstperson = $group->People()->First();
151
        $this->assertTrue($firstperson->Surname != 'Baggins');
152
153
        $response = $this->get('GridFieldDetailFormTest_Controller');
154
        $this->assertFalse($response->isError());
155
        $parser = new CSSContentParser($response->getBody());
156
        $editlinkitem = $parser->getBySelector('.ss-gridfield-items .first .edit-link');
157
        $editlink = (string) $editlinkitem[0]['href'];
158
159
        $response = $this->get($editlink);
160
        $this->assertFalse($response->isError());
161
162
        $parser = new CSSContentParser($response->getBody());
163
        $editform = $parser->getBySelector('#Form_ItemEditForm');
164
        $editformurl = (string) $editform[0]['action'];
165
166
        $response = $this->post(
167
            $editformurl,
168
            [
169
                'FirstName' => 'Bilbo',
170
                'Surname' => 'Baggins',
171
                'action_doSave' => 1
172
            ]
173
        );
174
        $this->assertFalse($response->isError());
175
176
        $group = PeopleGroup::get()
177
            ->filter('Name', 'My Group')
178
            ->sort('Name')
179
            ->First();
180
        $this->assertListContains([['Surname' => 'Baggins']], $group->People());
181
    }
182
183
    public function testEditFormWithManyMany()
184
    {
185
        $this->logInWithPermission('ADMIN');
186
187
        // Edit the first person
188
        $response = $this->get('GridFieldDetailFormTest_CategoryController');
189
        // Find the link to add a new favourite group
190
        $parser = new CSSContentParser($response->getBody());
191
        $addLink = $parser->getBySelector('#Form_Form_testgroupsfield .new-link');
192
        $addLink = (string) $addLink[0]['href'];
193
194
        // Add a new favourite group
195
        $response = $this->get($addLink);
196
        $parser = new CSSContentParser($response->getBody());
197
        $addform = $parser->getBySelector('#Form_ItemEditForm');
198
        $addformurl = (string) $addform[0]['action'];
199
200
        $response = $this->post(
201
            $addformurl,
202
            [
203
                'Name' => 'My Favourite Group',
204
                'ajax' => 1,
205
                'action_doSave' => 1
206
            ]
207
        );
208
        $this->assertFalse($response->isError());
209
210
        $person = $this->objFromFixture(Person::class, 'jane');
211
        $favouriteGroup = $person->FavouriteGroups()->first();
0 ignored issues
show
Bug introduced by
The method FavouriteGroups() does not exist on SilverStripe\ORM\DataObject. 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

211
        $favouriteGroup = $person->/** @scrutinizer ignore-call */ FavouriteGroups()->first();
Loading history...
212
213
        $this->assertInstanceOf(PeopleGroup::class, $favouriteGroup);
214
    }
215
216
    public function testEditFormWithManyManyExtraData()
217
    {
218
        $this->logInWithPermission('ADMIN');
219
220
        // Lists all categories for a person
221
        $response = $this->get('GridFieldDetailFormTest_CategoryController');
222
        $this->assertFalse($response->isError());
223
        $parser = new CSSContentParser($response->getBody());
224
        $editlinkitem = $parser->getBySelector('.ss-gridfield-items .first .edit-link');
225
        $editlink = (string) $editlinkitem[0]['href'];
226
227
        // Edit a single category, incl. manymany extrafields added manually
228
        // through GridFieldDetailFormTest_CategoryController
229
        $response = $this->get($editlink);
230
        $this->assertFalse($response->isError());
231
        $parser = new CSSContentParser($response->getBody());
232
        $editform = $parser->getBySelector('#Form_ItemEditForm');
233
        $editformurl = (string) $editform[0]['action'];
234
235
        $manyManyField = $parser->getByXpath('//*[@id="Form_ItemEditForm"]//input[@name="ManyMany[IsPublished]"]');
236
        $this->assertTrue((bool)$manyManyField);
237
238
        // Test save of IsPublished field
239
        $response = $this->post(
240
            $editformurl,
241
            [
242
                'Name' => 'Updated Category',
243
                'ManyMany' => [
244
                    'IsPublished' => 1,
245
                    'PublishedBy' => 'Richard'
246
                ],
247
                'action_doSave' => 1
248
            ]
249
        );
250
        $this->assertFalse($response->isError());
251
        $person = $this->objFromFixture(Person::class, 'jane');
252
        $category = $person->Categories()->filter(['Name' => 'Updated Category'])->First();
0 ignored issues
show
Bug introduced by
The method Categories() does not exist on SilverStripe\ORM\DataObject. 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

252
        $category = $person->/** @scrutinizer ignore-call */ Categories()->filter(['Name' => 'Updated Category'])->First();
Loading history...
253
        $this->assertEquals(
254
            [
255
                'IsPublished' => 1,
256
                'PublishedBy' => 'Richard'
257
            ],
258
            $person->Categories()->getExtraData('', $category->ID)
259
        );
260
261
        // Test update of value with falsey value
262
        $response = $this->post(
263
            $editformurl,
264
            [
265
                'Name' => 'Updated Category',
266
                'ManyMany' => [
267
                    'PublishedBy' => ''
268
                ],
269
                'action_doSave' => 1
270
            ]
271
        );
272
        $this->assertFalse($response->isError());
273
274
        $person = $this->objFromFixture(Person::class, 'jane');
275
        $category = $person->Categories()->filter(['Name' => 'Updated Category'])->First();
276
        $this->assertEquals(
277
            [
278
                'IsPublished' => 0,
279
                'PublishedBy' => ''
280
            ],
281
            $person->Categories()->getExtraData('', $category->ID)
282
        );
283
    }
284
285
    public function testNestedEditForm()
286
    {
287
        $this->logInWithPermission('ADMIN');
288
289
        $group = $this->objFromFixture(PeopleGroup::class, 'group');
290
        $person = $group->People()->First();
291
        $category = $person->Categories()->First();
292
293
        // Get first form (GridField managing PeopleGroup)
294
        $response = $this->get('GridFieldDetailFormTest_GroupController');
295
        $this->assertFalse($response->isError());
296
        $parser = new CSSContentParser($response->getBody());
297
298
        $groupEditLink = $parser->getByXpath(
299
            '//tr[contains(@class, "ss-gridfield-item") and contains(@data-id, "'
300
            . $group->ID . '")]//a'
301
        );
302
        $this->assertEquals(
303
            'GridFieldDetailFormTest_GroupController/Form/field/testfield/item/' . $group->ID . '/edit',
304
            (string)$groupEditLink[0]['href']
305
        );
306
307
        // Get second level form (GridField managing Person)
308
        $response = $this->get((string)$groupEditLink[0]['href']);
309
        $this->assertFalse($response->isError());
310
        $parser = new CSSContentParser($response->getBody());
311
        $personEditLink = $parser->getByXpath(
312
            '//fieldset[@id="Form_ItemEditForm_People"]' .
313
            '//tr[contains(@class, "ss-gridfield-item") and contains(@data-id, "' . $person->ID . '")]//a'
314
        );
315
        $this->assertEquals(
316
            sprintf(
317
                'GridFieldDetailFormTest_GroupController/Form/field/testfield/item/%d/ItemEditForm/field/People'
318
                . '/item/%d/edit',
319
                $group->ID,
320
                $person->ID
321
            ),
322
            (string)$personEditLink[0]['href']
323
        );
324
325
        // Get third level form (GridField managing Category)
326
        $response = $this->get((string)$personEditLink[0]['href']);
327
        $this->assertFalse($response->isError());
328
        $parser = new CSSContentParser($response->getBody());
329
        $categoryEditLink = $parser->getByXpath(
330
            '//fieldset[@id="Form_ItemEditForm_Categories"]'
331
            . '//tr[contains(@class, "ss-gridfield-item") and contains(@data-id, "' . $category->ID . '")]//a'
332
        );
333
        $this->assertEquals(
334
            sprintf(
335
                'GridFieldDetailFormTest_GroupController/Form/field/testfield/item/%d/ItemEditForm/field/People'
336
                . '/item/%d/ItemEditForm/field/Categories/item/%d/edit',
337
                $group->ID,
338
                $person->ID,
339
                $category->ID
340
            ),
341
            (string)$categoryEditLink[0]['href']
342
        );
343
344
        // Fourth level form would be a Category detail view
345
    }
346
347
    public function testCustomItemRequestClass()
348
    {
349
        $this->logInWithPermission('ADMIN');
350
351
        $component = new GridFieldDetailForm();
352
        $this->assertEquals('SilverStripe\\Forms\\GridField\\GridFieldDetailForm_ItemRequest', $component->getItemRequestClass());
353
        $component->setItemRequestClass('GridFieldDetailFormTest_ItemRequest');
354
        $this->assertEquals('GridFieldDetailFormTest_ItemRequest', $component->getItemRequestClass());
355
    }
356
357
    public function testItemEditFormCallback()
358
    {
359
        $this->logInWithPermission('ADMIN');
360
361
        $category = new Category();
362
        $component = new GridFieldDetailForm();
363
        $component->setItemEditFormCallback(
364
            function ($form, $component) {
0 ignored issues
show
Unused Code introduced by
The parameter $component is not used and could be removed. ( Ignorable by Annotation )

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

364
            function ($form, /** @scrutinizer ignore-unused */ $component) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
365
                $form->Fields()->push(new HiddenField('Callback'));
366
            }
367
        );
368
        // Note: A lot of scaffolding to execute the tested logic,
369
        // due to the coupling of form creation with itemRequest handling (and its context)
370
        /** @skipUpgrade */
371
        $itemRequest = new GridFieldDetailForm_ItemRequest(
372
            GridField::create('Categories', 'Categories'),
373
            $component,
374
            $category,
375
            Controller::curr(),
376
            'Form'
377
        );
378
        $itemRequest->setRequest(Controller::curr()->getRequest());
379
        $form = $itemRequest->ItemEditForm();
380
        $this->assertNotNull($form->Fields()->fieldByName('Callback'));
0 ignored issues
show
Bug introduced by
The method Fields() does not exist on SilverStripe\Control\HTTPResponse. ( Ignorable by Annotation )

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

380
        $this->assertNotNull($form->/** @scrutinizer ignore-call */ Fields()->fieldByName('Callback'));

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
381
    }
382
383
    /**
384
     * Tests that a has-many detail form is pre-populated with the parent ID.
385
     */
386
    public function testHasManyFormPrePopulated()
387
    {
388
        $group = $this->objFromFixture(
389
            PeopleGroup::class,
390
            'group'
391
        );
392
393
        $this->logInWithPermission('ADMIN');
394
395
        $response = $this->get('GridFieldDetailFormTest_Controller');
396
        $parser = new CSSContentParser($response->getBody());
397
        $addLink = $parser->getBySelector('.grid-field .new-link');
398
        $addLink = (string) $addLink[0]['href'];
399
400
        $response = $this->get($addLink);
401
        $parser = new CSSContentParser($response->getBody());
402
        $title = $parser->getBySelector('#Form_ItemEditForm_GroupID_Holder span');
403
        $id = $parser->getBySelector('#Form_ItemEditForm_GroupID_Holder input');
404
405
        $this->assertEquals($group->Name, (string) $title[0]);
0 ignored issues
show
Bug Best Practice introduced by
The property Name does not exist on SilverStripe\ORM\DataObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
406
        $this->assertEquals($group->ID, (string) $id[0]['value']);
407
    }
408
409
    public function testRedirectMissingRecords()
410
    {
411
        $origAutoFollow = $this->autoFollowRedirection;
412
        $this->autoFollowRedirection = false;
413
414
        // GridField is filtered people in "My Group", which does't include "jack"
415
        $included = $this->objFromFixture(Person::class, 'joe');
416
        $excluded = $this->objFromFixture(Person::class, 'jack');
417
418
        $response = $this->get(sprintf(
419
            'GridFieldDetailFormTest_Controller/Form/field/testfield/item/%d/edit',
420
            $included->ID
421
        ));
422
        $this->assertFalse(
423
            $response->isRedirect(),
424
            'Existing records are not redirected'
425
        );
426
427
        $response = $this->get(sprintf(
428
            'GridFieldDetailFormTest_Controller/Form/field/testfield/item/%d/edit',
429
            $excluded->ID
430
        ));
431
        $this->assertTrue(
432
            $response->isRedirect(),
433
            'Non-existing records are redirected'
434
        );
435
436
        $this->autoFollowRedirection = $origAutoFollow;
437
    }
438
}
439