From a129c71d79a4385b4873cffade3a80a47948cfc4 Mon Sep 17 00:00:00 2001 From: Benjamin Nussbaum Date: Wed, 27 Aug 2025 20:08:47 +0200 Subject: [PATCH 1/6] feat: trmnlp config add support for field_types: text, code, time --- .../views/livewire/plugins/recipe.blade.php | 44 +++++++++++++++++-- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/resources/views/livewire/plugins/recipe.blade.php b/resources/views/livewire/plugins/recipe.blade.php index 7a73358..9226af6 100644 --- a/resources/views/livewire/plugins/recipe.blade.php +++ b/resources/views/livewire/plugins/recipe.blade.php @@ -574,7 +574,7 @@ HTML; $fieldKey = $field['keyname'] ?? $field['key'] ?? $field['name']; $currentValue = $configuration[$fieldKey] ?? ''; @endphp -
+
@if($field['field_type'] === 'author_bio') @continue @endif @@ -587,14 +587,35 @@ HTML; + @elseif($field['field_type'] === 'text') + + @elseif($field['field_type'] === 'code') + @elseif($field['field_type'] === 'password') @@ -611,6 +633,7 @@ HTML; label="{{ $field['name'] }}" wire:model="configuration.{{ $fieldKey }}" description="{{ $field['description'] ?? '' }}" + descriptionTrailing="{{ $field['help_text'] ?? '' }}" > @foreach(timezone_identifiers_list() as $timezone) @@ -622,6 +645,7 @@ HTML; type="number" label="{{ $field['name'] }}" description="{{ $field['description'] ?? $field['name'] }}" + descriptionTrailing="{{ $field['help_text'] ?? '' }}" wire:model="configuration.{{ $fieldKey }}" value="{{ $currentValue }}" /> @@ -629,6 +653,7 @@ HTML; @@ -637,6 +662,16 @@ HTML; type="date" label="{{ $field['name'] }}" description="{{ $field['description'] ?? $field['name'] }}" + descriptionTrailing="{{ $field['help_text'] ?? '' }}" + wire:model="configuration.{{ $fieldKey }}" + value="{{ $currentValue }}" + /> + @elseif($field['field_type'] === 'time') + @@ -646,6 +681,7 @@ HTML; label="{{ $field['name'] }}" wire:model="configuration.{{ $fieldKey }}" description="{{ $field['description'] ?? '' }}" + descriptionTrailing="{{ $field['help_text'] ?? '' }}" > @if(isset($field['options']) && is_array($field['options'])) @foreach($field['options'] as $option) @@ -664,6 +700,7 @@ HTML; label="{{ $field['name'] }}" wire:model="configuration.{{ $fieldKey }}" description="{{ $field['description'] ?? '' }}" + descriptionTrailing="{{ $field['help_text'] ?? '' }}" > @if(isset($field['options']) && is_array($field['options'])) @@ -687,6 +724,7 @@ HTML; label="{{ $field['name'] }}" wire:model="configuration.{{ $fieldKey }}" description="{{ $field['description'] ?? '' }}" + descriptionTrailing="{{ $field['help_text'] ?? '' }}" wire:init="loadXhrSelectOptions('{{ $fieldKey }}', '{{ $field['endpoint'] }}')" > @@ -722,7 +760,7 @@ HTML; wire:click="searchXhrSelect('{{ $fieldKey }}', '{{ $field['endpoint'] }}')" icon="magnifying-glass"/> - + {{ $field['help_text'] ?? '' }} @if((isset($xhrSelectOptions[$fieldKey]) && is_array($xhrSelectOptions[$fieldKey]) && count($xhrSelectOptions[$fieldKey]) > 0) || !empty($currentValue)) @else -

{{ $field['name'] }}: Field type "{{ $field['field_type'] }}" not yet supported

