Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

ignaciodev's avatar

assertInertia() fails when testing Inertia visits

assertInertia() throws a Not a valid Inertia response error when simulating an Inertia.js visit like so:

$response = $this
    ->withHeaders([
        "accept" => "text/html, application/xhtml+xml",
        "content-type" => "application/json",
        "x-inertia" => "true",
        "x-inertia-partial-component" => "Post/Edit",
        "x-inertia-partial-data" => "post",
        "x-inertia-version" => "eaa52f64811e388602bb56eca093f022",
        "x-requested-with" => "XMLHttpRequest",
    ])
    ->get('/some-route')
    ->assertInertia(fn (AssertableInertia $page) => 
        // ...
    );

How do you test this type of request?

0 likes
9 replies
gych's avatar

Might be related to all the headers you've added to the request.

Try this:

$response = $this->get('/some-route')
    ->assertInertia(fn (AssertableInertia $page) => 
        // ...
    );
ignaciodev's avatar

@gych thank you for your reply!

The reason for the headers is to emulate an Inertia.js visit, since I have a middleware that checks for $request>inertia().

I think when I add the "x-inertia" => "true" header to make my middleware pass, the Inertia::render('some/page') doesn't actually return a page, so this method from AssertableInertia.php does not pass:

public static function fromTestResponse(TestResponse $response): self
    {
        try {
            $response->assertViewHas('page');
            $page = json_decode(json_encode($response->viewData('page')), true);

            PHPUnit::assertIsArray($page);
            PHPUnit::assertArrayHasKey('component', $page);
            PHPUnit::assertArrayHasKey('props', $page);
            PHPUnit::assertArrayHasKey('url', $page);
            PHPUnit::assertArrayHasKey('version', $page);
        } catch (AssertionFailedError $e) {
            PHPUnit::fail('Not a valid Inertia response.');
        }

        $instance = static::fromArray($page['props']);
        $instance->component = $page['component'];
        $instance->url = $page['url'];
        $instance->version = $page['version'];

        return $instance;
    }

In particular, the $response->assertViewHas('page'); line.

gych's avatar

@ignaciodev What is returned then as response when this fails ? Also for what is the middleware exactly used?

ignaciodev's avatar

@gych

The controller is returning:

Inertia::render("Post/Edit", ['post' => $post ]);

Due to some (complex) logic of the app I'm building, if the request is not an Inertia.js partial visit coming from a particular page, my middleware will redirect to posts.show route.

It's all working great, my only issue comes from the automated tests.

The headers I have added have been copied from a dd($request), to ensure they are identical to when I make the request by clicking on my UI.

The response's assertOk() is passing.

The $this->get() on my test returns a Illuminate\Testing\TestResponse with a 200 status code.

gych's avatar

@ignaciodev Ok and for the test, does the middleware recognize the request with the headers you've added as Inertia request ?

ignaciodev's avatar

@gych yes! The code execution makes it all the way to the Inertia::render without issues, and the response code is 200.

The middleware (which passes without issues) is checking it like this:

if (
    $request->inertia() &&
    $request->header('x-inertia-partial-component') === 'Post/Show'
) {
    return $next($request);
}
gych's avatar

@ignaciodev When you debug the response which data does it contain?

$response = $this
    ->withHeaders([
        "accept" => "text/html, application/xhtml+xml",
        "content-type" => "application/json",
        "x-inertia" => "true",
        "x-inertia-partial-component" => "Post/Edit",
        "x-inertia-partial-data" => "post",
        "x-inertia-version" => "eaa52f64811e388602bb56eca093f022",
        "x-requested-with" => "XMLHttpRequest",
    ])
    ->get('/some-route');

dd($response);

$response->assertInertia(fn (AssertableInertia $page) => 
	// ...
);
ignaciodev's avatar

@gych this is what the dd($response) is showing:

