blob: d5fcc1780a859d2a008a06bed6c5659410a3af26 [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 org.apache.myfaces.trinidad.convert;
import java.util.Locale;
import javax.faces.convert.ConverterException;
import javax.faces.convert.NumberConverter;
import javax.faces.component.UIComponent;
import org.apache.myfaces.trinidad.convert.ConverterTestCase;
import org.apache.myfaces.trinidadbuild.test.MockUIComponentWrapper;
import org.apache.myfaces.test.mock.MockFacesContext;
import org.jmock.Mock;
/**
* Test NumberConverter
* @version $Name: $ ($version: $) $Date: 16-aug-2005.15:12:23 $
*/
public abstract class NumberConverterTestCase extends ConverterTestCase
{
public NumberConverterTestCase(String name)
{
super(name);
}
/**
* Test when context is set to null
*/
public void testNullContext()
{
Mock mock = mock(UIComponent.class);
UIComponent component = (UIComponent) mock.proxy();
//we do not care about getValueExpression() being called or not
mock.stubs().method("getValueExpression");
MockUIComponentWrapper wrapper = new MockUIComponentWrapper(mock, component);
NumberConverter converter = getNumberConverter();
doTestNullContext(wrapper, converter);
}
public void testNullComponent()
{
NumberConverter converter = getNumberConverter();
doTestNullComponent(facesContext, converter);
}
/**
* Tests that null returns immediately.
*
* @throws ConverterException when test fails
*/
public void testNullInputValue() throws ConverterException
{
Mock mock = mock(UIComponent.class);
UIComponent component = (UIComponent) mock.proxy();
//we do not care about getValueExpression() being called or not
mock.stubs().method("getValueExpression");
MockUIComponentWrapper wrapper = new MockUIComponentWrapper(mock, component);
NumberConverter converter = getNumberConverter();
doTestNull(facesContext, wrapper, converter);
}
public void testEmptyValueConversion()
{
super.doTestBlankValue(getNumberConverter());
}
public void testValueType()
{
Mock mock = mock(UIComponent.class);
UIComponent component = (UIComponent) mock.proxy();
//we do not care about getValueExpression() being called or not
mock.stubs().method("getValueExpression");
setFacesContext(facesContext);
try
{
String input = "123";
NumberConverter converter = getNumberConverter();
Object number = converter.getAsObject(facesContext, component, input);
assertEquals(true, number instanceof Number);
assertEquals(true, (((Number)number).intValue() == 123));
String outVal = converter.getAsString(facesContext, component, number);
assertEquals(input, outVal);
}
finally
{
setFacesContext(null);
}
mock.verify();
}
public void testAppropriateFormatsArePicked()
{
// check if appropriate formtas based on the types are chosen.
// like numeric, currency, percent are picked. Chose pattern if set avoiding
// types
String[] patterns = {"##,##",null, null, null,null};
//pick pattern, numeric, percent, currency
String[] types = {null,"number", "percent", "currency", "currency"};
String[] inputValues = {"99,99","99", "99%","$99", "$99.00"} ;
Number[] expectedValues = {new Long(9999), new Long(99), new Double(0.99), new Long(99), new Long(99)};
String[] expectedStringValues = {"99,99","99", "99%","$99.00", "$99.00"} ;
Locale usLocl = Locale.US;
Locale[] locales = {usLocl, usLocl, usLocl, usLocl,Locale.CANADA};
NumberConverter nconv = getNumberConverter();
for (int i = 0; i < patterns.length; i++)
{
Mock mock = mock(UIComponent.class);
UIComponent component = (UIComponent) mock.proxy();
//we do not care about getValueExpression() being called or not
mock.stubs().method("getValueExpression");
setFacesContext(facesContext);
try
{
nconv.setPattern(patterns[i]);
nconv.setType(types[i]);
nconv.setLocale(locales[i]);
Object convValue = nconv.getAsObject(facesContext, component, inputValues[i]);
// Trinidad does BigDecimal, for some reasons.
// see TRINIDAD-1124
if(i==2)
{
convValue = ((Number) convValue).doubleValue();
}
else
{
convValue = ((Number) convValue).longValue();
}
assertEquals(expectedValues[i], convValue);
String outValue = nconv.getAsString(facesContext, component, expectedValues[i]);
assertEquals(expectedStringValues[i], outValue);
}
finally
{
setFacesContext(null);
}
mock.verify();
}
}
public void testStateHolderSaveRestore()
{
NumberConverter converter = getNumberConverter();
NumberConverter restoreConverter = getNumberConverter();
Mock mock = mock(UIComponent.class);
UIComponent component = (UIComponent) mock.proxy();
//we do not care about getValueExpression() being called or not
mock.stubs().method("getValueExpression");
MockUIComponentWrapper wrapper = new MockUIComponentWrapper(mock, component);
for (int i = 0; i < _LOCALES.length; i++)
{
converter.setLocale(_LOCALES[i]);
restoreConverter.setLocale(_LOCALES[i]);
doTestStateHolderSaveRestore(converter, restoreConverter, facesContext, wrapper);
converter.setCurrencyCode( _CURRENCY_CODES[i]);
restoreConverter.setCurrencyCode( _CURRENCY_CODES[i]);
doTestStateHolderSaveRestore(converter, restoreConverter, facesContext, wrapper);
converter.setCurrencySymbol(_CURRENCY_SYMBOLS[i]);
restoreConverter.setCurrencySymbol(_CURRENCY_SYMBOLS[i]);
doTestStateHolderSaveRestore(converter, restoreConverter, facesContext, wrapper);
converter.setIntegerOnly(_INTEGER_ONLY[1]);
restoreConverter.setIntegerOnly(_INTEGER_ONLY[1]);
doTestStateHolderSaveRestore(converter, restoreConverter, facesContext, wrapper);
converter.setMaxFractionDigits(_MAX_FRACTION_DIGITS[i]);
restoreConverter.setMaxFractionDigits(_MAX_FRACTION_DIGITS[i]);
doTestStateHolderSaveRestore(converter, restoreConverter, facesContext, wrapper);
converter.setMaxIntegerDigits(_MAX_INT_DIGITS[i]);
restoreConverter.setMaxIntegerDigits(_MAX_INT_DIGITS[i]);
doTestStateHolderSaveRestore(converter, restoreConverter, facesContext, wrapper);
converter.setMinFractionDigits(_MIN_FRACT_DIGITS[i]);
restoreConverter.setMinFractionDigits(_MIN_FRACT_DIGITS[i]);
doTestStateHolderSaveRestore(converter, restoreConverter, facesContext, wrapper);
converter.setMinIntegerDigits(_MIN_INT_DIGITS[i]);
restoreConverter.setMinIntegerDigits(_MIN_INT_DIGITS[i]);
doTestStateHolderSaveRestore(converter, restoreConverter, facesContext, wrapper);
converter.setPattern( _PATTTERNS[i]);
restoreConverter.setPattern(_PATTTERNS[i]);
doTestStateHolderSaveRestore(converter, restoreConverter, facesContext, wrapper);
converter.setTransient(_TRANSIENT[i]);
restoreConverter.setTransient(_TRANSIENT[i]);
doTestStateHolderSaveRestore(converter, restoreConverter, facesContext, wrapper);
converter.setType(_TYPES[i]);
doTestStateHolderSaveRestore(converter, restoreConverter, facesContext, wrapper);
}
}
public void testCurrencyCodeIsHonoured()
{
NumberConverter converter = getNumberConverter();
Mock mock = mock(UIComponent.class);
UIComponent component = (UIComponent) mock.proxy();
//we do not care about getValueExpression() being called or not
mock.stubs().method("getValueExpression");
converter.setLocale(Locale.US);
converter.setType("currency");
Double value = new Double(99);
setFacesContext(facesContext);
try
{
String outPut = converter.getAsString(facesContext, component, value);
assertEquals("$99.00", outPut);
//Locale is US. By general convention the output prefix would be '$'
// since we set the currency code to 'DEM' value should be DEM[value]
converter.setCurrencyCode("DEM");
outPut = converter.getAsString(facesContext, component, value);
assertEquals("DEM99.00", outPut);
}
finally
{
setFacesContext(null);
}
mock.verify();
}
public void testCurrencyCodeIsHonouredWhenCurrencyCodeAndCurrencySymbolIsSet()
{
NumberConverter converter = getNumberConverter();
Mock mock = buildMockUIComponent(2);
UIComponent component = (UIComponent) mock.proxy();
//we do not care about getValueExpression() being called or not
mock.stubs().method("getValueExpression");
converter.setLocale(Locale.US);
converter.setType("currency");
Double value = new Double(99);
setFacesContext(facesContext);
try
{
String outPut = converter.getAsString(facesContext, component, value);
assertEquals("$99.00", outPut);
//Locale is US. By general convention the output prefix would be '$'
// since we set the currency code to 'DEM' value should be DEM[value]
converter.setCurrencyCode("DEM");
// Let us set the symbol to '*'. This should not take effect, since currency
// code is set.
converter.setCurrencySymbol("*");
outPut = converter.getAsString(facesContext, component, value);
assertEquals("DEM99.00", outPut);
try
{
Number outValue = (Number)converter.getAsObject(facesContext, component, "DEM99.00");
// FIXME =-= AdamWiner: this is not reporting an error as of
// JSF 1.2 - should it?
// fail("Exception should occur - since currency should not be considered while formatting");
}
catch(Exception e)
{
;//Expected to fail.
}
}
finally
{
setFacesContext(null);
}
mock.verify();
}
public void testCurrencySymbolIsHonoured()
{
NumberConverter converter = getNumberConverter();
Mock mock = mock(UIComponent.class);
UIComponent component = (UIComponent) mock.proxy();
//we do not care about getValueExpression() being called or not
mock.stubs().method("getValueExpression");
converter.setLocale(Locale.US);
converter.setType("currency");
Double value = new Double(99);
//Locale is US. By general convention the output prefix would be '$'
// since we set currency symbol to '*' we should get the value to be *99.00
converter.setCurrencySymbol("*");
setFacesContext(facesContext);
try
{
String outPut = converter.getAsString(facesContext, component, value);
assertEquals("*99.00", outPut);
}
finally
{
setFacesContext(null);
}
mock.verify();
}
public void testIntegerOnlyIsHonoured()
{
// integerOnly is used only while parsing to create number objects
NumberConverter converter = getNumberConverter();
Mock mock = mock(UIComponent.class);
UIComponent component = (UIComponent) mock.proxy();
//we do not care about getValueExpression() being called or not
mock.stubs().method("getValueExpression");
converter.setLocale(Locale.US);
String[] inputs = {"23.10", "44.90876", "11111", "67859.0001"};
Number[] expectedValues = {new Long(23), new Long(44), new Long(11111), new Long(67859)};
setFacesContext(facesContext);
try
{
for (int i = 0; i < inputs.length; i++)
{
converter.setIntegerOnly(true);
Number num = (Number) converter.getAsObject(facesContext, component, inputs[i]);
assertEquals(expectedValues[i], num);
}
}
finally
{
setFacesContext(null);
}
mock.verify();
}
public void testSettingFractDigitsAndSettingMinDigitsDoesNotAffectParsing()
{
// integerOnly is used only while parsing to create number objects
NumberConverter converter = getNumberConverter();
Mock mock = mock(UIComponent.class);
UIComponent component = (UIComponent) mock.proxy();
//we do not care about getValueExpression() being called or not
mock.stubs().method("getValueExpression");
converter.setLocale(Locale.US);
String[] inputs = {"23.10", "44.90876", "11111", "67859.0001"};
Number[] expectedValues = {new Long(23), new Long(44), new Long(11111), new Long(67859)};
setFacesContext(facesContext);
try
{
for (int i = 0; i < inputs.length; i++)
{
// setting these values should not affect parsing.
converter.setMaxFractionDigits(10);
converter.setMaxIntegerDigits(1);
converter.setMinFractionDigits(1);
converter.setMinFractionDigits(0);
// this should be taken care by the parsing code
converter.setIntegerOnly(true);
Number num = (Number) converter.getAsObject(facesContext, component, inputs[i]);
assertEquals(expectedValues[i], num);
}
}
finally
{
setFacesContext(null);
}
mock.verify();
}
public void testLocaleIsPickedUpFromViewRoot()
{
NumberConverter converter = getNumberConverter();
Mock mock = mock(UIComponent.class);
UIComponent component = (UIComponent) mock.proxy();
//we do not care about getValueExpression() being called or not
mock.stubs().method("getValueExpression");
String input = "1234.56";
setFacesContext(facesContext);
facesContext.getViewRoot().setLocale(Locale.US);
try
{
// if we get a valid object, implies locale was indeed picked up.
// otherwise we would have got a null pointer exception or other exception
Object value = converter.getAsObject(facesContext, component, input);
assertEquals(new Double(1234.56), ((Number)value).doubleValue());
}
finally
{
setFacesContext(null);
}
}
public void testGroupingIsHonoured()
{
Number[] inputValues = {new Long(9999), new Long(99), new Double(0.99), new Double(99999.567), new Long(9999)};
boolean [] isGroupingUsed = {true, true, true, false, false };
String[] expectedValues = {"9,999", "99", "0.99", "99999.567", "9999"};
NumberConverter converter = getNumberConverter();
Mock mock = mock(UIComponent.class);
UIComponent component = (UIComponent) mock.proxy();
//we do not care about getValueExpression() being called or not
mock.stubs().method("getValueExpression");
converter.setLocale(Locale.US);
setFacesContext(facesContext);
try
{
for (int i = 0; i < inputValues.length; i++)
{
converter.setGroupingUsed(isGroupingUsed[i]);
String out = converter.getAsString(facesContext, component, inputValues[i]);
assertEquals(expectedValues[i], out);
}
}
finally
{
setFacesContext(null);
}
mock.verify();
}
public void testStrictnessOfConversion()
{
String[] inputValues = {"123ABC", "22.22.2" };
Mock mock = buildMockUIComponent(inputValues.length * 3);
UIComponent component = (UIComponent) mock.proxy();
//we do not care about getValueExpression() being called or not
mock.stubs().method("getValueExpression");
MockUIComponentWrapper wrapper = new MockUIComponentWrapper(mock, component);
for (int i = 0; i < inputValues.length; i++)
{
doTestStrictNess(facesContext, wrapper, Locale.US, inputValues[i]);
}
mock.verify();
}
public void testSettingFractDigitsAndSettingMinDigitsAreHononured()
{
Number[] inputValues = {new Long(1234), new Double(1234.5678), new Double(1234), new Double(10.00)};
String[] expectedValues = {"1,234", "34.57", "1,234", "10.00"};
int[] maxFractDigits = {0, 2, 2, 2};
int[] maxIntDigits = {4, 2, 4, 3};
int[] minIntDigits = {4, 1, 2, 1};
int[] minFractDigits = {0, 2, 0, 2};
NumberConverter converter = getNumberConverter();
Mock mock = mock(UIComponent.class);
UIComponent component = (UIComponent) mock.proxy();
//we do not care about getValueExpression() being called or not
mock.stubs().method("getValueExpression");
setFacesContext(facesContext);
try
{
converter.setLocale(Locale.US);
for (int i = 0; i < maxFractDigits.length; i++)
{
converter.setMaxFractionDigits(maxFractDigits[i]);
converter.setMaxIntegerDigits(maxIntDigits[i]);
converter.setMinFractionDigits(minFractDigits[i]);
converter.setMinIntegerDigits(minIntDigits[i]);
String out = converter.getAsString(facesContext, component, inputValues[i]);
assertEquals(expectedValues[i], out);
}
}
finally
{
setFacesContext(null);
}
mock.verify();
}
protected abstract NumberConverter getNumberConverter();
protected abstract void doTestStrictNess(
MockFacesContext context,
MockUIComponentWrapper wrapper,
Locale locale,
String inputValue);
private static final String[] _CURRENCY_CODES = {"USD", "DEM" };
private static final String[] _CURRENCY_SYMBOLS = {"*", "!"};
private static final Locale[] _LOCALES = {Locale.US, Locale.GERMAN};
private static final int[] _MAX_FRACTION_DIGITS = {2, 3};
private static final int[] _MAX_INT_DIGITS = {5, 6};
private static final int[] _MIN_FRACT_DIGITS = {2, 3};
private static final int[] _MIN_INT_DIGITS = {2, 3};
private static final String[] _PATTTERNS = {"##,##", null};
private static final String[] _TYPES = {"currency","percent"};
// -= Simon Lessard =-
// TODO: Never read locally as of 2006-08-09. Remove whenever possible
// or implements a grouping test using this constant.
//private static final boolean[] _GROUPING = {true, false};
private static final boolean[] _INTEGER_ONLY = {true, false};
private static final boolean[] _TRANSIENT = {true, false};
}
// DONOT DELETE LET THESE STAY HERE.
// CurrencyCode
// CurrencySymbol
// Locale
// MaxFractionDigits
// MaxIntegerDigits
// MinFractionDigits
// MinIntegerDigits
// Pattern
// Type
// GroupingUsed
// IntegerOnly
//Currency Code | Country Currency
//USD - United States Dollar
//
//ITL - Italian Lira
//
//DEM - German Mark
//
//HKG - Hong Kong Dollar
//
//MXN - Mexican Peso
//
//EUR - Euro
// CurrencyCode tested
// CurrencySymbol tested
// Locale tested to pick up from viewRoot
// MaxFractionDigits only while formatting
// MaxIntegerDigits only while formatting
// MinFractionDigits only while formatting
// MinIntegerDigits only while formatting
// Pattern tested
// Type tested
// GroupingUsed tested
// IntegerOnly tested // only while parsing