Completed
Pull Request — 3.4 (#6168)
by Damian
10:25
created

DropdownFieldTest::testGetSource()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 35
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 25
nc 1
nop 0
dl 0
loc 35
rs 8.8571
c 0
b 0
f 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', 2 => 'two');
10
		$field = new DropdownField('Field', null, $source);
11
		$this->assertEquals(
12
			$source,
13
			$field->getSource()
14
		);
15
		$this->assertEquals(
16
			$source,
17
			$field->getSourceAsArray()
18
		);
19
20
		$items = new ArrayList(array(
21
			array( 'ID' => 1, 'Title' => 'ichi', 'OtherField' => 'notone' ),
22
			array( 'ID' => 2, 'Title' => 'ni', 'OtherField' => 'nottwo' ),
23
		));
24
		$field->setSource($items);
25
		$this->assertEquals(
26
			$field->getSourceAsArray(),
27
			array(
28
				1 => 'ichi',
29
				2 => 'ni',
30
			)
31
		);
32
33
		$map = new SS_Map($items, 'ID', 'OtherField');
34
		$field->setSource($map);
35
		$this->assertEquals(
36
			$field->getSourceAsArray(),
37
			array(
38
				1 => 'notone',
39
				2 => 'nottwo',
40
			)
41
		);
42
	}
43
44
	public function testReadonlyField() {
45
		$field = new DropdownField('FeelingOk', 'Are you feeling ok?', array(0 => 'No', 1 => 'Yes'));
46
		$field->setEmptyString('(Select one)');
47
		$field->setValue(1);
48
		$readonlyField = $field->performReadonlyTransformation();
49
		preg_match('/Yes/', $field->Field(), $matches);
50
		$this->assertEquals($matches[0], 'Yes');
51
	}
52
53
	public function testHasEmptyDefault() {
54
		$source = array(1 => 'one');
55
56
		// Test getSource with empty
57
		$field = new DropdownField('Field', null, $source);
58
		$field->setHasEmptyDefault(true);
59
60
		$this->assertEquals(
61
			$field->getSource(),
62
			array(
63
				1 => 'one'
64
			)
65
		);
66
67
		// Test that an empty option comes through in the markup however
68
		$options = $this->findOptionElements($field->Field());
69
70
		$this->assertEquals(
71
			2,
72
			count($options),
73
			'Two options exist in the markup, one for the source, one for empty'
74
		);
75
76
		// the default value should be first
77
		$first = array_shift($options);
78
		$attrs = $first->attributes();
79
80
		$this->assertNotEquals(
81
			1,
82
			$attrs['value'],
83
			'First value is the not value (not the source value)'
84
		);
85
86
		// Test Field Without Empty
87
		$FieldWithoutEmpty = new DropdownField('Field', null, $source);
88
		$this->assertEquals(
89
			$FieldWithoutEmpty->getSource(),
90
			array(
91
				1 => 'one'
92
			)
93
		);
94
95
		$this->assertEquals(
96
			1,
97
			count($options),
98
			'As hasEmptyDefault is not provided, then no default option.'
99
		);
100
	}
101
102
	public function testZeroArraySourceNotOverwrittenByEmptyString() {
103
		$source = array(0=>'zero');
104
		$field = new DropdownField('Field', null, $source);
105
		$field->setEmptyString('select...');
106
		$this->assertEquals(
107
			$field->getSource(),
108
			array(
109
				0 => 'zero'
110
			)
111
		);
112
113
		$options = $this->findOptionElements($field->Field());
114
115
		$this->assertEquals(
116
			2,
117
			count($options),
118
			'Two options exist in the markup, one for the source, one for empty'
119
		);
120
	}
121
122
	public function testStringZeroValueSelectedOptionBehaviour() {
123
		$field = new DropdownField('Field', null, array(
124
			'-1' => 'some negative',
125
			'0' => 'none',
126
			'1' => 'one',
127
			'2+' => 'two or more'
128
		), '0');
129
130
		$selectedOptions = $this->findSelectedOptionElements($field->Field());
131
		$this->assertEquals((string) $selectedOptions[0], 'none', 'The selected option is "none"');
132
133
		$field = new DropdownField('Field', null, array(
134
			'-1' => 'some negative',
135
			'0' => 'none',
136
			'1' => 'one',
137
			'2+' => 'two or more'
138
		), 0);
139
140
		$selectedOptions = $this->findSelectedOptionElements($field->Field());
141
		$this->assertEquals((string) $selectedOptions[0], 'none', 'The selected option is "none"');
142
	}
