From dd238319dad41e63de9ae2dedf2cf334bfd6f5c1 Mon Sep 17 00:00:00 2001 From: fadrian06 Date: Thu, 25 Jun 2026 17:05:46 -0400 Subject: [PATCH] Add component prop-passing coverage Extend View component rendering tests to cover functional and class components receiving props via variadic and individual parameters, and update View callable invocation to map template data into callable arguments. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- flight/template/View.php | 40 ++++++++++++++++++- tests/ViewTest.php | 21 ++++++++++ .../my-class-component-with-props.php | 22 ++++++++++ ...tional-component-with-individual-props.php | 6 +++ .../my-functional-component-with-props.php | 9 +++++ .../page-with-class-component-with-props.php | 1 + ...tional-component-with-individual-props.php | 1 + ...e-with-functional-component-with-props.php | 1 + 8 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 tests/views/components/my-class-component-with-props.php create mode 100644 tests/views/components/my-functional-component-with-individual-props.php create mode 100644 tests/views/components/my-functional-component-with-props.php create mode 100644 tests/views/pages/page-with-class-component-with-props.php create mode 100644 tests/views/pages/page-with-functional-component-with-individual-props.php create mode 100644 tests/views/pages/page-with-functional-component-with-props.php diff --git a/flight/template/View.php b/flight/template/View.php index 8983db5..453f533 100644 --- a/flight/template/View.php +++ b/flight/template/View.php @@ -4,7 +4,9 @@ declare(strict_types=1); namespace flight\template; +use Closure; use Exception; +use ReflectionFunction; /** * The View class represents output to be displayed. It provides @@ -153,7 +155,8 @@ class View switch (true) { case is_callable($component): - $view = $component(); + $arguments = $this->getCallableArguments($component, $data); + $view = $component(...$arguments); ob_end_clean(); break; @@ -290,4 +293,39 @@ class View ): string { return str_replace(['\\', '/'], $separator, $path); } + + /** + * @param callable $component + * @param ?array $data + * @return array + */ + private function getCallableArguments(callable $component, ?array $data): array + { + if (!is_array($data) || !$data) { + return []; + } + + $arguments = []; + $remainingData = $data; + $reflection = new ReflectionFunction(Closure::fromCallable($component)); + + foreach ($reflection->getParameters() as $parameter) { + if ($parameter->isVariadic()) { + foreach ($remainingData as $value) { + $arguments[] = $value; + } + + break; + } + + $name = $parameter->getName(); + + if (array_key_exists($name, $remainingData)) { + $arguments[] = $remainingData[$name]; + unset($remainingData[$name]); + } + } + + return $arguments; + } } diff --git a/tests/ViewTest.php b/tests/ViewTest.php index ce37cd6..78c5d2d 100644 --- a/tests/ViewTest.php +++ b/tests/ViewTest.php @@ -308,6 +308,27 @@ class ViewTest extends TestCase my-class-component html, ], + [ + 'page-with-functional-component-with-props', + <<<'html' + functional-component-with-props: Astronaut Victoria + html, + ['name' => 'Victoria', 'occupation' => 'Astronaut'], + ], + [ + 'page-with-functional-component-with-individual-props', + <<<'html' + functional-component-with-individual-props: Astronaut Victoria + html, + ['name' => 'Victoria', 'occupation' => 'Astronaut'], + ], + [ + 'page-with-class-component-with-props', + <<<'html' + class-component-with-props: Astronaut Victoria + html, + ['name' => 'Victoria', 'occupation' => 'Astronaut'], + ], [ 'page-with-class-component-with-styles', <<<'html' diff --git a/tests/views/components/my-class-component-with-props.php b/tests/views/components/my-class-component-with-props.php new file mode 100644 index 0000000..66abcad --- /dev/null +++ b/tests/views/components/my-class-component-with-props.php @@ -0,0 +1,22 @@ +name = $name; + $this->occupation = $occupation; + } + + public function html(): string + { + return "class-component-with-props: $this->occupation $this->name"; + } +}; diff --git a/tests/views/components/my-functional-component-with-individual-props.php b/tests/views/components/my-functional-component-with-individual-props.php new file mode 100644 index 0000000..9f3bdb9 --- /dev/null +++ b/tests/views/components/my-functional-component-with-individual-props.php @@ -0,0 +1,6 @@ + + "functional-component-with-individual-props: $occupation $name"; diff --git a/tests/views/components/my-functional-component-with-props.php b/tests/views/components/my-functional-component-with-props.php new file mode 100644 index 0000000..ef8856e --- /dev/null +++ b/tests/views/components/my-functional-component-with-props.php @@ -0,0 +1,9 @@ + sprintf( + 'functional-component-with-props: %s %s', + $props[1] ?? '', + $props[0] ?? '' +); diff --git a/tests/views/pages/page-with-class-component-with-props.php b/tests/views/pages/page-with-class-component-with-props.php new file mode 100644 index 0000000..a2bd6d9 --- /dev/null +++ b/tests/views/pages/page-with-class-component-with-props.php @@ -0,0 +1 @@ + diff --git a/tests/views/pages/page-with-functional-component-with-individual-props.php b/tests/views/pages/page-with-functional-component-with-individual-props.php new file mode 100644 index 0000000..f77480a --- /dev/null +++ b/tests/views/pages/page-with-functional-component-with-individual-props.php @@ -0,0 +1 @@ + diff --git a/tests/views/pages/page-with-functional-component-with-props.php b/tests/views/pages/page-with-functional-component-with-props.php new file mode 100644 index 0000000..dddef9f --- /dev/null +++ b/tests/views/pages/page-with-functional-component-with-props.php @@ -0,0 +1 @@ +