myol
myol

Reputation: 9838

Testing redirect links to external sites

I have a link on a page /my/example/page which links to a laravel route my.route.

Route

Route::group(['middleware' => ['auth']], function () {
    Route::group(['middleware' => ['Some\Custom\Auth\Middleware:1']], function () {
        Route::match(['GET', 'POST'], '/my/route/to/external/controller', 'exampleController@externalLink')->name('my.route');
    }
}    

Link on /my/example/page

<a href="/my/route/to/external/controller">Link</a>

This route /my/route/to/external/controller points to this controller method externalLink in the exampleController controller, which returns the url for the href to use

public function externalLink()
{
    return $this->redirect->away('www.externalsite.com');
}

My test is

$this->visit(/my/example/page)
     ->click('Link')
     ->assertRedirectedToRoute('my.route');

I constantly get the error

Symfony\Component\HttpKernel\Exception\NotFoundHttpException

when I use the click() testing method.

I can catch this using @expectedException but his doesn't help as I am expecting to see a different page.

I have also tried (not together);

->assertResponseStatus(200);
->seePageIs('www.externalsite.com');
->assertRedirect();
->followRedirects();

From browser inspection, when the url is clicked I get

http://www.example.com/my/route/to/external      302
http://www.externalsite.com                      200

How can I functionally test the button being clicked and redirecting to an external site?

Upvotes: 19

Views: 2663

Answers (2)

mercuryseries
mercuryseries

Reputation: 41

A simple way is to use the get method instead of visit.

An example: $this->get('/facebook') ->assertRedirectedTo('https://www.facebook.com/Les-Teachers-du-NET-516952535045054');

Upvotes: 2

AndyBeeSee
AndyBeeSee

Reputation: 206

I am struggling with a similar problem right now, and I have just about given up on testing the endpoint directly. Opting for a solution like this...

Test that the link contains proper information in the view:

$this->visit('/my/example/page')
    ->seeElement('a', ['href' => route('my.route')]);

Moving the logic in the controller to something you can test directly. The Laravel\Socialite package has some interesting tests that might be helpful if you do this...

class ExternalLinkRedirect {
    public function __construct($request){
        $this->request = $request;
    }

    public function redirect()
    {
        return redirect()->away('exteranlsite.com');
    }
}

Then test it directly

    $route = route('my.route');
    $request = \Illuminate\Http\Request::create($route);
    $redirector = new ExternalLinkRedirect($request);
    $response = $redirector->redirect();
    $this->assertEquals('www.externalsite.com', $response->getTargetUrl());

Upvotes: 4

Related Questions