mv com/google/domain/registry google/registry

This change renames directories in preparation for the great package
rename. The repository is now in a broken state because the code
itself hasn't been updated. However this should ensure that git
correctly preserves history for each file.
This commit is contained in:
Justine Tunney 2016-05-13 18:55:08 -04:00
parent a41677aea1
commit 5012893c1d
2396 changed files with 0 additions and 0 deletions

View file

@ -0,0 +1,25 @@
package(default_visibility = ["//java/com/google/domain/registry:registry_project"])
load("//java/com/google/testing/builddefs:GenTestRules.bzl", "GenTestRules")
java_library(
name = "forms",
srcs = glob(["*.java"]),
deps = [
"//java/com/google/common/base",
"//java/com/google/common/collect",
"//java/com/google/common/testing",
"//java/com/google/domain/registry/ui/forms",
"//third_party/java/hamcrest",
"//third_party/java/junit",
"//third_party/java/mockito",
"//third_party/java/truth",
],
)
GenTestRules(
name = "GeneratedTestRules",
test_files = glob(["*Test.java"]),
deps = [":forms"],
)

View file

@ -0,0 +1,69 @@
// 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 com.google.domain.registry.ui.forms;
import static com.google.common.truth.Truth.assertThat;
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;
/** Unit tests for {@link FormFieldException}. */
@RunWith(JUnit4.class)
public class FormFieldExceptionTest {
@Rule
public final ExpectedException thrown = ExpectedException.none();
@Test
public void testGetFieldName_multiplePropagations_joinsUsingJsonNotation() throws Exception {
assertThat(
new FormFieldException("This field is required.")
.propagate("attack")
.propagate("cat")
.propagate(0)
.propagate("lol")
.getFieldName())
.isEqualTo("lol[0].cat.attack");
}
@Test
public void testGetFieldName_singlePropagations_noFancyJoining() throws Exception {
assertThat(
new FormFieldException("This field is required.")
.propagate("cat")
.getFieldName())
.isEqualTo("cat");
}
@Test
public void testGetFieldName_noPropagations_throwsIse() throws Exception {
thrown.expect(IllegalStateException.class);
new FormFieldException("This field is required.").getFieldName();
}
@Test
public void testNullness() {
NullPointerTester tester = new NullPointerTester()
.setDefault(FormField.class, FormField.named("love").build());
tester.testAllPublicConstructors(FormFieldException.class);
tester.testAllPublicStaticMethods(FormFieldException.class);
tester.testAllPublicInstanceMethods(new FormFieldException("lol"));
}
}

View file

@ -0,0 +1,491 @@
// 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 com.google.domain.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());
}
}

View file

@ -0,0 +1,107 @@
// 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 com.google.domain.registry.ui.forms;
import static com.google.common.truth.Truth.assertThat;
import static org.hamcrest.Matchers.equalTo;
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;
/** Unit tests for {@link FormFields}. */
@RunWith(JUnit4.class)
public class FormFieldsTest {
@Rule
public final ExpectedException thrown = ExpectedException.none();
@Test
public void testXsToken_collapsesAndTrimsWhitespace() {
assertThat(FormFields.XS_TOKEN.convert(" hello \r\n\t there\n")).hasValue("hello there");
}
@Test
public void testXsNormalizedString_extraSpaces_doesntCare() {
assertThat(FormFields.XS_NORMALIZED_STRING.convert("hello there")).hasValue("hello there");
}
@Test
public void testXsNormalizedString_sideSpaces_doesntCare() {
assertThat(FormFields.XS_NORMALIZED_STRING.convert(" hello there ")).hasValue(" hello there ");
}
@Test
public void testXsNormalizedString_containsNonSpaceWhitespace_fails() {
thrown.expect(equalTo(
new FormFieldException("Must not contain tabs or multiple lines.")
.propagate("xsNormalizedString")));
FormFields.XS_NORMALIZED_STRING.convert(" hello \r\n\t there\n");
}
@Test
public void testXsEppE164PhoneNumber_nanpaNumber_validates() {
assertThat(FormFields.XS_NORMALIZED_STRING.convert("+1.2125650000")).hasValue("+1.2125650000");
}
@Test
public void testXsEppE164PhoneNumber_londonNumber_validates() {
assertThat(FormFields.XS_NORMALIZED_STRING.convert("+44.2011112222"))
.hasValue("+44.2011112222");
}
@Test
public void testXsEppE164PhoneNumber_localizedNumber_fails() {
thrown.expect(FormFieldException.class);
thrown.expectMessage("Must be a valid +E.164 phone number, e.g. +1.2125650000");
FormFields.PHONE_NUMBER.convert("(212) 565-0000");
}
@Test
public void testXsEppE164PhoneNumber_appliesXsTokenTransform() {
assertThat(FormFields.PHONE_NUMBER.convert(" +1.2125650000 \r")).hasValue("+1.2125650000");
}
@Test
public void testXsEppRoid_correctSyntax_validates() {
assertThat(FormFields.ROID.convert("SH8013-REP")).hasValue("SH8013-REP");
}
@Test
public void testXsEppRoid_lowerCase_validates() {
assertThat(FormFields.ROID.convert("sh8013-rep")).hasValue("sh8013-rep");
}
@Test
public void testXsEppRoid_missingHyphen_fails() {
thrown.expect(FormFieldException.class);
thrown.expectMessage("Please enter a valid EPP ROID, e.g. SH8013-REP");
FormFields.ROID.convert("SH8013REP");
}
@Test
public void testXsEppRoid_appliesXsTokenTransform() {
assertThat(FormFields.ROID.convert("\n FOO-BAR \r")).hasValue("FOO-BAR");
}
@Test
public void testNullness() {
new NullPointerTester().testAllPublicStaticMethods(FormFields.class);
}
}

View file

@ -0,0 +1,23 @@
package(default_visibility = ["//java/com/google/domain/registry:registry_project"])
load("//third_party/closure/compiler:closure_js_library.bzl", "closure_js_library")
load("//third_party/closure/testing:closure_js_test.bzl", "closure_js_test")
closure_js_library(
name = "testing",
srcs = ["testing.js"],
deps = ["//javascript/closure"],
)
closure_js_test(
name = "test",
size = "medium",
timeout = "short",
srcs = glob(["*_test.js"]),
deps = [
":testing",
"//java/com/google/domain/registry/ui/js",
"//javascript/closure",
],
)

View file

@ -0,0 +1,43 @@
// 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.
goog.setTestOnly();
goog.require('goog.dispose');
goog.require('goog.testing.MockControl');
goog.require('goog.testing.jsunit');
goog.require('registry.Component');
goog.require('registry.Console');
var mocks = new goog.testing.MockControl();
function setUp() {
mocks = new goog.testing.MockControl();
}
function tearDown() {
mocks.$tearDown();
}
function testCreationAndDisposal_dontTouchConsoleObject() {
var console = mocks.createStrictMock(registry.Console);
mocks.$replayAll();
var component = new registry.Component(console);
goog.dispose(component);
mocks.$verifyAll();
}

View file

@ -0,0 +1,30 @@
package(default_visibility = ["//java/com/google/domain/registry:registry_project"])
load("//third_party/closure/compiler:closure_js_library.bzl", "closure_js_library")
load("//third_party/closure/testing:closure_js_test.bzl", "closure_js_test")
closure_js_library(
name = "console_test_util",
srcs = ["console_test_util.js"],
deps = [
"//java/com/google/domain/registry/ui/js",
"//java/com/google/domain/registry/ui/js/registrar",
"//javascript/closure",
],
)
closure_js_test(
name = "test",
size = "medium",
timeout = "short",
srcs = glob(["*_test.js"]),
deps = [
":console_test_util",
"//java/com/google/domain/registry/ui/js",
"//java/com/google/domain/registry/ui/js/registrar",
"//java/com/google/domain/registry/ui/soy/registrar:Console",
"//javascript/closure",
"//javatests/com/google/domain/registry/ui/js:testing",
],
)

View file

@ -0,0 +1,97 @@
// 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.
goog.setTestOnly();
goog.require('goog.dispose');
goog.require('goog.dom');
goog.require('goog.style');
goog.require('goog.testing.MockControl');
goog.require('goog.testing.asserts');
goog.require('goog.testing.jsunit');
goog.require('registry.registrar.BrainFrame');
goog.require('registry.testing');
var mocks = new goog.testing.MockControl();
var brainframe;
var mockPostMessage;
function setUp() {
registry.testing.addToDocument('<form><div id="bf"></div></form>');
brainframe = new registry.registrar.BrainFrame('omg', 'bf');
mockPostMessage =
mocks.createMethodMock(registry.registrar.BrainFrame, 'postMessage_');
}
function tearDown() {
goog.dispose(brainframe);
mocks.$tearDown();
}
function testRun_sendsTokenRequestToParent() {
mockPostMessage('{"type":"token_request"}', 'omg');
mocks.$replayAll();
brainframe.run();
mocks.$verifyAll();
}
function testTokenResponseMessage_callsSetup() {
var called = false;
goog.global.braintree = {};
goog.global.braintree.setup = function(token, mode, args) {
called = true;
assertEquals('imatoken', token);
assertEquals('dropin', mode);
assertEquals('bf', args.container.id);
};
brainframe.onMessage_({
getBrowserEvent: function() {
return {
source: window.parent,
origin: 'omg',
data: '{"type": "token_response", "token": "imatoken"}'
};
}
});
assertTrue(called);
}
function testPaymentMethodMessage_sendsInfo() {
mockPostMessage('{"type":"payment_method","submit":false,"method":"hi"}',
'omg');
mocks.$replayAll();
brainframe.onPaymentMethod_('hi');
mocks.$verifyAll();
}
function testOnResizeTimer_sendsHeight() {
mockPostMessage('{"type":"resize_request","height":123}', 'omg');
mocks.$replayAll();
goog.style.setHeight(goog.dom.getElement('bf'), 123);
brainframe.onResizeTimer_();
mocks.$verifyAll();
// But does not send height if size hasn't changed.
mocks.$replayAll();
brainframe.onResizeTimer_();
mocks.$verifyAll();
}

View file

@ -0,0 +1,156 @@
// 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.
goog.setTestOnly();
goog.require('goog.dom');
goog.require('goog.dom.classlist');
goog.require('goog.json');
goog.require('goog.soy');
goog.require('goog.testing.MockControl');
goog.require('goog.testing.PropertyReplacer');
goog.require('goog.testing.asserts');
goog.require('goog.testing.jsunit');
goog.require('goog.testing.mockmatchers');
goog.require('goog.testing.net.XhrIo');
goog.require('registry.registrar.ConsoleTestUtil');
goog.require('registry.soy.registrar.console');
goog.require('registry.testing');
goog.require('registry.util');
var $ = goog.dom.getRequiredElement;
var stubs = new goog.testing.PropertyReplacer();
var test = {
testXsrfToken: 'testToken',
testClientId: 'daddy',
mockControl: new goog.testing.MockControl()
};
function setUp() {
registry.testing.addToDocument('<div id="test"/>');
registry.testing.addToDocument('<div class="kd-butterbar"/>');
stubs.setPath('goog.net.XhrIo', goog.testing.net.XhrIo);
var testElt = goog.dom.getElement('test');
goog.soy.renderElement(testElt, registry.soy.registrar.console.main, {
xsrfToken: test.testXsrfToken,
username: 'blah',
logoutUrl: 'omg',
isAdmin: true,
clientId: test.testClientId,
showPaymentLink: false
});
registry.registrar.ConsoleTestUtil.setup(test);
var regNavlist = $('reg-navlist');
var active = regNavlist.querySelector('a[href="/registrar#contact-us"]');
assertTrue(active != null);
}
function tearDown() {
goog.testing.net.XhrIo.cleanup();
stubs.reset();
test.mockControl.$tearDown();
}
function testButter() {
registry.registrar.ConsoleTestUtil.visit(test);
registry.util.butter('butter msg');
var butter = goog.dom.getElementByClass(goog.getCssName('kd-butterbar'));
assertNotNull(butter.innerHTML.match(/.*butter msg.*/));
assertTrue(goog.dom.classlist.contains(butter, goog.getCssName('shown')));
}
/**
* The EPP login should be triggered if the user {@code isGaeLoggedIn}
* but not yet {@code isEppLoggedIn}.
*/
function testEppLogin() {
// This is a little complex, as handleHashChange triggers an async
// event to do the EPP login with a callback to come back to
// handleHashChange after completion.
registry.registrar.ConsoleTestUtil.visit(
test, {
isEppLoggedIn: true,
testClientId: test.testClientId,
testXsrfToken: test.testXsrfToken
}, function() {
test.sessionMock.login(
goog.testing.mockmatchers.isFunction).$does(function() {
test.sessionMock.$reset();
test.sessionMock.isEppLoggedIn().$returns(true).$anyTimes();
test.sessionMock.getClientId().$returns(
test.testClientId).$anyTimes();
test.sessionMock.$replay();
test.console.handleHashChange(test.testClientId);
}).$anyTimes();
});
assertTrue(test.console.session.isEppLoggedIn());
assertNotNull(goog.dom.getElement('domain-registrar-dashboard'));
}
/** Authed user with no path op specified should nav to welcome page. */
function testShowLoginOrDash() {
registry.registrar.ConsoleTestUtil.visit(test);
assertNotNull(goog.dom.getElement('domain-registrar-dashboard'));
}
function testNavToResources() {
registry.registrar.ConsoleTestUtil.visit(test, {
path: 'resources',
testXsrfToken: test.testXsrfToken
});
var xhr = goog.testing.net.XhrIo.getSendInstances().pop();
assertTrue(xhr.isActive());
assertEquals('/registrar-settings', xhr.getLastUri());
assertEquals(test.testXsrfToken,
xhr.getLastRequestHeaders().get('X-CSRF-Token'));
xhr.simulateResponse(200, goog.json.serialize({
status: 'SUCCESS',
message: 'OK',
results: [{
driveFolderId: 'blahblah'
}]
}));
assertContains('blahblah', $('reg-resources-driveLink').getAttribute('href'));
}
function testNavToContactUs() {
registry.registrar.ConsoleTestUtil.visit(test, {
path: 'contact-us',
testXsrfToken: test.testXsrfToken
});
var xhr = goog.testing.net.XhrIo.getSendInstances().pop();
assertTrue(xhr.isActive());
assertEquals('/registrar-settings', xhr.getLastUri());
assertEquals(test.testXsrfToken,
xhr.getLastRequestHeaders().get('X-CSRF-Token'));
var passcode = '5-5-5-5-5';
xhr.simulateResponse(200, goog.json.serialize({
status: 'SUCCESS',
message: 'OK',
results: [{
phonePasscode: passcode
}]
}));
assertEquals(passcode,
goog.dom.getTextContent($('domain-registrar-phone-passcode')));
}

View file

@ -0,0 +1,95 @@
// 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.
goog.provide('registry.registrar.ConsoleTestUtil');
goog.setTestOnly('registry.registrar.ConsoleTestUtil');
goog.require('goog.History');
goog.require('goog.asserts');
goog.require('goog.dom.xml');
goog.require('goog.testing.mockmatchers');
goog.require('registry.registrar.Console');
goog.require('registry.registrar.EppSession');
goog.require('registry.xml');
/**
* Utility method that attaches mocks to a {@code TestCase}. This was
* originally in the ctor for ConsoleTest and should simply be
* inherited but jstd_test breaks inheritance in test cases.
* @param {Object} test the test case to configure.
*/
registry.registrar.ConsoleTestUtil.setup = function(test) {
test.historyMock = test.mockControl.createLooseMock(goog.History, true);
test.sessionMock = test.mockControl.createLooseMock(
registry.registrar.EppSession, true);
/** @suppress {missingRequire} */
test.mockControl.createConstructorMock(goog, 'History')()
.$returns(test.historyMock);
/** @suppress {missingRequire} */
test.mockControl
.createConstructorMock(registry.registrar, 'EppSession')(
goog.testing.mockmatchers.isObject,
goog.testing.mockmatchers.isString,
goog.testing.mockmatchers.isString)
.$returns(test.sessionMock);
};
/**
* Simulates visiting a page on the console. Sets path, then mocks
* session and calls {@code handleHashChange_}.
* @param {Object} test the test case to configure.
* @param {Object=} opt_args may include path, isEppLoggedIn.
* @param {Function=} opt_moar extra setup after called just before
* {@code $replayAll}. See memegen/3437690.
*/
registry.registrar.ConsoleTestUtil.visit = function(
test, opt_args, opt_moar) {
opt_args = opt_args || {};
opt_args.path = opt_args.path || '';
opt_args.testClientId = opt_args.testClientId || 'dummyRegistrarId';
opt_args.testXsrfToken = opt_args.testXsrfToken || 'dummyXsrfToken';
if (opt_args.isEppLoggedIn === undefined) {
opt_args.isEppLoggedIn = true;
}
test.historyMock.$reset();
test.sessionMock.$reset();
test.historyMock.getToken().$returns(opt_args.path).$anyTimes();
test.sessionMock.isEppLoggedIn().$returns(opt_args.isEppLoggedIn).$anyTimes();
test.sessionMock.getClientId().$returns(opt_args.isEppLoggedIn ?
opt_args.testClientId : null).$anyTimes();
if (opt_args.rspXml) {
test.sessionMock
.send(goog.testing.mockmatchers.isString,
goog.testing.mockmatchers.isFunction)
.$does(function(args, cb) {
// XXX: Args should be checked.
var xml = goog.dom.xml.loadXml(opt_args.rspXml);
goog.asserts.assert(xml != null);
cb(registry.xml.convertToJson(xml));
}).$anyTimes();
}
if (opt_moar) {
opt_moar();
}
test.mockControl.$replayAll();
/** @type {!registry.registrar.Console} */
test.console = new registry.registrar.Console(
opt_args.testXsrfToken,
opt_args.testClientId);
// XXX: Should be triggered via event passing.
test.console.handleHashChange();
test.mockControl.$verifyAll();
};

View file

