From 7948031f5e2d6775e53f12159e3525891e13a457 Mon Sep 17 00:00:00 2001 From: Jeroen Govers Date: Thu, 7 Mar 2024 21:27:34 +0100 Subject: [PATCH 1/3] added requestProp testing method --- src/ServiceProvider.php | 12 ++++++ src/Testing/AssertableInertia.php | 38 +++++++++++++++++++ .../Listeners/RequestHandledListener.php | 15 ++++++++ tests/Testing/AssertableInertiaTest.php | 36 ++++++++++++++++++ .../Listeners/RequestHandledListener.php | 25 ++++++++++++ 5 files changed, 126 insertions(+) create mode 100644 src/Testing/Listeners/RequestHandledListener.php create mode 100644 tests/Testing/Listeners/RequestHandledListener.php diff --git a/src/ServiceProvider.php b/src/ServiceProvider.php index 35f651b8..91da8676 100644 --- a/src/ServiceProvider.php +++ b/src/ServiceProvider.php @@ -2,6 +2,8 @@ namespace Inertia; +use Illuminate\Contracts\Events\Dispatcher; +use Illuminate\Foundation\Http\Events\RequestHandled; use LogicException; use Inertia\Ssr\Gateway; use ReflectionException; @@ -13,6 +15,7 @@ use Inertia\Testing\TestResponseMacros; use Illuminate\Support\ServiceProvider as BaseServiceProvider; use Illuminate\Foundation\Testing\TestResponse as LegacyTestResponse; +use Inertia\Testing\Listeners\RequestHandledListener; class ServiceProvider extends BaseServiceProvider { @@ -38,6 +41,10 @@ public function register(): void $app['config']->get('inertia.testing.page_extensions') ); }); + + $this->app->bind('inertia.testing.request', function ($app) { + return null; + }); } public function boot(): void @@ -47,6 +54,11 @@ public function boot(): void $this->publishes([ __DIR__.'/../config/inertia.php' => config_path('inertia.php'), ]); + + if (app()->environment('testing') === true) { + $dispatcher = app(Dispatcher::class); + $dispatcher->listen(RequestHandled::class, RequestHandledListener::class); + } } protected function registerBladeDirectives(): void diff --git a/src/Testing/AssertableInertia.php b/src/Testing/AssertableInertia.php index 370e748d..fbe4fa81 100644 --- a/src/Testing/AssertableInertia.php +++ b/src/Testing/AssertableInertia.php @@ -3,6 +3,10 @@ namespace Inertia\Testing; use InvalidArgumentException; +use Closure; +use Illuminate\Contracts\Http\Kernel; +use Illuminate\Support\Facades\Event; +use Illuminate\Support\Testing\Fakes\Fake; use Illuminate\Testing\TestResponse; use PHPUnit\Framework\Assert as PHPUnit; use PHPUnit\Framework\AssertionFailedError; @@ -71,6 +75,40 @@ public function version(string $value): self return $this; } + public function requestProp(string $prop, Closure $assert = null): self + { + $request = app('inertia.testing.request'); + if ($request === null) { + if (Event::getFacadeRoot() instanceof Fake) { + PHPUnit::fail('Unable to listen to the `\Illuminate\Foundation\Http\Events\RequestHandled` event. Please use Event::fakeExcept(RequestHandled::class) when using requestProp if you want to block other events.'); + } + + PHPUnit::fail('Unable to catch the previous request via the `\Illuminate\Foundation\Http\Events\RequestHandled` event using listener.'); + } + + $request->headers->add([ + 'X-Inertia-Partial-Component' => $this->component, + 'X-Inertia-Partial-Data' => $prop, + ]); + + + $kernel = app()->make(Kernel::class); + $response = $kernel->handle($request); + + $kernel->terminate($request, $response); + + $testResponse = TestResponse::fromBaseResponse($response); + $testResponse->assertInertia(function (AssertableInertia $page) use ($prop, $assert) { + $page->has($prop); + + if($assert !== null){ + $assert($page); + } + }); + + return $this; + } + public function toArray() { return [ diff --git a/src/Testing/Listeners/RequestHandledListener.php b/src/Testing/Listeners/RequestHandledListener.php new file mode 100644 index 00000000..85fe4edd --- /dev/null +++ b/src/Testing/Listeners/RequestHandledListener.php @@ -0,0 +1,15 @@ +bind('inertia.testing.request', function () use ($event) { + return $event->request; + }); + } +} diff --git a/tests/Testing/AssertableInertiaTest.php b/tests/Testing/AssertableInertiaTest.php index 613cccc2..068005bc 100644 --- a/tests/Testing/AssertableInertiaTest.php +++ b/tests/Testing/AssertableInertiaTest.php @@ -3,6 +3,7 @@ namespace Inertia\Tests\Testing; use Inertia\Inertia; +use Inertia\Testing\AssertableInertia; use Inertia\Tests\TestCase; use PHPUnit\Framework\AssertionFailedError; @@ -207,4 +208,39 @@ public function the_asset_version_does_not_match(): void $inertia->version('different-version'); }); } + + /** @test */ + public function the_lazy_prop_can_be_fetch_via_the_request_prop_method(): void + { + $response = $this->makeMockRequest( + Inertia::render('foo', [ + 'bar' => Inertia::lazy(function () { + return 'foobar'; + }), + ]) + ); + $response->assertInertia(function ($inertia) { + $inertia->missing('bar'); + + $inertia->requestProp('bar', function ($subInertia) { + $this->assertInstanceOf(AssertableInertia::class, $subInertia); + + $subInertia->where('bar', 'foobar'); + }); + }); + } + + /** @test */ + public function the_request_prop_method_fails_if_prop_does_not_exists(): void + { + $response = $this->makeMockRequest( + Inertia::render('foo') + ); + + $this->expectException(AssertionFailedError::class); + + $response->assertInertia(function ($inertia) { + $inertia->requestProp('bar'); + }); + } } diff --git a/tests/Testing/Listeners/RequestHandledListener.php b/tests/Testing/Listeners/RequestHandledListener.php new file mode 100644 index 00000000..7cb043bb --- /dev/null +++ b/tests/Testing/Listeners/RequestHandledListener.php @@ -0,0 +1,25 @@ +assertNull(app('inertia.testing.request')); + + Event::dispatch(new RequestHandled($request, $response)); + + $this->assertSame($request, app('inertia.testing.request')); + } +} From ab4f09c346b8fbb4832046af71d986bbd5d29c00 Mon Sep 17 00:00:00 2001 From: Jeroen Govers Date: Sat, 9 Mar 2024 09:22:10 +0100 Subject: [PATCH 2/3] Compatibility added to deprecated Assert class --- src/Testing/Assert.php | 32 +++++++++++++++++++++++++ tests/Testing/AssertableInertiaTest.php | 3 --- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/Testing/Assert.php b/src/Testing/Assert.php index 903a6086..ef9e7655 100644 --- a/src/Testing/Assert.php +++ b/src/Testing/Assert.php @@ -4,6 +4,8 @@ use Closure; use const E_USER_DEPRECATED; +use Illuminate\Contracts\Http\Kernel; +use Illuminate\Foundation\Testing\TestResponse; use Illuminate\Support\Traits\Macroable; use PHPUnit\Framework\Assert as PHPUnit; use Illuminate\Contracts\Support\Arrayable; @@ -89,4 +91,34 @@ public static function fromTestResponse($response): self return new self($page['component'], $page['props'], $page['url'], $page['version']); } + + public function requestProp(string $prop, Closure $assert = null): self + { + $request = app('inertia.testing.request'); + if ($request === null) { + PHPUnit::fail('Unable to catch the previous request via the `\Illuminate\Foundation\Http\Events\RequestHandled` event using listener. If you are using Event::fake(), please use Event::fakeExcept(RequestHandled::class) instead when calling requestProp if you want to block other events.'); + } + + $request->headers->add([ + 'X-Inertia-Partial-Component' => $this->component, + 'X-Inertia-Partial-Data' => $prop, + ]); + + + $kernel = app()->make(Kernel::class); + $response = $kernel->handle($request); + + $kernel->terminate($request, $response); + + $testResponse = TestResponse::fromBaseResponse($response); + $testResponse->assertInertia(function (Assert $page) use ($prop, $assert) { + $page->has($prop); + + if ($assert !== null) { + $assert($page); + } + }); + + return $this; + } } diff --git a/tests/Testing/AssertableInertiaTest.php b/tests/Testing/AssertableInertiaTest.php index 068005bc..3eb89cec 100644 --- a/tests/Testing/AssertableInertiaTest.php +++ b/tests/Testing/AssertableInertiaTest.php @@ -3,7 +3,6 @@ namespace Inertia\Tests\Testing; use Inertia\Inertia; -use Inertia\Testing\AssertableInertia; use Inertia\Tests\TestCase; use PHPUnit\Framework\AssertionFailedError; @@ -223,8 +222,6 @@ public function the_lazy_prop_can_be_fetch_via_the_request_prop_method(): void $inertia->missing('bar'); $inertia->requestProp('bar', function ($subInertia) { - $this->assertInstanceOf(AssertableInertia::class, $subInertia); - $subInertia->where('bar', 'foobar'); }); }); From 24922c34f69a529c3405aeb70cf2389c1ff10d92 Mon Sep 17 00:00:00 2001 From: Jeroen Govers Date: Sat, 9 Mar 2024 09:30:25 +0100 Subject: [PATCH 3/3] LegacyTestResponse fix --- src/Testing/Assert.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Testing/Assert.php b/src/Testing/Assert.php index ef9e7655..e4bc1a1d 100644 --- a/src/Testing/Assert.php +++ b/src/Testing/Assert.php @@ -5,7 +5,8 @@ use Closure; use const E_USER_DEPRECATED; use Illuminate\Contracts\Http\Kernel; -use Illuminate\Foundation\Testing\TestResponse; +use Illuminate\Testing\TestResponse; +use Illuminate\Foundation\Testing\TestResponse as LegacyTestResponse; use Illuminate\Support\Traits\Macroable; use PHPUnit\Framework\Assert as PHPUnit; use Illuminate\Contracts\Support\Arrayable; @@ -110,7 +111,12 @@ public function requestProp(string $prop, Closure $assert = null): self $kernel->terminate($request, $response); - $testResponse = TestResponse::fromBaseResponse($response); + $testResponseClass = TestResponse::class; + if (class_exists($testResponseClass) == false) { + $testResponseClass = LegacyTestResponse::class; + } + + $testResponse = $testResponseClass::fromBaseResponse($response); $testResponse->assertInertia(function (Assert $page) use ($prop, $assert) { $page->has($prop);