From 9705ed34ba45f6db8d860e4f5b2fb9e954cc01fa Mon Sep 17 00:00:00 2001 From: cristianpela Date: Thu, 15 Oct 2020 11:42:03 +0300 Subject: [PATCH] #615 Implemented and tested WalletPaymentMethods. --- .../java/com/selfxdsd/api/PaymentMethods.java | 2 - .../core/projects/WalletPaymentMethods.java | 123 +++++++++ .../WalletPaymentMethodsTestCase.java | 253 ++++++++++++++++++ 3 files changed, 376 insertions(+), 2 deletions(-) create mode 100644 self-core-impl/src/main/java/com/selfxdsd/core/projects/WalletPaymentMethods.java create mode 100644 self-core-impl/src/test/java/com/selfxdsd/core/projects/WalletPaymentMethodsTestCase.java diff --git a/self-api/src/main/java/com/selfxdsd/api/PaymentMethods.java b/self-api/src/main/java/com/selfxdsd/api/PaymentMethods.java index 61bd46b3..7ebb437f 100644 --- a/self-api/src/main/java/com/selfxdsd/api/PaymentMethods.java +++ b/self-api/src/main/java/com/selfxdsd/api/PaymentMethods.java @@ -27,8 +27,6 @@ * @author criske * @version $Id$ * @since 0.0.26 - * @todo #608:60min Provide implementation and unit tests for - * PaymentMethods#ofWallet(...). */ public interface PaymentMethods extends Iterable { diff --git a/self-core-impl/src/main/java/com/selfxdsd/core/projects/WalletPaymentMethods.java b/self-core-impl/src/main/java/com/selfxdsd/core/projects/WalletPaymentMethods.java new file mode 100644 index 00000000..d4d7c5db --- /dev/null +++ b/self-core-impl/src/main/java/com/selfxdsd/core/projects/WalletPaymentMethods.java @@ -0,0 +1,123 @@ +/** + * Copyright (c) 2020, Self XDSD Contributors + * All rights reserved. + *

+ * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), + * to read the Software only. Permission is hereby NOT GRANTED to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software. + *

