- Move 12 markdown files from root to docs/ subdirectories - Organize documentation by category: • docs/troubleshooting/ (1 file) - Technical troubleshooting guides • docs/deployment/ (4 files) - Deployment and security documentation • docs/guides/ (3 files) - Feature-specific guides • docs/planning/ (4 files) - Planning and improvement proposals Root directory cleanup: - Reduced from 16 to 4 markdown files in root - Only essential project files remain: • CLAUDE.md (AI instructions) • README.md (Main project readme) • CLEANUP_PLAN.md (Current cleanup plan) • SRC_STRUCTURE_IMPROVEMENTS.md (Structure improvements) This improves: ✅ Documentation discoverability ✅ Logical organization by purpose ✅ Clean root directory ✅ Better maintainability
177 lines
5.0 KiB
PHP
177 lines
5.0 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Framework\DI\DefaultContainer;
|
|
use App\Framework\Meta\MetaData;
|
|
use App\Framework\View\DomWrapper;
|
|
use App\Framework\View\Processors\ForProcessor;
|
|
use App\Framework\View\Processors\PlaceholderReplacer;
|
|
use App\Framework\View\RenderContext;
|
|
|
|
beforeEach(function () {
|
|
$this->container = new DefaultContainer();
|
|
$this->container->singleton(
|
|
PlaceholderReplacer::class,
|
|
new PlaceholderReplacer($this->container)
|
|
);
|
|
$this->processor = new ForProcessor($this->container);
|
|
});
|
|
|
|
describe('ForProcessor', function () {
|
|
it('processes simple for loops with array data', function () {
|
|
$html = <<<HTML
|
|
<ul>
|
|
<for var="item" in="items">
|
|
<li>{{ item.name }}</li>
|
|
</for>
|
|
</ul>
|
|
HTML;
|
|
|
|
$context = new RenderContext(
|
|
template: 'test',
|
|
metaData: new MetaData('Test', 'Test'),
|
|
data: [
|
|
'items' => [
|
|
['name' => 'Item 1'],
|
|
['name' => 'Item 2'],
|
|
['name' => 'Item 3']
|
|
]
|
|
],
|
|
controllerClass: null
|
|
);
|
|
|
|
$dom = DomWrapper::fromString($html);
|
|
$result = $this->processor->process($dom, $context);
|
|
$output = $result->toHtml(true);
|
|
|
|
expect($output)->toContain('Item 1');
|
|
expect($output)->toContain('Item 2');
|
|
expect($output)->toContain('Item 3');
|
|
expect(str_contains($output, '<for'))->toBeFalse();
|
|
});
|
|
|
|
it('processes table rows in for loops', function () {
|
|
$html = <<<HTML
|
|
<table>
|
|
<tbody>
|
|
<for var="check" in="health_checks">
|
|
<tr>
|
|
<td>{{ check.componentName }}</td>
|
|
<td>{{ check.status }}</td>
|
|
</tr>
|
|
</for>
|
|
</tbody>
|
|
</table>
|
|
HTML;
|
|
|
|
$context = new RenderContext(
|
|
template: 'health',
|
|
metaData: new MetaData('Health', 'Health'),
|
|
data: [
|
|
'health_checks' => [
|
|
['componentName' => 'Database', 'status' => 'healthy'],
|
|
['componentName' => 'Cache', 'status' => 'healthy'],
|
|
['componentName' => 'Queue', 'status' => 'degraded']
|
|
]
|
|
],
|
|
controllerClass: null
|
|
);
|
|
|
|
$dom = DomWrapper::fromString($html);
|
|
$result = $this->processor->process($dom, $context);
|
|
$output = $result->toHtml(true);
|
|
|
|
expect($output)->toContain('Database');
|
|
expect($output)->toContain('Cache');
|
|
expect($output)->toContain('Queue');
|
|
expect($output)->toContain('healthy');
|
|
expect($output)->toContain('degraded');
|
|
expect(str_contains($output, '<for'))->toBeFalse();
|
|
});
|
|
|
|
it('handles empty arrays gracefully', function () {
|
|
$html = <<<HTML
|
|
<ul>
|
|
<for var="item" in="items">
|
|
<li>{{ item.name }}</li>
|
|
</for>
|
|
</ul>
|
|
HTML;
|
|
|
|
$context = new RenderContext(
|
|
template: 'test',
|
|
metaData: new MetaData('Test', 'Test'),
|
|
data: ['items' => []],
|
|
controllerClass: null
|
|
);
|
|
|
|
$dom = DomWrapper::fromString($html);
|
|
$result = $this->processor->process($dom, $context);
|
|
$output = $result->toHtml(true);
|
|
|
|
expect(str_contains($output, '<for'))->toBeFalse();
|
|
expect(str_contains($output, '{{ item.name }}'))->toBeFalse();
|
|
});
|
|
|
|
it('processes nested property paths', function () {
|
|
$html = <<<HTML
|
|
<div>
|
|
<for var="user" in="data.users">
|
|
<p>{{ user.profile.displayName }}</p>
|
|
</for>
|
|
</div>
|
|
HTML;
|
|
|
|
$context = new RenderContext(
|
|
template: 'test',
|
|
metaData: new MetaData('Test', 'Test'),
|
|
data: [
|
|
'data' => [
|
|
'users' => [
|
|
['profile' => ['displayName' => 'John Doe']],
|
|
['profile' => ['displayName' => 'Jane Smith']]
|
|
]
|
|
]
|
|
],
|
|
controllerClass: null
|
|
);
|
|
|
|
$dom = DomWrapper::fromString($html);
|
|
$result = $this->processor->process($dom, $context);
|
|
$output = $result->toHtml(true);
|
|
|
|
expect($output)->toContain('John Doe');
|
|
expect($output)->toContain('Jane Smith');
|
|
});
|
|
|
|
it('handles boolean values correctly', function () {
|
|
$html = <<<HTML
|
|
<div>
|
|
<for var="item" in="items">
|
|
<span>{{ item.active }}</span>
|
|
</for>
|
|
</div>
|
|
HTML;
|
|
|
|
$context = new RenderContext(
|
|
template: 'test',
|
|
metaData: new MetaData('Test', 'Test'),
|
|
data: [
|
|
'items' => [
|
|
['active' => true],
|
|
['active' => false]
|
|
]
|
|
],
|
|
controllerClass: null
|
|
);
|
|
|
|
$dom = DomWrapper::fromString($html);
|
|
$result = $this->processor->process($dom, $context);
|
|
$output = $result->toHtml(true);
|
|
|
|
expect($output)->toContain('true');
|
|
expect($output)->toContain('false');
|
|
});
|
|
});
|