inertiajs / inertia-laravel

The Laravel adapter for Inertia.js.
https://inertiajs.com
MIT License
2.03k stars 227 forks source link

Assertable Inertia working only with Vite #516

Closed paulmax-os closed 1 year ago

paulmax-os commented 1 year ago

Hi everybody, first of all, thanks for all of your work. I love Inertia! Today I stumbled over an issue that I haven't noticed in previous versions of Inertia (before 1.x release):

When testing my pages, I'm utilizing the endpoint testing, which is being described in the Inertia docs. Today I noticed that my tests were suddenly failing. I didn't change a thing, but then I noticed they were always failing because my vite build was either outdated or vite dev wasn't running.

I initialized a fresh Laravel + Breeze + Vue project, in order to find out if it was because of the configuration in my project or if this was happening with a clean project too:

# routes/web.php
Route::get('/test-inertia', function() {
    return Inertia::render('TestInertia', [
        'foo' => 'bar'
    ]);
})->name('inertiatest');
<!--  resources/js/Pages/TestInertia.vue -->
<script setup>
const { foo } = defineProps({
    foo: String
});
</script>
<template>
    <div>
        {{ foo }}
    </div>
</template>
# Some test file based upon Tests\TestCase
public function test_inertia()
{
    $response = $this->get(route('inertiatest'));
    $response->assertInertia(function(AssertableInertia $page) {
        $page->component('TestInertia');
        $page->has('foo');
    });
}

So, to make the story short: The test was failing:

1) Tests\Feature\ExampleTest::test_inertia
Not a valid Inertia response.

/vendor/inertiajs/inertia-laravel/src/Testing/AssertableInertia.php:34
/vendor/inertiajs/inertia-laravel/src/Testing/TestResponseMacros.php:14
/vendor/laravel/framework/src/Illuminate/Macroable/Traits/Macroable.php:124
/vendor/laravel/framework/src/Illuminate/Testing/TestResponse.php:1755
/tests/Feature/ExampleTest.php:29
/vendor/laravel/framework/src/Illuminate/Foundation/Testing/TestCase.php:173

The test will pass though, when npm run dev is active, meaning the vite dev server or when I ran npm run build before executing the test, which probably is because the vite manifest doesn't know about the page.

So well, I don't know if that is expected behavior or a bug. At least I wasn't able to find anything about it in the docs, so I wanted to report it at least and see if there's anything I am doing wrong or if it's just the way it is or if it's really an issue.

Thanks a lot for your time and efforts :) I am happy to provide further help!

RobertBoes commented 1 year ago

It makes sense that it would fail, because Laravel would throw an exception. You're making a request to a page, which renders using the @vite() directive, this would throw an exception when there is no manifest present and/or the Vite devserver isn't running.

This isn't really something Inertia can prevent, as that's just Laravel behavior. One thing you can use to get better feedback: Assert the response is a 200, that way PHPUnit will tell you there is an unexpected response, instead of the vague Inertia error Not a valid Inertia response

$this->get(route('inertiatest'))
    ->assertOk()
    ->assertInertia(...);

That way PHPUnit will show you the following error:

Expected response status code [200] but received 500.
Failed asserting that 200 is identical to 500.

The following exception occurred during the last request:

Exception: Vite manifest not found at: /[path to project]/vendor/laravel/framework/src/Illuminate/Foundation/Vite.php:684

Stack trace:
...
seivad commented 1 year ago

Hey I've got the same issue, following the Inertia Testing docs it says it will work yet all I ever receive is Not a valid Inertia response.

I even made a page without authentication, i've ran npm run build (also had npm run dev running on other attempts) and no matter what it complains that it's not a view (that's the Throw error) and returns Not a valid Inertia response.

How do you test Vue 3 + Inertia in Laravel? I can't get it working at all and i've lost a lot of confidence now in this going into production if I can't have tests backing it up.

paulmax-os commented 1 year ago

@seivad Have you tried, running your test while npm run dev is active?

paulmax-os commented 1 year ago

Thanks for your feedback, @RobertBoes . I already figured that this is the underlying issue. Nevertheless I think, that the way of testing as described in the docs should work without the need of having to run a build. At least from my point of view, I'm not testing the actual UI/UX when using AssertableInertia. I am testing that the payload I'm sending to the client is the one I'm expecting to send and that I'm using the right page component.

So from my point of view I basically only want to validate the $page variable in the toResponse() method of the Inertia Response, when using AssertableInertia. I don't want to validate, that either Vite or Inertia itself are doing the job they're supposed to do in this situation; I would assume that this is the case. But this is only my opinion and it doesn't need to be correct.

Anyway... I totally feel @seivad here and can align to the doubts he has expressed. As last time I checked, for me everything was working fine after having run a build, my worries are kind of mitigated though. Nevertheless this should be added to the docs as other people will stumble over this issue, latest in CI/CD I guess. If @seivad is right though and it's not even working after having run a build, this might be a bigger issue that - at least from my point of view - should be really addressed.

I don't have much time that I can spend on creating PRs due to my job, but I would be happy to spend the time I have, to help figuring that out. But I also don't want to invest the little time I have only to see a potential PR lying around for years. No offense here, I assume everybody is having a job and is busy and I am really grateful for all the work that is going into this project - so please don't get me wrong. But maybe one of the core maintainers could check if this a valid issue that should be solved and if it fits into the roadmap.

RobertBoes commented 1 year ago

@paulmax-os Well, it doesn't have much to do with Inertia, it's basically how Laravel works. You're requesting a page, which needs to be rendered. And in order to render it, it needs the assets. Laravel does have the option to disable Vite in tests tho: https://laravel.com/docs/10.x/vite#disabling-vite-in-tests

But I don't think this is an issue that should be solved by Inertia tbh

paulmax-os commented 1 year ago

@RobertBoes Yeah, I know that currently it's the way it is. I am thinking about how this could be improved. Having something like the Facade::fake() helpers for Inertia, allowing you to write those tests without the requirement of a build process before:


public function test_inertia()
{
    Inertia::fake();

    $inertiaFakeResponseObject = $this->get(route('inertia.route');

    $inertiaFakeResponseObject->assertInertia();
}
seivad commented 1 year ago

I 100% have tried both npm run dev running whilst filtering the test in phpunit as well as also running npn run build as stated. It's not my first rodeo but it is with inertia. How do you get the inertia test to work at all? I inspected the $response dump and it's even picking up the correctly compiled app.js and css.js with their corresponding cache busting tags.

This is essentially a fresh build, I made a standalone controller / route / vue.js component and it still didn't work with that same error: Not a valid Inertia response. because it doesn't have the page key in the check that the response is a view function.

jameshulse commented 1 year ago

@seivad, did you try https://laravel.com/docs/10.x/vite#disabling-vite-in-tests ?

jessarcher commented 1 year ago

Hey there,

We're closing this issue because it's inactive, already solved, old or not relevant anymore. Feel to open up a new issue if you're still experiencing this problem.