+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +package com.selfxdsd.core.projects; + +import com.selfxdsd.api.PaymentMethod; +import com.selfxdsd.api.PaymentMethods; +import com.selfxdsd.api.Wallet; +import com.selfxdsd.api.exceptions.PaymentMethodsException; +import com.selfxdsd.api.storage.Storage; + +import java.util.Iterator; +import java.util.function.Supplier; +import java.util.stream.Stream; + +/** + * PaymentMethods for a Wallet. + * @author criske + * @version $Id$ + * @since 0.0.28 + */ +public final class WalletPaymentMethods implements PaymentMethods { + + /** + * The wallet in question. + */ + private final Wallet wallet; + + /** + * Payment methods for this Wallet. + */ + private final Supplier> paymentMethods; + + /** + * Storage. + */ + private final Storage storage; + + /** + * Ctor. + * @param wallet The wallet in question. + * @param paymentMethods Payment methods for this Wallet. + * @param storage Storage. + */ + public WalletPaymentMethods(final Wallet wallet, + final + Supplier> paymentMethods, + final Storage storage) { + this.wallet = wallet; + this.paymentMethods = paymentMethods; + this.storage = storage; + } + + @Override + public PaymentMethod register(final Wallet wallet, + final String identifier) { + if(!this.wallet.equals(wallet)){ + throw new PaymentMethodsException("Can't register this payment " + + "method because it will be part of different wallet."); + } + return this.storage.paymentMethods().register(wallet, identifier); + } + + @Override + public boolean remove(final PaymentMethod paymentMethod) { + if(!paymentMethod.wallet().equals(this.wallet)){ + throw new PaymentMethodsException("Can't remove this payment " + + "method because it's part of different wallet."); + } + return this.storage.paymentMethods().remove(paymentMethod); + } + + @Override + public PaymentMethods ofWallet(final Wallet wallet) { + if(!this.wallet.equals(wallet)){ + throw new PaymentMethodsException("These are payment methods for" + + wallet.toString() + ", can't call ofWallet() " + + "for other wallet."); + } + return this; + } + + @Override + public PaymentMethod active() { + return this.paymentMethods.get() + .filter(PaymentMethod::active) + .findFirst() + .orElse(null); + } + + @Override + public PaymentMethod activate(final PaymentMethod paymentMethod) { + if(!paymentMethod.wallet().equals(this.wallet)){ + throw new PaymentMethodsException("Can't activate this payment " + + "method because it's part of different wallet."); + } + return this.storage.paymentMethods().activate(paymentMethod); + } + + @Override + public Iterator iterator() { + return this.paymentMethods.get().iterator(); + } +} diff --git a/self-core-impl/src/test/java/com/selfxdsd/core/projects/WalletPaymentMethodsTestCase.java b/self-core-impl/src/test/java/com/selfxdsd/core/projects/WalletPaymentMethodsTestCase.java new file mode 100644 index 00000000..94bbea61 --- /dev/null +++ b/self-core-impl/src/test/java/com/selfxdsd/core/projects/WalletPaymentMethodsTestCase.java @@ -0,0 +1,253 @@ +/** + * Copyright (c) 2020, Self XDSD Contributors + * All rights reserved. + *

+ * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), + * to read the Software only. Permission is hereby NOT GRANTED to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software. + *

+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +package com.selfxdsd.core.projects; + +import com.selfxdsd.api.PaymentMethod; +import com.selfxdsd.api.PaymentMethods; +import com.selfxdsd.api.Wallet; +import com.selfxdsd.api.exceptions.PaymentMethodsException; +import com.selfxdsd.api.storage.Storage; +import org.hamcrest.MatcherAssert; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.mockito.Mockito; + +import java.util.stream.Stream; + +/** + * Unit tests for {@link WalletPaymentMethods}. + * @author criske + * @version $Id$ + * @since 0.0.28 + */ +public final class WalletPaymentMethodsTestCase { + + /** + * WalletPaymentMethods can be iterated. + */ + @Test + public void iterationWorks() { + final Storage storage = Mockito.mock(Storage.class); + final Wallet wallet = Mockito.mock(Wallet.class); + final Iterable pms = () -> new WalletPaymentMethods( + wallet, + () -> Stream.of( + Mockito.mock(PaymentMethod.class), + Mockito.mock(PaymentMethod.class), + Mockito.mock(PaymentMethod.class) + ), + storage + ).iterator(); + + MatcherAssert.assertThat(pms, Matchers.iterableWithSize(3)); + } + + /** + * WalletPaymentMethods can register a PaymentMethod. + */ + @Test + public void canRegisterPaymentMethod() { + final Storage storage = Mockito.mock(Storage.class); + final PaymentMethods all = Mockito.mock(PaymentMethods.class); + Mockito.when(storage.paymentMethods()).thenReturn(all); + + final Wallet wallet = Mockito.mock(Wallet.class); + final PaymentMethods pms = new WalletPaymentMethods( + wallet, + Stream::empty, + storage + ); + + pms.register(wallet, "pm_1"); + + Mockito.verify(all).register(wallet, "pm_1"); + } + + /** + * WalletPaymentMethods.register(...) throws if register PaymentMethod for + * other wallet. + */ + @Test(expected = PaymentMethodsException.class) + public void complainsIfRegisterPaymentMethodForOtherWallet() { + final Storage storage = Mockito.mock(Storage.class); + final PaymentMethods all = Mockito.mock(PaymentMethods.class); + Mockito.when(storage.paymentMethods()).thenReturn(all); + + final Wallet wallet = Mockito.mock(Wallet.class); + final PaymentMethods pms = new WalletPaymentMethods( + wallet, + Stream::empty, + storage + ); + + pms.register(Mockito.mock(Wallet.class), "pm_1"); + } + + /** + * WalletPaymentMethods.remove(...) throws if register PaymentMethod is from + * other wallet. + */ + @Test + public void canRemovePaymentMethod() { + final Storage storage = Mockito.mock(Storage.class); + final PaymentMethods all = Mockito.mock(PaymentMethods.class); + Mockito.when(storage.paymentMethods()).thenReturn(all); + + final Wallet wallet = Mockito.mock(Wallet.class); + final PaymentMethod pmeth = Mockito.mock(PaymentMethod.class); + Mockito.when(pmeth.wallet()).thenReturn(wallet); + final PaymentMethods pms = new WalletPaymentMethods( + wallet, + () -> Stream.of(pmeth), + storage + ); + + pms.remove(pmeth); + + Mockito.verify(all).remove(pmeth); + } + + /** + * WalletPaymentMethods can remove a PaymentMethod. + */ + @Test(expected = PaymentMethodsException.class) + public void complainsIfRemovePaymentMethodFromOtherWallet() { + final Storage storage = Mockito.mock(Storage.class); + final PaymentMethods all = Mockito.mock(PaymentMethods.class); + Mockito.when(storage.paymentMethods()).thenReturn(all); + + final Wallet wallet = Mockito.mock(Wallet.class); + final PaymentMethod pmeth = Mockito.mock(PaymentMethod.class); + Mockito.when(pmeth.wallet()).thenReturn(wallet); + final PaymentMethods pms = new WalletPaymentMethods( + wallet, + () -> Stream.of(pmeth), + storage + ); + final PaymentMethod otherPmeth = Mockito.mock(PaymentMethod.class); + Mockito.when(otherPmeth.wallet()) + .thenReturn(Mockito.mock(Wallet.class)); + + pms.remove(otherPmeth); + } + + /** + * Returns itself when calling ofWallet(...). + */ + @Test + public void returnsItself() { + final Wallet wallet = Mockito.mock(Wallet.class); + final PaymentMethods pms = new WalletPaymentMethods( + wallet, + Stream::empty, + Mockito.mock(Storage.class) + ); + MatcherAssert.assertThat(pms.ofWallet(wallet), Matchers.equalTo(pms)); + } + + /** + * Throws when calling ofWallet(...) for other Wallet. + */ + @Test(expected = PaymentMethodsException.class) + public void complainsIfFilteringForOtherWallet() { + final PaymentMethods pms = new WalletPaymentMethods( + Mockito.mock(Wallet.class), + Stream::empty, + Mockito.mock(Storage.class) + ); + pms.ofWallet(Mockito.mock(Wallet.class)); + } + + /** + * Returns active PaymentMethod. + */ + @Test + public void returnsActivePaymentMethod() { + final Storage storage = Mockito.mock(Storage.class); + final PaymentMethods all = Mockito.mock(PaymentMethods.class); + Mockito.when(storage.paymentMethods()).thenReturn(all); + + final PaymentMethod active = Mockito.mock(PaymentMethod.class); + Mockito.when(active.active()).thenReturn(true); + + final Wallet wallet = Mockito.mock(Wallet.class); + final PaymentMethods pms = new WalletPaymentMethods( + wallet, + () -> Stream.of( + Mockito.mock(PaymentMethod.class), + Mockito.mock(PaymentMethod.class), + Mockito.mock(PaymentMethod.class), + active + ), + storage + ); + + MatcherAssert.assertThat(pms.active(), Matchers.equalTo(active)); + } + + /** + * Can activate a PaymentMethod. + */ + @Test + public void canActivatePaymentMethod() { + final Storage storage = Mockito.mock(Storage.class); + final PaymentMethods all = Mockito.mock(PaymentMethods.class); + Mockito.when(storage.paymentMethods()).thenReturn(all); + + final Wallet wallet = Mockito.mock(Wallet.class); + final PaymentMethod pmeth = Mockito.mock(PaymentMethod.class); + Mockito.when(pmeth.wallet()).thenReturn(wallet); + + final PaymentMethods pms = new WalletPaymentMethods( + wallet, + () -> Stream.of(pmeth), + storage + ); + + pms.activate(pmeth); + + Mockito.verify(all).activate(pmeth); + } + + /** + * Complains when activate PaymentMethod if is attached to other Wallet. + */ + @Test(expected = PaymentMethodsException.class) + public void complainsWhenActivatePaymentMethodIfAttachedToOtherWallet() { + final Storage storage = Mockito.mock(Storage.class); + final PaymentMethods all = Mockito.mock(PaymentMethods.class); + Mockito.when(storage.paymentMethods()).thenReturn(all); + + final Wallet wallet = Mockito.mock(Wallet.class); + final PaymentMethod pmeth = Mockito.mock(PaymentMethod.class); + Mockito.when(pmeth.wallet()).thenReturn(Mockito.mock(Wallet.class)); + + final PaymentMethods pms = new WalletPaymentMethods( + wallet, + Stream::empty, + storage + ); + + pms.activate(pmeth); + } +}