This may be similar to 5660956, but I am doing a GET first...
I think the key here is Selenium, hence the tags. Just in case it matters: I'm working in Java, using NinjaFramewor, FluentLenium and Firefox. It runs locally, but also on a headless CI box with Xvfb. I have some FluentLenium tests passing, so the whole thing isn't broken!
I have a web page, with a simple login form that performs a call to JavaScript which does an AJAX POST. The AJAX response is caught by JavaScript and causes some of the body of the page to update, with different results for login, register and fail. I can see this happening when I test by hand, and even when I run these tests locally.
The test looks like this:
import org.fluentlenium.adapter.util.SharedDriver;
import org.fluentlenium.core.annotation.Page;
import org.junit.Test;
@SharedDriver(deleteCookies=true)
public class UserControllerTest extends JSTest {
@Page
HomePage home;
@Page
LoginPage login;
@Test
public void test_cantLoginUntilReg() {
goTo(login);
login.fillOutReg("test_cantLoginUntilReg");
login.chooseLogin(); // script that POSTS and does AJAX update
login.isErrorResult(); // errors
goTo(login);
login.fillOutReg("test_cantLoginUntilReg");
login.chooseRegister(); // script that POSTS and does AJAX update
login.isWelcomeResult(); // errors
login.chooseHome(); // GET on home
home.isLoggedIn(); // this works
}
// more tests
}
And the LoginPage, which is where I'm having trouble looks like (with a super class containing constants folded back in):
public class LoginPage extends FluentPage {
protected static final String HOME_PAGE = "http://localhost:8080";
private static final String PAGE = HOME_PAGE + "/login";
@AjaxElement
FluentWebElement welcomeDiv;
@AjaxElement
FluentWebElement errorDiv;
@Override
public String getUrl() {
return PAGE;
}
@Override
public void isAt() {
assertTrue("url is " + url(), url().contains("login"));
assertTrue("h1 is " + find("h1").getText(), find("h1").getText().contains("Login"));
assertTrue("h1 is " + find("h1").getText(), find("h1").getText().contains("Register"));
}
public void isErrorResult() {
assertTrue("h1 is " + find("h1").getText(), find("h1").getText().contains("Failed"));
assertNull("cookie is " + getCookie(SESSION_COOKIE_NAME), getCookie(SESSION_COOKIE_NAME));
}
public void fillOutReg(String testName) {
fill("#email").with(testName + "@UserControllerJSTests.test.com"); // this passes the minimal validation in place so far
fill("#password").with("reallyBadPassword");
fill("#identName").with(testName);
}
public void chooseLogin() {
executeScript(LOGIN_SCRIPT); // I'd prefer click on the form, but that seemed to be a source of trouble as well
}
// and so on
}
The isErrorResult() method is never satisfied! The find h1 shows that the h1 text is still as it was when the page was first loaded. Clearing the session cookie is showing different behaviour on different machines (probably needs to wait for something). I've also tried testing the contents of welcomeDiv. I have a feeling I ought to be able to use the @AjaxElement to help here, but I haven't quite worked out how.
I don't want to inspect the JSON coming back. I've got tests which don't involve Selenium that get pretty close to this already.
What I want to do is automate checking that the user will see the right thing at the browser end after a POST. Even if there is a work-around for this code, other functionality will have large enough uploads that GET really isn't sensible; and testable AJAX seems like a reasonable want.
Any ideas, please?