Completed
Push — master ( 01ba7c...6d88ca )
by Damian
21:36 queued 11:17
created

FormFieldTest   A

Complexity

Total Complexity 31

Size/Duplication

Total Lines 307
Duplicated Lines 0 %

Coupling/Cohesion

Components 3
Dependencies 9

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 31
c 2
b 0
f 0
lcom 3
cbo 9
dl 0
loc 307
rs 9.8

19 Methods

Rating   Name   Duplication   Size   Complexity  
A testRemoveManyExtraClasses() 0 22 1
A testUpdateAttributes() 0 4 1
B testDefaultClasses() 0 44 1
A testAddExtraClass() 0 6 1
A testRemoveExtraClass() 0 8 1
A testAddManyExtraClasses() 0 15 1
A testAttributes() 0 8 1
B testAttributesHTML() 0 34 1
A testReadonly() 0 7 1
A testDisabled() 0 7 1
C testEveryFieldTransformsReadonlyAsClone() 0 32 7
C testEveryFieldTransformsDisabledAsClone() 0 33 7
A testSetSchemaComponent() 0 6 1
A testGetSchemaDataDefaults() 0 5 1
A testGetSchemaData() 0 10 1
A testSetSchemaData() 0 13 1
A testGetSchemaState() 0 6 1
A testSetSchemaState() 0 13 1
A testGetSchemaStateWithFormValidation() 0 9 1
1
<?php
2
/**
3
 * @package framework
4
 * @subpackage tests
5
 */
