blob: a912e58185a38aa204a5e3373b5f517c900b22f0 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package javax.faces.component;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import java.io.IOException;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
import javax.el.ValueExpression;
import javax.faces.application.FacesMessage;
import javax.faces.component.visit.VisitContext;
import javax.faces.component.visit.VisitHint;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.ConverterException;
import javax.faces.event.ValueChangeEvent;
import javax.faces.validator.LengthValidator;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.myfaces.test.mock.MockRenderedValueExpression;
import org.apache.myfaces.test.base.junit4.AbstractJsfTestCase;
import org.apache.myfaces.test.el.MockValueExpression;
import org.apache.myfaces.test.mock.visit.MockVisitCallback;
import org.junit.Assert;
public class UIInputTest extends AbstractJsfTestCase
{
private Converter mockConverter;
private Validator mockValidator;
private UIInput input;
@Override
public void setUp() throws Exception
{
super.setUp();
input = new UIInput();
input.setId("testId");
mockConverter = createMock(Converter.class);
mockValidator = createMock(Validator.class);
}
@Override
public void tearDown() throws Exception
{
super.tearDown();
input = null;
mockConverter = null;
mockValidator = null;
}
public static class MyMockValueChangeBean
{
public void changeValue(ValueChangeEvent evt)
{
throw new IllegalStateException("method should not be called");
}
}
public static class MyMockValidatorBean implements Validator
{
public void validate(FacesContext context, UIComponent component,
Object value) throws ValidatorException
{
((UIInput)component).setValid(false);
}
}
public void testWhenSpecifiedConverterMessageIsUsedInCaseConverterExceptionOccurs()
{
input.setConverterMessage("Cannot convert");
input.setConverter(mockConverter);
expect(mockConverter.getAsObject(facesContext, input, "xxx")).andThrow(new ConverterException());
replay(mockConverter);
input.setSubmittedValue("xxx");
input.validate(facesContext);
verify(mockConverter);
Assert.assertFalse(input.isValid());
Assert.assertNotNull(facesContext.getMessages("testId"));
FacesMessage message = (FacesMessage) facesContext.getMessages("testId").next();
Assert.assertEquals(message.getDetail(), "Cannot convert");
Assert.assertEquals(message.getSummary(), "Cannot convert");
}
public void testWhenSpecifiedValidatorMessageIsUsedInCaseValidatorExceptionOccurs()
{
input.setValidatorMessage("Cannot validate");
input.addValidator(mockValidator);
mockValidator.validate(facesContext, input, "xxx");
expectLastCall().andThrow(new ValidatorException(new FacesMessage()));
replay(mockValidator);
input.validateValue(facesContext, "xxx");
verify(mockValidator);
Assert.assertFalse(input.isValid());
Assert.assertNotNull(facesContext.getMessages("testId"));
FacesMessage message = (FacesMessage) facesContext.getMessages("testId").next();
Assert.assertEquals(message.getDetail(), "Cannot validate");
Assert.assertEquals(message.getSummary(), "Cannot validate");
}
public void testUpdateModelSetsTheLocalValueToModelValue()
{
input.setValue("testValue");
ValueExpression expression = new MockValueExpression("#{requestScope.id}", String.class);
input.setValueExpression("value", expression);
input.updateModel(facesContext);
String updatedValue = expression.getValue(facesContext.getELContext()).toString();
Assert.assertEquals("testValue", updatedValue);
}
public void testValidateWithEmptyStringWithEmptyStringAsNullEnabled()
{
try
{
InitParameterMockExternalContext mockExtCtx =
new InitParameterMockExternalContext(servletContext, request, response);
mockExtCtx.getInitParameterMap().put("javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL", "true");
mockExtCtx.getInitParameterMap().put(UIInput.VALIDATE_EMPTY_FIELDS_PARAM_NAME, "true");
facesContext.setExternalContext(mockExtCtx);
input.addValidator(new Validator()
{
public void validate(FacesContext context,
UIComponent component, Object value)
throws ValidatorException
{
// the value must be null
Assert.assertNull(value);
}
});
input.setSubmittedValue("");
input.validate(facesContext);
Assert.assertEquals(null, input.getSubmittedValue());
}
finally
{
facesContext.setExternalContext(externalContext);
}
}
public void testValidateWithNonStringWithEmptyStringAsNullEnabled()
{
try
{
InitParameterMockExternalContext mockExtCtx =
new InitParameterMockExternalContext(servletContext, request, response);
mockExtCtx.getInitParameterMap().put("javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL", "true");
facesContext.setExternalContext(mockExtCtx);
input.addValidator(new Validator()
{
public void validate(FacesContext context,
UIComponent component, Object value)
throws ValidatorException
{
// the value must not be null
Assert.assertNotNull(value);
// throw Exception to ensure this was called
throw new RuntimeException();
}
});
// set Object with toString() returning "" as submittedValue
input.setSubmittedValue(new Object()
{
@Override
public String toString()
{
return "";
}
});
try
{
input.validate(facesContext);
Assert.fail(); // validate() was not called --> fail!
}
catch (RuntimeException e)
{
// great - validate() was called!
}
}
finally
{
facesContext.setExternalContext(externalContext);
}
}
public void testValidateWithNonEmptyStringWithEmptyStringAsNullEnabled()
{
try
{
InitParameterMockExternalContext mockExtCtx =
new InitParameterMockExternalContext(servletContext, request, response);
mockExtCtx.getInitParameterMap().put("javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL", "true");
facesContext.setExternalContext(mockExtCtx);
input.setValue("asd");
input.setSubmittedValue("asd");
input.validate(facesContext);
Assert.assertEquals(null, input.getSubmittedValue());
Assert.assertEquals("asd", input.getValue());
}
finally
{
facesContext.setExternalContext(externalContext);
}
}
public void testValidateWithEmptyStringWithEmptyStringAsNullDisabled()
{
try
{
InitParameterMockExternalContext mockExtCtx =
new InitParameterMockExternalContext(servletContext, request, response);
mockExtCtx.getInitParameterMap().put("javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL", "false");
facesContext.setExternalContext(mockExtCtx);
input.setValue("");
input.setSubmittedValue("");
input.validate(facesContext);
Assert.assertEquals("", input.getValue());
}
finally
{
facesContext.setExternalContext(externalContext);
}
}
public void testValidateWithEmptyStringWithEmptyStringAsNullNotSpecified()
{
try
{
InitParameterMockExternalContext mockExtCtx =
new InitParameterMockExternalContext(servletContext, request, response);
//mockExtCtx.getInitParameterMap().put("javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL", "false");
facesContext.setExternalContext(mockExtCtx);
input.setValue("");
input.setSubmittedValue("");
input.validate(facesContext);
Assert.assertEquals("", input.getValue());
}
finally
{
facesContext.setExternalContext(externalContext);
}
}
/**
* Tests if UIInput.processValidators() correctly calls FacesContext.validationFailed()
* if a validation error occurs.
*/
public void testValidationErrorTriggersFacesContextValidationFailed()
{
LengthValidator validator = new LengthValidator();
validator.setMinimum(5);
input.addValidator(validator);
input.setSubmittedValue("123");
Assert.assertFalse(facesContext.isValidationFailed());
input.processValidators(facesContext);
Assert.assertTrue(facesContext.isValidationFailed());
}
static public class InitParameterMockExternalContext extends org.apache.myfaces.test.mock.MockExternalContext {
private Map initParameters = new HashMap();
public InitParameterMockExternalContext(ServletContext context, HttpServletRequest request, HttpServletResponse response) {
super(context, request, response);
}
public String encodePartialActionURL(String url) {
return null;
}
public String getInitParameter(String name) {
return (String) initParameters.get(name);
}
public Map getInitParameterMap() {
return initParameters;
}
}
public void testProcessDecodesRenderedFalse() throws Exception {
input = new VerifyNoLifecycleMethodComponent();
UIComponent parent = MockRenderedValueExpression.setUpComponentStack(facesContext, input, false);
input.processDecodes(facesContext);
Assert.assertEquals("processDecodes must not change currentComponent", parent, UIComponent.getCurrentComponent(facesContext));
}
public void testProcessDecodesRenderedTrue() throws Exception {
UIComponent parent = MockRenderedValueExpression.setUpComponentStack(facesContext, input, true);
_setUpValueExpressionForImmediate();
input.processDecodes(facesContext);
Assert.assertEquals("processDecodes must not change currentComponent", parent, UIComponent.getCurrentComponent(facesContext));
}
public void testProcessValidatorsRenderedFalse() throws Exception {
input = new VerifyNoLifecycleMethodComponent();
UIComponent parent = MockRenderedValueExpression.setUpComponentStack(facesContext, input, false);
input.processValidators(facesContext);
Assert.assertEquals("processValidators must not change currentComponent", parent, UIComponent.getCurrentComponent(facesContext));
}
public void testProcessValidatorsRenderedTrue() throws Exception {
UIComponent parent = MockRenderedValueExpression.setUpComponentStack(facesContext, input, true);
_setUpValueExpressionForImmediate();
input.processValidators(facesContext);
Assert.assertEquals("processValidators must not change currentComponent", parent, UIComponent.getCurrentComponent(facesContext));
}
public void testProcessUpdatesRenderedFalse() throws Exception {
input = new VerifyNoLifecycleMethodComponent();
UIComponent parent = MockRenderedValueExpression.setUpComponentStack(facesContext,input, false);
input.processUpdates(facesContext);
Assert.assertEquals("processValidators must not change currentComponent", parent, UIComponent.getCurrentComponent(facesContext));
}
public void testProcessUpdatesRenderedTrue() throws Exception {
UIComponent parent = MockRenderedValueExpression.setUpComponentStack(facesContext, input, true);
_setUpValueExpressionForImmediate();
input.processUpdates(facesContext);
Assert.assertEquals("processValidators must not change currentComponent", parent, UIComponent.getCurrentComponent(facesContext));
}
public void testVisitTree() throws Exception {
UIComponent parent = MockRenderedValueExpression.setUpComponentStack(facesContext, input, true);
VisitContext visitContext = VisitContext.createVisitContext(facesContext, null, EnumSet.of(VisitHint.SKIP_UNRENDERED));
MockVisitCallback mockVisitCallback = new MockVisitCallback();
input.visitTree(visitContext, mockVisitCallback);
Assert.assertEquals("visitTree must not change currentComponent", parent, UIComponent.getCurrentComponent(facesContext));
}
/** Verifies no call to encode* and process* methods */
public class VerifyNoLifecycleMethodComponent extends UIInput
{
public void decode(FacesContext context) {
Assert.fail();
}
public void validate(FacesContext context) {
Assert.fail();
}
public void updateModel(FacesContext context) {
Assert.fail();
}
public void encodeBegin(FacesContext context) throws IOException {
Assert.fail();
}
public void encodeChildren(FacesContext context) throws IOException {
Assert.fail();
}
public void encodeEnd(FacesContext context) throws IOException {
Assert.fail();
}
}
private void _setUpValueExpressionForImmediate() {
ValueExpression ve = new MockRenderedValueExpression("#{component.id eq 'testId'}", Boolean.class, input, true);
input.setValueExpression("immediate", ve);
}
}