143
144
	public function testStringOneValueSelectedOptionBehaviour() {
145
		$field = new DropdownField('Field', null, array(
146
			'-1' => 'some negative',
147
			'0' => 'none',
148
			'1' => 'one',
149
			'2+' => 'two or more'
150
		), '1');
151
152
153
		$selectedOptions = $this->findSelectedOptionElements($field->Field());
154
		$this->assertEquals((string) $selectedOptions[0], 'one', 'The selected option is "one"');
155
156
		$field = new DropdownField('Field', null, array(
157
			'-1' => 'some negative',
158
			'0' => 'none',
159
			'1' => 'one',
160
			'2+' => 'two or more'
161
		), 1);
162
163
		$selectedOptions = $this->findSelectedOptionElements($field->Field());
164
		$this->assertEquals((string) $selectedOptions[0], 'one', 'The selected option is "one"');
165
	}
166
167
	public function testNumberOfSelectOptionsAvailable() {
168
		/* Create a field with a blank value */
169
		$field = $this->createDropdownField('(Any)');
170
171
		/* 3 options are available */
172
		$this->assertEquals(count($this->findOptionElements($field->Field())), 3, '3 options are available');
173
		$selectedOptions = $this->findSelectedOptionElements($field->Field());
174
		$this->assertEquals(count($selectedOptions), 1,
175
			'We only have 1 selected option, since a dropdown can only possibly have one!');
176
177
		/* Create a field without a blank value */
178
		$field = $this->createDropdownField();
179
180
		/* 2 options are available */
181
		$this->assertEquals(count($this->findOptionElements($field->Field())), 2, '2 options are available');
182
		$selectedOptions = $this->findSelectedOptionElements($field->Field());
183
		$this->assertEquals(count($selectedOptions), 0, 'There are no selected options');
184
	}
185
186
	public function testIntegerZeroValueSeelctedOptionBehaviour() {
187
		$field = $this->createDropdownField('(Any)', 0);
188
		$selectedOptions = $this->findSelectedOptionElements($field->Field());
189
		$this->assertEquals((string) $selectedOptions[0], 'No', 'The selected option is "No"');
190
	}
191
192
	public function testBlankStringValueSelectedOptionBehaviour() {
193
		$field = $this->createDropdownField('(Any)');
194
		$selectedOptions = $this->findSelectedOptionElements($field->Field());
195
		$this->assertEquals((string) $selectedOptions[0], '(Any)', 'The selected option is "(Any)"');
196
	}
197
198
	public function testNullValueSelectedOptionBehaviour() {
199
		$field = $this->createDropdownField('(Any)', null);
200
		$selectedOptions = $this->findSelectedOptionElements($field->Field());
201
		$this->assertEquals((string) $selectedOptions[0], '(Any)', 'The selected option is "(Any)"');
202
	}
203
204
	public function testStringValueSelectedOptionBehaviour() {
205
		$field = $this->createDropdownField('(Any)', '1');
206
		$selectedOptions = $this->findSelectedOptionElements($field->Field());
207
		$this->assertEquals((string) $selectedOptions[0], 'Yes', 'The selected option is "Yes"');
208
		$field->setSource(array(
209
			'Cats' => 'Cats and Kittens',
210
			'Dogs' => 'Dogs and Puppies'
211
		));
212
		$field->setValue('Cats');
213
		$selectedOptions = $this->findSelectedOptionElements($field->Field());
214
		$this->assertEquals((string) $selectedOptions[0], 'Cats and Kittens',
215
			'The selected option is "Cats and Kittens"');
216
	}
217
218
	public function testNumberOfDisabledOptions() {
219
		/* Create a field with a blank value & set 0 & 1 to disabled */
220
		$field = $this->createDropdownField('(Any)');
221
		$field->setDisabledItems(array(0,1));
222
223
		/* 3 options are available */
224
		$this->assertEquals(count($this->findOptionElements($field->Field())), 3, '3 options are available');
225
226
		/* There are 2 disabled options */
227
		$disabledOptions = $this->findDisabledOptionElements($field->Field());
228
		$this->assertEquals(count($disabledOptions), 2, 'We have 2 disabled options');
229
230
		/* Create a field without a blank value & set 1 to disabled, then set none to disabled (unset) */
231
		$field = $this->createDropdownField();
232
		$field->setDisabledItems(array(1));
233
234
		/* 2 options are available */
235
		$this->assertEquals(count($this->findOptionElements($field->Field())), 2, '2 options are available');
236
237
		/* get disabled items returns an array of one */
238
		$this->assertEquals(
239
			$field->getDisabledItems(),
240
			array( 1 )
241
		);
242
243
		/* unset disabled items */
244
		$field->setDisabledItems(array());
245
246
		/* There are no disabled options anymore */
247
		$disabledOptions = $this->findDisabledOptionElements($field->Field());
248
		$this->assertEquals(count($disabledOptions), 0, 'There are no disabled options');
249
	}
