diff --git a/java/google/registry/flows/domain/DomainTransferRequestFlow.java b/java/google/registry/flows/domain/DomainTransferRequestFlow.java index 22a9ebe51..1e3c408d7 100644 --- a/java/google/registry/flows/domain/DomainTransferRequestFlow.java +++ b/java/google/registry/flows/domain/DomainTransferRequestFlow.java @@ -32,7 +32,6 @@ import static google.registry.flows.domain.DomainFlowUtils.verifyUnitIsYears; import static google.registry.model.domain.DomainResource.extendRegistrationWithCap; import static google.registry.model.eppoutput.Result.Code.SUCCESS_WITH_ACTION_PENDING; import static google.registry.model.ofy.ObjectifyService.ofy; -import static google.registry.pricing.PricingEngineProxy.getDomainRenewCost; import static google.registry.util.DateTimeUtils.END_OF_TIME; import com.google.common.base.Optional; @@ -45,6 +44,7 @@ import google.registry.flows.FlowModule.ClientId; import google.registry.flows.FlowModule.Superuser; import google.registry.flows.FlowModule.TargetId; import google.registry.flows.TransactionalFlow; +import google.registry.flows.domain.DomainPricingLogic.FeesAndCredits; import google.registry.flows.exceptions.AlreadyPendingTransferException; import google.registry.flows.exceptions.ObjectAlreadySponsoredException; import google.registry.model.billing.BillingEvent; @@ -53,8 +53,6 @@ import google.registry.model.billing.BillingEvent.Reason; import google.registry.model.domain.DomainCommand.Transfer; import google.registry.model.domain.DomainResource; import google.registry.model.domain.Period; -import google.registry.model.domain.fee.BaseFee.FeeType; -import google.registry.model.domain.fee.Fee; import google.registry.model.domain.fee.FeeTransferCommandExtension; import google.registry.model.domain.fee.FeeTransformResponseExtension; import google.registry.model.domain.flags.FlagsTransferCommandExtension; @@ -125,6 +123,7 @@ public final class DomainTransferRequestFlow implements TransactionalFlow { @Inject HistoryEntry.Builder historyBuilder; @Inject Trid trid; @Inject EppResponse.Builder responseBuilder; + @Inject DomainPricingLogic pricingLogic; @Inject DomainTransferRequestFlow() {} @Override @@ -142,12 +141,11 @@ public final class DomainTransferRequestFlow implements TransactionalFlow { verifyTransferAllowed(existingDomain, period, now); String tld = existingDomain.getTld(); Registry registry = Registry.get(tld); - // The cost of the renewal implied by a transfer. - Money renewCost = getDomainRenewCost(targetId, now, years); // An optional extension from the client specifying what they think the transfer should cost. FeeTransferCommandExtension feeTransfer = eppInput.getSingleExtension(FeeTransferCommandExtension.class); - validateFeeChallenge(targetId, tld, now, feeTransfer, renewCost); + FeesAndCredits feesAndCredits = pricingLogic.getTransferPrice(registry, targetId, now, years); + validateFeeChallenge(targetId, tld, now, feeTransfer, feesAndCredits.getTotalCost()); HistoryEntry historyEntry = buildHistory(period, existingDomain, now); DateTime automaticTransferTime = now.plus(registry.getAutomaticTransferLength()); // The new expiration time if there is a server approval. @@ -160,7 +158,7 @@ public final class DomainTransferRequestFlow implements TransactionalFlow { serverApproveNewExpirationTime, historyEntry, existingDomain, - renewCost, + feesAndCredits.getTotalCost(), years, now); // Create the transfer data that represents the pending transfer. @@ -189,7 +187,7 @@ public final class DomainTransferRequestFlow implements TransactionalFlow { return responseBuilder .setResultFromCode(SUCCESS_WITH_ACTION_PENDING) .setResData(createResponse(period, existingDomain, newDomain, now)) - .setExtensions(createResponseExtensions(renewCost, feeTransfer)) + .setExtensions(createResponseExtensions(feesAndCredits, feeTransfer)) .build(); } @@ -241,7 +239,7 @@ public final class DomainTransferRequestFlow implements TransactionalFlow { DateTime serverApproveNewExpirationTime, HistoryEntry historyEntry, DomainResource existingDomain, - Money renewCost, + Money transferCost, int years, DateTime now) { // Create a TransferData for the server-approve case to use for the speculative poll messages. @@ -252,7 +250,7 @@ public final class DomainTransferRequestFlow implements TransactionalFlow { Registry registry = Registry.get(existingDomain.getTld()); return new ImmutableSet.Builder() .add(createTransferBillingEvent( - automaticTransferTime, historyEntry, registry, renewCost, years)) + automaticTransferTime, historyEntry, registry, transferCost, years)) .addAll(createOptionalAutorenewCancellation( automaticTransferTime, historyEntry, existingDomain) .asSet()) @@ -271,13 +269,13 @@ public final class DomainTransferRequestFlow implements TransactionalFlow { DateTime automaticTransferTime, HistoryEntry historyEntry, Registry registry, - Money renewCost, + Money transferCost, int years) { return new BillingEvent.OneTime.Builder() .setReason(Reason.TRANSFER) .setTargetId(targetId) .setClientId(gainingClientId) - .setCost(renewCost) + .setCost(transferCost) .setPeriodYears(years) .setEventTime(automaticTransferTime) .setBillingTime(automaticTransferTime.plus(registry.getTransferGracePeriodLength())) @@ -388,13 +386,14 @@ public final class DomainTransferRequestFlow implements TransactionalFlow { targetId, newDomain.getTransferData(), approveNowExtendedRegistrationTime); } - private ImmutableList createResponseExtensions(Money renewCost, - FeeTransferCommandExtension feeTransfer) { + private static ImmutableList createResponseExtensions( + FeesAndCredits feesAndCredits, FeeTransferCommandExtension feeTransfer) { return feeTransfer == null ? ImmutableList.of() : ImmutableList.of(feeTransfer.createResponseBuilder() - .setCurrency(renewCost.getCurrencyUnit()) - .setFees(ImmutableList.of(Fee.create(renewCost.getAmount(), FeeType.RENEW))) + .setFees(feesAndCredits.getFees()) + .setCredits(feesAndCredits.getCredits()) + .setCurrency(feesAndCredits.getCurrency()) .build()); } } diff --git a/java/google/registry/model/domain/fee/BaseFee.java b/java/google/registry/model/domain/fee/BaseFee.java index a065b2b9c..825fc4338 100644 --- a/java/google/registry/model/domain/fee/BaseFee.java +++ b/java/google/registry/model/domain/fee/BaseFee.java @@ -48,6 +48,14 @@ public abstract class BaseFee extends ImmutableObject { EAP("Early Access Period, fee expires: %s"), RENEW("renew"), RESTORE("restore"), + /** + * A transfer fee. + * + *

These are not used by the default system, in which the only fee associated with a transfer + * is the RENEW fee. These exist so that custom pricing logic can create a custom transfer fee + * if desired. + */ + TRANSFER("transfer"), UPDATE("update"), CREDIT("%s credit"); diff --git a/javatests/google/registry/flows/custom/TestDomainPricingCustomLogic.java b/javatests/google/registry/flows/custom/TestDomainPricingCustomLogic.java index c1fe704ec..708f562f9 100644 --- a/javatests/google/registry/flows/custom/TestDomainPricingCustomLogic.java +++ b/javatests/google/registry/flows/custom/TestDomainPricingCustomLogic.java @@ -42,27 +42,6 @@ public class TestDomainPricingCustomLogic extends DomainPricingCustomLogic { super(eppInput, sessionMetadata); } - private static BaseFee domainNameToFeeOrCredit(InternetDomainName domainName) { - // The second-level domain should be of the form "description-price", where description is the - // description string of the fee or credit, and price is the price (credit if negative, fee - // otherwise). To make sure this is a valid domain name, don't use any spaces, and limit prices - // to integers. Don't use a two-character description for credits, since it is illegal to have - // both the third and fourth characters of a domain name label be hyphens. - List components = - Splitter.on('-') - .limit(2) - .splitToList(Iterables.getFirst(Splitter.on('.').split(domainName.toString()), "")); - checkArgument(components.size() == 2, "Domain name must be of the form description-price.tld"); - int price = Integer.parseInt(components.get(1)); - if (price < 0) { - return Credit.create( - new BigDecimal(price), FeeType.valueOf(Ascii.toUpperCase(components.get(0)))); - } else { - return Fee.create( - new BigDecimal(price), FeeType.valueOf(Ascii.toUpperCase(components.get(0)))); - } - } - @Override public FeesAndCredits customizeCreatePrice(CreatePriceParameters priceParameters) throws EppException { @@ -85,53 +64,68 @@ public class TestDomainPricingCustomLogic extends DomainPricingCustomLogic { @Override public FeesAndCredits customizeApplicationUpdatePrice( ApplicationUpdatePriceParameters priceParameters) throws EppException { - if (priceParameters - .domainApplication() - .getFullyQualifiedDomainName() - .startsWith("non-free-update")) { - FeesAndCredits feesAndCredits = priceParameters.feesAndCredits(); - List newFeesAndCredits = - new ImmutableList.Builder() - .addAll(feesAndCredits.getFeesAndCredits()) - .add(Fee.create(BigDecimal.valueOf(100), FeeType.UPDATE)) - .build(); - return new FeesAndCredits( - feesAndCredits.getCurrency(), toArray(newFeesAndCredits, BaseFee.class)); - } else { - return priceParameters.feesAndCredits(); - } + return (priceParameters + .domainApplication() + .getFullyQualifiedDomainName() + .startsWith("non-free-update")) + ? addCustomFee( + priceParameters.feesAndCredits(), Fee.create(BigDecimal.valueOf(100), FeeType.UPDATE)) + : priceParameters.feesAndCredits(); } @Override public FeesAndCredits customizeRenewPrice(RenewPriceParameters priceParameters) throws EppException { - if (priceParameters.domainName().toString().startsWith("costly-renew")) { - FeesAndCredits feesAndCredits = priceParameters.feesAndCredits(); - List newFeesAndCredits = - new ImmutableList.Builder() - .addAll(feesAndCredits.getFeesAndCredits()) - .add(Fee.create(BigDecimal.valueOf(100), FeeType.RENEW)) - .build(); - return new FeesAndCredits( - feesAndCredits.getCurrency(), toArray(newFeesAndCredits, BaseFee.class)); - } else { - return priceParameters.feesAndCredits(); - } + return (priceParameters.domainName().toString().startsWith("costly-renew")) + ? addCustomFee( + priceParameters.feesAndCredits(), Fee.create(BigDecimal.valueOf(100), FeeType.RENEW)) + : priceParameters.feesAndCredits(); + } + + @Override + public FeesAndCredits customizeTransferPrice(TransferPriceParameters priceParameters) + throws EppException { + return (priceParameters.domainName().toString().startsWith("expensive")) + ? addCustomFee( + priceParameters.feesAndCredits(), Fee.create(BigDecimal.valueOf(100), FeeType.TRANSFER)) + : priceParameters.feesAndCredits(); } @Override public FeesAndCredits customizeUpdatePrice(UpdatePriceParameters priceParameters) { - if (priceParameters.domainName().toString().startsWith("non-free-update")) { - FeesAndCredits feesAndCredits = priceParameters.feesAndCredits(); - List newFeesAndCredits = - new ImmutableList.Builder() - .addAll(feesAndCredits.getFeesAndCredits()) - .add(Fee.create(TEN, FeeType.UPDATE)) - .build(); - return new FeesAndCredits( - feesAndCredits.getCurrency(), toArray(newFeesAndCredits, BaseFee.class)); + return (priceParameters.domainName().toString().startsWith("non-free-update")) + ? addCustomFee(priceParameters.feesAndCredits(), Fee.create(TEN, FeeType.UPDATE)) + : priceParameters.feesAndCredits(); + } + + private static FeesAndCredits addCustomFee(FeesAndCredits feesAndCredits, BaseFee customFee) { + List newFeesAndCredits = + new ImmutableList.Builder() + .addAll(feesAndCredits.getFeesAndCredits()) + .add(customFee) + .build(); + return new FeesAndCredits( + feesAndCredits.getCurrency(), toArray(newFeesAndCredits, BaseFee.class)); + } + + private static BaseFee domainNameToFeeOrCredit(InternetDomainName domainName) { + // The second-level domain should be of the form "description-price", where description is the + // description string of the fee or credit, and price is the price (credit if negative, fee + // otherwise). To make sure this is a valid domain name, don't use any spaces, and limit prices + // to integers. Don't use a two-character description for credits, since it is illegal to have + // both the third and fourth characters of a domain name label be hyphens. + List components = + Splitter.on('-') + .limit(2) + .splitToList(Iterables.getFirst(Splitter.on('.').split(domainName.toString()), "")); + checkArgument(components.size() == 2, "Domain name must be of the form description-price.tld"); + int price = Integer.parseInt(components.get(1)); + if (price < 0) { + return Credit.create( + new BigDecimal(price), FeeType.valueOf(Ascii.toUpperCase(components.get(0)))); } else { - return priceParameters.feesAndCredits(); + return Fee.create( + new BigDecimal(price), FeeType.valueOf(Ascii.toUpperCase(components.get(0)))); } } } diff --git a/javatests/google/registry/flows/domain/DomainTransferApproveFlowTest.java b/javatests/google/registry/flows/domain/DomainTransferApproveFlowTest.java index 93d6d6096..ce886ef18 100644 --- a/javatests/google/registry/flows/domain/DomainTransferApproveFlowTest.java +++ b/javatests/google/registry/flows/domain/DomainTransferApproveFlowTest.java @@ -94,7 +94,7 @@ public class DomainTransferApproveFlowTest .build()); setClientIdForFlow("TheRegistrar"); createTld("extra"); - setupDomainWithPendingTransfer(); + setupDomainWithPendingTransfer("example", "tld"); clock.advanceOneMilli(); } @@ -278,7 +278,7 @@ public class DomainTransferApproveFlowTest .asBuilder() .setTransferGracePeriodLength(Duration.standardMinutes(10)) .build()); - setupDomainWithPendingTransfer("net"); + setupDomainWithPendingTransfer("example", "net"); doSuccessfulTest( "net", "domain_transfer_approve_net.xml", diff --git a/javatests/google/registry/flows/domain/DomainTransferCancelFlowTest.java b/javatests/google/registry/flows/domain/DomainTransferCancelFlowTest.java index 44432fa66..6443ba449 100644 --- a/javatests/google/registry/flows/domain/DomainTransferCancelFlowTest.java +++ b/javatests/google/registry/flows/domain/DomainTransferCancelFlowTest.java @@ -53,7 +53,7 @@ public class DomainTransferCancelFlowTest public void setUp() throws Exception { setEppInput("domain_transfer_cancel.xml"); setClientIdForFlow("NewRegistrar"); - setupDomainWithPendingTransfer(); + setupDomainWithPendingTransfer("example", "tld"); } private void doSuccessfulTest(String commandFilename, String expectedXmlFilename) diff --git a/javatests/google/registry/flows/domain/DomainTransferFlowTestCase.java b/javatests/google/registry/flows/domain/DomainTransferFlowTestCase.java index 4678a9aa0..5f24b888d 100644 --- a/javatests/google/registry/flows/domain/DomainTransferFlowTestCase.java +++ b/javatests/google/registry/flows/domain/DomainTransferFlowTestCase.java @@ -106,10 +106,6 @@ public class DomainTransferFlowTestCase TRANSFER_REQUEST_TIME); } - protected void setupDomain(String tld) throws Exception { - setupDomain("example", tld); - } - /** Adds a domain with no pending transfer on it. */ protected void setupDomain(String label, String tld) throws Exception { createTld(tld); @@ -230,14 +226,9 @@ public class DomainTransferFlowTestCase .hasCurrentSponsorClientId("TheRegistrar"); } - /** Adds a .tld domain that has a pending transfer on it from TheRegistrar to NewRegistrar. */ - protected void setupDomainWithPendingTransfer() throws Exception { - setupDomainWithPendingTransfer("tld"); - } - /** Adds a domain that has a pending transfer on it from TheRegistrar to NewRegistrar. */ - protected void setupDomainWithPendingTransfer(String tld) throws Exception { - setupDomain(tld); + protected void setupDomainWithPendingTransfer(String label, String tld) throws Exception { + setupDomain(label, tld); domain = persistWithPendingTransfer(domain); } diff --git a/javatests/google/registry/flows/domain/DomainTransferQueryFlowTest.java b/javatests/google/registry/flows/domain/DomainTransferQueryFlowTest.java index 07ebc2297..6b09f5b87 100644 --- a/javatests/google/registry/flows/domain/DomainTransferQueryFlowTest.java +++ b/javatests/google/registry/flows/domain/DomainTransferQueryFlowTest.java @@ -42,7 +42,7 @@ public class DomainTransferQueryFlowTest public void setUp() throws Exception { setEppInput("domain_transfer_query.xml"); setClientIdForFlow("NewRegistrar"); - setupDomainWithPendingTransfer(); + setupDomainWithPendingTransfer("example", "tld"); } private void doSuccessfulTest( diff --git a/javatests/google/registry/flows/domain/DomainTransferRejectFlowTest.java b/javatests/google/registry/flows/domain/DomainTransferRejectFlowTest.java index a952c4761..2f96f9bfc 100644 --- a/javatests/google/registry/flows/domain/DomainTransferRejectFlowTest.java +++ b/javatests/google/registry/flows/domain/DomainTransferRejectFlowTest.java @@ -55,7 +55,7 @@ public class DomainTransferRejectFlowTest public void setUp() throws Exception { setEppInput("domain_transfer_reject.xml"); setClientIdForFlow("TheRegistrar"); - setupDomainWithPendingTransfer(); + setupDomainWithPendingTransfer("example", "tld"); clock.advanceOneMilli(); } diff --git a/javatests/google/registry/flows/domain/DomainTransferRequestFlowTest.java b/javatests/google/registry/flows/domain/DomainTransferRequestFlowTest.java index 8a7743a23..4a442cc3e 100644 --- a/javatests/google/registry/flows/domain/DomainTransferRequestFlowTest.java +++ b/javatests/google/registry/flows/domain/DomainTransferRequestFlowTest.java @@ -18,10 +18,10 @@ import static com.google.common.truth.Truth.assertThat; import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.testing.DatastoreHelper.assertBillingEvents; import static google.registry.testing.DatastoreHelper.createTld; -import static google.registry.testing.DatastoreHelper.deleteResource; import static google.registry.testing.DatastoreHelper.getOnlyHistoryEntryOfType; import static google.registry.testing.DatastoreHelper.getOnlyPollMessage; import static google.registry.testing.DatastoreHelper.getPollMessages; +import static google.registry.testing.DatastoreHelper.persistActiveContact; import static google.registry.testing.DatastoreHelper.persistResource; import static google.registry.testing.DomainResourceSubject.assertAboutDomains; import static google.registry.testing.GenericEppResourceSubject.assertAboutEppResources; @@ -33,6 +33,7 @@ import static org.joda.money.CurrencyUnit.EUR; import static org.joda.money.CurrencyUnit.USD; import com.google.common.base.Function; +import com.google.common.base.Optional; import com.google.common.base.Predicates; import com.google.common.collect.FluentIterable; import com.google.common.collect.ImmutableMap; @@ -95,8 +96,6 @@ public class DomainTransferRequestFlowTest public void setUp() throws Exception { setEppInput("domain_transfer_request.xml"); setClientIdForFlow("NewRegistrar"); - setupDomain("tld"); - createTld("flags"); } private void assertTransferRequested(DomainResource domain) throws Exception { @@ -107,7 +106,7 @@ public class DomainTransferRequestFlowTest .hasTransferRequestClientTrid(getClientTrid()).and() .hasCurrentSponsorClientId("TheRegistrar").and() .hasPendingTransferExpirationTime( - clock.nowUtc().plus(Registry.get("tld").getAutomaticTransferLength())).and() + clock.nowUtc().plus(Registry.get(domain.getTld()).getAutomaticTransferLength())).and() .hasStatusValue(StatusValue.PENDING_TRANSFER); } @@ -118,7 +117,8 @@ public class DomainTransferRequestFlowTest } private void assertTransferApproved(DomainResource domain) { - DateTime afterAutoAck = clock.nowUtc().plus(Registry.get("tld").getAutomaticTransferLength()); + DateTime afterAutoAck = + clock.nowUtc().plus(Registry.get(domain.getTld()).getAutomaticTransferLength()); assertAboutDomains().that(domain) .hasTransferStatus(TransferStatus.SERVER_APPROVED).and() .hasCurrentSponsorClientId("NewRegistrar").and() @@ -128,7 +128,8 @@ public class DomainTransferRequestFlowTest } private void assertTransferApproved(HostResource host) { - DateTime afterAutoAck = clock.nowUtc().plus(Registry.get("tld").getAutomaticTransferLength()); + DateTime afterAutoAck = + clock.nowUtc().plus(Registry.get(domain.getTld()).getAutomaticTransferLength()); assertAboutHosts().that(host) .hasCurrentSponsorClientId("NewRegistrar").and() .hasLastTransferTime(afterAutoAck).and() @@ -145,6 +146,7 @@ public class DomainTransferRequestFlowTest String expectedXmlFilename, DateTime expectedExpirationTime, Map substitutions, + Optional transferCost, BillingEvent.Cancellation.Builder... extraExpectedBillingEvents) throws Exception { setEppInput(commandFilename, substitutions); ImmutableSet originalGracePeriods = domain.getGracePeriods(); @@ -153,8 +155,8 @@ public class DomainTransferRequestFlowTest // For all of the other transfer flow tests, 'now' corresponds to day 3 of the transfer, but // for the request test we want that same 'now' to be the initial request time, so we shift // the transfer timeline 3 days later by adjusting the implicit transfer time here. - DateTime implicitTransferTime = - clock.nowUtc().plus(Registry.get("tld").getAutomaticTransferLength()); + Registry registry = Registry.get(domain.getTld()); + DateTime implicitTransferTime = clock.nowUtc().plus(registry.getAutomaticTransferLength()); // Setup done; run the test. assertTransactionalFlow(true); runFlowAssertResponse(readFile(expectedXmlFilename, substitutions)); @@ -183,10 +185,9 @@ public class DomainTransferRequestFlowTest .setReason(Reason.TRANSFER) .setTargetId(domain.getFullyQualifiedDomainName()) .setEventTime(implicitTransferTime) - .setBillingTime( - implicitTransferTime.plus(Registry.get("tld").getTransferGracePeriodLength())) + .setBillingTime(implicitTransferTime.plus(registry.getTransferGracePeriodLength())) .setClientId("NewRegistrar") - .setCost(Money.of(USD, 11).multipliedBy(registrationYears)) + .setCost(transferCost.or(Money.of(USD, 11).multipliedBy(registrationYears))) .setPeriodYears(registrationYears) .setParent(historyEntryTransferRequest) .build(); @@ -225,8 +226,8 @@ public class DomainTransferRequestFlowTest GracePeriod.create( GracePeriodStatus.TRANSFER, clock.nowUtc() - .plus(Registry.get("tld").getAutomaticTransferLength()) - .plus(Registry.get("tld").getTransferGracePeriodLength()), + .plus(registry.getAutomaticTransferLength()) + .plus(registry.getTransferGracePeriodLength()), "NewRegistrar", null), transferBillingEvent)); @@ -285,8 +286,8 @@ public class DomainTransferRequestFlowTest .isEqualTo(expectedExpirationTime); // And after the expected grace time, the grace period should be gone. DomainResource afterGracePeriod = domain.cloneProjectedAtTime( - clock.nowUtc().plus(Registry.get("tld").getAutomaticTransferLength()).plus( - Registry.get("tld").getTransferGracePeriodLength())); + clock.nowUtc().plus(registry.getAutomaticTransferLength()).plus( + registry.getTransferGracePeriodLength())); assertThat(afterGracePeriod.getGracePeriods()).isEmpty(); } @@ -300,6 +301,7 @@ public class DomainTransferRequestFlowTest expectedXmlFilename, expectedExpirationTime, ImmutableMap.of(), + Optional.absent(), extraExpectedBillingEvents); } @@ -312,7 +314,8 @@ public class DomainTransferRequestFlowTest commandFilename, expectedXmlFilename, domain.getRegistrationExpirationTime().plusYears(1), - substitutions); + substitutions, + Optional.absent()); } private void doSuccessfulTest(String commandFilename, String expectedXmlFilename) @@ -349,6 +352,7 @@ public class DomainTransferRequestFlowTest @Test public void testDryRun() throws Exception { + setupDomain("example", "tld"); setEppInput("domain_transfer_request.xml"); eppLoader.replaceAll("JD1234-REP", contact.getRepoId()); dryRunFlowAssertResponse(readFile("domain_transfer_request_response.xml")); @@ -356,29 +360,34 @@ public class DomainTransferRequestFlowTest @Test public void testSuccess() throws Exception { + setupDomain("example", "tld"); doSuccessfulTest("domain_transfer_request.xml", "domain_transfer_request_response.xml"); } @Test public void testSuccess_fee_v06() throws Exception { + setupDomain("example", "tld"); doSuccessfulTest( "domain_transfer_request_fee.xml", "domain_transfer_request_response_fee.xml", FEE_06_MAP); } @Test public void testSuccess_fee_v11() throws Exception { + setupDomain("example", "tld"); doSuccessfulTest( "domain_transfer_request_fee.xml", "domain_transfer_request_response_fee.xml", FEE_11_MAP); } @Test public void testSuccess_fee_v12() throws Exception { + setupDomain("example", "tld"); doSuccessfulTest( "domain_transfer_request_fee.xml", "domain_transfer_request_response_fee.xml", FEE_12_MAP); } @Test public void testSuccess_fee_withDefaultAttributes_v06() throws Exception { + setupDomain("example", "tld"); doSuccessfulTest( "domain_transfer_request_fee_defaults.xml", "domain_transfer_request_response_fee.xml", @@ -387,6 +396,7 @@ public class DomainTransferRequestFlowTest @Test public void testSuccess_fee_withDefaultAttributes_v11() throws Exception { + setupDomain("example", "tld"); doSuccessfulTest( "domain_transfer_request_fee_defaults.xml", "domain_transfer_request_response_fee.xml", @@ -395,6 +405,7 @@ public class DomainTransferRequestFlowTest @Test public void testSuccess_fee_withDefaultAttributes_v12() throws Exception { + setupDomain("example", "tld"); doSuccessfulTest( "domain_transfer_request_fee_defaults.xml", "domain_transfer_request_response_fee.xml", @@ -403,60 +414,70 @@ public class DomainTransferRequestFlowTest @Test public void testFailure_refundableFee_v06() throws Exception { + setupDomain("example", "tld"); thrown.expect(UnsupportedFeeAttributeException.class); doFailingTest("domain_transfer_request_fee_refundable.xml", FEE_06_MAP); } @Test public void testFailure_refundableFee_v11() throws Exception { + setupDomain("example", "tld"); thrown.expect(UnsupportedFeeAttributeException.class); doFailingTest("domain_transfer_request_fee_refundable.xml", FEE_11_MAP); } @Test public void testFailure_refundableFee_v12() throws Exception { + setupDomain("example", "tld"); thrown.expect(UnsupportedFeeAttributeException.class); doFailingTest("domain_transfer_request_fee_refundable.xml", FEE_12_MAP); } @Test public void testFailure_gracePeriodFee_v06() throws Exception { + setupDomain("example", "tld"); thrown.expect(UnsupportedFeeAttributeException.class); doFailingTest("domain_transfer_request_fee_grace_period.xml", FEE_06_MAP); } @Test public void testFailure_gracePeriodFee_v11() throws Exception { + setupDomain("example", "tld"); thrown.expect(UnsupportedFeeAttributeException.class); doFailingTest("domain_transfer_request_fee_grace_period.xml", FEE_11_MAP); } @Test public void testFailure_gracePeriodFee_v12() throws Exception { + setupDomain("example", "tld"); thrown.expect(UnsupportedFeeAttributeException.class); doFailingTest("domain_transfer_request_fee_grace_period.xml", FEE_12_MAP); } @Test public void testFailure_appliedFee_v06() throws Exception { + setupDomain("example", "tld"); thrown.expect(UnsupportedFeeAttributeException.class); doFailingTest("domain_transfer_request_fee_applied.xml", FEE_06_MAP); } @Test public void testFailure_appliedFee_v11() throws Exception { + setupDomain("example", "tld"); thrown.expect(UnsupportedFeeAttributeException.class); doFailingTest("domain_transfer_request_fee_applied.xml", FEE_11_MAP); } @Test public void testFailure_appliedFee_v12() throws Exception { + setupDomain("example", "tld"); thrown.expect(UnsupportedFeeAttributeException.class); doFailingTest("domain_transfer_request_fee_applied.xml", FEE_12_MAP); } @Test public void testSuccess_nonDefaultAutomaticTransferLength() throws Exception { + setupDomain("example", "tld"); persistResource( Registry.get("tld") .asBuilder() @@ -469,6 +490,7 @@ public class DomainTransferRequestFlowTest @Test public void testSuccess_nonDefaultTransferGracePeriod() throws Exception { + setupDomain("example", "tld"); persistResource( Registry.get("tld") .asBuilder() @@ -479,12 +501,14 @@ public class DomainTransferRequestFlowTest @Test public void testSuccess_missingPeriod() throws Exception { + setupDomain("example", "tld"); doSuccessfulTest("domain_transfer_request_missing_period.xml", "domain_transfer_request_response.xml"); } @Test public void testSuccess_cappedExpiration() throws Exception { + setupDomain("example", "tld"); // The current expiration is in 15 months, so requesting 10 years would give 11 years 3 months, // were it not that we cap at 10 years. (MAX_REGISTRATION_YEARS == 10 and is unlikely to ever // change; we just use a constant for readability.) @@ -497,13 +521,31 @@ public class DomainTransferRequestFlowTest @Test public void testSuccess_domainAuthInfo() throws Exception { + setupDomain("example", "tld"); doSuccessfulTest( "domain_transfer_request_domain_authinfo.xml", "domain_transfer_request_response.xml"); } + @Test + public void testSuccess_customLogicFee() throws Exception { + setupDomain("expensive-domain", "foo"); + clock.advanceOneMilli(); + doSuccessfulTest( + "domain_transfer_request_wildcard.xml", + "domain_transfer_request_response_wildcard.xml", + domain.getRegistrationExpirationTime().plusYears(3), + new ImmutableMap.Builder() + .put("DOMAIN", "expensive-domain.foo") + .put("YEARS", "3") + .put("EXDATE", "2004-09-08T22:00:00.0Z") + .build(), + Optional.of(Money.of(USD, 133))); + } + @Test public void testFailure_notAuthorizedForTld() throws Exception { + setupDomain("example", "tld"); persistResource( Registrar.loadByClientId("NewRegistrar") .asBuilder() @@ -515,6 +557,7 @@ public class DomainTransferRequestFlowTest @Test public void testSuccess_autorenewBeforeAutomaticTransfer() throws Exception { + setupDomain("example", "tld"); DomainResource oldResource = persistResource(reloadResourceByForeignKey().asBuilder() .setRegistrationExpirationTime(clock.nowUtc().plusDays(1).plus(1)) .build()); @@ -559,6 +602,7 @@ public class DomainTransferRequestFlowTest } private void runWrongCurrencyTest(Map substitutions) throws Exception { + setupDomain("example", "tld"); persistResource( Registry.get("tld") .asBuilder() @@ -575,33 +619,39 @@ public class DomainTransferRequestFlowTest @Test public void testFailure_wrongCurrency_v06() throws Exception { + setupDomain("example", "tld"); runWrongCurrencyTest(FEE_06_MAP); } @Test public void testFailure_wrongCurrency_v11() throws Exception { + setupDomain("example", "tld"); runWrongCurrencyTest(FEE_11_MAP); } @Test public void testFailure_wrongCurrency_v12() throws Exception { + setupDomain("example", "tld"); runWrongCurrencyTest(FEE_12_MAP); } @Test public void testFailure_feeGivenInWrongScale_v06() throws Exception { + setupDomain("example", "tld"); thrown.expect(CurrencyValueScaleException.class); doFailingTest("domain_transfer_request_fee_bad_scale.xml", FEE_06_MAP); } @Test public void testFailure_feeGivenInWrongScale_v11() throws Exception { + setupDomain("example", "tld"); thrown.expect(CurrencyValueScaleException.class); doFailingTest("domain_transfer_request_fee_bad_scale.xml", FEE_11_MAP); } @Test public void testFailure_feeGivenInWrongScale_v12() throws Exception { + setupDomain("example", "tld"); thrown.expect(CurrencyValueScaleException.class); doFailingTest("domain_transfer_request_fee_bad_scale.xml", FEE_12_MAP); } @@ -619,16 +669,19 @@ public class DomainTransferRequestFlowTest @Test public void testFailure_wrongFeeAmount_v06() throws Exception { + setupDomain("example", "tld"); runWrongFeeAmountTest(FEE_06_MAP); } @Test public void testFailure_wrongFeeAmount_v11() throws Exception { + setupDomain("example", "tld"); runWrongFeeAmountTest(FEE_11_MAP); } @Test public void testFailure_wrongFeeAmount_v12() throws Exception { + setupDomain("example", "tld"); runWrongFeeAmountTest(FEE_12_MAP); } @@ -651,12 +704,14 @@ public class DomainTransferRequestFlowTest @Test public void testFailure_noAuthInfo() throws Exception { + setupDomain("example", "tld"); thrown.expect(MissingTransferRequestAuthInfoException.class); doFailingTest("domain_transfer_request_no_authinfo.xml"); } @Test public void testFailure_badContactPassword() throws Exception { + setupDomain("example", "tld"); // Change the contact's password so it does not match the password in the file. contact = persistResource( contact.asBuilder() @@ -668,6 +723,7 @@ public class DomainTransferRequestFlowTest @Test public void testFailure_badContactRepoId() throws Exception { + setupDomain("example", "tld"); // Set the contact to a different ROID, but don't persist it; this is just so the substitution // code above will write the wrong ROID into the file. contact = contact.asBuilder().setRepoId("DEADBEEF_TLD-ROID").build(); @@ -677,36 +733,42 @@ public class DomainTransferRequestFlowTest @Test public void testSuccess_clientApproved() throws Exception { + setupDomain("example", "tld"); changeTransferStatus(TransferStatus.CLIENT_APPROVED); doSuccessfulTest("domain_transfer_request.xml", "domain_transfer_request_response.xml"); } @Test public void testSuccess_clientRejected() throws Exception { + setupDomain("example", "tld"); changeTransferStatus(TransferStatus.CLIENT_REJECTED); doSuccessfulTest("domain_transfer_request.xml", "domain_transfer_request_response.xml"); } @Test public void testSuccess_clientCancelled() throws Exception { + setupDomain("example", "tld"); changeTransferStatus(TransferStatus.CLIENT_CANCELLED); doSuccessfulTest("domain_transfer_request.xml", "domain_transfer_request_response.xml"); } @Test public void testSuccess_serverApproved() throws Exception { + setupDomain("example", "tld"); changeTransferStatus(TransferStatus.SERVER_APPROVED); doSuccessfulTest("domain_transfer_request.xml", "domain_transfer_request_response.xml"); } @Test public void testSuccess_serverCancelled() throws Exception { + setupDomain("example", "tld"); changeTransferStatus(TransferStatus.SERVER_CANCELLED); doSuccessfulTest("domain_transfer_request.xml", "domain_transfer_request_response.xml"); } @Test public void testFailure_pending() throws Exception { + setupDomain("example", "tld"); domain = persistResource(domain.asBuilder() .setTransferData(domain.getTransferData().asBuilder() .setTransferStatus(TransferStatus.PENDING) @@ -719,6 +781,7 @@ public class DomainTransferRequestFlowTest @Test public void testFailure_badDomainPassword() throws Exception { + setupDomain("example", "tld"); // Change the domain's password so it does not match the password in the file. domain = persistResource(domain.asBuilder() .setAuthInfo(DomainAuthInfo.create(PasswordAuth.create("badpassword"))) @@ -729,6 +792,7 @@ public class DomainTransferRequestFlowTest @Test public void testFailure_sponsoringClient() throws Exception { + setupDomain("example", "tld"); setClientIdForFlow("TheRegistrar"); thrown.expect(ObjectAlreadySponsoredException.class); doFailingTest("domain_transfer_request.xml"); @@ -736,6 +800,7 @@ public class DomainTransferRequestFlowTest @Test public void testFailure_deletedDomain() throws Exception { + setupDomain("example", "tld"); domain = persistResource( domain.asBuilder().setDeletionTime(clock.nowUtc().minusDays(1)).build()); thrown.expect( @@ -746,7 +811,10 @@ public class DomainTransferRequestFlowTest @Test public void testFailure_invalidDomain() throws Exception { - setEppInput("domain_transfer_request_wildcard.xml", ImmutableMap.of("DOMAIN", "--invalid")); + setupDomain("example", "tld"); + setEppInput( + "domain_transfer_request_wildcard.xml", + ImmutableMap.of("YEARS", "1", "DOMAIN", "--invalid", "EXDATE", "2002-09-08T22:00:00.0Z")); eppLoader.replaceAll("JD1234-REP", contact.getRepoId()); assertTransactionalFlow(true); thrown.expect(ResourceDoesNotExistException.class, "(--invalid)"); @@ -755,21 +823,24 @@ public class DomainTransferRequestFlowTest @Test public void testFailure_nonexistentDomain() throws Exception { - deleteResource(domain); + createTld("tld"); + contact = persistActiveContact("jd1234"); thrown.expect( ResourceDoesNotExistException.class, - String.format("(%s)", getUniqueIdFromCommand())); + String.format("(%s)", "example.tld")); doFailingTest("domain_transfer_request.xml"); } @Test public void testFailure_periodInMonths() throws Exception { + setupDomain("example", "tld"); thrown.expect(BadPeriodUnitException.class); doFailingTest("domain_transfer_request_months.xml"); } @Test public void testFailure_pendingDelete() throws Exception { + setupDomain("example", "tld"); domain = persistResource( domain.asBuilder().addStatusValue(StatusValue.PENDING_DELETE).build()); thrown.expect(ResourceStatusProhibitsOperationException.class); diff --git a/javatests/google/registry/flows/domain/testdata/domain_transfer_request_response_wildcard.xml b/javatests/google/registry/flows/domain/testdata/domain_transfer_request_response_wildcard.xml new file mode 100644 index 000000000..bc67c5ee6 --- /dev/null +++ b/javatests/google/registry/flows/domain/testdata/domain_transfer_request_response_wildcard.xml @@ -0,0 +1,23 @@ + + + + Command completed successfully; action pending + + + + %DOMAIN% + pending + NewRegistrar + 2000-06-09T22:00:00.0Z + TheRegistrar + 2000-06-14T22:00:00.0Z + %EXDATE% + + + + ABC-12345 + server-trid + + + diff --git a/javatests/google/registry/flows/domain/testdata/domain_transfer_request_wildcard.xml b/javatests/google/registry/flows/domain/testdata/domain_transfer_request_wildcard.xml index 898dfe906..31c914e88 100644 --- a/javatests/google/registry/flows/domain/testdata/domain_transfer_request_wildcard.xml +++ b/javatests/google/registry/flows/domain/testdata/domain_transfer_request_wildcard.xml @@ -4,7 +4,7 @@ %DOMAIN% - 1 + %YEARS% 2fooBAR