google-nomulus/javatests/google/registry/ui/forms/FormFieldTest.java
Michael Muller c458c05801 Rename Java packages to use the .google TLD
The dark lord Gosling designed the Java package naming system so that
ownership flows from the DNS system. Since we own the domain name
registry.google, it seems only appropriate that we should use
google.registry as our package name.
2016-05-13 20:04:42 -04:00

491 lines
16 KiB
Java

// Copyright 2016 The Domain Registry Authors. 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 google.registry.ui.forms;
import static com.google.common.collect.Range.atLeast;
import static com.google.common.collect.Range.atMost;
import static com.google.common.collect.Range.closed;
import static com.google.common.truth.Truth.assertThat;
import static org.hamcrest.Matchers.equalTo;
import com.google.common.base.CharMatcher;
import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Range;
import com.google.common.testing.NullPointerTester;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
/** Unit tests for {@link FormField}. */
@RunWith(JUnit4.class)
public class FormFieldTest {
private enum ICanHazEnum { LOL, CAT }
@Rule
public final ExpectedException thrown = ExpectedException.none();
@Test
public void testConvert_nullString_notPresent() {
assertThat(FormField.named("lol").build().convert(null)).isAbsent();
}
@Test
public void testConvert_emptyString_returnsEmpty() {
assertThat(FormField.named("lol").build().convert("").get()).isEmpty();
}
@Test
public void testWithDefault_hasValue_returnsValue() {
assertThat(FormField.named("lol").withDefault("default").build().convert("return me!"))
.hasValue("return me!");
}
@Test
public void testWithDefault_nullValue_returnsDefault() {
assertThat(FormField.named("lol").withDefault("default").build().convert(null))
.hasValue("default");
}
@Test
public void testEmptyToNull_emptyString_notPresent() {
assertThat(FormField.named("lol").emptyToNull().build().convert("")).isAbsent();
}
@Test
public void testEmptyToNullRequired_emptyString_throwsFfe() {
thrown.expect(equalTo(new FormFieldException("This field is required.").propagate("lol")));
FormField.named("lol").emptyToNull().required().build().convert("");
}
@Test
public void testEmptyToNull_typeMismatch() {
thrown.expect(IllegalStateException.class);
FormField.named("lol", Object.class).emptyToNull();
}
@Test
public void testNamedLong() {
assertThat(FormField.named("lol", Long.class).build().convert(666L)).hasValue(666L);
}
@Test
public void testUppercased() {
FormField<String, String> field = FormField.named("lol").uppercased().build();
assertThat(field.convert(null)).isAbsent();
assertThat(field.convert("foo")).hasValue("FOO");
assertThat(field.convert("BAR")).hasValue("BAR");
}
@Test
public void testLowercased() {
FormField<String, String> field = FormField.named("lol").lowercased().build();
assertThat(field.convert(null)).isAbsent();
assertThat(field.convert("foo")).hasValue("foo");
assertThat(field.convert("BAR")).hasValue("bar");
}
@Test
public void testIn_passesThroughNull() {
FormField<String, String> field = FormField.named("lol")
.in(ImmutableSet.of("foo", "bar"))
.build();
assertThat(field.convert(null)).isAbsent();
}
@Test
public void testIn_valueIsContainedInSet() {
FormField<String, String> field = FormField.named("lol")
.in(ImmutableSet.of("foo", "bar"))
.build();
assertThat(field.convert("foo")).hasValue("foo");
assertThat(field.convert("bar")).hasValue("bar");
}
@Test
public void testIn_valueMissingFromSet() {
FormField<String, String> field = FormField.named("lol")
.in(ImmutableSet.of("foo", "bar"))
.build();
thrown.expect(equalTo(new FormFieldException("Unrecognized value.").propagate("lol")));
field.convert("omfg");
}
@Test
public void testRange_hasLowerBound_nullValue_passesThrough() {
assertThat(FormField.named("lol").range(atLeast(5)).build().convert(null)).isAbsent();
}
@Test
public void testRange_minimum_stringLengthEqualToMinimum_doesNothing() {
assertThat(FormField.named("lol").range(atLeast(5)).build().convert("hello")).hasValue("hello");
}
@Test
public void testRange_minimum_stringLengthShorterThanMinimum_throwsFfe() {
thrown.expect(FormFieldException.class);
thrown.expectMessage("Number of characters (3) not in range [4");
FormField.named("lol").range(atLeast(4)).build().convert("lol");
}
@Test
public void testRange_noLowerBound_nullValue_passThrough() {
assertThat(FormField.named("lol").range(atMost(5)).build().convert(null)).isAbsent();
}
@Test
public void testRange_maximum_stringLengthEqualToMaximum_doesNothing() {
assertThat(FormField.named("lol").range(atMost(5)).build().convert("hello")).hasValue("hello");
}
@Test
public void testRange_maximum_stringLengthShorterThanMaximum_throwsFfe() {
thrown.expect(FormFieldException.class);
thrown.expectMessage("Number of characters (6) not in range");
FormField.named("lol").range(atMost(5)).build().convert("omgomg");
}
@Test
public void testRange_numericTypes() {
FormField.named("lol", Byte.class).range(closed(5, 10)).build().convert((byte) 7);
FormField.named("lol", Short.class).range(closed(5, 10)).build().convert((short) 7);
FormField.named("lol", Integer.class).range(closed(5, 10)).build().convert(7);
FormField.named("lol", Long.class).range(closed(5, 10)).build().convert(7L);
FormField.named("lol", Float.class).range(closed(5, 10)).build().convert(7F);
FormField.named("lol", Double.class).range(closed(5, 10)).build().convert(7D);
}
@Test
public void testRange_typeMismatch() {
thrown.expect(IllegalStateException.class);
FormField.named("lol", Object.class).range(atMost(5));
}
@Test
public void testMatches_matches_doesNothing() {
assertThat(FormField.named("lol").matches(Pattern.compile("[a-z]+")).build().convert("abc"))
.hasValue("abc");
}
@Test
public void testMatches_mismatch_throwsFfeAndShowsDefaultErrorMessageWithPattern() {
thrown.expect(equalTo(new FormFieldException("Must match pattern: [a-z]+").propagate("lol")));
FormField.named("lol").matches(Pattern.compile("[a-z]+")).build().convert("123abc456");
}
@Test
public void testMatches_typeMismatch() {
thrown.expect(IllegalStateException.class);
FormField.named("lol", Object.class).matches(Pattern.compile("."));
}
@Test
public void testRetains() {
assertThat(
FormField.named("lol")
.retains(CharMatcher.anyOf("0123456789"))
.build()
.convert(" 123 1593-43 453 45 4 4 \t"))
.hasValue("1231593434534544");
}
@Test
public void testCast() {
assertThat(
FormField.named("lol")
.transform(
Integer.class,
new Function<String, Integer>() {
@Override
public Integer apply(String input) {
return Integer.parseInt(input);
}
})
.build()
.convert("123"))
.hasValue(123);
}
@Test
public void testCast_twice() {
assertThat(
FormField.named("lol")
.transform(
Object.class,
new Function<String, Object>() {
@Override
public Integer apply(String input) {
return Integer.parseInt(input);
}
})
.transform(String.class, Functions.toStringFunction())
.build()
.convert("123"))
.hasValue("123");
}
@Test
public void testAsList_null_notPresent() {
assertThat(FormField.named("lol").asList().build().convert(null)).isAbsent();
}
@Test
public void testAsList_empty_returnsEmpty() {
assertThat(FormField.named("lol").asList().build().convert(ImmutableList.<String>of()).get())
.isEmpty();
}
@Test
public void testAsListEmptyToNullRequired_empty_throwsFfe() {
thrown.expect(equalTo(new FormFieldException("This field is required.").propagate("lol")));
FormField.named("lol")
.asList()
.emptyToNull()
.required()
.build()
.convert(ImmutableList.<String>of());
}
@Test
public void testListEmptyToNull_empty_notPresent() {
assertThat(FormField.named("lol")
.asList()
.emptyToNull()
.build()
.convert(ImmutableList.<String>of()))
.isAbsent();
}
@Test
public void testAsEnum() {
FormField<String, ICanHazEnum> omgField = FormField.named("omg")
.asEnum(ICanHazEnum.class)
.build();
assertThat(omgField.convert("LOL").get()).isEqualTo(ICanHazEnum.LOL);
assertThat(omgField.convert("CAT").get()).isEqualTo(ICanHazEnum.CAT);
}
@Test
public void testAsEnum_lowercase_works() {
FormField<String, ICanHazEnum> omgField = FormField.named("omg")
.asEnum(ICanHazEnum.class)
.build();
assertThat(omgField.convert("lol").get()).isEqualTo(ICanHazEnum.LOL);
assertThat(omgField.convert("cat").get()).isEqualTo(ICanHazEnum.CAT);
}
@Test
public void testAsEnum_badInput_throwsFfe() {
FormField<String, ICanHazEnum> omgField = FormField.named("omg")
.asEnum(ICanHazEnum.class)
.build();
thrown.expect(equalTo(new FormFieldException("Enum ICanHazEnum does not contain 'helo'")
.propagate("omg")));
omgField.convert("helo");
}
@Test
public void testSplitList() {
FormField<String, List<String>> field = FormField.named("lol")
.asList(Splitter.on(',').omitEmptyStrings())
.build();
assertThat(field.convert("oh,my,goth").get())
.containsExactly("oh", "my", "goth")
.inOrder();
assertThat(field.convert("").get()).isEmpty();
assertThat(field.convert(null)).isAbsent();
}
@Test
public void testSplitSet() {
FormField<String, Set<String>> field = FormField.named("lol")
.uppercased()
.asSet(Splitter.on(',').omitEmptyStrings())
.build();
assertThat(field.convert("oh,my,goth").get())
.containsExactly("OH", "MY", "GOTH")
.inOrder();
assertThat(field.convert("").get()).isEmpty();
assertThat(field.convert(null)).isAbsent();
}
@Test
public void testAsList() {
assertThat(
FormField.named("lol").asList().build().convert(ImmutableList.of("lol", "cat", "")).get())
.containsExactly("lol", "cat", "").inOrder();
}
@Test
public void testAsList_trimmedEmptyToNullOnItems() {
assertThat(FormField.named("lol")
.trimmed()
.emptyToNull()
.matches(Pattern.compile("[a-z]+"))
.asList()
.range(closed(1, 2))
.build()
.convert(ImmutableList.of("lol\n", "\tcat "))
.get())
.containsExactly("lol", "cat").inOrder();
}
@Test
public void testAsList_nullElements_getIgnored() {
assertThat(FormField.named("lol")
.emptyToNull()
.asList()
.build()
.convert(ImmutableList.of("omg", ""))
.get())
.containsExactly("omg");
}
@Test
public void testAsListRequiredElements_nullElement_throwsFfeWithIndex() {
thrown.expect(equalTo(new FormFieldException("This field is required.")
.propagate(1)
.propagate("lol")));
FormField.named("lol")
.emptyToNull()
.required()
.asList()
.build()
.convert(ImmutableList.of("omg", ""));
}
@Test
public void testMapAsListRequiredElements_nullElement_throwsFfeWithIndexAndKey() {
thrown.expect(equalTo(new FormFieldException("This field is required.")
.propagate("cat")
.propagate(0)
.propagate("lol")));
FormField.mapNamed("lol")
.transform(String.class, new Function<Map<String, ?>, String>() {
@Override
public String apply(Map<String, ?> input) {
return FormField.named("cat")
.emptyToNull()
.required()
.build()
.extractUntyped(input)
.get();
}})
.asList()
.build()
.convert(ImmutableList.<Map<String, ?>>of(
ImmutableMap.of("cat", "")));
}
@Test
public void testAsListTrimmed_typeMismatch() {
FormField.named("lol").trimmed().asList();
thrown.expect(IllegalStateException.class);
FormField.named("lol").asList().trimmed();
}
@Test
public void testAsMatrix() {
assertThat(
FormField.named("lol", Integer.class)
.transform(new Function<Integer, Integer>() {
@Override
public Integer apply(Integer input) {
return input * 2;
}})
.asList()
.asList()
.build()
.convert(Lists.cartesianProduct(ImmutableList.of(
ImmutableList.of(1, 2),
ImmutableList.of(3, 4))))
.get())
.containsExactly(
ImmutableList.of(2, 6),
ImmutableList.of(2, 8),
ImmutableList.of(4, 6),
ImmutableList.of(4, 8)).inOrder();
}
@Test
public void testAsSet() {
assertThat(FormField.named("lol")
.asSet()
.build()
.convert(ImmutableList.of("lol", "cat", "cat"))
.get())
.containsExactly("lol", "cat");
}
@Test
public void testTrimmed() {
assertThat(FormField.named("lol").trimmed().build().convert(" \thello \t\n")).hasValue("hello");
}
@Test
public void testTrimmed_typeMismatch() {
thrown.expect(IllegalStateException.class);
FormField.named("lol", Object.class).trimmed();
}
@Test
public void testAsBuilder() {
FormField<String, String> field = FormField.named("omg").uppercased().build();
assertThat(field.name()).isEqualTo("omg");
assertThat(field.convert("hello")).hasValue("HELLO");
field = field.asBuilder().build();
assertThat(field.name()).isEqualTo("omg");
assertThat(field.convert("hello")).hasValue("HELLO");
}
@Test
public void testAsBuilderNamed() {
FormField<String, String> field = FormField.named("omg").uppercased().build();
assertThat(field.name()).isEqualTo("omg");
assertThat(field.convert("hello")).hasValue("HELLO");
field = field.asBuilderNamed("bog").build();
assertThat(field.name()).isEqualTo("bog");
assertThat(field.convert("hello")).hasValue("HELLO");
}
@Test
public void testNullness() {
NullPointerTester tester = new NullPointerTester()
.setDefault(Class.class, Object.class)
.setDefault(Function.class, Functions.identity())
.setDefault(Pattern.class, Pattern.compile("."))
.setDefault(Range.class, Range.all())
.setDefault(Map.class, ImmutableMap.of())
.setDefault(Set.class, ImmutableSet.of())
.setDefault(String.class, "hello.com");
tester.testAllPublicStaticMethods(FormField.class);
tester.testAllPublicInstanceMethods(FormField.named("lol"));
tester.testAllPublicInstanceMethods(FormField.named("lol").build());
}
}