Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Has test helper and scoping into first result #226

Closed
malinky opened this issue Mar 9, 2021 · 2 comments
Closed

Has test helper and scoping into first result #226

malinky opened this issue Mar 9, 2021 · 2 comments

Comments

@malinky
Copy link

malinky commented Mar 9, 2021

Hi, I'm trying to use the has and where test helpers and I can't understand why the following test is failing.

users.data is returned from Laravel's paginate method and I'm trying to assert that there is 1 result and then scope into that result and assert that the email of that user is thisusersemail@example.com.

$response
            ->assertStatus(200)
            ->assertInertia(fn (InertiaAssert $page) => $page
                ->has('users.data', 1, fn (InertiaAssert $page) => $page
                    ->where('email', 'thisusersemail@example.com')
                )
);

I then get the following test failure which lists the other properties on the users model but without the email property.

1) Tests\Feature\User\UserTest::test_can_search_users
Unexpected Inertia properties were found in scope [users.data.0].
Failed asserting that two arrays are identical.
--- Expected
+++ Actual
@@ @@
-Array &0 ()
+Array &0 (
+    0 => 'id'
+    1 => 'username'
+    2 => 'first_name'
+    3 => 'surname'
+    5 => 'email_verified_at'
+    6 => 'blocked'
+    7 => 'created_at'
+    8 => 'updated_at'
+)

I've dumped the $page variable and it does include the correct email address. I'm not sure if this is a bug or I'm using the helpers incorrectly.

For reference I can make the test pass using the following assertions but I'd like to combine the count and then scope straight into the first result as mentioned in the documentation.

$response
            ->assertStatus(200)
            ->assertInertia(fn (InertiaAssert $page) => $page
                ->has('users.data', 1)
                ->has('users.data', fn (InertiaAssert $page) => $page
                ->where('0.email', 'thisusersemail@example.com')
            )
);

Thanks for your help.

@claudiodekker
Copy link
Member

claudiodekker commented Mar 9, 2021

Hi,

Although your assertions are all passing, the reason the test itself is still failing is because of the built-in interaction check.

This check automatically occurs in every has scope except for the top/root-level one, and it's goal is to prevent your tests from silently passing when you (for instance) accidentally start exposing some field(s) that weren't meant to be included in your response (e.g. the password field, credit card details, etc..)

The recommended way to solve this, is to interact with all fields in that scope using the has, hasAll or where methods:

        $response
            ->assertStatus(200)
            ->assertInertia(fn (InertiaAssert $page) => $page
                ->has('users.data', 1, fn (InertiaAssert $page) => $page
                    ->where('email', 'thisusersemail@example.com')
                    ->hasAll([
                        'id',
                        'username',
                        'first_name',
                        'surname',
                        'email_verified_at',
                        'blocked',
                        'created_at',
                        'updated_at'
                    ]) 
                )
            );

Alternatively, if you simply don't care about this automatic behaviour, you can chain ->etc() on the end of that scope, which will disable this interaction check entirely. Do note that when you do this, this means that in order to test that a field is not included, you'll need to use the missing method (which isn't needed by default / when the interaction check is enabled):

        $response
            ->assertStatus(200)
            ->assertInertia(fn (InertiaAssert $page) => $page
                ->has('users.data', 1, fn (InertiaAssert $page) => $page
                    ->where('email', 'thisusersemail@example.com')
                    ->missing('password')
                    ->etc()
                )
            );

In case the above still doesn't make sense, I've written a more in-depth explanation of it here:
laravel/framework#36454 (comment)

Hope this helps!

@malinky
Copy link
Author

malinky commented Mar 9, 2021

Thank you for the detailed response and also the additional link. That makes sense now and I've got my tests passing using either of your suggested methods. Great to see this integrated into the Inertia Laravel adapter now and also the Laravel framework. Thanks again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants