JAMES-1781 Vacation update should be done using a specific object.
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/75b5767e Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/75b5767e Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/75b5767e Branch: refs/heads/master Commit: 75b5767e97f9968e8a0445685e86e0c0aa903e95 Parents: b7d41df Author: Benoit Tellier <[email protected]> Authored: Mon Jun 27 17:44:30 2016 +0700 Committer: Benoit Tellier <[email protected]> Committed: Thu Sep 29 12:48:14 2016 +0200 ---------------------------------------------------------------------- .../apache/james/utils/ExtendedServerProbe.java | 3 +- .../apache/james/utils/GuiceServerProbe.java | 5 +- .../james/jmap/api/vacation/VacationPatch.java | 207 ++++++++++++ .../jmap/api/vacation/VacationRepository.java | 2 +- .../AbstractVacationRepositoryTest.java | 283 ++++++++++++++++- .../jmap/api/vacation/VacationPatchTest.java | 311 +++++++++++++++++++ .../james/jmap/model/VacationResponseTest.java | 1 + 7 files changed, 793 insertions(+), 19 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/james-project/blob/75b5767e/server/container/guice/guice-common/src/main/java/org/apache/james/utils/ExtendedServerProbe.java ---------------------------------------------------------------------- diff --git a/server/container/guice/guice-common/src/main/java/org/apache/james/utils/ExtendedServerProbe.java b/server/container/guice/guice-common/src/main/java/org/apache/james/utils/ExtendedServerProbe.java index f1da266..20dbc81 100644 --- a/server/container/guice/guice-common/src/main/java/org/apache/james/utils/ExtendedServerProbe.java +++ b/server/container/guice/guice-common/src/main/java/org/apache/james/utils/ExtendedServerProbe.java @@ -27,6 +27,7 @@ import javax.mail.Flags; import org.apache.james.cli.probe.ServerProbe; import org.apache.james.jmap.api.vacation.AccountId; import org.apache.james.jmap.api.vacation.Vacation; +import org.apache.james.jmap.api.vacation.VacationUpdate; import org.apache.james.mailbox.exception.BadCredentialsException; import org.apache.james.mailbox.exception.MailboxException; import org.apache.james.mailbox.model.MailboxPath; @@ -39,7 +40,7 @@ public interface ExtendedServerProbe extends ServerProbe { Mailbox getMailbox(String namespace, String user, String name); - void modifyVacation(AccountId accountId, Vacation vacation); + void modifyVacation(AccountId accountId, VacationUpdate vacationUpdate); Vacation retrieveVacation(AccountId accountId); } http://git-wip-us.apache.org/repos/asf/james-project/blob/75b5767e/server/container/guice/guice-common/src/main/java/org/apache/james/utils/GuiceServerProbe.java ---------------------------------------------------------------------- diff --git a/server/container/guice/guice-common/src/main/java/org/apache/james/utils/GuiceServerProbe.java b/server/container/guice/guice-common/src/main/java/org/apache/james/utils/GuiceServerProbe.java index 8d5b734..fcda3f9 100644 --- a/server/container/guice/guice-common/src/main/java/org/apache/james/utils/GuiceServerProbe.java +++ b/server/container/guice/guice-common/src/main/java/org/apache/james/utils/GuiceServerProbe.java @@ -36,6 +36,7 @@ import org.apache.james.domainlist.api.DomainList; import org.apache.james.jmap.api.vacation.AccountId; import org.apache.james.jmap.api.vacation.Vacation; import org.apache.james.jmap.api.vacation.VacationRepository; +import org.apache.james.jmap.api.vacation.VacationUpdate; import org.apache.james.mailbox.MailboxManager; import org.apache.james.mailbox.MailboxSession; import org.apache.james.mailbox.MessageManager; @@ -356,8 +357,8 @@ public class GuiceServerProbe implements ExtendedServerProbe { } @Override - public void modifyVacation(AccountId accountId, Vacation vacation) { - vacationRepository.modifyVacation(accountId, vacation).join(); + public void modifyVacation(AccountId accountId, VacationUpdate vacationUpdate) { + vacationRepository.modifyVacation(accountId, vacationUpdate).join(); } @Override http://git-wip-us.apache.org/repos/asf/james-project/blob/75b5767e/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/vacation/VacationPatch.java ---------------------------------------------------------------------- diff --git a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/vacation/VacationPatch.java b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/vacation/VacationPatch.java new file mode 100644 index 0000000..721ab34 --- /dev/null +++ b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/vacation/VacationPatch.java @@ -0,0 +1,207 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you 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 org.apache.james.jmap.api.vacation; + +import java.time.ZonedDateTime; +import java.util.Objects; +import java.util.Optional; + +import org.apache.james.util.PatchedValue; + +import com.google.common.base.Preconditions; + +public class VacationPatch { + + public static Builder builder() { + return new Builder(); + } + + public static Builder builderFrom(Vacation vacation) { + return VacationPatch.builder() + .subject(PatchedValue.ofOptional(vacation.getSubject())) + .textBody(PatchedValue.ofOptional(vacation.getTextBody())) + .htmlBody(PatchedValue.ofOptional(vacation.getHtmlBody())) + .fromDate(PatchedValue.ofOptional(vacation.getFromDate())) + .toDate(PatchedValue.ofOptional(vacation.getToDate())) + .isEnabled(PatchedValue.modifyTo(vacation.isEnabled())); + } + + public static class Builder { + private PatchedValue<String> subject = PatchedValue.keep(); + private PatchedValue<String> textBody = PatchedValue.keep(); + private PatchedValue<String> htmlBody = PatchedValue.keep(); + private PatchedValue<ZonedDateTime> toDate = PatchedValue.keep(); + private PatchedValue<ZonedDateTime> fromDate = PatchedValue.keep(); + private PatchedValue<Boolean> isEnabled = PatchedValue.keep(); + + public Builder subject(PatchedValue<String> subject) { + Preconditions.checkNotNull(subject); + this.subject = subject; + return this; + } + + public Builder subject(String subject) { + this.subject = PatchedValue.modifyTo(subject); + return this; + } + + public Builder textBody(PatchedValue<String> textBody) { + Preconditions.checkNotNull(textBody); + this.textBody = textBody; + return this; + } + + public Builder textBody(String textBody) { + this.textBody = PatchedValue.modifyTo(textBody); + return this; + } + + public Builder htmlBody(PatchedValue<String> htmlBody) { + Preconditions.checkNotNull(htmlBody); + this.htmlBody = htmlBody; + return this; + } + + public Builder htmlBody(String htmlBody) { + this.htmlBody = PatchedValue.modifyTo(htmlBody); + return this; + } + + public Builder toDate(PatchedValue<ZonedDateTime> toDate) { + Preconditions.checkNotNull(toDate); + this.toDate = toDate; + return this; + } + + public Builder toDate(ZonedDateTime toDate) { + this.toDate = PatchedValue.modifyTo(toDate); + return this; + } + + public Builder fromDate(PatchedValue<ZonedDateTime> fromDate) { + Preconditions.checkNotNull(fromDate); + this.fromDate = fromDate; + return this; + } + + public Builder fromDate(ZonedDateTime fromDate) { + this.fromDate = PatchedValue.modifyTo(fromDate); + return this; + } + + public Builder isEnabled(PatchedValue<Boolean> isEnabled) { + Preconditions.checkNotNull(isEnabled); + this.isEnabled = isEnabled; + return this; + } + + public Builder isEnabled(Boolean isEnabled) { + this.isEnabled = PatchedValue.modifyTo(isEnabled); + return this; + } + + public VacationPatch build() { + return new VacationPatch(subject, textBody, htmlBody, toDate, fromDate, isEnabled); + } + } + + private final PatchedValue<String> subject; + private final PatchedValue<String> textBody; + private final PatchedValue<String> htmlBody; + private final PatchedValue<ZonedDateTime> toDate; + private final PatchedValue<ZonedDateTime> fromDate; + private final PatchedValue<Boolean> isEnabled; + + private VacationPatch(PatchedValue<String> subject, PatchedValue<String> textBody, PatchedValue<String> htmlBody, + PatchedValue<ZonedDateTime> toDate, PatchedValue<ZonedDateTime> fromDate, PatchedValue<Boolean> isEnabled) { + Preconditions.checkState(!isEnabled.isRemoved()); + this.subject = subject; + this.textBody = textBody; + this.htmlBody = htmlBody; + this.toDate = toDate; + this.fromDate = fromDate; + this.isEnabled = isEnabled; + } + + public PatchedValue<String> getSubject() { + return subject; + } + + public PatchedValue<String> getTextBody() { + return textBody; + } + + public PatchedValue<String> getHtmlBody() { + return htmlBody; + } + + public PatchedValue<ZonedDateTime> getToDate() { + return toDate; + } + + public PatchedValue<ZonedDateTime> getFromDate() { + return fromDate; + } + + public PatchedValue<Boolean> getIsEnabled() { + return isEnabled; + } + + public Vacation patch(Vacation vacation) { + return Vacation.builder() + .subject(subject.notKeptOrElse(vacation.getSubject())) + .fromDate(fromDate.notKeptOrElse(vacation.getFromDate())) + .toDate(toDate.notKeptOrElse(vacation.getToDate())) + .textBody(textBody.notKeptOrElse(vacation.getTextBody())) + .htmlBody(htmlBody.notKeptOrElse(vacation.getHtmlBody())) + .enabled(isEnabled.notKeptOrElse(Optional.of(vacation.isEnabled())).get()) + .build(); + } + + public boolean isIdentity() { + return subject.isKept() + && textBody.isKept() + && htmlBody.isKept() + && toDate.isKept() + && fromDate.isKept() + && isEnabled.isKept(); + } + + @Override + public boolean equals(Object o) { + if (o instanceof VacationPatch) { + VacationPatch that = (VacationPatch) o; + + return Objects.equals(this.subject, that.subject) + && Objects.equals(this.textBody, that.textBody) + && Objects.equals(this.htmlBody, that.htmlBody) + && Objects.equals(this.toDate, that.toDate) + && Objects.equals(this.fromDate, that.fromDate) + && Objects.equals(this.isEnabled, that.isEnabled); + } else { + return false; + } + } + + @Override + public int hashCode() { + return Objects.hash(subject, textBody, htmlBody, toDate, fromDate, isEnabled); + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/75b5767e/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/vacation/VacationRepository.java ---------------------------------------------------------------------- diff --git a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/vacation/VacationRepository.java b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/vacation/VacationRepository.java index 02ff1c6..8267249 100644 --- a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/vacation/VacationRepository.java +++ b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/vacation/VacationRepository.java @@ -25,7 +25,7 @@ public interface VacationRepository { Vacation DEFAULT_VACATION = Vacation.builder().enabled(false).build(); - CompletableFuture<Void> modifyVacation(AccountId accountId, Vacation vacation); + CompletableFuture<Void> modifyVacation(AccountId accountId, VacationPatch vacationPatch); CompletableFuture<Vacation> retrieveVacation(AccountId accountId); http://git-wip-us.apache.org/repos/asf/james-project/blob/75b5767e/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/vacation/AbstractVacationRepositoryTest.java ---------------------------------------------------------------------- diff --git a/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/vacation/AbstractVacationRepositoryTest.java b/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/vacation/AbstractVacationRepositoryTest.java index ee7ad0c..ef90fb4 100644 --- a/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/vacation/AbstractVacationRepositoryTest.java +++ b/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/vacation/AbstractVacationRepositoryTest.java @@ -24,19 +24,20 @@ import static org.assertj.core.api.Assertions.assertThat; import java.time.ZonedDateTime; import java.util.Optional; +import org.apache.james.util.PatchedValue; import org.junit.Before; import org.junit.Test; public abstract class AbstractVacationRepositoryTest { public static final AccountId ACCOUNT_ID = AccountId.fromString("identifier"); - public static final ZonedDateTime ZONED_DATE_TIME = ZonedDateTime.parse("2016-04-03T02:01+07:00[Asia/Vientiane]"); - public static final Vacation VACATION_1 = Vacation.builder() - .enabled(true) - .textBody("other Message") - .build(); - public static final Vacation VACATION_2 = Vacation.builder() - .fromDate(Optional.of(ZONED_DATE_TIME)) + public static final ZonedDateTime DATE_2014 = ZonedDateTime.parse("2014-04-03T02:01+07:00[Asia/Vientiane]"); + public static final ZonedDateTime DATE_2015 = ZonedDateTime.parse("2015-04-03T02:01+07:00[Asia/Vientiane]"); + public static final ZonedDateTime DATE_2016 = ZonedDateTime.parse("2016-04-03T02:01+07:00[Asia/Vientiane]"); + public static final ZonedDateTime DATE_2017 = ZonedDateTime.parse("2017-04-03T02:01+07:00[Asia/Vientiane]"); + public static final Vacation VACATION = Vacation.builder() + .fromDate(Optional.of(DATE_2015)) + .toDate(Optional.of(DATE_2016)) .enabled(true) .subject(Optional.of("subject")) .textBody("anyMessage") @@ -59,18 +60,270 @@ public abstract class AbstractVacationRepositoryTest { } @Test - public void modifyVacationShouldWork() { - vacationRepository.modifyVacation(ACCOUNT_ID, VACATION_1).join(); + public void modifyVacationShouldUpdateEnabled() { + VacationPatch vacationPatch = VacationPatch.builder() + .isEnabled(true) + .build(); + + vacationRepository.modifyVacation(ACCOUNT_ID, vacationPatch).join(); + + assertThat(vacationRepository.retrieveVacation(ACCOUNT_ID).join()) + .isEqualTo(Vacation.builder() + .enabled(true) + .build()); + } + + @Test + public void modifyVacationShouldUpdateFromDate() { + VacationPatch vacationPatch = VacationPatch.builder() + .fromDate(DATE_2014) + .build(); + + vacationRepository.modifyVacation(ACCOUNT_ID, vacationPatch).join(); + + assertThat(vacationRepository.retrieveVacation(ACCOUNT_ID).join()) + .isEqualTo(Vacation.builder() + .fromDate(Optional.of(DATE_2014)) + .enabled(false) + .build()); + } + + @Test + public void modifyVacationShouldUpdateToDate() { + VacationPatch vacationPatch = VacationPatch.builder() + .toDate(DATE_2017) + .build(); + + vacationRepository.modifyVacation(ACCOUNT_ID, vacationPatch).join(); + + assertThat(vacationRepository.retrieveVacation(ACCOUNT_ID).join()) + .isEqualTo(Vacation.builder() + .toDate(Optional.of(DATE_2017)) + .enabled(false) + .build()); + } + + @Test + public void modifyVacationShouldUpdateSubject() { + String newSubject = "new subject"; + VacationPatch vacationPatch = VacationPatch.builder() + .subject(newSubject) + .build(); + + vacationRepository.modifyVacation(ACCOUNT_ID, vacationPatch).join(); + + assertThat(vacationRepository.retrieveVacation(ACCOUNT_ID).join()) + .isEqualTo(Vacation.builder() + .subject(Optional.of(newSubject)) + .enabled(false) + .build()); + } + + @Test + public void modifyVacationShouldUpdateTextBody() { + String newTextBody = "new text body"; + VacationPatch vacationPatch = VacationPatch.builder() + .textBody(newTextBody) + .build(); + + vacationRepository.modifyVacation(ACCOUNT_ID, vacationPatch).join(); + + assertThat(vacationRepository.retrieveVacation(ACCOUNT_ID).join()) + .isEqualTo(Vacation.builder() + .textBody(newTextBody) + .enabled(false) + .build()); + } + + @Test + public void modifyVacationShouldUpdateHtmlBody() { + String newHtmlBody = "new <b>html</b> body"; + VacationPatch vacationPatch = VacationPatch.builder() + .htmlBody(newHtmlBody) + .build(); + + vacationRepository.modifyVacation(ACCOUNT_ID, vacationPatch).join(); + + assertThat(vacationRepository.retrieveVacation(ACCOUNT_ID).join()) + .isEqualTo(Vacation.builder() + .enabled(false) + .htmlBody(newHtmlBody) + .build()); + } + + @Test + public void modifyVacationShouldAllowToUpdateAllFieldsAtOnce() { + VacationPatch vacationPatch = VacationPatch.builderFrom(VACATION) + .build(); - assertThat(vacationRepository.retrieveVacation(ACCOUNT_ID).join()).isEqualTo(VACATION_1); + vacationRepository.modifyVacation(ACCOUNT_ID, vacationPatch).join(); + + assertThat(vacationRepository.retrieveVacation(ACCOUNT_ID).join()) + .isEqualTo(VACATION); + } + + @Test + public void modifyVacationShouldAllowEmptyUpdates() { + VacationPatch vacationPatch = VacationPatch.builder() + .build(); + + vacationRepository.modifyVacation(ACCOUNT_ID, vacationPatch).join(); + + assertThat(vacationRepository.retrieveVacation(ACCOUNT_ID).join()) + .isEqualTo(VacationRepository.DEFAULT_VACATION); + } + + @Test + public void emptyUpdatesShouldNotChangeExistingVacations() { + // Given + vacationRepository.modifyVacation(ACCOUNT_ID, + VacationPatch.builderFrom(VACATION) + .build()) + .join(); + + // When + vacationRepository.modifyVacation(ACCOUNT_ID, VacationPatch.builder() + .build()) + .join(); + + // Then + assertThat(vacationRepository.retrieveVacation(ACCOUNT_ID).join()) + .isEqualTo(VACATION); + } + + @Test + public void nullUpdateShouldResetSubject() { + // Given + vacationRepository.modifyVacation(ACCOUNT_ID, + VacationPatch.builderFrom(VACATION) + .build()) + .join(); + + // When + vacationRepository.modifyVacation(ACCOUNT_ID, VacationPatch.builder() + .subject(PatchedValue.remove()) + .build()) + .join(); + + // Then + Vacation vacation = vacationRepository.retrieveVacation(ACCOUNT_ID).join(); + assertThat(vacation.getSubject()).isEmpty(); + assertThat(vacation) + .isEqualTo(Vacation.builder() + .fromDate(VACATION.getFromDate()) + .toDate(VACATION.getToDate()) + .enabled(VACATION.isEnabled()) + .textBody(VACATION.getTextBody()) + .htmlBody(VACATION.getHtmlBody()) + .build()); } @Test - public void modifyVacationShouldReplacePreviousValue() { - vacationRepository.modifyVacation(ACCOUNT_ID, VACATION_1).join(); - vacationRepository.modifyVacation(ACCOUNT_ID, VACATION_2).join(); + public void nullUpdateShouldResetText() { + // Given + vacationRepository.modifyVacation(ACCOUNT_ID, + VacationPatch.builderFrom(VACATION) + .build()) + .join(); + + // When + vacationRepository.modifyVacation(ACCOUNT_ID, VacationPatch.builder() + .textBody(PatchedValue.remove()) + .build()) + .join(); + + // Then + Vacation vacation = vacationRepository.retrieveVacation(ACCOUNT_ID).join(); + assertThat(vacation.getTextBody()).isEmpty(); + assertThat(vacation) + .isEqualTo(Vacation.builder() + .fromDate(VACATION.getFromDate()) + .toDate(VACATION.getToDate()) + .enabled(VACATION.isEnabled()) + .subject(VACATION.getSubject()) + .htmlBody(VACATION.getHtmlBody()) + .build()); + } + + @Test + public void nullUpdateShouldResetHtml() { + // Given + vacationRepository.modifyVacation(ACCOUNT_ID, + VacationPatch.builderFrom(VACATION) + .build()) + .join(); + + // When + vacationRepository.modifyVacation(ACCOUNT_ID, VacationPatch.builder() + .htmlBody(PatchedValue.remove()) + .build()) + .join(); + + // Then + Vacation vacation = vacationRepository.retrieveVacation(ACCOUNT_ID).join(); + assertThat(vacation.getHtmlBody()).isEmpty(); + assertThat(vacation) + .isEqualTo(Vacation.builder() + .fromDate(VACATION.getFromDate()) + .toDate(VACATION.getToDate()) + .enabled(VACATION.isEnabled()) + .subject(VACATION.getSubject()) + .textBody(VACATION.getTextBody()) + .build()); + } + + @Test + public void nullUpdateShouldResetToDate() { + // Given + vacationRepository.modifyVacation(ACCOUNT_ID, + VacationPatch.builderFrom(VACATION) + .build()) + .join(); + + // When + vacationRepository.modifyVacation(ACCOUNT_ID, VacationPatch.builder() + .toDate(PatchedValue.remove()) + .build()) + .join(); + + // Then + Vacation vacation = vacationRepository.retrieveVacation(ACCOUNT_ID).join(); + assertThat(vacation.getToDate()).isEmpty(); + assertThat(vacation) + .isEqualTo(Vacation.builder() + .fromDate(VACATION.getFromDate()) + .enabled(VACATION.isEnabled()) + .subject(VACATION.getSubject()) + .textBody(VACATION.getTextBody()) + .htmlBody(VACATION.getHtmlBody()) + .build()); + } + + @Test + public void nullUpdateShouldResetFromDate() { + // Given + vacationRepository.modifyVacation(ACCOUNT_ID, + VacationPatch.builderFrom(VACATION) + .build()) + .join(); + + // When + vacationRepository.modifyVacation(ACCOUNT_ID, VacationPatch.builder() + .fromDate(PatchedValue.remove()) + .build()) + .join(); - assertThat(vacationRepository.retrieveVacation(ACCOUNT_ID).join()).isEqualTo(VACATION_2); + // Then + Vacation vacation = vacationRepository.retrieveVacation(ACCOUNT_ID).join(); + assertThat(vacation.getFromDate()).isEmpty(); + assertThat(vacation) + .isEqualTo(Vacation.builder() + .toDate(VACATION.getToDate()) + .enabled(VACATION.isEnabled()) + .subject(VACATION.getSubject()) + .textBody(VACATION.getTextBody()) + .htmlBody(VACATION.getHtmlBody()) + .build()); } @Test(expected = NullPointerException.class) @@ -80,7 +333,7 @@ public abstract class AbstractVacationRepositoryTest { @Test(expected = NullPointerException.class) public void modifyVacationShouldThrowOnNullAccountId() { - vacationRepository.modifyVacation(null, VACATION_1); + vacationRepository.modifyVacation(null, VacationPatch.builder().build()); } @Test(expected = NullPointerException.class) http://git-wip-us.apache.org/repos/asf/james-project/blob/75b5767e/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/vacation/VacationPatchTest.java ---------------------------------------------------------------------- diff --git a/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/vacation/VacationPatchTest.java b/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/vacation/VacationPatchTest.java new file mode 100644 index 0000000..13db92a --- /dev/null +++ b/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/vacation/VacationPatchTest.java @@ -0,0 +1,311 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you 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 org.apache.james.jmap.api.vacation; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.time.ZonedDateTime; +import java.util.Optional; + +import org.apache.james.util.PatchedValue; +import org.junit.Test; + +public class VacationPatchTest { + + public static final ZonedDateTime DATE_2014 = ZonedDateTime.parse("2014-04-03T02:01+07:00[Asia/Vientiane]"); + public static final ZonedDateTime DATE_2015 = ZonedDateTime.parse("2015-04-03T02:01+07:00[Asia/Vientiane]"); + public static final ZonedDateTime DATE_2017 = ZonedDateTime.parse("2017-04-03T02:01+07:00[Asia/Vientiane]"); + public static final Vacation VACATION = Vacation.builder() + .fromDate(Optional.of(DATE_2014)) + .toDate(Optional.of(DATE_2015)) + .enabled(true) + .subject(Optional.of("subject")) + .textBody("anyMessage") + .htmlBody("html Message") + .build(); + + @Test + public void fromDateShouldThrowNPEOnNullInput() { + assertThatThrownBy(() -> VacationPatch.builder().fromDate((PatchedValue) null)).isInstanceOf(NullPointerException.class); + } + + @Test + public void toDateShouldThrowNPEOnNullInput() { + assertThatThrownBy(() -> VacationPatch.builder().toDate((PatchedValue) null)).isInstanceOf(NullPointerException.class); + } + + @Test + public void textBodyShouldThrowNPEOnNullInput() { + assertThatThrownBy(() -> VacationPatch.builder().textBody((PatchedValue) null)).isInstanceOf(NullPointerException.class); + } + + @Test + public void htmlBodyShouldThrowNPEOnNullInput() { + assertThatThrownBy(() -> VacationPatch.builder().htmlBody((PatchedValue) null)).isInstanceOf(NullPointerException.class); + } + + @Test + public void subjectShouldThrowNPEOnNullInput() { + assertThatThrownBy(() -> VacationPatch.builder().subject((PatchedValue) null)).isInstanceOf(NullPointerException.class); + } + + @Test + public void isEnabledShouldThrowNPEOnNullInput() { + assertThatThrownBy(() -> VacationPatch.builder().isEnabled((PatchedValue) null)).isInstanceOf(NullPointerException.class); + } + + @Test + public void isIdentityShouldBeTrueWhenUpdateIsEmpty() { + assertThat( + VacationPatch.builder() + .build() + .isIdentity()) + .isTrue(); + } + + @Test + public void isIdentityShouldBeFalseWhenUpdateIsNotEmpty() { + assertThat( + VacationPatch.builder() + .subject(PatchedValue.modifyTo("any subject")) + .build() + .isIdentity()) + .isFalse(); + } + + @Test + public void builderShouldWellSetFields() { + PatchedValue<String> subject = PatchedValue.modifyTo("subject"); + PatchedValue<String> htmlBody = PatchedValue.modifyTo("html text"); + PatchedValue<String> textBody = PatchedValue.modifyTo("simple text"); + PatchedValue<Boolean> isEnabled = PatchedValue.modifyTo(true); + + VacationPatch update = VacationPatch.builder() + .fromDate(PatchedValue.modifyTo(DATE_2014)) + .toDate(PatchedValue.modifyTo(DATE_2015)) + .subject(subject) + .htmlBody(htmlBody) + .textBody(textBody) + .isEnabled(isEnabled) + .build(); + + assertThat(update.getFromDate()).isEqualTo(PatchedValue.modifyTo(DATE_2014)); + assertThat(update.getToDate()).isEqualTo(PatchedValue.modifyTo(DATE_2015)); + assertThat(update.getSubject()).isEqualTo(subject); + assertThat(update.getHtmlBody()).isEqualTo(htmlBody); + assertThat(update.getTextBody()).isEqualTo(textBody); + assertThat(update.getIsEnabled()).isEqualTo(isEnabled); + } + + @Test + public void patchVacationShouldUpdateEnabled() { + VacationPatch vacationPatch = VacationPatch.builder() + .isEnabled(PatchedValue.modifyTo(true)) + .build(); + + assertThat(vacationPatch.patch(VacationRepository.DEFAULT_VACATION)) + .isEqualTo(Vacation.builder() + .enabled(true) + .build()); + } + + @Test + public void patchVacationShouldUpdateFromDate() { + VacationPatch vacationPatch = VacationPatch.builder() + .fromDate(PatchedValue.modifyTo(DATE_2014)) + .build(); + + assertThat(vacationPatch.patch(VacationRepository.DEFAULT_VACATION)) + .isEqualTo(Vacation.builder() + .fromDate(Optional.of(DATE_2014)) + .enabled(false) + .build()); + } + + @Test + public void patchVacationShouldUpdateToDate() { + VacationPatch vacationPatch = VacationPatch.builder() + .toDate(PatchedValue.modifyTo(DATE_2017)) + .build(); + + assertThat(vacationPatch.patch(VacationRepository.DEFAULT_VACATION)) + .isEqualTo(Vacation.builder() + .toDate(Optional.of(DATE_2017)) + .enabled(false) + .build()); + } + + @Test + public void patchVacationShouldUpdateSubject() { + String newSubject = "new subject"; + VacationPatch vacationPatch = VacationPatch.builder() + .subject(PatchedValue.modifyTo(newSubject)) + .build(); + + assertThat(vacationPatch.patch(VacationRepository.DEFAULT_VACATION)) + .isEqualTo(Vacation.builder() + .subject(Optional.of(newSubject)) + .enabled(false) + .build()); + } + + @Test + public void patchVacationShouldUpdateTextBody() { + String newTextBody = "new text body"; + VacationPatch vacationPatch = VacationPatch.builder() + .textBody(PatchedValue.modifyTo(newTextBody)) + .build(); + + assertThat(vacationPatch.patch(VacationRepository.DEFAULT_VACATION)) + .isEqualTo(Vacation.builder() + .textBody(newTextBody) + .enabled(false) + .build()); + } + + @Test + public void patchVacationShouldUpdateHtmlBody() { + String newHtmlBody = "new <b>html</b> body"; + VacationPatch vacationPatch = VacationPatch.builder() + .htmlBody(PatchedValue.modifyTo(newHtmlBody)) + .build(); + + assertThat(vacationPatch.patch(VacationRepository.DEFAULT_VACATION)) + .isEqualTo(Vacation.builder() + .enabled(false) + .htmlBody(newHtmlBody) + .build()); + } + + @Test + public void patchVacationShouldAllowToUpdateAllFieldsAtOnce() { + VacationPatch vacationPatch = VacationPatch.builder() + .subject(PatchedValue.ofOptional(VACATION.getSubject())) + .textBody(PatchedValue.ofOptional(VACATION.getTextBody())) + .htmlBody(PatchedValue.ofOptional(VACATION.getHtmlBody())) + .fromDate(PatchedValue.ofOptional(VACATION.getFromDate())) + .toDate(PatchedValue.ofOptional(VACATION.getToDate())) + .isEnabled(PatchedValue.modifyTo(VACATION.isEnabled())) + .build(); + + assertThat(vacationPatch.patch(VacationRepository.DEFAULT_VACATION)) + .isEqualTo(VACATION); + } + + @Test + public void emptyPatchesShouldNotChangeExistingVacations() { + assertThat(VacationPatch.builder() + .build() + .patch(VACATION)) + .isEqualTo(VACATION); + } + + @Test + public void nullUpdateShouldResetSubject() { + Vacation vacation = VacationPatch.builderFrom(VACATION) + .subject(PatchedValue.remove()) + .build() + .patch(VACATION); + + assertThat(vacation.getSubject()).isEmpty(); + assertThat(vacation) + .isEqualTo(Vacation.builder() + .fromDate(VACATION.getFromDate()) + .toDate(VACATION.getToDate()) + .enabled(VACATION.isEnabled()) + .textBody(VACATION.getTextBody()) + .htmlBody(VACATION.getHtmlBody()) + .build()); + } + + @Test + public void nullUpdateShouldResetText() { + Vacation vacation = VacationPatch.builderFrom(VACATION) + .textBody(PatchedValue.remove()) + .build() + .patch(VACATION); + + assertThat(vacation.getTextBody()).isEmpty(); + assertThat(vacation) + .isEqualTo(Vacation.builder() + .fromDate(VACATION.getFromDate()) + .toDate(VACATION.getToDate()) + .enabled(VACATION.isEnabled()) + .subject(VACATION.getSubject()) + .htmlBody(VACATION.getHtmlBody()) + .build()); + } + + @Test + public void nullUpdateShouldResetHtml() { + Vacation vacation = VacationPatch.builderFrom(VACATION) + .htmlBody(PatchedValue.remove()) + .build() + .patch(VACATION); + + assertThat(vacation.getHtmlBody()).isEmpty(); + assertThat(vacation) + .isEqualTo(Vacation.builder() + .fromDate(VACATION.getFromDate()) + .toDate(VACATION.getToDate()) + .enabled(VACATION.isEnabled()) + .subject(VACATION.getSubject()) + .textBody(VACATION.getTextBody()) + .build()); + } + + @Test + public void nullUpdateShouldResetToDate() { + Vacation vacation = VacationPatch.builderFrom(VACATION) + .toDate(PatchedValue.remove()) + .build() + .patch(VACATION); + + assertThat(vacation.getToDate()).isEmpty(); + assertThat(vacation) + .isEqualTo(Vacation.builder() + .fromDate(VACATION.getFromDate()) + .enabled(VACATION.isEnabled()) + .subject(VACATION.getSubject()) + .textBody(VACATION.getTextBody()) + .htmlBody(VACATION.getHtmlBody()) + .build()); + } + + @Test + public void nullUpdateShouldResetFromDate() { + Vacation vacation = VacationPatch.builderFrom(VACATION) + .fromDate(PatchedValue.remove()) + .build() + .patch(VACATION); + + assertThat(vacation.getFromDate()).isEmpty(); + assertThat(vacation) + .isEqualTo(Vacation.builder() + .toDate(VACATION.getToDate()) + .enabled(VACATION.isEnabled()) + .subject(VACATION.getSubject()) + .textBody(VACATION.getTextBody()) + .htmlBody(VACATION.getHtmlBody()) + .build()); + } + +} http://git-wip-us.apache.org/repos/asf/james-project/blob/75b5767e/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/VacationResponseTest.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/VacationResponseTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/VacationResponseTest.java index 503acdf..779a812 100644 --- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/VacationResponseTest.java +++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/VacationResponseTest.java @@ -25,6 +25,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import java.time.ZonedDateTime; import java.util.Optional; +import org.apache.james.jmap.api.vacation.Vacation; import org.junit.Test; public class VacationResponseTest { --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
