Passed
Push — fix-9162 ( d08835 )
by Sam
07:26
created

ListboxFieldTest   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 271
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 170
dl 0
loc 271
rs 10
c 0
b 0
f 0
wmc 12

12 Methods

Rating   Name   Duplication   Size   Complexity  
A testSaveIntoManyManyRelation() 0 25 1
A testSaveIntoNullValueWithMultipleOn() 0 11 1
A testSaveInto() 0 9 1
A testSaveIntoMultiple() 0 18 1
A testSaveIntoNullValueWithMultipleOff() 0 11 1
A testFieldRenderingMultipleOn() 0 11 1
A testValidationWithDataList() 0 44 1
A testValidationWithArray() 0 29 1
A testFieldWithDisabledItems() 0 20 1
A testFieldWithManyManyRelationship() 0 16 1
A testFieldRenderingMultipleOff() 0 11 1
A testFieldWithDefaultItems() 0 31 1
1
<?php
2
3
namespace SilverStripe\Forms\Tests;
4
5
use SilverStripe\Forms\Tests\ListboxFieldTest\Article;
6
use SilverStripe\Forms\Tests\ListboxFieldTest\Tag;
7
use SilverStripe\Forms\Tests\ListboxFieldTest\TestObject;
8
use SilverStripe\ORM\DataObject;
9
use SilverStripe\Dev\CSSContentParser;
10
use SilverStripe\Dev\SapphireTest;
11
use SilverStripe\Forms\ListboxField;
12
use SilverStripe\Forms\RequiredFields;
13
use SilverStripe\View\ArrayData;
14
15
class ListboxFieldTest extends SapphireTest
16
{
17
18
    protected static $fixture_file = 'ListboxFieldTest.yml';
19
20
    protected static $extra_dataobjects = array(
21
        TestObject::class,
22
        Article::class,
23
        Tag::class,
24
    );
25
26
    public function testFieldWithManyManyRelationship()
27
    {
28
        $articleWithTags = $this->objFromFixture(Article::class, 'articlewithtags');
29
        $tag1 = $this->objFromFixture(Tag::class, 'tag1');
30
        $tag2 = $this->objFromFixture(Tag::class, 'tag2');
31
        $tag3 = $this->objFromFixture(Tag::class, 'tag3');
32
        $field = new ListboxField("Tags", "Test field", DataObject::get(Tag::class)->map()->toArray());
33
        $field->setValue(null, $articleWithTags);
34
35
        $p = new CSSContentParser($field->Field());
36
        $tag1xml = $p->getByXpath('//option[@value=' . $tag1->ID . ']');
37
        $tag2xml = $p->getByXpath('//option[@value=' . $tag2->ID . ']');
38
        $tag3xml = $p->getByXpath('//option[@value=' . $tag3->ID . ']');
39
        $this->assertEquals('selected', (string)$tag1xml[0]['selected']);
40
        $this->assertEquals('selected', (string)$tag2xml[0]['selected']);
41
        $this->assertNull($tag3xml[0]['selected']);
42
    }
43
44
    public function testFieldWithDisabledItems()
45
    {
46
        $articleWithTags = $this->objFromFixture(Article::class, 'articlewithtags');
47
        $tag1 = $this->objFromFixture(Tag::class, 'tag1');
48
        $tag2 = $this->objFromFixture(Tag::class, 'tag2');
49
        $tag3 = $this->objFromFixture(Tag::class, 'tag3');
50
        $field = new ListboxField("Tags", "Test field", DataObject::get(Tag::class)->map()->toArray());
51
        $field->setValue(null, $articleWithTags);
52
        $field->setDisabledItems(array($tag1->ID, $tag3->ID));
53
54
        $p = new CSSContentParser($field->Field());
55
        $tag1xml = $p->getByXpath('//option[@value=' . $tag1->ID . ']');
56
        $tag2xml = $p->getByXpath('//option[@value=' . $tag2->ID . ']');
57
        $tag3xml = $p->getByXpath('//option[@value=' . $tag3->ID . ']');
58
        $this->assertEquals('selected', (string)$tag1xml[0]['selected']);
59
        $this->assertEquals('disabled', (string)$tag1xml[0]['disabled']);
60
        $this->assertEquals('selected', (string)$tag2xml[0]['selected']);
61
        $this->assertNull($tag2xml[0]['disabled']);
62
        $this->assertNull($tag3xml[0]['selected']);
63
        $this->assertEquals('disabled', (string)$tag3xml[0]['disabled']);
64
    }
65
66
    public function testSaveIntoNullValueWithMultipleOff()
67
    {
68
        $choices = array('a' => 'a value', 'b' => 'b value','c' => 'c value');
69
        $field = new ListboxField('Choices', 'Choices', $choices);
70
71
        $obj = new TestObject();
72
        $field->setValue('a');
73
        $field->saveInto($obj);
74
        $field->setValue(null);
75
        $field->saveInto($obj);
76
        $this->assertNull($obj->Choices);
0 ignored issues
show
Bug Best Practice introduced by
The property Choices does not exist on SilverStripe\Forms\Tests...boxFieldTest\TestObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
77
    }
78
79
    public function testSaveIntoNullValueWithMultipleOn()
80
    {
81
        $choices = array('a' => 'a value', 'b' => 'b value','c' => 'c value');
82
        $field = new ListboxField('Choices', 'Choices', $choices);
83
84
        $obj = new TestObject();
85
        $field->setValue(array('a', 'c'));
86
        $field->saveInto($obj);
87
        $field->setValue('');
88
        $field->saveInto($obj);
89
        $this->assertEquals('', $obj->Choices);
0 ignored issues
show
Bug Best Practice introduced by
The property Choices does not exist on SilverStripe\Forms\Tests...boxFieldTest\TestObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
90
    }
91
92
    public function testSaveInto()
93
    {
94
        $choices = array('a' => 'a value', 'b' => 'b value','c' => 'c value');
95
        $field = new ListboxField('Choices', 'Choices', $choices);
96
97
        $obj = new TestObject();
98
        $field->setValue('a');
99
        $field->saveInto($obj);
100
        $this->assertEquals('["a"]', $obj->Choices);
0 ignored issues
show
Bug Best Practice introduced by
The property Choices does not exist on SilverStripe\Forms\Tests...boxFieldTest\TestObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
101
    }
102
103
    public function testSaveIntoMultiple()
104
    {
105
        $choices = array('a' => 'a value', 'b' => 'b value','c' => 'c value');
106
        $field = new ListboxField('Choices', 'Choices', $choices);
107
108
        // As array
109
        $obj1 = new TestObject();
110
        $field->setValue(array('a', 'c'));
111
        $field->saveInto($obj1);
112
        $this->assertEquals('["a","c"]', $obj1->Choices);
0 ignored issues
show
Bug Best Practice introduced by
The property Choices does not exist on SilverStripe\Forms\Tests...boxFieldTest\TestObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
113
114
        // As string
115
        $obj2 = new TestObject();
116
        $obj2->Choices = '["a","c"]';
0 ignored issues
show
Bug Best Practice introduced by
The property Choices does not exist on SilverStripe\Forms\Tests...boxFieldTest\TestObject. Since you implemented __set, consider adding a @property annotation.
Loading history...
117
        $field->setValue(null, $obj2);
118
        $this->assertEquals(array('a', 'c'), $field->Value());
119
        $field->saveInto($obj2);
120
        $this->assertEquals('["a","c"]', $obj2->Choices);
121
    }
122
123
    public function testSaveIntoManyManyRelation()
124
    {
125
        $article = $this->objFromFixture(Article::class, 'articlewithouttags');
126
        $articleWithTags = $this->objFromFixture(Article::class, 'articlewithtags');
0 ignored issues
show
Unused Code introduced by
The assignment to $articleWithTags is dead and can be removed.
Loading history...
127
        $tag1 = $this->objFromFixture(Tag::class, 'tag1');
128
        $tag2 = $this->objFromFixture(Tag::class, 'tag2');
129
        $field = new ListboxField("Tags", "Test field", DataObject::get(Tag::class)->map()->toArray());
130
131
        // Save new relations
132
        $field->setValue(array($tag1->ID,$tag2->ID));
133
        $field->saveInto($article);
134
        $article = DataObject::get_by_id(Article::class, $article->ID, false);
135
        $this->assertEquals(array($tag1->ID, $tag2->ID), $article->Tags()->sort('ID')->column('ID'));
0 ignored issues
show
Bug introduced by
The method Tags() 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

135
        $this->assertEquals(array($tag1->ID, $tag2->ID), $article->/** @scrutinizer ignore-call */ Tags()->sort('ID')->column('ID'));
Loading history...
136
137
        // Remove existing relation
138
        $field->setValue(array($tag1->ID));
139
        $field->saveInto($article);
140
        $article = DataObject::get_by_id(Article::class, $article->ID, false);
141
        $this->assertEquals(array($tag1->ID), $article->Tags()->sort('ID')->column('ID'));
142
143
        // Set NULL value
144
        $field->setValue(null);
145
        $field->saveInto($article);
146
        $article = DataObject::get_by_id(Article::class, $article->ID, false);
147
        $this->assertEquals(array(), $article->Tags()->sort('ID')->column('ID'));
148
    }
149
150
    public function testFieldRenderingMultipleOff()
151
    {
152
        $choices = array('a' => 'a value', 'b' => 'b value','c' => 'c value');
153
        $field = new ListboxField('Choices', 'Choices', $choices);
154
        $field->setValue('a');
155
        $parser = new CSSContentParser($field->Field());
156
        $optEls = $parser->getBySelector('option');
157
        $this->assertEquals(3, count($optEls));
158
        $this->assertEquals('selected', (string)$optEls[0]['selected']);
159
        $this->assertEquals('', (string)$optEls[1]['selected']);
160
        $this->assertEquals('', (string)$optEls[2]['selected']);
161
    }
162
163
    public function testFieldRenderingMultipleOn()
164
    {
165
        $choices = array('a' => 'a value', 'b' => 'b value','c' => 'c value');
166
        $field = new ListboxField('Choices', 'Choices', $choices);
167
        $field->setValue(array('a', 'c'));
168
        $parser = new CSSContentParser($field->Field());
169
        $optEls = $parser->getBySelector('option');
170
        $this->assertEquals(3, count($optEls));
171
        $this->assertEquals('selected', (string)$optEls[0]['selected']);
172
        $this->assertEquals('', (string)$optEls[1]['selected']);
173
        $this->assertEquals('selected', (string)$optEls[2]['selected']);
174
    }
175
176
    public function testValidationWithArray()
177
    {
178
        //test with array input
179
        $field = ListboxField::create(
180
            'Test',
181
            'Testing',
182
            array(
183
            1 => "One",
184
            2 => "Two",
185
            3 => "Three"
186
            )
187
        );
188
        $validator = new RequiredFields();
189
190
        $field->setValue(1);
191
        $this->assertTrue(
192
            $field->validate($validator),
193
            'Validates values in source map'
194
        );
195
        $field->setValue(array(1));
196
        $this->assertTrue(
197
            $field->validate($validator),
198
            'Validates values within source array'
199
        );
200
        //non valid value should fail
201
        $field->setValue(4);
202
        $this->assertFalse(
203
            $field->validate($validator),
204
            'Does not validates values not within source array'
205
        );
206
    }
207
208
    public function testValidationWithDataList()
209
    {
210
        //test with datalist input
211
        $tag1 = $this->objFromFixture(Tag::class, 'tag1');
212
        $tag2 = $this->objFromFixture(Tag::class, 'tag2');
213
        $tag3 = $this->objFromFixture(Tag::class, 'tag3');
0 ignored issues
show
Unused Code introduced by
The assignment to $tag3 is dead and can be removed.
Loading history...
214
        $field = ListboxField::create('Test', 'Testing', DataObject::get(Tag::class)->map()->toArray());
215
        $validator = new RequiredFields();
216
217
        $field->setValue(
218
            $tag1->ID
219
        );
220
        $this->assertTrue(
221
            $field->validate($validator),
222
            'Field validates values in source map'
223
        );
224
225
        /**
226
         * @todo re-enable these tests when field validation is removed from {@link ListboxField::setValue()} and moved
227
         * to the {@link ListboxField::validate()} function
228
         */
229
        //      $field->setValue(4);
230
        //      $this->assertFalse(
231
        //          $field->validate($validator),
232
        //          'Field does not validate values outside of source map'
233
        //      );
234
        $field->setValue(
235
            false,
236
            new ArrayData(
237
                array(
238
                $tag1->ID => $tag1->ID,
239
                $tag2->ID => $tag2->ID
240
                )
241
            )
242
        );
243
        $this->assertTrue(
244
            $field->validate($validator),
245
            'Validates values in source map'
246
        );
247
        //invalid value should fail
248
        $field->setValue(4);
249
        $this->assertFalse(
250
            $field->validate($validator),
251
            'Does not validate values not within source map'
252
        );
253
    }
254
255
    public function testFieldWithDefaultItems()
256
    {
257
        $articleWithTags = $this->objFromFixture(Article::class, 'articlewithtags');
258
        $tag1 = $this->objFromFixture(Tag::class, 'tag1');
259
        $tag2 = $this->objFromFixture(Tag::class, 'tag2');
260
        $tag3 = $this->objFromFixture(Tag::class, 'tag3');
261
        $field = new ListboxField("Tags", "Test field", DataObject::get(Tag::class)->map()->toArray());
262
        $field->setDefaultItems([$tag1->ID, $tag2->ID]);
263
264
265
        $field->setValue(null, $articleWithTags);
266
        $field->setDisabledItems(array($tag1->ID, $tag3->ID));
267
268
        // Confirm that tag1 and tag2 are selected
269
        $p = new CSSContentParser($field->Field());
270
        $tag1xml = $p->getByXpath('//option[@value=' . $tag1->ID . ']');
271
        $tag2xml = $p->getByXpath('//option[@value=' . $tag2->ID . ']');
272
        $tag3xml = $p->getByXpath('//option[@value=' . $tag3->ID . ']');
273
        $this->assertEquals('selected', (string)$tag1xml[0]['selected']);
274
        $this->assertEquals('selected', (string)$tag2xml[0]['selected']);
275
        $this->assertNull($tag3xml[0]['selected']);
276
277
        // Confirm that tag1 and tag2 are listed in the readonly variation
278
        $p = new CSSContentParser($field->performReadonlyTransformation()->Field());
279
        $this->assertEquals(
280
            'Tag 1, Tag 2',
281
            trim(preg_replace('/\s+/', ' ', $p->getByXpath('//span')[0]))
282
        );
283
        $this->assertEquals(
284
            '1, 2',
285
            '' . $p->getByXpath('//input')[0]['value']
286
        );
287
    }
288
}
289