Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 58 additions & 8 deletions src/WebAssert.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,17 @@ public function __construct(Session $session)
* Checks that current session address is equals to provided one.
*
* @param string $page
* @param bool $compareQueryString Whether the query string takes part in the comparison.
* Off by default, so suites comparing the path alone keep working.
*
* @return void
*
* @throws ExpectationException
*/
public function addressEquals(string $page)
public function addressEquals(string $page, bool $compareQueryString = false)
{
$expected = $this->cleanUrl($page);
$actual = $this->getCurrentUrlPath();
$expected = $this->cleanAddress($page, $compareQueryString);
$actual = $this->getCurrentAddress($compareQueryString);

$this->assert($actual === $expected, sprintf('Current page is "%s", but "%s" expected.', $actual, $expected));
}
Expand All @@ -63,15 +65,17 @@ public function addressEquals(string $page)
* Checks that current session address is not equals to provided one.
*
* @param string $page
* @param bool $compareQueryString Whether the query string takes part in the comparison.
* Off by default, so suites comparing the path alone keep working.
*
* @return void
*
* @throws ExpectationException
*/
public function addressNotEquals(string $page)
public function addressNotEquals(string $page, bool $compareQueryString = false)
{
$expected = $this->cleanUrl($page);
$actual = $this->getCurrentUrlPath();
$expected = $this->cleanAddress($page, $compareQueryString);
$actual = $this->getCurrentAddress($compareQueryString);

$this->assert($actual !== $expected, sprintf('Current page is "%s", but should not be.', $actual));
}
Expand All @@ -80,14 +84,16 @@ public function addressNotEquals(string $page)
* Checks that current session address matches regex.
*
* @param string $regex
* @param bool $compareQueryString Whether the query string is part of the address the regex is
* matched against. Off by default.
*
* @return void
*
* @throws ExpectationException
*/
public function addressMatches(string $regex)
public function addressMatches(string $regex, bool $compareQueryString = false)
{
$actual = $this->getCurrentUrlPath();
$actual = $this->getCurrentAddress($compareQueryString);
$message = sprintf('Current page "%s" does not match the regex "%s".', $actual, $regex);

$this->assert((bool) preg_match($regex, $actual), $message);
Expand Down Expand Up @@ -869,6 +875,50 @@ protected function cleanUrl(string $url)
return preg_replace('/^\/[^\.\/]+\.php\//', '/', $path).$fragment;
}

/**
* Gets the current address the way getCurrentUrlPath() does, optionally keeping its query string.
*
* Without the query string this is getCurrentUrlPath() itself, so a subclass overriding it keeps
* deciding what the address looks like for every assertion written before this option existed.
*/
private function getCurrentAddress(bool $compareQueryString): string
{
if (!$compareQueryString) {
return $this->getCurrentUrlPath();
}

return $this->cleanAddress($this->session->getCurrentUrl(), true);
}

/**
* Cleans the URL the way cleanUrl() does, optionally keeping its query string.
*
* The query is spliced back in front of the fragment rather than parsed here, so that a
* subclass overriding cleanUrl() keeps deciding what the rest of the address looks like.
*/
private function cleanAddress(string $url, bool $compareQueryString): string
{
$address = $this->cleanUrl($url);

if (!$compareQueryString) {
return $address;
}

$query = parse_url($url, \PHP_URL_QUERY);

if (!\is_string($query) || '' === $query) {
return $address;
}

$fragmentPosition = strpos($address, '#');

if (false === $fragmentPosition) {
return $address.'?'.$query;
}

return substr($address, 0, $fragmentPosition).'?'.$query.substr($address, $fragmentPosition);
}

/**
* Asserts a condition.
*
Expand Down
86 changes: 86 additions & 0 deletions tests/WebAssertTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,92 @@ function () {
);
}

public function testAddressEqualsWithQueryString()
{
$this->session
->expects($this->exactly(2))
->method('getCurrentUrl')
->will($this->returnValue('http://example.com/login?return_url=/user'))
;

$this->assertCorrectAssertion(function () {
$this->assert->addressEquals('/login?return_url=/user', true);
});
$this->assertWrongAssertion(
function () {
$this->assert->addressEquals('/login', true);
},
'Behat\\Mink\\Exception\\ExpectationException',
'Current page is "/login?return_url=/user", but "/login" expected.'
);
}

public function testAddressEqualsIgnoresTheQueryStringByDefault()
{
$this->session
->expects($this->once())
->method('getCurrentUrl')
->will($this->returnValue('http://example.com/login?return_url=/user'))
;

$this->assertCorrectAssertion(function () {
$this->assert->addressEquals('/login');
});
}

public function testAddressEqualsKeepsTheQueryStringInFrontOfTheFragment()
{
$this->session
->expects($this->once())
->method('getCurrentUrl')
->will($this->returnValue('http://example.com/script.php/sub/url?param=true#webapp/nav'))
;

$this->assertCorrectAssertion(function () {
$this->assert->addressEquals('/sub/url?param=true#webapp/nav', true);
});
}

public function testAddressNotEqualsWithQueryString()
{
$this->session
->expects($this->exactly(2))
->method('getCurrentUrl')
->will($this->returnValue('http://example.com/login?return_url=/user'))
;

$this->assertCorrectAssertion(function () {
$this->assert->addressNotEquals('/login?return_url=/admin', true);
});
$this->assertWrongAssertion(
function () {
$this->assert->addressNotEquals('/login?return_url=/user', true);
},
'Behat\\Mink\\Exception\\ExpectationException',
'Current page is "/login?return_url=/user", but should not be.'
);
}

public function testAddressMatchesWithQueryString()
{
$this->session
->expects($this->exactly(2))
->method('getCurrentUrl')
->will($this->returnValue('http://example.com/login?return_url=/user'))
;

$this->assertCorrectAssertion(function () {
$this->assert->addressMatches('/return_url/', true);
});
$this->assertWrongAssertion(
function () {
$this->assert->addressMatches('/return_url/');
},
'Behat\\Mink\\Exception\\ExpectationException',
'Current page "/login" does not match the regex "/return_url/".'
);
}

public function testAddressEqualsEmptyPath()
{
$this->session
Expand Down
Loading