Completed
Push — 4.7 ( 1a75ef...d13d3a )
by Maxime
28s queued 18s
created

testObjectForKeyObjectValue()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 1
eloc 8
c 1
b 1
f 0
nc 1
nop 0
dl 0
loc 11
rs 10
1
<?php
2
3
namespace SilverStripe\Forms\Tests;
4
5
use SilverStripe\Assets\File;
6
use SilverStripe\Assets\Folder;
7
use SilverStripe\Control\Session;
8
use SilverStripe\Dev\CSSContentParser;
9
use SilverStripe\Dev\SapphireTest;
10
use SilverStripe\Control\HTTPRequest;
11
use SilverStripe\Forms\FieldList;
12
use SilverStripe\Forms\Form;
13
use SilverStripe\Forms\TreeDropdownField;
14
use SilverStripe\ORM\DataObject;
15
use SilverStripe\ORM\Tests\HierarchyTest\TestObject;
16
17
class TreeDropdownFieldTest extends SapphireTest
18
{
19
20
    protected static $fixture_file = 'TreeDropdownFieldTest.yml';
21
22
    protected static $extra_dataobjects = [
23
        TestObject::class
24
    ];
25
26
    public function testSchemaStateDefaults()
27
    {
28
        $field = new TreeDropdownField('TestTree', 'Test tree', Folder::class);
29
        $folder = $this->objFromFixture(Folder::class, 'folder1-subfolder1');
30
31
        $schema = $field->getSchemaStateDefaults();
32
        $this->assertFalse(isset($schema['data']['valueObject']));
33
34
        $field->setValue($folder->ID);
35
36
        $schema = $field->getSchemaStateDefaults();
37
        $this->assertEquals($folder->ID, $schema['data']['valueObject']['id']);
38
        $this->assertTrue(isset($schema['data']['valueObject']));
39
        $this->assertFalse($schema['data']['showSelectedPath']);
40
        $this->assertEquals('', $schema['data']['valueObject']['titlePath']);
41
42
        $field->setShowSelectedPath(true);
43
        $schema = $field->getSchemaStateDefaults();
44
        $this->assertTrue($schema['data']['showSelectedPath']);
45
        $this->assertEquals(
46
            'FileTest-folder1/FileTest-folder1-subfolder1/',
47
            $schema['data']['valueObject']['titlePath']
48
        );
49
    }
50
51
    public function testTreeSearchJson()
52
    {
53
        $field = new TreeDropdownField('TestTree', 'Test tree', Folder::class);
54
55
        // case insensitive search against keyword 'sub' for folders
56
        $request = new HTTPRequest('GET', 'url', ['search'=>'sub', 'format' => 'json']);
57
        $request->setSession(new Session([]));
58
        $response = $field->tree($request);
59
        $tree = json_decode($response->getBody(), true);
60
61
        $folder1 = $this->objFromFixture(Folder::class, 'folder1');
62
        $folder1Subfolder1 = $this->objFromFixture(Folder::class, 'folder1-subfolder1');
63
64
        $this->assertContains(
65
            $folder1->Name,
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...
66
            array_column($tree['children'], 'title'),
67
            $folder1->Name . ' is found in the json'
68
        );
69
70
        $filtered = array_filter($tree['children'], function ($entry) use ($folder1) {
71
            return $folder1->Name === $entry['title'];
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...
72
        });
73
        $folder1Tree = array_pop($filtered);
74
75
        $this->assertContains(
76
            $folder1Subfolder1->Name,
77
            array_column($folder1Tree['children'], 'title'),
78
            $folder1Subfolder1->Name . ' is found in the folder1 entry in the json'
79
        );
80
    }
81
82
    public function testTreeSearchJsonFlatlist()
83
    {
84
        $field = new TreeDropdownField('TestTree', 'Test tree', Folder::class);
85
86
        // case insensitive search against keyword 'sub' for folders
87
        $request = new HTTPRequest('GET', 'url', ['search'=>'sub', 'format' => 'json', 'flatList' => '1']);
88
        $request->setSession(new Session([]));
89
        $response = $field->tree($request);
90
        $tree = json_decode($response->getBody(), true);
91
92
        $folder1 = $this->objFromFixture(Folder::class, 'folder1');
93
        $folder1Subfolder1 = $this->objFromFixture(Folder::class, 'folder1-subfolder1');
94
95
        $this->assertNotContains(
96
            $folder1->Name,
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...
97
            array_column($tree['children'], 'title'),
98
            $folder1->Name . ' is not found in the json'
99
        );
100
101
        $this->assertContains(
102
            $folder1Subfolder1->Name,
103
            array_column($tree['children'], 'title'),
104
            $folder1Subfolder1->Name . ' is found in the json'
105
        );
106
    }
107
108
    public function testTreeSearchJsonFlatlistWithLowNodeThreshold()
109
    {
110
        // Initialise our TreeDropDownField
111
        $field = new TreeDropdownField('TestTree', 'Test tree', TestObject::class);
112
        $field->config()->set('node_threshold_total', 2);
113
114
        // Search for all Test object matching our criteria
115
        $request = new HTTPRequest(
116
            'GET',
117
            'url',
118
            ['search' => 'MatchSearchCriteria', 'format' => 'json', 'flatList' => '1']
119
        );
120
        $request->setSession(new Session([]));
121
        $response = $field->tree($request);
122
        $tree = json_decode($response->getBody(), true);
123
        $actualNodeIDs = array_column($tree['children'], 'id');
124
125
126
        // Get the list of expected node IDs from the YML Fixture
127
        $expectedNodeIDs = array_map(
128
            function ($key) {
129
                return $this->objFromFixture(TestObject::class, $key)->ID;
130
            },
131
            ['zero', 'oneA', 'twoAi', 'three'] // Those are the identifiers of the object we expect our search to find
132
        );
133
134
        sort($actualNodeIDs);
135
        sort($expectedNodeIDs);
136
137
        $this->assertEquals($expectedNodeIDs, $actualNodeIDs);
138
    }
139
140
    public function testTreeSearch()
141
    {
142
        $field = new TreeDropdownField('TestTree', 'Test tree', Folder::class);
143
144
        // case insensitive search against keyword 'sub' for folders
145
        $request = new HTTPRequest('GET', 'url', ['search'=>'sub']);
146
        $request->setSession(new Session([]));
147
        $response = $field->tree($request);
148
        $tree = $response->getBody();
149
150
        $folder1 = $this->objFromFixture(Folder::class, 'folder1');
151
        $folder1Subfolder1 = $this->objFromFixture(Folder::class, 'folder1-subfolder1');
152
153
        $parser = new CSSContentParser($tree);
154
        $cssPath = 'ul.tree li#selector-TestTree-' . $folder1->ID . ' li#selector-TestTree-' . $folder1Subfolder1->ID . ' a span.item';
155
        $firstResult = $parser->getBySelector($cssPath);
156
        $this->assertEquals(
157
            $folder1Subfolder1->Name,
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...
158
            (string)$firstResult[0],
159
            $folder1Subfolder1->Name . ' is found, nested under ' . $folder1->Name
160
        );
161
162
        $subfolder = $this->objFromFixture(Folder::class, 'subfolder');
163
        $cssPath = 'ul.tree li#selector-TestTree-' . $subfolder->ID . ' a span.item';
164
        $secondResult = $parser->getBySelector($cssPath);
165
        $this->assertEquals(
166
            $subfolder->Name,
167
            (string)$secondResult[0],
168
            $subfolder->Name . ' is found at root level'
169
        );
170
171
        // other folders which don't contain the keyword 'sub' are not returned in search results
172
        $folder2 = $this->objFromFixture(Folder::class, 'folder2');
173
        $cssPath = 'ul.tree li#selector-TestTree-' . $folder2->ID . ' a span.item';
174
        $noResult = $parser->getBySelector($cssPath);
175
        $this->assertEmpty(
176
            $noResult,
177
            $folder2 . ' is not found'
178
        );
179
180
        $field = new TreeDropdownField('TestTree', 'Test tree', File::class);
181
182
        // case insensitive search against keyword 'sub' for files
183
        $request = new HTTPRequest('GET', 'url', ['search'=>'sub']);
184
        $request->setSession(new Session([]));
185
        $response = $field->tree($request);
186
        $tree = $response->getBody();
187
188
        $parser = new CSSContentParser($tree);
189
190
        // Even if we used File as the source object, folders are still returned because Folder is a File
191
        $cssPath = 'ul.tree li#selector-TestTree-' . $folder1->ID . ' li#selector-TestTree-' . $folder1Subfolder1->ID . ' a span.item';
192
        $firstResult = $parser->getBySelector($cssPath);
193
        $this->assertEquals(
194
            $folder1Subfolder1->Name,
195
            (string)$firstResult[0],
196
            $folder1Subfolder1->Name . ' is found, nested under ' . $folder1->Name
197
        );
198
199
        // Looking for two files with 'sub' in their name, both under the same folder
200
        $file1 = $this->objFromFixture(File::class, 'subfolderfile1');
201
        $file2 = $this->objFromFixture(File::class, 'subfolderfile2');
202
        $cssPath = 'ul.tree li#selector-TestTree-' . $subfolder->ID . ' li#selector-TestTree-' . $file1->ID . ' a';
203
        $firstResult = $parser->getBySelector($cssPath);
204
        $this->assertNotEmpty(
205
            $firstResult,
206
            $file1->Name . ' with ID ' . $file1->ID . ' is in search results'
207
        );
208
        $this->assertEquals(
209
            $file1->Name,
210
            (string)$firstResult[0],
211
            $file1->Name . ' is found nested under ' . $subfolder->Name
212
        );
213
214
        $cssPath = 'ul.tree li#selector-TestTree-' . $subfolder->ID . ' li#selector-TestTree-' . $file2->ID . ' a';
215
        $secondResult = $parser->getBySelector($cssPath);
216
        $this->assertNotEmpty(
217
            $secondResult,
218
            $file2->Name . ' with ID ' . $file2->ID . ' is in search results'
219
        );
220
        $this->assertEquals(
221
            $file2->Name,
222
            (string)$secondResult[0],
223
            $file2->Name . ' is found nested under ' . $subfolder->Name
224
        );
225
226
        // other files which don't include 'sub' are not returned in search results
227
        $file3 = $this->objFromFixture(File::class, 'asdf');
228
        $cssPath = 'ul.tree li#selector-TestTree-' . $file3->ID;
229
        $noResult = $parser->getBySelector($cssPath);
230
        $this->assertEmpty(
231
            $noResult,
232
            $file3->Name . ' is not found'
233
        );
234
    }
235
236
    public function testReadonly()
237
    {
238
        $field = new TreeDropdownField('TestTree', 'Test tree', File::class);
239
        $fileMock = $this->objFromFixture(File::class, 'asdf');
240
        $field->setValue($fileMock->ID);
241
        $readonlyField = $field->performReadonlyTransformation();
242
        $result = (string) $readonlyField->Field();
243
        $this->assertContains(
244
            '<span class="readonly" id="TestTree">&lt;Special &amp; characters&gt;</span>',
245
            $result
246
        );
247
        $this->assertContains(
248
            '<input type="hidden" name="TestTree" value="' . $fileMock->ID . '" />',
249
            $result
250
        );
251
    }
252
253
    /**
254
     * This is to test setting $key to an Object in the protected function objectForKey()
255
     * This is to fix an issue where postgres will not fail gracefully when you do this
256
     */
257
    public function testObjectForKeyObjectValue()
258
    {
259
        $form = Form::create();
260
        $fieldList = FieldList::create();
261
        $field = TreeDropdownField::create('TestTree', 'Test tree', File::class);
262
        $fieldList->add($field);
263
        $form->setFields($fieldList);
264
        $field->setValue(DataObject::create());
265
        // The following previously errored in postgres
266
        $field->getSchemaStateDefaults();
267
        $this->assertTrue(true);
268
    }
269
}
270