mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-12-22 14:41:29 +01:00
Basic Etemplate testing
Some simple exec / process round-trip tests
This commit is contained in:
parent
490a8f6ff4
commit
9d1756e5d9
@ -368,7 +368,15 @@ class Etemplate extends Etemplate\Widget\Template
|
||||
|
||||
//error_log(__METHOD__."(,".array2string($content).')');
|
||||
//error_log(' validated='.array2string($validated));
|
||||
$content = ExecMethod(self::$request->method, self::complete_array_merge(self::$request->preserv, $validated));
|
||||
if(is_callable(self::$request->method))
|
||||
{
|
||||
call_user_func(self::$request->method,self::complete_array_merge(self::$request->preserv, $validated));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Deprecated, but may still be needed
|
||||
$content = ExecMethod(self::$request->method, self::complete_array_merge(self::$request->preserv, $validated));
|
||||
}
|
||||
|
||||
$tcontent = is_array($content) ? $content :
|
||||
self::complete_array_merge(self::$request->preserv, $validated);
|
||||
|
@ -22,12 +22,53 @@ require_once realpath(__DIR__.'/../../test/WidgetBaseTest.php');
|
||||
class TemplateTest extends \EGroupware\Api\Etemplate\WidgetBaseTest {
|
||||
|
||||
/**
|
||||
* Test instanciation of a template
|
||||
* Test instanciation of template from a file
|
||||
*/
|
||||
public function testInstance()
|
||||
public function testSimpleInstance()
|
||||
{
|
||||
$this->markTestIncomplete(
|
||||
'This test has not been implemented yet.'
|
||||
);
|
||||
static $name = 'api.prompt';
|
||||
|
||||
$template = Template::instance($name);
|
||||
$this->assertInstanceOf(Template::class, $template);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test instanciating nested template
|
||||
*
|
||||
*/
|
||||
public function testNestedInstanciation()
|
||||
{
|
||||
static $template = 'api.nested';
|
||||
|
||||
$template = Template::instance($template, 'test');
|
||||
$this->assertInstanceOf(Template::class, $template);
|
||||
|
||||
// Check for the sub-child to see if the nested template was loaded
|
||||
$this->assertInstanceOf(\EGroupware\Api\Etemplate\Widget::class, $template->getElementById('sub_child'));
|
||||
|
||||
// Check that it's not just making things up
|
||||
$this->assertNull($template->getElementById('not_existing'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test that we can instanciate a sub-template from a file, once the file
|
||||
* is in the cache
|
||||
*
|
||||
* @depends testNestedInstanciation
|
||||
*/
|
||||
public function testSubTemplate()
|
||||
{
|
||||
// No file matches this, but it was loaded and cached in the previous test
|
||||
static $template = 'api.nested.sub_template';
|
||||
$template = Template::instance($template, 'test');
|
||||
$this->assertInstanceOf(Template::class, $template);
|
||||
|
||||
// Check for the sub-child to see if the template was loaded
|
||||
$this->assertInstanceOf(\EGroupware\Api\Etemplate\Widget::class, $template->getElementById('sub_child'));
|
||||
|
||||
// Check that it's not just making things up
|
||||
$this->assertNull($template->getElementById('not_existing'));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -12,9 +12,14 @@
|
||||
|
||||
namespace EGroupware\Api\Etemplate;
|
||||
|
||||
use Egroupware\Api\Etemplate;
|
||||
|
||||
// test base providing Egw environment, since we need the DB
|
||||
require_once realpath(__DIR__.'/../../test/LoggedInTest.php');
|
||||
|
||||
// Store request in the session, file access probably won't work due to permissions
|
||||
\EGroupware\Api\Etemplate\Request::$request_class = 'EGroupware\Api\Etemplate\Request\Session';
|
||||
|
||||
/**
|
||||
* Base class for all widget tests doing needed setup so the tests can run, and
|
||||
* providing common utilities.
|
||||
@ -24,6 +29,16 @@ require_once realpath(__DIR__.'/../../test/LoggedInTest.php');
|
||||
*/
|
||||
abstract class WidgetBaseTest extends \EGroupware\Api\LoggedInTest {
|
||||
|
||||
/**
|
||||
* We use our own callback for results of executing, here we store the results
|
||||
* until returned
|
||||
*
|
||||
* @var Array
|
||||
*/
|
||||
protected static $mocked_exec_result = array();
|
||||
|
||||
protected $ajax_response = null;
|
||||
|
||||
public static function setUpBeforeClass()
|
||||
{
|
||||
parent::setUpBeforeClass();
|
||||
@ -34,23 +49,89 @@ abstract class WidgetBaseTest extends \EGroupware\Api\LoggedInTest {
|
||||
new \EGroupware\Api\Etemplate();
|
||||
}
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
// Mock AJAX response
|
||||
$this->ajax_response = $this->mock_ajax_response();
|
||||
}
|
||||
public function tearDown()
|
||||
{
|
||||
// Clean up AJAX response
|
||||
$this->ajax_response->initResponseArray();
|
||||
$ref = new \ReflectionProperty('\\EGroupware\\Api\\Json\\Response', 'response');
|
||||
$ref->setAccessible(true);
|
||||
$ref->setValue(null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use a known, public callback so we can hook into it, if needed
|
||||
*/
|
||||
public static function public_callback($content)
|
||||
{
|
||||
static::$mocked_exec_result = $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mocks what is needed to fake a call to exec, and catch its output.
|
||||
* The resulting array of information, which would normally be sent to the
|
||||
* client as JSON, is returned for evaluation.
|
||||
*
|
||||
* @param String $method
|
||||
* @param Etemplate $etemplate
|
||||
* @param array $content
|
||||
* @param array $sel_options
|
||||
* @param array $readonlys
|
||||
* @param array $preserv
|
||||
*/
|
||||
protected function mockedExec(\EGroupware\Api\Etemplate $etemplate, $method,array $content,array $sel_options=null,array $readonlys=null,array $preserv=null)
|
||||
protected function mockedExec(Etemplate $etemplate, array $content,array $sel_options=null,array $readonlys=null,array $preserv=null)
|
||||
{
|
||||
ob_start();
|
||||
|
||||
// Exec the template
|
||||
$etemplate->exec(__CLASS__ . '::public_callback', $content, $sel_options, $readonlys, $preserv, 4);
|
||||
$result = $this->ajax_response->returnResult();
|
||||
|
||||
// Store & clean the request
|
||||
//$etemplate->destroy_request();
|
||||
|
||||
ob_end_clean();
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function mockedRoundTrip(\EGroupware\Api\Etemplate $etemplate, array $content,array $sel_options=null,array $readonlys=null,array $preserv=null)
|
||||
{
|
||||
|
||||
$result = $this->mockedExec($etemplate, $content, $sel_options, $readonlys, $preserv);
|
||||
|
||||
// Check for the load
|
||||
$data = array();
|
||||
foreach($result as $command)
|
||||
{
|
||||
if($command['type'] == 'et2_load')
|
||||
{
|
||||
$data = $command['data'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Etemplate::ajax_process_content($data['data']['etemplate_exec_id'], $data['data']['content'], false);
|
||||
|
||||
$content = static::$mocked_exec_result;
|
||||
static::$mocked_exec_result = array();
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mock the ajax response and override it so it doesn't try to send headers,
|
||||
* which generates errors since PHPUnit has already done that
|
||||
*/
|
||||
protected function mock_ajax_response()
|
||||
{
|
||||
$response = $this->getMockBuilder('\\EGroupware\\Api\\Json\\Response')
|
||||
->disableOriginalConstructor()
|
||||
->setMethods(['get'/*,'generic'*/])
|
||||
->getMock($etemplate);
|
||||
->getMock();
|
||||
// Replace protected self reference with mock object
|
||||
$ref = new \ReflectionProperty('\\EGroupware\\Api\\Json\\Response', 'response');
|
||||
$ref->setAccessible(true);
|
||||
@ -62,19 +143,6 @@ abstract class WidgetBaseTest extends \EGroupware\Api\LoggedInTest {
|
||||
// Don't send headers, like the real one does
|
||||
return self::$response;
|
||||
});
|
||||
|
||||
ob_start();
|
||||
|
||||
// Exec the template
|
||||
$etemplate->exec($method, $content, $sel_options, $readonlys, $preserv, 4);
|
||||
$result = $response->returnResult();
|
||||
|
||||
// Clean json response
|
||||
$response->initResponseArray();
|
||||
$ref->setValue(null, null);
|
||||
|
||||
ob_end_clean();
|
||||
|
||||
return $result;
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
|
@ -31,6 +31,10 @@ class EtemplateTest extends Etemplate\WidgetBaseTest {
|
||||
*/
|
||||
const TEST_TEMPLATE = 'api.prompt';
|
||||
|
||||
protected $content = array('value' => 'test content');
|
||||
protected $sel_options = array(array('value' => 0, 'label' => 'label'));
|
||||
protected $readonlys = array('value' => true);
|
||||
|
||||
/**
|
||||
* Test reading xml files
|
||||
*
|
||||
@ -48,7 +52,7 @@ class EtemplateTest extends Etemplate\WidgetBaseTest {
|
||||
$this->assertEquals(true, $etemplate->read(static::TEST_TEMPLATE));
|
||||
|
||||
// This loads and parses
|
||||
$result = $this->mockedExec($etemplate, '',array());
|
||||
$result = $this->mockedExec($etemplate, array());
|
||||
|
||||
// Look for the load and match the template name
|
||||
foreach($result as $command)
|
||||
@ -74,7 +78,7 @@ class EtemplateTest extends Etemplate\WidgetBaseTest {
|
||||
// Change the target DOM ID
|
||||
$etemplate->set_dom_id('test_id');
|
||||
|
||||
$result = $this->mockedExec($etemplate, '',array());
|
||||
$result = $this->mockedExec($etemplate, array());
|
||||
|
||||
// Check for the load
|
||||
foreach($result as $command)
|
||||
@ -92,10 +96,6 @@ class EtemplateTest extends Etemplate\WidgetBaseTest {
|
||||
*/
|
||||
public function testExec()
|
||||
{
|
||||
$content = array('id' => 'value');
|
||||
$sel_options = array(array('value' => 0, 'label' => 'label'));
|
||||
$readonlys = array('id' => true);
|
||||
|
||||
// Templates must be in the correct templates directory - use one from API
|
||||
$etemplate = new Etemplate();
|
||||
$etemplate->read(static::TEST_TEMPLATE);
|
||||
@ -103,7 +103,7 @@ class EtemplateTest extends Etemplate\WidgetBaseTest {
|
||||
// Change the target DOM ID
|
||||
$etemplate->set_dom_id('test_id');
|
||||
|
||||
$result = $this->mockedExec($etemplate, '',$content, $sel_options, $readonlys);
|
||||
$result = $this->mockedExec($etemplate, $this->content, $this->sel_options, $this->readonlys);
|
||||
|
||||
// Check for the load
|
||||
$data = array();
|
||||
@ -116,8 +116,103 @@ class EtemplateTest extends Etemplate\WidgetBaseTest {
|
||||
}
|
||||
}
|
||||
|
||||
$this->assertArraySubset($content, $data['data']['content'], false, 'Content does not match');
|
||||
$this->assertArraySubset($sel_options, $data['data']['sel_options'], false, 'Select options do not match');
|
||||
$this->assertArraySubset($readonlys, $data['data']['readonlys'], false, 'Readonlys does not match');
|
||||
$this->assertArraySubset($this->content, $data['data']['content'], false, 'Content does not match');
|
||||
$this->assertArraySubset($this->sel_options, $data['data']['sel_options'], false, 'Select options do not match');
|
||||
$this->assertArraySubset($this->readonlys, $data['data']['readonlys'], false, 'Readonlys does not match');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that data passed in is passed back
|
||||
*
|
||||
* In this case, since there's one input widget and we're passing it's value, and
|
||||
* we're not passing anything extra and no preserve, it should be the same.
|
||||
*
|
||||
* @depends testExec
|
||||
*/
|
||||
public function testRoundTrip()
|
||||
{
|
||||
// Templates must be in the correct templates directory - use one from API
|
||||
$etemplate = new Etemplate();
|
||||
$etemplate->read(static::TEST_TEMPLATE);
|
||||
|
||||
$this->readonlys['value'] = false;
|
||||
|
||||
$result = $this->mockedRoundTrip($etemplate, $this->content, $this->sel_options, $this->readonlys);
|
||||
|
||||
$this->assertEquals($this->content, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple test of a read-only widget
|
||||
*
|
||||
* The value is passed in, but does not come back
|
||||
*
|
||||
* @depends testExec
|
||||
*/
|
||||
public function testSimpleReadonly()
|
||||
{
|
||||
// Templates must be in the correct templates directory - use one from API
|
||||
$etemplate = new Etemplate();
|
||||
$etemplate->read(static::TEST_TEMPLATE);
|
||||
|
||||
$this->readonlys['value'] = true;
|
||||
|
||||
$result = $this->mockedRoundTrip($etemplate, $this->content, $this->sel_options, $this->readonlys);
|
||||
|
||||
// The only input widget is readonly, expect an empty array
|
||||
$this->assertEquals(array(), $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple test of preserve
|
||||
*
|
||||
* The value is passed in, and comes back, even if the widget is readonly,
|
||||
* or if there is no matching widget.
|
||||
*
|
||||
* @depends testExec
|
||||
*/
|
||||
public function testArbitraryPreserve()
|
||||
{
|
||||
// Templates must be in the correct templates directory - use one from API
|
||||
$etemplate = new Etemplate();
|
||||
$etemplate->read(static::TEST_TEMPLATE);
|
||||
|
||||
$this->readonlys['value'] = true;
|
||||
|
||||
$preserve = array('arbitrary' => 'value');
|
||||
$result = $this->mockedRoundTrip($etemplate, $this->content, $this->sel_options, $this->readonlys, $preserve);
|
||||
|
||||
// The only input widget is readonly, expect preserve back
|
||||
$this->assertEquals($preserve, $result);
|
||||
|
||||
// Now try with widget
|
||||
$this->readonlys['value'] = false;
|
||||
|
||||
$result = $this->mockedRoundTrip($etemplate, $this->content, $this->sel_options, $this->readonlys, $preserve);
|
||||
|
||||
// The only input widget is readonly, expect preserve + content back
|
||||
$this->assertArraySubset($this->content, $result);
|
||||
$this->assertArraySubset($preserve, $result);
|
||||
}
|
||||
|
||||
public function testReadonlyPreserve()
|
||||
{
|
||||
$etemplate = new Etemplate();
|
||||
$etemplate->read(static::TEST_TEMPLATE);
|
||||
|
||||
$this->readonlys['value'] = true;
|
||||
$preserve['value'] = 'preserved_value';
|
||||
|
||||
$result = $this->mockedRoundTrip($etemplate, $this->content, $this->sel_options, $this->readonlys, $preserve);
|
||||
|
||||
// The only input widget is readonly, expect preserve back, not content
|
||||
$this->assertEquals($preserve['value'], $result['value']);
|
||||
|
||||
$this->readonlys['value'] = false;
|
||||
$result = $this->mockedRoundTrip($etemplate, $this->content, $this->sel_options, $this->readonlys, $preserve);
|
||||
|
||||
// The only input widget is editable, expect content back, not preserve
|
||||
$this->assertEquals($this->content['value'], $result['value']);
|
||||
|
||||
}
|
||||
}
|
||||
|
12
api/templates/test/nested.xet
Normal file
12
api/templates/test/nested.xet
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE overlay PUBLIC "-//EGroupware GmbH//eTemplate 2//EN" "http://www.egroupware.org/etemplate2.dtd">
|
||||
<!-- This template is used in automated testing -->
|
||||
<overlay>
|
||||
<template id="api.nested.sub_template" template="" lang="" group="0" version="16.1">
|
||||
<widget id="sub_child"/>
|
||||
</template>
|
||||
<template id="api.nested" template="" lang="" group="0" version="16.1">
|
||||
<widget id="only_child"/>
|
||||
<template id="api.nested.sub_template"/>
|
||||
</template>
|
||||
</overlay>
|
Loading…
Reference in New Issue
Block a user