Framework: [5.4] Follow redirects for HTTP tests

Created on 20 Feb 2017  路  12Comments  路  Source: laravel/framework

  • Laravel Version: 5.4.12
  • PHP Version: 7.0

Description:

I noticed that the followRedirects() method is not in the new HTTP tests API. Is this intended or is this something that can be added?

Here is what I added to my TestCase abstract class.

protected function followRedirects(TestResponse $response)
{
    while ($response->isRedirect()) {
        $response = $this->get($response->headers->get('Location'));
    }

    return $response;
}

Example Test:

/** @test */
public function it_redirects_to_login_if_user_is_not_authenticated_with_a_flash_message()
{
    $response = $this->get('/home')->assertRedirect('/login');

    $this->followRedirects($response)
        ->assertSee('Login to continue.');
}

Most helpful comment

Hi @naveen519,

I ended up using the example I described above. I just created my own followRedirects($response) method.

Although, if you want to try using a macro, this might be another solution. To be honest, I think this might be a cleaner solution then the one above.

What do you think?

class ExampleTest extends TestCase
{
    protected function setUp()
    {
        parent::setUp();

        TestResponse::macro('followRedirects', function ($testCase) {
            $response = $this;

            while ($response->isRedirect()) {
                $response = $testCase->get($response->headers->get('Location'));
            }

            return $response;
        });
    }

    /** @test */
    function follow_redirects()
    {
        $this->get('/home')
            ->assertRedirect('/login')
            ->followRedirects($this)
            ->assertSee('Login to continue.');  
    }
}

All 12 comments

Hey nathanjisaac,

Got the same issue here, how did you manage to resolve it ? Any solution ?

Thanks,

Hi @naveen519,

I ended up using the example I described above. I just created my own followRedirects($response) method.

Although, if you want to try using a macro, this might be another solution. To be honest, I think this might be a cleaner solution then the one above.

What do you think?

class ExampleTest extends TestCase
{
    protected function setUp()
    {
        parent::setUp();

        TestResponse::macro('followRedirects', function ($testCase) {
            $response = $this;

            while ($response->isRedirect()) {
                $response = $testCase->get($response->headers->get('Location'));
            }

            return $response;
        });
    }

    /** @test */
    function follow_redirects()
    {
        $this->get('/home')
            ->assertRedirect('/login')
            ->followRedirects($this)
            ->assertSee('Login to continue.');  
    }
}

I think this is also possible/cleaner:

class ExampleTest extends TestCase
{
    protected function setUp()
    {
        parent::setUp();

        $test = $this;

        TestResponse::macro('followRedirects', function ($testCase = null) use ($test) {
            $response = $this;
            $testCase = $testCase ?: $test;

            while ($response->isRedirect()) {
                $response = $testCase->get($response->headers->get('Location'));
            }

            return $response;
        });
    }

    /** @test */
    function follow_redirects()
    {
        $this->get('/home')
            ->assertRedirect('/login')
            ->followRedirects()                 // no need to pass $this
            ->assertSee('Login to continue.');  
    }
}

@ajcastro is it possible to put the macro in the TestCase abstract class?

@lucasff, absolutely!. That's what I actually did.

Any thought into making a PR for this?

A problem I can see here is about HTTP methods. What if the request is a POST, PATCH, DELETE... request? With the current behaviour, it'd be converted to a GET request...

I'm not aware of any browsers that don't change the method to GET for a 301. The spec says "a user agent MAY change the request method from POST to GET for the subsequent request," but are there _any_ that don't do this? I know it would break all my applications if redirects from POST requests were also made as POST requests. That's not what my routing is setup as.

Anyway, this macro is very useful and I would love to see it included in TestResponse.

Hello, can someone please open a PR to re-introduce the function?

The workarounds mentioned above do not work anymore. I gives the error

PHP Fatal error: Declaration of Tests\Unit\RouteTest::setUp() must be compatible with Illuminate\Foundation\Testing\TestCase::setUp(): void in /path/to/laravel-application/php/tests/Unit/RouteTest.php on line 75

I am in need of a mechanism to follow redirects because my routes go through an authentication middleware which redirects to the requested page.

@davehowson - See #21771.

@davehowson just change the protected function setUp() to protected function setUp(): void

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jackmu95 picture jackmu95  路  3Comments

SachinAgarwal1337 picture SachinAgarwal1337  路  3Comments

Fuzzyma picture Fuzzyma  路  3Comments

gabriellimo picture gabriellimo  路  3Comments

felixsanz picture felixsanz  路  3Comments