Enrique Moreno Tent
Enrique Moreno Tent

Reputation: 25267

Laravel - Testing what happens after a redirect

I have a controller that after submitting a email, performs a redirect to the home, like this:

return Redirect::route('home')->with("message", "Ok!");

I am writing the tests for it, and I am not sure how to make phpunit to follow the redirect, to test the success message:

public function testMessageSucceeds() {
    $crawler = $this->client->request('POST', '/contact', ['email' => '[email protected]', 'message' => "lorem ipsum"]);

    $this->assertResponseStatus(302);
    $this->assertRedirectedToRoute('home');

    $message = $crawler->filter('.success-message');

    // Here it fails
    $this->assertCount(1, $message);
}

If I substitute the code on the controller for this, and I remove the first 2 asserts, it works

Session::flash('message', 'Ok!');
return $this->makeView('staticPages.home');

But I would like to use the Redirect::route. Is there a way to make PHPUnit to follow the redirect?

Upvotes: 37

Views: 39750

Answers (6)

huntie
huntie

Reputation: 1060

You can get PHPUnit to follow redirects with:

Modern Laravel (>= 5.5.19):

$this->followingRedirects();

Older Laravel (< 5.4.12):

$this->followRedirects();

Usage:

$response = $this->followingRedirects()
    ->post('/login', ['email' => '[email protected]'])
    ->assertStatus(200);

Note: This needs to be set explicitly for each request.


For versions between these two:

See https://github.com/laravel/framework/issues/18016#issuecomment-322401713 for a workaround.

Upvotes: 68

DEV Tiago Fran&#231;a
DEV Tiago Fran&#231;a

Reputation: 1696

//routes/web.php
Route::get('/', function () {
    return redirect()->route('users.index');
})->name('index');


//on my TestClass
$response = $this->get('/');


$response->assertStatus(302);
$response->assertRedirect(route('users.index'));

Upvotes: 1

H&#233;ctor William
H&#233;ctor William

Reputation: 796

Laravel 8 tested

$response = $this->post'/contact', ['email' => '[email protected]', 'message' => "lorem ipsum"]);

$response->assertStatus(302);
$response->assertRedirect('home');

$this->followRedirects($response)->assertSee('.success-message');
//or
$this->followRedirects($response)->assertSee('Ok!');

Worked for me, hoped it helps.

Upvotes: 12

yesnik
yesnik

Reputation: 4695

Since Laravel 5.5 to test redirect you can use assertRedirect:

/** @test */
public function store_creates_claim()
{
    $response = $this->post(route('claims.store'), [
        'first_name' => 'Joe',
    ]);

    $response->assertRedirect(route('claims.index'));
}

Upvotes: 4

Ryan Firth
Ryan Firth

Reputation: 1

For Laravel 5.6, you can set

$protected followRedirects = true;

within your class file for your test case

Upvotes: -4

jsawo
jsawo

Reputation: 131

You can tell crawler to follow a redirect this way:

$crawler = $this->client->followRedirect();

so in your case that would be something like:

public function testMessageSucceeds() {
    $this->client->request('POST', '/contact', ['email' => '[email protected]', 'message' => "lorem ipsum"]);

    $this->assertResponseStatus(302);
    $this->assertRedirectedToRoute('home');

    $crawler = $this->client->followRedirect();

    $message = $crawler->filter('.success-message');

    $this->assertCount(1, $message);
}

Upvotes: 8

Related Questions