@ -0,0 +1,320 @@
// 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.
goog.setTestOnly();
goog.require('goog.array');
goog.require('goog.dispose');
goog.require('goog.dom');
goog.require('goog.soy');
goog.require('goog.testing.MockControl');
goog.require('goog.testing.PropertyReplacer');
goog.require('goog.testing.asserts');
goog.require('goog.testing.jsunit');
goog.require('goog.testing.net.XhrIo');
goog.require('registry.registrar.ConsoleTestUtil');
goog.require('registry.soy.registrar.console');
goog.require('registry.testing');
goog.require('registry.util');
var $ = goog.dom.getRequiredElement;
var stubs = new goog.testing.PropertyReplacer();
var testContact = null;
var test = {
testXsrfToken: '༼༎෴ ༎༽',
testClientId: 'testClientId',
mockControl: new goog.testing.MockControl()
};
function setUp() {
registry.testing.addToDocument('<div id="test"/>');
registry.testing.addToDocument('<div class="kd-butterbar"/>');
testContact = createTestContact();
goog.soy.renderElement($('test'), registry.soy.registrar.console.main, {
xsrfToken: test.testXsrfToken,
username: 'blah',
logoutUrl: 'omg',
isAdmin: true,
clientId: test.testClientId,
showPaymentLink: false
});
stubs.setPath('goog.net.XhrIo', goog.testing.net.XhrIo);
registry.registrar.ConsoleTestUtil.setup(test);
}
function tearDown() {
goog.dispose(test.console);
goog.testing.net.XhrIo.cleanup();
stubs.reset();
test.mockControl.$tearDown();
}
function testCollectionView() {
registry.registrar.ConsoleTestUtil.visit(test, {
path: 'contact-settings',
testXsrfToken: test.testXsrfToken,
testClientId: test.testClientId
});
registry.testing.assertReqMockRsp(
test.testXsrfToken,
'/registrar-settings',
{op: 'read', args: {}},
{
status: 'SUCCESS',
message: 'OK',
results: [{
contacts: [testContact]
}]
}
);
assertEquals(1, $('admin-contacts').childNodes.length);
// XXX: Needs more field testing.
}
function testItemView() {
registry.registrar.ConsoleTestUtil.visit(test, {
path: 'contact-settings/test@example.com',
testXsrfToken: test.testXsrfToken,
testClientId: test.testClientId
});
registry.testing.assertReqMockRsp(
test.testXsrfToken,
'/registrar-settings',
{op: 'read', args: {}},
{
status: 'SUCCESS',
message: 'OK',
results: [{
contacts: [testContact]
}]
}
);
assertEquals(testContact.name, $('contacts[0].name').value);
assertEquals(testContact.emailAddress, $('contacts[0].emailAddress').value);
assertEquals(testContact.phoneNumber, $('contacts[0].phoneNumber').value);
assertEquals(testContact.faxNumber, $('contacts[0].faxNumber').value);
// XXX: Types are no longer broken out as individual settings, so relying on
// screenshot test.
}
// XXX: Should be hoisted.
function testItemEditButtons() {
testItemView();
registry.testing.assertVisible($('reg-app-btns-edit'));
registry.testing.assertHidden($('reg-app-btns-save'));
registry.testing.click($('reg-app-btn-edit'));
registry.testing.assertHidden($('reg-app-btns-edit'));
registry.testing.assertVisible($('reg-app-btns-save'));
registry.testing.click($('reg-app-btn-cancel'));
registry.testing.assertVisible($('reg-app-btns-edit'));
registry.testing.assertHidden($('reg-app-btns-save'));
}
function testItemEdit() {
testItemView();
registry.testing.click($('reg-app-btn-edit'));
document.forms.namedItem('item').elements['contacts[0].name'].value = 'bob';
registry.testing.click($('reg-app-btn-save'));
testContact.name = 'bob';
registry.testing.assertReqMockRsp(
test.testXsrfToken,
'/registrar-settings',
{
op: 'update',
args: {
contacts: [testContact],
readonly: false
}
},
{
status: 'SUCCESS',
message: 'OK',
results: [{
contacts: [testContact]
}]
}
);
registry.testing.assertObjectEqualsPretty(
testContact,
simulateJsonForContact(registry.util.parseForm('item').contacts[0]));
}
function testChangeContactTypes() {
testItemView();
registry.testing.click($('reg-app-btn-edit'));
$('contacts[0].type.admin').removeAttribute('checked');
$('contacts[0].type.legal').setAttribute('checked', 'checked');
$('contacts[0].type.marketing').setAttribute('checked', 'checked');
registry.testing.click($('reg-app-btn-save'));
testContact.types = 'LEGAL,MARKETING';
registry.testing.assertReqMockRsp(
test.testXsrfToken,
'/registrar-settings',
{
op: 'update',
args: {
contacts: [testContact],
readonly: false
}
},
{
status: 'SUCCESS',
message: 'OK',
results: [{
contacts: [testContact]
}]
}
);
registry.testing.assertObjectEqualsPretty(
testContact,
simulateJsonForContact(registry.util.parseForm('item').contacts[0]));
}
function testOneOfManyUpdate() {
registry.registrar.ConsoleTestUtil.visit(test, {
path: 'contact-settings/test@example.com',
testXsrfToken: test.testXsrfToken,
testClientId: test.testClientId
});
var testContacts = [
createTestContact('new1@asdf.com'),
testContact,
createTestContact('new2@asdf.com')
];
registry.testing.assertReqMockRsp(
test.testXsrfToken,
'/registrar-settings',
{op: 'read', args: {}},
{
status: 'SUCCESS',
message: 'OK',
results: [{
contacts: testContacts
}]
}
);
// Edit testContact.
registry.testing.click($('reg-app-btn-edit'));
$('contacts[1].type.admin').removeAttribute('checked');
$('contacts[1].type.legal').setAttribute('checked', 'checked');
$('contacts[1].type.marketing').setAttribute('checked', 'checked');
registry.testing.click($('reg-app-btn-save'));
// Should save them all back, with only testContact changed.
testContacts[1].types = 'LEGAL,MARKETING';
registry.testing.assertReqMockRsp(
test.testXsrfToken,
'/registrar-settings',
{op: 'update', args: {contacts: testContacts, readonly: false}},
{
status: 'SUCCESS',
message: 'OK',
results: [{
contacts: testContacts
}]
}
);
}
function testDelete() {
registry.registrar.ConsoleTestUtil.visit(test, {
path: 'contact-settings/test@example.com',
testXsrfToken: test.testXsrfToken,
testClientId: test.testClientId
});
var testContacts = [
createTestContact('new1@asdf.com'),
testContact,
createTestContact('new2@asdf.com')
];
registry.testing.assertReqMockRsp(
test.testXsrfToken,
'/registrar-settings',
{op: 'read', args: {}},
{
status: 'SUCCESS',
message: 'OK',
results: [{
contacts: testContacts
}]
}
);
// Delete testContact.
registry.testing.click($('reg-app-btn-edit'));
registry.testing.click($('reg-app-btn-delete'));
// Should save them all back, with testContact gone.
goog.array.removeAt(testContacts, 1);
registry.testing.assertReqMockRsp(
test.testXsrfToken,
'/registrar-settings',
{op: 'update', args: {contacts: testContacts, readonly: false}},
{
status: 'SUCCESS',
message: 'OK',
results: [{
contacts: testContacts
}]
}
);
}
/**
* @param {string=} opt_email
*/
function createTestContact(opt_email) {
var nameMail = opt_email || 'test@example.com';
return {
name: nameMail,
emailAddress: nameMail,
phoneNumber: '+1.2345551234',
faxNumber: '+1.2345551234',
visibleInWhoisAsAdmin: false,
visibleInWhoisAsTech: false,
types: 'ADMIN'
};
}
/**
* Convert parsed formContact to simulated wire form.
* @param {!Element} contact
*/
function simulateJsonForContact(contact) {
contact.visibleInWhoisAsAdmin = contact.visibleInWhoisAsAdmin == 'true';
contact.visibleInWhoisAsTech = contact.visibleInWhoisAsTech == 'true';
contact.types = '';
for (var tNdx in contact.type) {
if (contact.type[tNdx]) {
if (contact.types.length > 0) {
contact.types += ',';
}
contact.types += ('' + tNdx).toUpperCase();
}
}
delete contact['type'];
return contact;
}

View file

@ -0,0 +1,128 @@
// 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.
goog.setTestOnly();
goog.require('goog.dispose');
goog.require('goog.dom');
goog.require('goog.soy');
goog.require('goog.testing.MockControl');
goog.require('goog.testing.asserts');
goog.require('goog.testing.jsunit');
goog.require('registry.registrar.ConsoleTestUtil');
goog.require('registry.soy.registrar.console');
goog.require('registry.testing');
var $ = goog.dom.getRequiredElement;
var test = {
mockControl: new goog.testing.MockControl()
};
function setUp() {
registry.testing.addToDocument('<div id="test"/>');
registry.testing.addToDocument('<div class="kd-butterbar"/>');
goog.soy.renderElement($('test'), registry.soy.registrar.console.main, {
xsrfToken: 'test',
username: 'blah',
logoutUrl: 'omg',
isAdmin: true,
clientId: 'daddy',
showPaymentLink: false
});
registry.registrar.ConsoleTestUtil.setup(test);
}
function tearDown() {
goog.dispose(test.console);
test.mockControl.$tearDown();
}
/** Contact hash path should nav to contact page. */
function testVisitContact() {
registry.registrar.ConsoleTestUtil.visit(test, {
path: 'contact/pabloistrad',
rspXml: '<?xml version="1.0"?>' +
'<epp xmlns:domain="urn:ietf:params:xml:ns:domain-1.0"' +
' xmlns:contact="urn:ietf:params:xml:ns:contact-1.0"' +
' xmlns:host="urn:ietf:params:xml:ns:host-1.0"' +
' xmlns:launch="urn:ietf:params:xml:ns:launch-1.0"' +
' xmlns:rgp="urn:ietf:params:xml:ns:rgp-1.0"' +
' xmlns="urn:ietf:params:xml:ns:epp-1.0"' +
' xmlns:secDNS="urn:ietf:params:xml:ns:secDNS-1.1"' +
' xmlns:mark="urn:ietf:params:xml:ns:mark-1.0">' +
' <response>' +
' <result code="1000">' +
' <msg>Command completed successfully</msg>' +
' </result>' +
' <resData>' +
' <contact:infData>' +
' <contact:id>pabloistrad</contact:id>' +
' <contact:roid>1-roid</contact:roid>' +
' <contact:status s="ok"/>' +
' <contact:postalInfo type="int">' +
' <contact:name>name2</contact:name>' +
' <contact:addr>' +
' <contact:street></contact:street>' +
' <contact:city>city2</contact:city>' +
' <contact:cc>US</contact:cc>' +
' </contact:addr>' +
' </contact:postalInfo>' +
' <contact:voice/>' +
' <contact:fax/>' +
' <contact:email>test2.ui@example.com</contact:email>' +
' <contact:clID>daddy</contact:clID>' +
' <contact:crID>daddy</contact:crID>' +
' <contact:crDate>2014-05-06T22:16:36Z</contact:crDate>' +
' <contact:upID>daddy</contact:upID>' +
' <contact:upDate>2014-05-07T16:20:07Z</contact:upDate>' +
' <contact:authInfo>' +
' <contact:pw>asdfasdf</contact:pw>' +
' </contact:authInfo>' +
' </contact:infData>' +
' </resData>' +
' <trID>' +
' <clTRID>abc-1234</clTRID>' +
' <svTRID>c4O3B0pRRKKSrrXsJvxP5w==-2</svTRID>' +
' </trID>' +
' </response>' +
'</epp>'
});
assertEquals(3, $('contact-postalInfo').childNodes.length);
}
/** Contact hash path should nav to contact page. */
function testEdit() {
testVisitContact();
registry.testing.assertVisible($('reg-app-btns-edit'));
registry.testing.click($('reg-app-btn-edit'));
registry.testing.assertHidden($('reg-app-btns-edit'));
registry.testing.assertVisible($('reg-app-btns-save'));
}
/** Contact hash path should nav to contact page. */
function testAddPostalInfo() {
testEdit();
var addPiBtn = $('domain-contact-postalInfo-add-button');
assertNull(addPiBtn.getAttribute('disabled'));
registry.testing.click(addPiBtn);
assertTrue(addPiBtn.hasAttribute('disabled'));
assertEquals(4, $('contact-postalInfo').childNodes.length);
}

View file

