user12003867
user12003867

Reputation:

Laravel Sanctum testing

I'm trying to test my API auth methods, so I created ConfirmPasswordControllerTest with:

/** @test */
public function confirm_password_confirms()
{
    $user = factory(User::class)->create();
    $data = ['password' => 'password'];

    $response = $this->actingAs($user)
                ->post('api/password-confirmation', $data);

    dd($response);
    $response->assertStatus(200);
}

I use dd() to check error messages in the response and I see all time:

RuntimeException: Session store not set on request.

I can't understand what happens here, I'm using Laravel Sanctum so my api routes have the auth:sanctum middleware.

EDIT: If I don't include any data in the post like:

$response = $this->postJson('api/password-confirmation');

The test runs as expected:

{"message":"The given data was invalid.","errors":{"password":["The password field is required."]}}

EDIT 2: I debug the app and I see the problem is with the PasswordConfirmController:

public function confirm(Request $request)
{
    $request->validate($this->rules(), $this->validationErrorMessages());

    $this->resetPasswordConfirmationTimeout($request); //HERE

    return $request->wantsJson()
                ? new Response('', 204)
                : redirect()->intended($this->redirectPath());
}

It calls resetPasswordConfirmationTimeout() and this method need to use a session:

protected function resetPasswordConfirmationTimeout(Request $request)
{
    $request->session()->put('auth.password_confirmed_at', time());
}

Upvotes: 3

Views: 1698

Answers (1)

Tahiaji
Tahiaji

Reputation: 430

This is quite an old question, but I ran into a similar problem and spent some time solving it. It is quite simple, but not obvious.

If EnsureFrontendRequestsAreStateful middleware is used for Sanctum, then there is interesting logic that connects additional middlewares (frontendMiddleware()) if the request comes from the frontend.

The frontendMiddleware method contains StartSession::class, which we need to start the session. The condition for its triggering is the presence of referer or origin headers with domain from sanctum.stateful config.

Accordingly, all we need to do is add a header to the request.

$response = $this->actingAs($user)
    ->post(
        'api/password-confirmation', 
        $data,
        ['referer' => 'localhost'],  //set any domain from `sanctum.stateful` config. 
    );

Upvotes: 0

Related Questions