Files
michaelschiemer/tests/Unit/Framework/Template/Expression/ExpressionEvaluatorTest.php
2025-11-24 21:28:25 +01:00

195 lines
5.9 KiB
PHP

<?php
declare(strict_types=1);
namespace Tests\Unit\Framework\Template\Expression;
use App\Framework\Template\Expression\ExpressionEvaluator;
describe('ExpressionEvaluator', function () {
beforeEach(function () {
$this->evaluator = new ExpressionEvaluator();
});
describe('nested array access', function () {
it('supports single level array access', function () {
$context = [
'item' => ['name' => 'Test'],
];
$result = $this->evaluator->evaluate("item['name']", $context);
expect($result)->toBe('Test');
});
it('supports nested array access', function () {
$context = [
'item' => [
'user' => [
'name' => 'John',
'email' => 'john@example.com',
],
],
];
$result = $this->evaluator->evaluate("item['user']['name']", $context);
expect($result)->toBe('John');
});
it('supports nested array access with $ prefix', function () {
$context = [
'item' => [
'user' => [
'name' => 'John',
],
],
];
$result = $this->evaluator->evaluate("\$item['user']['name']", $context);
expect($result)->toBe('John');
});
it('returns null for missing nested keys', function () {
$context = [
'item' => ['name' => 'Test'],
];
$result = $this->evaluator->evaluate("item['user']['name']", $context);
expect($result)->toBeNull();
});
it('supports numeric indices in nested arrays', function () {
$context = [
'items' => [
[0 => ['name' => 'First']],
[0 => ['name' => 'Second']],
],
];
$result = $this->evaluator->evaluate("items[0][0]['name']", $context);
expect($result)->toBe('First');
});
});
describe('fallback mechanism', function () {
it('supports null coalescing operator', function () {
$context = [
'name' => null,
];
// Note: This is handled by ForTransformer/PlaceholderTransformer, not ExpressionEvaluator
// ExpressionEvaluator just evaluates the expression
$result = $this->evaluator->evaluate("name", $context);
expect($result)->toBeNull();
});
});
describe('error handling', function () {
it('returns null for missing variables', function () {
$context = [];
$result = $this->evaluator->evaluate('missingVar', $context);
expect($result)->toBeNull();
});
it('returns null for missing array keys', function () {
$context = [
'item' => ['name' => 'Test'],
];
$result = $this->evaluator->evaluate("item['missing']", $context);
expect($result)->toBeNull();
});
it('handles invalid expressions gracefully', function () {
$context = [];
$result = $this->evaluator->evaluate('invalid[expression', $context);
expect($result)->toBeNull();
});
});
describe('dot notation', function () {
it('supports dot notation for nested properties', function () {
$context = [
'user' => [
'profile' => [
'name' => 'John',
],
],
];
$result = $this->evaluator->evaluate('user.profile.name', $context);
expect($result)->toBe('John');
});
it('supports dot notation with numeric indices', function () {
$context = [
'items' => [
['name' => 'First'],
['name' => 'Second'],
],
];
$result = $this->evaluator->evaluate('items.0.name', $context);
expect($result)->toBe('First');
});
it('supports dot notation with $ prefix for arrays', function () {
$context = [
'option' => [
'id' => 'landing_page',
'name' => 'Landing Page',
],
];
$result = $this->evaluator->evaluate('$option.id', $context);
expect($result)->toBe('landing_page');
});
it('supports dot notation with $ prefix for nested arrays', function () {
$context = [
'option' => [
'user' => [
'name' => 'John',
],
],
];
$result = $this->evaluator->evaluate('$option.user.name', $context);
expect($result)->toBe('John');
});
it('supports both array notation and dot notation', function () {
$context = [
'option' => [
'id' => 'test',
'name' => 'Test',
],
];
$arrayResult = $this->evaluator->evaluate("option['id']", $context);
$dotResult = $this->evaluator->evaluate('option.id', $context);
$dollarDotResult = $this->evaluator->evaluate('$option.id', $context);
expect($arrayResult)->toBe('test');
expect($dotResult)->toBe('test');
expect($dollarDotResult)->toBe('test');
});
});
});