@ -0,0 +1,480 @@
// 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.
goog.setTestOnly();
goog.require('goog.History');
goog.require('goog.dispose');
goog.require('goog.dom');
goog.require('goog.soy');
goog.require('goog.testing.MockControl');
goog.require('goog.testing.PropertyReplacer');
goog.require('goog.testing.asserts');
goog.require('goog.testing.jsunit');
goog.require('goog.testing.mockmatchers');
goog.require('goog.testing.net.XhrIo');
goog.require('registry.registrar.Console');
goog.require('registry.soy.registrar.console');
goog.require('registry.testing');
var $ = goog.dom.getRequiredElement;
var _ = goog.testing.mockmatchers.ignoreArgument;
var stubs = new goog.testing.PropertyReplacer();
var mocks = new goog.testing.MockControl();
var historyMock;
var registrarConsole;
function setUp() {
registry.testing.addToDocument('<div id="test"/>');
registry.testing.addToDocument('<div class="kd-butterbar"/>');
goog.soy.renderElement($('test'), registry.soy.registrar.console.main, {
xsrfToken: 'ignore',
username: 'jart',
logoutUrl: 'https://justinetunney.com',
isAdmin: true,
clientId: 'ignore',
showPaymentLink: false
});
stubs.setPath('goog.net.XhrIo', goog.testing.net.XhrIo);
historyMock = mocks.createStrictMock(goog.History);
mocks.createConstructorMock(goog, 'History')().$returns(historyMock);
historyMock.addEventListener(_, _, _);
historyMock.setEnabled(true);
mocks.$replayAll();
registrarConsole = new registry.registrar.Console('☢', 'jartine');
mocks.$verifyAll();
}
function tearDown() {
goog.dispose(registrarConsole);
stubs.reset();
mocks.$tearDown();
goog.testing.net.XhrIo.cleanup();
}
/** Handles EPP login. */
function handleLogin() {
var request = registry.testing.loadXml(
'<?xml version="1.0"?>' +
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">' +
' <command>' +
' <login>' +
' <clID>jartine</clID>' +
' <pw>undefined</pw>' +
' <options>' +
' <version>1.0</version>' +
' <lang>en</lang>' +
' </options>' +
' <svcs>' +
' <objURI>urn:ietf:params:xml:ns:host-1.0</objURI>' +
' <objURI>urn:ietf:params:xml:ns:domain-1.0</objURI>' +
' <objURI>urn:ietf:params:xml:ns:contact-1.0</objURI>' +
' </svcs>' +
' </login>' +
' <clTRID>asdf-1235</clTRID>' +
' </command>' +
'</epp>');
var response = registry.testing.loadXml(
'<?xml version="1.0"?>' +
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">' +
' <response>' +
' <result code="2002">' +
' <msg>Registrar is already logged in</msg>' +
' </result>' +
' <trID>' +
' <clTRID>asdf-1235</clTRID>' +
' <svTRID>ytk1RO+8SmaDQxrTIdulnw==-3</svTRID>' +
' </trID>' +
' </response>' +
'</epp>');
var xhr = goog.testing.net.XhrIo.getSendInstances().pop();
assertTrue(xhr.isActive());
assertEquals('/registrar-xhr', xhr.getLastUri());
assertEquals('☢', xhr.getLastRequestHeaders().get('X-CSRF-Token'));
registry.testing.assertXmlEquals(request, xhr.getLastContent());
xhr.simulateResponse(200, response);
}
function testView() {
historyMock.$reset();
historyMock.getToken().$returns('domain/justine.lol').$anyTimes();
mocks.$replayAll();
registrarConsole.handleHashChange();
handleLogin();
var request = registry.testing.loadXml(
'<?xml version="1.0"?>' +
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">' +
' <command>' +
' <info>' +
' <domain:info xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">' +
' <domain:name hosts="all">justine.lol</domain:name>' +
' </domain:info>' +
' </info>' +
' <clTRID>abc-1234</clTRID>' +
' </command>' +
'</epp>');
var response = registry.testing.loadXml(
'<?xml version="1.0"?>' +
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">' +
' <response>' +
' <result code="1000">' +
' <msg>Command completed successfully</msg>' +
' </result>' +
' <resData>' +
' <domain:infData xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">' +
' <domain:name>justine.lol</domain:name>' +
' <domain:roid>6-roid</domain:roid>' +
' <domain:status s="inactive"/>' +
' <domain:registrant>GK Chesterton</domain:registrant>' +
' <domain:contact type="admin">&lt;justine&gt;</domain:contact>' +
' <domain:contact type="billing">candycrush</domain:contact>' +
' <domain:contact type="tech">krieger</domain:contact>' +
' <domain:ns>' +
' <domain:hostObj>ns1.justine.lol</domain:hostObj>' +
' <domain:hostObj>ns2.justine.lol</domain:hostObj>' +
' </domain:ns>' +
' <domain:host>ns1.justine.lol</domain:host>' +
' <domain:clID>justine</domain:clID>' +
' <domain:crID>justine</domain:crID>' +
' <domain:crDate>2014-07-10T02:17:02Z</domain:crDate>' +
' <domain:exDate>2015-07-10T02:17:02Z</domain:exDate>' +
' <domain:authInfo>' +
' <domain:pw>lolcat</domain:pw>' +
' </domain:authInfo>' +
' </domain:infData>' +
' </resData>' +
' <trID>' +
' <clTRID>abc-1234</clTRID>' +
' <svTRID>ytk1RO+8SmaDQxrTIdulnw==-4</svTRID>' +
' </trID>' +
' </response>' +
'</epp>');
var xhr = goog.testing.net.XhrIo.getSendInstances().pop();
assertTrue('XHR is inactive.', xhr.isActive());
assertEquals('/registrar-xhr', xhr.getLastUri());
assertEquals('☢', xhr.getLastRequestHeaders().get('X-CSRF-Token'));
registry.testing.assertXmlEquals(request, xhr.getLastContent());
xhr.simulateResponse(200, response);
assertEquals('We require more vespene gas.',
0, goog.testing.net.XhrIo.getSendInstances().length);
mocks.$verifyAll();
assertTrue('Form should be read-only.', $('domain:exDate').readOnly);
assertContains('justine.lol', $('reg-content').innerHTML);
assertEquals('2015-07-10T02:17:02Z', $('domain:exDate').value);
assertEquals('GK Chesterton', $('domain:registrant').value);
assertEquals('<justine>', $('domain:contact[0].value').value);
assertEquals('candycrush', $('domain:contact[1].value').value);
assertEquals('krieger', $('domain:contact[2].value').value);
assertEquals('lolcat', $('domain:authInfo.domain:pw').value);
assertEquals('ns1.justine.lol', $('domain:ns.domain:hostObj[0].value').value);
assertEquals('ns2.justine.lol', $('domain:ns.domain:hostObj[1].value').value);
}
function testEdit() {
testView();
historyMock.$reset();
mocks.$replayAll();
registry.testing.click($('reg-app-btn-edit'));
assertFalse('Form should be edible.', $('domain:exDate').readOnly);
$('domain:registrant').value = 'Jonathan Swift';
$('domain:authInfo.domain:pw').value = '(✿◕‿◕)';
registry.testing.click($('reg-app-btn-save'));
var request = registry.testing.loadXml(
'<?xml version="1.0"?>' +
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">' +
' <command>' +
' <update>' +
' <domain:update xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">' +
' <domain:name>justine.lol</domain:name>' +
' <domain:chg>' +
' <domain:registrant>Jonathan Swift</domain:registrant>' +
' <domain:authInfo>' +
' <domain:pw>(✿◕‿◕)</domain:pw>' +
' </domain:authInfo>' +
' </domain:chg>' +
' </domain:update>' +
' </update>' +
' <clTRID>abc-1234</clTRID>' +
' </command>' +
'</epp>');
var response = registry.testing.loadXml(
'<?xml version="1.0"?>' +
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">' +
' <response>' +
' <result code="1000">' +
' <msg>This world is built from a million lies.</msg>' +
' </result>' +
' <trID>' +
' <clTRID>abc-1234</clTRID>' +
' <svTRID>214CjbYuTsijoP8sgyFUNg==-e</svTRID>' +
' </trID>' +
' </response>' +
'</epp>');
var xhr = goog.testing.net.XhrIo.getSendInstances().pop();
assertTrue('XHR is inactive.', xhr.isActive());
assertEquals('/registrar-xhr', xhr.getLastUri());
assertEquals('☢', xhr.getLastRequestHeaders().get('X-CSRF-Token'));
registry.testing.assertXmlEquals(request, xhr.getLastContent());
xhr.simulateResponse(200, response);
request = registry.testing.loadXml(
'<?xml version="1.0"?>' +
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">' +
' <command>' +
' <info>' +
' <domain:info xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">' +
' <domain:name hosts="all">justine.lol</domain:name>' +
' </domain:info>' +
' </info>' +
' <clTRID>abc-1234</clTRID>' +
' </command>' +
'</epp>');
response = registry.testing.loadXml(
'<?xml version="1.0"?>' +
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">' +
' <response>' +
' <result code="1000">' +
' <msg>How can we live in the land of the dead?</msg>' +
' </result>' +
' <resData>' +
' <domain:infData xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">' +
' <domain:name>justine.lol</domain:name>' +
' <domain:roid>6-roid</domain:roid>' +
' <domain:status s="inactive"/>' +
' <domain:registrant>Jonathan Swift</domain:registrant>' +
' <domain:contact type="admin">&lt;justine&gt;</domain:contact>' +
' <domain:contact type="billing">candycrush</domain:contact>' +
' <domain:contact type="tech">krieger</domain:contact>' +
' <domain:ns>' +
' <domain:hostObj>ns1.justine.lol</domain:hostObj>' +
' <domain:hostObj>ns2.justine.lol</domain:hostObj>' +
' </domain:ns>' +
' <domain:host>ns1.justine.lol</domain:host>' +
' <domain:clID>justine</domain:clID>' +
' <domain:crID>justine</domain:crID>' +
' <domain:crDate>2014-07-10T02:17:02Z</domain:crDate>' +
' <domain:exDate>2015-07-10T02:17:02Z</domain:exDate>' +
' <domain:authInfo>' +
' <domain:pw>(✿◕‿◕)</domain:pw>' +
' </domain:authInfo>' +
' </domain:infData>' +
' </resData>' +
' <trID>' +
' <clTRID>abc-1234</clTRID>' +
' <svTRID>ytk1RO+8SmaDQxrTIdulnw==-4</svTRID>' +
' </trID>' +
' </response>' +
'</epp>');
xhr = goog.testing.net.XhrIo.getSendInstances().pop();
assertTrue('XHR is inactive.', xhr.isActive());
assertEquals('/registrar-xhr', xhr.getLastUri());
assertEquals('☢', xhr.getLastRequestHeaders().get('X-CSRF-Token'));
registry.testing.assertXmlEquals(request, xhr.getLastContent());
xhr.simulateResponse(200, response);
assertEquals('We require more vespene gas.',
0, goog.testing.net.XhrIo.getSendInstances().length);
mocks.$verifyAll();
assertTrue($('domain:exDate').readOnly);
assertContains('justine.lol', $('reg-content').innerHTML);
assertEquals('2015-07-10T02:17:02Z', $('domain:exDate').value);
assertEquals('Jonathan Swift', $('domain:registrant').value);
assertEquals('<justine>', $('domain:contact[0].value').value);
assertEquals('candycrush', $('domain:contact[1].value').value);
assertEquals('krieger', $('domain:contact[2].value').value);
assertEquals('(✿◕‿◕)', $('domain:authInfo.domain:pw').value);
assertEquals('ns1.justine.lol', $('domain:ns.domain:hostObj[0].value').value);
assertEquals('ns2.justine.lol', $('domain:ns.domain:hostObj[1].value').value);
}
function testEdit_cancel_restoresOriginalValues() {
testView();
registry.testing.click($('reg-app-btn-edit'));
assertFalse('Form should be edible.', $('domain:exDate').readOnly);
$('domain:registrant').value = 'Jonathan Swift';
$('domain:authInfo.domain:pw').value = '(✿◕‿◕)';
registry.testing.click($('reg-app-btn-cancel'));
assertTrue('Form should be read-only.', $('domain:exDate').readOnly);
assertEquals('GK Chesterton', $('domain:registrant').value);
assertEquals('lolcat', $('domain:authInfo.domain:pw').value);
}
function testCreate() {
historyMock.$reset();
historyMock.getToken().$returns('domain').$anyTimes();
mocks.$replayAll();
registrarConsole.handleHashChange();
handleLogin();
mocks.$verifyAll();
assertFalse('Form should be edible.', $('domain:name').readOnly);
$('domain:name').value = 'bog.lol';
$('domain:period').value = '1';
$('domain:authInfo.domain:pw').value = 'attorney at lawl';
$('domain:registrant').value = 'Chris Pohl';
registry.testing.click($('domain-contact-add-button'));
$('domain:contact[0].value').value = 'BlutEngel';
$('domain:contact[0].@type').value = 'admin';
registry.testing.click($('domain-contact-add-button'));
$('domain:contact[1].value').value = 'Ravenous';
$('domain:contact[1].@type').value = 'tech';
registry.testing.click($('domain-contact-add-button'));
$('domain:contact[2].value').value = 'Dark Angels';
$('domain:contact[2].@type').value = 'billing';
historyMock.$reset();
mocks.$replayAll();
registry.testing.click($('reg-app-btn-save'));
var request = registry.testing.loadXml(
'<?xml version="1.0"?>' +
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">' +
' <command>' +
' <create>' +
' <domain:create xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">' +
' <domain:name>bog.lol</domain:name>' +
' <domain:period unit="y">1</domain:period>' +
' <domain:registrant>Chris Pohl</domain:registrant>' +
' <domain:contact type="admin">BlutEngel</domain:contact>' +
' <domain:contact type="tech">Ravenous</domain:contact>' +
' <domain:contact type="billing">Dark Angels</domain:contact>' +
' <domain:authInfo>' +
' <domain:pw>attorney at lawl</domain:pw>' +
' </domain:authInfo>' +
' </domain:create>' +
' </create>' +
' <clTRID>abc-1234</clTRID>' +
' </command>' +
'</epp>');
var response = registry.testing.loadXml(
'<?xml version="1.0"?>' +
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">' +
' <response>' +
' <result code="1000">' +
' <msg>Command completed successfully</msg>' +
' </result>' +
' <resData>' +
' <domain:creData xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">' +
' <domain:name>bog.lol</domain:name>' +
' <domain:crDate>2014-07-17T08:19:24Z</domain:crDate>' +
' <domain:exDate>2015-07-17T08:19:24Z</domain:exDate>' +
' </domain:creData>' +
' </resData>' +
' <trID>' +
' <clTRID>abc-1234</clTRID>' +
' <svTRID>OBPI6JvEQfOUaO8qGf+IKA==-7</svTRID>' +
' </trID>' +
' </response>' +
'</epp>');
var xhr = goog.testing.net.XhrIo.getSendInstances().pop();
assertTrue('XHR is inactive.', xhr.isActive());
assertEquals('/registrar-xhr', xhr.getLastUri());
assertEquals('☢', xhr.getLastRequestHeaders().get('X-CSRF-Token'));
registry.testing.assertXmlEquals(request, xhr.getLastContent());
xhr.simulateResponse(200, response);
request = registry.testing.loadXml(
'<?xml version="1.0"?>' +
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">' +
' <command>' +
' <info>' +
' <domain:info xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">' +
' <domain:name hosts="all">bog.lol</domain:name>' +
' </domain:info>' +
' </info>' +
' <clTRID>abc-1234</clTRID>' +
' </command>' +
'</epp>');
response = registry.testing.loadXml(
'<?xml version="1.0"?>' +
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">' +
' <response>' +
' <result code="1000">' +
' <msg>Command completed successfully</msg>' +
' </result>' +
' <resData>' +
' <domain:infData xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">' +
' <domain:name>bog.lol</domain:name>' +
' <domain:roid>1f-roid</domain:roid>' +
' <domain:status s="inactive"/>' +
' <domain:registrant>Chris Pohl</domain:registrant>' +
' <domain:contact type="admin">BlutEngel</domain:contact>' +
' <domain:contact type="tech">Ravenous</domain:contact>' +
' <domain:contact type="billing">Dark Angels</domain:contact>' +
' <domain:clID>justine</domain:clID>' +
' <domain:crID>justine</domain:crID>' +
' <domain:crDate>2014-07-17T08:19:24Z</domain:crDate>' +
' <domain:exDate>2015-07-17T08:19:24Z</domain:exDate>' +
' <domain:authInfo>' +
' <domain:pw>attorney at lawl</domain:pw>' +
' </domain:authInfo>' +
' </domain:infData>' +
' </resData>' +
' <extension>' +
' <rgp:infData xmlns:rgp="urn:ietf:params:xml:ns:rgp-1.0">' +
' <rgp:rgpStatus s="addPeriod"/>' +
' </rgp:infData>' +
' </extension>' +
' <trID>' +
' <clTRID>abc-1234</clTRID>' +
' <svTRID>OBPI6JvEQfOUaO8qGf+IKA==-8</svTRID>' +
' </trID>' +
' </response>' +
'</epp>');
xhr = goog.testing.net.XhrIo.getSendInstances().pop();
assertTrue('XHR is inactive.', xhr.isActive());
assertEquals('/registrar-xhr', xhr.getLastUri());
assertEquals('☢', xhr.getLastRequestHeaders().get('X-CSRF-Token'));
registry.testing.assertXmlEquals(request, xhr.getLastContent());
xhr.simulateResponse(200, response);
assertEquals('We require more vespene gas.',
0, goog.testing.net.XhrIo.getSendInstances().length);
mocks.$verifyAll();
assertTrue('Form should be read-only.', $('domain:exDate').readOnly);
assertContains('bog.lol', $('reg-content').innerHTML);
assertEquals('2015-07-17T08:19:24Z', $('domain:exDate').value);
assertEquals('Chris Pohl', $('domain:registrant').value);
assertEquals('BlutEngel', $('domain:contact[0].value').value);
assertEquals('Ravenous', $('domain:contact[1].value').value);
assertEquals('Dark Angels', $('domain:contact[2].value').value);
assertEquals('attorney at lawl', $('domain:authInfo.domain:pw').value);
assertNull(goog.dom.getElement('domain:ns.domain:hostObj[0].value'));
}

View file

@ -0,0 +1,420 @@
// 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.
goog.setTestOnly();
goog.require('goog.History');
goog.require('goog.dispose');
goog.require('goog.dom');
goog.require('goog.soy');
goog.require('goog.testing.MockControl');
goog.require('goog.testing.PropertyReplacer');
goog.require('goog.testing.asserts');
goog.require('goog.testing.jsunit');
goog.require('goog.testing.mockmatchers');
goog.require('goog.testing.net.XhrIo');
goog.require('registry.registrar.Console');
goog.require('registry.soy.registrar.console');
goog.require('registry.testing');
var $ = goog.dom.getRequiredElement;
var _ = goog.testing.mockmatchers.ignoreArgument;
var stubs = new goog.testing.PropertyReplacer();
var mocks = new goog.testing.MockControl();
var historyMock;
var registrarConsole;
function setUp() {
registry.testing.addToDocument('<div id="test"/>');
registry.testing.addToDocument('<div class="kd-butterbar"/>');
goog.soy.renderElement($('test'), registry.soy.registrar.console.main, {
xsrfToken: 'ignore',
username: 'jart',
logoutUrl: 'https://example.com',
isAdmin: true,
clientId: 'ignore',
showPaymentLink: false
});
stubs.setPath('goog.net.XhrIo', goog.testing.net.XhrIo);
historyMock = mocks.createStrictMock(goog.History);
mocks.createConstructorMock(goog, 'History')().$returns(historyMock);
historyMock.addEventListener(_, _, _);
historyMock.setEnabled(true);
mocks.$replayAll();
registrarConsole = new registry.registrar.Console('☢', 'jartine');
mocks.$verifyAll();
}
function tearDown() {
goog.dispose(registrarConsole);
stubs.reset();
mocks.$tearDown();
goog.testing.net.XhrIo.cleanup();
}
/** Handles EPP login. */
function handleLogin() {
var request = registry.testing.loadXml(
'<?xml version="1.0"?>' +
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">' +
' <command>' +
' <login>' +
' <clID>jartine</clID>' +
' <pw>undefined</pw>' +
' <options>' +
' <version>1.0</version>' +
' <lang>en</lang>' +
' </options>' +
' <svcs>' +
' <objURI>urn:ietf:params:xml:ns:host-1.0</objURI>' +
' <objURI>urn:ietf:params:xml:ns:domain-1.0</objURI>' +
' <objURI>urn:ietf:params:xml:ns:contact-1.0</objURI>' +
' </svcs>' +
' </login>' +
' <clTRID>asdf-1235</clTRID>' +
' </command>' +
'</epp>');
var response = registry.testing.loadXml(
'<?xml version="1.0"?>' +
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">' +
' <response>' +
' <result code="2002">' +
' <msg>Registrar is already logged in</msg>' +
' </result>' +
' <trID>' +
' <clTRID>asdf-1235</clTRID>' +
' <svTRID>ytk1RO+8SmaDQxrTIdulnw==-3</svTRID>' +
' </trID>' +
' </response>' +
'</epp>');
var xhr = goog.testing.net.XhrIo.getSendInstances().pop();
assertTrue(xhr.isActive());
assertEquals('/registrar-xhr', xhr.getLastUri());
assertEquals('☢', xhr.getLastRequestHeaders().get('X-CSRF-Token'));
registry.testing.assertXmlEquals(request, xhr.getLastContent());
xhr.simulateResponse(200, response);
}
function testView() {
historyMock.$reset();
historyMock.getToken().$returns('host/ns1.justine.lol').$anyTimes();
mocks.$replayAll();
registrarConsole.handleHashChange();
handleLogin();
var request = registry.testing.loadXml(
'<?xml version="1.0"?>' +
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">' +
' <command>' +
' <info>' +
' <host:info xmlns:host="urn:ietf:params:xml:ns:host-1.0">' +
' <host:name>ns1.justine.lol</host:name>' +
' </host:info>' +
' </info>' +
' <clTRID>abc-1234</clTRID>' +
' </command>' +
'</epp>');
var response = registry.testing.loadXml(
'<?xml version="1.0"?>' +
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0"' +
' xmlns:host="urn:ietf:params:xml:ns:host-1.0">' +
' <response>' +
' <result code="1000">' +
' <msg>Command completed successfully</msg>' +
' </result>' +
' <resData>' +
' <host:infData>' +
' <host:name>ns1.justine.lol</host:name>' +
' <host:roid>8-roid</host:roid>' +
' <host:status s="ok"/>' +
' <host:addr ip="v4">8.8.8.8</host:addr>' +
' <host:addr ip="v6">feed:a:bee::1</host:addr>' +
' <host:clID>justine</host:clID>' +
' <host:crID>justine</host:crID>' +
' <host:crDate>2014-07-10T02:18:34Z</host:crDate>' +
' </host:infData>' +
' </resData>' +
' <trID>' +
' <clTRID>abc-1234</clTRID>' +
' <svTRID>EweBEzCZTJirOqRmrtYrAA==-b</svTRID>' +
' </trID>' +
' </response>' +
'</epp>');
var xhr = goog.testing.net.XhrIo.getSendInstances().pop();
assertTrue('XHR is inactive.', xhr.isActive());
assertEquals('/registrar-xhr', xhr.getLastUri());
assertEquals('application/epp+xml',
xhr.getLastRequestHeaders().get('Content-Type'));
assertEquals('☢', xhr.getLastRequestHeaders().get('X-CSRF-Token'));
registry.testing.assertXmlEquals(request, xhr.getLastContent());
xhr.simulateResponse(200, response);
assertEquals('We require more vespene gas.',
0, goog.testing.net.XhrIo.getSendInstances().length);
mocks.$verifyAll();
assertTrue('Form should be read-only.', $('host:chgName').readOnly);
assertContains('ns1.justine.lol', $('reg-content').innerHTML);
assertEquals('ns1.justine.lol', $('host:chgName').value);
assertEquals('8.8.8.8', $('host:addr[0].value').value);
assertEquals('feed:a:bee::1', $('host:addr[1].value').value);
}
function testEditFirstAddr_ignoreSecond_addThird() {
testView();
historyMock.$reset();
mocks.$replayAll();
registry.testing.click($('reg-app-btn-edit'));
assertFalse('Form should be edible.', $('host:addr[0].value').readOnly);
$('host:addr[0].value').value = '1.2.3.4';
registry.testing.click($('domain-host-addr-add-button'));
$('host:addr[2].value').value = 'feed:a:fed::1';
registry.testing.click($('reg-app-btn-save'));
var request = registry.testing.loadXml(
'<?xml version="1.0"?>' +
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">' +
' <command>' +
' <update>' +
' <host:update xmlns:host="urn:ietf:params:xml:ns:host-1.0">' +
' <host:name>ns1.justine.lol</host:name>' +
' <host:add>' +
' <host:addr ip="v4">1.2.3.4</host:addr>' +
' <host:addr ip="v6">feed:a:fed::1</host:addr>' +
' </host:add>' +
' <host:rem>' +
' <host:addr ip="v4">8.8.8.8</host:addr>' +
' </host:rem>' +
' </host:update>' +
' </update>' +
' <clTRID>abc-1234</clTRID>' +
' </command>' +
'</epp>');
var response = registry.testing.loadXml(
'<?xml version="1.0"?>' +
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">' +
' <response>' +
' <result code="1000">' +
' <msg>This world is built from a million lies.</msg>' +
' </result>' +
' <trID>' +
' <clTRID>abc-1234</clTRID>' +
' <svTRID>214CjbYuTsijoP8sgyFUNg==-e</svTRID>' +
' </trID>' +
' </response>' +
'</epp>');
var xhr = goog.testing.net.XhrIo.getSendInstances().pop();
assertTrue('XHR is inactive.', xhr.isActive());
assertEquals('/registrar-xhr', xhr.getLastUri());
assertEquals('☢', xhr.getLastRequestHeaders().get('X-CSRF-Token'));
registry.testing.assertXmlEquals(request, xhr.getLastContent());
xhr.simulateResponse(200, response);
request = registry.testing.loadXml(
'<?xml version="1.0"?>' +
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">' +
' <command>' +
' <info>' +
' <host:info xmlns:host="urn:ietf:params:xml:ns:host-1.0">' +
' <host:name>ns1.justine.lol</host:name>' +
' </host:info>' +
' </info>' +
' <clTRID>abc-1234</clTRID>' +
' </command>' +
'</epp>');
response = registry.testing.loadXml(
'<?xml version="1.0"?>' +
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0"' +
' xmlns:host="urn:ietf:params:xml:ns:host-1.0">' +
' <response>' +
' <result code="1000">' +
' <msg>Command completed successfully</msg>' +
' </result>' +
' <resData>' +
' <host:infData>' +
' <host:name>ns1.justine.lol</host:name>' +
' <host:roid>8-roid</host:roid>' +
' <host:status s="ok"/>' +
' <host:addr ip="v6">feed:a:bee::1</host:addr>' +
' <host:addr ip="v4">1.2.3.4</host:addr>' +
' <host:addr ip="v6">feed:a:fed::1</host:addr>' +
' <host:clID>justine</host:clID>' +
' <host:crID>justine</host:crID>' +
' <host:crDate>2014-07-10T02:18:34Z</host:crDate>' +
' </host:infData>' +
' </resData>' +
' <trID>' +
' <clTRID>abc-1234</clTRID>' +
' <svTRID>EweBEzCZTJirOqRmrtYrAA==-b</svTRID>' +
' </trID>' +
' </response>' +
'</epp>');
xhr = goog.testing.net.XhrIo.getSendInstances().pop();
assertTrue('XHR is inactive.', xhr.isActive());
assertEquals('/registrar-xhr', xhr.getLastUri());
assertEquals('☢', xhr.getLastRequestHeaders().get('X-CSRF-Token'));
registry.testing.assertXmlEquals(request, xhr.getLastContent());
xhr.simulateResponse(200, response);
assertEquals('We require more vespene gas.',
0, goog.testing.net.XhrIo.getSendInstances().length);
mocks.$verifyAll();
assertTrue('Form should be read-only.', $('host:chgName').readOnly);
assertContains('ns1.justine.lol', $('reg-content').innerHTML);
assertEquals('ns1.justine.lol', $('host:chgName').value);
assertEquals('feed:a:bee::1', $('host:addr[0].value').value);
assertEquals('1.2.3.4', $('host:addr[1].value').value);
assertEquals('feed:a:fed::1', $('host:addr[2].value').value);
}
function testCreate() {
historyMock.$reset();
historyMock.getToken().$returns('host').$anyTimes();
mocks.$replayAll();
registrarConsole.handleHashChange();
handleLogin();
mocks.$verifyAll();
assertFalse('Form should be edible.', $('host:name').readOnly);
$('host:name').value = 'ns1.example.tld';
registry.testing.click($('domain-host-addr-add-button'));
$('host:addr[0].value').value = '192.0.2.2';
registry.testing.click($('domain-host-addr-add-button'));
$('host:addr[1].value').value = '192.0.2.29';
registry.testing.click($('domain-host-addr-add-button'));
$('host:addr[2].value').value = '1080:0:0:0:8:800:200C:417A';
historyMock.$reset();
mocks.$replayAll();
registry.testing.click($('reg-app-btn-save'));
var request = registry.testing.loadXml(
'<?xml version="1.0"?>' +
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">' +
' <command>' +
' <create>' +
' <host:create xmlns:host="urn:ietf:params:xml:ns:host-1.0">' +
' <host:name>ns1.example.tld</host:name>' +
' <host:addr ip="v4">192.0.2.2</host:addr>' +
' <host:addr ip="v4">192.0.2.29</host:addr>' +
' <host:addr ip="v6">1080:0:0:0:8:800:200C:417A</host:addr>' +
' </host:create>' +
' </create>' +
' <clTRID>abc-1234</clTRID>' +
' </command>' +
'</epp>');
var response = registry.testing.loadXml(
'<?xml version="1.0"?>' +
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">' +
' <response>' +
' <result code="1000">' +
' <msg>Command completed successfully</msg>' +
' </result>' +
' <resData>' +
' <host:creData xmlns:host="urn:ietf:params:xml:ns:host-1.0">' +
' <host:name>ns1.example.tld</host:name>' +
' <host:crDate>1999-04-03T22:00:00.0Z</host:crDate>' +
' </host:creData>' +
' </resData>' +
' <trID>' +
' <clTRID>abc-1234</clTRID>' +
' <svTRID>EweBEzCZTJirOqRmrtYrAA==-b</svTRID>' +
' </trID>' +
' </response>' +
'</epp>');
var xhr = goog.testing.net.XhrIo.getSendInstances().pop();
assertTrue('XHR is inactive.', xhr.isActive());
assertEquals('/registrar-xhr', xhr.getLastUri());
assertEquals('☢', xhr.getLastRequestHeaders().get('X-CSRF-Token'));
registry.testing.assertXmlEquals(request, xhr.getLastContent());
xhr.simulateResponse(200, response);
request = registry.testing.loadXml(
'<?xml version="1.0"?>' +
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">' +
' <command>' +
' <info>' +
' <host:info xmlns:host="urn:ietf:params:xml:ns:host-1.0">' +
' <host:name>ns1.example.tld</host:name>' +
' </host:info>' +
' </info>' +
' <clTRID>abc-1234</clTRID>' +
' </command>' +
'</epp>');
response = registry.testing.loadXml(
'<?xml version="1.0"?>' +
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">' +
' <response>' +
' <result code="1000">' +
' <msg>Command completed successfully</msg>' +
' </result>' +
' <resData>' +
' <host:infData xmlns:host="urn:ietf:params:xml:ns:host-1.0">' +
' <host:name>ns1.example.tld</host:name>' +
' <host:roid>NS1_EXAMPLE1-REP</host:roid>' +
' <host:status s="linked"/>' +
' <host:status s="clientUpdateProhibited"/>' +
' <host:addr ip="v4">192.0.2.2</host:addr>' +
' <host:addr ip="v4">192.0.2.29</host:addr>' +
' <host:addr ip="v6">1080:0:0:0:8:800:200C:417A</host:addr>' +
' <host:clID>TheRegistrar</host:clID>' +
' <host:crID>NewRegistrar</host:crID>' +
' <host:crDate>1999-04-03T22:00:00.0Z</host:crDate>' +
' <host:upID>NewRegistrar</host:upID>' +
' <host:upDate>1999-12-03T09:00:00.0Z</host:upDate>' +
' <host:trDate>2000-04-08T09:00:00.0Z</host:trDate>' +
' </host:infData>' +
' </resData>' +
' <trID>' +
' <clTRID>abc-1234</clTRID>' +
' <svTRID>EweBEzCZTJirOqRmrtYrAA==-b</svTRID>' +
' </trID>' +
' </response>' +
'</epp>');
xhr = goog.testing.net.XhrIo.getSendInstances().pop();
assertTrue('XHR is inactive.', xhr.isActive());
assertEquals('/registrar-xhr', xhr.getLastUri());
assertEquals('☢', xhr.getLastRequestHeaders().get('X-CSRF-Token'));
registry.testing.assertXmlEquals(request, xhr.getLastContent());
xhr.simulateResponse(200, response);
assertEquals('We require more vespene gas.',
0, goog.testing.net.XhrIo.getSendInstances().length);
mocks.$verifyAll();
assertTrue('Form should be read-only.', $('host:chgName').readOnly);
assertEquals('ns1.example.tld', $('host:chgName').value);
assertEquals('192.0.2.2', $('host:addr[0].value').value);
assertEquals('192.0.2.29', $('host:addr[1].value').value);
assertEquals('1080:0:0:0:8:800:200C:417A', $('host:addr[2].value').value);
}

