package lt.inventi.wicket.component.autocomplete; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNotNull; import static junit.framework.Assert.assertNull; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.nullValue; import static org.junit.Assert.assertThat; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import net.sf.json.JSONArray; import net.sf.json.JSONObject; import org.apache.wicket.Component; import org.apache.wicket.markup.html.form.Form; import org.apache.wicket.markup.html.form.HiddenField; import org.apache.wicket.markup.html.form.SubmitLink; import org.apache.wicket.markup.html.panel.Panel; import org.apache.wicket.model.IModel; import org.apache.wicket.model.Model; import org.apache.wicket.protocol.http.mock.MockHttpServletResponse; import org.apache.wicket.util.tester.FormTester; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import lt.inventi.wicket.component.autocomplete.Autocomplete.ValueField; import lt.inventi.wicket.resource.ResourceSettings; import lt.inventi.wicket.test.BaseNonInjectedTest; public class AutoCompleteTest extends BaseNonInjectedTest { private Autocomplete<Long, TestObject, SearchObject> autoComplete; private Panel panel; private List<SearchObject> list; private IModel<TestObject> model; @Before public void setUp(){ ResourceSettings.installEmpty(tester.getApplication()); list = new ArrayList<SearchObject>(); list.add(new SearchObject("1", "SomeName", "SomeDescription")); list.add(new SearchObject("2", "OldName", "OldDescription")); list.add(new SearchObject("3", "OtherName", "OtherDescription")); model = new Model<TestObject>(new TestObject(2L, "OldName")); autoComplete = new Autocomplete<Long, TestObject, SearchObject>("autoComplete", model); autoComplete.setSearchProvider(new SearchProvider()); autoComplete.setDataProvider(new DataProvider()); autoComplete.setDataValueProvider(new DataLabelProvider()); autoComplete.setNewItemHandler(new NewItemProvider()); panel = new TestPanel("panel"); Form<TestObject> form = new Form<TestObject>("form", new Model<TestObject>()); form.add(autoComplete); panel.add(form); tester.startComponentInPage(panel); } @Test public void testQuery(){ tester.getRequest().getPostParameters().addParameterValue("term", "test text"); tester.getRequest().getPostParameters().addParameterValue("limit", "10"); autoComplete.onQuery(); tester.processRequest(tester.getRequestCycle().getRequestHandlerScheduledAfterCurrent()); MockHttpServletResponse response = tester.getLastResponse(); assertThat(response.getContentType(), equalTo("application/json; charset=utf-8")); assertThat(response.getHeader("Expires"), equalTo("Mon, 26 Jul 1997 05:00:00 GMT")); assertThat(response.getHeader("Cache-Control"), equalTo("no-cache, must-revalidate")); assertThat(response.getHeader("Pragma"), equalTo("no-cache")); JSONArray items = JSONArray.fromObject(response.getDocument()); assertThat(((JSONObject) items.get(0)).get("id").toString(), equalTo("1")); assertThat(((JSONObject) items.get(0)).get("label").toString(), equalTo("SomeName - SomeDescription")); assertThat(((JSONObject) items.get(1)).get("id").toString(), equalTo("2")); assertThat(((JSONObject) items.get(1)).get("label").toString(), equalTo("OldName - OldDescription")); } @Test public void rerendersValueFieldInput() { tester.newFormTester("panel:form") .setValue("autoComplete:id", "3") .submit(); assertThat(model.getObject().id, is(3L)); assertThat(autoComplete.getValueField().getModelObject(), equalTo("OtherName")); autoComplete.clearAllInput(); panel.render(); assertThat(autoComplete.getValueField().getModelObject(), equalTo("OtherName")); } @Test public void rendersEmptyValueWhenModelObjectIsNulledOut() { tester.newFormTester("panel:form") .setValue("autoComplete:id", "3") .submit(); assertThat(autoComplete.getValueField().getModelObject(), equalTo("OtherName")); autoComplete.setModelObject(null); panel.render(); assertThat(autoComplete.getValueField().getModelObject(), is(nullValue())); } @Test public void testStructure(){ tester.assertComponent("panel:form:autoComplete:value", ValueField.class); tester.assertComponent("panel:form:autoComplete:id", HiddenField.class); tester.assertComponent("panel:form:autoComplete:addNew", SubmitLink.class); tester.assertVisible("panel:form:autoComplete:addNew"); autoComplete.disallowAddingNewItems(); tester.startComponentInPage(panel); tester.assertInvisible("panel:form:autoComplete:addNew"); } @Test public void testClearInput() { FormTester formTest = tester.newFormTester("panel:form"); formTest.setValue("autoComplete:value", "test"); formTest.setValue("autoComplete:id", "otherId"); autoComplete.getValueField().inputChanged(); autoComplete.getIdField().inputChanged(); assertNotNull(autoComplete.getValueField().getRawInput()); assertNotNull(autoComplete.getIdField().getRawInput()); autoComplete.clearAllInput(); assertNull(autoComplete.getValueField().getRawInput()); assertNull(autoComplete.getIdField().getRawInput()); } @Test @Ignore public void testNewItem(){ //click addNew button Component cmp = tester.getComponentFromLastRenderedPage("panel:form:autoComplete:addNew"); ((SubmitLink)cmp).onSubmit(); //create new item TestObject newObj = new TestObject(1L, "NewName"); //list.add(newObj); tester.startComponent(autoComplete); assertEquals(newObj.getId(), autoComplete.getIdField().getInput()); } @Test public void testSubmit(){ FormTester formTest = tester.newFormTester("panel:form"); formTest.setValue("autoComplete:value", "test"); formTest.setValue("autoComplete:id", "3"); formTest.submit(); assertThat(list.get(2).id, equalTo(model.getObject().id.toString())); assertThat(list.get(2).name, equalTo(model.getObject().name)); } @Test public void submitsUsingValueIfNoIdIsPresent() { tester.newFormTester("panel:form") .setValue("autoComplete:id", "") .setValue("autoComplete:value", "SomeName") .submit(); assertThat(list.get(0).id, equalTo(model.getObject().id.toString())); assertThat(list.get(0).name, equalTo(model.getObject().name)); } @Test public void convertsToNullIfNotFoundByKeyNorByValue() { tester.newFormTester("panel:form") .setValue("autoComplete:id", "") .setValue("autoComplete:value", "DoesNotExist") .submit(); assertThat(model.getObject(), is(nullValue())); } private static class TestObject implements Serializable { private Long id; private String name; public TestObject(Long id, String name){ this.id = id; this.name = name; } public Long getId() { return id; } } private static class SearchObject { final String id; final String name; final String description; public SearchObject(String id, String name, String description) { this.id = id; this.name = name; this.description = description; } } private class TestPanel extends Panel{ public TestPanel(String id) { super(id); } } private class NewItemProvider implements AddNewItemHandler<TestObject> { @Override public void onNewItem(String input, NewAutocompleteItemCallback<TestObject> callback) { } } private class DataProvider extends AbstractDataProvider<TestObject> { @Override public String getId(TestObject object) { return ""+object.getId(); } @Override protected TestObject findExactByValue(String value) { for (SearchObject o : list) { if (o.name.equals(value)) { return new TestObject(Long.valueOf(o.id), o.name); } } return null; } @Override protected TestObject doLoadById(String id) { for (SearchObject o : list) { if (o.id.equals(id)) { return new TestObject(Long.valueOf(id), o.name); } } throw new IllegalStateException("Unknown id " + id); } } private class SearchProvider extends AbstractSearchProvider<SearchObject> { @Override public List<SearchObject> searchItems(String query, int size) { return list; } @Override public String extractSearchLabel(SearchObject item) { return item.name + " - " + item.description; } @Override public String extractValue(SearchObject item) { return item.name; } @Override protected String extractId(SearchObject item) { return item.id; } } public class DataLabelProvider implements AutocompleteDataValueProvider<TestObject> { @Override public String extractValue(TestObject item) { return item.name; } } }