Completed
Push — master ( 5776a0...605463 )
by Daniel
23s
created

ViewableDataTest   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 181
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 13

Importance

Changes 3
Bugs 3 Features 0
Metric Value
c 3
b 3
f 0
dl 0
loc 181
rs 10
wmc 12
lcom 1
cbo 13

11 Methods

Rating   Name   Duplication   Size   Complexity  
A testRequiresCasting() 0 6 1
A testFailoverRequiresCasting() 0 11 1
A testCastingXMLVal() 0 10 1
A testArrayCustomise() 0 16 1
A testObjectCustomise() 0 13 1
A testDefaultValueWrapping() 0 12 1
A testCastingClass() 0 17 2
A testObjWithCachedStringValueReturnsValidObject() 0 21 1
A testCaching() 0 17 1
A testSetFailover() 0 17 1
B testCasting() 0 27 1
1
<?php
2
3
use SilverStripe\ORM\FieldType\DBField;
4
5
/**
6
 * See {@link SSViewerTest->testCastingHelpers()} for more tests related to casting and ViewableData behaviour,
7
 * from a template-parsing perspective.
8
 *
9
 * @package framework
10
 * @subpackage tests
11
 */
12
class ViewableDataTest extends SapphireTest {
13
14
	public function testCasting() {
15
		$htmlString = "&quot;";
16
		$textString = '"';
17
18
		$htmlField = DBField::create_field('HTMLFragment', $textString);
19
20
		$this->assertEquals($textString, $htmlField->forTemplate());
21
		$this->assertEquals($htmlString, $htmlField->obj('HTMLATT')->forTemplate());
22
		$this->assertEquals('%22', $htmlField->obj('URLATT')->forTemplate());
23
		$this->assertEquals('%22', $htmlField->obj('RAWURLATT')->forTemplate());
24
		$this->assertEquals($htmlString, $htmlField->obj('ATT')->forTemplate());
25
		$this->assertEquals($textString, $htmlField->obj('RAW')->forTemplate());
26
		$this->assertEquals('\"', $htmlField->obj('JS')->forTemplate());
27
		$this->assertEquals($htmlString, $htmlField->obj('HTML')->forTemplate());
28
		$this->assertEquals($htmlString, $htmlField->obj('XML')->forTemplate());
29
30
		$textField = DBField::create_field('Text', $textString);
31
		$this->assertEquals($htmlString, $textField->forTemplate());
32
		$this->assertEquals($htmlString, $textField->obj('HTMLATT')->forTemplate());
33
		$this->assertEquals('%22', $textField->obj('URLATT')->forTemplate());
34
		$this->assertEquals('%22', $textField->obj('RAWURLATT')->forTemplate());
35
		$this->assertEquals($htmlString, $textField->obj('ATT')->forTemplate());
36
		$this->assertEquals($textString, $textField->obj('RAW')->forTemplate());
37
		$this->assertEquals('\"', $textField->obj('JS')->forTemplate());
38
		$this->assertEquals($htmlString, $textField->obj('HTML')->forTemplate());
39
		$this->assertEquals($htmlString, $textField->obj('XML')->forTemplate());
40
	}
41
42
	public function testRequiresCasting() {
43
		$caster = new ViewableDataTest_Castable();
44
45
		$this->assertInstanceOf('ViewableDataTest_RequiresCasting', $caster->obj('alwaysCasted'));
46
		$this->assertInstanceOf('ViewableData_Caster', $caster->obj('noCastingInformation'));
47
	}
48
49
	public function testFailoverRequiresCasting() {
50
		$caster = new ViewableDataTest_Castable();
51
		$container = new ViewableDataTest_Container();
52
		$container->setFailover($caster);
53
54
		$this->assertInstanceOf('ViewableDataTest_RequiresCasting', $container->obj('alwaysCasted'));
55
		$this->assertInstanceOf('ViewableDataTest_RequiresCasting', $caster->obj('alwaysCasted'));
56
57
		$this->assertInstanceOf('ViewableData_Caster', $container->obj('noCastingInformation'));
58
		$this->assertInstanceOf('ViewableData_Caster', $caster->obj('noCastingInformation'));
59
	}
60
61
	public function testCastingXMLVal() {
62
		$caster = new ViewableDataTest_Castable();
63
64
		$this->assertEquals('casted', $caster->XML_val('alwaysCasted'));
65
		$this->assertEquals('casted', $caster->XML_val('noCastingInformation'));
66
67
		// Test automatic escaping is applied even to fields with no 'casting'
68
		$this->assertEquals('casted', $caster->XML_val('unsafeXML'));
69
		$this->assertEquals('&lt;foo&gt;', $caster->XML_val('castedUnsafeXML'));
70
	}
71
72
	public function testArrayCustomise() {
73
		$viewableData    = new ViewableDataTest_Castable();
74
		$newViewableData = $viewableData->customise(array (
75
			'test'         => 'overwritten',
76
			'alwaysCasted' => 'overwritten'
77
		));
78
79
		$this->assertEquals('test', $viewableData->XML_val('test'));
80
		$this->assertEquals('casted', $viewableData->XML_val('alwaysCasted'));
81
82
		$this->assertEquals('overwritten', $newViewableData->XML_val('test'));
83
		$this->assertEquals('overwritten', $newViewableData->XML_val('alwaysCasted'));
84
85
		$this->assertEquals('castable', $viewableData->forTemplate());
86
		$this->assertEquals('castable', $newViewableData->forTemplate());
87
	}
88
89
	public function testObjectCustomise() {
90
		$viewableData    = new ViewableDataTest_Castable();
91
		$newViewableData = $viewableData->customise(new ViewableDataTest_RequiresCasting());
92
93
		$this->assertEquals('test', $viewableData->XML_val('test'));
94
		$this->assertEquals('casted', $viewableData->XML_val('alwaysCasted'));
95
96
		$this->assertEquals('overwritten', $newViewableData->XML_val('test'));
97
		$this->assertEquals('casted', $newViewableData->XML_val('alwaysCasted'));
98
99
		$this->assertEquals('castable', $viewableData->forTemplate());
100
		$this->assertEquals('casted', $newViewableData->forTemplate());
101
	}
102
103
	public function testDefaultValueWrapping() {
104
		$data = new ArrayData(array('Title' => 'SomeTitleValue'));
105
		// this results in a cached raw string in ViewableData:
106
		$this->assertTrue($data->hasValue('Title'));
107
		$this->assertFalse($data->hasValue('SomethingElse'));
108
		// this should cast the raw string to a StringField since we are
109
		// passing true as the third argument:
110
		$obj = $data->obj('Title', null, true);
111
		$this->assertTrue(is_object($obj));
112
		// and the string field should have the value of the raw string:
113
		$this->assertEquals('SomeTitleValue', $obj->forTemplate());
114
	}
115
116
	public function testCastingClass() {
117
		$expected = array(
118
			//'NonExistant'   => null,
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% 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...
119
			'Field'         => 'CastingType',
120
			'Argument'      => 'ArgumentType',
121
			'ArrayArgument' => 'ArrayArgumentType'
122
		);
123
		$obj = new ViewableDataTest_CastingClass();
124
125
		foreach($expected as $field => $class) {
126
			$this->assertEquals(
127
				$class,
128
				$obj->castingClass($field),
129
				"castingClass() returns correct results for ::\$$field"
130
			);
131
		}
132
	}
133
134
	public function testObjWithCachedStringValueReturnsValidObject() {
135
		$obj = new ViewableDataTest_NoCastingInformation();
136
137
		// Save a literal string into cache
138
		$cache = true;
139
		$uncastedData = $obj->obj('noCastingInformation', null, false, $cache);
140
141
		// Fetch the cached string as an object
142
		$forceReturnedObject = true;
143
		$castedData = $obj->obj('noCastingInformation', null, $forceReturnedObject);
144
145
		// Uncasted data should always be the nonempty string
146
		$this->assertNotEmpty($uncastedData, 'Uncasted data was empty.');
147
		//$this->assertTrue(is_string($uncastedData), 'Uncasted data should be a string.');
0 ignored issues
show
Unused Code Comprehensibility introduced by
77% 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...
148
149
		// Casted data should be the string wrapped in a DBField-object.
150
		$this->assertNotEmpty($castedData, 'Casted data was empty.');
151
		$this->assertInstanceOf('SilverStripe\\ORM\\FieldType\\DBField', $castedData, 'Casted data should be instance of DBField.');
152
153
		$this->assertEquals($uncastedData, $castedData->getValue(), 'Casted and uncasted strings are not equal.');
154
	}
155
156
	public function testCaching() {
157
		$objCached = new ViewableDataTest_Cached();
158
		$objNotCached = new ViewableDataTest_NotCached();
159
160
		$objCached->Test = 'AAA';
161
		$objNotCached->Test = 'AAA';
162
163
		$this->assertEquals('AAA', $objCached->obj('Test', null, true, true));
164
		$this->assertEquals('AAA', $objNotCached->obj('Test', null, true, true));
165
166
		$objCached->Test = 'BBB';
167
		$objNotCached->Test = 'BBB';
168
169
		// Cached data must be always the same
170
		$this->assertEquals('AAA', $objCached->obj('Test', null, true, true));
171
		$this->assertEquals('BBB', $objNotCached->obj('Test', null, true, true));
172
	}
173
174
	public function testSetFailover() {
175
		$failover = new ViewableData();
176
		$container = new ViewableDataTest_Container();
177
		$container->setFailover($failover);
178
179
		$this->assertSame($failover, $container->getFailover(), 'getFailover() returned a different object');
180
		$this->assertFalse($container->hasMethod('testMethod'), 'testMethod() is already defined when it shouldn’t be');
181
182
		// Ensure that defined methods detected from the failover aren't cached when setting a new failover
183
		$container->setFailover(new ViewableDataTest_Failover);
184
		$this->assertTrue($container->hasMethod('testMethod'));
185
186
		// Test the reverse - that defined methods previously detected in a failover are removed if they no longer exist
187
		$container->setFailover($failover);
188
		$this->assertSame($failover, $container->getFailover(), 'getFailover() returned a different object');
189
		$this->assertFalse($container->hasMethod('testMethod'), 'testMethod() incorrectly reported as existing');
190
	}
191
192
}
193
194
/**#@+
195
 * @ignore
196
 */
197
class ViewableDataTest_Castable extends ViewableData {
198
199
	private static $default_cast = 'ViewableData_Caster';
200
201
	private static $casting = array (
202
		'alwaysCasted'    => 'ViewableDataTest_RequiresCasting',
203
		'castedUnsafeXML' => 'ViewableData_UnescaptedCaster',
204
		'test' => 'Text',
205
	);
206
207
	public $test = 'test';
208
209
	public $uncastedZeroValue = 0;
210
211
	public function alwaysCasted() {
212
		return 'alwaysCasted';
213
	}
214
215
	public function noCastingInformation() {
216
		return 'noCastingInformation';
217
	}
218
219
	public function unsafeXML() {
220
		return '<foo>';
221
	}
222
223
	public function castedUnsafeXML() {
224
		return $this->unsafeXML();
225
	}
226
227
	public function forTemplate() {
228
		return 'castable';
229
	}
230
}
231
232
class ViewableDataTest_RequiresCasting extends ViewableData {
233
234
	public $test = 'overwritten';
235
236
	public function forTemplate() {
237
		return 'casted';
238
	}
239
240
	public function setValue() {}
241
242
}
243
244
class ViewableData_UnescaptedCaster extends ViewableData {
245
246
	protected $value;
247
248
	public function setValue($value) {
249
		$this->value = $value;
250
	}
251
252
	public function forTemplate() {
253
		return Convert::raw2xml($this->value);
254
	}
255
256
}
257
258
class ViewableData_Caster extends ViewableData {
259
260
	public function forTemplate() {
261
		return 'casted';
262
	}
263
264
	public function setValue() {}
265
266
}
267
268
class ViewableDataTest_Container extends ViewableData {
269
270
}
271
272
class ViewableDataTest_CastingClass extends ViewableData {
273
	private static $casting = array(
274
		'Field'         => 'CastingType',
275
		'Argument'      => 'ArgumentType(Argument)',
276
		'ArrayArgument' => 'ArrayArgumentType(array(foo, bar))'
277
	);
278
}
279
280
class ViewableDataTest_NoCastingInformation extends ViewableData {
281
	public function noCastingInformation() {
282
		return "No casting information";
283
	}
284
}
285
286
class ViewableDataTest_Cached extends ViewableData {
287
	public $Test;
288
}
289
290
class ViewableDataTest_NotCached extends ViewableData {
291
	public $Test;
292
293
	protected function objCacheGet($key) {
294
		// Disable caching
295
		return null;
296
	}
297
}
298
299
class ViewableDataTest_Failover extends ViewableData {
300
	public function testMethod() {}
301
}
302