View file

@ -0,0 +1,208 @@
// 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.
goog.setTestOnly();
goog.require('goog.dispose');
goog.require('goog.dom');
goog.require('goog.dom.classlist');
goog.require('goog.events.EventType');
goog.require('goog.json');
goog.require('goog.testing.PropertyReplacer');
goog.require('goog.testing.asserts');
goog.require('goog.testing.events');
goog.require('goog.testing.events.Event');
goog.require('goog.testing.jsunit');
goog.require('goog.testing.net.XhrIo');
goog.require('registry.registrar.Payment');
goog.require('registry.testing');
var $ = goog.dom.getRequiredElement;
var $$ = goog.dom.getRequiredElementByClass;
var stubs = new goog.testing.PropertyReplacer();
var page;
function setUp() {
registry.testing.addToDocument('<div id="reg-content"></div>');
registry.testing.addToDocument('<div class="kd-butterbar"></div>');
registry.testing.addToDocument('<div class="kd-butterbar-text"></div>');
stubs.setPath('goog.net.XhrIo', goog.testing.net.XhrIo);
page = new registry.registrar.Payment(null, '?');
page.bindToDom();
}
function tearDown() {
goog.dispose(page);
stubs.reset();
goog.testing.net.XhrIo.cleanup();
}
function testRenderForm() {
registry.testing.assertReqMockRsp(
'?',
'/registrar-payment-setup',
{},
{
status: 'SUCCESS',
results: [
{
token: 'omg-im-a-token',
currencies: ['LOL', 'OMG'],
brainframe: ''
}
]
});
assertEquals('', $('amount').value);
assertEquals('LOL', goog.dom.getTextContent($$('selected', $('currency'))));
assertTrue(
goog.dom.classlist.contains($$('reg-payment-form-submit'), 'disabled'));
}
function testResize() {
testRenderForm();
send({
type: 'resize_request',
height: 123
});
assertEquals('123', $$('reg-payment-form-method').height);
}
function testReady() {
testRenderForm();
send({type: 'ready'});
assertFalse(
goog.dom.classlist.contains($$('reg-payment-form-submit'), 'disabled'));
}
function testPaymentMethodCard() {
testRenderForm();
send({
type: 'payment_method',
method: {
type: 'CreditCard',
nonce: 'omg-im-a-nonce',
details: {
cardType: 'Amex',
lastTwo: '12'
}
}
});
assertEquals(
'American Express: xxxx xxxxxx xxx12',
goog.dom.getTextContent($$('reg-payment-form-method-info')));
}
function testPaymentMethodPaypal() {
testRenderForm();
send({
type: 'payment_method',
method: {
type: 'PayPalAccount',
nonce: 'omg-im-a-nonce',
details: {
email: 'sparrows@nightingales.example'
}
}
});
assertEquals(
'PayPal: sparrows@nightingales.example',
goog.dom.getTextContent($$('reg-payment-form-method-info')));
}
function testBadAmount_displaysError() {
testPaymentMethodCard();
$('amount').value = '3.14';
submit();
registry.testing.assertReqMockRsp(
'?',
'/registrar-payment',
{
amount: '3.14',
currency: 'LOL',
paymentMethodNonce: 'omg-im-a-nonce'
},
{
status: 'ERROR',
message: 'gimmeh moar money',
field: 'amount'
});
assertTrue(goog.dom.classlist.contains($('amount'), 'kd-formerror'));
assertEquals('gimmeh moar money',
goog.dom.getTextContent($$('kd-errormessage')));
}
function testGoodPayment_displaysSuccessPage() {
testPaymentMethodCard();
$('amount').value = '314';
submit();
registry.testing.assertReqMockRsp(
'?',
'/registrar-payment',
{
amount: '314',
currency: 'LOL',
paymentMethodNonce: 'omg-im-a-nonce'
},
{
status: 'SUCCESS',
results: [
{
id: 'omg-im-an-id',
formattedAmount: '$314'
}
]
});
assertContains('Payment Processed',
goog.dom.getTextContent($$('reg-payment')));
assertContains('omg-im-an-id',
goog.dom.getTextContent($$('reg-payment')));
assertContains('$314',
goog.dom.getTextContent($$('reg-payment')));
}
/**
* Sends message to page.
* @param {string} message
*/
function send(message) {
page.onMessage_({
getBrowserEvent: function() {
return {
source: goog.dom.getFrameContentWindow($$('reg-payment-form-method')),
data: goog.json.serialize(message)
};
}
});
}
/** Submits payment form. */
function submit() {
goog.testing.events.fireBrowserEvent(
new goog.testing.events.Event(
goog.events.EventType.SUBMIT,
$$('reg-payment-form')));
}

View file

@ -0,0 +1,142 @@
// 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.
goog.setTestOnly();
goog.require('goog.dispose');
goog.require('goog.dom');
goog.require('goog.soy');
goog.require('goog.testing.MockControl');
goog.require('goog.testing.PropertyReplacer');
goog.require('goog.testing.asserts');
goog.require('goog.testing.jsunit');
goog.require('goog.testing.net.XhrIo');
goog.require('registry.registrar.ConsoleTestUtil');
goog.require('registry.soy.registrar.console');
goog.require('registry.testing');
goog.require('registry.util');
var $ = goog.dom.getRequiredElement;
var stubs = new goog.testing.PropertyReplacer();
var expectedRegistrar = {
ipAddressWhitelist: [],
phonePasscode: '12345',
clientCertificate: null,
clientCertificateHash: null,
failoverClientCertificate: null
};
var test = {
testXsrfToken: '༼༎෴ ༎༽',
testClientId: 'testClientId',
mockControl: new goog.testing.MockControl()
};
function setUp() {
registry.testing.addToDocument('<div id="test"/>');
registry.testing.addToDocument('<div class="kd-butterbar"/>');
goog.soy.renderElement($('test'), registry.soy.registrar.console.main, {
username: 'jart',
logoutUrl: 'https://example.com',
isAdmin: true,
xsrfToken: test.testXsrfToken,
clientId: test.testClientId,
showPaymentLink: false
});
stubs.setPath('goog.net.XhrIo', goog.testing.net.XhrIo);
registry.registrar.ConsoleTestUtil.setup(test);
}
function tearDown() {
goog.dispose(test.console);
goog.testing.net.XhrIo.cleanup();
stubs.reset();
test.mockControl.$tearDown();
}
function testView() {
registry.registrar.ConsoleTestUtil.visit(test, {
path: 'security-settings',
testXsrfToken: test.testXsrfToken,
testClientId: test.testClientId
});
registry.testing.assertReqMockRsp(
test.testXsrfToken,
'/registrar-settings',
{op: 'read', args: {}},
{
status: 'SUCCESS',
message: 'OK',
results: [expectedRegistrar]
});
assertEquals(expectedRegistrar.phonePasscode,
registry.util.parseForm('item').phonePasscode);
}
function testEdit() {
testView();
registry.testing.click($('reg-app-btn-edit'));
var form = document.forms.namedItem('item');
form.elements['newIp'].value = '1.1.1.1';
registry.testing.click($('btn-add-ip'));
form.elements['newIp'].value = '2.2.2.2';
registry.testing.click($('btn-add-ip'));
var exampleCert = $('exampleCert').value;
var exampleCertHash = '6NKKNBnd2fKFooBINmn3V7L3JOTHh02+2lAqYHdlTgk';
form.elements['clientCertificate'].value = exampleCert;
form.elements['failoverClientCertificate'].value = 'bourgeois blues';
registry.testing.click($('reg-app-btn-save'));
registry.testing.assertReqMockRsp(
test.testXsrfToken,
'/registrar-settings',
{op: 'update', args: {
clientCertificate: exampleCert,
clientCertificateHash: null,
failoverClientCertificate: 'bourgeois blues',
ipAddressWhitelist: ['1.1.1.1', '2.2.2.2'],
phonePasscode: expectedRegistrar.phonePasscode,
readonly: false }},
{status: 'SUCCESS',
message: 'OK',
results: [{}]});
// XXX: The response above is ignored as the page re-issues a fetch. Should
// either provide the real response here and use anyTimes(), or have
// resource_component use this directly.
expectedRegistrar.clientCertificate = exampleCert;
expectedRegistrar.clientCertificateHash = exampleCertHash;
expectedRegistrar.failoverClientCertificate = 'bourgeois blues';
expectedRegistrar.ipAddressWhitelist = ['1.1.1.1/32', '2.2.2.2/32'];
registry.testing.assertReqMockRsp(
test.testXsrfToken,
'/registrar-settings',
{op: 'read', args: {}},
{status: 'SUCCESS',
message: 'OK',
results: [expectedRegistrar]});
delete expectedRegistrar['clientCertificateHash'];
registry.testing.assertObjectEqualsPretty(
expectedRegistrar, registry.util.parseForm('item'));
}

View file

@ -0,0 +1,173 @@
// 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.
goog.setTestOnly();
goog.require('goog.dispose');
goog.require('goog.dom');
goog.require('goog.dom.classlist');
goog.require('goog.soy');
goog.require('goog.testing.MockControl');
goog.require('goog.testing.PropertyReplacer');
goog.require('goog.testing.asserts');
goog.require('goog.testing.jsunit');
goog.require('goog.testing.net.XhrIo');
goog.require('registry.registrar.ConsoleTestUtil');
goog.require('registry.soy.registrar.console');
goog.require('registry.testing');
goog.require('registry.util');
var $ = goog.dom.getRequiredElement;
var $$ = goog.dom.getRequiredElementByClass;
var stubs = new goog.testing.PropertyReplacer();
var test = {
testXsrfToken: '༼༎෴ ༎༽',
testClientId: 'testClientId',
mockControl: new goog.testing.MockControl()
};
function setUp() {
registry.testing.addToDocument('<div id="test"/>');
registry.testing.addToDocument('<div class="kd-butterbar"/>');
goog.soy.renderElement($('test'), registry.soy.registrar.console.main, {
xsrfToken: test.testXsrfToken,
username: 'blah',
logoutUrl: 'omg',
isAdmin: true,
clientId: test.testClientId,
showPaymentLink: false
});
stubs.setPath('goog.net.XhrIo', goog.testing.net.XhrIo);
registry.registrar.ConsoleTestUtil.setup(test);
}
function tearDown() {
goog.dispose(test.console);
stubs.reset();
goog.testing.net.XhrIo.cleanup();
test.mockControl.$tearDown();
}
/** Creates a test registrar. */
function createTestRegistrar() {
return {
emailAddress: 'test2.ui@example.com',
clientIdentifier: 'theRegistrar',
ianaIdentifier: 1,
icannReferralEmail: 'lol@sloth.test',
whoisServer: 'foo.bar.baz',
referralUrl: 'blah.blar',
phoneNumber: '+1.2125650000',
faxNumber: '+1.2125650001',
localizedAddress: {
street: ['111 Eighth Avenue', 'Eleventh Floor', 'lol'],
city: 'New York',
state: 'NY',
zip: '10011',
countryCode: 'US'
}};
}
function testView() {
registry.registrar.ConsoleTestUtil.visit(test, {
path: 'whois-settings',
testXsrfToken: test.testXsrfToken,
testClientId: test.testClientId
});
var testRegistrar = createTestRegistrar();
registry.testing.assertReqMockRsp(
test.testXsrfToken,
'/registrar-settings',
{op: 'read', args: {}},
{
status: 'SUCCESS',
message: 'OK',
results: [testRegistrar]
});
var parsed = registry.util.parseForm('item');
parsed.ianaIdentifier = parseInt(parsed.ianaIdentifier);
registry.testing.assertObjectEqualsPretty(testRegistrar, parsed);
}
function testEdit() {
testView();
registry.testing.click($('reg-app-btn-edit'));
$('emailAddress').value = 'test2.ui@example.com';
$('localizedAddress.street[0]').value = 'look at me i am';
$('localizedAddress.street[1]').value = 'the mistress of the night';
$('localizedAddress.street[2]').value = '';
var parsed = registry.util.parseForm('item');
parsed.readonly = false;
registry.testing.click($('reg-app-btn-save'));
registry.testing.assertReqMockRsp(
test.testXsrfToken,
'/registrar-settings',
{op: 'update', args: parsed},
{
status: 'SUCCESS',
message: 'OK',
results: [parsed]
});
}
function testEditFieldError_insertsError() {
testView();
registry.testing.click($('reg-app-btn-edit'));
$('phoneNumber').value = 'foo';
var parsed = registry.util.parseForm('item');
parsed.readonly = false;
registry.testing.click($('reg-app-btn-save'));
var errMsg = 'Carpe brunchus. --Pablo';
registry.testing.assertReqMockRsp(
test.testXsrfToken,
'/registrar-settings',
{op: 'update', args: parsed},
{
status: 'ERROR',
field: 'phoneNumber',
message: errMsg
});
var msgBox = goog.dom.getNextElementSibling($('phoneNumber'));
assertTrue(goog.dom.classlist.contains(msgBox, 'kd-errormessage'));
assertTrue(goog.dom.classlist.contains($('phoneNumber'), 'kd-formerror'));
assertEquals(errMsg, goog.dom.getTextContent(msgBox));
}
function testEditNonFieldError_showsButterBar() {
testView();
registry.testing.click($('reg-app-btn-edit'));
var parsed = registry.util.parseForm('item');
parsed.readonly = false;
registry.testing.click($('reg-app-btn-save'));
var errMsg = 'One must still have chaos in oneself to be able to give ' +
'birth to a dancing star. --Nietzsche';
registry.testing.assertReqMockRsp(
test.testXsrfToken,
'/registrar-settings',
{op: 'update', args: parsed},
{
status: 'ERROR',
message: errMsg
});
assertEquals(errMsg, goog.dom.getTextContent($$('kd-butterbar-text')));
}

