silverstripe-framework/tests/view/ViewableDataTest.php

306 lines
9.5 KiB
PHP
Raw Normal View History

<?php
/**
2014-08-15 08:53:05 +02:00
* See {@link SSViewerTest->testCastingHelpers()} for more tests related to casting and ViewableData behaviour,
2012-02-29 20:35:48 +01:00
* from a template-parsing perspective.
2014-08-15 08:53:05 +02:00
*
* @package framework
* @subpackage tests
*/
class ViewableDataTest extends SapphireTest {
2014-08-15 08:53:05 +02:00
public function testRequiresCasting() {
$caster = new ViewableDataTest_Castable();
2014-08-15 08:53:05 +02:00
$this->assertTrue($caster->obj('alwaysCasted') instanceof ViewableDataTest_RequiresCasting);
$this->assertTrue($caster->obj('noCastingInformation') instanceof ViewableData_Caster);
2014-08-15 08:53:05 +02:00
$this->assertTrue($caster->obj('alwaysCasted', null, false) instanceof ViewableDataTest_RequiresCasting);
$this->assertFalse($caster->obj('noCastingInformation', null, false) instanceof ViewableData_Caster);
}
public function testFailoverRequiresCasting() {
$caster = new ViewableDataTest_Castable();
$container = new ViewableDataTest_Container();
$container->setFailover($caster);
$this->assertTrue($container->obj('alwaysCasted') instanceof ViewableDataTest_RequiresCasting);
$this->assertTrue($caster->obj('alwaysCasted', null, false) instanceof ViewableDataTest_RequiresCasting);
/* @todo This currently fails, because the default_cast static variable is always taken from the topmost
* object, not the failover object the field actually came from. Should we fix this, or declare current
* behaviour as correct?
2014-08-15 08:53:05 +02:00
*
* $this->assertTrue($container->obj('noCastingInformation') instanceof ViewableData_Caster);
* $this->assertFalse($caster->obj('noCastingInformation', null, false) instanceof ViewableData_Caster);
*/
}
public function testCastingXMLVal() {
$caster = new ViewableDataTest_Castable();
2014-08-15 08:53:05 +02:00
$this->assertEquals('casted', $caster->XML_val('alwaysCasted'));
$this->assertEquals('noCastingInformation', $caster->XML_val('noCastingInformation'));
2014-08-15 08:53:05 +02:00
// test automatic escaping is only applied by casted classes
$this->assertEquals('<foo>', $caster->XML_val('unsafeXML'));
$this->assertEquals('&lt;foo&gt;', $caster->XML_val('castedUnsafeXML'));
}
2014-08-15 08:53:05 +02:00
public function testUncastedXMLVal() {
$caster = new ViewableDataTest_Castable();
$this->assertEquals($caster->XML_val('uncastedZeroValue'), 0);
}
2014-08-15 08:53:05 +02:00
public function testArrayCustomise() {
$viewableData = new ViewableDataTest_Castable();
$newViewableData = $viewableData->customise(array (
'test' => 'overwritten',
'alwaysCasted' => 'overwritten'
));
2014-08-15 08:53:05 +02:00
$this->assertEquals('test', $viewableData->XML_val('test'));
$this->assertEquals('casted', $viewableData->XML_val('alwaysCasted'));
$this->assertEquals('overwritten', $newViewableData->XML_val('test'));
$this->assertEquals('overwritten', $newViewableData->XML_val('alwaysCasted'));
$this->assertEquals('castable', $viewableData->forTemplate());
$this->assertEquals('castable', $newViewableData->forTemplate());
}
public function testObjectCustomise() {
$viewableData = new ViewableDataTest_Castable();
$newViewableData = $viewableData->customise(new ViewableDataTest_RequiresCasting());
$this->assertEquals('test', $viewableData->XML_val('test'));
$this->assertEquals('casted', $viewableData->XML_val('alwaysCasted'));
$this->assertEquals('overwritten', $newViewableData->XML_val('test'));
$this->assertEquals('casted', $newViewableData->XML_val('alwaysCasted'));
$this->assertEquals('castable', $viewableData->forTemplate());
$this->assertEquals('casted', $newViewableData->forTemplate());
}
public function testDefaultValueWrapping() {
$data = new ArrayData(array('Title' => 'SomeTitleValue'));
// this results in a cached raw string in ViewableData:
$this->assertTrue($data->hasValue('Title'));
$this->assertFalse($data->hasValue('SomethingElse'));
// this should cast the raw string to a StringField since we are
// passing true as the third argument:
$obj = $data->obj('Title', null, true);
$this->assertTrue(is_object($obj));
// and the string field should have the value of the raw string:
$this->assertEquals('SomeTitleValue', $obj->forTemplate());
}
public function testRAWVal() {
$data = new ViewableDataTest_Castable();
$data->test = 'This &amp; This';
$this->assertEquals($data->RAW_val('test'), 'This & This');
}
2014-08-15 08:53:05 +02:00
public function testSQLVal() {
$data = new ViewableDataTest_Castable();
$this->assertEquals($data->SQL_val('test'), 'test');
}
public function testJSVal() {
$data = new ViewableDataTest_Castable();
$data->test = '"this is a test"';
$this->assertEquals($data->JS_val('test'), '\"this is a test\"');
}
public function testATTVal() {
$data = new ViewableDataTest_Castable();
$data->test = '"this is a test"';
$this->assertEquals($data->ATT_val('test'), '&quot;this is a test&quot;');
}
public function testCastingClass() {
$expected = array(
'NonExistant' => null,
'Field' => 'CastingType',
'Argument' => 'ArgumentType',
'ArrayArgument' => 'ArrayArgumentType'
);
$obj = new ViewableDataTest_CastingClass();
foreach($expected as $field => $class) {
$this->assertEquals(
$class,
$obj->castingClass($field),
"castingClass() returns correct results for ::\$$field"
);
}
}
public function testObjWithCachedStringValueReturnsValidObject() {
$obj = new ViewableDataTest_NoCastingInformation();
// Save a literal string into cache
$cache = true;
$uncastedData = $obj->obj('noCastingInformation', null, false, $cache);
// Fetch the cached string as an object
$forceReturnedObject = true;
$castedData = $obj->obj('noCastingInformation', null, $forceReturnedObject);
// Uncasted data should always be the nonempty string
$this->assertNotEmpty($uncastedData, 'Uncasted data was empty.');
$this->assertTrue(is_string($uncastedData), 'Uncasted data should be a string.');
// Casted data should be the string wrapped in a DBField-object.
$this->assertNotEmpty($castedData, 'Casted data was empty.');
$this->assertInstanceOf('SilverStripe\\ORM\\FieldType\\DBField', $castedData, 'Casted data should be instance of DBField.');
$this->assertEquals($uncastedData, $castedData->getValue(), 'Casted and uncasted strings are not equal.');
}
2015-03-01 22:07:58 +01:00
public function testCaching() {
$objCached = new ViewableDataTest_Cached();
$objNotCached = new ViewableDataTest_NotCached();
$objCached->Test = 'AAA';
$objNotCached->Test = 'AAA';
$this->assertEquals('AAA', $objCached->obj('Test', null, true, true));
$this->assertEquals('AAA', $objNotCached->obj('Test', null, true, true));
$objCached->Test = 'BBB';
$objNotCached->Test = 'BBB';
// Cached data must be always the same
$this->assertEquals('AAA', $objCached->obj('Test', null, true, true));
$this->assertEquals('BBB', $objNotCached->obj('Test', null, true, true));
}
public function testSetFailover() {
$failover = new ViewableData();
$container = new ViewableDataTest_Container();
$container->setFailover($failover);
$this->assertSame($failover, $container->getFailover(), 'getFailover() returned a different object');
$this->assertFalse($container->hasMethod('testMethod'), 'testMethod() is already defined when it shouldnt be');
// Ensure that defined methods detected from the failover aren't cached when setting a new failover
$container->setFailover(new ViewableDataTest_Failover);
$this->assertTrue($container->hasMethod('testMethod'));
// Test the reverse - that defined methods previously detected in a failover are removed if they no longer exist
$container->setFailover($failover);
$this->assertSame($failover, $container->getFailover(), 'getFailover() returned a different object');
$this->assertFalse($container->hasMethod('testMethod'), 'testMethod() incorrectly reported as existing');
}
}
/**#@+
* @ignore
*/
class ViewableDataTest_Castable extends ViewableData {
2014-08-15 08:53:05 +02:00
private static $default_cast = 'ViewableData_Caster';
2014-08-15 08:53:05 +02:00
private static $casting = array (
'alwaysCasted' => 'ViewableDataTest_RequiresCasting',
'castedUnsafeXML' => 'ViewableData_UnescaptedCaster'
);
2014-08-15 08:53:05 +02:00
public $test = 'test';
2014-08-15 08:53:05 +02:00
public $uncastedZeroValue = 0;
2014-08-15 08:53:05 +02:00
public function alwaysCasted() {
return 'alwaysCasted';
}
2014-08-15 08:53:05 +02:00
public function noCastingInformation() {
return 'noCastingInformation';
}
2014-08-15 08:53:05 +02:00
public function unsafeXML() {
return '<foo>';
}
2014-08-15 08:53:05 +02:00
public function castedUnsafeXML() {
return $this->unsafeXML();
}
public function forTemplate() {
return 'castable';
}
}
class ViewableDataTest_RequiresCasting extends ViewableData {
2014-08-15 08:53:05 +02:00
public $test = 'overwritten';
2014-08-15 08:53:05 +02:00
public function forTemplate() {
return 'casted';
}
2014-08-15 08:53:05 +02:00
public function setValue() {}
2014-08-15 08:53:05 +02:00
}
class ViewableData_UnescaptedCaster extends ViewableData {
2014-08-15 08:53:05 +02:00
protected $value;
2014-08-15 08:53:05 +02:00
public function setValue($value) {
$this->value = $value;
}
2014-08-15 08:53:05 +02:00
public function forTemplate() {
return Convert::raw2xml($this->value);
}
2014-08-15 08:53:05 +02:00
}
class ViewableData_Caster extends ViewableData {
2014-08-15 08:53:05 +02:00
public function forTemplate() {
return 'casted';
}
2014-08-15 08:53:05 +02:00
public function setValue() {}
2014-08-15 08:53:05 +02:00
}
class ViewableDataTest_Container extends ViewableData {
}
class ViewableDataTest_CastingClass extends ViewableData {
private static $casting = array(
'Field' => 'CastingType',
'Argument' => 'ArgumentType(Argument)',
'ArrayArgument' => 'ArrayArgumentType(array(foo, bar))'
);
}
class ViewableDataTest_NoCastingInformation extends ViewableData {
public function noCastingInformation() {
return "No casting information";
}
}
2015-03-01 22:07:58 +01:00
class ViewableDataTest_Cached extends ViewableData {
public $Test;
}
class ViewableDataTest_NotCached extends ViewableData {
public $Test;
protected function objCacheGet($key) {
// Disable caching
return null;
}
}
class ViewableDataTest_Failover extends ViewableData {
public function testMethod() {}
}