{{ $title }}
@@ -52,135 +258,147 @@
);
});
-test('preserves dynamic attributes with static false', function () {
- $input = '
';
+test('does not synthesize a default slot when one is explicit', function () {
+ $input = <<<'BLADE'
+
+ Ignored loose content
+ Explicit content
+
+ BLADE;
$node = app(Parser::class)->parse($input)[0];
- $foldable = new Foldable($node, new ComponentSource(fixture_path('views/components/foldable/input.blade.php')), app(BladeRenderer::class), app(BladeService::class));
- expect($foldable->fold())->toEqualCollapsingWhitespace(
- '
'
- );
-});
+ mock(BladeRenderer::class)
+ ->expects('render')
+ ->once()->withArgs(function (ComponentNode $node) {
+ expect($node->render())->toBe('
BLAZE_PLACEHOLDER_0_');
-test('preserves dynamic attributes with static null', function () {
- $input = '
';
+ return true;
+ })
+ ->andReturn('
BLAZE_PLACEHOLDER_0_
');
- $node = app(Parser::class)->parse($input)[0];
- $foldable = new Foldable($node, new ComponentSource(fixture_path('views/components/foldable/input.blade.php')), app(BladeRenderer::class), app(BladeService::class));
+ $output = (new Foldable($node, '', app(BladeRenderer::class), app(BladeService::class)))->fold();
- expect($foldable->fold())->toEqualCollapsingWhitespace(
- '
'
- );
+ expect($output)->toBe('
Explicit content
');
});
-test('merges aware props from parent attributes', function () {
- $input = '
';
+test('handles newlines consumed by slot php blocks', function () {
+ $node = app(Parser::class)->parse('
Content')[0];
- $node = app(Parser::class)->parse($input)[0];
- $foldable = new Foldable($node, new ComponentSource(fixture_path('views/components/foldable/input-aware.blade.php')), app(BladeRenderer::class), app(BladeService::class));
-
- $node->setParentsAttributes([
- 'type' => new Attribute(
- name: 'type',
- value: 'number',
- propName: 'type',
- dynamic: false
- ),
- ]);
-
- expect($foldable->fold())->toEqualCollapsingWhitespace(
- '
'
- );
-});
-
-test('merges dynamic aware props from parent attributes', function () {
- $input = '
';
+ mock(BladeRenderer::class)
+ ->expects('render')
+ ->once()->withArgs(function (ComponentNode $node) {
+ expect($node->render())->toBe('
BLAZE_PLACEHOLDER_0_');
- $node = app(Parser::class)->parse($input)[0];
- $node->setParentsAttributes([
- 'type' => new Attribute(
- name: 'type',
- value: '$type',
- propName: 'type',
- dynamic: true,
- prefix: ':',
- quotes: '"',
- ),
- ]);
-
- $foldable = new Foldable($node, new ComponentSource(fixture_path('views/components/foldable/input-aware.blade.php')), app(BladeRenderer::class), app(BladeService::class));
-
- expect($foldable->fold())->toEqualCollapsingWhitespace(
- '
'
- );
-});
+ return true;
+ })
+ ->andReturn("
BLAZE_PLACEHOLDER_0_\n
");
-test('folds dynamic attributes passed through attribute bag', function () {
- $input = '
';
+ $output = (new Foldable($node, '', app(BladeRenderer::class), app(BladeService::class)))->fold();
- $node = app(Parser::class)->parse($input)[0];
- $foldable = new Foldable($node, new ComponentSource(fixture_path('views/components/foldable/input.blade.php')), app(BladeRenderer::class), app(BladeService::class));
-
- expect($foldable->fold())->toEqualCollapsingWhitespace(
- sprintf('
', join('', [
- '',
- 'readonly=""',
- '',
- ]))
- );
-});
-
-test('folds dynamic attributes reused under a different key', function () {
- $input = '
';
- $node = app(Parser::class)->parse($input)[0];
- $foldable = new Foldable($node, new ComponentSource(fixture_path('views/components/foldable/button.blade.php')), app(BladeRenderer::class), app(BladeService::class));
- expect($foldable->fold())->toEqualCollapsingWhitespace(
- '
'
- );
+ expect($output)->toBe("
Content\n\n
");
});
test('wraps output with aware macros if descendants use aware', function () {
- $input = '
';
+ $node = app(Parser::class)->parse('
')[0];
- $node = app(Parser::class)->parse($input)[0];
$node->hasAwareDescendants = true;
- $foldable = new Foldable($node, new ComponentSource(fixture_path('views/components/foldable/wrapper.blade.php')), app(BladeRenderer::class), app(BladeService::class));
+ mock(BladeRenderer::class)
+ ->expects('render')
+ ->once()->withArgs(function (ComponentNode $node) {
+ expect($node->render())->toBe('
');
+
+ return true;
+ })
+ ->andReturn('
');
+
+ $output = (new Foldable($node, '', app(BladeRenderer::class), app(BladeService::class)))->fold();
- expect($foldable->fold())->toEqualCollapsingWhitespace(join('', [
- 'pushData([\'name\' => \'John\']); $__env->pushConsumableComponentData([\'name\' => \'John\']); ?>',
- '
',
+ expect($output)->toEqualCollapsingWhitespace(join('', [
+ 'pushData([\'theme\' => \'dark\']); $__env->pushConsumableComponentData([\'theme\' => \'dark\']); ?>',
+ '
',
'popData(); $__env->popConsumableComponentData(); ?>',
]));
});
test('compiles dynamic attributes in aware macros', function () {
- $input = '
';
+ $node = app(Parser::class)->parse('
')[0];
- $node = app(Parser::class)->parse($input)[0];
$node->hasAwareDescendants = true;
- $foldable = new Foldable($node, new ComponentSource(fixture_path('views/components/foldable/wrapper.blade.php')), app(BladeRenderer::class), app(BladeService::class));
+ mock(BladeRenderer::class)
+ ->expects('render')
+ ->once()->withArgs(function (ComponentNode $node) {
+ expect($node->render())->toBe('
');
+
+ return true;
+ })
+ ->andReturn('
');
+
+ $output = (new Foldable($node, '', app(BladeRenderer::class), app(BladeService::class)))->fold();
- expect($foldable->fold())->toEqualCollapsingWhitespace(join('', [
- 'pushData([\'name\' => $name]); $__env->pushConsumableComponentData([\'name\' => $name]); ?>',
- '
',
+ expect($output)->toEqualCollapsingWhitespace(join('', [
+ 'pushData([\'theme\' => $theme]); $__env->pushConsumableComponentData([\'theme\' => $theme]); ?>',
+ '
',
'popData(); $__env->popConsumableComponentData(); ?>',
]));
});
test('compiles echo attributes in aware macros', function () {
- $input = '
';
-
- $node = app(Parser::class)->parse($input)[0];
+ $node = app(Parser::class)->parse('
')[0];
$node->hasAwareDescendants = true;
- $foldable = new Foldable($node, new ComponentSource(fixture_path('views/components/foldable/wrapper.blade.php')), app(BladeRenderer::class), app(BladeService::class));
+ mock(BladeRenderer::class)
+ ->expects('render')
+ ->once()->withArgs(function (ComponentNode $node) {
+ expect($node->render())->toBe('
');
+
+ return true;
+ })
+ ->andReturn('
');
- expect($foldable->fold())->toEqualCollapsingWhitespace(join('', [
- 'pushData([\'name\' => \'Mr. \'.e($name)]); $__env->pushConsumableComponentData([\'name\' => \'Mr. \'.e($name)]); ?>',
- '
',
+ $output = (new Foldable($node, '', app(BladeRenderer::class), app(BladeService::class)))->fold();
+
+ expect($output)->toEqualCollapsingWhitespace(join('', [
+ 'pushData([\'theme\' => \'dark-\'.e($variant)]); $__env->pushConsumableComponentData([\'theme\' => \'dark-\'.e($variant)]); ?>',
+ '
',
'popData(); $__env->popConsumableComponentData(); ?>',
]));
});
+
+test('does not add aware macros to components without attributes', function () {
+ $node = app(Parser::class)->parse('
')[0];
+ $node->hasAwareDescendants = true;
+
+ mock(BladeRenderer::class)
+ ->expects('render')
+ ->once()->withArgs(function (ComponentNode $node) {
+ expect($node->render())->toBe('
');
+
+ return true;
+ })
+ ->andReturn('
');
+
+ expect((new Foldable($node, '', app(BladeRenderer::class), app(BladeService::class)))->fold())
+ ->toBe('
');
+});
+
+test('does not add aware macros for inherited attributes only', function () {
+ $node = app(Parser::class)->parse('
')[0];
+ $node->hasAwareDescendants = true;
+ $node->setParentsAttributes(app(AttributeParser::class)->parse('theme="dark"'));
+
+ mock(BladeRenderer::class)
+ ->expects('render')
+ ->once()->withArgs(function (ComponentNode $node) {
+ expect($node->render())->toBe('
');
+ expect($node->parentsAttributes['theme']->render())->toBe('theme="dark"');
+
+ return true;
+ })
+ ->andReturn('
');
+
+ expect((new Foldable($node, '', app(BladeRenderer::class), app(BladeService::class)))->fold())
+ ->toBe('
');
+});
diff --git a/tests/Folder/FolderTest.php b/tests/Folder/FolderTest.php
index 45f70d24..c0a0889b 100644
--- a/tests/Folder/FolderTest.php
+++ b/tests/Folder/FolderTest.php
@@ -80,6 +80,20 @@
expect($folded)->toBeInstanceOf(ComponentNode::class);
});
+test('does not fold components with attribute spread from parent', function () {
+ $input = '
';
+
+ $node = app(Parser::class)->parse($input)[0];
+
+ $node->setParentsAttributes(
+ app(AttributeParser::class)->parse(':attributes="$attributes"')
+ );
+
+ $folded = app(Folder::class)->fold($node);
+
+ expect($folded)->toBeInstanceOf(ComponentNode::class);
+});
+
test('folds components with slots', function () {
$input = '
HeaderBody';
diff --git a/tests/Folder/UnblazeTest.php b/tests/Folder/UnblazeTest.php
index 508548e4..bdc7c907 100644
--- a/tests/Folder/UnblazeTest.php
+++ b/tests/Folder/UnblazeTest.php
@@ -3,14 +3,13 @@
use Livewire\Blaze\BladeRenderer;
use Livewire\Blaze\BladeService;
use Livewire\Blaze\Folder\Foldable;
-use Livewire\Blaze\Support\ComponentSource;
use Livewire\Blaze\Parser\Parser;
test('compiles unblaze blocks', function () {
$input = '
';
$node = app(Parser::class)->parse($input)[0];
- $foldable = new Foldable($node, new ComponentSource(fixture_path('views/components/foldable/input-unblaze.blade.php')), app(BladeRenderer::class), app(BladeService::class));
+ $foldable = new Foldable($node, fixture_path('views/components/foldable/input-unblaze.blade.php'), app(BladeRenderer::class), app(BladeService::class));
expect($foldable->fold())->toEqualCollapsingWhitespace(
sprintf('
', join('', [
@@ -26,7 +25,7 @@
$input = '
';
$node = app(Parser::class)->parse($input)[0];
- $foldable = new Foldable($node, new ComponentSource(fixture_path('views/components/foldable/nested-input-unblaze.blade.php')), app(BladeRenderer::class), app(BladeService::class));
+ $foldable = new Foldable($node, fixture_path('views/components/foldable/nested-input-unblaze.blade.php'), app(BladeRenderer::class), app(BladeService::class));
expect($foldable->fold())->toEqualCollapsingWhitespace(
sprintf('
', join('', [
@@ -42,7 +41,7 @@
$input = '
';
$node = app(Parser::class)->parse($input)[0];
- $foldable = new Foldable($node, new ComponentSource(fixture_path('views/components/foldable/input-unblaze.blade.php')), app(BladeRenderer::class), app(BladeService::class));
+ $foldable = new Foldable($node, fixture_path('views/components/foldable/input-unblaze.blade.php'), app(BladeRenderer::class), app(BladeService::class));
expect($foldable->fold())->toEqualCollapsingWhitespace(
sprintf('
', join('', [
diff --git a/tests/fixtures/views/components/foldable/input-aware-no-props.blade.php b/tests/fixtures/views/components/foldable/input-aware-no-props.blade.php
new file mode 100644
index 00000000..cc7158ba
--- /dev/null
+++ b/tests/fixtures/views/components/foldable/input-aware-no-props.blade.php
@@ -0,0 +1,8 @@
+@blaze(fold: true)
+
+@aware(['type'])
+
+{{-- We intentionally do not set @props here to ensure aware props are preserved in $attributes --}}
+{{-- When type="number" is passed, below should be rendered as
--}}
+
+
diff --git a/tests/fixtures/views/components/foldable/input-aware.blade.php b/tests/fixtures/views/components/foldable/input-aware.blade.php
index ddc6e6c0..626f42d7 100644
--- a/tests/fixtures/views/components/foldable/input-aware.blade.php
+++ b/tests/fixtures/views/components/foldable/input-aware.blade.php
@@ -1,5 +1,7 @@
@blaze(fold: true)
-@aware(['type' => 'text'])
+@aware(['type'])
-
+@props(['type' => 'text'])
+
+