Merklin's avatar

PHPUnit test fails when it should pass

Hi all. I am running this test, where in fact I am testing my polices, that a user cannot do what he is not supposed to:

For some reason, the test cannot_delete_foreign_record fails i.e. the client is deleted, when it should not, because in my Client model policy I have this:

    /**
     * Determine whether the user can delete the client.
     */
    public function delete(User $user, Client $client): bool
    {
        return $user->can('delete_client') || $client->user_id === $user->id;
    }

The test result:

The assigned role 'ProjectOwner' doesn't have permission to delete_client.

What am I doing wrong on my test? Because all the other tests pass.

0 likes
9 replies
mhdev's avatar

Does your Client model use Soft Deletes? If so, then it could be because of that - because the database record still exists, but the deleted_at column will now be set, rather than null.

Merklin's avatar

@mhdev No, no soft-deletes. But even with soft deletes, it will remain in the database.

In the test, the record MUST remain in the database, while actually it got deleted, which is wrong.

According to the policy, a user should not be able to delete a client that belongs to another user.

Tray2's avatar

Does it pass if you run only that test?

Merklin's avatar

@Tray2 No, fails again. Even did dd() of $this->foreignClient and `$user->id`` just to be sure they are different.

In fact, I am currently running only this class and tried even only this method: fails every time.

Also tried to create a completely new client inside the method: failed again.

It makes no sense to me: cannot_edit_foreign_record and cannot_delete_foreign_record are basically same, but the edit pass and the delete fails.

Tray2's avatar

@Merklin Hmm, I guess the project owner has the right to delete whatever in that project, so maybe that is the issue?

Niush's avatar

Umm.. you are directly calling $this->foreignClient->delete(); so it of course deletes from the database. You know like Client::find(1)->delete()?

Shouldn't you be testing the route? like:

// $this->actingAs($this->user);
$response = $this->delete('/clients/1');
$response->assertStatus(403);

Or, you can also simply test policies:

$clientPolicy = new ClientPolicy();
$result = $clientPolicy->delete($user, $client);
$this->assertFalse($result); // i.e. cannot delete
Merklin's avatar

@Niush There is no delete route, it's a filament table. But even in this case, the policy should work.

Niush's avatar

@Merklin The policy won't get triggered when calling Model's delete function. It is triggered from middleware, Gate, etc.

I have edited above, but you could instead test the policy itself. Like this:

$clientPolicy = new ClientPolicy();
$result = $clientPolicy->delete($user, $client);
$this->assertFalse($result); // i.e. cannot delete

Please or to participate in this conversation.