Two Codeception acceptance tests gotchas

AJAX and full URL matching.

The problem

While writing a Codeception acceptance test I came across the need to check the page URL for the existence of path and a query string.
Say I expect the URL to be http://example.com/index.php?foo=bar after visiting the homepage and clicking the “Foo” button; I want to make sure the query variable is in the URL and am running my acceptance tests using the Codeception WebDriver module.

I wrote this code in a Codeception Cest test case or in a straight Cept one:

$I->amOnPage('/');
$I->click('button.foo');

// some js will fire here and the `foo` query var should be appended to the URL

$I->seeInCurrentUrl('/index.php'); // failing
$I->seeInCurrentUrl('foo=bar');

Since this test is passing when manually done the first thought I’ve had is about timing: the automated test ran so fast the JS script had not updated the location yet when the tests fired; here it comes the first modification.

Waiting for Ajax to complete

In my case the JavaScript operation is an AJAX request and so I’ve modified the code to be sure, following this answer on Stackoverflow, that the test will wait for any jQuery triggered AJAX request to complete.

$I->amOnPage('/index.php');
$I->click('button.foo');

// some js will fire here and the `foo` query var should be appended to the URL
$I->waitForJs('return jQuery.active == 0', 10);

$I->seeInCurrentUrl('/index.php'); // passing
$I->seeInCurrentUrl('foo=bar'); // failing

First assertion is now passing but the second one is still failing.

Full URL

The second test is not working as the seeInCurrentUrl method of the WebDriver module is not checking the full URL but just the URI.
After some web search I’ve found a solution, again thanks to Stackoverflow that has made all assertions pass.
Pre-requirement for the tests to pass is the inclusion of the Asserts module in the acceptance.suite.yml file and a codecept build call, after that I’ve modified the test to use the new “powers” and make it pass.

$I->amOnPage('/index.php');
$I->click('button.foo');

// some js will fire here and the `foo` query var should be appended to the URL
$I->waitForJs('return jQuery.active == 0', 10);

$fullUrl = $I->executeJS('return location.href');
$I->assertContains('/index.php'); // passing
$I->assertContains('foo=bar'); // passing