250
251
	/**
252
	 * The Field() method should be able to handle arrays as values in an edge case. If it couldn't handle it then
253
	 * this test would trigger an array to string conversion PHP notice
254
	 *
255
	 * @dataProvider arrayValueProvider
256
	 */
257
	public function testDropdownWithArrayValues($value) {
258
		$field = $this->createDropdownField();
259
		$field->setValue($value);
260
		$this->assertInstanceOf('HTMLText', $field->Field());
261
        $this->assertSame($value, $field->Value());
262
	}
263
264
	/**
265
	 * @return array
266
	 */
267
	public function arrayValueProvider() {
268
		return array(
269
			array(array()),
270
			array(array(0)),
271
			array(array(123)),
272
			array(array('string')),
273
			array('Regression-ish test.')
274
		);
275
	}
276
277
	/**
278
	 * Create a test dropdown field, with the option to
279
	 * set what source and blank value it should contain
280
	 * as optional parameters.
281
	 *
282
	 * @param string|null $emptyString The text to display for the empty value
283
	 * @param string|integer $value The default value of the field
284
	 * @return DropdownField object
285
	 */
286
	public function createDropdownField($emptyString = null, $value = '') {
287
		/* Set up source, with 0 and 1 integers as the values */
288
		$source = array(
289
			0 => 'No',
290
			1 => 'Yes'
291
		);
292
293
		$field = new DropdownField('Field', null, $source, $value);
294
295
		if($emptyString !== null) {
296
			$field->setEmptyString($emptyString);
297
		}
298
299
		return $field;
300
	}
301
302
	/**
303
	 * Find all the <OPTION> elements from a
304
	 * string of HTML.
305
	 *
306
	 * @param string $html HTML to scan for elements
307
	 * @return SimpleXMLElement
308
	 */
309
	public function findOptionElements($html) {
310
		$parser = new CSSContentParser($html);
311
		return $parser->getBySelector('option');
312
	}
313
314
	/**
315
	 * Find all the <OPTION> elements from a
316
	 * string of HTML that have the "selected"
317
	 * attribute.
318
	 *
319
	 * @param string $html HTML to parse for elements
320
	 * @return array of SimpleXMLElement objects
321
	 */
322
	public function findSelectedOptionElements($html) {
323
		$options = $this->findOptionElements($html);
324
325
		/* Find any elements that have the "selected" attribute and put them into a list */
326
		$foundSelected = array();
327
		foreach($options as $option) {
328
			$attributes = $option->attributes();
329
			if($attributes) foreach($attributes as $attribute => $value) {
330
				if($attribute == 'selected') {
331
					$foundSelected[] = $option;
332
				}
333
			}
334
		}
335
336
		return $foundSelected;
337
	}
338
339
	/**
340
	 * Find all the <OPTION> elements from a
341
	 * string of HTML that have the "disabled"
342
	 * attribute.
343
	 *
344
	 * @param string $html HTML to parse for elements
345
	 * @return array of SimpleXMLElement objects
346
	 */
347
	public function findDisabledOptionElements($html) {
348
		$options = $this->findOptionElements($html);
349
350
		/* Find any elements that have the "disabled" attribute and put them into a list */
351
		$foundDisabled = array();
352
		foreach($options as $option) {
353
			$attributes = $option->attributes();
354
			if($attributes) foreach($attributes as $attribute => $value) {
355
				if($attribute == 'disabled') {
356
					$foundDisabled[] = $option;
357
				}
358
			}
359
		}
360
361
		return $foundDisabled;
362
	}
363
364
	public function testValidation() {
365
		$field = DropdownField::create('Test', 'Testing', array(
366
			"One" => "One",
367
			"Two" => "Two",
368
			"Five" => "Five"
369
		));
370
		$validator = new RequiredFields();
371
		$form = new Form($this, 'Form', new FieldList($field), new FieldList(), $validator);
372
		$field->setValue("One");
373
		$this->assertTrue($field->validate($validator));
374
		$field->setName("TestNew"); //try changing name of field
375
		$this->assertTrue($field->validate($validator));
376
		//non-existent value should make the field invalid
377
		$field->setValue("Three");
378
		$this->assertFalse($field->validate($validator));
379
		//empty string shouldn't validate
380
		$field->setValue('');
381
		$this->assertFalse($field->validate($validator));
382
		//empty field should validate after being set
383
		$field->setEmptyString('Empty String');
384
		$field->setValue('');
385
		$this->assertTrue($field->validate($validator));
386
		//disabled items shouldn't validate
387
		$field->setDisabledItems(array('Five'));
388
		$field->setValue('Five');
389
		$this->assertFalse($field->validate($validator));
390
	}
391
392
}
393