Completed
Push — namespace-template ( 7967f2...367a36 )
by Sam
10:48
created

testStringValueSelectedOptionBehaviour()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 11

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 13
rs 9.4285
cc 1
eloc 11
nc 1
nop 0
1
<?php
2
/**
3
 * @package framework
4
 * @subpackage tests
5
 */
6
class DropdownFieldTest extends SapphireTest {
7
8
	public function testGetSource() {
9
		$source = array(1=>'one');
10
		$field = new DropdownField('Field', null, $source);
11
		$this->assertEquals(
12
			$field->getSource(),
13
			array(
14
				1 => 'one'
15
			)
16
		);
17
	}
18
19
	/**
20
	 * Test different data sources
21
	 */
22 View Code Duplication
	public function testSources() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
23
		// Array
24
		$items = array('a' => 'Apple', 'b' => 'Banana', 'c' => 'Cranberry');
25
		$field = new DropdownField('Field', null, $items);
26
		$this->assertEquals($items, $field->getSource());
27
28
		// SS_List
29
		$list = new ArrayList(array(
30
			new ArrayData(array(
31
				'ID' => 'a',
32
				'Title' => 'Apple'
33
			)),
34
			new ArrayData(array(
35
				'ID' => 'b',
36
				'Title' => 'Banana'
37
			)),
38
			new ArrayData(array(
39
				'ID' => 'c',
40
				'Title' => 'Cranberry'
41
			))
42
		));
43
		$field2 = new DropdownField('Field', null, $list);
44
		$this->assertEquals($items, $field2->getSource());
45
46
		$field3 = new DropdownField('Field', null, $list->map());
47
		$this->assertEquals($items, $field3->getSource());
48
	}
49
50 View Code Duplication
	public function testReadonlyField() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
51
		$field = new DropdownField('FeelingOk', 'Are you feeling ok?', array(0 => 'No', 1 => 'Yes'));
52
		$field->setEmptyString('(Select one)');
53
		$field->setValue(1);
54
		$readonlyField = $field->performReadonlyTransformation();
0 ignored issues
show
Unused Code introduced by
$readonlyField is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
55
		preg_match('/Yes/', $field->Field(), $matches);
56
		$this->assertEquals($matches[0], 'Yes');
57
	}
58
59
	public function testHasEmptyDefault() {
60
		$source = array(1 => 'one');
61
62
		// Test getSource with empty
63
		$field = new DropdownField('Field', null, $source);
64
		$field->setHasEmptyDefault(true);
65
66
		$this->assertEquals(
67
			$field->getSource(),
68
			array(
69
				1 => 'one'
70
			)
71
		);
72
73
		// Test that an empty option comes through in the markup however
74
		$options = $this->findOptionElements($field->Field());
75
76
		$this->assertEquals(
77
			2,
78
			count($options),
79
			'Two options exist in the markup, one for the source, one for empty'
80
		);
81
82
		// the default value should be first
83
		$first = array_shift($options);
84
		$attrs = $first->attributes();
85
86
		$this->assertNotEquals(
87
			1,
88
			$attrs['value'],
89
			'First value is the not value (not the source value)'
90
		);
91
92
		// Test Field Without Empty
93
		$FieldWithoutEmpty = new DropdownField('Field', null, $source);
94
		$this->assertEquals(
95
			$FieldWithoutEmpty->getSource(),
96
			array(
97
				1 => 'one'
98
			)
99
		);
100
101
		$this->assertEquals(
102
			1,
103
			count($options),
104
			'As hasEmptyDefault is not provided, then no default option.'
105
		);
106
	}
107
108
	public function testZeroArraySourceNotOverwrittenByEmptyString() {
109
		$source = array(0=>'zero');
110
		$field = new DropdownField('Field', null, $source);
111
		$field->setEmptyString('select...');
112
		$this->assertEquals(
113
			$field->getSource(),
114
			array(
115
				0 => 'zero'
116
			)
117
		);
118
119
		$options = $this->findOptionElements($field->Field());
120
121
		$this->assertEquals(
122
			2,
123
			count($options),
124
			'Two options exist in the markup, one for the source, one for empty'
125
		);
126
	}
127
128 View Code Duplication
	public function testStringZeroValueSelectedOptionBehaviour() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
129
		$field = new DropdownField('Field', null, array(
130
			'-1' => 'some negative',
131
			'0' => 'none',
132
			'1' => 'one',
133
			'2+' => 'two or more'
134
		), '0');
135
136
		$selectedOptions = $this->findSelectedOptionElements($field->Field());
137
		$this->assertEquals((string) $selectedOptions[0], 'none', 'The selected option is "none"');
138
139
		$field = new DropdownField('Field', null, array(
140
			'-1' => 'some negative',
141
			'0' => 'none',
142
			'1' => 'one',
143
			'2+' => 'two or more'
144
		), 0);
145
146
		$selectedOptions = $this->findSelectedOptionElements($field->Field());