6
class FormFieldTest extends SapphireTest {
7
8
	protected $requiredExtensions = array(
9
		'FormField' => array('FormFieldTest_Extension')
10
	);
11
12
	public function testDefaultClasses() {
13
		Config::nest();
14
15
		Config::inst()->update('FormField', 'default_classes', array(
16
			'class1',
17
		));
18
19
		$field = new FormField('MyField');
20
21
		$this->assertContains('class1', $field->extraClass(), 'Class list does not contain expected class');
22
23
		Config::inst()->update('FormField', 'default_classes', array(
24
			'class1',
25
			'class2',
26
		));
27
28
		$field = new FormField('MyField');
29
30
		$this->assertContains('class1 class2', $field->extraClass(), 'Class list does not contain expected class');
31
32
		Config::inst()->update('FormField', 'default_classes', array(
33
			'class3',
34
		));
35
36
		$field = new FormField('MyField');
37
38
		$this->assertContains('class3', $field->extraClass(), 'Class list does not contain expected class');
39
40
		$field->removeExtraClass('class3');
41
42
		$this->assertNotContains('class3', $field->extraClass(), 'Class list contains unexpected class');
43
44
		Config::inst()->update('TextField', 'default_classes', array(
45
			'textfield-class',
46
		));
47
48
		$field = new TextField('MyField');
49
50
		//check default classes inherit
51
		$this->assertContains('class3', $field->extraClass(), 'Class list does not contain inherited class');
52
		$this->assertContains('textfield-class', $field->extraClass(), 'Class list does not contain expected class');
53
54
		Config::unnest();
55
	}
56
57
	public function testAddExtraClass() {
58
		$field = new FormField('MyField');
59
		$field->addExtraClass('class1');
60
		$field->addExtraClass('class2');
61
		$this->assertStringEndsWith('class1 class2', $field->extraClass());
62
	}
63
64
	public function testRemoveExtraClass() {
65
		$field = new FormField('MyField');
66
		$field->addExtraClass('class1');
67
		$field->addExtraClass('class2');
68
		$this->assertStringEndsWith('class1 class2', $field->extraClass());
69
		$field->removeExtraClass('class1');
70
		$this->assertStringEndsWith('class2', $field->extraClass());
71
	}
72
73
	public function testAddManyExtraClasses() {
74
		$field = new FormField('MyField');
75
		//test we can split by a range of spaces and tabs
76
		$field->addExtraClass('class1 class2     class3	class4		class5');
77
		$this->assertStringEndsWith(
78
			'class1 class2 class3 class4 class5',
79
			$field->extraClass()
80
		);
81
		//test that duplicate classes don't get added
82
		$field->addExtraClass('class1 class2');
83
		$this->assertStringEndsWith(
84
			'class1 class2 class3 class4 class5',
85
			$field->extraClass()
86
		);
87
	}
88
89
	public function testRemoveManyExtraClasses() {
90
		$field = new FormField('MyField');
91
		$field->addExtraClass('class1 class2     class3	class4		class5');
92
		//test we can remove a single class we just added
93
		$field->removeExtraClass('class3');
94
		$this->assertStringEndsWith(
95
			'class1 class2 class4 class5',
96
			$field->extraClass()
97
		);
98
		//check we can remove many classes at once
99
		$field->removeExtraClass('class1 class5');
100
		$this->assertStringEndsWith(
101
			'class2 class4',
102
			$field->extraClass()
103
		);
104
		//check that removing a dud class is fine
105
		$field->removeExtraClass('dudClass');
106
		$this->assertStringEndsWith(
107
			'class2 class4',
108
			$field->extraClass()
109
		);
110
	}
111
112
	public function testAttributes() {
113
		$field = new FormField('MyField');
114
		$field->setAttribute('foo', 'bar');
115
		$this->assertEquals('bar', $field->getAttribute('foo'));
116
		$attrs = $field->getAttributes();
117
		$this->assertArrayHasKey('foo', $attrs);
118
		$this->assertEquals('bar', $attrs['foo']);
119
	}
120
121
	public function testAttributesHTML() {
122
		$field = new FormField('MyField');
123
124
		$field->setAttribute('foo', 'bar');
125
		$this->assertContains('foo="bar"', $field->getAttributesHTML());
126
127
		$field->setAttribute('foo', null);
128
		$this->assertNotContains('foo=', $field->getAttributesHTML());
129
130
		$field->setAttribute('foo', '');
131
		$this->assertNotContains('foo=', $field->getAttributesHTML());
132
133
		$field->setAttribute('foo', false);
134
		$this->assertNotContains('foo=', $field->getAttributesHTML());
135
136
		$field->setAttribute('foo', true);
137
		$this->assertContains('foo="foo"', $field->getAttributesHTML());
138
139
		$field->setAttribute('foo', 'false');
140
		$this->assertContains('foo="false"', $field->getAttributesHTML());
141
142
		$field->setAttribute('foo', 'true');
143
		$this->assertContains('foo="true"', $field->getAttributesHTML());
144
145
		$field->setAttribute('foo', 0);
146
		$this->assertContains('foo="0"', $field->getAttributesHTML());
147
148
		$field->setAttribute('one', 1);
149
		$field->setAttribute('two', 2);
150
		$field->setAttribute('three', 3);
151
		$this->assertNotContains('one="1"', $field->getAttributesHTML('one', 'two'));
152
		$this->assertNotContains('two="2"', $field->getAttributesHTML('one', 'two'));
153
		$this->assertContains('three="3"', $field->getAttributesHTML('one', 'two'));
154
	}
155
156
	public function testReadonly() {
157
		$field = new FormField('MyField');
158
		$field->setReadonly(true);
159
		$this->assertContains('readonly="readonly"', $field->getAttributesHTML());
160
		$field->setReadonly(false);
161
		$this->assertNotContains('readonly="readonly"', $field->getAttributesHTML());
162
	}
163
164
	public function testDisabled() {
165
		$field = new FormField('MyField');
166
		$field->setDisabled(true);
167
		$this->assertContains('disabled="disabled"', $field->getAttributesHTML());
168
		$field->setDisabled(false);
169
		$this->assertNotContains('disabled="disabled"', $field->getAttributesHTML());
170
	}
171
172
	public function testEveryFieldTransformsReadonlyAsClone() {
173
		$fieldClasses = ClassInfo::subclassesFor('FormField');
174
		foreach($fieldClasses as $fieldClass) {
0 ignored issues
show
Bug introduced by
The expression $fieldClasses of type null|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
175
			$reflectionClass = new ReflectionClass($fieldClass);
176
			if(!$reflectionClass->isInstantiable()) continue;
177
			$constructor = $reflectionClass->getMethod('__construct');
178
			if($constructor->getNumberOfRequiredParameters() > 1) continue;
179
			if($fieldClass == 'CompositeField' || is_subclass_of($fieldClass, 'CompositeField')) continue;
180
181
			if ( $fieldClass = 'NullableField' ) {
182
				$instance = new $fieldClass(new TextField("{$fieldClass}_instance"));
183
			} else {
184
				$instance = new $fieldClass("{$fieldClass}_instance");
185
			}
186
			$isReadonlyBefore = $instance->isReadonly();
187
			$readonlyInstance = $instance->performReadonlyTransformation();
188
			$this->assertEquals(
189
				$isReadonlyBefore,
190
				$instance->isReadonly(),
191
				"FormField class {$fieldClass} retains its readonly state after calling performReadonlyTransformation()"
192
			);
193
			$this->assertTrue(
194
				$readonlyInstance->isReadonly(),
195
				"FormField class {$fieldClass} returns a valid readonly representation as of isReadonly()"
196
			);
197
			$this->assertNotSame(
198
				$readonlyInstance,
199
				$instance,
200
				"FormField class {$fieldClass} returns a valid cloned readonly representation"
201
			);
202
		}
203
	}
204
205
	public function testEveryFieldTransformsDisabledAsClone() {
206
		$fieldClasses = ClassInfo::subclassesFor('FormField');
207
		foreach($fieldClasses as $fieldClass) {
0 ignored issues
show
Bug introduced by
The expression $fieldClasses of type null|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
208
			$reflectionClass = new ReflectionClass($fieldClass);
209
			if(!$reflectionClass->isInstantiable()) continue;
210
			$constructor = $reflectionClass->getMethod('__construct');
211
			if($constructor->getNumberOfRequiredParameters() > 1) continue;
212
			if($fieldClass == 'CompositeField' || is_subclass_of($fieldClass, 'CompositeField')) continue;
213
214
			if ( $fieldClass = 'NullableField' ) {
215
				$instance = new $fieldClass(new TextField("{$fieldClass}_instance"));
216
			} else {
217
				$instance = new $fieldClass("{$fieldClass}_instance");
218
			}
219
220
			$isDisabledBefore = $instance->isDisabled();
221
			$disabledInstance = $instance->performDisabledTransformation();
222
			$this->assertEquals(
223
				$isDisabledBefore,
224
				$instance->isDisabled(),
225
				"FormField class {$fieldClass} retains its disabled state after calling performDisabledTransformation()"
226
			);
227
			$this->assertTrue(
228
				$disabledInstance->isDisabled(),
229
				"FormField class {$fieldClass} returns a valid disabled representation as of isDisabled()"
230
			);
231
			$this->assertNotSame(
232
				$disabledInstance,
233
				$instance,
234
				"FormField class {$fieldClass} returns a valid cloned disabled representation"
235
			);
236
		}
237
	}
238
239
	public function testUpdateAttributes() {
240
		$field = new FormField('MyField');
241
		$this->assertArrayHasKey('extended', $field->getAttributes());
242
	}
243
244
	public function testSetSchemaComponent() {
245
		$field = new FormField('MyField');
246
		$field = $field->setSchemaComponent('MyComponent');
247
		$component = $field->getSchemaComponent();
248
		$this->assertEquals('MyComponent', $component);
249
	}
250
251
	public function testGetSchemaDataDefaults() {
252
		$field = new FormField('MyField');
253
		$schema = $field->getSchemaDataDefaults();
254
		$this->assertInternalType('array', $schema);
255
	}
256
257
	public function testGetSchemaData() {
258
		$field = new FormField('MyField');
259
		$schema = $field->getSchemaData();
260
		$this->assertEquals('MyField', $schema['name']);
261
262
		// Make sure the schema data is up-to-date with object properties.
263
		$field->setName('UpdatedField');
264
		$schema = $field->getSchemaData();
265
		$this->assertEquals($field->getName(), $schema['name']);
266
	}
267
268
	public function testSetSchemaData() {
269
		$field = new FormField('MyField');
270
271
		// Make sure the user can update values.
272
		$field = $field->setSchemaData(['name' => 'MyUpdatedField']);
273
		$schema = $field->getSchemaData();
274
		$this->assertEquals($schema['name'], 'MyUpdatedField');
275
276
		// Make user the user can't define custom keys on the schema.
277
		$field = $field->setSchemaData(['myCustomKey' => 'yolo']);
278
		$schema = $field->getSchemaData();
279
		$this->assertEquals(array_key_exists('myCustomKey', $schema), false);
280
	}
281
282
	public function testGetSchemaState() {
283
		$field = new FormField('MyField');
284
		$field->setValue('My value');
285
		$schema = $field->getSchemaState();
286
		$this->assertEquals('My value', $schema['value']);
287
	}
288
289
	public function testSetSchemaState() {
290
		$field = new FormField('MyField');
291
292
		// Make sure the user can update values.
293
		$field = $field->setSchemaState(['value' => 'My custom value']);
294
		$schema = $field->getSchemaState();
295
		$this->assertEquals($schema['value'], 'My custom value');
296
297
		// Make user the user can't define custom keys on the schema.
298
		$field = $field->setSchemaState(['myCustomKey' => 'yolo']);
299
		$schema = $field->getSchemaState();
300
		$this->assertEquals(array_key_exists('myCustomKey', $schema), false);
301
	}
302
303
	public function testGetSchemaStateWithFormValidation() {
304
		$field = new FormField('MyField');
305
		$validator = new RequiredFields('MyField');
306
		$form = new Form(new Controller(), 'TestForm', new FieldList($field), new FieldList(), $validator);
307
		$validator->validationError('MyField', 'Something is wrong', 'error');
308
		$schema = $field->getSchemaState();
309
		$this->assertEquals(count($schema['messages']), 1);
310
		$this->assertEquals('Something is wrong', $schema['messages'][0]['value']);
311
	}
312
}
313
314
/**
315
 * @package framework
316
 * @subpackage tests
317
 */
318
class FormFieldTest_Extension extends Extension implements TestOnly {
319
320
	public function updateAttributes(&$attrs) {
321
		$attrs['extended'] = true;
322
	}
323
324
}
325