Description
I’ve got an application that only allows you to visit a url once (doing the same request again takes you elsewhere).
For example, imagine a wizard (or a purchase flow), something like this:
Step 1 > Step 2 > Step 3 > Step 4
...where between each step, the user POSTs a form and gets redirected to the next page using a standard Post/Redirect/Get flow.
...and the system is built so that going back/forward unexpectedly in the flow should take me to step 1.
For example:
- browser back button should take me to step 1
- browser back + forward button should take me to step 1
When I’m using BrowserKit to write a test for my application, it doesn't seem to do the same thing as my browser does.
This is how my regular browser (Chrome/Firefox) behaves (with HTTP requests in parentheses
):
- I visit the first page (
GET /wizard-view-step-1
) - I submit my choices (
POST /wizard-complete-step-1
) - I get redirected to the next page (
GET /wizard-view-step-2
) - I submit my choices (
POST /wizard-complete-step-2
) - I get redirected to the next page (
GET /wizard-view-step-3
) - I click my browser's back button (
GET /wizard-view-step-2
) <-- notice the skipping of the previous POST (no 4 above) and going directly to the last GET request (no 3 above), as per the Post/Redirect/Get pattern. - I get redirected to the first page (
GET /wizard-view-step-1
) - I click my browser's forward button (
GET /wizard-view-step-3
) <-- notice that my browser still remembers the page I've "already been to in the future" and takes me there. - I get redirected to the first page (
GET /wizard-view-step-1
)
...however...
When I do this with BrowserKit, there are 2 major differences compared to my regular graphical browser:
A) History->back()
doesn't follow "PRG" (Post/Redirect/Get) flows correctly. It only steps backwards 1 step in my history, not skipping the POST requests that returned a redirect (HTTP status 3xx
).
B) Being redirected differently when going back clears "future history". In BrowserKit (assuming that I manually skip the POST
requests), when I go back (no 6 above), get redirected (no 7) and then try to go forward again I get a \LogicException
with You are already on the last page
.
Here's a simplified unit test (for BrowserKit\History
) to illustrate "B" above (assuming we're keeping PRG flows out of the equation for now):
public function testBackAndForward()
{
$history = new History();
$history->add(new Request('http://www.example.com/wizard-view-step-1', 'get'));
$history->add(new Request('http://www.example2a.com/wizard-view-step-2', 'get'));
$history->add(new Request('http://www.example2a.com/wizard-view-step-3', 'get'));
$history->back();
$history->add(new Request('http://www.example.com/wizard-view-step-1', 'get'));
$history->forward();
$this->assertSame(
'http://www.example.com/wizard-view-step-3',
$history->current()->getUri(),
'->forward() returns the next request in the history'
);
}