From b59d74a7a059f73fff7da40db5dbc4da830d3639 Mon Sep 17 00:00:00 2001 From: Viktor Shcherbyna Date: Mon, 10 Jun 2019 18:09:11 +0300 Subject: [PATCH 01/10] HW-52637: PayPal Account second line --- .../CommonTransferMethodIdentification.java | 64 ++++++++++++++++ .../ListTransferMethodFragment.java | 75 ++++++++++++------- ...alAccountTransferMethodIdentification.java | 36 +++++++++ .../TransferMethodIdentificationStrategy.java | 41 ++++++++++ 4 files changed, 190 insertions(+), 26 deletions(-) create mode 100644 ui/src/main/java/com/hyperwallet/android/ui/transfermethod/CommonTransferMethodIdentification.java create mode 100644 ui/src/main/java/com/hyperwallet/android/ui/transfermethod/PayPalAccountTransferMethodIdentification.java create mode 100644 ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodIdentificationStrategy.java diff --git a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/CommonTransferMethodIdentification.java b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/CommonTransferMethodIdentification.java new file mode 100644 index 000000000..e5882b5b5 --- /dev/null +++ b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/CommonTransferMethodIdentification.java @@ -0,0 +1,64 @@ +/* + * The MIT License (MIT) + * Copyright (c) 2018 Hyperwallet Systems Inc. + * + * 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 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; + +import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodFields.BANK_ACCOUNT_ID; +import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodFields.CARD_NUMBER; +import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodFields.TYPE; +import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.BANK_ACCOUNT; +import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.BANK_CARD; +import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.PREPAID_CARD; +import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.WIRE_ACCOUNT; + +import android.content.Context; + +import androidx.annotation.NonNull; + +import com.hyperwallet.android.hyperwallet_ui.R; +import com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod; + + +public class CommonTransferMethodIdentification implements TransferMethodIdentificationStrategy { + private static final int LAST_FOUR_DIGIT = 4; + + @NonNull + @Override + public String getIdentificationText(@NonNull Context context, + @NonNull HyperwalletTransferMethod transferMethod) { + + return context.getString(R.string.transfer_method_list_item_description, + getAccountIdentifier(transferMethod)); + } + + private String getAccountIdentifier(@NonNull final HyperwalletTransferMethod transferMethod) { + String transferIdentification = ""; + switch (transferMethod.getField(TYPE)) { + case BANK_ACCOUNT: + case WIRE_ACCOUNT: + transferIdentification = transferMethod.getField(BANK_ACCOUNT_ID); + break; + case BANK_CARD: + case PREPAID_CARD: + transferIdentification = transferMethod.getField(CARD_NUMBER); + break; + default: // none for paper check + } + return (transferIdentification.length() > LAST_FOUR_DIGIT + ? transferIdentification.substring(transferIdentification.length() - LAST_FOUR_DIGIT) + : transferIdentification); + } +} diff --git a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/ListTransferMethodFragment.java b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/ListTransferMethodFragment.java index 385d827a6..d946c170d 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/ListTransferMethodFragment.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/ListTransferMethodFragment.java @@ -16,12 +16,11 @@ */ package com.hyperwallet.android.ui.transfermethod; -import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodFields.BANK_ACCOUNT_ID; -import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodFields.CARD_NUMBER; import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodFields.TRANSFER_METHOD_COUNTRY; import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodFields.TYPE; import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.BANK_ACCOUNT; import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.BANK_CARD; +import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.PAYPAL_ACCOUNT; import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.PREPAID_CARD; import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.WIRE_ACCOUNT; import static com.hyperwallet.android.ui.transfermethod.TransferMethodUtils.getStringFontIcon; @@ -58,14 +57,16 @@ import com.hyperwallet.android.ui.view.widget.OneClickListener; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Locale; +import java.util.Map; public class ListTransferMethodFragment extends Fragment implements ListTransferMethodContract.View { static final String ARGUMENT_IS_TRANSFER_METHODS_RELOAD_NEEDED = "ARGUMENT_IS_TRANSFER_METHODS_RELOAD_NEEDED"; - private static final int LAST_FOUR_DIGIT = 4; + private static final String ARGUMENT_TRANSFER_METHOD_LIST = "ARGUMENT_TRANSFER_METHOD_LIST"; private View mEmptyListView; @@ -301,6 +302,7 @@ interface OnLoadTransferMethodNetworkErrorCallback { private static class ListTransferMethodAdapter extends RecyclerView.Adapter { private List mTransferMethodList; private OnTransferMethodContextMenuDeletionSelected mOnTransferMethodContextMenuDeletionSelected; + private Map mTMIdentifications = new HashMap<>(2); ListTransferMethodAdapter(final List transferMethodList, final OnTransferMethodContextMenuDeletionSelected onTransferMethodContextMenuSelection) { @@ -310,9 +312,12 @@ private static class ListTransferMethodAdapter extends RecyclerView.Adapter LAST_FOUR_DIGIT - ? transferIdentification.substring(transferIdentification.length() - LAST_FOUR_DIGIT) - : transferIdentification); - } @Override public int getItemCount() { @@ -373,16 +361,19 @@ class ViewHolder extends RecyclerView.ViewHolder { void bind(@NonNull final HyperwalletTransferMethod transferMethod) { + String type = transferMethod.getField(TYPE); + TransferMethodIdentificationStrategy identificationStrategy = getIdentificationStrategy(type); + mTitle.setText( - getStringResourceByName(mTitle.getContext(), transferMethod.getField(TYPE))); + getStringResourceByName(mTitle.getContext(), type)); Locale locale = new Locale.Builder().setRegion( transferMethod.getField(TRANSFER_METHOD_COUNTRY)).build(); - mIcon.setText(getStringFontIcon(mIcon.getContext(), transferMethod.getField(TYPE))); + mIcon.setText(getStringFontIcon(mIcon.getContext(), type)); mTransferMethodCountry.setText(locale.getDisplayName()); - mTransferMethodIdentification.setText(mTransferMethodIdentification - .getContext().getString(R.string.transfer_method_list_item_description, - getAccountIdentifier(transferMethod))); + mTransferMethodIdentification.setText( + identificationStrategy.getIdentificationText(mTransferMethodIdentification + .getContext(), transferMethod)); mImageButton.setOnClickListener(new View.OnClickListener() { @Override @@ -415,5 +406,37 @@ void recycle() { mImageButton.setOnClickListener(null); } } + + @NonNull + private TransferMethodIdentificationStrategy getIdentificationStrategy(String type) { + TransferMethodIdentificationStrategy identificationStrategy; + if (type != null && !mTMIdentifications.containsKey(type)) { + identificationStrategy = getTransferMethodIdentificationStrategy(type); + mTMIdentifications.put(type, identificationStrategy); + } else if (type != null && mTMIdentifications.containsKey(type)) { + identificationStrategy = mTMIdentifications.get(type); + } else { + identificationStrategy = TransferMethodIdentificationStrategy.DEFAULT; + } + + return identificationStrategy; + } + + @NonNull + private TransferMethodIdentificationStrategy getTransferMethodIdentificationStrategy(@NonNull String type) { + + switch (type) { + case BANK_CARD: + case PREPAID_CARD: + case BANK_ACCOUNT: + case WIRE_ACCOUNT: + return new CommonTransferMethodIdentification(); + case PAYPAL_ACCOUNT: + return new PayPalAccountTransferMethodIdentification(); + + default: + return TransferMethodIdentificationStrategy.DEFAULT; + } + } } } diff --git a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/PayPalAccountTransferMethodIdentification.java b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/PayPalAccountTransferMethodIdentification.java new file mode 100644 index 000000000..cd1244411 --- /dev/null +++ b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/PayPalAccountTransferMethodIdentification.java @@ -0,0 +1,36 @@ +/* + * The MIT License (MIT) + * Copyright (c) 2018 Hyperwallet Systems Inc. + * + * 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 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; + +import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodFields.EMAIL; + +import android.content.Context; + +import androidx.annotation.NonNull; + +import com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod; + + +public class PayPalAccountTransferMethodIdentification implements TransferMethodIdentificationStrategy { + @NonNull + @Override + public String getIdentificationText(@NonNull Context context, + @NonNull HyperwalletTransferMethod transferMethod) { + String identificationText = transferMethod.getField(EMAIL); + return identificationText != null ? identificationText : ""; + } +} diff --git a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodIdentificationStrategy.java b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodIdentificationStrategy.java new file mode 100644 index 000000000..14637749c --- /dev/null +++ b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodIdentificationStrategy.java @@ -0,0 +1,41 @@ +/* + * The MIT License (MIT) + * Copyright (c) 2018 Hyperwallet Systems Inc. + * + * 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 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; + +import android.content.Context; + +import androidx.annotation.NonNull; + +import com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod; + +public interface TransferMethodIdentificationStrategy { + + TransferMethodIdentificationStrategy DEFAULT = new TransferMethodIdentificationStrategy() { + + @NonNull + @Override + public String getIdentificationText(@NonNull Context context, + @NonNull HyperwalletTransferMethod transferMethod) { + return ""; + } + }; + + + @NonNull + String getIdentificationText(@NonNull final Context context, + @NonNull final HyperwalletTransferMethod transferMethod); +} From e9658c00e397859bbb93602a79ba9a9f5e7b331d Mon Sep 17 00:00:00 2001 From: Viktor Shcherbyna Date: Mon, 10 Jun 2019 18:27:37 +0300 Subject: [PATCH 02/10] add test case for email --- .../android/transfermethod/ui/ListTransferMethodTest.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/ListTransferMethodTest.java b/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/ListTransferMethodTest.java index 9c7038a6f..bed399977 100644 --- a/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/ListTransferMethodTest.java +++ b/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/ListTransferMethodTest.java @@ -132,6 +132,8 @@ public void testListTransferMethod_userHasMultipleTransferMethods() { onView(withId(R.id.list_transfer_method_item)).check( matches(atPosition(3, hasDescendant(withText(R.string.paper_check))))); onView(withId(R.id.list_transfer_method_item)).check(matches(atPosition(3, hasDescendant(withText("Canada"))))); + onView(withId(R.id.list_transfer_method_item)).check( + matches(atPosition(3, hasDescendant(withText(""))))); onView(withId(R.id.list_transfer_method_item)).check( matches(atPosition(3, hasDescendant(withDrawable(R.drawable.ic_three_dots_16dp))))); @@ -151,6 +153,8 @@ public void testListTransferMethod_userHasMultipleTransferMethods() { matches(atPosition(5, hasDescendant(withText(R.string.paypal_account))))); onView(withId(R.id.list_transfer_method_item)).check( matches(atPosition(5, hasDescendant(withText("United States"))))); + onView(withId(R.id.list_transfer_method_item)).check( + matches(atPosition(5, hasDescendant(withText("honey.thigpen@ukbuilder.com"))))); //TODO: Try to check for non existence of transfer_method_type_description_2 onView(withId(R.id.list_transfer_method_item)).check( matches(atPosition(5, hasDescendant(withDrawable(R.drawable.ic_three_dots_16dp))))); From 671854ac7bb348f3ad5cfd4778ee0f2a753b356e Mon Sep 17 00:00:00 2001 From: Viktor Shcherbyna Date: Mon, 10 Jun 2019 18:09:11 +0300 Subject: [PATCH 03/10] HW-52637: PayPal Account second line --- .../ui/ListTransferMethodTest.java | 1 - .../ListTransferMethodFragment.java | 57 ++------- ...PayPalAccountTransferMethodSecondLine.java | 37 ++++++ .../transfermethod/SecondLinePresenter.java | 6 + .../TransferMethodSecondLine.java | 66 ++++++++++ .../TransferMethodSecondLinePresenter.java | 48 +++++++ .../TransferMethodSecondLineStrategy.java | 44 +++++++ .../TransferMethodRepositoryImplTest.java | 8 +- ...TransferMethodSecondLinePresenterTest.java | 117 ++++++++++++++++++ .../test/resources/paper_check_response.json | 34 +++++ 10 files changed, 366 insertions(+), 52 deletions(-) create mode 100644 ui/src/main/java/com/hyperwallet/android/ui/transfermethod/PayPalAccountTransferMethodSecondLine.java create mode 100644 ui/src/main/java/com/hyperwallet/android/ui/transfermethod/SecondLinePresenter.java create mode 100644 ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSecondLine.java create mode 100644 ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSecondLinePresenter.java create mode 100644 ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSecondLineStrategy.java create mode 100644 ui/src/test/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSecondLinePresenterTest.java create mode 100644 ui/src/test/resources/paper_check_response.json diff --git a/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/ListTransferMethodTest.java b/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/ListTransferMethodTest.java index bed399977..edbaa0ada 100644 --- a/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/ListTransferMethodTest.java +++ b/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/ListTransferMethodTest.java @@ -155,7 +155,6 @@ public void testListTransferMethod_userHasMultipleTransferMethods() { matches(atPosition(5, hasDescendant(withText("United States"))))); onView(withId(R.id.list_transfer_method_item)).check( matches(atPosition(5, hasDescendant(withText("honey.thigpen@ukbuilder.com"))))); - //TODO: Try to check for non existence of transfer_method_type_description_2 onView(withId(R.id.list_transfer_method_item)).check( matches(atPosition(5, hasDescendant(withDrawable(R.drawable.ic_three_dots_16dp))))); diff --git a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/ListTransferMethodFragment.java b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/ListTransferMethodFragment.java index d946c170d..0f413b0ad 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/ListTransferMethodFragment.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/ListTransferMethodFragment.java @@ -18,11 +18,6 @@ import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodFields.TRANSFER_METHOD_COUNTRY; import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodFields.TYPE; -import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.BANK_ACCOUNT; -import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.BANK_CARD; -import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.PAYPAL_ACCOUNT; -import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.PREPAID_CARD; -import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.WIRE_ACCOUNT; import static com.hyperwallet.android.ui.transfermethod.TransferMethodUtils.getStringFontIcon; import static com.hyperwallet.android.ui.transfermethod.TransferMethodUtils.getStringResourceByName; @@ -57,10 +52,8 @@ import com.hyperwallet.android.ui.view.widget.OneClickListener; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Locale; -import java.util.Map; public class ListTransferMethodFragment extends Fragment implements ListTransferMethodContract.View { @@ -80,6 +73,7 @@ public class ListTransferMethodFragment extends Fragment implements ListTransfer private OnLoadTransferMethodNetworkErrorCallback mOnLoadTransferMethodNetworkErrorCallback; private boolean mIsTransferMethodsReloadNeeded; private RecyclerView recyclerView; + private TransferMethodSecondLinePresenter mSecondLinePresenter; /** * Please don't use this constructor this is reserved for Android Core Framework @@ -150,7 +144,7 @@ public void onViewStateRestored(@Nullable Bundle savedInstanceState) { mIsTransferMethodsReloadNeeded = true; } mListTransferMethodAdapter = new ListTransferMethodAdapter(mTransferMethodList, - mOnTransferMethodContextMenuDeletionSelected); + mOnTransferMethodContextMenuDeletionSelected, mSecondLinePresenter); recyclerView.setAdapter(mListTransferMethodAdapter); } @@ -187,6 +181,7 @@ public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); RepositoryFactory factory = RepositoryFactory.getInstance(); mPresenter = new ListTransferMethodPresenter(factory.getTransferMethodRepository(), this); + mSecondLinePresenter = new TransferMethodSecondLinePresenter(); } @@ -300,14 +295,16 @@ interface OnLoadTransferMethodNetworkErrorCallback { } private static class ListTransferMethodAdapter extends RecyclerView.Adapter { + private final TransferMethodSecondLinePresenter mSecondLinePresenter; private List mTransferMethodList; private OnTransferMethodContextMenuDeletionSelected mOnTransferMethodContextMenuDeletionSelected; - private Map mTMIdentifications = new HashMap<>(2); ListTransferMethodAdapter(final List transferMethodList, - final OnTransferMethodContextMenuDeletionSelected onTransferMethodContextMenuSelection) { + final OnTransferMethodContextMenuDeletionSelected onTransferMethodContextMenuSelection, + TransferMethodSecondLinePresenter secondLinePresenter) { mTransferMethodList = transferMethodList; mOnTransferMethodContextMenuDeletionSelected = onTransferMethodContextMenuSelection; + mSecondLinePresenter = secondLinePresenter; } @NonNull @@ -315,9 +312,6 @@ private static class ListTransferMethodAdapter extends RecyclerView.Adapter LAST_FOUR_DIGIT + ? transferIdentification.substring(transferIdentification.length() - LAST_FOUR_DIGIT) + : transferIdentification); + } + + +} diff --git a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSecondLinePresenter.java b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSecondLinePresenter.java new file mode 100644 index 000000000..fe6bff2b5 --- /dev/null +++ b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSecondLinePresenter.java @@ -0,0 +1,48 @@ +package com.hyperwallet.android.ui.transfermethod; + +import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.BANK_ACCOUNT; +import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.BANK_CARD; +import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.PAYPAL_ACCOUNT; +import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.PREPAID_CARD; +import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.WIRE_ACCOUNT; + +import androidx.annotation.NonNull; + +import java.util.HashMap; +import java.util.Map; + +final class TransferMethodSecondLinePresenter implements SecondLinePresenter { + private Map mSecondLineStrategies = new HashMap<>(2); + + @Override + @NonNull + public TransferMethodSecondLineStrategy obtainSecondLineStrategy(String type) { + if (type == null) { + return TransferMethodSecondLineStrategy.DEFAULT; + } + + switch (type) { + case BANK_CARD: + case PREPAID_CARD: + case BANK_ACCOUNT: + case WIRE_ACCOUNT: + if (!mSecondLineStrategies.containsKey(TransferMethodSecondLine.class)) { + mSecondLineStrategies.put(TransferMethodSecondLine.class, new TransferMethodSecondLine()); + } + + //noinspection ConstantConditions + return mSecondLineStrategies.get(TransferMethodSecondLine.class); + case PAYPAL_ACCOUNT: + if (!mSecondLineStrategies.containsKey(PayPalAccountTransferMethodSecondLine.class)) { + mSecondLineStrategies.put(PayPalAccountTransferMethodSecondLine.class, + new PayPalAccountTransferMethodSecondLine()); + } + + //noinspection ConstantConditions + return mSecondLineStrategies.get(PayPalAccountTransferMethodSecondLine.class); + + default: + return TransferMethodSecondLineStrategy.DEFAULT; + } + } +} diff --git a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSecondLineStrategy.java b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSecondLineStrategy.java new file mode 100644 index 000000000..0e7f628d9 --- /dev/null +++ b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSecondLineStrategy.java @@ -0,0 +1,44 @@ +/* + * The MIT License (MIT) + * Copyright (c) 2018 Hyperwallet Systems Inc. + * + * 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 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; + +import android.content.Context; + +import androidx.annotation.NonNull; + +import com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod; + +/** + * Represents abstract strategy for the second line of TransferMethod list item. + */ +public interface TransferMethodSecondLineStrategy { + + TransferMethodSecondLineStrategy DEFAULT = new TransferMethodSecondLineStrategy() { + + @NonNull + @Override + public String getText(@NonNull Context context, + @NonNull HyperwalletTransferMethod transferMethod) { + return ""; + } + }; + + + @NonNull + String getText(@NonNull final Context context, + @NonNull final HyperwalletTransferMethod transferMethod); +} diff --git a/ui/src/test/java/com/hyperwallet/android/ui/repository/TransferMethodRepositoryImplTest.java b/ui/src/test/java/com/hyperwallet/android/ui/repository/TransferMethodRepositoryImplTest.java index 6135c42b2..334ad2044 100644 --- a/ui/src/test/java/com/hyperwallet/android/ui/repository/TransferMethodRepositoryImplTest.java +++ b/ui/src/test/java/com/hyperwallet/android/ui/repository/TransferMethodRepositoryImplTest.java @@ -33,7 +33,7 @@ import com.hyperwallet.android.model.transfermethod.HyperwalletBankAccount; import com.hyperwallet.android.model.transfermethod.HyperwalletBankCard; import com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod; -import com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethodPagination; +import com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethodQueryParam; import com.hyperwallet.android.model.transfermethod.PayPalAccount; import org.junit.Before; @@ -423,7 +423,7 @@ public Object answer(InvocationOnMock invocation) { listener.onSuccess(pageList); return listener; } - }).when(mHyperwallet).listTransferMethods((HyperwalletTransferMethodPagination) any(), + }).when(mHyperwallet).listTransferMethods((HyperwalletTransferMethodQueryParam) any(), ArgumentMatchers.>>any()); // test @@ -448,7 +448,7 @@ public Object answer(InvocationOnMock invocation) { listener.onSuccess(null); return listener; } - }).when(mHyperwallet).listTransferMethods((HyperwalletTransferMethodPagination) any(), + }).when(mHyperwallet).listTransferMethods((HyperwalletTransferMethodQueryParam) any(), ArgumentMatchers.>>any()); // test @@ -475,7 +475,7 @@ public Object answer(InvocationOnMock invocation) { listener.onFailure(new HyperwalletException(errors)); return listener; } - }).when(mHyperwallet).listTransferMethods((HyperwalletTransferMethodPagination) any(), + }).when(mHyperwallet).listTransferMethods((HyperwalletTransferMethodQueryParam) any(), ArgumentMatchers.>>any()); // test diff --git a/ui/src/test/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSecondLinePresenterTest.java b/ui/src/test/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSecondLinePresenterTest.java new file mode 100644 index 000000000..6cdbfa176 --- /dev/null +++ b/ui/src/test/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSecondLinePresenterTest.java @@ -0,0 +1,117 @@ +package com.hyperwallet.android.ui.transfermethod; + +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.not; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; + +import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.BANK_ACCOUNT; +import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.BANK_CARD; +import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.PAPER_CHECK; +import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.PAYPAL_ACCOUNT; + +import android.content.Context; + +import com.hyperwallet.android.hyperwallet_ui.R; +import com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod; +import com.hyperwallet.android.ui.rule.HyperwalletExternalResourceManager; + +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.robolectric.RobolectricTestRunner; + +@RunWith(RobolectricTestRunner.class) +public class TransferMethodSecondLinePresenterTest { + private TransferMethodSecondLinePresenter mPresenter; + + @Rule + public HyperwalletExternalResourceManager mExternalResourceManager = new HyperwalletExternalResourceManager(); + + @Before + public void setUp() { + mPresenter = new TransferMethodSecondLinePresenter(); + } + + @Test + public void testObtainSecondLineStrategy_returnsCachedSecondLineStrategy() { + TransferMethodSecondLineStrategy actualStrategy = mPresenter.obtainSecondLineStrategy(BANK_CARD); + TransferMethodSecondLineStrategy candidateStrategy = mPresenter.obtainSecondLineStrategy(BANK_ACCOUNT); + assertThat(actualStrategy, is(candidateStrategy)); + } + + @Test + public void testObtainSecondLineStrategy_returnsSecondLineStrategy() { + TransferMethodSecondLineStrategy strategy1 = mPresenter.obtainSecondLineStrategy(BANK_CARD); + TransferMethodSecondLineStrategy strategy2 = mPresenter.obtainSecondLineStrategy(PAYPAL_ACCOUNT); + assertThat(strategy1, not(strategy2)); + } + + @Test + public void testObtainSecondLineStrategy_returnsEndingOn() { + TransferMethodSecondLineStrategy strategy = mPresenter.obtainSecondLineStrategy(BANK_CARD); + assertThat(strategy, is(strategy)); + + } + + @Test + public void testObtainSecondLineStrategy_returnsPayPalSecondLine() throws JSONException { + Context context = mock(Context.class); + String json = mExternalResourceManager.getResourceContent("paypal_response.json"); + JSONObject htmJsonObject = new JSONObject(json); + HyperwalletTransferMethod transferMethod = new HyperwalletTransferMethod(htmJsonObject); + + TransferMethodSecondLineStrategy strategy = mPresenter.obtainSecondLineStrategy(PAYPAL_ACCOUNT); + String actual = strategy.getText(context, transferMethod); + assertThat(strategy, instanceOf(PayPalAccountTransferMethodSecondLine.class)); + assertThat(actual, is("sunshine.carreiro@hyperwallet.com")); + } + + @Test + public void testObtainSecondLineStrategy_returnsBankCardSecondLine() throws JSONException { + Context context = mock(Context.class); + String json = mExternalResourceManager.getResourceContent("bank_card_response.json"); + JSONObject htmJsonObject = new JSONObject(json); + HyperwalletTransferMethod transferMethod = new HyperwalletTransferMethod(htmJsonObject); + TransferMethodSecondLineStrategy strategy = mPresenter.obtainSecondLineStrategy(BANK_CARD); + strategy.getText(context, transferMethod); + + assertThat(strategy, instanceOf(TransferMethodSecondLine.class)); + verify(context).getString(eq(R.string.transfer_method_list_item_description), eq("0006")); + } + + @Test + public void testObtainSecondLineStrategy_returnsBankAccountSecondLine() throws JSONException { + Context context = mock(Context.class); + String json = mExternalResourceManager.getResourceContent("bank_account_response.json"); + JSONObject htmJsonObject = new JSONObject(json); + HyperwalletTransferMethod transferMethod = new HyperwalletTransferMethod(htmJsonObject); + TransferMethodSecondLineStrategy strategy = mPresenter.obtainSecondLineStrategy(BANK_ACCOUNT); + strategy.getText(context, transferMethod); + + assertThat(strategy, instanceOf(TransferMethodSecondLine.class)); + verify(context).getString(eq(R.string.transfer_method_list_item_description), eq("0254")); + } + + @Test + public void testObtainSecondLineStrategy_returnsPaperCheckSecondLine() throws JSONException { + Context context = mock(Context.class); + String json = mExternalResourceManager.getResourceContent("paper_check_response.json"); + JSONObject htmJsonObject = new JSONObject(json); + HyperwalletTransferMethod transferMethod = new HyperwalletTransferMethod(htmJsonObject); + TransferMethodSecondLineStrategy strategy = mPresenter.obtainSecondLineStrategy(PAPER_CHECK); + String actual = strategy.getText(context, transferMethod); + + assertThat(strategy, instanceOf(TransferMethodSecondLineStrategy.class)); + assertThat(actual, is("")); + verify(context, never()).getString(eq(R.string.transfer_method_list_item_description), anyString()); + } +} diff --git a/ui/src/test/resources/paper_check_response.json b/ui/src/test/resources/paper_check_response.json new file mode 100644 index 000000000..7cc6d5fd5 --- /dev/null +++ b/ui/src/test/resources/paper_check_response.json @@ -0,0 +1,34 @@ +{ + "token": "trm-316843d4-bfde-4dec-a391-ef926e4affbb", + "type": "PAPER_CHECK", + "status": "ACTIVATED", + "verificationStatus": "NOT_REQUIRED", + "createdOn": "2019-02-26T22:03:53", + "transferMethodCountry": "CA", + "transferMethodCurrency": "USD", + "bankAccountRelationship": "SELF", + "profileType": "INDIVIDUAL", + "firstName": "Gannon", + "lastName": "Evan", + "dateOfBirth": "1980-01-01", + "countryOfBirth": "US", + "countryOfNationality": "CA", + "gender": "MALE", + "phoneNumber": "+1 604 6666666", + "mobileNumber": "604 666 6666", + "governmentId": "987654321", + "addressLine1": "950 Granville Street", + "city": "Vancouver", + "stateProvince": "BC", + "country": "CA", + "postalCode": "V6Z1L2", + "shippingMethod": "EXPEDITED", + "links": [ + { + "params": { + "rel": "self" + }, + "href": "https://localhost:8181/rest/v3/users/usr-a51c7522-ccba-4bcf-a6a7-bc59dae8f9b0/bank-accounts/trm-92320ebd-c569-4b16-8790-6d22b477ac3c" + } + ] +} \ No newline at end of file From 6bb5d125fe57cd2078ea03c786a75914bd0719db Mon Sep 17 00:00:00 2001 From: Viktor Shcherbyna Date: Tue, 11 Jun 2019 11:44:48 +0300 Subject: [PATCH 04/10] add License header --- .../CommonTransferMethodIdentification.java | 64 ------------------- ...alAccountTransferMethodIdentification.java | 36 ----------- .../transfermethod/SecondLinePresenter.java | 17 ++++- .../TransferMethodIdentificationStrategy.java | 41 ------------ .../TransferMethodSecondLinePresenter.java | 16 +++++ 5 files changed, 32 insertions(+), 142 deletions(-) delete mode 100644 ui/src/main/java/com/hyperwallet/android/ui/transfermethod/CommonTransferMethodIdentification.java delete mode 100644 ui/src/main/java/com/hyperwallet/android/ui/transfermethod/PayPalAccountTransferMethodIdentification.java delete mode 100644 ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodIdentificationStrategy.java diff --git a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/CommonTransferMethodIdentification.java b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/CommonTransferMethodIdentification.java deleted file mode 100644 index e5882b5b5..000000000 --- a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/CommonTransferMethodIdentification.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * The MIT License (MIT) - * Copyright (c) 2018 Hyperwallet Systems Inc. - * - * 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 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; - -import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodFields.BANK_ACCOUNT_ID; -import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodFields.CARD_NUMBER; -import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodFields.TYPE; -import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.BANK_ACCOUNT; -import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.BANK_CARD; -import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.PREPAID_CARD; -import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.WIRE_ACCOUNT; - -import android.content.Context; - -import androidx.annotation.NonNull; - -import com.hyperwallet.android.hyperwallet_ui.R; -import com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod; - - -public class CommonTransferMethodIdentification implements TransferMethodIdentificationStrategy { - private static final int LAST_FOUR_DIGIT = 4; - - @NonNull - @Override - public String getIdentificationText(@NonNull Context context, - @NonNull HyperwalletTransferMethod transferMethod) { - - return context.getString(R.string.transfer_method_list_item_description, - getAccountIdentifier(transferMethod)); - } - - private String getAccountIdentifier(@NonNull final HyperwalletTransferMethod transferMethod) { - String transferIdentification = ""; - switch (transferMethod.getField(TYPE)) { - case BANK_ACCOUNT: - case WIRE_ACCOUNT: - transferIdentification = transferMethod.getField(BANK_ACCOUNT_ID); - break; - case BANK_CARD: - case PREPAID_CARD: - transferIdentification = transferMethod.getField(CARD_NUMBER); - break; - default: // none for paper check - } - return (transferIdentification.length() > LAST_FOUR_DIGIT - ? transferIdentification.substring(transferIdentification.length() - LAST_FOUR_DIGIT) - : transferIdentification); - } -} diff --git a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/PayPalAccountTransferMethodIdentification.java b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/PayPalAccountTransferMethodIdentification.java deleted file mode 100644 index cd1244411..000000000 --- a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/PayPalAccountTransferMethodIdentification.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * The MIT License (MIT) - * Copyright (c) 2018 Hyperwallet Systems Inc. - * - * 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 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; - -import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodFields.EMAIL; - -import android.content.Context; - -import androidx.annotation.NonNull; - -import com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod; - - -public class PayPalAccountTransferMethodIdentification implements TransferMethodIdentificationStrategy { - @NonNull - @Override - public String getIdentificationText(@NonNull Context context, - @NonNull HyperwalletTransferMethod transferMethod) { - String identificationText = transferMethod.getField(EMAIL); - return identificationText != null ? identificationText : ""; - } -} diff --git a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/SecondLinePresenter.java b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/SecondLinePresenter.java index 8c7fedfa0..4364be661 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/SecondLinePresenter.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/SecondLinePresenter.java @@ -1,6 +1,21 @@ +/* + * The MIT License (MIT) + * Copyright (c) 2018 Hyperwallet Systems Inc. + * + * 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 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; - interface SecondLinePresenter { TransferMethodSecondLineStrategy obtainSecondLineStrategy(String type); } diff --git a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodIdentificationStrategy.java b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodIdentificationStrategy.java deleted file mode 100644 index 14637749c..000000000 --- a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodIdentificationStrategy.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * The MIT License (MIT) - * Copyright (c) 2018 Hyperwallet Systems Inc. - * - * 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 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; - -import android.content.Context; - -import androidx.annotation.NonNull; - -import com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod; - -public interface TransferMethodIdentificationStrategy { - - TransferMethodIdentificationStrategy DEFAULT = new TransferMethodIdentificationStrategy() { - - @NonNull - @Override - public String getIdentificationText(@NonNull Context context, - @NonNull HyperwalletTransferMethod transferMethod) { - return ""; - } - }; - - - @NonNull - String getIdentificationText(@NonNull final Context context, - @NonNull final HyperwalletTransferMethod transferMethod); -} diff --git a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSecondLinePresenter.java b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSecondLinePresenter.java index fe6bff2b5..4f891549d 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSecondLinePresenter.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSecondLinePresenter.java @@ -1,3 +1,19 @@ +/* + * The MIT License (MIT) + * Copyright (c) 2018 Hyperwallet Systems Inc. + * + * 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 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; import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.BANK_ACCOUNT; From 33cf4ca342d99bcf2cf79cac4cbc6a9e6a244915 Mon Sep 17 00:00:00 2001 From: Peter Joseph Olamit Date: Tue, 11 Jun 2019 14:44:59 -0700 Subject: [PATCH 05/10] HW-52584 receipt list (#31) --- build.gradle | 2 + .../android/common/util/DateUtils.java | 123 ++++++ .../view/HorizontalDividerItemDecorator.java | 8 +- .../android/common/viewmodel/Event.java | 65 +++ common/src/main/res/drawable/circle.xml | 2 +- common/src/main/res/drawable/circle_white.xml | 8 +- common/src/main/res/font/icomoon.ttf | Bin 21940 -> 21992 bytes common/src/main/res/values/colors.xml | 1 + common/src/main/res/values/dimens.xml | 2 + .../android/common/util/DateUtilsTest.java | 63 +++ receipt/build.gradle | 16 + receipt/src/androidTest/AndroidManifest.xml | 9 + ...yperwalletInstrumentedTestApplication.java | 31 ++ .../android/receipt/ListReceiptsTest.java | 265 ++++++++++++ .../HyperwalletExternalResourceManager.java | 73 ++++ .../rule/HyperwalletMockWebServer.java | 115 ++++++ .../android/util/EspressoUtils.java | 187 +++++++++ .../android/util/NestedScrollToAction.java | 41 ++ .../util/RecyclerViewCountAssertion.java | 30 ++ .../util/TestAuthenticationProvider.java | 51 +++ receipt/src/main/AndroidManifest.xml | 15 +- .../receipt/repository/ReceiptDataSource.java | 189 +++++++++ .../repository/ReceiptDataSourceFactory.java | 54 +++ .../receipt/repository/ReceiptRepository.java | 58 +++ .../repository/ReceiptRepositoryFactory.java | 56 +++ .../repository/ReceiptRepositoryImpl.java | 93 +++++ .../receipt/view/ListReceiptActivity.java | 133 ++++++ .../receipt/view/ListReceiptFragment.java | 264 ++++++++++++ .../view/ReceiptItemDividerDecorator.java | 102 +++++ .../viewmodel/ListReceiptViewModel.java | 93 +++++ .../src/main/res/drawable/circle_negative.xml | 9 + .../src/main/res/drawable/circle_positive.xml | 9 + .../main/res/drawable/item_view_border.xml | 20 + .../res/drawable/item_view_border_header.xml | 20 + .../main/res/layout/activity_list_receipt.xml | 41 ++ receipt/src/main/res/layout/item_receipt.xml | 73 ++++ .../res/layout/item_receipt_with_header.xml | 26 ++ .../main/res/layout/list_receipt_fragment.xml | 26 ++ receipt/src/main/res/values/colors.xml | 6 + receipt/src/main/res/values/dimens.xml | 6 + receipt/src/main/res/values/strings.xml | 15 + receipt/src/main/res/values/styles.xml | 19 + .../main/res/xml/network_security_config.xml | 6 + .../ReceiptDataSourceFactoryTest.java | 38 ++ .../repository/ReceiptDataSourceTest.java | 389 ++++++++++++++++++ .../ReceiptRepositoryFactoryTest.java | 39 ++ .../HyperwalletExternalResourceManager.java | 72 ++++ .../authentication_token_response.json | 3 + .../resources/receipt_credit_response.json | 30 ++ .../resources/receipt_debit_response.json | 25 ++ .../receipt_list_date_grouping_response.json | 90 ++++ .../test/resources/receipt_list_response.json | 64 +++ .../receipt_unknown_type_response.json | 30 ++ ui/src/androidTest/AndroidManifest.xml | 2 +- .../hyperwallet/android/ui/HyperwalletUi.java | 8 + .../TransferMethodRepositoryImpl.java | 8 +- .../ListTransferMethodFragment.java | 4 +- .../SelectTransferMethodFragment.java | 4 +- 58 files changed, 3213 insertions(+), 18 deletions(-) create mode 100644 common/src/main/java/com/hyperwallet/android/common/util/DateUtils.java rename {ui/src/main/java/com/hyperwallet/android/ui => common/src/main/java/com/hyperwallet/android/common}/view/HorizontalDividerItemDecorator.java (96%) create mode 100644 common/src/main/java/com/hyperwallet/android/common/viewmodel/Event.java create mode 100644 common/src/test/java/com/hyperwallet/android/common/util/DateUtilsTest.java create mode 100644 receipt/src/androidTest/AndroidManifest.xml create mode 100644 receipt/src/androidTest/java/com/hyperwallet/android/HyperwalletInstrumentedTestApplication.java create mode 100644 receipt/src/androidTest/java/com/hyperwallet/android/receipt/ListReceiptsTest.java create mode 100644 receipt/src/androidTest/java/com/hyperwallet/android/rule/HyperwalletExternalResourceManager.java create mode 100644 receipt/src/androidTest/java/com/hyperwallet/android/rule/HyperwalletMockWebServer.java create mode 100644 receipt/src/androidTest/java/com/hyperwallet/android/util/EspressoUtils.java create mode 100644 receipt/src/androidTest/java/com/hyperwallet/android/util/NestedScrollToAction.java create mode 100644 receipt/src/androidTest/java/com/hyperwallet/android/util/RecyclerViewCountAssertion.java create mode 100644 receipt/src/androidTest/java/com/hyperwallet/android/util/TestAuthenticationProvider.java create mode 100644 receipt/src/main/java/com/hyperwallet/android/receipt/repository/ReceiptDataSource.java create mode 100644 receipt/src/main/java/com/hyperwallet/android/receipt/repository/ReceiptDataSourceFactory.java create mode 100644 receipt/src/main/java/com/hyperwallet/android/receipt/repository/ReceiptRepository.java create mode 100644 receipt/src/main/java/com/hyperwallet/android/receipt/repository/ReceiptRepositoryFactory.java create mode 100644 receipt/src/main/java/com/hyperwallet/android/receipt/repository/ReceiptRepositoryImpl.java create mode 100644 receipt/src/main/java/com/hyperwallet/android/receipt/view/ListReceiptActivity.java create mode 100644 receipt/src/main/java/com/hyperwallet/android/receipt/view/ListReceiptFragment.java create mode 100644 receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptItemDividerDecorator.java create mode 100644 receipt/src/main/java/com/hyperwallet/android/receipt/viewmodel/ListReceiptViewModel.java create mode 100644 receipt/src/main/res/drawable/circle_negative.xml create mode 100644 receipt/src/main/res/drawable/circle_positive.xml create mode 100644 receipt/src/main/res/drawable/item_view_border.xml create mode 100644 receipt/src/main/res/drawable/item_view_border_header.xml create mode 100644 receipt/src/main/res/layout/activity_list_receipt.xml create mode 100644 receipt/src/main/res/layout/item_receipt.xml create mode 100644 receipt/src/main/res/layout/item_receipt_with_header.xml create mode 100644 receipt/src/main/res/layout/list_receipt_fragment.xml create mode 100644 receipt/src/main/res/values/colors.xml create mode 100644 receipt/src/main/res/values/dimens.xml create mode 100644 receipt/src/main/res/values/styles.xml create mode 100644 receipt/src/main/res/xml/network_security_config.xml create mode 100644 receipt/src/test/java/com/hyperwallet/android/receipt/repository/ReceiptDataSourceFactoryTest.java create mode 100644 receipt/src/test/java/com/hyperwallet/android/receipt/repository/ReceiptDataSourceTest.java create mode 100644 receipt/src/test/java/com/hyperwallet/android/receipt/repository/ReceiptRepositoryFactoryTest.java create mode 100644 receipt/src/test/java/com/hyperwallet/android/rule/HyperwalletExternalResourceManager.java create mode 100644 receipt/src/test/resources/authentication_token_response.json create mode 100644 receipt/src/test/resources/receipt_credit_response.json create mode 100644 receipt/src/test/resources/receipt_debit_response.json create mode 100644 receipt/src/test/resources/receipt_list_date_grouping_response.json create mode 100644 receipt/src/test/resources/receipt_list_response.json create mode 100644 receipt/src/test/resources/receipt_unknown_type_response.json diff --git a/build.gradle b/build.gradle index 3df2d26b2..4cfcc4791 100644 --- a/build.gradle +++ b/build.gradle @@ -45,6 +45,8 @@ subprojects { constraintlayoutVersion = '1.1.3' legacySupportV4Version = '1.0.0' recycleViewVersion = '1.0.0' + lifecycleExtensionsVersion = '2.0.0' + pagingRuntimeVersion = '2.1.0' //Testing extJunitVerson = '1.1.1' testRunnerVersion = '1.2.0' diff --git a/common/src/main/java/com/hyperwallet/android/common/util/DateUtils.java b/common/src/main/java/com/hyperwallet/android/common/util/DateUtils.java new file mode 100644 index 000000000..7fd65e5aa --- /dev/null +++ b/common/src/main/java/com/hyperwallet/android/common/util/DateUtils.java @@ -0,0 +1,123 @@ +/* + * The MIT License (MIT) + * Copyright (c) 2019 Hyperwallet Systems Inc. + * + * 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 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.common.util; + +import androidx.annotation.NonNull; +import androidx.annotation.VisibleForTesting; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; + +/** + * Common HW-SDK UI Date Utility class, that will assist on safe presentation of date whatever the mobile device setting + * is set Locale, Timezone and etc... that dictates how that dates are being presented + * + * Moreover all date string to {@link Date} object conversion is automatically converted from + * GMT date string from API to locale Date set by the phone + */ +public final class DateUtils { + + private static final String DATE_FORMAT = "yyyy-MM-dd"; + private static final String DATE_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss"; + private static final String DATE_TIME_FORMAT_MILLISECONDS = "yyyy-MM-dd'T'HH:mm:ss.SSS"; + private static final TimeZone API_TIMEZONE = TimeZone.getTimeZone("GMT"); + + private DateUtils() { + } + + /** + * Creates a string date format: yyyy-MM-dd + * + * @param date Date object + * @return string date in yyyy-MM-dd format + */ + public static String toDateFormat(@NonNull final Date date) { + SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT, Locale.getDefault()); + dateFormat.setTimeZone(TimeZone.getDefault()); + return dateFormat.format(date); + } + + /** + * Creates a string date in specified format + * + * @param date Date object + * @param format specify desired format of date + * @return formatted date string based on format specified + */ + public static String toDateFormat(@NonNull final Date date, @NonNull final String format) { + SimpleDateFormat dateFormat = new SimpleDateFormat(format, Locale.getDefault()); + dateFormat.setTimeZone(TimeZone.getDefault()); + return dateFormat.format(date); + } + + /** + * Creates a string date format + * + * @param date Date object + * @return formatted string in yyyy-MM-dd'T'HH:mm:ss format + */ + public static String toDateTimeFormat(@NonNull final Date date) { + SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_TIME_FORMAT, Locale.getDefault()); + dateFormat.setTimeZone(TimeZone.getDefault()); + return dateFormat.format(date); + } + + /** + * Creates a string date format + * + * @param date Date object + * @return formatted string in yyyy-MM-dd'T'HH:mm:ss.SSS format + */ + public static String toDateTimeMillisFormat(@NonNull final Date date) { + SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_TIME_FORMAT_MILLISECONDS, Locale.getDefault()); + dateFormat.setTimeZone(TimeZone.getDefault()); + return dateFormat.format(date); + } + + /** + * Creates a Date object from string date using API Timezone + * + * @param dateString String date from API with GMT timezone + * @return date Date object converted to local timezone + * @throws IllegalArgumentException when string is un-parsable + */ + public static Date fromDateTimeString(@NonNull final String dateString) { + try { + SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_TIME_FORMAT, Locale.getDefault()); + dateFormat.setTimeZone(API_TIMEZONE); + return dateFormat.parse(dateString); + } catch (ParseException e) { + throw new IllegalArgumentException("An exception occurred when attempting to parse " + + "the date " + dateString, e); + } + } + + @VisibleForTesting + static Date fromDateTimeString(@NonNull final String dateString, @NonNull final String format) { + try { + SimpleDateFormat dateFormat = new SimpleDateFormat(format, Locale.getDefault()); + dateFormat.setTimeZone(API_TIMEZONE); + return dateFormat.parse(dateString); + } catch (ParseException e) { + throw new IllegalArgumentException("An exception occurred when attempting to parse " + + "the date " + dateString, e); + } + } +} diff --git a/ui/src/main/java/com/hyperwallet/android/ui/view/HorizontalDividerItemDecorator.java b/common/src/main/java/com/hyperwallet/android/common/view/HorizontalDividerItemDecorator.java similarity index 96% rename from ui/src/main/java/com/hyperwallet/android/ui/view/HorizontalDividerItemDecorator.java rename to common/src/main/java/com/hyperwallet/android/common/view/HorizontalDividerItemDecorator.java index 22b3b432a..3e9d3777f 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/view/HorizontalDividerItemDecorator.java +++ b/common/src/main/java/com/hyperwallet/android/common/view/HorizontalDividerItemDecorator.java @@ -14,7 +14,7 @@ * 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.view; +package com.hyperwallet.android.common.view; import android.content.Context; import android.graphics.Canvas; @@ -26,12 +26,12 @@ import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; -import com.hyperwallet.android.hyperwallet_ui.R; +import com.hyperwallet.android.common.R; public class HorizontalDividerItemDecorator extends RecyclerView.ItemDecoration { - private final Drawable mHorizontalItemDivider; - private final int mDefaultPadding; + protected final Drawable mHorizontalItemDivider; + protected final int mDefaultPadding; public HorizontalDividerItemDecorator(@NonNull final Context context, final boolean withHeaderDivider) { mHorizontalItemDivider = context.getResources().getDrawable(R.drawable.horizontal_divider, null); diff --git a/common/src/main/java/com/hyperwallet/android/common/viewmodel/Event.java b/common/src/main/java/com/hyperwallet/android/common/viewmodel/Event.java new file mode 100644 index 000000000..a07aab0e1 --- /dev/null +++ b/common/src/main/java/com/hyperwallet/android/common/viewmodel/Event.java @@ -0,0 +1,65 @@ +/* + * The MIT License (MIT) + * Copyright (c) 2019 Hyperwallet Systems Inc. + * + * 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 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.common.viewmodel; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +/** + * Class that represents {@link androidx.lifecycle.LiveData} event with content + */ +public class Event { + + private final T content; + private boolean mIsContentConsumed; + + public Event(@NonNull final T t) { + content = t; + } + + /** + * @return content of this event, will also mark {@link Event#mIsContentConsumed} to true + * that will also mean that {@link Event#getContentIfNotConsumed()} will also return true + */ + @NonNull + public T getContent() { + mIsContentConsumed = true; + return content; + } + + /** + * @return true if content assigned to event is already referenced + * from {@link Event#getContent()}; false otherwise. + */ + public boolean isContentConsumed() { + return mIsContentConsumed; + } + + /** + * Retrieve assigned content based on if and only if content has not been referenced from {@link Event#getContent()} + * + * @return content if content is not yet consumed; otherwise null + */ + @Nullable + public T getContentIfNotConsumed() { + if (!mIsContentConsumed) { + mIsContentConsumed = true; + return content; + } + return null; + } +} diff --git a/common/src/main/res/drawable/circle.xml b/common/src/main/res/drawable/circle.xml index b6e02a0bc..4a83f9077 100644 --- a/common/src/main/res/drawable/circle.xml +++ b/common/src/main/res/drawable/circle.xml @@ -3,7 +3,7 @@ - + diff --git a/common/src/main/res/drawable/circle_white.xml b/common/src/main/res/drawable/circle_white.xml index 237aac74a..def791761 100644 --- a/common/src/main/res/drawable/circle_white.xml +++ b/common/src/main/res/drawable/circle_white.xml @@ -4,11 +4,9 @@ - - - - - + + diff --git a/common/src/main/res/font/icomoon.ttf b/common/src/main/res/font/icomoon.ttf index f216ee945686dacd9a87036c7df1f9b6e34b6fa0..384737f83301b709956e43431d06b3b965b73c2f 100644 GIT binary patch delta 990 zcma)4TWk|Y6rDS>4{!Wf+w1k#d04hLFG6U7qxGtZ6GHQ0ND8s+qz@1(ZlI22r=$sL z)2OXe6!DM{Rk4hUh=c$kAw_Bn;Ugb>1Ox~ng!<8s!WU9$1yNNAsii7Sx4rB1r+*#Y z(abq#=G?n?_Ua-$S%eY+LWq;h5k@+PvmJ5SFSH|b4d>pmiQMGxzg)RX2-G9qm(NX4 z;_5{_hpQuB{OH~8p1pCzM+r%b%T4S*Jt+N&xF3@oo;)yp5DUdI zdgqJf6ws3}40I_CAIf4s2yBJUmhXEbIa3V?daSt@bQXrLc%m1gy3#eP4F%wAU6@8I zvB+mT7xdVI=<(i>T~1#l6&PsG>{_d+J5@SsRiN+#4y&@d+9bEtKU>ulMO(ElEB>vo zKC>!>Tp0E>mePN(u&>w(*+7QKCs&630ADDd1 zrq^R5*kU4%R}&^`7$|8t1Bvq;baN&f{60Q8sFGFeEM)7dV`{=|Cw zba_6zqhq1=*SbTIhtYRpeX(!#FZJ7vGfm$#A8t9+a;f#r)=#T>46cxbj HBNyQx%+A&M delta 928 zcmZ`&OK1~87@o;yXLpk}n`EkL`d@TN(2;#wEcK-Rk`Ty_#7G~bx zzza9<6v7B0JDNrmigu)GW4xPG19JzyeSJge(XStGJwXVU0q!42kBvff0-lD*4h$YS z@Vf5GTfip~>Riq2PxpH+Y@A1^Yd4(7Ge9s8sZW4s0f#a}M>ZzXV72#_v z?_P5i+Xc0)WJhgp`e&=RyTmeMOyHTXFpLSqsB%SQObp56kql#26p~3m6PG$%p{Z8H zQj63i>PBA^BJDwCU82GM>k{TzI3DI4 zw3VWKzDA$V>K8+youN?W7GGJ+Ey#A8Ez#gtl=etO4=^s4<1B-sz#i3*+D@r{Y#2lnF~&+th%Bap_>)&!*?r}st)GgpKh%}f~kZo+2=h%uBH1j{tdXc BxZwZ* diff --git a/common/src/main/res/values/colors.xml b/common/src/main/res/values/colors.xml index 2d8989b26..39fdb8129 100644 --- a/common/src/main/res/values/colors.xml +++ b/common/src/main/res/values/colors.xml @@ -23,5 +23,6 @@ #E5F7FA + #737373 diff --git a/common/src/main/res/values/dimens.xml b/common/src/main/res/values/dimens.xml index 1a3f3fb32..db66a3e95 100644 --- a/common/src/main/res/values/dimens.xml +++ b/common/src/main/res/values/dimens.xml @@ -73,4 +73,6 @@ 4dp 6dp 32dp + 48dp + 3dp diff --git a/common/src/test/java/com/hyperwallet/android/common/util/DateUtilsTest.java b/common/src/test/java/com/hyperwallet/android/common/util/DateUtilsTest.java new file mode 100644 index 000000000..27102325b --- /dev/null +++ b/common/src/test/java/com/hyperwallet/android/common/util/DateUtilsTest.java @@ -0,0 +1,63 @@ +package com.hyperwallet.android.common.util; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.Before; +import org.junit.Test; + +import java.util.Date; +import java.util.TimeZone; + +public class DateUtilsTest { + + @Before + public void setTestLocalTimezone() { + TimeZone.setDefault(TimeZone.getTimeZone("PST")); + } + + @Test + public void testToDateFormat_returnsExpectedStringFormat() { + String dateString = "2019-05-27"; + Date dateTarget = DateUtils.fromDateTimeString("2019-05-27T15:57:49"); + + // test + String targetDate = DateUtils.toDateFormat(dateTarget); + assertThat(targetDate, is(notNullValue())); + assertThat(targetDate, is(dateString)); + } + + @Test + public void testToDateFormat_returnsExpectedStringFormatFromParameter() { + String dateString = "November 2019"; + Date dateTarget = DateUtils.fromDateTimeString("2019-11-27T15:57:49"); + + // test + String targetDate = DateUtils.toDateFormat(dateTarget, "MMMM yyyy"); + assertThat(targetDate, is(notNullValue())); + assertThat(targetDate, is(dateString)); + } + + @Test + public void testToDateTimeFormat_returnsExpectedStringFormat() { + String localTime = "2019-11-27T07:57:00"; + Date dateTarget = DateUtils.fromDateTimeString("2019-11-27T15:57:00"); + + // test + String targetDate = DateUtils.toDateTimeFormat(dateTarget); + assertThat(targetDate, is(notNullValue())); + assertThat(targetDate, is(localTime)); + } + + @Test + public void testToDateTimeMillisFormat_returnsExpectedStringFormat() { + String localTime = "2019-11-27T07:57:00.000"; + Date dateTarget = DateUtils.fromDateTimeString("2019-11-27T15:57:00.000", "yyyy-MM-dd'T'HH:mm:ss.SSS"); + + // test + String targetDate = DateUtils.toDateTimeMillisFormat(dateTarget); + assertThat(targetDate, is(notNullValue())); + assertThat(targetDate, is(localTime)); + } +} diff --git a/receipt/build.gradle b/receipt/build.gradle index 39c963b04..6aa8d9d42 100644 --- a/receipt/build.gradle +++ b/receipt/build.gradle @@ -2,6 +2,22 @@ apply from: "$rootProject.projectDir/android-library.gradle" dependencies { api project(":common") + + implementation "com.google.android.material:material:$androidMaterialVersion" + implementation "androidx.constraintlayout:constraintlayout:$constraintlayoutVersion" + implementation "androidx.legacy:legacy-support-v4:$legacySupportV4Version" + implementation "androidx.recyclerview:recyclerview:$recycleViewVersion" + implementation "androidx.lifecycle:lifecycle-extensions:$lifecycleExtensionsVersion" + implementation "androidx.paging:paging-runtime:$pagingRuntimeVersion" + + testImplementation "org.robolectric:robolectric:$robolectricVersion" + + androidTestImplementation "androidx.test:rules:$testRulesVersion" + androidTestImplementation "androidx.test.espresso:espresso-contrib:$espressoVersion" + androidTestImplementation "androidx.test.espresso:espresso-intents:$espressoVersion" + androidTestImplementation "com.squareup.okhttp3:mockwebserver:$mockServerVersion" + androidTestImplementation "com.squareup.leakcanary:leakcanary-android-instrumentation:$leakcanaryVersion" + androidTestImplementation "com.squareup.leakcanary:leakcanary-support-fragment:$leakcanaryVersion" } def aarFile = file("$buildDir/outputs/aar/receipt-$version" + ".aar") diff --git a/receipt/src/androidTest/AndroidManifest.xml b/receipt/src/androidTest/AndroidManifest.xml new file mode 100644 index 000000000..8495adb45 --- /dev/null +++ b/receipt/src/androidTest/AndroidManifest.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/receipt/src/androidTest/java/com/hyperwallet/android/HyperwalletInstrumentedTestApplication.java b/receipt/src/androidTest/java/com/hyperwallet/android/HyperwalletInstrumentedTestApplication.java new file mode 100644 index 000000000..dfc559d2e --- /dev/null +++ b/receipt/src/androidTest/java/com/hyperwallet/android/HyperwalletInstrumentedTestApplication.java @@ -0,0 +1,31 @@ +package com.hyperwallet.android; + + +import android.app.Application; + +import com.squareup.leakcanary.InstrumentationLeakDetector; +import com.squareup.leakcanary.LeakCanary; + +public class HyperwalletInstrumentedTestApplication extends Application { + + @Override + public void onCreate() { + + super.onCreate(); + if (LeakCanary.isInAnalyzerProcess(this)) { + // This process is dedicated to LeakCanary for heap analysis. + // You should not init your app in this process. + return; + } + installLeakCanary(); + } + + + protected void installLeakCanary() { + + InstrumentationLeakDetector.instrumentationRefWatcher(this) + .buildAndInstall(); + + } + +} \ No newline at end of file diff --git a/receipt/src/androidTest/java/com/hyperwallet/android/receipt/ListReceiptsTest.java b/receipt/src/androidTest/java/com/hyperwallet/android/receipt/ListReceiptsTest.java new file mode 100644 index 000000000..5eb430354 --- /dev/null +++ b/receipt/src/androidTest/java/com/hyperwallet/android/receipt/ListReceiptsTest.java @@ -0,0 +1,265 @@ +package com.hyperwallet.android.receipt; + +import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.assertion.ViewAssertions.matches; +import static androidx.test.espresso.matcher.ViewMatchers.hasDescendant; +import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; +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 org.hamcrest.Matchers.allOf; +import static org.hamcrest.Matchers.instanceOf; + +import static java.net.HttpURLConnection.HTTP_NO_CONTENT; +import static java.net.HttpURLConnection.HTTP_OK; + +import static com.hyperwallet.android.util.EspressoUtils.atPosition; + +import android.content.Context; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.widget.TextView; + +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.rule.ActivityTestRule; + +import com.hyperwallet.android.Hyperwallet; +import com.hyperwallet.android.receipt.repository.ReceiptRepositoryFactory; +import com.hyperwallet.android.receipt.view.ListReceiptActivity; +import com.hyperwallet.android.rule.HyperwalletExternalResourceManager; +import com.hyperwallet.android.rule.HyperwalletMockWebServer; +import com.hyperwallet.android.util.RecyclerViewCountAssertion; +import com.hyperwallet.android.util.TestAuthenticationProvider; + +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.util.Locale; + +@RunWith(AndroidJUnit4.class) +public class ListReceiptsTest { + + @ClassRule + public static HyperwalletExternalResourceManager sResourceManager = new HyperwalletExternalResourceManager(); + @Rule + public HyperwalletMockWebServer mMockWebServer = new HyperwalletMockWebServer(8080); + @Rule + public ActivityTestRule mActivityTestRule = + new ActivityTestRule<>(ListReceiptActivity.class, true, false); + + @Before + public void setup() { + Hyperwallet.getInstance(new TestAuthenticationProvider()); + + mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager + .getResourceContent("authentication_token_response.json")).mock(); + + setLocale(Locale.US); + } + + @After + public void cleanup() { + ReceiptRepositoryFactory.clearInstance(); + } + + @Test + public void testListReceipts_userHasMultipleTransactions() { + mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager + .getResourceContent("receipt_list_response.json")).mock(); + mMockWebServer.mockResponse().withHttpResponseCode(HTTP_NO_CONTENT).withBody("").mock(); + + // run test + mActivityTestRule.launchActivity(null); + + // assert + onView(allOf(instanceOf(TextView.class), withParent(withId(R.id.toolbar)))) + .check(matches(withText(R.string.title_activity_receipt_list))); + onView(withId(R.id.list_receipts)).check(matches(isDisplayed())); + + onView(withId(R.id.list_receipts)) + .check(matches(atPosition(0, hasDescendant(withText("June 2019"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(0, + hasDescendant(withText(com.hyperwallet.android.receipt.R.string.credit))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(0, hasDescendant(withText("Payment"))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(0, hasDescendant(withText("+ 20.00"))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(0, hasDescendant(withText("June 07, 2019"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("USD"))))); + + onView(withId(R.id.list_receipts)).check(matches(atPosition(1, + hasDescendant(withText(com.hyperwallet.android.receipt.R.string.credit))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(1, hasDescendant(withText("Payment"))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(1, hasDescendant(withText("+ 25.00"))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(1, hasDescendant(withText("June 02, 2019"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(1, hasDescendant(withText("CAD"))))); + + onView(withId(R.id.list_receipts)).check(matches(atPosition(2, + hasDescendant(withText(com.hyperwallet.android.receipt.R.string.debit))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(2, hasDescendant(withText("Card Activation Fee"))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(2, hasDescendant(withText("- 1.95"))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(2, hasDescendant(withText("June 01, 2019"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(2, hasDescendant(withText("USD"))))); + + onView(withId(R.id.list_receipts)) + .check(matches(atPosition(3, hasDescendant(withText("December 2018"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(3, + hasDescendant(withText(com.hyperwallet.android.receipt.R.string.debit))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(3, hasDescendant(withText("Card Load"))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(3, hasDescendant(withText("- 18.05"))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(3, hasDescendant(withText("December 01, 2018"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(3, hasDescendant(withText("USD"))))); + + onView(withId(R.id.list_receipts)).check(new RecyclerViewCountAssertion(4)); + } + + @Test + public void testListReceipts_displayCreditTransaction() { + mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager + .getResourceContent("receipt_credit_response.json")).mock(); + mMockWebServer.mockResponse().withHttpResponseCode(HTTP_NO_CONTENT).withBody("").mock(); + + // run test + mActivityTestRule.launchActivity(null); + + // assert + onView(allOf(instanceOf(TextView.class), withParent(withId(R.id.toolbar)))) + .check(matches(withText(R.string.title_activity_receipt_list))); + onView(withId(R.id.list_receipts)).check(matches(isDisplayed())); + + onView(withId(R.id.list_receipts)) + .check(matches(atPosition(0, hasDescendant(withText("June 2019"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(0, + hasDescendant(withText(com.hyperwallet.android.receipt.R.string.credit))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(0, hasDescendant(withText(R.string.payment))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(0, hasDescendant(withText("+ 25.00"))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(0, hasDescendant(withText("June 02, 2019"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("CAD"))))); + + onView(withId(R.id.list_receipts)).check(new RecyclerViewCountAssertion(1)); + } + + @Test + public void testListReceipts_displayDebitTransaction() { + mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager + .getResourceContent("receipt_debit_response.json")).mock(); + mMockWebServer.mockResponse().withHttpResponseCode(HTTP_NO_CONTENT).withBody("").mock(); + + // run test + mActivityTestRule.launchActivity(null); + + // assert + onView(allOf(instanceOf(TextView.class), withParent(withId(R.id.toolbar)))) + .check(matches(withText(R.string.title_activity_receipt_list))); + onView(withId(R.id.list_receipts)).check(matches(isDisplayed())); + + onView(withId(R.id.list_receipts)) + .check(matches(atPosition(0, hasDescendant(withText("May 2019"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(0, + hasDescendant(withText(com.hyperwallet.android.receipt.R.string.debit))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(0, hasDescendant(withText(R.string.transfer_to_prepaid_card))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(0, hasDescendant(withText("- 18.05"))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(0, hasDescendant(withText("May 02, 2019"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("USD"))))); + + onView(withId(R.id.list_receipts)).check(new RecyclerViewCountAssertion(1)); + } + + @Test + public void testListReceipts_displayUnknownTransactionType() { + mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager + .getResourceContent("receipt_unknown_type_response.json")).mock(); + mMockWebServer.mockResponse().withHttpResponseCode(HTTP_NO_CONTENT).withBody("").mock(); + + // run test + mActivityTestRule.launchActivity(null); + + // assert + onView(allOf(instanceOf(TextView.class), withParent(withId(R.id.toolbar)))) + .check(matches(withText(R.string.title_activity_receipt_list))); + onView(withId(R.id.list_receipts)).check(matches(isDisplayed())); + + onView(withId(R.id.list_receipts)) + .check(matches(atPosition(0, hasDescendant(withText("June 2019"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(0, + hasDescendant(withText(com.hyperwallet.android.receipt.R.string.credit))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(0, hasDescendant(withText(R.string.unknown_type))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(0, hasDescendant(withText("+ 25.00"))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(0, hasDescendant(withText("June 02, 2019"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("CAD"))))); + + onView(withId(R.id.list_receipts)).check(new RecyclerViewCountAssertion(1)); + } + + @Test + public void testListReceipt_userHasNoTransactions() { + mMockWebServer.mockResponse().withHttpResponseCode(HTTP_NO_CONTENT).withBody("").mock(); + + // run test + mActivityTestRule.launchActivity(null); + + onView(withId(R.id.toolbar)).check(matches(isDisplayed())); + onView(allOf(instanceOf(TextView.class), withParent(withId(R.id.toolbar)))) + .check(matches(withText(R.string.title_activity_receipt_list))); + //todo: check empty view when it will be ready + } + + @Test + public void testListReceipts_checkDateTextOnLocaleChange() { + mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager + .getResourceContent("receipt_debit_response.json")).mock(); + mMockWebServer.mockResponse().withHttpResponseCode(HTTP_NO_CONTENT).withBody("").mock(); + + setLocale(Locale.ITALY); + // run test + mActivityTestRule.launchActivity(null); + // assert + onView(withId(R.id.list_receipts)) + .check(matches(atPosition(0, hasDescendant(withText("maggio 2019"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("maggio 02, 2019"))))); + mActivityTestRule.finishActivity(); + setLocale(Locale.US); + mActivityTestRule.launchActivity(null); + onView(withId(R.id.list_receipts)) + .check(matches(atPosition(0, hasDescendant(withText("May 2019"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("May 02, 2019"))))); + } + + private void setLocale(Locale locale) { + Context context = ApplicationProvider.getApplicationContext(); + Locale.setDefault(locale); + Resources resources = context.getResources(); + Configuration configuration = resources.getConfiguration(); + if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.JELLY_BEAN) { + configuration.setLocale(locale); + } else { + configuration.locale = locale; + } + resources.updateConfiguration(configuration, resources.getDisplayMetrics()); + } +} diff --git a/receipt/src/androidTest/java/com/hyperwallet/android/rule/HyperwalletExternalResourceManager.java b/receipt/src/androidTest/java/com/hyperwallet/android/rule/HyperwalletExternalResourceManager.java new file mode 100644 index 000000000..e7e546063 --- /dev/null +++ b/receipt/src/androidTest/java/com/hyperwallet/android/rule/HyperwalletExternalResourceManager.java @@ -0,0 +1,73 @@ +package com.hyperwallet.android.rule; + +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.StringWriter; +import java.io.Writer; +import java.net.URL; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class HyperwalletExternalResourceManager extends TestWatcher { + + private static final String EMPTY = ""; + private ClassLoader classLoader; + private Logger logger; + + @Override + protected void starting(Description description) { + super.starting(description); + classLoader = description.getTestClass().getClassLoader(); + logger = Logger.getLogger(description.getTestClass().getName()); + } + + public String getResourceContent(final String resourceName) { + if (resourceName == null) { + throw new IllegalArgumentException("Parameter resourceName cannot be null"); + } + + return getContent(resourceName); + } + + private String getContent(final String resourceName) { + + URL resource = classLoader.getResource(resourceName); + InputStream inputStream = null; + Writer writer = new StringWriter(); + String resourceContent = EMPTY; + if (resource != null) { + try { + inputStream = resource.openStream(); + BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); + String line = reader.readLine(); + while (line != null) { + writer.write(line); + line = reader.readLine(); + } + resourceContent = writer.toString(); + + } catch (Exception e) { + logger.log(Level.WARNING, "There was an error loading an external resource", e); + } finally { + try { + if (inputStream != null) { + inputStream.close(); + } + } catch (Exception e) { + logger.log(Level.SEVERE, "There was an error closing input stream", e); + } + try { + writer.close(); + } catch (IOException e) { + logger.log(Level.SEVERE, "There was an error closing writer", e); + } + } + } + return resourceContent; + } +} diff --git a/receipt/src/androidTest/java/com/hyperwallet/android/rule/HyperwalletMockWebServer.java b/receipt/src/androidTest/java/com/hyperwallet/android/rule/HyperwalletMockWebServer.java new file mode 100644 index 000000000..9f42f6128 --- /dev/null +++ b/receipt/src/androidTest/java/com/hyperwallet/android/rule/HyperwalletMockWebServer.java @@ -0,0 +1,115 @@ +package com.hyperwallet.android.rule; + +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; + +import java.io.IOException; +import java.net.HttpURLConnection; + +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; + +public final class HyperwalletMockWebServer extends TestWatcher { + + private MockWebServer mServer; + private int port; + + public HyperwalletMockWebServer(int port) { + this.port = port; + } + + @Override + protected void starting(Description description) { + super.starting(description); + mServer = new MockWebServer(); + try { + mServer.start(port); + } catch (IOException e) { + throw new IllegalStateException("Unable to start mock server", e); + } + } + + @Override + protected void finished(Description description) { + super.finished(description); + try { + mServer.shutdown(); + mServer.close(); + } catch (IOException e) { + throw new IllegalStateException("Un error occurred when shutting down mock server", e); + } + } + + public HyperwalletMockResponse mockResponse() { + return new Builder(mServer).build(); + } + + public MockWebServer getServer() { + return mServer; + } + + public static class HyperwalletMockResponse { + + private String path; + private String body; + private int httpResponseCode; + private Builder builder; + + HyperwalletMockResponse(Builder builder) { + this.path = builder.path; + this.httpResponseCode = builder.responseCode; + this.body = builder.body; + this.builder = builder; + } + + public HyperwalletMockResponse withHttpResponseCode(final int code) { + builder.responseCode(code); + return builder.build(); + } + + public HyperwalletMockResponse withBody(final String body) { + builder.body(body); + return builder.build(); + } + + public void mock() { + mockRequest(); + } + + private String mockRequest() { + builder.server.enqueue(new MockResponse().setResponseCode(httpResponseCode).setBody(body)); + return builder.server.url(path).toString(); + } + + } + + private static class Builder { + + private String path; + private String body; + private int responseCode; + private MockWebServer server; + + + Builder(final MockWebServer server) { + this.path = ""; + this.responseCode = HttpURLConnection.HTTP_OK; + this.body = ""; + this.server = server; + } + + Builder responseCode(final int code) { + this.responseCode = code; + return this; + } + + Builder body(final String body) { + this.body = body; + return this; + } + + HyperwalletMockResponse build() { + return new HyperwalletMockResponse(this); + } + } +} diff --git a/receipt/src/androidTest/java/com/hyperwallet/android/util/EspressoUtils.java b/receipt/src/androidTest/java/com/hyperwallet/android/util/EspressoUtils.java new file mode 100644 index 000000000..92a711f96 --- /dev/null +++ b/receipt/src/androidTest/java/com/hyperwallet/android/util/EspressoUtils.java @@ -0,0 +1,187 @@ +package com.hyperwallet.android.util; + +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.drawable.Drawable; +import android.view.View; +import android.widget.EditText; +import android.widget.ImageView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; +import androidx.test.espresso.ViewAction; +import androidx.test.espresso.action.ViewActions; +import androidx.test.espresso.matcher.BoundedMatcher; + +import com.google.android.material.textfield.TextInputLayout; + +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeMatcher; + +import java.util.Objects; + +public class EspressoUtils { + + public static Matcher withHint(final String expectedHint) { + return new TypeSafeMatcher() { + + @Override + public boolean matchesSafely(View view) { + if (!(view instanceof TextInputLayout)) { + return false; + } + + String hint = Objects.toString(((TextInputLayout) view).getHint()); + return expectedHint.equals(hint); + } + + @Override + public void describeTo(Description description) { + description.appendText(expectedHint); + } + }; + } + + public static Matcher hasErrorText(final String expectedErrorMessage) { + return new TypeSafeMatcher() { + + @Override + public boolean matchesSafely(View view) { + if (!(view instanceof TextInputLayout)) { + return false; + } + + String errorMessage = Objects.toString(((TextInputLayout) view).getError()); + return expectedErrorMessage.equals(errorMessage); + } + + @Override + public void describeTo(Description description) { + description.appendText(expectedErrorMessage); + } + }; + } + + public static Matcher hasErrorText(final int resourceId) { + return new TypeSafeMatcher() { + + @Override + public boolean matchesSafely(View view) { + if (!(view instanceof TextInputLayout)) { + return false; + } + String expectedErrorMessage = view.getResources().getString(resourceId); + String errorMessage = Objects.toString(((TextInputLayout) view).getError()); + + return expectedErrorMessage.equals(errorMessage); + } + + @Override + public void describeTo(Description description) { + } + }; + } + + public static Matcher withDrawable(final int resourceId) { + return new TypeSafeMatcher() { + + @Override + public boolean matchesSafely(View view) { + if (!(view instanceof ImageView)) { + return false; + } + + Drawable drawable = ((ImageView) view).getDrawable(); + if (drawable == null) { + return false; + } + Drawable expectedDrawable = view.getContext().getResources().getDrawable(resourceId); + + Bitmap bitmap = getBitmap(drawable); + Bitmap expectedBitmap = getBitmap(expectedDrawable); + + return bitmap.sameAs(expectedBitmap); + } + + @Override + public void describeTo(Description description) { + } + }; + } + + public static Matcher atPosition(final int position, @NonNull final Matcher matcher) { + return new BoundedMatcher(RecyclerView.class) { + + @Override + protected boolean matchesSafely(final RecyclerView view) { + RecyclerView.ViewHolder viewHolder = view.findViewHolderForAdapterPosition(position); + + if (viewHolder == null) { + return false; + } + + return matcher.matches(viewHolder.itemView); + } + + @Override + public void describeTo(Description description) { + description.appendText("has item at position " + position + ": "); + matcher.describeTo(description); + } + }; + } + + public static ViewAction nestedScrollTo() { + return ViewActions.actionWithAssertions(new NestedScrollToAction()); + } + + private static Bitmap getBitmap(Drawable drawable) { + Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), + drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); + + Canvas canvas = new Canvas(bitmap); + drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); + drawable.draw(canvas); + + return bitmap; + } + + public static Matcher hasNoErrorText() { + return new TypeSafeMatcher() { + + @Override + public boolean matchesSafely(View view) { + if (!(view instanceof TextInputLayout)) { + return false; + } + return ((TextInputLayout) view).getError() == null; + } + + @Override + public void describeTo(Description description) { + description.appendText("has no error text: "); + } + }; + } + + public static Matcher hasEmptyText() { + return new TypeSafeMatcher() { + + @Override + public boolean matchesSafely(View view) { + if (!(view instanceof EditText)) { + return false; + } + String text = ((EditText) view).getText().toString(); + + return text.isEmpty(); + } + + @Override + public void describeTo(Description description) { + } + }; + } +} + diff --git a/receipt/src/androidTest/java/com/hyperwallet/android/util/NestedScrollToAction.java b/receipt/src/androidTest/java/com/hyperwallet/android/util/NestedScrollToAction.java new file mode 100644 index 000000000..392867387 --- /dev/null +++ b/receipt/src/androidTest/java/com/hyperwallet/android/util/NestedScrollToAction.java @@ -0,0 +1,41 @@ +package com.hyperwallet.android.util; + +import static androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom; +import static androidx.test.espresso.matcher.ViewMatchers.isDescendantOfA; +import static androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility; + +import static org.hamcrest.Matchers.allOf; +import static org.hamcrest.Matchers.anyOf; + +import android.view.View; + +import androidx.core.widget.NestedScrollView; +import androidx.test.espresso.UiController; +import androidx.test.espresso.ViewAction; +import androidx.test.espresso.action.ScrollToAction; +import androidx.test.espresso.matcher.ViewMatchers; + +import org.hamcrest.Matcher; + +public class NestedScrollToAction implements ViewAction { + private static final String TAG = ScrollToAction.class.getSimpleName(); + + @SuppressWarnings("unchecked") + @Override + public Matcher getConstraints() { + return allOf( + withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE), + isDescendantOfA( + anyOf(isAssignableFrom(NestedScrollView.class)))); + } + + @Override + public void perform(UiController uiController, View view) { + new ScrollToAction().perform(uiController, view); + } + + @Override + public String getDescription() { + return "scroll to"; + } +} diff --git a/receipt/src/androidTest/java/com/hyperwallet/android/util/RecyclerViewCountAssertion.java b/receipt/src/androidTest/java/com/hyperwallet/android/util/RecyclerViewCountAssertion.java new file mode 100644 index 000000000..bb3aecaff --- /dev/null +++ b/receipt/src/androidTest/java/com/hyperwallet/android/util/RecyclerViewCountAssertion.java @@ -0,0 +1,30 @@ +package com.hyperwallet.android.util; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; + +import android.view.View; + +import androidx.recyclerview.widget.RecyclerView; +import androidx.test.espresso.NoMatchingViewException; +import androidx.test.espresso.ViewAssertion; + +public class RecyclerViewCountAssertion implements ViewAssertion { + private final int mCount; + + public RecyclerViewCountAssertion(int count) { + this.mCount = count; + } + + @Override + public void check(View view, NoMatchingViewException noViewFoundException) { + if (noViewFoundException != null) { + throw noViewFoundException; + } + + RecyclerView recyclerView = (RecyclerView) view; + RecyclerView.Adapter adapter = recyclerView.getAdapter(); + + assertThat(adapter.getItemCount(), is(mCount)); + } +} diff --git a/receipt/src/androidTest/java/com/hyperwallet/android/util/TestAuthenticationProvider.java b/receipt/src/androidTest/java/com/hyperwallet/android/util/TestAuthenticationProvider.java new file mode 100644 index 000000000..686ccbf30 --- /dev/null +++ b/receipt/src/androidTest/java/com/hyperwallet/android/util/TestAuthenticationProvider.java @@ -0,0 +1,51 @@ +package com.hyperwallet.android.util; + +import com.hyperwallet.android.HyperwalletAuthenticationTokenListener; +import com.hyperwallet.android.HyperwalletAuthenticationTokenProvider; + +import java.io.IOException; +import java.text.MessageFormat; +import java.util.UUID; + +import okhttp3.Call; +import okhttp3.Callback; +import okhttp3.MediaType; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; + +public class TestAuthenticationProvider implements HyperwalletAuthenticationTokenProvider { + + public static final MediaType JSON + = MediaType.get("application/json; charset=utf-8"); + private static final String mBaseUrl = "http://localhost:8080/rest/v3/users/{0}/authentication-token"; + private static final String mUserToken = "user_token"; + + @Override + public void retrieveAuthenticationToken(final HyperwalletAuthenticationTokenListener authenticationTokenListener) { + + OkHttpClient client = new OkHttpClient(); + + String payload = "{}"; + String baseUrl = MessageFormat.format(mBaseUrl, mUserToken); + + RequestBody body = RequestBody.create(JSON, payload); + Request request = new Request.Builder() + .url(baseUrl) + .post(body) + .build(); + + client.newCall(request).enqueue(new Callback() { + @Override + public void onFailure(Call call, IOException e) { + authenticationTokenListener.onFailure(UUID.randomUUID(), e.getMessage()); + } + + @Override + public void onResponse(Call call, Response response) throws IOException { + authenticationTokenListener.onSuccess(response.body().string()); + } + }); + } +} diff --git a/receipt/src/main/AndroidManifest.xml b/receipt/src/main/AndroidManifest.xml index bf6f4ad0c..3039f6d18 100644 --- a/receipt/src/main/AndroidManifest.xml +++ b/receipt/src/main/AndroidManifest.xml @@ -1,2 +1,13 @@ - + + + + + + + + + + \ No newline at end of file diff --git a/receipt/src/main/java/com/hyperwallet/android/receipt/repository/ReceiptDataSource.java b/receipt/src/main/java/com/hyperwallet/android/receipt/repository/ReceiptDataSource.java new file mode 100644 index 000000000..5320214fb --- /dev/null +++ b/receipt/src/main/java/com/hyperwallet/android/receipt/repository/ReceiptDataSource.java @@ -0,0 +1,189 @@ +/* + * The MIT License (MIT) + * Copyright (c) 2019 Hyperwallet Systems Inc. + * + * 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 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.receipt.repository; + +import android.os.Handler; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; +import androidx.paging.PageKeyedDataSource; + +import com.hyperwallet.android.Hyperwallet; +import com.hyperwallet.android.common.viewmodel.Event; +import com.hyperwallet.android.exception.HyperwalletException; +import com.hyperwallet.android.listener.HyperwalletListener; +import com.hyperwallet.android.model.HyperwalletErrors; +import com.hyperwallet.android.model.paging.HyperwalletPageList; +import com.hyperwallet.android.model.receipt.Receipt; +import com.hyperwallet.android.model.receipt.ReceiptQueryParam; + +import java.util.Calendar; + +/** + * ReceiptDataSource mediates communication to HW API Platform particularly on + * Receipts V3 API + */ +public class ReceiptDataSource extends PageKeyedDataSource { + + private static final int YEAR_BEFORE_NOW = -1; + private final Calendar mCalendarYearBeforeNow; + private final MutableLiveData> mErrors = new MutableLiveData<>(); + private final MutableLiveData mIsFetchingData = new MutableLiveData<>(); + private LoadInitialCallback mLoadInitialCallback; + private LoadInitialParams mLoadInitialParams; + private LoadCallback mLoadAfterCallback; + private LoadParams mLoadAfterParams; + + ReceiptDataSource() { + super(); + mCalendarYearBeforeNow = Calendar.getInstance(); + mCalendarYearBeforeNow.add(Calendar.YEAR, YEAR_BEFORE_NOW); + } + + /** + * @see {@link PageKeyedDataSource#loadInitial(LoadInitialParams, LoadInitialCallback)} + */ + @Override + public void loadInitial(@NonNull final LoadInitialParams params, + @NonNull final LoadInitialCallback callback) { + mLoadInitialCallback = callback; + mLoadInitialParams = params; + mIsFetchingData.postValue(Boolean.TRUE); + + ReceiptQueryParam queryParam = new ReceiptQueryParam.Builder() + .createdAfter(mCalendarYearBeforeNow.getTime()) + .limit(params.requestedLoadSize) + .sortByCreatedOnDesc().build(); + + getHyperwallet().listReceipts(queryParam, + new HyperwalletListener>() { + @Override + public void onSuccess(@Nullable HyperwalletPageList result) { + mIsFetchingData.postValue(Boolean.FALSE); + mErrors.postValue(null); + + if (result != null) { + int next = result.getLimit() + result.getOffset(); + int previous = 0; + callback.onResult(result.getDataList(), previous, next); + } + // reset + mLoadInitialCallback = null; + mLoadInitialParams = null; + } + + @Override + public void onFailure(HyperwalletException exception) { + mIsFetchingData.postValue(Boolean.FALSE); + mErrors.postValue(new Event<>(exception.getHyperwalletErrors())); + } + + @Override + public Handler getHandler() { + return null; + } + }); + } + + /** + * Unused in this case + * + * @see {@link PageKeyedDataSource#loadBefore(LoadParams, LoadCallback)} + */ + @Override + public void loadBefore(@NonNull LoadParams params, + @NonNull LoadCallback callback) { + } + + /** + * @see {@link PageKeyedDataSource#loadAfter(LoadParams, LoadCallback)} + * */ + @Override + public void loadAfter(@NonNull LoadParams params, + final @NonNull LoadCallback callback) { + mLoadInitialCallback = null; + mLoadInitialParams = null; + mLoadAfterCallback = callback; + mLoadAfterParams = params; + mIsFetchingData.postValue(Boolean.TRUE); + + ReceiptQueryParam queryParam = new ReceiptQueryParam.Builder() + .createdAfter(mCalendarYearBeforeNow.getTime()) + .limit(params.requestedLoadSize) + .offset(params.key) + .sortByCreatedOnDesc().build(); + + getHyperwallet().listReceipts(queryParam, + new HyperwalletListener>() { + @Override + public void onSuccess(@Nullable HyperwalletPageList result) { + mIsFetchingData.postValue(Boolean.FALSE); + mErrors.postValue(null); + + if (result != null) { + int next = result.getLimit() + result.getOffset(); + callback.onResult(result.getDataList(), next); + } + + // reset + mLoadAfterCallback = null; + mLoadAfterParams = null; + } + + @Override + public void onFailure(HyperwalletException exception) { + mIsFetchingData.postValue(Boolean.FALSE); + mErrors.postValue(new Event<>(exception.getHyperwalletErrors())); + } + + @Override + public Handler getHandler() { + return null; + } + }); + } + + /** + * Facilitates retry when network is down; any error that we can have a retry operation + * */ + void retry() { + if (mLoadInitialCallback != null) { + loadInitial(mLoadInitialParams, mLoadInitialCallback); + } else if (mLoadAfterCallback != null) { + loadAfter(mLoadAfterParams, mLoadAfterCallback); + } + } + + /** + * Retrieve reference of Hyperwallet errors inorder for consumers to observe on data changes + * + * @return Live event data of {@link HyperwalletErrors} + * */ + public LiveData> getErrors() { + return mErrors; + } + + LiveData isFetchingData() { + return mIsFetchingData; + } + + Hyperwallet getHyperwallet() { + return Hyperwallet.getDefault(); + } +} diff --git a/receipt/src/main/java/com/hyperwallet/android/receipt/repository/ReceiptDataSourceFactory.java b/receipt/src/main/java/com/hyperwallet/android/receipt/repository/ReceiptDataSourceFactory.java new file mode 100644 index 000000000..a2b81216b --- /dev/null +++ b/receipt/src/main/java/com/hyperwallet/android/receipt/repository/ReceiptDataSourceFactory.java @@ -0,0 +1,54 @@ +/* + * The MIT License (MIT) + * Copyright (c) 2019 Hyperwallet Systems Inc. + * + * 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 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.receipt.repository; + +import androidx.annotation.NonNull; +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; +import androidx.paging.DataSource; + +/** + * Data source factory that uses {@link DataSource.Factory} facility + */ +public class ReceiptDataSourceFactory extends DataSource.Factory { + + private final MutableLiveData mDataSourceMutableLiveData; + private final ReceiptDataSource mReceiptDataSource; + + ReceiptDataSourceFactory() { + super(); + mReceiptDataSource = new ReceiptDataSource(); + mDataSourceMutableLiveData = new MutableLiveData<>(); + mDataSourceMutableLiveData.setValue(mReceiptDataSource); + } + + /** + * Returns observable members of receipt data source + */ + LiveData getReceiptDataSource() { + return mDataSourceMutableLiveData; + } + + /** + * @see {@link DataSource.Factory#create()} + */ + @NonNull + @Override + public DataSource create() { + return mReceiptDataSource; + } +} diff --git a/receipt/src/main/java/com/hyperwallet/android/receipt/repository/ReceiptRepository.java b/receipt/src/main/java/com/hyperwallet/android/receipt/repository/ReceiptRepository.java new file mode 100644 index 000000000..542d03c89 --- /dev/null +++ b/receipt/src/main/java/com/hyperwallet/android/receipt/repository/ReceiptRepository.java @@ -0,0 +1,58 @@ +/* + * The MIT License (MIT) + * Copyright (c) 2019 Hyperwallet Systems Inc. + * + * 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 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.receipt.repository; + +import androidx.lifecycle.LiveData; +import androidx.paging.PagedList; + +import com.hyperwallet.android.common.viewmodel.Event; +import com.hyperwallet.android.model.HyperwalletErrors; +import com.hyperwallet.android.model.receipt.Receipt; + +/** + * Receipt Repository Contract + */ +public interface ReceiptRepository { + + /** + * Load receipts information, consumer can subscribe to receipts data changes events + * + * @return live data paged receipts + */ + LiveData> loadReceipts(); + + /** + * Loading indicator consumer can subscribe to loading of data events + * + * @return live data true if load receipt is in loading state; false otherwise + */ + LiveData isLoading(); + + /** + * Error information, consumer can subscribe of errors occur during data retrieval + * + * @return live event data list of errors if there's an error + */ + LiveData> getErrors(); + + /** + * Reload receipt information, usually invoked when error is raised after the first load and consumer opts to retry + * the last operation + */ + void retryLoadReceipt(); + +} diff --git a/receipt/src/main/java/com/hyperwallet/android/receipt/repository/ReceiptRepositoryFactory.java b/receipt/src/main/java/com/hyperwallet/android/receipt/repository/ReceiptRepositoryFactory.java new file mode 100644 index 000000000..b096ab7a0 --- /dev/null +++ b/receipt/src/main/java/com/hyperwallet/android/receipt/repository/ReceiptRepositoryFactory.java @@ -0,0 +1,56 @@ +/* + * The MIT License (MIT) + * Copyright (c) 2019 Hyperwallet Systems Inc. + * + * 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 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.receipt.repository; + +/** + * {@link ReceiptRepository} factory + */ +public class ReceiptRepositoryFactory { + + private static ReceiptRepositoryFactory sInstance; + private final ReceiptRepository mReceiptRepository; + + private ReceiptRepositoryFactory() { + mReceiptRepository = new ReceiptRepositoryImpl(); + } + + /** + * Creates context single instance of this Factory + * + * @return receipt repository factory instance + */ + public static synchronized ReceiptRepositoryFactory getInstance() { + if (sInstance == null) { + sInstance = new ReceiptRepositoryFactory(); + } + return sInstance; + } + + /** + * Clears instance of repository factory + */ + public static void clearInstance() { + sInstance = null; + } + + /** + * @return ReceiptRepository instance implementation + * */ + public ReceiptRepository getReceiptRepository() { + return mReceiptRepository; + } +} diff --git a/receipt/src/main/java/com/hyperwallet/android/receipt/repository/ReceiptRepositoryImpl.java b/receipt/src/main/java/com/hyperwallet/android/receipt/repository/ReceiptRepositoryImpl.java new file mode 100644 index 000000000..cde7edd94 --- /dev/null +++ b/receipt/src/main/java/com/hyperwallet/android/receipt/repository/ReceiptRepositoryImpl.java @@ -0,0 +1,93 @@ +/* + * The MIT License (MIT) + * Copyright (c) 2019 Hyperwallet Systems Inc. + * + * 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 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.receipt.repository; + +import androidx.lifecycle.LiveData; +import androidx.paging.LivePagedListBuilder; +import androidx.paging.PagedList; + +import com.hyperwallet.android.common.viewmodel.Event; +import com.hyperwallet.android.model.HyperwalletErrors; +import com.hyperwallet.android.model.receipt.Receipt; + +/** + * {@link ReceiptRepository} implementation + */ +public class ReceiptRepositoryImpl implements ReceiptRepository { + + private static final int PAGE_SIZE = 10; + private static final int INITIAL_LOAD_SIZE = 20; + + private final ReceiptDataSourceFactory mDataSourceFactory; + private final LiveData mReceiptDataSourceLiveData; + private LiveData> mErrorsLiveData; + private LiveData mIsFetchingData; + private LiveData> mReceiptsLiveData; + + ReceiptRepositoryImpl() { + mDataSourceFactory = new ReceiptDataSourceFactory(); + mReceiptDataSourceLiveData = mDataSourceFactory.getReceiptDataSource(); + } + + /** + * @see {@link ReceiptRepository#loadReceipts()} + */ + @Override + public LiveData> loadReceipts() { + if (mReceiptsLiveData == null) { + PagedList.Config config = new PagedList.Config.Builder() + .setPageSize(PAGE_SIZE) + .setEnablePlaceholders(true) + .setInitialLoadSizeHint(INITIAL_LOAD_SIZE) + .build(); + mReceiptsLiveData = new LivePagedListBuilder<>(mDataSourceFactory, config).build(); + } + return mReceiptsLiveData; + } + + /** + * @see {@link ReceiptRepository#isLoading()} + */ + @Override + public LiveData isLoading() { + if (mIsFetchingData == null) { + mIsFetchingData = mReceiptDataSourceLiveData.getValue().isFetchingData(); + } + return mIsFetchingData; + } + + /** + * @see {@link ReceiptRepository#getErrors()} + * */ + @Override + public LiveData> getErrors() { + if (mErrorsLiveData == null) { + mErrorsLiveData = mReceiptDataSourceLiveData.getValue().getErrors(); + } + return mErrorsLiveData; + } + + /** + * @see {@link ReceiptRepository#retryLoadReceipt()} + * */ + @Override + public void retryLoadReceipt() { + if (mReceiptDataSourceLiveData.getValue() != null) { + mReceiptDataSourceLiveData.getValue().retry(); + } + } +} diff --git a/receipt/src/main/java/com/hyperwallet/android/receipt/view/ListReceiptActivity.java b/receipt/src/main/java/com/hyperwallet/android/receipt/view/ListReceiptActivity.java new file mode 100644 index 000000000..e7f57c821 --- /dev/null +++ b/receipt/src/main/java/com/hyperwallet/android/receipt/view/ListReceiptActivity.java @@ -0,0 +1,133 @@ +/* + * The MIT License (MIT) + * Copyright (c) 2019 Hyperwallet Systems Inc. + * + * 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 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.receipt.view; + +import android.content.Intent; +import android.os.Bundle; +import android.view.View; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.Toolbar; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentTransaction; +import androidx.lifecycle.Observer; +import androidx.lifecycle.ViewModelProviders; + +import com.hyperwallet.android.common.view.error.DefaultErrorDialogFragment; +import com.hyperwallet.android.common.view.error.OnNetworkErrorCallback; +import com.hyperwallet.android.common.viewmodel.Event; +import com.hyperwallet.android.model.HyperwalletError; +import com.hyperwallet.android.model.HyperwalletErrors; +import com.hyperwallet.android.receipt.R; +import com.hyperwallet.android.receipt.repository.ReceiptRepositoryFactory; +import com.hyperwallet.android.receipt.viewmodel.ListReceiptViewModel; + +import java.util.List; + +public class ListReceiptActivity extends AppCompatActivity implements OnNetworkErrorCallback { + + private ListReceiptViewModel mListReceiptViewModel; + + @Override + protected void onCreate(final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_list_receipt); + + Toolbar toolbar = findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + getSupportActionBar().setDisplayShowHomeEnabled(true); + getSupportActionBar().setTitle(R.string.title_activity_receipt_list); + toolbar.setNavigationOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + finish(); + } + }); + + ReceiptRepositoryFactory factory = ReceiptRepositoryFactory.getInstance(); + mListReceiptViewModel = ViewModelProviders.of(this, new ListReceiptViewModel + .ListReceiptViewModelFactory(factory.getReceiptRepository())) + .get(ListReceiptViewModel.class); + + mListReceiptViewModel.getReceiptErrors().observe(this, new Observer>() { + @Override + public void onChanged(Event event) { + if (event != null && !event.isContentConsumed()) { + showErrorOnLoadReceipt(event.getContent().getErrors()); + } + } + }); + + if (savedInstanceState == null) { + initFragment(ListReceiptFragment.newInstance()); + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + ReceiptRepositoryFactory.clearInstance(); + } + + @Override + protected void onActivityResult(final int requestCode, final int resultCode, @Nullable final Intent data) { + super.onActivityResult(requestCode, resultCode, data); + } + + @Override + public boolean onSupportNavigateUp() { + onBackPressed(); + return true; + } + + private void initFragment(@NonNull final Fragment fragment) { + FragmentManager fragmentManager = getSupportFragmentManager(); + FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); + fragmentTransaction.add(R.id.list_receipt_fragment, fragment); + fragmentTransaction.commit(); + } + + @Override + public void retry() { + FragmentManager fragmentManager = getSupportFragmentManager(); + ListReceiptFragment fragment = (ListReceiptFragment) + fragmentManager.findFragmentById(R.id.list_receipt_fragment); + + if (fragment == null) { + fragment = ListReceiptFragment.newInstance(); + } + fragment.retry(); + } + + private void showErrorOnLoadReceipt(@NonNull final List errors) { + FragmentManager fragmentManager = getSupportFragmentManager(); + DefaultErrorDialogFragment fragment = (DefaultErrorDialogFragment) + fragmentManager.findFragmentByTag(DefaultErrorDialogFragment.TAG); + + if (fragment == null) { + fragment = DefaultErrorDialogFragment.newInstance(errors); + } + + if (!fragment.isAdded()) { + fragment.show(fragmentManager); + } + } +} diff --git a/receipt/src/main/java/com/hyperwallet/android/receipt/view/ListReceiptFragment.java b/receipt/src/main/java/com/hyperwallet/android/receipt/view/ListReceiptFragment.java new file mode 100644 index 000000000..ce6f9fd4d --- /dev/null +++ b/receipt/src/main/java/com/hyperwallet/android/receipt/view/ListReceiptFragment.java @@ -0,0 +1,264 @@ +/* + * The MIT License (MIT) + * Copyright (c) 2019 Hyperwallet Systems Inc. + * + * 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 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.receipt.view; + +import static com.hyperwallet.android.model.receipt.Receipt.Entries.CREDIT; +import static com.hyperwallet.android.model.receipt.Receipt.Entries.DEBIT; + +import android.content.Context; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.lifecycle.Observer; +import androidx.lifecycle.ViewModelProviders; +import androidx.paging.PagedList; +import androidx.paging.PagedListAdapter; +import androidx.recyclerview.widget.DiffUtil; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.hyperwallet.android.common.util.DateUtils; +import com.hyperwallet.android.model.receipt.Receipt; +import com.hyperwallet.android.receipt.R; +import com.hyperwallet.android.receipt.viewmodel.ListReceiptViewModel; + +import java.util.Calendar; +import java.util.Locale; +import java.util.Objects; + +public class ListReceiptFragment extends Fragment { + + private ListReceiptAdapter mListReceiptAdapter; + private RecyclerView mListReceiptsView; + private ListReceiptViewModel mListReceiptViewModel; + private View mProgressBar; + + /** + * Please don't use this constructor this is reserved for Android Core Framework + * + * @see {@link ListReceiptFragment#newInstance()} instead. + */ + public ListReceiptFragment() { + setRetainInstance(true); + } + + static ListReceiptFragment newInstance() { + ListReceiptFragment fragment = new ListReceiptFragment(); + return fragment; + } + + @Override + public void onCreate(@Nullable final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mListReceiptViewModel = ViewModelProviders.of(requireActivity()).get( + ListReceiptViewModel.class); + } + + @Override + public View onCreateView(@NonNull final LayoutInflater inflater, @Nullable final ViewGroup container, + @Nullable Bundle savedInstanceState) { + return inflater.inflate(R.layout.list_receipt_fragment, container, false); + } + + @Override + public void onViewCreated(@NonNull final View view, @Nullable final Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + mProgressBar = view.findViewById(R.id.list_receipt_progress_bar); + mListReceiptAdapter = new ListReceiptAdapter(new ListReceiptItemDiffCallback()); + mListReceiptsView = view.findViewById(R.id.list_receipts); + mListReceiptsView.setHasFixedSize(true); + mListReceiptsView.setLayoutManager(new LinearLayoutManager(getActivity())); + mListReceiptsView.addItemDecoration(new ReceiptItemDividerDecorator(requireContext(), false)); + mListReceiptsView.setAdapter(mListReceiptAdapter); + registerObservers(); + } + + private void registerObservers() { + mListReceiptViewModel.getReceiptList().observe(getViewLifecycleOwner(), new Observer>() { + @Override + public void onChanged(PagedList transferMethods) { + mListReceiptAdapter.submitList(transferMethods); + } + }); + + mListReceiptViewModel.isLoadingData().observe(getViewLifecycleOwner(), new Observer() { + @Override + public void onChanged(Boolean loading) { + if (loading) { + mProgressBar.setVisibility(View.VISIBLE); + } else { + mProgressBar.setVisibility(View.GONE); + } + } + }); + } + + void retry() { + mListReceiptViewModel.retryLoadReceipts(); + } + + private static class ListReceiptItemDiffCallback extends DiffUtil.ItemCallback { + + @Override + public boolean areItemsTheSame(@NonNull final Receipt oldItem, @NonNull final Receipt newItem) { + return oldItem.hashCode() == newItem.hashCode() + && Objects.equals(oldItem, newItem); + } + + @Override + public boolean areContentsTheSame(@NonNull final Receipt oldItem, @NonNull final Receipt newItem) { + return oldItem.hashCode() == newItem.hashCode() + && Objects.equals(oldItem, newItem); + } + } + + private static class ListReceiptAdapter + extends PagedListAdapter { + + private static final String HEADER_DATE_FORMAT = "MMMM yyyy"; + private static final String CAPTION_DATE_FORMAT = "MMMM dd, yyyy"; + private static final int HEADER_VIEW_TYPE = 1; + private static final int DATA_VIEW_TYPE = 0; + + ListReceiptAdapter(@NonNull final DiffUtil.ItemCallback diffCallback) { + super(diffCallback); + } + + @Override + public int getItemViewType(final int position) { + if (position != 0) { + Receipt previous = getItem(position - 1); + Receipt current = getItem(position); + if (isDataViewType(previous, current)) { + return DATA_VIEW_TYPE; + } + } + return HEADER_VIEW_TYPE; + } + + boolean isDataViewType(@NonNull final Receipt previous, @NonNull final Receipt current) { + Calendar prev = Calendar.getInstance(); + prev.setTime(DateUtils.fromDateTimeString(previous.getCreatedOn())); + Calendar curr = Calendar.getInstance(); + curr.setTime(DateUtils.fromDateTimeString(current.getCreatedOn())); + + return prev.get(Calendar.MONTH) == curr.get(Calendar.MONTH) + && prev.get(Calendar.YEAR) == curr.get(Calendar.YEAR); + } + + @NonNull + @Override + public ReceiptViewHolder onCreateViewHolder(final @NonNull ViewGroup viewGroup, int viewType) { + LayoutInflater layout = LayoutInflater.from(viewGroup.getContext()); + + if (viewType == HEADER_VIEW_TYPE) { + View headerView = layout.inflate(R.layout.item_receipt_with_header, viewGroup, false); + return new ReceiptViewHolderWithHeader(headerView); + } + View dataView = layout.inflate(R.layout.item_receipt, viewGroup, false); + return new ReceiptViewHolder(dataView); + } + + @Override + public void onBindViewHolder(@NonNull final ReceiptViewHolder holder, final int position) { + final Receipt receipt = getItem(position); + if (receipt != null) { + holder.bind(receipt); + } + } + + class ReceiptViewHolder extends RecyclerView.ViewHolder { + private final TextView mTransactionAmount; + private final TextView mTransactionCurrency; + private final TextView mTransactionDate; + private final TextView mTransactionTitle; + private final TextView mTransactionTypeIcon; + + ReceiptViewHolder(@NonNull final View item) { + super(item); + mTransactionAmount = item.findViewById(R.id.transaction_amount); + mTransactionCurrency = item.findViewById(R.id.transaction_currency); + mTransactionDate = item.findViewById(R.id.transaction_date); + mTransactionTitle = item.findViewById(R.id.transaction_title); + mTransactionTypeIcon = item.findViewById(R.id.transaction_type_icon); + } + + void bind(@NonNull final Receipt receipt) { + if (CREDIT.equals(receipt.getEntry())) { + mTransactionAmount.setTextColor(mTransactionAmount.getContext() + .getResources().getColor(R.color.positiveColor)); + mTransactionAmount.setText(mTransactionAmount.getContext() + .getString(R.string.credit_sign, receipt.getAmount())); + mTransactionTypeIcon.setTextColor(mTransactionTypeIcon.getContext() + .getResources().getColor(R.color.positiveColor)); + mTransactionTypeIcon.setBackground(mTransactionTypeIcon.getContext() + .getDrawable(R.drawable.circle_positive)); + mTransactionTypeIcon.setText(mTransactionTypeIcon.getContext().getText(R.string.credit)); + } else if (DEBIT.equals(receipt.getEntry())) { + mTransactionAmount.setTextColor(mTransactionAmount.getContext() + .getResources().getColor(R.color.colorAccent)); + mTransactionAmount.setText(mTransactionAmount.getContext() + .getString(R.string.debit_sign, receipt.getAmount())); + mTransactionTypeIcon.setTextColor(mTransactionTypeIcon.getContext() + .getResources().getColor(R.color.colorAccent)); + mTransactionTypeIcon.setBackground(mTransactionTypeIcon.getContext() + .getDrawable(R.drawable.circle_negative)); + mTransactionTypeIcon.setText(mTransactionTypeIcon.getContext().getText(R.string.debit)); + } + + mTransactionCurrency.setText(receipt.getCurrency()); + mTransactionTitle.setText(getTransactionTitle(receipt.getType(), mTransactionTitle.getContext())); + mTransactionDate.setText(DateUtils.toDateFormat(DateUtils. + fromDateTimeString(receipt.getCreatedOn()), CAPTION_DATE_FORMAT)); + } + + String getTransactionTitle(@NonNull final String receiptType, @NonNull final Context context) { + String showTitle = context.getResources().getString(R.string.unknown_type); + int resourceId = context.getResources().getIdentifier(receiptType.toLowerCase(Locale.ROOT), "string", + context.getPackageName()); + if (resourceId != 0) { + showTitle = context.getResources().getString(resourceId); + } + + return showTitle; + } + } + + class ReceiptViewHolderWithHeader extends ReceiptViewHolder { + + private final TextView mTransactionHeaderText; + + ReceiptViewHolderWithHeader(@NonNull final View item) { + super(item); + mTransactionHeaderText = item.findViewById(R.id.item_date_header_title); + } + + @Override + void bind(@NonNull final Receipt receipt) { + super.bind(receipt); + mTransactionHeaderText.setText(DateUtils.toDateFormat( + DateUtils.fromDateTimeString(receipt.getCreatedOn()), HEADER_DATE_FORMAT)); + } + } + } +} diff --git a/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptItemDividerDecorator.java b/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptItemDividerDecorator.java new file mode 100644 index 000000000..c61b22e5d --- /dev/null +++ b/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptItemDividerDecorator.java @@ -0,0 +1,102 @@ +/* + * The MIT License (MIT) + * Copyright (c) 2019 Hyperwallet Systems Inc. + * + * 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 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.receipt.view; + +import android.content.Context; +import android.graphics.Canvas; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.hyperwallet.android.common.view.HorizontalDividerItemDecorator; + +public class ReceiptItemDividerDecorator extends HorizontalDividerItemDecorator { + + ReceiptItemDividerDecorator(@NonNull final Context context, final boolean withHeaderDivider) { + super(context, withHeaderDivider); + } + + @Override + public void onDrawOver(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { + int right = parent.getWidth() - parent.getPaddingRight(); + + int childCount = parent.getChildCount(); + for (int i = 0; i < childCount; i++) { + int left = 0; + int top; + int bottom; + View child = parent.getChildAt(i); + RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); + + if (i == 0) { // first + // draw top + top = child.getTop() + params.topMargin; + bottom = top + mHorizontalItemDivider.getIntrinsicHeight(); + mHorizontalItemDivider.setBounds(left, top, right, bottom); + mHorizontalItemDivider.draw(c); + + if (childCount > 1) { // draw bottom + if (child instanceof LinearLayout) { // receipt header + // peek if next is a header then draw line from beginning + if (parent.getChildAt(i + 1) != null + && parent.getChildAt(i + 1) instanceof LinearLayout) { + left = 0; + } else { + left = ((ViewGroup) ((ViewGroup) child).getChildAt(1)).getChildAt(1).getLeft(); + } + } else { // receipt item + // peek if next is a header then draw line from beginning + if (parent.getChildAt(i + 1) != null + && parent.getChildAt(i + 1) instanceof LinearLayout) { + left = 0; + } else { + left = ((ViewGroup) child).getChildAt(1).getLeft(); + } + } + } + top = child.getBottom() + params.bottomMargin; + } else if (i == parent.getChildCount() - 1) { // draw bottom + top = child.getBottom() + params.bottomMargin; + } else { //draw middle + if (child instanceof LinearLayout) { // header found + // peek if next is a header then draw line from beginning + if (parent.getChildAt(i + 1) != null + && parent.getChildAt(i + 1) instanceof LinearLayout) { + left = 0; + } else { + left = ((ViewGroup) ((ViewGroup) child).getChildAt(1)).getChildAt(1).getLeft(); + } + } else { // non header + // peek if next is a header then draw line from beginning + if (parent.getChildAt(i + 1) != null + && parent.getChildAt(i + 1) instanceof LinearLayout) { + left = 0; + } else { + left = ((ViewGroup) child).getChildAt(1).getLeft(); + } + } + top = child.getBottom() + params.bottomMargin; + } + bottom = top + mHorizontalItemDivider.getIntrinsicHeight(); + mHorizontalItemDivider.setBounds(left, top, right, bottom); + mHorizontalItemDivider.draw(c); + } + } +} diff --git a/receipt/src/main/java/com/hyperwallet/android/receipt/viewmodel/ListReceiptViewModel.java b/receipt/src/main/java/com/hyperwallet/android/receipt/viewmodel/ListReceiptViewModel.java new file mode 100644 index 000000000..57f41b5c1 --- /dev/null +++ b/receipt/src/main/java/com/hyperwallet/android/receipt/viewmodel/ListReceiptViewModel.java @@ -0,0 +1,93 @@ +/* + * The MIT License (MIT) + * Copyright (c) 2019 Hyperwallet Systems Inc. + * + * 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 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.receipt.viewmodel; + +import androidx.annotation.NonNull; +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; +import androidx.lifecycle.Observer; +import androidx.lifecycle.ViewModel; +import androidx.lifecycle.ViewModelProvider; +import androidx.paging.PagedList; + +import com.hyperwallet.android.common.viewmodel.Event; +import com.hyperwallet.android.model.HyperwalletErrors; +import com.hyperwallet.android.model.receipt.Receipt; +import com.hyperwallet.android.receipt.repository.ReceiptRepository; + +public class ListReceiptViewModel extends ViewModel { + + private MutableLiveData> mErrorEvent = new MutableLiveData<>(); + private Observer> mErrorEventObserver; + private ReceiptRepository mReceiptRepository; + + private ListReceiptViewModel(@NonNull final ReceiptRepository receiptRepository) { + mReceiptRepository = receiptRepository; + // load initial receipts + mReceiptRepository.loadReceipts(); + + // register one time error event observer + mErrorEventObserver = new Observer>() { + @Override + public void onChanged(Event event) { + mErrorEvent.postValue(event); + } + }; + mReceiptRepository.getErrors().observeForever(mErrorEventObserver); + } + + public LiveData isLoadingData() { + return mReceiptRepository.isLoading(); + } + + public LiveData> getReceiptErrors() { + return mErrorEvent; + } + + public LiveData> getReceiptList() { + return mReceiptRepository.loadReceipts(); + } + + public void retryLoadReceipts() { + mReceiptRepository.retryLoadReceipt(); + } + + @Override + protected void onCleared() { + super.onCleared(); + mReceiptRepository.getErrors().removeObserver(mErrorEventObserver); + mReceiptRepository = null; + } + + public static class ListReceiptViewModelFactory implements ViewModelProvider.Factory { + + private final ReceiptRepository mReceiptRepository; + + public ListReceiptViewModelFactory(@NonNull final ReceiptRepository receiptRepository) { + mReceiptRepository = receiptRepository; + } + + @NonNull + @Override + public T create(@NonNull Class modelClass) { + if (modelClass.isAssignableFrom(ListReceiptViewModel.class)) { + return (T) new ListReceiptViewModel(mReceiptRepository); + } + throw new IllegalArgumentException("Expecting ViewModel class: " + ListReceiptViewModel.class.getName()); + } + } +} diff --git a/receipt/src/main/res/drawable/circle_negative.xml b/receipt/src/main/res/drawable/circle_negative.xml new file mode 100644 index 000000000..c7ae00b18 --- /dev/null +++ b/receipt/src/main/res/drawable/circle_negative.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/receipt/src/main/res/drawable/circle_positive.xml b/receipt/src/main/res/drawable/circle_positive.xml new file mode 100644 index 000000000..8b6506627 --- /dev/null +++ b/receipt/src/main/res/drawable/circle_positive.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/receipt/src/main/res/drawable/item_view_border.xml b/receipt/src/main/res/drawable/item_view_border.xml new file mode 100644 index 000000000..1bd67efd9 --- /dev/null +++ b/receipt/src/main/res/drawable/item_view_border.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/receipt/src/main/res/drawable/item_view_border_header.xml b/receipt/src/main/res/drawable/item_view_border_header.xml new file mode 100644 index 000000000..cceee0055 --- /dev/null +++ b/receipt/src/main/res/drawable/item_view_border_header.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/receipt/src/main/res/layout/activity_list_receipt.xml b/receipt/src/main/res/layout/activity_list_receipt.xml new file mode 100644 index 000000000..44beb1444 --- /dev/null +++ b/receipt/src/main/res/layout/activity_list_receipt.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/receipt/src/main/res/layout/item_receipt.xml b/receipt/src/main/res/layout/item_receipt.xml new file mode 100644 index 000000000..4388d4ab7 --- /dev/null +++ b/receipt/src/main/res/layout/item_receipt.xml @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/receipt/src/main/res/layout/item_receipt_with_header.xml b/receipt/src/main/res/layout/item_receipt_with_header.xml new file mode 100644 index 000000000..29f002169 --- /dev/null +++ b/receipt/src/main/res/layout/item_receipt_with_header.xml @@ -0,0 +1,26 @@ + + + + + + + + + + \ No newline at end of file diff --git a/receipt/src/main/res/layout/list_receipt_fragment.xml b/receipt/src/main/res/layout/list_receipt_fragment.xml new file mode 100644 index 000000000..52e9725db --- /dev/null +++ b/receipt/src/main/res/layout/list_receipt_fragment.xml @@ -0,0 +1,26 @@ + + + + + + + + \ No newline at end of file diff --git a/receipt/src/main/res/values/colors.xml b/receipt/src/main/res/values/colors.xml new file mode 100644 index 000000000..89155ac94 --- /dev/null +++ b/receipt/src/main/res/values/colors.xml @@ -0,0 +1,6 @@ + + + #FEF7F7 + #5FBF00 + #F1FAE8 + diff --git a/receipt/src/main/res/values/dimens.xml b/receipt/src/main/res/values/dimens.xml new file mode 100644 index 000000000..999d990b2 --- /dev/null +++ b/receipt/src/main/res/values/dimens.xml @@ -0,0 +1,6 @@ + + 3dp + 10dp + 8dp + 70dp + diff --git a/receipt/src/main/res/values/strings.xml b/receipt/src/main/res/values/strings.xml index c3ca11b97..6c6730a9e 100644 --- a/receipt/src/main/res/values/strings.xml +++ b/receipt/src/main/res/values/strings.xml @@ -1,6 +1,21 @@ receipt + Transactions + Seems like, you don\'t have any Transactions, + yet. + + Transfer Funds + \uE900 + Placeholder + + + \uE900 + \uE902 + - %s + + %s + + Unknown Transaction Type Annual Fee Annual Fee Refund Customer Service Fee diff --git a/receipt/src/main/res/values/styles.xml b/receipt/src/main/res/values/styles.xml new file mode 100644 index 000000000..b27a3a524 --- /dev/null +++ b/receipt/src/main/res/values/styles.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/receipt/src/main/res/xml/network_security_config.xml b/receipt/src/main/res/xml/network_security_config.xml new file mode 100644 index 000000000..5e4ba9c97 --- /dev/null +++ b/receipt/src/main/res/xml/network_security_config.xml @@ -0,0 +1,6 @@ + + + + localhost + + \ No newline at end of file diff --git a/receipt/src/test/java/com/hyperwallet/android/receipt/repository/ReceiptDataSourceFactoryTest.java b/receipt/src/test/java/com/hyperwallet/android/receipt/repository/ReceiptDataSourceFactoryTest.java new file mode 100644 index 000000000..cf5c63114 --- /dev/null +++ b/receipt/src/test/java/com/hyperwallet/android/receipt/repository/ReceiptDataSourceFactoryTest.java @@ -0,0 +1,38 @@ +package com.hyperwallet.android.receipt.repository; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.notNullValue; + +import androidx.lifecycle.LiveData; +import androidx.paging.DataSource; + +import org.hamcrest.CoreMatchers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; + +@RunWith(RobolectricTestRunner.class) +public class ReceiptDataSourceFactoryTest { + + @Test + public void testGetReceiptDataSource_returnsLiveDataReceiptSource() { + // initialize + ReceiptDataSourceFactory dataSourceFactory = new ReceiptDataSourceFactory(); + // test + LiveData liveData = dataSourceFactory.getReceiptDataSource(); + // assert + assertThat(liveData, is(notNullValue())); + } + + @Test + public void testCreate_returnsDataSource() { + // initialize + ReceiptDataSourceFactory dataSourceFactory = new ReceiptDataSourceFactory(); + // test + DataSource dataSource = dataSourceFactory.create(); + // assert + assertThat(dataSource, is(notNullValue())); + assertThat(dataSource, CoreMatchers.instanceOf(ReceiptDataSource.class)); + } +} diff --git a/receipt/src/test/java/com/hyperwallet/android/receipt/repository/ReceiptDataSourceTest.java b/receipt/src/test/java/com/hyperwallet/android/receipt/repository/ReceiptDataSourceTest.java new file mode 100644 index 000000000..d09854710 --- /dev/null +++ b/receipt/src/test/java/com/hyperwallet/android/receipt/repository/ReceiptDataSourceTest.java @@ -0,0 +1,389 @@ +package com.hyperwallet.android.receipt.repository; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.nullValue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import static com.hyperwallet.android.model.receipt.Receipt.Entries.CREDIT; +import static com.hyperwallet.android.model.receipt.Receipt.Entries.DEBIT; +import static com.hyperwallet.android.model.receipt.Receipt.ReceiptTypes.PAYMENT; +import static com.hyperwallet.android.model.receipt.Receipt.ReceiptTypes.TRANSFER_TO_BANK_ACCOUNT; + +import androidx.paging.PageKeyedDataSource; + +import com.hyperwallet.android.Hyperwallet; +import com.hyperwallet.android.exception.HyperwalletException; +import com.hyperwallet.android.listener.HyperwalletListener; +import com.hyperwallet.android.model.HyperwalletError; +import com.hyperwallet.android.model.HyperwalletErrors; +import com.hyperwallet.android.model.paging.HyperwalletPageList; +import com.hyperwallet.android.model.receipt.Receipt; +import com.hyperwallet.android.model.receipt.ReceiptQueryParam; +import com.hyperwallet.android.rule.HyperwalletExternalResourceManager; + +import org.hamcrest.Matchers; +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.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.util.ArrayList; +import java.util.List; + +@RunWith(RobolectricTestRunner.class) +public class ReceiptDataSourceTest { + + @Rule + public MockitoRule mMockito = MockitoJUnit.rule(); + @Rule + public HyperwalletExternalResourceManager mExternalResourceManager = new HyperwalletExternalResourceManager(); + + @Mock + private Hyperwallet mHyperwallet; + @Mock + private PageKeyedDataSource.LoadInitialParams mInitialParams; + @Mock + private PageKeyedDataSource.LoadInitialCallback mInitialCallback; + // can't be mocked due to params.key is of type Integer and autoboxing will not work with null to 0 + private final PageKeyedDataSource.LoadParams mLoadAfterParams = + new PageKeyedDataSource.LoadParams<>(10, 10); + @Mock + private PageKeyedDataSource.LoadCallback mLoadAfterCallback; + + @Captor + private ArgumentCaptor> mListArgumentCaptor; + @Captor + private ArgumentCaptor mPreviousCaptor; + @Captor + private ArgumentCaptor mNextCaptor; + + @Spy + private ReceiptDataSource mReceiptDataSource; + + @Before + public void setUp() { + doReturn(mHyperwallet).when(mReceiptDataSource).getHyperwallet(); + } + + @Test + public void testLoadInitial_returnsReceipts() throws Exception { + String json = mExternalResourceManager.getResourceContent("receipt_list_date_grouping_response.json"); + JSONObject jsonObject = new JSONObject(json); + final HyperwalletPageList response = new HyperwalletPageList<>(jsonObject, Receipt.class); + doAnswer(new Answer() { + @Override + public Object answer(InvocationOnMock invocation) { + HyperwalletListener listener = (HyperwalletListener) invocation.getArguments()[1]; + listener.onSuccess(response); + return listener; + } + }).when(mHyperwallet).listReceipts(any(ReceiptQueryParam.class), + ArgumentMatchers.>>any()); + + // test + mReceiptDataSource.loadInitial(mInitialParams, mInitialCallback); + + verify(mHyperwallet).listReceipts(any(ReceiptQueryParam.class), + ArgumentMatchers.>>any()); + verify(mInitialCallback).onResult(mListArgumentCaptor.capture(), mPreviousCaptor.capture(), + mNextCaptor.capture()); + + assertThat(mPreviousCaptor.getValue(), is(0)); + assertThat(mNextCaptor.getValue(), is(10)); + + // assert receipts information + List receipts = mListArgumentCaptor.getValue(); + assertThat(receipts, Matchers.hasSize(5)); + assertThat(receipts.get(0).getJournalId(), is("51660665")); + assertThat(receipts.get(0).getType(), is(PAYMENT)); + assertThat(receipts.get(0).getEntry(), is(CREDIT)); + assertThat(receipts.get(0).getSourceToken(), is("act-b1f6dc28-e534-45f4-a661-3523f051f77a")); + assertThat(receipts.get(0).getDestinationToken(), is("usr-b4e8ec34-52d8-4a81-9566-bdde1bd745b6")); + assertThat(receipts.get(0).getAmount(), is("5000.00")); + assertThat(receipts.get(0).getFee(), is("0.00")); + assertThat(receipts.get(0).getCurrency(), is("USD")); + assertThat(receipts.get(0).getDetails(), is(notNullValue())); + assertThat(receipts.get(0).getDetails().getPayeeName(), is("Kevin Puckett")); + assertThat(receipts.get(0).getDetails().getClientPaymentId(), is("trans-0001")); + assertThat(receipts.get(1).getJournalId(), is("51660666")); + assertThat(receipts.get(1).getType(), is(TRANSFER_TO_BANK_ACCOUNT)); + assertThat(receipts.get(1).getEntry(), is(DEBIT)); + assertThat(receipts.get(1).getSourceToken(), is("usr-b4e8ec34-52d8-4a81-9566-bdde1bd745b6")); + assertThat(receipts.get(1).getDestinationToken(), is("trm-0a2ac589-2cae-4ed3-9b0b-658246a34687")); + assertThat(receipts.get(1).getAmount(), is("10.25")); + assertThat(receipts.get(1).getFee(), is("0.25")); + assertThat(receipts.get(1).getCurrency(), is("USD")); + assertThat(receipts.get(1).getDetails(), is(notNullValue())); + assertThat(receipts.get(1).getDetails().getPayeeName(), is("Kevin Puckett")); + assertThat(receipts.get(1).getDetails().getBankAccountId(), is("patzachery.mcclary@example.com")); + + assertThat(mReceiptDataSource.getErrors().getValue(), is(nullValue())); + assertThat(mReceiptDataSource.isFetchingData().getValue(), is(false)); + } + + @Test + public void testLoadInitial_returnNoReceipt() { + doAnswer(new Answer() { + @Override + public Object answer(InvocationOnMock invocation) { + HyperwalletListener listener = (HyperwalletListener) invocation.getArguments()[1]; + listener.onSuccess(null); + return listener; + } + }).when(mHyperwallet).listReceipts(any(ReceiptQueryParam.class), + ArgumentMatchers.>>any()); + + // test + mReceiptDataSource.loadInitial(mInitialParams, mInitialCallback); + + verify(mHyperwallet).listReceipts(any(ReceiptQueryParam.class), + ArgumentMatchers.>>any()); + verify(mInitialCallback, never()).onResult(ArgumentMatchers.anyList(), anyInt(), anyInt()); + + assertThat(mReceiptDataSource.getErrors().getValue(), is(nullValue())); + assertThat(mReceiptDataSource.isFetchingData().getValue(), is(false)); + } + + @Test + public void testLoadInitial_withError() { + final HyperwalletError error = new HyperwalletError("test message", "TEST_CODE"); + List errorList = new ArrayList<>(); + errorList.add(error); + final HyperwalletErrors errors = new HyperwalletErrors(errorList); + + doAnswer(new Answer() { + @Override + public Object answer(InvocationOnMock invocation) { + HyperwalletListener listener = (HyperwalletListener) invocation.getArguments()[1]; + listener.onFailure(new HyperwalletException(errors)); + return listener; + } + }).when(mHyperwallet).listReceipts(any(ReceiptQueryParam.class), + ArgumentMatchers.>>any()); + + // test + mReceiptDataSource.loadInitial(mInitialParams, mInitialCallback); + + verify(mHyperwallet).listReceipts(any(ReceiptQueryParam.class), + ArgumentMatchers.>>any()); + verify(mInitialCallback, never()).onResult(ArgumentMatchers.anyList(), anyInt(), anyInt()); + + assertThat(mReceiptDataSource.getErrors().getValue(), is(notNullValue())); + assertThat(mReceiptDataSource.getErrors().getValue().getContent().getErrors(), + Matchers.hasSize(1)); + assertThat(mReceiptDataSource.getErrors().getValue().getContent().getErrors().get(0).getCode(), + is("TEST_CODE")); + assertThat(mReceiptDataSource.getErrors().getValue().getContent().getErrors().get(0).getMessage(), + is("test message")); + assertThat(mReceiptDataSource.isFetchingData().getValue(), is(false)); + } + + @Test + public void testRetry_loadInitial() { + final HyperwalletError error = new HyperwalletError("test message", "TEST_CODE"); + List errorList = new ArrayList<>(); + errorList.add(error); + final HyperwalletErrors errors = new HyperwalletErrors(errorList); + + doAnswer(new Answer() { + @Override + public Object answer(InvocationOnMock invocation) { + HyperwalletListener listener = (HyperwalletListener) invocation.getArguments()[1]; + listener.onFailure(new HyperwalletException(errors)); + return listener; + } + }).when(mHyperwallet).listReceipts(any(ReceiptQueryParam.class), + ArgumentMatchers.>>any()); + + // test + mReceiptDataSource.loadInitial(mInitialParams, mInitialCallback); + + verify(mHyperwallet).listReceipts(any(ReceiptQueryParam.class), + ArgumentMatchers.>>any()); + verify(mInitialCallback, never()).onResult(ArgumentMatchers.anyList(), anyInt(), anyInt()); + + // error occurred, this will save params and callback + assertThat(mReceiptDataSource.getErrors().getValue(), is(notNullValue())); + + // test retry, saved params and callback will be used and no null pointer exception is thrown + mReceiptDataSource.retry(); + + // verify calls + verify(mReceiptDataSource, times(2)).loadInitial( + ArgumentMatchers.>any(), + ArgumentMatchers.>any()); + verify(mReceiptDataSource, never()).loadAfter( + ArgumentMatchers.>any(), + ArgumentMatchers.>any()); + } + + @Test + public void testLoadAfter_returnsReceipts() throws Exception { + String json = mExternalResourceManager.getResourceContent("receipt_list_date_grouping_response.json"); + JSONObject jsonObject = new JSONObject(json); + final HyperwalletPageList response = new HyperwalletPageList<>(jsonObject, Receipt.class); + doAnswer(new Answer() { + @Override + public Object answer(InvocationOnMock invocation) { + HyperwalletListener listener = (HyperwalletListener) invocation.getArguments()[1]; + listener.onSuccess(response); + return listener; + } + }).when(mHyperwallet).listReceipts(any(ReceiptQueryParam.class), + ArgumentMatchers.>>any()); + + // test + mReceiptDataSource.loadAfter(mLoadAfterParams, mLoadAfterCallback); + + verify(mHyperwallet).listReceipts(any(ReceiptQueryParam.class), + ArgumentMatchers.>>any()); + verify(mLoadAfterCallback).onResult(mListArgumentCaptor.capture(), mNextCaptor.capture()); + + assertThat(mNextCaptor.getValue(), is(10)); + + // assert receipts information + List receipts = mListArgumentCaptor.getValue(); + assertThat(receipts, Matchers.hasSize(5)); + assertThat(receipts.get(3).getJournalId(), is("51660675")); + assertThat(receipts.get(3).getType(), is(PAYMENT)); + assertThat(receipts.get(3).getEntry(), is(CREDIT)); + assertThat(receipts.get(3).getSourceToken(), is("act-b1f6dc28-e534-45f4-a661-3523f051f77a")); + assertThat(receipts.get(3).getDestinationToken(), is("usr-b4e8ec34-52d8-4a81-9566-bdde1bd745b6")); + assertThat(receipts.get(3).getAmount(), is("13.00")); + assertThat(receipts.get(3).getFee(), is("0.00")); + assertThat(receipts.get(3).getCurrency(), is("USD")); + assertThat(receipts.get(3).getDetails(), is(notNullValue())); + assertThat(receipts.get(3).getDetails().getPayeeName(), is("Kevin Puckett")); + assertThat(receipts.get(3).getDetails().getClientPaymentId(), is("CSietnRJQQ0bscYkOoPJxNiTDiVALhjQ")); + assertThat(receipts.get(4).getJournalId(), is("51660676")); + assertThat(receipts.get(4).getType(), is(PAYMENT)); + assertThat(receipts.get(4).getEntry(), is(CREDIT)); + assertThat(receipts.get(4).getSourceToken(), is("act-b1f6dc28-e534-45f4-a661-3523f051f77a")); + assertThat(receipts.get(4).getDestinationToken(), is("usr-b4e8ec34-52d8-4a81-9566-bdde1bd745b6")); + assertThat(receipts.get(4).getAmount(), is("14.00")); + assertThat(receipts.get(4).getFee(), is("0.00")); + assertThat(receipts.get(4).getCurrency(), is("USD")); + assertThat(receipts.get(4).getDetails(), is(notNullValue())); + assertThat(receipts.get(4).getDetails().getPayeeName(), is("Kevin Puckett")); + assertThat(receipts.get(4).getDetails().getClientPaymentId(), is("wUOdfLlJONacbdHlAHOAXQT7uwX7LTPy")); + + assertThat(mReceiptDataSource.getErrors().getValue(), is(nullValue())); + assertThat(mReceiptDataSource.isFetchingData().getValue(), is(false)); + } + + @Test + public void testLoadAfter_returnNoReceipt() { + doAnswer(new Answer() { + @Override + public Object answer(InvocationOnMock invocation) { + HyperwalletListener listener = (HyperwalletListener) invocation.getArguments()[1]; + listener.onSuccess(null); + return listener; + } + }).when(mHyperwallet).listReceipts(any(ReceiptQueryParam.class), + ArgumentMatchers.>>any()); + + // test + mReceiptDataSource.loadAfter(mLoadAfterParams, mLoadAfterCallback); + + verify(mHyperwallet).listReceipts(any(ReceiptQueryParam.class), + ArgumentMatchers.>>any()); + verify(mLoadAfterCallback, never()).onResult(ArgumentMatchers.>any(), anyInt()); + + assertThat(mReceiptDataSource.getErrors().getValue(), is(nullValue())); + assertThat(mReceiptDataSource.isFetchingData().getValue(), is(false)); + } + + @Test + public void testLoadAfter_withError() { + final HyperwalletError error = new HyperwalletError("test message load after", "LOAD_AFTER_CODE"); + List errorList = new ArrayList<>(); + errorList.add(error); + final HyperwalletErrors errors = new HyperwalletErrors(errorList); + + doAnswer(new Answer() { + @Override + public Object answer(InvocationOnMock invocation) { + HyperwalletListener listener = (HyperwalletListener) invocation.getArguments()[1]; + listener.onFailure(new HyperwalletException(errors)); + return listener; + } + }).when(mHyperwallet).listReceipts(any(ReceiptQueryParam.class), + ArgumentMatchers.>>any()); + + // test + mReceiptDataSource.loadAfter(mLoadAfterParams, mLoadAfterCallback); + + verify(mHyperwallet).listReceipts(any(ReceiptQueryParam.class), + ArgumentMatchers.>>any()); + verify(mLoadAfterCallback, never()).onResult(ArgumentMatchers.anyList(), anyInt()); + + // error occurred, this will save params and callback + assertThat(mReceiptDataSource.getErrors().getValue(), is(notNullValue())); + assertThat(mReceiptDataSource.getErrors().getValue().getContent().getErrors(), + Matchers.hasSize(1)); + assertThat(mReceiptDataSource.getErrors().getValue().getContent().getErrors().get(0).getCode(), + is("LOAD_AFTER_CODE")); + assertThat(mReceiptDataSource.getErrors().getValue().getContent().getErrors().get(0).getMessage(), + is("test message load after")); + assertThat(mReceiptDataSource.isFetchingData().getValue(), is(false)); + } + + @Test + public void testRetry_loadAfter() { + final HyperwalletError error = new HyperwalletError("test message", "TEST_CODE"); + List errorList = new ArrayList<>(); + errorList.add(error); + final HyperwalletErrors errors = new HyperwalletErrors(errorList); + + doAnswer(new Answer() { + @Override + public Object answer(InvocationOnMock invocation) { + HyperwalletListener listener = (HyperwalletListener) invocation.getArguments()[1]; + listener.onFailure(new HyperwalletException(errors)); + return listener; + } + }).when(mHyperwallet).listReceipts(any(ReceiptQueryParam.class), + ArgumentMatchers.>>any()); + + // test + mReceiptDataSource.loadAfter(mLoadAfterParams, mLoadAfterCallback); + + verify(mHyperwallet).listReceipts(any(ReceiptQueryParam.class), + ArgumentMatchers.>>any()); + verify(mLoadAfterCallback, never()).onResult(ArgumentMatchers.anyList(), anyInt()); + + // error occurred, this will save params and callback + assertThat(mReceiptDataSource.getErrors().getValue(), is(notNullValue())); + + // test retry, saved params and callback will be used and no null pointer exception is thrown + mReceiptDataSource.retry(); + + // verify calls + verify(mReceiptDataSource, times(2)).loadAfter( + ArgumentMatchers.>any(), + ArgumentMatchers.>any()); + verify(mReceiptDataSource, never()).loadInitial( + ArgumentMatchers.>any(), + ArgumentMatchers.>any()); + } +} diff --git a/receipt/src/test/java/com/hyperwallet/android/receipt/repository/ReceiptRepositoryFactoryTest.java b/receipt/src/test/java/com/hyperwallet/android/receipt/repository/ReceiptRepositoryFactoryTest.java new file mode 100644 index 000000000..3326f2916 --- /dev/null +++ b/receipt/src/test/java/com/hyperwallet/android/receipt/repository/ReceiptRepositoryFactoryTest.java @@ -0,0 +1,39 @@ +package com.hyperwallet.android.receipt.repository; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.not; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.notNullValue; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; + +@RunWith(RobolectricTestRunner.class) +public class ReceiptRepositoryFactoryTest { + + @Test + public void testGetInstance_verifyRepositoriesInitialized() { + // test + ReceiptRepositoryFactory factory = ReceiptRepositoryFactory.getInstance(); + assertThat(factory, is(notNullValue())); + assertThat(factory.getReceiptRepository(), is(notNullValue())); + + ReceiptRepositoryFactory factory2 = ReceiptRepositoryFactory.getInstance(); + assertThat(factory, is(factory2)); + assertThat(factory.getReceiptRepository(), is(factory2.getReceiptRepository())); + } + + @Test + public void testClearInstance_verifyRepositoriesCleared() { + ReceiptRepositoryFactory factory = ReceiptRepositoryFactory.getInstance(); + assertThat(factory, is(notNullValue())); + assertThat(factory.getReceiptRepository(), is(notNullValue())); + + // test clear + ReceiptRepositoryFactory.clearInstance(); + ReceiptRepositoryFactory factory2 = ReceiptRepositoryFactory.getInstance(); + assertThat(factory, is(not(factory2))); + assertThat(factory.getReceiptRepository(), is(not(factory2.getReceiptRepository()))); + } +} diff --git a/receipt/src/test/java/com/hyperwallet/android/rule/HyperwalletExternalResourceManager.java b/receipt/src/test/java/com/hyperwallet/android/rule/HyperwalletExternalResourceManager.java new file mode 100644 index 000000000..9061af9b8 --- /dev/null +++ b/receipt/src/test/java/com/hyperwallet/android/rule/HyperwalletExternalResourceManager.java @@ -0,0 +1,72 @@ +package com.hyperwallet.android.rule; + +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.StringWriter; +import java.io.Writer; +import java.net.URL; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class HyperwalletExternalResourceManager extends TestWatcher { + + private static final String EMPTY = ""; + private ClassLoader classLoader; + private Logger logger; + + @Override + protected void starting(Description description) { + super.starting(description); + classLoader = description.getTestClass().getClassLoader(); + logger = Logger.getLogger(description.getTestClass().getName()); + } + + public String getResourceContent(final String resourceName) { + if (resourceName == null) { + throw new IllegalArgumentException("Parameter resourceName cannot be null"); + } + + return getContent(resourceName); + } + + private String getContent(final String resourceName) { + URL resource = classLoader.getResource(resourceName); + InputStream inputStream = null; + Writer writer = new StringWriter(); + String resourceContent = EMPTY; + if (resource != null) { + try { + inputStream = resource.openStream(); + BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); + String line = reader.readLine(); + while (line != null) { + writer.write(line); + line = reader.readLine(); + } + resourceContent = writer.toString(); + + } catch (Exception e) { + logger.log(Level.WARNING, "There was an error loading an external resource", e); + } finally { + try { + if (inputStream != null) { + inputStream.close(); + } + } catch (Exception e) { + logger.log(Level.SEVERE, "There was an error closing input stream", e); + } + try { + writer.close(); + } catch (IOException e) { + logger.log(Level.SEVERE, "There was an error closing writer", e); + } + } + } + return resourceContent; + } +} diff --git a/receipt/src/test/resources/authentication_token_response.json b/receipt/src/test/resources/authentication_token_response.json new file mode 100644 index 000000000..e8e41bf37 --- /dev/null +++ b/receipt/src/test/resources/authentication_token_response.json @@ -0,0 +1,3 @@ +{ + "value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ1c3ItZjZlNmZjY2EtNTBmNy00ZWY1LWExYzUtNWZmMDJlMDU2MzgzIiwiaWF0IjoxNTQ5NTgwMzk0LCJleHAiOjI1NDk1ODA5OTQsImF1ZCI6InBndS03YTEyMzJlOC0xNDc5LTQzNzAtOWY1NC03ODc1ZjdiMTg2NmMiLCJpc3MiOiJwcmctY2NhODAyNWUtODVhMy0xMWU2LTg2MGEtNThhZDVlY2NlNjFkIiwicmVzdC11cmkiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvcmVzdC92My8iLCJncmFwaHFsLXVyaSI6Imh0dHA6Ly9sb2NhbGhvc3Q6ODA4MC9ncmFwaHFsIn0.kILSynYHbepbl4sVqENnNog09iGByfTrckHhSCjVgnuRnuspI72cx3rt0SB2V_neHwzYkD_VfhNKk9gJDOwXeQ" +} \ No newline at end of file diff --git a/receipt/src/test/resources/receipt_credit_response.json b/receipt/src/test/resources/receipt_credit_response.json new file mode 100644 index 000000000..4351d17a2 --- /dev/null +++ b/receipt/src/test/resources/receipt_credit_response.json @@ -0,0 +1,30 @@ +{ + "count": 1, + "offset": 0, + "limit": 10, + "data": [ + { + "journalId": "3051581", + "type": "PAYMENT", + "createdOn": "2019-06-02T17:09:07", + "entry": "CREDIT", + "sourceToken": "act-12345", + "destinationToken": "usr-fa76a738-f43d-48b9-9a7a-7048d44a5d2d", + "amount": "25.00", + "fee": "0.00", + "currency": "CAD", + "details": { + "clientPaymentId": "ABC1234", + "payeeName": "A Person" + } + } + ], + "links": [ + { + "params": { + "rel": "self" + }, + "href": "https://api.sandbox.hyperwallet.com/rest/v3/users/usr-fa76a738-f43d-48b9-9a7a-7048d44a5d2d/receipts?offset=0&limit=10" + } + ] +} \ No newline at end of file diff --git a/receipt/src/test/resources/receipt_debit_response.json b/receipt/src/test/resources/receipt_debit_response.json new file mode 100644 index 000000000..8ed756455 --- /dev/null +++ b/receipt/src/test/resources/receipt_debit_response.json @@ -0,0 +1,25 @@ +{ + "count": 1, + "offset": 0, + "limit": 10, + "data": [ + { + "journalId": "3051590", + "type": "TRANSFER_TO_PREPAID_CARD", + "createdOn": "2019-05-02T17:12:18", + "entry": "DEBIT", + "sourceToken": "usr-fa76a738-f43d-48b9-9a7a-7048d44a5d2d", + "destinationToken": "trm-12345", + "amount": "18.05", + "currency": "USD" + } + ], + "links": [ + { + "params": { + "rel": "self" + }, + "href": "https://api.sandbox.hyperwallet.com/rest/v3/users/usr-fa76a738-f43d-48b9-9a7a-7048d44a5d2d/receipts?offset=0&limit=10" + } + ] +} \ No newline at end of file diff --git a/receipt/src/test/resources/receipt_list_date_grouping_response.json b/receipt/src/test/resources/receipt_list_date_grouping_response.json new file mode 100644 index 000000000..d4d552972 --- /dev/null +++ b/receipt/src/test/resources/receipt_list_date_grouping_response.json @@ -0,0 +1,90 @@ +{ + "count": 5, + "offset": 0, + "limit": 10, + "data": [ + { + "journalId": "51660665", + "type": "PAYMENT", + "createdOn": "2019-05-27T15:42:07", + "entry": "CREDIT", + "sourceToken": "act-b1f6dc28-e534-45f4-a661-3523f051f77a", + "destinationToken": "usr-b4e8ec34-52d8-4a81-9566-bdde1bd745b6", + "amount": "5000.00", + "fee": "0.00", + "currency": "USD", + "details": { + "clientPaymentId": "trans-0001", + "payeeName": "Kevin Puckett" + } + }, + { + "journalId": "51660666", + "type": "TRANSFER_TO_BANK_ACCOUNT", + "createdOn": "2019-05-27T15:57:49", + "entry": "DEBIT", + "sourceToken": "usr-b4e8ec34-52d8-4a81-9566-bdde1bd745b6", + "destinationToken": "trm-0a2ac589-2cae-4ed3-9b0b-658246a34687", + "amount": "10.25", + "fee": "0.25", + "currency": "USD", + "details": { + "payeeName": "Kevin Puckett", + "bankAccountId": "patzachery.mcclary@example.com" + } + }, + { + "journalId": "51660667", + "type": "PAYMENT", + "createdOn": "2019-05-27T16:01:10", + "entry": "CREDIT", + "sourceToken": "act-b1f6dc28-e534-45f4-a661-3523f051f77a", + "destinationToken": "usr-b4e8ec34-52d8-4a81-9566-bdde1bd745b6", + "amount": "11.00", + "fee": "0.00", + "currency": "USD", + "details": { + "clientPaymentId": "trans-02", + "payeeName": "Kevin Puckett" + } + }, + { + "journalId": "51660675", + "type": "PAYMENT", + "createdOn": "2019-06-04T10:35:23", + "entry": "CREDIT", + "sourceToken": "act-b1f6dc28-e534-45f4-a661-3523f051f77a", + "destinationToken": "usr-b4e8ec34-52d8-4a81-9566-bdde1bd745b6", + "amount": "13.00", + "fee": "0.00", + "currency": "USD", + "details": { + "clientPaymentId": "CSietnRJQQ0bscYkOoPJxNiTDiVALhjQ", + "payeeName": "Kevin Puckett" + } + }, + { + "journalId": "51660676", + "type": "PAYMENT", + "createdOn": "2019-06-04T11:16:21", + "entry": "CREDIT", + "sourceToken": "act-b1f6dc28-e534-45f4-a661-3523f051f77a", + "destinationToken": "usr-b4e8ec34-52d8-4a81-9566-bdde1bd745b6", + "amount": "14.00", + "fee": "0.00", + "currency": "USD", + "details": { + "clientPaymentId": "wUOdfLlJONacbdHlAHOAXQT7uwX7LTPy", + "payeeName": "Kevin Puckett" + } + } + ], + "links": [ + { + "params": { + "rel": "self" + }, + "href": "https://localhost:8181/rest/v3/users/usr-b4e8ec34-52d8-4a81-9566-bdde1bd745b6/receipts?offset=0&limit=10&createdAfter=2019-1-1" + } + ] +} \ No newline at end of file diff --git a/receipt/src/test/resources/receipt_list_response.json b/receipt/src/test/resources/receipt_list_response.json new file mode 100644 index 000000000..7e7cc58af --- /dev/null +++ b/receipt/src/test/resources/receipt_list_response.json @@ -0,0 +1,64 @@ +{ + "count": 4, + "offset": 0, + "limit": 10, + "data": [ + { + "journalId": "3051579", + "type": "PAYMENT", + "createdOn": "2019-06-07T17:08:58", + "entry": "CREDIT", + "sourceToken": "act-12345", + "destinationToken": "usr-fa76a738-f43d-48b9-9a7a-7048d44a5d2d", + "amount": "20.00", + "fee": "0.00", + "currency": "USD", + "details": { + "clientPaymentId": "8OxXefx5", + "payeeName": "A Person" + } + }, + { + "journalId": "3051581", + "type": "PAYMENT", + "createdOn": "2019-06-02T16:09:07", + "entry": "CREDIT", + "sourceToken": "act-12345", + "destinationToken": "usr-fa76a738-f43d-48b9-9a7a-7048d44a5d2d", + "amount": "25.00", + "fee": "0.00", + "currency": "CAD", + "details": { + "clientPaymentId": "Q3SVvpv0", + "payeeName": "A Person" + } + }, + { + "journalId": "3051582", + "type": "CARD_ACTIVATION_FEE", + "createdOn": "2019-06-01T11:09:16", + "entry": "DEBIT", + "sourceToken": "usr-fa76a738-f43d-48b9-9a7a-7048d44a5d2d", + "amount": "1.95", + "currency": "USD" + }, + { + "journalId": "3051590", + "type": "TRANSFER_TO_PREPAID_CARD", + "createdOn": "2018-12-01T17:12:18", + "entry": "DEBIT", + "sourceToken": "usr-fa76a738-f43d-48b9-9a7a-7048d44a5d2d", + "destinationToken": "trm-12345", + "amount": "18.05", + "currency": "USD" + } + ], + "links": [ + { + "params": { + "rel": "self" + }, + "href": "https://api.sandbox.hyperwallet.com/rest/v3/users/usr-fa76a738-f43d-48b9-9a7a-7048d44a5d2d/receipts?offset=0&limit=10" + } + ] +} \ No newline at end of file diff --git a/receipt/src/test/resources/receipt_unknown_type_response.json b/receipt/src/test/resources/receipt_unknown_type_response.json new file mode 100644 index 000000000..bf856ed63 --- /dev/null +++ b/receipt/src/test/resources/receipt_unknown_type_response.json @@ -0,0 +1,30 @@ +{ + "count": 1, + "offset": 0, + "limit": 10, + "data": [ + { + "journalId": "3051581", + "type": "ICK", + "createdOn": "2019-06-02T17:09:07", + "entry": "CREDIT", + "sourceToken": "act-12345", + "destinationToken": "usr-fa76a738-f43d-48b9-9a7a-7048d44a5d2d", + "amount": "25.00", + "fee": "0.00", + "currency": "CAD", + "details": { + "clientPaymentId": "ABC1234", + "payeeName": "A Person" + } + } + ], + "links": [ + { + "params": { + "rel": "self" + }, + "href": "https://api.sandbox.hyperwallet.com/rest/v3/users/usr-fa76a738-f43d-48b9-9a7a-7048d44a5d2d/receipts?offset=0&limit=10" + } + ] +} \ No newline at end of file diff --git a/ui/src/androidTest/AndroidManifest.xml b/ui/src/androidTest/AndroidManifest.xml index 9b2c52c35..0cd133def 100644 --- a/ui/src/androidTest/AndroidManifest.xml +++ b/ui/src/androidTest/AndroidManifest.xml @@ -1,6 +1,6 @@ + package="com.hyperwallet.android.hyperwallet_ui.test"> diff --git a/ui/src/main/java/com/hyperwallet/android/ui/HyperwalletUi.java b/ui/src/main/java/com/hyperwallet/android/ui/HyperwalletUi.java index d2f6b9123..aae63fa7e 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/HyperwalletUi.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/HyperwalletUi.java @@ -31,6 +31,7 @@ import com.hyperwallet.android.Hyperwallet; import com.hyperwallet.android.HyperwalletAuthenticationTokenProvider; +import com.hyperwallet.android.receipt.view.ListReceiptActivity; import com.hyperwallet.android.ui.transfermethod.AddTransferMethodActivity; import com.hyperwallet.android.ui.transfermethod.ListTransferMethodActivity; import com.hyperwallet.android.ui.transfermethod.SelectTransferMethodActivity; @@ -78,6 +79,13 @@ public Intent getIntentSelectTransferMethodActivity(@NonNull final Context conte return new Intent(context, SelectTransferMethodActivity.class); } + /** + * @param context A Context of the application consuming this Intent. + * @return an Intent with the data necessary to launch the {@link ListReceiptActivity} + */ + public Intent getIntentListReceiptActivity(@NonNull final Context context) { + return new Intent(context, ListReceiptActivity.class); + } /** * @param context A Context of the application consuming this Intent. diff --git a/ui/src/main/java/com/hyperwallet/android/ui/repository/TransferMethodRepositoryImpl.java b/ui/src/main/java/com/hyperwallet/android/ui/repository/TransferMethodRepositoryImpl.java index 7d6b77063..902971023 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/repository/TransferMethodRepositoryImpl.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/repository/TransferMethodRepositoryImpl.java @@ -16,6 +16,7 @@ */ package com.hyperwallet.android.ui.repository; +import static com.hyperwallet.android.model.HyperwalletStatusTransition.StatusDefinition.ACTIVATED; import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodFields.TOKEN; import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodFields.TYPE; import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.BANK_ACCOUNT; @@ -36,6 +37,7 @@ import com.hyperwallet.android.model.transfermethod.HyperwalletBankAccount; import com.hyperwallet.android.model.transfermethod.HyperwalletBankCard; import com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod; +import com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethodQueryParam; import com.hyperwallet.android.model.transfermethod.PayPalAccount; public class TransferMethodRepositoryImpl implements TransferMethodRepository { @@ -66,7 +68,11 @@ public void createTransferMethod(@NonNull final HyperwalletTransferMethod transf @Override public void loadTransferMethods(@NonNull final LoadTransferMethodListCallback callback) { - getHyperwallet().listTransferMethods(null, + + HyperwalletTransferMethodQueryParam queryParam = new HyperwalletTransferMethodQueryParam.Builder() + .status(ACTIVATED) + .build(); + getHyperwallet().listTransferMethods(queryParam, new HyperwalletListener>() { @Override public void onSuccess(@Nullable HyperwalletPageList result) { diff --git a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/ListTransferMethodFragment.java b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/ListTransferMethodFragment.java index 0f413b0ad..3a5d22a50 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/ListTransferMethodFragment.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/ListTransferMethodFragment.java @@ -42,13 +42,13 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; +import com.hyperwallet.android.common.view.HorizontalDividerItemDecorator; import com.hyperwallet.android.hyperwallet_ui.R; import com.hyperwallet.android.model.HyperwalletError; import com.hyperwallet.android.model.HyperwalletStatusTransition; import com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod; import com.hyperwallet.android.ui.HyperwalletLocalBroadcast; import com.hyperwallet.android.ui.repository.RepositoryFactory; -import com.hyperwallet.android.ui.view.HorizontalDividerItemDecorator; import com.hyperwallet.android.ui.view.widget.OneClickListener; import java.util.ArrayList; @@ -173,7 +173,7 @@ public void onOneClick(View v) { recyclerView = view.findViewById(R.id.list_transfer_method_item); recyclerView.setHasFixedSize(true); recyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); - recyclerView.addItemDecoration(new HorizontalDividerItemDecorator(getContext(), false)); + recyclerView.addItemDecoration(new HorizontalDividerItemDecorator(requireContext(), false)); } @Override diff --git a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/SelectTransferMethodFragment.java b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/SelectTransferMethodFragment.java index aa4a9408f..154a2bff0 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/SelectTransferMethodFragment.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/SelectTransferMethodFragment.java @@ -38,12 +38,12 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; +import com.hyperwallet.android.common.view.HorizontalDividerItemDecorator; import com.hyperwallet.android.hyperwallet_ui.R; import com.hyperwallet.android.model.HyperwalletError; import com.hyperwallet.android.ui.repository.RepositoryFactory; import com.hyperwallet.android.ui.view.CountrySelectionDialogFragment; import com.hyperwallet.android.ui.view.CurrencySelectionDialogFragment; -import com.hyperwallet.android.ui.view.HorizontalDividerItemDecorator; import com.hyperwallet.android.ui.view.widget.OneClickListener; import java.util.ArrayList; @@ -183,7 +183,7 @@ public void onTransferMethodSelected(TransferMethodSelectionItem transferMethodT mRecyclerView.setAdapter(mTransferMethodTypesAdapter); mRecyclerView.setHasFixedSize(true); mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext())); - mRecyclerView.addItemDecoration(new HorizontalDividerItemDecorator(getContext(), true)); + mRecyclerView.addItemDecoration(new HorizontalDividerItemDecorator(requireContext(), true)); } @Override From 256ad67720c9e2b2a5a29226bbfae948af0addd9 Mon Sep 17 00:00:00 2001 From: Viktor Shcherbyna Date: Thu, 13 Jun 2019 21:18:22 +0300 Subject: [PATCH 06/10] address callouts --- .../ui/transfermethod/AccountSecondLine.java | 51 +++++++++++++++++++ ...dLineStrategy.java => CardSecondLine.java} | 35 ++++++++----- .../ListTransferMethodFragment.java | 2 +- ...Line.java => PayPalAccountSecondLine.java} | 15 +++--- .../transfermethod/SecondLinePresenter.java | 14 ++++- .../TransferMethodSecondLine.java | 51 ++++++------------- .../TransferMethodSecondLinePresenter.java | 37 ++++++++++---- ...TransferMethodSecondLinePresenterTest.java | 41 +++++++-------- 8 files changed, 158 insertions(+), 88 deletions(-) create mode 100644 ui/src/main/java/com/hyperwallet/android/ui/transfermethod/AccountSecondLine.java rename ui/src/main/java/com/hyperwallet/android/ui/transfermethod/{TransferMethodSecondLineStrategy.java => CardSecondLine.java} (55%) rename ui/src/main/java/com/hyperwallet/android/ui/transfermethod/{PayPalAccountTransferMethodSecondLine.java => PayPalAccountSecondLine.java} (77%) diff --git a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/AccountSecondLine.java b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/AccountSecondLine.java new file mode 100644 index 000000000..055c0e23b --- /dev/null +++ b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/AccountSecondLine.java @@ -0,0 +1,51 @@ +/* + * The MIT License (MIT) + * Copyright (c) 2018 Hyperwallet Systems Inc. + * + * 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 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; + +import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodFields.BANK_ACCOUNT_ID; + +import android.content.Context; + +import androidx.annotation.NonNull; + +import com.hyperwallet.android.hyperwallet_ui.R; +import com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod; + +/** + * Retrieves Bank account Id from the {@link HyperwalletTransferMethod} field + * and forms an identifier String of the last 4 digits. + */ +public class AccountSecondLine implements TransferMethodSecondLine { + private static final int LAST_FOUR_DIGIT = 4; + + @NonNull + @Override + public String getText(@NonNull final Context context, + @NonNull final HyperwalletTransferMethod transferMethod) { + + return context.getString(R.string.transfer_method_list_item_description, + getAccountIdentifier(transferMethod)); + } + + private String getAccountIdentifier(@NonNull final HyperwalletTransferMethod transferMethod) { + final String transferIdentification = transferMethod.getField(BANK_ACCOUNT_ID); + + return (transferIdentification.length() > LAST_FOUR_DIGIT + ? transferIdentification.substring(transferIdentification.length() - LAST_FOUR_DIGIT) + : transferIdentification); + } +} diff --git a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSecondLineStrategy.java b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/CardSecondLine.java similarity index 55% rename from ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSecondLineStrategy.java rename to ui/src/main/java/com/hyperwallet/android/ui/transfermethod/CardSecondLine.java index 0e7f628d9..37ec35d07 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSecondLineStrategy.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/CardSecondLine.java @@ -16,29 +16,38 @@ */ package com.hyperwallet.android.ui.transfermethod; +import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodFields.CARD_NUMBER; + import android.content.Context; import androidx.annotation.NonNull; +import com.hyperwallet.android.hyperwallet_ui.R; import com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod; /** - * Represents abstract strategy for the second line of TransferMethod list item. + * Retrieves Card number from the {@link HyperwalletTransferMethod} field + * and forms an identifier String of the last 4 digits. */ -public interface TransferMethodSecondLineStrategy { +public class CardSecondLine implements TransferMethodSecondLine { + private static final int LAST_FOUR_DIGIT = 4; - TransferMethodSecondLineStrategy DEFAULT = new TransferMethodSecondLineStrategy() { + @NonNull + @Override + public String getText(@NonNull final Context context, + @NonNull final HyperwalletTransferMethod transferMethod) { - @NonNull - @Override - public String getText(@NonNull Context context, - @NonNull HyperwalletTransferMethod transferMethod) { - return ""; - } - }; + return context.getString(R.string.transfer_method_list_item_description, + getCardIdentifier(transferMethod)); + } + + private String getCardIdentifier(@NonNull final HyperwalletTransferMethod transferMethod) { + final String transferIdentification = transferMethod.getField(CARD_NUMBER); + + return (transferIdentification.length() > LAST_FOUR_DIGIT + ? transferIdentification.substring(transferIdentification.length() - LAST_FOUR_DIGIT) + : transferIdentification); + } - @NonNull - String getText(@NonNull final Context context, - @NonNull final HyperwalletTransferMethod transferMethod); } diff --git a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/ListTransferMethodFragment.java b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/ListTransferMethodFragment.java index 3a5d22a50..a274aafd8 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/ListTransferMethodFragment.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/ListTransferMethodFragment.java @@ -356,7 +356,7 @@ class ViewHolder extends RecyclerView.ViewHolder { void bind(@NonNull final HyperwalletTransferMethod transferMethod) { String type = transferMethod.getField(TYPE); - TransferMethodSecondLineStrategy identificationStrategy = mSecondLinePresenter.obtainSecondLineStrategy( + TransferMethodSecondLine identificationStrategy = mSecondLinePresenter.getSecondLinePresenter( type); mTitle.setText( diff --git a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/PayPalAccountTransferMethodSecondLine.java b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/PayPalAccountSecondLine.java similarity index 77% rename from ui/src/main/java/com/hyperwallet/android/ui/transfermethod/PayPalAccountTransferMethodSecondLine.java rename to ui/src/main/java/com/hyperwallet/android/ui/transfermethod/PayPalAccountSecondLine.java index 29dd446d4..7d837872a 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/PayPalAccountTransferMethodSecondLine.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/PayPalAccountSecondLine.java @@ -24,14 +24,17 @@ import com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod; - -public class PayPalAccountTransferMethodSecondLine implements TransferMethodSecondLineStrategy { +/** + * Retrieves PayPal account email from the {@link HyperwalletTransferMethod} and forms an identifier String. + */ +public class PayPalAccountSecondLine implements TransferMethodSecondLine { @NonNull @Override - public String getText(@NonNull Context context, - @NonNull HyperwalletTransferMethod transferMethod) { - String identificationText = transferMethod.getField(EMAIL); - return identificationText != null ? identificationText : ""; + public String getText(@NonNull final Context context, + @NonNull final HyperwalletTransferMethod transferMethod) { + + final String identificationText = transferMethod.getField(EMAIL); + return identificationText != null ? identificationText : EMPTY_STRING; } } diff --git a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/SecondLinePresenter.java b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/SecondLinePresenter.java index 4364be661..da781da2e 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/SecondLinePresenter.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/SecondLinePresenter.java @@ -16,6 +16,18 @@ */ package com.hyperwallet.android.ui.transfermethod; +import com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod; + +/** + * Factory makes instance of a {@link TransferMethodSecondLine} by a corresponding + * {@link HyperwalletTransferMethod.TransferMethodType} + */ interface SecondLinePresenter { - TransferMethodSecondLineStrategy obtainSecondLineStrategy(String type); + /** + * Get {@link TransferMethodSecondLine} by a {@link HyperwalletTransferMethod.TransferMethodType} + * + * @param type @{@link HyperwalletTransferMethod.TransferMethodType} + * @return Implementation of the {@link TransferMethodSecondLine} + */ + TransferMethodSecondLine getSecondLinePresenter(@HyperwalletTransferMethod.TransferMethodType final String type); } diff --git a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSecondLine.java b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSecondLine.java index f578027ec..004f3b2ac 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSecondLine.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSecondLine.java @@ -16,51 +16,30 @@ */ package com.hyperwallet.android.ui.transfermethod; -import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodFields.BANK_ACCOUNT_ID; -import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodFields.CARD_NUMBER; -import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodFields.TYPE; -import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.BANK_ACCOUNT; -import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.BANK_CARD; -import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.PREPAID_CARD; -import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.WIRE_ACCOUNT; - import android.content.Context; import androidx.annotation.NonNull; -import com.hyperwallet.android.hyperwallet_ui.R; import com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod; +/** + * Represents abstract strategy for the second line of TransferMethod list item. + */ +public interface TransferMethodSecondLine { -public class TransferMethodSecondLine implements TransferMethodSecondLineStrategy { - private static final int LAST_FOUR_DIGIT = 4; - - @NonNull - @Override - public String getText(@NonNull Context context, - @NonNull HyperwalletTransferMethod transferMethod) { + String EMPTY_STRING = ""; + TransferMethodSecondLine DEFAULT = new TransferMethodSecondLine() { - return context.getString(R.string.transfer_method_list_item_description, - getAccountIdentifier(transferMethod)); - } + @NonNull + @Override + public String getText(@NonNull final Context context, + @NonNull final HyperwalletTransferMethod transferMethod) { - private String getAccountIdentifier(@NonNull final HyperwalletTransferMethod transferMethod) { - String transferIdentification = ""; - switch (transferMethod.getField(TYPE)) { - case BANK_ACCOUNT: - case WIRE_ACCOUNT: - transferIdentification = transferMethod.getField(BANK_ACCOUNT_ID); - break; - case BANK_CARD: - case PREPAID_CARD: - transferIdentification = transferMethod.getField(CARD_NUMBER); - break; - default: // none for paper check + return EMPTY_STRING; } - return (transferIdentification.length() > LAST_FOUR_DIGIT - ? transferIdentification.substring(transferIdentification.length() - LAST_FOUR_DIGIT) - : transferIdentification); - } - + }; + @NonNull + String getText(@NonNull final Context context, + @NonNull final HyperwalletTransferMethod transferMethod); } diff --git a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSecondLinePresenter.java b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSecondLinePresenter.java index 4f891549d..004610a1e 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSecondLinePresenter.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSecondLinePresenter.java @@ -24,41 +24,56 @@ import androidx.annotation.NonNull; +import com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod; + import java.util.HashMap; import java.util.Map; +/** + * Factory instantiates instance of a {@link TransferMethodSecondLine} by a corresponding + * {@link HyperwalletTransferMethod.TransferMethodType} + */ final class TransferMethodSecondLinePresenter implements SecondLinePresenter { - private Map mSecondLineStrategies = new HashMap<>(2); + private Map mSecondLineStrategies = new HashMap<>(3); @Override @NonNull - public TransferMethodSecondLineStrategy obtainSecondLineStrategy(String type) { + public TransferMethodSecondLine getSecondLinePresenter( + @HyperwalletTransferMethod.TransferMethodType final String type) { if (type == null) { - return TransferMethodSecondLineStrategy.DEFAULT; + return TransferMethodSecondLine.DEFAULT; } switch (type) { case BANK_CARD: case PREPAID_CARD: + if (!mSecondLineStrategies.containsKey(CardSecondLine.class)) { + mSecondLineStrategies.put( + CardSecondLine.class, new CardSecondLine()); + } + + //noinspection ConstantConditions + return mSecondLineStrategies.get(CardSecondLine.class); case BANK_ACCOUNT: case WIRE_ACCOUNT: - if (!mSecondLineStrategies.containsKey(TransferMethodSecondLine.class)) { - mSecondLineStrategies.put(TransferMethodSecondLine.class, new TransferMethodSecondLine()); + if (!mSecondLineStrategies.containsKey(AccountSecondLine.class)) { + mSecondLineStrategies.put( + AccountSecondLine.class, new AccountSecondLine()); } //noinspection ConstantConditions - return mSecondLineStrategies.get(TransferMethodSecondLine.class); + return mSecondLineStrategies.get(AccountSecondLine.class); case PAYPAL_ACCOUNT: - if (!mSecondLineStrategies.containsKey(PayPalAccountTransferMethodSecondLine.class)) { - mSecondLineStrategies.put(PayPalAccountTransferMethodSecondLine.class, - new PayPalAccountTransferMethodSecondLine()); + if (!mSecondLineStrategies.containsKey(PayPalAccountSecondLine.class)) { + mSecondLineStrategies.put(PayPalAccountSecondLine.class, + new PayPalAccountSecondLine()); } //noinspection ConstantConditions - return mSecondLineStrategies.get(PayPalAccountTransferMethodSecondLine.class); + return mSecondLineStrategies.get(PayPalAccountSecondLine.class); default: - return TransferMethodSecondLineStrategy.DEFAULT; + return TransferMethodSecondLine.DEFAULT; } } } diff --git a/ui/src/test/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSecondLinePresenterTest.java b/ui/src/test/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSecondLinePresenterTest.java index 6cdbfa176..c07152649 100644 --- a/ui/src/test/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSecondLinePresenterTest.java +++ b/ui/src/test/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSecondLinePresenterTest.java @@ -42,75 +42,76 @@ public void setUp() { } @Test - public void testObtainSecondLineStrategy_returnsCachedSecondLineStrategy() { - TransferMethodSecondLineStrategy actualStrategy = mPresenter.obtainSecondLineStrategy(BANK_CARD); - TransferMethodSecondLineStrategy candidateStrategy = mPresenter.obtainSecondLineStrategy(BANK_ACCOUNT); + public void testGetSecondLine_returnsCachedSecondLine() { + TransferMethodSecondLine actualStrategy = mPresenter.getSecondLinePresenter( + HyperwalletTransferMethod.TransferMethodTypes.WIRE_ACCOUNT); + TransferMethodSecondLine candidateStrategy = mPresenter.getSecondLinePresenter(BANK_ACCOUNT); assertThat(actualStrategy, is(candidateStrategy)); } @Test - public void testObtainSecondLineStrategy_returnsSecondLineStrategy() { - TransferMethodSecondLineStrategy strategy1 = mPresenter.obtainSecondLineStrategy(BANK_CARD); - TransferMethodSecondLineStrategy strategy2 = mPresenter.obtainSecondLineStrategy(PAYPAL_ACCOUNT); + public void testGetSecondLine_returnsSecondLine() { + TransferMethodSecondLine strategy1 = mPresenter.getSecondLinePresenter(BANK_CARD); + TransferMethodSecondLine strategy2 = mPresenter.getSecondLinePresenter(PAYPAL_ACCOUNT); assertThat(strategy1, not(strategy2)); } @Test - public void testObtainSecondLineStrategy_returnsEndingOn() { - TransferMethodSecondLineStrategy strategy = mPresenter.obtainSecondLineStrategy(BANK_CARD); + public void testGetSecondLine_returnsEndingOn() { + TransferMethodSecondLine strategy = mPresenter.getSecondLinePresenter(BANK_CARD); assertThat(strategy, is(strategy)); } @Test - public void testObtainSecondLineStrategy_returnsPayPalSecondLine() throws JSONException { + public void testGetSecondLine_returnsPayPalSecondLine() throws JSONException { Context context = mock(Context.class); String json = mExternalResourceManager.getResourceContent("paypal_response.json"); JSONObject htmJsonObject = new JSONObject(json); HyperwalletTransferMethod transferMethod = new HyperwalletTransferMethod(htmJsonObject); - TransferMethodSecondLineStrategy strategy = mPresenter.obtainSecondLineStrategy(PAYPAL_ACCOUNT); + TransferMethodSecondLine strategy = mPresenter.getSecondLinePresenter(PAYPAL_ACCOUNT); String actual = strategy.getText(context, transferMethod); - assertThat(strategy, instanceOf(PayPalAccountTransferMethodSecondLine.class)); + assertThat(strategy, instanceOf(PayPalAccountSecondLine.class)); assertThat(actual, is("sunshine.carreiro@hyperwallet.com")); } @Test - public void testObtainSecondLineStrategy_returnsBankCardSecondLine() throws JSONException { + public void testGetSecondLine_returnsCardSecondLine() throws JSONException { Context context = mock(Context.class); String json = mExternalResourceManager.getResourceContent("bank_card_response.json"); JSONObject htmJsonObject = new JSONObject(json); HyperwalletTransferMethod transferMethod = new HyperwalletTransferMethod(htmJsonObject); - TransferMethodSecondLineStrategy strategy = mPresenter.obtainSecondLineStrategy(BANK_CARD); + TransferMethodSecondLine strategy = mPresenter.getSecondLinePresenter(BANK_CARD); strategy.getText(context, transferMethod); - assertThat(strategy, instanceOf(TransferMethodSecondLine.class)); + assertThat(strategy, instanceOf(CardSecondLine.class)); verify(context).getString(eq(R.string.transfer_method_list_item_description), eq("0006")); } @Test - public void testObtainSecondLineStrategy_returnsBankAccountSecondLine() throws JSONException { + public void testGetSecondLine_returnsAccountSecondLine() throws JSONException { Context context = mock(Context.class); String json = mExternalResourceManager.getResourceContent("bank_account_response.json"); JSONObject htmJsonObject = new JSONObject(json); HyperwalletTransferMethod transferMethod = new HyperwalletTransferMethod(htmJsonObject); - TransferMethodSecondLineStrategy strategy = mPresenter.obtainSecondLineStrategy(BANK_ACCOUNT); + TransferMethodSecondLine strategy = mPresenter.getSecondLinePresenter(BANK_ACCOUNT); strategy.getText(context, transferMethod); - assertThat(strategy, instanceOf(TransferMethodSecondLine.class)); + assertThat(strategy, instanceOf(AccountSecondLine.class)); verify(context).getString(eq(R.string.transfer_method_list_item_description), eq("0254")); } @Test - public void testObtainSecondLineStrategy_returnsPaperCheckSecondLine() throws JSONException { + public void testGetSecondLine_returnsPaperCheckSecondLine() throws JSONException { Context context = mock(Context.class); String json = mExternalResourceManager.getResourceContent("paper_check_response.json"); JSONObject htmJsonObject = new JSONObject(json); HyperwalletTransferMethod transferMethod = new HyperwalletTransferMethod(htmJsonObject); - TransferMethodSecondLineStrategy strategy = mPresenter.obtainSecondLineStrategy(PAPER_CHECK); + TransferMethodSecondLine strategy = mPresenter.getSecondLinePresenter(PAPER_CHECK); String actual = strategy.getText(context, transferMethod); - assertThat(strategy, instanceOf(TransferMethodSecondLineStrategy.class)); + assertThat(strategy, instanceOf(TransferMethodSecondLine.class)); assertThat(actual, is("")); verify(context, never()).getString(eq(R.string.transfer_method_list_item_description), anyString()); } From 73c7cffa2a6cf02a7eecab4601f462924d55f945 Mon Sep 17 00:00:00 2001 From: Shyang Koong Date: Thu, 13 Jun 2019 14:18:01 -0700 Subject: [PATCH 07/10] Implement lazy loading automation and fixing lint error (#41) --- .../android/receipt/ListReceiptsTest.java | 35 ++ receipt/src/main/AndroidManifest.xml | 3 +- receipt/src/main/res/layout/item_receipt.xml | 1 + .../receipt_list_paged_last_response.json | 189 ++++++++++ .../receipt_list_paged_response.json | 351 ++++++++++++++++++ .../receipt_list_paged_second_response.json | 202 ++++++++++ .../receipt_list_paged_third_response.json | 201 ++++++++++ 7 files changed, 981 insertions(+), 1 deletion(-) create mode 100644 receipt/src/test/resources/receipt_list_paged_last_response.json create mode 100644 receipt/src/test/resources/receipt_list_paged_response.json create mode 100644 receipt/src/test/resources/receipt_list_paged_second_response.json create mode 100644 receipt/src/test/resources/receipt_list_paged_third_response.json diff --git a/receipt/src/androidTest/java/com/hyperwallet/android/receipt/ListReceiptsTest.java b/receipt/src/androidTest/java/com/hyperwallet/android/receipt/ListReceiptsTest.java index 5eb430354..05c0e5c59 100644 --- a/receipt/src/androidTest/java/com/hyperwallet/android/receipt/ListReceiptsTest.java +++ b/receipt/src/androidTest/java/com/hyperwallet/android/receipt/ListReceiptsTest.java @@ -22,6 +22,7 @@ import android.widget.TextView; import androidx.test.core.app.ApplicationProvider; +import androidx.test.espresso.contrib.RecyclerViewActions; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.rule.ActivityTestRule; @@ -229,6 +230,40 @@ public void testListReceipt_userHasNoTransactions() { //todo: check empty view when it will be ready } + @Test + public void testListReceipt_displayPagedTransactions() throws InterruptedException { + mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager + .getResourceContent("receipt_list_paged_response.json")).mock(); + mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager + .getResourceContent("receipt_list_paged_second_response.json")).mock(); + mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager + .getResourceContent("receipt_list_paged_third_response.json")).mock(); + mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager + .getResourceContent("receipt_list_paged_last_response.json")).mock(); + mMockWebServer.mockResponse().withHttpResponseCode(HTTP_NO_CONTENT).withBody("").mock(); + + // run test + mActivityTestRule.launchActivity(null); + + onView(withId(R.id.toolbar)).check(matches(isDisplayed())); + onView(allOf(instanceOf(TextView.class), withParent(withId(R.id.toolbar)))) + .check(matches(withText(R.string.title_activity_receipt_list))); + + onView(withId(R.id.list_receipts)).check(new RecyclerViewCountAssertion(20)); + onView(withId(R.id.list_receipts)).perform(RecyclerViewActions.scrollToPosition(10)); + onView(withId(R.id.list_receipts)).check(new RecyclerViewCountAssertion(30)); + onView(withId(R.id.list_receipts)).perform(RecyclerViewActions.scrollToPosition(20)); + onView(withId(R.id.list_receipts)).check(new RecyclerViewCountAssertion(40)); + onView(withId(R.id.list_receipts)).perform(RecyclerViewActions.scrollToPosition(30)); + onView(withId(R.id.list_receipts)).check(new RecyclerViewCountAssertion(50)); + + // verify that when the list reaches the end no additional data is loaded + onView(withId(R.id.list_receipts)).perform(RecyclerViewActions.scrollToPosition(40)); + onView(withId(R.id.list_receipts)).check(new RecyclerViewCountAssertion(50)); + onView(withId(R.id.list_receipts)).perform(RecyclerViewActions.scrollToPosition(50)); + onView(withId(R.id.list_receipts)).check(new RecyclerViewCountAssertion(50)); + } + @Test public void testListReceipts_checkDateTextOnLocaleChange() { mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager diff --git a/receipt/src/main/AndroidManifest.xml b/receipt/src/main/AndroidManifest.xml index 3039f6d18..3716721ff 100644 --- a/receipt/src/main/AndroidManifest.xml +++ b/receipt/src/main/AndroidManifest.xml @@ -1,10 +1,11 @@ - + diff --git a/receipt/src/main/res/layout/item_receipt.xml b/receipt/src/main/res/layout/item_receipt.xml index 4388d4ab7..83a0fe875 100644 --- a/receipt/src/main/res/layout/item_receipt.xml +++ b/receipt/src/main/res/layout/item_receipt.xml @@ -32,6 +32,7 @@ android:ellipsize="end" android:maxLines="1" android:textAppearance="@style/TextAppearance.MaterialComponents.Subtitle1" + android:textStyle="bold" app:layout_constraintEnd_toStartOf="@+id/transaction_amount" app:layout_constraintStart_toEndOf="@+id/transaction_type_icon" app:layout_constraintTop_toTopOf="parent"/> diff --git a/receipt/src/test/resources/receipt_list_paged_last_response.json b/receipt/src/test/resources/receipt_list_paged_last_response.json new file mode 100644 index 000000000..be47b01ab --- /dev/null +++ b/receipt/src/test/resources/receipt_list_paged_last_response.json @@ -0,0 +1,189 @@ +{ + "count": 50, + "offset": 40, + "limit": 10, + "data": [ + { + "journalId": "55241289", + "type": "TRANSFER_TO_BANK_ACCOUNT", + "createdOn": "2019-01-05T20:29:08", + "entry": "DEBIT", + "sourceToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "destinationToken": "trm-cc13b0b0-5f4b-4c99-baed-eb16c8952f46", + "amount": "22.00", + "fee": "2.00", + "currency": "USD", + "details": { + "payeeName": "Brendan Zachery", + "branchId": "021000021", + "bankAccountId": "******9129", + "bankAccountPurpose": "SAVINGS" + } + }, + { + "journalId": "55241288", + "type": "TRANSFER_TO_BANK_ACCOUNT", + "createdOn": "2019-01-05T20:29:08", + "entry": "DEBIT", + "sourceToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "destinationToken": "trm-cc13b0b0-5f4b-4c99-baed-eb16c8952f46", + "amount": "17.00", + "fee": "2.00", + "currency": "USD", + "details": { + "payeeName": "Brendan Zachery", + "branchId": "021000021", + "bankAccountId": "******9129", + "bankAccountPurpose": "SAVINGS" + } + }, + { + "journalId": "55241287", + "type": "PAYMENT", + "createdOn": "2019-01-01T19:29:08", + "entry": "CREDIT", + "sourceToken": "act-68adaba2-42f4-4f0f-8670-81c09f319a12", + "destinationToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "amount": "15.00", + "fee": "0.00", + "currency": "USD", + "details": { + "clientPaymentId": "G2iCyydpjEYied0PFLfo2HyrEQg0VUYv", + "notes": "ABC1", + "payeeName": "Brendan Zachery" + } + }, + { + "journalId": "55241286", + "type": "PAYMENT", + "createdOn": "2019-01-01T19:29:08", + "entry": "CREDIT", + "sourceToken": "act-68adaba2-42f4-4f0f-8670-81c09f319a12", + "destinationToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "amount": "90.00", + "fee": "0.00", + "currency": "USD", + "details": { + "clientPaymentId": "1F81fMHy0Y1NPr6erbCTy67v3lcsMl4S", + "notes": "ABC1", + "payeeName": "Brendan Zachery" + } + }, + { + "journalId": "55241285", + "type": "PAYMENT", + "createdOn": "2019-01-01T19:29:08", + "entry": "CREDIT", + "sourceToken": "act-68adaba2-42f4-4f0f-8670-81c09f319a12", + "destinationToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "amount": "80.00", + "fee": "0.00", + "currency": "USD", + "details": { + "clientPaymentId": "AWab45eQg5XrMN1LG2WXS3jtKkMUjc01", + "notes": "ABC1", + "payeeName": "Brendan Zachery" + } + }, + { + "journalId": "55241284", + "type": "PAYMENT", + "createdOn": "2019-01-01T19:29:08", + "entry": "CREDIT", + "sourceToken": "act-68adaba2-42f4-4f0f-8670-81c09f319a12", + "destinationToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "amount": "50.00", + "fee": "0.00", + "currency": "USD", + "details": { + "clientPaymentId": "15MWFNmfEYaSp38NXyH7fw0jsrjKDB3h", + "notes": "ABC1", + "payeeName": "Brendan Zachery" + } + }, + { + "journalId": "55241283", + "type": "PAYMENT", + "createdOn": "2019-01-01T19:29:08", + "entry": "CREDIT", + "sourceToken": "act-68adaba2-42f4-4f0f-8670-81c09f319a12", + "destinationToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "amount": "30.00", + "fee": "0.00", + "currency": "USD", + "details": { + "clientPaymentId": "l06YPYvEiBYIjKSNV4lnMi5X1WagNxja", + "notes": "ABC1", + "payeeName": "Brendan Zachery" + } + }, + { + "journalId": "55241282", + "type": "PAYMENT", + "createdOn": "2019-01-01T19:29:08", + "entry": "CREDIT", + "sourceToken": "act-68adaba2-42f4-4f0f-8670-81c09f319a12", + "destinationToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "amount": "30.00", + "fee": "0.00", + "currency": "USD", + "details": { + "clientPaymentId": "jPq1QVXJDhAWMVsAU2Rnso1V3DLkudSY", + "notes": "ABC1", + "payeeName": "Brendan Zachery" + } + }, + { + "journalId": "55241281", + "type": "PAYMENT", + "createdOn": "2019-01-01T19:29:08", + "entry": "CREDIT", + "sourceToken": "act-68adaba2-42f4-4f0f-8670-81c09f319a12", + "destinationToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "amount": "30.00", + "fee": "0.00", + "currency": "USD", + "details": { + "clientPaymentId": "h42SUtuNGp7SJEvaAqaEkTjFmMDkGPWF", + "notes": "ABC1", + "payeeName": "Brendan Zachery" + } + }, + { + "journalId": "55241280", + "type": "PAYMENT", + "createdOn": "2019-01-01T19:29:08", + "entry": "CREDIT", + "sourceToken": "act-68adaba2-42f4-4f0f-8670-81c09f319a12", + "destinationToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "amount": "99.00", + "fee": "0.00", + "currency": "USD", + "details": { + "clientPaymentId": "lkrVqCxjYwxeDq2xr7PMa7eoLugC7ipk", + "notes": "ABC1", + "payeeName": "Brendan Zachery" + } + } + ], + "links": [ + { + "params": { + "rel": "self" + }, + "href": "https://qamaster-hyperwallet.aws.paylution.net/rest/v3/users/usr-02d381d3-bf7e-43fe-9d00-02e26b28df57/receipts?offset=40&limit=10&sortBy=-createdOn&createdAfter=2018-06-10T13%3A29%3A49" + }, + { + "params": { + "rel": "previous" + }, + "href": "https://qamaster-hyperwallet.aws.paylution.net/rest/v3/users/usr-02d381d3-bf7e-43fe-9d00-02e26b28df57/receipts?offset=30&limit=10&sortBy=-createdOn&createdAfter=2018-06-10T13%3A29%3A49" + }, + { + "params": { + "rel": "first" + }, + "href": "https://qamaster-hyperwallet.aws.paylution.net/rest/v3/users/usr-02d381d3-bf7e-43fe-9d00-02e26b28df57/receipts?offset=0&limit=10&sortBy=-createdOn&createdAfter=2018-06-10T13%3A29%3A49" + } + ] +} \ No newline at end of file diff --git a/receipt/src/test/resources/receipt_list_paged_response.json b/receipt/src/test/resources/receipt_list_paged_response.json new file mode 100644 index 000000000..d934b96c0 --- /dev/null +++ b/receipt/src/test/resources/receipt_list_paged_response.json @@ -0,0 +1,351 @@ +{ + "count": 50, + "offset": 0, + "limit": 20, + "data": [ + { + "journalId": "55452697", + "type": "PAYMENT", + "createdOn": "2019-06-07T23:43:51", + "entry": "CREDIT", + "sourceToken": "act-68adaba2-42f4-4f0f-8670-81c09f319a12", + "destinationToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "amount": "100.00", + "fee": "0.00", + "currency": "USD", + "details": { + "clientPaymentId": "bUxGdH3cMnMwmDkKNB6AWeDBXbcAw2eT", + "notes": "ABC1", + "payeeName": "Brendan Zachery" + } + }, + { + "journalId": "55241328", + "type": "PAYMENT", + "createdOn": "2019-05-31T22:20:46", + "entry": "CREDIT", + "sourceToken": "act-68adaba2-42f4-4f0f-8670-81c09f319a12", + "destinationToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "amount": "57.00", + "fee": "0.00", + "currency": "CAD", + "details": { + "clientPaymentId": "CJOmbMXDSSosXNmoS8SOmukbwnPBWA6e", + "notes": "ABC1", + "payeeName": "Brendan Zachery" + } + }, + { + "journalId": "55241327", + "type": "PAYMENT", + "createdOn": "2019-05-31T21:00:02", + "entry": "CREDIT", + "sourceToken": "act-68adaba2-42f4-4f0f-8670-81c09f319a12", + "destinationToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "amount": "45.00", + "fee": "0.00", + "currency": "USD", + "details": { + "clientPaymentId": "QIai7gcuCNsl3CGnDLTEgCkKcQlvFjKU", + "notes": "ABC1", + "payeeName": "Brendan Zachery" + } + }, + { + "journalId": "55241326", + "type": "PAYMENT", + "createdOn": "2019-05-31T21:00:01", + "entry": "CREDIT", + "sourceToken": "act-68adaba2-42f4-4f0f-8670-81c09f319a12", + "destinationToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "amount": "44.00", + "fee": "0.00", + "currency": "USD", + "details": { + "clientPaymentId": "tyRdLmOeXtikCgeX1XEdCTTSfbpVWDxt", + "notes": "ABC1", + "payeeName": "Brendan Zachery" + } + }, + { + "journalId": "55241325", + "type": "PAYMENT", + "createdOn": "2019-05-31T20:59:59", + "entry": "CREDIT", + "sourceToken": "act-68adaba2-42f4-4f0f-8670-81c09f319a12", + "destinationToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "amount": "70.00", + "fee": "0.00", + "currency": "USD", + "details": { + "clientPaymentId": "7IJPL4LhiqVTSySkBoWkcB1Os2xRBvug", + "notes": "ABC1", + "payeeName": "Brendan Zachery" + } + }, + { + "journalId": "55241324", + "type": "PAYMENT", + "createdOn": "2019-05-31T20:59:58", + "entry": "CREDIT", + "sourceToken": "act-68adaba2-42f4-4f0f-8670-81c09f319a12", + "destinationToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "amount": "20.00", + "fee": "0.00", + "currency": "USD", + "details": { + "clientPaymentId": "HByAlgikQMEg0FuHJ8LxomEiPBhbP1FA", + "notes": "ABC1", + "payeeName": "Brendan Zachery" + } + }, + { + "journalId": "55241323", + "type": "PAYMENT", + "createdOn": "2019-05-31T20:59:58", + "entry": "CREDIT", + "sourceToken": "act-68adaba2-42f4-4f0f-8670-81c09f319a12", + "destinationToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "amount": "77.00", + "fee": "0.00", + "currency": "USD", + "details": { + "clientPaymentId": "V4U2WdYWmxnm0pr3GyjO04t83MxrfXDq", + "notes": "ABC1", + "payeeName": "Brendan Zachery" + } + }, + { + "journalId": "55241322", + "type": "PAYMENT", + "createdOn": "2019-05-31T20:59:57", + "entry": "CREDIT", + "sourceToken": "act-68adaba2-42f4-4f0f-8670-81c09f319a12", + "destinationToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "amount": "6.00", + "fee": "0.00", + "currency": "USD", + "details": { + "clientPaymentId": "8beVx1bgJvwCUd5D2oGjC8ncSo6y7Nkk", + "notes": "ABC1", + "payeeName": "Brendan Zachery" + } + }, + { + "journalId": "55241321", + "type": "PAYMENT", + "createdOn": "2019-05-04T08:31:08", + "entry": "CREDIT", + "sourceToken": "act-68adaba2-42f4-4f0f-8670-81c09f319a12", + "destinationToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "amount": "14.00", + "fee": "0.00", + "currency": "USD", + "details": { + "clientPaymentId": "lLw5Rk0C7PxbFeHRqJ1k8j17KIjqh4bO", + "notes": "ABC1", + "payeeName": "Brendan Zachery" + } + }, + { + "journalId": "55241320", + "type": "PAYMENT", + "createdOn": "2019-05-04T08:31:08", + "entry": "CREDIT", + "sourceToken": "act-68adaba2-42f4-4f0f-8670-81c09f319a12", + "destinationToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "amount": "54.00", + "fee": "0.00", + "currency": "USD", + "details": { + "clientPaymentId": "uS7EsR8xs1EMAnwjKBbJSE60ULI3s33L", + "notes": "ABC1", + "payeeName": "Brendan Zachery" + } + }, + { + "journalId": "55241319", + "type": "PAYMENT", + "createdOn": "2019-05-04T08:31:08", + "entry": "CREDIT", + "sourceToken": "act-68adaba2-42f4-4f0f-8670-81c09f319a12", + "destinationToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "amount": "27.00", + "fee": "0.00", + "currency": "USD", + "details": { + "clientPaymentId": "1MPa0sDeuWr8P7Iy2pQs4Jv7yUF02SP4", + "notes": "ABC1", + "payeeName": "Brendan Zachery" + } + }, + { + "journalId": "55241318", + "type": "PAYMENT", + "createdOn": "2019-05-04T03:25:08", + "entry": "CREDIT", + "sourceToken": "act-68adaba2-42f4-4f0f-8670-81c09f319a12", + "destinationToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "amount": "8.00", + "fee": "0.00", + "currency": "USD", + "details": { + "clientPaymentId": "UL2PeLYK2VsOLtA6CTatkoSKTP7TbNXu", + "notes": "ABC1", + "payeeName": "Brendan Zachery" + } + }, + { + "journalId": "55241317", + "type": "PAYMENT", + "createdOn": "2019-05-04T03:25:08", + "entry": "CREDIT", + "sourceToken": "act-68adaba2-42f4-4f0f-8670-81c09f319a12", + "destinationToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "amount": "18.00", + "fee": "0.00", + "currency": "USD", + "details": { + "clientPaymentId": "qOdsFgE7nnXB0lAu6x5NYd7g3UPVaVLE", + "notes": "ABC1", + "payeeName": "Brendan Zachery" + } + }, + { + "journalId": "55241316", + "type": "PAYMENT", + "createdOn": "2019-05-04T03:25:08", + "entry": "CREDIT", + "sourceToken": "act-68adaba2-42f4-4f0f-8670-81c09f319a12", + "destinationToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "amount": "68.00", + "fee": "0.00", + "currency": "USD", + "details": { + "clientPaymentId": "xvGWbxlrJUfOUt4yaeUXrpkvnOPc1nOr", + "notes": "ABC1", + "payeeName": "Brendan Zachery" + } + }, + { + "journalId": "55241315", + "type": "TRANSFER_TO_BANK_ACCOUNT", + "createdOn": "2019-04-18T23:25:08", + "entry": "DEBIT", + "sourceToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "destinationToken": "trm-070124d6-778a-4886-95d9-c2e179533a42", + "amount": "78.00", + "fee": "2.00", + "currency": "USD", + "details": { + "payeeName": "Brendan Zachery", + "branchId": "021000021", + "bankAccountId": "********5888", + "bankAccountPurpose": "SAVINGS" + } + }, + { + "journalId": "55241314", + "type": "TRANSFER_TO_BANK_ACCOUNT", + "createdOn": "2019-04-18T23:25:08", + "entry": "DEBIT", + "sourceToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "destinationToken": "trm-070124d6-778a-4886-95d9-c2e179533a42", + "amount": "10.00", + "fee": "2.00", + "currency": "USD", + "details": { + "payeeName": "Brendan Zachery", + "branchId": "021000021", + "bankAccountId": "********5888", + "bankAccountPurpose": "SAVINGS" + } + }, + { + "journalId": "55241313", + "type": "TRANSFER_TO_BANK_ACCOUNT", + "createdOn": "2019-04-18T23:25:08", + "entry": "DEBIT", + "sourceToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "destinationToken": "trm-070124d6-778a-4886-95d9-c2e179533a42", + "amount": "33.00", + "fee": "2.00", + "currency": "USD", + "details": { + "payeeName": "Brendan Zachery", + "branchId": "021000021", + "bankAccountId": "********5888", + "bankAccountPurpose": "SAVINGS" + } + }, + { + "journalId": "55241312", + "type": "TRANSFER_TO_BANK_ACCOUNT", + "createdOn": "2019-04-18T22:25:08", + "entry": "DEBIT", + "sourceToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "destinationToken": "trm-070124d6-778a-4886-95d9-c2e179533a42", + "amount": "46.00", + "fee": "2.00", + "currency": "USD", + "details": { + "payeeName": "Brendan Zachery", + "branchId": "021000021", + "bankAccountId": "********5888", + "bankAccountPurpose": "SAVINGS" + } + }, + { + "journalId": "55241311", + "type": "PAYMENT", + "createdOn": "2019-04-18T22:25:08", + "entry": "CREDIT", + "sourceToken": "act-68adaba2-42f4-4f0f-8670-81c09f319a12", + "destinationToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "amount": "22.00", + "fee": "0.00", + "currency": "USD", + "details": { + "clientPaymentId": "Ffib6Cr4a1amY8NCsBIpbg055Gn5Twgl", + "notes": "ABC1", + "payeeName": "Brendan Zachery" + } + }, + { + "journalId": "55241310", + "type": "PAYMENT", + "createdOn": "2019-04-18T22:25:08", + "entry": "CREDIT", + "sourceToken": "act-68adaba2-42f4-4f0f-8670-81c09f319a12", + "destinationToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "amount": "68.00", + "fee": "0.00", + "currency": "USD", + "details": { + "clientPaymentId": "bf0W6uPSWlbCw4C4g5IknEuIxP6KArxg", + "notes": "ABC1", + "payeeName": "Brendan Zachery" + } + } + ], + "links": [ + { + "params": { + "rel": "self" + }, + "href": "https://qamaster-hyperwallet.aws.paylution.net/rest/v3/users/usr-02d381d3-bf7e-43fe-9d00-02e26b28df57/receipts?offset=0&limit=20&sortBy=-createdOn&createdAfter=2018-06-10T13%3A29%3A49" + }, + { + "params": { + "rel": "next" + }, + "href": "https://qamaster-hyperwallet.aws.paylution.net/rest/v3/users/usr-02d381d3-bf7e-43fe-9d00-02e26b28df57/receipts?offset=20&limit=20&sortBy=-createdOn&createdAfter=2018-06-10T13%3A29%3A49" + }, + { + "params": { + "rel": "last" + }, + "href": "https://qamaster-hyperwallet.aws.paylution.net/rest/v3/users/usr-02d381d3-bf7e-43fe-9d00-02e26b28df57/receipts?offset=30&limit=20&sortBy=-createdOn&createdAfter=2018-06-10T13%3A29%3A49" + } + ] +} \ No newline at end of file diff --git a/receipt/src/test/resources/receipt_list_paged_second_response.json b/receipt/src/test/resources/receipt_list_paged_second_response.json new file mode 100644 index 000000000..ea5ff7d8f --- /dev/null +++ b/receipt/src/test/resources/receipt_list_paged_second_response.json @@ -0,0 +1,202 @@ +{ + "count": 50, + "offset": 20, + "limit": 10, + "data": [ + { + "journalId": "55241309", + "type": "PAYMENT", + "createdOn": "2019-04-01T22:25:08", + "entry": "CREDIT", + "sourceToken": "act-68adaba2-42f4-4f0f-8670-81c09f319a12", + "destinationToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "amount": "31.00", + "fee": "0.00", + "currency": "USD", + "details": { + "clientPaymentId": "6gxTXpwcubH3fVRtFdQNurWOyUW1HkVX", + "notes": "ABC1", + "payeeName": "Brendan Zachery" + } + }, + { + "journalId": "55241308", + "type": "PAYMENT", + "createdOn": "2019-04-01T22:25:08", + "entry": "CREDIT", + "sourceToken": "act-68adaba2-42f4-4f0f-8670-81c09f319a12", + "destinationToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "amount": "86.00", + "fee": "0.00", + "currency": "USD", + "details": { + "clientPaymentId": "S1qT2lRll6L30mC0DFj7KcVe3mWoKDQB", + "notes": "ABC1", + "payeeName": "Brendan Zachery" + } + }, + { + "journalId": "55241307", + "type": "PAYMENT", + "createdOn": "2019-04-01T22:25:08", + "entry": "CREDIT", + "sourceToken": "act-68adaba2-42f4-4f0f-8670-81c09f319a12", + "destinationToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "amount": "71.00", + "fee": "0.00", + "currency": "USD", + "details": { + "clientPaymentId": "HtMITxyTfeCcSdhLWsQT5qkGjpucotrF", + "notes": "ABC1", + "payeeName": "Brendan Zachery" + } + }, + { + "journalId": "55241306", + "type": "PAYMENT", + "createdOn": "2019-04-01T22:25:08", + "entry": "CREDIT", + "sourceToken": "act-68adaba2-42f4-4f0f-8670-81c09f319a12", + "destinationToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "amount": "51.00", + "fee": "0.00", + "currency": "USD", + "details": { + "clientPaymentId": "khPj2gCEvgLE3DbMgIP3FrCFrdQwBltv", + "notes": "ABC1", + "payeeName": "Brendan Zachery" + } + }, + { + "journalId": "55241305", + "type": "PAYMENT", + "createdOn": "2019-04-01T22:25:08", + "entry": "CREDIT", + "sourceToken": "act-68adaba2-42f4-4f0f-8670-81c09f319a12", + "destinationToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "amount": "44.00", + "fee": "0.00", + "currency": "USD", + "details": { + "clientPaymentId": "3pqvOo05oV0uhDl27f2Qqm73jYDWNwK8", + "notes": "ABC1", + "payeeName": "Brendan Zachery" + } + }, + { + "journalId": "55241304", + "type": "TRANSFER_TO_BANK_ACCOUNT", + "createdOn": "2019-03-11T22:25:08", + "entry": "DEBIT", + "sourceToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "destinationToken": "trm-070124d6-778a-4886-95d9-c2e179533a42", + "amount": "60.00", + "fee": "2.00", + "currency": "USD", + "details": { + "payeeName": "Brendan Zachery", + "branchId": "021000021", + "bankAccountId": "********5888", + "bankAccountPurpose": "SAVINGS" + } + }, + { + "journalId": "55241303", + "type": "TRANSFER_TO_BANK_ACCOUNT", + "createdOn": "2019-03-11T22:25:08", + "entry": "DEBIT", + "sourceToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "destinationToken": "trm-070124d6-778a-4886-95d9-c2e179533a42", + "amount": "86.00", + "fee": "2.00", + "currency": "USD", + "details": { + "payeeName": "Brendan Zachery", + "branchId": "021000021", + "bankAccountId": "********5888", + "bankAccountPurpose": "SAVINGS" + } + }, + { + "journalId": "55241302", + "type": "TRANSFER_TO_BANK_ACCOUNT", + "createdOn": "2019-03-11T22:25:08", + "entry": "DEBIT", + "sourceToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "destinationToken": "trm-070124d6-778a-4886-95d9-c2e179533a42", + "amount": "74.00", + "fee": "2.00", + "currency": "USD", + "details": { + "payeeName": "Brendan Zachery", + "branchId": "021000021", + "bankAccountId": "********5888", + "bankAccountPurpose": "SAVINGS" + } + }, + { + "journalId": "55241301", + "type": "PAYMENT", + "createdOn": "2019-03-11T22:25:08", + "entry": "CREDIT", + "sourceToken": "act-68adaba2-42f4-4f0f-8670-81c09f319a12", + "destinationToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "amount": "27.00", + "fee": "0.00", + "currency": "USD", + "details": { + "clientPaymentId": "E1PCxrtc6o3UUGck3wGBWIevYgaMcIrR", + "notes": "ABC1", + "payeeName": "Brendan Zachery" + } + }, + { + "journalId": "55241300", + "type": "PAYMENT", + "createdOn": "2019-03-05T22:25:08", + "entry": "CREDIT", + "sourceToken": "act-68adaba2-42f4-4f0f-8670-81c09f319a12", + "destinationToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "amount": "33.00", + "fee": "0.00", + "currency": "USD", + "details": { + "clientPaymentId": "gyHQFLHOTH540eDlysJsSVPOJdSOSHRl", + "notes": "ABC1", + "payeeName": "Brendan Zachery" + } + } + ], + "links": [ + { + "params": { + "rel": "self" + }, + "href": "https://qamaster-hyperwallet.aws.paylution.net/rest/v3/users/usr-02d381d3-bf7e-43fe-9d00-02e26b28df57/receipts?offset=20&limit=10&sortBy=-createdOn&createdAfter=2018-06-10T13%3A29%3A49" + }, + { + "params": { + "rel": "next" + }, + "href": "https://qamaster-hyperwallet.aws.paylution.net/rest/v3/users/usr-02d381d3-bf7e-43fe-9d00-02e26b28df57/receipts?offset=30&limit=10&sortBy=-createdOn&createdAfter=2018-06-10T13%3A29%3A49" + }, + { + "params": { + "rel": "previous" + }, + "href": "https://qamaster-hyperwallet.aws.paylution.net/rest/v3/users/usr-02d381d3-bf7e-43fe-9d00-02e26b28df57/receipts?offset=10&limit=10&sortBy=-createdOn&createdAfter=2018-06-10T13%3A29%3A49" + }, + { + "params": { + "rel": "first" + }, + "href": "https://qamaster-hyperwallet.aws.paylution.net/rest/v3/users/usr-02d381d3-bf7e-43fe-9d00-02e26b28df57/receipts?offset=0&limit=10&sortBy=-createdOn&createdAfter=2018-06-10T13%3A29%3A49" + }, + { + "params": { + "rel": "last" + }, + "href": "https://qamaster-hyperwallet.aws.paylution.net/rest/v3/users/usr-02d381d3-bf7e-43fe-9d00-02e26b28df57/receipts?offset=40&limit=10&sortBy=-createdOn&createdAfter=2018-06-10T13%3A29%3A49" + } + ] +} \ No newline at end of file diff --git a/receipt/src/test/resources/receipt_list_paged_third_response.json b/receipt/src/test/resources/receipt_list_paged_third_response.json new file mode 100644 index 000000000..80b92d304 --- /dev/null +++ b/receipt/src/test/resources/receipt_list_paged_third_response.json @@ -0,0 +1,201 @@ +{ + "count": 50, + "offset": 30, + "limit": 10, + "data": [ + { + "journalId": "55241299", + "type": "PAYMENT", + "createdOn": "2019-03-05T22:25:08", + "entry": "CREDIT", + "sourceToken": "act-68adaba2-42f4-4f0f-8670-81c09f319a12", + "destinationToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "amount": "1.00", + "fee": "0.00", + "currency": "USD", + "details": { + "clientPaymentId": "UlwCsRXTdgrdFUuRTPg636Mbvn8XRGjs", + "notes": "ABC1", + "payeeName": "Brendan Zachery" + } + }, + { + "journalId": "55241298", + "type": "PAYMENT", + "createdOn": "2019-03-05T22:25:08", + "entry": "CREDIT", + "sourceToken": "act-68adaba2-42f4-4f0f-8670-81c09f319a12", + "destinationToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "amount": "13.00", + "fee": "0.00", + "currency": "USD", + "details": { + "clientPaymentId": "tfM0IjyVMBRGqmsD1dEO3Fy8rK2QUoSm", + "notes": "ABC1", + "payeeName": "Brendan Zachery" + } + }, + { + "journalId": "55241297", + "type": "PAYMENT", + "createdOn": "2019-03-05T22:25:08", + "entry": "CREDIT", + "sourceToken": "act-68adaba2-42f4-4f0f-8670-81c09f319a12", + "destinationToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "amount": "4.00", + "fee": "0.00", + "currency": "USD", + "details": { + "clientPaymentId": "HnttPuohg4cnUbfMJ6vlhcELeRhWwOhT", + "notes": "ABC1", + "payeeName": "Brendan Zachery" + } + }, + { + "journalId": "55241296", + "type": "PAYMENT", + "createdOn": "2019-02-05T12:29:08", + "entry": "CREDIT", + "sourceToken": "act-68adaba2-42f4-4f0f-8670-81c09f319a12", + "destinationToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "amount": "27.00", + "fee": "0.00", + "currency": "USD", + "details": { + "clientPaymentId": "itps4wsLu1ifsYHBEmD2g5ti185lEEjr", + "notes": "ABC1", + "payeeName": "Brendan Zachery" + } + }, + { + "journalId": "55241295", + "type": "PAYMENT", + "createdOn": "2019-02-05T12:29:08", + "entry": "CREDIT", + "sourceToken": "act-68adaba2-42f4-4f0f-8670-81c09f319a12", + "destinationToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "amount": "77.00", + "fee": "0.00", + "currency": "USD", + "details": { + "clientPaymentId": "CRRWrHBQKPBui4nfsDmXnohiaFheOp5l", + "notes": "ABC1", + "payeeName": "Brendan Zachery" + } + }, + { + "journalId": "55241294", + "type": "PAYMENT", + "createdOn": "2019-02-05T12:29:08", + "entry": "CREDIT", + "sourceToken": "act-68adaba2-42f4-4f0f-8670-81c09f319a12", + "destinationToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "amount": "71.00", + "fee": "0.00", + "currency": "USD", + "details": { + "clientPaymentId": "VYHB8eQswywLoCBDgesOwfqh5T55b3mB", + "notes": "ABC1", + "payeeName": "Brendan Zachery" + } + }, + { + "journalId": "55241293", + "type": "PAYMENT", + "createdOn": "2019-02-05T12:29:08", + "entry": "CREDIT", + "sourceToken": "act-68adaba2-42f4-4f0f-8670-81c09f319a12", + "destinationToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "amount": "72.00", + "fee": "0.00", + "currency": "USD", + "details": { + "clientPaymentId": "QDLwuItkjGNPVwQNOfiLrjeJpDxmEiWt", + "notes": "ABC1", + "payeeName": "Brendan Zachery" + } + }, + { + "journalId": "55241292", + "type": "PAYMENT", + "createdOn": "2019-02-05T12:29:08", + "entry": "CREDIT", + "sourceToken": "act-68adaba2-42f4-4f0f-8670-81c09f319a12", + "destinationToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "amount": "37.00", + "fee": "0.00", + "currency": "USD", + "details": { + "clientPaymentId": "N6gwhx1BhxXs5ug6bH3xXWXB6p7gixT4", + "notes": "ABC1", + "payeeName": "Brendan Zachery" + } + }, + { + "journalId": "55241291", + "type": "TRANSFER_TO_BANK_ACCOUNT", + "createdOn": "2019-01-05T20:29:08", + "entry": "DEBIT", + "sourceToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "destinationToken": "trm-cc13b0b0-5f4b-4c99-baed-eb16c8952f46", + "amount": "35.00", + "fee": "2.00", + "currency": "USD", + "details": { + "payeeName": "Brendan Zachery", + "branchId": "021000021", + "bankAccountId": "******9129", + "bankAccountPurpose": "SAVINGS" + } + }, + { + "journalId": "55241290", + "type": "TRANSFER_TO_BANK_ACCOUNT", + "createdOn": "2019-01-05T20:29:08", + "entry": "DEBIT", + "sourceToken": "usr-02d381d3-bf7e-43fe-9d00-02e26b28df57", + "destinationToken": "trm-cc13b0b0-5f4b-4c99-baed-eb16c8952f46", + "amount": "22.00", + "fee": "2.00", + "currency": "USD", + "details": { + "payeeName": "Brendan Zachery", + "branchId": "021000021", + "bankAccountId": "******9129", + "bankAccountPurpose": "SAVINGS" + } + } + ], + "links": [ + { + "params": { + "rel": "self" + }, + "href": "https://qamaster-hyperwallet.aws.paylution.net/rest/v3/users/usr-02d381d3-bf7e-43fe-9d00-02e26b28df57/receipts?offset=30&limit=10&sortBy=-createdOn&createdAfter=2018-06-10T13%3A29%3A49" + }, + { + "params": { + "rel": "next" + }, + "href": "https://qamaster-hyperwallet.aws.paylution.net/rest/v3/users/usr-02d381d3-bf7e-43fe-9d00-02e26b28df57/receipts?offset=40&limit=10&sortBy=-createdOn&createdAfter=2018-06-10T13%3A29%3A49" + }, + { + "params": { + "rel": "previous" + }, + "href": "https://qamaster-hyperwallet.aws.paylution.net/rest/v3/users/usr-02d381d3-bf7e-43fe-9d00-02e26b28df57/receipts?offset=20&limit=10&sortBy=-createdOn&createdAfter=2018-06-10T13%3A29%3A49" + }, + { + "params": { + "rel": "first" + }, + "href": "https://qamaster-hyperwallet.aws.paylution.net/rest/v3/users/usr-02d381d3-bf7e-43fe-9d00-02e26b28df57/receipts?offset=0&limit=10&sortBy=-createdOn&createdAfter=2018-06-10T13%3A29%3A49" + }, + { + "params": { + "rel": "last" + }, + "href": "https://qamaster-hyperwallet.aws.paylution.net/rest/v3/users/usr-02d381d3-bf7e-43fe-9d00-02e26b28df57/receipts?offset=40&limit=10&sortBy=-createdOn&createdAfter=2018-06-10T13%3A29%3A49" + } + ] +} \ No newline at end of file From 5607c9424bb9663ddfaa55823cde5047499cc3f6 Mon Sep 17 00:00:00 2001 From: Anna <48258136+azakrevska-epam@users.noreply.github.com> Date: Fri, 14 Jun 2019 00:49:08 +0300 Subject: [PATCH 08/10] HW-53463, HW-53464. Updated createTransferMethod(Wire Account) and tests (#38) --- .../TransferMethodRepositoryImpl.java | 3 + .../AddTransferMethodFragment.java | 8 +++ .../TransferMethodRepositoryImplTest.java | 71 +++++++++++++++++++ 3 files changed, 82 insertions(+) diff --git a/ui/src/main/java/com/hyperwallet/android/ui/repository/TransferMethodRepositoryImpl.java b/ui/src/main/java/com/hyperwallet/android/ui/repository/TransferMethodRepositoryImpl.java index 902971023..17aab2028 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/repository/TransferMethodRepositoryImpl.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/repository/TransferMethodRepositoryImpl.java @@ -22,6 +22,7 @@ import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.BANK_ACCOUNT; import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.BANK_CARD; import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.PAYPAL_ACCOUNT; +import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.WIRE_ACCOUNT; import android.os.Handler; @@ -54,6 +55,7 @@ public void createTransferMethod(@NonNull final HyperwalletTransferMethod transf LoadTransferMethodCallback callback) { switch (transferMethod.getField(TYPE)) { case BANK_ACCOUNT: + case WIRE_ACCOUNT: createBankAccount(transferMethod, callback); break; case BANK_CARD: @@ -96,6 +98,7 @@ public void deactivateTransferMethod(@NonNull final HyperwalletTransferMethod tr @NonNull final DeactivateTransferMethodCallback callback) { switch (transferMethod.getField(TYPE)) { case BANK_ACCOUNT: + case WIRE_ACCOUNT: deactivateBankAccount(transferMethod, callback); break; case BANK_CARD: diff --git a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/AddTransferMethodFragment.java b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/AddTransferMethodFragment.java index 2fb5203bc..53e290aa9 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/AddTransferMethodFragment.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/AddTransferMethodFragment.java @@ -23,6 +23,7 @@ import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.BANK_ACCOUNT; import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.BANK_CARD; import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.PAYPAL_ACCOUNT; +import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.WIRE_ACCOUNT; import android.app.Activity; import android.content.Context; @@ -509,6 +510,13 @@ private void triggerSubmit() { .transferMethodCurrency(mCurrency) .build(); break; + case WIRE_ACCOUNT: + mTransferMethod = new HyperwalletBankAccount.Builder() + .transferMethodCountry(mCountry) + .transferMethodCurrency(mCurrency) + .transferMethodType(WIRE_ACCOUNT) + .build(); + break; default: mTransferMethod = new HyperwalletTransferMethod(); mTransferMethod.setField(TRANSFER_METHOD_COUNTRY, mCountry); diff --git a/ui/src/test/java/com/hyperwallet/android/ui/repository/TransferMethodRepositoryImplTest.java b/ui/src/test/java/com/hyperwallet/android/ui/repository/TransferMethodRepositoryImplTest.java index 334ad2044..59c3d3ee9 100644 --- a/ui/src/test/java/com/hyperwallet/android/ui/repository/TransferMethodRepositoryImplTest.java +++ b/ui/src/test/java/com/hyperwallet/android/ui/repository/TransferMethodRepositoryImplTest.java @@ -558,4 +558,75 @@ public Object answer(InvocationOnMock invocation) { // assert assertThat(mErrorsArgumentCaptor.getValue().getErrors(), hasItem(returnedError)); } + + @Test + public void testCreateTransferMethod_wireAccountWithSuccess() { + HyperwalletBankAccount bankAccount = new HyperwalletBankAccount + .Builder("US", "USD", "1411413412") + .transferMethodType(HyperwalletTransferMethod.TransferMethodTypes.WIRE_ACCOUNT) + .build(); + + doAnswer(new Answer() { + @Override + public Object answer(InvocationOnMock invocation) { + HyperwalletListener listener = (HyperwalletListener) invocation.getArguments()[1]; + HyperwalletBankAccount returnedBank = new HyperwalletBankAccount + .Builder("US", "USD", "1411413412") + .bankName("Mock Bank Response") + .transferMethodType(HyperwalletTransferMethod.TransferMethodTypes.WIRE_ACCOUNT) + .build(); + listener.onSuccess(returnedBank); + return listener; + } + }).when(mHyperwallet).createBankAccount(any(HyperwalletBankAccount.class), + ArgumentMatchers.>any()); + + // test + mTransferMethodRepository.createTransferMethod(bankAccount, mLoadTransferMethodCallback); + + verify(mLoadTransferMethodCallback).onTransferMethodLoaded(mBankAccountArgumentCaptor.capture()); + verify(mLoadTransferMethodCallback, never()).onError(any(HyperwalletErrors.class)); + + HyperwalletBankAccount transferMethod = mBankAccountArgumentCaptor.getValue(); + assertThat(transferMethod, is(notNullValue())); + assertThat(transferMethod.getField(TYPE), is(HyperwalletTransferMethod.TransferMethodTypes.WIRE_ACCOUNT)); + assertThat(transferMethod.getField(BANK_NAME), is("Mock Bank Response")); + assertThat(transferMethod.getField(TRANSFER_METHOD_COUNTRY), is("US")); + assertThat(transferMethod.getField(TRANSFER_METHOD_CURRENCY), is("USD")); + assertThat(transferMethod.getField(BANK_ACCOUNT_ID), is("1411413412")); + } + + @Test + public void testDeactivateTransferMethod_wireAccountWithSuccess() { + HyperwalletBankAccount bankAccount = new HyperwalletBankAccount + .Builder("CA", "CAD", "3423423432") + .transferMethodType(HyperwalletTransferMethod.TransferMethodTypes.WIRE_ACCOUNT) + .token("trm-123") + .build(); + bankAccount.setField(STATUS, HyperwalletStatusTransition.StatusDefinition.ACTIVATED); + doAnswer(new Answer() { + @Override + public Object answer(InvocationOnMock invocation) { + HyperwalletStatusTransition statusTransition = new HyperwalletStatusTransition(DE_ACTIVATED); + statusTransition.setNotes("Closing this account."); + HyperwalletListener listener = (HyperwalletListener) invocation.getArguments()[2]; + listener.onSuccess(statusTransition); + return listener; + } + }).when(mHyperwallet).deactivateBankAccount(anyString(), ArgumentMatchers.isNull(), + ArgumentMatchers.>any()); + + // test + mTransferMethodRepository.deactivateTransferMethod(bankAccount, mDeactivateTransferMethodCallback); + + verify(mDeactivateTransferMethodCallback).onTransferMethodDeactivated( + mStatusTransitionArgumentCaptor.capture()); + verify(mDeactivateTransferMethodCallback, never()).onError(any(HyperwalletErrors.class)); + + HyperwalletStatusTransition statusTransition = mStatusTransitionArgumentCaptor.getValue(); + assertThat(statusTransition, is(notNullValue())); + assertThat(statusTransition.getTransition(), is(DE_ACTIVATED)); + assertThat(statusTransition.getNotes(), is("Closing this account.")); + } + } \ No newline at end of file From 4b8574e74766cdd3028b03b80a6c7ce06890cfd8 Mon Sep 17 00:00:00 2001 From: vshcherbyna-epam <48257687+vshcherbyna-epam@users.noreply.github.com> Date: Sat, 15 Jun 2019 01:08:21 +0300 Subject: [PATCH 09/10] HW-53384: Update UI group id (#40) * HW-53384: Update UI group id --- README.md | 2 +- build.gradle | 2 +- common/build.gradle | 2 +- common/src/main/AndroidManifest.xml | 2 +- .../{ => ui}/common/util/DateUtils.java | 2 +- .../common/util/EspressoIdlingResource.java | 2 +- .../view/HorizontalDividerItemDecorator.java | 4 +- .../error/DefaultErrorDialogFragment.java | 4 +- .../DefaultErrorDialogFragmentContract.java | 2 +- .../DefaultErrorDialogFragmentPresenter.java | 2 +- .../view/error/OnNetworkErrorCallback.java | 2 +- .../{ => ui}/common/viewmodel/Event.java | 2 +- .../{ => ui}/common/util/DateUtilsTest.java | 2 +- ...faultErrorDialogFragmentPresenterTest.java | 4 +- receipt/build.gradle | 4 +- receipt/src/androidTest/AndroidManifest.xml | 2 +- .../HyperwalletExternalResourceManager.java | 73 ------- .../rule/HyperwalletMockWebServer.java | 115 ----------- .../{ => ui}/receipt/ListReceiptsTest.java | 20 +- .../android/util/EspressoUtils.java | 187 ------------------ .../android/util/NestedScrollToAction.java | 41 ---- .../util/RecyclerViewCountAssertion.java | 30 --- .../util/TestAuthenticationProvider.java | 51 ----- receipt/src/main/AndroidManifest.xml | 2 +- .../receipt/repository/ReceiptDataSource.java | 4 +- .../repository/ReceiptDataSourceFactory.java | 2 +- .../receipt/repository/ReceiptRepository.java | 4 +- .../repository/ReceiptRepositoryFactory.java | 2 +- .../repository/ReceiptRepositoryImpl.java | 4 +- .../receipt/view/ListReceiptActivity.java | 14 +- .../receipt/view/ListReceiptFragment.java | 8 +- .../view/ReceiptItemDividerDecorator.java | 4 +- .../viewmodel/ListReceiptViewModel.java | 6 +- .../ReceiptDataSourceFactoryTest.java | 2 +- .../repository/ReceiptDataSourceTest.java | 2 +- .../ReceiptRepositoryFactoryTest.java | 2 +- .../HyperwalletExternalResourceManager.java | 0 ui/build.gradle | 4 +- ui/src/androidTest/AndroidManifest.xml | 2 +- ...yperwalletInstrumentedTestApplication.java | 31 --- ...yperwalletInstrumentedTestApplication.java | 2 +- .../HyperwalletExternalResourceManager.java | 2 +- .../rule/HyperwalletMockWebServer.java | 2 +- .../AddTransferMethodTest.java | 19 +- .../transfermethod}/BankAccountTest.java | 25 ++- .../transfermethod}/BankCardTest.java | 21 +- .../ListTransferMethodTest.java | 17 +- .../ui => ui/transfermethod}/PayPalTest.java | 21 +- .../SelectTransferMethodTest.java | 19 +- .../android/{ => ui}/util/EspressoUtils.java | 2 +- .../{ => ui}/util/NestedScrollToAction.java | 2 +- .../util/RecyclerViewCountAssertion.java | 2 +- .../util/TestAuthenticationProvider.java | 2 +- ui/src/main/AndroidManifest.xml | 2 +- .../hyperwallet/android/ui/HyperwalletUi.java | 2 +- ...sferMethodConfigurationRepositoryImpl.java | 3 +- .../AddTransferMethodActivity.java | 6 +- .../AddTransferMethodFragment.java | 2 +- .../ui/transfermethod/FeeFormatter.java | 2 +- .../ListTransferMethodActivity.java | 6 +- .../ListTransferMethodFragment.java | 4 +- .../SelectTransferMethodActivity.java | 6 +- .../SelectTransferMethodFragment.java | 4 +- ...thodConfirmDeactivationDialogFragment.java | 2 +- .../transfermethod/TransferMethodUtils.java | 2 +- .../view/CountrySelectionDialogFragment.java | 2 +- .../view/CurrencySelectionDialogFragment.java | 2 +- .../ui/view/WidgetDateDialogFragment.java | 2 +- .../view/WidgetSelectionDialogFragment.java | 2 +- .../android/ui/view/widget/DateWidget.java | 2 +- .../ui/view/widget/DefaultAccountWidget.java | 2 +- .../ui/view/widget/ExpiryDateWidget.java | 2 +- .../android/ui/view/widget/NumberWidget.java | 2 +- .../android/ui/view/widget/PhoneWidget.java | 2 +- .../ui/view/widget/SelectionWidget.java | 2 +- .../android/ui/view/widget/TextWidget.java | 2 +- ui/src/main/res/values/strings.xml | 2 +- .../ui/transfermethod/FeeFormatterTest.java | 2 +- .../TransferMethodUtilsTest.java | 2 +- 79 files changed, 160 insertions(+), 695 deletions(-) rename common/src/main/java/com/hyperwallet/android/{ => ui}/common/util/DateUtils.java (99%) rename common/src/main/java/com/hyperwallet/android/{ => ui}/common/util/EspressoIdlingResource.java (92%) rename common/src/main/java/com/hyperwallet/android/{ => ui}/common/view/HorizontalDividerItemDecorator.java (98%) rename common/src/main/java/com/hyperwallet/android/{ => ui}/common/view/error/DefaultErrorDialogFragment.java (98%) rename common/src/main/java/com/hyperwallet/android/{ => ui}/common/view/error/DefaultErrorDialogFragmentContract.java (96%) rename common/src/main/java/com/hyperwallet/android/{ => ui}/common/view/error/DefaultErrorDialogFragmentPresenter.java (98%) rename common/src/main/java/com/hyperwallet/android/{ => ui}/common/view/error/OnNetworkErrorCallback.java (82%) rename common/src/main/java/com/hyperwallet/android/{ => ui}/common/viewmodel/Event.java (97%) rename common/src/test/java/com/hyperwallet/android/{ => ui}/common/util/DateUtilsTest.java (97%) rename common/src/test/java/com/hyperwallet/android/{ => ui}/common/view/error/DefaultErrorDialogFragmentPresenterTest.java (96%) delete mode 100644 receipt/src/androidTest/java/com/hyperwallet/android/rule/HyperwalletExternalResourceManager.java delete mode 100644 receipt/src/androidTest/java/com/hyperwallet/android/rule/HyperwalletMockWebServer.java rename receipt/src/androidTest/java/com/hyperwallet/android/{ => ui}/receipt/ListReceiptsTest.java (94%) delete mode 100644 receipt/src/androidTest/java/com/hyperwallet/android/util/EspressoUtils.java delete mode 100644 receipt/src/androidTest/java/com/hyperwallet/android/util/NestedScrollToAction.java delete mode 100644 receipt/src/androidTest/java/com/hyperwallet/android/util/RecyclerViewCountAssertion.java delete mode 100644 receipt/src/androidTest/java/com/hyperwallet/android/util/TestAuthenticationProvider.java rename receipt/src/main/java/com/hyperwallet/android/{ => ui}/receipt/repository/ReceiptDataSource.java (98%) rename receipt/src/main/java/com/hyperwallet/android/{ => ui}/receipt/repository/ReceiptDataSourceFactory.java (97%) rename receipt/src/main/java/com/hyperwallet/android/{ => ui}/receipt/repository/ReceiptRepository.java (94%) rename receipt/src/main/java/com/hyperwallet/android/{ => ui}/receipt/repository/ReceiptRepositoryFactory.java (97%) rename receipt/src/main/java/com/hyperwallet/android/{ => ui}/receipt/repository/ReceiptRepositoryImpl.java (96%) rename receipt/src/main/java/com/hyperwallet/android/{ => ui}/receipt/view/ListReceiptActivity.java (91%) rename receipt/src/main/java/com/hyperwallet/android/{ => ui}/receipt/view/ListReceiptFragment.java (98%) rename receipt/src/main/java/com/hyperwallet/android/{ => ui}/receipt/view/ReceiptItemDividerDecorator.java (97%) rename receipt/src/main/java/com/hyperwallet/android/{ => ui}/receipt/viewmodel/ListReceiptViewModel.java (95%) rename receipt/src/test/java/com/hyperwallet/android/{ => ui}/receipt/repository/ReceiptDataSourceFactoryTest.java (95%) rename receipt/src/test/java/com/hyperwallet/android/{ => ui}/receipt/repository/ReceiptDataSourceTest.java (99%) rename receipt/src/test/java/com/hyperwallet/android/{ => ui}/receipt/repository/ReceiptRepositoryFactoryTest.java (96%) rename receipt/src/test/java/com/hyperwallet/android/{ => ui}/rule/HyperwalletExternalResourceManager.java (100%) delete mode 100644 ui/src/androidTest/java/com/hyperwallet/android/HyperwalletInstrumentedTestApplication.java rename {receipt/src/androidTest/java/com/hyperwallet/android => ui/src/androidTest/java/com/hyperwallet/android/ui}/HyperwalletInstrumentedTestApplication.java (95%) rename ui/src/androidTest/java/com/hyperwallet/android/{ => ui}/rule/HyperwalletExternalResourceManager.java (98%) rename ui/src/androidTest/java/com/hyperwallet/android/{ => ui}/rule/HyperwalletMockWebServer.java (98%) rename ui/src/androidTest/java/com/hyperwallet/android/{transfermethod/ui => ui/transfermethod}/AddTransferMethodTest.java (93%) rename ui/src/androidTest/java/com/hyperwallet/android/{transfermethod/ui => ui/transfermethod}/BankAccountTest.java (96%) rename ui/src/androidTest/java/com/hyperwallet/android/{transfermethod/ui => ui/transfermethod}/BankCardTest.java (95%) rename ui/src/androidTest/java/com/hyperwallet/android/{transfermethod/ui => ui/transfermethod}/ListTransferMethodTest.java (97%) rename ui/src/androidTest/java/com/hyperwallet/android/{transfermethod/ui => ui/transfermethod}/PayPalTest.java (93%) rename ui/src/androidTest/java/com/hyperwallet/android/{transfermethod/ui => ui/transfermethod}/SelectTransferMethodTest.java (97%) rename ui/src/androidTest/java/com/hyperwallet/android/{ => ui}/util/EspressoUtils.java (99%) rename ui/src/androidTest/java/com/hyperwallet/android/{ => ui}/util/NestedScrollToAction.java (96%) rename ui/src/androidTest/java/com/hyperwallet/android/{ => ui}/util/RecyclerViewCountAssertion.java (95%) rename ui/src/androidTest/java/com/hyperwallet/android/{ => ui}/util/TestAuthenticationProvider.java (97%) diff --git a/README.md b/README.md index 3923e8130..96ba8f126 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Note that this SDK is geared towards those who need both backend data and UI fea To install Hyperwallet UI SDK, you just need to add the dependency into your build.gradle file in Android Studio (or Gradle). For example: ```bash -api 'com.hyperwallet.android:ui-sdk:1.0.0-beta02' +api 'com.hyperwallet.android.ui:ui-sdk:1.0.0-beta02' ``` ## Initialization diff --git a/build.gradle b/build.gradle index 4cfcc4791..baab4fd0d 100644 --- a/build.gradle +++ b/build.gradle @@ -31,7 +31,7 @@ allprojects { subprojects { ext { - hyperwalletGroupId = 'com.hyperwallet.android' + hyperwalletGroupId = 'com.hyperwallet.android.ui' compileVersion = 28 minVersion = 21 diff --git a/common/build.gradle b/common/build.gradle index e4df818b5..cf60c3f49 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -81,7 +81,7 @@ sonarqube { properties { def libraries = project.android.sdkDirectory.getPath() + "/platforms/android-28/android.jar" property "sonar.sources", "src/main/java" - property "sonar.binaries", "build/intermediates/javac/release/compileReleaseJavaWithJavac/classes/com/hyperwallet/android" + property "sonar.binaries", "build/intermediates/javac/release/compileReleaseJavaWithJavac/classes/com/hyperwallet/android/ui" property "sonar.libraries", libraries property "sonar.projectName", "android-ui-sdk-common" } diff --git a/common/src/main/AndroidManifest.xml b/common/src/main/AndroidManifest.xml index 72af9106f..414a3f924 100644 --- a/common/src/main/AndroidManifest.xml +++ b/common/src/main/AndroidManifest.xml @@ -1,2 +1,2 @@ + package="com.hyperwallet.android.ui.common"/> diff --git a/common/src/main/java/com/hyperwallet/android/common/util/DateUtils.java b/common/src/main/java/com/hyperwallet/android/ui/common/util/DateUtils.java similarity index 99% rename from common/src/main/java/com/hyperwallet/android/common/util/DateUtils.java rename to common/src/main/java/com/hyperwallet/android/ui/common/util/DateUtils.java index 7fd65e5aa..56ce6cc88 100644 --- a/common/src/main/java/com/hyperwallet/android/common/util/DateUtils.java +++ b/common/src/main/java/com/hyperwallet/android/ui/common/util/DateUtils.java @@ -14,7 +14,7 @@ * 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.common.util; +package com.hyperwallet.android.ui.common.util; import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; diff --git a/common/src/main/java/com/hyperwallet/android/common/util/EspressoIdlingResource.java b/common/src/main/java/com/hyperwallet/android/ui/common/util/EspressoIdlingResource.java similarity index 92% rename from common/src/main/java/com/hyperwallet/android/common/util/EspressoIdlingResource.java rename to common/src/main/java/com/hyperwallet/android/ui/common/util/EspressoIdlingResource.java index 92e6cf3a4..56c870127 100644 --- a/common/src/main/java/com/hyperwallet/android/common/util/EspressoIdlingResource.java +++ b/common/src/main/java/com/hyperwallet/android/ui/common/util/EspressoIdlingResource.java @@ -1,4 +1,4 @@ -package com.hyperwallet.android.common.util; +package com.hyperwallet.android.ui.common.util; import androidx.test.espresso.IdlingResource; import androidx.test.espresso.idling.CountingIdlingResource; diff --git a/common/src/main/java/com/hyperwallet/android/common/view/HorizontalDividerItemDecorator.java b/common/src/main/java/com/hyperwallet/android/ui/common/view/HorizontalDividerItemDecorator.java similarity index 98% rename from common/src/main/java/com/hyperwallet/android/common/view/HorizontalDividerItemDecorator.java rename to common/src/main/java/com/hyperwallet/android/ui/common/view/HorizontalDividerItemDecorator.java index 3e9d3777f..86d294933 100644 --- a/common/src/main/java/com/hyperwallet/android/common/view/HorizontalDividerItemDecorator.java +++ b/common/src/main/java/com/hyperwallet/android/ui/common/view/HorizontalDividerItemDecorator.java @@ -14,7 +14,7 @@ * 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.common.view; +package com.hyperwallet.android.ui.common.view; import android.content.Context; import android.graphics.Canvas; @@ -26,7 +26,7 @@ import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; -import com.hyperwallet.android.common.R; +import com.hyperwallet.android.ui.common.R; public class HorizontalDividerItemDecorator extends RecyclerView.ItemDecoration { diff --git a/common/src/main/java/com/hyperwallet/android/common/view/error/DefaultErrorDialogFragment.java b/common/src/main/java/com/hyperwallet/android/ui/common/view/error/DefaultErrorDialogFragment.java similarity index 98% rename from common/src/main/java/com/hyperwallet/android/common/view/error/DefaultErrorDialogFragment.java rename to common/src/main/java/com/hyperwallet/android/ui/common/view/error/DefaultErrorDialogFragment.java index b3ea55029..17f2db87d 100644 --- a/common/src/main/java/com/hyperwallet/android/common/view/error/DefaultErrorDialogFragment.java +++ b/common/src/main/java/com/hyperwallet/android/ui/common/view/error/DefaultErrorDialogFragment.java @@ -14,7 +14,7 @@ * 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.common.view.error; +package com.hyperwallet.android.ui.common.view.error; import static com.hyperwallet.android.ExceptionMapper.EC_AUTHENTICATION_TOKEN_PROVIDER_EXCEPTION; import static com.hyperwallet.android.ExceptionMapper.EC_IO_EXCEPTION; @@ -33,8 +33,8 @@ import androidx.fragment.app.DialogFragment; import androidx.fragment.app.FragmentManager; -import com.hyperwallet.android.common.R; import com.hyperwallet.android.model.HyperwalletError; +import com.hyperwallet.android.ui.common.R; import java.util.ArrayList; import java.util.List; diff --git a/common/src/main/java/com/hyperwallet/android/common/view/error/DefaultErrorDialogFragmentContract.java b/common/src/main/java/com/hyperwallet/android/ui/common/view/error/DefaultErrorDialogFragmentContract.java similarity index 96% rename from common/src/main/java/com/hyperwallet/android/common/view/error/DefaultErrorDialogFragmentContract.java rename to common/src/main/java/com/hyperwallet/android/ui/common/view/error/DefaultErrorDialogFragmentContract.java index 6fd3db51c..2cfc0e219 100644 --- a/common/src/main/java/com/hyperwallet/android/common/view/error/DefaultErrorDialogFragmentContract.java +++ b/common/src/main/java/com/hyperwallet/android/ui/common/view/error/DefaultErrorDialogFragmentContract.java @@ -14,7 +14,7 @@ * 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.common.view.error; +package com.hyperwallet.android.ui.common.view.error; import android.content.res.Resources; diff --git a/common/src/main/java/com/hyperwallet/android/common/view/error/DefaultErrorDialogFragmentPresenter.java b/common/src/main/java/com/hyperwallet/android/ui/common/view/error/DefaultErrorDialogFragmentPresenter.java similarity index 98% rename from common/src/main/java/com/hyperwallet/android/common/view/error/DefaultErrorDialogFragmentPresenter.java rename to common/src/main/java/com/hyperwallet/android/ui/common/view/error/DefaultErrorDialogFragmentPresenter.java index b9f493359..080209765 100644 --- a/common/src/main/java/com/hyperwallet/android/common/view/error/DefaultErrorDialogFragmentPresenter.java +++ b/common/src/main/java/com/hyperwallet/android/ui/common/view/error/DefaultErrorDialogFragmentPresenter.java @@ -14,7 +14,7 @@ * 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.common.view.error; +package com.hyperwallet.android.ui.common.view.error; import static com.hyperwallet.android.ExceptionMapper.EC_AUTHENTICATION_TOKEN_PROVIDER_EXCEPTION; import static com.hyperwallet.android.ExceptionMapper.EC_IO_EXCEPTION; diff --git a/common/src/main/java/com/hyperwallet/android/common/view/error/OnNetworkErrorCallback.java b/common/src/main/java/com/hyperwallet/android/ui/common/view/error/OnNetworkErrorCallback.java similarity index 82% rename from common/src/main/java/com/hyperwallet/android/common/view/error/OnNetworkErrorCallback.java rename to common/src/main/java/com/hyperwallet/android/ui/common/view/error/OnNetworkErrorCallback.java index a6822c545..e537157a9 100644 --- a/common/src/main/java/com/hyperwallet/android/common/view/error/OnNetworkErrorCallback.java +++ b/common/src/main/java/com/hyperwallet/android/ui/common/view/error/OnNetworkErrorCallback.java @@ -1,4 +1,4 @@ -package com.hyperwallet.android.common.view.error; +package com.hyperwallet.android.ui.common.view.error; import java.util.List; diff --git a/common/src/main/java/com/hyperwallet/android/common/viewmodel/Event.java b/common/src/main/java/com/hyperwallet/android/ui/common/viewmodel/Event.java similarity index 97% rename from common/src/main/java/com/hyperwallet/android/common/viewmodel/Event.java rename to common/src/main/java/com/hyperwallet/android/ui/common/viewmodel/Event.java index a07aab0e1..0914c82f5 100644 --- a/common/src/main/java/com/hyperwallet/android/common/viewmodel/Event.java +++ b/common/src/main/java/com/hyperwallet/android/ui/common/viewmodel/Event.java @@ -14,7 +14,7 @@ * 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.common.viewmodel; +package com.hyperwallet.android.ui.common.viewmodel; import androidx.annotation.NonNull; import androidx.annotation.Nullable; diff --git a/common/src/test/java/com/hyperwallet/android/common/util/DateUtilsTest.java b/common/src/test/java/com/hyperwallet/android/ui/common/util/DateUtilsTest.java similarity index 97% rename from common/src/test/java/com/hyperwallet/android/common/util/DateUtilsTest.java rename to common/src/test/java/com/hyperwallet/android/ui/common/util/DateUtilsTest.java index 27102325b..4b599078b 100644 --- a/common/src/test/java/com/hyperwallet/android/common/util/DateUtilsTest.java +++ b/common/src/test/java/com/hyperwallet/android/ui/common/util/DateUtilsTest.java @@ -1,4 +1,4 @@ -package com.hyperwallet.android.common.util; +package com.hyperwallet.android.ui.common.util; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; diff --git a/common/src/test/java/com/hyperwallet/android/common/view/error/DefaultErrorDialogFragmentPresenterTest.java b/common/src/test/java/com/hyperwallet/android/ui/common/view/error/DefaultErrorDialogFragmentPresenterTest.java similarity index 96% rename from common/src/test/java/com/hyperwallet/android/common/view/error/DefaultErrorDialogFragmentPresenterTest.java rename to common/src/test/java/com/hyperwallet/android/ui/common/view/error/DefaultErrorDialogFragmentPresenterTest.java index aa3848d07..39eb47085 100644 --- a/common/src/test/java/com/hyperwallet/android/common/view/error/DefaultErrorDialogFragmentPresenterTest.java +++ b/common/src/test/java/com/hyperwallet/android/ui/common/view/error/DefaultErrorDialogFragmentPresenterTest.java @@ -1,4 +1,4 @@ -package com.hyperwallet.android.common.view.error; +package com.hyperwallet.android.ui.common.view.error; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; @@ -15,8 +15,8 @@ import android.content.res.Resources; -import com.hyperwallet.android.common.R; import com.hyperwallet.android.model.HyperwalletError; +import com.hyperwallet.android.ui.common.R; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/receipt/build.gradle b/receipt/build.gradle index 6aa8d9d42..03133faa3 100644 --- a/receipt/build.gradle +++ b/receipt/build.gradle @@ -60,7 +60,7 @@ publishing { configurations.implementation.allDependencies.each { def dependencyNode = dependenciesNode.appendNode('dependency') if (it.group == "hyperwallet-android-ui-sdk") { - dependencyNode.appendNode('groupId', "com.hyperwallet.android") + dependencyNode.appendNode('groupId', "com.hyperwallet.android.ui") } else { dependencyNode.appendNode('groupId', it.group) } @@ -104,7 +104,7 @@ sonarqube { properties { def libraries = project.android.sdkDirectory.getPath() + "/platforms/android-28/android.jar" property "sonar.sources", "src/main/java" - property "sonar.binaries", "build/intermediates/javac/release/compileReleaseJavaWithJavac/classes/com/hyperwallet/android" + property "sonar.binaries", "build/intermediates/javac/release/compileReleaseJavaWithJavac/classes/com/hyperwallet/android/ui" property "sonar.libraries", libraries property "sonar.projectName", "android-ui-sdk-receipt" } diff --git a/receipt/src/androidTest/AndroidManifest.xml b/receipt/src/androidTest/AndroidManifest.xml index 8495adb45..eb1e37113 100644 --- a/receipt/src/androidTest/AndroidManifest.xml +++ b/receipt/src/androidTest/AndroidManifest.xml @@ -1,6 +1,6 @@ + package="com.hyperwallet.android.ui.receipt.test"> diff --git a/receipt/src/androidTest/java/com/hyperwallet/android/rule/HyperwalletExternalResourceManager.java b/receipt/src/androidTest/java/com/hyperwallet/android/rule/HyperwalletExternalResourceManager.java deleted file mode 100644 index e7e546063..000000000 --- a/receipt/src/androidTest/java/com/hyperwallet/android/rule/HyperwalletExternalResourceManager.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.hyperwallet.android.rule; - -import org.junit.rules.TestWatcher; -import org.junit.runner.Description; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.StringWriter; -import java.io.Writer; -import java.net.URL; -import java.util.logging.Level; -import java.util.logging.Logger; - -public class HyperwalletExternalResourceManager extends TestWatcher { - - private static final String EMPTY = ""; - private ClassLoader classLoader; - private Logger logger; - - @Override - protected void starting(Description description) { - super.starting(description); - classLoader = description.getTestClass().getClassLoader(); - logger = Logger.getLogger(description.getTestClass().getName()); - } - - public String getResourceContent(final String resourceName) { - if (resourceName == null) { - throw new IllegalArgumentException("Parameter resourceName cannot be null"); - } - - return getContent(resourceName); - } - - private String getContent(final String resourceName) { - - URL resource = classLoader.getResource(resourceName); - InputStream inputStream = null; - Writer writer = new StringWriter(); - String resourceContent = EMPTY; - if (resource != null) { - try { - inputStream = resource.openStream(); - BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); - String line = reader.readLine(); - while (line != null) { - writer.write(line); - line = reader.readLine(); - } - resourceContent = writer.toString(); - - } catch (Exception e) { - logger.log(Level.WARNING, "There was an error loading an external resource", e); - } finally { - try { - if (inputStream != null) { - inputStream.close(); - } - } catch (Exception e) { - logger.log(Level.SEVERE, "There was an error closing input stream", e); - } - try { - writer.close(); - } catch (IOException e) { - logger.log(Level.SEVERE, "There was an error closing writer", e); - } - } - } - return resourceContent; - } -} diff --git a/receipt/src/androidTest/java/com/hyperwallet/android/rule/HyperwalletMockWebServer.java b/receipt/src/androidTest/java/com/hyperwallet/android/rule/HyperwalletMockWebServer.java deleted file mode 100644 index 9f42f6128..000000000 --- a/receipt/src/androidTest/java/com/hyperwallet/android/rule/HyperwalletMockWebServer.java +++ /dev/null @@ -1,115 +0,0 @@ -package com.hyperwallet.android.rule; - -import org.junit.rules.TestWatcher; -import org.junit.runner.Description; - -import java.io.IOException; -import java.net.HttpURLConnection; - -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; - -public final class HyperwalletMockWebServer extends TestWatcher { - - private MockWebServer mServer; - private int port; - - public HyperwalletMockWebServer(int port) { - this.port = port; - } - - @Override - protected void starting(Description description) { - super.starting(description); - mServer = new MockWebServer(); - try { - mServer.start(port); - } catch (IOException e) { - throw new IllegalStateException("Unable to start mock server", e); - } - } - - @Override - protected void finished(Description description) { - super.finished(description); - try { - mServer.shutdown(); - mServer.close(); - } catch (IOException e) { - throw new IllegalStateException("Un error occurred when shutting down mock server", e); - } - } - - public HyperwalletMockResponse mockResponse() { - return new Builder(mServer).build(); - } - - public MockWebServer getServer() { - return mServer; - } - - public static class HyperwalletMockResponse { - - private String path; - private String body; - private int httpResponseCode; - private Builder builder; - - HyperwalletMockResponse(Builder builder) { - this.path = builder.path; - this.httpResponseCode = builder.responseCode; - this.body = builder.body; - this.builder = builder; - } - - public HyperwalletMockResponse withHttpResponseCode(final int code) { - builder.responseCode(code); - return builder.build(); - } - - public HyperwalletMockResponse withBody(final String body) { - builder.body(body); - return builder.build(); - } - - public void mock() { - mockRequest(); - } - - private String mockRequest() { - builder.server.enqueue(new MockResponse().setResponseCode(httpResponseCode).setBody(body)); - return builder.server.url(path).toString(); - } - - } - - private static class Builder { - - private String path; - private String body; - private int responseCode; - private MockWebServer server; - - - Builder(final MockWebServer server) { - this.path = ""; - this.responseCode = HttpURLConnection.HTTP_OK; - this.body = ""; - this.server = server; - } - - Builder responseCode(final int code) { - this.responseCode = code; - return this; - } - - Builder body(final String body) { - this.body = body; - return this; - } - - HyperwalletMockResponse build() { - return new HyperwalletMockResponse(this); - } - } -} diff --git a/receipt/src/androidTest/java/com/hyperwallet/android/receipt/ListReceiptsTest.java b/receipt/src/androidTest/java/com/hyperwallet/android/ui/receipt/ListReceiptsTest.java similarity index 94% rename from receipt/src/androidTest/java/com/hyperwallet/android/receipt/ListReceiptsTest.java rename to receipt/src/androidTest/java/com/hyperwallet/android/ui/receipt/ListReceiptsTest.java index 05c0e5c59..b68f3ec04 100644 --- a/receipt/src/androidTest/java/com/hyperwallet/android/receipt/ListReceiptsTest.java +++ b/receipt/src/androidTest/java/com/hyperwallet/android/ui/receipt/ListReceiptsTest.java @@ -1,4 +1,4 @@ -package com.hyperwallet.android.receipt; +package com.hyperwallet.android.ui.receipt; import static androidx.test.espresso.Espresso.onView; import static androidx.test.espresso.assertion.ViewAssertions.matches; @@ -27,10 +27,10 @@ import androidx.test.rule.ActivityTestRule; import com.hyperwallet.android.Hyperwallet; -import com.hyperwallet.android.receipt.repository.ReceiptRepositoryFactory; -import com.hyperwallet.android.receipt.view.ListReceiptActivity; import com.hyperwallet.android.rule.HyperwalletExternalResourceManager; import com.hyperwallet.android.rule.HyperwalletMockWebServer; +import com.hyperwallet.android.ui.receipt.repository.ReceiptRepositoryFactory; +import com.hyperwallet.android.ui.receipt.view.ListReceiptActivity; import com.hyperwallet.android.util.RecyclerViewCountAssertion; import com.hyperwallet.android.util.TestAuthenticationProvider; @@ -86,7 +86,7 @@ public void testListReceipts_userHasMultipleTransactions() { onView(withId(R.id.list_receipts)) .check(matches(atPosition(0, hasDescendant(withText("June 2019"))))); onView(withId(R.id.list_receipts)).check(matches(atPosition(0, - hasDescendant(withText(com.hyperwallet.android.receipt.R.string.credit))))); + hasDescendant(withText(com.hyperwallet.android.ui.receipt.R.string.credit))))); onView(withId(R.id.list_receipts)).check( matches(atPosition(0, hasDescendant(withText("Payment"))))); onView(withId(R.id.list_receipts)).check( @@ -96,7 +96,7 @@ public void testListReceipts_userHasMultipleTransactions() { onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("USD"))))); onView(withId(R.id.list_receipts)).check(matches(atPosition(1, - hasDescendant(withText(com.hyperwallet.android.receipt.R.string.credit))))); + hasDescendant(withText(com.hyperwallet.android.ui.receipt.R.string.credit))))); onView(withId(R.id.list_receipts)).check( matches(atPosition(1, hasDescendant(withText("Payment"))))); onView(withId(R.id.list_receipts)).check( @@ -106,7 +106,7 @@ public void testListReceipts_userHasMultipleTransactions() { onView(withId(R.id.list_receipts)).check(matches(atPosition(1, hasDescendant(withText("CAD"))))); onView(withId(R.id.list_receipts)).check(matches(atPosition(2, - hasDescendant(withText(com.hyperwallet.android.receipt.R.string.debit))))); + hasDescendant(withText(com.hyperwallet.android.ui.receipt.R.string.debit))))); onView(withId(R.id.list_receipts)).check( matches(atPosition(2, hasDescendant(withText("Card Activation Fee"))))); onView(withId(R.id.list_receipts)).check( @@ -118,7 +118,7 @@ public void testListReceipts_userHasMultipleTransactions() { onView(withId(R.id.list_receipts)) .check(matches(atPosition(3, hasDescendant(withText("December 2018"))))); onView(withId(R.id.list_receipts)).check(matches(atPosition(3, - hasDescendant(withText(com.hyperwallet.android.receipt.R.string.debit))))); + hasDescendant(withText(com.hyperwallet.android.ui.receipt.R.string.debit))))); onView(withId(R.id.list_receipts)).check( matches(atPosition(3, hasDescendant(withText("Card Load"))))); onView(withId(R.id.list_receipts)).check( @@ -147,7 +147,7 @@ public void testListReceipts_displayCreditTransaction() { onView(withId(R.id.list_receipts)) .check(matches(atPosition(0, hasDescendant(withText("June 2019"))))); onView(withId(R.id.list_receipts)).check(matches(atPosition(0, - hasDescendant(withText(com.hyperwallet.android.receipt.R.string.credit))))); + hasDescendant(withText(com.hyperwallet.android.ui.receipt.R.string.credit))))); onView(withId(R.id.list_receipts)).check( matches(atPosition(0, hasDescendant(withText(R.string.payment))))); onView(withId(R.id.list_receipts)).check( @@ -176,7 +176,7 @@ public void testListReceipts_displayDebitTransaction() { onView(withId(R.id.list_receipts)) .check(matches(atPosition(0, hasDescendant(withText("May 2019"))))); onView(withId(R.id.list_receipts)).check(matches(atPosition(0, - hasDescendant(withText(com.hyperwallet.android.receipt.R.string.debit))))); + hasDescendant(withText(com.hyperwallet.android.ui.receipt.R.string.debit))))); onView(withId(R.id.list_receipts)).check( matches(atPosition(0, hasDescendant(withText(R.string.transfer_to_prepaid_card))))); onView(withId(R.id.list_receipts)).check( @@ -205,7 +205,7 @@ public void testListReceipts_displayUnknownTransactionType() { onView(withId(R.id.list_receipts)) .check(matches(atPosition(0, hasDescendant(withText("June 2019"))))); onView(withId(R.id.list_receipts)).check(matches(atPosition(0, - hasDescendant(withText(com.hyperwallet.android.receipt.R.string.credit))))); + hasDescendant(withText(com.hyperwallet.android.ui.receipt.R.string.credit))))); onView(withId(R.id.list_receipts)).check( matches(atPosition(0, hasDescendant(withText(R.string.unknown_type))))); onView(withId(R.id.list_receipts)).check( diff --git a/receipt/src/androidTest/java/com/hyperwallet/android/util/EspressoUtils.java b/receipt/src/androidTest/java/com/hyperwallet/android/util/EspressoUtils.java deleted file mode 100644 index 92a711f96..000000000 --- a/receipt/src/androidTest/java/com/hyperwallet/android/util/EspressoUtils.java +++ /dev/null @@ -1,187 +0,0 @@ -package com.hyperwallet.android.util; - -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.drawable.Drawable; -import android.view.View; -import android.widget.EditText; -import android.widget.ImageView; - -import androidx.annotation.NonNull; -import androidx.recyclerview.widget.RecyclerView; -import androidx.test.espresso.ViewAction; -import androidx.test.espresso.action.ViewActions; -import androidx.test.espresso.matcher.BoundedMatcher; - -import com.google.android.material.textfield.TextInputLayout; - -import org.hamcrest.Description; -import org.hamcrest.Matcher; -import org.hamcrest.TypeSafeMatcher; - -import java.util.Objects; - -public class EspressoUtils { - - public static Matcher withHint(final String expectedHint) { - return new TypeSafeMatcher() { - - @Override - public boolean matchesSafely(View view) { - if (!(view instanceof TextInputLayout)) { - return false; - } - - String hint = Objects.toString(((TextInputLayout) view).getHint()); - return expectedHint.equals(hint); - } - - @Override - public void describeTo(Description description) { - description.appendText(expectedHint); - } - }; - } - - public static Matcher hasErrorText(final String expectedErrorMessage) { - return new TypeSafeMatcher() { - - @Override - public boolean matchesSafely(View view) { - if (!(view instanceof TextInputLayout)) { - return false; - } - - String errorMessage = Objects.toString(((TextInputLayout) view).getError()); - return expectedErrorMessage.equals(errorMessage); - } - - @Override - public void describeTo(Description description) { - description.appendText(expectedErrorMessage); - } - }; - } - - public static Matcher hasErrorText(final int resourceId) { - return new TypeSafeMatcher() { - - @Override - public boolean matchesSafely(View view) { - if (!(view instanceof TextInputLayout)) { - return false; - } - String expectedErrorMessage = view.getResources().getString(resourceId); - String errorMessage = Objects.toString(((TextInputLayout) view).getError()); - - return expectedErrorMessage.equals(errorMessage); - } - - @Override - public void describeTo(Description description) { - } - }; - } - - public static Matcher withDrawable(final int resourceId) { - return new TypeSafeMatcher() { - - @Override - public boolean matchesSafely(View view) { - if (!(view instanceof ImageView)) { - return false; - } - - Drawable drawable = ((ImageView) view).getDrawable(); - if (drawable == null) { - return false; - } - Drawable expectedDrawable = view.getContext().getResources().getDrawable(resourceId); - - Bitmap bitmap = getBitmap(drawable); - Bitmap expectedBitmap = getBitmap(expectedDrawable); - - return bitmap.sameAs(expectedBitmap); - } - - @Override - public void describeTo(Description description) { - } - }; - } - - public static Matcher atPosition(final int position, @NonNull final Matcher matcher) { - return new BoundedMatcher(RecyclerView.class) { - - @Override - protected boolean matchesSafely(final RecyclerView view) { - RecyclerView.ViewHolder viewHolder = view.findViewHolderForAdapterPosition(position); - - if (viewHolder == null) { - return false; - } - - return matcher.matches(viewHolder.itemView); - } - - @Override - public void describeTo(Description description) { - description.appendText("has item at position " + position + ": "); - matcher.describeTo(description); - } - }; - } - - public static ViewAction nestedScrollTo() { - return ViewActions.actionWithAssertions(new NestedScrollToAction()); - } - - private static Bitmap getBitmap(Drawable drawable) { - Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), - drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); - - Canvas canvas = new Canvas(bitmap); - drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); - drawable.draw(canvas); - - return bitmap; - } - - public static Matcher hasNoErrorText() { - return new TypeSafeMatcher() { - - @Override - public boolean matchesSafely(View view) { - if (!(view instanceof TextInputLayout)) { - return false; - } - return ((TextInputLayout) view).getError() == null; - } - - @Override - public void describeTo(Description description) { - description.appendText("has no error text: "); - } - }; - } - - public static Matcher hasEmptyText() { - return new TypeSafeMatcher() { - - @Override - public boolean matchesSafely(View view) { - if (!(view instanceof EditText)) { - return false; - } - String text = ((EditText) view).getText().toString(); - - return text.isEmpty(); - } - - @Override - public void describeTo(Description description) { - } - }; - } -} - diff --git a/receipt/src/androidTest/java/com/hyperwallet/android/util/NestedScrollToAction.java b/receipt/src/androidTest/java/com/hyperwallet/android/util/NestedScrollToAction.java deleted file mode 100644 index 392867387..000000000 --- a/receipt/src/androidTest/java/com/hyperwallet/android/util/NestedScrollToAction.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.hyperwallet.android.util; - -import static androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom; -import static androidx.test.espresso.matcher.ViewMatchers.isDescendantOfA; -import static androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility; - -import static org.hamcrest.Matchers.allOf; -import static org.hamcrest.Matchers.anyOf; - -import android.view.View; - -import androidx.core.widget.NestedScrollView; -import androidx.test.espresso.UiController; -import androidx.test.espresso.ViewAction; -import androidx.test.espresso.action.ScrollToAction; -import androidx.test.espresso.matcher.ViewMatchers; - -import org.hamcrest.Matcher; - -public class NestedScrollToAction implements ViewAction { - private static final String TAG = ScrollToAction.class.getSimpleName(); - - @SuppressWarnings("unchecked") - @Override - public Matcher getConstraints() { - return allOf( - withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE), - isDescendantOfA( - anyOf(isAssignableFrom(NestedScrollView.class)))); - } - - @Override - public void perform(UiController uiController, View view) { - new ScrollToAction().perform(uiController, view); - } - - @Override - public String getDescription() { - return "scroll to"; - } -} diff --git a/receipt/src/androidTest/java/com/hyperwallet/android/util/RecyclerViewCountAssertion.java b/receipt/src/androidTest/java/com/hyperwallet/android/util/RecyclerViewCountAssertion.java deleted file mode 100644 index bb3aecaff..000000000 --- a/receipt/src/androidTest/java/com/hyperwallet/android/util/RecyclerViewCountAssertion.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.hyperwallet.android.util; - -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; - -import android.view.View; - -import androidx.recyclerview.widget.RecyclerView; -import androidx.test.espresso.NoMatchingViewException; -import androidx.test.espresso.ViewAssertion; - -public class RecyclerViewCountAssertion implements ViewAssertion { - private final int mCount; - - public RecyclerViewCountAssertion(int count) { - this.mCount = count; - } - - @Override - public void check(View view, NoMatchingViewException noViewFoundException) { - if (noViewFoundException != null) { - throw noViewFoundException; - } - - RecyclerView recyclerView = (RecyclerView) view; - RecyclerView.Adapter adapter = recyclerView.getAdapter(); - - assertThat(adapter.getItemCount(), is(mCount)); - } -} diff --git a/receipt/src/androidTest/java/com/hyperwallet/android/util/TestAuthenticationProvider.java b/receipt/src/androidTest/java/com/hyperwallet/android/util/TestAuthenticationProvider.java deleted file mode 100644 index 686ccbf30..000000000 --- a/receipt/src/androidTest/java/com/hyperwallet/android/util/TestAuthenticationProvider.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.hyperwallet.android.util; - -import com.hyperwallet.android.HyperwalletAuthenticationTokenListener; -import com.hyperwallet.android.HyperwalletAuthenticationTokenProvider; - -import java.io.IOException; -import java.text.MessageFormat; -import java.util.UUID; - -import okhttp3.Call; -import okhttp3.Callback; -import okhttp3.MediaType; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.RequestBody; -import okhttp3.Response; - -public class TestAuthenticationProvider implements HyperwalletAuthenticationTokenProvider { - - public static final MediaType JSON - = MediaType.get("application/json; charset=utf-8"); - private static final String mBaseUrl = "http://localhost:8080/rest/v3/users/{0}/authentication-token"; - private static final String mUserToken = "user_token"; - - @Override - public void retrieveAuthenticationToken(final HyperwalletAuthenticationTokenListener authenticationTokenListener) { - - OkHttpClient client = new OkHttpClient(); - - String payload = "{}"; - String baseUrl = MessageFormat.format(mBaseUrl, mUserToken); - - RequestBody body = RequestBody.create(JSON, payload); - Request request = new Request.Builder() - .url(baseUrl) - .post(body) - .build(); - - client.newCall(request).enqueue(new Callback() { - @Override - public void onFailure(Call call, IOException e) { - authenticationTokenListener.onFailure(UUID.randomUUID(), e.getMessage()); - } - - @Override - public void onResponse(Call call, Response response) throws IOException { - authenticationTokenListener.onSuccess(response.body().string()); - } - }); - } -} diff --git a/receipt/src/main/AndroidManifest.xml b/receipt/src/main/AndroidManifest.xml index 3716721ff..d817501e5 100644 --- a/receipt/src/main/AndroidManifest.xml +++ b/receipt/src/main/AndroidManifest.xml @@ -1,7 +1,7 @@ + package="com.hyperwallet.android.ui.receipt"> diff --git a/receipt/src/main/java/com/hyperwallet/android/receipt/repository/ReceiptDataSource.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/ReceiptDataSource.java similarity index 98% rename from receipt/src/main/java/com/hyperwallet/android/receipt/repository/ReceiptDataSource.java rename to receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/ReceiptDataSource.java index 5320214fb..f6e30479b 100644 --- a/receipt/src/main/java/com/hyperwallet/android/receipt/repository/ReceiptDataSource.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/ReceiptDataSource.java @@ -14,7 +14,7 @@ * 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.receipt.repository; +package com.hyperwallet.android.ui.receipt.repository; import android.os.Handler; @@ -25,13 +25,13 @@ import androidx.paging.PageKeyedDataSource; import com.hyperwallet.android.Hyperwallet; -import com.hyperwallet.android.common.viewmodel.Event; import com.hyperwallet.android.exception.HyperwalletException; import com.hyperwallet.android.listener.HyperwalletListener; import com.hyperwallet.android.model.HyperwalletErrors; import com.hyperwallet.android.model.paging.HyperwalletPageList; import com.hyperwallet.android.model.receipt.Receipt; import com.hyperwallet.android.model.receipt.ReceiptQueryParam; +import com.hyperwallet.android.ui.common.viewmodel.Event; import java.util.Calendar; diff --git a/receipt/src/main/java/com/hyperwallet/android/receipt/repository/ReceiptDataSourceFactory.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/ReceiptDataSourceFactory.java similarity index 97% rename from receipt/src/main/java/com/hyperwallet/android/receipt/repository/ReceiptDataSourceFactory.java rename to receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/ReceiptDataSourceFactory.java index a2b81216b..ca3186540 100644 --- a/receipt/src/main/java/com/hyperwallet/android/receipt/repository/ReceiptDataSourceFactory.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/ReceiptDataSourceFactory.java @@ -14,7 +14,7 @@ * 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.receipt.repository; +package com.hyperwallet.android.ui.receipt.repository; import androidx.annotation.NonNull; import androidx.lifecycle.LiveData; diff --git a/receipt/src/main/java/com/hyperwallet/android/receipt/repository/ReceiptRepository.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/ReceiptRepository.java similarity index 94% rename from receipt/src/main/java/com/hyperwallet/android/receipt/repository/ReceiptRepository.java rename to receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/ReceiptRepository.java index 542d03c89..2db846a4f 100644 --- a/receipt/src/main/java/com/hyperwallet/android/receipt/repository/ReceiptRepository.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/ReceiptRepository.java @@ -14,14 +14,14 @@ * 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.receipt.repository; +package com.hyperwallet.android.ui.receipt.repository; import androidx.lifecycle.LiveData; import androidx.paging.PagedList; -import com.hyperwallet.android.common.viewmodel.Event; import com.hyperwallet.android.model.HyperwalletErrors; import com.hyperwallet.android.model.receipt.Receipt; +import com.hyperwallet.android.ui.common.viewmodel.Event; /** * Receipt Repository Contract diff --git a/receipt/src/main/java/com/hyperwallet/android/receipt/repository/ReceiptRepositoryFactory.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/ReceiptRepositoryFactory.java similarity index 97% rename from receipt/src/main/java/com/hyperwallet/android/receipt/repository/ReceiptRepositoryFactory.java rename to receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/ReceiptRepositoryFactory.java index b096ab7a0..8fc76d7ab 100644 --- a/receipt/src/main/java/com/hyperwallet/android/receipt/repository/ReceiptRepositoryFactory.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/ReceiptRepositoryFactory.java @@ -14,7 +14,7 @@ * 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.receipt.repository; +package com.hyperwallet.android.ui.receipt.repository; /** * {@link ReceiptRepository} factory diff --git a/receipt/src/main/java/com/hyperwallet/android/receipt/repository/ReceiptRepositoryImpl.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/ReceiptRepositoryImpl.java similarity index 96% rename from receipt/src/main/java/com/hyperwallet/android/receipt/repository/ReceiptRepositoryImpl.java rename to receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/ReceiptRepositoryImpl.java index cde7edd94..74fe8755d 100644 --- a/receipt/src/main/java/com/hyperwallet/android/receipt/repository/ReceiptRepositoryImpl.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/ReceiptRepositoryImpl.java @@ -14,15 +14,15 @@ * 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.receipt.repository; +package com.hyperwallet.android.ui.receipt.repository; import androidx.lifecycle.LiveData; import androidx.paging.LivePagedListBuilder; import androidx.paging.PagedList; -import com.hyperwallet.android.common.viewmodel.Event; import com.hyperwallet.android.model.HyperwalletErrors; import com.hyperwallet.android.model.receipt.Receipt; +import com.hyperwallet.android.ui.common.viewmodel.Event; /** * {@link ReceiptRepository} implementation diff --git a/receipt/src/main/java/com/hyperwallet/android/receipt/view/ListReceiptActivity.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListReceiptActivity.java similarity index 91% rename from receipt/src/main/java/com/hyperwallet/android/receipt/view/ListReceiptActivity.java rename to receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListReceiptActivity.java index e7f57c821..6f203949d 100644 --- a/receipt/src/main/java/com/hyperwallet/android/receipt/view/ListReceiptActivity.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListReceiptActivity.java @@ -14,7 +14,7 @@ * 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.receipt.view; +package com.hyperwallet.android.ui.receipt.view; import android.content.Intent; import android.os.Bundle; @@ -30,14 +30,14 @@ import androidx.lifecycle.Observer; import androidx.lifecycle.ViewModelProviders; -import com.hyperwallet.android.common.view.error.DefaultErrorDialogFragment; -import com.hyperwallet.android.common.view.error.OnNetworkErrorCallback; -import com.hyperwallet.android.common.viewmodel.Event; import com.hyperwallet.android.model.HyperwalletError; import com.hyperwallet.android.model.HyperwalletErrors; -import com.hyperwallet.android.receipt.R; -import com.hyperwallet.android.receipt.repository.ReceiptRepositoryFactory; -import com.hyperwallet.android.receipt.viewmodel.ListReceiptViewModel; +import com.hyperwallet.android.ui.common.view.error.DefaultErrorDialogFragment; +import com.hyperwallet.android.ui.common.view.error.OnNetworkErrorCallback; +import com.hyperwallet.android.ui.common.viewmodel.Event; +import com.hyperwallet.android.ui.receipt.R; +import com.hyperwallet.android.ui.receipt.repository.ReceiptRepositoryFactory; +import com.hyperwallet.android.ui.receipt.viewmodel.ListReceiptViewModel; import java.util.List; diff --git a/receipt/src/main/java/com/hyperwallet/android/receipt/view/ListReceiptFragment.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListReceiptFragment.java similarity index 98% rename from receipt/src/main/java/com/hyperwallet/android/receipt/view/ListReceiptFragment.java rename to receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListReceiptFragment.java index ce6f9fd4d..2e2e33cac 100644 --- a/receipt/src/main/java/com/hyperwallet/android/receipt/view/ListReceiptFragment.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListReceiptFragment.java @@ -14,7 +14,7 @@ * 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.receipt.view; +package com.hyperwallet.android.ui.receipt.view; import static com.hyperwallet.android.model.receipt.Receipt.Entries.CREDIT; import static com.hyperwallet.android.model.receipt.Receipt.Entries.DEBIT; @@ -37,10 +37,10 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; -import com.hyperwallet.android.common.util.DateUtils; import com.hyperwallet.android.model.receipt.Receipt; -import com.hyperwallet.android.receipt.R; -import com.hyperwallet.android.receipt.viewmodel.ListReceiptViewModel; +import com.hyperwallet.android.ui.common.util.DateUtils; +import com.hyperwallet.android.ui.receipt.R; +import com.hyperwallet.android.ui.receipt.viewmodel.ListReceiptViewModel; import java.util.Calendar; import java.util.Locale; diff --git a/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptItemDividerDecorator.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ReceiptItemDividerDecorator.java similarity index 97% rename from receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptItemDividerDecorator.java rename to receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ReceiptItemDividerDecorator.java index c61b22e5d..16f4d51ee 100644 --- a/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptItemDividerDecorator.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ReceiptItemDividerDecorator.java @@ -14,7 +14,7 @@ * 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.receipt.view; +package com.hyperwallet.android.ui.receipt.view; import android.content.Context; import android.graphics.Canvas; @@ -25,7 +25,7 @@ import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; -import com.hyperwallet.android.common.view.HorizontalDividerItemDecorator; +import com.hyperwallet.android.ui.common.view.HorizontalDividerItemDecorator; public class ReceiptItemDividerDecorator extends HorizontalDividerItemDecorator { diff --git a/receipt/src/main/java/com/hyperwallet/android/receipt/viewmodel/ListReceiptViewModel.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/viewmodel/ListReceiptViewModel.java similarity index 95% rename from receipt/src/main/java/com/hyperwallet/android/receipt/viewmodel/ListReceiptViewModel.java rename to receipt/src/main/java/com/hyperwallet/android/ui/receipt/viewmodel/ListReceiptViewModel.java index 57f41b5c1..264e78974 100644 --- a/receipt/src/main/java/com/hyperwallet/android/receipt/viewmodel/ListReceiptViewModel.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/viewmodel/ListReceiptViewModel.java @@ -14,7 +14,7 @@ * 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.receipt.viewmodel; +package com.hyperwallet.android.ui.receipt.viewmodel; import androidx.annotation.NonNull; import androidx.lifecycle.LiveData; @@ -24,10 +24,10 @@ import androidx.lifecycle.ViewModelProvider; import androidx.paging.PagedList; -import com.hyperwallet.android.common.viewmodel.Event; import com.hyperwallet.android.model.HyperwalletErrors; import com.hyperwallet.android.model.receipt.Receipt; -import com.hyperwallet.android.receipt.repository.ReceiptRepository; +import com.hyperwallet.android.ui.common.viewmodel.Event; +import com.hyperwallet.android.ui.receipt.repository.ReceiptRepository; public class ListReceiptViewModel extends ViewModel { diff --git a/receipt/src/test/java/com/hyperwallet/android/receipt/repository/ReceiptDataSourceFactoryTest.java b/receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/ReceiptDataSourceFactoryTest.java similarity index 95% rename from receipt/src/test/java/com/hyperwallet/android/receipt/repository/ReceiptDataSourceFactoryTest.java rename to receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/ReceiptDataSourceFactoryTest.java index cf5c63114..b8a6974f2 100644 --- a/receipt/src/test/java/com/hyperwallet/android/receipt/repository/ReceiptDataSourceFactoryTest.java +++ b/receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/ReceiptDataSourceFactoryTest.java @@ -1,4 +1,4 @@ -package com.hyperwallet.android.receipt.repository; +package com.hyperwallet.android.ui.receipt.repository; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; diff --git a/receipt/src/test/java/com/hyperwallet/android/receipt/repository/ReceiptDataSourceTest.java b/receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/ReceiptDataSourceTest.java similarity index 99% rename from receipt/src/test/java/com/hyperwallet/android/receipt/repository/ReceiptDataSourceTest.java rename to receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/ReceiptDataSourceTest.java index d09854710..9cf699e83 100644 --- a/receipt/src/test/java/com/hyperwallet/android/receipt/repository/ReceiptDataSourceTest.java +++ b/receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/ReceiptDataSourceTest.java @@ -1,4 +1,4 @@ -package com.hyperwallet.android.receipt.repository; +package com.hyperwallet.android.ui.receipt.repository; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; diff --git a/receipt/src/test/java/com/hyperwallet/android/receipt/repository/ReceiptRepositoryFactoryTest.java b/receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/ReceiptRepositoryFactoryTest.java similarity index 96% rename from receipt/src/test/java/com/hyperwallet/android/receipt/repository/ReceiptRepositoryFactoryTest.java rename to receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/ReceiptRepositoryFactoryTest.java index 3326f2916..714becb62 100644 --- a/receipt/src/test/java/com/hyperwallet/android/receipt/repository/ReceiptRepositoryFactoryTest.java +++ b/receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/ReceiptRepositoryFactoryTest.java @@ -1,4 +1,4 @@ -package com.hyperwallet.android.receipt.repository; +package com.hyperwallet.android.ui.receipt.repository; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.not; diff --git a/receipt/src/test/java/com/hyperwallet/android/rule/HyperwalletExternalResourceManager.java b/receipt/src/test/java/com/hyperwallet/android/ui/rule/HyperwalletExternalResourceManager.java similarity index 100% rename from receipt/src/test/java/com/hyperwallet/android/rule/HyperwalletExternalResourceManager.java rename to receipt/src/test/java/com/hyperwallet/android/ui/rule/HyperwalletExternalResourceManager.java diff --git a/ui/build.gradle b/ui/build.gradle index 7d74976ae..bc6fa3a49 100644 --- a/ui/build.gradle +++ b/ui/build.gradle @@ -62,7 +62,7 @@ publishing { configurations.implementation.allDependencies.each { def dependencyNode = dependenciesNode.appendNode('dependency') if (it.group == "hyperwallet-android-ui-sdk") { - dependencyNode.appendNode('groupId', "com.hyperwallet.android") + dependencyNode.appendNode('groupId', "com.hyperwallet.android.ui") } else { dependencyNode.appendNode('groupId', it.group) } @@ -106,7 +106,7 @@ sonarqube { properties { def libraries = project.android.sdkDirectory.getPath() + "/platforms/android-28/android.jar" property "sonar.sources", "src/main/java" - property "sonar.binaries", "build/intermediates/javac/release/compileReleaseJavaWithJavac/classes/com/hyperwallet/android" + property "sonar.binaries", "build/intermediates/javac/release/compileReleaseJavaWithJavac/classes/com/hyperwallet/android/ui" property "sonar.libraries", libraries property "sonar.projectName", "android-ui-sdk" } diff --git a/ui/src/androidTest/AndroidManifest.xml b/ui/src/androidTest/AndroidManifest.xml index 0cd133def..ac7de9735 100644 --- a/ui/src/androidTest/AndroidManifest.xml +++ b/ui/src/androidTest/AndroidManifest.xml @@ -1,6 +1,6 @@ + package="com.hyperwallet.android.ui.test"> diff --git a/ui/src/androidTest/java/com/hyperwallet/android/HyperwalletInstrumentedTestApplication.java b/ui/src/androidTest/java/com/hyperwallet/android/HyperwalletInstrumentedTestApplication.java deleted file mode 100644 index dfc559d2e..000000000 --- a/ui/src/androidTest/java/com/hyperwallet/android/HyperwalletInstrumentedTestApplication.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.hyperwallet.android; - - -import android.app.Application; - -import com.squareup.leakcanary.InstrumentationLeakDetector; -import com.squareup.leakcanary.LeakCanary; - -public class HyperwalletInstrumentedTestApplication extends Application { - - @Override - public void onCreate() { - - super.onCreate(); - if (LeakCanary.isInAnalyzerProcess(this)) { - // This process is dedicated to LeakCanary for heap analysis. - // You should not init your app in this process. - return; - } - installLeakCanary(); - } - - - protected void installLeakCanary() { - - InstrumentationLeakDetector.instrumentationRefWatcher(this) - .buildAndInstall(); - - } - -} \ No newline at end of file diff --git a/receipt/src/androidTest/java/com/hyperwallet/android/HyperwalletInstrumentedTestApplication.java b/ui/src/androidTest/java/com/hyperwallet/android/ui/HyperwalletInstrumentedTestApplication.java similarity index 95% rename from receipt/src/androidTest/java/com/hyperwallet/android/HyperwalletInstrumentedTestApplication.java rename to ui/src/androidTest/java/com/hyperwallet/android/ui/HyperwalletInstrumentedTestApplication.java index dfc559d2e..1e77c01b7 100644 --- a/receipt/src/androidTest/java/com/hyperwallet/android/HyperwalletInstrumentedTestApplication.java +++ b/ui/src/androidTest/java/com/hyperwallet/android/ui/HyperwalletInstrumentedTestApplication.java @@ -1,4 +1,4 @@ -package com.hyperwallet.android; +package com.hyperwallet.android.ui; import android.app.Application; diff --git a/ui/src/androidTest/java/com/hyperwallet/android/rule/HyperwalletExternalResourceManager.java b/ui/src/androidTest/java/com/hyperwallet/android/ui/rule/HyperwalletExternalResourceManager.java similarity index 98% rename from ui/src/androidTest/java/com/hyperwallet/android/rule/HyperwalletExternalResourceManager.java rename to ui/src/androidTest/java/com/hyperwallet/android/ui/rule/HyperwalletExternalResourceManager.java index e7e546063..0fd013e52 100644 --- a/ui/src/androidTest/java/com/hyperwallet/android/rule/HyperwalletExternalResourceManager.java +++ b/ui/src/androidTest/java/com/hyperwallet/android/ui/rule/HyperwalletExternalResourceManager.java @@ -1,4 +1,4 @@ -package com.hyperwallet.android.rule; +package com.hyperwallet.android.ui.rule; import org.junit.rules.TestWatcher; import org.junit.runner.Description; diff --git a/ui/src/androidTest/java/com/hyperwallet/android/rule/HyperwalletMockWebServer.java b/ui/src/androidTest/java/com/hyperwallet/android/ui/rule/HyperwalletMockWebServer.java similarity index 98% rename from ui/src/androidTest/java/com/hyperwallet/android/rule/HyperwalletMockWebServer.java rename to ui/src/androidTest/java/com/hyperwallet/android/ui/rule/HyperwalletMockWebServer.java index 9f42f6128..fd37ac735 100644 --- a/ui/src/androidTest/java/com/hyperwallet/android/rule/HyperwalletMockWebServer.java +++ b/ui/src/androidTest/java/com/hyperwallet/android/ui/rule/HyperwalletMockWebServer.java @@ -1,4 +1,4 @@ -package com.hyperwallet.android.rule; +package com.hyperwallet.android.ui.rule; import org.junit.rules.TestWatcher; import org.junit.runner.Description; diff --git a/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/AddTransferMethodTest.java b/ui/src/androidTest/java/com/hyperwallet/android/ui/transfermethod/AddTransferMethodTest.java similarity index 93% rename from ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/AddTransferMethodTest.java rename to ui/src/androidTest/java/com/hyperwallet/android/ui/transfermethod/AddTransferMethodTest.java index f8751b9b6..18989446a 100644 --- a/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/AddTransferMethodTest.java +++ b/ui/src/androidTest/java/com/hyperwallet/android/ui/transfermethod/AddTransferMethodTest.java @@ -1,4 +1,4 @@ -package com.hyperwallet.android.transfermethod.ui; +package com.hyperwallet.android.ui.transfermethod; import static androidx.test.espresso.Espresso.onView; import static androidx.test.espresso.action.ViewActions.click; @@ -21,8 +21,8 @@ import static java.net.HttpURLConnection.HTTP_BAD_REQUEST; import static java.net.HttpURLConnection.HTTP_OK; -import static com.hyperwallet.android.common.view.error.DefaultErrorDialogFragment.RESULT_ERROR; -import static com.hyperwallet.android.util.EspressoUtils.nestedScrollTo; +import static com.hyperwallet.android.ui.common.view.error.DefaultErrorDialogFragment.RESULT_ERROR; +import static com.hyperwallet.android.ui.util.EspressoUtils.nestedScrollTo; import android.app.Instrumentation; import android.content.Intent; @@ -35,14 +35,13 @@ import androidx.test.rule.ActivityTestRule; import com.hyperwallet.android.Hyperwallet; -import com.hyperwallet.android.common.util.EspressoIdlingResource; -import com.hyperwallet.android.common.view.error.DefaultErrorDialogFragment; -import com.hyperwallet.android.hyperwallet_ui.R; -import com.hyperwallet.android.rule.HyperwalletExternalResourceManager; -import com.hyperwallet.android.rule.HyperwalletMockWebServer; +import com.hyperwallet.android.ui.R; +import com.hyperwallet.android.ui.common.util.EspressoIdlingResource; +import com.hyperwallet.android.ui.common.view.error.DefaultErrorDialogFragment; import com.hyperwallet.android.ui.repository.RepositoryFactory; -import com.hyperwallet.android.ui.transfermethod.AddTransferMethodActivity; -import com.hyperwallet.android.util.TestAuthenticationProvider; +import com.hyperwallet.android.ui.rule.HyperwalletExternalResourceManager; +import com.hyperwallet.android.ui.rule.HyperwalletMockWebServer; +import com.hyperwallet.android.ui.util.TestAuthenticationProvider; import org.junit.After; import org.junit.Before; diff --git a/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/BankAccountTest.java b/ui/src/androidTest/java/com/hyperwallet/android/ui/transfermethod/BankAccountTest.java similarity index 96% rename from ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/BankAccountTest.java rename to ui/src/androidTest/java/com/hyperwallet/android/ui/transfermethod/BankAccountTest.java index 5bd2e49dd..45d92c6a7 100644 --- a/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/BankAccountTest.java +++ b/ui/src/androidTest/java/com/hyperwallet/android/ui/transfermethod/BankAccountTest.java @@ -1,4 +1,4 @@ -package com.hyperwallet.android.transfermethod.ui; +package com.hyperwallet.android.ui.transfermethod; import static androidx.test.espresso.Espresso.onView; import static androidx.test.espresso.action.ViewActions.click; @@ -24,11 +24,11 @@ import static java.util.concurrent.TimeUnit.SECONDS; import static com.hyperwallet.android.model.transfermethod.HyperwalletBankAccount.Purpose.SAVINGS; -import static com.hyperwallet.android.util.EspressoUtils.hasEmptyText; -import static com.hyperwallet.android.util.EspressoUtils.hasErrorText; -import static com.hyperwallet.android.util.EspressoUtils.hasNoErrorText; -import static com.hyperwallet.android.util.EspressoUtils.nestedScrollTo; -import static com.hyperwallet.android.util.EspressoUtils.withHint; +import static com.hyperwallet.android.ui.util.EspressoUtils.hasEmptyText; +import static com.hyperwallet.android.ui.util.EspressoUtils.hasErrorText; +import static com.hyperwallet.android.ui.util.EspressoUtils.hasNoErrorText; +import static com.hyperwallet.android.ui.util.EspressoUtils.nestedScrollTo; +import static com.hyperwallet.android.ui.util.EspressoUtils.withHint; import android.app.Activity; import android.content.BroadcastReceiver; @@ -45,15 +45,14 @@ import androidx.test.rule.ActivityTestRule; import com.hyperwallet.android.Hyperwallet; -import com.hyperwallet.android.common.util.EspressoIdlingResource; -import com.hyperwallet.android.hyperwallet_ui.R; import com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod; -import com.hyperwallet.android.rule.HyperwalletExternalResourceManager; -import com.hyperwallet.android.rule.HyperwalletMockWebServer; +import com.hyperwallet.android.ui.R; +import com.hyperwallet.android.ui.common.util.EspressoIdlingResource; import com.hyperwallet.android.ui.repository.RepositoryFactory; -import com.hyperwallet.android.ui.transfermethod.AddTransferMethodActivity; -import com.hyperwallet.android.util.RecyclerViewCountAssertion; -import com.hyperwallet.android.util.TestAuthenticationProvider; +import com.hyperwallet.android.ui.rule.HyperwalletExternalResourceManager; +import com.hyperwallet.android.ui.rule.HyperwalletMockWebServer; +import com.hyperwallet.android.ui.util.RecyclerViewCountAssertion; +import com.hyperwallet.android.ui.util.TestAuthenticationProvider; import org.junit.After; import org.junit.Before; diff --git a/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/BankCardTest.java b/ui/src/androidTest/java/com/hyperwallet/android/ui/transfermethod/BankCardTest.java similarity index 95% rename from ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/BankCardTest.java rename to ui/src/androidTest/java/com/hyperwallet/android/ui/transfermethod/BankCardTest.java index f3c15fa11..8f98ffabf 100644 --- a/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/BankCardTest.java +++ b/ui/src/androidTest/java/com/hyperwallet/android/ui/transfermethod/BankCardTest.java @@ -1,4 +1,4 @@ -package com.hyperwallet.android.transfermethod.ui; +package com.hyperwallet.android.ui.transfermethod; import static androidx.test.espresso.Espresso.onView; import static androidx.test.espresso.action.ViewActions.click; @@ -22,10 +22,10 @@ import static java.net.HttpURLConnection.HTTP_OK; import static java.util.concurrent.TimeUnit.SECONDS; -import static com.hyperwallet.android.util.EspressoUtils.hasEmptyText; -import static com.hyperwallet.android.util.EspressoUtils.hasErrorText; -import static com.hyperwallet.android.util.EspressoUtils.nestedScrollTo; -import static com.hyperwallet.android.util.EspressoUtils.withHint; +import static com.hyperwallet.android.ui.util.EspressoUtils.hasEmptyText; +import static com.hyperwallet.android.ui.util.EspressoUtils.hasErrorText; +import static com.hyperwallet.android.ui.util.EspressoUtils.nestedScrollTo; +import static com.hyperwallet.android.ui.util.EspressoUtils.withHint; import android.app.Activity; import android.content.BroadcastReceiver; @@ -42,14 +42,13 @@ import androidx.test.rule.ActivityTestRule; import com.hyperwallet.android.Hyperwallet; -import com.hyperwallet.android.common.util.EspressoIdlingResource; -import com.hyperwallet.android.hyperwallet_ui.R; import com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod; -import com.hyperwallet.android.rule.HyperwalletExternalResourceManager; -import com.hyperwallet.android.rule.HyperwalletMockWebServer; +import com.hyperwallet.android.ui.R; +import com.hyperwallet.android.ui.common.util.EspressoIdlingResource; import com.hyperwallet.android.ui.repository.RepositoryFactory; -import com.hyperwallet.android.ui.transfermethod.AddTransferMethodActivity; -import com.hyperwallet.android.util.TestAuthenticationProvider; +import com.hyperwallet.android.ui.rule.HyperwalletExternalResourceManager; +import com.hyperwallet.android.ui.rule.HyperwalletMockWebServer; +import com.hyperwallet.android.ui.util.TestAuthenticationProvider; import org.junit.After; import org.junit.Before; diff --git a/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/ListTransferMethodTest.java b/ui/src/androidTest/java/com/hyperwallet/android/ui/transfermethod/ListTransferMethodTest.java similarity index 97% rename from ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/ListTransferMethodTest.java rename to ui/src/androidTest/java/com/hyperwallet/android/ui/transfermethod/ListTransferMethodTest.java index edbaa0ada..fc567b50e 100644 --- a/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/ListTransferMethodTest.java +++ b/ui/src/androidTest/java/com/hyperwallet/android/ui/transfermethod/ListTransferMethodTest.java @@ -1,4 +1,4 @@ -package com.hyperwallet.android.transfermethod.ui; +package com.hyperwallet.android.ui.transfermethod; import static androidx.test.espresso.Espresso.onView; import static androidx.test.espresso.action.ViewActions.click; @@ -21,8 +21,8 @@ import static java.util.concurrent.TimeUnit.SECONDS; import static com.hyperwallet.android.model.HyperwalletStatusTransition.StatusDefinition.DE_ACTIVATED; -import static com.hyperwallet.android.util.EspressoUtils.atPosition; -import static com.hyperwallet.android.util.EspressoUtils.withDrawable; +import static com.hyperwallet.android.ui.util.EspressoUtils.atPosition; +import static com.hyperwallet.android.ui.util.EspressoUtils.withDrawable; import android.content.BroadcastReceiver; import android.content.Context; @@ -38,14 +38,13 @@ import androidx.test.rule.ActivityTestRule; import com.hyperwallet.android.Hyperwallet; -import com.hyperwallet.android.hyperwallet_ui.R; import com.hyperwallet.android.model.HyperwalletStatusTransition; -import com.hyperwallet.android.rule.HyperwalletExternalResourceManager; -import com.hyperwallet.android.rule.HyperwalletMockWebServer; +import com.hyperwallet.android.ui.R; import com.hyperwallet.android.ui.repository.RepositoryFactory; -import com.hyperwallet.android.ui.transfermethod.ListTransferMethodActivity; -import com.hyperwallet.android.util.RecyclerViewCountAssertion; -import com.hyperwallet.android.util.TestAuthenticationProvider; +import com.hyperwallet.android.ui.rule.HyperwalletExternalResourceManager; +import com.hyperwallet.android.ui.rule.HyperwalletMockWebServer; +import com.hyperwallet.android.ui.util.RecyclerViewCountAssertion; +import com.hyperwallet.android.ui.util.TestAuthenticationProvider; import org.hamcrest.Matchers; import org.junit.After; diff --git a/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/PayPalTest.java b/ui/src/androidTest/java/com/hyperwallet/android/ui/transfermethod/PayPalTest.java similarity index 93% rename from ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/PayPalTest.java rename to ui/src/androidTest/java/com/hyperwallet/android/ui/transfermethod/PayPalTest.java index ec88b9dd0..1bef2a80a 100644 --- a/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/PayPalTest.java +++ b/ui/src/androidTest/java/com/hyperwallet/android/ui/transfermethod/PayPalTest.java @@ -1,4 +1,4 @@ -package com.hyperwallet.android.transfermethod.ui; +package com.hyperwallet.android.ui.transfermethod; import static androidx.test.espresso.Espresso.onView; import static androidx.test.espresso.action.ViewActions.click; @@ -24,10 +24,10 @@ import static java.net.HttpURLConnection.HTTP_OK; import static java.util.concurrent.TimeUnit.SECONDS; -import static com.hyperwallet.android.util.EspressoUtils.hasEmptyText; -import static com.hyperwallet.android.util.EspressoUtils.hasErrorText; -import static com.hyperwallet.android.util.EspressoUtils.nestedScrollTo; -import static com.hyperwallet.android.util.EspressoUtils.withHint; +import static com.hyperwallet.android.ui.util.EspressoUtils.hasEmptyText; +import static com.hyperwallet.android.ui.util.EspressoUtils.hasErrorText; +import static com.hyperwallet.android.ui.util.EspressoUtils.nestedScrollTo; +import static com.hyperwallet.android.ui.util.EspressoUtils.withHint; import android.app.Activity; import android.content.BroadcastReceiver; @@ -44,14 +44,13 @@ import androidx.test.rule.ActivityTestRule; import com.hyperwallet.android.Hyperwallet; -import com.hyperwallet.android.common.util.EspressoIdlingResource; -import com.hyperwallet.android.hyperwallet_ui.R; import com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod; -import com.hyperwallet.android.rule.HyperwalletExternalResourceManager; -import com.hyperwallet.android.rule.HyperwalletMockWebServer; +import com.hyperwallet.android.ui.R; +import com.hyperwallet.android.ui.common.util.EspressoIdlingResource; import com.hyperwallet.android.ui.repository.RepositoryFactory; -import com.hyperwallet.android.ui.transfermethod.AddTransferMethodActivity; -import com.hyperwallet.android.util.TestAuthenticationProvider; +import com.hyperwallet.android.ui.rule.HyperwalletExternalResourceManager; +import com.hyperwallet.android.ui.rule.HyperwalletMockWebServer; +import com.hyperwallet.android.ui.util.TestAuthenticationProvider; import org.junit.After; import org.junit.Before; diff --git a/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/SelectTransferMethodTest.java b/ui/src/androidTest/java/com/hyperwallet/android/ui/transfermethod/SelectTransferMethodTest.java similarity index 97% rename from ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/SelectTransferMethodTest.java rename to ui/src/androidTest/java/com/hyperwallet/android/ui/transfermethod/SelectTransferMethodTest.java index c644703cd..ad44411c8 100644 --- a/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/SelectTransferMethodTest.java +++ b/ui/src/androidTest/java/com/hyperwallet/android/ui/transfermethod/SelectTransferMethodTest.java @@ -1,4 +1,4 @@ -package com.hyperwallet.android.transfermethod.ui; +package com.hyperwallet.android.ui.transfermethod; import static androidx.test.espresso.Espresso.onView; import static androidx.test.espresso.action.ViewActions.click; @@ -29,8 +29,8 @@ import static com.hyperwallet.android.ui.transfermethod.AddTransferMethodActivity.EXTRA_TRANSFER_METHOD_CURRENCY; import static com.hyperwallet.android.ui.transfermethod.AddTransferMethodActivity.EXTRA_TRANSFER_METHOD_PROFILE_TYPE; import static com.hyperwallet.android.ui.transfermethod.AddTransferMethodActivity.EXTRA_TRANSFER_METHOD_TYPE; -import static com.hyperwallet.android.util.EspressoUtils.atPosition; -import static com.hyperwallet.android.util.EspressoUtils.withDrawable; +import static com.hyperwallet.android.ui.util.EspressoUtils.atPosition; +import static com.hyperwallet.android.ui.util.EspressoUtils.withDrawable; import android.widget.TextView; @@ -42,14 +42,13 @@ import androidx.test.rule.ActivityTestRule; import com.hyperwallet.android.Hyperwallet; -import com.hyperwallet.android.common.util.EspressoIdlingResource; -import com.hyperwallet.android.hyperwallet_ui.R; -import com.hyperwallet.android.rule.HyperwalletExternalResourceManager; -import com.hyperwallet.android.rule.HyperwalletMockWebServer; +import com.hyperwallet.android.ui.R; +import com.hyperwallet.android.ui.common.util.EspressoIdlingResource; import com.hyperwallet.android.ui.repository.RepositoryFactory; -import com.hyperwallet.android.ui.transfermethod.SelectTransferMethodActivity; -import com.hyperwallet.android.util.RecyclerViewCountAssertion; -import com.hyperwallet.android.util.TestAuthenticationProvider; +import com.hyperwallet.android.ui.rule.HyperwalletExternalResourceManager; +import com.hyperwallet.android.ui.rule.HyperwalletMockWebServer; +import com.hyperwallet.android.ui.util.RecyclerViewCountAssertion; +import com.hyperwallet.android.ui.util.TestAuthenticationProvider; import org.junit.After; import org.junit.Before; diff --git a/ui/src/androidTest/java/com/hyperwallet/android/util/EspressoUtils.java b/ui/src/androidTest/java/com/hyperwallet/android/ui/util/EspressoUtils.java similarity index 99% rename from ui/src/androidTest/java/com/hyperwallet/android/util/EspressoUtils.java rename to ui/src/androidTest/java/com/hyperwallet/android/ui/util/EspressoUtils.java index 92a711f96..72891a832 100644 --- a/ui/src/androidTest/java/com/hyperwallet/android/util/EspressoUtils.java +++ b/ui/src/androidTest/java/com/hyperwallet/android/ui/util/EspressoUtils.java @@ -1,4 +1,4 @@ -package com.hyperwallet.android.util; +package com.hyperwallet.android.ui.util; import android.graphics.Bitmap; import android.graphics.Canvas; diff --git a/ui/src/androidTest/java/com/hyperwallet/android/util/NestedScrollToAction.java b/ui/src/androidTest/java/com/hyperwallet/android/ui/util/NestedScrollToAction.java similarity index 96% rename from ui/src/androidTest/java/com/hyperwallet/android/util/NestedScrollToAction.java rename to ui/src/androidTest/java/com/hyperwallet/android/ui/util/NestedScrollToAction.java index 392867387..54f08aed7 100644 --- a/ui/src/androidTest/java/com/hyperwallet/android/util/NestedScrollToAction.java +++ b/ui/src/androidTest/java/com/hyperwallet/android/ui/util/NestedScrollToAction.java @@ -1,4 +1,4 @@ -package com.hyperwallet.android.util; +package com.hyperwallet.android.ui.util; import static androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom; import static androidx.test.espresso.matcher.ViewMatchers.isDescendantOfA; diff --git a/ui/src/androidTest/java/com/hyperwallet/android/util/RecyclerViewCountAssertion.java b/ui/src/androidTest/java/com/hyperwallet/android/ui/util/RecyclerViewCountAssertion.java similarity index 95% rename from ui/src/androidTest/java/com/hyperwallet/android/util/RecyclerViewCountAssertion.java rename to ui/src/androidTest/java/com/hyperwallet/android/ui/util/RecyclerViewCountAssertion.java index bb3aecaff..e3c7945fd 100644 --- a/ui/src/androidTest/java/com/hyperwallet/android/util/RecyclerViewCountAssertion.java +++ b/ui/src/androidTest/java/com/hyperwallet/android/ui/util/RecyclerViewCountAssertion.java @@ -1,4 +1,4 @@ -package com.hyperwallet.android.util; +package com.hyperwallet.android.ui.util; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; diff --git a/ui/src/androidTest/java/com/hyperwallet/android/util/TestAuthenticationProvider.java b/ui/src/androidTest/java/com/hyperwallet/android/ui/util/TestAuthenticationProvider.java similarity index 97% rename from ui/src/androidTest/java/com/hyperwallet/android/util/TestAuthenticationProvider.java rename to ui/src/androidTest/java/com/hyperwallet/android/ui/util/TestAuthenticationProvider.java index 686ccbf30..1f8350f8f 100644 --- a/ui/src/androidTest/java/com/hyperwallet/android/util/TestAuthenticationProvider.java +++ b/ui/src/androidTest/java/com/hyperwallet/android/ui/util/TestAuthenticationProvider.java @@ -1,4 +1,4 @@ -package com.hyperwallet.android.util; +package com.hyperwallet.android.ui.util; import com.hyperwallet.android.HyperwalletAuthenticationTokenListener; import com.hyperwallet.android.HyperwalletAuthenticationTokenProvider; diff --git a/ui/src/main/AndroidManifest.xml b/ui/src/main/AndroidManifest.xml index c147fe710..6888120a5 100644 --- a/ui/src/main/AndroidManifest.xml +++ b/ui/src/main/AndroidManifest.xml @@ -1,7 +1,7 @@ + package="com.hyperwallet.android.ui"> diff --git a/ui/src/main/java/com/hyperwallet/android/ui/HyperwalletUi.java b/ui/src/main/java/com/hyperwallet/android/ui/HyperwalletUi.java index aae63fa7e..b47c1f87d 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/HyperwalletUi.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/HyperwalletUi.java @@ -31,7 +31,7 @@ import com.hyperwallet.android.Hyperwallet; import com.hyperwallet.android.HyperwalletAuthenticationTokenProvider; -import com.hyperwallet.android.receipt.view.ListReceiptActivity; +import com.hyperwallet.android.ui.receipt.view.ListReceiptActivity; import com.hyperwallet.android.ui.transfermethod.AddTransferMethodActivity; import com.hyperwallet.android.ui.transfermethod.ListTransferMethodActivity; import com.hyperwallet.android.ui.transfermethod.SelectTransferMethodActivity; diff --git a/ui/src/main/java/com/hyperwallet/android/ui/repository/TransferMethodConfigurationRepositoryImpl.java b/ui/src/main/java/com/hyperwallet/android/ui/repository/TransferMethodConfigurationRepositoryImpl.java index 4fe1861a4..a058b61d3 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/repository/TransferMethodConfigurationRepositoryImpl.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/repository/TransferMethodConfigurationRepositoryImpl.java @@ -33,7 +33,6 @@ import androidx.annotation.VisibleForTesting; import com.hyperwallet.android.Hyperwallet; -import com.hyperwallet.android.common.util.EspressoIdlingResource; import com.hyperwallet.android.exception.HyperwalletException; import com.hyperwallet.android.listener.HyperwalletListener; import com.hyperwallet.android.model.graphql.HyperwalletTransferMethodConfigurationField; @@ -41,7 +40,7 @@ import com.hyperwallet.android.model.graphql.keyed.HyperwalletTransferMethodType; import com.hyperwallet.android.model.graphql.query.HyperwalletTransferMethodConfigurationFieldQuery; import com.hyperwallet.android.model.graphql.query.HyperwalletTransferMethodConfigurationKeysQuery; -import com.hyperwallet.android.common.util.EspressoIdlingResource; +import com.hyperwallet.android.ui.common.util.EspressoIdlingResource; import java.util.HashMap; import java.util.Map; diff --git a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/AddTransferMethodActivity.java b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/AddTransferMethodActivity.java index 4dbd6eb55..9c1fa1d77 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/AddTransferMethodActivity.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/AddTransferMethodActivity.java @@ -28,10 +28,10 @@ import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentTransaction; -import com.hyperwallet.android.common.view.error.DefaultErrorDialogFragment; -import com.hyperwallet.android.common.view.error.OnNetworkErrorCallback; -import com.hyperwallet.android.hyperwallet_ui.R; import com.hyperwallet.android.model.HyperwalletError; +import com.hyperwallet.android.ui.R; +import com.hyperwallet.android.ui.common.view.error.DefaultErrorDialogFragment; +import com.hyperwallet.android.ui.common.view.error.OnNetworkErrorCallback; import com.hyperwallet.android.ui.view.WidgetDateDialogFragment; import com.hyperwallet.android.ui.view.WidgetSelectionDialogFragment; diff --git a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/AddTransferMethodFragment.java b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/AddTransferMethodFragment.java index 53e290aa9..471f184f5 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/AddTransferMethodFragment.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/AddTransferMethodFragment.java @@ -46,7 +46,6 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager; import com.hyperwallet.android.exception.HyperwalletException; -import com.hyperwallet.android.hyperwallet_ui.R; import com.hyperwallet.android.model.HyperwalletError; import com.hyperwallet.android.model.graphql.HyperwalletFee; import com.hyperwallet.android.model.graphql.field.HyperwalletField; @@ -56,6 +55,7 @@ import com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod; import com.hyperwallet.android.model.transfermethod.PayPalAccount; import com.hyperwallet.android.ui.HyperwalletLocalBroadcast; +import com.hyperwallet.android.ui.R; import com.hyperwallet.android.ui.repository.RepositoryFactory; import com.hyperwallet.android.ui.view.WidgetDateDialogFragment; import com.hyperwallet.android.ui.view.WidgetSelectionDialogFragment; diff --git a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/FeeFormatter.java b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/FeeFormatter.java index 9e0c25358..e073e0a1b 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/FeeFormatter.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/FeeFormatter.java @@ -22,8 +22,8 @@ import androidx.annotation.NonNull; -import com.hyperwallet.android.hyperwallet_ui.R; import com.hyperwallet.android.model.graphql.HyperwalletFee; +import com.hyperwallet.android.ui.R; import java.util.List; diff --git a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/ListTransferMethodActivity.java b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/ListTransferMethodActivity.java index 9f3f37654..64ba48309 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/ListTransferMethodActivity.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/ListTransferMethodActivity.java @@ -30,11 +30,11 @@ import androidx.fragment.app.FragmentTransaction; import com.google.android.material.floatingactionbutton.FloatingActionButton; -import com.hyperwallet.android.common.view.error.DefaultErrorDialogFragment; -import com.hyperwallet.android.common.view.error.OnNetworkErrorCallback; -import com.hyperwallet.android.hyperwallet_ui.R; import com.hyperwallet.android.model.HyperwalletError; import com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod; +import com.hyperwallet.android.ui.R; +import com.hyperwallet.android.ui.common.view.error.DefaultErrorDialogFragment; +import com.hyperwallet.android.ui.common.view.error.OnNetworkErrorCallback; import com.hyperwallet.android.ui.view.widget.OneClickListener; import java.util.List; diff --git a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/ListTransferMethodFragment.java b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/ListTransferMethodFragment.java index a274aafd8..8fdb6eb8d 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/ListTransferMethodFragment.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/ListTransferMethodFragment.java @@ -42,12 +42,12 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; -import com.hyperwallet.android.common.view.HorizontalDividerItemDecorator; -import com.hyperwallet.android.hyperwallet_ui.R; import com.hyperwallet.android.model.HyperwalletError; import com.hyperwallet.android.model.HyperwalletStatusTransition; import com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod; import com.hyperwallet.android.ui.HyperwalletLocalBroadcast; +import com.hyperwallet.android.ui.R; +import com.hyperwallet.android.ui.common.view.HorizontalDividerItemDecorator; import com.hyperwallet.android.ui.repository.RepositoryFactory; import com.hyperwallet.android.ui.view.widget.OneClickListener; diff --git a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/SelectTransferMethodActivity.java b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/SelectTransferMethodActivity.java index a0582988b..9415590ac 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/SelectTransferMethodActivity.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/SelectTransferMethodActivity.java @@ -31,10 +31,10 @@ import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentTransaction; -import com.hyperwallet.android.common.view.error.DefaultErrorDialogFragment; -import com.hyperwallet.android.common.view.error.OnNetworkErrorCallback; -import com.hyperwallet.android.hyperwallet_ui.R; import com.hyperwallet.android.model.HyperwalletError; +import com.hyperwallet.android.ui.R; +import com.hyperwallet.android.ui.common.view.error.DefaultErrorDialogFragment; +import com.hyperwallet.android.ui.common.view.error.OnNetworkErrorCallback; import com.hyperwallet.android.ui.view.CountrySelectionDialogFragment; import com.hyperwallet.android.ui.view.CurrencySelectionDialogFragment; diff --git a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/SelectTransferMethodFragment.java b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/SelectTransferMethodFragment.java index 154a2bff0..8c757bb2e 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/SelectTransferMethodFragment.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/SelectTransferMethodFragment.java @@ -38,9 +38,9 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; -import com.hyperwallet.android.common.view.HorizontalDividerItemDecorator; -import com.hyperwallet.android.hyperwallet_ui.R; import com.hyperwallet.android.model.HyperwalletError; +import com.hyperwallet.android.ui.R; +import com.hyperwallet.android.ui.common.view.HorizontalDividerItemDecorator; import com.hyperwallet.android.ui.repository.RepositoryFactory; import com.hyperwallet.android.ui.view.CountrySelectionDialogFragment; import com.hyperwallet.android.ui.view.CurrencySelectionDialogFragment; diff --git a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodConfirmDeactivationDialogFragment.java b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodConfirmDeactivationDialogFragment.java index 433bfa879..bd9339659 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodConfirmDeactivationDialogFragment.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodConfirmDeactivationDialogFragment.java @@ -27,7 +27,7 @@ import androidx.fragment.app.DialogFragment; import androidx.fragment.app.FragmentManager; -import com.hyperwallet.android.hyperwallet_ui.R; +import com.hyperwallet.android.ui.R; public class TransferMethodConfirmDeactivationDialogFragment extends DialogFragment { diff --git a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodUtils.java b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodUtils.java index 87877cddd..127c21818 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodUtils.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodUtils.java @@ -29,9 +29,9 @@ import androidx.annotation.NonNull; -import com.hyperwallet.android.hyperwallet_ui.R; import com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod; import com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodType; +import com.hyperwallet.android.ui.R; import java.util.Locale; diff --git a/ui/src/main/java/com/hyperwallet/android/ui/view/CountrySelectionDialogFragment.java b/ui/src/main/java/com/hyperwallet/android/ui/view/CountrySelectionDialogFragment.java index 828697756..66980f24b 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/view/CountrySelectionDialogFragment.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/view/CountrySelectionDialogFragment.java @@ -46,7 +46,7 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; -import com.hyperwallet.android.hyperwallet_ui.R; +import com.hyperwallet.android.ui.R; import java.util.ArrayList; import java.util.List; diff --git a/ui/src/main/java/com/hyperwallet/android/ui/view/CurrencySelectionDialogFragment.java b/ui/src/main/java/com/hyperwallet/android/ui/view/CurrencySelectionDialogFragment.java index 84e0ed3fc..e9ee2bde1 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/view/CurrencySelectionDialogFragment.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/view/CurrencySelectionDialogFragment.java @@ -47,7 +47,7 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; -import com.hyperwallet.android.hyperwallet_ui.R; +import com.hyperwallet.android.ui.R; import java.util.ArrayList; import java.util.List; diff --git a/ui/src/main/java/com/hyperwallet/android/ui/view/WidgetDateDialogFragment.java b/ui/src/main/java/com/hyperwallet/android/ui/view/WidgetDateDialogFragment.java index 0fd6910ff..d81e51369 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/view/WidgetDateDialogFragment.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/view/WidgetDateDialogFragment.java @@ -12,7 +12,7 @@ import androidx.fragment.app.DialogFragment; import androidx.fragment.app.FragmentManager; -import com.hyperwallet.android.hyperwallet_ui.R; +import com.hyperwallet.android.ui.R; import com.hyperwallet.android.ui.view.widget.DateUtil; import java.util.Calendar; diff --git a/ui/src/main/java/com/hyperwallet/android/ui/view/WidgetSelectionDialogFragment.java b/ui/src/main/java/com/hyperwallet/android/ui/view/WidgetSelectionDialogFragment.java index 42b98af70..d3efca613 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/view/WidgetSelectionDialogFragment.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/view/WidgetSelectionDialogFragment.java @@ -45,7 +45,7 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; -import com.hyperwallet.android.hyperwallet_ui.R; +import com.hyperwallet.android.ui.R; import java.util.ArrayList; import java.util.List; diff --git a/ui/src/main/java/com/hyperwallet/android/ui/view/widget/DateWidget.java b/ui/src/main/java/com/hyperwallet/android/ui/view/widget/DateWidget.java index 1c7e3a12d..0d576066a 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/view/widget/DateWidget.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/view/widget/DateWidget.java @@ -30,8 +30,8 @@ import androidx.annotation.Nullable; import com.google.android.material.textfield.TextInputLayout; -import com.hyperwallet.android.hyperwallet_ui.R; import com.hyperwallet.android.model.graphql.field.HyperwalletField; +import com.hyperwallet.android.ui.R; import java.text.ParseException; diff --git a/ui/src/main/java/com/hyperwallet/android/ui/view/widget/DefaultAccountWidget.java b/ui/src/main/java/com/hyperwallet/android/ui/view/widget/DefaultAccountWidget.java index 99bfabc0b..f9a1401bf 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/view/widget/DefaultAccountWidget.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/view/widget/DefaultAccountWidget.java @@ -13,7 +13,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import com.hyperwallet.android.hyperwallet_ui.R; +import com.hyperwallet.android.ui.R; public class DefaultAccountWidget extends AbstractWidget { diff --git a/ui/src/main/java/com/hyperwallet/android/ui/view/widget/ExpiryDateWidget.java b/ui/src/main/java/com/hyperwallet/android/ui/view/widget/ExpiryDateWidget.java index 8ae7dfacf..834629f85 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/view/widget/ExpiryDateWidget.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/view/widget/ExpiryDateWidget.java @@ -38,8 +38,8 @@ import androidx.annotation.Nullable; import com.google.android.material.textfield.TextInputLayout; -import com.hyperwallet.android.hyperwallet_ui.R; import com.hyperwallet.android.model.graphql.field.HyperwalletField; +import com.hyperwallet.android.ui.R; public class ExpiryDateWidget extends AbstractWidget { private final ExpireDateUtil mExpireDateUtil; diff --git a/ui/src/main/java/com/hyperwallet/android/ui/view/widget/NumberWidget.java b/ui/src/main/java/com/hyperwallet/android/ui/view/widget/NumberWidget.java index 2d4e9562c..dc20d4dc1 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/view/widget/NumberWidget.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/view/widget/NumberWidget.java @@ -31,8 +31,8 @@ import androidx.annotation.Nullable; import com.google.android.material.textfield.TextInputLayout; -import com.hyperwallet.android.hyperwallet_ui.R; import com.hyperwallet.android.model.graphql.field.HyperwalletField; +import com.hyperwallet.android.ui.R; public class NumberWidget extends AbstractWidget { private ViewGroup mContainer; diff --git a/ui/src/main/java/com/hyperwallet/android/ui/view/widget/PhoneWidget.java b/ui/src/main/java/com/hyperwallet/android/ui/view/widget/PhoneWidget.java index 346c1972c..8ce4aad9f 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/view/widget/PhoneWidget.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/view/widget/PhoneWidget.java @@ -31,8 +31,8 @@ import androidx.annotation.Nullable; import com.google.android.material.textfield.TextInputLayout; -import com.hyperwallet.android.hyperwallet_ui.R; import com.hyperwallet.android.model.graphql.field.HyperwalletField; +import com.hyperwallet.android.ui.R; public class PhoneWidget extends AbstractWidget { private ViewGroup mContainer; diff --git a/ui/src/main/java/com/hyperwallet/android/ui/view/widget/SelectionWidget.java b/ui/src/main/java/com/hyperwallet/android/ui/view/widget/SelectionWidget.java index 102eea656..f6558922b 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/view/widget/SelectionWidget.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/view/widget/SelectionWidget.java @@ -31,9 +31,9 @@ import androidx.core.content.ContextCompat; import com.google.android.material.textfield.TextInputLayout; -import com.hyperwallet.android.hyperwallet_ui.R; import com.hyperwallet.android.model.graphql.field.HyperwalletField; import com.hyperwallet.android.model.graphql.field.HyperwalletFieldSelectionOption; +import com.hyperwallet.android.ui.R; import com.hyperwallet.android.ui.view.WidgetSelectionDialogFragment; import java.util.Set; diff --git a/ui/src/main/java/com/hyperwallet/android/ui/view/widget/TextWidget.java b/ui/src/main/java/com/hyperwallet/android/ui/view/widget/TextWidget.java index 599b77b9a..9533752c5 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/view/widget/TextWidget.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/view/widget/TextWidget.java @@ -31,8 +31,8 @@ import androidx.annotation.Nullable; import com.google.android.material.textfield.TextInputLayout; -import com.hyperwallet.android.hyperwallet_ui.R; import com.hyperwallet.android.model.graphql.field.HyperwalletField; +import com.hyperwallet.android.ui.R; public class TextWidget extends AbstractWidget { private ViewGroup mContainer; diff --git a/ui/src/main/res/values/strings.xml b/ui/src/main/res/values/strings.xml index 0c983668d..f77d5e91e 100644 --- a/ui/src/main/res/values/strings.xml +++ b/ui/src/main/res/values/strings.xml @@ -1,5 +1,5 @@ - hyperwallet_ui + hyperwallet.ui Add Account Not Available Unknown diff --git a/ui/src/test/java/com/hyperwallet/android/ui/transfermethod/FeeFormatterTest.java b/ui/src/test/java/com/hyperwallet/android/ui/transfermethod/FeeFormatterTest.java index 269efa42e..ce5a9df3e 100644 --- a/ui/src/test/java/com/hyperwallet/android/ui/transfermethod/FeeFormatterTest.java +++ b/ui/src/test/java/com/hyperwallet/android/ui/transfermethod/FeeFormatterTest.java @@ -8,8 +8,8 @@ import android.content.Context; import android.content.res.Resources; -import com.hyperwallet.android.hyperwallet_ui.R; import com.hyperwallet.android.model.graphql.HyperwalletFee; +import com.hyperwallet.android.ui.R; import com.hyperwallet.android.ui.rule.HyperwalletExternalResourceManager; import org.json.JSONException; diff --git a/ui/src/test/java/com/hyperwallet/android/ui/transfermethod/TransferMethodUtilsTest.java b/ui/src/test/java/com/hyperwallet/android/ui/transfermethod/TransferMethodUtilsTest.java index 6d57d30ff..186428ef3 100644 --- a/ui/src/test/java/com/hyperwallet/android/ui/transfermethod/TransferMethodUtilsTest.java +++ b/ui/src/test/java/com/hyperwallet/android/ui/transfermethod/TransferMethodUtilsTest.java @@ -14,8 +14,8 @@ import android.content.Context; import android.content.res.Resources; -import com.hyperwallet.android.hyperwallet_ui.R; import com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod; +import com.hyperwallet.android.ui.R; import com.hyperwallet.android.ui.rule.HyperwalletExternalResourceManager; import org.json.JSONException; From f16f4dceca5d76021c54a869a4e530ed6c3a0047 Mon Sep 17 00:00:00 2001 From: Viktor Shcherbyna Date: Tue, 18 Jun 2019 13:00:10 +0300 Subject: [PATCH 10/10] move second line implementation to the TransferMethodUtils --- .../ui/transfermethod/AccountSecondLine.java | 51 -------- .../ui/transfermethod/CardSecondLine.java | 53 -------- .../ListTransferMethodFragment.java | 17 +-- .../PayPalAccountSecondLine.java | 40 ------ .../transfermethod/SecondLinePresenter.java | 33 ----- .../TransferMethodSecondLine.java | 45 ------- .../TransferMethodSecondLinePresenter.java | 79 ------------ .../transfermethod/TransferMethodUtils.java | 54 ++++++++ ...TransferMethodSecondLinePresenterTest.java | 118 ------------------ .../TransferMethodUtilsTest.java | 50 ++++++++ 10 files changed, 110 insertions(+), 430 deletions(-) delete mode 100644 ui/src/main/java/com/hyperwallet/android/ui/transfermethod/AccountSecondLine.java delete mode 100644 ui/src/main/java/com/hyperwallet/android/ui/transfermethod/CardSecondLine.java delete mode 100644 ui/src/main/java/com/hyperwallet/android/ui/transfermethod/PayPalAccountSecondLine.java delete mode 100644 ui/src/main/java/com/hyperwallet/android/ui/transfermethod/SecondLinePresenter.java delete mode 100644 ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSecondLine.java delete mode 100644 ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSecondLinePresenter.java delete mode 100644 ui/src/test/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSecondLinePresenterTest.java diff --git a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/AccountSecondLine.java b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/AccountSecondLine.java deleted file mode 100644 index 055c0e23b..000000000 --- a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/AccountSecondLine.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * The MIT License (MIT) - * Copyright (c) 2018 Hyperwallet Systems Inc. - * - * 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 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; - -import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodFields.BANK_ACCOUNT_ID; - -import android.content.Context; - -import androidx.annotation.NonNull; - -import com.hyperwallet.android.hyperwallet_ui.R; -import com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod; - -/** - * Retrieves Bank account Id from the {@link HyperwalletTransferMethod} field - * and forms an identifier String of the last 4 digits. - */ -public class AccountSecondLine implements TransferMethodSecondLine { - private static final int LAST_FOUR_DIGIT = 4; - - @NonNull - @Override - public String getText(@NonNull final Context context, - @NonNull final HyperwalletTransferMethod transferMethod) { - - return context.getString(R.string.transfer_method_list_item_description, - getAccountIdentifier(transferMethod)); - } - - private String getAccountIdentifier(@NonNull final HyperwalletTransferMethod transferMethod) { - final String transferIdentification = transferMethod.getField(BANK_ACCOUNT_ID); - - return (transferIdentification.length() > LAST_FOUR_DIGIT - ? transferIdentification.substring(transferIdentification.length() - LAST_FOUR_DIGIT) - : transferIdentification); - } -} diff --git a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/CardSecondLine.java b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/CardSecondLine.java deleted file mode 100644 index 37ec35d07..000000000 --- a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/CardSecondLine.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * The MIT License (MIT) - * Copyright (c) 2018 Hyperwallet Systems Inc. - * - * 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 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; - -import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodFields.CARD_NUMBER; - -import android.content.Context; - -import androidx.annotation.NonNull; - -import com.hyperwallet.android.hyperwallet_ui.R; -import com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod; - -/** - * Retrieves Card number from the {@link HyperwalletTransferMethod} field - * and forms an identifier String of the last 4 digits. - */ -public class CardSecondLine implements TransferMethodSecondLine { - private static final int LAST_FOUR_DIGIT = 4; - - @NonNull - @Override - public String getText(@NonNull final Context context, - @NonNull final HyperwalletTransferMethod transferMethod) { - - return context.getString(R.string.transfer_method_list_item_description, - getCardIdentifier(transferMethod)); - } - - private String getCardIdentifier(@NonNull final HyperwalletTransferMethod transferMethod) { - final String transferIdentification = transferMethod.getField(CARD_NUMBER); - - return (transferIdentification.length() > LAST_FOUR_DIGIT - ? transferIdentification.substring(transferIdentification.length() - LAST_FOUR_DIGIT) - : transferIdentification); - } - - -} diff --git a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/ListTransferMethodFragment.java b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/ListTransferMethodFragment.java index 8fdb6eb8d..fde0b7446 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/ListTransferMethodFragment.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/ListTransferMethodFragment.java @@ -73,7 +73,6 @@ public class ListTransferMethodFragment extends Fragment implements ListTransfer private OnLoadTransferMethodNetworkErrorCallback mOnLoadTransferMethodNetworkErrorCallback; private boolean mIsTransferMethodsReloadNeeded; private RecyclerView recyclerView; - private TransferMethodSecondLinePresenter mSecondLinePresenter; /** * Please don't use this constructor this is reserved for Android Core Framework @@ -144,7 +143,7 @@ public void onViewStateRestored(@Nullable Bundle savedInstanceState) { mIsTransferMethodsReloadNeeded = true; } mListTransferMethodAdapter = new ListTransferMethodAdapter(mTransferMethodList, - mOnTransferMethodContextMenuDeletionSelected, mSecondLinePresenter); + mOnTransferMethodContextMenuDeletionSelected); recyclerView.setAdapter(mListTransferMethodAdapter); } @@ -181,7 +180,6 @@ public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); RepositoryFactory factory = RepositoryFactory.getInstance(); mPresenter = new ListTransferMethodPresenter(factory.getTransferMethodRepository(), this); - mSecondLinePresenter = new TransferMethodSecondLinePresenter(); } @@ -295,16 +293,13 @@ interface OnLoadTransferMethodNetworkErrorCallback { } private static class ListTransferMethodAdapter extends RecyclerView.Adapter { - private final TransferMethodSecondLinePresenter mSecondLinePresenter; private List mTransferMethodList; private OnTransferMethodContextMenuDeletionSelected mOnTransferMethodContextMenuDeletionSelected; ListTransferMethodAdapter(final List transferMethodList, - final OnTransferMethodContextMenuDeletionSelected onTransferMethodContextMenuSelection, - TransferMethodSecondLinePresenter secondLinePresenter) { + final OnTransferMethodContextMenuDeletionSelected onTransferMethodContextMenuSelection) { mTransferMethodList = transferMethodList; mOnTransferMethodContextMenuDeletionSelected = onTransferMethodContextMenuSelection; - mSecondLinePresenter = secondLinePresenter; } @NonNull @@ -356,7 +351,9 @@ class ViewHolder extends RecyclerView.ViewHolder { void bind(@NonNull final HyperwalletTransferMethod transferMethod) { String type = transferMethod.getField(TYPE); - TransferMethodSecondLine identificationStrategy = mSecondLinePresenter.getSecondLinePresenter( + final String transferMethodIdentification = TransferMethodUtils.getTransferMethodDetail( + mTransferMethodIdentification.getContext(), + transferMethod, type); mTitle.setText( @@ -366,9 +363,7 @@ void bind(@NonNull final HyperwalletTransferMethod transferMethod) { transferMethod.getField(TRANSFER_METHOD_COUNTRY)).build(); mIcon.setText(getStringFontIcon(mIcon.getContext(), type)); mTransferMethodCountry.setText(locale.getDisplayName()); - mTransferMethodIdentification.setText( - identificationStrategy.getText(mTransferMethodIdentification - .getContext(), transferMethod)); + mTransferMethodIdentification.setText(transferMethodIdentification); mImageButton.setOnClickListener(new View.OnClickListener() { @Override diff --git a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/PayPalAccountSecondLine.java b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/PayPalAccountSecondLine.java deleted file mode 100644 index 7d837872a..000000000 --- a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/PayPalAccountSecondLine.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * The MIT License (MIT) - * Copyright (c) 2018 Hyperwallet Systems Inc. - * - * 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 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; - -import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodFields.EMAIL; - -import android.content.Context; - -import androidx.annotation.NonNull; - -import com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod; - -/** - * Retrieves PayPal account email from the {@link HyperwalletTransferMethod} and forms an identifier String. - */ -public class PayPalAccountSecondLine implements TransferMethodSecondLine { - - @NonNull - @Override - public String getText(@NonNull final Context context, - @NonNull final HyperwalletTransferMethod transferMethod) { - - final String identificationText = transferMethod.getField(EMAIL); - return identificationText != null ? identificationText : EMPTY_STRING; - } -} diff --git a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/SecondLinePresenter.java b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/SecondLinePresenter.java deleted file mode 100644 index da781da2e..000000000 --- a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/SecondLinePresenter.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * The MIT License (MIT) - * Copyright (c) 2018 Hyperwallet Systems Inc. - * - * 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 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; - -import com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod; - -/** - * Factory makes instance of a {@link TransferMethodSecondLine} by a corresponding - * {@link HyperwalletTransferMethod.TransferMethodType} - */ -interface SecondLinePresenter { - /** - * Get {@link TransferMethodSecondLine} by a {@link HyperwalletTransferMethod.TransferMethodType} - * - * @param type @{@link HyperwalletTransferMethod.TransferMethodType} - * @return Implementation of the {@link TransferMethodSecondLine} - */ - TransferMethodSecondLine getSecondLinePresenter(@HyperwalletTransferMethod.TransferMethodType final String type); -} diff --git a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSecondLine.java b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSecondLine.java deleted file mode 100644 index 004f3b2ac..000000000 --- a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSecondLine.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * The MIT License (MIT) - * Copyright (c) 2018 Hyperwallet Systems Inc. - * - * 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 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; - -import android.content.Context; - -import androidx.annotation.NonNull; - -import com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod; - -/** - * Represents abstract strategy for the second line of TransferMethod list item. - */ -public interface TransferMethodSecondLine { - - String EMPTY_STRING = ""; - TransferMethodSecondLine DEFAULT = new TransferMethodSecondLine() { - - @NonNull - @Override - public String getText(@NonNull final Context context, - @NonNull final HyperwalletTransferMethod transferMethod) { - - return EMPTY_STRING; - } - }; - - @NonNull - String getText(@NonNull final Context context, - @NonNull final HyperwalletTransferMethod transferMethod); -} diff --git a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSecondLinePresenter.java b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSecondLinePresenter.java deleted file mode 100644 index 004610a1e..000000000 --- a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSecondLinePresenter.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * The MIT License (MIT) - * Copyright (c) 2018 Hyperwallet Systems Inc. - * - * 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 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; - -import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.BANK_ACCOUNT; -import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.BANK_CARD; -import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.PAYPAL_ACCOUNT; -import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.PREPAID_CARD; -import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.WIRE_ACCOUNT; - -import androidx.annotation.NonNull; - -import com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod; - -import java.util.HashMap; -import java.util.Map; - -/** - * Factory instantiates instance of a {@link TransferMethodSecondLine} by a corresponding - * {@link HyperwalletTransferMethod.TransferMethodType} - */ -final class TransferMethodSecondLinePresenter implements SecondLinePresenter { - private Map mSecondLineStrategies = new HashMap<>(3); - - @Override - @NonNull - public TransferMethodSecondLine getSecondLinePresenter( - @HyperwalletTransferMethod.TransferMethodType final String type) { - if (type == null) { - return TransferMethodSecondLine.DEFAULT; - } - - switch (type) { - case BANK_CARD: - case PREPAID_CARD: - if (!mSecondLineStrategies.containsKey(CardSecondLine.class)) { - mSecondLineStrategies.put( - CardSecondLine.class, new CardSecondLine()); - } - - //noinspection ConstantConditions - return mSecondLineStrategies.get(CardSecondLine.class); - case BANK_ACCOUNT: - case WIRE_ACCOUNT: - if (!mSecondLineStrategies.containsKey(AccountSecondLine.class)) { - mSecondLineStrategies.put( - AccountSecondLine.class, new AccountSecondLine()); - } - - //noinspection ConstantConditions - return mSecondLineStrategies.get(AccountSecondLine.class); - case PAYPAL_ACCOUNT: - if (!mSecondLineStrategies.containsKey(PayPalAccountSecondLine.class)) { - mSecondLineStrategies.put(PayPalAccountSecondLine.class, - new PayPalAccountSecondLine()); - } - - //noinspection ConstantConditions - return mSecondLineStrategies.get(PayPalAccountSecondLine.class); - - default: - return TransferMethodSecondLine.DEFAULT; - } - } -} diff --git a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodUtils.java b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodUtils.java index 127c21818..95d10041a 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodUtils.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/transfermethod/TransferMethodUtils.java @@ -16,6 +16,9 @@ */ package com.hyperwallet.android.ui.transfermethod; +import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodFields.BANK_ACCOUNT_ID; +import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodFields.CARD_NUMBER; +import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodFields.EMAIL; import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodFields.TYPE; import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.BANK_ACCOUNT; import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.BANK_CARD; @@ -28,6 +31,7 @@ import android.content.res.Resources; import androidx.annotation.NonNull; +import androidx.annotation.StringRes; import com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod; import com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodType; @@ -37,6 +41,8 @@ public class TransferMethodUtils { + private static final int LAST_FOUR_DIGIT = 4; + /** * Get string resource by TransferMethodType * @@ -125,4 +131,52 @@ public static String getTransferMethodName(@NonNull final Context context, return title; } + + /** + * Gets Transfer method identifier from the {@link HyperwalletTransferMethod} field + * by a {@link TransferMethodType}. + * + * @param context Context + * @param transferMethod HyperwalletTransferMethod + * @param type TransferMethodType + */ + public static String getTransferMethodDetail(@NonNull Context context, + @NonNull final HyperwalletTransferMethod transferMethod, + @TransferMethodType final String type) { + if (type == null) { + return ""; + } + + switch (type) { + case BANK_CARD: + case PREPAID_CARD: + return getFourDigitsIdentification(context, + transferMethod, + CARD_NUMBER, + R.string.transfer_method_list_item_description); + case BANK_ACCOUNT: + case WIRE_ACCOUNT: + return getFourDigitsIdentification(context, transferMethod, BANK_ACCOUNT_ID, + R.string.transfer_method_list_item_description); + case PAYPAL_ACCOUNT: + final String transferIdentification = transferMethod.getField(EMAIL); + return transferIdentification != null ? transferIdentification : ""; + default: + return ""; + } + } + + private static String getFourDigitsIdentification(@NonNull final Context context, + @NonNull final HyperwalletTransferMethod transferMethod, + @NonNull @HyperwalletTransferMethod.TransferMethodFieldKey final String fieldKey, + @StringRes final int stringResId) { + final String transferIdentification = transferMethod.getField(fieldKey); + + final String identificationText = + transferIdentification != null && transferIdentification.length() > LAST_FOUR_DIGIT + ? transferIdentification.substring(transferIdentification.length() - LAST_FOUR_DIGIT) + : ""; + + return context.getString(stringResId, identificationText); + } } diff --git a/ui/src/test/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSecondLinePresenterTest.java b/ui/src/test/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSecondLinePresenterTest.java deleted file mode 100644 index c07152649..000000000 --- a/ui/src/test/java/com/hyperwallet/android/ui/transfermethod/TransferMethodSecondLinePresenterTest.java +++ /dev/null @@ -1,118 +0,0 @@ -package com.hyperwallet.android.ui.transfermethod; - -import static org.hamcrest.CoreMatchers.instanceOf; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.not; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; - -import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.BANK_ACCOUNT; -import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.BANK_CARD; -import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.PAPER_CHECK; -import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.PAYPAL_ACCOUNT; - -import android.content.Context; - -import com.hyperwallet.android.hyperwallet_ui.R; -import com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod; -import com.hyperwallet.android.ui.rule.HyperwalletExternalResourceManager; - -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.robolectric.RobolectricTestRunner; - -@RunWith(RobolectricTestRunner.class) -public class TransferMethodSecondLinePresenterTest { - private TransferMethodSecondLinePresenter mPresenter; - - @Rule - public HyperwalletExternalResourceManager mExternalResourceManager = new HyperwalletExternalResourceManager(); - - @Before - public void setUp() { - mPresenter = new TransferMethodSecondLinePresenter(); - } - - @Test - public void testGetSecondLine_returnsCachedSecondLine() { - TransferMethodSecondLine actualStrategy = mPresenter.getSecondLinePresenter( - HyperwalletTransferMethod.TransferMethodTypes.WIRE_ACCOUNT); - TransferMethodSecondLine candidateStrategy = mPresenter.getSecondLinePresenter(BANK_ACCOUNT); - assertThat(actualStrategy, is(candidateStrategy)); - } - - @Test - public void testGetSecondLine_returnsSecondLine() { - TransferMethodSecondLine strategy1 = mPresenter.getSecondLinePresenter(BANK_CARD); - TransferMethodSecondLine strategy2 = mPresenter.getSecondLinePresenter(PAYPAL_ACCOUNT); - assertThat(strategy1, not(strategy2)); - } - - @Test - public void testGetSecondLine_returnsEndingOn() { - TransferMethodSecondLine strategy = mPresenter.getSecondLinePresenter(BANK_CARD); - assertThat(strategy, is(strategy)); - - } - - @Test - public void testGetSecondLine_returnsPayPalSecondLine() throws JSONException { - Context context = mock(Context.class); - String json = mExternalResourceManager.getResourceContent("paypal_response.json"); - JSONObject htmJsonObject = new JSONObject(json); - HyperwalletTransferMethod transferMethod = new HyperwalletTransferMethod(htmJsonObject); - - TransferMethodSecondLine strategy = mPresenter.getSecondLinePresenter(PAYPAL_ACCOUNT); - String actual = strategy.getText(context, transferMethod); - assertThat(strategy, instanceOf(PayPalAccountSecondLine.class)); - assertThat(actual, is("sunshine.carreiro@hyperwallet.com")); - } - - @Test - public void testGetSecondLine_returnsCardSecondLine() throws JSONException { - Context context = mock(Context.class); - String json = mExternalResourceManager.getResourceContent("bank_card_response.json"); - JSONObject htmJsonObject = new JSONObject(json); - HyperwalletTransferMethod transferMethod = new HyperwalletTransferMethod(htmJsonObject); - TransferMethodSecondLine strategy = mPresenter.getSecondLinePresenter(BANK_CARD); - strategy.getText(context, transferMethod); - - assertThat(strategy, instanceOf(CardSecondLine.class)); - verify(context).getString(eq(R.string.transfer_method_list_item_description), eq("0006")); - } - - @Test - public void testGetSecondLine_returnsAccountSecondLine() throws JSONException { - Context context = mock(Context.class); - String json = mExternalResourceManager.getResourceContent("bank_account_response.json"); - JSONObject htmJsonObject = new JSONObject(json); - HyperwalletTransferMethod transferMethod = new HyperwalletTransferMethod(htmJsonObject); - TransferMethodSecondLine strategy = mPresenter.getSecondLinePresenter(BANK_ACCOUNT); - strategy.getText(context, transferMethod); - - assertThat(strategy, instanceOf(AccountSecondLine.class)); - verify(context).getString(eq(R.string.transfer_method_list_item_description), eq("0254")); - } - - @Test - public void testGetSecondLine_returnsPaperCheckSecondLine() throws JSONException { - Context context = mock(Context.class); - String json = mExternalResourceManager.getResourceContent("paper_check_response.json"); - JSONObject htmJsonObject = new JSONObject(json); - HyperwalletTransferMethod transferMethod = new HyperwalletTransferMethod(htmJsonObject); - TransferMethodSecondLine strategy = mPresenter.getSecondLinePresenter(PAPER_CHECK); - String actual = strategy.getText(context, transferMethod); - - assertThat(strategy, instanceOf(TransferMethodSecondLine.class)); - assertThat(actual, is("")); - verify(context, never()).getString(eq(R.string.transfer_method_list_item_description), anyString()); - } -} diff --git a/ui/src/test/java/com/hyperwallet/android/ui/transfermethod/TransferMethodUtilsTest.java b/ui/src/test/java/com/hyperwallet/android/ui/transfermethod/TransferMethodUtilsTest.java index 186428ef3..8d3dd0b5b 100644 --- a/ui/src/test/java/com/hyperwallet/android/ui/transfermethod/TransferMethodUtilsTest.java +++ b/ui/src/test/java/com/hyperwallet/android/ui/transfermethod/TransferMethodUtilsTest.java @@ -5,11 +5,16 @@ import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.BANK_ACCOUNT; import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.BANK_CARD; +import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.PAPER_CHECK; +import static com.hyperwallet.android.model.transfermethod.HyperwalletTransferMethod.TransferMethodTypes.PAYPAL_ACCOUNT; import android.content.Context; import android.content.res.Resources; @@ -18,6 +23,7 @@ import com.hyperwallet.android.ui.R; import com.hyperwallet.android.ui.rule.HyperwalletExternalResourceManager; +import org.hamcrest.CoreMatchers; import org.json.JSONException; import org.json.JSONObject; import org.junit.Before; @@ -134,4 +140,48 @@ public void testGetStringFontIcon_returnsDefaultValue() { verify(mResources, times(2)).getIdentifier(anyString(), anyString(), anyString()); verify(mContext, times(1)).getString(anyInt()); } + + @Test + public void testGetSecondLine_returnsPayPalSecondLine() throws JSONException { + String json = mExternalResourceManager.getResourceContent("paypal_response.json"); + JSONObject htmJsonObject = new JSONObject(json); + HyperwalletTransferMethod transferMethod = new HyperwalletTransferMethod(htmJsonObject); + + String actual = TransferMethodUtils.getTransferMethodDetail(mContext, transferMethod, PAYPAL_ACCOUNT); + assertThat(actual, is("sunshine.carreiro@hyperwallet.com")); + } + + @Test + public void testGetSecondLine_returnsCardSecondLine() throws JSONException { + String json = mExternalResourceManager.getResourceContent("bank_card_response.json"); + JSONObject htmJsonObject = new JSONObject(json); + HyperwalletTransferMethod transferMethod = new HyperwalletTransferMethod(htmJsonObject); + when(mContext.getString(eq(R.string.transfer_method_list_item_description), eq("0006"))).thenReturn( + "Ending on 0006"); + String actual = TransferMethodUtils.getTransferMethodDetail(mContext, transferMethod, BANK_CARD); + assertThat(actual, is("Ending on 0006")); + } + + @Test + public void testGetSecondLine_returnsAccountSecondLine() throws JSONException { + String json = mExternalResourceManager.getResourceContent("bank_account_response.json"); + JSONObject htmJsonObject = new JSONObject(json); + HyperwalletTransferMethod transferMethod = new HyperwalletTransferMethod(htmJsonObject); + when(mContext.getString(eq(R.string.transfer_method_list_item_description), eq("0254"))).thenReturn( + "Ending on 0254"); + String actual = TransferMethodUtils.getTransferMethodDetail(mContext, transferMethod, BANK_ACCOUNT); + assertThat(actual, is("Ending on 0254")); + } + + @Test + public void testGetSecondLine_returnsPaperCheckSecondLine() throws JSONException { + Context context = mock(Context.class); + String json = mExternalResourceManager.getResourceContent("paper_check_response.json"); + JSONObject htmJsonObject = new JSONObject(json); + HyperwalletTransferMethod transferMethod = new HyperwalletTransferMethod(htmJsonObject); + String actual = TransferMethodUtils.getTransferMethodDetail(mContext, transferMethod, PAPER_CHECK); + + assertThat(actual, CoreMatchers.is("")); + verify(context, never()).getString(eq(R.string.transfer_method_list_item_description), anyString()); + } }