Search code examples
phplaravelvalidationphpunitvalidationrules

Laravel exists custom validation rule unable to validate user id with phpunit


I have a validation rule taken from the Laravel Documentation which checks if the given ID belongs to the (Auth) user, however the test is failing as when I dump the session I can see the validation fails for the exists, I get the custom message I set.

I have dumped and died the factory in the test and the given factory does belong to the user so it should validate, but it isn't.

Controller Store Method

 $ensureAuthOwnsAuthorId = Rule::exists('authors')->where(function ($query) {
        return $query->where('user_id', Auth::id());
    });

    $request->validate([
        'author_id' => ['required', $ensureAuthOwnsAuthorId],
    ],
    [
        'author_id.exists' => trans('The author you have selected does not belong to you.'),
    ]);

PHPUnit Test

/**
 * @test
 */
function adding_a_valid_poem()
{
   // $this->withoutExceptionHandling();

    $user = User::factory()->create();

    $response = $this->actingAs($user)->post(route('poems.store'), [
        'title'        => 'Title',
        'author_id'    => Author::factory()->create(['name' => 'Author', 'user_id' => $user->id])->id,
        'poem'         => 'Content',
        'published_at' => null,
    ]);

    tap(Poem::first(), function ($poem) use ($response, $user)
    {
        $response->assertStatus(302);
        $response->assertRedirect(route('poems.show', $poem));
        $this->assertTrue($poem->user->is($user));
        $poem->publish();
        $this->assertTrue($poem->isPublished());
        $this->assertEquals('Title', $poem->title);
        $this->assertEquals('Author', $poem->author->name);
        $this->assertEquals('Content', $poem->poem);
    });
}

Any assistance would be most appreciated, I'm scratching my head at this. My only guess is that the rule itself is wrong somehow. All values are added to the database so the models are fine.

Thank you so much!


Solution

  • In your Rule::exists(), you need to specify column otherwise laravel takes the field name as column name

    Rule::exists('authors', 'id')
    

    Since column was not specified, your code was basically doing

    Rule::exists('authors', 'author_id')