diff --git a/commonui/src/main/java/com/hyperwallet/android/ui/common/intent/HyperwalletIntent.java b/commonui/src/main/java/com/hyperwallet/android/ui/common/intent/HyperwalletIntent.java
index d87c5d13d..992ddfb3f 100644
--- a/commonui/src/main/java/com/hyperwallet/android/ui/common/intent/HyperwalletIntent.java
+++ b/commonui/src/main/java/com/hyperwallet/android/ui/common/intent/HyperwalletIntent.java
@@ -65,6 +65,11 @@ private HyperwalletIntent() {
*/
public static final short SELECT_TRANSFER_SOURCE_REQUEST_CODE = 104;
+ /**
+ * Update Transfer method request code
+ */
+ public static final short UPDATE_TRANSFER_METHOD_REQUEST_CODE = 105;
+
/**
* SDK Broadcast payload error
*/
@@ -81,5 +86,10 @@ private HyperwalletIntent() {
*/
public static final String EXTRA_TRANSFER_METHOD_ADDED = "EXTRA_TRANSFER_METHOD_ADDED";
+ /**
+ * Transfer method updated, extra activity parcelable transfer method payload
+ */
+ public static final String EXTRA_TRANSFER_METHOD_UPDATED = "EXTRA_TRANSFER_METHOD_UPDATED";
+
}
diff --git a/commonui/src/main/res/drawable/ic_edit.xml b/commonui/src/main/res/drawable/ic_edit.xml
new file mode 100644
index 000000000..bf16bd5cc
--- /dev/null
+++ b/commonui/src/main/res/drawable/ic_edit.xml
@@ -0,0 +1,12 @@
+
+
+
diff --git a/commonui/src/main/res/drawable/ic_trash.xml b/commonui/src/main/res/drawable/ic_trash.xml
index 5fdcd6dfe..caa047ad8 100644
--- a/commonui/src/main/res/drawable/ic_trash.xml
+++ b/commonui/src/main/res/drawable/ic_trash.xml
@@ -1,20 +1,12 @@
-
-
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
diff --git a/commonui/src/main/res/values/strings.xml b/commonui/src/main/res/values/strings.xml
index d1ece3372..c350f1971 100644
--- a/commonui/src/main/res/values/strings.xml
+++ b/commonui/src/main/res/values/strings.xml
@@ -33,6 +33,7 @@
Authentication Error
Cancel
+ Edit
Remove
Are you sure?
diff --git a/transfermethodrepository/src/main/java/com/hyperwallet/android/ui/transfermethod/repository/TransferMethodConfigurationRepositoryImpl.java b/transfermethodrepository/src/main/java/com/hyperwallet/android/ui/transfermethod/repository/TransferMethodConfigurationRepositoryImpl.java
index c953ff758..a6a2793a9 100644
--- a/transfermethodrepository/src/main/java/com/hyperwallet/android/ui/transfermethod/repository/TransferMethodConfigurationRepositoryImpl.java
+++ b/transfermethodrepository/src/main/java/com/hyperwallet/android/ui/transfermethod/repository/TransferMethodConfigurationRepositoryImpl.java
@@ -184,6 +184,11 @@ class FieldMapKey {
this.mTransferMethodType = mTransferMethodType;
}
+ FieldMapKey() {
+ this.mCountry = null;
+ this.mCurrency = null;
+ this.mTransferMethodType = null;
+ }
private String getCountry() {
return mCountry;
}
diff --git a/transfermethodrepository/src/main/java/com/hyperwallet/android/ui/transfermethod/repository/TransferMethodRepository.java b/transfermethodrepository/src/main/java/com/hyperwallet/android/ui/transfermethod/repository/TransferMethodRepository.java
index f11f896c5..d94d7279c 100644
--- a/transfermethodrepository/src/main/java/com/hyperwallet/android/ui/transfermethod/repository/TransferMethodRepository.java
+++ b/transfermethodrepository/src/main/java/com/hyperwallet/android/ui/transfermethod/repository/TransferMethodRepository.java
@@ -46,6 +46,17 @@ void createTransferMethod(@NonNull TransferMethod transferMethod,
*/
void loadTransferMethods(@NonNull LoadTransferMethodListCallback callback);
+
+ /**
+ * Update transfer method specified.
+ *
+ * @param transferMethod transfer method to deactivate @see {@link TransferMethod}
+ * @param callback @see {@link DeactivateTransferMethodCallback}
+ */
+ void updateTransferMethod(@NonNull final TransferMethod transferMethod,
+ @NonNull LoadTransferMethodCallback callback);
+
+
/**
* Load latest transfer methods available, associated with current context
*
diff --git a/transfermethodrepository/src/main/java/com/hyperwallet/android/ui/transfermethod/repository/TransferMethodRepositoryFactory.java b/transfermethodrepository/src/main/java/com/hyperwallet/android/ui/transfermethod/repository/TransferMethodRepositoryFactory.java
index ed9360c6f..daede99ff 100644
--- a/transfermethodrepository/src/main/java/com/hyperwallet/android/ui/transfermethod/repository/TransferMethodRepositoryFactory.java
+++ b/transfermethodrepository/src/main/java/com/hyperwallet/android/ui/transfermethod/repository/TransferMethodRepositoryFactory.java
@@ -20,10 +20,12 @@ public class TransferMethodRepositoryFactory {
private static TransferMethodRepositoryFactory sInstance;
private TransferMethodRepository mTransferMethodRepository;
private TransferMethodConfigurationRepository mTransferMethodConfigurationRepository;
+ private TransferMethodUpdateConfigurationRepository mTransferMethodUpdateConfigurationRepository;
private TransferMethodRepositoryFactory() {
mTransferMethodRepository = new TransferMethodRepositoryImpl();
mTransferMethodConfigurationRepository = new TransferMethodConfigurationRepositoryImpl();
+ mTransferMethodUpdateConfigurationRepository = new TransferMethodUpdateConfigurationRepositoryImpl();
}
public static synchronized TransferMethodRepositoryFactory getInstance() {
@@ -44,4 +46,9 @@ public TransferMethodRepository getTransferMethodRepository() {
public TransferMethodConfigurationRepository getTransferMethodConfigurationRepository() {
return mTransferMethodConfigurationRepository;
}
+
+ public TransferMethodUpdateConfigurationRepository getTransferMethodUpdateConfigurationRepository() {
+ return mTransferMethodUpdateConfigurationRepository;
+ }
+
}
diff --git a/transfermethodrepository/src/main/java/com/hyperwallet/android/ui/transfermethod/repository/TransferMethodRepositoryImpl.java b/transfermethodrepository/src/main/java/com/hyperwallet/android/ui/transfermethod/repository/TransferMethodRepositoryImpl.java
index 89299912f..5252bfa8a 100644
--- a/transfermethodrepository/src/main/java/com/hyperwallet/android/ui/transfermethod/repository/TransferMethodRepositoryImpl.java
+++ b/transfermethodrepository/src/main/java/com/hyperwallet/android/ui/transfermethod/repository/TransferMethodRepositoryImpl.java
@@ -123,6 +123,31 @@ public Handler getHandler() {
});
}
+ @Override
+ public void updateTransferMethod(@NonNull TransferMethod transferMethod,
+ @NonNull LoadTransferMethodCallback callback) {
+ switch (transferMethod.getField(TYPE)) {
+ case BANK_ACCOUNT:
+ case WIRE_ACCOUNT:
+ updateBankAccount(transferMethod, callback);
+ break;
+ case BANK_CARD:
+ updateBankCard(transferMethod, callback);
+ break;
+ case PAYPAL_ACCOUNT:
+ updatePayPalAccount(transferMethod, callback);
+ break;
+ case VENMO_ACCOUNT:
+ updateVenmoAccount(transferMethod, callback);
+ break;
+ case PAPER_CHECK:
+ updatePaperCheck(transferMethod, callback);
+ break;
+ default: // error on unknown transfer type
+ callback.onError(getErrorsOnUnsupportedTransferType());
+ }
+ }
+
/**
* @see TransferMethodRepository#loadLatestTransferMethod(LoadTransferMethodCallback)
*/
@@ -247,7 +272,7 @@ public Handler getHandler() {
}
private void deactivateVenmoAccount(@NonNull final TransferMethod transferMethod,
- @NonNull final DeactivateTransferMethodCallback callback) {
+ @NonNull final DeactivateTransferMethodCallback callback) {
getHyperwallet().deactivateVenmoAccount(transferMethod.getField(TOKEN), null,
new HyperwalletListener() {
@Override
@@ -289,7 +314,7 @@ public Handler getHandler() {
}
private void createBankAccount(final TransferMethod transferMethod,
- final LoadTransferMethodCallback callback) {
+ final LoadTransferMethodCallback callback) {
BankAccount bankAccount = (BankAccount) transferMethod;
getHyperwallet().createBankAccount(bankAccount, new HyperwalletListener() {
@@ -333,7 +358,7 @@ public Handler getHandler() {
}
private void createPayPalAccount(@NonNull final TransferMethod transferMethod,
- @NonNull final LoadTransferMethodCallback callback) {
+ @NonNull final LoadTransferMethodCallback callback) {
PayPalAccount payPalAccount = (PayPalAccount) transferMethod;
getHyperwallet().createPayPalAccount(payPalAccount, new HyperwalletListener() {
@@ -355,7 +380,7 @@ public Handler getHandler() {
}
private void createVenmoAccount(@NonNull final TransferMethod transferMethod,
- @NonNull final LoadTransferMethodCallback callback) {
+ @NonNull final LoadTransferMethodCallback callback) {
VenmoAccount venmoAccount = (VenmoAccount) transferMethod;
getHyperwallet().createVenmoAccount(venmoAccount, new HyperwalletListener() {
@@ -405,4 +430,115 @@ private Errors getErrorsOnUnsupportedTransferType() {
EC_UNEXPECTED_EXCEPTION);
return new Errors(Collections.singletonList(error));
}
+
+ private void updateBankAccount(final TransferMethod transferMethod,
+ final LoadTransferMethodCallback callback) {
+ BankAccount bankAccount = (BankAccount) transferMethod;
+
+ getHyperwallet().updateBankAccount(bankAccount, new HyperwalletListener() {
+ @Override
+ public void onSuccess(@Nullable BankAccount result) {
+ callback.onTransferMethodLoaded(result);
+ }
+
+ @Override
+ public void onFailure(HyperwalletException exception) {
+ callback.onError(exception.getErrors());
+ }
+
+ @Override
+ public Handler getHandler() {
+ return mHandler;
+ }
+ });
+ }
+
+ private void updateBankCard(@NonNull final TransferMethod transferMethod,
+ @NonNull final LoadTransferMethodCallback callback) {
+ BankCard bankCard = (BankCard) transferMethod;
+
+ getHyperwallet().updateBankCard(bankCard, new HyperwalletListener() {
+ @Override
+ public void onSuccess(@Nullable BankCard result) {
+ callback.onTransferMethodLoaded(result);
+ }
+
+ @Override
+ public void onFailure(HyperwalletException exception) {
+ callback.onError(exception.getErrors());
+ }
+
+ @Override
+ public Handler getHandler() {
+ return mHandler;
+ }
+ });
+ }
+
+ private void updatePayPalAccount(@NonNull final TransferMethod transferMethod,
+ @NonNull final LoadTransferMethodCallback callback) {
+ PayPalAccount payPalAccount = (PayPalAccount) transferMethod;
+
+ getHyperwallet().updatePayPalAccount(payPalAccount, new HyperwalletListener() {
+ @Override
+ public void onSuccess(@Nullable PayPalAccount result) {
+ callback.onTransferMethodLoaded(result);
+ }
+
+ @Override
+ public void onFailure(HyperwalletException exception) {
+ callback.onError(exception.getErrors());
+ }
+
+ @Override
+ public Handler getHandler() {
+ return mHandler;
+ }
+ });
+ }
+
+ private void updateVenmoAccount(@NonNull final TransferMethod transferMethod,
+ @NonNull final LoadTransferMethodCallback callback) {
+ VenmoAccount venmoAccount = (VenmoAccount) transferMethod;
+
+ getHyperwallet().updateVenmoAccount(venmoAccount, new HyperwalletListener() {
+ @Override
+ public void onSuccess(@Nullable VenmoAccount result) {
+ callback.onTransferMethodLoaded(result);
+ }
+
+ @Override
+ public void onFailure(HyperwalletException exception) {
+ callback.onError(exception.getErrors());
+ }
+
+ @Override
+ public Handler getHandler() {
+ return mHandler;
+ }
+ });
+ }
+
+ private void updatePaperCheck(@NonNull final TransferMethod transferMethod,
+ @NonNull final LoadTransferMethodCallback callback) {
+ PaperCheck paperCheck = (PaperCheck) transferMethod;
+
+ getHyperwallet().updatePaperCheck(paperCheck, new HyperwalletListener() {
+ @Override
+ public void onSuccess(@Nullable PaperCheck result) {
+ callback.onTransferMethodLoaded(result);
+ }
+
+ @Override
+ public void onFailure(HyperwalletException exception) {
+ callback.onError(exception.getErrors());
+ }
+
+ @Override
+ public Handler getHandler() {
+ return mHandler;
+ }
+ });
+ }
+
}
diff --git a/transfermethodrepository/src/main/java/com/hyperwallet/android/ui/transfermethod/repository/TransferMethodUpdateConfigurationRepository.java b/transfermethodrepository/src/main/java/com/hyperwallet/android/ui/transfermethod/repository/TransferMethodUpdateConfigurationRepository.java
new file mode 100644
index 000000000..5110c62f5
--- /dev/null
+++ b/transfermethodrepository/src/main/java/com/hyperwallet/android/ui/transfermethod/repository/TransferMethodUpdateConfigurationRepository.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2018 Hyperwallet
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated
+ * documentation files (the "Software"), to deal in the Software without restriction, including
+ * without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and
+ * to permit persons to whom the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of
+ * the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO
+ * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
+ * EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+package com.hyperwallet.android.ui.transfermethod.repository;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.hyperwallet.android.model.Errors;
+import com.hyperwallet.android.model.graphql.HyperwalletTransferMethodConfigurationField;
+
+public interface TransferMethodUpdateConfigurationRepository {
+
+ void getFields(@NonNull final String transferMethodToken,
+ @NonNull final LoadFieldsCallback loadFieldsCallback);
+
+
+ void refreshFields();
+
+ interface LoadFieldsCallback {
+
+ void onFieldsLoaded(@Nullable final HyperwalletTransferMethodConfigurationField field);
+
+ void onError(@NonNull final Errors errors);
+ }
+}
diff --git a/transfermethodrepository/src/main/java/com/hyperwallet/android/ui/transfermethod/repository/TransferMethodUpdateConfigurationRepositoryImpl.java b/transfermethodrepository/src/main/java/com/hyperwallet/android/ui/transfermethod/repository/TransferMethodUpdateConfigurationRepositoryImpl.java
new file mode 100644
index 000000000..59ba2a218
--- /dev/null
+++ b/transfermethodrepository/src/main/java/com/hyperwallet/android/ui/transfermethod/repository/TransferMethodUpdateConfigurationRepositoryImpl.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2018 Hyperwallet
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated
+ * documentation files (the "Software"), to deal in the Software without restriction, including
+ * without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and
+ * to permit persons to whom the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of
+ * the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO
+ * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
+ * EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+package com.hyperwallet.android.ui.transfermethod.repository;
+
+import android.os.Handler;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+
+import com.hyperwallet.android.Hyperwallet;
+import com.hyperwallet.android.exception.HyperwalletException;
+import com.hyperwallet.android.listener.HyperwalletListener;
+import com.hyperwallet.android.model.graphql.HyperwalletTransferMethodConfigurationField;
+import com.hyperwallet.android.model.graphql.HyperwalletTransferMethodConfigurationKey;
+import com.hyperwallet.android.model.graphql.query.TransferMethodUpdateConfigurationFieldQuery;
+import com.hyperwallet.android.ui.common.repository.EspressoIdlingResource;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class TransferMethodUpdateConfigurationRepositoryImpl implements TransferMethodUpdateConfigurationRepository {
+ private final Handler mHandler;
+ private final Map mFieldMap;
+
+ public TransferMethodUpdateConfigurationRepositoryImpl() {
+ mHandler = new Handler();
+ mFieldMap = new HashMap<>();
+ }
+
+ @VisibleForTesting()
+ protected TransferMethodUpdateConfigurationRepositoryImpl(@Nullable Handler handler,
+ Map fieldMap) {
+ mHandler = handler;
+ mFieldMap = fieldMap;
+ }
+
+ @VisibleForTesting
+ Hyperwallet getHyperwallet() {
+ return Hyperwallet.getDefault();
+ }
+
+ @VisibleForTesting
+ void getTransferMethodConfigurationFieldResult(
+ @NonNull final String transferMethodToken,
+ @NonNull final LoadFieldsCallback loadFieldsCallback) {
+ TransferMethodUpdateConfigurationFieldQuery query = new TransferMethodUpdateConfigurationFieldQuery(
+ transferMethodToken);
+ EspressoIdlingResource.increment();
+
+ getHyperwallet().retrieveUpdateTransferMethodConfigurationFields(
+ query,
+ new HyperwalletListener() {
+ @Override
+ public void onSuccess(HyperwalletTransferMethodConfigurationField result) {
+ FieldMapKey fieldMapKey = new FieldMapKey();
+ mFieldMap.put(fieldMapKey, result);
+ loadFieldsCallback.onFieldsLoaded(result);
+ EspressoIdlingResource.decrement();
+ }
+
+ @Override
+ public void onFailure(HyperwalletException exception) {
+ loadFieldsCallback.onError(exception.getErrors());
+ EspressoIdlingResource.decrement();
+ }
+
+ @Override
+ public Handler getHandler() {
+ return mHandler;
+ }
+ });
+
+ }
+
+ @Override
+ public synchronized void getFields(
+ @NonNull final String transferMethodToken,
+ @NonNull final LoadFieldsCallback loadFieldsCallback) {
+
+ getTransferMethodConfigurationFieldResult(transferMethodToken, loadFieldsCallback);
+ }
+
+ @Override
+ public void refreshFields() {
+ mFieldMap.clear();
+ }
+
+}
\ No newline at end of file
diff --git a/transfermethodrepository/src/test/java/com/hyperwallet/android/ui/transfermethod/repository/FieldMapKeyTest.java b/transfermethodrepository/src/test/java/com/hyperwallet/android/ui/transfermethod/repository/FieldMapKeyTest.java
index f0541bb9a..2b18445a9 100644
--- a/transfermethodrepository/src/test/java/com/hyperwallet/android/ui/transfermethod/repository/FieldMapKeyTest.java
+++ b/transfermethodrepository/src/test/java/com/hyperwallet/android/ui/transfermethod/repository/FieldMapKeyTest.java
@@ -13,6 +13,12 @@ public void testEquals_withSameReference() {
assertEquals(thisKey, thisKey);
}
+ @Test
+ public void testEquals_withSameReference_withAnotherConstructor() {
+ FieldMapKey thisKey = new FieldMapKey();
+ assertEquals(thisKey, thisKey);
+ }
+
@Test
public void testEquals_withDifferentObjectType() {
FieldMapKey thisKey = new FieldMapKey("US", "USD", "BANK_ACCOUNT");
@@ -33,5 +39,4 @@ public void testEquals_withDifferentReferencesDifferentValues() {
FieldMapKey thatKey = new FieldMapKey("CA", "CAD", "BANK_ACCOUNT");
assertNotEquals(thisKey, thatKey);
}
-
}
diff --git a/transfermethodrepository/src/test/java/com/hyperwallet/android/ui/transfermethod/repository/TransferMethodRepositoryFactoryTest.java b/transfermethodrepository/src/test/java/com/hyperwallet/android/ui/transfermethod/repository/TransferMethodRepositoryFactoryTest.java
index 7e89c5a03..232f724f3 100644
--- a/transfermethodrepository/src/test/java/com/hyperwallet/android/ui/transfermethod/repository/TransferMethodRepositoryFactoryTest.java
+++ b/transfermethodrepository/src/test/java/com/hyperwallet/android/ui/transfermethod/repository/TransferMethodRepositoryFactoryTest.java
@@ -14,6 +14,7 @@ public void testGetInstance_verifyRepositoriesInitialized() {
assertThat(repositoryFactory, is(notNullValue()));
assertThat(repositoryFactory.getTransferMethodRepository(), is(notNullValue()));
assertThat(repositoryFactory.getTransferMethodConfigurationRepository(), is(notNullValue()));
+ assertThat(repositoryFactory.getTransferMethodUpdateConfigurationRepository(), is(notNullValue()));
}
@Test
@@ -23,10 +24,13 @@ public void testClearInstance_verifyRepositoryCleared() {
TransferMethodRepository transferMethodRepository = repositoryFactory.getTransferMethodRepository();
TransferMethodConfigurationRepository configurationRepository =
repositoryFactory.getTransferMethodConfigurationRepository();
+ TransferMethodUpdateConfigurationRepository transferMethodUpdateConfigurationRepository =
+ repositoryFactory.getTransferMethodUpdateConfigurationRepository();
TransferMethodRepositoryFactory currentRepositoryFactory = TransferMethodRepositoryFactory.getInstance();
assertThat(repositoryFactory, is(currentRepositoryFactory));
assertThat(transferMethodRepository, is(currentRepositoryFactory.getTransferMethodRepository()));
assertThat(configurationRepository, is(currentRepositoryFactory.getTransferMethodConfigurationRepository()));
+ assertThat(transferMethodUpdateConfigurationRepository,is(currentRepositoryFactory.getTransferMethodUpdateConfigurationRepository()));
TransferMethodRepositoryFactory.clearInstance();
@@ -35,5 +39,6 @@ public void testClearInstance_verifyRepositoryCleared() {
assertThat(transferMethodRepository, is(not(anotherRepositoryFactory.getTransferMethodRepository())));
assertThat(configurationRepository,
is(not(anotherRepositoryFactory.getTransferMethodConfigurationRepository())));
+ assertThat(transferMethodUpdateConfigurationRepository,is(not(anotherRepositoryFactory.getTransferMethodUpdateConfigurationRepository())));
}
}
\ No newline at end of file
diff --git a/transfermethodrepository/src/test/java/com/hyperwallet/android/ui/transfermethod/repository/TransferMethodRepositoryImplTest.java b/transfermethodrepository/src/test/java/com/hyperwallet/android/ui/transfermethod/repository/TransferMethodRepositoryImplTest.java
index 272678bee..0018dff20 100644
--- a/transfermethodrepository/src/test/java/com/hyperwallet/android/ui/transfermethod/repository/TransferMethodRepositoryImplTest.java
+++ b/transfermethodrepository/src/test/java/com/hyperwallet/android/ui/transfermethod/repository/TransferMethodRepositoryImplTest.java
@@ -34,6 +34,7 @@
import com.hyperwallet.android.model.paging.PageList;
import com.hyperwallet.android.model.transfermethod.BankAccount;
import com.hyperwallet.android.model.transfermethod.BankCard;
+import com.hyperwallet.android.model.transfermethod.PaperCheck;
import com.hyperwallet.android.model.transfermethod.TransferMethod;
import com.hyperwallet.android.model.transfermethod.TransferMethodQueryParam;
import com.hyperwallet.android.model.transfermethod.PayPalAccount;
@@ -87,7 +88,7 @@ public class TransferMethodRepositoryImplTest {
@Captor
private ArgumentCaptor mVenmoAccountArgumentCaptor;
@Captor
- private ArgumentCaptor mPaperCheckArgumentCaptor; //todo paper check
+ private ArgumentCaptor mPaperCheckArgumentCaptor;
@Captor
private ArgumentCaptor mStatusTransitionArgumentCaptor;
@Captor
@@ -143,6 +144,41 @@ public Object answer(InvocationOnMock invocation) {
assertThat(transferMethod.getField(BANK_ACCOUNT_ID), is("3423423432"));
}
+ @Test
+ public void testUpdateTransferMethod_bankAccountWithSuccess() {
+ BankAccount bankAccount = new BankAccount
+ .Builder("CA", "CAD", "3423423432")
+ .build();
+
+ doAnswer(new Answer() {
+ @Override
+ public Object answer(InvocationOnMock invocation) {
+ HyperwalletListener listener = (HyperwalletListener) invocation.getArguments()[1];
+ BankAccount returnedBank = new BankAccount
+ .Builder("CA", "CAD", "3423423432")
+ .bankName("Mock Bank Response")
+ .build();
+ listener.onSuccess(returnedBank);
+ return listener;
+ }
+ }).when(mHyperwallet).updateBankAccount(any(BankAccount.class),
+ ArgumentMatchers.>any());
+
+ // test
+ mTransferMethodRepository.updateTransferMethod(bankAccount, mLoadTransferMethodCallback);
+
+ verify(mLoadTransferMethodCallback).onTransferMethodLoaded(mBankAccountArgumentCaptor.capture());
+ verify(mLoadTransferMethodCallback, never()).onError(any(Errors.class));
+
+ BankAccount transferMethod = mBankAccountArgumentCaptor.getValue();
+ assertThat(transferMethod, is(notNullValue()));
+ assertThat(transferMethod.getField(TYPE), is(TransferMethod.TransferMethodTypes.BANK_ACCOUNT));
+ assertThat(transferMethod.getField(BANK_NAME), is("Mock Bank Response"));
+ assertThat(transferMethod.getField(TRANSFER_METHOD_COUNTRY), is("CA"));
+ assertThat(transferMethod.getField(TRANSFER_METHOD_CURRENCY), is("CAD"));
+ assertThat(transferMethod.getField(BANK_ACCOUNT_ID), is("3423423432"));
+ }
+
@Test
public void testCreateTransferMethod_bankAccountWithError() {
BankAccount bankAccount = new BankAccount
@@ -173,6 +209,35 @@ public Object answer(InvocationOnMock invocation) {
assertThat(mErrorsArgumentCaptor.getValue().getErrors(), hasItem(error));
}
+ @Test
+ public void testUpdateTransferMethod_bankAccountWithError() {
+ BankAccount bankAccount = new BankAccount
+ .Builder(COUNTRY_US, CURRENCY_USD, "23432432")
+ .build();
+
+ final Error error = new Error(TEST_MESSAGE, TEST_CODE);
+
+ doAnswer(new Answer() {
+ @Override
+ public Object answer(InvocationOnMock invocation) {
+ HyperwalletListener listener = (HyperwalletListener) invocation.getArguments()[1];
+ List errorList = new ArrayList<>();
+ errorList.add(error);
+ Errors errors = new Errors(errorList);
+ HyperwalletException exception = new HyperwalletException(errors);
+ listener.onFailure(exception);
+ return listener;
+ }
+ }).when(mHyperwallet).updateBankAccount(any(BankAccount.class),
+ ArgumentMatchers.>any());
+
+ // test
+ mTransferMethodRepository.updateTransferMethod(bankAccount, mLoadTransferMethodCallback);
+
+ verify(mLoadTransferMethodCallback).onError(mErrorsArgumentCaptor.capture());
+ verify(mLoadTransferMethodCallback, never()).onTransferMethodLoaded(any(TransferMethod.class));
+ assertThat(mErrorsArgumentCaptor.getValue().getErrors(), hasItem(error));
+ }
@Test
public void testCreateTransferMethod_withUnsupportedTransferMethodType() {
BankAccount bankAccount = new BankAccount
@@ -485,6 +550,40 @@ public Object answer(InvocationOnMock invocation) {
assertThat(transferMethod.getField(TransferMethod.TransferMethodFields.CARD_TYPE), is("cardType"));
}
+ @Test
+ public void testUpdateTransferMethod_bankCardWithSuccess() {
+ BankCard bankCard = new BankCard
+ .Builder("CA", "CAD", "1232345456784", "2019-05", "234")
+ .build();
+
+ doAnswer(new Answer() {
+ @Override
+ public Object answer(InvocationOnMock invocation) {
+ HyperwalletListener listener = (HyperwalletListener) invocation.getArguments()[1];
+ BankCard returnedBankCard = new BankCard
+ .Builder("CA", "CAD", "1232345456784", "2019-05", "234")
+ .cardBrand("Brand")
+ .cardType("cardType")
+ .build();
+ listener.onSuccess(returnedBankCard);
+ return listener;
+ }
+ }).when(mHyperwallet).updateBankCard(any(BankCard.class),
+ ArgumentMatchers.>any());
+
+ // test
+ mTransferMethodRepository.updateTransferMethod(bankCard, mLoadTransferMethodCallback);
+
+ verify(mLoadTransferMethodCallback).onTransferMethodLoaded(mBankCardArgumentCaptor.capture());
+ verify(mLoadTransferMethodCallback, never()).onError(any(Errors.class));
+
+ BankCard transferMethod = mBankCardArgumentCaptor.getValue();
+ assertThat(transferMethod, is(notNullValue()));
+ assertThat(transferMethod.getField(TYPE), is(TransferMethod.TransferMethodTypes.BANK_CARD));
+ assertThat(transferMethod.getField(TransferMethod.TransferMethodFields.CARD_BRAND), is("Brand"));
+ assertThat(transferMethod.getField(TransferMethod.TransferMethodFields.CARD_TYPE), is("cardType"));
+ }
+
@Test
public void testCreateTransferMethod_bankCardWithError() {
BankCard bankCard = new BankCard
@@ -514,7 +613,35 @@ public Object answer(InvocationOnMock invocation) {
verify(mLoadTransferMethodCallback, never()).onTransferMethodLoaded(any(TransferMethod.class));
assertThat(mErrorsArgumentCaptor.getValue().getErrors(), hasItem(error));
}
+ @Test
+ public void testUpdateTransferMethod_bankCardWithError() {
+ BankCard bankCard = new BankCard
+ .Builder("CA", "CAD", "1232345456784", "2019-05", "234")
+ .build();
+
+ final Error error = new Error("bank card test message", "BANK_CARD_TEST_CODE");
+
+ doAnswer(new Answer() {
+ @Override
+ public Object answer(InvocationOnMock invocation) {
+ HyperwalletListener listener = (HyperwalletListener) invocation.getArguments()[1];
+ List errorList = new ArrayList<>();
+ errorList.add(error);
+ Errors errors = new Errors(errorList);
+ HyperwalletException exception = new HyperwalletException(errors);
+ listener.onFailure(exception);
+ return listener;
+ }
+ }).when(mHyperwallet).updateBankCard(any(BankCard.class),
+ ArgumentMatchers.>any());
+
+ // test
+ mTransferMethodRepository.updateTransferMethod(bankCard, mLoadTransferMethodCallback);
+ verify(mLoadTransferMethodCallback).onError(mErrorsArgumentCaptor.capture());
+ verify(mLoadTransferMethodCallback, never()).onTransferMethodLoaded(any(TransferMethod.class));
+ assertThat(mErrorsArgumentCaptor.getValue().getErrors(), hasItem(error));
+ }
@Test
public void testLoadTransferMethod_returnsBankAccount() {
@@ -722,6 +849,42 @@ public Object answer(InvocationOnMock invocation) {
assertThat(payPalAccount.getField(TOKEN), is("trm-token-1342242314"));
}
+ // @Test
+ public void testUpdateTransferMethod_payPalAccountWithSuccess() {
+ // prepare
+ final PayPalAccount returnedPayPalAccount = new PayPalAccount.Builder()
+ .email("money@mail.com")
+ .token("trm-token-1342242314")
+ .build();
+
+ doAnswer(new Answer() {
+ @Override
+ public Object answer(InvocationOnMock invocation) {
+ HyperwalletListener listener = (HyperwalletListener) invocation.getArguments()[1];
+ returnedPayPalAccount.setField(STATUS, ACTIVATED);
+ listener.onSuccess(returnedPayPalAccount);
+ return listener;
+ }
+ }).when(mHyperwallet).updatePayPalAccount(any(PayPalAccount.class),
+ ArgumentMatchers.>any());
+
+ PayPalAccount parameter = new PayPalAccount.Builder().build();
+
+ // test
+ mTransferMethodRepository.updateTransferMethod(parameter, mLoadTransferMethodCallback);
+
+ // verify
+ verify(mLoadTransferMethodCallback).onTransferMethodLoaded(mPayPalAccountArgumentCaptor.capture());
+ verify(mLoadTransferMethodCallback, never()).onError(any(Errors.class));
+
+ // assert
+ PayPalAccount payPalAccount = mPayPalAccountArgumentCaptor.getValue();
+ assertThat(payPalAccount, is(notNullValue()));
+ assertThat(payPalAccount.getEmail(), is("money@mail.com"));
+ assertThat(payPalAccount.getField(STATUS), is(ACTIVATED));
+ assertThat(payPalAccount.getField(TOKEN), is("trm-token-1342242314"));
+ }
+
@Test
public void testCreateTransferMethod_payPalAccountWithError() {
// prepare
@@ -753,6 +916,37 @@ public Object answer(InvocationOnMock invocation) {
assertThat(mErrorsArgumentCaptor.getValue().getErrors(), hasItem(returnedError));
}
+ // @Test
+ public void testUpdateTransferMethod_payPalAccountWithError() {
+ // prepare
+ final Error returnedError = new Error("PayPal test message", "PAYPAL_TEST_CODE");
+
+ doAnswer(new Answer() {
+ @Override
+ public Object answer(InvocationOnMock invocation) {
+ HyperwalletListener listener = (HyperwalletListener) invocation.getArguments()[1];
+
+ List errorList = new ArrayList<>();
+ errorList.add(returnedError);
+
+ listener.onFailure(new HyperwalletException(new Errors(errorList)));
+ return listener;
+ }
+ }).when(mHyperwallet).updatePayPalAccount(any(PayPalAccount.class),
+ ArgumentMatchers.>any());
+ PayPalAccount parameter = new PayPalAccount.Builder().build();
+
+ // test
+ mTransferMethodRepository.updateTransferMethod(parameter, mLoadTransferMethodCallback);
+
+ // verify
+ verify(mLoadTransferMethodCallback, never()).onTransferMethodLoaded(any(TransferMethod.class));
+ verify(mLoadTransferMethodCallback).onError(mErrorsArgumentCaptor.capture());
+
+ // assert
+ assertThat(mErrorsArgumentCaptor.getValue().getErrors(), hasItem(returnedError));
+ }
+
@Test
public void createTransferMethod_venmoAccountWithSuccess() {
final VenmoAccount returnedVenmoAccount = buildVenmoAccount();
@@ -782,11 +976,7 @@ public Object answer(InvocationOnMock invocation) {
assertThat(venmoAccount.getField(TOKEN), is(TEST_TOKEN));
}
- @Test
- public void createTransferMethod_paperCheckWithSuccess() {
-
- //Todo paper check
-
+ public void updateTransferMethod_venmoAccountWithSuccess() {
final VenmoAccount returnedVenmoAccount = buildVenmoAccount();
doAnswer(new Answer() {
@Override
@@ -796,11 +986,11 @@ public Object answer(InvocationOnMock invocation) {
listener.onSuccess(returnedVenmoAccount);
return listener;
}
- }).when(mHyperwallet).createVenmoAccount(any(VenmoAccount.class), any(HyperwalletListener.class));
+ }).when(mHyperwallet).updateVenmoAccount(any(VenmoAccount.class), any(HyperwalletListener.class));
VenmoAccount parameter = new VenmoAccount.Builder().build();
- mTransferMethodRepository.createTransferMethod(parameter, mLoadTransferMethodCallback);
+ mTransferMethodRepository.updateTransferMethod(parameter, mLoadTransferMethodCallback);
verify(mLoadTransferMethodCallback).onTransferMethodLoaded(mVenmoAccountArgumentCaptor.capture());
verify(mLoadTransferMethodCallback, never()).onError(any(Errors.class));
@@ -814,6 +1004,61 @@ public Object answer(InvocationOnMock invocation) {
assertThat(venmoAccount.getField(TOKEN), is(TEST_TOKEN));
}
+ @Test
+ public void createTransferMethod_paperCheckWithSuccess() {
+ final PaperCheck returnedPaperCheck = buildPaperCheck();
+ doAnswer(new Answer() {
+ @Override
+ public Object answer(InvocationOnMock invocation) {
+ HyperwalletListener listener = (HyperwalletListener) invocation.getArguments()[1];
+ returnedPaperCheck.setField(STATUS, ACTIVATED);
+ listener.onSuccess(returnedPaperCheck);
+ return listener;
+ }
+ }).when(mHyperwallet).createPaperCheck(any(PaperCheck.class), any(HyperwalletListener.class));
+
+ PaperCheck parameter = new PaperCheck.Builder().build();
+
+ mTransferMethodRepository.createTransferMethod(parameter, mLoadTransferMethodCallback);
+
+ verify(mLoadTransferMethodCallback).onTransferMethodLoaded(mPaperCheckArgumentCaptor.capture());
+ verify(mLoadTransferMethodCallback, never()).onError(any(Errors.class));
+
+ PaperCheck paperCheck = mPaperCheckArgumentCaptor.getValue();
+ assertThat(paperCheck, is(notNullValue()));
+ assertThat(paperCheck.getCountry(), is(COUNTRY_US));
+ assertThat(paperCheck.getCurrency(), is(CURRENCY_USD));
+ assertThat(paperCheck.getField(STATUS), is(ACTIVATED));
+ assertThat(paperCheck.getField(TOKEN), is(TEST_TOKEN));
+ }
+
+ @Test
+ public void updateTransferMethod_paperCheckWithSuccess() {
+ final PaperCheck returnedPaperCheck = buildPaperCheck();
+ doAnswer(new Answer() {
+ @Override
+ public Object answer(InvocationOnMock invocation) {
+ HyperwalletListener listener = (HyperwalletListener) invocation.getArguments()[1];
+ returnedPaperCheck.setField(STATUS, ACTIVATED);
+ listener.onSuccess(returnedPaperCheck);
+ return listener;
+ }
+ }).when(mHyperwallet).updatePaperCheck(any(PaperCheck.class), any(HyperwalletListener.class));
+
+ PaperCheck parameter = new PaperCheck.Builder().build();
+
+ mTransferMethodRepository.updateTransferMethod(parameter, mLoadTransferMethodCallback);
+
+ verify(mLoadTransferMethodCallback).onTransferMethodLoaded(mPaperCheckArgumentCaptor.capture());
+ verify(mLoadTransferMethodCallback, never()).onError(any(Errors.class));
+
+ PaperCheck paperCheck = mPaperCheckArgumentCaptor.getValue();
+ assertThat(paperCheck, is(notNullValue()));
+ assertThat(paperCheck.getCountry(), is(COUNTRY_US));
+ assertThat(paperCheck.getCurrency(), is(CURRENCY_USD));
+ assertThat(paperCheck.getField(STATUS), is(ACTIVATED));
+ assertThat(paperCheck.getField(TOKEN), is(TEST_TOKEN));
+ }
@Test
public void createTransferMethod_venmoAccountWithError() {
final Error returnedError = new Error(TEST_MESSAGE, TEST_CODE);
@@ -839,10 +1084,31 @@ public Object answer(InvocationOnMock invocation) {
}
@Test
- public void createTransferMethod_paperCheckWithError() {
+ public void updateTransferMethod_venmoAccountWithError() {
+ final Error returnedError = new Error(TEST_MESSAGE, TEST_CODE);
+ doAnswer(new Answer() {
+ @Override
+ public Object answer(InvocationOnMock invocation) {
+ HyperwalletListener listener = (HyperwalletListener) invocation.getArguments()[1];
+
+ List errorList = new ArrayList<>();
+ errorList.add(returnedError);
+
+ listener.onFailure(new HyperwalletException(new Errors(errorList)));
+ return listener;
+ }
+ }).when(mHyperwallet).updateVenmoAccount(any(VenmoAccount.class), any(HyperwalletListener.class));
+ VenmoAccount parameter = new VenmoAccount.Builder().build();
- //Todo paper check
+ mTransferMethodRepository.updateTransferMethod(parameter, mLoadTransferMethodCallback);
+
+ verify(mLoadTransferMethodCallback, never()).onTransferMethodLoaded(any(TransferMethod.class));
+ verify(mLoadTransferMethodCallback).onError(mErrorsArgumentCaptor.capture());
+ assertThat(mErrorsArgumentCaptor.getValue().getErrors(), hasItem(returnedError));
+ }
+ @Test
+ public void createTransferMethod_paperCheckWithError() {
final Error returnedError = new Error(TEST_MESSAGE, TEST_CODE);
doAnswer(new Answer() {
@Override
@@ -855,8 +1121,8 @@ public Object answer(InvocationOnMock invocation) {
listener.onFailure(new HyperwalletException(new Errors(errorList)));
return listener;
}
- }).when(mHyperwallet).createVenmoAccount(any(VenmoAccount.class), any(HyperwalletListener.class));
- VenmoAccount parameter = new VenmoAccount.Builder().build();
+ }).when(mHyperwallet).createPaperCheck(any(PaperCheck.class), any(HyperwalletListener.class));
+ PaperCheck parameter = new PaperCheck.Builder().build();
mTransferMethodRepository.createTransferMethod(parameter, mLoadTransferMethodCallback);
@@ -864,6 +1130,31 @@ public Object answer(InvocationOnMock invocation) {
verify(mLoadTransferMethodCallback).onError(mErrorsArgumentCaptor.capture());
assertThat(mErrorsArgumentCaptor.getValue().getErrors(), hasItem(returnedError));
}
+
+ @Test
+ public void updateTransferMethod_paperCheckWithError() {
+ final Error returnedError = new Error(TEST_MESSAGE, TEST_CODE);
+ doAnswer(new Answer() {
+ @Override
+ public Object answer(InvocationOnMock invocation) {
+ HyperwalletListener listener = (HyperwalletListener) invocation.getArguments()[1];
+
+ List errorList = new ArrayList<>();
+ errorList.add(returnedError);
+
+ listener.onFailure(new HyperwalletException(new Errors(errorList)));
+ return listener;
+ }
+ }).when(mHyperwallet).updatePaperCheck(any(PaperCheck.class), any(HyperwalletListener.class));
+ PaperCheck parameter = new PaperCheck.Builder().build();
+
+ mTransferMethodRepository.updateTransferMethod(parameter, mLoadTransferMethodCallback);
+
+ verify(mLoadTransferMethodCallback, never()).onTransferMethodLoaded(any(TransferMethod.class));
+ verify(mLoadTransferMethodCallback).onError(mErrorsArgumentCaptor.capture());
+ assertThat(mErrorsArgumentCaptor.getValue().getErrors(), hasItem(returnedError));
+ }
+
@Test
public void testCreateTransferMethod_wireAccountWithSuccess() {
BankAccount bankAccount = new BankAccount
@@ -968,4 +1259,12 @@ private VenmoAccount buildVenmoAccount() {
.token(TEST_TOKEN)
.build();
}
+
+ private PaperCheck buildPaperCheck() {
+ return new PaperCheck.Builder()
+ .transferMethodCountry(COUNTRY_US)
+ .transferMethodCurrency(CURRENCY_USD)
+ .token(TEST_TOKEN)
+ .build();
+ }
}
diff --git a/transfermethodrepository/src/test/java/com/hyperwallet/android/ui/transfermethod/repository/TransferMethodUpdateConfigurationRepositoryImplTest.java b/transfermethodrepository/src/test/java/com/hyperwallet/android/ui/transfermethod/repository/TransferMethodUpdateConfigurationRepositoryImplTest.java
new file mode 100644
index 000000000..96b65ed05
--- /dev/null
+++ b/transfermethodrepository/src/test/java/com/hyperwallet/android/ui/transfermethod/repository/TransferMethodUpdateConfigurationRepositoryImplTest.java
@@ -0,0 +1,177 @@
+package com.hyperwallet.android.ui.transfermethod.repository;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import com.hyperwallet.android.Hyperwallet;
+import com.hyperwallet.android.exception.HyperwalletException;
+import com.hyperwallet.android.listener.HyperwalletListener;
+import com.hyperwallet.android.model.Error;
+import com.hyperwallet.android.model.Errors;
+import com.hyperwallet.android.model.TypeReference;
+import com.hyperwallet.android.model.graphql.HyperwalletTransferMethodConfigurationField;
+import com.hyperwallet.android.model.graphql.field.FieldGroup;
+import com.hyperwallet.android.model.graphql.field.TransferMethodConfiguration;
+import com.hyperwallet.android.model.graphql.field.TransferMethodConfigurationFieldResult;
+import com.hyperwallet.android.model.graphql.field.TransferMethodUpdateConfigurationFieldResult;
+import com.hyperwallet.android.model.graphql.query.TransferMethodUpdateConfigurationFieldQuery;
+import com.hyperwallet.android.ui.testutils.rule.HyperwalletExternalResourceManager;
+import com.hyperwallet.android.util.JsonUtils;
+
+import org.hamcrest.collection.IsEmptyCollection;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.ArgumentMatchers;
+import org.mockito.Captor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.mockito.stubbing.Answer;
+import org.robolectric.RobolectricTestRunner;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.HashMap;
+import java.util.List;
+
+@RunWith(RobolectricTestRunner.class)
+public class TransferMethodUpdateConfigurationRepositoryImplTest {
+
+ private static final String TRANSFER_TOKEN = "trm-fake";
+ @Rule
+ public HyperwalletExternalResourceManager externalResourceManager = new HyperwalletExternalResourceManager();
+ @Rule
+ public MockitoRule mockito = MockitoJUnit.rule();
+ @Mock
+ private TransferMethodUpdateConfigurationRepository.LoadFieldsCallback loadFieldsCallback;
+ @Captor
+ private ArgumentCaptor fieldResultArgumentCaptor;
+ @Captor
+ private ArgumentCaptor mErrorsArgumentCaptor;
+ @Mock
+ private Hyperwallet mHyperwallet;
+ @Mock
+ private HashMap mFieldsMap;
+ @Spy
+ @InjectMocks
+ private TransferMethodUpdateConfigurationRepositoryImpl mTransferMethodUpdateConfigurationRepositoryImplMock;
+
+ @Before
+ public void setUp() {
+ doReturn(mHyperwallet).when(mTransferMethodUpdateConfigurationRepositoryImplMock).getHyperwallet();
+ }
+
+ @Test
+ public void testGetFields_callsListenerWithFieldResultOnSuccess()
+ throws NoSuchMethodException, InstantiationException, IllegalAccessException, JSONException,
+ InvocationTargetException {
+ String responseBody = externalResourceManager.getResourceContent(
+ "successful_tmc_update_field_bank_account_response.json");
+ final TransferMethodUpdateConfigurationFieldResult result = JsonUtils.fromJsonString(responseBody,
+ new TypeReference() {
+ });
+ doAnswer(new Answer() {
+ @Override
+ public Object answer(InvocationOnMock invocation) {
+ HyperwalletListener listener = (HyperwalletListener) invocation.getArguments()[1];
+ listener.onSuccess(result);
+ return listener;
+ }
+ }).when(mHyperwallet).retrieveUpdateTransferMethodConfigurationFields(
+ ArgumentMatchers.any(),
+ ArgumentMatchers.>any());
+
+ mTransferMethodUpdateConfigurationRepositoryImplMock.getFields(TRANSFER_TOKEN,loadFieldsCallback);
+
+ verify(loadFieldsCallback).onFieldsLoaded(fieldResultArgumentCaptor.capture());
+ verify(loadFieldsCallback, never()).onError(any(Errors.class));
+
+ HyperwalletTransferMethodConfigurationField transferMethodConfigurationFieldResult =
+ fieldResultArgumentCaptor.getValue();
+ assertNotNull(transferMethodConfigurationFieldResult);
+ TransferMethodConfiguration transferMethodConfiguration =
+ transferMethodConfigurationFieldResult.getFields();
+ assertThat(transferMethodConfiguration, is(notNullValue()));
+ assertThat(transferMethodConfiguration.getFieldGroups(),
+ is(not(IsEmptyCollection.empty())));
+ }
+
+ @Test
+ public void testGetFields_callsListenerWithErrorResultOnFailure()
+ throws NoSuchMethodException, InstantiationException, IllegalAccessException, JSONException,
+ InvocationTargetException {
+ String responseBody = externalResourceManager.getResourceContent("error_tmc_keys_response.json");
+ final Errors errors = JsonUtils.fromJsonString(responseBody,
+ new TypeReference() {
+ });
+ final HyperwalletException exception = new HyperwalletException(errors);
+ doAnswer(new Answer() {
+ @Override
+ public Object answer(InvocationOnMock invocation) {
+ HyperwalletListener listener = (HyperwalletListener) invocation.getArguments()[1];
+
+ listener.onFailure(exception);
+ return listener;
+ }
+ }).when(mHyperwallet).retrieveUpdateTransferMethodConfigurationFields(
+ ArgumentMatchers.any(),
+ ArgumentMatchers.>any());
+
+
+ mTransferMethodUpdateConfigurationRepositoryImplMock.getFields(TRANSFER_TOKEN, loadFieldsCallback);
+
+ verify(loadFieldsCallback, never()).onFieldsLoaded(any(HyperwalletTransferMethodConfigurationField.class));
+ verify(loadFieldsCallback).onError(mErrorsArgumentCaptor.capture());
+
+ Errors errorsList = mErrorsArgumentCaptor.getValue();
+ assertNotNull(errorsList);
+ List inErrors = errorsList.getErrors();
+ assertNotNull(errors);
+ Error inError = inErrors.get(0);
+ assertThat(errors.getErrors().get(0), is(inError));
+ }
+
+ @Test
+ public void testGetFields_callsListenerWithFieldResultFromCacheWhenNotNull() throws Exception {
+ String responseBody = externalResourceManager.getResourceContent(
+ "successful_tmc_update_field_bank_account_response.json");
+ final TransferMethodUpdateConfigurationFieldResult result = JsonUtils.fromJsonString(responseBody,
+ new TypeReference() {
+ });
+
+ mTransferMethodUpdateConfigurationRepositoryImplMock.getFields(TRANSFER_TOKEN, loadFieldsCallback);
+ verify(loadFieldsCallback, never()).onError(any(Errors.class));
+ }
+
+ @Test
+ public void testRefreshFields_clearsFieldMapWhenNotEmpty() throws Exception {
+ String responseBody = externalResourceManager.getResourceContent(
+ "successful_tmc_update_field_bank_account_response.json");
+ JSONObject jsonObject = new JSONObject(responseBody);
+ FieldMapKey fieldMapKey = new FieldMapKey();
+ HashMap fieldMap = new HashMap<>();
+ fieldMap.put(fieldMapKey, new TransferMethodUpdateConfigurationFieldResult(jsonObject));
+ TransferMethodConfigurationRepositoryImpl repositoryWithCache = new TransferMethodConfigurationRepositoryImpl(
+ null, null, fieldMap);
+ repositoryWithCache.refreshFields();
+ assertTrue(fieldMap.isEmpty());
+ }
+}
diff --git a/transfermethodrepository/src/test/resources/successful_tmc_update_field_bank_account_response.json b/transfermethodrepository/src/test/resources/successful_tmc_update_field_bank_account_response.json
new file mode 100644
index 000000000..7c5003d5e
--- /dev/null
+++ b/transfermethodrepository/src/test/resources/successful_tmc_update_field_bank_account_response.json
@@ -0,0 +1,1192 @@
+{
+ "data": {
+ "transferMethodUpdateUIConfigurations": {
+ "nodes": [
+ {
+ "country": "US",
+ "currency": "USD",
+ "transferMethodType": "BANK_ACCOUNT",
+ "profile": "INDIVIDUAL",
+ "fieldGroups": {
+ "nodes": [
+ {
+ "group": "ACCOUNT_INFORMATION",
+ "isEditable": true,
+ "instruction": {
+ "textBottom": "On a paper check, the routing number is printed as the first 9 digits on the bottom of the check, followed by 4-17 digits for the account number."
+ },
+ "fields": [
+ {
+ "category": "ACCOUNT",
+ "value": "021000021",
+ "dataType": "NUMBER",
+ "isRequired": true,
+ "isEditable": true,
+ "label": "Routing Number",
+ "maxLength": 9,
+ "minLength": 9,
+ "name": "branchId",
+ "placeholder": "",
+ "regularExpression": "^[0-9]{9}$",
+ "validationMessage": {
+ "length": "The exact length of this field is 9.",
+ "pattern": "is invalid length or format.",
+ "empty": "You must provide a value for this field"
+ },
+ "fieldValueMasked": false
+ },
+ {
+ "category": "ACCOUNT",
+ "value": "****",
+ "dataType": "NUMBER",
+ "isRequired": true,
+ "isEditable": true,
+ "label": "Account Number",
+ "maxLength": 17,
+ "minLength": 3,
+ "name": "bankAccountId",
+ "placeholder": "",
+ "regularExpression": "^(?![0-]+$)[0-9-]{3,17}$",
+ "validationMessage": {
+ "length": "The minimum length of this field is 3 and maximum length is 17.",
+ "pattern": "is invalid length or format.",
+ "empty": "You must provide a value for this field"
+ },
+ "fieldValueMasked": true
+ },
+ {
+ "category": "ACCOUNT",
+ "value": "SAVINGS",
+ "dataType": "SELECTION",
+ "isRequired": true,
+ "isEditable": true,
+ "label": "Account Type",
+ "name": "bankAccountPurpose",
+ "placeholder": "",
+ "fieldSelectionOptions": [
+ {
+ "label": "Checking",
+ "value": "CHECKING"
+ },
+ {
+ "label": "Savings",
+ "value": "SAVINGS"
+ }
+ ],
+ "validationMessage": {
+ "length": "",
+ "pattern": "is invalid length or format.",
+ "empty": "You must provide a value for this field"
+ },
+ "fieldValueMasked": false
+ }
+ ]
+ },
+ {
+ "group": "ACCOUNT_HOLDER",
+ "isEditable": true,
+ "instruction": {
+ },
+ "fields": [
+ {
+ "category": "PROFILE",
+ "value": "iOS Mobile",
+ "dataType": "TEXT",
+ "isRequired": true,
+ "isEditable": true,
+ "label": "First Name",
+ "name": "firstName",
+ "placeholder": "",
+ "regularExpression": "^[\\sa-zA-Z0-9\\-.,'\\u00C0-\\u00FF\\u0100-\\u017F\\u0180-\\u024F]{1,50}$",
+ "validationMessage": {
+ "length": "",
+ "pattern": "is invalid length or format.",
+ "empty": "You must provide a value for this field"
+ },
+ "fieldValueMasked": false
+ },
+ {
+ "category": "PROFILE",
+ "value": "mobile-qa",
+ "dataType": "TEXT",
+ "isRequired": false,
+ "isEditable": true,
+ "label": "Middle Name",
+ "name": "middleName",
+ "placeholder": "",
+ "regularExpression": "^[\\sa-zA-Z0-9\\-.,'\\u00C0-\\u00FF\\u0100-\\u017F\\u0180-\\u024F]{1,50}$",
+ "validationMessage": {
+ "length": "",
+ "pattern": "is invalid length or format.",
+ "empty": "You must provide a value for this field"
+ },
+ "fieldValueMasked": false
+ },
+ {
+ "category": "PROFILE",
+ "value": "UITest",
+ "dataType": "TEXT",
+ "isRequired": true,
+ "isEditable": true,
+ "label": "Last Name",
+ "name": "lastName",
+ "placeholder": "",
+ "regularExpression": "^[\\sa-zA-Z0-9\\-.,'\\u00C0-\\u00FF\\u0100-\\u017F\\u0180-\\u024F]{1,50}$",
+ "validationMessage": {
+ "length": "",
+ "pattern": "is invalid length or format.",
+ "empty": "You must provide a value for this field"
+ },
+ "fieldValueMasked": false
+ }
+ ]
+ },
+ {
+ "group": "ADDRESS",
+ "isEditable": true,
+ "instruction": {
+ },
+ "fields": [
+ {
+ "category": "ADDRESS",
+ "value": "CA",
+ "dataType": "SELECTION",
+ "isRequired": true,
+ "isEditable": true,
+ "label": "Country",
+ "name": "country",
+ "placeholder": "",
+ "fieldSelectionOptions": [
+ {
+ "label": "Afghanistan",
+ "value": "AF"
+ },
+ {
+ "label": "Åland Islands",
+ "value": "AX"
+ },
+ {
+ "label": "Albania",
+ "value": "AL"
+ },
+ {
+ "label": "Algeria",
+ "value": "DZ"
+ },
+ {
+ "label": "American Samoa",
+ "value": "AS"
+ },
+ {
+ "label": "Andorra",
+ "value": "AD"
+ },
+ {
+ "label": "Angola",
+ "value": "AO"
+ },
+ {
+ "label": "Anguilla",
+ "value": "AI"
+ },
+ {
+ "label": "Antarctica",
+ "value": "AQ"
+ },
+ {
+ "label": "Antigua & Barbuda",
+ "value": "AG"
+ },
+ {
+ "label": "Argentina",
+ "value": "AR"
+ },
+ {
+ "label": "Armenia",
+ "value": "AM"
+ },
+ {
+ "label": "Aruba",
+ "value": "AW"
+ },
+ {
+ "label": "Australia",
+ "value": "AU"
+ },
+ {
+ "label": "Austria",
+ "value": "AT"
+ },
+ {
+ "label": "Azerbaijan",
+ "value": "AZ"
+ },
+ {
+ "label": "Bahamas",
+ "value": "BS"
+ },
+ {
+ "label": "Bahrain",
+ "value": "BH"
+ },
+ {
+ "label": "Bangladesh",
+ "value": "BD"
+ },
+ {
+ "label": "Barbados",
+ "value": "BB"
+ },
+ {
+ "label": "Belgium",
+ "value": "BE"
+ },
+ {
+ "label": "Belize",
+ "value": "BZ"
+ },
+ {
+ "label": "Benin",
+ "value": "BJ"
+ },
+ {
+ "label": "Bermuda",
+ "value": "BM"
+ },
+ {
+ "label": "Bhutan",
+ "value": "BT"
+ },
+ {
+ "label": "Bolivia",
+ "value": "BO"
+ },
+ {
+ "label": "Caribbean Netherlands",
+ "value": "BQ"
+ },
+ {
+ "label": "Bosnia & Herzegovina",
+ "value": "BA"
+ },
+ {
+ "label": "Botswana",
+ "value": "BW"
+ },
+ {
+ "label": "Bouvet Island",
+ "value": "BV"
+ },
+ {
+ "label": "Brazil",
+ "value": "BR"
+ },
+ {
+ "label": "British Indian Ocean Territory",
+ "value": "IO"
+ },
+ {
+ "label": "Brunei",
+ "value": "BN"
+ },
+ {
+ "label": "Bulgaria",
+ "value": "BG"
+ },
+ {
+ "label": "Burkina Faso",
+ "value": "BF"
+ },
+ {
+ "label": "Burundi",
+ "value": "BI"
+ },
+ {
+ "label": "Cambodia",
+ "value": "KH"
+ },
+ {
+ "label": "Cameroon",
+ "value": "CM"
+ },
+ {
+ "label": "Canada",
+ "value": "CA"
+ },
+ {
+ "label": "Cape Verde",
+ "value": "CV"
+ },
+ {
+ "label": "Cayman Islands",
+ "value": "KY"
+ },
+ {
+ "label": "Chad",
+ "value": "TD"
+ },
+ {
+ "label": "Chile",
+ "value": "CL"
+ },
+ {
+ "label": "China",
+ "value": "CN"
+ },
+ {
+ "label": "Christmas Island",
+ "value": "CX"
+ },
+ {
+ "label": "Cocos (Keeling) Islands",
+ "value": "CC"
+ },
+ {
+ "label": "Colombia",
+ "value": "CO"
+ },
+ {
+ "label": "Comoros",
+ "value": "KM"
+ },
+ {
+ "label": "Congo - Brazzaville",
+ "value": "CG"
+ },
+ {
+ "label": "Cook Islands",
+ "value": "CK"
+ },
+ {
+ "label": "Costa Rica",
+ "value": "CR"
+ },
+ {
+ "label": "Côte d’Ivoire",
+ "value": "CI"
+ },
+ {
+ "label": "Croatia",
+ "value": "HR"
+ },
+ {
+ "label": "Curaçao",
+ "value": "CW"
+ },
+ {
+ "label": "Cyprus",
+ "value": "CY"
+ },
+ {
+ "label": "Czechia",
+ "value": "CZ"
+ },
+ {
+ "label": "Denmark",
+ "value": "DK"
+ },
+ {
+ "label": "Djibouti",
+ "value": "DJ"
+ },
+ {
+ "label": "Dominica",
+ "value": "DM"
+ },
+ {
+ "label": "Dominican Republic",
+ "value": "DO"
+ },
+ {
+ "label": "Timor-Leste",
+ "value": "TL"
+ },
+ {
+ "label": "Ecuador",
+ "value": "EC"
+ },
+ {
+ "label": "Egypt",
+ "value": "EG"
+ },
+ {
+ "label": "El Salvador",
+ "value": "SV"
+ },
+ {
+ "label": "Equatorial Guinea",
+ "value": "GQ"
+ },
+ {
+ "label": "Estonia",
+ "value": "EE"
+ },
+ {
+ "label": "Ethiopia",
+ "value": "ET"
+ },
+ {
+ "label": "Falkland Islands",
+ "value": "FK"
+ },
+ {
+ "label": "Faroe Islands",
+ "value": "FO"
+ },
+ {
+ "label": "Fiji",
+ "value": "FJ"
+ },
+ {
+ "label": "Finland",
+ "value": "FI"
+ },
+ {
+ "label": "France",
+ "value": "FR"
+ },
+ {
+ "label": "French Guiana",
+ "value": "GF"
+ },
+ {
+ "label": "French Polynesia",
+ "value": "PF"
+ },
+ {
+ "label": "French Southern Territories",
+ "value": "TF"
+ },
+ {
+ "label": "Gabon",
+ "value": "GA"
+ },
+ {
+ "label": "Gambia",
+ "value": "GM"
+ },
+ {
+ "label": "Georgia",
+ "value": "GE"
+ },
+ {
+ "label": "Germany",
+ "value": "DE"
+ },
+ {
+ "label": "Ghana",
+ "value": "GH"
+ },
+ {
+ "label": "Gibraltar",
+ "value": "GI"
+ },
+ {
+ "label": "Greece",
+ "value": "GR"
+ },
+ {
+ "label": "Greenland",
+ "value": "GL"
+ },
+ {
+ "label": "Grenada",
+ "value": "GD"
+ },
+ {
+ "label": "Guadeloupe",
+ "value": "GP"
+ },
+ {
+ "label": "Guam",
+ "value": "GU"
+ },
+ {
+ "label": "Guatemala",
+ "value": "GT"
+ },
+ {
+ "label": "Guernsey",
+ "value": "GG"
+ },
+ {
+ "label": "Guinea",
+ "value": "GN"
+ },
+ {
+ "label": "Guyana",
+ "value": "GY"
+ },
+ {
+ "label": "Haiti",
+ "value": "HT"
+ },
+ {
+ "label": "Heard & McDonald Islands",
+ "value": "HM"
+ },
+ {
+ "label": "Honduras",
+ "value": "HN"
+ },
+ {
+ "label": "Hong Kong SAR China",
+ "value": "HK"
+ },
+ {
+ "label": "Hungary",
+ "value": "HU"
+ },
+ {
+ "label": "Iceland",
+ "value": "IS"
+ },
+ {
+ "label": "India",
+ "value": "IN"
+ },
+ {
+ "label": "Indonesia",
+ "value": "ID"
+ },
+ {
+ "label": "Ireland",
+ "value": "IE"
+ },
+ {
+ "label": "Isle of Man",
+ "value": "IM"
+ },
+ {
+ "label": "Israel",
+ "value": "IL"
+ },
+ {
+ "label": "Italy",
+ "value": "IT"
+ },
+ {
+ "label": "Jamaica",
+ "value": "JM"
+ },
+ {
+ "label": "Japan",
+ "value": "JP"
+ },
+ {
+ "label": "Jersey",
+ "value": "JE"
+ },
+ {
+ "label": "Jordan",
+ "value": "JO"
+ },
+ {
+ "label": "Kazakhstan",
+ "value": "KZ"
+ },
+ {
+ "label": "Kenya",
+ "value": "KE"
+ },
+ {
+ "label": "Kiribati",
+ "value": "KI"
+ },
+ {
+ "label": "South Korea",
+ "value": "KR"
+ },
+ {
+ "label": "Kosovo",
+ "value": "XK"
+ },
+ {
+ "label": "Kuwait",
+ "value": "KW"
+ },
+ {
+ "label": "Kyrgyzstan",
+ "value": "KG"
+ },
+ {
+ "label": "Laos",
+ "value": "LA"
+ },
+ {
+ "label": "Latvia",
+ "value": "LV"
+ },
+ {
+ "label": "Lesotho",
+ "value": "LS"
+ },
+ {
+ "label": "Liechtenstein",
+ "value": "LI"
+ },
+ {
+ "label": "Lithuania",
+ "value": "LT"
+ },
+ {
+ "label": "Luxembourg",
+ "value": "LU"
+ },
+ {
+ "label": "Macao SAR China",
+ "value": "MO"
+ },
+ {
+ "label": "North Macedonia",
+ "value": "MK"
+ },
+ {
+ "label": "Madagascar",
+ "value": "MG"
+ },
+ {
+ "label": "Malawi",
+ "value": "MW"
+ },
+ {
+ "label": "Malaysia",
+ "value": "MY"
+ },
+ {
+ "label": "Maldives",
+ "value": "MV"
+ },
+ {
+ "label": "Mali",
+ "value": "ML"
+ },
+ {
+ "label": "Malta",
+ "value": "MT"
+ },
+ {
+ "label": "Marshall Islands",
+ "value": "MH"
+ },
+ {
+ "label": "Martinique",
+ "value": "MQ"
+ },
+ {
+ "label": "Mauritania",
+ "value": "MR"
+ },
+ {
+ "label": "Mauritius",
+ "value": "MU"
+ },
+ {
+ "label": "Mayotte",
+ "value": "YT"
+ },
+ {
+ "label": "Mexico",
+ "value": "MX"
+ },
+ {
+ "label": "Micronesia",
+ "value": "FM"
+ },
+ {
+ "label": "Moldova",
+ "value": "MD"
+ },
+ {
+ "label": "Monaco",
+ "value": "MC"
+ },
+ {
+ "label": "Mongolia",
+ "value": "MN"
+ },
+ {
+ "label": "Montenegro",
+ "value": "ME"
+ },
+ {
+ "label": "Montserrat",
+ "value": "MS"
+ },
+ {
+ "label": "Morocco",
+ "value": "MA"
+ },
+ {
+ "label": "Mozambique",
+ "value": "MZ"
+ },
+ {
+ "label": "Namibia",
+ "value": "NA"
+ },
+ {
+ "label": "Nauru",
+ "value": "NR"
+ },
+ {
+ "label": "Nepal",
+ "value": "NP"
+ },
+ {
+ "label": "Netherlands",
+ "value": "NL"
+ },
+ {
+ "label": "Curaçao",
+ "value": "AN"
+ },
+ {
+ "label": "New Caledonia",
+ "value": "NC"
+ },
+ {
+ "label": "New Zealand",
+ "value": "NZ"
+ },
+ {
+ "label": "Nicaragua",
+ "value": "NI"
+ },
+ {
+ "label": "Niger",
+ "value": "NE"
+ },
+ {
+ "label": "Nigeria",
+ "value": "NG"
+ },
+ {
+ "label": "Niue",
+ "value": "NU"
+ },
+ {
+ "label": "Norfolk Island",
+ "value": "NF"
+ },
+ {
+ "label": "Northern Mariana Islands",
+ "value": "MP"
+ },
+ {
+ "label": "Norway",
+ "value": "NO"
+ },
+ {
+ "label": "Oman",
+ "value": "OM"
+ },
+ {
+ "label": "Pakistan",
+ "value": "PK"
+ },
+ {
+ "label": "Palau",
+ "value": "PW"
+ },
+ {
+ "label": "Palestinian Territories",
+ "value": "PS"
+ },
+ {
+ "label": "Panama",
+ "value": "PA"
+ },
+ {
+ "label": "Papua New Guinea",
+ "value": "PG"
+ },
+ {
+ "label": "Paraguay",
+ "value": "PY"
+ },
+ {
+ "label": "Peru",
+ "value": "PE"
+ },
+ {
+ "label": "Philippines",
+ "value": "PH"
+ },
+ {
+ "label": "Pitcairn Islands",
+ "value": "PN"
+ },
+ {
+ "label": "Poland",
+ "value": "PL"
+ },
+ {
+ "label": "Portugal",
+ "value": "PT"
+ },
+ {
+ "label": "Puerto Rico",
+ "value": "PR"
+ },
+ {
+ "label": "Qatar",
+ "value": "QA"
+ },
+ {
+ "label": "Réunion",
+ "value": "RE"
+ },
+ {
+ "label": "Romania",
+ "value": "RO"
+ },
+ {
+ "label": "Russia",
+ "value": "RU"
+ },
+ {
+ "label": "Rwanda",
+ "value": "RW"
+ },
+ {
+ "label": "St. Kitts & Nevis",
+ "value": "KN"
+ },
+ {
+ "label": "St. Lucia",
+ "value": "LC"
+ },
+ {
+ "label": "St. Martin",
+ "value": "MF"
+ },
+ {
+ "label": "St. Vincent & Grenadines",
+ "value": "VC"
+ },
+ {
+ "label": "Samoa",
+ "value": "WS"
+ },
+ {
+ "label": "San Marino",
+ "value": "SM"
+ },
+ {
+ "label": "São Tomé & Príncipe",
+ "value": "ST"
+ },
+ {
+ "label": "Saudi Arabia",
+ "value": "SA"
+ },
+ {
+ "label": "Senegal",
+ "value": "SN"
+ },
+ {
+ "label": "Serbia",
+ "value": "RS"
+ },
+ {
+ "label": "Seychelles",
+ "value": "SC"
+ },
+ {
+ "label": "Sierra Leone",
+ "value": "SL"
+ },
+ {
+ "label": "Singapore",
+ "value": "SG"
+ },
+ {
+ "label": "Sint Maarten",
+ "value": "SX"
+ },
+ {
+ "label": "Slovakia",
+ "value": "SK"
+ },
+ {
+ "label": "Slovenia",
+ "value": "SI"
+ },
+ {
+ "label": "Solomon Islands",
+ "value": "SB"
+ },
+ {
+ "label": "South Africa",
+ "value": "ZA"
+ },
+ {
+ "label": "South Georgia & South Sandwich Islands",
+ "value": "GS"
+ },
+ {
+ "label": "South Sudan",
+ "value": "SS"
+ },
+ {
+ "label": "Spain",
+ "value": "ES"
+ },
+ {
+ "label": "Sri Lanka",
+ "value": "LK"
+ },
+ {
+ "label": "St. Barthélemy",
+ "value": "BL"
+ },
+ {
+ "label": "St. Helena",
+ "value": "SH"
+ },
+ {
+ "label": "St. Pierre & Miquelon",
+ "value": "PM"
+ },
+ {
+ "label": "Suriname",
+ "value": "SR"
+ },
+ {
+ "label": "Svalbard & Jan Mayen",
+ "value": "SJ"
+ },
+ {
+ "label": "Eswatini",
+ "value": "SZ"
+ },
+ {
+ "label": "Sweden",
+ "value": "SE"
+ },
+ {
+ "label": "Switzerland",
+ "value": "CH"
+ },
+ {
+ "label": "Taiwan",
+ "value": "TW"
+ },
+ {
+ "label": "Tajikistan",
+ "value": "TJ"
+ },
+ {
+ "label": "Tanzania",
+ "value": "TZ"
+ },
+ {
+ "label": "Thailand",
+ "value": "TH"
+ },
+ {
+ "label": "Togo",
+ "value": "TG"
+ },
+ {
+ "label": "Tokelau",
+ "value": "TK"
+ },
+ {
+ "label": "Tonga",
+ "value": "TO"
+ },
+ {
+ "label": "Trinidad & Tobago",
+ "value": "TT"
+ },
+ {
+ "label": "Tunisia",
+ "value": "TN"
+ },
+ {
+ "label": "Turkey",
+ "value": "TR"
+ },
+ {
+ "label": "Turkmenistan",
+ "value": "TM"
+ },
+ {
+ "label": "Turks & Caicos Islands",
+ "value": "TC"
+ },
+ {
+ "label": "Tuvalu",
+ "value": "TV"
+ },
+ {
+ "label": "Uganda",
+ "value": "UG"
+ },
+ {
+ "label": "Ukraine",
+ "value": "UA"
+ },
+ {
+ "label": "United Arab Emirates",
+ "value": "AE"
+ },
+ {
+ "label": "United Kingdom",
+ "value": "GB"
+ },
+ {
+ "label": "United States",
+ "value": "US"
+ },
+ {
+ "label": "U.S. Outlying Islands",
+ "value": "UM"
+ },
+ {
+ "label": "Uruguay",
+ "value": "UY"
+ },
+ {
+ "label": "Uzbekistan",
+ "value": "UZ"
+ },
+ {
+ "label": "Vanuatu",
+ "value": "VU"
+ },
+ {
+ "label": "Vatican City",
+ "value": "VA"
+ },
+ {
+ "label": "Venezuela",
+ "value": "VE"
+ },
+ {
+ "label": "Vietnam",
+ "value": "VN"
+ },
+ {
+ "label": "British Virgin Islands",
+ "value": "VG"
+ },
+ {
+ "label": "U.S. Virgin Islands",
+ "value": "VI"
+ },
+ {
+ "label": "Wallis & Futuna",
+ "value": "WF"
+ },
+ {
+ "label": "Western Sahara",
+ "value": "EH"
+ },
+ {
+ "label": "Zambia",
+ "value": "ZM"
+ }
+ ],
+ "validationMessage": {
+ "length": "",
+ "pattern": "is invalid length or format.",
+ "empty": "You must provide a value for this field"
+ },
+ "fieldValueMasked": false
+ },
+ {
+ "category": "ADDRESS",
+ "value": "BC",
+ "dataType": "TEXT",
+ "isRequired": true,
+ "isEditable": true,
+ "label": "State/Province",
+ "name": "stateProvince",
+ "placeholder": "",
+ "regularExpression": "^[\\sa-zA-Z0-9\\-().,'\\u00C0-\\u00FF\\u0100-\\u017F\\u0180-\\u024F]{2,50}$",
+ "validationMessage": {
+ "length": "",
+ "pattern": "is invalid length or format.",
+ "empty": "You must provide a value for this field"
+ },
+ "fieldValueMasked": false
+ },
+ {
+ "category": "ADDRESS",
+ "value": "475 howe st",
+ "dataType": "TEXT",
+ "isRequired": true,
+ "isEditable": true,
+ "label": "Address Line 1",
+ "name": "addressLine1",
+ "placeholder": "",
+ "regularExpression": "^[\\sa-zA-Z0-9\\/\\-:().,#;'°&\\u00C0-\\u00FF\\u0100-\\u017F\\u0180-\\u024F]{2,100}$",
+ "validationMessage": {
+ "length": "",
+ "pattern": "is invalid length or format.",
+ "empty": "You must provide a value for this field"
+ },
+ "fieldValueMasked": false
+ },
+ {
+ "category": "ADDRESS",
+ "dataType": "TEXT",
+ "isRequired": false,
+ "isEditable": true,
+ "label": "Address Line 2",
+ "name": "addressLine2",
+ "placeholder": "",
+ "regularExpression": "^[\\sa-zA-Z0-9\\/\\-:().,#;'°&\\u00C0-\\u00FF\\u0100-\\u017F\\u0180-\\u024F]{2,100}$",
+ "validationMessage": {
+ "length": "",
+ "pattern": "is invalid length or format.",
+ "empty": "You must provide a value for this field"
+ },
+ "fieldValueMasked": false
+ },
+ {
+ "category": "ADDRESS",
+ "value": "vancouver",
+ "dataType": "TEXT",
+ "isRequired": true,
+ "isEditable": true,
+ "label": "City",
+ "name": "city",
+ "placeholder": "",
+ "regularExpression": "^[\\sa-zA-Z0-9\\-().,'\\u00C0-\\u00FF\\u0100-\\u017F\\u0180-\\u024F]{2,50}$",
+ "validationMessage": {
+ "length": "",
+ "pattern": "is invalid length or format.",
+ "empty": "You must provide a value for this field"
+ },
+ "fieldValueMasked": false
+ },
+ {
+ "category": "ADDRESS",
+ "value": "V6Z1L2",
+ "dataType": "TEXT",
+ "isRequired": true,
+ "isEditable": true,
+ "label": "Zip/Postal Code",
+ "name": "postalCode",
+ "placeholder": "",
+ "regularExpression": "^(?![\\-]+$)[\\sa-zA-Z0-9\\-]{2,16}$",
+ "validationMessage": {
+ "length": "",
+ "pattern": "is invalid length or format.",
+ "empty": "You must provide a value for this field"
+ },
+ "fieldValueMasked": false
+ }
+ ]
+ }
+ ]
+ }
+ }
+ ]
+ }
+ }
+}
\ No newline at end of file
diff --git a/transfermethodui/build.gradle b/transfermethodui/build.gradle
index cd908659d..207b83eb2 100644
--- a/transfermethodui/build.gradle
+++ b/transfermethodui/build.gradle
@@ -25,6 +25,7 @@ dependencies {
implementation project(':commonui')
implementation project(":userrepository")
implementation project(":transfermethodrepository")
+ implementation project(":transferui")
androidTestImplementation "androidx.test:rules:$testRulesVersion"
diff --git a/transfermethodui/src/androidTest/java/com/hyperwallet/android/ui/transfermethod/EditTransferMethodTest.java b/transfermethodui/src/androidTest/java/com/hyperwallet/android/ui/transfermethod/EditTransferMethodTest.java
new file mode 100644
index 000000000..e1144cdbf
--- /dev/null
+++ b/transfermethodui/src/androidTest/java/com/hyperwallet/android/ui/transfermethod/EditTransferMethodTest.java
@@ -0,0 +1,257 @@
+package com.hyperwallet.android.ui.transfermethod;
+
+import android.app.Instrumentation;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.view.MenuItem;
+import android.widget.ImageButton;
+import android.widget.TextView;
+
+import androidx.localbroadcastmanager.content.LocalBroadcastManager;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.espresso.IdlingRegistry;
+import androidx.test.espresso.Root;
+import androidx.test.espresso.assertion.ViewAssertions;
+import androidx.test.espresso.matcher.ViewMatchers;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.rule.ActivityTestRule;
+
+import com.hyperwallet.android.model.StatusTransition;
+import com.hyperwallet.android.ui.R;
+import com.hyperwallet.android.ui.common.repository.EspressoIdlingResource;
+import com.hyperwallet.android.ui.common.view.error.DefaultErrorDialogFragment;
+import com.hyperwallet.android.ui.testutils.rule.HyperwalletExternalResourceManager;
+import com.hyperwallet.android.ui.testutils.rule.HyperwalletMockWebServer;
+import com.hyperwallet.android.ui.testutils.util.RecyclerViewCountAssertion;
+import com.hyperwallet.android.ui.transfermethod.repository.TransferMethodRepositoryFactory;
+import com.hyperwallet.android.ui.transfermethod.rule.HyperwalletInsightMockRule;
+import com.hyperwallet.android.ui.transfermethod.view.AddTransferMethodActivity;
+import com.hyperwallet.android.ui.transfermethod.view.ListTransferMethodActivity;
+
+import org.hamcrest.Matchers;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.IOException;
+import java.util.concurrent.CountDownLatch;
+
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.action.ViewActions.click;
+import static androidx.test.espresso.action.ViewActions.replaceText;
+import static androidx.test.espresso.action.ViewActions.typeText;
+import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.matcher.RootMatchers.isDialog;
+import static androidx.test.espresso.matcher.ViewMatchers.hasDescendant;
+import static androidx.test.espresso.matcher.ViewMatchers.hasSibling;
+import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility;
+import static androidx.test.espresso.matcher.ViewMatchers.withId;
+import static androidx.test.espresso.matcher.ViewMatchers.withParent;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
+import static com.hyperwallet.android.model.StatusTransition.StatusDefinition.DE_ACTIVATED;
+import static com.hyperwallet.android.ui.common.view.error.DefaultErrorDialogFragment.RESULT_ERROR;
+import static com.hyperwallet.android.ui.testutils.util.EspressoUtils.atPosition;
+import static com.hyperwallet.android.ui.testutils.util.EspressoUtils.nestedScrollTo;
+import static com.hyperwallet.android.ui.testutils.util.EspressoUtils.withDrawable;
+import static java.net.HttpURLConnection.HTTP_BAD_REQUEST;
+import static java.net.HttpURLConnection.HTTP_OK;
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.allOf;
+import static org.hamcrest.Matchers.instanceOf;
+import static org.hamcrest.Matchers.is;
+
+@RunWith(AndroidJUnit4.class)
+public class EditTransferMethodTest {
+
+ private static final String ACCOUNT_NUMBER = "8017110254";
+ private static final String ROUTING_NUMBER = "211179539";
+
+ @ClassRule
+ public static HyperwalletExternalResourceManager sResourceManager = new HyperwalletExternalResourceManager();
+ @Rule
+ public HyperwalletInsightMockRule mHyperwalletInsightMockRule = new HyperwalletInsightMockRule();
+ @Rule
+ public HyperwalletMockWebServer mMockWebServer = new HyperwalletMockWebServer(8080);
+ @Rule
+ public ActivityTestRule mActivityTestRule =
+ new ActivityTestRule<>(ListTransferMethodActivity.class, true, false);
+
+ @Before
+ public void setup() {
+ mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager
+ .getResourceContent("authentication_token_response.json")).mock();
+ IdlingRegistry.getInstance().register(EspressoIdlingResource.getIdlingResource());
+ }
+
+ @After
+ public void cleanup() {
+ TransferMethodRepositoryFactory.clearInstance();
+ IdlingRegistry.getInstance().unregister(EspressoIdlingResource.getIdlingResource());
+ }
+
+
+ @Test
+ public void testUpdateTransferMethodFragment_verifyUpdateBankAccountTransferMethod() throws InterruptedException {
+ mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager
+ .getResourceContent("transfer_method_list_single_bank_account_response.json")).mock();
+ mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager
+ .getResourceContent("transfer_method_update_bankacount_response.json")).mock();
+
+
+ final CountDownLatch gate = new CountDownLatch(1);
+ final BroadcastReceiver br = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ gate.countDown();
+
+ StatusTransition statusTransition = intent.getParcelableExtra(
+ "hyperwallet-local-broadcast-payload");
+ assertThat("Transition is not valid", statusTransition.getTransition(), is(DE_ACTIVATED));
+ }
+ };
+
+ // run test
+ mActivityTestRule.launchActivity(null);
+ LocalBroadcastManager.getInstance(mActivityTestRule.getActivity().getApplicationContext())
+ .registerReceiver(br, new IntentFilter("ACTION_HYPERWALLET_TRANSFER_METHOD_DEACTIVATED"));
+
+ // assert
+ onView(withId(R.id.toolbar)).check(matches(isDisplayed()));
+ onView(withId(R.id.toolbar))
+ .check(matches(
+ hasDescendant(withText(R.string.mobileTransferMethodsHeader))));
+ onView(withId(R.id.fab)).check(matches(isDisplayed()));
+
+ onView(withId(R.id.list_transfer_method_item)).check(
+ matches(atPosition(0, hasDescendant(withText(R.string.bank_account_font_icon)))));
+ onView(withId(R.id.list_transfer_method_item)).check(
+ matches(atPosition(0, hasDescendant(withText(R.string.bank_account)))));
+ onView(withId(R.id.list_transfer_method_item)).check(
+ matches(atPosition(0, hasDescendant(withText("United States")))));
+ onView(withId(R.id.list_transfer_method_item)).check(
+ matches(atPosition(0, hasDescendant(withText(getEndingIn("1332"))))));
+ onView(withId(R.id.list_transfer_method_item)).check(
+ matches(atPosition(0, hasDescendant(withDrawable(R.drawable.ic_three_dots_16dp)))));
+
+ onView(allOf(instanceOf(ImageButton.class), hasSibling(withText(R.string.bank_account)))).perform(click())
+ .inRoot(Matchers.instanceOf(MenuItem.class));
+ onView(withDrawable(R.drawable.ic_trash)).check(matches(isDisplayed()));
+ onView(withText(R.string.edit)).check(matches(isDisplayed())).perform(click());
+
+ onView(withId(R.id.branchIdLabel)).check(matches(isDisplayed()));
+
+ onView(withId(R.id.branchId)).perform(nestedScrollTo()).check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
+ .check(matches(withText("021000021")));
+
+ onView(ViewMatchers.withId(R.id.branchIdLabel))
+ .check(ViewAssertions.matches(ViewMatchers.isDisplayed()));
+
+ onView(ViewMatchers.withId(R.id.bankAccountId))
+ .perform(nestedScrollTo())
+ .check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
+ .check(matches(withText("****")));
+
+ onView(ViewMatchers.withId(R.id.bankAccountIdLabel))
+ .check(ViewAssertions.matches(ViewMatchers.isDisplayed()));
+
+ // ACCOUNT HOLDER INFO
+ onView(
+ Matchers.allOf(
+ ViewMatchers.withId(R.id.section_header_title),
+ ViewMatchers.withText(R.string.account_holder)
+ )
+ )
+ .perform(nestedScrollTo())
+ .check(ViewAssertions.matches(ViewMatchers.isDisplayed()));
+
+ onView(ViewMatchers.withId(R.id.firstName))
+ .perform(nestedScrollTo())
+ .check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
+ .check(matches(withText("Android Mobile")));
+
+ onView(ViewMatchers.withId(R.id.firstNameLabel))
+ .check(ViewAssertions.matches(ViewMatchers.isDisplayed()));
+
+ onView(ViewMatchers.withId(R.id.middleName))
+ .perform(nestedScrollTo())
+ .check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
+ .check(matches(withText("mobile-qa")));
+
+ onView(ViewMatchers.withId(R.id.middleNameLabel))
+ .check(ViewAssertions.matches(ViewMatchers.isDisplayed()));
+
+ onView(ViewMatchers.withId(R.id.lastName))
+ .perform(nestedScrollTo())
+ .check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
+ .check(matches(withText("UITest")));
+
+ onView(ViewMatchers.withId(R.id.lastNameLabel))
+ .check(ViewAssertions.matches(ViewMatchers.isDisplayed()));
+
+ // ADDRESS
+ onView(
+ Matchers.allOf(
+ ViewMatchers.withId(R.id.section_header_title),
+ ViewMatchers.withText(R.string.address)
+ )
+ ).perform(nestedScrollTo())
+ .check(ViewAssertions.matches(ViewMatchers.isDisplayed()));
+
+ onView(ViewMatchers.withId(R.id.country))
+ .perform(nestedScrollTo())
+ .check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
+ .check(matches(withText("Canada")));
+
+ onView(ViewMatchers.withId(R.id.countryLabel))
+ .check(ViewAssertions.matches(ViewMatchers.isDisplayed()));
+
+ onView(ViewMatchers.withId(R.id.stateProvince))
+ .perform(nestedScrollTo())
+ .check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
+ .check(matches(withText("BC")));
+
+ onView(ViewMatchers.withId(R.id.stateProvinceLabel))
+ .check(ViewAssertions.matches(ViewMatchers.isDisplayed()));
+
+ onView(ViewMatchers.withId(R.id.addressLine1))
+ .perform(nestedScrollTo())
+ .check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
+ .check(matches(withText("475 howe st")));
+
+ onView(ViewMatchers.withId(R.id.addressLine1Label))
+ .check(ViewAssertions.matches(ViewMatchers.isDisplayed()));
+
+ onView(ViewMatchers.withId(R.id.city))
+ .perform(nestedScrollTo())
+ .check(matches(withText("vancouver")))
+ .check(ViewAssertions.matches(ViewMatchers.isDisplayed()));
+
+ onView(ViewMatchers.withId(R.id.cityLabel))
+ .check(ViewAssertions.matches(ViewMatchers.isDisplayed()));
+
+ onView(ViewMatchers.withId(R.id.postalCode))
+ .perform(nestedScrollTo())
+ .check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
+ .check(matches(withText("V6Z1L2")));
+
+ onView(ViewMatchers.withId(R.id.postalCodeLabel))
+ .check(ViewAssertions.matches(ViewMatchers.isDisplayed()));
+
+ }
+
+ private String getEndingIn(String ending) {
+ return String.format(InstrumentationRegistry.getInstrumentation().getTargetContext()
+ .getString(R.string.endingIn), ending);
+ }
+
+}
diff --git a/transfermethodui/src/main/AndroidManifest.xml b/transfermethodui/src/main/AndroidManifest.xml
index 2a97d4dee..d46f47fb2 100644
--- a/transfermethodui/src/main/AndroidManifest.xml
+++ b/transfermethodui/src/main/AndroidManifest.xml
@@ -12,6 +12,11 @@
android:theme="@style/AppTheme.NoActionBar"
android:windowSoftInputMode="adjustResize"/>
+
+
true screen will be locked to Portrait mode;
+ * otherwise false screen will follow whatever the
+ * device orientation is directed.
+ * @return an Intent with the data necessary to launch the {@link UpdateTransferMethodActivity}
+ */
+ public Intent getIntentUpdateTransferMethodActivity(@NonNull final Context context,
+ @NonNull final String transferMethodToken, final boolean lockScreenToPortrait) {
+ Intent intent = new Intent(context, UpdateTransferMethodActivity.class);
+ intent.putExtra(EXTRA_TRANSFER_METHOD_TOKEN, transferMethodToken);
+ intent.putExtra(AddTransferMethodActivity.EXTRA_LOCK_SCREEN_ORIENTATION_TO_PORTRAIT, lockScreenToPortrait);
+ return intent;
+ }
+
public static void clearInstance() {
sInstance = null;
Hyperwallet.clearInstance();
diff --git a/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodLocalBroadcast.java b/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodLocalBroadcast.java
index f0d88bca0..5d703d328 100644
--- a/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodLocalBroadcast.java
+++ b/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodLocalBroadcast.java
@@ -19,6 +19,7 @@
import static com.hyperwallet.android.ui.common.intent.HyperwalletIntent.HYPERWALLET_LOCAL_BROADCAST_PAYLOAD_KEY;
import static com.hyperwallet.android.ui.transfermethod.TransferMethodLocalBroadcast.TransferMethodLocalBroadcastAction.ACTION_HYPERWALLET_TRANSFER_METHOD_ADDED;
import static com.hyperwallet.android.ui.transfermethod.TransferMethodLocalBroadcast.TransferMethodLocalBroadcastAction.ACTION_HYPERWALLET_TRANSFER_METHOD_DEACTIVATED;
+import static com.hyperwallet.android.ui.transfermethod.TransferMethodLocalBroadcast.TransferMethodLocalBroadcastAction.ACTION_HYPERWALLET_TRANSFER_METHOD_UPDATED;
import android.content.Intent;
import android.os.Parcelable;
@@ -40,6 +41,12 @@ public static Intent createBroadcastIntentTransferMethodAdded(
ACTION_HYPERWALLET_TRANSFER_METHOD_ADDED);
}
+ public static Intent createBroadcastIntentTransferMethodUpdated(
+ @NonNull final TransferMethod transferMethod) {
+ return createBroadcastIntent(transferMethod,
+ ACTION_HYPERWALLET_TRANSFER_METHOD_UPDATED);
+ }
+
public static Intent createBroadcastIntentTransferMethodDeactivated(
@NonNull final StatusTransition StatusTransition) {
return createBroadcastIntent(StatusTransition,
@@ -57,6 +64,7 @@ private static Intent createBroadcastIntent(@NonNull final Parcelable parcelable
@Retention(RetentionPolicy.SOURCE)
@StringDef({
ACTION_HYPERWALLET_TRANSFER_METHOD_ADDED,
+ ACTION_HYPERWALLET_TRANSFER_METHOD_UPDATED,
ACTION_HYPERWALLET_TRANSFER_METHOD_DEACTIVATED
})
public @interface TransferMethodLocalBroadcastActionType {
@@ -69,5 +77,7 @@ private TransferMethodLocalBroadcastAction() {}
"ACTION_HYPERWALLET_TRANSFER_METHOD_ADDED";
public static final String ACTION_HYPERWALLET_TRANSFER_METHOD_DEACTIVATED =
"ACTION_HYPERWALLET_TRANSFER_METHOD_DEACTIVATED";
+ public static final String ACTION_HYPERWALLET_TRANSFER_METHOD_UPDATED =
+ "ACTION_HYPERWALLET_TRANSFER_METHOD_UPDATED";
}
}
diff --git a/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/view/ListTransferMethodActivity.java b/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/view/ListTransferMethodActivity.java
index f81e7a84b..ab11d8e15 100644
--- a/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/view/ListTransferMethodActivity.java
+++ b/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/view/ListTransferMethodActivity.java
@@ -17,6 +17,7 @@
package com.hyperwallet.android.ui.transfermethod.view;
import static com.hyperwallet.android.ui.common.intent.HyperwalletIntent.SELECT_TRANSFER_METHOD_REQUEST_CODE;
+import static com.hyperwallet.android.ui.common.intent.HyperwalletIntent.UPDATE_TRANSFER_METHOD_REQUEST_CODE;
import static com.hyperwallet.android.ui.transfermethod.view.ListTransferMethodFragment.ARGUMENT_IS_TRANSFER_METHODS_RELOAD_NEEDED;
import android.content.Intent;
@@ -49,7 +50,7 @@ public class ListTransferMethodActivity extends AppCompatActivity implements
ListTransferMethodFragment.OnAddNewTransferMethodSelected,
ListTransferMethodFragment.OnDeactivateTransferMethodNetworkErrorCallback,
ListTransferMethodFragment.OnLoadTransferMethodNetworkErrorCallback,
- ListTransferMethodFragment.OnTransferMethodContextMenuDeletionSelected,
+ ListTransferMethodFragment.OnTransferMethodContextMenuItemSelected,
OnTransferMethodDeactivateCallback, OnNetworkErrorCallback {
public static final String TAG = "transfer-method:list:list-transfer-methods";
@@ -134,6 +135,9 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (fragment != null && fragment.getArguments() != null) {
fragment.getArguments().putBoolean(ARGUMENT_IS_TRANSFER_METHODS_RELOAD_NEEDED, true);
}
+ } else if (requestCode == UPDATE_TRANSFER_METHOD_REQUEST_CODE && resultCode == RESULT_OK) {
+ ActivityUtils.initFragment(this, ListTransferMethodFragment.newInstance(),
+ R.id.list_transfer_method_fragment);
}
}
@@ -177,6 +181,15 @@ public void showConfirmationDialog(@NonNull TransferMethod transferMethod) {
}
}
+ @Override
+ public void invokeTransferMethodEdit(@NonNull TransferMethod transferMethod) {
+ String token = transferMethod.getField(TransferMethod.TransferMethodFields.TOKEN);
+ Intent intent = new Intent(this, UpdateTransferMethodActivity.class);
+ intent.putExtra(UpdateTransferMethodActivity.EXTRA_TRANSFER_METHOD_TOKEN, token);
+ intent.putExtra(UpdateTransferMethodActivity.EXTRA_LOCK_SCREEN_ORIENTATION_TO_PORTRAIT, true);
+ startActivityForResult(intent, UPDATE_TRANSFER_METHOD_REQUEST_CODE);
+ }
+
@Override
public void confirm() {
mRetryCode = RETRY_CONFIRM_DEACTIVATE_TRANSFER_METHOD;
diff --git a/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/view/ListTransferMethodFragment.java b/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/view/ListTransferMethodFragment.java
index 9f4ccb6a8..f5c185311 100644
--- a/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/view/ListTransferMethodFragment.java
+++ b/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/view/ListTransferMethodFragment.java
@@ -69,7 +69,7 @@ public class ListTransferMethodFragment extends Fragment implements ListTransfer
private View mProgressBar;
private ArrayList mTransferMethodList;
private OnAddNewTransferMethodSelected mOnAddNewTransferMethodSelected;
- private OnTransferMethodContextMenuDeletionSelected mOnTransferMethodContextMenuDeletionSelected;
+ private OnTransferMethodContextMenuItemSelected mOnTransferMethodContextMenuItemSelected;
private OnDeactivateTransferMethodNetworkErrorCallback mOnDeactivateTransferMethodNetworkErrorCallback;
private OnLoadTransferMethodNetworkErrorCallback mOnLoadTransferMethodNetworkErrorCallback;
private boolean mIsTransferMethodsReloadNeeded;
@@ -105,10 +105,10 @@ public void onAttach(Context context) {
}
try {
- mOnTransferMethodContextMenuDeletionSelected = (OnTransferMethodContextMenuDeletionSelected) context;
+ mOnTransferMethodContextMenuItemSelected = (OnTransferMethodContextMenuItemSelected) context;
} catch (ClassCastException e) {
throw new ClassCastException(getActivity().toString() + " must implement "
- + OnTransferMethodContextMenuDeletionSelected.class.getCanonicalName());
+ + OnTransferMethodContextMenuItemSelected.class.getCanonicalName());
}
try {
@@ -144,7 +144,7 @@ public void onViewStateRestored(@Nullable Bundle savedInstanceState) {
mIsTransferMethodsReloadNeeded = true;
}
mListTransferMethodAdapter = new ListTransferMethodAdapter(mTransferMethodList,
- mOnTransferMethodContextMenuDeletionSelected);
+ mOnTransferMethodContextMenuItemSelected);
recyclerView.setAdapter(mListTransferMethodAdapter);
}
@@ -187,7 +187,11 @@ public void onActivityCreated(@Nullable Bundle savedInstanceState) {
public void onResume() {
super.onResume();
mIsTransferMethodsReloadNeeded = getArguments().getBoolean(ARGUMENT_IS_TRANSFER_METHODS_RELOAD_NEEDED, true);
- if (mIsTransferMethodsReloadNeeded) {
+ loadTransferMethodsList(mIsTransferMethodsReloadNeeded);
+ }
+
+ private void loadTransferMethodsList(boolean shouldReload) {
+ if (shouldReload) {
getArguments().putBoolean(ARGUMENT_IS_TRANSFER_METHODS_RELOAD_NEEDED, false);
mPresenter.loadTransferMethods();
} else {
@@ -272,9 +276,11 @@ public void loadTransferMethods() {
mPresenter.loadTransferMethods();
}
- interface OnTransferMethodContextMenuDeletionSelected {
+ interface OnTransferMethodContextMenuItemSelected {
void showConfirmationDialog(@NonNull final TransferMethod transferMethod);
+
+ void invokeTransferMethodEdit(@NonNull final TransferMethod transferMethod);
}
interface OnAddNewTransferMethodSelected {
@@ -294,12 +300,12 @@ interface OnLoadTransferMethodNetworkErrorCallback {
private static class ListTransferMethodAdapter extends RecyclerView.Adapter {
private List mTransferMethodList;
- private OnTransferMethodContextMenuDeletionSelected mOnTransferMethodContextMenuDeletionSelected;
+ private OnTransferMethodContextMenuItemSelected mOnTransferMethodContextMenuItemSelected;
ListTransferMethodAdapter(final List transferMethodList,
- final OnTransferMethodContextMenuDeletionSelected onTransferMethodContextMenuSelection) {
+ final OnTransferMethodContextMenuItemSelected onTransferMethodContextMenuSelection) {
mTransferMethodList = transferMethodList;
- mOnTransferMethodContextMenuDeletionSelected = onTransferMethodContextMenuSelection;
+ mOnTransferMethodContextMenuItemSelected = onTransferMethodContextMenuSelection;
}
@NonNull
@@ -388,7 +394,10 @@ public void onClick(View v) {
@Override
public boolean onMenuItemClick(MenuItem item) {
if (item.getItemId() == R.id.remove_account_context_option) {
- mOnTransferMethodContextMenuDeletionSelected.showConfirmationDialog(transferMethod);
+ mOnTransferMethodContextMenuItemSelected.showConfirmationDialog(transferMethod);
+ return true;
+ } if (item.getItemId() == R.id.edit_account_context_option) {
+ mOnTransferMethodContextMenuItemSelected.invokeTransferMethodEdit(transferMethod);
return true;
}
return false;
diff --git a/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/view/UpdateTransferMethodActivity.java b/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/view/UpdateTransferMethodActivity.java
new file mode 100644
index 000000000..7bb47db9c
--- /dev/null
+++ b/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/view/UpdateTransferMethodActivity.java
@@ -0,0 +1,169 @@
+package com.hyperwallet.android.ui.transfermethod.view;
+
+import android.content.pm.ActivityInfo;
+import android.os.Bundle;
+import android.view.View;
+import android.view.WindowManager;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.Toolbar;
+import androidx.core.content.ContextCompat;
+import androidx.fragment.app.FragmentManager;
+
+import com.google.android.material.appbar.CollapsingToolbarLayout;
+import com.hyperwallet.android.model.Error;
+import com.hyperwallet.android.ui.R;
+import com.hyperwallet.android.ui.common.util.PageGroups;
+import com.hyperwallet.android.ui.common.view.ActivityUtils;
+import com.hyperwallet.android.ui.common.view.TransferMethodUtils;
+import com.hyperwallet.android.ui.common.view.error.OnNetworkErrorCallback;
+
+import java.util.List;
+
+public class UpdateTransferMethodActivity extends AppCompatActivity implements
+ WidgetSelectionDialogFragment.WidgetSelectionItemListener,
+ UpdateTransferMethodFragment.OnUpdateTransferMethodNetworkErrorCallback,
+ UpdateTransferMethodFragment.OnLoadTransferMethodConfigurationFieldsNetworkErrorCallback,
+ OnNetworkErrorCallback, WidgetDateDialogFragment.OnSelectedDateCallback {
+
+ public static final String TAG = "transfer-method:update:collect-transfer-method-information";
+
+ public static final String EXTRA_TRANSFER_METHOD_TOKEN = "EXTRA_TRANSFER_METHOD_TOKEN";
+ private static final String ARGUMENT_RETRY_ACTION = "ARGUMENT_RETRY_ACTION";
+ public static final String EXTRA_LOCK_SCREEN_ORIENTATION_TO_PORTRAIT = "EXTRA_LOCK_SCREEN_ORIENTATION_TO_PORTRAIT";
+ private static final short RETRY_SHOW_ERROR_UPDATE_TRANSFER_METHOD = 100;
+ private static final short RETRY_SHOW_ERROR_LOAD_TMC_FIELDS = 101;
+
+ private short mRetryCode;
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_update_transfer_method);
+
+ getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
+
+ Toolbar toolbar = findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+ getSupportActionBar().setDisplayShowHomeEnabled(true);
+ CollapsingToolbarLayout collapsingToolbar = findViewById(R.id.collapsing_toolbar);
+ int titleStyleCollapse = TransferMethodUtils.getAdjustCollapseTitleStyle(getTitle().toString());
+ collapsingToolbar.setCollapsedTitleTextAppearance(titleStyleCollapse);
+ int titleStyleExpanded = TransferMethodUtils.getAdjustExpandTitleStyle(getTitle().toString());
+ collapsingToolbar.setExpandedTitleTextAppearance(titleStyleExpanded);
+ getSupportActionBar().setTitle("");
+
+ toolbar.setNavigationOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ finish();
+ }
+ });
+
+ if (getIntent().getBooleanExtra(EXTRA_LOCK_SCREEN_ORIENTATION_TO_PORTRAIT, false)) {
+ setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+ }
+ if (savedInstanceState == null) {
+ ActivityUtils.initFragment(this, UpdateTransferMethodFragment.newInstance(
+ getIntent().getStringExtra(EXTRA_TRANSFER_METHOD_TOKEN)
+ ), R.id.update_transfer_method_fragment);
+ } else {
+ mRetryCode = savedInstanceState.getShort(ARGUMENT_RETRY_ACTION);
+ }
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ outState.putShort(ARGUMENT_RETRY_ACTION, mRetryCode);
+ super.onSaveInstanceState(outState);
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Bundle savedInstanceState) {
+ super.onRestoreInstanceState(savedInstanceState);
+
+ if (savedInstanceState != null) {
+ mRetryCode = savedInstanceState.getShort(ARGUMENT_RETRY_ACTION);
+ }
+ }
+
+ @Override
+ public boolean onSupportNavigateUp() {
+ onBackPressed();
+ return true;
+ }
+
+ @Override
+ public void onBackPressed() {
+ getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
+ getWindow().setStatusBarColor(ContextCompat.getColor(this, R.color.colorPrimaryDark));
+ getWindow().getDecorView().setSystemUiVisibility(0);
+ super.onBackPressed();
+ }
+
+ @Override
+ public void retry() {
+ UpdateTransferMethodFragment fragment = getUpdateTransferFragment();
+ switch (mRetryCode) {
+ case RETRY_SHOW_ERROR_UPDATE_TRANSFER_METHOD:
+ fragment.retryUpdateTransferMethod();
+ break;
+ case RETRY_SHOW_ERROR_LOAD_TMC_FIELDS:
+ fragment.reloadTransferMethodConfigurationFields();
+ break;
+ default: // no default action
+ }
+ }
+
+ private UpdateTransferMethodFragment getUpdateTransferFragment() {
+ FragmentManager fragmentManager = getSupportFragmentManager();
+ UpdateTransferMethodFragment fragment = (UpdateTransferMethodFragment)
+ fragmentManager.findFragmentById(R.id.update_transfer_method_fragment);
+
+ if (fragment == null) {
+ fragment = UpdateTransferMethodFragment.newInstance(
+ getIntent().getStringExtra(EXTRA_TRANSFER_METHOD_TOKEN));
+ }
+ return fragment;
+ }
+
+ @Override
+ public void showErrorsLoadTransferMethodConfigurationFields(@NonNull List errors) {
+ mRetryCode = RETRY_SHOW_ERROR_LOAD_TMC_FIELDS;
+ ActivityUtils.showError(this, TAG, PageGroups.TRANSFER_METHOD, errors);
+ }
+
+ @Override
+ public void showErrorsUpdateTransferMethod(@NonNull List errors) {
+ mRetryCode = RETRY_SHOW_ERROR_UPDATE_TRANSFER_METHOD;
+ ActivityUtils.showError(this, TAG, PageGroups.TRANSFER_METHOD, errors);
+ }
+
+ @Override
+ public void setSelectedDateField(@NonNull String fieldName, String selectedValue) {
+ FragmentManager fragmentManager = getSupportFragmentManager();
+ UpdateTransferMethodFragment updateTransferMethodFragment =
+ (UpdateTransferMethodFragment) fragmentManager.findFragmentById(R.id.update_transfer_method_fragment);
+ if (updateTransferMethodFragment != null) {
+ updateTransferMethodFragment.onDateSelected(selectedValue, fieldName);
+ }
+ }
+
+ @Override
+ public void onWidgetSelectionItemClicked(@NonNull String selectedValue, @NonNull String fieldName) {
+ FragmentManager fragmentManager = getSupportFragmentManager();
+ UpdateTransferMethodFragment updateTransferMethodFragment =
+ (UpdateTransferMethodFragment) fragmentManager.findFragmentById(R.id.update_transfer_method_fragment);
+ updateTransferMethodFragment.onWidgetSelectionItemClicked(selectedValue, fieldName);
+
+ WidgetSelectionDialogFragment widgetSelectionDialogFragment =
+ (WidgetSelectionDialogFragment) fragmentManager.findFragmentById(android.R.id.content);
+ widgetSelectionDialogFragment.dismiss();
+ getSupportFragmentManager().popBackStack(WidgetSelectionDialogFragment.TAG,
+ FragmentManager.POP_BACK_STACK_INCLUSIVE);
+ }
+}
diff --git a/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/view/UpdateTransferMethodContract.java b/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/view/UpdateTransferMethodContract.java
new file mode 100644
index 000000000..b66bdda1f
--- /dev/null
+++ b/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/view/UpdateTransferMethodContract.java
@@ -0,0 +1,65 @@
+package com.hyperwallet.android.ui.transfermethod.view;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.hyperwallet.android.model.Error;
+import com.hyperwallet.android.model.graphql.Fee;
+import com.hyperwallet.android.model.graphql.HyperwalletTransferMethodConfigurationField;
+import com.hyperwallet.android.model.graphql.ProcessingTime;
+import com.hyperwallet.android.model.graphql.field.FieldGroup;
+import com.hyperwallet.android.model.transfermethod.TransferMethod;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * View and Presenter Contract for Updating Transfer Method
+ */
+public interface UpdateTransferMethodContract {
+
+ interface View {
+
+ void notifyTransferMethodUpdated(@NonNull final TransferMethod transferMethod);
+
+ void showErrorUpdateTransferMethod(@NonNull final List errors);
+
+ void showErrorLoadTransferMethodConfigurationFields(@NonNull final List errors);
+
+ void showTransferMethodFields(@NonNull final HyperwalletTransferMethodConfigurationField field);
+
+ void showTransactionInformation(@NonNull final List fees,
+ @Nullable final ProcessingTime processingTime);
+
+ void showUpdateButtonProgressBar();
+
+ void hideUpdateButtonProgressBar();
+
+ void showProgressBar();
+
+ void hideProgressBar();
+
+ void showInputErrors(@NonNull final List errors);
+
+ /**
+ * Check the state of a View
+ *
+ * @return true when View is added to Container
+ */
+ boolean isActive();
+
+ void retryUpdateTransferMethod();
+
+ void reloadTransferMethodConfigurationFields();
+ }
+
+ interface Presenter {
+
+ void updateTransferMethod(@NonNull TransferMethod transferMethod);
+
+ void loadTransferMethodConfigurationFields(boolean forceUpdate, @NonNull final String transferMethodType, @NonNull final String transferMethodToken);
+
+ void handleUnmappedFieldError(@NonNull final Map fieldSet,
+ @NonNull final List errors);
+ }
+}
diff --git a/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/view/UpdateTransferMethodFragment.java b/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/view/UpdateTransferMethodFragment.java
new file mode 100644
index 000000000..49ad03ac6
--- /dev/null
+++ b/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/view/UpdateTransferMethodFragment.java
@@ -0,0 +1,689 @@
+package com.hyperwallet.android.ui.transfermethod.view;
+
+import static com.hyperwallet.android.model.transfermethod.TransferMethod.TransferMethodFields.TYPE;
+import static com.hyperwallet.android.model.transfermethod.TransferMethod.TransferMethodTypes.BANK_ACCOUNT;
+import static com.hyperwallet.android.model.transfermethod.TransferMethod.TransferMethodTypes.BANK_CARD;
+import static com.hyperwallet.android.model.transfermethod.TransferMethod.TransferMethodTypes.PAPER_CHECK;
+import static com.hyperwallet.android.model.transfermethod.TransferMethod.TransferMethodTypes.PAYPAL_ACCOUNT;
+import static com.hyperwallet.android.model.transfermethod.TransferMethod.TransferMethodTypes.VENMO_ACCOUNT;
+import static com.hyperwallet.android.model.transfermethod.TransferMethod.TransferMethodTypes.WIRE_ACCOUNT;
+import static com.hyperwallet.android.ui.common.intent.HyperwalletIntent.EXTRA_TRANSFER_METHOD_UPDATED;
+import static com.hyperwallet.android.ui.transfermethod.TransferMethodLocalBroadcast.TransferMethodLocalBroadcastAction.ACTION_HYPERWALLET_TRANSFER_METHOD_UPDATED;
+import static com.hyperwallet.android.ui.transfermethod.view.FeeFormatter.isFeeAvailable;
+import static com.hyperwallet.android.ui.transfermethod.view.FeeFormatter.isProcessingTimeAvailable;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.Button;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.core.widget.NestedScrollView;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentTransaction;
+import androidx.localbroadcastmanager.content.LocalBroadcastManager;
+
+import com.hyperwallet.android.exception.HyperwalletException;
+import com.hyperwallet.android.model.Error;
+import com.hyperwallet.android.model.graphql.Fee;
+import com.hyperwallet.android.model.graphql.HyperwalletTransferMethodConfigurationField;
+import com.hyperwallet.android.model.graphql.ProcessingTime;
+import com.hyperwallet.android.model.graphql.field.Field;
+import com.hyperwallet.android.model.graphql.field.FieldGroup;
+import com.hyperwallet.android.model.graphql.field.TransferMethodConfiguration;
+import com.hyperwallet.android.model.transfermethod.BankAccount;
+import com.hyperwallet.android.model.transfermethod.BankCard;
+import com.hyperwallet.android.model.transfermethod.PaperCheck;
+import com.hyperwallet.android.model.transfermethod.PayPalAccount;
+import com.hyperwallet.android.model.transfermethod.TransferMethod;
+import com.hyperwallet.android.model.transfermethod.VenmoAccount;
+import com.hyperwallet.android.ui.R;
+import com.hyperwallet.android.ui.common.insight.HyperwalletInsight;
+import com.hyperwallet.android.ui.common.util.ErrorTypes;
+import com.hyperwallet.android.ui.common.util.PageGroups;
+import com.hyperwallet.android.ui.common.view.TransferMethodUtils;
+import com.hyperwallet.android.ui.transfermethod.TransferMethodLocalBroadcast;
+import com.hyperwallet.android.ui.transfermethod.repository.TransferMethodRepositoryFactory;
+import com.hyperwallet.android.ui.transfermethod.view.widget.AbstractWidget;
+import com.hyperwallet.android.ui.transfermethod.view.widget.DateChangedListener;
+import com.hyperwallet.android.ui.transfermethod.view.widget.DateWidget;
+import com.hyperwallet.android.ui.transfermethod.view.widget.WidgetEventListener;
+import com.hyperwallet.android.ui.transfermethod.view.widget.WidgetFactory;
+import com.hyperwallet.android.ui.transfermethod.view.widget.WidgetInputState;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.TreeMap;
+
+public class UpdateTransferMethodFragment extends Fragment implements WidgetEventListener,
+ UpdateTransferMethodContract.View {
+
+ public static final String TAG = UpdateTransferMethodActivity.TAG;
+
+ private static final String ARGUMENT_TRANSFER_METHOD_TOKEN = "ARGUMENT_TRANSFER_METHOD_TOKEN";
+ private static final String ARGUMENT_SHOW_UPDATE_PROGRESS_BAR = "ARGUMENT_SHOW_UPDATE_PROGRESS_BAR";
+ private static final String ARGUMENT_WIDGET_STATE_MAP = "ARGUMENT_WIDGET_STATE_MAP";
+ private static final boolean FORCE_UPDATE = false;
+ private View mUpdateButtonProgressBar;
+ private Button mUpdateTransferMethodButton;
+ private ViewGroup mDynamicContainer;
+ private NestedScrollView mNestedScrollView;
+ private OnUpdateTransferMethodNetworkErrorCallback mOnUpdateTransferMethodNetworkErrorCallback;
+ private OnLoadTransferMethodConfigurationFieldsNetworkErrorCallback
+ mOnLoadTransferMethodConfigurationFieldsNetworkErrorCallback;
+ private UpdateTransferMethodContract.Presenter mPresenter;
+ private View mProgressBar;
+ private boolean mUpdateProgressBar;
+ private String mTransferMethodType;
+ private TransferMethod mTransferMethod;
+ private String mTransferMethodToken;
+ private HashMap mWidgetInputStateHashMap;
+ private boolean isEdited;
+
+ /**
+ * Please do not use this to have instance of UpdateTransferMethodFragment this is reserved for android framework
+ */
+ public UpdateTransferMethodFragment() {
+ }
+
+ /**
+ * Creates new instance of UpdateTransferMethodFragment this is the proper initialization of this class
+ * since the default constructor is reserved for android framework when lifecycle is triggered.
+ * The parameters in {@link UpdateTransferMethodFragment#newInstance(String)} is mandatory
+ * and should be supplied with correct data or this fragment will not initialize properly.
+ *
+ * @param transferMethodToken the country selected when creating transfer method
+ */
+ public static UpdateTransferMethodFragment newInstance(@NonNull String transferMethodToken) {
+ UpdateTransferMethodFragment updateTransferMethodFragment = new UpdateTransferMethodFragment();
+ Bundle arguments = new Bundle();
+
+ updateTransferMethodFragment.mTransferMethodToken = transferMethodToken;
+ updateTransferMethodFragment.mWidgetInputStateHashMap = new HashMap<>(1);
+ updateTransferMethodFragment.mTransferMethod = null;
+ arguments.putString(ARGUMENT_TRANSFER_METHOD_TOKEN, transferMethodToken);
+ arguments.putSerializable(ARGUMENT_WIDGET_STATE_MAP, updateTransferMethodFragment.mWidgetInputStateHashMap);
+ updateTransferMethodFragment.setArguments(arguments);
+
+ return updateTransferMethodFragment;
+ }
+
+ @Override
+ public void onAttach(Context context) {
+ super.onAttach(context);
+
+ try {
+ mOnUpdateTransferMethodNetworkErrorCallback = (OnUpdateTransferMethodNetworkErrorCallback) context;
+ } catch (ClassCastException e) {
+ throw new ClassCastException(getActivity().toString() + " must implement "
+ + OnUpdateTransferMethodNetworkErrorCallback.class.getCanonicalName());
+ }
+
+ try {
+ mOnLoadTransferMethodConfigurationFieldsNetworkErrorCallback =
+ (OnLoadTransferMethodConfigurationFieldsNetworkErrorCallback) context;
+ } catch (ClassCastException e) {
+ throw new ClassCastException(getActivity().toString() + " must implement "
+ + OnLoadTransferMethodConfigurationFieldsNetworkErrorCallback.class.getCanonicalName());
+ }
+ }
+
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setRetainInstance(true);
+ }
+
+
+ @Nullable
+ @Override
+ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
+ @Nullable Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.fragment_update_transfer_method, container, false);
+ }
+
+ @Override
+ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+
+ mDynamicContainer = view.findViewById(R.id.update_transfer_method_dynamic_container);
+ mNestedScrollView = view.findViewById(R.id.update_transfer_method_scroll_view);
+
+ mUpdateButtonProgressBar = view.findViewById(R.id.update_transfer_method_button_progress_bar);
+ mProgressBar = view.findViewById(R.id.update_transfer_method_progress_bar_layout);
+ mUpdateTransferMethodButton = view.findViewById(R.id.update_transfer_method_button);
+
+ mUpdateTransferMethodButton.setBackgroundColor(getResources().getColor(R.color.colorPrimary));
+ mUpdateTransferMethodButton.setTextColor(getResources().getColor(R.color.regularColorPrimary));
+ mUpdateTransferMethodButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ HyperwalletInsight.getInstance().trackClick(requireContext(),
+ TAG, PageGroups.TRANSFER_METHOD,
+ HyperwalletInsight.LINK_SELECT_TRANSFER_METHOD_CREATE,
+ new HyperwalletInsight.TransferMethodParamsBuilder()
+ .type(mTransferMethodType)
+ .build());
+
+ triggerUpdate();
+ }
+ });
+ }
+
+ @Override
+ public void onActivityCreated(@Nullable Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+
+ TransferMethodRepositoryFactory factory = TransferMethodRepositoryFactory.getInstance();
+ mPresenter = new UpdateTransferMethodPresenter(this,
+ factory.getTransferMethodUpdateConfigurationRepository(),
+ factory.getTransferMethodRepository());
+ }
+
+ @Override
+ public void onViewStateRestored(@Nullable Bundle savedInstanceState) {
+ super.onViewStateRestored(savedInstanceState);
+
+ if (savedInstanceState != null) {
+ mWidgetInputStateHashMap = (HashMap) savedInstanceState.getSerializable(ARGUMENT_WIDGET_STATE_MAP);
+ mTransferMethodToken = savedInstanceState.getString(ARGUMENT_TRANSFER_METHOD_TOKEN);
+ mUpdateProgressBar = savedInstanceState.getBoolean(ARGUMENT_SHOW_UPDATE_PROGRESS_BAR);
+ mTransferMethod = savedInstanceState.getParcelable(ARGUMENT_TRANSFER_METHOD_TOKEN);
+ } else { // same as UpdateTransferMethodFragment#newInstance
+ mWidgetInputStateHashMap = (HashMap) getArguments().getSerializable(ARGUMENT_WIDGET_STATE_MAP);
+ mTransferMethodToken = getArguments().getString(ARGUMENT_TRANSFER_METHOD_TOKEN);
+ }
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ mPresenter.loadTransferMethodConfigurationFields(FORCE_UPDATE, mTransferMethodType, mTransferMethodToken);
+ }
+
+ @Override
+ public void showErrorUpdateTransferMethod(@NonNull final List errors) {
+ mOnUpdateTransferMethodNetworkErrorCallback.showErrorsUpdateTransferMethod(errors);
+ }
+
+ @Override
+ public void onSaveInstanceState(@NonNull Bundle outState) {
+ outState.putSerializable(ARGUMENT_WIDGET_STATE_MAP, mWidgetInputStateHashMap);
+ outState.putString(ARGUMENT_TRANSFER_METHOD_TOKEN, mTransferMethodToken);
+ outState.putBoolean(ARGUMENT_SHOW_UPDATE_PROGRESS_BAR, mUpdateProgressBar);
+ super.onSaveInstanceState(outState);
+ }
+
+ private void triggerUpdate() {
+ hideSoftKeys();
+ if (performValidation()) {
+ switch (mTransferMethodType) {
+ case BANK_ACCOUNT:
+ mTransferMethod = new BankAccount.Builder()
+ .token(mTransferMethodToken)
+ .build();
+ break;
+ case BANK_CARD:
+ mTransferMethod = new BankCard.Builder()
+ .token(mTransferMethodToken)
+ .build();
+ break;
+ case PAYPAL_ACCOUNT:
+ mTransferMethod = new PayPalAccount.Builder()
+ .token(mTransferMethodToken)
+ .build();
+ break;
+ case WIRE_ACCOUNT:
+ mTransferMethod = new BankAccount.Builder()
+ .token(mTransferMethodToken)
+ .transferMethodType(WIRE_ACCOUNT)
+ .build();
+ break;
+ case VENMO_ACCOUNT:
+ mTransferMethod = new VenmoAccount.Builder()
+ .token(mTransferMethodToken)
+ .build();
+ break;
+ case PAPER_CHECK:
+ mTransferMethod = new PaperCheck.Builder()
+ .token(mTransferMethodToken)
+ .build();
+ break;
+ default:
+ mTransferMethod = new TransferMethod();
+ mTransferMethod.setField(TYPE, mTransferMethodType);
+ }
+
+ for (int i = 0; i < mDynamicContainer.getChildCount(); i++) {
+ View view = mDynamicContainer.getChildAt(i);
+ if (view.getTag() instanceof AbstractWidget) {
+ AbstractWidget widget = (AbstractWidget) view.getTag();
+ if (widget.isEdited) {
+ isEdited = true;
+ mTransferMethod.setField(widget.getName(), widget.getValue());
+ }
+ }
+ }
+
+ if (isEdited) {
+ mPresenter.updateTransferMethod(mTransferMethod);
+ } else {
+ getActivity().finish();
+ }
+ }
+ }
+
+ private void hideSoftKeys() {
+ View view = requireActivity().getCurrentFocus();
+
+ if (view != null) {
+ view.clearFocus();
+ InputMethodManager inputMethodManager = (InputMethodManager) view.getContext().getSystemService(
+ Activity.INPUT_METHOD_SERVICE);
+ inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
+ }
+ }
+
+ /**
+ * Use this to perform validation on an entire form, typically used during form submission.
+ *
+ * @return true if the form is valid
+ */
+ private boolean performValidation() {
+ boolean containsInvalidWidget = false;
+
+ // this is added since some phones triggers the create button but the widgets are not yet initialized
+ boolean hasWidget = false;
+ Resources resources = requireContext().getResources();
+ int pixels = (int) (resources.getDimension(R.dimen.negative_padding) * resources.getDisplayMetrics().density);
+
+ for (int i = 0; i < mDynamicContainer.getChildCount(); i++) {
+ View currentView = mDynamicContainer.getChildAt(i);
+ if (currentView.getTag() instanceof AbstractWidget) {
+ hasWidget = true;
+
+ AbstractWidget widget = (AbstractWidget) currentView.getTag();
+ WidgetInputState widgetInputState = mWidgetInputStateHashMap.get(widget.getName());
+ widgetInputState.setValue(widget.getValue());
+
+ if (!isWidgetItemValid(widget) && !containsInvalidWidget) {
+ containsInvalidWidget = true;
+ mNestedScrollView.smoothScrollTo(0, currentView.getTop() - pixels);
+ }
+ }
+ }
+ return hasWidget && !containsInvalidWidget;
+ }
+
+ /**
+ * Use this to perform validation on a single widget item, typically used while the user is inputting data.
+ *
+ * @param widget the widget to validate
+ * @return true if the input is valid
+ */
+ private boolean isWidgetItemValid(@NonNull final AbstractWidget widget) {
+ boolean valid = true;
+ Context context = requireContext();
+
+ WidgetInputState widgetInputState = mWidgetInputStateHashMap.get(widget.getName());
+ widgetInputState.setValue(widget.getValue());
+ if (widget.isValid()) {
+ if (!widgetInputState.hasApiError()) {
+ widgetInputState.setErrorMessage(null);
+ widget.showValidationError(null);
+ }
+ } else {
+ HyperwalletInsight.getInstance().trackError(context,
+ TAG, PageGroups.TRANSFER_METHOD,
+ new HyperwalletInsight.ErrorParamsBuilder()
+ .message(widget.getErrorMessage())
+ .fieldName(widget.getName())
+ .type(ErrorTypes.FORM_ERROR)
+ .addAll(new HyperwalletInsight.TransferMethodParamsBuilder()
+ .type(mTransferMethodType)
+ .build())
+ .build());
+
+ valid = false;
+ widget.showValidationError(null);
+ widgetInputState.setErrorMessage(null);
+ widget.showValidationError(widget.getErrorMessage());
+ widgetInputState.setErrorMessage(widget.getErrorMessage());
+ widgetInputState.setHasApiError(false);
+ }
+ return valid;
+ }
+
+ @Override
+ public void notifyTransferMethodUpdated(@NonNull TransferMethod transferMethod) {
+ HyperwalletInsight.getInstance().trackImpression(requireContext(),
+ TAG, PageGroups.TRANSFER_METHOD,
+ new HyperwalletInsight.TransferMethodParamsBuilder()
+ .goal(HyperwalletInsight.TRANSFER_METHOD_GOAL)
+ .type(mTransferMethodType)
+ .build());
+
+ Intent intent = TransferMethodLocalBroadcast.createBroadcastIntentTransferMethodUpdated(
+ transferMethod);
+ LocalBroadcastManager.getInstance(getContext()).sendBroadcast(intent);
+
+ Intent activityResult = new Intent();
+ activityResult.setAction(ACTION_HYPERWALLET_TRANSFER_METHOD_UPDATED);
+ activityResult.putExtra(EXTRA_TRANSFER_METHOD_UPDATED, transferMethod);
+ getActivity().setResult(Activity.RESULT_OK, activityResult);
+ getActivity().finish();
+ }
+
+ @Override
+ public void showErrorLoadTransferMethodConfigurationFields(@NonNull List errors) {
+ mOnLoadTransferMethodConfigurationFieldsNetworkErrorCallback.showErrorsLoadTransferMethodConfigurationFields(
+ errors);
+ }
+
+ private String getSectionHeaderText(@NonNull final FieldGroup group, @NonNull final Locale locale,
+ @NonNull final String currency) {
+ if (FieldGroup.GroupTypes.ACCOUNT_INFORMATION.equals(group.getGroupName())) {
+ return requireContext().getString(R.string.account_information,
+ locale.getDisplayName().toUpperCase(), currency);
+ }
+
+ return requireContext().getString(requireContext().getResources()
+ .getIdentifier(group.getGroupName().toLowerCase(Locale.ROOT), "string",
+ requireContext().getPackageName()));
+ }
+
+ @Override
+ public void showTransactionInformation(@NonNull List fees,
+ @Nullable ProcessingTime processingTime) {
+ View header = getView().findViewById(R.id.update_transfer_method_static_container_header);
+ View container = getView().findViewById(R.id.update_transfer_method_static_container);
+ TextView feeAndProcessingTime = getView().findViewById(R.id.update_transfer_method_information);
+
+ if (isFeeAvailable(fees) && isProcessingTimeAvailable(processingTime)) {
+ String formattedFee = FeeFormatter.getFormattedFee(header.getContext(), fees);
+ feeAndProcessingTime.setVisibility(View.VISIBLE);
+ feeAndProcessingTime.setText(
+ feeAndProcessingTime.getContext().getString(R.string.feeAndProcessingTimeInformation, formattedFee,
+ processingTime.getValue()));
+ } else if (isFeeAvailable(fees) && !isProcessingTimeAvailable(processingTime)) {
+ String formattedFee = FeeFormatter.getFormattedFee(header.getContext(), fees);
+ feeAndProcessingTime.setVisibility(View.VISIBLE);
+ feeAndProcessingTime.setText(
+ feeAndProcessingTime.getContext().getString(R.string.feeInformation, formattedFee));
+ } else if (isProcessingTimeAvailable(processingTime) && !isFeeAvailable(fees)) {
+ feeAndProcessingTime.setVisibility(View.VISIBLE);
+ feeAndProcessingTime.setText(processingTime.getValue());
+ } else {
+ feeAndProcessingTime.setVisibility(View.GONE);
+ }
+
+ if (feeAndProcessingTime.getVisibility() == View.VISIBLE) {
+ header.setVisibility(View.VISIBLE);
+ container.setVisibility(View.VISIBLE);
+ } else {
+ header.setVisibility(View.GONE);
+ container.setVisibility(View.GONE);
+ }
+ }
+
+ @Override
+ public void showTransferMethodFields(
+ @NonNull HyperwalletTransferMethodConfigurationField hyperwalletTransferMethodConfigurationField) {
+ mDynamicContainer.removeAllViews();
+ mUpdateTransferMethodButton.setVisibility(View.VISIBLE);
+
+ try {
+ TransferMethodConfiguration fields = hyperwalletTransferMethodConfigurationField.getFields();
+ Locale locale = new Locale.Builder().setRegion(fields.getCountry()).build();
+ mTransferMethodType = fields.getTransferMethodType();
+ String transferMethod = TransferMethodUtils.getTransferMethodName(getContext(), mTransferMethodType);
+ ((UpdateTransferMethodActivity) getActivity()).getSupportActionBar().setTitle(transferMethod);
+ // group
+ for (FieldGroup group : fields.getFieldGroups()) {
+ View sectionHeader = LayoutInflater.from(mDynamicContainer.getContext())
+ .inflate(R.layout.item_widget_section_header, mDynamicContainer, false);
+ TextView sectionTitle = sectionHeader.findViewById(R.id.section_header_title);
+ sectionTitle.setText(getSectionHeaderText(group, locale, fields.getCurrency()));
+ sectionHeader.setId(View.generateViewId());
+ mDynamicContainer.addView(sectionHeader);
+
+ // group fields
+ for (final Field field : group.getFields()) {
+ AbstractWidget widget = WidgetFactory
+ .newWidget(field, this, mWidgetInputStateHashMap.containsKey(field.getName()) ?
+ mWidgetInputStateHashMap.get(field.getName()).getValue() : field.getValue(),
+ mUpdateTransferMethodButton);
+ if (mWidgetInputStateHashMap.isEmpty() || !mWidgetInputStateHashMap.containsKey(widget.getName())) {
+ mWidgetInputStateHashMap.put(widget.getName(), widget.getWidgetInputState());
+ }
+
+ View widgetView = widget.getView(mDynamicContainer);
+ widgetView.setTag(widget);
+ widgetView.setId(View.generateViewId());
+ final String error = mWidgetInputStateHashMap.get(widget.getName()).getErrorMessage();
+ widget.showValidationError(error);
+ mDynamicContainer.addView(widgetView);
+ }
+ }
+
+ HyperwalletInsight.getInstance().trackImpression(requireContext(),
+ TAG, PageGroups.TRANSFER_METHOD,
+ new HyperwalletInsight.TransferMethodParamsBuilder()
+ .type(mTransferMethodType)
+ .build());
+
+ if (mUpdateProgressBar) {
+ setVisibleAndDisableFields();
+ }
+ } catch (HyperwalletException e) {
+ throw new IllegalStateException("Widget initialization error: " + e.getMessage());
+ }
+ }
+
+ @Override
+ public void showUpdateButtonProgressBar() {
+ mUpdateProgressBar = true;
+ setVisibleAndDisableFields();
+ }
+
+ private void setVisibleAndDisableFields() {
+ getActivity().getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
+ WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
+ getActivity().getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
+ WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
+ mUpdateButtonProgressBar.setVisibility(View.VISIBLE);
+ mUpdateTransferMethodButton.setBackgroundColor(getResources().getColor(R.color.colorSecondaryDark));
+ }
+
+ @Override
+ public void hideUpdateButtonProgressBar() {
+ mUpdateProgressBar = false;
+ getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
+ getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
+ mUpdateButtonProgressBar.setVisibility(View.GONE);
+ mUpdateTransferMethodButton.setBackgroundColor(getResources().getColor(R.color.colorPrimary));
+ mUpdateTransferMethodButton.setTextColor(getResources().getColor(R.color.regularColorPrimary));
+ }
+
+ @Override
+ public void showProgressBar() {
+ mProgressBar.setVisibility(View.VISIBLE);
+ }
+
+ @Override
+ public void hideProgressBar() {
+ mProgressBar.setVisibility(View.GONE);
+ mUpdateTransferMethodButton.setVisibility(View.VISIBLE);
+ }
+
+ @Override
+ public void showInputErrors(@NonNull List errors) {
+ boolean focusSet = false;
+ Context context = requireContext();
+ Resources resources = context.getResources();
+ int pixels = (int) (resources.getDimension(R.dimen.negative_padding) * resources.getDisplayMetrics().density);
+
+ for (Error error : errors) {
+ for (int i = 0; i < mDynamicContainer.getChildCount(); i++) {
+ View view = mDynamicContainer.getChildAt(i);
+ if (view.getTag() instanceof AbstractWidget) {
+ AbstractWidget widget = (AbstractWidget) view.getTag();
+ WidgetInputState widgetInputState = mWidgetInputStateHashMap.get(widget.getName());
+ if (widget.getName().equals(error.getFieldName())) {
+ if (!focusSet) {
+ mNestedScrollView.smoothScrollTo(0, view.getTop() - pixels);
+ focusSet = true;
+ }
+ HyperwalletInsight.getInstance().trackError(context,
+ TAG, PageGroups.TRANSFER_METHOD,
+ new HyperwalletInsight.ErrorParamsBuilder()
+ .code(error.getCode())
+ .message(error.getMessage())
+ .fieldName(error.getFieldName())
+ .type(ErrorTypes.API_ERROR)
+ .build());
+
+ widget.showValidationError(null);
+ widgetInputState.setErrorMessage(null);
+ widget.showValidationError(error.getMessage());
+ widgetInputState.setErrorMessage(error.getMessage());
+ widgetInputState.setHasApiError(true);
+ } else {
+ widget.showValidationError(null);
+ widgetInputState.setErrorMessage(null);
+ }
+ }
+ }
+ }
+
+ mPresenter.handleUnmappedFieldError(mWidgetInputStateHashMap, errors);
+ }
+
+ @Override
+ public boolean isActive() {
+ return isAdded();
+ }
+
+ @Override
+ public void retryUpdateTransferMethod() {
+ mPresenter.updateTransferMethod(mTransferMethod);
+ }
+
+ @Override
+ public void reloadTransferMethodConfigurationFields() {
+ mPresenter.loadTransferMethodConfigurationFields(FORCE_UPDATE, mTransferMethodType, mTransferMethodToken);
+ }
+
+ @Override
+ public void valueChanged(@NonNull AbstractWidget widget) {
+ isWidgetItemValid(widget);
+ }
+
+ @Override
+ public boolean isWidgetSelectionFragmentDialogOpen() {
+ return getFragmentManager().findFragmentByTag(WidgetSelectionDialogFragment.TAG) != null;
+ }
+
+ @Override
+ public void openWidgetSelectionFragmentDialog(@NonNull TreeMap nameValueMap,
+ @NonNull String selectedName, @NonNull String fieldLabel, @NonNull String fieldName) {
+ String selectedLabel = selectedName;
+ if (TextUtils.isEmpty(selectedLabel)) {
+ selectedLabel = mWidgetInputStateHashMap.get(fieldName).getSelectedName();
+ } else {
+ mWidgetInputStateHashMap.get(fieldName).setSelectedName(selectedLabel);
+ }
+
+ if (!isWidgetSelectionFragmentDialogOpen()) {
+ WidgetSelectionDialogFragment widgetSelectionDialogFragment = WidgetSelectionDialogFragment
+ .newInstance(nameValueMap, selectedLabel, fieldLabel, fieldName);
+
+ FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
+ fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
+ fragmentTransaction.replace(android.R.id.content, widgetSelectionDialogFragment,
+ WidgetSelectionDialogFragment.TAG);
+ fragmentTransaction.addToBackStack(WidgetSelectionDialogFragment.TAG);
+ fragmentTransaction.commit();
+ }
+ }
+
+ @Override
+ public void widgetFocused(@NonNull String fieldName) {
+ WidgetInputState widgetInputState = mWidgetInputStateHashMap.get(fieldName);
+ widgetInputState.setHasFocused(true);
+ }
+
+ @Override
+ public void saveTextChanged(@NonNull String fieldName, @NonNull String value) {
+ WidgetInputState inputState = mWidgetInputStateHashMap.get(fieldName);
+ if (inputState.hasApiError()) {
+ String oldValue = inputState.getValue();
+ if (!TextUtils.isEmpty(oldValue) && !oldValue.equals(value)) {
+ inputState.setHasApiError(false);
+ }
+ }
+ inputState.setValue(value);
+ }
+
+ void onWidgetSelectionItemClicked(@NonNull final String selectedValue, @NonNull final String fieldName) {
+ for (int i = 0; i < mDynamicContainer.getChildCount(); i++) {
+ View view = mDynamicContainer.getChildAt(i);
+ if (view.getTag() instanceof WidgetSelectionDialogFragment.WidgetSelectionItemType) {
+ AbstractWidget widget = (AbstractWidget) view.getTag();
+ if (fieldName.equals(widget.getName())) {
+ ((WidgetSelectionDialogFragment.WidgetSelectionItemType) view.getTag())
+ .onWidgetSelectionItemClicked(selectedValue);
+ return;
+ }
+ }
+ }
+ }
+
+ @Override
+ public void openWidgetDateDialog(@Nullable String date, @NonNull String fieldName) {
+ if (getFragmentManager() != null) {
+ WidgetDateDialogFragment dateDialogFragment = (WidgetDateDialogFragment)
+ getFragmentManager().findFragmentByTag(WidgetDateDialogFragment.TAG);
+
+ if (dateDialogFragment == null) {
+ dateDialogFragment = WidgetDateDialogFragment.newInstance(date, fieldName);
+ }
+
+ if (!dateDialogFragment.isAdded()) {
+ dateDialogFragment.show(getFragmentManager());
+ }
+ }
+ }
+
+ void onDateSelected(@NonNull final String selectedValue, @NonNull final String fieldName) {
+ for (int i = 0; i < mDynamicContainer.getChildCount(); i++) {
+ View view = mDynamicContainer.getChildAt(i);
+ if (view.getTag() instanceof DateWidget) {
+ AbstractWidget widget = (AbstractWidget) view.getTag();
+ if (fieldName.equals(widget.getName()) && widget instanceof DateChangedListener) {
+ ((DateChangedListener) view.getTag()).onUpdate(selectedValue);
+ return;
+ }
+ }
+ }
+ }
+
+ interface OnLoadTransferMethodConfigurationFieldsNetworkErrorCallback {
+ void showErrorsLoadTransferMethodConfigurationFields(@NonNull final List errors);
+ }
+
+ interface OnUpdateTransferMethodNetworkErrorCallback {
+ void showErrorsUpdateTransferMethod(@NonNull final List errors);
+ }
+}
diff --git a/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/view/UpdateTransferMethodPresenter.java b/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/view/UpdateTransferMethodPresenter.java
new file mode 100644
index 000000000..3194f6055
--- /dev/null
+++ b/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/view/UpdateTransferMethodPresenter.java
@@ -0,0 +1,109 @@
+package com.hyperwallet.android.ui.transfermethod.view;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.hyperwallet.android.model.Error;
+import com.hyperwallet.android.model.Errors;
+import com.hyperwallet.android.model.graphql.HyperwalletTransferMethodConfigurationField;
+import com.hyperwallet.android.model.transfermethod.TransferMethod;
+import com.hyperwallet.android.ui.R;
+import com.hyperwallet.android.ui.transfermethod.repository.TransferMethodRepository;
+import com.hyperwallet.android.ui.transfermethod.repository.TransferMethodUpdateConfigurationRepository;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public class UpdateTransferMethodPresenter implements UpdateTransferMethodContract.Presenter {
+ private static final String ERROR_UNMAPPED_FIELD = "ERROR_UNMAPPED_FIELD";
+ private final TransferMethodUpdateConfigurationRepository mTransferMethodUpdateConfigurationRepository;
+ private final TransferMethodRepository mTransferMethodRepository;
+ private final UpdateTransferMethodContract.View mView;
+
+ public UpdateTransferMethodPresenter(UpdateTransferMethodContract.View view,
+ TransferMethodUpdateConfigurationRepository transferMethodUpdateConfigurationRepository,
+ TransferMethodRepository transferMethodRepository) {
+ mView = view;
+ mTransferMethodUpdateConfigurationRepository = transferMethodUpdateConfigurationRepository;
+ mTransferMethodRepository = transferMethodRepository;
+ }
+
+ @Override
+ public void loadTransferMethodConfigurationFields(boolean forceUpdate, @NonNull String transferMethodType,
+ @NonNull final String transferMethodToken) {
+ mView.showProgressBar();
+
+ if (forceUpdate) {
+ mTransferMethodUpdateConfigurationRepository.refreshFields();
+ }
+
+ mTransferMethodUpdateConfigurationRepository.getFields(transferMethodToken,
+ new TransferMethodUpdateConfigurationRepository.LoadFieldsCallback() {
+ @Override
+ public void onFieldsLoaded(@Nullable HyperwalletTransferMethodConfigurationField field) {
+ if (!mView.isActive()) {
+ return;
+ }
+
+ mView.hideProgressBar();
+ mView.showTransferMethodFields(field);
+ // there can be multiple fees when we have flat fee + percentage fees
+ mView.showTransactionInformation(field.getFees(), field.getProcessingTime());
+ }
+
+ @Override
+ public void onError(@NonNull Errors errors) {
+ if (!mView.isActive()) {
+ return;
+ }
+ mView.hideProgressBar();
+ mView.showErrorLoadTransferMethodConfigurationFields(errors.getErrors());
+ }
+ });
+ }
+
+ @Override
+ public void updateTransferMethod(@NonNull TransferMethod transferMethod) {
+ mView.showUpdateButtonProgressBar();
+ mTransferMethodRepository.updateTransferMethod(transferMethod,
+ new TransferMethodRepository.LoadTransferMethodCallback() {
+ @Override
+ public void onTransferMethodLoaded(TransferMethod transferMethod) {
+
+ if (!mView.isActive()) {
+ return;
+ }
+ mView.hideUpdateButtonProgressBar();
+ mView.notifyTransferMethodUpdated(transferMethod);
+ }
+
+ @Override
+ public void onError(Errors errors) {
+ if (!mView.isActive()) {
+ return;
+ }
+
+ mView.hideUpdateButtonProgressBar();
+ if (errors.containsInputError()) {
+ mView.showInputErrors(errors.getErrors());
+ } else {
+ mView.showErrorUpdateTransferMethod(errors.getErrors());
+ }
+ }
+ });
+ }
+
+ @Override
+ public void handleUnmappedFieldError(@NonNull Map fieldSet, @NonNull List errors) {
+ for (Error error : errors) {
+ if (fieldSet.get(error.getFieldName()) == null) {
+ List errorList = new ArrayList() {{
+ add(new Error(R.string.error_unmapped_field, ERROR_UNMAPPED_FIELD));
+ }};
+ mView.showErrorUpdateTransferMethod(errorList);
+ return;
+ }
+ }
+ }
+}
diff --git a/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/view/widget/AbstractMaskedInputWidget.java b/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/view/widget/AbstractMaskedInputWidget.java
index 72cf67afa..87218b628 100644
--- a/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/view/widget/AbstractMaskedInputWidget.java
+++ b/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/view/widget/AbstractMaskedInputWidget.java
@@ -69,7 +69,7 @@ String formatToApi(@NonNull final String displayValue) {
* @return a String formatted to the specification in the mask pattern
*/
String formatToDisplay(@NonNull final String apiValue) {
- if (mField != null && mField.getMask() != null) {
+ if (mField != null && mField.getMask() != null && !mField.isFieldValueMasked()) {
// format
String pattern = mField.getMask().getPattern(apiValue);
if (!TextUtils.isEmpty(pattern)) {
diff --git a/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/view/widget/AbstractWidget.java b/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/view/widget/AbstractWidget.java
index 3db0c5618..0e9cb8311 100644
--- a/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/view/widget/AbstractWidget.java
+++ b/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/view/widget/AbstractWidget.java
@@ -36,6 +36,7 @@ public abstract class AbstractWidget {
protected final WidgetEventListener mListener;
protected int mBottomViewId = 0;
protected WidgetInputState mWidgetInputState;
+ public boolean isEdited = false;
public AbstractWidget(@Nullable Field field, @NonNull WidgetEventListener listener,
@Nullable String defaultValue, @NonNull View defaultFocusView) {
@@ -64,6 +65,9 @@ public boolean isValid() {
if (mField == null) {
return true;
}
+ else if(!isEdited && mField.isFieldValueMasked()) {
+ return true;
+ }
return !isInvalidEmptyValue() && !isInvalidLength() && !isInvalidRegex();
}
@@ -163,6 +167,7 @@ public DefaultKeyListener(View focusView, View clearFocusView) {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
+ isEdited = true;
if (event.getAction() == KeyEvent.ACTION_DOWN) {
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_CENTER:
diff --git a/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/view/widget/ExpireDateUtils.java b/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/view/widget/ExpireDateUtils.java
index d26dbd81b..697c890de 100644
--- a/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/view/widget/ExpireDateUtils.java
+++ b/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/view/widget/ExpireDateUtils.java
@@ -154,8 +154,11 @@ private Calendar getInputDate(@NonNull final String input) throws ParseException
//get month from server month part
private String getMonthFromServer(String[] splitDate) {
- return splitDate.length != 2 ? "" :
- splitDate[1].length() == 1 && Integer.parseInt(splitDate[1]) > 1 ?
- ZERO.concat(splitDate[1]) : splitDate[1];
+ if (splitDate.length >= 2) {
+ return splitDate[1].length() == 1 && Integer.parseInt(splitDate[1]) > 1 ? ZERO.concat(splitDate[1])
+ : splitDate[1];
+ } else {
+ return "";
+ }
}
}
\ No newline at end of file
diff --git a/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/view/widget/NumberWidget.java b/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/view/widget/NumberWidget.java
index 2b1e5a70e..690347109 100644
--- a/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/view/widget/NumberWidget.java
+++ b/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/view/widget/NumberWidget.java
@@ -57,9 +57,9 @@ public View getView(@NonNull final ViewGroup viewGroup) {
editText.setTextColor(viewGroup.getContext().getResources().getColor(R.color.regularColorSecondary));
editText.setEnabled(mField.isEditable());
+ editText.setSelectAllOnFocus(mField.isFieldValueMasked());
setIdFromFieldLabel(mTextInputLayout);
setIdFromFieldName(editText);
-
editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
diff --git a/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/view/widget/SelectionWidget.java b/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/view/widget/SelectionWidget.java
index 2fe33c069..93510d78f 100644
--- a/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/view/widget/SelectionWidget.java
+++ b/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/view/widget/SelectionWidget.java
@@ -144,6 +144,7 @@ public void onWidgetSelectionItemClicked(@NonNull String selectedValue) {
mListener.valueChanged(SelectionWidget.this);
mEditText.setText(getKeyFromValue(selectedValue));
mEditText.requestFocus();
+ isEdited = true;
}
private void hideSoftKey(@NonNull View focusedView) {
diff --git a/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/view/widget/TextWidget.java b/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/view/widget/TextWidget.java
index 4e8994718..7b99fbacb 100644
--- a/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/view/widget/TextWidget.java
+++ b/transfermethodui/src/main/java/com/hyperwallet/android/ui/transfermethod/view/widget/TextWidget.java
@@ -54,7 +54,7 @@ public View getView(@NonNull final ViewGroup viewGroup) {
new ContextThemeWrapper(viewGroup.getContext(), R.style.Widget_Hyperwallet_TextInputEditText));
editText.setTextColor(viewGroup.getContext().getResources().getColor(R.color.regularColorSecondary));
editText.setEnabled(mField.isEditable());
-
+ editText.setSelectAllOnFocus(mField.isFieldValueMasked());
mTextInputLayout.setHint(mField.getLabel());
setIdFromFieldLabel(mTextInputLayout);
setIdFromFieldName(editText);
diff --git a/transfermethodui/src/main/res/layout/activity_update_transfer_method.xml b/transfermethodui/src/main/res/layout/activity_update_transfer_method.xml
new file mode 100644
index 000000000..35a86b7d2
--- /dev/null
+++ b/transfermethodui/src/main/res/layout/activity_update_transfer_method.xml
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/transfermethodui/src/main/res/layout/fragment_update_transfer_method.xml b/transfermethodui/src/main/res/layout/fragment_update_transfer_method.xml
new file mode 100644
index 000000000..47ee191f6
--- /dev/null
+++ b/transfermethodui/src/main/res/layout/fragment_update_transfer_method.xml
@@ -0,0 +1,122 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/transfermethodui/src/main/res/menu/transfer_method_context_menu.xml b/transfermethodui/src/main/res/menu/transfer_method_context_menu.xml
index 93fd95f14..954b1b589 100644
--- a/transfermethodui/src/main/res/menu/transfer_method_context_menu.xml
+++ b/transfermethodui/src/main/res/menu/transfer_method_context_menu.xml
@@ -1,5 +1,9 @@