001// Generated by delombok at Sun Jul 30 17:21:56 UTC 2023 002package de.cuioss.test.jsf.validator; 003 004import static org.junit.jupiter.api.Assertions.assertEquals; 005import static org.junit.jupiter.api.Assertions.assertThrows; 006import static org.junit.jupiter.api.Assertions.fail; 007import javax.faces.application.FacesMessage; 008import javax.faces.component.UIComponent; 009import javax.faces.component.html.HtmlInputText; 010import javax.faces.context.FacesContext; 011import javax.faces.validator.Validator; 012import javax.faces.validator.ValidatorException; 013import org.junit.jupiter.api.BeforeEach; 014import org.junit.jupiter.api.Test; 015import de.cuioss.test.generator.junit.EnableGeneratorController; 016import de.cuioss.test.jsf.junit5.EnableJsfEnvironment; 017import de.cuioss.test.jsf.junit5.JsfEnabledTestEnvironment; 018import de.cuioss.test.valueobjects.objects.ConfigurationCallBackHandler; 019import de.cuioss.test.valueobjects.objects.impl.DefaultInstantiator; 020import de.cuioss.tools.reflect.MoreReflection; 021// owolff we need to migrate this aspect later 022/** 023 * Base Class for testing implementations of {@link Validator} within a Junit 5 024 * context 025 * <h3>Setup</h3> 026 * <p> 027 * It uses {@link EnableJsfEnvironment}, for the basic test-infrastructure.See 028 * the class-documentation for details. 029 * </p> 030 * <p> 031 * {@link #initValidator()}: Instantiates the concrete {@link Validator} using 032 * reflection. After this the method calls {@link #configure(Object)} that can 033 * be used for further configuration of the {@link Validator} 034 * </p> 035 * <p> 036 * In case you want you want to create the {@link Validator} yourself you can 037 * overwrite {@link #getValidator()} 038 * </p> 039 * <p> 040 * In case you want a pass another {@link UIComponent} as parameter to the 041 * {@link Validator} you can overwrite {@link #getComponent()} 042 * </p> 043 * <h3>Test-Methods</h3> 044 * <p> 045 * The core test-methods are {@link #shouldFailOnInvalidTestdata()} and 046 * {@link #shouldHandleValidTestdata()}. They call {@link #populate(TestItems)} 047 * in oder to create corresponding test-data. The implementation is in the 048 * actual test-class. 049 * </p> 050 * <h3>API-Test</h3> 051 * <p> 052 * The api as defined within {@link Validator} is tested with the methods 053 * {@link #shouldFailOnNullComponent()}, {@link #shouldFailOnNullFacesContext()} 054 * and {@link #shouldHandleNullValue()} 055 * </p> 056 * <h3>Example</h3> 057 * 058 * <pre> 059 * <code> 060 * @EnableJsfEnvironment 061 * class LengthValidatorTest extends AbstractValidatorTest<LengthValidator, String> { 062 * 063 * @Override 064 * public void populate(final TestItems<String> testItems) { 065 * testItems.addValid("1").addValid("abc").addInvalidWithMessage("123456", 066 * LengthValidator.MAXIMUM_MESSAGE_ID); 067 * } 068 * 069 * @Override 070 * public void configure(final LengthValidator validator) { 071 * validator.setMaximum(5); 072 * } 073 * } 074 * </code> 075 * </pre> 076 * <p> 077 * 078 * @author Oliver Wolff 079 * @param <V> identifying the concrete {@link Validator} to be tested. 080 * @param <T> identifying the type of elements to be passed into the validator 081 */ 082@SuppressWarnings({"rawtypes", "unchecked"}) 083@EnableGeneratorController 084public abstract class AbstractValidatorTest<V extends Validator, T> extends JsfEnabledTestEnvironment implements ConfigurationCallBackHandler<V> { 085 private final UIComponent component = new HtmlInputText(); 086 private V validator; 087 088 /** 089 * Instantiates and initially configures a concrete {@link Validator} 090 */ 091 @BeforeEach 092 void initValidator() { 093 final Class<V> klazz = MoreReflection.extractFirstGenericTypeArgument(getClass()); 094 validator = new DefaultInstantiator<>(klazz).newInstance(); 095 configure(validator); 096 } 097 098 /** 099 * Checks the api contract regarding {@code null} as parameter for 100 * {@link UIComponent}, see 101 * {@link Validator#validate(javax.faces.context.FacesContext, UIComponent, Object)} 102 */ 103 @Test 104 void shouldFailOnNullComponent() { 105 assertThrows(NullPointerException.class, () -> getValidator().validate(getFacesContext(), null, null)); 106 } 107 108 /** 109 * Checks the api contract regarding {@code null} as parameter for 110 * {@link FacesContext}, see 111 * {@link Validator#validate(javax.faces.context.FacesContext, UIComponent, Object)} 112 */ 113 @Test 114 void shouldFailOnNullFacesContext() { 115 assertThrows(NullPointerException.class, () -> getValidator().validate(null, getComponent(), null)); 116 } 117 118 /** 119 * Checks the api contract regarding {@code null} as parameter for the actual 120 * value, see 121 * {@link Validator#validate(javax.faces.context.FacesContext, UIComponent, Object)} 122 */ 123 @Test 124 void shouldHandleNullValue() { 125 getValidator().validate(getFacesContext(), getComponent(), null); 126 } 127 128 /** 129 * Tests whether the valid {@link TestItems} are validated without 130 * {@link ValidatorException} 131 */ 132 @Test 133 void shouldHandleValidTestdata() { 134 final var items = new TestItems<T>(); 135 populate(items); 136 items.allValid().forEach(item -> validator.validate(getFacesContext(), getComponent(), item.getTestValue())); 137 } 138 139 /** 140 * Tests whether the invalid {@link TestItems} fail to validate by throwing 141 * {@link ValidatorException}. In case the single {@link TestItems} provide a 142 * message, it will be compared as well. 143 */ 144 @Test 145 void shouldFailOnInvalidTestdata() { 146 final var items = new TestItems<T>(); 147 populate(items); 148 for (final TestItem<T> item : items.allInvalid()) { 149 try { 150 validator.validate(getFacesContext(), getComponent(), item.getTestValue()); 151 fail("Validation should have thrown a ValidatorException for testValue" + item); 152 } catch (final ValidatorException e) { 153 assertEquals(FacesMessage.SEVERITY_ERROR, e.getFacesMessage().getSeverity()); 154 if (null != item.getErrorMessage()) { 155 assertEquals(item.getErrorMessage(), e.getFacesMessage().getSummary(), "The validation failed as expected, but the messages are not equal as expected"); 156 } 157 } 158 } 159 } 160 161 /** 162 * Populates the test-items 163 * 164 * @param testItems to be populated, is never null 165 */ 166 public abstract void populate(TestItems<T> testItems); 167 168 @java.lang.SuppressWarnings("all") 169 @lombok.Generated 170 public UIComponent getComponent() { 171 return this.component; 172 } 173 174 @java.lang.SuppressWarnings("all") 175 @lombok.Generated 176 public V getValidator() { 177 return this.validator; 178 } 179}