147
		$this->assertEquals((string) $selectedOptions[0], 'none', 'The selected option is "none"');
148
	}
149
150 View Code Duplication
	public function testStringOneValueSelectedOptionBehaviour() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
151
		$field = new DropdownField('Field', null, array(
152
			'-1' => 'some negative',
153
			'0' => 'none',
154
			'1' => 'one',
155
			'2+' => 'two or more'
156
		), '1');
157
158
159
		$selectedOptions = $this->findSelectedOptionElements($field->Field());
160
		$this->assertEquals((string) $selectedOptions[0], 'one', 'The selected option is "one"');
161
162
		$field = new DropdownField('Field', null, array(
163
			'-1' => 'some negative',
164
			'0' => 'none',
165
			'1' => 'one',
166
			'2+' => 'two or more'
167
		), 1);
168
169
		$selectedOptions = $this->findSelectedOptionElements($field->Field());
170
		$this->assertEquals((string) $selectedOptions[0], 'one', 'The selected option is "one"');
171
	}
172
173
	public function testNumberOfSelectOptionsAvailable() {
174
		/* Create a field with a blank value */
175
		$field = $this->createDropdownField('(Any)');
176
177
		/* 3 options are available */
178
		$this->assertEquals(count($this->findOptionElements($field->Field())), 3, '3 options are available');
179
		$selectedOptions = $this->findSelectedOptionElements($field->Field());
180
		$this->assertEquals(count($selectedOptions), 1,
181
			'We only have 1 selected option, since a dropdown can only possibly have one!');
182
183
		/* Create a field without a blank value */
184
		$field = $this->createDropdownField();
185
186
		/* 2 options are available */
187
		$this->assertEquals(count($this->findOptionElements($field->Field())), 2, '2 options are available');
188
		$selectedOptions = $this->findSelectedOptionElements($field->Field());
189
		$this->assertEquals(count($selectedOptions), 0, 'There are no selected options');
190
	}
191
192
	public function testIntegerZeroValueSeelctedOptionBehaviour() {
193
		$field = $this->createDropdownField('(Any)', 0);
194
		$selectedOptions = $this->findSelectedOptionElements($field->Field());
195
		$this->assertEquals((string) $selectedOptions[0], 'No', 'The selected option is "No"');
196
	}
197
198
	public function testBlankStringValueSelectedOptionBehaviour() {
199
		$field = $this->createDropdownField('(Any)');
200
		$selectedOptions = $this->findSelectedOptionElements($field->Field());
201
		$this->assertEquals((string) $selectedOptions[0], '(Any)', 'The selected option is "(Any)"');
202
	}
203
204
	public function testNullValueSelectedOptionBehaviour() {
205
		$field = $this->createDropdownField('(Any)', null);
206
		$selectedOptions = $this->findSelectedOptionElements($field->Field());
207
		$this->assertEquals((string) $selectedOptions[0], '(Any)', 'The selected option is "(Any)"');
208
	}
209
210
	public function testStringValueSelectedOptionBehaviour() {
211
		$field = $this->createDropdownField('(Any)', '1');
212
		$selectedOptions = $this->findSelectedOptionElements($field->Field());
213
		$this->assertEquals((string) $selectedOptions[0], 'Yes', 'The selected option is "Yes"');
214
		$field->setSource(array(
215
			'Cats' => 'Cats and Kittens',
216
			'Dogs' => 'Dogs and Puppies'
217
		));
218
		$field->setValue('Cats');
219
		$selectedOptions = $this->findSelectedOptionElements($field->Field());
220
		$this->assertEquals((string) $selectedOptions[0], 'Cats and Kittens',
221
			'The selected option is "Cats and Kittens"');
222
	}
223
224
	public function testNumberOfDisabledOptions() {
225
		/* Create a field with a blank value & set 0 & 1 to disabled */
226
		$field = $this->createDropdownField('(Any)');
227
		$field->setDisabledItems(array(0,1));
228
229
		/* 3 options are available */
230
		$this->assertEquals(count($this->findOptionElements($field->Field())), 3, '3 options are available');
231
232
		/* There are 2 disabled options */
233
		$disabledOptions = $this->findDisabledOptionElements($field->Field());
234
		$this->assertEquals(count($disabledOptions), 2, 'We have 2 disabled options');
235
236
		/* Create a field without a blank value & set 1 to disabled, then set none to disabled (unset) */
237
		$field = $this->createDropdownField();
238
		$field->setDisabledItems(array(1));
239
240
		/* 2 options are available */
241
		$this->assertEquals(count($this->findOptionElements($field->Field())), 2, '2 options are available');
242
243
		/* get disabled items returns an array of one */
244
		$this->assertEquals(
245
			$field->getDisabledItems(),
246
			array( 1 )
247
		);
248
249
		/* unset disabled items */
250
		$field->setDisabledItems(array());
251
252
		/* There are no disabled options anymore */
253
		$disabledOptions = $this->findDisabledOptionElements($field->Field());
254
		$this->assertEquals(count($disabledOptions), 0, 'There are no disabled options');
255
	}
