Passed
Push — master ( 72e173...aab521 )
by Robbie
23:38 queued 15:49
created

ListboxFieldTest::testFieldWithDefaultItems()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 31
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 22
nc 1
nop 0
dl 0
loc 31
rs 9.568
c 0
b 0
f 0
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);
0 ignored issues
show
Unused Code Comprehensibility introduced by
75% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
230
        //      $this->assertFalse(
231
        //          $field->validate($validator),
0 ignored issues
show
Unused Code Comprehensibility introduced by
75% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
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