View file

@ -0,0 +1,161 @@
// 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.
goog.provide('registry.testing');
goog.setTestOnly('registry.testing');
goog.require('goog.asserts');
goog.require('goog.dom');
goog.require('goog.dom.classlist');
goog.require('goog.dom.xml');
goog.require('goog.events.EventType');
goog.require('goog.format.JsonPrettyPrinter');
goog.require('goog.html.legacyconversions');
goog.require('goog.json');
goog.require('goog.testing.asserts');
goog.require('goog.testing.events');
goog.require('goog.testing.events.Event');
goog.require('goog.testing.net.XhrIo');
/**
* Adds specified HTML string to document.
* @param {string} html
*/
registry.testing.addToDocument = function(html) {
goog.global.document.body.appendChild(
goog.dom.safeHtmlToNode(
goog.html.legacyconversions.safeHtmlFromString(html)));
};
/**
* Extracts XML document from inside an {@code <iframe>}.
* @param {string} xmlText
* @return {!Document}
*/
registry.testing.loadXml = function(xmlText) {
var xml = goog.dom.xml.loadXml(xmlText);
goog.asserts.assert(xml != null);
if ('parsererror' in xml) {
fail(xml['parsererror']['keyValue']);
}
return xml;
};
/**
* Extracts plain text string from inside an {@code <iframe>}.
* @param {string|!Document|!Element} want
* @param {string|!Document|!Element} got
*/
registry.testing.assertXmlEquals = function(want, got) {
assertHTMLEquals(registry.testing.sanitizeXml_(want),
registry.testing.sanitizeXml_(got));
};
/**
* Simulates a mouse click on a browser element.
* @param {!Element} element
*/
registry.testing.click = function(element) {
goog.testing.events.fireBrowserEvent(
new goog.testing.events.Event(
goog.events.EventType.CLICK, element));
};
/**
* Asserts {@code element} has 'shown' class.
* @param {!Element} element
*/
registry.testing.assertVisible = function(element) {
assertTrue('Element should have CSS "shown" class',
goog.dom.classlist.contains(element, 'shown'));
};
/**
* Asserts {@code element} has 'hidden' class.
* @param {!Element} element
*/
registry.testing.assertHidden = function(element) {
assertTrue('Element should have CSS "hidden" class',
goog.dom.classlist.contains(element, 'hidden'));
};
/**
* Like {@code assertObjectEquals} but with a better error message.
* @param {?Object} a
* @param {?Object} b
*/
registry.testing.assertObjectEqualsPretty = function(a, b) {
try {
assertObjectEquals(a, b);
} catch (e) {
throw Error(e.message + '\n' +
'expected: ' +
registry.testing.pretty_.format(a) + '\n' +
'got: ' +
registry.testing.pretty_.format(b));
}
};
/**
* JSON request/response simulator for {@code ResourceComponent} subclasses.
* @param {string} xsrfToken
* @param {string} path server resource path.
* @param {!Object} expectReqJson assert this object was sent,
* e.g. {'op':'read',{}}
* @param {!Object} mockRspJson mock a response, e.g. {'set':[]}
*/
registry.testing.assertReqMockRsp =
function(xsrfToken, path, expectReqJson, mockRspJson) {
var xhr = goog.testing.net.XhrIo.getSendInstances().pop();
assertTrue('XHR is active.', xhr.isActive());
assertEquals(path, xhr.getLastUri());
// XXX: XHR header checking should probably be added. Was inconsistent
// between admin and registrar consoles.
registry.testing.assertObjectEqualsPretty(
expectReqJson, goog.json.parse(xhr.getLastContent()));
xhr.simulateResponse(200, goog.json.serialize(mockRspJson));
};
/**
* Removes stuff from XML text that we don't want to compare.
* @param {string|!Document|!Element} xml
* @return {string}
* @private
*/
registry.testing.sanitizeXml_ = function(xml) {
var xmlString = goog.isString(xml) ? xml : goog.dom.xml.serialize(xml);
return xmlString
.replace(/^\s*<\?.*?\?>\s*/, '') // Remove declaration thing.
.replace(/xmlns(:\w+)?="[^"]+"/g, '') // Remove namespace things.
.replace(/>\s+</g, '><') // Remove spaces between XML tags.
.replace(/<!--.*?-->/, ''); // Remove comments.
};
/**
* JSON pretty printer.
* @type {!goog.format.JsonPrettyPrinter}
* @private
*/
registry.testing.pretty_ = new goog.format.JsonPrettyPrinter(
new goog.format.JsonPrettyPrinter.TextDelimiters());

View file

@ -0,0 +1,183 @@
// 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.
goog.setTestOnly();
goog.require('goog.dom.xml');
goog.require('goog.testing.asserts');
goog.require('goog.testing.jsunit');
goog.require('registry.testing');
goog.require('registry.xml');
function testEmptyElement_hasNoKeyValue() {
assertXmlTurnsIntoJson(
{'epp': {}},
'<epp></epp>');
}
function testSelfClosingRootElement_hasNoKeyValue() {
assertXmlTurnsIntoJson(
{'epp': {}},
'<epp/>');
}
function testElementWithWhitespaceTextContent_getsIgnored() {
assertXmlTurnsIntoJson(
{'epp': {}},
'<epp> \r\n </epp>');
}
function testElementWithTextContent_getsSetToKeyValueField() {
assertXmlTurnsIntoJson(
{'epp': {'keyValue': 'hello'}},
'<epp>hello</epp>');
}
function testTextWithSpacesOnSides_getsTrimmed() {
assertXmlTurnsIntoJson(
{'epp': {'keyValue': 'hello'}},
'<epp> hello </epp>');
}
function testAttribute_getsSetToFieldPrefixedByAtSymbol() {
assertXmlTurnsIntoJson(
{'epp': {'@ohmy': 'goth'}},
'<epp ohmy="goth"/>');
}
function testSingleNestedElement_keyIsNameAndValueIsNode() {
assertXmlTurnsIntoJson(
{'epp': {'ohmy': {'keyValue': 'goth'}}},
'<epp><ohmy>goth</ohmy></epp>');
}
function testMultipleNestedElements_valueBecomesArray() {
assertXmlTurnsIntoJson(
{'epp': {'ohmy': [{'keyValue': 'goth1'}, {'keyValue': 'goth2'}]}},
'<epp><ohmy>goth1</ohmy><ohmy>goth2</ohmy></epp>');
}
function testInterspersedText_throwsError() {
assertEquals(
'XML text "hello" interspersed with "there"',
assertThrows(function() {
registry.xml.convertToJson(
goog.dom.xml.loadXml(
'<epp> hello <omg/> there </epp>'));
}).message);
}
function testEppMessage() {
assertXmlTurnsIntoJson(
{
'epp': {
'@xmlns': 'urn:ietf:params:xml:ns:epp-1.0',
'response': {
'result': {
'@code': '1000',
'msg': {'keyValue': 'Command completed successfully'}
},
'resData': {
'domain:infData': {
'@xmlns:domain': 'urn:ietf:params:xml:ns:domain-1.0',
'domain:name': {'keyValue': 'justine.lol'},
'domain:roid': {'keyValue': '6-roid'},
'domain:status': {'@s': 'inactive'},
'domain:registrant': {'keyValue': 'GK Chesterton'},
'domain:contact': [
{'@type': 'admin', 'keyValue': '<justine>'},
{'@type': 'billing', 'keyValue': 'candycrush'},
{'@type': 'tech', 'keyValue': 'krieger'}
],
'domain:ns': {
'domain:hostObj': [
{'keyValue': 'ns1.justine.lol'},
{'keyValue': 'ns2.justine.lol'}
]
},
'domain:host': {'keyValue': 'ns1.justine.lol'},
'domain:clID': {'keyValue': 'justine'},
'domain:crID': {'keyValue': 'justine'},
'domain:crDate': {'keyValue': '2014-07-10T02:17:02Z'},
'domain:exDate': {'keyValue': '2015-07-10T02:17:02Z'},
'domain:authInfo': {
'domain:pw': {'keyValue': 'lolcat'}
}
}
},
'trID': {
'clTRID': {'keyValue': 'abc-1234'},
'svTRID': {'keyValue': 'ytk1RO+8SmaDQxrTIdulnw==-4'}
}
}
}
},
'<?xml version="1.0"?>' +
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">' +
' <response>' +
' <result code="1000">' +
' <msg>Command completed successfully</msg>' +
' </result>' +
' <resData>' +
' <domain:infData' +
' xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">' +
' <domain:name>justine.lol</domain:name>' +
' <domain:roid>6-roid</domain:roid>' +
' <domain:status s="inactive"/>' +
' <domain:registrant>GK Chesterton</domain:registrant>' +
' <domain:contact type="admin">&lt;justine&gt;</domain:contact>' +
' <domain:contact type="billing">candycrush</domain:contact>' +
' <domain:contact type="tech">krieger</domain:contact>' +
' <domain:ns>' +
' <domain:hostObj>ns1.justine.lol</domain:hostObj>' +
' <domain:hostObj>ns2.justine.lol</domain:hostObj>' +
' </domain:ns>' +
' <domain:host>ns1.justine.lol</domain:host>' +
' <domain:clID>justine</domain:clID>' +
' <domain:crID>justine</domain:crID>' +
' <domain:crDate>2014-07-10T02:17:02Z</domain:crDate>' +
' <domain:exDate>2015-07-10T02:17:02Z</domain:exDate>' +
' <domain:authInfo>' +
' <domain:pw>lolcat</domain:pw>' +
' </domain:authInfo>' +
' </domain:infData>' +
' </resData>' +
' <trID>' +
' <clTRID>abc-1234</clTRID>' +
' <svTRID>ytk1RO+8SmaDQxrTIdulnw==-4</svTRID>' +
' </trID>' +
' </response>' +
'</epp>');
}
/**
* Asserts {@code xml} turns into {@code json}.
* @param {!Object} json
* @param {string} xml
*/
function assertXmlTurnsIntoJson(json, xml) {
registry.testing.assertObjectEqualsPretty(
json, registry.xml.convertToJson(goog.dom.xml.loadXml(xml)));
}

View file

@ -0,0 +1,23 @@
package(default_visibility = ["//java/com/google/domain/registry:registry_project"])
load("//java/com/google/testing/builddefs:GenTestRules.bzl", "GenTestRules")
java_library(
name = "server",
srcs = glob(["*.java"]),
deps = [
"//java/com/google/domain/registry/ui/forms",
"//java/com/google/domain/registry/ui/server",
"//javatests/com/google/domain/registry/testing",
"//third_party/java/hamcrest",
"//third_party/java/junit",
"//third_party/java/truth",
],
)
GenTestRules(
name = "GeneratedTestRules",
test_files = glob(["*Test.java"]),
deps = [":server"],
)

View file

@ -0,0 +1,65 @@
// 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 com.google.domain.registry.ui.server;
import static com.google.common.truth.Truth.assertThat;
import static org.hamcrest.Matchers.equalTo;
import com.google.domain.registry.testing.CertificateSamples;
import com.google.domain.registry.ui.forms.FormFieldException;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/** Unit tests for {@link RegistrarFormFields}. */
@RunWith(JUnit4.class)
public class RegistrarFormFieldsTest {
@Rule
public final ExpectedException thrown = ExpectedException.none();
@Test
public void testValidCertificate_doesntThrowError() {
assertThat(RegistrarFormFields.CLIENT_CERTIFICATE_FIELD.convert(CertificateSamples.SAMPLE_CERT))
.hasValue(CertificateSamples.SAMPLE_CERT);
}
@Test
public void testBadCertificate_throwsFfe() {
thrown.expect(equalTo(
new FormFieldException("Invalid X.509 PEM certificate")
.propagate("clientCertificate")));
RegistrarFormFields.CLIENT_CERTIFICATE_FIELD.convert("palfun");
}
@Test
public void testValidCertificateHash_doesntThrowError() {
assertThat(
RegistrarFormFields.CLIENT_CERTIFICATE_HASH_FIELD.convert(
CertificateSamples.SAMPLE_CERT_HASH))
.hasValue(CertificateSamples.SAMPLE_CERT_HASH);
}
@Test
public void testBadCertificateHash_throwsFfe() {
thrown.expect(equalTo(
new FormFieldException("Field must contain a base64 value.")
.propagate("clientCertificateHash")));
RegistrarFormFields.CLIENT_CERTIFICATE_HASH_FIELD.convert("~~~");
}
}

View file

@ -0,0 +1,27 @@
package(default_visibility = ["//java/com/google/domain/registry:registry_project"])
load("//java/com/google/testing/builddefs:GenTestRules.bzl", "GenTestRules")
java_library(
name = "api",
srcs = glob(["*.java"]),
deps = [
"//java/com/google/common/collect",
"//java/com/google/domain/registry/model",
"//java/com/google/domain/registry/ui/server/api",
"//javatests/com/google/domain/registry/testing",
"//third_party/java/appengine:appengine-api-testonly",
"//third_party/java/json_simple",
"//third_party/java/junit",
"//third_party/java/mockito",
"//third_party/java/servlet/servlet_api",
"//third_party/java/truth",
],
)
GenTestRules(
name = "GeneratedTestRules",
test_files = glob(["*Test.java"]),
deps = [":api"],
)

View file

@ -0,0 +1,193 @@
// 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 com.google.domain.registry.ui.server.api;
import static com.google.common.truth.Truth.assertThat;
import static com.google.domain.registry.testing.DatastoreHelper.createTld;
import static com.google.domain.registry.testing.DatastoreHelper.persistActiveDomain;
import static com.google.domain.registry.testing.DatastoreHelper.persistReservedList;
import static com.google.domain.registry.testing.DatastoreHelper.persistResource;
import static org.mockito.Mockito.when;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.domain.registry.model.registrar.Registrar;
import com.google.domain.registry.model.registry.Registry;
import com.google.domain.registry.testing.AppEngineRule;
import org.json.simple.JSONValue;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/** Tests for {@link CheckApiServlet}. */
@RunWith(MockitoJUnitRunner.class)
public class CheckApiServletTest {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.build();
@Mock HttpServletRequest req;
@Mock HttpServletResponse rsp;
private final StringWriter writer = new StringWriter();
private final CheckApiServlet servlet = new CheckApiServlet();
@Before
public void init() throws Exception {
createTld("example");
persistResource(
Registry.get("example")
.asBuilder()
.setReservedLists(persistReservedList("example-reserved", "foo,FULLY_BLOCKED"))
.build());
when(rsp.getWriter()).thenReturn(new PrintWriter(writer));
}
private void doTest(Map<String, ?> expected) throws Exception {
servlet.doGet(req, rsp);
assertThat(JSONValue.parse(writer.toString())).isEqualTo(expected);
}
@Test
public void testFailure_nullDomain() throws Exception {
doTest(ImmutableMap.of(
"status", "error",
"reason", "Must supply a valid second level domain name"));
}
@Test
public void testFailure_emptyDomain() throws Exception {
when(req.getParameter("domain")).thenReturn("");
doTest(ImmutableMap.of(
"status", "error",
"reason", "Must supply a valid second level domain name"));
}
@Test
public void testFailure_invalidDomain() throws Exception {
when(req.getParameter("domain")).thenReturn("@#$%^");
doTest(ImmutableMap.of(
"status", "error",
"reason", "Must supply a valid second level domain name"));
}
@Test
public void testFailure_singlePartDomain() throws Exception {
when(req.getParameter("domain")).thenReturn("foo");
doTest(ImmutableMap.of(
"status", "error",
"reason", "Must supply a valid second level domain name"));
}
@Test
public void testFailure_nonExistentTld() throws Exception {
when(req.getParameter("domain")).thenReturn("foo.bar");
doTest(ImmutableMap.of(
"status", "error",
"reason", "Domain name is under tld bar which doesn't exist"));
}
@Test
public void testFailure_unauthorizedTld() throws Exception {
createTld("foo");
persistResource(
Registrar.loadByClientId("TheRegistrar")
.asBuilder()
.setAllowedTlds(ImmutableSet.of("foo"))
.build());
when(req.getParameter("domain")).thenReturn("timmy.example");
doTest(ImmutableMap.of(
"status", "error",
"reason", "Registrar is not authorized to access the TLD example"));
}
@Test
public void testSuccess_availableStandard() throws Exception {
when(req.getParameter("domain")).thenReturn("somedomain.example");
doTest(ImmutableMap.of(
"status", "success",
"available", true,
"tier", "standard"));
}
@Test
public void testSuccess_availableCapital() throws Exception {
when(req.getParameter("domain")).thenReturn("SOMEDOMAIN.EXAMPLE");
doTest(ImmutableMap.of(
"status", "success",
"available", true,
"tier", "standard"));
}
@Test
public void testSuccess_availableUnicode() throws Exception {
when(req.getParameter("domain")).thenReturn("ééé.example");
doTest(ImmutableMap.of(
"status", "success",
"available", true,
"tier", "standard"));
}
@Test
public void testSuccess_availablePunycode() throws Exception {
when(req.getParameter("domain")).thenReturn("xn--9caaa.example");
doTest(ImmutableMap.of(
"status", "success",
"available", true,
"tier", "standard"));
}
@Test
public void testSuccess_availablePremium() throws Exception {
when(req.getParameter("domain")).thenReturn("rich.example");
doTest(ImmutableMap.of(
"status", "success",
"available", true,
"tier", "premium"));
}
@Test
public void testSuccess_alreadyRegistered() throws Exception {
persistActiveDomain("somedomain.example");
when(req.getParameter("domain")).thenReturn("somedomain.example");
doTest(ImmutableMap.of(
"status", "success",
"available", false,
"reason", "In use"));
}
@Test
public void testSuccess_reserved() throws Exception {
when(req.getParameter("domain")).thenReturn("foo.example");
doTest(ImmutableMap.of(
"status", "success",
"available", false,
"reason", "Reserved"));
}
}

