From 680da44789aa1612aa84f7b962a32b3461799b3b Mon Sep 17 00:00:00 2001 From: Nikolay Labinskiy Date: Fri, 7 Apr 2017 14:39:54 +0300 Subject: [PATCH] [BrowserKit] Emulate back/forward browser navigation --- src/Symfony/Component/BrowserKit/CHANGELOG.md | 3 +++ src/Symfony/Component/BrowserKit/Client.php | 15 +++++++++++++-- .../Component/BrowserKit/Tests/ClientTest.php | 19 +++++++++++++++++++ 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/BrowserKit/CHANGELOG.md b/src/Symfony/Component/BrowserKit/CHANGELOG.md index 036595c9b458..3ddc3d7c5238 100644 --- a/src/Symfony/Component/BrowserKit/CHANGELOG.md +++ b/src/Symfony/Component/BrowserKit/CHANGELOG.md @@ -7,6 +7,9 @@ CHANGELOG * [BC BREAK] The request method is dropped from POST to GET when the response status code is 301. + * [BC BREAK] Client will skip redirects during history navigation + (back and forward calls) according to W3C Browsers recommendation + 3.2.0 ----- diff --git a/src/Symfony/Component/BrowserKit/Client.php b/src/Symfony/Component/BrowserKit/Client.php index 50bcca301a3e..5ceabb569a25 100644 --- a/src/Symfony/Component/BrowserKit/Client.php +++ b/src/Symfony/Component/BrowserKit/Client.php @@ -42,6 +42,7 @@ abstract class Client private $maxRedirects = -1; private $redirectCount = 0; + private $redirects = array(); private $isMainRequest = true; /** @@ -328,6 +329,8 @@ public function request($method, $uri, array $parameters = array(), array $files } if ($this->followRedirects && $this->redirect) { + $this->redirects[serialize($this->history->current())] = true; + return $this->crawler = $this->followRedirect(); } @@ -430,7 +433,11 @@ protected function createCrawlerFromContent($uri, $content, $type) */ public function back() { - return $this->requestFromRequest($this->history->back(), false); + do { + $request = $this->history->back(); + } while (array_key_exists(serialize($request), $this->redirects)); + + return $this->requestFromRequest($request, false); } /** @@ -440,7 +447,11 @@ public function back() */ public function forward() { - return $this->requestFromRequest($this->history->forward(), false); + do { + $request = $this->history->forward(); + } while (array_key_exists(serialize($request), $this->redirects)); + + return $this->requestFromRequest($request, false); } /** diff --git a/src/Symfony/Component/BrowserKit/Tests/ClientTest.php b/src/Symfony/Component/BrowserKit/Tests/ClientTest.php index 5bd4dad7b6ec..9c7267e83b72 100644 --- a/src/Symfony/Component/BrowserKit/Tests/ClientTest.php +++ b/src/Symfony/Component/BrowserKit/Tests/ClientTest.php @@ -573,6 +573,25 @@ public function testForward() $this->assertEquals($content, $client->getRequest()->getContent(), '->forward() keeps content'); } + public function testBackAndFrowardWithRedirects() + { + $client = new TestClient(); + + $client->request('GET', 'http://www.example.com/foo'); + $client->setNextResponse(new Response('', 301, array('Location' => 'http://www.example.com/redirected'))); + $client->request('GET', 'http://www.example.com/bar'); + + $this->assertEquals('http://www.example.com/redirected', $client->getRequest()->getUri(), 'client followed redirect'); + + $client->back(); + + $this->assertEquals('http://www.example.com/foo', $client->getRequest()->getUri(), '->back() goes back in the history skipping redirects'); + + $client->forward(); + + $this->assertEquals('http://www.example.com/redirected', $client->getRequest()->getUri(), '->forward() goes forward in the history skipping redirects'); + } + public function testReload() { $client = new TestClient();