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(); |
|
|
|
|
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(); |
|
|
|
|
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(); |
|
|
|
|
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) { |
|
|
|
|
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')); |
|
|
|
|
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]); |
|
|
|
|
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
|
|
|
|