Completed
Push — 4.6 ( 169c06...67a008 )
by Maxime
33s queued 20s
created

TreeDropdownFieldTest::testTreeBaseID()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 26
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

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