+ Field type "{{ $field['field_type'] }}" not yet supported @endif
@endforeach From 2eee024b3654f394bbb537632dcc4bf5abbc751e Mon Sep 17 00:00:00 2001 From: Benjamin Nussbaum Date: Wed, 27 Aug 2025 20:38:28 +0200 Subject: [PATCH 2/6] chore: refactor PluginInlineTemplatesTest to Pest --- tests/Feature/PluginInlineTemplatesTest.php | 229 +++++++++----------- 1 file changed, 107 insertions(+), 122 deletions(-) diff --git a/tests/Feature/PluginInlineTemplatesTest.php b/tests/Feature/PluginInlineTemplatesTest.php index ce83d9d..fb35344 100644 --- a/tests/Feature/PluginInlineTemplatesTest.php +++ b/tests/Feature/PluginInlineTemplatesTest.php @@ -1,23 +1,15 @@ create([ - 'name' => 'Test Plugin', - 'markup_language' => 'liquid', - 'render_markup' => <<<'LIQUID' +test('renders plugin with inline templates', function () { + $plugin = Plugin::factory()->create([ + 'name' => 'Test Plugin', + 'markup_language' => 'liquid', + 'render_markup' => <<<'LIQUID' {% assign min = 1 %} {% assign max = facts | size %} {% assign diff = max | minus: min %} @@ -39,7 +31,6 @@ class PluginInlineTemplatesTest extends TestCase {% template title_bar %}
- {{ trmnl.plugin_settings.instance_name }} {{ instance }}
@@ -59,32 +50,31 @@ class PluginInlineTemplatesTest extends TestCase %}
LIQUID - , - 'data_payload' => [ - 'facts' => ['Fact 1', 'Fact 2', 'Fact 3'], - ], - ]); + , + 'data_payload' => [ + 'facts' => ['Fact 1', 'Fact 2', 'Fact 3'], + ], + ]); - $result = $plugin->render('full'); + $result = $plugin->render('full'); - // Should render both templates - // Check for any of the facts (since random number generation is non-deterministic) - $this->assertTrue( - str_contains($result, 'Fact 1') || - str_contains($result, 'Fact 2') || - str_contains($result, 'Fact 3') - ); - $this->assertStringContainsString('Test Plugin', $result); - $this->assertStringContainsString('Please try to enjoy each fact equally', $result); - $this->assertStringContainsString('class="view view--full"', $result); - } + // Should render both templates + // Check for any of the facts (since random number generation is non-deterministic) + $this->assertTrue( + str_contains($result, 'Fact 1') || + str_contains($result, 'Fact 2') || + str_contains($result, 'Fact 3') + ); + $this->assertStringContainsString('Test Plugin', $result); + $this->assertStringContainsString('Please try to enjoy each fact equally', $result); + $this->assertStringContainsString('class="view view--full"', $result); +}); - public function test_plugin_with_inline_templates_using_with_syntax(): void - { - $plugin = Plugin::factory()->create([ - 'name' => 'Test Plugin', - 'markup_language' => 'liquid', - 'render_markup' => <<<'LIQUID' +test('renders plugin with inline templates using with syntax', function () { + $plugin = Plugin::factory()->create([ + 'name' => 'Test Plugin', + 'markup_language' => 'liquid', + 'render_markup' => <<<'LIQUID' {% assign min = 1 %} {% assign max = facts | size %} {% assign diff = max | minus: min %} @@ -126,31 +116,30 @@ LIQUID %} LIQUID - , - 'data_payload' => [ - 'facts' => ['Fact 1', 'Fact 2', 'Fact 3'], - ], - ]); + , + 'data_payload' => [ + 'facts' => ['Fact 1', 'Fact 2', 'Fact 3'], + ], + ]); - $result = $plugin->render('full'); + $result = $plugin->render('full'); - // Should render both templates - // Check for any of the facts (since random number generation is non-deterministic) - $this->assertTrue( - str_contains($result, 'Fact 1') || - str_contains($result, 'Fact 2') || - str_contains($result, 'Fact 3') - ); - $this->assertStringContainsString('Test Plugin', $result); - $this->assertStringContainsString('Please try to enjoy each fact equally', $result); - $this->assertStringContainsString('class="view view--full"', $result); - } + // Should render both templates + // Check for any of the facts (since random number generation is non-deterministic) + $this->assertTrue( + str_contains($result, 'Fact 1') || + str_contains($result, 'Fact 2') || + str_contains($result, 'Fact 3') + ); + $this->assertStringContainsString('Test Plugin', $result); + $this->assertStringContainsString('Please try to enjoy each fact equally', $result); + $this->assertStringContainsString('class="view view--full"', $result); +}); - public function test_plugin_with_simple_inline_template(): void - { - $plugin = Plugin::factory()->create([ - 'markup_language' => 'liquid', - 'render_markup' => <<<'LIQUID' +test('renders plugin with simple inline template', function () { + $plugin = Plugin::factory()->create([ + 'markup_language' => 'liquid', + 'render_markup' => <<<'LIQUID' {% template simple %}

{{ title }}

@@ -163,21 +152,20 @@ LIQUID content: "This is a test" %} LIQUID - , - ]); + , + ]); - $result = $plugin->render('full'); + $result = $plugin->render('full'); - $this->assertStringContainsString('Hello World', $result); - $this->assertStringContainsString('This is a test', $result); - $this->assertStringContainsString('class="simple"', $result); - } + $this->assertStringContainsString('Hello World', $result); + $this->assertStringContainsString('This is a test', $result); + $this->assertStringContainsString('class="simple"', $result); +}); - public function test_plugin_with_find_by_filter(): void - { - $plugin = Plugin::factory()->create([ - 'markup_language' => 'liquid', - 'render_markup' => <<<'LIQUID' +test('renders plugin with liquid filter find_by', function () { + $plugin = Plugin::factory()->create([ + 'markup_language' => 'liquid', + 'render_markup' => <<<'LIQUID' {% template user_info %}

{{ user.name }}

@@ -188,68 +176,65 @@ LIQUID {% assign found_user = collection | find_by: 'name', 'Ryan' %} {% render "user_info", user: found_user %} LIQUID - , - 'data_payload' => [ - 'collection' => [ - ['name' => 'Ryan', 'age' => 35], - ['name' => 'Sara', 'age' => 29], - ['name' => 'Jimbob', 'age' => 29], - ], + , + 'data_payload' => [ + 'collection' => [ + ['name' => 'Ryan', 'age' => 35], + ['name' => 'Sara', 'age' => 29], + ['name' => 'Jimbob', 'age' => 29], ], - ]); + ], + ]); - $result = $plugin->render('full'); + $result = $plugin->render('full'); - // Should render the user info for Ryan - $this->assertStringContainsString('Ryan', $result); - $this->assertStringContainsString('Age: 35', $result); - $this->assertStringContainsString('class="user"', $result); - } + // Should render the user info for Ryan + $this->assertStringContainsString('Ryan', $result); + $this->assertStringContainsString('Age: 35', $result); + $this->assertStringContainsString('class="user"', $result); +}); - public function test_plugin_with_find_by_filter_and_fallback(): void - { - $plugin = Plugin::factory()->create([ - 'markup_language' => 'liquid', - 'render_markup' => <<<'LIQUID' +test('renders plugin with liquid filter find_by and fallback', function () { + $plugin = Plugin::factory()->create([ + 'markup_language' => 'liquid', + 'render_markup' => <<<'LIQUID' {{ collection | find_by: 'name', 'ronak', 'Not Found' }} LIQUID - , - 'data_payload' => [ - 'collection' => [ - ['name' => 'Ryan', 'age' => 35], - ['name' => 'Sara', 'age' => 29], - ['name' => 'Jimbob', 'age' => 29], - ], + , + 'data_payload' => [ + 'collection' => [ + ['name' => 'Ryan', 'age' => 35], + ['name' => 'Sara', 'age' => 29], + ['name' => 'Jimbob', 'age' => 29], ], - ]); + ], + ]); - $result = $plugin->render('full'); + $result = $plugin->render('full'); - // Should return the fallback value - $this->assertStringContainsString('Not Found', $result); - } + // Should return the fallback value + $this->assertStringContainsString('Not Found', $result); +}); - public function test_plugin_with_group_by_filter(): void - { - $plugin = Plugin::factory()->create([ - 'markup_language' => 'liquid', - 'render_markup' => <<<'LIQUID' +test('renders plugin with liquid filter group_by', function () { + $plugin = Plugin::factory()->create([ + 'markup_language' => 'liquid', + 'render_markup' => <<<'LIQUID' {{ collection | group_by: 'age' | json }} LIQUID - , - 'data_payload' => [ - 'collection' => [ - ['name' => 'Ryan', 'age' => 35], - ['name' => 'Sara', 'age' => 29], - ['name' => 'Jimbob', 'age' => 29], - ], + , + 'data_payload' => [ + 'collection' => [ + ['name' => 'Ryan', 'age' => 35], + ['name' => 'Sara', 'age' => 29], + ['name' => 'Jimbob', 'age' => 29], ], - ]); + ], + ]); - $result = $plugin->render('full'); + $result = $plugin->render('full'); - // Should output JSON representation of grouped data - $this->assertStringContainsString('"35":[{"name":"Ryan","age":35}]', $result); - $this->assertStringContainsString('"29":[{"name":"Sara","age":29},{"name":"Jimbob","age":29}]', $result); - } -} + // Should output JSON representation of grouped data + $this->assertStringContainsString('"35":[{"name":"Ryan","age":35}]', $result); + $this->assertStringContainsString('"29":[{"name":"Sara","age":29},{"name":"Jimbob","age":29}]', $result); +}); From f38ac778f1c91d3bfd8bda2b6213128e01b8f831 Mon Sep 17 00:00:00 2001 From: Benjamin Nussbaum Date: Wed, 27 Aug 2025 21:18:22 +0200 Subject: [PATCH 3/6] feat: add Liquid filters 'sample', 'days_ago' --- app/Liquid/Filters/Data.php | 15 ++++++++++ app/Liquid/Filters/Date.php | 25 ++++++++++++++++ app/Models/Plugin.php | 7 +++-- tests/Unit/Liquid/Filters/DataTest.php | 40 ++++++++++++++++++++++++++ tests/Unit/Liquid/Filters/DateTest.php | 32 +++++++++++++++++++++ 5 files changed, 117 insertions(+), 2 deletions(-) create mode 100644 app/Liquid/Filters/Date.php create mode 100644 tests/Unit/Liquid/Filters/DateTest.php diff --git a/app/Liquid/Filters/Data.php b/app/Liquid/Filters/Data.php index 4437032..bbf613b 100644 --- a/app/Liquid/Filters/Data.php +++ b/app/Liquid/Filters/Data.php @@ -63,4 +63,19 @@ class Data extends FiltersProvider return $grouped; } + + /** + * Return a random element from an array + * + * @param array $array The array to sample from + * @return mixed A random element from the array + */ + public function sample(array $array): mixed + { + if (empty($array)) { + return null; + } + + return $array[array_rand($array)]; + } } diff --git a/app/Liquid/Filters/Date.php b/app/Liquid/Filters/Date.php new file mode 100644 index 0000000..d8cc309 --- /dev/null +++ b/app/Liquid/Filters/Date.php @@ -0,0 +1,25 @@ +subDays($days)->toDateString(); + } +} diff --git a/app/Models/Plugin.php b/app/Models/Plugin.php index 72da730..0dceddf 100644 --- a/app/Models/Plugin.php +++ b/app/Models/Plugin.php @@ -4,6 +4,7 @@ namespace App\Models; use App\Liquid\FileSystems\InlineTemplatesFileSystem; use App\Liquid\Filters\Data; +use App\Liquid\Filters\Date; use App\Liquid\Filters\Localization; use App\Liquid\Filters\Numbers; use App\Liquid\Filters\StringMarkup; @@ -215,6 +216,7 @@ class Plugin extends Model { $replacements = [ 'date: "%N"' => 'date: "u"', + 'date: "%u"' => 'date: "u"', '%-m/%-d/%Y' => 'm/d/Y', ]; @@ -271,11 +273,12 @@ class Plugin extends Model ); // Register all custom filters - $environment->filterRegistry->register(Numbers::class); $environment->filterRegistry->register(Data::class); + $environment->filterRegistry->register(Date::class); + $environment->filterRegistry->register(Localization::class); + $environment->filterRegistry->register(Numbers::class); $environment->filterRegistry->register(StringMarkup::class); $environment->filterRegistry->register(Uniqueness::class); - $environment->filterRegistry->register(Localization::class); // Register the template tag for inline templates $environment->tagRegistry->register(TemplateTag::class); diff --git a/tests/Unit/Liquid/Filters/DataTest.php b/tests/Unit/Liquid/Filters/DataTest.php index 8145088..5937670 100644 --- a/tests/Unit/Liquid/Filters/DataTest.php +++ b/tests/Unit/Liquid/Filters/DataTest.php @@ -237,3 +237,43 @@ test('group_by filter handles mixed data types as keys', function () { '' => [['name' => 'Alice', 'active' => null]], // PHP converts null keys to empty string ]); }); + +test('sample filter returns a random element from array', function () { + $filter = new Data(); + $array = ['1', '2', '3', '4', '5']; + + $result = $filter->sample($array); + expect($result)->toBeIn($array); +}); + +test('sample filter returns a random element from string array', function () { + $filter = new Data(); + $array = ['cat', 'dog']; + + $result = $filter->sample($array); + expect($result)->toBeIn($array); +}); + +test('sample filter returns null for empty array', function () { + $filter = new Data(); + $array = []; + + $result = $filter->sample($array); + expect($result)->toBeNull(); +}); + +test('sample filter returns the only element from single element array', function () { + $filter = new Data(); + $array = ['single']; + + $result = $filter->sample($array); + expect($result)->toBe('single'); +}); + +test('sample filter works with mixed data types', function () { + $filter = new Data(); + $array = [1, 'string', true, null, ['nested']]; + + $result = $filter->sample($array); + expect($result)->toBeIn($array); +}); diff --git a/tests/Unit/Liquid/Filters/DateTest.php b/tests/Unit/Liquid/Filters/DateTest.php new file mode 100644 index 0000000..5813e10 --- /dev/null +++ b/tests/Unit/Liquid/Filters/DateTest.php @@ -0,0 +1,32 @@ +subDays(3)->toDateString(); + + expect($filter->days_ago(3))->toBe($threeDaysAgo); +}); + +test('days_ago filter handles string input', function () { + $filter = new Date(); + $fiveDaysAgo = Carbon::now()->subDays(5)->toDateString(); + + expect($filter->days_ago('5'))->toBe($fiveDaysAgo); +}); + +test('days_ago filter with zero days returns today', function () { + $filter = new Date(); + $today = Carbon::now()->toDateString(); + + expect($filter->days_ago(0))->toBe($today); +}); + +test('days_ago filter with large number works correctly', function () { + $filter = new Date(); + $hundredDaysAgo = Carbon::now()->subDays(100)->toDateString(); + + expect($filter->days_ago(100))->toBe($hundredDaysAgo); +}); From 9d1f62c6ddc801b81f3ac72e4a201c288295ac57 Mon Sep 17 00:00:00 2001 From: Benjamin Nussbaum Date: Wed, 27 Aug 2025 21:31:21 +0200 Subject: [PATCH 4/6] feat: add Liquid filters 'parse_json' --- app/Liquid/Filters/Data.php | 11 ++++++ tests/Unit/Liquid/Filters/DataTest.php | 48 ++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/app/Liquid/Filters/Data.php b/app/Liquid/Filters/Data.php index bbf613b..2bbb5a9 100644 --- a/app/Liquid/Filters/Data.php +++ b/app/Liquid/Filters/Data.php @@ -78,4 +78,15 @@ class Data extends FiltersProvider return $array[array_rand($array)]; } + + /** + * Parse a JSON string into a PHP value + * + * @param string $json The JSON string to parse + * @return mixed The parsed JSON value + */ + public function parse_json(string $json): mixed + { + return json_decode($json, true); + } } diff --git a/tests/Unit/Liquid/Filters/DataTest.php b/tests/Unit/Liquid/Filters/DataTest.php index 5937670..1e56b91 100644 --- a/tests/Unit/Liquid/Filters/DataTest.php +++ b/tests/Unit/Liquid/Filters/DataTest.php @@ -277,3 +277,51 @@ test('sample filter works with mixed data types', function () { $result = $filter->sample($array); expect($result)->toBeIn($array); }); + +test('parse_json filter parses JSON string to array', function () { + $filter = new Data(); + $jsonString = '[{"a":1,"b":"c"},"d"]'; + + $result = $filter->parse_json($jsonString); + expect($result)->toBe([['a' => 1, 'b' => 'c'], 'd']); +}); + +test('parse_json filter parses simple JSON object', function () { + $filter = new Data(); + $jsonString = '{"name":"John","age":30,"city":"New York"}'; + + $result = $filter->parse_json($jsonString); + expect($result)->toBe(['name' => 'John', 'age' => 30, 'city' => 'New York']); +}); + +test('parse_json filter parses JSON array', function () { + $filter = new Data(); + $jsonString = '["apple","banana","cherry"]'; + + $result = $filter->parse_json($jsonString); + expect($result)->toBe(['apple', 'banana', 'cherry']); +}); + +test('parse_json filter parses nested JSON structure', function () { + $filter = new Data(); + $jsonString = '{"users":[{"id":1,"name":"Alice"},{"id":2,"name":"Bob"}],"total":2}'; + + $result = $filter->parse_json($jsonString); + expect($result)->toBe([ + 'users' => [ + ['id' => 1, 'name' => 'Alice'], + ['id' => 2, 'name' => 'Bob'] + ], + 'total' => 2 + ]); +}); + +test('parse_json filter handles primitive values', function () { + $filter = new Data(); + + expect($filter->parse_json('"hello"'))->toBe('hello'); + expect($filter->parse_json('123'))->toBe(123); + expect($filter->parse_json('true'))->toBe(true); + expect($filter->parse_json('false'))->toBe(false); + expect($filter->parse_json('null'))->toBe(null); +}); From 14d0fbfa7eb2a1a02c4d5ef4405d501c133412e4 Mon Sep 17 00:00:00 2001 From: Benjamin Nussbaum Date: Wed, 27 Aug 2025 22:14:34 +0200 Subject: [PATCH 5/6] feat(test): test_quotes_template_with_modulo_filter --- app/Liquid/Filters/Date.php | 2 +- tests/Unit/Liquid/Filters/DataTest.php | 4 +- tests/Unit/Liquid/InlineTemplatesTest.php | 45 ++++++++++++++++++++++- 3 files changed, 47 insertions(+), 4 deletions(-) diff --git a/app/Liquid/Filters/Date.php b/app/Liquid/Filters/Date.php index d8cc309..2f730ac 100644 --- a/app/Liquid/Filters/Date.php +++ b/app/Liquid/Filters/Date.php @@ -2,8 +2,8 @@ namespace App\Liquid\Filters; -use Keepsuit\Liquid\Filters\FiltersProvider; use Carbon\Carbon; +use Keepsuit\Liquid\Filters\FiltersProvider; /** * Data filters for Liquid templates diff --git a/tests/Unit/Liquid/Filters/DataTest.php b/tests/Unit/Liquid/Filters/DataTest.php index 1e56b91..bdf649f 100644 --- a/tests/Unit/Liquid/Filters/DataTest.php +++ b/tests/Unit/Liquid/Filters/DataTest.php @@ -310,9 +310,9 @@ test('parse_json filter parses nested JSON structure', function () { expect($result)->toBe([ 'users' => [ ['id' => 1, 'name' => 'Alice'], - ['id' => 2, 'name' => 'Bob'] + ['id' => 2, 'name' => 'Bob'], ], - 'total' => 2 + 'total' => 2, ]); }); diff --git a/tests/Unit/Liquid/InlineTemplatesTest.php b/tests/Unit/Liquid/InlineTemplatesTest.php index bf68ddf..172dc1e 100644 --- a/tests/Unit/Liquid/InlineTemplatesTest.php +++ b/tests/Unit/Liquid/InlineTemplatesTest.php @@ -6,9 +6,15 @@ namespace Tests\Unit\Liquid; use App\Liquid\FileSystems\InlineTemplatesFileSystem; use App\Liquid\Filters\Data; +use App\Liquid\Filters\Date; +use App\Liquid\Filters\Localization; +use App\Liquid\Filters\Numbers; +use App\Liquid\Filters\StringMarkup; +use App\Liquid\Filters\Uniqueness; use App\Liquid\Tags\TemplateTag; use Keepsuit\Liquid\Environment; use Keepsuit\Liquid\Exceptions\LiquidException; +use Keepsuit\Liquid\Extensions\StandardExtension; use Keepsuit\Liquid\Tags\RenderTag; use PHPUnit\Framework\TestCase; @@ -24,11 +30,17 @@ class InlineTemplatesTest extends TestCase $this->fileSystem = new InlineTemplatesFileSystem(); $this->environment = new Environment( - fileSystem: $this->fileSystem + fileSystem: $this->fileSystem, + extensions: [new StandardExtension()] ); $this->environment->tagRegistry->register(TemplateTag::class); $this->environment->tagRegistry->register(RenderTag::class); $this->environment->filterRegistry->register(Data::class); + $this->environment->filterRegistry->register(Date::class); + $this->environment->filterRegistry->register(Localization::class); + $this->environment->filterRegistry->register(Numbers::class); + $this->environment->filterRegistry->register(StringMarkup::class); + $this->environment->filterRegistry->register(Uniqueness::class); } public function test_template_tag_registers_template(): void @@ -296,4 +308,35 @@ LIQUID // Should not throw an error and should return empty string $this->assertEquals('', $result); } + + public function test_quotes_template_with_modulo_filter(): void + { + $template = $this->environment->parseString(<<<'LIQUID' +{% assign quotes_array = quotes[trmnl.plugin_settings.custom_fields_values.language] %} +{% assign random_index = 'now' | date: '%s' | modulo: quotes_array.size %} +{{ quotes_array[random_index] }} +LIQUID + ); + + $context = $this->environment->newRenderContext( + data: [ + 'quotes' => [ + 'english' => ['Demo Quote'], + 'german' => ['Demo Zitat'] + ], + 'trmnl' => [ + 'plugin_settings' => [ + 'custom_fields_values' => [ + 'language' => 'english' + ] + ] + ] + ] + ); + + $result = $template->render($context); + // Should render a quote from the english array + $this->assertStringContainsString('Demo Quote', $result); + $this->assertStringNotContainsString('Demo Zitat', $result); + } } From f777e850b19fc8860df494f438b3ff032008a136 Mon Sep 17 00:00:00 2001 From: Benjamin Nussbaum Date: Wed, 27 Aug 2025 23:03:07 +0200 Subject: [PATCH 6/6] chore: pint --- tests/Unit/Liquid/InlineTemplatesTest.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/Unit/Liquid/InlineTemplatesTest.php b/tests/Unit/Liquid/InlineTemplatesTest.php index 172dc1e..e3685b8 100644 --- a/tests/Unit/Liquid/InlineTemplatesTest.php +++ b/tests/Unit/Liquid/InlineTemplatesTest.php @@ -322,15 +322,15 @@ LIQUID data: [ 'quotes' => [ 'english' => ['Demo Quote'], - 'german' => ['Demo Zitat'] + 'german' => ['Demo Zitat'], ], 'trmnl' => [ 'plugin_settings' => [ 'custom_fields_values' => [ - 'language' => 'english' - ] - ] - ] + 'language' => 'english', + ], + ], + ], ] );