package de.flower.rmt.ui.markup.html.form; import de.flower.common.test.StringUtils; import de.flower.common.test.wicket.WicketTesterHelper; import de.flower.common.ui.ajax.markup.html.form.AjaxSubmitLink; import de.flower.rmt.test.AbstractRMTWicketIntegrationTests; import de.flower.rmt.test.Assert; import de.flower.rmt.ui.markup.html.form.field.TextFieldPanel; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.feedback.FeedbackMessage; import org.apache.wicket.markup.Markup; import org.apache.wicket.markup.html.WebPage; import org.apache.wicket.markup.html.form.Form; import org.apache.wicket.util.tester.FormTester; import org.hibernate.validator.constraints.NotBlank; import org.hibernate.validator.constraints.ScriptAssert; import org.testng.annotations.Test; import org.wicketstuff.jsr303.validator.FormComponentBeanValidator; import javax.validation.constraints.Size; import javax.validation.groups.Default; import java.io.Serializable; import java.util.List; import static org.testng.AssertJUnit.assertEquals; /** * @author flowerrrr */ public class EntityFormTest extends AbstractRMTWicketIntegrationTests { @Test public void testRender() { wicketTester.startPage(new EntityFormTestPage(new TestEntity())); wicketTester.dumpPage(); wicketTester.debugComponentTrees(); wicketTester.assertInvisible("hasErrors"); wicketTester.assertComponent("submitButton", AjaxSubmitLink.class); } /** * Submit empty form. * Verify that feedback messages are not duplicated in global feebackpanel and field level feedback panels. */ @Test public void testRenderError() { TestEntity entity = new TestEntity(); wicketTester.startPage(new EntityFormTestPage(entity)); wicketTester.dumpPage(); wicketTester.clickLink("submitButton"); wicketTester.dumpPage(); wicketTester.assertVisible("hasErrors"); wicketTester.assertErrorMessagesContains(TestEntity.notBlankAssertMessage); wicketTester.assertContains(TestEntity.notBlankAssertMessage); wicketTester.assertVisible("form:name:feedback:feedbackul"); // does not work well here, cause it might give false positive wicketTester.assertInvisible("form:formFeedbackPanel:feedback:feedbackul"); // must check by analyzing the page dump. int matches = StringUtils.countMatches(wicketTester.getLastResponseAsString(), TestEntity.notBlankAssertMessage); assertEquals(1, matches); wicketTester.debugComponentTrees(); } /** * This test verifies that the implementation of debugComponentTrees * is overridden with a safe version that does not produce error logs and messes with * model objects. */ @Test public void testDebugComponentTrees() { wicketTester.startPage(new EntityFormTestPage(new TestEntity2())); wicketTester.clickLink("submitButton"); wicketTester.dumpPage(); wicketTester.assertContains(TestEntity2.scriptAssertMessage); // now same thing again but this time with call of debugComponentTrees wicketTester.startPage(new EntityFormTestPage(new TestEntity2())); // in the original version this call will trigger evaluation of model objects that // then remain in invalid state. in this test case it would lead to not displaying // the error message. wicketTester.debugComponentTrees(); wicketTester.clickLink("submitButton"); wicketTester.dumpPage(); wicketTester.assertContains(TestEntity2.scriptAssertMessage); } /** * A component with a property validator and an additional formbeanvalidator should * first use the propertyvalidator and stop validating if property validation fails. */ @Test public void testValidationOrder() { wicketTester.startPage(new EntityFormTestPage(new TestEntity())); // must set value, empty fields are valid for @Size FormTester formTester = wicketTester.newFormTester("form"); formTester.setValue("password:input", "1"); wicketTester.clickLink("submitButton"); // want to see only NotBlank and Size messages wicketTester.dumpPage(); List<String> list = wicketTester.getMessagesAsString(FeedbackMessage.ERROR); log.info(list.toString()); Assert.assertContains(list.get(0), TestEntity.notBlankAssertMessage); Assert.assertContains(list.get(1), TestEntity.sizeAssertMessage); } private static class EntityFormTestPage extends WebPage { public EntityFormTestPage(Object entity) { EntityForm<Object> form = new EntityForm<Object>("form", entity) { @Override protected void onSubmit(AjaxRequestTarget target, Form<Object> form) { } }; add(form); form.add(new TextFieldPanel("name")); TextFieldPanel password = new TextFieldPanel("password"); form.add(password); password.addValidator(new FormComponentBeanValidator(TestEntity.IScriptAssert.class)); } @Override public Markup getAssociatedMarkup() { return WicketTesterHelper.creatPageMarkup("<html><body>\n" + "<form wicket:id='form'>\n" + "<div wicket:id='formFeedbackPanel' />" // can use whatever tag we like, since only the body is rendered + "<wicket:container wicket:id='name' labelKey='login.username' />\n" + "<wicket:container wicket:id='password' labelKey='login.password' />\n" + "<a wicket:id='submitButton' >save</a>" + "</form>\n" + "</body></html>", this); } } @ScriptAssert(script = "_this.name != 'foo';", lang = "javascript", message = TestEntity.scriptAssertMessage, groups = {TestEntity.IScriptAssert.class, Default.class} ) private static class TestEntity implements Serializable { public interface IScriptAssert { } public final static String scriptAssertMessage = "__boundToComponent__"; public final static String notBlankAssertMessage = "__notBlankMesssage__"; public final static String sizeAssertMessage = "__sizeMesssage__"; @NotBlank(message = TestEntity.notBlankAssertMessage) private String name; @Size(min = 6, max = 10, message = TestEntity.sizeAssertMessage) private String password; public String getName() { return name; } public void setName(final String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(final String password) { this.password = password; } } @ScriptAssert(script = "false", lang = "javascript", message = TestEntity2.scriptAssertMessage) private static class TestEntity2 implements Serializable { public final static String scriptAssertMessage = "__unboundErrorMessage__"; private String name; private String password; public String getName() { return name; } public void setName(final String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(final String password) { this.password = password; } } }