/* * Copyright (c) 2002-2012 Alibaba Group Holding Limited. * All rights reserved. * * 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.alibaba.citrus.service.form; import static com.alibaba.citrus.test.TestEnvStatic.*; import static com.alibaba.citrus.test.TestUtil.*; import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; import java.beans.PropertyEditorSupport; import java.io.File; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Collection; import java.util.Date; import java.util.Iterator; import java.util.TimeZone; import com.alibaba.citrus.service.form.configuration.GroupConfig; import org.apache.commons.fileupload.FileItem; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; import org.springframework.beans.TypeMismatchException; import org.springframework.context.ApplicationContext; @RunWith(Parameterized.class) public class GroupTests extends AbstractFormServiceTests { private final ApplicationContext factory; private final boolean withParserRequestContext; private Form form; private Group group; private Field field1; private Field field2; public GroupTests(ApplicationContext factory, boolean withParserRequestContext) { this.factory = factory; this.withParserRequestContext = withParserRequestContext; } @Parameters public static Collection<Object[]> data() { // 分别测试两组:1. 有parser request context 2. 无parser request context,纯HttpServletRequest ApplicationContext withParserRequestContextAndUpload = createContext("services-form.xml", true); ApplicationContext noParserRequestContextOrUpload = createContext("services-form.xml", false); return Arrays.asList(new Object[][] { { withParserRequestContextAndUpload, true }, { noParserRequestContextOrUpload, false } }); } @Before public void init() throws Exception { getFormService("form1", factory); invokePost(factory, null); form = formService.getForm(); group = form.getGroup("group1"); field1 = group.getField("field1"); field2 = group.getField("field2"); assertEquals(false, group.isValidated()); assertEquals(true, group.isValid()); assertEquals("default1", field1.getValue()); // specified default value assertEquals(null, field2.getValue()); // default is null } @Test public void getGroupConfig() throws Exception { GroupConfig gc = group.getGroupConfig(); assertNotNull(gc); assertSame(form.getFormConfig(), gc.getFormConfig()); } @Test public void getForm() throws Exception { assertSame(form, group.getForm()); } @Test public void getName() throws Exception { assertEquals("group1", group.getName()); } @Test public void getKey() throws Exception { assertEquals("_fm.g._0", group.getKey()); group = form.getGroup("group1", "111"); assertEquals("_fm.g.111", group.getKey()); } @Test public void getInstanceKey() throws Exception { assertEquals("_0", group.getInstanceKey()); group = form.getGroup("group1", "111"); assertEquals("111", group.getInstanceKey()); } /** 确保validator可以读到后面的field值。 */ @Test public void validate_multiFields() throws Exception { getFormService("form2", factory); // field1 failed to validate Object[][] args = new Object[][] { { "sumbit", "提交" }, // { "_fm.g._0.f", "aaa" }, // group1.field1 { "_fm.g._0.fi", "bbb" }, // group1.field2 }; invokePost(factory, args); form = formService.getForm(); assertEquals(false, form.isValid()); group = form.getGroup("group1"); assertEquals(false, group.isValid()); assertEquals(false, group.getField("field1").isValid()); assertEquals(true, group.getField("field2").isValid()); // succeeded in validating args = new Object[][] { { "sumbit", "提交" }, // { "_fm.g._0.f", "value1" }, // group1.field1 { "_fm.g._0.fi", "value2" }, // group1.field2 }; invokePost(factory, args); form = formService.getForm(); assertEquals(true, form.isValid()); group = form.getGroup("group1"); assertEquals(true, group.isValid()); assertEquals(true, group.getField("field1").isValid()); assertEquals(true, group.getField("field2").isValid()); } @Test public void isValidated() throws Exception { // no data assertEquals(false, group.isValidated()); // with data Object[][] args = new Object[][] { { "sumbit", "提交" }, // { "_fm.g._0.f", "aaa" }, // group1.field1 { "_fm.g._0.fi", "bbb" }, // group1.field2 }; invokePost(factory, args); form = formService.getForm(); group = form.getGroup("group1"); assertEquals(true, group.isValidated()); // re-init form.init(); group = form.getGroup("group1"); assertEquals(false, group.isValidated()); } @Test public void getFields() throws Exception { Object[][] args = new Object[][] { { "sumbit", "提交" }, // { "_fm.g._0.f", "aaa" }, // group1.field1 }; invokePost(factory, args); form = formService.getForm(); assertEquals(false, form.isValid()); group = form.getGroup("group1"); assertEquals(false, group.isValid()); // getFields Collection<Field> fields = group.getFields(); Iterator<Field> i = fields.iterator(); assertEquals(2, fields.size()); assertEquals(true, i.next().isValid()); assertEquals(false, i.next().isValid()); // getField Field field1 = group.getField("field1"); Field field2 = group.getField("field2"); assertEquals(true, field1.isValid()); assertEquals(false, field2.isValid()); } @Test public void mapTo_null() throws Exception { group.mapTo(null); // 状态不变 assertEquals(false, group.isValidated()); assertEquals(true, group.isValid()); assertEquals("default1", field1.getValue()); assertEquals(null, field2.getValue()); } /** isValidated == true,不允许执行mapTo。 */ @Test public void mapTo_isValidated() throws Exception { group.validate(); assertEquals(true, group.isValidated()); assertEquals(false, group.isValid()); group.mapTo(new MyIntObject(234)); // 原状态不受影响 assertEquals(true, group.isValidated()); assertEquals(false, group.isValid()); assertEquals(true, field1.isValid()); assertEquals("default1", field1.getValue()); // 不是234 assertEquals(false, field2.isValid()); assertEquals(null, field2.getValue()); } @Test public void mapTo_simpleValue() throws Exception { group.mapTo(new MyIntObject(234)); // field1(property1)存在,field2不存在 // mapTo不影响isValidated和isValid状态 assertEquals(false, group.isValidated()); assertEquals(true, group.isValid()); assertEquals(true, field1.isValid()); assertEquals("234", field1.getValue()); assertEquals(true, field2.isValid()); assertEquals(null, field2.getValue()); } @Test public void mapTo_stringArray() throws Exception { group.mapTo(new MyStringArrayObject("aaa", "bbb")); // field1(property1)不存在,field2存在 // mapTo不影响isValidated和isValid状态 assertEquals(false, group.isValidated()); assertEquals(true, group.isValid()); assertEquals(true, field1.isValid()); assertEquals("default1", field1.getValue()); assertEquals(true, field2.isValid()); assertEquals("aaa", field2.getValue()); assertArrayEquals(new Object[] { "aaa", "bbb" }, field2.getValues()); } @Test public void mapTo_customType() throws Exception { group.mapTo(new MyCustomObject(new SimpleValue("aaa"))); // field1(property1)不存在,field2存在 // mapTo不影响isValidated和isValid状态 assertEquals(false, group.isValidated()); assertEquals(true, group.isValid()); assertEquals(true, field1.isValid()); assertEquals("default1", field1.getValue()); assertEquals(true, field2.isValid()); assertEquals("aaa", field2.getValue()); } @Test public void mapTo_date() throws Exception { group.mapTo(new MyDateObject("1989-06-04")); assertEquals(false, group.isValidated()); assertEquals(true, group.isValid()); assertEquals(true, field1.isValid()); assertEquals("1989-06-04", field1.getValue()); assertEquals(true, field2.isValid()); assertEquals(null, field2.getValue()); } @Test public void setProperties_null() throws Exception { Object[][] args = new Object[][] { { "sumbit", "提交" }, // { "_fm.g._0.f", "aaa" }, // group1.field1 { "_fm.g._0.fi", "bbb" }, // group1.field2 }; invokePost(factory, args); form = formService.getForm(); group = form.getGroup("group1"); assertEquals(true, group.isValid()); assertEquals(true, group.isValidated()); group.setProperties(null); assertEquals(true, group.isValid()); assertEquals(true, group.isValidated()); } @Test public void setProperties_unSet() throws Exception { invokePost(factory, null); form = formService.getForm(); group = form.getGroup("group1"); group.getField("field1").setValue("234"); assertEquals(true, group.isValid()); assertEquals(false, group.isValidated()); MyIntObject obj = new MyIntObject(); group.setProperties(obj); assertEquals(true, group.isValid()); assertEquals(false, group.isValidated()); assertEquals(-1, obj.getProperty1()); // not set } @Test public void setProperties_invalid() throws Exception { Object[][] args = new Object[][] { { "sumbit", "提交" }, // { "_fm.g._0.f", "aaa" }, // group1.field1 { "_fm.g._0.fi", "" }, // group1.field2 }; invokePost(factory, args); form = formService.getForm(); group = form.getGroup("group1"); assertEquals(false, group.isValid()); assertEquals(true, group.isValidated()); MyIntObject obj = new MyIntObject(); try { group.setProperties(obj); fail(); } catch (InvalidGroupStateException e) { assertThat(e, exception("Attempted to call setProperties from an invalid input")); } assertEquals(false, group.isValid()); assertEquals(true, group.isValidated()); } @Test public void setProperties_simpleValue() throws Exception { Object[][] args = new Object[][] { { "sumbit", "提交" }, // { "_fm.g._0.f", "234" }, // group1.field1 { "_fm.g._0.fi", "bbb" }, // group1.field2 }; invokePost(factory, args); form = formService.getForm(); group = form.getGroup("group1"); assertEquals(true, group.isValid()); assertEquals(true, group.isValidated()); // field1(property1)存在,field2不存在 MyIntObject obj = new MyIntObject(); group.setProperties(obj); assertEquals(123, obj.getProperty1()); // 由于custom editor的存在,值变成123 assertEquals(true, group.isValid()); assertEquals(true, group.isValidated()); } @Test public void setProperties_quietMode() throws Exception { getFormService("form3", factory); Object[][] args = new Object[][] { { "sumbit", "提交" }, // { "_fm.g._0.f", "illegal" }, // group1.field1 }; invokePost(factory, args); form = formService.getForm(); group = form.getGroup("group1"); assertEquals(true, group.isValid()); assertEquals(true, group.isValidated()); // 转换失败,但是quiet=true,使用默认值。 MyIntObject obj = new MyIntObject(); group.setProperties(obj); assertEquals(0, obj.getProperty1()); } @Test public void setProperties_noisyMode() throws Exception { getFormService("form4", factory); Object[][] args = new Object[][] { { "sumbit", "提交" }, // { "_fm.g._0.f", "illegal" }, // group1.field1 }; invokePost(factory, args); form = formService.getForm(); group = form.getGroup("group1"); assertEquals(true, group.isValid()); assertEquals(true, group.isValidated()); // 转换失败,但是quiet=true,使用默认值。 try { group.setProperties(new MyIntObject()); fail(); } catch (TypeMismatchException e) { assertThat(e, exception("illegal")); } } @Test public void setProperties_stringArray() throws Exception { Object[][] args = new Object[][] { { "sumbit", "提交" }, // { "_fm.g._0.f", "aaa" }, // group1.field1 { "_fm.g._0.fi", new String[] { "bbb", "ccc", "ddd" } }, // group1.field2 }; invokePost(factory, args); form = formService.getForm(); group = form.getGroup("group1"); assertEquals(true, group.isValid()); assertEquals(true, group.isValidated()); // field1(property1)不存在,field2存在 MyStringArrayObject obj = new MyStringArrayObject(); group.setProperties(obj); assertArrayEquals(new String[] { "bbb", "ccc", "ddd" }, obj.getField2()); assertEquals(true, group.isValid()); assertEquals(true, group.isValidated()); } @Test public void setProperties_customType() throws Exception { Object[][] args = new Object[][] { { "sumbit", "提交" }, // { "_fm.g._0.f", "aaa" }, // group1.field1 { "_fm.g._0.fi", "bbb" }, // group1.field2 }; invokePost(factory, args); form = formService.getForm(); group = form.getGroup("group1"); assertEquals(true, group.isValid()); assertEquals(true, group.isValidated()); // field1(property1)不存在,field2存在 MyCustomObject obj = new MyCustomObject(); group.setProperties(obj); assertEquals("bbb", obj.getField2().value); assertEquals(true, group.isValid()); assertEquals(true, group.isValidated()); } @Test public void setProperties_noValues() throws Exception { Object[][] args = new Object[][] { { "sumbit", "提交" }, // { "_fm.gro._0.f", "aaa" }, // group3.field1 }; invokePost(factory, args); form = formService.getForm(); group = form.getGroup("group3"); assertEquals(true, group.isValid()); assertEquals(true, group.isValidated()); // field1(property1)不存在,field2存在 MyCustomObject obj = new MyCustomObject(); group.setProperties(obj); assertEquals(null, obj.getField2()); assertEquals(true, group.isValid()); assertEquals(true, group.isValidated()); } @Test public void setProperties_fileItem() throws Exception { Object[][] args = new Object[][] { { "sumbit", "提交" }, // { "_fm.g._0.f", "aaa" }, // group1.field1 { "_fm.g._0.fi", new File(srcdir, "data/file1.txt") }, // group1.field2 }; invokePostMime(factory, args); if (!withParserRequestContext) { assertTrue(newRequest.getParameterMap().isEmpty()); return; } form = formService.getForm(); group = form.getGroup("group1"); field1 = group.getField("field1"); field2 = group.getField("field2"); assertEquals(true, group.isValid()); assertThat(field2.getValue(), instanceOf(FileItem.class)); MyFileItemObject fio = new MyFileItemObject(); group.setProperties(fio); assertEquals(1, fio.getField2().length); assertThat(fio.getField2()[0], instanceOf(FileItem.class)); } @Test public void setProperties_fileItems() throws Exception { Object[][] args = new Object[][] { { "sumbit", "提交" }, // { "_fm.g._0.f", "aaa" }, // group1.field1 { "_fm.g._0.fi", new File[] { new File(srcdir, "data/file1.txt"), new File(srcdir, "data/file2.txt") } }, // group1.field2 }; invokePostMime(factory, args); if (!withParserRequestContext) { assertTrue(newRequest.getParameterMap().isEmpty()); return; } form = formService.getForm(); group = form.getGroup("group1"); field1 = group.getField("field1"); field2 = group.getField("field2"); assertEquals(true, group.isValid()); assertThat(field2.getValue(), instanceOf(FileItem.class)); // fileItems MyFileItemObject fio = new MyFileItemObject(); group.setProperties(fio); assertEquals(2, fio.getField2().length); assertThat(fio.getField2()[0], instanceOf(FileItem.class)); assertThat(fio.getField2()[1], instanceOf(FileItem.class)); } @Test public void setProperties_date() throws Exception { Object[][] args = new Object[][] { { "sumbit", "提交" }, // { "_fm.g._0.f", "1989-6-4" }, // group1.field1 { "_fm.g._0.fi", "bbb" }, // group1.field2 }; invokePost(factory, args); form = formService.getForm(); group = form.getGroup("group1"); assertEquals(true, group.isValid()); assertEquals(true, group.isValidated()); MyDateObject obj = new MyDateObject(); group.setProperties(obj); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); sdf.setTimeZone(TimeZone.getTimeZone("GMT")); assertEquals("1989-06-04", sdf.format(obj.getProperty1())); assertEquals(true, group.isValid()); assertEquals(true, group.isValidated()); } @Test public void toString_() throws Exception { Object[][] args = new Object[][] { { "sumbit", "提交" }, // { "_fm.g._0.f", "aaa" }, // group1.default.field1 { "_fm.g.11.f", "aaa" }, // group1.11.field1 }; invokePost(factory, args); form = formService.getForm(); group = form.getGroup("group1"); assertEquals("Group[name: group1._0, fields: 2, validated: true, valid: false]", group.toString()); group = form.getGroup("group1", "11"); assertEquals("Group[name: group1.11, fields: 2, validated: true, valid: false]", group.toString()); } public static class MyIntObject { private int property1; public MyIntObject() { this(-1); } public MyIntObject(int property1) { this.property1 = property1; } public int getProperty1() { return property1; } public void setProperty1(int property1) { this.property1 = property1; } } public static class MyStringArrayObject { private String[] field2; public MyStringArrayObject(String... field2) { this.field2 = field2; } public String[] getField2() { return field2; } public void setField2(String[] field2) { this.field2 = field2; } } public static class MyCustomObject { private SimpleValue field2; public MyCustomObject() { } public MyCustomObject(SimpleValue field2) { this.field2 = field2; } public SimpleValue getField2() { return field2; } public void setField2(SimpleValue field2) { this.field2 = field2; } } public static class MyFileItemObject { private FileItem[] field2; public FileItem[] getField2() { return field2; } public void setField2(FileItem[] field2) { this.field2 = field2; } } public static class MyDateObject { private Date property1; public MyDateObject() { } public MyDateObject(String property1) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); sdf.setTimeZone(TimeZone.getTimeZone("GMT")); try { this.property1 = sdf.parse(property1); } catch (ParseException e) { fail(e.getMessage()); } } public Date getProperty1() { return property1; } public void setProperty1(Date property1) { this.property1 = property1; } } public static class SimpleValue { private String value; public SimpleValue(String value) { this.value = value; } @Override public String toString() { return value; } } public static class SimpleValueEditor extends PropertyEditorSupport { @Override public void setAsText(String text) throws IllegalArgumentException { setValue(new SimpleValue(text)); } } }