Two Codeception acceptance tests gotchas
November 4, 2015
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