FullCompiler.php
<?php
namespace Phad\Test\Compilation;
/**
* Tests to verify compiler output
*
* Tests I may need to add in the future:
* - multiple <p-data> nodes
* - multiple <on> nodes
* - <on> nodes nested inside <p-data> nodes
* - item nodes nested inside other item nodes
* - item nodes adjacent to other item nodes
* - multiple routes
* - general flow of logic (probably won't ever go in THIS one though)
*
*/
class FullCompiler extends \Phad\Tester {
/** the template file contents */
protected $template;
public function prepare(){
$this->template = file_get_contents($this->file('code/template/main.php'));
}
public function testBackendInputNodesRemoved(){
$this->test('with indent');
$view = <<<HTML
<form item="Blog">
<onsubmit><?php
\$BlogRow['slug'] = str_replace(' ', '-', strtolower(\$BlogRow['title']));
/** set phad_block to null to skip submission */
if (false)\$BlogItem->phad_mode = null;
?></onsubmit>
<input type="text" name="title" maxlength="75">
<textarea name="body" maxlength="2000" minlength="50"></textarea>
<input type="backend" name="slug" minlength=4 maxlength=150 />
</form>
HTML;
$compiler = new \Phad\TemplateCompiler();
$output = $compiler->compile($view, $this->template);
echo $output;
$this->str_not_contains($output, 'type="backend"');
}
public function testRouteNodeRemoved(){
$this->test('with indent');
//this one passes, bc there is whitespace, therefore a textnode before the <route> node
//so i run this test again, without the indent
$view = <<<VIEW
<route pattern="/route/no-items/"></route>
<route pattern="/route/still-no-items/"></route>
<div>
<h1>No Items</h1>
</div>
VIEW;
$compiler = new \Phad\TemplateCompiler();
$output = $compiler->compile($view, $this->template);
echo $output;
$this->str_not_contains($output,'<route','</route>');
$this->test("no indent");
$view = <<<VIEW
<route pattern="/route/no-items/"></route>
<route pattern="/route/still-no-items/"></route>
<div>
<h1>No Items</h1>
</div>
VIEW;
$compiler = new \Phad\TemplateCompiler();
$output = $compiler->compile($view, $this->template);
echo $output;
$this->str_not_contains($output,'<route','</route>');
}
public function testIncludesOnSubmitWhenThereIsANestedItem(){
$verify = '/*verify onsubmit presence*/';
$form = <<<FORM
<form item="Blog" target="/blog/{title}/">
<onsubmit><?php $verify ?></onsubmit>
<input type="text" name="title" maxlength="75">
<div item="Candy"><?=\$Candy->id</div>
</form>
FORM;
$compiler = new \Phad\TemplateCompiler($form);
$output = $compiler->compile($form,$this->template);
echo $output;
$this->str_contains($output, $verify);
$this->str_not_contains($output, '<onsubmit><?php');
}
public function testCanReadNode(){
$code = <<<HTML
<a href="/whatever/" access="role:guest">Am Link</a>
HTML;
$output = <<<HTML
<?php if (\$phad->can_read_node(array (
'href' => '/whatever/',
'access' => 'role:guest',
'tagName' => 'a',
))): ?>
<a href="/whatever/">Am Link</a>
<?php endif; ?>
HTML;
$compiler = new \Phad\TemplateCompiler($code);
$compiled = $compiler->compile($code,$this->template);
echo $compiled;
$this->str_contains($compiled,array_map('trim', explode("\n", $output)));
// $this->str_
}
public function testAddFormNodeInfoWithFileInput(){
$form = <<<FORM
<form item="Blog" target="/blog/{title}/">
<input type="text" name="title" maxlength="75">
<textarea name="body" maxlength="2000" minlength="50"></textarea>
<input type="file" name="document" />
</form>
FORM;
$expect = '<form enctype="multipart/form-data" action="" method="POST">';
$compiler = new \Phad\TemplateCompiler($form);
$output = $compiler->compile($form,$this->template);
echo $output;
// $this-
$this->str_contains($output, $expect, '<input type="file" name="document">');
}
/**
* @test setting action on a form
* @test setting method on a form
* @test removing `candelete` attribute from form nodes
*/
public function testAddFormNodeInfo(){
$form = <<<FORM
<form item="Blog" target="/blog/{title}/" candelete="whatever">
<input type="text" name="title" maxlength="75">
<textarea name="body" maxlength="2000" minlength="50"></textarea>
</form>
FORM;
$expect = '<form action="" method="POST">';
$compiler = new \Phad\TemplateCompiler($form);
$output = $compiler->compile($form,$this->template);
echo $output;
// $this-
$this->str_contains($output, $expect);
}
/**
* @test that code in <on s=404> is present in output
*/
public function testOnS404(){
//@note dec-6-2022 test failing bc $expect needs to be changed
$view = <<<VIEW
<div item="Blog">
<on s=404><p>Type: <span prop="type"></span></p></on>
<h1 prop="title"></h1>
<p prop="description"></p>
</div>
VIEW;
$expect = <<<'EXPECT'
if ($_node['response_code'] == 404){
if ($_index === 0):
?><p>Type: <span><?=$Blog->type?></span></p><?php
endif;
}
EXPECT;
$compiler = new \Phad\TemplateCompiler($view);
$output = $compiler->compile($view,$this->template);
// echo $output;
// $this-
$this->str_contains_lines($output, $expect);
}
/**
* @test that code in <on s=200> is present in output
* @test that inside on <on>, a prop node's inner html (in the compiled output) will print $Item->prop_name
*/
public function testOnS200(){
$view = <<<VIEW
<div item="Blog">
<on s=200><p>Type: <span prop="type"></span></p></on>
<h1 prop="title"></h1>
<p prop="description"></p>
</div>
VIEW;
$expect = <<<EXPECT
if (\$BlogInfo->data_index === 0 ):
?><p>Type: <span><?=\$Blog->type?></span></p><?php
endif;
EXPECT;
$compiler = new \Phad\TemplateCompiler($view);
$output = $compiler->compile($view,$this->template);
echo $output;
$this->str_contains($output, $expect);
}
/**
*
* @test that an `<p-data>` node is printed to `$BlogItem->accessList[] = (array of access node info)` in compiled output
*/
public function testAccess(){
$view = <<<VIEW
<div item="Blog">
<p-data access="role:guest" handler="tlf:check_throttles" name="type" where="Blog.type LIKE :type" limit="0,2"></p-data>
<h1 prop="title"></h1>
<p prop="description"></p>
</div>
VIEW;
$expect = <<<EXPECT
'data_nodes' => array (
0 =>
array (
'access' => 'role:guest',
'handler' => 'tlf:check_throttles',
'name' => 'type',
'where' => 'Blog.type LIKE :type',
'limit' => '0,2',
'type' => 'node',
),
1 =>
array (
'type' => 'default',
),
),
EXPECT;
$compiler = new \Phad\TemplateCompiler($view);
$output = $compiler->compile($view,$this->template);
echo $output;
$this->str_contains($output, $expect);
}
/**
* @test that <form>'s <onsubmit> node contents are included in the compiled output
*/
public function testFormOnSubmit(){
$view = <<<VIEW
<form item="Baby">
<onsubmit><?php \$Baby->title = "cats";?> ...dogs...</onsubmit>
<h1 class="title" prop="title">Am Title</h1>
</form>
VIEW;
$compiler = new \Phad\TemplateCompiler($view);
$output = $compiler->compile($view,$this->template);
// echo $output;
// exit;
$this->str_contains($output,
[
'<?php $Baby->title = "cats";?> ...dogs...',
'foreach ($BabyInfo->rows as $RowIndex_Baby => $BabyRow ):',
]
);
}
/**
* @test that form property info is extracted from prop-nodes & included in compiled output
*/
public function testFormProperties(){
$view = <<<VIEW
<form item="Blog" target="/blog/{title}/">
<input type="text" name="title" maxlength="75">
<textarea name="body" maxlength="2000" minlength="50"></textarea>
</form>
VIEW;
$properties =
[
'title' =>
[
'type' => 'text',
'maxlength' => '75',
'tagName' => 'input',
],
'body' =>
[
'maxlength' => '2000',
'minlength' => '50',
'tagName' => 'textarea',
],
'id' =>
[
'tagName' => 'input',
'type' => 'hidden',
],
];
$compiler = new \Phad\TemplateCompiler($view);
$output = $compiler->compile($view,$this->template);
// echo $output;
// remove all space-characters from both strings (compiled properties output is indented)
$output = str_replace(' ', '', $output);
$properties = var_export($properties,true);
$properties = str_replace(' ', '', $properties);
$this->str_contains($output, $properties);
}
/**
* @test that target in `<form target="TARGET">` is included in the compiled output
*/
public function testFormTarget(){
$view = <<<VIEW
<form item="Baby" target="/baby/{name}/">
<onsubmit><?php \$Baby->title = "cats";?> ...dogs...</onsubmit>
<h1 class="title" prop="title">Am Title</h1>
</form>
VIEW;
$compiler = new \Phad\TemplateCompiler($view);
$output = $compiler->compile($view,$this->template);
// echo $output;
// exit;
$this->str_contains($output,
[
"'target' => '/baby/{name}/'",
'<?php $Baby->title = "cats";?> ...dogs...',
'foreach ($BabyInfo->rows as $RowIndex_Baby => $BabyRow ):',
]
);
}
/**
* @test that <x-item> nodes are removed AND the foreach item loop is still created
*/
public function testXItem(){
$view = <<<VIEW
<h1>K</h1>
<x-item class="class_gets_removed" item="Baby">
<h1 class="title" prop="title">Am Title</h1>
<p prop="description">Am some description</p>
</x-item>
VIEW;
$compiler = new \Phad\TemplateCompiler($view);
$output = $compiler->compile($view,$this->template);
// echo $output;
$this->str_contains($output,
[
'foreach ($BabyInfo->rows as $RowIndex_Baby => $BabyRow ):',
'<h1 class="title"><?=$Baby->title?></h1>',
'endforeach;',
'<h1>K</h1>'
]
);
$this->str_not_contains($output,
['class_gets_removed',
'x-item',
]
);
}
/**
* @test that sitemap information is present in the compiled output
*/
public function testSitemap(){
$view = <<<VIEW
<route pattern="/blog/{slug}/">
<sitemap
sql="SELECT slug FROM blog"
handler="testns:blogSitemapHandler"
priority=0.8
last_mod=1354
changefreq=daily
>
</sitemap>
</route>
VIEW;
$compiler = new \Phad\TemplateCompiler($view);
$output = $compiler->compile($view,$this->template);
$output = $output;
echo "\n\n\n$output\n\n\n";
$this->str_contains($output,
[
'Route'=>
var_export([0=>['pattern'=>'/blog/{slug}/']],true),
'Sitemap'=>
var_export(
['/blog/{slug}/'=>
[
'sql'=> 'SELECT slug FROM blog',
'handler'=> 'testns:blogSitemapHandler',
'priority'=>'0.8',
'last_mod'=>'1354',
'changefreq'=>'daily',
'pattern'=>'/blog/{slug}/'
]
]
,true
),
]
);
}
/**
* @bug $output['routes'] is empty, but the routes DO get added to the compiled output
* @test that route information is present in compiled file
*/
public function testSimpleRoute(){
$view = <<<VIEW
<route pattern="/some-page/"></route>
<div class="Parent">
<h1 class="title">Am Title</h1>
<p>Am some description</p>
</div>
VIEW;
$compiler = new \Phad\TemplateCompiler($view);
$output = $compiler->compile($view,$this->template);
echo $output;
$this->str_contains($output,
[
var_export([0=>['pattern'=>'/some-page/']],true),
]
);
}
/**
* @test that compiler creates a foreach(): loop for items & property printers in property nodes
* @todo create 'empty-object' array from prop values listed in the html, like 'Am Title' below, so the view can be displayed with the default/placeholder content
*/
public function testItemCanReadRow(){
//can_read_row() was removed from compiled view output and is now being called during read_data(), making this test obsolete, as it only checks for compiled output & does not test can_read_row() functionality itself.
$this->disable();
return;
$view = <<<VIEW
<div class="Parent" item="Baby" can_read_row>
<h1 class="title" prop="title">Am Title</h1>
<p prop="description">Am some description</p>
</div>
VIEW;
$compiler = new \Phad\TemplateCompiler();
$output = $compiler->compile($view, $this->template);
echo $output;
$this->str_contains($output,
[
// 'if (!$phad->can_read_row($BabyRow, $BabyInfo, $BabyInfo->name)){',
]
);
$this->str_not_contains($output, 'can_read_row>');
}
/**
* @test that compiler creates a foreach(): loop for items & property printers in property nodes
* @todo create 'empty-object' array from prop values listed in the html, like 'Am Title' below, so the view can be displayed with the default/placeholder content
*/
public function testItem(){
$view = <<<VIEW
<div class="Parent" item="Baby">
<h1 class="title" prop="title">Am Title</h1>
<p prop="description">Am some description</p>
</div>
VIEW;
$compiler = new \Phad\TemplateCompiler();
$output = $compiler->compile($view, $this->template);
echo $output;
$this->str_contains($output,
[
'foreach ($BabyInfo->rows as $RowIndex_Baby => $BabyRow ):',
'<h1 class="title"><?=$Baby->title?></h1>',
'endforeach;',
]
);
$this->str_not_contains($output,
[
'if (!$phad->can_read_row($BabyRow, $BabyInfo, $Baby)){',
]
);
}
/**
* @test that compiler has any output
*/
public function testOutput(){
$view = <<<VIEW
<div class="Parent">
<h1 class="title">Am Title</h1>
<p>Am some description</p>
</div>
VIEW;
$compiler = new \Phad\TemplateCompiler();
$output = $compiler->compile($view, $this->template);
echo $output;
$this->str_contains($output, 'class="Parent"');
$this->str_contains($output, 'class="title"');
$this->str_contains($output,'<p>Am');
}
}