View file

@ -0,0 +1,43 @@
package(default_visibility = ["//java/com/google/domain/registry:registry_project"])
load("//java/com/google/testing/builddefs:GenTestRules.bzl", "GenTestRules")
java_library(
name = "registrar",
srcs = glob(["*.java"]),
resources = glob(["testdata/*"]),
deps = [
"//java/com/google/common/base",
"//java/com/google/common/collect",
"//java/com/google/common/io",
"//java/com/google/common/net",
"//java/com/google/common/testing",
"//java/com/google/domain/registry/braintree",
"//java/com/google/domain/registry/config",
"//java/com/google/domain/registry/export/sheet",
"//java/com/google/domain/registry/model",
"//java/com/google/domain/registry/security",
"//java/com/google/domain/registry/ui/server/registrar",
"//java/com/google/domain/registry/ui/soy/registrar:soy_java_wrappers",
"//java/com/google/domain/registry/util",
"//javatests/com/google/domain/registry/security",
"//javatests/com/google/domain/registry/testing",
"//third_party/java/appengine:appengine-api-testonly",
"//third_party/java/braintree",
"//third_party/java/joda_money",
"//third_party/java/joda_time",
"//third_party/java/json_simple",
"//third_party/java/junit",
"//third_party/java/mockito",
"//third_party/java/objectify:objectify-v4_1",
"//third_party/java/servlet/servlet_api",
"//third_party/java/truth",
],
)
GenTestRules(
name = "GeneratedTestRules",
test_files = glob(["*Test.java"]),
deps = [":registrar"],
)

View file

@ -0,0 +1,101 @@
// 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 com.google.domain.registry.ui.server.registrar;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.when;
import com.google.appengine.api.users.UserServiceFactory;
import com.google.common.net.MediaType;
import com.google.domain.registry.testing.AppEngineRule;
import com.google.domain.registry.testing.FakeResponse;
import com.google.domain.registry.testing.UserInfo;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import javax.servlet.http.HttpServletRequest;
/** Unit tests for {@link ConsoleUiAction}. */
@RunWith(MockitoJUnitRunner.class)
public class ConsoleUiActionTest {
@Rule
public final AppEngineRule appEngineRule = AppEngineRule.builder()
.withDatastore()
.withUserService(UserInfo.create("marla.singer@example.com", "12345"))
.build();
@Mock
private SessionUtils sessionUtils;
private final FakeResponse response = new FakeResponse();
private final ConsoleUiAction action = new ConsoleUiAction();
@Before
public void setUp() throws Exception {
action.enabled = true;
action.response = response;
action.sessionUtils = sessionUtils;
action.userService = UserServiceFactory.getUserService();
when(sessionUtils.checkRegistrarConsoleLogin(any(HttpServletRequest.class))).thenReturn(true);
when(sessionUtils.getRegistrarClientId(any(HttpServletRequest.class)))
.thenReturn("TheRegistrar");
}
@Test
public void webPage_disallowsIframe() throws Exception {
action.run();
assertThat(response.getHeaders()).containsEntry("X-Frame-Options", "SAMEORIGIN");
}
@Test
public void webPage_setsHtmlUtf8ContentType() throws Exception {
action.run();
assertThat(response.getContentType()).isEqualTo(MediaType.HTML_UTF_8);
}
@Test
public void webPage_containsUserNickname() throws Exception {
action.run();
assertThat(response.getPayload()).contains("marla.singer");
}
@Test
public void userHasAccessAsTheRegistrar_showsRegistrarConsole() throws Exception {
action.run();
assertThat(response.getPayload()).contains("Registrar Console");
assertThat(response.getPayload()).contains("reg-content-and-footer");
}
@Test
public void consoleDisabled_showsDisabledPage() throws Exception {
action.enabled = false;
action.run();
assertThat(response.getPayload()).contains("<h1>Console is disabled</h1>");
}
@Test
public void userDoesntHaveAccessToAnyRegistrar_showsWhoAreYouPage() throws Exception {
when(sessionUtils.checkRegistrarConsoleLogin(any(HttpServletRequest.class))).thenReturn(false);
action.run();
assertThat(response.getPayload()).contains("<h1>You need permission</h1>");
}
}

View file

@ -0,0 +1,139 @@
// 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 com.google.domain.registry.ui.server.registrar;
import static com.google.common.truth.Truth.assertThat;
import static com.google.domain.registry.security.JsonHttpTestUtils.createJsonPayload;
import static org.mockito.Mockito.when;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.domain.registry.model.registrar.Registrar;
import com.google.domain.registry.model.registrar.RegistrarContact;
import com.google.domain.registry.testing.AppEngineRule;
import com.google.domain.registry.testing.DatastoreHelper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.runners.MockitoJUnitRunner;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Unit tests for contact_settings.js use of {@link RegistrarServlet}.
*
* <p>The default read and session validation tests are handled by the
* superclass.
*/
@RunWith(MockitoJUnitRunner.class)
public class ContactSettingsTest extends RegistrarServletTestCase {
@Test
public void testPost_readContacts_success() throws Exception {
when(req.getReader()).thenReturn(createJsonPayload(ImmutableMap.of(
"op", "read",
"args", ImmutableMap.of())));
servlet.service(req, rsp);
@SuppressWarnings("unchecked")
List<Map<String, ?>> results = (List<Map<String, ?>>) json.get().get("results");
assertThat(results.get(0).get("contacts"))
.isEqualTo(Registrar.loadByClientId(CLIENT_ID).toJsonMap().get("contacts"));
}
@Test
public void testPost_loadSaveRegistrar_success() throws Exception {
when(req.getReader()).thenReturn(createJsonPayload(ImmutableMap.of(
"op", "update",
"args", Registrar.loadByClientId(CLIENT_ID).toJsonMap())));
servlet.service(req, rsp);
assertThat(json.get()).containsEntry("status", "SUCCESS");
}
@Test
public void testPost_updateContacts_success() throws Exception {
// Remove all the contacts but the first by updating with list of
// just it.
Map<String, /* @Nullable */ Object> adminContact1 = new HashMap<>();
adminContact1.put("name", "contact1");
adminContact1.put("emailAddress", "contact1@email.com");
adminContact1.put("phoneNumber", "+1.2125650001");
// Have to keep ADMIN or else expect FormException for at-least-one.
adminContact1.put("types", "ADMIN");
Registrar registrar = Registrar.loadByClientId(CLIENT_ID);
Map<String, Object> regMap = registrar.toJsonMap();
regMap.put("contacts", ImmutableList.of(adminContact1));
when(req.getReader()).thenReturn(createJsonPayload(ImmutableMap.of(
"op", "update",
"args", regMap)));
servlet.service(req, rsp);
assertThat(json.get()).containsEntry("status", "SUCCESS");
RegistrarContact newContact = new RegistrarContact.Builder()
.setParent(registrar)
.setName((String) adminContact1.get("name"))
.setEmailAddress((String) adminContact1.get("emailAddress"))
.setPhoneNumber((String) adminContact1.get("phoneNumber"))
.setTypes(ImmutableList.of(RegistrarContact.Type.ADMIN))
.build();
assertThat(Registrar.loadByClientId(CLIENT_ID).getContacts())
.containsExactlyElementsIn(ImmutableSet.of(newContact));
}
@Test
public void testPost_updateContacts_requiredTypes_error() throws Exception {
Map<String, Object> reqJson = Registrar.loadByClientId(CLIENT_ID).toJsonMap();
reqJson.put("contacts",
ImmutableList.of(AppEngineRule.makeRegistrarContact2()
.asBuilder()
.setTypes(ImmutableList.<RegistrarContact.Type>of())
.build().toJsonMap()));
when(req.getReader()).thenReturn(createJsonPayload(ImmutableMap.of(
"op", "update",
"args", reqJson)));
servlet.service(req, rsp);
assertThat(json.get()).containsEntry("status", "ERROR");
assertThat(json.get()).containsEntry("message", "Must have at least one "
+ RegistrarContact.Type.ADMIN.getDisplayName() + " contact");
}
@Test
public void testPost_updateContacts_requireTechPhone_error() throws Exception {
// First make the contact a tech contact as well.
Registrar registrar = Registrar.loadByClientId(CLIENT_ID);
RegistrarContact rc = AppEngineRule.makeRegistrarContact2()
.asBuilder()
.setTypes(ImmutableSet.of(RegistrarContact.Type.ADMIN, RegistrarContact.Type.TECH))
.build();
// Lest we anger the timestamp inversion bug.
DatastoreHelper.persistResource(registrar);
DatastoreHelper.persistSimpleGlobalResources(ImmutableSet.of(rc));
// Now try to remove the phone number.
rc = rc.asBuilder().setPhoneNumber(null).build();
Map<String, Object> reqJson = registrar.toJsonMap();
reqJson.put("contacts", ImmutableList.of(rc.toJsonMap()));
when(req.getReader()).thenReturn(createJsonPayload(ImmutableMap.of(
"op", "update",
"args", reqJson)));
servlet.service(req, rsp);
assertThat(json.get()).containsEntry("status", "ERROR");
assertThat(json.get()).containsEntry("message", "At least one "
+ RegistrarContact.Type.TECH.getDisplayName() + " contact must have a phone number");
}
}

View file

@ -0,0 +1,446 @@
// 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 com.google.domain.registry.ui.server.registrar;
import static com.google.common.truth.Truth.assertThat;
import static com.google.domain.registry.testing.ReflectiveFieldExtractor.extractField;
import static java.util.Arrays.asList;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import com.google.common.collect.ImmutableMap;
import com.google.domain.registry.model.registrar.Registrar;
import com.google.domain.registry.testing.AppEngineRule;
import com.braintreegateway.BraintreeGateway;
import com.braintreegateway.Result;
import com.braintreegateway.Transaction;
import com.braintreegateway.Transaction.GatewayRejectionReason;
import com.braintreegateway.TransactionGateway;
import com.braintreegateway.TransactionRequest;
import com.braintreegateway.ValidationError;
import com.braintreegateway.ValidationErrorCode;
import com.braintreegateway.ValidationErrors;
import org.joda.money.CurrencyUnit;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import java.math.BigDecimal;
/** Tests for {@link RegistrarPaymentAction}. */
@RunWith(MockitoJUnitRunner.class)
public class RegistrarPaymentActionTest {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
@Mock
private BraintreeGateway braintreeGateway;
@Mock
private TransactionGateway transactionGateway;
@Mock
private Result<Transaction> result;
@Mock
private Transaction transaction;
@Mock
private ValidationErrors validationErrors;
@Captor
private ArgumentCaptor<TransactionRequest> transactionRequestCaptor;
private final RegistrarPaymentAction paymentAction = new RegistrarPaymentAction();
@Before
public void before() throws Exception {
paymentAction.registrar = Registrar.loadByClientId("TheRegistrar");
paymentAction.accountIds =
ImmutableMap.of(
CurrencyUnit.USD, "merchant-account-usd",
CurrencyUnit.JPY, "merchant-account-jpy");
paymentAction.braintreeGateway = braintreeGateway;
when(braintreeGateway.transaction()).thenReturn(transactionGateway);
when(transactionGateway.sale(any(TransactionRequest.class))).thenReturn(result);
}
@Test
public void testCurrencyIsUsd_usesAmericanMerchantAccount() throws Exception {
when(result.isSuccess()).thenReturn(true);
when(result.getTarget()).thenReturn(transaction);
when(transaction.getId()).thenReturn("omg-im-an-id");
when(transaction.getAmount()).thenReturn(BigDecimal.valueOf(123.4));
when(transaction.getCurrencyIsoCode()).thenReturn("USD");
assertThat(
paymentAction.handleJsonRequest(
ImmutableMap.of(
"amount", " 123.4 ",
"currency", "USD",
"paymentMethodNonce", "abc-123")))
.containsExactly(
"status", "SUCCESS",
"message", "Payment processed successfully",
"results", asList(
ImmutableMap.of(
"id", "omg-im-an-id",
"formattedAmount", "$123.40")));
verify(transactionGateway).sale(transactionRequestCaptor.capture());
TransactionRequest transactionRequest = transactionRequestCaptor.getAllValues().get(0);
assertThat(extractField(BigDecimal.class, transactionRequest, "amount"))
.isEqualTo(BigDecimal.valueOf(123.4).setScale(2));
assertThat(extractField(String.class, transactionRequest, "merchantAccountId"))
.isEqualTo("merchant-account-usd");
assertThat(extractField(String.class, transactionRequest, "customerId"))
.isEqualTo("TheRegistrar");
}
@Test
public void testCurrencyIsJpy_usesJapaneseMerchantAccount() throws Exception {
when(result.isSuccess()).thenReturn(true);
when(result.getTarget()).thenReturn(transaction);
when(transaction.getId()).thenReturn("omg-im-an-id");
when(transaction.getAmount()).thenReturn(BigDecimal.valueOf(123));
when(transaction.getCurrencyIsoCode()).thenReturn("JPY");
assertThat(
paymentAction.handleJsonRequest(
ImmutableMap.of(
"amount", "123",
"currency", "JPY",
"paymentMethodNonce", "abc-123")))
.containsExactly(
"status", "SUCCESS",
"message", "Payment processed successfully",
"results", asList(
ImmutableMap.of(
"id", "omg-im-an-id",
"formattedAmount", "JPY 123")));
verify(transactionGateway).sale(transactionRequestCaptor.capture());
TransactionRequest transactionRequest = transactionRequestCaptor.getAllValues().get(0);
assertThat(extractField(BigDecimal.class, transactionRequest, "amount"))
.isEqualTo(BigDecimal.valueOf(123));
assertThat(extractField(String.class, transactionRequest, "merchantAccountId"))
.isEqualTo("merchant-account-jpy");
}
@Test
public void testAmountNotPresent_returnsErrorOnAmountField() throws Exception {
assertThat(
paymentAction.handleJsonRequest(
ImmutableMap.of(
"currency", "JPY",
"paymentMethodNonce", "abc-123")))
.containsExactly(
"status", "ERROR",
"message", "This field is required.",
"field", "amount",
"results", asList());
}
@Test
public void testAmountNotNumber_returnsErrorOnAmountField() throws Exception {
assertThat(
paymentAction.handleJsonRequest(
ImmutableMap.of(
"amount", "abc",
"currency", "JPY",
"paymentMethodNonce", "abc-123")))
.containsExactly(
"status", "ERROR",
"message", "Invalid number.",
"field", "amount",
"results", asList());
}
@Test
public void testNegativeAmount_returnsErrorOnAmountField() throws Exception {
assertThat(
paymentAction.handleJsonRequest(
ImmutableMap.of(
"amount", "-10",
"currency", "JPY",
"paymentMethodNonce", "abc-123")))
.containsExactly(
"status", "ERROR",
"message", "Must be a positive number.",
"field", "amount",
"results", asList());
}
@Test
public void testZeroAmount_returnsErrorOnAmountField() throws Exception {
assertThat(
paymentAction.handleJsonRequest(
ImmutableMap.of(
"amount", "0",
"currency", "JPY",
"paymentMethodNonce", "abc-123")))
.containsExactly(
"status", "ERROR",
"message", "Must be a positive number.",
"field", "amount",
"results", asList());
}
@Test
public void testAmountHasMorePrecisionThanUsdCurrencyAllows_returnsError() throws Exception {
assertThat(
paymentAction.handleJsonRequest(
ImmutableMap.of(
"amount", "123.456",
"currency", "USD",
"paymentMethodNonce", "abc-123")))
.containsExactly(
"status", "ERROR",
"message", "Scale of amount 123.456 is greater than the scale of the currency USD",
"field", "amount",
"results", asList());
}
@Test
public void testAmountHasMorePrecisionThanJpyCurrencyAllows_returnsError() throws Exception {
assertThat(
paymentAction.handleJsonRequest(
ImmutableMap.of(
"amount", "1.1",
"currency", "JPY",
"paymentMethodNonce", "abc-123")))
.containsExactly(
"status", "ERROR",
"message", "Scale of amount 1.1 is greater than the scale of the currency JPY",
"field", "amount",
"results", asList());
}
@Test
public void testCurrencyValidButNotSupported_returnsErrorOnCurrencyField() throws Exception {
assertThat(
paymentAction.handleJsonRequest(
ImmutableMap.of(
"amount", "123",
"currency", "EUR",
"paymentMethodNonce", "abc-123")))
.containsExactly(
"status", "ERROR",
"message", "Unsupported currency.",
"field", "currency",
"results", asList());
}
@Test
public void testCurrencyBogus_returnsErrorOnCurrencyField() throws Exception {
assertThat(
paymentAction.handleJsonRequest(
ImmutableMap.of(
"amount", "123",
"currency", "rm -rf /etc/passwd",
"paymentMethodNonce", "abc-123")))
.containsExactly(
"status", "ERROR",
"message", "Invalid currency code.",
"field", "currency",
"results", asList());
}
@Test
public void testCurrencyCodeNotAssigned_returnsErrorOnCurrencyField() throws Exception {
assertThat(
paymentAction.handleJsonRequest(
ImmutableMap.of(
"amount", "123",
"currency", "ZZZ",
"paymentMethodNonce", "abc-123")))
.containsExactly(
"status", "ERROR",
"message", "Unknown ISO currency code.",
"field", "currency",
"results", asList());
}
@Test
public void testCurrencyMissing_returnsErrorOnCurrencyField() throws Exception {
assertThat(
paymentAction.handleJsonRequest(
ImmutableMap.of(
"amount", "123",
"paymentMethodNonce", "omg")))
.containsExactly(
"status", "ERROR",
"message", "This field is required.",
"field", "currency",
"results", asList());
}
@Test
public void testPaymentMethodMissing_returnsErrorOnPaymentMethodField() throws Exception {
assertThat(
paymentAction.handleJsonRequest(
ImmutableMap.of(
"amount", "123",
"currency", "JPY")))
.containsExactly(
"status", "ERROR",
"message", "This field is required.",
"field", "paymentMethodNonce",
"results", asList());
}
@Test
public void testProcessorDeclined_returnsErrorResponse() throws Exception {
when(result.isSuccess()).thenReturn(false);
when(result.getTransaction()).thenReturn(transaction);
when(transaction.getStatus()).thenReturn(Transaction.Status.PROCESSOR_DECLINED);
when(transaction.getProcessorResponseText())
.thenReturn("You don't know the power of the dark side");
assertThat(
paymentAction.handleJsonRequest(
ImmutableMap.of(
"amount", "123",
"currency", "USD",
"paymentMethodNonce", "abc-123")))
.containsExactly(
"status", "ERROR",
"message", "Payment declined: You don't know the power of the dark side",
"results", asList());
}
@Test
public void testGatewayRejectedDueToCvv_returnsErrorResponse() throws Exception {
when(result.isSuccess()).thenReturn(false);
when(result.getTransaction()).thenReturn(transaction);
when(transaction.getStatus()).thenReturn(Transaction.Status.GATEWAY_REJECTED);
when(transaction.getGatewayRejectionReason()).thenReturn(GatewayRejectionReason.CVV);
assertThat(
paymentAction.handleJsonRequest(
ImmutableMap.of(
"amount", "123",
"currency", "USD",
"paymentMethodNonce", "abc-123")))
.containsExactly(
"status", "ERROR",
"message", "Payment rejected: Invalid CVV code.",
"results", asList());
}
@Test
public void testGatewayRejectedDueToAddress_returnsErrorResponse() throws Exception {
when(result.isSuccess()).thenReturn(false);
when(result.getTransaction()).thenReturn(transaction);
when(transaction.getStatus()).thenReturn(Transaction.Status.GATEWAY_REJECTED);
when(transaction.getGatewayRejectionReason()).thenReturn(GatewayRejectionReason.AVS);
assertThat(
paymentAction.handleJsonRequest(
ImmutableMap.of(
"amount", "123",
"currency", "USD",
"paymentMethodNonce", "abc-123")))
.containsExactly(
"status", "ERROR",
"message", "Payment rejected: Invalid address.",
"results", asList());
}
@Test
public void testSettlementDeclined_returnsErrorResponse() throws Exception {
when(result.isSuccess()).thenReturn(false);
when(result.getTransaction()).thenReturn(transaction);
when(transaction.getStatus()).thenReturn(Transaction.Status.SETTLEMENT_DECLINED);
when(transaction.getProcessorSettlementResponseText())
.thenReturn("mine eyes have seen the glory of the coming of the borg");
assertThat(
paymentAction.handleJsonRequest(
ImmutableMap.of(
"amount", "123",
"currency", "USD",
"paymentMethodNonce", "abc-123")))
.containsExactly(
"status", "ERROR",
"message", "Payment declined: mine eyes have seen the glory of the coming of the borg",
"results", asList());
}
@Test
public void testHasTransactionObjectWithWeirdStatus_returnsErrorResponse() throws Exception {
when(result.isSuccess()).thenReturn(false);
when(result.getTransaction()).thenReturn(transaction);
when(transaction.getStatus()).thenReturn(Transaction.Status.UNRECOGNIZED);
when(transaction.getProcessorResponseText())
.thenReturn("he is preempting the instance where the deadlocked shards are stored");
assertThat(
paymentAction.handleJsonRequest(
ImmutableMap.of(
"amount", "123",
"currency", "USD",
"paymentMethodNonce", "abc-123")))
.containsExactly(
"status", "ERROR",
"message", "Payment failure: "
+ "he is preempting the instance where the deadlocked shards are stored",
"results", asList());
}
@Test
public void testFailedWithWeirdStatusButNoHelpfulText_usesWeirdStatusAsMsg() throws Exception {
when(result.isSuccess()).thenReturn(false);
when(result.getTransaction()).thenReturn(transaction);
when(transaction.getStatus()).thenReturn(Transaction.Status.FAILED);
assertThat(
paymentAction.handleJsonRequest(
ImmutableMap.of(
"amount", "123",
"currency", "USD",
"paymentMethodNonce", "abc-123")))
.containsExactly(
"status", "ERROR",
"message", "Payment failure: FAILED",
"results", asList());
}
@Test
public void testRemoteValidationError_showsErrorOnlyOnFirstFormField() throws Exception {
when(result.isSuccess()).thenReturn(false);
when(result.getErrors()).thenReturn(validationErrors);
when(validationErrors.getAllDeepValidationErrors())
.thenReturn(asList(
new ValidationError(
"amount",
ValidationErrorCode.TRANSACTION_SETTLEMENT_AMOUNT_IS_LESS_THAN_SERVICE_FEE_AMOUNT,
"Gimmeh moar moneys"),
new ValidationError(
"fax",
ValidationErrorCode.CUSTOMER_FAX_IS_TOO_LONG,
"Fax is too long")));
assertThat(
paymentAction.handleJsonRequest(
ImmutableMap.of(
"amount", "123",
"currency", "USD",
"paymentMethodNonce", "abc-123")))
.containsExactly(
"status", "ERROR",
"message", "Gimmeh moar moneys",
"field", "amount",
"results", asList());
}
}

