Intertia Testing Docs
Intertia Testing Docs
To start testing your Inertia pages, simply call the assertInertia method on your
TestResponse responses, and chain any of the available assertions on its closure/callback
argument:
$response->assertInertia(fn ($page) => $page->someInertiaAssertion());
When using this library to its fullest extent, your tests will end up looking similar to this:
use ClaudioDekker\Inertia\Assert;
NOTE: The above uses arrow functions, which are available as of PHP 7.4+. If you are
using this library on an older version of PHP, you will unfortunately need to use a
regular callback instead:
NOTE: While type-hinting the Assert isn't necessary (and will cause some minor
search-and-replaceable breakage once migrating away from this package), it allows
your IDE to automatically suggest the assertion methods that can be chained.
Available Assertions
Basics:
Component
(Page) URL
(Asset) Version
In-depth:
has
Count / Size / Length
Scoping
where
Using a Closure
etc
missing
Helpers:
Debugging
Component
To assert that the Inertia page has the page component you expect, you can use the component
assertion:
$response->assertInertia(fn (Assert $page) => $page-
>component('Podcasts/Show'));
Apart from asserting that the component matches what you expect, this assertion will also
automatically attempt to locate the page component on the filesystem, and will fail when it cannot
be found.
NOTE: By default, lookup occurs relative to the resources/js/Pages folder, and
will only accept matching files that have a .vue or .svelte extension. All of these
settings are configurable in our configuration file.
If you are missing any default extensions (such as those for React), please let us know
which ones should be supported by opening an issue!
(Page) URL
To assert that the Page URL matches what you expect, you may use the url assertion:
$response->assertInertia(fn (Assert $page) => $page->url('/podcasts'));
(Asset) Version
To assert that the (asset) version matches what you expect, you may use the version assertion:
$expected = md5(mix('/js/app.js'));
NOTE: We recommend to only use this assertion when you are using asset versioning.
has
Basic Usage
To assert that Inertia has a property, you may use the has method. You can think of has similar to
PHP's isset:
$response->assertInertia(fn (Assert $page) => $page
// Checking a root-level property
->has('podcast')
// Checking that the podcast prop has a nested id property using "dot"
notation
->has('podcast.id')
);
The above will first assert that the property exists, as well as that is the expected size. This means
that there is no need to manually ensure that the property exists using a separate has call.
Scoping
In a previous version of this library, testing code could become fairly verbose, and the deeper your
assertions went, the more complex your assertions became. For instance, here is a real example of
some assertion logic we used to write:
$response->assertInertiaHas('message.comments.0.files.0.url',
'/storage/attachments/example-attachment.pdf');
$response->assertInertiaHas('message.comments.0.files.0.name', 'example-
attachment.pdf');
Fortunately, we no longer have to do this. Instead, we can simply scope properties using the has
method:
$response->assertInertia(fn (Assert $page) => $page
// Creating a single-level property scope
->has('message', fn (Assert $page) => $page
// We can now continue chaining methods
->has('subject')
->has('comments', 5)
While this is already a significant improvement, that's not all: As you can see in the example above,
you'll often run into situations where you'll want to check that a property has a certain length, and
then tap into one of the entries to make sure that all the props there are as expected:
->has('comments', 5)
->has('comments.0', fn (Assert $page) => $page
// ...
To simplify this, you can simply combine the two calls, providing the scope as the third argument:
$response->assertInertia(fn (Assert $page) => $page
// Assert that there are five comments, and automatically scope into the
first comment.
->has('comments', 5, fn(Assert $page) => $page
->has('body')
// ...
)
);
where
To assert that an Inertia property has an expected value, you may use the where assertion:
$response->assertInertia(fn (Assert $page) => $page
->has('message', fn (Assert $page) => $page
// Assert that the subject prop matches the given message
->where('subject', 'This is an example message')
For example:
$user = User::factory()->create(['name' => 'John Doe']);
Using a Closure
Finally, it's also possible to assert against a callback / closure. To do so, simply provide a callback as
the value, and make sure that the response is true in order to make the assertion pass, or anything
else to fail the assertion:
$response->assertInertia(fn (Assert $page) => $page
->where('foo', fn ($value) => $value === 'bar')
Because working with arrays directly isn't always a great experience, we'll automatically cast arrays
to Collections:
$response->assertInertia(fn (Assert $page) => $page
->where('foo', function (Collection $value) {
return $value->median() === 1.5;
})
);
etc
This library will automatically fail your test when you haven't interacted with at least one of the
props in a scope. While this is generally useful, you might run into situations where you're working
with unreliable data (such as from a feed), or with data that you really don't want interact with, in
order to keep your test simple. For those situations, the etc method exists:
$response->assertInertia(fn (Assert $page) => $page
->has('message', fn (Assert $page) => $page
->has('subject')
->has('comments')
->etc()
)
);
IMPORTANT: This automatic property check DOES NOT APPLY TO YOUR TOP-
LEVEL PROPS. If you wish to enforce this for the top-level of your page as well, you
may enable this in our configuration file.
NOTE: While etc reads fluently at the end of a query scope, placing it at the
beginning or somewhere in the middle of your assertions does not change how it
behaves: It will disable the automatic check that asserts that all properties in the current
scope have been interacted with.
missing
Because missing isn't necessary by default, it provides a great solution when using etc.
In short, it does the exact opposite of the has method, ensuring that the property does not exist:
$response->assertInertia(fn (Assert $page) => $page
->has('message', fn (Assert $page) => $page
->has('subject')
->missing('published_at')
->etc()
)
);
Reducing verbosity
To reduce the amount of where, has or missing calls, there are a couple of convenience
methods that allow you to make these same assertions in a slightly less-verbose looking way. Do
note that these methods do not make your assertions any faster, and really only exist to help you
reduce your test's visual complexity.
has
Instead of making multiple has calls, you may use the hasAll assertion instead. Depending on
how you provide arguments, this method will perform a series of slightly different but predictable
assertion:
Basic has usage
$response->assertInertia(fn (Assert $page) => $page
// Before
->has('messages')
->has('subscribers')
// After
->hasAll([
'messages',
'subscribers',
])
// Alternative
->hasAll('messages', 'subscribers')
);
Count / Size / Length
$response->assertInertia(fn (Assert $page) => $page
// Before
->has('messages', 5)
->has('subscribers', 11)
// After
->hasAll([
'messages' => 5,
'subscribers' => 11,
])
);
where
To reduce the amount of where calls, the whereAll method exists.
Since this method checks properties against values by design, there isn't a lot of flexibility like with
some of these other methods, meaning that only the array-syntax exists for it right now:
$response->assertInertia(fn (Assert $page) => $page
// Before
->where('subject', 'Hello World')
->has('user.name', 'Claudio')
// After
->whereAll([
'subject' => 'Hello World',
'user.name' => fn ($value) => $value === 'Claudio',
])
);
missing
Instead of making multiple missing call, you may use missingAll instead.
Similar to basic hasAll usage, this assertion accepts both a single array or a list of arguments, at
which point it will assert that the given props do not exist:
$response->assertInertia(fn (Assert $page) => $page
// Before
->missing('subject')
->missing('user.name')
// After
->missingAll([
'subject',
'user.name',
])
// Alternative
->missingAll('subject', 'user.name')
);
Debugging
While writing your tests, you might find yourself wanting to inspect some of the page's props using
Laravel's dump or dd helpers. Luckily, this is really easy to do, and would work more or less how
you'd expect it to:
$response->assertInertia(fn (Assert $page) => $page
// Dumping all props in the current scope
// while still running all other assertions
->dump()
->where('user.name', 'Claudio')