256
257
	/**
258
	 * The Field() method should be able to handle arrays as values in an edge case. If it couldn't handle it then
259
	 * this test would trigger an array to string conversion PHP notice
260
	 *
261
	 * @dataProvider arrayValueProvider
262
	 */
263
	public function testDropdownWithArrayValues($value) {
264
		$field = $this->createDropdownField();
265
		$field->setValue($value);
266
		$this->assertInstanceOf('SilverStripe\Model\FieldType\DBHTMLText', $field->Field());
267
        $this->assertSame($value, $field->Value());
268
	}
269
270
	/**
271
	 * @return array
272
	 */
273
	public function arrayValueProvider() {
274
		return array(
275
			array(array()),
276
			array(array(0)),
277
			array(array(123)),
278
			array(array('string')),
279
			array('Regression-ish test.')
280
		);
281
	}
282
283
	/**
284
	 * Create a test dropdown field, with the option to
285
	 * set what source and blank value it should contain
286
	 * as optional parameters.
287
	 *
288
	 * @param string|null $emptyString The text to display for the empty value
289
	 * @param string|integer $value The default value of the field
290
	 * @return DropdownField object
291
	 */
292
	public function createDropdownField($emptyString = null, $value = '') {
293
		/* Set up source, with 0 and 1 integers as the values */
294
		$source = array(
295
			0 => 'No',
296
			1 => 'Yes'
297
		);
298
299
		$field = new DropdownField('Field', null, $source, $value);
300
301
		if($emptyString !== null) {
302
			$field->setEmptyString($emptyString);
303
		}
304
305
		return $field;
306
	}
307
308
	/**
309
	 * Find all the <OPTION> elements from a
310
	 * string of HTML.
311
	 *
312
	 * @param string $html HTML to scan for elements
313
	 * @return SimpleXMLElement
314
	 */
315
	public function findOptionElements($html) {
316
		$parser = new CSSContentParser($html);
317
		return $parser->getBySelector('option');
318
	}
319
320
	/**
321
	 * Find all the <OPTION> elements from a
322
	 * string of HTML that have the "selected"
323
	 * attribute.
324
	 *
325
	 * @param string $html HTML to parse for elements
326
	 * @return array of SimpleXMLElement objects
327
	 */
328 View Code Duplication
	public function findSelectedOptionElements($html) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
329
		$options = $this->findOptionElements($html);
330
331
		/* Find any elements that have the "selected" attribute and put them into a list */
332
		$foundSelected = array();
333
		foreach($options as $option) {
334
			$attributes = $option->attributes();
335
			if($attributes) foreach($attributes as $attribute => $value) {
336
				if($attribute == 'selected') {
337
					$foundSelected[] = $option;
338
				}
339
			}
340
		}
341
342
		return $foundSelected;
343
	}
344
345
	/**
346
	 * Find all the <OPTION> elements from a
347
	 * string of HTML that have the "disabled"
348
	 * attribute.
349
	 *
350
	 * @param string $html HTML to parse for elements
351
	 * @return array of SimpleXMLElement objects
352
	 */
353 View Code Duplication
	public function findDisabledOptionElements($html) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
354
		$options = $this->findOptionElements($html);
355
356
		/* Find any elements that have the "disabled" attribute and put them into a list */
357
		$foundDisabled = array();
358
		foreach($options as $option) {
359
			$attributes = $option->attributes();
360
			if($attributes) foreach($attributes as $attribute => $value) {
361
				if($attribute == 'disabled') {
362
					$foundDisabled[] = $option;
363
				}
364
			}
365
		}
366
367
		return $foundDisabled;
368
	}
369
370
	public function testValidation() {
371
		$field = DropdownField::create('Test', 'Testing', array(
372
			"One" => "One",
373
			"Two" => "Two",
374
			"Five" => "Five"
375
		));
376
		$validator = new RequiredFields();
377
		$form = new Form($this, 'Form', new FieldList($field), new FieldList(), $validator);
0 ignored issues
show
Documentation introduced by
$this is of type this<DropdownFieldTest>, but the function expects a object<Controller>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Unused Code introduced by
$form is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
378
		$field->setValue("One");
379
		$this->assertTrue($field->validate($validator));
380
		$field->setName("TestNew"); //try changing name of field
381
		$this->assertTrue($field->validate($validator));
382
		//non-existent value should make the field invalid
383
		$field->setValue("Three");
384
		$this->assertFalse($field->validate($validator));
385
		//empty string shouldn't validate
386
		$field->setValue('');
387
		$this->assertFalse($field->validate($validator));
388
		//empty field should validate after being set
389
		$field->setEmptyString('Empty String');
390
		$field->setValue('');
391
		$this->assertTrue($field->validate($validator));
392
		//disabled items shouldn't validate
393
		$field->setDisabledItems(array('Five'));
394
		$field->setValue('Five');
395
		$this->assertFalse($field->validate($validator));
396
	}
397
398
}
399