View file

@ -0,0 +1,112 @@
// 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 com.google.domain.registry.ui.server.registrar;
import static com.google.common.truth.Truth.assertThat;
import static java.util.Arrays.asList;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import com.google.common.collect.ImmutableMap;
import com.google.domain.registry.braintree.BraintreeRegistrarSyncer;
import com.google.domain.registry.model.registrar.Registrar;
import com.google.domain.registry.testing.AppEngineRule;
import com.braintreegateway.BraintreeGateway;
import com.braintreegateway.ClientTokenGateway;
import org.joda.money.CurrencyUnit;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
/** Tests for {@link RegistrarPaymentSetupAction}. */
@RunWith(MockitoJUnitRunner.class)
public class RegistrarPaymentSetupActionTest {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.build();
@Mock
private BraintreeGateway braintreeGateway;
@Mock
private ClientTokenGateway clientTokenGateway;
@Mock
private BraintreeRegistrarSyncer customerSyncer;
private final RegistrarPaymentSetupAction action = new RegistrarPaymentSetupAction();
@Before
public void before() throws Exception {
action.braintreeGateway = braintreeGateway;
action.customerSyncer = customerSyncer;
action.registrar =
Registrar.loadByClientId("TheRegistrar").asBuilder()
.setBillingMethod(Registrar.BillingMethod.BRAINTREE)
.build();
when(braintreeGateway.clientToken()).thenReturn(clientTokenGateway);
}
@Test
public void testTokenGeneration() throws Exception {
action.brainframe = "/doodle";
action.accountIds =
ImmutableMap.of(
CurrencyUnit.USD, "sorrow",
CurrencyUnit.JPY, "torment");
String blanketsOfSadness = "our hearts are beating, but no one is breathing";
when(clientTokenGateway.generate()).thenReturn(blanketsOfSadness);
assertThat(action.handleJsonRequest(ImmutableMap.<String, Object>of()))
.containsExactly(
"status", "SUCCESS",
"message", "Success",
"results", asList(
ImmutableMap.of(
"token", blanketsOfSadness,
"currencies", asList("USD", "JPY"),
"brainframe", "/doodle")));
verify(customerSyncer).sync(eq(action.registrar));
}
@Test
public void testNonEmptyRequestObject_returnsError() throws Exception {
assertThat(action.handleJsonRequest(ImmutableMap.of("oh", "no")))
.containsExactly(
"status", "ERROR",
"message", "JSON request object must be empty",
"results", asList());
}
@Test
public void testNotOnCreditCardBillingTerms_showsErrorPage() throws Exception {
action.registrar =
Registrar.loadByClientId("TheRegistrar").asBuilder()
.setBillingMethod(Registrar.BillingMethod.EXTERNAL)
.build();
assertThat(action.handleJsonRequest(ImmutableMap.<String, Object>of()))
.containsExactly(
"status", "ERROR",
"message", "not-using-cc-billing",
"results", asList());
}
}

View file

@ -0,0 +1,170 @@
// 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 com.google.domain.registry.ui.server.registrar;
import static com.google.common.truth.Truth.assertThat;
import static com.google.domain.registry.security.JsonHttpTestUtils.createJsonPayload;
import static com.google.domain.registry.testing.TaskQueueHelper.assertNoTasksEnqueued;
import static com.google.domain.registry.testing.TaskQueueHelper.assertTasksEnqueued;
import static com.google.domain.registry.util.ResourceUtils.readResourceUtf8;
import static java.util.Arrays.asList;
import static javax.servlet.http.HttpServletResponse.SC_OK;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import com.google.common.collect.ImmutableMap;
import com.google.domain.registry.export.sheet.SyncRegistrarsSheetAction;
import com.google.domain.registry.model.registrar.Registrar;
import com.google.domain.registry.testing.TaskQueueHelper.TaskMatcher;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.runners.MockitoJUnitRunner;
import javax.mail.internet.InternetAddress;
/** Tests for {@link RegistrarServlet}. */
@RunWith(MockitoJUnitRunner.class)
public class RegistrarServletTest extends RegistrarServletTestCase {
@Test
public void testSuccess_updateRegistrarInfo_andSendsNotificationEmail() throws Exception {
String jsonPostData = readResourceUtf8(getClass(), "testdata/update_registrar.json");
String expectedEmailBody = readResourceUtf8(getClass(), "testdata/update_registrar_email.txt");
when(req.getReader()).thenReturn(createJsonPayload(jsonPostData));
servlet.service(req, rsp);
verify(rsp).setStatus(SC_OK);
verify(emailService).createMessage();
verify(emailService).sendMessage(message);
assertThat(message.getAllRecipients()).asList().containsExactly(
new InternetAddress("notification@test.example"),
new InternetAddress("notification2@test.example"));
assertThat(message.getContent()).isEqualTo(expectedEmailBody);
assertTasksEnqueued("sheet", new TaskMatcher()
.url(SyncRegistrarsSheetAction.PATH)
.method("GET")
.header("Host", "backend.hostname"));
}
@Test
public void testFailure_updateRegistrarInfo_duplicateContacts() throws Exception {
String jsonPostData =
readResourceUtf8(getClass(), "testdata/update_registrar_duplicate_contacts.json");
when(req.getReader()).thenReturn(createJsonPayload(jsonPostData));
servlet.service(req, rsp);
assertThat(json.get()).containsEntry("status", "ERROR");
assertThat((String) json.get().get("message")).startsWith("One email address");
}
@Test
public void testRead_missingXsrfToken_failure() throws Exception {
when(req.getHeader(eq("X-CSRF-Token"))).thenReturn("");
servlet.service(req, rsp);
verify(rsp).sendError(403, "Invalid X-CSRF-Token");
assertNoTasksEnqueued("sheet");
}
@Test
public void testRead_invalidXsrfToken_failure() throws Exception {
when(req.getHeader(eq("X-CSRF-Token"))).thenReturn("humbug");
servlet.service(req, rsp);
verify(rsp).sendError(403, "Invalid X-CSRF-Token");
assertNoTasksEnqueued("sheet");
}
@Test
public void testRead_notLoggedIn_failure() throws Exception {
when(sessionUtils.isLoggedIn()).thenReturn(false);
servlet.service(req, rsp);
assertThat(json.get()).containsEntry("status", "ERROR");
assertThat(json.get()).containsEntry("message", "Not logged in");
assertNoTasksEnqueued("sheet");
}
@Test
public void testRead_notAuthorized_failure() throws Exception {
when(sessionUtils.checkRegistrarConsoleLogin(req)).thenReturn(false);
servlet.service(req, rsp);
assertThat(json.get()).containsEntry("status", "ERROR");
assertThat((String) json.get().get("message")).startsWith("Not authorized");
assertNoTasksEnqueued("sheet");
}
@Test
public void testRead_emptyPayload_failure() throws Exception {
when(req.getReader()).thenReturn(createJsonPayload(""));
servlet.service(req, rsp);
verify(rsp).sendError(400, "Malformed JSON");
assertNoTasksEnqueued("sheet");
}
/**
* This is the default read test for the registrar settings servlets.
*/
@Test
public void testRead_authorized_returnsRegistrarJson() throws Exception {
servlet.service(req, rsp);
assertThat(json.get()).containsEntry("status", "SUCCESS");
assertThat(json.get()).containsEntry("results", asList(
Registrar.loadByClientId(CLIENT_ID).toJsonMap()));
}
@Test
public void testRead_authorized_nilClientId_failure() throws Exception {
String nilClientId = "doesnotexist";
when(sessionUtils.getRegistrarClientId(req)).thenReturn(nilClientId);
servlet.service(req, rsp);
verify(rsp).sendError(404, "No registrar exists with the given client id: " + nilClientId);
}
@Test
public void testUpdate_emptyJsonObject_errorEmailFieldRequired() throws Exception {
when(req.getReader()).thenReturn(createJsonPayload(ImmutableMap.of(
"op", "update",
"args", ImmutableMap.of())));
servlet.service(req, rsp);
assertThat(json.get()).containsEntry("status", "ERROR");
assertThat(json.get()).containsEntry("field", "emailAddress");
assertThat(json.get()).containsEntry("message", "This field is required.");
assertNoTasksEnqueued("sheet");
}
@Test
public void testUpdate_badEmail_errorEmailField() throws Exception {
when(req.getReader()).thenReturn(createJsonPayload(ImmutableMap.of(
"op", "update",
"args", ImmutableMap.of(
"emailAddress", "lolcat"))));
servlet.service(req, rsp);
assertThat(json.get()).containsEntry("status", "ERROR");
assertThat(json.get()).containsEntry("field", "emailAddress");
assertThat(json.get()).containsEntry("message", "Please enter a valid email address.");
assertNoTasksEnqueued("sheet");
}
@Test
public void testPost_nonAsciiCharacters_getsAngry() throws Exception {
when(req.getReader()).thenReturn(createJsonPayload(ImmutableMap.of(
"op", "update",
"args", ImmutableMap.of(
"emailAddress", "ヘ(◕。◕ヘ)@example.com"))));
servlet.service(req, rsp);
assertThat(json.get()).containsEntry("status", "ERROR");
assertThat(json.get()).containsEntry("field", "emailAddress");
assertThat(json.get()).containsEntry("message", "Please only use ASCII-US characters.");
assertNoTasksEnqueued("sheet");
}
}

View file

@ -0,0 +1,112 @@
// 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 com.google.domain.registry.ui.server.registrar;
import static com.google.domain.registry.security.JsonHttpTestUtils.createJsonPayload;
import static com.google.domain.registry.security.JsonHttpTestUtils.createJsonResponseSupplier;
import static com.google.domain.registry.security.XsrfTokenManager.generateToken;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.when;
import com.google.appengine.api.modules.ModulesService;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMap;
import com.google.domain.registry.export.sheet.SyncRegistrarsSheetAction;
import com.google.domain.registry.model.ofy.Ofy;
import com.google.domain.registry.testing.AppEngineRule;
import com.google.domain.registry.testing.ExceptionRule;
import com.google.domain.registry.testing.FakeClock;
import com.google.domain.registry.testing.InjectRule;
import com.google.domain.registry.util.SendEmailService;
import com.google.domain.registry.util.SendEmailUtils;
import org.joda.time.DateTime;
import org.junit.Before;
import org.junit.Rule;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Map;
import java.util.Properties;
import javax.mail.Message;
import javax.mail.Session;
import javax.mail.internet.MimeMessage;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/** Base class for tests using {@link RegistrarServlet}. */
@RunWith(MockitoJUnitRunner.class)
public class RegistrarServletTestCase {
static final String CLIENT_ID = "TheRegistrar";
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.withTaskQueue()
.build();
@Rule
public final InjectRule inject = new InjectRule();
@Rule
public final ExceptionRule thrown = new ExceptionRule();
@Mock
HttpServletRequest req;
@Mock
HttpServletResponse rsp;
@Mock
SessionUtils sessionUtils;
@Mock
SendEmailService emailService;
@Mock
ModulesService modulesService;
Message message;
final RegistrarServlet servlet = new RegistrarServlet();
final StringWriter writer = new StringWriter();
final Supplier<Map<String, Object>> json = createJsonResponseSupplier(writer);
final FakeClock clock = new FakeClock(DateTime.parse("2014-01-01T00:00:00Z"));
@Before
public void setUp() throws Exception {
inject.setStaticField(Ofy.class, "clock", clock);
inject.setStaticField(ResourceServlet.class, "sessionUtils", sessionUtils);
inject.setStaticField(SendEmailUtils.class, "emailService", emailService);
inject.setStaticField(SyncRegistrarsSheetAction.class, "modulesService", modulesService);
message = new MimeMessage(Session.getDefaultInstance(new Properties(), null));
when(emailService.createMessage()).thenReturn(message);
when(req.getMethod()).thenReturn("POST");
when(rsp.getWriter()).thenReturn(new PrintWriter(writer));
when(req.getContentType()).thenReturn("application/json");
when(req.getHeader(eq("X-CSRF-Token"))).thenReturn(generateToken("console"));
when(req.getReader()).thenReturn(createJsonPayload(ImmutableMap.of("op", "read")));
when(sessionUtils.isLoggedIn()).thenReturn(true);
when(sessionUtils.redirectIfNotLoggedIn(req, rsp)).thenReturn(true);
when(sessionUtils.checkRegistrarConsoleLogin(req)).thenReturn(true);
when(sessionUtils.getRegistrarClientId(req)).thenReturn(CLIENT_ID);
when(modulesService.getVersionHostname("backend", null)).thenReturn("backend.hostname");
}
}

View file

