package lt.inventi.wicket.component.repeater.expandable;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.Matchers.contains;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.wicket.Component;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.protocol.http.mock.MockHttpServletResponse;
import org.apache.wicket.util.tester.FormTester;
import org.junit.Before;
import org.junit.Test;
import lt.inventi.wicket.test.BaseNonInjectedTest;
public class ExpandableViewTest extends BaseNonInjectedTest {
private ArrayList<String> values;
@Before
public void before(){
values = new ArrayList<String>();
values.add("test1");
values.add("test2");
}
@Test
public void outputsItemMarkupIds() {
IModel<List<String>> model = new PropertyModel<List<String>>(this, "values");
ExpandableView<String> panel = new ExpandableView<String>("test", model) {
@Override
protected void populateItem(Item<String> item) {
// do nothing
}
};
tester.startComponentInPage(panel);
Iterator<Item<String>> items = panel.getItems();
while (items.hasNext()) {
assertThat(items.next().getOutputMarkupId(), is(true));
}
}
@Test
public void shouldContainUpdatedModelItems() {
NonNullItemTestPanel panel = new NonNullItemTestPanel();
tester.startComponentInPage(panel);
TestView view = panel.getTestView();
view.onBeforeRender();
values.add("test3");
view.onBeforeRender();
values.add("test4");
view.onBeforeRender();
assertEquals(4, numberOfItems(view));
}
@Test
public void handlesModelObjectChanges() {
NonNullItemTestPanel panel = new NonNullItemTestPanel();
tester.startComponentInPage(panel);
TestView view = panel.getTestView();
values.remove(0);
view.onBeforeRender();
assertThat(numberOfItems(view), is(1));
}
@Test
public void shouldAddNonNullItemsToTheList() {
NonNullItemTestPanel panel = new NonNullItemTestPanel();
tester.startComponentInPage(panel);
tester.executeAjaxEvent(panel.getAddItemLink(), "click");
assertThat(values, contains("test1", "test2", "test3"));
assertThat(panel.getTestView().get("2:field").getOutputMarkupId(), is(true));
String addElementScript = "var item=document.createElement('span');item.id='test3';$('#form4').append(item);";
String focusScript = "Wicket.Focus.setFocusOnId('test3_field');";
checkScripts(addElementScript, focusScript);
tester.executeAjaxEvent(panel.getAddItemLink(), "click");
assertThat(values, contains("test1", "test2", "test3", "test3"));
}
@Test
public void addsNullItemsToTheEndOfTheList() {
NullItemTestPanel panel = new NullItemTestPanel();
tester.startComponentInPage(panel);
tester.executeAjaxEvent(panel.getAddItemLink(), "click");
assertThat(values, contains("test1", "test2", null));
assertThat(panel.getTestView().size(), is(3));
String addElementScript = "var item=document.createElement('span');item.id='null';$('#form4').append(item);";
String focusScript = "Wicket.Focus.setFocusOnId('null_field');";
checkScripts(addElementScript, focusScript);
tester.executeAjaxEvent(panel.getAddItemLink(), "click");
assertThat(values, contains("test1", "test2", null, null));
assertThat(panel.getTestView().size(), is(4));
// this is a degenerate case. We shouldn't be setting markup ids equal to model object values
addElementScript = "var item=document.createElement('span');item.id='null';$('#form4').append(item);";
focusScript = "Wicket.Focus.setFocusOnId('null_field');";
checkScripts(addElementScript, focusScript);
}
@Test
public void removesNullItemsUsingRemoveItemLink() {
NullItemTestPanel panel = new NullItemTestPanel();
tester.startComponentInPage(panel);
tester.clickLink(panel.getAddItemLink());
tester.clickLink(panel.getAddItemLink());
assertThat(values, contains("test1", "test2", null, null));
tester.executeAjaxEvent(panel.getTestView().get("2:remove"), "click");
assertThat(values, contains("test1", "test2", null));
}
@Test
public void shouldAddAndRemoveItems() {
NonNullItemTestPanel panel = new NonNullItemTestPanel();
tester.startComponentInPage(panel);
// add third item
tester.executeAjaxEvent(panel.getAddItemLink(), "click");
assertThat(values, contains("test1", "test2", "test3"));
// remove second item
tester.executeAjaxEvent(panel.getTestView().get("1:remove"), "click");
assertThat(values, contains("test1", "test3"));
FormTester formTester = tester.newFormTester("test:form");
formTester.setValue("view:2:field", "newValue");
formTester.submit();
tester.executeAjaxEvent(panel.getAddItemLink(), "click");
assertThat(values, contains("test1", "newValue", "test3"));
}
@Test
public void shouldRemoveItemsFromTheList() {
NonNullItemTestPanel panel = new NonNullItemTestPanel();
tester.startComponentInPage(panel);
tester.executeAjaxEvent(panel.getAddItemLink(), "click");
assertThat(values, contains("test1", "test2", "test3"));
String focusScript = "Wicket.Focus.setFocusOnId('test2_field');";
// remove last item
tester.executeAjaxEvent(panel.getTestView().get("2:remove"), "click");
assertThat(values, contains("test1", "test2"));
checkScripts("$('#test3').remove()", focusScript);
// remove first item
tester.executeAjaxEvent(panel.getTestView().get("0:remove"), "click");
assertThat(values, contains("test2"));
checkScripts("$('#test1').remove()", focusScript);
}
@Test
public void shouldRemoveItemsFromTheMiddle() {
NonNullItemTestPanel panel = new NonNullItemTestPanel();
tester.startComponentInPage(panel);
tester.executeAjaxEvent(panel.getAddItemLink(), "click");
tester.executeAjaxEvent(panel.getAddItemLink(), "click");
tester.executeAjaxEvent(panel.getAddItemLink(), "click");
assertThat(values, contains("test1", "test2", "test3", "test3", "test3"));
assertThat(panel.getTestView().size(), is(5));
tester.executeAjaxEvent(panel.getTestView().get("1:remove"), "click");
assertThat(values, contains("test1", "test3", "test3", "test3"));
tester.executeAjaxEvent(panel.getTestView().get("2:remove"), "click");
assertThat(values, contains("test1", "test3", "test3"));
tester.executeAjaxEvent(panel.getTestView().get("3:remove"), "click");
assertThat(values, contains("test1", "test3"));
tester.executeAjaxEvent(panel.getTestView().get("4:remove"), "click");
assertThat(values, contains("test1"));
}
@Test
public void shouldReplaceItemsInTheBackingListModel() {
NonNullItemTestPanel panel = new NonNullItemTestPanel();
tester.startComponentInPage(panel);
FormTester formTester = tester.newFormTester("test:form");
formTester.setValue("view:0:field", "newValue");
formTester.submit();
assertThat(values, contains("newValue", "test2"));
}
private void checkScripts(String... scripts) {
MockHttpServletResponse response = tester.getLastResponse();
for (String s : scripts) {
assertThat(response.getDocument(), containsString(s));
}
}
public abstract class TestPanel extends Panel {
private final IModel<? extends List<String>> model;
protected TestPanel() {
super("test");
this.model = new PropertyModel<List<String>>(ExpandableViewTest.this, "values");
}
protected TestPanel(IModel<? extends List<String>> model) {
super("test");
this.model = model;
}
public Component getAddItemLink() {
return get("form:add");
}
public TestView getTestView() {
return (TestView) get("form:view");
}
@Override
protected void onInitialize() {
super.onInitialize();
TestView view = new TestView(this.model);
add(new Form<Void>("form").add(view, newItemLink("add", view)));
}
protected abstract AddNewItemLink<String> newItemLink(String id, ExpandableView<String> view);
}
public class NonNullItemTestPanel extends TestPanel {
public NonNullItemTestPanel() {
super();
}
public NonNullItemTestPanel(IModel<? extends List<String>> model) {
super(model);
}
@Override
protected AddNewItemLink<String> newItemLink(String id, ExpandableView<String> view) {
return new AutoAddNewItemLink<String>(id, view) {
@Override
protected String createNewItem() {
return "test3";
}
};
}
}
public class NullItemTestPanel extends TestPanel {
public NullItemTestPanel() {
super();
}
public NullItemTestPanel(IModel<? extends List<String>> model) {
super(model);
}
@Override
protected AddNewItemLink<String> newItemLink(String id, ExpandableView<String> view) {
return new AutoAddNewItemLink<String>(id, view) {
@Override
protected String createNewItem() {
return null;
}
};
}
}
public class TestView extends ExpandableView<String> {
public TestView(IModel<? extends List<String>> model) {
super("view", model);
}
@Override
protected void populateItem(final Item<String> item) {
item.setMarkupId(String.valueOf(item.getModelObject()));
item.add(new TextField<String>("field", item.getModel()).setMarkupId(item.getModelObject() + "_field"));
item.add(new AutoRemoveItemLink<String>("remove", item));
}
@Override
protected void onBeforeRender(){
super.onBeforeRender();
}
}
private static int numberOfItems(TestView view) {
Iterator<Item<String>> items = view.getItems();
int size = 0;
while (items.hasNext()) {
items.next();
size++;
}
return size;
}
}