5

Is there a straightforward way to simulate HTTP_REFERER in a Dusk test? I'm using Laravel\Dusk\Browser and calling the visit() method on various pages. This is using the Selenium driver.


Something like setReferer below:

namespace Example\Tests\Browser\Processes\PublicSite;

class SampleBrowser extends Browser {
    use MakesAssertions, ProvidesAdditionalBrowserActions, WaitsForElements;
    public function __construct(RemoteWebDriver $driver, $resolver = null)
    {
        parent::__construct($driver, new ElementResolver($driver,
                            $resolver->prefix ?? 'body'));
    }
}


class SampleTestCase extends BrowserTestCase
{
    /**
     * Test that the deal builder modal shows up.
     */
    public function testRefererRendering()
    {
        $this->browse(function (SampleBrowser $browser) {
            $browser
                // this is the bit that I want
                ->setReferer('https://example.org/') 
                ->visit('/')
                ->waitForLocation('/?came_via=example.org')
                ->assertCookieValue('came_via', 'example.org');
        });
    }
}
artlung
  • 33,305
  • 16
  • 69
  • 121
  • 1
    I don't think there is. Dusk doesn't allow you to send custom headers. – Jonas Staudenmeir Mar 11 '19 at 17:32
  • Glad to know I'm not missing something obvious @JonasStaudenmeir - is there a way to extend the Selenium driver to add it to the environment somehow? This is new to me. – artlung Mar 11 '19 at 17:39
  • 2
    I don't know, but I doubt it. If you google the overall topic, you'll find a lot of people asking for similar features. But the response is always the same: "Selenium's mission statement is to emulate user actions." In your case, that would mean visiting the referring page and actually clicking on the link. Also related: https://stackoverflow.com/q/51711350/4848587 – Jonas Staudenmeir Mar 11 '19 at 17:49
  • I hear that @JonasStaudenmeir. Of course, the external website clickthrough doesn't feed into my test environment, it feeds to my production environment. As to the link you posted, questioner could assertVisible that text unique to the sites 404 page was there. – artlung Mar 11 '19 at 18:09
  • 2
    What you could do: Visit the referring page and use JavaScript to replace the link target with your testing URL. Not very elegant, but the best option I see at the moment. – Jonas Staudenmeir Mar 11 '19 at 18:45
  • 1
    Show your test class or code fragment - that would help a lot. – Alex Mar 24 '19 at 16:43
  • @Alex added some sample code. – artlung Mar 27 '19 at 18:31
  • 1
    @artlung this is a workaround, but can you try visiting the referer website, then injecting a script that does `window.location = where_you_want`? – WoLfulus Mar 27 '19 at 18:44
  • @WoLfulus that seems like the same as what Jonas Staudenmeir above was saying. I wonder if I need to spin up a dummy instance of this other website so I'm not haphazardly loading referer website and sort of abusing their resources. – artlung Mar 27 '19 at 20:14
  • 1
    Are you going to do any complex tests or you just want to test the redirect? If you are just testing the redirect, you can do a request without selenium passing down the Referer and looking up for the resulting http status code and Location headers – WoLfulus Mar 28 '19 at 13:30
  • @WoLfulus I'm not sure I understand the distinction. But if simulating the redirect by faking the headers such that they get injected, and so the application/page *responds* by adding the cookie and the query string, that would suffice. – artlung Mar 28 '19 at 13:56
  • 1
    It just depends on how the application sets that kind of information (if its javascript in the frontend, that won't help much). You won't be using the browser in this case to make the request, so you're free to set the referer to whatever you want. Then you can check for cookies and/or redirects. – WoLfulus Mar 28 '19 at 16:56
  • yeah it's the underlying PHP that does the validation of the referer and sets state. Thanks for the answer @WoLfulus! – artlung Mar 28 '19 at 20:13
  • I'm still searching for better alternatives though :/ – WoLfulus Mar 29 '19 at 20:32

1 Answers1

7

Dusk or any Browser/Selenium testing solution doesn't implement this kind of feature, and it doesn't seem they ever will.

See https://github.com/seleniumhq/selenium-google-code-issue-archive/issues/2047

Option 1

Navigate to the referer URL, then inject a script that makes the page navigate to the one you want to test.

Option 2

Use a proxy server that intercepts the requests and sets the referer to the one you want

https://github.com/j-bennet/selenium-referer

Option 3

If you're trying to test the behaviour of the server-side code, you can always test it without fully emulating the client side with a browser.

For example:

<?php

namespace App\Http\Controllers;

use \Illuminate\Http\Request;
use Illuminate\Routing\Controller;

class HomeController extends Controller
{
    public function home(Request $request)
    {
        $referer = $request->header('Referer');
        if ($referer) {
            return redirect()->route('home', ['came_via' => $referer]);
        }
        return view('welcome');
    }
}

and the TestCase

<?php

namespace Tests\Feature;

use Tests\TestCase;

class RedirectTest extends TestCase
{
    /**
     * A basic redirect example.
     *
     * @return void
     */
    public function testRedirection()
    {
        // Normal request
        $response = $this->get('/');
        $response->assertStatus(200);

        // Referer check redirection
        $referer = 'http://google.com';
        $response = $this->call('GET', '/', [], [], [], ['HTTP_REFERER' => $referer]);
        $response->assertRedirect('/?came_via=' . urlencode($referer));
    }
}

Result

OK (2 tests, 4 assertions)
WoLfulus
  • 1,948
  • 1
  • 14
  • 21