package example.domain.web.nodriver;
import org.apache.commons.lang.StringUtils;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.mock.web.MockHttpServletRequest;
import static ch.lambdaj.Lambda.having;
import static ch.lambdaj.Lambda.on;
import static ch.lambdaj.collection.LambdaCollections.with;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
@SuppressWarnings({"unchecked"})
public class HtmlForm {
private final Element form;
private final Browser browser;
public HtmlForm(Element form, Browser browser) {
this.browser = browser;
this.form = form;
}
public void setInputValue(String fieldName, String value) {
input(fieldName).val(value);
}
public void showsInputValue(String fieldName, String value) {
assertThat(fieldName, input(fieldName).val(), equalTo(value));
}
public void selectOptionByValue(String fieldName, String value) {
for (Element option : options(fieldName, "option")) {
if (option.val().equals(value)) {
option.attr("selected", "selected");
} else {
option.removeAttr("selected");
}
}
}
public void showsSelectedOptionWithValue(String fieldName, String value) {
Elements options = options(fieldName, "option[selected]");
if (!with(options).exists(having(on(Element.class).val(), equalTo(value)))) {
fail("Select '" + fieldName + "' does not have '" + value + "' selected in " + form.outerHtml());
}
}
public <T> T submitAndExpect(Class<T> pageClass) {
String method = StringUtils.defaultIfEmpty(form.attr("method"), "post");
String action = StringUtils.defaultIfEmpty(form.attr("action"), browser.currentURI());
MockHttpServletRequest request = new MockHttpServletRequest(method.toUpperCase(), action);
addTextFieldValues(request);
addSelectedOptions(request);
return browser.send(request, pageClass);
}
private void addTextFieldValues(MockHttpServletRequest request) {
for (Element input : form.select("input[type=text]")) {
request.addParameter(input.attr("name"), input.val());
}
}
private void addSelectedOptions(MockHttpServletRequest request) {
for (Element select : form.select("select")) {
String name = select.attr("name");
Elements selected = select.select("option[selected]");
if (selected.isEmpty()) {
Elements options = select.select("option");
if (options.size() > 0) {
request.addParameter(name, options.first().val());
}
} else {
for (Element option : selected) {
request.addParameter(name, option.val());
}
}
}
}
private Element input(String fieldName) {
return first("input[name=" + fieldName + "][type=text]");
}
private Elements options(String fieldName, String option) {
String query = "select[name=" + fieldName + "] " + option;
Elements options = form.select(query);
if (options.isEmpty()) {
fail("Cannot find " + query + " in " + form.outerHtml());
}
return options;
}
private Element first(String selector) {
Elements elements = form.select(selector);
if (elements.isEmpty()) {
fail("Cannot find " + selector + " in " + form.outerHtml());
return null;
}
return elements.first();
}
}