/* * Copyright 2000-2016 Vaadin Ltd. * * Licensed 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 com.vaadin.tests.design; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.io.File; import java.math.BigDecimal; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashSet; import java.util.TimeZone; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import com.vaadin.event.ShortcutAction; import com.vaadin.event.ShortcutAction.KeyCode; import com.vaadin.event.ShortcutAction.ModifierKey; import com.vaadin.server.ExternalResource; import com.vaadin.server.FileResource; import com.vaadin.server.FontAwesome; import com.vaadin.server.FontIcon; import com.vaadin.server.GenericFontIcon; import com.vaadin.server.Resource; import com.vaadin.server.ThemeResource; import com.vaadin.shared.ApplicationConstants; import com.vaadin.shared.util.SharedUtil; import com.vaadin.ui.declarative.DesignFormatter; /** * Various tests related to formatter. * * @since 7.4 * @author Vaadin Ltd */ public class DesignFormatterTest { private DesignFormatter formatter; @Before public void setUp() { // initialise with default classes formatter = new DesignFormatter(); } @Test public void testSupportedClasses() { for (Class<?> type : new Class<?>[] { boolean.class, char.class, byte.class, short.class, int.class, long.class, float.class, double.class, Boolean.class, Character.class, Byte.class, Short.class, Integer.class, Long.class, Float.class, Double.class, BigDecimal.class, String.class, ShortcutAction.class, Date.class, FileResource.class, ExternalResource.class, ThemeResource.class, Resource.class, TimeZone.class }) { assertTrue("not supported " + type.getSimpleName(), formatter.canConvert(type)); } } @Test public void testBoolean() { assertEquals("", formatter.format(true)); assertEquals("false", formatter.format(false)); Assert.assertTrue(formatter.parse("true", boolean.class)); Assert.assertTrue(formatter.parse("foobar", boolean.class)); Assert.assertTrue(formatter.parse("", boolean.class)); Assert.assertFalse(formatter.parse("false", boolean.class)); Assert.assertTrue(formatter.parse("true", Boolean.class)); Assert.assertTrue(formatter.parse("foobar", Boolean.class)); Assert.assertTrue(formatter.parse("", Boolean.class)); Assert.assertFalse(formatter.parse("false", Boolean.class)); } @Test public void testIntegral() { byte b = 123; assertEquals("123", formatter.format(b)); assertEquals(b, (byte) formatter.parse("123", byte.class)); assertEquals((Byte) b, formatter.parse("123", Byte.class)); b = -123; assertEquals("-123", formatter.format(b)); assertEquals(b, (byte) formatter.parse("-123", byte.class)); assertEquals((Byte) b, formatter.parse("-123", Byte.class)); short s = 12345; assertEquals("12345", formatter.format(s)); assertEquals(s, (short) formatter.parse("12345", short.class)); assertEquals((Short) s, formatter.parse("12345", Short.class)); s = -12345; assertEquals("-12345", formatter.format(s)); assertEquals(s, (short) formatter.parse("-12345", short.class)); assertEquals((Short) s, formatter.parse("-12345", Short.class)); int i = 123456789; assertEquals("123456789", formatter.format(i)); assertEquals(i, (int) formatter.parse("123456789", int.class)); assertEquals((Integer) i, formatter.parse("123456789", Integer.class)); i = -123456789; assertEquals("-123456789", formatter.format(i)); assertEquals(i, (int) formatter.parse("-123456789", int.class)); assertEquals((Integer) i, formatter.parse("-123456789", Integer.class)); long l = 123456789123456789L; assertEquals("123456789123456789", formatter.format(l)); assertEquals(l, (long) formatter.parse("123456789123456789", long.class)); assertEquals((Long) l, formatter.parse("123456789123456789", Long.class)); l = -123456789123456789L; assertEquals("-123456789123456789", formatter.format(l)); assertEquals(l, (long) formatter.parse("-123456789123456789", long.class)); assertEquals((Long) l, formatter.parse("-123456789123456789", Long.class)); } @Test public void testFloatingPoint() { float f = 123.4567f; assertEquals("123.457", formatter.format(f)); float f1 = formatter.parse("123.4567", float.class); assertEquals(f, f1, 1e-4); Float f2 = formatter.parse("123.4567", Float.class); assertEquals(f, f2, 1e-4); double d = 123456789.123456789; assertEquals("123456789.123", formatter.format(d)); assertEquals(d, formatter.parse("123456789.123456789", double.class), 1e-9); assertEquals(d, formatter.parse("123456789.123456789", Double.class), 1e-9); } @Test public void testBigDecimal() { BigDecimal bd = new BigDecimal("123456789123456789.123456789123456789"); assertEquals("123456789123456789.123", formatter.format(bd)); assertEquals(bd, formatter.parse( "123456789123456789.123456789123456789", BigDecimal.class)); } @Test public void testChar() { char c = '\uABCD'; assertEquals("\uABCD", formatter.format(c)); assertEquals(c, (char) formatter.parse("\uABCD", char.class)); assertEquals((Character) c, formatter.parse("\uABCD", Character.class)); c = 'y'; assertEquals(c, (char) formatter.parse("yes", char.class)); } @Test public void testString() { for (String s : new String[] { "", "foobar", "\uABCD", "驯鹿" }) { assertEquals(s, formatter.format(s)); assertEquals(s, formatter.parse(s, String.class)); } } @Test public void testDate() throws Exception { Date date = new SimpleDateFormat("yyyy-MM-dd").parse("2012-02-17"); String formatted = formatter.format(date); Date result = formatter.parse(formatted, Date.class); // writing will always give full date string String timeZone = new SimpleDateFormat("Z").format(date); assertEquals("2012-02-17 00:00:00" + timeZone, formatted); assertEquals(date, result); // try short date as well result = formatter.parse("2012-02-17", Date.class); assertEquals(date, result); } @Test public void testShortcutActions() { ShortcutAction action = new ShortcutAction("&^d"); String formatted = formatter.format(action); // note the space here - it separates key combination from caption assertEquals("ctrl-alt-d d", formatted); ShortcutAction result = formatter.parse(formatted, ShortcutAction.class); assertTrue(equals(action, result)); } @Test public void testShortcutActionNoCaption() { ShortcutAction action = new ShortcutAction(null, KeyCode.D, new int[] { ModifierKey.ALT, ModifierKey.CTRL }); String formatted = formatter.format(action); assertEquals("ctrl-alt-d", formatted); ShortcutAction result = formatter.parse(formatted, ShortcutAction.class); assertTrue(equals(action, result)); } @Test public void testInvalidShortcutAction() { assertInvalidShortcut("-"); assertInvalidShortcut("foo"); assertInvalidShortcut("atl-ctrl"); assertInvalidShortcut("-a"); } protected void assertInvalidShortcut(String shortcut) { try { formatter.parse(shortcut, ShortcutAction.class); Assert.fail("Invalid shortcut '" + shortcut + "' should throw"); } catch (IllegalArgumentException e) { // expected } } @Test public void testTimeZone() { TimeZone zone = TimeZone.getTimeZone("GMT+2"); String formatted = formatter.format(zone); assertEquals("GMT+02:00", formatted); TimeZone result = formatter.parse(formatted, TimeZone.class); assertEquals(zone, result); // try shorthand notation as well result = formatter.parse("GMT+2", TimeZone.class); assertEquals(zone, result); } @Test public void testExternalResource() { String url = "://example.com/my%20icon.png?a=b"; for (String scheme : new String[] { "http", "https", "ftp", "ftps" }) { Resource resource = formatter.parse(scheme + url, Resource.class); assertTrue(scheme + " url should be parsed as ExternalResource", resource instanceof ExternalResource); assertEquals("parsed ExternalResource", scheme + url, ((ExternalResource) resource).getURL()); String formatted = formatter .format(new ExternalResource(scheme + url)); assertEquals("formatted ExternalResource", scheme + url, formatted); } } @Test public void testResourceFormat() { String httpUrl = "http://example.com/icon.png"; String httpsUrl = "https://example.com/icon.png"; String themePath = "icons/icon.png"; String fontAwesomeUrl = "fonticon://FontAwesome/f0f9"; String someOtherFontUrl = "fonticon://SomeOther/F0F9"; String fileSystemPath = "c:/app/resources/icon.png"; assertEquals(httpUrl, formatter.format(new ExternalResource(httpUrl))); assertEquals(httpsUrl, formatter.format(new ExternalResource(httpsUrl))); assertEquals(ApplicationConstants.THEME_PROTOCOL_PREFIX + themePath, formatter.format(new ThemeResource(themePath))); assertEquals(fontAwesomeUrl, formatter.format(FontAwesome.AMBULANCE)); assertEquals(someOtherFontUrl.toLowerCase(), formatter.format(new GenericFontIcon("SomeOther", 0xf0f9)) .toLowerCase()); assertEquals(fileSystemPath, formatter.format(new FileResource(new File(fileSystemPath)))); } @Test(expected = IllegalArgumentException.class) public void testResourceParseException() { String someRandomResourceUrl = "random://url"; formatter.parse(someRandomResourceUrl, Resource.class); } @Test(expected = IllegalArgumentException.class) public void testResourceFormatException() { formatter.format(new Resource() { // must use unknown resource type @Override public String getMIMEType() { // TODO Auto-generated method stub return null; } }); } @Test public void testResourceParse() { String httpUrl = "http://example.com/icon.png"; String httpsUrl = "https://example.com/icon.png"; String themePath = "icons/icon.png"; String fontAwesomeUrl = "fonticon://FontAwesome/f0f9"; String someOtherFont = "fonticon://SomeOther/F0F9"; String fontAwesomeUrlOld = "font://AMBULANCE"; String fileSystemPath = "c:\\app\\resources\\icon.png"; assertEquals(new ExternalResource(httpUrl).getURL(), formatter.parse(httpUrl, ExternalResource.class).getURL()); assertEquals(new ExternalResource(httpsUrl).getURL(), formatter.parse(httpsUrl, ExternalResource.class).getURL()); assertEquals(new ThemeResource(themePath), formatter.parse( ApplicationConstants.THEME_PROTOCOL_PREFIX + themePath, ThemeResource.class)); assertEquals(FontAwesome.AMBULANCE, formatter.parse(fontAwesomeUrlOld, FontAwesome.class)); assertEquals(FontAwesome.AMBULANCE, formatter.parse(fontAwesomeUrl, FontAwesome.class)); assertEquals(new GenericFontIcon("SomeOther", 0xF0F9), formatter.parse(someOtherFont, FontIcon.class)); assertEquals(new FileResource(new File(fileSystemPath)).getSourceFile(), formatter.parse(fileSystemPath, FileResource.class) .getSourceFile()); } /** * A static method to allow comparison two different actions. * * @param act * One action to compare. * @param other * Second action to compare. * @return <b>true</b> when both actions are the same (caption, icon, and * key combination). */ public static final boolean equals(ShortcutAction act, ShortcutAction other) { if (SharedUtil.equals(other.getCaption(), act.getCaption()) && SharedUtil.equals(other.getIcon(), act.getIcon()) && act.getKeyCode() == other.getKeyCode() && act.getModifiers().length == other.getModifiers().length) { HashSet<Integer> thisSet = new HashSet<>(act.getModifiers().length); // this is a bit tricky comparison, but there is no nice way of // making int[] into a Set for (int mod : act.getModifiers()) { thisSet.add(mod); } for (int mod : other.getModifiers()) { thisSet.remove(mod); } return thisSet.isEmpty(); } return false; } }