@ -0,0 +1,148 @@
// 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 com.google.domain.registry.ui.server.registrar;
import static com.google.common.truth.Truth.assertThat;
import static com.google.domain.registry.security.JsonHttpTestUtils.createJsonPayload;
import static com.google.domain.registry.testing.CertificateSamples.SAMPLE_CERT;
import static com.google.domain.registry.testing.CertificateSamples.SAMPLE_CERT2;
import static com.google.domain.registry.testing.CertificateSamples.SAMPLE_CERT2_HASH;
import static com.google.domain.registry.testing.CertificateSamples.SAMPLE_CERT_HASH;
import static com.google.domain.registry.testing.DatastoreHelper.persistResource;
import static com.google.domain.registry.util.DateTimeUtils.START_OF_TIME;
import static java.util.Arrays.asList;
import static org.mockito.Mockito.when;
import com.google.common.collect.ImmutableMap;
import com.google.domain.registry.config.RegistryEnvironment;
import com.google.domain.registry.model.registrar.Registrar;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.runners.MockitoJUnitRunner;
import java.util.Map;
/**
* Unit tests for security_settings.js use of {@link RegistrarServlet}.
*
* <p>The default read and session validation tests are handled by the
* superclass.
*/
@RunWith(MockitoJUnitRunner.class)
public class SecuritySettingsTest extends RegistrarServletTestCase {
@Test
public void testPost_updateCert_success() throws Exception {
Registrar modified = Registrar.loadByClientId(CLIENT_ID).asBuilder()
.setClientCertificate(SAMPLE_CERT, clock.nowUtc())
.build();
when(req.getReader()).thenReturn(createJsonPayload(ImmutableMap.of(
"op", "update",
"args", modified.toJsonMap())));
servlet.service(req, rsp);
// Empty whoisServer and referralUrl fields should be set to defaults by server.
modified = modified.asBuilder()
.setWhoisServer(RegistryEnvironment.get().config().getRegistrarDefaultWhoisServer())
.setReferralUrl(
RegistryEnvironment.get().config().getRegistrarDefaultReferralUrl().toString())
.build();
assertThat(json.get()).containsEntry("status", "SUCCESS");
assertThat(json.get()).containsEntry("results", asList(modified.toJsonMap()));
assertThat(Registrar.loadByClientId(CLIENT_ID)).isEqualTo(modified);
}
@Test
public void testPost_updateCert_failure() throws Exception {
Map<String, Object> reqJson = Registrar.loadByClientId(CLIENT_ID).toJsonMap();
reqJson.put("clientCertificate", "BLAH");
when(req.getReader()).thenReturn(createJsonPayload(ImmutableMap.of(
"op", "update",
"args", reqJson)));
servlet.service(req, rsp);
assertThat(json.get()).containsEntry("status", "ERROR");
assertThat(json.get()).containsEntry("message", "Invalid X.509 PEM certificate");
}
@Test
public void testChangeCertificates() throws Exception {
Map<String, Object> jsonMap = Registrar.loadByClientId(CLIENT_ID).toJsonMap();
jsonMap.put("clientCertificate", SAMPLE_CERT);
jsonMap.put("failoverClientCertificate", null);
when(req.getReader()).thenReturn(
createJsonPayload(ImmutableMap.of("op", "update", "args", jsonMap)));
servlet.service(req, rsp);
assertThat(json.get()).containsEntry("status", "SUCCESS");
Registrar registrar = Registrar.loadByClientId(CLIENT_ID);
assertThat(registrar.getClientCertificate()).isEqualTo(SAMPLE_CERT);
assertThat(registrar.getClientCertificateHash()).isEqualTo(SAMPLE_CERT_HASH);
assertThat(registrar.getFailoverClientCertificate()).isNull();
assertThat(registrar.getFailoverClientCertificateHash()).isNull();
}
@Test
public void testChangeFailoverCertificate() throws Exception {
Map<String, Object> jsonMap = Registrar.loadByClientId(CLIENT_ID).toJsonMap();
jsonMap.put("failoverClientCertificate", SAMPLE_CERT2);
when(req.getReader()).thenReturn(
createJsonPayload(ImmutableMap.of("op", "update", "args", jsonMap)));
servlet.service(req, rsp);
assertThat(json.get()).containsEntry("status", "SUCCESS");
Registrar registrar = Registrar.loadByClientId(CLIENT_ID);
assertThat(registrar.getFailoverClientCertificate()).isEqualTo(SAMPLE_CERT2);
assertThat(registrar.getFailoverClientCertificateHash()).isEqualTo(SAMPLE_CERT2_HASH);
}
@Test
public void testEmptyOrNullCertificate_doesNotClearOutCurrentOne() throws Exception {
persistResource(
Registrar.loadByClientId(CLIENT_ID).asBuilder()
.setClientCertificate(SAMPLE_CERT, START_OF_TIME)
.setFailoverClientCertificate(SAMPLE_CERT2, START_OF_TIME)
.build());
Map<String, Object> jsonMap = Registrar.loadByClientId(CLIENT_ID).toJsonMap();
jsonMap.put("clientCertificate", null);
jsonMap.put("failoverClientCertificate", "");
when(req.getReader()).thenReturn(
createJsonPayload(ImmutableMap.of("op", "update", "args", jsonMap)));
servlet.service(req, rsp);
assertThat(json.get()).containsEntry("status", "SUCCESS");
Registrar registrar = Registrar.loadByClientId(CLIENT_ID);
assertThat(registrar.getClientCertificate()).isEqualTo(SAMPLE_CERT);
assertThat(registrar.getClientCertificateHash()).isEqualTo(SAMPLE_CERT_HASH);
assertThat(registrar.getFailoverClientCertificate()).isEqualTo(SAMPLE_CERT2);
assertThat(registrar.getFailoverClientCertificateHash()).isEqualTo(SAMPLE_CERT2_HASH);
}
@Test
public void testToJsonMap_containsCertificate() throws Exception {
Map<String, Object> jsonMap = Registrar.loadByClientId(CLIENT_ID).asBuilder()
.setClientCertificate(SAMPLE_CERT2, START_OF_TIME)
.build()
.toJsonMap();
assertThat(jsonMap).containsEntry("clientCertificate", SAMPLE_CERT2);
assertThat(jsonMap).containsEntry("clientCertificateHash", SAMPLE_CERT2_HASH);
}
@Test
public void testToJsonMap_containsFailoverCertificate() throws Exception {
Map<String, Object> jsonMap = Registrar.loadByClientId(CLIENT_ID).asBuilder()
.setFailoverClientCertificate(SAMPLE_CERT2, START_OF_TIME)
.build()
.toJsonMap();
assertThat(jsonMap).containsEntry("failoverClientCertificate", SAMPLE_CERT2);
assertThat(jsonMap).containsEntry("failoverClientCertificateHash", SAMPLE_CERT2_HASH);
}
}

View file

@ -0,0 +1,146 @@
// 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 com.google.domain.registry.ui.server.registrar;
import static com.google.common.truth.Truth.assertThat;
import static com.google.domain.registry.testing.AppEngineRule.THE_REGISTRAR_GAE_USER_ID;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.common.testing.NullPointerTester;
import com.google.domain.registry.model.registrar.Registrar;
import com.google.domain.registry.model.registrar.RegistrarContact;
import com.google.domain.registry.testing.AppEngineRule;
import com.google.domain.registry.testing.ExceptionRule;
import com.google.domain.registry.testing.InjectRule;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/** Unit tests for {@link SessionUtils}. */
@RunWith(MockitoJUnitRunner.class)
public class SessionUtilsTest {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.build();
@Rule
public final ExceptionRule thrown = new ExceptionRule();
@Rule
public final InjectRule inject = new InjectRule();
@Mock
private UserService userService;
@Mock
private HttpServletRequest req;
@Mock
private HttpServletResponse rsp;
@Mock
private HttpSession session;
private SessionUtils sessionUtils;
private final User jart = new User("jart@google.com", "google.com", THE_REGISTRAR_GAE_USER_ID);
private final User bozo = new User("bozo@bing.com", "bing.com", "badGaeUserId");
@Before
public void before() throws Exception {
sessionUtils = new SessionUtils(userService);
when(req.getSession()).thenReturn(session);
}
@Test
public void testRedirectIfNotLoggedIn_loggedIn_doesNothing() throws Exception {
when(userService.isUserLoggedIn()).thenReturn(true);
assertThat(sessionUtils.redirectIfNotLoggedIn(req, rsp)).isTrue();
verifyZeroInteractions(req, rsp);
}
@Test
public void testRedirectIfNotLoggedIn_notLoggedIn_sendsTemporaryRedirect() throws Exception {
when(userService.isUserLoggedIn()).thenReturn(false);
when(req.getRequestURI()).thenReturn("foo");
when(userService.createLoginURL(eq("foo"))).thenReturn("bar");
assertThat(sessionUtils.redirectIfNotLoggedIn(req, rsp)).isFalse();
verify(rsp).setStatus(eq(302));
verify(rsp).setHeader(eq("Location"), eq("bar"));
verifyNoMoreInteractions(rsp);
}
@Test
public void testCheckRegistrarConsoleLogin_authedButNoSession_createsSession() throws Exception {
when(userService.getCurrentUser()).thenReturn(jart);
assertThat(sessionUtils.checkRegistrarConsoleLogin(req)).isTrue();
verify(session).setAttribute(eq("clientId"), eq("TheRegistrar"));
}
@Test
public void testCheckRegistrarConsoleLogin_authedWithValidSession_doesNothing() throws Exception {
when(session.getAttribute("clientId")).thenReturn("TheRegistrar");
when(userService.getCurrentUser()).thenReturn(jart);
assertThat(sessionUtils.checkRegistrarConsoleLogin(req)).isTrue();
verify(session).getAttribute("clientId");
verifyNoMoreInteractions(session);
}
@Test
public void testCheckRegistrarConsoleLogin_sessionRevoked_invalidates() throws Exception {
RegistrarContact.updateContacts(
Registrar.loadByClientId("TheRegistrar"),
new java.util.HashSet<RegistrarContact>());
when(session.getAttribute("clientId")).thenReturn("TheRegistrar");
when(userService.getCurrentUser()).thenReturn(jart);
assertThat(sessionUtils.checkRegistrarConsoleLogin(req)).isFalse();
verify(session).invalidate();
}
@Test
public void testCheckRegistrarConsoleLogin_notLoggedIn_throwsIse() throws Exception {
thrown.expect(IllegalStateException.class);
assertThat(sessionUtils.checkRegistrarConsoleLogin(req)).isNull();
}
@Test
public void testCheckRegistrarConsoleLogin_notAllowed_returnsFalse() throws Exception {
when(userService.getCurrentUser()).thenReturn(bozo);
assertThat(sessionUtils.checkRegistrarConsoleLogin(req)).isFalse();
}
@Test
public void testNullness() throws Exception {
new NullPointerTester()
.setDefault(HttpServletRequest.class, req)
.setDefault(HttpServletResponse.class, rsp)
.testAllPublicStaticMethods(SessionUtils.class);
}
}

View file

@ -0,0 +1,128 @@
// 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 com.google.domain.registry.ui.server.registrar;
import static com.google.common.base.Strings.repeat;
import static com.google.common.truth.Truth.assertThat;
import static com.google.domain.registry.security.JsonHttpTestUtils.createJsonPayload;
import static java.util.Arrays.asList;
import static org.mockito.Mockito.when;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.domain.registry.model.registrar.Registrar;
import com.google.domain.registry.model.registrar.RegistrarAddress;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.runners.MockitoJUnitRunner;
/**
* Unit tests for security_settings.js use of {@link RegistrarServlet}.
*
* <p>The default read and session validation tests are handled by the superclass.
*/
@RunWith(MockitoJUnitRunner.class)
public class WhoisSettingsTest extends RegistrarServletTestCase {
@Test
public void testPost_update_success() throws Exception {
Registrar modified = Registrar.loadByClientId(CLIENT_ID).asBuilder()
.setEmailAddress("hello.kitty@example.com")
.setPhoneNumber("+1.2125650000")
.setFaxNumber("+1.2125650001")
.setReferralUrl("http://acme.com/")
.setWhoisServer("ns1.foo.bar")
.setLocalizedAddress(new RegistrarAddress.Builder()
.setStreet(ImmutableList.of("76 Ninth Avenue", "Eleventh Floor"))
.setCity("New York")
.setState("NY")
.setZip("10009")
.setCountryCode("US")
.build())
.build();
when(req.getReader()).thenReturn(createJsonPayload(ImmutableMap.of(
"op", "update",
"args", modified.toJsonMap())));
servlet.service(req, rsp);
assertThat(json.get().get("status")).isEqualTo("SUCCESS");
assertThat(json.get().get("results")).isEqualTo(asList(modified.toJsonMap()));
assertThat(Registrar.loadByClientId(CLIENT_ID)).isEqualTo(modified);
}
@Test
public void testPost_badUsStateCode_returnsFormFieldError() throws Exception {
Registrar modified = Registrar.loadByClientId(CLIENT_ID).asBuilder()
.setEmailAddress("hello.kitty@example.com")
.setPhoneNumber("+1.2125650000")
.setFaxNumber("+1.2125650001")
.setLocalizedAddress(new RegistrarAddress.Builder()
.setStreet(ImmutableList.of("76 Ninth Avenue", "Eleventh Floor"))
.setCity("New York")
.setState("ZZ")
.setZip("10009")
.setCountryCode("US")
.build())
.build();
when(req.getReader()).thenReturn(createJsonPayload(ImmutableMap.of(
"op", "update",
"args", modified.toJsonMap())));
servlet.service(req, rsp);
assertThat(json.get().get("status")).isEqualTo("ERROR");
assertThat(json.get().get("field")).isEqualTo("localizedAddress.state");
assertThat(json.get().get("message")).isEqualTo("Unknown US state code.");
assertThat(Registrar.loadByClientId(CLIENT_ID)).isNotEqualTo(modified);
}
@Test
public void testPost_badAddress_returnsFormFieldError() throws Exception {
Registrar modified = Registrar.loadByClientId(CLIENT_ID).asBuilder()
.setEmailAddress("hello.kitty@example.com")
.setPhoneNumber("+1.2125650000")
.setFaxNumber("+1.2125650001")
.setLocalizedAddress(new RegistrarAddress.Builder()
.setStreet(ImmutableList.of("76 Ninth Avenue", repeat("lol", 200)))
.setCity("New York")
.setState("NY")
.setZip("10009")
.setCountryCode("US")
.build())
.build();
when(req.getReader()).thenReturn(createJsonPayload(ImmutableMap.of(
"op", "update",
"args", modified.toJsonMap())));
servlet.service(req, rsp);
assertThat(json.get().get("status")).isEqualTo("ERROR");
assertThat(json.get().get("field")).isEqualTo("localizedAddress.street[1]");
assertThat((String) json.get().get("message"))
.contains("Number of characters (600) not in range");
assertThat(Registrar.loadByClientId(CLIENT_ID)).isNotEqualTo(modified);
}
@Test
public void testPost_badWhoisServer_returnsFormFieldError() throws Exception {
Registrar modified = Registrar.loadByClientId(CLIENT_ID).asBuilder()
.setWhoisServer("tears@dry.tragical.lol")
.build();
when(req.getReader()).thenReturn(createJsonPayload(ImmutableMap.of(
"op", "update",
"args", modified.toJsonMap())));
servlet.service(req, rsp);
assertThat(json.get().get("status")).isEqualTo("ERROR");
assertThat(json.get().get("field")).isEqualTo("whoisServer");
assertThat(json.get().get("message")).isEqualTo("Not a valid hostname.");
assertThat(Registrar.loadByClientId(CLIENT_ID)).isNotEqualTo(modified);
}
}

View file

@ -0,0 +1,59 @@
{
"op": "update",
"args": {
"clientIdentifier": "theregistrar",
"driveFolderId": null,
"registrarName": "The Registrar",
"lastUpdateTime": "2015-01-22T17:27:36.999Z",
"state": "ACTIVE",
"type": "REAL",
"contacts": [
{
"visibleInWhoisAsAdmin": true,
"faxNumber": null,
"phoneNumber": null,
"name": "Extra Terrestrial",
"visibleInWhoisAsTech": false,
"emailAddress": "etphonehome@example.com",
"gaeUserId": null,
"types": "ADMIN,BILLING,TECH,WHOIS"
}
],
"allowedTlds": [
"ga"
],
"clientCertificateHash": null,
"faxNumber": "",
"ianaIdentifier": "1",
"phoneNumber": "+1.2223335555",
"internationalizedAddress": null,
"whoisServer": "foo.bar.baz",
"creationTime": "2014-04-15T21:57:54.765Z",
"clientCertificate": null,
"emailAddress": "thase@the.registrar",
"ipAddressWhitelist": [
"1.1.1.1\/32",
"2.2.2.2\/32",
"4.4.4.4\/32"
],
"localizedAddress": {
"street": [
"123 Street Rd",
"Ste 156",
""
],
"city": "New York",
"state": "NY",
"zip": "10011",
"countryCode": "US"
},
"billingIdentifier": null,
"url": null,
"icannReferralEmail": "asdf@asdf.com",
"phonePasscode": null,
"referralUrl": "",
"blockPremiumNames": false,
"lastCertificateUpdateTime": null,
"e": false
}
}

View file

@ -0,0 +1,69 @@
{
"op": "update",
"args": {
"clientIdentifier": "theregistrar",
"driveFolderId": null,
"registrarName": "The Registrar",
"lastUpdateTime": "2015-01-22T17:27:36.999Z",
"state": "ACTIVE",
"type": "REAL",
"contacts": [
{
"visibleInWhoisAsAdmin": true,
"faxNumber": null,
"phoneNumber": null,
"name": "Extra Terrestrial",
"visibleInWhoisAsTech": false,
"emailAddress": "etphonehome@example.com",
"gaeUserId": null,
"types": "ADMIN,BILLING,TECH,WHOIS"
},
{
"visibleInWhoisAsAdmin": true,
"faxNumber": null,
"phoneNumber": null,
"name": "E.T.",
"visibleInWhoisAsTech": false,
"emailAddress": "etphonehome@example.com",
"gaeUserId": null,
"types": "MARKETING"
}
],
"allowedTlds": [
"ga"
],
"clientCertificateHash": null,
"faxNumber": "",
"ianaIdentifier": "1",
"phoneNumber": "+1.2223335555",
"internationalizedAddress": null,
"whoisServer": "foo.bar.baz",
"creationTime": "2014-04-15T21:57:54.765Z",
"clientCertificate": null,
"emailAddress": "thase@the.registrar",
"ipAddressWhitelist": [
"1.1.1.1\/32",
"2.2.2.2\/32",
"4.4.4.4\/32"
],
"localizedAddress": {
"street": [
"123 Street Rd",
"Ste 156",
""
],
"city": "New York",
"state": "NY",
"zip": "10011",
"countryCode": "US"
},
"billingIdentifier": null,
"url": null,
"icannReferralEmail": "asdf@asdf.com",
"phonePasscode": null,
"referralUrl": "",
"blockPremiumNames": false,
"lastCertificateUpdateTime": null,
"e": false
}
}

View file

@ -0,0 +1,16 @@
The following changes were made to the registrar:
whoisServer -> [null, foo.bar.baz]
ipAddressWhitelist -> [null, [1.1.1.1/32, 2.2.2.2/32, 4.4.4.4/32]]
localizedAddress.street.0 -> [123 Example Bőulevard, 123 Street Rd]
localizedAddress.street.1 -> [null, Ste 156]
localizedAddress.city -> [Williamsburg, New York]
localizedAddress.zip -> [11211, 10011]
phoneNumber -> [+1.2223334444, +1.2223335555]
emailAddress -> [new.registrar@example.com, thase@the.registrar]
contacts ->
ADDED:
{parent=Key<?>(EntityGroupRoot("cross-tld")/Registrar("TheRegistrar")), name=Extra Terrestrial, emailAddress=etphonehome@example.com, phoneNumber=null, faxNumber=null, types=[ADMIN, BILLING, TECH, WHOIS], gaeUserId=null, visibleInWhoisAsAdmin=true, visibleInWhoisAsTech=false}
REMOVED:
{parent=Key<?>(EntityGroupRoot("cross-tld")/Registrar("TheRegistrar")), name=John Doe, emailAddress=johndoe@theregistrar.com, phoneNumber=+1.1234567890, faxNumber=null, types=[ADMIN], gaeUserId=31337, visibleInWhoisAsAdmin=false, visibleInWhoisAsTech=false}
FINAL CONTENTS:
{parent=Key<?>(EntityGroupRoot("cross-tld")/Registrar("TheRegistrar")), name=Extra Terrestrial, emailAddress=etphonehome@example.com, phoneNumber=null, faxNumber=null, types=[ADMIN, BILLING, TECH, WHOIS], gaeUserId=null, visibleInWhoisAsAdmin=true, visibleInWhoisAsTech=false}