Illuminate\Testing\TestResponse^ {#2324 // tests/Feature/PepeTest.php:44
  +baseResponse: Illuminate\Http\JsonResponse^ {#2233
    +headers: Symfony\Component\HttpFoundation\ResponseHeaderBag^ {#2248
      #headers: array:5 [
        "x-inertia" => array:1 [
          0 => "true"
        ]
        "cache-control" => array:1 [
          0 => "no-cache, private"
        ]
        "date" => array:1 [
          0 => "Tue, 23 Apr 2024 13:39:37 GMT"
        ]
        "content-type" => array:1 [
          0 => "application/json"
        ]
        "vary" => array:1 [
          0 => "X-Inertia"
        ]
      ]
      #cacheControl: []
      #computedCacheControl: array:2 [
        "no-cache" => true
        "private" => true
      ]
      #cookies: array:1 [
        "" => array:1 [
          "/" => array:2 [
            "XSRF-TOKEN" => Symfony\Component\HttpFoundation\Cookie^ {#2284
              #name: "XSRF-TOKEN"
              #value: "eyJpdiI6IjJCWFZwSEd1aGdvRUZJSUd6Vm1reHc9PSIsInZhbHVlIjoia3BpUTJiM00va1AwejlKZkE2QVFWV3FEQXVIYi9LQlovaEtxVVJ0WWg3U3pHYTY3YWFqVGo0aksxMEt4WFFSL2REWjFVcGt4Qld1dDJ5NFcwbXNoRkRtS0tPbFpiUCsyZlVZVHg5RCtHWkhJVmpRbEdUaWpud2xJUkRuR2R6cysiLCJtYWMiOiIxNWQ3ZGE5MjhhYjI3OTczM2IwZGI1ZWI2ZTcxNzc3ZGVkYmI5MDQ4OTI1ZDQyOTg1YjA2MDdkNmZiYzM1MjFhIiwidGFnIjoiIn0="
              #domain: null
              #expire: 1713886777
              #path: "/"
              #secure: false
              #httpOnly: false
              -raw: false
              -sameSite: "lax"
              -secureDefault: false
            }
            "my_video_session_session" => Symfony\Component\HttpFoundation\Cookie^ {#2282
              #name: "my_video_session_session"
              #value: "eyJpdiI6ImQ4ZmtHOEtmSkwwNjRvRG9vL1NpcEE9PSIsInZhbHVlIjoiWU1HSDV3WGIxb21HNkhlWm5kNTFhSWJndUNKeWQvZlR2K1psak9UL0RPUWhMSUI5OFpQZ0VIM08yellMTnVCQVRwU0FReWJYZ01YSlFxUCtOZzRVa1pxMlhMZ2tURyt4alI2dHZTV21IbDU0OTBpc0tEVmtUMTBDaG9tUm5ONFIiLCJtYWMiOiJjMmJhMmRmYzA1YWVhMGViMWJiNWEwOTliMDU2NjdlOGM3YTNlYjYzODA1ZTI5ODM2ODEzMWMzYmJmM2RmYjY1IiwidGFnIjoiIn0="
              #domain: null
              #expire: 1713886777
              #path: "/"
              #secure: false
              #httpOnly: true
              -raw: false
              -sameSite: "lax"
              -secureDefault: false
            }
          ]
        ]
      ]
      #headerNames: array:6 [
        "x-inertia" => "X-Inertia"
        "cache-control" => "Cache-Control"
        "date" => "Date"
        "content-type" => "Content-Type"
        "vary" => "Vary"
        "set-cookie" => "Set-Cookie"
      ]
    }
    #content: "{"component":"Post\/EditPage","props":[],"url":"\/posts\/YmxkazYeJ0P\/edit","version":"eaa52f64811e388602bb56eca093f022"}"
    #version: "1.1"
    #statusCode: 200
    #statusText: "OK"
    #charset: null
    #data: "{"component":"Post\/EditPage","props":[],"url":"\/posts\/YmxkazYeJ0P\/edit","version":"eaa52f64811e388602bb56eca093f022"}"
    #callback: null
    #encodingOptions: 0
    +original: array:4 [
      "component" => "Post/EditPage"
      "props" => []
      "url" => "/posts/YmxkazYeJ0P/edit"
      "version" => "eaa52f64811e388602bb56eca093f022"
    ]
    +exception: null
  }
  +exceptions: Illuminate\Testing\LoggedExceptionCollection^ {#857
    #items: []
    #escapeWhenCastingToString: false
  }
  #streamedContent: null
}
gych's avatar

@ignaciodev Indeed when adding the x-inertia header it doesn't return the page component.

What is it, that you want to achieve by checking that the request is an Inertia request ? For example what should happen if it doesn't pass the middleware?

Please or to participate in this conversation.