How to get Ajax response in HTML Unit (it renders the HTML of the web page)
ajax, htmlunit, jquery, json, testing
Solution
I had a similar problem and found a solution using the HtmlUnit FAQ page:
You can subclass HttpWebConnection and override getResponse() as:
new WebConnectionWrapper(webClient) {
public WebResponse getResponse(WebRequest request) throws IOException {
WebResponse response = super.getResponse(request);
if (request.getUrl().toExternalForm().contains("my_url")) {
String content = response.getContentAsString("UTF-8");
//change content
WebResponseData data = new WebResponseData(content.getBytes("UTF-8"),
response.getStatusCode(), response.getStatusMessage(), >response.getResponseHeaders());
response = new WebResponse(data, request, response.getLoadTime());
}
return response;
}
};
What this means is that we can wrap our webClient object, intercept any request and response we need, extract them or make changes.
I made an inner class which extends WebConnectionWrapper, and has one field which is JSON I need:
private class JsonResponseWebWrapper extends WebConnectionWrapper{
public JsonResponseWebWrapper(WebClient webClient){
super(webClient);
}
String jsonResponse;
@Override
public WebResponse getResponse(WebRequest request) throws IOException {;
WebResponse response = super.getResponse(request);
//extract JSON from response
jsonResponse = response.getContentAsString();
return response;
}
public String getJsonResponse() {
return jsonResponse;
}
};
This way we will intercept every single response. But first we need to wrap the webClient. I did this just before requesting JSON response, so I didn't have to add conditions to my wrapper:
JsonResponseWebWrapper jrww = new JsonResponseWebWrapper(webClient);
page = button.click();
String rawJSON = jrww.getJsonResponse();
And after that you can parse it using your favorite JSON parser. Hope this helps!
Problem
I have a web application that returns JSON when I make AJAX requests to the server for CRUD operations. The reason of this is because I use jQuery to handle the data without refreshing the page (MVC), so if I create a new entry in the system, the server will return a response which have the created entry in JSON format. jQuery manages the data received and renders the entry on a list (with the previously created entries). Now I am testing it with HTML Unit, but if I try ``` WebResponse response = page.getWebResponse() ``` I get 200 status and message "OK". But I was expecting the JSON data of the entry I created. And if I try ``` page.asText() ``` I get the HTML of the current page (with the entry already in the list, but not the data I want). It is a similar issue than this one, that had no response: Json ajax call returning response 200 ok PD: The jQuery form has two fields, one is a text input for the name and another is a select for the car settings. I pass to this function a list of settings to select. The name is autogenerated with a timestamp and a static int seed. This is the code that I am using: ``` public void create(List<Settings> settings) throws FailingHttpStatusCodeException, MalformedURLException, IOException { page = webClient.getPage("localhost:8080/cars/list"); int elementsCount = getEntitiesCount(); creationSeed = elementsCount+1; HtmlAnchor anchor = (HtmlAnchor) page.getFirstByXPath("//a[@class='action-createCar']"); page = (HtmlPage) anchor.click(); HtmlForm form = page.getFirstByXPath("//form[@class='CarsForm']"); form = page.getForms().get(0); HtmlTextInput nameField = form.getInputByName("CarsForm-name"); nameField.setText("Test " + creationSeed + " - " + new Date().getTime()); HtmlSelect columnSelectList = (HtmlSelect) form.getSelectByName("CarsForm-settings"); if (settings != null && settings.size() > 0) for (Settings setting : settings) { HtmlOption htmlOption = columnSelectList.getOptionByValue(setting.name()); htmlOption.setSelected(true); } //looking for the button to submit the form HtmlDivision buttonSet = page.getFirstByXPath("//div[@class='ui-dialog-buttonset']"); HtmlButton okButton = (HtmlButton) buttonSet.getFirstElementChild(); page = okButton.click(); assertEquals(elementsCount + 1, getEntitiesCount()); //Here is where I want to get the server response to check the data which is returned by the server //And neither page.getWebResponse() or page.asText() contains it } ``` }